PIPS
sc-fais-int-sm.c
Go to the documentation of this file.
1 /*
2 
3  $Id: sc-fais-int-sm.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 plint */
26 
27 #ifdef HAVE_CONFIG_H
28  #include "config.h"
29 #endif
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 
34 #include "linear_assert.h"
35 #include "boolean.h"
36 #include "arithmetique.h"
37 #include "vecteur.h"
38 #include "contrainte.h"
39 #include "sc.h"
40 
41 #include "matrix.h"
42 
43 #include "ray_dte.h"
44 #include "sommet.h"
45 
46 /* pour recuperer les declarations des fonctions de conversion de
47  * sc en liste de sommets et reciproquement, bien que ca casse le
48  * DAG des types de donnees
49  */
50 
51 #include "polyedre.h"
52 
53 #include "plint.h"
54 
55 #define MALLOC(s,t,f) malloc((unsigned)(s))
56 #define FREE(s,t,f) free((char *)(s))
57 
58 
59 /* void var_posit(Psysteme ps, int B[], int m, int nbl):
60  * Recherche des inegalites que doivent respecter les variables
61  * non contraintes pour que les variables de depart soient positives
62  *
63  * La matrice B passee en parametres est celle calculee a l'aide
64  * de la fonction "matrice_smith"
65  *
66  * Les parametres de la fonction :
67  *
68  *!Psysteme ps : systeme lineaire d'inegalites
69  * int B[] : matrice de dimension (m,m+1) correspondant a la matrice
70  * solution du systeme d'egalites du systeme lineaire
71  * int n : nombre de lignes de la matrice
72  * int m : nombre de colonnes de la matrice
73  * int nbl : nombre de variables non contraintes ajoutees a la matrice
74  */
75 void var_posit(ps,B,m,nbl)
76 Psysteme ps;
77 Pmatrix B;
78 int m;
79 int nbl;
80 {
81  Pvecteur pv=NULL;
82  Pcontrainte pc=NULL;
83  Pcontrainte cp = NULL;
84  int i,j;
85  Value den = VALUE_ONE;
86  int sgn_den;
87  ps->dimension = 0;
88  ps->base = NULL;
89 
90  for (i = 1; i <= nbl; i++)
91  (void) creat_new_var(ps);
92 
93  den =MATRIX_DENOMINATOR(B);
94  sgn_den = value_sign(den);
95  if (den) {
96  for (i=1;i<=m; i++) {
97  Pbase b = ps->base;
98  Value tmp = MATRIX_ELEM(B,i,1);
99 
100  cp = contrainte_new();
101 
102  if (sgn_den==1) value_oppose(tmp);
103  pv = vect_new(TCST,tmp);
104 
105  for (j=1;j<=nbl && b!=VECTEUR_NUL;j++, b = b->succ)
106  {
107  tmp = MATRIX_ELEM(B,i,j+1);
108  if (sgn_den==1) value_oppose(tmp);
109  vect_chg_coeff(&pv, vecteur_var(b), tmp);
110  }
111  assert(j>nbl);
112 
113  cp->vecteur = pv;
114  cp->vecteur = vect_clean(cp->vecteur);
115  cp->succ = pc;
116  pc = cp;
117  }
118  }
119  ps->egalites = NULL;
120  ps->inegalites = pc;
121  ps->nb_ineq = nbl;
122 }
123 
124 /* Psysteme smith_int(Psysteme ps):
125  * Resolution d'un systeme d'egalites en nombres entiers par la methode de
126  * Smith et recherche du systeme lineaire que doit verifier les nouvelles
127  * variables non contraintes du systeme pour que les variables de depart
128  * soient positives.
129  *
130  * resultat retourne par la fonction :
131  *
132  * Psysteme : le systeme lineaire que doit verifier les
133  * variables non contraintes
134  *
135  *
136  * Les parametres de la fonction :
137  *
138  * Psysteme ps : systeme lineaire
139  */
141 Psysteme ps;
142 {
143 
144  Psysteme sys=sc_dup(ps);
145  int i;
156  Value den=VALUE_ONE;
157  int nbl;
158  int nblg = sys->nb_eq; /* nombre de lignes du systeme */
159  int nbv = sys->dimension; /* nombre de variables du systeme */
160  int n; /* nombre d'equations du systeme */
161  int m; /* nombre de variables du systeme */
162  int n_min,m_min; /* numero de la ligne et de la colonne correspondant
163  au plus petit entier non nul appartenant a la
164  partie triangulaire superieure de la matrice */
165  int level = 0;
166  bool trouve = false;
167  bool stop = false;
168  bool infaisab = false;
169 
170  if(ps)
171  sys = sc_normalize(sc_dup(sys));
172  if (nbv && nblg && sys)
173  {
174  MAT = matrix_new(nblg,nbv);
175 
176  MATN = matrix_new(nblg,nbv);
177 
178  P = matrix_new(nblg,nblg);
179  PN = matrix_new(nblg,nblg);
180  PN2 =matrix_new(nblg,nblg );
181 
182  Q =matrix_new(nbv,nbv);
183  QN =matrix_new(nbv,nbv );
184  QN2 = matrix_new(nbv,nbv );
185 
186  B = matrix_new(nbv,(nbv+1));
187  B2 = matrix_new(nbv,(nbv+1));
188 
189 #ifdef TRACE
190  printf(" systeme lineaire initial \n");
191  sc_fprint (stdout,sys,noms_var);
192 #endif
193 
194  /* Initialisation des parametres */
195  n = sys->nb_eq;
196  m = sys->dimension;
197 
198  sys_mat_conv(sys,MAT,B,n,m);
199 
200  if (sys->egalites != NULL)
202  sys->egalites = NULL;
203 
206 
207  matrix_nulle(B);
208 
209  matrix_identity(PN,0);
210  matrix_identity(QN,0);
211  matrix_identity(P,0);
212  matrix_identity(Q,0);
213 
214  while (!stop) {
215  matrix_min(MAT,&n_min,&m_min,level);
216  if ((((n_min==1 + level) || (m_min==1+level)) && !trouve ) ||
217  ( (n_min >1 +level) || (m_min >1 +level))) {
218  if (n_min >1 + level)
219  {
220  matrix_nulle(P);
221  matrix_perm_col(P,n_min,level);
222 
223  matrix_multiply(P,MAT,MATN);
224  matrix_multiply(P,PN,PN2);
225 
226  matrix_assign(MATN,MAT);
227  matrix_assign(PN2,PN);
228  }
229 
230 #ifdef TRACE
231  printf (" apres alignement du plus petit element a la premiere colonne \n");
232  matrix_print(MAT);
233 #endif
234 
235  if (m_min >1+level)
236  {
237  matrix_nulle(Q);
238  matrix_perm_line(Q,m_min,level);
239 
240  matrix_multiply(MAT,Q,MATN);
241  matrix_multiply(QN,Q,QN2);
242 
243  matrix_assign(MATN,MAT);
244  matrix_assign(QN2,QN);
245  }
246 
247 #ifdef TRACE
248  printf (" apres alignement du plus petit element a la premiere ligne \n");
249  matrix_print(MAT);
250 #endif
251 
252  if (m_min>0 && n_min >0) {
253  if(matrix_col_el(MAT,level)) {
254  matrix_maj_col(MAT,P,level);
255 
256  matrix_multiply(P,MAT,MATN);
257  matrix_multiply(P,PN,PN2);
258 
259  matrix_assign(MATN,MAT);
260  matrix_assign(PN2,PN);
261  }
262 
263 #ifdef TRACE
264  printf("apres division par A%d%d des termes de la %d-ieme colonne \n",level+1,level+
265  1,level+
266  1);
267  matrix_print(MAT);
268 #endif
269 
270  if(matrix_line_el(MAT,level)) {
271  matrix_maj_line(MAT,Q,level);
272 
273  matrix_multiply(MAT,Q,MATN);
274  matrix_multiply(QN,Q,QN2);
275 
276  matrix_assign(MATN,MAT);
277  matrix_assign(QN2,QN);
278  }
279 #ifdef TRACE
280  printf("apres division par A%d%d des termes de la %d-ieme ligne \n",level+1,level+
281  1,level+1);
282  matrix_print(MAT);
283 #endif
284 
285  }
286  trouve = true;
287  }
288  else {
289  if (!n_min || !m_min)
290  stop = true;
291  else
292  {
293  level++;
294  trouve = false;
295  }
296  }
297  }
298 #ifdef TRACE
299 
300  printf (" la matrice D apres transformation est la suivante :");
301  matrix_print(MAT);
302 
303  printf (" la matrice P est \n");
304  matrix_print(PN);
305 
306  printf (" la matrice Q est \n");
307  matrix_print(QN);
308 
309 #endif
310 
311  /* Pre-multiplication par la matrice P */
312  matrix_multiply(PN,B,B2);
313  matrix_assign(B2,B);
314 
315 #ifdef TRACE
316  printf (" apres pre-multiplication par P \n");
317  matrix_print(B);
318 #endif
319 
320  nbl = 2;
321 
322  for (i=1;i<=n && i<=m && !infaisab;i++) {
323  /* Division de chaque terme non nul de B par le terme
324  correspondant de la diagonale de la matrice D */
325  if (value_notzero_p(MATRIX_ELEM(MAT,i,i))) {
327  MATRIX_ELEM(MAT,i,i))))
329  MATRIX_ELEM(MAT,i,i));
330  else
331  infaisab = true;
332  }
333  else {
334  /* Si un terme diagonal est nul, on verifie que la variable
335  correspondante est bien nulle, i.e. que son coefficient
336  dans B est bien zero et on ajoute une variable
337  non contrainte au systeme.
338 
339  En effet, l'equation "0 * x = 0" ==>
340  "la variable x est non contrainte" */
341  if (value_zero_p(MATRIX_ELEM(B,i,1))) {
342  MATRIX_ELEM(B,i,nbl) = den;
343  nbl++;
344  }
345  else
346  /* si la variable est non nulle ==> il y a une erreur
347  ==> systeme infaisable */
348  infaisab = true;
349  }
350  }
351 
352  if (infaisab) {
353  matrix_nulle(B);
354  sc_rm(sys);
355  sys = NULL;
356 #ifdef TRACE
357  printf (" systeme infaisable en nombres entiers \n");
358 #endif
359  }
360  else {
361 #ifdef TRACE
362  printf (" apres division par les elements diagonaux de D \n");
363  matrix_print(B);
364 #endif
365  /* ajout des variables non contraintes */
366  if (m>n) {
367  for (i=n+1; i<=m; i++,nbl++)
368  MATRIX_ELEM(B,i,nbl) = den;
369  }
370  nbl -= 2;
371  /* Pre-multiplication par la matrice Q */
372  matrix_multiply(QN,B,B2);
373  matrix_assign(B2,B);
374 
375 #ifdef TRACE
376  printf (" apres pre-multiplication par Q \n");
377  matrix_print(B);
378 #endif
379 
381  /* recherche des contraintes lineaires que doivent respecter les
382  variables supplementaires pour que les variables de depart
383  soient positives */
384  var_posit(sys,B,m,nbl);
385  }
386  FREE(MAT,MATRIX,"smith");
387  FREE(MATN,MATRIX,"smith");
388  FREE(P,MATRIX,"smith");
389  FREE(PN,MATRIX,"smith");
390  FREE(PN2,MATRIX,"smith");
391  FREE(Q,MATRIX,"smith");
392  FREE(QN,MATRIX,"smith");
393  FREE(QN2,MATRIX,"smith");
394  FREE(B,MATRIX,"smith");
395  FREE(B2,MATRIX,"smith");
396  }
397 #ifdef TRACE
398  sc_fprint(stdout,sys,noms_var);
399 #endif
400 
401  return(sys);
402 }
403 
404 /* bool syst_smith(Psysteme ps):
405  * Test de faisabilite d'un systeme lineaire en nombres entiers positifs par
406  * resolution du systeme par la methode de Smith.
407  *
408  * Le resultat n'est pas toujours bon. Il existe des cas ou la fonction ne
409  * detecte pas l'infaisabilite du systeme en nombres entiers, mais il sera
410  * du moins dans ce cas faisable en nombres reels.
411  *
412  * resultat retourne par la fonction :
413  *
414  * boolean : true si le systeme lineaire a une solution entiere
415  * false si le systeme lineaire n'a pas de solution
416  * entiere
417  *
418  * Les parametres de la fonction :
419  *
420  * Psommet ps : systeme lineaire
421 */
422 bool syst_smith(ps)
423 Psysteme ps;
424 {
425  Psysteme sys2 = NULL;
426  Psysteme sys_cond_posit= NULL;
427  Psommet som1 = NULL;
428  bool is_faisab = true;
429 #ifdef TRACE
430  printf (" ** syst_smith - test de faisabilite d'un systeme avec Smith \n");
431 #endif
432 
433  if ((ps->egalites != NULL) || (ps->inegalites != NULL)) {
434 
435  if ( (sys2 =sc_normalize(sc_dup(ps))) != NULL) {
436 
437  Pvecteur lvbase = NULL;
438  int nb_som = 0;
439  int nbvars;
440  Pbase b = BASE_NULLE;
441 
442  nb_som = ps->nb_eq + ps->nb_ineq;
443  nbvars = ps->dimension;
444  b = base_dup(ps->base);
445 
446  /*
447  * transformation du systeme lineaire sous la forme d'un
448  * Psommet
449  */
450  som1 = sys_som_conv(sys2,&nb_som);
451  sc_rm(sys2);
452 
453  /*
454  * ajout des variables d'ecart et transformation des
455  * inegalites du systeme en egalites.
456  */
457  som1 = var_ecart_sup(som1,nb_som,&lvbase,&nbvars,&b);
458 
459  if ((sys2 = som_sys_conv(som1)) != NULL) {
460  sys2->dimension = nbvars;
461  sys2->base = b;
462  }
463 
464  /* resolution du systeme par la methode de Smith et
465  * recherche du systeme de contraintes
466  * (sys_cond_posit) que doit verifier les variables non
467  * contraintes pour que les variables de depart soient
468  * positives.
469  */
470  sys_cond_posit = smith_int(sys2);
471  sc_rm(sys2);
472 
473  /* Test de faisabilite du systeme de contraintes obtenu. */
474  if ((sys2 = sc_normalize(sc_dup(sys_cond_posit))) != NULL)
475  /*
476  * On utilise le test de faisabilite en reels, au lieu
477  * d'utiliser le test de faisabilite en entiers ==> on obtient
478  * des resultats un peu moins bon, mais un gain de temps
479  * appreciable.
480  */
481  is_faisab = sc_faisabilite(sys2);
482  else
483  is_faisab = false;
484  sc_rm(sys_cond_posit);
485  }
486  else
487  is_faisab = false;
488 
489 #ifdef TRACE
490  if (is_faisab)
491  printf (" -- smith_int ==> systeme faisable \n");
492  else printf (" -- smith_int ==> systeme non faisable \n");
493 #endif
494  }
495  return(is_faisab);
496 }
#define value_sign(v)
trian operators on values
#define value_oppose(ref)
#define value_notzero_p(val)
#define value_zero_p(val)
int Value
#define value_division(ref, val)
#define VALUE_ONE
#define value_mod(v1, v2)
char * noms_var(entity e)
comp_expr_to_pnome.c
Pcontrainte contraintes_free(Pcontrainte pc)
Pcontrainte contraintes_free(Pcontrainte pc): desallocation de toutes les contraintes de la liste pc.
Definition: alloc.c:226
Pcontrainte contrainte_new(void)
package contrainte - allocations et desallocations
Definition: alloc.c:47
#define B(A)
Definition: iabrev.h:61
#define MATRIX
FI #define NULL 0.
#define MATRIX_UNDEFINED
Definition: matrix-local.h:70
#define MATRIX_DENOMINATOR(matrix)
int MATRIX_DENONIMATOR(matrix): acces au denominateur global d'une matrice matrix
Definition: matrix-local.h:86
#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_normalizec(Pmatrix MAT)
void matrix_normalizec(Pmatrix MAT): Normalisation des coefficients de la matrice MAT,...
Definition: matrix.c:187
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_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
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_perm_col(Pmatrix, int, int)
void matrix_perm_col(Pmatrix MAT, int k, int level): Calcul de la matrice de permutation permettant ...
Definition: sub-matrix.c:115
void matrix_print(Pmatrix)
void matrix_print(matrice a): print an (nxm) rational matrix
Definition: matrix_io.c:70
void matrix_maj_col(Pmatrix, Pmatrix, int)
void matrix_maj_col(Pmatrix A, matrice P, int level): Calcul de la matrice permettant de remplacer ch...
Definition: sub-matrix.c:256
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
void matrix_perm_line(Pmatrix, int, int)
void matrix_perm_line(Pmatrix MAT, int k, int level): Calcul de la matrice de permutation permettant...
Definition: sub-matrix.c:150
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
void matrix_maj_line(Pmatrix, Pmatrix, int)
void matrix_maj_line(Pmatrix A, matrice Q, int level): Calcul de la matrice permettant de remplacer c...
Definition: sub-matrix.c:294
#define assert(ex)
Definition: newgen_assert.h:41
#define Q
Definition: pip__type.h:39
Psommet var_ecart_sup(Psommet sys, int nb_som, Pvecteur *lvbase, int *nbvars, Pbase *b)
Psommet var_ecart_sup(Psommet sys, int nb_som, Pvecteur * lvbase, int * nbvars, Pbase *b): ajout des ...
Definition: plvar-ecart.c:156
void var_posit(Psysteme ps, Pmatrix B, int m, int nbl)
void var_posit(Psysteme ps, int B[], int m, int nbl): Recherche des inegalites que doivent respecter ...
bool syst_smith(Psysteme ps)
bool syst_smith(Psysteme ps): Test de faisabilite d'un systeme lineaire en nombres entiers positifs p...
Psysteme smith_int(Psysteme ps)
Psysteme smith_int(Psysteme ps): Resolution d'un systeme d'egalites en nombres entiers par la methode...
#define FREE(s, t, f)
void sc_rm(Psysteme ps)
void sc_rm(Psysteme ps): liberation de l'espace memoire occupe par le systeme de contraintes ps;
Definition: sc_alloc.c:277
Psysteme sc_dup(Psysteme ps)
Psysteme sc_dup(Psysteme ps): should becomes a link.
Definition: sc_alloc.c:176
#define level
Pvecteur cp
pointeur sur l'egalite ou l'inegalite courante
Definition: sc_read.c:87
void sc_fprint(FILE *fp, Psysteme ps, get_variable_name_t nom_var)
void sc_fprint(FILE * f, Psysteme ps, char * (*nom_var)()): cette fonction imprime dans le fichier po...
Definition: sc_io.c:220
int printf()
Psysteme sc_normalize(Psysteme ps)
Psysteme sc_normalize(Psysteme ps): normalisation d'un systeme d'equation et d'inequations lineaires ...
void sys_mat_conv(Psysteme ps, Pmatrix A, Pmatrix B, int n, int m)
package sur les polyedres
Definition: sc_to_matrice.c:65
Variable creat_new_var(Psysteme ps)
char * noms_var(int i): cette fonction convertit un numero de variable en chaine de caracteres
Definition: sc_var.c:102
Pvecteur vect_clean(Pvecteur v)
Pvecteur vect_clean(Pvecteur v): elimination de tous les couples dont le coefficient vaut 0 dans le v...
Definition: scalaires.c:80
package matrice
Definition: matrix-local.h:63
Pcontrainte egalites
Definition: sc-local.h:70
Pbase base
Definition: sc-local.h:75
int dimension
Definition: sc-local.h:74
int nb_eq
Definition: sc-local.h:72
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
struct Svecteur * succ
Definition: vecteur-local.h:92
structure de donnees Sommet
Definition: sommet-local.h:64
#define TCST
VARIABLE REPRESENTANT LE TERME CONSTANT.
#define vecteur_var(v)
#define VECTEUR_NUL
DEFINITION DU VECTEUR NUL.
#define BASE_NULLE
MACROS SUR LES BASES.
Pbase base_dup(Pbase b)
Pbase base_dup(Pbase b) Note: this function changes the value of the pointer.
Definition: alloc.c:268
Pvecteur vect_new(Variable var, Value coeff)
Pvecteur vect_new(Variable var,Value coeff): allocation d'un vecteur colineaire au vecteur de base va...
Definition: alloc.c:110
void vect_chg_coeff(Pvecteur *ppv, Variable var, Value val)
void vect_chg_coeff(Pvecteur *ppv, Variable var, Value val): mise de la coordonnee var du vecteur *pp...
Definition: unaires.c:143