00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef PPL_Pointset_Powerset_templates_hh
00025 #define PPL_Pointset_Powerset_templates_hh 1
00026
00027 #include "Constraint.defs.hh"
00028 #include "Constraint_System.defs.hh"
00029 #include "Constraint_System.inlines.hh"
00030 #include "C_Polyhedron.defs.hh"
00031 #include "NNC_Polyhedron.defs.hh"
00032 #include "Variables_Set.defs.hh"
00033 #include <algorithm>
00034 #include <deque>
00035 #include <string>
00036 #include <iostream>
00037 #include <sstream>
00038 #include <stdexcept>
00039
00040 namespace Parma_Polyhedra_Library {
00041
00042 template <typename PSET>
00043 void
00044 Pointset_Powerset<PSET>::add_disjunct(const PSET& ph) {
00045 Pointset_Powerset& x = *this;
00046 if (x.space_dimension() != ph.space_dimension()) {
00047 std::ostringstream s;
00048 s << "PPL::Pointset_Powerset<PSET>::add_disjunct(ph):\n"
00049 << "this->space_dimension() == " << x.space_dimension() << ", "
00050 << "ph.space_dimension() == " << ph.space_dimension() << ".";
00051 throw std::invalid_argument(s.str());
00052 }
00053 x.sequence.push_back(Determinate<PSET>(ph));
00054 x.reduced = false;
00055 PPL_ASSERT_HEAVY(x.OK());
00056 }
00057
00058 template <>
00059 template <typename QH>
00060 Pointset_Powerset<NNC_Polyhedron>
00061 ::Pointset_Powerset(const Pointset_Powerset<QH>& y,
00062 Complexity_Class complexity)
00063 : Base(), space_dim(y.space_dimension()) {
00064 Pointset_Powerset& x = *this;
00065 for (typename Pointset_Powerset<QH>::const_iterator i = y.begin(),
00066 y_end = y.end(); i != y_end; ++i)
00067 x.sequence.push_back(Determinate<NNC_Polyhedron>
00068 (NNC_Polyhedron(i->pointset(), complexity)));
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 x.reduced = y.reduced;
00080
00081 PPL_ASSERT_HEAVY(x.OK());
00082 }
00083
00084 template <typename PSET>
00085 template <typename QH>
00086 Pointset_Powerset<PSET>
00087 ::Pointset_Powerset(const Pointset_Powerset<QH>& y,
00088 Complexity_Class complexity)
00089 : Base(), space_dim(y.space_dimension()) {
00090 Pointset_Powerset& x = *this;
00091 for (typename Pointset_Powerset<QH>::const_iterator i = y.begin(),
00092 y_end = y.end(); i != y_end; ++i)
00093 x.sequence.push_back(Determinate<PSET>(PSET(i->pointset(), complexity)));
00094
00095
00096
00097 x.reduced = false;
00098 PPL_ASSERT_HEAVY(x.OK());
00099 }
00100
00101 template <typename PSET>
00102 void
00103 Pointset_Powerset<PSET>::concatenate_assign(const Pointset_Powerset& y) {
00104 Pointset_Powerset& x = *this;
00105
00106 x.omega_reduce();
00107 y.omega_reduce();
00108 Pointset_Powerset<PSET> new_x(x.space_dim + y.space_dim, EMPTY);
00109 for (const_iterator xi = x.begin(), x_end = x.end(),
00110 y_begin = y.begin(), y_end = y.end(); xi != x_end; ) {
00111 for (const_iterator yi = y_begin; yi != y_end; ++yi) {
00112 Det_PSET zi = *xi;
00113 zi.concatenate_assign(*yi);
00114 PPL_ASSERT_HEAVY(!zi.is_bottom());
00115 new_x.sequence.push_back(zi);
00116 }
00117 ++xi;
00118 if (abandon_expensive_computations && xi != x_end && y_begin != y_end) {
00119
00120 PSET xph = xi->pointset();
00121 for (++xi; xi != x_end; ++xi)
00122 xph.upper_bound_assign(xi->pointset());
00123 const_iterator yi = y_begin;
00124 PSET yph = yi->pointset();
00125 for (++yi; yi != y_end; ++yi)
00126 yph.upper_bound_assign(yi->pointset());
00127 xph.concatenate_assign(yph);
00128 x.swap(new_x);
00129 x.add_disjunct(xph);
00130 PPL_ASSERT_HEAVY(x.OK());
00131 return;
00132 }
00133 }
00134 x.swap(new_x);
00135 PPL_ASSERT_HEAVY(x.OK());
00136 }
00137
00138 template <typename PSET>
00139 void
00140 Pointset_Powerset<PSET>::add_constraint(const Constraint& c) {
00141 Pointset_Powerset& x = *this;
00142 for (Sequence_iterator si = x.sequence.begin(),
00143 s_end = x.sequence.end(); si != s_end; ++si)
00144 si->pointset().add_constraint(c);
00145 x.reduced = false;
00146 PPL_ASSERT_HEAVY(x.OK());
00147 }
00148
00149 template <typename PSET>
00150 void
00151 Pointset_Powerset<PSET>::refine_with_constraint(const Constraint& c) {
00152 Pointset_Powerset& x = *this;
00153 for (Sequence_iterator si = x.sequence.begin(),
00154 s_end = x.sequence.end(); si != s_end; ++si)
00155 si->pointset().refine_with_constraint(c);
00156 x.reduced = false;
00157 PPL_ASSERT_HEAVY(x.OK());
00158 }
00159
00160 template <typename PSET>
00161 void
00162 Pointset_Powerset<PSET>::add_constraints(const Constraint_System& cs) {
00163 Pointset_Powerset& x = *this;
00164 for (Sequence_iterator si = x.sequence.begin(),
00165 s_end = x.sequence.end(); si != s_end; ++si)
00166 si->pointset().add_constraints(cs);
00167 x.reduced = false;
00168 PPL_ASSERT_HEAVY(x.OK());
00169 }
00170
00171 template <typename PSET>
00172 void
00173 Pointset_Powerset<PSET>::refine_with_constraints(const Constraint_System& cs) {
00174 Pointset_Powerset& x = *this;
00175 for (Sequence_iterator si = x.sequence.begin(),
00176 s_end = x.sequence.end(); si != s_end; ++si)
00177 si->pointset().refine_with_constraints(cs);
00178 x.reduced = false;
00179 PPL_ASSERT_HEAVY(x.OK());
00180 }
00181
00182 template <typename PSET>
00183 void
00184 Pointset_Powerset<PSET>::add_congruence(const Congruence& c) {
00185 Pointset_Powerset& x = *this;
00186 for (Sequence_iterator si = x.sequence.begin(),
00187 s_end = x.sequence.end(); si != s_end; ++si)
00188 si->pointset().add_congruence(c);
00189 x.reduced = false;
00190 PPL_ASSERT_HEAVY(x.OK());
00191 }
00192
00193 template <typename PSET>
00194 void
00195 Pointset_Powerset<PSET>::refine_with_congruence(const Congruence& cg) {
00196 Pointset_Powerset& x = *this;
00197 for (Sequence_iterator si = x.sequence.begin(),
00198 s_end = x.sequence.end(); si != s_end; ++si)
00199 si->pointset().refine_with_congruence(cg);
00200 x.reduced = false;
00201 PPL_ASSERT_HEAVY(x.OK());
00202 }
00203
00204 template <typename PSET>
00205 void
00206 Pointset_Powerset<PSET>::add_congruences(const Congruence_System& cs) {
00207 Pointset_Powerset& x = *this;
00208 for (Sequence_iterator si = x.sequence.begin(),
00209 s_end = x.sequence.end(); si != s_end; ++si)
00210 si->pointset().add_congruences(cs);
00211 x.reduced = false;
00212 PPL_ASSERT_HEAVY(x.OK());
00213 }
00214
00215 template <typename PSET>
00216 void
00217 Pointset_Powerset<PSET>::refine_with_congruences(const Congruence_System& cgs) {
00218 Pointset_Powerset& x = *this;
00219 for (Sequence_iterator si = x.sequence.begin(),
00220 s_end = x.sequence.end(); si != s_end; ++si)
00221 si->pointset().refine_with_congruences(cgs);
00222 x.reduced = false;
00223 PPL_ASSERT_HEAVY(x.OK());
00224 }
00225
00226 template <typename PSET>
00227 void
00228 Pointset_Powerset<PSET>::unconstrain(const Variable var) {
00229 Pointset_Powerset& x = *this;
00230 for (Sequence_iterator si = x.sequence.begin(),
00231 s_end = x.sequence.end(); si != s_end; ++si) {
00232 si->pointset().unconstrain(var);
00233 x.reduced = false;
00234 }
00235 PPL_ASSERT_HEAVY(x.OK());
00236 }
00237
00238 template <typename PSET>
00239 void
00240 Pointset_Powerset<PSET>::unconstrain(const Variables_Set& vars) {
00241 Pointset_Powerset& x = *this;
00242 for (Sequence_iterator si = x.sequence.begin(),
00243 s_end = x.sequence.end(); si != s_end; ++si) {
00244 si->pointset().unconstrain(vars);
00245 x.reduced = false;
00246 }
00247 PPL_ASSERT_HEAVY(x.OK());
00248 }
00249
00250 template <typename PSET>
00251 void
00252 Pointset_Powerset<PSET>::add_space_dimensions_and_embed(dimension_type m) {
00253 Pointset_Powerset& x = *this;
00254 for (Sequence_iterator si = x.sequence.begin(),
00255 s_end = x.sequence.end(); si != s_end; ++si)
00256 si->pointset().add_space_dimensions_and_embed(m);
00257 x.space_dim += m;
00258 PPL_ASSERT_HEAVY(x.OK());
00259 }
00260
00261 template <typename PSET>
00262 void
00263 Pointset_Powerset<PSET>::add_space_dimensions_and_project(dimension_type m) {
00264 Pointset_Powerset& x = *this;
00265 for (Sequence_iterator si = x.sequence.begin(),
00266 s_end = x.sequence.end(); si != s_end; ++si)
00267 si->pointset().add_space_dimensions_and_project(m);
00268 x.space_dim += m;
00269 PPL_ASSERT_HEAVY(x.OK());
00270 }
00271
00272 template <typename PSET>
00273 void
00274 Pointset_Powerset<PSET>::remove_space_dimensions(const Variables_Set& vars) {
00275 Pointset_Powerset& x = *this;
00276 Variables_Set::size_type num_removed = vars.size();
00277 if (num_removed > 0) {
00278 for (Sequence_iterator si = x.sequence.begin(),
00279 s_end = x.sequence.end(); si != s_end; ++si) {
00280 si->pointset().remove_space_dimensions(vars);
00281 x.reduced = false;
00282 }
00283 x.space_dim -= num_removed;
00284 PPL_ASSERT_HEAVY(x.OK());
00285 }
00286 }
00287
00288 template <typename PSET>
00289 void
00290 Pointset_Powerset<PSET>
00291 ::remove_higher_space_dimensions(dimension_type new_dimension) {
00292 Pointset_Powerset& x = *this;
00293 if (new_dimension < x.space_dim) {
00294 for (Sequence_iterator si = x.sequence.begin(),
00295 s_end = x.sequence.end(); si != s_end; ++si) {
00296 si->pointset().remove_higher_space_dimensions(new_dimension);
00297 x.reduced = false;
00298 }
00299 x.space_dim = new_dimension;
00300 PPL_ASSERT_HEAVY(x.OK());
00301 }
00302 }
00303
00304 template <typename PSET>
00305 template <typename Partial_Function>
00306 void
00307 Pointset_Powerset<PSET>::map_space_dimensions(const Partial_Function& pfunc) {
00308 Pointset_Powerset& x = *this;
00309 if (x.is_bottom()) {
00310 dimension_type n = 0;
00311 for (dimension_type i = x.space_dim; i-- > 0; ) {
00312 dimension_type new_i;
00313 if (pfunc.maps(i, new_i))
00314 ++n;
00315 }
00316 x.space_dim = n;
00317 }
00318 else {
00319 Sequence_iterator s_begin = x.sequence.begin();
00320 for (Sequence_iterator si = s_begin,
00321 s_end = x.sequence.end(); si != s_end; ++si)
00322 si->pointset().map_space_dimensions(pfunc);
00323 x.space_dim = s_begin->pointset().space_dimension();
00324 x.reduced = false;
00325 }
00326 PPL_ASSERT_HEAVY(x.OK());
00327 }
00328
00329 template <typename PSET>
00330 void
00331 Pointset_Powerset<PSET>::expand_space_dimension(Variable var,
00332 dimension_type m) {
00333 Pointset_Powerset& x = *this;
00334 for (Sequence_iterator si = x.sequence.begin(),
00335 s_end = x.sequence.end(); si != s_end; ++si)
00336 si->pointset().expand_space_dimension(var, m);
00337 x.space_dim += m;
00338 PPL_ASSERT_HEAVY(x.OK());
00339 }
00340
00341 template <typename PSET>
00342 void
00343 Pointset_Powerset<PSET>::fold_space_dimensions(const Variables_Set& vars,
00344 Variable dest) {
00345 Pointset_Powerset& x = *this;
00346 Variables_Set::size_type num_folded = vars.size();
00347 if (num_folded > 0) {
00348 for (Sequence_iterator si = x.sequence.begin(),
00349 s_end = x.sequence.end(); si != s_end; ++si)
00350 si->pointset().fold_space_dimensions(vars, dest);
00351 }
00352 x.space_dim -= num_folded;
00353 PPL_ASSERT_HEAVY(x.OK());
00354 }
00355
00356 template <typename PSET>
00357 void
00358 Pointset_Powerset<PSET>::affine_image(Variable var,
00359 const Linear_Expression& expr,
00360 Coefficient_traits::const_reference
00361 denominator) {
00362 Pointset_Powerset& x = *this;
00363 for (Sequence_iterator si = x.sequence.begin(),
00364 s_end = x.sequence.end(); si != s_end; ++si) {
00365 si->pointset().affine_image(var, expr, denominator);
00366
00367
00368
00369 x.reduced = false;
00370 }
00371 PPL_ASSERT_HEAVY(x.OK());
00372 }
00373
00374 template <typename PSET>
00375 void
00376 Pointset_Powerset<PSET>::affine_preimage(Variable var,
00377 const Linear_Expression& expr,
00378 Coefficient_traits::const_reference
00379 denominator) {
00380 Pointset_Powerset& x = *this;
00381 for (Sequence_iterator si = x.sequence.begin(),
00382 s_end = x.sequence.end(); si != s_end; ++si) {
00383 si->pointset().affine_preimage(var, expr, denominator);
00384
00385
00386
00387 x.reduced = false;
00388 }
00389 PPL_ASSERT_HEAVY(x.OK());
00390 }
00391
00392
00393 template <typename PSET>
00394 void
00395 Pointset_Powerset<PSET>
00396 ::generalized_affine_image(const Linear_Expression& lhs,
00397 const Relation_Symbol relsym,
00398 const Linear_Expression& rhs) {
00399 Pointset_Powerset& x = *this;
00400 for (Sequence_iterator si = x.sequence.begin(),
00401 s_end = x.sequence.end(); si != s_end; ++si) {
00402 si->pointset().generalized_affine_image(lhs, relsym, rhs);
00403 x.reduced = false;
00404 }
00405 PPL_ASSERT_HEAVY(x.OK());
00406 }
00407
00408 template <typename PSET>
00409 void
00410 Pointset_Powerset<PSET>
00411 ::generalized_affine_preimage(const Linear_Expression& lhs,
00412 const Relation_Symbol relsym,
00413 const Linear_Expression& rhs) {
00414 Pointset_Powerset& x = *this;
00415 for (Sequence_iterator si = x.sequence.begin(),
00416 s_end = x.sequence.end(); si != s_end; ++si) {
00417 si->pointset().generalized_affine_preimage(lhs, relsym, rhs);
00418 x.reduced = false;
00419 }
00420 PPL_ASSERT_HEAVY(x.OK());
00421 }
00422
00423 template <typename PSET>
00424 void
00425 Pointset_Powerset<PSET>
00426 ::generalized_affine_image(Variable var,
00427 const Relation_Symbol relsym,
00428 const Linear_Expression& expr,
00429 Coefficient_traits::const_reference denominator) {
00430 Pointset_Powerset& x = *this;
00431 for (Sequence_iterator si = x.sequence.begin(),
00432 s_end = x.sequence.end(); si != s_end; ++si) {
00433 si->pointset().generalized_affine_image(var, relsym, expr, denominator);
00434 x.reduced = false;
00435 }
00436 PPL_ASSERT_HEAVY(x.OK());
00437 }
00438
00439 template <typename PSET>
00440 void
00441 Pointset_Powerset<PSET>
00442 ::generalized_affine_preimage(Variable var,
00443 const Relation_Symbol relsym,
00444 const Linear_Expression& expr,
00445 Coefficient_traits::const_reference
00446 denominator) {
00447 Pointset_Powerset& x = *this;
00448 for (Sequence_iterator si = x.sequence.begin(),
00449 s_end = x.sequence.end(); si != s_end; ++si) {
00450 si->pointset().generalized_affine_preimage(var, relsym, expr, denominator);
00451 x.reduced = false;
00452 }
00453 PPL_ASSERT_HEAVY(x.OK());
00454 }
00455
00456
00457 template <typename PSET>
00458 void
00459 Pointset_Powerset<PSET>
00460 ::bounded_affine_image(Variable var,
00461 const Linear_Expression& lb_expr,
00462 const Linear_Expression& ub_expr,
00463 Coefficient_traits::const_reference denominator) {
00464 Pointset_Powerset& x = *this;
00465 for (Sequence_iterator si = x.sequence.begin(),
00466 s_end = x.sequence.end(); si != s_end; ++si) {
00467 si->pointset().bounded_affine_image(var, lb_expr, ub_expr, denominator);
00468 x.reduced = false;
00469 }
00470 PPL_ASSERT_HEAVY(x.OK());
00471 }
00472
00473 template <typename PSET>
00474 void
00475 Pointset_Powerset<PSET>
00476 ::bounded_affine_preimage(Variable var,
00477 const Linear_Expression& lb_expr,
00478 const Linear_Expression& ub_expr,
00479 Coefficient_traits::const_reference denominator) {
00480 Pointset_Powerset& x = *this;
00481 for (Sequence_iterator si = x.sequence.begin(),
00482 s_end = x.sequence.end(); si != s_end; ++si) {
00483 si->pointset().bounded_affine_preimage(var, lb_expr, ub_expr,
00484 denominator);
00485 x.reduced = false;
00486 }
00487 PPL_ASSERT_HEAVY(x.OK());
00488 }
00489
00490 template <typename PSET>
00491 dimension_type
00492 Pointset_Powerset<PSET>::affine_dimension() const {
00493
00494
00495 const Pointset_Powerset& x = *this;
00496 C_Polyhedron x_ph(space_dim, EMPTY);
00497
00498 for (Sequence_const_iterator si = x.sequence.begin(),
00499 s_end = x.sequence.end(); si != s_end; ++si) {
00500 PSET pi(si->pointset());
00501 if (!pi.is_empty()) {
00502 C_Polyhedron phi(space_dim);
00503 const Constraint_System& cs = pi.minimized_constraints();
00504 for (Constraint_System::const_iterator i = cs.begin(),
00505 cs_end = cs.end(); i != cs_end; ++i) {
00506 const Constraint& c = *i;
00507 if (c.is_equality())
00508 phi.add_constraint(c);
00509 }
00510 x_ph.poly_hull_assign(phi);
00511 }
00512 }
00513
00514 return x_ph.affine_dimension();
00515 }
00516
00517 template <typename PSET>
00518 bool
00519 Pointset_Powerset<PSET>::is_universe() const {
00520 const Pointset_Powerset& x = *this;
00521
00522 if (x.is_omega_reduced())
00523 return x.size() == 1 && x.begin()->pointset().is_universe();
00524
00525
00526 for (const_iterator x_i = x.begin(), x_end = x.end(); x_i != x_end; ++x_i)
00527 if (x_i->pointset().is_universe()) {
00528
00529 if (x.size() > 1) {
00530 Pointset_Powerset<PSET> universe(x.space_dimension(), UNIVERSE);
00531 Pointset_Powerset& xx = const_cast<Pointset_Powerset&>(x);
00532 xx.swap(universe);
00533 }
00534 return true;
00535 }
00536 return false;
00537 }
00538
00539 template <typename PSET>
00540 bool
00541 Pointset_Powerset<PSET>::is_empty() const {
00542 const Pointset_Powerset& x = *this;
00543 for (Sequence_const_iterator si = x.sequence.begin(),
00544 s_end = x.sequence.end(); si != s_end; ++si)
00545 if (!si->pointset().is_empty())
00546 return false;
00547 return true;
00548 }
00549
00550 template <typename PSET>
00551 bool
00552 Pointset_Powerset<PSET>::is_discrete() const {
00553 const Pointset_Powerset& x = *this;
00554 for (Sequence_const_iterator si = x.sequence.begin(),
00555 s_end = x.sequence.end(); si != s_end; ++si)
00556 if (!si->pointset().is_discrete())
00557 return false;
00558 return true;
00559 }
00560
00561 template <typename PSET>
00562 bool
00563 Pointset_Powerset<PSET>::is_topologically_closed() const {
00564 const Pointset_Powerset& x = *this;
00565
00566
00567 x.omega_reduce();
00568 for (Sequence_const_iterator si = x.sequence.begin(),
00569 s_end = x.sequence.end(); si != s_end; ++si)
00570 if (!si->pointset().is_topologically_closed())
00571 return false;
00572 return true;
00573 }
00574
00575 template <typename PSET>
00576 bool
00577 Pointset_Powerset<PSET>::is_bounded() const {
00578 const Pointset_Powerset& x = *this;
00579 for (Sequence_const_iterator si = x.sequence.begin(),
00580 s_end = x.sequence.end(); si != s_end; ++si)
00581 if (!si->pointset().is_bounded())
00582 return false;
00583 return true;
00584 }
00585
00586 template <typename PSET>
00587 bool
00588 Pointset_Powerset<PSET>::constrains(Variable var) const {
00589 const Pointset_Powerset& x = *this;
00590
00591 const dimension_type var_space_dim = var.space_dimension();
00592 if (x.space_dimension() < var_space_dim) {
00593 std::ostringstream s;
00594 s << "PPL::Pointset_Powerset<PSET>::constrains(v):\n"
00595 << "this->space_dimension() == " << x.space_dimension() << ", "
00596 << "v.space_dimension() == " << var_space_dim << ".";
00597 throw std::invalid_argument(s.str());
00598 }
00599
00600 x.omega_reduce();
00601
00602 if (x.is_empty())
00603 return true;
00604 for (const_iterator x_i = x.begin(), x_end = x.end(); x_i != x_end; ++x_i)
00605 if (x_i->pointset().constrains(var))
00606 return true;
00607 return false;
00608 }
00609
00610 template <typename PSET>
00611 bool
00612 Pointset_Powerset<PSET>::is_disjoint_from(const Pointset_Powerset& y) const {
00613 const Pointset_Powerset& x = *this;
00614 for (Sequence_const_iterator si = x.sequence.begin(),
00615 xs_end = x.sequence.end(); si != xs_end; ++si) {
00616 const PSET& pi = si->pointset();
00617 for (Sequence_const_iterator sj = y.sequence.begin(),
00618 ys_end = y.sequence.end(); sj != ys_end; ++sj) {
00619 const PSET& pj = sj->pointset();
00620 if (!pi.is_disjoint_from(pj))
00621 return false;
00622 }
00623 }
00624 return true;
00625 }
00626
00627 template <typename PSET>
00628 void
00629 Pointset_Powerset<PSET>
00630 ::drop_some_non_integer_points(const Variables_Set& vars,
00631 Complexity_Class complexity) {
00632 Pointset_Powerset& x = *this;
00633 for (Sequence_iterator si = x.sequence.begin(),
00634 s_end = x.sequence.end(); si != s_end; ++si)
00635 si->pointset().drop_some_non_integer_points(vars, complexity);
00636 x.reduced = false;
00637 PPL_ASSERT_HEAVY(x.OK());
00638 }
00639
00640 template <typename PSET>
00641 void
00642 Pointset_Powerset<PSET>
00643 ::drop_some_non_integer_points(Complexity_Class complexity) {
00644 Pointset_Powerset& x = *this;
00645 for (Sequence_iterator si = x.sequence.begin(),
00646 s_end = x.sequence.end(); si != s_end; ++si)
00647 si->pointset().drop_some_non_integer_points(complexity);
00648 x.reduced = false;
00649 PPL_ASSERT_HEAVY(x.OK());
00650 }
00651
00652 template <typename PSET>
00653 void
00654 Pointset_Powerset<PSET>::topological_closure_assign() {
00655 Pointset_Powerset& x = *this;
00656 for (Sequence_iterator si = x.sequence.begin(),
00657 s_end = x.sequence.end(); si != s_end; ++si)
00658 si->pointset().topological_closure_assign();
00659 PPL_ASSERT_HEAVY(x.OK());
00660 }
00661
00662 template <typename PSET>
00663 bool
00664 Pointset_Powerset<PSET>
00665 ::intersection_preserving_enlarge_element(PSET& dest) const {
00666
00667 const Pointset_Powerset& context = *this;
00668 PPL_ASSERT(context.space_dimension() == dest.space_dimension());
00669 bool nonempty_intersection = false;
00670
00671 PSET enlarged(context.space_dimension(), UNIVERSE);
00672 for (Sequence_const_iterator si = context.sequence.begin(),
00673 s_end = context.sequence.end(); si != s_end; ++si) {
00674 PSET context_i(si->pointset());
00675 context_i.intersection_assign(enlarged);
00676 PSET enlarged_i(dest);
00677 nonempty_intersection
00678 |= enlarged_i.simplify_using_context_assign(context_i);
00679
00680 enlarged.intersection_assign(enlarged_i);
00681 }
00682 dest.swap(enlarged);
00683 return nonempty_intersection;
00684 }
00685
00686 template <typename PSET>
00687 bool
00688 Pointset_Powerset<PSET>
00689 ::simplify_using_context_assign(const Pointset_Powerset& y) {
00690 Pointset_Powerset& x = *this;
00691
00692
00693
00694
00695
00696
00697 x.omega_reduce();
00698 if (x.is_empty())
00699 return false;
00700 y.omega_reduce();
00701 if (y.is_empty()) {
00702 x = y;
00703 return false;
00704 }
00705
00706 if (y.size() == 1) {
00707
00708 const PSET& y_i = y.sequence.begin()->pointset();
00709 for (Sequence_iterator si = x.sequence.begin(),
00710 s_end = x.sequence.end(); si != s_end; ) {
00711 PSET& x_i = si->pointset();
00712 if (x_i.simplify_using_context_assign(y_i))
00713 ++si;
00714 else
00715
00716 si = x.sequence.erase(si);
00717 }
00718 }
00719 else {
00720
00721 for (Sequence_iterator si = x.sequence.begin(),
00722 s_end = x.sequence.end(); si != s_end; ) {
00723 if (y.intersection_preserving_enlarge_element(si->pointset()))
00724 ++si;
00725 else
00726
00727 si = x.sequence.erase(si);
00728 }
00729 }
00730 x.reduced = false;
00731 PPL_ASSERT_HEAVY(x.OK());
00732 return !x.sequence.empty();
00733 }
00734
00735 template <typename PSET>
00736 bool
00737 Pointset_Powerset<PSET>::contains(const Pointset_Powerset& y) const {
00738 const Pointset_Powerset& x = *this;
00739 for (Sequence_const_iterator si = y.sequence.begin(),
00740 ys_end = y.sequence.end(); si != ys_end; ++si) {
00741 const PSET& pi = si->pointset();
00742 bool pi_is_contained = false;
00743 for (Sequence_const_iterator sj = x.sequence.begin(),
00744 xs_end = x.sequence.end();
00745 (sj != xs_end && !pi_is_contained); ++sj) {
00746 const PSET& pj = sj->pointset();
00747 if (pj.contains(pi))
00748 pi_is_contained = true;
00749 }
00750 if (!pi_is_contained)
00751 return false;
00752 }
00753 return true;
00754 }
00755
00756 template <typename PSET>
00757 bool
00758 Pointset_Powerset<PSET>::strictly_contains(const Pointset_Powerset& y) const {
00759
00760
00761
00762 const Pointset_Powerset& x = *this;
00763 x.omega_reduce();
00764 for (Sequence_const_iterator si = y.sequence.begin(),
00765 ys_end = y.sequence.end(); si != ys_end; ++si) {
00766 const PSET& pi = si->pointset();
00767 bool pi_is_strictly_contained = false;
00768 for (Sequence_const_iterator sj = x.sequence.begin(),
00769 xs_end = x.sequence.end();
00770 (sj != xs_end && !pi_is_strictly_contained); ++sj) {
00771 const PSET& pj = sj->pointset();
00772 if (pj.strictly_contains(pi))
00773 pi_is_strictly_contained = true;
00774 }
00775 if (!pi_is_strictly_contained)
00776 return false;
00777 }
00778 return true;
00779 }
00780
00781 template <typename PSET>
00782 Poly_Con_Relation
00783 Pointset_Powerset<PSET>::relation_with(const Congruence& cg) const {
00784 const Pointset_Powerset& x = *this;
00785
00786
00787 bool is_included = true;
00788
00789 bool is_disjoint = true;
00790
00791
00792 bool is_strictly_intersecting = false;
00793
00794
00795 bool saturates_once = false;
00796 bool may_saturate = true;
00797 for (Sequence_const_iterator si = x.sequence.begin(),
00798 s_end = x.sequence.end(); si != s_end; ++si) {
00799 Poly_Con_Relation relation_i = si->pointset().relation_with(cg);
00800 if (!relation_i.implies(Poly_Con_Relation::is_included()))
00801 is_included = false;
00802 if (!relation_i.implies(Poly_Con_Relation::is_disjoint()))
00803 is_disjoint = false;
00804 if (relation_i.implies(Poly_Con_Relation::strictly_intersects()))
00805 is_strictly_intersecting = true;
00806 if (relation_i.implies(Poly_Con_Relation::saturates()))
00807 saturates_once = true;
00808 else if (!relation_i.implies(Poly_Con_Relation::is_disjoint()))
00809 may_saturate = false;
00810 }
00811
00812 Poly_Con_Relation result = Poly_Con_Relation::nothing();
00813 if (is_included)
00814 result = result && Poly_Con_Relation::is_included();
00815 if (is_disjoint)
00816 result = result && Poly_Con_Relation::is_disjoint();
00817 if (is_strictly_intersecting)
00818 result = result && Poly_Con_Relation::strictly_intersects();
00819 if (saturates_once && may_saturate)
00820 result = result && Poly_Con_Relation::saturates();
00821
00822 return result;
00823 }
00824
00825 template <typename PSET>
00826 Poly_Con_Relation
00827 Pointset_Powerset<PSET>::relation_with(const Constraint& c) const {
00828 const Pointset_Powerset& x = *this;
00829
00830
00831 bool is_included = true;
00832
00833 bool is_disjoint = true;
00834
00835
00836 bool is_strictly_intersecting = false;
00837
00838
00839 bool saturates_once = false;
00840 bool may_saturate = true;
00841 for (Sequence_const_iterator si = x.sequence.begin(),
00842 s_end = x.sequence.end(); si != s_end; ++si) {
00843 Poly_Con_Relation relation_i = si->pointset().relation_with(c);
00844 if (!relation_i.implies(Poly_Con_Relation::is_included()))
00845 is_included = false;
00846 if (!relation_i.implies(Poly_Con_Relation::is_disjoint()))
00847 is_disjoint = false;
00848 if (relation_i.implies(Poly_Con_Relation::strictly_intersects()))
00849 is_strictly_intersecting = true;
00850 if (relation_i.implies(Poly_Con_Relation::saturates()))
00851 saturates_once = true;
00852 else if (!relation_i.implies(Poly_Con_Relation::is_disjoint()))
00853 may_saturate = false;
00854 }
00855
00856 Poly_Con_Relation result = Poly_Con_Relation::nothing();
00857 if (is_included)
00858 result = result && Poly_Con_Relation::is_included();
00859 if (is_disjoint)
00860 result = result && Poly_Con_Relation::is_disjoint();
00861 if (is_strictly_intersecting)
00862 result = result && Poly_Con_Relation::strictly_intersects();
00863 if (saturates_once && may_saturate)
00864 result = result && Poly_Con_Relation::saturates();
00865
00866 return result;
00867 }
00868
00869 template <typename PSET>
00870 Poly_Gen_Relation
00871 Pointset_Powerset<PSET>::relation_with(const Generator& g) const {
00872 const Pointset_Powerset& x = *this;
00873
00874 for (Sequence_const_iterator si = x.sequence.begin(),
00875 s_end = x.sequence.end(); si != s_end; ++si) {
00876 Poly_Gen_Relation relation_i = si->pointset().relation_with(g);
00877 if (relation_i.implies(Poly_Gen_Relation::subsumes()))
00878 return Poly_Gen_Relation::subsumes();
00879 }
00880
00881 return Poly_Gen_Relation::nothing();
00882 }
00883
00884 template <typename PSET>
00885 bool
00886 Pointset_Powerset<PSET>
00887 ::bounds_from_above(const Linear_Expression& expr) const {
00888 const Pointset_Powerset& x = *this;
00889 x.omega_reduce();
00890 for (Sequence_const_iterator si = x.sequence.begin(),
00891 s_end = x.sequence.end(); si != s_end; ++si)
00892 if (!si->pointset().bounds_from_above(expr))
00893 return false;
00894 return true;
00895 }
00896
00897 template <typename PSET>
00898 bool
00899 Pointset_Powerset<PSET>
00900 ::bounds_from_below(const Linear_Expression& expr) const {
00901 const Pointset_Powerset& x = *this;
00902 x.omega_reduce();
00903 for (Sequence_const_iterator si = x.sequence.begin(),
00904 s_end = x.sequence.end(); si != s_end; ++si)
00905 if (!si->pointset().bounds_from_below(expr))
00906 return false;
00907 return true;
00908 }
00909
00910 template <typename PSET>
00911 bool
00912 Pointset_Powerset<PSET>::maximize(const Linear_Expression& expr,
00913 Coefficient& sup_n,
00914 Coefficient& sup_d,
00915 bool& maximum) const {
00916 const Pointset_Powerset& x = *this;
00917 x.omega_reduce();
00918 if (x.is_empty())
00919 return false;
00920
00921 bool first = true;
00922
00923 PPL_DIRTY_TEMP_COEFFICIENT(supt_n);
00924 PPL_DIRTY_TEMP_COEFFICIENT(supt_d);
00925 supt_n = 0;
00926 supt_d = 1;
00927 bool maxt = 0;
00928
00929 PPL_DIRTY_TEMP_COEFFICIENT(supi_n);
00930 PPL_DIRTY_TEMP_COEFFICIENT(supi_d);
00931 supi_n = 0;
00932 supi_d = 1;
00933 bool maxi = 0;
00934
00935 PPL_DIRTY_TEMP_COEFFICIENT(tmp);
00936
00937 for (Sequence_const_iterator si = x.sequence.begin(),
00938 s_end = x.sequence.end(); si != s_end; ++si) {
00939 if (!si->pointset().maximize(expr, supi_n, supi_d, maxi))
00940 return false;
00941 else
00942 if (first) {
00943 first = false;
00944 supt_n = supi_n;
00945 supt_d = supi_d;
00946 maxt = maxi;
00947 }
00948 else {
00949 tmp = (supt_n * supi_d) - (supi_n * supt_d);
00950 if (tmp < 0) {
00951 supt_n = supi_n;
00952 supt_d = supi_d;
00953 maxt = maxi;
00954 }
00955 else if (tmp == 0)
00956 maxt = maxt || maxi;
00957 }
00958 }
00959 sup_n = supt_n;
00960 sup_d = supt_d;
00961 maximum = maxt;
00962 return true;
00963 }
00964
00965 template <typename PSET>
00966 bool
00967 Pointset_Powerset<PSET>::maximize(const Linear_Expression& expr,
00968 Coefficient& sup_n,
00969 Coefficient& sup_d,
00970 bool& maximum,
00971 Generator& g) const {
00972 const Pointset_Powerset& x = *this;
00973 x.omega_reduce();
00974 if (x.is_empty())
00975 return false;
00976
00977 bool first = true;
00978
00979 PPL_DIRTY_TEMP_COEFFICIENT(supt_n);
00980 PPL_DIRTY_TEMP_COEFFICIENT(supt_d);
00981 supt_n = 0;
00982 supt_d = 1;
00983 bool maxt = 0;
00984 Generator gt = point();
00985
00986 PPL_DIRTY_TEMP_COEFFICIENT(supi_n);
00987 PPL_DIRTY_TEMP_COEFFICIENT(supi_d);
00988 supi_n = 0;
00989 supi_d = 1;
00990 bool maxi = 0;
00991 Generator gi = point();
00992
00993 PPL_DIRTY_TEMP_COEFFICIENT(tmp);
00994
00995 for (Sequence_const_iterator si = x.sequence.begin(),
00996 s_end = x.sequence.end(); si != s_end; ++si) {
00997 if (!si->pointset().maximize(expr, supi_n, supi_d, maxi, gi))
00998 return false;
00999 else
01000 if (first) {
01001 first = false;
01002 supt_n = supi_n;
01003 supt_d = supi_d;
01004 maxt = maxi;
01005 gt = gi;
01006 }
01007 else {
01008 tmp = (supt_n * supi_d) - (supi_n * supt_d);
01009 if (tmp < 0) {
01010 supt_n = supi_n;
01011 supt_d = supi_d;
01012 maxt = maxi;
01013 gt = gi;
01014 }
01015 else if (tmp == 0) {
01016 maxt = maxt || maxi;
01017 gt = gi;
01018 }
01019 }
01020 }
01021 sup_n = supt_n;
01022 sup_d = supt_d;
01023 maximum = maxt;
01024 g = gt;
01025 return true;
01026 }
01027
01028 template <typename PSET>
01029 bool
01030 Pointset_Powerset<PSET>::minimize(const Linear_Expression& expr,
01031 Coefficient& inf_n,
01032 Coefficient& inf_d,
01033 bool& minimum) const {
01034 const Pointset_Powerset& x = *this;
01035 x.omega_reduce();
01036 if (x.is_empty())
01037 return false;
01038
01039 bool first = true;
01040
01041 PPL_DIRTY_TEMP_COEFFICIENT(inft_n);
01042 PPL_DIRTY_TEMP_COEFFICIENT(inft_d);
01043 inft_n = 0;
01044 inft_d = 1;
01045 bool mint = 0;
01046
01047 PPL_DIRTY_TEMP_COEFFICIENT(infi_n);
01048 PPL_DIRTY_TEMP_COEFFICIENT(infi_d);
01049 infi_n = 0;
01050 infi_d = 1;
01051 bool mini = 0;
01052
01053 PPL_DIRTY_TEMP_COEFFICIENT(tmp);
01054
01055 for (Sequence_const_iterator si = x.sequence.begin(),
01056 s_end = x.sequence.end(); si != s_end; ++si) {
01057 if (!si->pointset().minimize(expr, infi_n, infi_d, mini))
01058 return false;
01059 else
01060 if (first) {
01061 first = false;
01062 inft_n = infi_n;
01063 inft_d = infi_d;
01064 mint = mini;
01065 }
01066 else {
01067 tmp = (inft_n * infi_d) - (infi_n * inft_d);
01068 if (tmp > 0) {
01069 inft_n = infi_n;
01070 inft_d = infi_d;
01071 mint = mini;
01072 }
01073 else if (tmp == 0)
01074 mint = mint || mini;
01075 }
01076 }
01077 inf_n = inft_n;
01078 inf_d = inft_d;
01079 minimum = mint;
01080 return true;
01081 }
01082
01083 template <typename PSET>
01084 bool
01085 Pointset_Powerset<PSET>::minimize(const Linear_Expression& expr,
01086 Coefficient& inf_n,
01087 Coefficient& inf_d,
01088 bool& minimum,
01089 Generator& g) const {
01090 const Pointset_Powerset& x = *this;
01091 x.omega_reduce();
01092 if (x.is_empty())
01093 return false;
01094
01095 bool first = true;
01096
01097 PPL_DIRTY_TEMP_COEFFICIENT(inft_n);
01098 PPL_DIRTY_TEMP_COEFFICIENT(inft_d);
01099 inft_n = 0;
01100 inft_d = 1;
01101 bool mint = 0;
01102 Generator gt = point();
01103
01104 PPL_DIRTY_TEMP_COEFFICIENT(infi_n);
01105 PPL_DIRTY_TEMP_COEFFICIENT(infi_d);
01106 infi_n = 0;
01107 infi_d = 1;
01108 bool mini = 0;
01109 Generator gi = point();
01110
01111 PPL_DIRTY_TEMP_COEFFICIENT(tmp);
01112
01113 for (Sequence_const_iterator si = x.sequence.begin(),
01114 s_end = x.sequence.end(); si != s_end; ++si) {
01115 if (!si->pointset().minimize(expr, infi_n, infi_d, mini, gi))
01116 return false;
01117 else
01118 if (first) {
01119 first = false;
01120 inft_n = infi_n;
01121 inft_d = infi_d;
01122 mint = mini;
01123 gt = gi;
01124 }
01125 else {
01126 tmp = (inft_n * infi_d) - (infi_n * inft_d);
01127 if (tmp > 0) {
01128 inft_n = infi_n;
01129 inft_d = infi_d;
01130 mint = mini;
01131 gt = gi;
01132 }
01133 else if (tmp == 0) {
01134 mint = mint || mini;
01135 gt = gi;
01136 }
01137 }
01138 }
01139 inf_n = inft_n;
01140 inf_d = inft_d;
01141 minimum = mint;
01142 g = gt;
01143 return true;
01144 }
01145
01146 template <typename PSET>
01147 bool
01148 Pointset_Powerset<PSET>::contains_integer_point() const {
01149 const Pointset_Powerset& x = *this;
01150 for (Sequence_const_iterator si = x.sequence.begin(),
01151 s_end = x.sequence.end(); si != s_end; ++si)
01152 if (si->pointset().contains_integer_point())
01153 return true;
01154 return false;
01155 }
01156
01157 template <typename PSET>
01158 void
01159 Pointset_Powerset<PSET>::wrap_assign(const Variables_Set& vars,
01160 Bounded_Integer_Type_Width w,
01161 Bounded_Integer_Type_Representation r,
01162 Bounded_Integer_Type_Overflow o,
01163 const Constraint_System* pcs,
01164 unsigned complexity_threshold,
01165 bool wrap_individually) {
01166 Pointset_Powerset& x = *this;
01167 for (Sequence_iterator si = x.sequence.begin(),
01168 s_end = x.sequence.end(); si != s_end; ++si)
01169 si->pointset().wrap_assign(vars, w, r, o, pcs,
01170 complexity_threshold, wrap_individually);
01171 x.reduced = false;
01172 PPL_ASSERT_HEAVY(x.OK());
01173 }
01174
01175 template <typename PSET>
01176 void
01177 Pointset_Powerset<PSET>::pairwise_reduce() {
01178 Pointset_Powerset& x = *this;
01179
01180 x.omega_reduce();
01181
01182 size_type n = x.size();
01183 size_type deleted;
01184 do {
01185 Pointset_Powerset new_x(x.space_dim, EMPTY);
01186 std::deque<bool> marked(n, false);
01187 deleted = 0;
01188 Sequence_iterator s_begin = x.sequence.begin();
01189 Sequence_iterator s_end = x.sequence.end();
01190 unsigned si_index = 0;
01191 for (Sequence_iterator si = s_begin; si != s_end; ++si, ++si_index) {
01192 if (marked[si_index])
01193 continue;
01194 PSET& pi = si->pointset();
01195 Sequence_const_iterator sj = si;
01196 unsigned sj_index = si_index;
01197 for (++sj, ++sj_index; sj != s_end; ++sj, ++sj_index) {
01198 if (marked[sj_index])
01199 continue;
01200 const PSET& pj = sj->pointset();
01201 if (pi.upper_bound_assign_if_exact(pj)) {
01202 marked[si_index] = marked[sj_index] = true;
01203 new_x.add_non_bottom_disjunct_preserve_reduction(pi);
01204 ++deleted;
01205 goto next;
01206 }
01207 }
01208 next:
01209 ;
01210 }
01211 iterator nx_begin = new_x.begin();
01212 iterator nx_end = new_x.end();
01213 unsigned xi_index = 0;
01214 for (const_iterator xi = x.begin(),
01215 x_end = x.end(); xi != x_end; ++xi, ++xi_index)
01216 if (!marked[xi_index])
01217 nx_begin = new_x.add_non_bottom_disjunct_preserve_reduction(*xi,
01218 nx_begin,
01219 nx_end);
01220 std::swap(x.sequence, new_x.sequence);
01221 n -= deleted;
01222 } while (deleted > 0);
01223 PPL_ASSERT_HEAVY(x.OK());
01224 }
01225
01226 template <typename PSET>
01227 template <typename Widening>
01228 void
01229 Pointset_Powerset<PSET>::
01230 BGP99_heuristics_assign(const Pointset_Powerset& y, Widening wf) {
01231
01232 Pointset_Powerset& x = *this;
01233
01234 #ifndef NDEBUG
01235 {
01236
01237 const Pointset_Powerset<PSET> x_copy = x;
01238 const Pointset_Powerset<PSET> y_copy = y;
01239 PPL_ASSERT_HEAVY(y_copy.definitely_entails(x_copy));
01240 }
01241 #endif
01242
01243 size_type n = x.size();
01244 Pointset_Powerset new_x(x.space_dim, EMPTY);
01245 std::deque<bool> marked(n, false);
01246 const_iterator x_begin = x.begin();
01247 const_iterator x_end = x.end();
01248 unsigned i_index = 0;
01249 for (const_iterator i = x_begin,
01250 y_begin = y.begin(), y_end = y.end(); i != x_end; ++i, ++i_index)
01251 for (const_iterator j = y_begin; j != y_end; ++j) {
01252 const PSET& pi = i->pointset();
01253 const PSET& pj = j->pointset();
01254 if (pi.contains(pj)) {
01255 PSET pi_copy = pi;
01256 wf(pi_copy, pj);
01257 new_x.add_non_bottom_disjunct_preserve_reduction(pi_copy);
01258 marked[i_index] = true;
01259 }
01260 }
01261 iterator nx_begin = new_x.begin();
01262 iterator nx_end = new_x.end();
01263 i_index = 0;
01264 for (const_iterator i = x_begin; i != x_end; ++i, ++i_index)
01265 if (!marked[i_index])
01266 nx_begin = new_x.add_non_bottom_disjunct_preserve_reduction(*i,
01267 nx_begin,
01268 nx_end);
01269 std::swap(x.sequence, new_x.sequence);
01270 PPL_ASSERT_HEAVY(x.OK());
01271 PPL_ASSERT(x.is_omega_reduced());
01272 }
01273
01274 template <typename PSET>
01275 template <typename Widening>
01276 void
01277 Pointset_Powerset<PSET>::
01278 BGP99_extrapolation_assign(const Pointset_Powerset& y,
01279 Widening wf,
01280 unsigned max_disjuncts) {
01281
01282 Pointset_Powerset& x = *this;
01283
01284 #ifndef NDEBUG
01285 {
01286
01287 const Pointset_Powerset<PSET> x_copy = x;
01288 const Pointset_Powerset<PSET> y_copy = y;
01289 PPL_ASSERT_HEAVY(y_copy.definitely_entails(x_copy));
01290 }
01291 #endif
01292
01293 x.pairwise_reduce();
01294 if (max_disjuncts != 0)
01295 x.collapse(max_disjuncts);
01296 x.BGP99_heuristics_assign(y, wf);
01297 }
01298
01299 template <typename PSET>
01300 template <typename Cert>
01301 void
01302 Pointset_Powerset<PSET>::
01303 collect_certificates(std::map<Cert, size_type,
01304 typename Cert::Compare>& cert_ms) const {
01305 const Pointset_Powerset& x = *this;
01306 PPL_ASSERT(x.is_omega_reduced());
01307 PPL_ASSERT(cert_ms.size() == 0);
01308 for (const_iterator i = x.begin(), end = x.end(); i != end; i++) {
01309 Cert ph_cert(i->pointset());
01310 ++cert_ms[ph_cert];
01311 }
01312 }
01313
01314 template <typename PSET>
01315 template <typename Cert>
01316 bool
01317 Pointset_Powerset<PSET>::
01318 is_cert_multiset_stabilizing(const std::map<Cert, size_type,
01319 typename Cert::Compare>& y_cert_ms) const {
01320 typedef std::map<Cert, size_type, typename Cert::Compare> Cert_Multiset;
01321 Cert_Multiset x_cert_ms;
01322 collect_certificates(x_cert_ms);
01323 typename Cert_Multiset::const_iterator
01324 xi = x_cert_ms.begin(),
01325 x_cert_ms_end = x_cert_ms.end(),
01326 yi = y_cert_ms.begin(),
01327 y_cert_ms_end = y_cert_ms.end();
01328 while (xi != x_cert_ms_end && yi != y_cert_ms_end) {
01329 const Cert& xi_cert = xi->first;
01330 const Cert& yi_cert = yi->first;
01331 switch (xi_cert.compare(yi_cert)) {
01332 case 0:
01333
01334 {
01335 const size_type& xi_count = xi->second;
01336 const size_type& yi_count = yi->second;
01337 if (xi_count == yi_count) {
01338
01339 ++xi;
01340 ++yi;
01341 }
01342 else
01343
01344 return xi_count < yi_count;
01345 break;
01346 }
01347 case 1:
01348
01349 return false;
01350
01351 case -1:
01352
01353 return true;
01354 }
01355 }
01356
01357
01358 return yi != y_cert_ms_end;
01359 }
01360
01361 template <typename PSET>
01362 template <typename Cert, typename Widening>
01363 void
01364 Pointset_Powerset<PSET>::BHZ03_widening_assign(const Pointset_Powerset& y,
01365 Widening wf) {
01366
01367 Pointset_Powerset& x = *this;
01368
01369 #ifndef NDEBUG
01370 {
01371
01372 const Pointset_Powerset<PSET> x_copy = x;
01373 const Pointset_Powerset<PSET> y_copy = y;
01374 PPL_ASSERT_HEAVY(y_copy.definitely_entails(x_copy));
01375 }
01376 #endif
01377
01378
01379
01380
01381 PPL_ASSERT(x.size() > 0);
01382 if (y.size() == 0)
01383 return;
01384
01385
01386 PSET x_hull(x.space_dim, EMPTY);
01387 for (const_iterator i = x.begin(), x_end = x.end(); i != x_end; ++i)
01388 x_hull.upper_bound_assign(i->pointset());
01389
01390
01391 PSET y_hull(y.space_dim, EMPTY);
01392 for (const_iterator i = y.begin(), y_end = y.end(); i != y_end; ++i)
01393 y_hull.upper_bound_assign(i->pointset());
01394
01395 const Cert y_hull_cert(y_hull);
01396
01397
01398 int hull_stabilization = y_hull_cert.compare(x_hull);
01399 if (hull_stabilization == 1)
01400 return;
01401
01402
01403 const bool y_is_not_a_singleton = y.size() > 1;
01404
01405
01406
01407 typedef std::map<Cert, size_type, typename Cert::Compare> Cert_Multiset;
01408 Cert_Multiset y_cert_ms;
01409 bool y_cert_ms_computed = false;
01410
01411 if (hull_stabilization == 0 && y_is_not_a_singleton) {
01412
01413 y.collect_certificates(y_cert_ms);
01414 y_cert_ms_computed = true;
01415
01416 if (x.is_cert_multiset_stabilizing(y_cert_ms))
01417 return;
01418 }
01419
01420
01421 Pointset_Powerset<PSET> bgp99_heuristics = x;
01422 bgp99_heuristics.BGP99_heuristics_assign(y, wf);
01423
01424
01425 PSET bgp99_heuristics_hull(x.space_dim, EMPTY);
01426 for (const_iterator i = bgp99_heuristics.begin(),
01427 bh_end = bgp99_heuristics.end(); i != bh_end; ++i)
01428 bgp99_heuristics_hull.upper_bound_assign(i->pointset());
01429
01430
01431
01432 hull_stabilization = y_hull_cert.compare(bgp99_heuristics_hull);
01433 if (hull_stabilization == 1) {
01434
01435 std::swap(x, bgp99_heuristics);
01436 return;
01437 }
01438 else if (hull_stabilization == 0 && y_is_not_a_singleton) {
01439
01440 if (!y_cert_ms_computed) {
01441 y.collect_certificates(y_cert_ms);
01442 y_cert_ms_computed = true;
01443 }
01444 if (bgp99_heuristics.is_cert_multiset_stabilizing(y_cert_ms)) {
01445 std::swap(x, bgp99_heuristics);
01446 return;
01447 }
01448
01449
01450
01451
01452 Pointset_Powerset<PSET> reduced_bgp99_heuristics(bgp99_heuristics);
01453 reduced_bgp99_heuristics.pairwise_reduce();
01454 if (reduced_bgp99_heuristics.is_cert_multiset_stabilizing(y_cert_ms)) {
01455 std::swap(x, reduced_bgp99_heuristics);
01456 return;
01457 }
01458 }
01459
01460
01461
01462 if (bgp99_heuristics_hull.strictly_contains(y_hull)) {
01463
01464 PSET ph = bgp99_heuristics_hull;
01465 wf(ph, y_hull);
01466
01467 ph.difference_assign(bgp99_heuristics_hull);
01468 x.add_disjunct(ph);
01469 return;
01470 }
01471
01472
01473 Pointset_Powerset<PSET> x_hull_singleton(x.space_dim, EMPTY);
01474 x_hull_singleton.add_disjunct(x_hull);
01475 std::swap(x, x_hull_singleton);
01476 }
01477
01478 template <typename PSET>
01479 void
01480 Pointset_Powerset<PSET>::ascii_dump(std::ostream& s) const {
01481 const Pointset_Powerset& x = *this;
01482 s << "size " << x.size()
01483 << "\nspace_dim " << x.space_dim
01484 << "\n";
01485 for (const_iterator xi = x.begin(), x_end = x.end(); xi != x_end; ++xi)
01486 xi->pointset().ascii_dump(s);
01487 }
01488
01489 PPL_OUTPUT_TEMPLATE_DEFINITIONS(PSET, Pointset_Powerset<PSET>)
01490
01491 template <typename PSET>
01492 bool
01493 Pointset_Powerset<PSET>::ascii_load(std::istream& s) {
01494 Pointset_Powerset& x = *this;
01495 std::string str;
01496
01497 if (!(s >> str) || str != "size")
01498 return false;
01499
01500 size_type sz;
01501
01502 if (!(s >> sz))
01503 return false;
01504
01505 if (!(s >> str) || str != "space_dim")
01506 return false;
01507
01508 if (!(s >> x.space_dim))
01509 return false;
01510
01511 Pointset_Powerset new_x(x.space_dim, EMPTY);
01512 while (sz-- > 0) {
01513 PSET ph;
01514 if (!ph.ascii_load(s))
01515 return false;
01516 new_x.add_disjunct(ph);
01517 }
01518 x.swap(new_x);
01519
01520
01521 PPL_ASSERT_HEAVY(x.OK());
01522 return true;
01523 }
01524
01525 template <typename PSET>
01526 bool
01527 Pointset_Powerset<PSET>::OK() const {
01528 const Pointset_Powerset& x = *this;
01529 for (const_iterator xi = x.begin(), x_end = x.end(); xi != x_end; ++xi) {
01530 const PSET& pi = xi->pointset();
01531 if (pi.space_dimension() != x.space_dim) {
01532 #ifndef NDEBUG
01533 std::cerr << "Space dimension mismatch: is " << pi.space_dimension()
01534 << " in an element of the sequence,\nshould be "
01535 << x.space_dim << "."
01536 << std::endl;
01537 #endif
01538 return false;
01539 }
01540 }
01541 return x.Base::OK();
01542 }
01543
01544 namespace Implementation {
01545
01546 namespace Pointset_Powersets {
01547
01548 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
01549
01550
01555 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
01556 template <typename PSET>
01557 void
01558 linear_partition_aux(const Constraint& c,
01559 PSET& qq,
01560 Pointset_Powerset<NNC_Polyhedron>& r) {
01561 Linear_Expression le(c);
01562 const Constraint& neg_c = c.is_strict_inequality() ? (le <= 0) : (le < 0);
01563 NNC_Polyhedron qqq(qq);
01564 qqq.add_constraint(neg_c);
01565 if (!qqq.is_empty())
01566 r.add_disjunct(qqq);
01567 qq.add_constraint(c);
01568 }
01569
01570 }
01571
01572 }
01573
01574
01576 template <typename PSET>
01577 std::pair<PSET, Pointset_Powerset<NNC_Polyhedron> >
01578 linear_partition(const PSET& p, const PSET& q) {
01579 using Implementation::Pointset_Powersets::linear_partition_aux;
01580
01581 Pointset_Powerset<NNC_Polyhedron> r(p.space_dimension(), EMPTY);
01582 PSET qq = q;
01583 const Constraint_System& pcs = p.constraints();
01584 for (Constraint_System::const_iterator i = pcs.begin(),
01585 pcs_end = pcs.end(); i != pcs_end; ++i) {
01586 const Constraint& c = *i;
01587 if (c.is_equality()) {
01588 Linear_Expression le(c);
01589 linear_partition_aux(le <= 0, qq, r);
01590 linear_partition_aux(le >= 0, qq, r);
01591 }
01592 else
01593 linear_partition_aux(c, qq, r);
01594 }
01595 return std::make_pair(qq, r);
01596 }
01597
01598 }
01599
01600 #endif // !defined(PPL_Pointset_Powerset_templates_hh)