PIPS
sc_intersection.c
Go to the documentation of this file.
1 /*
2 
3  $Id: sc_intersection.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 sc */
26 
27 #ifdef HAVE_CONFIG_H
28  #include "config.h"
29 #endif
30 
31 #include <stdlib.h>
32 #include <string.h>
33 #include <stdio.h>
34 
35 #include "linear_assert.h"
36 #include "boolean.h"
37 #include "arithmetique.h"
38 #include "vecteur.h"
39 #include "contrainte.h"
40 #include "sc.h"
41 
42 /* Psysteme sc_fusion(Psysteme s1, Psysteme s2): fusion de deux systemes
43  * de contraintes afin d'obtenir un systeme contenant les egalites
44  * et les inegalites des deux systemes donnes; aucune elimination de
45  * redondance n'est effectuee.
46  *
47  * attention: les deux systemes donnes, s1 et s2, sont detruits.
48  *
49  * Note: sc_fusion() est considere comme obsolete; voir sc_intersection()
50  * et sc_append().
51  *
52  * The base is not updated.
53  */
55 {
57 
58  if (SC_UNDEFINED_P(s1))
59  return s2;
60 
61  if (sc_rn_p(s1)) {
62  free(s1);
63  return s2;
64  }
65 
66  if (SC_UNDEFINED_P(s2))
67  return s1;
68 
69  if (sc_rn_p(s2)) {
70  free(s2);
71  return s1;
72  }
73 
74  if (s1->nb_eq != 0)
75  {
76  for (eq = s1->egalites;
77  eq->succ != (Pcontrainte) NULL;
78  eq = eq->succ)
79  ;
80  eq->succ = s2->egalites,
81  s1->nb_eq += s2->nb_eq;
82  }
83  else
84  s1->egalites = s2->egalites,
85  s1->nb_eq = s2->nb_eq;
86 
87  if (s1->nb_ineq != 0)
88  {
89  for (eq = s1->inegalites;
90  eq->succ != (Pcontrainte)NULL;
91  eq = eq->succ)
92  ;
93  eq->succ = s2->inegalites,
94  s1->nb_ineq += s2->nb_ineq;
95  }
96  else
97  s1->inegalites = s2->inegalites,
98  s1->nb_ineq = s2->nb_ineq;
99 
100  s2->inegalites = NULL;
101  s2->egalites = NULL;
102  sc_rm(s2);
103 
104  return(s1);
105 }
106 
107 /* Psysteme sc_intersection(Psysteme s1, Psysteme s2, Psysteme s3):
108  * calcul d'un systeme de contraintes s1 representant l'intersection
109  * des polyedres convexes definis par les systemes de contraintes s2 et s3.
110  *
111  * s1 := intersection(s2,s3);
112  * return s1;
113  *
114  * Les listes d'egalites et d'inegalites de s2 et de s3 sont simplement
115  * concatenees. Aucun test de redondance n'est effectuee.
116  * Cependant, les valeurs particulieres SC_RN (element neutre) et SC_EMPTY
117  * (element absorbant) sont traitees de maniere a donner des resultats
118  * corrects.
119  *
120  * Attention: le systeme s1 est d'abord vide de ses egalites et inegalites
121  * s'il est different de s2 et de s3; sinon, les modifications sont faites
122  * en place, sur s2 ou sur s3.
123  */
125 {
126  if(s1==s2) {
127  s1 = sc_append(s2,s3);
128  }
129  else if(s1==s3) {
130  s1 = sc_append(s3,s2);
131  }
132  else {
133  if(!SC_EMPTY_P(s1)) {
134  /* on pourrait se contenter de desallouer les deux listes
135  d'egalites et d'inegalites a condition d'avoir un sc_copy() */
136  sc_rm(s1);
137  }
138  s1 = sc_copy(s2);
139  s1 = sc_append(s1,s3);
140  }
141  return(s1);
142 }
143 
144 /* Psysteme sc_append(Psysteme s1, Psysteme s2): calcul de l'intersection
145  * des polyedres definis par s1 et par s2 sous forme d'un systeme de
146  * contraintes et renvoi de s1
147  *
148  * s1 := intersection(s1,s2)
149  * return s1;
150  *
151  * Attention, SC_RN est un element neutre et SC_EMPTY un element absorbant.
152  * SC_UNDEFINED devrait aussi etre teste proprement.
153  *
154  * Modifications:
155  * - mise a jour de la base de s1 (FI, 2/1/90)
156  */
158 Psysteme s1;
159 Psysteme s2;
160 {
161  Pcontrainte c;
162 
163  if(SC_RN_P(s1))
164  /* ne rien faire et renvoyer s2 */
165  s1 = sc_copy(s2);
166  else if(SC_RN_P(s2))
167  /* ne rien faire et renvoyer s1 */
168  ;
169  else if(SC_EMPTY_P(s1)) {
170  /* ne rien faire et renvoyer s1 */
171  /* on ne devrait jamais passer la dans le futur proche car
172  SC_EMPTY==SC_RN */
173  assert(false);
174  ;
175  }
176  else if(SC_EMPTY_P(s2)) {
177  /* desallouer s1 et renvoyer SC_EMPTY */
178  assert(false);
179  sc_rm(s1);
180  s1 = SC_EMPTY;
181  }
182  else {
183 
184  /* ni s1 ni s2 ne sont des systemes particuliers */
185  for(c = sc_egalites(s2); c != (Pcontrainte) NULL; c = c->succ) {
187  }
188  for(c = sc_inegalites(s2); c != (Pcontrainte) NULL; c = c->succ) {
190  }
191 
192  /* update s1 basis with s2's vectors */
193  base_append(&s1->base, s2->base);
194  s1->dimension = vect_size(s1->base);
195  }
196 
197  return s1;
198 }
199 
200 
201 /* Psysteme sc_safe_intersection(Psysteme s1, Psysteme s2, Psysteme s3)
202  * input :
203  * output : calcul d'un systeme de contraintes s1 representant l'intersection
204  * des polyedres convexes definis par les systemes de contraintes s2 et s3.
205  *
206  * s1 := intersection(s2,s3);
207  * return s1;
208  *
209  * modifies : s1 is modified if it is not undefined.
210  * comment :
211  * calcul d'un systeme de contraintes s1 representant l'intersection
212  * des polyedres convexes definis par les systemes de contraintes s2 et s3.
213  *
214  * Les listes d'egalites et d'inegalites de s2 et de s3 sont simplement
215  * concatenees. Aucun test de redondance n'est effectuee.
216  * Cependant, les valeurs particulieres sc_rn (element neutre) et sc_empty
217  * (element absorbant) sont traitees de maniere a donner des resultats
218  * corrects ( different de sc_intercestion).
219  *
220  * Attention: le systeme s1 est d'abord vide de ses egalites et inegalites
221  * s'il est different de s2 et de s3; sinon, les modifications sont faites
222  * en place, sur s2 ou sur s3.
223  */
225 Psysteme s1;
226 Psysteme s2;
227 Psysteme s3;
228 {
229  if(s1==s2) {
230  s1 = sc_safe_append(s2,s3);
231  }
232  else if(s1==s3) {
233  s1 = sc_safe_append(s3,s2);
234  }
235  else {
236  if(!SC_UNDEFINED_P(s1)) {
237  /* on pourrait se contenter de desallouer les deux listes
238  d'egalites et d'inegalites a condition d'avoir un sc_copy() */
239  sc_rm(s1);
240  }
241  s1 = sc_copy(s2);
242  s1 = sc_safe_append(s1,s3);
243  }
244  return(s1);
245 }
246 
247 /* Psysteme sc_safe_append(Psysteme s1, Psysteme s2)
248  * input :
249  * output : calcul de l'intersection des polyedres definis par s1 et
250  * par s2 sous forme d'un systeme de contraintes et renvoi de s1.
251  *
252  * s1 := intersection(s1,s2)
253  * return s1;
254  * modifies : s1.
255  * comment : sc_rn et sc_empty sont traite's de manie`re particulie`re pour tenir
256  * compte de leur se'mantique.
257  *
258  */
260 Psysteme s1;
261 Psysteme s2;
262 {
263  Pcontrainte c;
264  Pbase b;
265  Pvecteur coord;
266 
267  assert(!SC_UNDEFINED_P(s1) && !SC_UNDEFINED_P(s2));
268 
269  if(sc_rn_p(s1)) {
270  /* ne rien faire et renvoyer s2 apre`s mise a` jour de la base */
271  sc_rm(s1);
272  s1 = sc_copy(s2);
273  }
274  else if(sc_rn_p(s2))
275  /* ne rien faire et renvoyer s1 apre`s mise a` jour de la base */
276  ;
277  else if(sc_empty_p(s1))
278  /* ne rien faire et renvoyer s1 apre`s mise a` jour de la base */
279  ;
280  else if(sc_empty_p(s2)) {
281  /* ne rien faire et renvoyer s2 apre`s mise a` jour de la base */
282  sc_rm(s1);
283  s1 = sc_copy(s2);
284  }
285  else {
286  /* ni s1 ni s2 ne sont des systemes particuliers :
287  * on ajoute a` s1 les e'galite's et ine'galite's de s2 */
288  for(c = sc_egalites(s2); c != (Pcontrainte) NULL; c = c->succ) {
290  }
291  for(c = sc_inegalites(s2); c != (Pcontrainte) NULL; c = c->succ) {
293  }
294  }
295 
296  /* update s1 basis with s2's vectors */
297  b = s1->base;
298  for(coord = s2->base; !VECTEUR_NUL_P(coord); coord = coord->succ) {
299  Variable v = vecteur_var(coord);
300  b = base_add_variable(b, v);
301  }
302  s1->base = b;
303  s1->dimension = vect_size(b);
304 
305  return(s1);
306 }
307 
308 
309 /* bool sc_intersection_empty_p_ofl(ps1, ps2)
310  * input : two polyhedra
311  * output : true if their intersection is empty, false otherwise.
312  * modifies : nothing
313  * comment : calls sc_faisabilite_ofl in order to trap overflow errors
314  * BC, 1994.
315  */
317 Psysteme ps1, ps2;
318 {
319  Psysteme ps = SC_UNDEFINED;
320  bool result;
321  ps1 = sc_copy(ps1);
322  ps2 = sc_copy(ps2);
323  ps = sc_safe_intersection(ps,ps1,ps2);
324  result = !(sc_faisabilite_ofl(ps));
325  sc_rm(ps1);
326  sc_rm(ps2);
327  sc_rm(ps);
328  ps1 = ps2 = ps = NULL;
329  return result;
330 }
331 
332 /* returns the common subsystem if appropriate...
333  * s1 and s2 are modified accordingly.
334  */
336 {
337  Pcontrainte
338  e = extract_common_constraints(&s1->egalites, &s2->egalites, true),
339  i = extract_common_constraints(&s1->inegalites, &s2->inegalites, false);
340 
341  sc_fix(s1);
342  sc_fix(s2);
343 
344  return sc_make(e, i);
345 }
Pbase base_add_variable(Pbase b, Variable var)
Pbase base_add_variable(Pbase b, Variable v): add variable v as a new dimension to basis b at the end...
Definition: base.c:88
void base_append(Pbase *pb1, Pbase b2)
appends b2 to b1.
Definition: base.c:384
struct Scontrainte * Pcontrainte
Pcontrainte contrainte_copy(Pcontrainte c_in)
Have a look at contrainte_dup and contraintes_dup which reverse the order of the list This copy versi...
Definition: alloc.c:254
Pcontrainte extract_common_constraints(Pcontrainte *pc1, Pcontrainte *pc2, bool eq)
common (simply equal) contraints are extracted, whether equalities or inequalities.
Definition: binaires.c:285
void free(void *)
int vect_size(Pvecteur v)
package vecteur - reductions
Definition: reductions.c:47
#define assert(ex)
Definition: newgen_assert.h:41
Psysteme sc_make(Pcontrainte leg, Pcontrainte lineg)
Psysteme sc_make(Pcontrainte leg, Pcontrainte lineg): allocation et initialisation d'un systeme d'equ...
Definition: sc.c:78
bool sc_rn_p(Psysteme sc)
bool sc_rn_p(Psysteme sc): check if the set associated to sc is the whole space, rn
Definition: sc_alloc.c:369
void sc_fix(Psysteme s)
fix system s for coherency of the base and number of things.
Definition: sc_alloc.c:141
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
void sc_add_egalite(Psysteme p, Pcontrainte e)
void sc_add_egalite(Psysteme p, Pcontrainte e): macro ajoutant une egalite e a un systeme p; la base ...
Definition: sc_alloc.c:389
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_add_inegalite(Psysteme p, Pcontrainte i)
void sc_add_inegalite(Psysteme p, Pcontrainte i): macro ajoutant une inegalite i a un systeme p; la b...
Definition: sc_alloc.c:406
Psysteme sc_copy(Psysteme ps)
Psysteme sc_copy(Psysteme ps): duplication d'un systeme (allocation et copie complete des champs sans...
Definition: sc_alloc.c:230
Pcontrainte eq
element du vecteur colonne du systeme donne par l'analyse
Definition: sc_gram.c:108
Psysteme sc_append(Psysteme s1, Psysteme s2)
Psysteme sc_append(Psysteme s1, Psysteme s2): calcul de l'intersection des polyedres definis par s1 e...
bool sc_intersection_empty_p_ofl(Psysteme ps1, Psysteme ps2)
bool sc_intersection_empty_p_ofl(ps1, ps2) input : two polyhedra output : true if their intersection ...
Psysteme sc_safe_intersection(Psysteme s1, Psysteme s2, Psysteme s3)
Psysteme sc_safe_intersection(Psysteme s1, Psysteme s2, Psysteme s3) input : output : calcul d'un sys...
Psysteme sc_safe_append(Psysteme s1, Psysteme s2)
Psysteme sc_safe_append(Psysteme s1, Psysteme s2) input : output : calcul de l'intersection des polye...
Psysteme extract_common_syst(Psysteme s1, Psysteme s2)
returns the common subsystem if appropriate...
Psysteme sc_fusion(Psysteme s1, Psysteme s2)
package sc
Psysteme sc_intersection(Psysteme s1, Psysteme s2, Psysteme s3)
Psysteme sc_intersection(Psysteme s1, Psysteme s2, Psysteme s3): calcul d'un systeme de contraintes s...
s1
Definition: set.c:247
struct Scontrainte * succ
Pcontrainte inegalites
Definition: sc-local.h:71
Pcontrainte egalites
Definition: sc-local.h:70
Pbase base
Definition: sc-local.h:75
int nb_ineq
Definition: sc-local.h:73
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
#define vecteur_var(v)
#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