1 /******************************************************************************
2 * PIP : Parametric Integer Programming *
3 ******************************************************************************
5 ******************************************************************************
7 * Copyright Paul Feautrier, 1988, 1993, 1994, 1996, 2002 *
9 * This is free software; you can redistribute it and/or modify it under the *
10 * terms of the GNU General Public License as published by the Free Software *
11 * Foundation; either version 2 of the License, or (at your option) any later *
14 * This software is distributed in the hope that it will be useful, but *
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
19 * You should have received a copy of the GNU General Public License along *
20 * with software; if not, write to the Free Software Foundation, Inc., *
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
23 * Written by Cedric Bastoul *
25 ******************************************************************************/
27 /* Premiere version du 30 juillet 2001. */
33 #include <piplib/piplib.h>
35 extern long int cross_product
, limit
;
38 extern int compa_count
;
39 extern char dump_name
[] ;
42 /******************************************************************************
43 * Fonctions d'affichage des structures *
44 ******************************************************************************/
47 /* Fonction pip_matrix_print :
48 * Cette fonction se charge d'imprimer sur le flux 'foo' les informations
49 * que contient la structure de type PipMatrix qu'elle recoit en parametre.
50 * Premiere version : Ced. 29 juillet 2001.
51 * 24 octobre 2002 : premiere version MP.
53 void pip_matrix_print(FILE * foo
, PipMatrix
* Mat
)
56 unsigned NbRows
, NbColumns
;
58 fprintf(foo
,"%d %d\n", NbRows
=Mat
->NbRows
, NbColumns
=Mat
->NbColumns
) ;
59 for (i
=0;i
<NbRows
;i
++)
61 for (j
=0;j
<NbColumns
;j
++)
63 mpz_out_str(foo
,10,*p
++) ;
70 /* Fonction pip_vector_print :
71 * Cette fonction se charge d'imprimer sur le flux 'foo' les informations
72 * que contient la structure de type PipVector qu'elle recoit en parametre.
73 * Premiere version : Ced. 20 juillet 2001.
74 * 24 octobre 2002 : premiere version MP.
76 void pip_vector_print(FILE * foo
, PipVector
* vector
)
81 for (i
=0;i
<vector
->nb_elements
;i
++)
83 mpz_out_str(foo
,10,vector
->the_vector
[i
]) ;
84 if (mpz_cmp(vector
->the_deno
[i
],UN
) != 0)
86 mpz_out_str(foo
,10,vector
->the_deno
[i
]) ;
94 /* Fonction pip_newparm_print :
95 * Cette fonction se charge d'imprimer sur le flux 'foo' les informations
96 * que contient la structure de type PipNewparm qu'elle recoit en parametre.
97 * Le parametre indent est le nombre d'espaces blancs en debut de chaque
98 * ligne avant indentation. Une valeur negative de indent signifie qu'on ne
99 * desire pas d'indentation.
100 * Premiere version : Ced. 18 octobre 2001.
101 * 24 octobre 2002 : premiere version MP.
103 void pip_newparm_print(FILE * foo
, PipNewparm
* newparm
, int indent
)
108 { for (i
=0;i
<indent
;i
++) fprintf(foo
," ") ; /* Indent. */
109 fprintf(foo
,"(newparm ") ;
110 fprintf(foo
,"%d",newparm
->rank
) ;
111 fprintf(foo
," (div ") ;
112 pip_vector_print(foo
,newparm
->vector
) ;
114 mpz_out_str(foo
,10,newparm
->deno
) ;
115 fprintf(foo
,"))\n") ;
117 while ((newparm
= newparm
->next
) != NULL
) ;
122 /* Fonction pip_list_print :
123 * Cette fonction se charge d'imprimer sur le flux 'foo' les informations
124 * que contient la structure de type PipList qu'elle recoit en parametre.
125 * Le parametre indent est le nombre d'espaces blancs en debut de chaque
126 * ligne avant indentation. Une valeur negative de indent signifie qu'on ne
127 * desire pas d'indentation.
128 * Premiere version : Ced. 18 octobre 2001.
130 void pip_list_print(FILE * foo
, PipList
* list
, int indent
)
134 { for (i
=0;i
<indent
;i
++) fprintf(foo
," ") ; /* Indent. */
135 fprintf(foo
,"()\n") ;
138 { for (i
=0;i
<indent
;i
++) fprintf(foo
," ") ; /* Indent. */
139 fprintf(foo
,"(list\n") ;
141 { for (i
=0;i
<indent
+1;i
++) fprintf(foo
," ") ; /* Indent. */
142 pip_vector_print(foo
,list
->vector
) ;
145 while ((list
= list
->next
) != NULL
) ;
146 for (i
=0;i
<indent
;i
++) fprintf(foo
," ") ; /* Indent. */
152 /* Fonction pip_quast_print :
153 * Cette fonction se charge d'imprimer sur le flux 'foo' les informations
154 * que contient la structure de type PipQuast qu'elle recoit en parametre.
155 * Le parametre indent est le nombre d'espaces blancs en debut de chaque
156 * ligne avant indentation. Une valeur negative de indent signifie qu'on ne
157 * desire pas d'indentation.
158 * 20 juillet 2001 : Premiere version, Ced.
159 * 18 octobre 2001 : eclatement.
161 void pip_quast_print(FILE * foo
, PipQuast
* solution
, int indent
)
165 if (solution
!= NULL
)
166 { pip_newparm_print(foo
,solution
->newparm
,indent
) ;
167 if (solution
->condition
== NULL
)
168 pip_list_print(foo
,solution
->list
,indent
) ;
170 { for (i
=0;i
<indent
;i
++) fprintf(foo
," ") ; /* Indent. */
171 fprintf(foo
,"(if ") ;
172 pip_vector_print(foo
,solution
->condition
) ;
174 if (indent
>=0) /* Indent. */
175 { pip_quast_print(foo
,solution
->next_then
,indent
+1) ;
176 pip_quast_print(foo
,solution
->next_else
,indent
+1) ;
179 { pip_quast_print(foo
,solution
->next_then
,indent
) ;
180 pip_quast_print(foo
,solution
->next_else
,indent
) ;
182 for (i
=0;i
<indent
;i
++) fprintf(foo
," ") ; /* Indent. */
187 { for (i
=0;i
<indent
;i
++) fprintf(foo
," ") ; /* Indent. */
188 fprintf(foo
,"void\n") ;
193 /******************************************************************************
194 * Fonctions de liberation memoire *
195 ******************************************************************************/
198 /* Fonction pip_matrix_free :
199 * Cette fonction libere la memoire reservee a la structure de type PipMatrix
200 * que pointe son parametre.
201 * Premiere version : Ced. 29 juillet 2001.
202 * 24 octobre 2002 : premiere version MP.
204 void pip_matrix_free(PipMatrix
* matrix
)
209 for (i
=0;i
<matrix
->NbRows
;i
++)
210 for (j
=0;j
<matrix
->NbColumns
;j
++)
214 { free(matrix
->p_Init
) ;
221 /* Fonction pip_vector_free :
222 * Cette fonction libere la memoire reservee a la structure de type PipVector
223 * que pointe son parametre.
224 * 20 juillet 2001 : Premiere version, Ced.
225 * 18 octobre 2001 : simplification suite a l'eclatement de PipVector.
226 * 24 octobre 2002 : premiere version MP.
228 void pip_vector_free(PipVector
* vector
)
231 for (i
=0;i
<vector
->nb_elements
;i
++)
232 { mpz_clear(vector
->the_vector
[i
]);
233 mpz_clear(vector
->the_deno
[i
]);
235 free(vector
->the_vector
) ;
236 free(vector
->the_deno
) ;
241 /* Fonction pip_newparm_free :
242 * Cette fonction libere la memoire reservee a la structure de type PipNewparm
243 * que pointe son parametre. Sont liberes aussi tous les elements de la
244 * liste chainee dont il pouvait etre le depart.
245 * Premiere version : Ced. 18 octobre 2001.
246 * 24 octobre 2002 : premiere version MP.
248 void pip_newparm_free(PipNewparm
* newparm
)
249 { PipNewparm
* next
;
251 while (newparm
!= NULL
)
252 { next
= newparm
->next
;
253 mpz_clear(newparm
->deno
);
254 pip_vector_free(newparm
->vector
) ;
261 /* Fonction pip_list_free :
262 * Cette fonction libere la memoire reservee a la structure de type PipList
263 * que pointe son parametre. Sont liberes aussi tous les elements de la
264 * liste chainee dont il pouvait etre le depart.
265 * Premiere version : Ced. 18 octobre 2001.
267 void pip_list_free(PipList
* list
)
271 { next
= list
->next
;
272 pip_vector_free(list
->vector
) ;
279 /* Fonction pip_quast_free :
280 * Cette fonction libere la memoire reservee a la structure de type
281 * PipSolution que pointe son parametre. Sont liberees aussi toutes les
282 * differentes listes chainees qui pouvaient en partir.
283 * 20 juillet 2001 : Premiere version, Ced.
284 * 18 octobre 2001 : simplification suite a l'eclatement de PipVector.
286 void pip_quast_free(PipQuast
* solution
)
287 { if (solution
!= NULL
)
288 { if (solution
->newparm
!= NULL
)
289 pip_newparm_free(solution
->newparm
) ;
291 if (solution
->list
!= NULL
)
292 pip_list_free(solution
->list
) ;
294 if (solution
->condition
!= NULL
)
295 { pip_vector_free(solution
->condition
) ;
296 pip_quast_free(solution
->next_then
) ;
297 pip_quast_free(solution
->next_else
) ;
304 /******************************************************************************
305 * Fonctions d'acquisition de matrices *
306 ******************************************************************************/
309 /* Fonction pip_matrix_alloc :
310 * Fonction (tres) modifiee de Matrix_Alloc de la polylib. Elle alloue l'espace
311 * memoire necessaire pour recevoir le contenu d'une matrice de NbRows lignes
312 * et de NbColumns colonnes, et initialise les valeurs a 0. Elle retourne un
313 * pointeur sur l'espace memoire alloue.
314 * Premiere version : Ced. 18 octobre 2001.
315 * 24 octobre 2002 : premiere version MP.
317 PipMatrix
* pip_matrix_alloc(unsigned NbRows
, unsigned NbColumns
)
318 { PipMatrix
* matrix
;
322 matrix
= (PipMatrix
*)malloc(sizeof(PipMatrix
)) ;
324 { fprintf(stderr
, "Memory Overflow.\n") ;
327 matrix
->NbRows
= NbRows
;
328 matrix
->NbColumns
= NbColumns
;
331 matrix
->p_Init
= NULL
;
334 { if (NbColumns
== 0)
336 matrix
->p_Init
= NULL
;
339 { p
= (Entier
**)malloc(NbRows
*sizeof(Entier
*)) ;
341 { fprintf(stderr
, "Memory Overflow.\n") ;
344 q
= (Entier
*)malloc(NbRows
* NbColumns
* sizeof(Entier
)) ;
346 { fprintf(stderr
, "Memory Overflow.\n") ;
351 for (i
=0;i
<NbRows
;i
++)
353 for (j
=0;j
<NbColumns
;j
++)
354 mpz_init_set_si(*(q
+j
),0) ;
363 /* Fonction pip_matrix_read :
364 * Adaptation de Matrix_Read de la polylib. Cette fonction lit les donnees
365 * d'une matrice dans un fichier 'foo' et retourne un pointeur vers une
366 * structure ou elle a copie les informations de cette matrice. Les donnees
367 * doivent se presenter tq :
368 * - des lignes de commentaires commencant par # (optionnelles),
369 * - le nombre de lignes suivit du nombre de colonnes de la matrice, puis
370 * eventuellement d'un commentaire sur une meme ligne,
371 * - des lignes de la matrice, chaque ligne devant etre sur sa propre ligne de
372 * texte et eventuellement suivies d'un commentaire.
373 * Premiere version : Ced. 18 octobre 2001.
374 * 24 octobre 2002 : premiere version MP, attention, uniquement capable de
375 * lire des long long pour l'instant. On utilise pas
376 * mpz_inp_str car on lit depuis des char * et non des FILE.
378 PipMatrix
* pip_matrix_read(FILE * foo
)
379 { unsigned NbRows
, NbColumns
;
382 char *c
, s
[1024], str
[1024] ;
386 while (fgets(s
,1024,foo
) == 0) ;
387 while ((*s
=='#' || *s
=='\n') || (sscanf(s
," %u %u",&NbRows
,&NbColumns
)<2))
388 fgets(s
, 1024, foo
) ;
390 matrix
= pip_matrix_alloc(NbRows
,NbColumns
) ;
393 for (i
=0;i
<matrix
->NbRows
;i
++)
395 { c
= fgets(s
,1024,foo
) ;
396 while (isspace(*c
) && (*c
!= '\n'))
399 while (c
!= NULL
&& (*c
== '#' || *c
== '\n'));
402 { fprintf(stderr
, "Not enough rows.\n") ;
405 for (j
=0;j
<matrix
->NbColumns
;j
++)
406 { if (c
== NULL
|| *c
== '#' || *c
== '\n')
407 { fprintf(stderr
, "Not enough columns.\n") ;
410 /* NdCed : Dans le n ca met strlen(str). */
411 if (sscanf(c
,"%s%n",str
,&n
) == 0)
412 { fprintf(stderr
, "Not enough rows.\n") ;
415 sscanf(str
,FORMAT
,&val
) ;
416 mpz_init_set_si(*p
++,val
) ;
424 /******************************************************************************
425 * Fonction de resolution *
426 ******************************************************************************/
429 /* Fonction pip_solve :
430 * Cette fonction fait un appel a Pip pour la resolution d'un probleme. Le
431 * probleme est fourni dans les arguments. Deux matrices de la forme de celles
432 * utilisees dans la Polylib forment les systemes d'equations/inequations :
433 * un pour les inconnues, l'autre pour les parametres. Bg est le 'bignum', Nq
434 * est un booleen renseignant si on cherche une solution entiere (vrai=1) ou
435 * non (faux=0). Verbose est un booleen permettant de rendre Pip bavard
436 * (Verbose a vrai=1), il imprimera alors la plupart de ses traitements dans le
437 * fichier dont le nom est dans la variable d'environnement DEBUG, ou si DEBUG
438 * n'est pas placee, dans un nouveau fichier de nom genere par mkstemp, si
439 * Verbose est a faux=0, Pip restera muet. Simplify est un booleen permettant
440 * de demander a Pip de simplifier sa solution (en eliminant les formes de type
441 * 'if #[...] () ()') quand il est a vrai=1, ou non quand il est a faux=0. Max
442 * n'est pas encore utilise et doit etre mis a 0. Cette fonction retourne la
443 * solution sous la forme d'un arbre de structures PipQuast.
444 * 30 juillet 2001 : Premiere version, Ced.
445 * 18 octobre 2001 : suppression de l'argument Np, le nombre de parametres. Il
446 * est a present deduit de ineqpar. Si ineqpar vaut NULL,
447 * c'est que Np vaut 0. S'il y a des parametres mais pas de
448 * contraintes dessus, ineqpar sera une matrice de 0 lignes
449 * mais du bon nombre de colonnes (Np + 2).
450 * 24 octobre 2002 : premiere version MP.
452 PipQuast
* pip_solve(inequnk
, ineqpar
, Bg
, Nq
, Verbose
, Simplify
, Max
)
453 PipMatrix
* inequnk
, * ineqpar
;
454 int Bg
, Nq
, Verbose
, Simplify
, Max
;
455 { Tableau
* ineq
, * context
, * ctxt
;
456 int i
, Np
, Nn
, Nl
, Nm
, p
, q
, xq
, non_vide
;
458 struct high_water_mark hq
;
459 PipQuast
* solution
;
461 mpz_init_set_si(UN
, 1);
462 mpz_init_set_si(ZERO
, 0);
464 /* initialisations diverses :
465 * - la valeur de Verbose est placee dans sa variable globale. Dans le cas
466 * ou on doit etre en mode verbose, on ouvre le fichier dans lequel
467 * ecrire les tracages. Si la variable d'environnement DEBUG est placee,
468 * on ecrira dans le nom de fichier correspondant, sinon, dans un nouveau
469 * fichier de nom genere par mkstemp,
470 * - limit est mis au 0 long int (sa valeur par defaut dans Pip original),
471 * - on lance les initialisations pour tab et sol (autres mises en place
472 * de variables globales).
476 { g
= getenv("DEBUG") ;
478 { dump
= fopen(g
, "w") ;
480 { fprintf(stderr
,"%s unaccessible\n",g
) ;
485 { mkstemp(dump_name
) ;
486 dump
= fopen(dump_name
, "w") ;
493 /* Si inequnk est NULL, la solution est automatiquement void (NULL). */
495 { /* Np vaut 0 si ineqpar vaut NULL, ineqpar->NbColumns - 2 sinon (on a -1
496 * pour la constante et -1 pour le marqueur d'egalite/inegalite = -2).
498 Np
= (ineqpar
== NULL
) ? 0 : ineqpar
->NbColumns
- 2 ;
499 /* Calcul du nombre d'inconnues du probleme. Comme les matrices d'entree
500 * sont sous la forme de la polylib.
502 Nn
= inequnk
->NbColumns
- Np
- 2 ;
503 /* Calcul du nombre d'inequations du probleme. Le format de matrice de la
504 * polylib permet les egalites, on doit donc les compter double quand il
507 Nl
= inequnk
->NbRows
;
508 for (i
=0;i
<inequnk
->NbRows
;i
++)
509 if (**(inequnk
->p
+ i
) == 0)
512 /* On prend les 'marques' de debut de traitement. */
517 /* On s'assure d'abord que le systeme pour le contexte n'est pas vide
518 * avant de commencer le traitement. Si c'est le cas, la solution est
522 { Nm
= ineqpar
->NbRows
;
523 for (i
=0;i
<ineqpar
->NbRows
;i
++)
524 if (**(ineqpar
->p
+ i
) == 0)
526 context
= tab_Matrix2Tableau(ineqpar
,Nm
,Np
,0) ;
528 { /* Traduction du format de matrice de la polylib vers celui de
529 * traitement de Pip. Puis traitement proprement dit.
531 ctxt
= expanser(context
, Np
, Nm
, Np
+1, Np
, 0, 0) ;
532 traiter(ctxt
, NULL
, True
, Np
, 0, Nm
, 0, -1) ;
533 non_vide
= is_not_Nil(p
) ;
541 context
= NULL
; /* ATTENTION, en toute rigueur on devrait faire un
542 * tab_Matrix2Tableau d'une matrice 0*0.
548 fprintf(dump
, "%d %d %d %d %d %d\n",Nn
, Np
, Nl
, Nm
, Bg
, Nq
) ;
550 /* S'il est possible de trouver une solution, on passe au traitement. */
552 { ineq
= tab_Matrix2Tableau(inequnk
,Nl
,Nn
,Nn
) ;
554 traiter(ineq
, context
, Nq
, Nn
, Np
, Nl
, Nm
, Bg
) ;
559 /* On traduit la solution du format de solution de Pip vers un arbre
560 * de structures de type PipQuast.
562 solution
= sol_quast_edit(&xq
,NULL
) ;