PIPS
io.c
Go to the documentation of this file.
1 /*
2 
3  $Id: io.c 1671 2019-06-26 19:14:11Z 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 contrainte - operations d'entree-sortie
26  */
27 
28 
29 /* modifications :
30  * - ajout du parame`tre a_la_fortran pour une impression compatible avec
31  * Fortran (permet a` certains logiciels externes de re'cupe'rer les
32  * syste`mes sous un format compatible au leur. BA, avril 1994.
33  */
34 
35 /*LINTLIBRARY*/
36 
37 #ifdef HAVE_CONFIG_H
38  #include "config.h"
39 #endif
40 
41 #include <stdio.h>
42 #include <string.h>
43 #include <stdlib.h>
44 #include "linear_assert.h"
45 
46 #include "boolean.h"
47 #include "arithmetique.h"
48 #include "vecteur.h"
49 #include "contrainte.h"
50 
51 /* void contrainte_fprint(FILE * fp, Pcontrainte c, bool is_inegalite,
52  * char * (*variable_name)()):
53  *
54  * imprime dans le fichier fp la contrainte c, de type egalite ou inegalite
55  * suivant la valeur du booleen is_inegalite, en utilisant la fonction
56  * variable_name pour trouver les noms des variables.
57  *
58  * Pour suivre les convention usuelles, le terme constant est imprime
59  * comme membre droit.
60  *
61  * On considere que CONTRAINTE_UNDEFINED => CONTRAINTE_NULLE
62  *
63  * Resultat:
64  * 2 * I - J = 4 LF
65  * -I + 3 * J <= 5 LF
66  *
67  * Note: l'impression se termine par un LF
68  * aucun routine ne sait lire ce format
69  * ancien nom eq_print
70  */
71 
72 /* returns the constant */
73 static Value
75  FILE * fp,
76  Pvecteur v,
77  char * (*variable_name)(Variable))
78 {
79  short int debut = 1;
80  Value constante = VALUE_ZERO;
81 
82  while (!VECTEUR_NUL_P(v)) {
83  Variable var = var_of(v);
84  Value coeff = val_of(v);
85  if (var!=TCST) {
86  char signe;
87 
88  if (value_notzero_p(coeff)) {
89 
90  if (value_pos_p(coeff))
91  signe = (debut) ? ' ' : '+';
92  else {
93  signe = '-';
94  coeff = value_uminus(coeff);
95  };
96  debut = 0;
97  (void) fprintf(fp, "%c", signe);
98  if (value_notone_p(coeff))
99  (void) fprintf(fp, " "), fprint_Value(fp, coeff);
100  (void) fprintf(fp, " %s ", variable_name(var));
101  }
102  }
103  else
104  /* on admet plusieurs occurences du terme constant!?! */
105  value_addto(constante, coeff);
106 
107  v = v->succ;
108  }
109 
110  /* To handle cases where the constraint only has constant (this is a bug
111  somewhere, we must remove the constraint). If we print:
112  "<= constant ," then sc_fscan cannot read this output, so let's print:
113  " constant <= constant ," which is readable by sc_fscan, and doesn't change
114  the sc.
115  */
116  if (debut) {
117  (void) fprintf(fp, " "), fprint_Value(fp, constante), fprintf(fp, " ");
118  }
119 
120  return constante;
121 }
122 
123 void contrainte_fprint(fp,c,is_inegalite,variable_name)
124 FILE *fp;
125 Pcontrainte c;
126 bool is_inegalite;
127 char * (*variable_name)(Variable);
128 {
129  Pvecteur v;
130  Value constante = VALUE_ZERO;
131 
132  if (!CONTRAINTE_UNDEFINED_P(c))
133  v = contrainte_vecteur(c);
134  else
135  v = VECTEUR_NUL;
136 
137  assert(vect_check(v));
138 
139  constante = fprint_contrainte_vecteur(fp, v, variable_name);
140 
141  (void) fprintf(fp, " %s ", is_inegalite? "<=": "==");
142  fprint_Value(fp, value_uminus(constante));
143  fprintf(fp, " ,\n");
144 }
145 
146 /* void egalite_fprint(FILE * fp, Pcontrainte eg, char * (*variable_name)()):
147  * impression d'une egalite eg dans le fichier fp avec des noms de
148  * variables donnes par variable_name; voir contrainte_fprint
149  *
150  * Ancien nom: eg_print(), print_eq()
151  */
152 void egalite_fprint(FILE *fp, Pcontrainte eg, char * (*variable_name)(Variable))
153 {
154  contrainte_fprint(fp,eg,false,variable_name);
155 }
156 
157 /* void egalite_dump(Pcontrainte c): impression "physique" d'une egalite;
158  * utilise en debugging
159  */
162 }
163 
164 /* void inegalite_fprint(FILE * fp, Pcontrainte ineg,
165  * char * (*variable_name)()):
166  * impression d'une inegalite ineg dans le fichier fp avec des noms de
167  * variables donnes par variable_name; voir contrainte_fprint
168  *
169  * Ancien nom: ineg_print(), print_ineq()
170  */
172 FILE *fp;
173 Pcontrainte ineg;
174 char * (*variable_name)(Variable);
175 {
176  contrainte_fprint(fp,ineg,true,variable_name);
177 }
178 
179 /* void inegalite_dump(Pcontrainte c): impression "physique" d'une inegalite;
180  * utilise en debugging
181  */
184 }
185 
186 /* void egalites_fprint(FILE * fp, Pcontrainte eg, char * (*variable_name)()):
187  * impression d'une liste d'egalites eg dans le fichier fp avec des noms de
188  * variables donnes par variable_name; voir contrainte_fprint
189  *
190  * Ancien nom: fprint_leq()
191  */
193 FILE *fp;
194 Pcontrainte eg;
195 char * (*variable_name)(Variable);
196 {
197  for( ; eg != NULL; eg = eg->succ)
198  contrainte_fprint(fp,eg,false,variable_name);
199 }
200 
202 {egalites_fprint(stderr, eg, variable_debug_name);}
203 
204 /* void inegalites_fprint(FILE * fp, Pcontrainte ineg,
205  * char * (*variable_name)()):
206  * impression d'une liste d'inegalites ineg dans le fichier fp avec des noms de
207  * variables donnes par variable_name; voir contrainte_fprint
208  *
209  * Ancien nom: fprint_lineq()
210  */
212 FILE *fp;
213 Pcontrainte ineg;
214 char * (*variable_name)(Variable);
215 {
216  for( ; ineg != NULL; ineg = ineg->succ)
217  contrainte_fprint(fp,ineg,true,variable_name);
218 }
219 
222 
223 void
224 sprint_operator(char *s, bool is_inegalite, bool a_la_fortran)
225 {
226  (void) sprintf(s, "%s",(is_inegalite? (a_la_fortran? ".LE.": "<="):
227  (a_la_fortran? ".EQ.": "==")));
228 }
229 
230 static char *
231 heuristique_1(s, v, is_inegalite, variable_name, a_la_fortran)
232 char * s;
233 Pvecteur v;
234 bool is_inegalite;
235 char * (*variable_name)(Variable);
236 bool a_la_fortran;
237 {
238  short int debut = 1;
239  Value constante = VALUE_ZERO;
240 
241  while (!VECTEUR_NUL_P(v)) {
242  Variable var = var_of(v);
243  Value coeff = val_of(v);
244  if (var!=TCST) {
245  char signe;
246 
247  if (value_notzero_p(coeff)) {
248  if (value_pos_p(coeff))
249  signe = (debut) ? ' ' : '+';
250  else {
251  signe = '-';
252  coeff = value_uminus(coeff);
253  };
254  debut = 0;
255  (void) sprintf(s+strlen(s),"%c", signe);
256  if (value_notone_p(coeff))
257  (void) sprint_Value(s+strlen(s), coeff);
258  (void) sprintf(s+strlen(s), "%s", variable_name(var));
259  }
260  }
261  else
262  /* on admet plusieurs occurences du terme constant!?! */
263  value_addto(constante, coeff);
264 
265  v = v->succ;
266  }
267 
268  (void) sprint_operator(s+strlen(s), is_inegalite, a_la_fortran);
269  (void) sprint_Value(s+strlen(s), value_uminus(constante));
270 
271  return s;
272 }
273 
274 static char *
275 heuristique_3(s, v, is_inegalite, variable_name, a_la_fortran)
276 char * s;
277 Pvecteur v;
278 bool is_inegalite;
279 char * (*variable_name)(Variable);
280 bool a_la_fortran;
281 {
282  Pvecteur coord;
283  short int debut = true;
284  int positive_terms = 0;
285  int negative_terms = 0;
286  Value const_coeff = 0;
287  bool const_coeff_p = false;
288 
289  if(!is_inegalite) {
290  for(coord = v; !VECTEUR_NUL_P(coord); coord = coord->succ) {
291  if(vecteur_var(coord)!= TCST) {
292  if(value_pos_p(vecteur_val(coord)))
293  positive_terms++;
294  else
295  negative_terms++;
296  }
297  }
298 
299  if(negative_terms > positive_terms) {
300  vect_chg_sgn(v);
301  }
302  }
303 
304  positive_terms = 0;
305  negative_terms = 0;
306 
307  for(coord = v; !VECTEUR_NUL_P(coord); coord = coord->succ) {
308  Value coeff = vecteur_val(coord);
309  Variable var = vecteur_var(coord);
310 
311  if (value_pos_p(coeff)) {
312  positive_terms++;
313  if (debut) {
314  debut = false;
315  if (value_one_p(coeff) && var!=TCST)
316  (void) sprintf(s+strlen(s),"%s",
317  variable_name(vecteur_var(coord)));
318  else if(!term_cst(coord) || is_inegalite){
319  (void) sprint_Value(s+strlen(s), coeff);
320  (void) sprintf(s+strlen(s),"%s", variable_name(var));
321  }
322  else {
323  debut = true;
324  positive_terms--;
325  }
326  }
327  else
328  if (value_one_p(coeff) && var!=TCST)
329  (void) sprintf(s+strlen(s),"+%s", variable_name(var));
330  else if(!term_cst(coord) || is_inegalite) {
331  (void) sprintf(s+strlen(s),"+");
332  (void) sprint_Value(s+strlen(s), coeff);
333  (void) sprintf(s+strlen(s),"%s", variable_name(var));
334  }
335  else
336  positive_terms--;
337  }
338  }
339 
340  if(positive_terms == 0)
341  (void) sprintf(s+strlen(s),"0");
342 
343  (void) sprint_operator(s+strlen(s), is_inegalite, a_la_fortran);
344 
345  debut = true;
346  for(coord = v; !VECTEUR_NUL_P(coord); coord = coord->succ) {
347  Value coeff = vecteur_val(coord);
348  Variable var = var_of(coord);
349 
350  if(term_cst(coord) && !is_inegalite) {
351  /* Save the constant term for future use */
352  const_coeff_p = true;
353  const_coeff = coeff;
354  /* And now, a lie... In fact, rhs_terms++ */
355  negative_terms++;
356  }
357  else if (value_neg_p(coeff)) {
358  negative_terms++;
359  if (debut == true) {
360  debut = false;
361  if (value_mone_p(coeff) && var!=TCST)
362  (void) sprintf(s+strlen(s),"%s", variable_name(var));
363  else {
364  (void) sprint_Value(s+strlen(s), value_uminus(coeff));
365  (void) sprintf(s+strlen(s),"%s", variable_name(var));
366  }
367  }
368  else
369  if (value_mone_p(coeff) && var!=TCST)
370  (void) sprintf(s+strlen(s),"+%s", variable_name(var));
371  else {
372  (void) sprintf(s+strlen(s),"+");
373  (void) sprint_Value(s+strlen(s), value_uminus(coeff));
374  (void) sprintf(s+strlen(s),"%s", variable_name(var));
375  }
376  }
377  }
378 
379  if(negative_terms == 0)
380  (void) sprintf(s+strlen(s),"0");
381  else if(const_coeff_p) {
382  assert(value_notzero_p(const_coeff));
383 
384  if(!debut && value_neg_p(const_coeff))
385  (void) sprintf(s+strlen(s), "+");
386 
387  sprint_Value(s+strlen(s), value_uminus(const_coeff));
388  }
389 
390  return s;
391 }
392 
393 /* char * contrainte_sprint(char * s, Pcontrainte c, bool is_inegalite,
394  * char * (*variable_name)()):
395  * Traduction d'une contrainte c en une chaine s de caracteres ASCII.
396  * Les noms des variables sont recuperes via la fonction variable_name().
397  * Egalites et inegalites sont traitees.
398  *
399  * La chaine s doit avoir ete allouee par le programme appelant, avec une
400  * longueur suffisante. Pour etre propre, il faudrait aussi passer cette
401  * longueur.
402  *
403  * Plusieurs heuristiques d'impression ont ete proposees:
404  * - h1: mettre le terme constant en partie droite (Francois Irigoin);
405  * inconvenient: -I <= -1 au lieu de I >= 1
406  * - h2: minimiser le nombre de signes "moins" en prenant la contrainte
407  * opposee si necessaire; le signe du terme constant n'est pas
408  * pris en compte (Francois Irigoin); inconvenient: I == J est
409  * imprime sous la forme I - J == 0
410  * - h3: mettre les termes du bon cote pour ne pas avoir de signe "moins"
411  * (Michel Lenci); inconvenient: I == -1 est imprime comme I+1 == 0
412  *
413  * Pour avoir de bons resultats, il doit sans doute falloir faire du cas
414  * par cas, distinguer les egalites des inegalites et prendre en compte
415  * le nombre de termes de la contrainte. A ameliorer experimentalement.
416  *
417  * Note: variable_name() should return an empty string for constant terms
418  *
419  * Modifications:
420  * - suppression de l'impression de la virgule de separation en fin
421  * de chaine (Francois Irigoin, 7 mai 1990)
422  */
423 char *
424 contrainte_sprint(s, c, is_inegalite, variable_name)
425 char * s;
426 Pcontrainte c;
427 bool is_inegalite;
428 char * (*variable_name)(Variable);
429 {
430  s = contrainte_sprint_format(s, c, is_inegalite, variable_name, false);
431  return s;
432 }
433 
434 char *
436  char * s,
437  Pcontrainte c,
438  bool is_inegalite,
439  char * (*variable_name)(Variable),
440  bool a_la_fortran)
441 {
442  Pvecteur v;
443  int heuristique = 3;
444 
445  if (!CONTRAINTE_UNDEFINED_P(c))
446  v = contrainte_vecteur(c);
447  else
448  v = VECTEUR_NUL;
449 
450  assert(vect_check(v));
451 
452  switch(heuristique) {
453  case 1: s = heuristique_1(s, v, is_inegalite, variable_name, a_la_fortran);
454  break;
455  case 3: s = heuristique_3(s, v, is_inegalite, variable_name, a_la_fortran);
456  break;
457  default: contrainte_error("contrainte_sprint", "unknown heuristics\n");
458  }
459 
460  return s;
461 }
462 
463 /* void egalite_fprint(FILE * fp, Pcontrainte eg, char * (*variable_name)()):
464  * impression d'une egalite eg dans la chaine s avec des noms de
465  * variables donnes par variable_name; voir contrainte_sprint
466  */
467 char *
469 char *s;
470 Pcontrainte eg;
471 char * (*variable_name)(Variable);
472 {
473  return contrainte_sprint(s, eg, false, variable_name);
474 }
475 
476 char *
478 char * s;
479 Pcontrainte ineg;
480 char * (*variable_name)(Variable);
481 {
482  return contrainte_sprint(s, ineg, true, variable_name);
483 }
484 
485 char *
487 char *s;
488 Pcontrainte eg;
489 char * (*variable_name)(Variable);
490 bool a_la_fortran;
491 {
493  (s, eg, false, variable_name, a_la_fortran);
494 }
495 
496 char *
497 inegalite_sprint_format(s, ineg, variable_name, a_la_fortran)
498 char * s;
499 Pcontrainte ineg;
500 char * (*variable_name)(Variable);
501 bool a_la_fortran;
502 {
504  (s, ineg, true, variable_name, a_la_fortran);
505 }
#define value_pos_p(val)
#define VALUE_ZERO
#define value_mone_p(val)
#define value_notzero_p(val)
#define value_uminus(val)
unary operators on values
#define value_notone_p(val)
#define value_one_p(val)
int Value
#define value_addto(ref, val)
#define value_neg_p(val)
#define CONTRAINTE_UNDEFINED_P(c)
#define contrainte_vecteur(c)
passage au champ vecteur d'une contrainte "a la Newgen"
void contrainte_error(char *, char *,...)
error.c
Definition: error.c:49
void sprint_Value(char *s, Value v)
Definition: io.c:53
void fprint_Value(FILE *f, Value v)
Definition: io.c:42
void egalite_fprint(FILE *fp, Pcontrainte eg, char *(*variable_name)(Variable))
void egalite_fprint(FILE * fp, Pcontrainte eg, char * (*variable_name)()): impression d'une egalite e...
Definition: io.c:152
void inegalites_fprint(FILE *fp, Pcontrainte ineg, char *(*variable_name)(Variable))
void inegalites_fprint(FILE * fp, Pcontrainte ineg, char * (*variable_name)()): impression d'une list...
Definition: io.c:211
char * inegalite_sprint_format(char *s, Pcontrainte ineg, char *(*variable_name)(Variable), bool a_la_fortran)
Definition: io.c:497
void egalite_dump(Pcontrainte c)
void egalite_dump(Pcontrainte c): impression "physique" d'une egalite; utilise en debugging
Definition: io.c:160
static char * heuristique_1(char *s, Pvecteur v, bool is_inegalite, char *(*variable_name)(Variable), bool a_la_fortran)
Definition: io.c:231
void inegalite_fprint(FILE *fp, Pcontrainte ineg, char *(*variable_name)(Variable))
void inegalite_fprint(FILE * fp, Pcontrainte ineg, char * (*variable_name)()): impression d'une inega...
Definition: io.c:171
char * egalite_sprint_format(char *s, Pcontrainte eg, char *(*variable_name)(Variable), bool a_la_fortran)
Definition: io.c:486
static char * heuristique_3(char *s, Pvecteur v, bool is_inegalite, char *(*variable_name)(Variable), bool a_la_fortran)
Definition: io.c:275
void egalites_fprint(FILE *fp, Pcontrainte eg, char *(*variable_name)(Variable))
void egalites_fprint(FILE * fp, Pcontrainte eg, char * (*variable_name)()): impression d'une liste d'...
Definition: io.c:192
void inegalites_dump(Pcontrainte eg)
Definition: io.c:220
char * inegalite_sprint(char *s, Pcontrainte ineg, char *(*variable_name)(Variable))
Definition: io.c:477
void sprint_operator(char *s, bool is_inegalite, bool a_la_fortran)
Definition: io.c:224
void contrainte_fprint(FILE *fp, Pcontrainte c, bool is_inegalite, char *(*variable_name)(Variable))
Definition: io.c:123
void egalites_dump(Pcontrainte eg)
Definition: io.c:201
char * contrainte_sprint(char *s, Pcontrainte c, bool is_inegalite, char *(*variable_name)(Variable))
char * contrainte_sprint(char * s, Pcontrainte c, bool is_inegalite, char * (*variable_name)()): Trad...
Definition: io.c:424
char * egalite_sprint(char *s, Pcontrainte eg, char *(*variable_name)(Variable))
void egalite_fprint(FILE * fp, Pcontrainte eg, char * (*variable_name)()): impression d'une egalite e...
Definition: io.c:468
void inegalite_dump(Pcontrainte c)
void inegalite_dump(Pcontrainte c): impression "physique" d'une inegalite; utilise en debugging
Definition: io.c:182
static Value fprint_contrainte_vecteur(FILE *fp, Pvecteur v, char *(*variable_name)(Variable))
package contrainte - operations d'entree-sortie
Definition: io.c:74
char * contrainte_sprint_format(char *s, Pcontrainte c, bool is_inegalite, char *(*variable_name)(Variable), bool a_la_fortran)
Definition: io.c:435
bool vect_check(Pvecteur cv)
bool vect_check(Pvecteur v): renvoie true si le vecteur v est coherent avec les specifications du pac...
Definition: reductions.c:529
char *(* variable_debug_name)(Variable)
Debug support: pointer to the function used by debug print outs.
Definition: variable.c:114
#define assert(ex)
Definition: newgen_assert.h:41
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * variable_name(Variable v)
polynome_ri.c
Definition: polynome_ri.c:73
void vect_chg_sgn(Pvecteur v)
void vect_chg_sgn(Pvecteur v): multiplie v par -1
Definition: scalaires.c:151
struct Scontrainte * succ
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
#define TCST
VARIABLE REPRESENTANT LE TERME CONSTANT.
#define vecteur_val(v)
#define vecteur_var(v)
#define val_of(varval)
#define VECTEUR_NUL
DEFINITION DU VECTEUR NUL.
#define VECTEUR_NUL_P(v)
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
#define var_of(varval)
#define term_cst(varval)