PIPS
smith.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include "linear_assert.h"
#include "boolean.h"
#include "arithmetique.h"
#include "matrix.h"
+ Include dependency graph for smith.c:

Go to the source code of this file.

Macros

#define MALLOC(s, t, f)   malloc((unsigned)(s))
 package matrix More...
 
#define FREE(s, t, f)   free((char *)(s))
 

Functions

void matrix_smith (Pmatrix MAT, Pmatrix P, Pmatrix D, Pmatrix Q)
 void matrix_smith(matrice MAT, matrix P, matrix D, matrix Q): Calcul de la forme reduite de Smith D d'une matrice entiere MAT et des deux matrices de changement de base unimodulaires associees, P et Q. More...
 
int matrices_to_1D_lattice (Pmatrix A, Pmatrix B, int n, int m, int i, Value *gcd_p, Value *c_p)
 Under the assumption A x = B, A[n,m] and B[n], compute the 1-D lattice for x_i of x[m] as. More...
 

Macro Definition Documentation

◆ FREE

#define FREE (   s,
  t,
  f 
)    free((char *)(s))

Definition at line 43 of file smith.c.

◆ MALLOC

#define MALLOC (   s,
  t,
  f 
)    malloc((unsigned)(s))

package matrix

Definition at line 42 of file smith.c.

Function Documentation

◆ matrices_to_1D_lattice()

int matrices_to_1D_lattice ( Pmatrix  A,
Pmatrix  B,
int  n,
int  m,
int  i,
Value gcd_p,
Value c_p 
)

Under the assumption A x = B, A[n,m] and B[n], compute the 1-D lattice for x_i of x[m] as.

x_i = gcd_i lambda + c_i

derived from the parametric solution of the system :

x_i = sum_{k<j<=m} q_{i,j} lambda_j + sum_{1<=j,=k} q_{i,j} y_c_{j}

where k is the rank of matrix A (0<=k<=n, k<=m), lambda_j are the free variables and y_c is the solution of the equations. This leads to:

gcd_i = sum_{k<j<=m} q_{i,j} and c_i = sum_{1<=j,=k} q_{i,j} y_c_{j}

when the system has a least one solution.

To compute Q and y_c, We use D[n,m], the Smith form of A, with D = P A Q and P[n,n] and Q[m,m] unimodular

inv(P) D inv(Q) x = b

inv(P) D y = b => D y = P b => some components of y[m] are constants, y_c[m]

y_c = D'{-1} P b, where D'[min(n,m),min(n,m)] is the top left submatrix of D[n,m]

y = inv(Q) x => x = Q (y_c[1..k],y[k+1..m])

where (a,b) represents s the concatenation of vectors a and b, and k<=min(n,m) the .

c_i = sum_j Q_{i,j} y_c_{j}

gcd = gcd_{j s.t. yc_j = 0} Q_{i,j}

Return false if the system Ax=b has no solution

This implements a partial parametric resolution of A x = B. It might be better from an engineering viewpoint to solve the system fully and then to exploit the equation for x_i.

Parameters
gcd_pcd_p
c_p_p

Definition at line 195 of file smith.c.

