PIPS
sc_min.c
Go to the documentation of this file.
1 /*
2 
3  $Id: sc_min.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 /* test sc_min : ce test s'appelle par :
26  * programme fichier1.data fichier2.data ... fichiern.data
27  * ou bien : programme<fichier.data
28  * Se compile grace a` "make min" dans le directory
29  * /home/users/pips/C3/Linear/Development/polyedre.dir/test.dir
30  */
31 
32 #ifdef HAVE_CONFIG_H
33  #include "config.h"
34 #endif
35 
36 #include <stdio.h>
37 #include <stdlib.h>
38 extern int fprintf();
39 extern int printf();
40 extern char * strdup();
41 
42 #include "boolean.h"
43 #include "arithmetique.h"
44 #include "linear_assert.h"
45 #include "vecteur.h"
46 #include "contrainte.h"
47 #include "ray_dte.h"
48 #include "sommet.h"
49 #include "sc.h"
50 #include "sg.h"
51 #include "types.h"
52 #include "polyedre.h"
53 
54 #define DEBUG 0
55 #define DEBUG1 0
56 #define DEBUG2 0
57 /* Hmmm. To be compatible with some weird old 16-bit constants... RK */
58 #define PTR_NIL (INTPTR_MIN+767)
59 #define INFINI (INTPTR_MAX-767)
60 #define NB_INEQ sc->nb_ineq
61 #define NONTCST (vect_coeff(pv->var,sc_base(sc)))
62 #define SIMPL(A,B) {if(A!=1 && B!=1){long I1,J1,K;I1=A,J1=B;while((K=I1%J1)!=0)I1=J1,J1=K;A=A/J1;B=B/J1;if(B<0)A=-A,B=-B;}}
63 #define G(J1,A,B) {long I1,K;if(B>1){I1=A,J1=B;while((K=I1%J1)!=0)I1=J1,J1=K;if(J1<0)J1=-J1;}else J1=B;}
64 #define SIMPLIFIE(FRAC) SIMPL(FRAC.num,FRAC.den)
65 #define NB_EQ sc->nb_eq
66 #define DIMENSION sc->dimension
67 #define NUMERO hashtable[h].numero
68 #define MAX_VAR 197 /* nombre max de variables */
69 #define MAXVAL 24 /* seuil au dela duquel on se mefie d'un overflow */
70 #define SOLUBLE(N) soluble=N;goto FINSIMPLEX ;
71 #define EGAL1(x) (x.num==x.den)
72 #define EGAL0(x) (x.num==0)
73 #define EGAL(x,y) (x.num==0 && y.num==0 ||x.den!=0 && y.den!=0 && x.num*y.den==x.den*y.num)
74 #define NEGATIF(x) (x.num<0&&x.den>0||x.num>0&&x.den<0)
75 #define POSITIF(x) (x.num>0&&x.den>0||x.num<0&&x.den<0)
76 #define SUP1(x) ((x.num>0) && (x.den>0) && (x.num>x.den)||(x.num<0) && (x.den<0) && (x.den>x.num))
77 #define INF(x,y) (x.num*y.den<x.den*y.num)
78 #define NUL(x) (x.num==0)
79 #define AFF(x,y) {x.num=y.num;x.den=y.den;}
80 #define METINFINI(x) {x.num=INFINI;x.den=1;}
81 #define DIV(x,y,z) {if(y.num==0)x.num=0,x.den=1;else{x.num=y.num*z.den;x.den=y.den*z.num;SIMPLIFIE(x);}}
82 #define MUL(x,y,z) {if(y.num==0||z.num==0)x.num=0,x.den=1;else{x.num=y.num*z.num;x.den=y.den*z.den;SIMPLIFIE(x);}}
83  /* Pivot : x = a - b c / d */
84 #define PIVOT(X,A,B,C,D) {if(A.num==0){if(B.num==0||C.num==0||D.den==0)X.num=0, X.den=1;else if(B.den<MAXVAL && C.den<MAXVAL && D.num<MAXVAL){X.num=-B.num*C.num*D.den;X.den=B.den*C.den*D.num;SIMPLIFIE(X);}else{frac uu;if(DEBUG2)printf("++ %d/%d %d/%d %d/%d %d/%d \n",A.num,A.den,B.num,B.den,C.num,C.den,D.num,D.den);MUL(uu,B,C);DIV(X,uu,D);X.num=-X.num;if(DEBUG2)printf("%d/%d\n",X.num,X.den);}} \
85 else if(B.num==0||C.num==0||D.den==0)X.num=A.num,X.den=A.den; \
86 else if(D.num==1&&A.den==1&&B.den==1&&C.den==1)X.den=1,X.num=A.num-B.num*C.num*D.den; \
87 else if(A.den<MAXVAL && B.den<MAXVAL && C.den<MAXVAL && D.num<MAXVAL){X.num=A.num*B.den*C.den*D.num-A.den*B.num*C.num*D.den;X.den=A.den*B.den*C.den*D.num;SIMPLIFIE(X);} \
88 else{frac uu,vv,ww;if(DEBUG2)printf("%d/%d %d/%d %d/%d %d/%d \n",A.num,A.den,B.num,B.den,C.num,C.den,D.num,D.den); \
89 uu.num=B.num;vv.num=C.num;ww.num=D.den;uu.den=B.den;vv.den=C.den;ww.den=D.num; \
90 SIMPL(uu.num,vv.den);SIMPL(uu.num,ww.den);SIMPL(vv.num,uu.den);SIMPL(vv.num,ww.den);SIMPL(ww.num,uu.den);SIMPL(ww.num,vv.den); \
91 vv.num*=uu.num*ww.num;vv.den*=uu.den*ww.den; \
92 SUB(X,A,vv);if(DEBUG2)printf("%d/%d\n",X.num,X.den);}\
93 }
94 #define SUB(X,A,B) { \
95 if(A.num==0)X.num=-B.num,X.den=B.den; \
96 else if(B.num==0)X.num=A.num,X.den=A.den; \
97 else if(A.den==1&&B.den==1)X.num=A.num-B.num,X.den=1; \
98 else{long GDEN,AD,BD;AD=A.den,BD=B.den; \
99  if(A.den>B.den)G(GDEN,AD,BD) \
100  else G(GDEN,BD,AD); \
101  if(GDEN!=1)AD=AD/GDEN,BD=BD/GDEN; \
102  X.num=A.num*BD-B.num*AD;X.den=AD*BD; \
103  if(GDEN!=1){SIMPLIFIE(X);SIMPL(X.num,GDEN);X.den=X.den*GDEN;} \
104 }}
105 #define VIDE 3
106 #define EQUATION 1
107 #define INEQUATION 2
108 
110 {
111  /* nature vide=3 , equation=1 , inequation=2 */
112  typedef struct {int numero ; int nature ; } rangee ;
113  typedef struct {long num ; long den ; } f ;
114 
115  rangee ligne[MAX_VAR] ; int taille ;
116  rangee colonne[MAX_VAR] ;
117  f t[MAX_VAR][MAX_VAR] ;
118  f frac0={0,1}, frac1={1,1} ;
119 
120  Pcontrainte pc ;
121  Pvecteur pv ;
122  int premier_hash = PTR_NIL ; /* tete de liste des noms de variables */
123  static struct { Variable nom; int numero; int hash ; int val ; int succ ; } hashtable[MAX_VAR] ;
124  /* Necessaire de declarer "hashtable" static
125  * pour initialiser tout automatiquement a` 0.
126  * Necessaire de chainer les enregistrements
127  * pour reinitialiser a 0
128  * en sortie de la procedure.
129  */
130  frac rapport1, rapport2, min1, min2, pivot, quot1, quot2, cc ;
131  long compteur ; /* compte les variables */
132  long valeur,i,j,k,h, numeroligne ;
133 
134  void printfrac(f x) {
135  printf(" %3.1d/%-3.1d",x.num,x.den) ;
136  }
137 
138  void dump_table(int taille,rangee ligne[MAX_VAR],rangee colonne[MAX_VAR],f t[MAX_VAR][MAX_VAR]) {
139  int i,j ;
140 
141  printf("Taille=%2.1d\n",taille) ;
142  if(taille>0) {
143  for(i=0;i<taille;i++) { printf( " %4.1d(%1.1d)",colonne[i].numero,colonne[i].nature) ; }
144  printf("\n\n");
145  for(i=0;i<taille;i++) { printf( " %4.1d(%1.1d)",ligne[i].numero,ligne[i].nature) ;
146  for(j=0;j<taille;j++) printfrac(t[i][j]) ;
147  printf("\n") ;
148  }
149  }
150  }
151 
152  int hash(Variable s) /* calcule le hashcode d'une chaine
153  sous forme d'un nombre compris entre 0 et MAX_VAR */
154  { int i ;
155  i=((long)s % MAX_VAR);
156  return (i) ;
157  }
158 
159  int entree() {
160  /* retourne le nume'ro de l'entree de la Variable pv->var du
161  * Psysteme sc dans la table hashcodee, apres l'avoir creee si
162  * elle n'existait pas
163  */
164  int h, trouve ;
165  h = hash(pv->var) ; trouve=0 ;
166  while (hashtable[h].nom != 0) {
167  if (hashtable[h].nom==pv->var) {
168  trouve=1 ;
169  break ;
170  }
171  else { h = (h+1) % MAX_VAR ; }
172  }
173  if(!trouve) {
174  hashtable[h].succ=premier_hash ;
175  premier_hash = h ;
176  hashtable[h].val = PTR_NIL ;
177  hashtable[h].numero=compteur++ ;
178  hashtable[h].nom=pv->var ;
179  }
180  return (h) ;
181  }
182 
183  void pivoter(int taille, rangee ligne[], rangee colonne[], f *t[],
184  int i, int j)
185  { /* Pivote le tableau t ayant les caracteristiques
186  * taille ligne[] et colonne[] autour du pivot de
187  * coordonnees i et j */
188 
189  int i1,j1 ;
190  f x ;
191 
192  for(i1=0; i1<taille;i1++)
193  if((i1 != i) && (j1 != j)) { /* Cas general */
194  PIVOT(x,t[i1][j1],t[i1][j],t[i][j1],t[i][j])
195  AFF(t[i1][j1],x)
196  } else if((i1 != i) && (j1 == j)) {
197  PIVOT(x,frac0,t[i1][j],frac1,t[i][j])
198  AFF(t[i1][j1],x)
199  } else if(i1==i) AFF(t[i][j],frac1) ;
200  /* intervertir les variables de la ligne et de la colonne pivot */
201  i1=colonne[j].numero ;
202  colonne[j].numero=ligne[i].numero ;
203  ligne[i].numero=i1 ;
204  i1=colonne[j].nature ;
205  colonne[j].nature=ligne[i].nature ;
206  ligne[i].nature=i1 ;
207  }
208 
209  if(sc_empty_p(sc)) return sc_empty(sc->base) ;
210  taille=NB_EQ+NB_INEQ ;
211 
212 /* 1) Recherche des variables a` valeur totalement determinee */
213 
214  for(pc=sc->egalites, i=0 ; pc!=0 ; pc=pc->succ,i++ ) {
215  valeur = 0 ; /* le terme cst vaut 0 par defaut */
216  for(pv=pc->vecteur, j=0 ; pv!=0 ; pv=pv->succ) {
217  if(NONTCST) { h=entree() ; j++ ; }
218  else valeur = - pv->val ;
219  }
220  if(j==1) { ligne[i].nature = VIDE ;
221  if(hashtable[h].val == PTR_NIL)
222  hashtable[h].val = valeur ;
223  else if(hashtable[h].val != valeur)
224  return(sc_empty(sc->base)) ;
225  }
226  }
227 
228 /* 2) Enregistrement des egalites */
229 
230  for(pc=sc->egalites, numeroligne=1 ; pc!=0 ; pc=pc->succ, numeroligne++ ) {
231  if( ligne[numeroligne].nature==VIDE ) continue ;
232  valeur = 0 ; /* le terme cst vaut 0 par defaut */
233  for(pv=pc->vecteur, j=0 ; pv!=0 ; pv=pv->succ) {
234  if(NONTCST) { h=entree() ; t[numeroligne][NUMERO].num=pv->val ;
235  t[numeroligne][NUMERO].den=1 ;
236  }
237  else t[numeroligne][0].num= - pv->val,t[numeroligne][NUMERO].den=1;
238  }
239  }
240  dump_table(compteur, ligne, colonne, t) ;
241 
242 /* 3) Enregistrement des inegalites */
243 
244  for(pc=sc->inegalites ; pc!=0 ; pc=pc->succ, numeroligne++ ) {
245  valeur = 0 ; /* le terme cst vaut 0 par defaut */
246  for(pv=pc->vecteur, j=0 ; pv!=0 ; pv=pv->succ) {
247  if(NONTCST) { h=entree() ; t[numeroligne][NUMERO].num=pv->val ;
248  t[numeroligne][NUMERO].den=1 ;
249  }
250  else t[numeroligne][0].num= - pv->val,t[numeroligne][NUMERO].den=1;
251  }
252  }
253 
254 } /* FIN DE sc_min */
255 
256 main(int argc, char *argv[])
257 {
258 /* Programme de test de faisabilite'
259  * d'un ensemble d'equations et d'inequations.
260  */
261  FILE * f1;
262  Psysteme sc=sc_new(),sc1;
263  int i; /* compte les systemes, chacun dans un fichier */
264 
265 /* lecture et test de la faisabilite' de systemes sur fichiers */
266 
267  if(argc>=2) for(i=1;i<argc;i++){
268  if((f1 = fopen(argv[i],"r")) == NULL) {
269  fprintf(stdout,"Ouverture fichier %s impossible\n",
270  argv[1]);
271  exit(4);
272  }
273  printf("systeme initial \n");
274  if(sc_fscan(f1,&sc)) {
275  fprintf(stdout,"syntaxe correcte dans %s\n",argv[i]);
276  sc_fprint(stdout, sc, *variable_default_name);
277  printf("Nb_eq %d , Nb_ineq %d, dimension %d\n",
278  NB_EQ, NB_INEQ, DIMENSION) ;
279  if(sc_empty_p(sc1=sc_min(sc)))
280  printf("Systeme infaisable (insoluble) en rationnels\n") ;
281  else { printf("Systeme minimum :\n");
282  sc_fprint(stdout,sc1,*variable_default_name) ;
283  }
284  fclose(f1) ;
285  }
286  else {
287  fprintf(stderr,"erreur syntaxe dans %s\n",argv[1]);
288  exit(1);
289  }
290  }
291  else { f1=stdin ;
292 
293 /* lecture et test de la faisabilite' du systeme sur stdin */
294 
295  printf("systeme initial \n");
296  if(sc_fscan(f1,&sc)) {
297  fprintf(stdout,"syntaxe correcte dans %s\n",argv[1]);
298  sc_fprint(stdout, sc, *variable_default_name);
299  printf("Nb_eq %d , Nb_ineq %d, dimension %d\n",
300  NB_EQ, NB_INEQ, DIMENSION) ;
301  if(sc_empty_p(sc1=sc_min(sc)))
302  printf("Systeme infaisable (insoluble) en rationnels\n") ;
303  else { printf("Systeme minimum :\n");
304  sc_fprint(stdout,sc1,*variable_default_name) ;
305  }
306 
307  exit(0) ;
308  }
309  else {
310  fprintf(stderr,"erreur syntaxe dans %s\n",argv[1]);
311  exit(1);
312  }
313  }
314  exit(0) ;
315 } /* FIN DE main */
316 
static int num
Definition: bourdoncle.c:137
char * variable_default_name(Variable v)
char * variable_default_name(Variable v): returns the name of variable v
Definition: variable.c:81
#define exit(code)
Definition: misc-local.h:54
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
void pivoter(Psommet sys, Psommet ligne, Variable var, Psommet fonct)
Definition: plpivoter.c:131
Psysteme sc_empty(Pbase b)
Psysteme sc_empty(Pbase b): build a Psysteme with one unfeasible constraint to define the empty subsp...
Definition: sc_alloc.c:319
Psysteme sc_new(void)
Psysteme sc_new(): alloue un systeme vide, initialise tous les champs avec des valeurs nulles,...
Definition: sc_alloc.c:55
bool sc_empty_p(Psysteme sc)
bool sc_empty_p(Psysteme sc): check if the set associated to sc is the constant sc_empty or not.
Definition: sc_alloc.c:350
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
bool sc_fscan(FILE *f, Psysteme *ps)
bool sc_fscan(FILE * f, Psysteme * ps): construit un systeme d'inegalites et d'egalites lineaires a p...
Definition: sc_io.c:121
#define PIVOT(X, A, B, C, D)
Pivot : x = a - b c / d
Definition: sc_min.c:84
#define AFF(x, y)
Definition: sc_min.c:79
#define NB_INEQ
Definition: sc_min.c:60
#define VIDE
Definition: sc_min.c:105
Psysteme sc_min(Psysteme sc)
Definition: sc_min.c:109
#define NUMERO
Definition: sc_min.c:67
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
#define DIMENSION
Definition: sc_min.c:66
#define NB_EQ
Definition: sc_min.c:65
#define PTR_NIL
Hmmm.
Definition: sc_min.c:58
int printf()
#define NONTCST
Definition: sc_min.c:61
#define MAX_VAR
Definition: sc_min.c:68
main(int argc, char *argv[])
FIN DE sc_min.
Definition: sc_min.c:256
void pivot(frac *X, frac A, frac B, frac C, frac D, bool ofl_ctrl)
static frac frac0
static int hash(Variable s)
dump_tableau
static void printfrac(frac x)
static char * x
Definition: split_file.c:159
Pvecteur vecteur
struct Scontrainte * succ
Pcontrainte inegalites
Definition: sc-local.h:71
Pcontrainte egalites
Definition: sc-local.h:70
Pbase base
Definition: sc-local.h:75
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
Value val
Definition: vecteur-local.h:91
Variable var
Definition: vecteur-local.h:90
struct Svecteur * succ
Definition: vecteur-local.h:92
Entier valeur(Tableau *tp, int i, int j, Entier D)
Definition: traiter.c:178
void * Variable
arithmetique is a requirement for vecteur, but I do not want to inforce it in all pips files....
Definition: vecteur-local.h:60