PPL  1.2
Partially_Reduced_Product_templates.hh
Go to the documentation of this file.
1 /* Partially_Reduced_Product class implementation:
2  non-inline template functions.
3  Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
4  Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
5 
6 This file is part of the Parma Polyhedra Library (PPL).
7 
8 The PPL is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 The PPL is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software Foundation,
20 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
21 
22 For the most up-to-date information see the Parma Polyhedra Library
23 site: http://bugseng.com/products/ppl/ . */
24 
25 #ifndef PPL_Partially_Reduced_Product_templates_hh
26 #define PPL_Partially_Reduced_Product_templates_hh 1
27 
28 #include "Grid_Generator_defs.hh"
31 #include <algorithm>
32 #include <deque>
33 
34 namespace Parma_Polyhedra_Library {
35 
36 template <typename D1, typename D2, typename R>
37 void
40  const char* reason) {
41  std::ostringstream s;
42  s << "PPL::Partially_Reduced_Product::" << method << ":" << std::endl
43  << reason << ".";
44  throw std::length_error(s.str());
45 }
46 
47 template <typename D1, typename D2, typename R>
50  reduce();
51  Constraint_System cs = d2.constraints();
52  const Constraint_System& cs1 = d1.constraints();
54  cs_end = cs1.end(); i != cs_end; ++i) {
55  cs.insert(*i);
56  }
57  return cs;
58 }
59 
60 template <typename D1, typename D2, typename R>
63  reduce();
64  Constraint_System cs = d2.constraints();
65  const Constraint_System& cs1 = d1.constraints();
67  cs_end = cs1.end(); i != cs_end; ++i) {
68  cs.insert(*i);
69  }
70  if (cs.has_strict_inequalities()) {
71  NNC_Polyhedron ph(cs);
72  return ph.minimized_constraints();
73  }
74  else {
75  C_Polyhedron ph(cs);
76  return ph.minimized_constraints();
77  }
78 }
79 
80 template <typename D1, typename D2, typename R>
83  reduce();
84  Congruence_System cgs = d2.congruences();
85  const Congruence_System& cgs1 = d1.congruences();
87  cgs_end = cgs1.end(); i != cgs_end; ++i) {
88  cgs.insert(*i);
89  }
90  return cgs;
91 }
92 
93 template <typename D1, typename D2, typename R>
96  reduce();
97  Congruence_System cgs = d2.congruences();
98  const Congruence_System& cgs1 = d1.congruences();
100  cgs_end = cgs1.end(); i != cgs_end; ++i) {
101  cgs.insert(*i);
102  }
103  Grid gr(cgs);
104  return gr.minimized_congruences();
105 }
106 
107 template <typename D1, typename D2, typename R>
108 void
111  if (d1.can_recycle_constraint_systems()) {
112  d2.refine_with_constraints(cs);
113  d1.add_recycled_constraints(cs);
114  }
115  else {
116  if (d2.can_recycle_constraint_systems()) {
117  d1.refine_with_constraints(cs);
118  d2.add_recycled_constraints(cs);
119  }
120  else {
121  d1.add_constraints(cs);
122  d2.add_constraints(cs);
123  }
124  }
125  clear_reduced_flag();
126 }
127 
128 template <typename D1, typename D2, typename R>
129 void
132  if (d1.can_recycle_congruence_systems()) {
133  d2.refine_with_congruences(cgs);
134  d1.add_recycled_congruences(cgs);
135  }
136  else {
137  if (d2.can_recycle_congruence_systems()) {
138  d1.refine_with_congruences(cgs);
139  d2.add_recycled_congruences(cgs);
140  }
141  else {
142  d1.add_congruences(cgs);
143  d2.add_congruences(cgs);
144  }
145  }
146  clear_reduced_flag();
147 }
148 
149 template <typename D1, typename D2, typename R>
152 ::relation_with(const Generator& g) const {
153  reduce();
154  if (Poly_Gen_Relation::nothing() == d1.relation_with(g)
155  || Poly_Gen_Relation::nothing() == d2.relation_with(g)) {
157  }
158  else {
160  }
161 }
162 
163 template <typename D1, typename D2, typename R>
166 ::relation_with(const Constraint& c) const {
167  reduce();
168  Poly_Con_Relation relation1 = d1.relation_with(c);
169  Poly_Con_Relation relation2 = d2.relation_with(c);
170 
172 
173  if (relation1.implies(Poly_Con_Relation::is_included())) {
174  result = result && Poly_Con_Relation::is_included();
175  }
176  else if (relation2.implies(Poly_Con_Relation::is_included())) {
177  result = result && Poly_Con_Relation::is_included();
178  }
179  if (relation1.implies(Poly_Con_Relation::saturates())) {
180  result = result && Poly_Con_Relation::saturates();
181  }
182  else if (relation2.implies(Poly_Con_Relation::saturates())) {
183  result = result && Poly_Con_Relation::saturates();
184  }
185  if (relation1.implies(Poly_Con_Relation::is_disjoint())) {
186  result = result && Poly_Con_Relation::is_disjoint();
187  }
188  else if (relation2.implies(Poly_Con_Relation::is_disjoint())) {
189  result = result && Poly_Con_Relation::is_disjoint();
190  }
191 
192  return result;
193 }
194 
195 template <typename D1, typename D2, typename R>
198 ::relation_with(const Congruence& cg) const {
199  reduce();
200  Poly_Con_Relation relation1 = d1.relation_with(cg);
201  Poly_Con_Relation relation2 = d2.relation_with(cg);
202 
204 
205  if (relation1.implies(Poly_Con_Relation::is_included())) {
206  result = result && Poly_Con_Relation::is_included();
207  }
208  else if (relation2.implies(Poly_Con_Relation::is_included())) {
209  result = result && Poly_Con_Relation::is_included();
210  }
211  if (relation1.implies(Poly_Con_Relation::saturates())) {
212  result = result && Poly_Con_Relation::saturates();
213  }
214  else if (relation2.implies(Poly_Con_Relation::saturates())) {
215  result = result && Poly_Con_Relation::saturates();
216  }
217  if (relation1.implies(Poly_Con_Relation::is_disjoint())) {
218  result = result && Poly_Con_Relation::is_disjoint();
219  }
220  else if (relation2.implies(Poly_Con_Relation::is_disjoint())) {
221  result = result && Poly_Con_Relation::is_disjoint();
222  }
223 
224  return result;
225 }
226 
227 template <typename D1, typename D2, typename R>
228 bool
231  Coefficient& sup_n,
232  Coefficient& sup_d,
233  bool& maximum) const {
234  reduce();
235 
236  if (is_empty()) {
237  return false;
238  }
239 
244  bool maximum1;
245  bool maximum2;
246  bool r1 = d1.maximize(expr, sup1_n, sup1_d, maximum1);
247  bool r2 = d2.maximize(expr, sup2_n, sup2_d, maximum2);
248  // If neither is bounded from above, return false.
249  if (!r1 && !r2) {
250  return false;
251  }
252  // If only d2 is bounded from above, then use the values for d2.
253  if (!r1) {
254  sup_n = sup2_n;
255  sup_d = sup2_d;
256  maximum = maximum2;
257  return true;
258  }
259  // If only d1 is bounded from above, then use the values for d1.
260  if (!r2) {
261  sup_n = sup1_n;
262  sup_d = sup1_d;
263  maximum = maximum1;
264  return true;
265  }
266  // If both d1 and d2 are bounded from above, then use the minimum values.
267  if (sup2_d * sup1_n >= sup1_d * sup2_n) {
268  sup_n = sup1_n;
269  sup_d = sup1_d;
270  maximum = maximum1;
271  }
272  else {
273  sup_n = sup2_n;
274  sup_d = sup2_d;
275  maximum = maximum2;
276  }
277  return true;
278 }
279 
280 template <typename D1, typename D2, typename R>
281 bool
284  Coefficient& inf_n,
285  Coefficient& inf_d,
286  bool& minimum) const {
287  reduce();
288 
289  if (is_empty()) {
290  return false;
291  }
292  PPL_ASSERT(reduced);
293 
298  bool minimum1;
299  bool minimum2;
300  bool r1 = d1.minimize(expr, inf1_n, inf1_d, minimum1);
301  bool r2 = d2.minimize(expr, inf2_n, inf2_d, minimum2);
302  // If neither is bounded from below, return false.
303  if (!r1 && !r2) {
304  return false;
305  }
306  // If only d2 is bounded from below, then use the values for d2.
307  if (!r1) {
308  inf_n = inf2_n;
309  inf_d = inf2_d;
310  minimum = minimum2;
311  return true;
312  }
313  // If only d1 is bounded from below, then use the values for d1.
314  if (!r2) {
315  inf_n = inf1_n;
316  inf_d = inf1_d;
317  minimum = minimum1;
318  return true;
319  }
320  // If both d1 and d2 are bounded from below, then use the minimum values.
321  if (inf2_d * inf1_n <= inf1_d * inf2_n) {
322  inf_n = inf1_n;
323  inf_d = inf1_d;
324  minimum = minimum1;
325  }
326  else {
327  inf_n = inf2_n;
328  inf_d = inf2_d;
329  minimum = minimum2;
330  }
331  return true;
332 }
333 
334 template <typename D1, typename D2, typename R>
335 bool
338  Coefficient& sup_n,
339  Coefficient& sup_d,
340  bool& maximum,
341  Generator& g) const {
342  reduce();
343 
344  if (is_empty()) {
345  return false;
346  }
347  PPL_ASSERT(reduced);
348 
353  bool maximum1;
354  bool maximum2;
355  Generator g1(point());
356  Generator g2(point());
357  bool r1 = d1.maximize(expr, sup1_n, sup1_d, maximum1, g1);
358  bool r2 = d2.maximize(expr, sup2_n, sup2_d, maximum2, g2);
359  // If neither is bounded from above, return false.
360  if (!r1 && !r2) {
361  return false;
362  }
363  // If only d2 is bounded from above, then use the values for d2.
364  if (!r1) {
365  sup_n = sup2_n;
366  sup_d = sup2_d;
367  maximum = maximum2;
368  g = g2;
369  return true;
370  }
371  // If only d1 is bounded from above, then use the values for d1.
372  if (!r2) {
373  sup_n = sup1_n;
374  sup_d = sup1_d;
375  maximum = maximum1;
376  g = g1;
377  return true;
378  }
379  // If both d1 and d2 are bounded from above, then use the minimum values.
380  if (sup2_d * sup1_n >= sup1_d * sup2_n) {
381  sup_n = sup1_n;
382  sup_d = sup1_d;
383  maximum = maximum1;
384  g = g1;
385  }
386  else {
387  sup_n = sup2_n;
388  sup_d = sup2_d;
389  maximum = maximum2;
390  g = g2;
391  }
392  return true;
393 }
394 
395 template <typename D1, typename D2, typename R>
396 bool
399  Coefficient& inf_n,
400  Coefficient& inf_d,
401  bool& minimum,
402  Generator& g) const {
403  reduce();
404 
405  if (is_empty()) {
406  return false;
407  }
408  PPL_ASSERT(reduced);
409 
414  bool minimum1;
415  bool minimum2;
416  Generator g1(point());
417  Generator g2(point());
418  bool r1 = d1.minimize(expr, inf1_n, inf1_d, minimum1, g1);
419  bool r2 = d2.minimize(expr, inf2_n, inf2_d, minimum2, g2);
420  // If neither is bounded from below, return false.
421  if (!r1 && !r2) {
422  return false;
423  }
424  // If only d2 is bounded from below, then use the values for d2.
425  if (!r1) {
426  inf_n = inf2_n;
427  inf_d = inf2_d;
428  minimum = minimum2;
429  g = g2;
430  return true;
431  }
432  // If only d1 is bounded from below, then use the values for d1.
433  if (!r2) {
434  inf_n = inf1_n;
435  inf_d = inf1_d;
436  minimum = minimum1;
437  g = g1;
438  return true;
439  }
440  // If both d1 and d2 are bounded from below, then use the minimum values.
441  if (inf2_d * inf1_n <= inf1_d * inf2_n) {
442  inf_n = inf1_n;
443  inf_d = inf1_d;
444  minimum = minimum1;
445  g = g1;
446  }
447  else {
448  inf_n = inf2_n;
449  inf_d = inf2_d;
450  minimum = minimum2;
451  g = g2;
452  }
453  return true;
454 }
455 
456 template <typename D1, typename D2, typename R>
457 inline bool
459  if (reduced) {
462  /* Force dp1 reduction */
463  dp1.clear_reduced_flag();
464  dp1.reduce();
465  if (dp1 != dp2) {
466  return false;
467  }
468  }
469  return d1.OK() && d2.OK();
470 }
471 
472 template <typename D1, typename D2, typename R>
473 bool
475  const char yes = '+';
476  const char no = '-';
477  std::string str;
478  if (!(s >> str) || str != "Partially_Reduced_Product") {
479  return false;
480  }
481  if (!(s >> str)
482  || (str[0] != yes && str[0] != no)
483  || str.substr(1) != "reduced") {
484  return false;
485  }
486  reduced = (str[0] == yes);
487  if (!(s >> str) || str != "Domain") {
488  return false;
489  }
490  if (!(s >> str) || str != "1:") {
491  return false;
492  }
493  if (!d1.ascii_load(s)) {
494  return false;
495  }
496  if (!(s >> str) || str != "Domain") {
497  return false;
498  }
499  if (!(s >> str) || str != "2:") {
500  return false;
501  }
502  return d2.ascii_load(s);
503 }
504 
505 template <typename D1, typename D2>
507  using std::swap;
508  if (d2.is_empty()) {
509  if (!d1.is_empty()) {
510  D1 new_d1(d1.space_dimension(), EMPTY);
511  swap(d1, new_d1);
512  }
513  }
514  else if (d1.is_empty()) {
515  D2 new_d2(d2.space_dimension(), EMPTY);
516  swap(d2, new_d2);
517  }
518 }
519 
520 template <typename D1, typename D2>
522  if (d1.is_empty() || d2.is_empty()) {
523  // If one of the components is empty, do the smash reduction and return.
525  sr.product_reduce(d1, d2);
526  return;
527  }
528  else {
529  using std::swap;
530  dimension_type space_dim = d1.space_dimension();
531  d1.refine_with_constraints(d2.minimized_constraints());
532  if (d1.is_empty()) {
533  D2 new_d2(space_dim, EMPTY);
534  swap(d2, new_d2);
535  return;
536  }
537  d2.refine_with_constraints(d1.minimized_constraints());
538  if (d2.is_empty()) {
539  D1 new_d1(space_dim, EMPTY);
540  swap(d1, new_d1);
541  }
542  }
543 }
544 
545 /* Auxiliary procedure for the Congruences_Reduction() method.
546  If more than one hyperplane defined by congruence cg intersect
547  d2, then d1 and d2 are unchanged; if exactly one intersects d2, then
548  the corresponding equality is added to d1 and d2;
549  otherwise d1 and d2 are set empty. */
550 template <typename D1, typename D2>
551 bool shrink_to_congruence_no_check(D1& d1, D2& d2, const Congruence& cg) {
552  // It is assumed that cg is a proper congruence.
553  PPL_ASSERT(cg.modulus() != 0);
554  // It is assumed that cg is satisfied by all points in d1.
555  PPL_ASSERT(d1.relation_with(cg) == Poly_Con_Relation::is_included());
556 
558 
559  // Find the maximum and minimum bounds for the domain element d with the
560  // linear expression e.
561  PPL_DIRTY_TEMP_COEFFICIENT(max_numer);
562  PPL_DIRTY_TEMP_COEFFICIENT(max_denom);
563  bool max_included;
564  PPL_DIRTY_TEMP_COEFFICIENT(min_numer);
565  PPL_DIRTY_TEMP_COEFFICIENT(min_denom);
566  if (d2.maximize(e, max_numer, max_denom, max_included)) {
567  bool min_included;
568  if (d2.minimize(e, min_numer, min_denom, min_included)) {
569  // Adjust values to allow for the denominators max_denom and min_denom.
570  max_numer *= min_denom;
571  min_numer *= max_denom;
574  denom = max_denom * min_denom;
575  mod = cg.modulus() * denom;
576  // If the difference between the maximum and minimum bounds is more than
577  // twice the modulus, then there will be two neighboring hyperplanes
578  // defined by cg that are intersected by the domain element d;
579  // there is no possible reduction in this case.
581  mod2 = 2 * mod;
582  if (max_numer - min_numer < mod2
583  || (max_numer - min_numer == mod2 && (!max_included || !min_included)))
584  {
585  PPL_DIRTY_TEMP_COEFFICIENT(shrink_amount);
586  PPL_DIRTY_TEMP_COEFFICIENT(max_decreased);
587  PPL_DIRTY_TEMP_COEFFICIENT(min_increased);
588  // Find the amount by which the maximum value may be decreased.
589  shrink_amount = max_numer % mod;
590  if (!max_included && shrink_amount == 0) {
591  shrink_amount = mod;
592  }
593  if (shrink_amount < 0) {
594  shrink_amount += mod;
595  }
596  max_decreased = max_numer - shrink_amount;
597  // Find the amount by which the minimum value may be increased.
598  shrink_amount = min_numer % mod;
599  if (!min_included && shrink_amount == 0) {
600  shrink_amount = - mod;
601  }
602  if (shrink_amount > 0) {
603  shrink_amount -= mod;
604  }
605  min_increased = min_numer - shrink_amount;
606  if (max_decreased == min_increased) {
607  // The domain element d2 intersects exactly one hyperplane
608  // defined by cg, so add the equality to d1 and d2.
609  Constraint new_c(denom * e == min_increased);
610  d1.refine_with_constraint(new_c);
611  d2.refine_with_constraint(new_c);
612  return true;
613  }
614  else {
615  if (max_decreased < min_increased) {
616  using std::swap;
617  // In this case, d intersects no hyperplanes defined by cg,
618  // so set d to empty and return false.
619  D1 new_d1(d1.space_dimension(), EMPTY);
620  swap(d1, new_d1);
621  D2 new_d2(d2.space_dimension(), EMPTY);
622  swap(d2, new_d2);
623  return false;
624  }
625  }
626  }
627  }
628  }
629  return true;
630 }
631 
632 template <typename D1, typename D2>
633 void
635  if (d1.is_empty() || d2.is_empty()) {
636  // If one of the components is empty, do the smash reduction and return.
638  sr.product_reduce(d1, d2);
639  return;
640  }
641  // Use the congruences representing d1 to shrink both components.
642  const Congruence_System cgs1 = d1.minimized_congruences();
644  cgs_end = cgs1.end(); i != cgs_end; ++i) {
645  const Congruence& cg1 = *i;
646  if (cg1.is_equality()) {
647  d2.refine_with_congruence(cg1);
648  }
649  else {
651  shrink_to_congruence_no_check(d1, d2, cg1)) {
652  // The product is empty.
653  return;
654  }
655  }
656  }
657  // Use the congruences representing d2 to shrink both components.
658  const Congruence_System cgs2 = d2.minimized_congruences();
660  cgs_end = cgs2.end(); i != cgs_end; ++i) {
661  const Congruence& cg2 = *i;
662  if (cg2.is_equality()) {
663  d1.refine_with_congruence(cg2);
664  }
665  else {
667  shrink_to_congruence_no_check(d2, d1, cg2)) {
668  // The product is empty.
669  return;
670  }
671  }
672  }
673 }
674 
675 template <typename D1, typename D2>
676 void
678  // First do the congruences reduction.
680  cgr.product_reduce(d1, d2);
681  if (d1.is_empty()) {
682  return;
683  }
684 
689 
690  // Use the constraints representing d2.
691  Constraint_System cs = d2.minimized_constraints();
692  Constraint_System refining_cs;
694  cs_end = cs.end(); i != cs_end; ++i) {
695  const Constraint& c = *i;
696  if (c.is_equality()) {
697  continue;
698  }
699  // Check the frequency and value of the linear expression for
700  // the constraint `c'.
702  if (!d1.frequency(le, freq_n, freq_d, val_n, val_d)) {
703  // Nothing to do.
704  continue;
705  }
706  if (val_n == 0) {
707  // Nothing to do.
708  continue;
709  }
710  // Adjust the value of the inhomogeneous term to satisfy
711  // the implied congruence.
712  if (val_n < 0) {
713  val_n = val_n*freq_d + val_d*freq_n;
714  val_d *= freq_d;
715  }
716  le *= val_d;
717  le -= val_n;
718  refining_cs.insert(le >= 0);
719  }
720  d2.refine_with_constraints(refining_cs);
721 
722  // Use the constraints representing d1.
723  cs = d1.minimized_constraints();
724  refining_cs.clear();
726  cs_end = cs.end(); i != cs_end; ++i) {
727  const Constraint& c = *i;
728  if (c.is_equality()) {
729  // Equalities already shared.
730  continue;
731  }
732  // Check the frequency and value of the linear expression for
733  // the constraint `c'.
735  if (!d2.frequency(le, freq_n, freq_d, val_n, val_d)) {
736  // Nothing to do.
737  continue;
738  }
739  if (val_n == 0) {
740  // Nothing to do.
741  continue;
742  }
743  // Adjust the value of the inhomogeneous term to satisfy
744  // the implied congruence.
745  if (val_n < 0) {
746  val_n = val_n*freq_d + val_d*freq_n;
747  val_d *= freq_d;
748  }
749  le *= val_d;
750  le -= val_n;
751  refining_cs.insert(le >= 0);
752  }
753  d1.refine_with_constraints(refining_cs);
754 
755  // The reduction may have introduced additional equalities
756  // so these must be shared with the other component.
758  cr.product_reduce(d1, d2);
759 }
760 
761 } // namespace Parma_Polyhedra_Library
762 
763 #endif // !defined(PPL_Partially_Reduced_Product_templates_hh)
The partially reduced product of two abstractions.
The empty element, i.e., the empty set.
static Poly_Con_Relation is_disjoint()
The polyhedron and the set of points satisfying the constraint are disjoint.
static Poly_Gen_Relation subsumes()
Adding the generator would not change the polyhedron.
Congruence_System congruences() const
Returns a system of congruences which approximates *this.
Coefficient_traits::const_reference modulus() const
Returns a const reference to the modulus of *this.
A linear equality or inequality.
bool is_equality() const
Returns true if and only if *this is an equality constraint.
void swap(CO_Tree &x, CO_Tree &y)
bool ascii_load(std::istream &s)
Loads from s an ASCII representation (as produced by ascii_dump(std::ostream&) const) and sets *this ...
static bool implies(flags_t x, flags_t y)
True if and only if the conjunction x implies the conjunction y.
size_t dimension_type
An unsigned integral type for representing space dimensions.
void insert(const Congruence &cg)
Inserts in *this a copy of the congruence cg, increasing the number of space dimensions if needed...
A line, ray, point or closure point.
void product_reduce(D1 &d1, D2 &d2)
The congruences reduction operator for detect emptiness or any equalities implied by each of the cong...
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
Poly_Con_Relation relation_with(const Constraint &c) const
Returns the relations holding between *this and c.
void product_reduce(D1 &d1, D2 &d2)
The constraints reduction operator for sharing constraints between the domains.
void insert(const Constraint &c)
Inserts in *this a copy of the constraint c, increasing the number of space dimensions if needed...
const_iterator end() const
Returns the past-the-end const_iterator.
static Poly_Con_Relation is_included()
The polyhedron is included in the set of points satisfying the constraint.
bool minimize(const Linear_Expression &expr, Coefficient &inf_n, Coefficient &inf_d, bool &minimum) const
Returns true if and only if *this is not empty and expr is bounded from below i *this, in which case the infimum value is computed.
expr_type expression() const
Partial read access to the (adapted) internal expression.
Congruence_System minimized_congruences() const
Returns a system of congruences which approximates *this, in reduced form.
void clear()
Removes all the constraints from the constraint system and sets its space dimension to 0...
This class provides the reduction method for the Constraints_Product domain.
static Poly_Con_Relation saturates()
The polyhedron is included in the set of points saturating the constraint.
const_iterator begin() const
Returns the const_iterator pointing to the first constraint, if *this is not empty; otherwise...
This class provides the reduction method for the Congruences_Product domain.
Constraint_System minimized_constraints() const
Returns a system of constraints which approximates *this, in reduced form.
void add_recycled_constraints(Constraint_System &cs)
Adds the constraint system in cs to *this.
void product_reduce(D1 &d1, D2 &d2)
The congruences reduction operator for detect emptiness or any equalities implied by each of the cong...
bool is_equality() const
Returns true if *this is an equality.
bool maximize(const Linear_Expression &expr, Coefficient &sup_n, Coefficient &sup_d, bool &maximum) const
Returns true if and only if *this is not empty and expr is bounded from above in *this, in which case the supremum value is computed.
const_iterator end() const
Returns the past-the-end const_iterator.
const Congruence_System & minimized_congruences() const
Returns the system of congruences in minimal form.
Definition: Grid_public.cc:319
bool shrink_to_congruence_no_check(D1 &d1, D2 &d2, const Congruence &cg)
A not necessarily closed convex polyhedron.
A closed convex polyhedron.
const_iterator begin() const
Returns the const_iterator pointing to the first congruence, if this is not empty; otherwise...
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
bool OK() const
Checks if all the invariants are satisfied.
The entire library is confined to this namespace.
Definition: version.hh:61
Constraint_System constraints() const
Returns a system of constraints which approximates *this.
void add_recycled_congruences(Congruence_System &cgs)
Adds the congruences in cgs to *this.
void product_reduce(D1 &d1, D2 &d2)
The smash reduction operator for propagating emptiness between the domain elements d1 and d2...
Coefficient c
Definition: PIP_Tree.cc:64
This class provides the reduction method for the Smash_Product domain.
expr_type expression() const
Partial read access to the (adapted) internal expression.
const Constraint_System & minimized_constraints() const
Returns the system of constraints, with no redundant constraint.
static Poly_Con_Relation nothing()
The assertion that says nothing.
static Poly_Gen_Relation nothing()
The assertion that says nothing.
bool le(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
The relation between a polyhedron and a generator.
The relation between a polyhedron and a constraint.
void throw_space_dimension_overflow(const char *method, const char *reason)
bool has_strict_inequalities() const
Returns true if and only if *this contains one or more strict inequality constraints.