196 {
197  // The number of equations is smaller than the number of variables
198  // Not necessarily because you may have redundant equations
199  // assert(n<=m);
200  int success = 1;
201  Pmatrix P, D, Q;
202  P = matrix_new(n,n);
203  D = matrix_new(n,m);
204  Q = matrix_new(m,m);
205  matrix_smith(A,P,D,Q);
206 
207  // Compute P b
208 
209  Pmatrix Pb = matrix_new(n, 1);
210  matrix_multiply(P, B, Pb);
211 
212  // Compute yc by solving D yc = P b
213 
214  Pmatrix yc = matrix_new(m, 1);
215  int j;
216  for(j=1; j <= m; j++)
217  MATRIX_ELEM(yc, j, 1) = VALUE_ZERO;
218  // FI: it might be sufficient to check the pseudo-diagonal element Dii
219  int k = 0;
220  for(j=1; j <= n && j <= m; j++) {
221  Value Pbj = MATRIX_ELEM(Pb, j, 1);
222  if(!value_zero_p(Pbj)) {
223  Value Djj = MATRIX_ELEM(D, j, j);
224  if(!value_zero_p(Djj)) {
225  Value r = modulo(Pbj, Djj);
226  if(value_zero_p(r))
227  MATRIX_ELEM(yc, j, 1) = DIVIDE(Pbj, Djj), k=j;
228  else
229  success = false;
230  }
231  }
232  }
233  for(j=k+1; j <= n; j++) {
234  Value Pbj = MATRIX_ELEM(Pb, j, 1);
235  if(!value_zero_p(Pbj)) {
236  success = false;
237  }
238  }
239 
240  // If the system has parametric solutions
241 
242  if(success) {
243  // k = MIN(n,m);
244  // Compute the constant term "c_i"
245  *c_p = VALUE_ZERO;
246  for(j=1; j <= k; j++) {
247  *c_p += value_mult(MATRIX_ELEM(Q, i, j), MATRIX_ELEM(yc, j, 1));
248  }
249 
250  // and the gcd "gcd_i" with x = Q yc
251  *gcd_p = VALUE_ZERO;
252  for(j=k+1; j <= m; j++) {
253  if(value_zero_p(*gcd_p))
254  *gcd_p = MATRIX_ELEM(Q, i, j);
255  else if(!value_zero_p(MATRIX_ELEM(Q, i, j)))
256  *gcd_p = pgcd(*gcd_p, MATRIX_ELEM(Q, i, j));
257  }
258 
259  // With no information at all, the gcd default value is one
260  if(value_zero_p(*gcd_p))
261  *gcd_p = VALUE_ONE;
262  *c_p = modulo(*c_p, *gcd_p);
263  }
264  free(P);
265  free(Pb);
266  free(D);
267  free(Q);
268  free(yc);
269  return success;
270 }
#define VALUE_ZERO
#define modulo(a, b)
#define DIVIDE(x, y)
division avec reste toujours positif basee sur les equations: a/(-b) = - (a/b) (-a)/b = - ((a+b-1)/b)...
#define pgcd(a, b)
Pour la recherche de performance, selection d'une implementation particuliere des fonctions.
#define value_zero_p(val)
int Value
#define VALUE_ONE
#define value_mult(v, w)
whether the default is protected or not this define makes no sense any more...
void free(void *)
bool success
Definition: gpips-local.h:59
#define B(A)
Definition: iabrev.h:61
#define D(A)
Definition: iabrev.h:56
#define MATRIX_ELEM(matrix, i, j)
Macros d'acces aux elements d'une matrice.
Definition: matrix-local.h:80
Pmatrix matrix_new(int m, int n)
package matrix
Definition: alloc.c:41
void matrix_smith(Pmatrix MAT, Pmatrix P, Pmatrix D, Pmatrix Q)
void matrix_smith(matrice MAT, matrix P, matrix D, matrix Q): Calcul de la forme reduite de Smith D d...
Definition: smith.c:68
void matrix_multiply(const Pmatrix a, const Pmatrix b, Pmatrix c)
void matrix_multiply(Pmatrix a, Pmatrix b, Pmatrix c): multiply rational matrix a by rational matrix ...
Definition: matrix.c:95
#define Q
Definition: pip__type.h:39
Definition: pip__tab.h:25
package matrice
Definition: matrix-local.h:63

References B, D, DIVIDE, free(), MATRIX_ELEM, matrix_multiply(), matrix_new(), matrix_smith(), modulo, pgcd, Q, value_mult, VALUE_ONE, VALUE_ZERO, and value_zero_p.

Referenced by transformer_to_1D_lattice().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ matrix_smith()

void matrix_smith ( Pmatrix  MAT,
Pmatrix  P,
Pmatrix  D,
Pmatrix  Q 
)

void matrix_smith(matrice MAT, matrix P, matrix D, matrix Q): Calcul de la forme reduite de Smith D d'une matrice entiere MAT et des deux matrices de changement de base unimodulaires associees, P et Q.

smith.c

D est la forme reduite de Smith, P et Q sont des matrices unimodulaires; telles que D == P x MAT x Q

(c.f. Programmation Lineaire. M.MINOUX. (83))

int MAT[n,m] : matrice int n : nombre de lignes de la matrice MAT int m : nombre de colonnes de la matrice MAT int P[n,n] : matrice int D[n,m] : matrice (quasi-diagonale) reduite de Smith int Q[m,m] : matrice

Les 3 matrices P(nxn), Q(mxm) et D(nxm) doivent etre allouees avant le calcul.

Note: les determinants des matrices MAT, P, Q et D ne sont pas utilises.

le plus petit element sur la diagonale

le rest de la division par ALL

precondition sur les parametres

le transformation n'est pas fini.

Parameters
MATAT

Definition at line 68 of file smith.c.

