PIPS
sc_enveloppe.c
Go to the documentation of this file.
1 /*
2 
3  $Id: sc_enveloppe.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 polyedre: enveloppe convexe de deux systemes lineaires
26  *
27  * Ce module est range dans le package polyedre bien qu'il soit utilisable
28  * en n'utilisant que des systemes lineaires (package sc) parce qu'il
29  * utilise lui-meme des routines sur les polyedres.
30  *
31  * Francois Irigoin, Janvier 1990
32  * Corinne Ancourt, Fabien Coelho from time to time (1999/2000)
33  */
34 
35 #ifdef HAVE_CONFIG_H
36  #include "config.h"
37 #endif
38 
39 #include <stdio.h>
40 #include <stdlib.h>
41 
42 #include "linear_assert.h"
43 #include "boolean.h"
44 #include "arithmetique.h"
45 #include "vecteur.h"
46 #include "contrainte.h"
47 #include "sc.h"
48 
49 #include "sommet.h"
50 #include "ray_dte.h"
51 #include "sg.h"
52 
53 #include "polyedre.h"
54 
55 /* Psysteme sc_enveloppe_chernikova_ofl_ctrl(Psysteme s1, s2, int ofl_ctrl)
56  * input :
57  * output :
58  * modifies : s1 and s2 are NOT modified.
59  * comment : s1 and s2 must have a basis.
60  *
61  * s = enveloppe(s1, s2);
62  * return s;
63  *
64  * calcul d'une representation par systeme
65  * lineaire de l'enveloppe convexe des polyedres definis par les systemes
66  * lineaires s1 et s2
67  */
69 Psysteme s1;
70 Psysteme s2;
71 int ofl_ctrl;
72 {
73  Psysteme s = SC_UNDEFINED;
74  volatile bool catch_performed = false;
75  /* mem_spy_begin(); */
76 
77  assert(!SC_UNDEFINED_P(s1) && !SC_UNDEFINED_P(s2));
78 
79  // yuk
80  if (ofl_ctrl == OFL_CTRL)
81  {
82  ofl_ctrl = FWD_OFL_CTRL;
83  catch_performed = true;
85  //CATCH(overflow_error) {
86  /*
87  * PLEASE do not remove this warning.
88  *
89  * BC 24/07/95
90  */
91  fprintf(stderr, "[sc_enveloppe_chernikova_ofl_ctrl] "
92  "arithmetic error occured\n" );
93  s = sc_rn(base_dup(sc_base(s1)));
94  return s;
95  }
96  }
97 
98  if (SC_RN_P(s2) || sc_rn_p(s2) || sc_dimension(s2)==0
99  || sc_empty_p(s1) || !sc_faisabilite_ofl(s1))
100  {
101  Psysteme sc2 = sc_dup(s2);
102  sc2 = sc_elim_redond(sc2);
103  s = SC_UNDEFINED_P(sc2)? sc_empty(base_dup(sc_base(s2))): sc2;
104  }
105  else
106  {
107  if (SC_RN_P(s1) ||sc_rn_p(s1) || sc_dimension(s1)==0
108  || sc_empty_p(s2) || !sc_faisabilite_ofl(s2))
109  {
110  Psysteme sc1 = sc_dup(s1);
111  sc1 = sc_elim_redond(sc1);
112  s = SC_UNDEFINED_P(sc1)? sc_empty(base_dup(sc_base(s1))): sc1;
113  }
114  else
115  {
116  /* calcul de l'enveloppe convexe */
117  s = sc_convex_hull(s1,s2);
118  /* printf("systeme final \n"); sc_dump(s); */
119  }
120  }
121  if (catch_performed)
123  /* mem_spy_end("sc_enveloppe_chernikova_ofl_ctrl"); */
124  return s;
125 }
126 
128 {
130 }
131 
132 /* call chernikova with compatible base.
133  */
135 {
136  Psysteme s;
137 
138  /* same common base! */
139  Pbase b1 = sc_base(s1), b2 = sc_base(s2), bu = base_union(b1, b2);
140  int d1 = sc_dimension(s1), d2 = sc_dimension(s2), du = vect_size(bu);
141 
142  sc_base(s1) = bu;
143  sc_dimension(s1) = du;
144  sc_base(s2) = bu;
145  sc_dimension(s2) = du;
146 
147  /* call chernikova directly.
148  sc_common_projection_convex_hull improvements have already been included.
149  */
150  s = sc_enveloppe_chernikova(s1, s2);
151 
152  /* restaure initial base */
153  sc_base(s1) = b1;
154  sc_dimension(s1) = d1;
155  sc_base(s2) = b2;
156  sc_dimension(s2) = d2;
157 
158  base_rm(bu);
159 
160  return s;
161 }
162 
163 /* implements FC basic idea of simple fast cases...
164  * returns s1 v s2.
165  * s1 and s2 are not touched.
166  * The bases should be minimum for best efficiency!
167  * otherwise useless columns are allocated and computed.
168  * a common base is rebuilt in actual_convex_union.
169  * other fast cases may be added?
170  */
172 {
173  bool
174  b1 = sc_empty_p(s1),
175  b2 = sc_empty_p(s2);
176 
177  if (b1 && b2)
178  return sc_empty(base_union(sc_base(s1), sc_base(s2)));
179 
180  if (b1) {
181  Psysteme s = sc_dup(s2);
182  Pbase b = base_union(sc_base(s1), sc_base(s2));
183  base_rm(sc_base(s));
184  sc_base(s) = b;
185  return s;
186  }
187 
188  if (b2) {
189  Psysteme s = sc_dup(s1);
190  Pbase b = base_union(sc_base(s1), sc_base(s2));
191  base_rm(sc_base(s));
192  sc_base(s) = b;
193  return s;
194  }
195 
196  if (sc_rn_p(s1) || sc_rn_p(s2) ||
197  !vect_common_variables_p(sc_base(s1), sc_base(s2)))
198  return sc_rn(base_union(sc_base(s1), sc_base(s2)));
199 
200  /*
201  if (sc_dimension(s1)==1 && sc_dimension(s2)==1 &&
202  sc_base(s1)->var == sc_base(s2)->var)
203  {
204  // fast computation...
205  }
206  */
207 
208  return actual_convex_union(s1, s2);
209 }
210 
211 
212 /********************************************** SET BASED TRANSITIVE CLOSURE */
213 
214 /* put base variables in set.
215  returns whether something was put.
216  */
218 {
219  bool modified = false;
220 
221  for (; b; b=b->succ)
222  if (b->var && !linear_hashtable_isin(s, b->var))
223  {
224  linear_hashtable_put(s, b->var, b->var);
225  modified = true;
226  }
227 
228  return modified;
229 }
230 
231 /* returns whether c contains variables of vars. */
233 {
234  for (; v; v = v->succ)
235  if (v->var && linear_hashtable_isin(vars, v->var))
236  return true;
237  return false;
238 }
239 
240 /* one pass only of transitive closure.
241  * returns whether vars was modified.
242  * appends extracted constraints to ex.
243  */
244 static bool
246  linear_hashtable_pt vars)
247 {
248  Pcontrainte c, cp, cn;
249  bool modified = false;
250 
251  for (c=*pc,
253  cn = c? c->succ: CONTRAINTE_UNDEFINED;
254  c;
255  cp = c==cn? cp: c,
256  c = cn,
257  cn = c? c->succ: CONTRAINTE_UNDEFINED)
258  {
259  if (contains_variables(c->vecteur, vars))
260  {
261  modified |= base_to_set(vars, c->vecteur);
262  c->succ = *ex, *ex = c;
263  if (cp) cp->succ = cn; else *pc = cn;
264  c = cn;
265  }
266  }
267 
268  return modified;
269 }
270 
271 /* transtitive extraction of constraints.
272  */
274 {
276  bool modified;
277 
278  do {
279  modified = transitive_closure_pass(&s->egalites, &e, vars);
280  modified |= transitive_closure_pass(&s->inegalites, &i, vars);
281  }
282  while (modified);
283 
284  sc_fix(s);
285  return sc_make(e, i);
286 }
287 
288 /* returns constraints from s which may depend on variables in b1 and b2.
289  * these constraints are removed from s, hence s is modified.
290  */
291 static Psysteme
293 {
294  Psysteme st;
296 
297  base_to_set(vars, b1);
298  base_to_set(vars, b2);
299  st = transitive_closure_system(s, vars);
300  linear_hashtable_free(vars);
301 
302  return st;
303 }
304 
305 /*********************************************** HOPEFULLY CUTE CONVEX UNION */
306 
307 /* returns s1 v s2.
308  * initial systems are not changed.
309  *
310  * v convex union
311  * u union
312  * n intersection
313  * T orthogonality
314  *
315  * (1) CA:
316  *
317  * P1 v P2 = (P n X1) v (P n X2) =
318  * let P = P' n P''
319  * so that P' T X1 and P' T X2 and P' T P'' built by transitive closure,
320  * then P1 v P2 = (P' n (P'' n X1)) v (P' n (P'' n X2)) =
321  * P' n ((P'' n X1) v (P'' n X2))
322  *
323  * Proof by considering generating systems:
324  * Def: A T B <=> var(A) n var(B) = 0
325  * Prop: A n B if A T B
326  * Let A = (x,v,l), B = (y,w,m)
327  * A n B = { z | z = (x) \mu + (v) d + (l) e + (0) f
328  * (0) + (0) + (0) (I)
329  * and z = (0) \nu + (0) g + (0) h + (I) f'
330  * (y) + (w) + (m) (0)
331  * with \mu>0, \nu>0, \sum\mu=1, \sum\nu=1, d>0, g>0 }
332  * we can always find f and f' equals to the other part (by extension) so
333  * A n B = { z | z = (x 0) \mu + (v 0) d + (l 0) e
334  * (0 y) \nu (0 w) g (0 m) h
335  * with \mu \nu d g constraints... }
336  * It is a convex : ((xi) , (v 0), (l 0))
337  * (yj)ij, (0 w), (0 m)
338  * we just need to prove that Cmn == Cg defined as
339  * (x 0) \mu == (xi) \gamma with >0 and \sum = 1
340  * (0 y) \nu (yj)ij
341  * . Cg in a convex.
342  * . Cg \in Cmn since ((xi)\‍(yj) ij) in Cmn
343  * with \mu = \delta i, \nu = \delta j
344  * . Cmn \in Cg by chosing \gamma_ij = \mu_i\nu_j, which >0 and \sum = 1
345  * Prop: A T B and A T C => A T (B v C) and A T (B n C)
346  * Theo: A T B and A T C => (A n B) v (A n C) = A n (B v C)
347  * compute both generating systems with above props. they are equal.
348  *
349  * (2) FI:
350  *
351  * perform exact projections of common equalities.
352  * no proof at the time. It looks ok anyway.
353  *
354  * (3) FC:
355  *
356  * base(P) n base(Q) = 0 => P u Q = Rn
357  * and some other very basic simplifications...
358  * which are not really interesting if no decomposition is performed?
359  *
360  * on overflows FI suggested.
361  *
362  * 1/ we want to compute : (A n B1) u (A n B2)
363  * 2/ we chose to approximate it as : (A n B1) v (A n B2)
364  * 3/ we try Corinne's factorization with transitive closure
365  * A' n ((A'' n B1) v (A'' n B2))
366  * 4/ on overflow, we can try A n (B1 v B2) // NOT IMPLEMENTED YET
367  * 5/ if we have one more overflow, then A looks good as an approximation.
368  */
370 {
371  Psysteme s1, s2, sc, stc, su, scsaved;
372  int current_overflow_count;
373 
374  s1 = sc_dup(is1);
375  s2 = sc_dup(is2);
376 
377  /* CA: extract common disjoint part.
378  */
379  sc = extract_common_syst(s1, s2);
380  scsaved = sc_dup(sc);
381  stc = transitive_closure_from_two_bases(sc, s1->base, s2->base);
382 
383  /* FI: in sc_common_projection_convex_hull
384  note that equalities are not that big a burden to chernikova?
385  */
386  sc_extract_exact_common_equalities(stc, sc, s1, s2);
387 
388  /* fast sc_append */
389  s1 = sc_fusion(s1, sc_dup(stc));
390  sc_fix(s1);
391 
392  s2 = sc_fusion(s2, stc);
393  sc_fix(s2);
394 
395  stc = NULL;
396 
397  current_overflow_count = linear_number_of_exception_thrown;
398 
399  su = elementary_convex_union(s1, s2);
400 
401  /* usually we use V (convex hull) as a U (set union) approximation.
402  * as we have : (A n B1) U (A n B2) \in A
403  * the common part of both systems is an approximation of the union!
404  * sc_rn is returned on overflows (and some other case).
405  * I don't think that the result is improved apart
406  * when actual overflow occurs. FC/CA.
407  */
408  if (current_overflow_count!=linear_number_of_exception_thrown)
409  {
410  if (su) sc_rm(su), su = NULL;
411  if (sc) sc_rm(sc), sc = NULL;
412  sc = scsaved;
413  }
414  else
415  {
416  sc_rm(scsaved);
417  }
418 
419  scsaved = NULL; /* dead. either rm or moved as sc. */
420  sc_rm(s1);
421  sc_rm(s2);
422 
423  /* better compatibility with previous version, as the convex union
424  * normalizes the system and removes redundancy, what is not done
425  * if part of the system is separated. Other calls may be considered here?
426  */
427  sc_transform_ineg_in_eg(sc); /* ok, it will look better. */
428  /* misleading... not really projected. { x==y, y==3 } => { x==3, y==3 } */
429  sc_project_very_simple_equalities(sc);
430 
431  /* sc, su: fast union of disjoint. */
432  sc = sc_fusion(sc, su);
433 
434  /* regenerate the expected base. */
435  if (sc)
436  {
437  sc_fix(sc);
438  if (sc_base(sc)) base_rm(sc_base(sc));
439  }
440  else
441  {
442  sc = sc_rn(NULL);
443  }
444  sc_base(sc) = base_union(sc_base(is1), sc_base(is2));
445  sc_dimension(sc) = vect_size(sc_base(sc));
446 
447  return sc;
448 }
449 
450 /* take the rectangular bounding box of the systeme @p sc,
451  * by projecting each constraint of the systeme against each of the basis
452  * in @p pb
453  *
454  * SG: this is basically a renaming of sc_projection_on_variables ...
455  */
457  volatile Psysteme rectangular = SC_UNDEFINED;
458  rectangular = sc_projection_on_variables(sc,pb,pb);
460  ;
461  // it does not matter if we fail ...
462  }
463  TRY {
464  sc_nredund(&rectangular);
466  }
467  return rectangular;
468 }
#define CATCH(what)
@ overflow_error
@ timeout_error
#define UNCATCH(what)
#define TRY
int linear_number_of_exception_thrown
Pbase base_union(Pbase b1, Pbase b2)
Pbase base_union(Pbase b1, Pbase b2): compute a new basis containing all elements of b1 and all eleme...
Definition: base.c:428
Psysteme sc_convex_hull(Psysteme sc1, Psysteme sc2)
Definition: chernikova.c:74
#define CONTRAINTE_UNDEFINED
bool linear_hashtable_isin(linear_hashtable_pt h, void *k)
Definition: hashpointer.c:273
void linear_hashtable_put(linear_hashtable_pt h, void *k, void *v)
Definition: hashpointer.c:263
linear_hashtable_pt linear_hashtable_make(void)
constructor.
Definition: hashpointer.c:165
void linear_hashtable_free(linear_hashtable_pt h)
destructor
Definition: hashpointer.c:189
static int is2(Pproblem XX, Pproblem VV, struct rproblem *RR)
=======================================================================
Definition: isolve.c:2158
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
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_rn(Pbase b)
Psysteme sc_rn(Pbase b): build a Psysteme without constraints to define R^n, where n is b's dimension...
Definition: sc_alloc.c:336
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
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
Psysteme sc_dup(Psysteme ps)
Psysteme sc_dup(Psysteme ps): should becomes a link.
Definition: sc_alloc.c:176
static Psysteme transitive_closure_from_two_bases(Psysteme s, Pbase b1, Pbase b2)
returns constraints from s which may depend on variables in b1 and b2.
Definition: sc_enveloppe.c:292
Psysteme sc_cute_convex_hull(Psysteme is1, Psysteme is2)
returns s1 v s2.
Definition: sc_enveloppe.c:369
static Psysteme actual_convex_union(Psysteme s1, Psysteme s2)
call chernikova with compatible base.
Definition: sc_enveloppe.c:134
Psysteme sc_rectangular_hull(Psysteme sc, Pbase pb)
take the rectangular bounding box of the systeme sc, by projecting each constraint of the systeme aga...
Definition: sc_enveloppe.c:456
static bool transitive_closure_pass(Pcontrainte *pc, Pcontrainte *ex, linear_hashtable_pt vars)
one pass only of transitive closure.
Definition: sc_enveloppe.c:245
static Psysteme transitive_closure_system(Psysteme s, linear_hashtable_pt vars)
transtitive extraction of constraints.
Definition: sc_enveloppe.c:273
Psysteme sc_enveloppe_chernikova_ofl_ctrl(Psysteme s1, Psysteme s2, int ofl_ctrl)
package polyedre: enveloppe convexe de deux systemes lineaires
Definition: sc_enveloppe.c:68
Psysteme sc_enveloppe_chernikova(Psysteme s1, Psysteme s2)
Definition: sc_enveloppe.c:127
Psysteme elementary_convex_union(Psysteme s1, Psysteme s2)
implements FC basic idea of simple fast cases...
Definition: sc_enveloppe.c:171
static bool contains_variables(Pvecteur v, linear_hashtable_pt vars)
returns whether c contains variables of vars.
Definition: sc_enveloppe.c:232
static bool base_to_set(linear_hashtable_pt s, Pvecteur b)
put base variables in set.
Definition: sc_enveloppe.c:217
Value b2
Definition: sc_gram.c:105
Value b1
booleen indiquant quel membre est en cours d'analyse
Definition: sc_gram.c:105
Pvecteur cp
pointeur sur l'egalite ou l'inegalite courante
Definition: sc_read.c:87
Psysteme extract_common_syst(Psysteme s1, Psysteme s2)
returns the common subsystem if appropriate...
Psysteme sc_fusion(Psysteme s1, Psysteme s2)
package sc
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
void sc_transform_ineg_in_eg(Psysteme sc)
Transform the two constraints A.x <= b and -A.x <= -b of system sc into an equality A....
s1
Definition: set.c:247
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
Variable var
Definition: vecteur-local.h:90
struct Svecteur * succ
Definition: vecteur-local.h:92
hidden structure to store the hashtable.
Definition: hashpointer.c:66
#define base_rm(b)
#define FWD_OFL_CTRL
#define OFL_CTRL
I do thing that overflows are managed in a very poor manner.
Pbase base_dup(Pbase b)
Pbase base_dup(Pbase b) Note: this function changes the value of the pointer.
Definition: alloc.c:268
bool vect_common_variables_p(Pvecteur v1, Pvecteur v2)
bool vect_common_variables_p(Pvecteur v1, v2) BA 19/05/94 input : two vectors.
Definition: unaires.c:397