PIPS
hermite.c
Go to the documentation of this file.
1 /*
2 
3  $Id: hermite.c 1669 2019-06-26 17:24:57Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of Linear/C3 Library.
8 
9  Linear/C3 Library is free software: you can redistribute it and/or modify it
10  under the terms of the GNU Lesser General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  Linear/C3 Library is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public License
21  along with Linear/C3 Library. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 
25  /* package matrix */
26 
27 #ifdef HAVE_CONFIG_H
28  #include "config.h"
29 #endif
30 
31 #include <stdlib.h>
32 #include <stdio.h>
33 
34 #include "linear_assert.h"
35 
36 #include "boolean.h"
37 #include "arithmetique.h"
38 
39 #include "matrix.h"
40 
41 /* void matrix_hermite(matrix MAT, matrix P, matrix H,
42  * matrix Q, int *det_p, int *det_q):
43  * calcul de la forme reduite de Hermite H de la matrice MAT avec
44  * les deux matrices de changement de base unimodulaire P et Q,
45  * telles que H = P x MAT x Q
46  * et en le meme temp, produit les determinants des P et Q.
47  * det_p = |P|, det_q = |Q|.
48  *
49  * (c.f. Programmation Lineaire. Theorie et algorithmes. tome 2. M.MINOUX. Dunod (1983))
50  * FI: Quels est l'invariant de l'algorithme? MAT = P x H x Q?
51  * FI: Quelle est la norme decroissante? La condition d'arret?
52  *
53  * Les parametres de la fonction :
54  *
55  * int MAT[n,m]: matrice
56  * int n : nombre de lignes de la matrice
57  * int m : nombre de colonnes de la matrice
58  * int P[n,n] : matrice
59  * int H[n,m] : matrice reduite de Hermite
60  * int Q[m,m] : matrice
61  * int *det_p : determinant de P (nombre de permutation de ligne)
62  * int *det_q : determinant de Q (nombre de permutation de colonne)
63  *
64  * Les 3 matrices P(nxn), Q(mxm) et H(nxm) doivent etre allouees avant le
65  * calcul.
66  *
67  * Note: les denominateurs de MAT, P, A et H ne sont pas utilises.
68  *
69  * Auteurs: Corinne Ancourt, Yi-qing Yang
70  *
71  * Modifications:
72  * - modification du profil de la fonction pour permettre le calcul du
73  * determinant de MAT
74  * - permutation de colonnes directe, remplacant une permutation
75  * par produit de matrices
76  * - suppression des copies entre H, P, Q et NH, PN, QN
77  */
78 void matrix_hermite(MAT,P,H,Q,det_p,det_q)
79 Pmatrix MAT;
80 Pmatrix P;
81 Pmatrix H;
82 Pmatrix Q;
83 Value *det_p;
84 Value *det_q;
85 {
86  Pmatrix PN=NULL;
87  Pmatrix QN=NULL;
88  Pmatrix HN = NULL;
89  int n,m;
90  /* indice de la ligne et indice de la colonne correspondant
91  au plus petit element de la sous-matrice traitee */
92  int ind_n,ind_m;
93 
94  /* niveau de la sous-matrice traitee */
95  int level = 0;
96 
97  Value ALL;/* le plus petit element sur la diagonale */
98  Value x=VALUE_ZERO; /* la quotient de la division par ALL */
99  bool stop = false;
100  int i;
101 
102  *det_p = *det_q = VALUE_ONE;
103  /* if ((n>0) && (m>0) && MAT) */
104  n = MATRIX_NB_LINES(MAT);
105  m=MATRIX_NB_COLUMNS(MAT);
106  assert(n >0 && m > 0);
108 
109  HN = matrix_new(n, m);
110  PN = matrix_new(n, n);
111  QN = matrix_new(m, m);
112 
113  /* Initialisation des matrices */
114 
115  matrix_assign(MAT,H);
116  matrix_identity(PN,0);
117  matrix_identity(QN,0);
118  matrix_identity(P,0);
119  matrix_identity(Q,0);
120  matrix_nulle(HN);
121 
122  while (!stop) {
123  /* tant qu'il reste des termes non nuls dans la partie
124  triangulaire superieure de la matrice H,
125  on cherche le plus petit element de la sous-matrice */
126  matrix_coeff_nnul(H,&ind_n,&ind_m,level);
127 
128  if (ind_n == 0 && ind_m == 0)
129  /* la sous-matrice restante est nulle, on a terminee */
130  stop = true;
131  else {
132  /* s'il existe un plus petit element non nul dans la partie
133  triangulaire superieure de la sous-matrice,
134  on amene cet element en haut sur la diagonale.
135  si cet element est deja sur la diagonale, et que tous les
136  termes de la ligne correspondante sont nuls,
137  on effectue les calculs sur la sous-matrice de rang superieur*/
138 
139  if (ind_n > level + 1) {
140  matrix_swap_rows(H,level+1,ind_n);
141  matrix_swap_rows(PN,level+1,ind_n);
142  *det_p = value_uminus(*det_p);
143  }
144 
145  if (ind_m > level+1) {
146  matrix_swap_columns(H,level+1,ind_m);
147  matrix_swap_columns(QN,level+1,ind_m);
148  *det_q = value_uminus(*det_q);
149  }
150 
151  if(matrix_line_el(H,level) != 0) {
152  ALL = SUB_MATRIX_ELEM(H,1,1,level);
153  for (i=level+2; i<=m; i++) {
154  x = value_div(MATRIX_ELEM(H,level+1,i),ALL);
157  }
158 
159  }
160  else level++;
161  }
162  }
163 
164  matrix_assign(PN,P);
165  matrix_assign(QN,Q);
166  matrix_free(HN);
167  matrix_free(PN);
168  matrix_free(QN);
169 }
170 
171 /* int matrix_hermite_rank(Pmatrix a): rang d'une matrice
172  * en forme de hermite
173  */
175 Pmatrix a;
176 {
177  int i;
178  int r = 0;
179  int n = MATRIX_NB_LINES(a);
180  for(i=1; i<=n; i++, r++)
181  if(MATRIX_ELEM(a, i, i) == 0) break;
182 
183  return r;
184 }
185 
186 
187 /* Calcul de la dimension de la matrice de Hermite H.
188  * La matrice de Hermite est une matrice tres particuliere,
189  * pour laquelle il est tres facile de calculer sa dimension.
190  * Elle est egale au nombre de colonnes non nulles de la matrice.
191  */
192 
193 
195 Pmatrix H;
196 {
197  int i,j;
198  bool trouve_j = false;
199  int res=0;
200  int n = MATRIX_NB_LINES(H);
201  int m = MATRIX_NB_COLUMNS(H);
202  for (j = 1; j<=m && !trouve_j;j++) {
203  for (i=1; i<= n && MATRIX_ELEM(H,i,j) == 0; i++);
204  if (i>n) {
205  trouve_j = true;
206  res= j-1;
207  }
208  }
209 
210 
211  if (!trouve_j && m>=1) res = m;
212  return (res);
213 
214 }
#define VALUE_ZERO
#define value_uminus(val)
unary operators on values
#define value_one_p(val)
int Value
#define VALUE_ONE
#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
#define matrix_free(m)
Allocation et desallocation d'une matrice.
Definition: matrix-local.h:73
#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
int matrix_dim_hermite(Pmatrix H)
Calcul de la dimension de la matrice de Hermite H.
Definition: hermite.c:194
int matrix_hermite_rank(Pmatrix a)
int matrix_hermite_rank(Pmatrix a): rang d'une matrice en forme de hermite
Definition: hermite.c:174
void matrix_hermite(Pmatrix MAT, Pmatrix P, Pmatrix H, Pmatrix Q, Value *det_p, Value *det_q)
package matrix
Definition: hermite.c:78
void matrix_nulle(Pmatrix Z)
void matrix_nulle(Pmatrix Z): Initialisation de la matrice Z a la valeur matrice nulle
Definition: matrix.c:293
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_coeff_nnul(Pmatrix, int *, int *, int)
void matrix_coeff_nnul(Pmatrix MAT, int * lg_nnul, int * cl_nnul, int level) renvoie les coordonnees ...
Definition: sub-matrix.c:421
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
#define assert(ex)
Definition: newgen_assert.h:41
#define Q
Definition: pip__type.h:39
#define ALL
Definition: readmakefile.c:178
#define level
static char * x
Definition: split_file.c:159
package matrice
Definition: matrix-local.h:63