73 {
74  int n_min,m_min;
75  int level = 0;
76  Value ALL; /* le plus petit element sur la diagonale */
77  Value x=VALUE_ZERO; /* le rest de la division par ALL */
78  int i;
79 
80  bool stop = false;
81  bool next = true;
82 
83  /* precondition sur les parametres */
84  int n = MATRIX_NB_LINES(MAT);
85  int m = MATRIX_NB_COLUMNS(MAT);
86  assert(m > 0 && n >0);
87  matrix_assign(MAT,D);
89 
90  matrix_identity(P,0);
91  matrix_identity(Q,0);
92 
93  while (!stop) {
94  matrix_min(D,&n_min,&m_min,level);
95 
96  if ((n_min == 0) && (m_min == 0))
97  stop = true;
98  else {
99  /* le transformation n'est pas fini. */
100  if (n_min > level +1) {
101  matrix_swap_rows(D,level+1,n_min);
102  matrix_swap_rows(P,level+1,n_min);
103  }
104 #ifdef TRACE
105  (void) printf (" apres alignement du plus petit element a la premiere ligne \n");
106  matrix_print(D);
107 #endif
108  if (m_min >1+level) {
109  matrix_swap_columns(D,level+1,m_min);
110  matrix_swap_columns(Q,level+1,m_min);
111  }
112 #ifdef TRACE
113  (void) printf (" apres alignement du plus petit element a la premiere colonne\n");
114  matrix_print(D);
115 #endif
116 
117  ALL = SUB_MATRIX_ELEM(D,1,1,level);
118  if (matrix_line_el(D,level) != 0)
119  for (i=level+2; i<=m; i++) {
120  x = value_div(MATRIX_ELEM(D,level+1,i),ALL);
123  next = false;
124  }
125  if (matrix_col_el(D,level) != 0)
126  for(i=level+2;i<=n;i++) {
127  x = value_div(MATRIX_ELEM(D,i,level+1),ALL);
130  next = false;
131  }
132 #ifdef TRACE
133  (void) printf("apres division par A(%d,%d) des termes de la %d-ieme ligne et de la %d-em colonne \n",level+1,level+1,level+1,level+1);
134  matrix_print(D);
135 #endif
136  if (next) level++;
137  next = true;
138  }
139  }
140 
141 #ifdef TRACE
142  (void) printf (" la matrice D apres transformation est la suivante :");
143  matrix_print(D);
144 
145  (void) printf (" la matrice P est \n");
146  matrix_print(P);
147 
148  (void) printf (" la matrice Q est \n");
149  matrix_print(Q);
150 #endif
151 }
#define value_one_p(val)
#define value_div(v1, v2)
#define SUB_MATRIX_ELEM(matrix, i, j, level)
MATRIX_RIGHT_INF_ELEM Permet d'acceder des sous-matrices dont le coin infe'rieur droit (i....
Definition: matrix-local.h:106
#define MATRIX_NB_LINES(matrix)
Definition: matrix-local.h:87
#define MATRIX_NB_COLUMNS(matrix)
Definition: matrix-local.h:88
#define MATRIX_DENOMINATOR(matrix)
int MATRIX_DENONIMATOR(matrix): acces au denominateur global d'une matrice matrix
Definition: matrix-local.h:86
void matrix_swap_rows(Pmatrix A, int r1, int r2)
void matrix_swap_rows(Pmatrix a, int r1, int r2): exchange rows r1 and r2 of an (nxm) rational matrix...
Definition: matrix.c:230
void matrix_swap_columns(Pmatrix A, int c1, int c2)
void matrix_swap_columns(Pmatrix a, int c1, int c2): exchange columns c1,c2 of an (nxm) rational matr...
Definition: matrix.c:209
void matrix_subtraction_column(Pmatrix MAT, int c1, int c2, Value x)
void matrix_subtraction_column(Pmatrix MAT,int c1,int c2,int x): Soustrait x fois la colonne c2 de la...
Definition: matrix.c:518
void matrix_assign(Pmatrix A, Pmatrix B)
void matrix_assign(Pmatrix A, Pmatrix B) Copie de la matrice A dans la matrice B
Definition: matrix.c:259
void matrix_subtraction_line(Pmatrix MAT, int r1, int r2, Value x)
void matrix_subtraction_line(Pmatrix MAT,int r1,int r2,int x): Soustrait x fois la ligne r2 de la lig...
Definition: matrix.c:541
void matrix_print(Pmatrix)
void matrix_print(matrice a): print an (nxm) rational matrix
Definition: matrix_io.c:70
int matrix_line_el(Pmatrix, int)
int matrix_line_el(Pmatrix MAT, int level) renvoie le numero de colonne absolu du premier element non...
Definition: sub-matrix.c:379
void matrix_identity(Pmatrix, int)
void matrix_identity(Pmatrix ID, int level) Construction d'une sous-matrice identity dans ID(level+1....
Definition: sub-matrix.c:322
int matrix_col_el(Pmatrix, int)
int matrix_col_el(Pmatrix MAT, int level) renvoie le numero de ligne absolu du premier element non nu...
Definition: sub-matrix.c:401
void matrix_min(Pmatrix, int *, int *, int)
void matrix_min(Pmatrix MAT, int * i_min, int * j_min, int level): Recherche des coordonnees (*i_min,...
Definition: sub-matrix.c:196
#define assert(ex)
Definition: newgen_assert.h:41
#define ALL
Definition: readmakefile.c:178
#define level
int printf()
static char * x
Definition: split_file.c:159

References ALL, assert, D, level, matrix_assign(), matrix_col_el(), MATRIX_DENOMINATOR, MATRIX_ELEM, matrix_identity(), matrix_line_el(), matrix_min(), MATRIX_NB_COLUMNS, MATRIX_NB_LINES, matrix_print(), matrix_subtraction_column(), matrix_subtraction_line(), matrix_swap_columns(), matrix_swap_rows(), printf(), Q, SUB_MATRIX_ELEM, value_div, value_one_p, VALUE_ZERO, and x.

Referenced by main(), matrices_to_1D_lattice(), and sc_resol_smith().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: