00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <ppl-config.h>
00026
00027 #include "Polyhedron.defs.hh"
00028 #include "Scalar_Products.defs.hh"
00029 #include "assert.hh"
00030 #include <string>
00031 #include <iostream>
00032 #include <sstream>
00033 #include <stdexcept>
00034
00035 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
00036
00045 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
00046 #define BE_LAZY 1
00047
00048 namespace PPL = Parma_Polyhedra_Library;
00049
00050 PPL::Polyhedron::Polyhedron(const Topology topol,
00051 const dimension_type num_dimensions,
00052 const Degenerate_Element kind)
00053 : con_sys(topol),
00054 gen_sys(topol),
00055 sat_c(),
00056 sat_g() {
00057
00058 PPL_ASSERT(num_dimensions <= max_space_dimension());
00059
00060 if (kind == EMPTY)
00061 status.set_empty();
00062 else if (num_dimensions > 0) {
00063 con_sys.add_low_level_constraints();
00064 con_sys.adjust_topology_and_space_dimension(topol, num_dimensions);
00065 set_constraints_minimized();
00066 }
00067 space_dim = num_dimensions;
00068 PPL_ASSERT_HEAVY(OK());
00069 }
00070
00071 PPL::Polyhedron::Polyhedron(const Polyhedron& y, Complexity_Class)
00072 : con_sys(y.topology()),
00073 gen_sys(y.topology()),
00074 status(y.status),
00075 space_dim(y.space_dim) {
00076
00077 PPL_ASSERT(topology() == y.topology());
00078 if (y.constraints_are_up_to_date())
00079 con_sys.assign_with_pending(y.con_sys);
00080 if (y.generators_are_up_to_date())
00081 gen_sys.assign_with_pending(y.gen_sys);
00082 if (y.sat_c_is_up_to_date())
00083 sat_c = y.sat_c;
00084 if (y.sat_g_is_up_to_date())
00085 sat_g = y.sat_g;
00086 }
00087
00088 PPL::Polyhedron::Polyhedron(const Topology topol, const Constraint_System& ccs)
00089 : con_sys(topol),
00090 gen_sys(topol),
00091 sat_c(),
00092 sat_g() {
00093
00094 PPL_ASSERT(ccs.space_dimension() <= max_space_dimension());
00095
00096
00097 Constraint_System cs = ccs;
00098
00099
00100 const dimension_type cs_space_dim = cs.space_dimension();
00101 if (!cs.adjust_topology_and_space_dimension(topol, cs_space_dim))
00102 throw_topology_incompatible((topol == NECESSARILY_CLOSED)
00103 ? "C_Polyhedron(cs)"
00104 : "NNC_Polyhedron(cs)", "cs", cs);
00105
00106
00107 space_dim = cs_space_dim;
00108
00109 if (space_dim > 0) {
00110
00111 std::swap(con_sys, cs);
00112 if (con_sys.num_pending_rows() > 0) {
00113
00114
00115
00116
00117 con_sys.unset_pending_rows();
00118 con_sys.set_sorted(false);
00119 }
00120 con_sys.add_low_level_constraints();
00121 set_constraints_up_to_date();
00122 }
00123 else {
00124
00125 if (cs.num_columns() > 0)
00126
00127 for (dimension_type i = cs.num_rows(); i-- > 0; )
00128 if (cs[i].is_inconsistent()) {
00129
00130 set_empty();
00131 break;
00132 }
00133 }
00134 PPL_ASSERT_HEAVY(OK());
00135 }
00136
00137 PPL::Polyhedron::Polyhedron(const Topology topol,
00138 Constraint_System& cs,
00139 Recycle_Input)
00140 : con_sys(topol),
00141 gen_sys(topol),
00142 sat_c(),
00143 sat_g() {
00144
00145 PPL_ASSERT(cs.space_dimension() <= max_space_dimension());
00146
00147
00148 const dimension_type cs_space_dim = cs.space_dimension();
00149 if (!cs.adjust_topology_and_space_dimension(topol, cs_space_dim))
00150 throw_topology_incompatible((topol == NECESSARILY_CLOSED)
00151 ? "C_Polyhedron(cs, recycle)"
00152 : "NNC_Polyhedron(cs, recycle)", "cs", cs);
00153
00154
00155 space_dim = cs_space_dim;
00156
00157 if (space_dim > 0) {
00158
00159 std::swap(con_sys, cs);
00160 if (con_sys.num_pending_rows() > 0) {
00161
00162
00163
00164
00165 con_sys.unset_pending_rows();
00166 con_sys.set_sorted(false);
00167 }
00168 con_sys.add_low_level_constraints();
00169 set_constraints_up_to_date();
00170 }
00171 else {
00172
00173 if (cs.num_columns() > 0)
00174
00175 for (dimension_type i = cs.num_rows(); i-- > 0; )
00176 if (cs[i].is_inconsistent()) {
00177
00178 set_empty();
00179 break;
00180 }
00181 }
00182 PPL_ASSERT_HEAVY(OK());
00183 }
00184
00185 PPL::Polyhedron::Polyhedron(const Topology topol, const Generator_System& cgs)
00186 : con_sys(topol),
00187 gen_sys(topol),
00188 sat_c(),
00189 sat_g() {
00190
00191 PPL_ASSERT(cgs.space_dimension() <= max_space_dimension());
00192
00193
00194 Generator_System gs = cgs;
00195
00196
00197 if (gs.has_no_rows()) {
00198 space_dim = gs.space_dimension();
00199 status.set_empty();
00200 PPL_ASSERT_HEAVY(OK());
00201 return;
00202 }
00203
00204
00205 if (!gs.has_points())
00206 throw_invalid_generators((topol == NECESSARILY_CLOSED)
00207 ? "C_Polyhedron(gs)"
00208 : "NNC_Polyhedron(gs)", "gs");
00209
00210 const dimension_type gs_space_dim = gs.space_dimension();
00211
00212 if (!gs.adjust_topology_and_space_dimension(topol, gs_space_dim))
00213 throw_topology_incompatible((topol == NECESSARILY_CLOSED)
00214 ? "C_Polyhedron(gs)"
00215 : "NNC_Polyhedron(gs)", "gs", gs);
00216
00217 if (gs_space_dim > 0) {
00218
00219 std::swap(gen_sys, gs);
00220
00221
00222 if (topol == NOT_NECESSARILY_CLOSED)
00223 gen_sys.add_corresponding_closure_points();
00224 if (gen_sys.num_pending_rows() > 0) {
00225
00226
00227
00228
00229 gen_sys.unset_pending_rows();
00230 gen_sys.set_sorted(false);
00231 }
00232
00233 set_generators_up_to_date();
00234
00235
00236 space_dim = gs_space_dim;
00237 PPL_ASSERT_HEAVY(OK());
00238 return;
00239 }
00240
00241
00242
00243
00244 space_dim = 0;
00245 PPL_ASSERT_HEAVY(OK());
00246 }
00247
00248 PPL::Polyhedron::Polyhedron(const Topology topol,
00249 Generator_System& gs,
00250 Recycle_Input)
00251 : con_sys(topol),
00252 gen_sys(topol),
00253 sat_c(),
00254 sat_g() {
00255
00256 PPL_ASSERT(gs.space_dimension() <= max_space_dimension());
00257
00258
00259 if (gs.has_no_rows()) {
00260 space_dim = gs.space_dimension();
00261 status.set_empty();
00262 PPL_ASSERT_HEAVY(OK());
00263 return;
00264 }
00265
00266
00267 if (!gs.has_points())
00268 throw_invalid_generators((topol == NECESSARILY_CLOSED)
00269 ? "C_Polyhedron(gs, recycle)"
00270 : "NNC_Polyhedron(gs, recycle)", "gs");
00271
00272 const dimension_type gs_space_dim = gs.space_dimension();
00273
00274 if (!gs.adjust_topology_and_space_dimension(topol, gs_space_dim))
00275 throw_topology_incompatible((topol == NECESSARILY_CLOSED)
00276 ? "C_Polyhedron(gs, recycle)"
00277 : "NNC_Polyhedron(gs, recycle)", "gs", gs);
00278
00279 if (gs_space_dim > 0) {
00280
00281 std::swap(gen_sys, gs);
00282
00283
00284 if (topol == NOT_NECESSARILY_CLOSED)
00285 gen_sys.add_corresponding_closure_points();
00286 if (gen_sys.num_pending_rows() > 0) {
00287
00288
00289
00290
00291 gen_sys.unset_pending_rows();
00292 gen_sys.set_sorted(false);
00293 }
00294
00295 set_generators_up_to_date();
00296
00297
00298 space_dim = gs_space_dim;
00299 PPL_ASSERT_HEAVY(OK());
00300 return;
00301 }
00302
00303
00304
00305
00306 space_dim = 0;
00307 PPL_ASSERT_HEAVY(OK());
00308 }
00309
00310 PPL::Polyhedron&
00311 PPL::Polyhedron::operator=(const Polyhedron& y) {
00312
00313 PPL_ASSERT(topology() == y.topology());
00314 space_dim = y.space_dim;
00315 if (y.marked_empty())
00316 set_empty();
00317 else if (space_dim == 0)
00318 set_zero_dim_univ();
00319 else {
00320 status = y.status;
00321 if (y.constraints_are_up_to_date())
00322 con_sys.assign_with_pending(y.con_sys);
00323 if (y.generators_are_up_to_date())
00324 gen_sys.assign_with_pending(y.gen_sys);
00325 if (y.sat_c_is_up_to_date())
00326 sat_c = y.sat_c;
00327 if (y.sat_g_is_up_to_date())
00328 sat_g = y.sat_g;
00329 }
00330 return *this;
00331 }
00332
00333 PPL::Polyhedron::Three_Valued_Boolean
00334 PPL::Polyhedron::quick_equivalence_test(const Polyhedron& y) const {
00335
00336 PPL_ASSERT(topology() == y.topology());
00337 PPL_ASSERT(space_dim == y.space_dim);
00338 PPL_ASSERT(!marked_empty() && !y.marked_empty() && space_dim > 0);
00339
00340 const Polyhedron& x = *this;
00341
00342 if (x.is_necessarily_closed()) {
00343 if (!x.has_something_pending() && !y.has_something_pending()) {
00344 bool css_normalized = false;
00345 if (x.constraints_are_minimized() && y.constraints_are_minimized()) {
00346
00347
00348 if (x.con_sys.num_rows() != y.con_sys.num_rows())
00349 return Polyhedron::TVB_FALSE;
00350
00351 dimension_type x_num_equalities = x.con_sys.num_equalities();
00352 if (x_num_equalities != y.con_sys.num_equalities())
00353 return Polyhedron::TVB_FALSE;
00354
00355
00356 css_normalized = (x_num_equalities == 0);
00357 }
00358
00359 if (x.generators_are_minimized() && y.generators_are_minimized()) {
00360
00361
00362 if (x.gen_sys.num_rows() != y.gen_sys.num_rows())
00363 return Polyhedron::TVB_FALSE;
00364
00365 const dimension_type x_num_lines = x.gen_sys.num_lines();
00366 if (x_num_lines != y.gen_sys.num_lines())
00367 return Polyhedron::TVB_FALSE;
00368
00369 if (x_num_lines == 0) {
00370
00371 x.obtain_sorted_generators();
00372 y.obtain_sorted_generators();
00373 if (x.gen_sys == y.gen_sys)
00374 return Polyhedron::TVB_TRUE;
00375 else
00376 return Polyhedron::TVB_FALSE;
00377 }
00378 }
00379
00380 if (css_normalized) {
00381
00382 x.obtain_sorted_constraints();
00383 y.obtain_sorted_constraints();
00384 if (x.con_sys == y.con_sys)
00385 return Polyhedron::TVB_TRUE;
00386 else
00387 return Polyhedron::TVB_FALSE;
00388 }
00389 }
00390 }
00391 return Polyhedron::TVB_DONT_KNOW;
00392 }
00393
00394 bool
00395 PPL::Polyhedron::is_included_in(const Polyhedron& y) const {
00396
00397 PPL_ASSERT(topology() == y.topology());
00398 PPL_ASSERT(space_dim == y.space_dim);
00399 PPL_ASSERT(!marked_empty() && !y.marked_empty() && space_dim > 0);
00400
00401 const Polyhedron& x = *this;
00402
00403
00404 if (x.has_pending_constraints() && !x.process_pending_constraints())
00405 return true;
00406
00407 if (y.has_pending_generators())
00408 y.process_pending_generators();
00409
00410 #if BE_LAZY
00411 if (!x.generators_are_up_to_date() && !x.update_generators())
00412 return true;
00413 if (!y.constraints_are_up_to_date())
00414 y.update_constraints();
00415 #else
00416 if (!x.generators_are_minimized())
00417 x.minimize();
00418 if (!y.constraints_are_minimized())
00419 y.minimize();
00420 #endif
00421
00422 PPL_ASSERT_HEAVY(x.OK());
00423 PPL_ASSERT_HEAVY(y.OK());
00424
00425 const Generator_System& gs = x.gen_sys;
00426 const Constraint_System& cs = y.con_sys;
00427
00428 if (x.is_necessarily_closed())
00429
00430
00431
00432
00433
00434
00435 for (dimension_type i = cs.num_rows(); i-- > 0; ) {
00436 const Constraint& c = cs[i];
00437 if (c.is_inequality()) {
00438 for (dimension_type j = gs.num_rows(); j-- > 0; ) {
00439 const Generator& g = gs[j];
00440 const int sp_sign = Scalar_Products::sign(c, g);
00441 if (g.is_line()) {
00442 if (sp_sign != 0)
00443 return false;
00444 }
00445 else
00446
00447 if (sp_sign < 0)
00448 return false;
00449 }
00450 }
00451 else {
00452
00453 for (dimension_type j = gs.num_rows(); j-- > 0; )
00454 if (Scalar_Products::sign(c, gs[j]) != 0)
00455 return false;
00456 }
00457 }
00458 else {
00459
00460
00461 for (dimension_type i = cs.num_rows(); i-- > 0; ) {
00462 const Constraint& c = cs[i];
00463 switch (c.type()) {
00464 case Constraint::NONSTRICT_INEQUALITY:
00465 for (dimension_type j = gs.num_rows(); j-- > 0; ) {
00466 const Generator& g = gs[j];
00467 const int sp_sign = Scalar_Products::reduced_sign(c, g);
00468 if (g.is_line()) {
00469 if (sp_sign != 0)
00470 return false;
00471 }
00472 else
00473
00474 if (sp_sign < 0)
00475 return false;
00476 }
00477 break;
00478 case Constraint::EQUALITY:
00479 for (dimension_type j = gs.num_rows(); j-- > 0; )
00480 if (Scalar_Products::reduced_sign(c, gs[j]) != 0)
00481 return false;
00482 break;
00483 case Constraint::STRICT_INEQUALITY:
00484 for (dimension_type j = gs.num_rows(); j-- > 0; ) {
00485 const Generator& g = gs[j];
00486 const int sp_sign = Scalar_Products::reduced_sign(c, g);
00487 switch (g.type()) {
00488 case Generator::POINT:
00489
00490
00491
00492 if (sp_sign <= 0)
00493 return false;
00494 break;
00495 case Generator::LINE:
00496
00497 if (sp_sign != 0)
00498 return false;
00499 break;
00500 case Generator::RAY:
00501
00502 case Generator::CLOSURE_POINT:
00503
00504 if (sp_sign < 0)
00505 return false;
00506 break;
00507 }
00508 }
00509 break;
00510 }
00511 }
00512 }
00513
00514
00515 return true;
00516 }
00517
00518 bool
00519 PPL::Polyhedron::bounds(const Linear_Expression& expr,
00520 const bool from_above) const {
00521
00522
00523 const dimension_type expr_space_dim = expr.space_dimension();
00524 if (space_dim < expr_space_dim)
00525 throw_dimension_incompatible((from_above
00526 ? "bounds_from_above(e)"
00527 : "bounds_from_below(e)"), "e", expr);
00528
00529
00530 if (space_dim == 0
00531 || marked_empty()
00532 || (has_pending_constraints() && !process_pending_constraints())
00533 || (!generators_are_up_to_date() && !update_generators()))
00534 return true;
00535
00536
00537 for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) {
00538 const Generator& g = gen_sys[i];
00539
00540 if (g.is_line_or_ray()) {
00541 const int sp_sign = Scalar_Products::homogeneous_sign(expr, g);
00542 if (sp_sign != 0
00543 && (g.is_line()
00544 || (from_above && sp_sign > 0)
00545 || (!from_above && sp_sign < 0)))
00546
00547 return false;
00548 }
00549 }
00550
00551
00552 return true;
00553 }
00554
00555 bool
00556 PPL::Polyhedron::max_min(const Linear_Expression& expr,
00557 const bool maximize,
00558 Coefficient& ext_n, Coefficient& ext_d,
00559 bool& included,
00560 Generator& g) const {
00561
00562
00563 const dimension_type expr_space_dim = expr.space_dimension();
00564 if (space_dim < expr_space_dim)
00565 throw_dimension_incompatible((maximize
00566 ? "maximize(e, ...)"
00567 : "minimize(e, ...)"), "e", expr);
00568
00569
00570 if (space_dim == 0) {
00571 if (marked_empty())
00572 return false;
00573 else {
00574 ext_n = expr.inhomogeneous_term();
00575 ext_d = 1;
00576 included = true;
00577 g = point();
00578 return true;
00579 }
00580 }
00581
00582
00583 if (marked_empty()
00584 || (has_pending_constraints() && !process_pending_constraints())
00585 || (!generators_are_up_to_date() && !update_generators()))
00586 return false;
00587
00588
00589
00590
00591 PPL_DIRTY_TEMP0(mpq_class, extremum);
00592
00593
00594 bool first_candidate = true;
00595
00596
00597 PPL_UNINITIALIZED(dimension_type, ext_position);
00598
00599
00600 PPL_UNINITIALIZED(bool, ext_included);
00601
00602 PPL_DIRTY_TEMP_COEFFICIENT(sp);
00603 for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) {
00604 const Generator& gen_sys_i = gen_sys[i];
00605 Scalar_Products::homogeneous_assign(sp, expr, gen_sys_i);
00606
00607 if (gen_sys_i.is_line_or_ray()) {
00608 const int sp_sign = sgn(sp);
00609 if (sp_sign != 0
00610 && (gen_sys_i.is_line()
00611 || (maximize && sp_sign > 0)
00612 || (!maximize && sp_sign < 0)))
00613
00614 return false;
00615 }
00616 else {
00617
00618 PPL_ASSERT(gen_sys_i.is_point() || gen_sys_i.is_closure_point());
00619
00620
00621 PPL_DIRTY_TEMP0(mpq_class, candidate);
00622 assign_r(candidate.get_num(), sp, ROUND_NOT_NEEDED);
00623 assign_r(candidate.get_den(), gen_sys_i[0], ROUND_NOT_NEEDED);
00624 candidate.canonicalize();
00625 const bool g_is_point = gen_sys_i.is_point();
00626 if (first_candidate
00627 || (maximize
00628 && (candidate > extremum
00629 || (g_is_point
00630 && !ext_included
00631 && candidate == extremum)))
00632 || (!maximize
00633 && (candidate < extremum
00634 || (g_is_point
00635 && !ext_included
00636 && candidate == extremum)))) {
00637
00638 first_candidate = false;
00639 extremum = candidate;
00640 ext_position = i;
00641 ext_included = g_is_point;
00642 }
00643 }
00644 }
00645
00646
00647 PPL_DIRTY_TEMP0(mpz_class, n);
00648 assign_r(n, expr.inhomogeneous_term(), ROUND_NOT_NEEDED);
00649 extremum += n;
00650
00651
00652
00653 PPL_ASSERT(!first_candidate);
00654
00655
00656
00657
00658
00659
00660
00661 ext_n = Coefficient(extremum.get_num());
00662 ext_d = Coefficient(extremum.get_den());
00663 included = ext_included;
00664 g = gen_sys[ext_position];
00665
00666 return true;
00667 }
00668
00669 void
00670 PPL::Polyhedron::set_zero_dim_univ() {
00671 status.set_zero_dim_univ();
00672 space_dim = 0;
00673 con_sys.clear();
00674 gen_sys.clear();
00675 }
00676
00677 void
00678 PPL::Polyhedron::set_empty() {
00679 status.set_empty();
00680
00681 con_sys.clear();
00682 gen_sys.clear();
00683 sat_c.clear();
00684 sat_g.clear();
00685 }
00686
00687 bool
00688 PPL::Polyhedron::process_pending_constraints() const {
00689 PPL_ASSERT(space_dim > 0 && !marked_empty());
00690 PPL_ASSERT(has_pending_constraints() && !has_pending_generators());
00691
00692 Polyhedron& x = const_cast<Polyhedron&>(*this);
00693
00694
00695
00696 if (!x.sat_c_is_up_to_date())
00697 x.sat_c.transpose_assign(x.sat_g);
00698 if (!x.con_sys.is_sorted())
00699 x.obtain_sorted_constraints_with_sat_c();
00700
00701
00702 x.con_sys.sort_pending_and_remove_duplicates();
00703 if (x.con_sys.num_pending_rows() == 0) {
00704
00705 x.clear_pending_constraints();
00706 PPL_ASSERT_HEAVY(OK(true));
00707 return true;
00708 }
00709
00710 const bool empty = add_and_minimize(true, x.con_sys, x.gen_sys, x.sat_c);
00711 PPL_ASSERT(x.con_sys.num_pending_rows() == 0);
00712
00713 if (empty)
00714 x.set_empty();
00715 else {
00716 x.clear_pending_constraints();
00717 x.clear_sat_g_up_to_date();
00718 x.set_sat_c_up_to_date();
00719 }
00720 PPL_ASSERT_HEAVY(OK(!empty));
00721 return !empty;
00722 }
00723
00724 void
00725 PPL::Polyhedron::process_pending_generators() const {
00726 PPL_ASSERT(space_dim > 0 && !marked_empty());
00727 PPL_ASSERT(has_pending_generators() && !has_pending_constraints());
00728
00729 Polyhedron& x = const_cast<Polyhedron&>(*this);
00730
00731
00732
00733 if (!x.sat_g_is_up_to_date())
00734 x.sat_g.transpose_assign(x.sat_c);
00735 if (!x.gen_sys.is_sorted())
00736 x.obtain_sorted_generators_with_sat_g();
00737
00738
00739 x.gen_sys.sort_pending_and_remove_duplicates();
00740 if (x.gen_sys.num_pending_rows() == 0) {
00741
00742 x.clear_pending_generators();
00743 PPL_ASSERT_HEAVY(OK(true));
00744 return;
00745 }
00746
00747 add_and_minimize(false, x.gen_sys, x.con_sys, x.sat_g);
00748 PPL_ASSERT(x.gen_sys.num_pending_rows() == 0);
00749
00750 x.clear_pending_generators();
00751 x.clear_sat_c_up_to_date();
00752 x.set_sat_g_up_to_date();
00753 }
00754
00755 void
00756 PPL::Polyhedron::remove_pending_to_obtain_constraints() const {
00757 PPL_ASSERT(has_something_pending());
00758
00759 Polyhedron& x = const_cast<Polyhedron&>(*this);
00760
00761
00762 if (x.has_pending_constraints()) {
00763
00764 x.con_sys.unset_pending_rows();
00765 x.con_sys.set_sorted(false);
00766 x.clear_pending_constraints();
00767 x.clear_constraints_minimized();
00768 x.clear_generators_up_to_date();
00769 }
00770 else {
00771 PPL_ASSERT(x.has_pending_generators());
00772
00773
00774 x.process_pending_generators();
00775 }
00776 PPL_ASSERT_HEAVY(OK(true));
00777 }
00778
00779 bool
00780 PPL::Polyhedron::remove_pending_to_obtain_generators() const {
00781 PPL_ASSERT(has_something_pending());
00782
00783 Polyhedron& x = const_cast<Polyhedron&>(*this);
00784
00785
00786 if (x.has_pending_generators()) {
00787
00788 x.gen_sys.unset_pending_rows();
00789 x.gen_sys.set_sorted(false);
00790 x.clear_pending_generators();
00791 x.clear_generators_minimized();
00792 x.clear_constraints_up_to_date();
00793 PPL_ASSERT_HEAVY(OK(true));
00794 return true;
00795 }
00796 else {
00797 PPL_ASSERT(x.has_pending_constraints());
00798
00799
00800 return x.process_pending_constraints();
00801 }
00802 }
00803
00804 void
00805 PPL::Polyhedron::update_constraints() const {
00806 PPL_ASSERT(space_dim > 0);
00807 PPL_ASSERT(!marked_empty());
00808 PPL_ASSERT(generators_are_up_to_date());
00809
00810 PPL_ASSERT(!has_something_pending());
00811
00812 Polyhedron& x = const_cast<Polyhedron&>(*this);
00813 minimize(false, x.gen_sys, x.con_sys, x.sat_c);
00814
00815 x.set_sat_c_up_to_date();
00816 x.clear_sat_g_up_to_date();
00817
00818
00819 x.set_constraints_minimized();
00820 x.set_generators_minimized();
00821 }
00822
00823 bool
00824 PPL::Polyhedron::update_generators() const {
00825 PPL_ASSERT(space_dim > 0);
00826 PPL_ASSERT(!marked_empty());
00827 PPL_ASSERT(constraints_are_up_to_date());
00828
00829 PPL_ASSERT(!has_something_pending());
00830
00831 Polyhedron& x = const_cast<Polyhedron&>(*this);
00832
00833
00834 const bool empty = minimize(true, x.con_sys, x.gen_sys, x.sat_g);
00835 if (empty)
00836 x.set_empty();
00837 else {
00838
00839 x.set_sat_g_up_to_date();
00840 x.clear_sat_c_up_to_date();
00841
00842
00843 x.set_constraints_minimized();
00844 x.set_generators_minimized();
00845 }
00846 return !empty;
00847 }
00848
00849 void
00850 PPL::Polyhedron::update_sat_c() const {
00851 PPL_ASSERT(constraints_are_minimized());
00852 PPL_ASSERT(generators_are_minimized());
00853 PPL_ASSERT(!sat_c_is_up_to_date());
00854
00855
00856 const dimension_type csr = con_sys.first_pending_row();
00857 const dimension_type gsr = gen_sys.first_pending_row();
00858 Polyhedron& x = const_cast<Polyhedron&>(*this);
00859
00860
00861
00862 x.sat_c.resize(gsr, csr);
00863 for (dimension_type i = gsr; i-- > 0; )
00864 for (dimension_type j = csr; j-- > 0; ) {
00865 const int sp_sign = Scalar_Products::sign(con_sys[j], gen_sys[i]);
00866
00867
00868
00869
00870 PPL_ASSERT(sp_sign >= 0);
00871 if (sp_sign > 0)
00872
00873 x.sat_c[i].set(j);
00874 else
00875
00876 x.sat_c[i].clear(j);
00877 }
00878 x.set_sat_c_up_to_date();
00879 }
00880
00881 void
00882 PPL::Polyhedron::update_sat_g() const {
00883 PPL_ASSERT(constraints_are_minimized());
00884 PPL_ASSERT(generators_are_minimized());
00885 PPL_ASSERT(!sat_g_is_up_to_date());
00886
00887
00888 const dimension_type csr = con_sys.first_pending_row();
00889 const dimension_type gsr = gen_sys.first_pending_row();
00890 Polyhedron& x = const_cast<Polyhedron&>(*this);
00891
00892
00893
00894 x.sat_g.resize(csr, gsr);
00895 for (dimension_type i = csr; i-- > 0; )
00896 for (dimension_type j = gsr; j-- > 0; ) {
00897 const int sp_sign = Scalar_Products::sign(con_sys[i], gen_sys[j]);
00898
00899
00900
00901
00902 PPL_ASSERT(sp_sign >= 0);
00903 if (sp_sign > 0)
00904
00905 x.sat_g[i].set(j);
00906 else
00907
00908 x.sat_g[i].clear(j);
00909 }
00910 x.set_sat_g_up_to_date();
00911 }
00912
00913 void
00914 PPL::Polyhedron::obtain_sorted_constraints() const {
00915 PPL_ASSERT(constraints_are_up_to_date());
00916
00917 Polyhedron& x = const_cast<Polyhedron&>(*this);
00918 if (!x.con_sys.is_sorted()) {
00919 if (x.sat_g_is_up_to_date()) {
00920
00921 x.con_sys.sort_and_remove_with_sat(x.sat_g);
00922
00923 x.clear_sat_c_up_to_date();
00924 }
00925 else if (x.sat_c_is_up_to_date()) {
00926
00927 x.sat_g.transpose_assign(x.sat_c);
00928 x.con_sys.sort_and_remove_with_sat(x.sat_g);
00929 x.set_sat_g_up_to_date();
00930 x.clear_sat_c_up_to_date();
00931 }
00932 else
00933
00934
00935 x.con_sys.sort_rows();
00936 }
00937
00938 PPL_ASSERT(con_sys.check_sorted());
00939 }
00940
00941 void
00942 PPL::Polyhedron::obtain_sorted_generators() const {
00943 PPL_ASSERT(generators_are_up_to_date());
00944
00945 Polyhedron& x = const_cast<Polyhedron&>(*this);
00946 if (!x.gen_sys.is_sorted()) {
00947 if (x.sat_c_is_up_to_date()) {
00948
00949 x.gen_sys.sort_and_remove_with_sat(x.sat_c);
00950
00951 x.clear_sat_g_up_to_date();
00952 }
00953 else if (x.sat_g_is_up_to_date()) {
00954
00955 x.sat_c.transpose_assign(x.sat_g);
00956 x.gen_sys.sort_and_remove_with_sat(x.sat_c);
00957 x.set_sat_c_up_to_date();
00958 x.clear_sat_g_up_to_date();
00959 }
00960 else
00961
00962
00963 x.gen_sys.sort_rows();
00964 }
00965
00966 PPL_ASSERT(gen_sys.check_sorted());
00967 }
00968
00969 void
00970 PPL::Polyhedron::obtain_sorted_constraints_with_sat_c() const {
00971 PPL_ASSERT(constraints_are_up_to_date());
00972 PPL_ASSERT(constraints_are_minimized());
00973
00974 Polyhedron& x = const_cast<Polyhedron&>(*this);
00975
00976 if (!x.sat_c_is_up_to_date() && !x.sat_g_is_up_to_date())
00977 x.update_sat_c();
00978
00979 if (x.con_sys.is_sorted()) {
00980 if (x.sat_c_is_up_to_date())
00981
00982
00983 return;
00984 }
00985 else {
00986 if (!x.sat_g_is_up_to_date()) {
00987
00988
00989 x.sat_g.transpose_assign(x.sat_c);
00990 x.set_sat_g_up_to_date();
00991 }
00992
00993 x.con_sys.sort_and_remove_with_sat(x.sat_g);
00994 }
00995
00996 x.sat_c.transpose_assign(x.sat_g);
00997 x.set_sat_c_up_to_date();
00998
00999 x.con_sys.set_sorted(true);
01000
01001 PPL_ASSERT(con_sys.check_sorted());
01002 }
01003
01004 void
01005 PPL::Polyhedron::obtain_sorted_generators_with_sat_g() const {
01006 PPL_ASSERT(generators_are_up_to_date());
01007
01008 Polyhedron& x = const_cast<Polyhedron&>(*this);
01009
01010 if (!x.sat_c_is_up_to_date() && !x.sat_g_is_up_to_date())
01011 x.update_sat_g();
01012
01013 if (x.gen_sys.is_sorted()) {
01014 if (x.sat_g_is_up_to_date())
01015
01016
01017 return;
01018 }
01019 else {
01020 if (!x.sat_c_is_up_to_date()) {
01021
01022
01023 x.sat_c.transpose_assign(x.sat_g);
01024 x.set_sat_c_up_to_date();
01025 }
01026
01027 x.gen_sys.sort_and_remove_with_sat(x.sat_c);
01028 }
01029
01030 x.sat_g.transpose_assign(sat_c);
01031 x.set_sat_g_up_to_date();
01032
01033 x.gen_sys.set_sorted(true);
01034
01035 PPL_ASSERT(gen_sys.check_sorted());
01036 }
01037
01038 bool
01039 PPL::Polyhedron::minimize() const {
01040
01041 if (marked_empty())
01042 return false;
01043 if (space_dim == 0)
01044 return true;
01045
01046
01047 if (has_something_pending()) {
01048 const bool not_empty = process_pending();
01049 PPL_ASSERT_HEAVY(OK());
01050 return not_empty;
01051 }
01052
01053
01054
01055 if (constraints_are_minimized() && generators_are_minimized())
01056 return true;
01057
01058
01059
01060
01061
01062
01063
01064 if (constraints_are_up_to_date()) {
01065
01066 const bool ret = update_generators();
01067 PPL_ASSERT_HEAVY(OK());
01068 return ret;
01069 }
01070 else {
01071 PPL_ASSERT(generators_are_up_to_date());
01072 update_constraints();
01073 PPL_ASSERT_HEAVY(OK());
01074 return true;
01075 }
01076 }
01077
01078 bool
01079 PPL::Polyhedron::strongly_minimize_constraints() const {
01080 PPL_ASSERT(!is_necessarily_closed());
01081
01082
01083 Polyhedron& x = const_cast<Polyhedron&>(*this);
01084
01085
01086
01087 if (!minimize())
01088 return false;
01089
01090
01091
01092 if (x.space_dim == 0)
01093 return true;
01094
01095
01096 if (!sat_g_is_up_to_date()) {
01097 PPL_ASSERT(sat_c_is_up_to_date());
01098 x.sat_g.transpose_assign(sat_c);
01099 }
01100
01101
01102
01103
01104 Bit_Row sat_all_but_rays;
01105 Bit_Row sat_all_but_points;
01106 Bit_Row sat_all_but_closure_points;
01107
01108 const dimension_type gs_rows = gen_sys.num_rows();
01109 const dimension_type n_lines = gen_sys.num_lines();
01110 for (dimension_type i = gs_rows; i-- > n_lines; )
01111 switch (gen_sys[i].type()) {
01112 case Generator::RAY:
01113 sat_all_but_rays.set(i);
01114 break;
01115 case Generator::POINT:
01116 sat_all_but_points.set(i);
01117 break;
01118 case Generator::CLOSURE_POINT:
01119 sat_all_but_closure_points.set(i);
01120 break;
01121 default:
01122
01123 throw std::runtime_error("PPL internal error: "
01124 "strongly_minimize_constraints.");
01125 }
01126 Bit_Row sat_lines_and_rays(sat_all_but_points, sat_all_but_closure_points);
01127 Bit_Row sat_lines_and_closure_points(sat_all_but_rays, sat_all_but_points);
01128 Bit_Row sat_lines(sat_lines_and_rays, sat_lines_and_closure_points);
01129
01130
01131
01132
01133 bool changed = false;
01134 bool found_eps_leq_one = false;
01135
01136
01137
01138
01139 Constraint_System& cs = x.con_sys;
01140 Bit_Matrix& sat = x.sat_g;
01141 dimension_type cs_rows = cs.num_rows();
01142 const dimension_type eps_index = cs.num_columns() - 1;
01143 for (dimension_type i = 0; i < cs_rows; )
01144 if (cs[i].is_strict_inequality()) {
01145
01146 Bit_Row sat_ci;
01147 set_union(sat[i], sat_lines_and_closure_points, sat_ci);
01148 if (sat_ci == sat_lines) {
01149
01150 if (!found_eps_leq_one) {
01151
01152 const Constraint& c = cs[i];
01153 bool all_zeroes = true;
01154 for (dimension_type k = eps_index; k-- > 1; )
01155 if (c[k] != 0) {
01156 all_zeroes = false;
01157 break;
01158 }
01159 if (all_zeroes && (c[0] + c[eps_index] == 0)) {
01160
01161 found_eps_leq_one = true;
01162
01163 ++i;
01164 continue;
01165 }
01166 }
01167
01168
01169
01170
01171 --cs_rows;
01172 std::swap(cs[i], cs[cs_rows]);
01173 std::swap(sat[i], sat[cs_rows]);
01174
01175 changed = true;
01176
01177
01178 continue;
01179 }
01180
01181
01182
01183 sat_ci.clear();
01184 set_union(sat[i], sat_all_but_points, sat_ci);
01185 bool eps_redundant = false;
01186 for (dimension_type j = 0; j < cs_rows; ++j)
01187 if (i != j && cs[j].is_strict_inequality()
01188 && subset_or_equal(sat[j], sat_ci)) {
01189
01190
01191
01192 --cs_rows;
01193 std::swap(cs[i], cs[cs_rows]);
01194 std::swap(sat[i], sat[cs_rows]);
01195 eps_redundant = true;
01196
01197 changed = true;
01198 break;
01199 }
01200
01201
01202 if (!eps_redundant)
01203 ++i;
01204 }
01205 else
01206
01207 ++i;
01208
01209 if (changed) {
01210
01211
01212 PPL_ASSERT(cs_rows < cs.num_rows());
01213 cs.erase_to_end(cs_rows);
01214
01215 cs.unset_pending_rows();
01216
01217 cs.set_sorted(false);
01218
01219 x.clear_generators_up_to_date();
01220
01221
01222
01223
01224 if (!found_eps_leq_one) {
01225 MIP_Problem lp;
01226
01227
01228
01229
01230 cs.set_necessarily_closed();
01231 try {
01232 lp.add_space_dimensions_and_embed(cs.space_dimension());
01233 lp.add_constraints(cs);
01234 cs.set_not_necessarily_closed();
01235 }
01236 catch (...) {
01237 cs.set_not_necessarily_closed();
01238 throw;
01239 }
01240
01241 lp.set_objective_function(Variable(x.space_dim));
01242 lp.set_optimization_mode(MAXIMIZATION);
01243 MIP_Problem_Status status = lp.solve();
01244 PPL_ASSERT(status != UNFEASIBLE_MIP_PROBLEM);
01245
01246
01247 if (status == UNBOUNDED_MIP_PROBLEM)
01248 cs.insert(Constraint::epsilon_leq_one());
01249 }
01250 }
01251
01252 PPL_ASSERT_HEAVY(OK());
01253 return true;
01254 }
01255
01256 bool
01257 PPL::Polyhedron::strongly_minimize_generators() const {
01258 PPL_ASSERT(!is_necessarily_closed());
01259
01260
01261 Polyhedron& x = const_cast<Polyhedron&>(*this);
01262
01263
01264
01265 if (!minimize())
01266 return false;
01267
01268
01269
01270 if (x.space_dim == 0)
01271 return true;
01272
01273
01274 if (!sat_c_is_up_to_date()) {
01275 PPL_ASSERT(sat_g_is_up_to_date());
01276 x.sat_c.transpose_assign(sat_g);
01277 }
01278
01279
01280
01281 Bit_Row sat_all_but_strict_ineq;
01282 const dimension_type cs_rows = con_sys.num_rows();
01283 const dimension_type n_equals = con_sys.num_equalities();
01284 for (dimension_type i = cs_rows; i-- > n_equals; )
01285 if (con_sys[i].is_strict_inequality())
01286 sat_all_but_strict_ineq.set(i);
01287
01288
01289 bool changed = false;
01290
01291
01292
01293 Generator_System& gs = const_cast<Generator_System&>(gen_sys);
01294 Bit_Matrix& sat = const_cast<Bit_Matrix&>(sat_c);
01295 dimension_type gs_rows = gs.num_rows();
01296 const dimension_type n_lines = gs.num_lines();
01297 const dimension_type eps_index = gs.num_columns() - 1;
01298 for (dimension_type i = n_lines; i < gs_rows; )
01299 if (gs[i].is_point()) {
01300
01301
01302 Bit_Row sat_gi(sat[i], sat_all_but_strict_ineq);
01303
01304
01305
01306 bool eps_redundant = false;
01307 for (dimension_type j = n_lines; j < gs_rows; ++j)
01308 if (i != j && gs[j].is_point() && subset_or_equal(sat[j], sat_gi)) {
01309
01310
01311
01312 --gs_rows;
01313 std::swap(gs[i], gs[gs_rows]);
01314 std::swap(sat[i], sat[gs_rows]);
01315 eps_redundant = true;
01316 changed = true;
01317 break;
01318 }
01319 if (!eps_redundant) {
01320
01321 Generator& gi = gs[i];
01322 if (gi[eps_index] != gi[0]) {
01323 gi[eps_index] = gi[0];
01324
01325 gi.normalize();
01326 changed = true;
01327 }
01328
01329 ++i;
01330 }
01331 }
01332 else
01333
01334 ++i;
01335
01336
01337
01338 if (gs_rows < gs.num_rows()) {
01339 gs.erase_to_end(gs_rows);
01340 gs.unset_pending_rows();
01341 }
01342
01343 if (changed) {
01344
01345 x.gen_sys.set_sorted(false);
01346
01347 x.clear_constraints_up_to_date();
01348 }
01349
01350 PPL_ASSERT_HEAVY(OK());
01351 return true;
01352 }
01353
01354 void
01355 PPL::Polyhedron::refine_no_check(const Constraint& c) {
01356 PPL_ASSERT(!marked_empty());
01357 PPL_ASSERT(space_dim >= c.space_dimension());
01358
01359
01360 if (space_dim == 0) {
01361 if (c.is_inconsistent())
01362 set_empty();
01363 return;
01364 }
01365
01366
01367 if (has_pending_generators())
01368 process_pending_generators();
01369 else if (!constraints_are_up_to_date())
01370 update_constraints();
01371
01372 const bool adding_pending = can_have_something_pending();
01373
01374 if (c.is_necessarily_closed() || !is_necessarily_closed())
01375
01376
01377 if (adding_pending)
01378 con_sys.insert_pending(c);
01379 else
01380 con_sys.insert(c);
01381 else {
01382
01383
01384
01385
01386 Linear_Expression nc_expr = Linear_Expression(c);
01387 if (c.is_equality())
01388 if (adding_pending)
01389 con_sys.insert_pending(nc_expr == 0);
01390 else
01391 con_sys.insert(nc_expr == 0);
01392 else
01393 if (adding_pending)
01394 con_sys.insert_pending(nc_expr >= 0);
01395 else
01396 con_sys.insert(nc_expr >= 0);
01397 }
01398
01399 if (adding_pending)
01400 set_constraints_pending();
01401 else {
01402
01403 clear_constraints_minimized();
01404 clear_generators_up_to_date();
01405 }
01406
01407
01408
01409 PPL_ASSERT_HEAVY(OK());
01410 }
01411
01412 bool
01413 PPL::Polyhedron::BHZ09_poly_hull_assign_if_exact(const Polyhedron& y) {
01414 Polyhedron& x = *this;
01415
01416
01417 PPL_ASSERT(x.topology() == y.topology());
01418 PPL_ASSERT(x.space_dim == y.space_dim);
01419
01420
01421 if (x.space_dim == 0) {
01422 x.upper_bound_assign(y);
01423 return true;
01424 }
01425
01426
01427 if (x.marked_empty()) {
01428 x = y;
01429 return true;
01430 }
01431 else if (y.is_empty())
01432 return true;
01433 else if (x.is_empty()) {
01434 x = y;
01435 return true;
01436 }
01437
01438 if (x.is_necessarily_closed())
01439 return x.BHZ09_C_poly_hull_assign_if_exact(y);
01440 else
01441 return x.BHZ09_NNC_poly_hull_assign_if_exact(y);
01442 }
01443
01444 bool
01445 PPL::Polyhedron::BHZ09_C_poly_hull_assign_if_exact(const Polyhedron& y) {
01446 Polyhedron& x = *this;
01447
01448 PPL_ASSERT(x.is_necessarily_closed() && y.is_necessarily_closed());
01449 PPL_ASSERT(x.space_dim > 0 && x.space_dim == y.space_dim);
01450 PPL_ASSERT(!x.is_empty() && !y.is_empty());
01451
01452
01453
01454
01455 (void) x.minimize();
01456 (void) y.minimize();
01457
01458
01459
01460
01461 const dimension_type x_affine_dim = x.affine_dimension();
01462 const dimension_type y_affine_dim = y.affine_dimension();
01463 if (x_affine_dim > y_affine_dim)
01464 return y.is_included_in(x);
01465 else if (x_affine_dim < y_affine_dim) {
01466 if (x.is_included_in(y)) {
01467 x = y;
01468 return true;
01469 }
01470 else
01471 return false;
01472 }
01473
01474 const Constraint_System& x_cs = x.con_sys;
01475 const Generator_System& x_gs = x.gen_sys;
01476 const Generator_System& y_gs = y.gen_sys;
01477 const dimension_type x_gs_num_rows = x_gs.num_rows();
01478 const dimension_type y_gs_num_rows = y_gs.num_rows();
01479
01480
01481 Bit_Row x_gs_red_in_y;
01482 dimension_type num_x_gs_red_in_y = 0;
01483 for (dimension_type i = x_gs_num_rows; i-- > 0; )
01484 if (y.relation_with(x_gs[i]).implies(Poly_Gen_Relation::subsumes())) {
01485 x_gs_red_in_y.set(i);
01486 ++num_x_gs_red_in_y;
01487 }
01488 Bit_Row y_gs_red_in_x;
01489 dimension_type num_y_gs_red_in_x = 0;
01490 for (dimension_type i = y_gs_num_rows; i-- > 0; )
01491 if (x.relation_with(y_gs[i]).implies(Poly_Gen_Relation::subsumes())) {
01492 y_gs_red_in_x.set(i);
01493 ++num_y_gs_red_in_x;
01494 }
01495
01496
01497
01498
01499 if (num_y_gs_red_in_x == y_gs_num_rows)
01500
01501 return true;
01502 if (num_x_gs_red_in_y == x_gs_num_rows) {
01503
01504 x = y;
01505 return true;
01506 }
01507
01508
01509
01510
01511 if (num_x_gs_red_in_y == 0 || num_y_gs_red_in_x == 0)
01512 return false;
01513
01514
01515
01516
01517
01518
01519
01520
01521 if (!x.sat_g_is_up_to_date())
01522 x.update_sat_g();
01523 const Bit_Matrix& x_sat = x.sat_g;
01524
01525 Bit_Row all_ones;
01526 all_ones.set_until(x_gs_num_rows);
01527 Bit_Row row_union;
01528 for (dimension_type i = x_cs.num_rows(); i-- > 0; ) {
01529 const bool included
01530 = y.relation_with(x_cs[i]).implies(Poly_Con_Relation::is_included());
01531 if (!included) {
01532 set_union(x_gs_red_in_y, x_sat[i], row_union);
01533 if (row_union != all_ones)
01534 return false;
01535 }
01536 }
01537
01538
01539 for (dimension_type j = y_gs_num_rows; j-- > 0; )
01540 if (!y_gs_red_in_x[j])
01541 add_generator(y_gs[j]);
01542
01543 PPL_ASSERT_HEAVY(OK());
01544 return true;
01545 }
01546
01547 bool
01548 PPL::Polyhedron::BHZ09_NNC_poly_hull_assign_if_exact(const Polyhedron& y) {
01549 const Polyhedron& x = *this;
01550
01551 PPL_ASSERT(!x.is_necessarily_closed() && !y.is_necessarily_closed());
01552 PPL_ASSERT(x.space_dim > 0 && x.space_dim == y.space_dim);
01553 PPL_ASSERT(!x.is_empty() && !y.is_empty());
01554
01555
01556
01557
01558 (void) x.minimize();
01559 (void) y.minimize();
01560
01561 const Generator_System& x_gs = x.gen_sys;
01562 const Generator_System& y_gs = y.gen_sys;
01563 const dimension_type x_gs_num_rows = x_gs.num_rows();
01564 const dimension_type y_gs_num_rows = y_gs.num_rows();
01565
01566
01567 Bit_Row x_gs_nonred_in_y;
01568 Bit_Row x_points_nonred_in_y;
01569 Bit_Row x_closure_points;
01570 dimension_type num_x_gs_nonred_in_y = 0;
01571 for (dimension_type i = x_gs_num_rows; i-- > 0; ) {
01572 const Generator& x_gs_i = x_gs[i];
01573 if (x_gs_i.is_closure_point())
01574 x_closure_points.set(i);
01575 if (y.relation_with(x_gs[i]).implies(Poly_Gen_Relation::subsumes()))
01576 continue;
01577 x_gs_nonred_in_y.set(i);
01578 ++num_x_gs_nonred_in_y;
01579 if (x_gs_i.is_point())
01580 x_points_nonred_in_y.set(i);
01581 }
01582
01583
01584 if (num_x_gs_nonred_in_y == 0) {
01585 *this = y;
01586 return true;
01587 }
01588
01589
01590 Bit_Row y_gs_nonred_in_x;
01591 Bit_Row y_points_nonred_in_x;
01592 Bit_Row y_closure_points;
01593 dimension_type num_y_gs_nonred_in_x = 0;
01594 for (dimension_type i = y_gs_num_rows; i-- > 0; ) {
01595 const Generator& y_gs_i = y_gs[i];
01596 if (y_gs_i.is_closure_point())
01597 y_closure_points.set(i);
01598 if (x.relation_with(y_gs_i).implies(Poly_Gen_Relation::subsumes()))
01599 continue;
01600 y_gs_nonred_in_x.set(i);
01601 ++num_y_gs_nonred_in_x;
01602 if (y_gs_i.is_point())
01603 y_points_nonred_in_x.set(i);
01604 }
01605
01606
01607 if (num_y_gs_nonred_in_x == 0)
01608 return true;
01609
01610 Bit_Row x_nonpoints_nonred_in_y;
01611 set_difference(x_gs_nonred_in_y, x_points_nonred_in_y,
01612 x_nonpoints_nonred_in_y);
01613
01614 const Constraint_System& x_cs = x.con_sys;
01615 const Constraint_System& y_cs = y.con_sys;
01616 const dimension_type x_cs_num_rows = x_cs.num_rows();
01617 const dimension_type y_cs_num_rows = y_cs.num_rows();
01618
01619
01620
01621 Bit_Row x_points_nonred_in_y_closure;
01622 for (dimension_type i = x_points_nonred_in_y.first();
01623 i != ULONG_MAX; i = x_points_nonred_in_y.next(i)) {
01624 const Generator& x_p = x_gs[i];
01625 PPL_ASSERT(x_p.is_point());
01626
01627
01628 for (dimension_type j = y_cs_num_rows; j-- > 0; ) {
01629 const Constraint& y_c = y_cs[j];
01630 const int sp_sign = Scalar_Products::reduced_sign(y_c, x_p);
01631 if (sp_sign < 0 || (y_c.is_equality() && sp_sign > 0)) {
01632 x_points_nonred_in_y_closure.set(i);
01633 break;
01634 }
01635 }
01636 }
01637
01638
01639
01640
01641 if (!x.sat_g_is_up_to_date())
01642 x.update_sat_g();
01643 const Bit_Matrix& x_sat = x.sat_g;
01644
01645 Bit_Row x_cs_condition_3;
01646 Bit_Row x_gs_condition_3;
01647 Bit_Row all_ones;
01648 all_ones.set_until(x_gs_num_rows);
01649 Bit_Row saturators;
01650 Bit_Row tmp_set;
01651 for (dimension_type i = x_cs_num_rows; i-- > 0; ) {
01652 const Constraint& x_c = x_cs[i];
01653
01654 if (y.relation_with(x_c).implies(Poly_Con_Relation::is_included()))
01655 continue;
01656 set_difference(all_ones, x_sat[i], saturators);
01657
01658 set_intersection(x_nonpoints_nonred_in_y, saturators, tmp_set);
01659 if (!tmp_set.empty())
01660 return false;
01661 if (x_c.is_strict_inequality()) {
01662
01663 x_cs_condition_3.set(i);
01664 set_intersection(x_closure_points, saturators, tmp_set);
01665 set_union(x_gs_condition_3, tmp_set, x_gs_condition_3);
01666 }
01667 else {
01668
01669 set_intersection(x_points_nonred_in_y_closure, saturators, tmp_set);
01670 if (!tmp_set.empty())
01671 return false;
01672 }
01673 }
01674
01675
01676
01677
01678 Bit_Row y_nonpoints_nonred_in_x;
01679 set_difference(y_gs_nonred_in_x, y_points_nonred_in_x,
01680 y_nonpoints_nonred_in_x);
01681
01682
01683
01684 Bit_Row y_points_nonred_in_x_closure;
01685 for (dimension_type i = y_points_nonred_in_x.first();
01686 i != ULONG_MAX; i = y_points_nonred_in_x.next(i)) {
01687 const Generator& y_p = y_gs[i];
01688 PPL_ASSERT(y_p.is_point());
01689
01690
01691 for (dimension_type j = x_cs_num_rows; j-- > 0; ) {
01692 const Constraint& x_c = x_cs[j];
01693 const int sp_sign = Scalar_Products::reduced_sign(x_c, y_p);
01694 if (sp_sign < 0 || (x_c.is_equality() && sp_sign > 0)) {
01695 y_points_nonred_in_x_closure.set(i);
01696 break;
01697 }
01698 }
01699 }
01700
01701
01702 if (!y.sat_g_is_up_to_date())
01703 y.update_sat_g();
01704 const Bit_Matrix& y_sat = y.sat_g;
01705
01706 Bit_Row y_cs_condition_3;
01707 Bit_Row y_gs_condition_3;
01708 all_ones.clear();
01709 all_ones.set_until(y_gs_num_rows);
01710 for (dimension_type i = y_cs_num_rows; i-- > 0; ) {
01711 const Constraint& y_c = y_cs[i];
01712
01713 if (x.relation_with(y_c).implies(Poly_Con_Relation::is_included()))
01714 continue;
01715 set_difference(all_ones, y_sat[i], saturators);
01716
01717 set_intersection(y_nonpoints_nonred_in_x, saturators, tmp_set);
01718 if (!tmp_set.empty())
01719 return false;
01720 if (y_c.is_strict_inequality()) {
01721
01722 y_cs_condition_3.set(i);
01723 set_intersection(y_closure_points, saturators, tmp_set);
01724 set_union(y_gs_condition_3, tmp_set, y_gs_condition_3);
01725 }
01726 else {
01727
01728 set_intersection(y_points_nonred_in_x_closure, saturators, tmp_set);
01729 if (!tmp_set.empty())
01730 return false;
01731 }
01732 }
01733
01734
01735
01736 if (x_cs_condition_3.empty() && y_cs_condition_3.empty()) {
01737
01738
01739 for (dimension_type j = y_gs_num_rows; j-- > 0; )
01740 if (y_gs_nonred_in_x[j])
01741 add_generator(y_gs[j]);
01742 return true;
01743 }
01744
01745
01746 Polyhedron ub(x);
01747 for (dimension_type j = y_gs_num_rows; j-- > 0; )
01748 if (y_gs_nonred_in_x[j])
01749 ub.add_generator(y_gs[j]);
01750 (void) ub.minimize();
01751 PPL_ASSERT(!ub.is_empty());
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761 Bit_Row x_gs_condition_3_not_in_y;
01762 for (dimension_type i = y_cs_num_rows; i-- > 0; ) {
01763 const Constraint& y_c = y_cs[i];
01764 if (y_c.is_strict_inequality()) {
01765 for (dimension_type j = x_gs_condition_3.first();
01766 j != ULONG_MAX; j = x_gs_condition_3.next(j)) {
01767 const Generator& x_cp = x_gs[j];
01768 PPL_ASSERT(x_cp.is_closure_point());
01769 const int sp_sign = Scalar_Products::reduced_sign(y_c, x_cp);
01770 PPL_ASSERT(sp_sign >= 0);
01771 if (sp_sign == 0) {
01772 x_gs_condition_3.clear(j);
01773 x_gs_condition_3_not_in_y.set(j);
01774 }
01775 }
01776 if (x_gs_condition_3.empty())
01777 break;
01778 }
01779 }
01780
01781
01782
01783 Bit_Row y_gs_condition_3_not_in_x;
01784 for (dimension_type i = x_cs_num_rows; i-- > 0; ) {
01785 if (x_cs[i].is_strict_inequality()) {
01786 const Constraint& x_c = x_cs[i];
01787 for (dimension_type j = y_gs_condition_3.first();
01788 j != ULONG_MAX; j = y_gs_condition_3.next(j)) {
01789 const Generator& y_cp = y_gs[j];
01790 PPL_ASSERT(y_cp.is_closure_point());
01791 const int sp_sign = Scalar_Products::reduced_sign(x_c, y_cp);
01792 PPL_ASSERT(sp_sign >= 0);
01793 if (sp_sign == 0) {
01794 y_gs_condition_3.clear(j);
01795 y_gs_condition_3_not_in_x.set(j);
01796 }
01797 }
01798 if (y_gs_condition_3.empty())
01799 break;
01800 }
01801 }
01802
01803
01804
01805
01806
01807 const Constraint_System& ub_cs = ub.constraints();
01808 for (dimension_type i = ub_cs.num_rows(); i-- > 0; ) {
01809 if (ub_cs[i].is_strict_inequality()) {
01810 const Constraint& ub_c = ub_cs[i];
01811 for (dimension_type j = x_gs_condition_3_not_in_y.first();
01812 j != ULONG_MAX; j = x_gs_condition_3_not_in_y.next(j)) {
01813 const Generator& x_cp = x_gs[j];
01814 PPL_ASSERT(x_cp.is_closure_point());
01815 const int sp_sign = Scalar_Products::reduced_sign(ub_c, x_cp);
01816 PPL_ASSERT(sp_sign >= 0);
01817 if (sp_sign == 0)
01818 x_gs_condition_3_not_in_y.clear(j);
01819 }
01820 for (dimension_type j = y_gs_condition_3_not_in_x.first();
01821 j != ULONG_MAX; j = y_gs_condition_3_not_in_x.next(j)) {
01822 const Generator& y_cp = y_gs[j];
01823 PPL_ASSERT(y_cp.is_closure_point());
01824 const int sp_sign = Scalar_Products::reduced_sign(ub_c, y_cp);
01825 PPL_ASSERT(sp_sign >= 0);
01826 if (sp_sign == 0)
01827 y_gs_condition_3_not_in_x.clear(j);
01828 }
01829 }
01830 }
01831
01832 if (!(x_gs_condition_3_not_in_y.empty()
01833 && y_gs_condition_3_not_in_x.empty()))
01834
01835
01836 return false;
01837
01838
01839
01840
01841
01842 for (dimension_type i = x_cs_condition_3.first();
01843 i != ULONG_MAX; i = x_cs_condition_3.next(i)) {
01844 const Constraint& x_cs_i = x_cs[i];
01845 PPL_ASSERT(x_cs_i.is_strict_inequality());
01846
01847 Constraint eq_i(Linear_Expression(x_cs_i) == 0);
01848 PPL_ASSERT(!(ub.relation_with(eq_i)
01849 .implies(Poly_Con_Relation::is_disjoint())));
01850 Polyhedron ub_inters_hyperplane(ub);
01851 ub_inters_hyperplane.add_constraint(eq_i);
01852 Polyhedron y_inters_hyperplane(y);
01853 y_inters_hyperplane.add_constraint(eq_i);
01854 if (!y_inters_hyperplane.contains(ub_inters_hyperplane))
01855
01856 return false;
01857 }
01858
01859
01860 for (dimension_type i = y_cs_condition_3.first();
01861 i != ULONG_MAX; i = y_cs_condition_3.next(i)) {
01862 const Constraint& y_cs_i = y_cs[i];
01863 PPL_ASSERT(y_cs_i.is_strict_inequality());
01864
01865 Constraint eq_i(Linear_Expression(y_cs_i) == 0);
01866 PPL_ASSERT(!(ub.relation_with(eq_i)
01867 .implies(Poly_Con_Relation::is_disjoint())));
01868 Polyhedron ub_inters_hyperplane(ub);
01869 ub_inters_hyperplane.add_constraint(eq_i);
01870 Polyhedron x_inters_hyperplane(x);
01871 x_inters_hyperplane.add_constraint(eq_i);
01872 if (!x_inters_hyperplane.contains(ub_inters_hyperplane))
01873
01874 return false;
01875 }
01876
01877
01878 swap(ub);
01879 return true;
01880 }
01881
01882 bool
01883 PPL::Polyhedron::BFT00_poly_hull_assign_if_exact(const Polyhedron& y) {
01884
01885 const Polyhedron& x = *this;
01886
01887 PPL_ASSERT(x.is_necessarily_closed());
01888 PPL_ASSERT(x.topology() == y.topology());
01889 PPL_ASSERT(x.space_dim == y.space_dim);
01890
01891
01892 if (x.space_dim == 0) {
01893 upper_bound_assign(y);
01894 return true;
01895 }
01896
01897 if (x.marked_empty()) {
01898 *this = y;
01899 return true;
01900 }
01901 else if (y.is_empty())
01902 return true;
01903 else if (x.is_empty()) {
01904 *this = y;
01905 return true;
01906 }
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918 (void) x.minimize();
01919 (void) y.minimize();
01920 const Constraint_System& x_cs = x.con_sys;
01921 const Constraint_System& y_cs = y.con_sys;
01922 const Generator_System& x_gs = x.gen_sys;
01923 const Generator_System& y_gs = y.gen_sys;
01924 const dimension_type x_gs_num_rows = x_gs.num_rows();
01925 const dimension_type y_gs_num_rows = y_gs.num_rows();
01926
01927
01928 std::vector<bool> x_gs_red_in_y(x_gs_num_rows, false);
01929 dimension_type num_x_gs_red_in_y = 0;
01930 for (dimension_type i = x_gs_num_rows; i-- > 0; )
01931 if (y.relation_with(x_gs[i]).implies(Poly_Gen_Relation::subsumes())) {
01932 x_gs_red_in_y[i] = true;
01933 ++num_x_gs_red_in_y;
01934 }
01935 std::vector<bool> y_gs_red_in_x(y_gs_num_rows, false);
01936 dimension_type num_y_gs_red_in_x = 0;
01937 for (dimension_type i = y_gs_num_rows; i-- > 0; )
01938 if (x.relation_with(y_gs[i]).implies(Poly_Gen_Relation::subsumes())) {
01939 y_gs_red_in_x[i] = true;
01940 ++num_y_gs_red_in_x;
01941 }
01942
01943
01944
01945 if (num_x_gs_red_in_y == 0 && num_y_gs_red_in_x == 0)
01946 return false;
01947
01948
01949 if (num_y_gs_red_in_x == y_gs_num_rows)
01950
01951 return true;
01952 if (num_x_gs_red_in_y == x_gs_num_rows) {
01953
01954 *this = y;
01955 return true;
01956 }
01957
01958
01959
01960
01961 const dimension_type x_cs_num_rows = x_cs.num_rows();
01962 std::vector<bool> x_cs_red_in_y(x_cs_num_rows, false);
01963 for (dimension_type i = x_cs_num_rows; i-- > 0; ) {
01964 const Constraint& x_cs_i = x_cs[i];
01965 if (y.relation_with(x_cs_i).implies(Poly_Con_Relation::is_included()))
01966 x_cs_red_in_y[i] = true;
01967 else if (x_cs_i.is_equality())
01968
01969
01970
01971
01972 return false;
01973 }
01974 const dimension_type y_cs_num_rows = y_cs.num_rows();
01975 std::vector<bool> y_cs_red_in_x(y_cs_num_rows, false);
01976 for (dimension_type i = y_cs_num_rows; i-- > 0; ) {
01977 const Constraint& y_cs_i = y_cs[i];
01978 if (x.relation_with(y_cs_i).implies(Poly_Con_Relation::is_included()))
01979 y_cs_red_in_x[i] = true;
01980 else if (y_cs_i.is_equality())
01981
01982
01983 return false;
01984 }
01985
01986
01987
01988
01989
01990
01991
01992
01993 Linear_Row mid_row;
01994 const Generator& mid_g = static_cast<const Generator&>(mid_row);
01995
01996 for (dimension_type i = x_gs_num_rows; i-- > 0; ) {
01997 if (x_gs_red_in_y[i])
01998 continue;
01999 const Linear_Row& x_row = static_cast<const Linear_Row&>(x_gs[i]);
02000 const dimension_type row_sz = x_row.size();
02001 const bool x_row_is_line = x_row.is_line_or_equality();
02002 for (dimension_type j = y_gs_num_rows; j-- > 0; ) {
02003 if (y_gs_red_in_x[j])
02004 continue;
02005 const Linear_Row& y_row = static_cast<const Linear_Row&>(y_gs[j]);
02006 const bool y_row_is_line = y_row.is_line_or_equality();
02007
02008
02009
02010
02011 mid_row = x_row;
02012 for (dimension_type k = row_sz; k-- > 0; )
02013 mid_row[k] += y_row[k];
02014
02015 const bool illegal_ray
02016 = (mid_row[0] == 0 && mid_row.all_homogeneous_terms_are_zero());
02017
02018
02019 PPL_ASSERT(!(illegal_ray && (x_row_is_line || y_row_is_line)));
02020 if (illegal_ray)
02021 continue;
02022 if (x_row_is_line) {
02023 mid_row.normalize();
02024 if (y_row_is_line)
02025
02026 mid_row.sign_normalize();
02027 else
02028
02029 mid_row.set_is_ray_or_point_or_inequality();
02030 }
02031
02032
02033 if (x.relation_with(mid_g) == Poly_Gen_Relation::nothing()
02034 && y.relation_with(mid_g) == Poly_Gen_Relation::nothing())
02035 return false;
02036
02037
02038
02039
02040 if (!x_row_is_line && y_row_is_line) {
02041
02042 mid_row = x_row;
02043 for (dimension_type k = row_sz; k-- > 0; )
02044 mid_row[k] -= y_row[k];
02045 mid_row.normalize();
02046
02047 if (x.relation_with(mid_g) == Poly_Gen_Relation::nothing()
02048 && y.relation_with(mid_g) == Poly_Gen_Relation::nothing())
02049 return false;
02050 }
02051 else if (x_row_is_line && !y_row_is_line) {
02052
02053 mid_row = y_row;
02054 for (dimension_type k = row_sz; k-- > 0; )
02055 mid_row[k] -= x_row[k];
02056 mid_row.normalize();
02057
02058 if (x.relation_with(mid_g) == Poly_Gen_Relation::nothing()
02059 && y.relation_with(mid_g) == Poly_Gen_Relation::nothing())
02060 return false;
02061 }
02062 }
02063 }
02064
02065
02066
02067
02068
02069 for (dimension_type j = 0; j < y_gs_num_rows; ++j) {
02070 if (!y_gs_red_in_x[j])
02071 add_generator(y_gs[j]);
02072 }
02073 PPL_ASSERT_HEAVY(OK());
02074 return true;
02075 }
02076
02077 void
02078 PPL::Polyhedron::drop_some_non_integer_points(const Variables_Set* pvars,
02079 Complexity_Class complexity) {
02080
02081 if (pvars != 0 && pvars->empty())
02082 return;
02083
02084
02085 if (marked_empty())
02086 return;
02087
02088
02089
02090 if (space_dim == 0) {
02091 set_empty();
02092 return;
02093 }
02094
02095
02096 if (has_pending_generators()) {
02097
02098 if (complexity != ANY_COMPLEXITY)
02099 return;
02100 else
02101 process_pending_generators();
02102 }
02103 if (!constraints_are_up_to_date()) {
02104
02105 if (complexity != ANY_COMPLEXITY)
02106 return;
02107 else
02108 update_constraints();
02109 }
02110
02111 if (!is_necessarily_closed() && has_pending_constraints()) {
02112 if (complexity != ANY_COMPLEXITY)
02113 return;
02114 else if (!process_pending_constraints())
02115
02116 return;
02117 }
02118
02119 PPL_ASSERT(!has_pending_generators() && constraints_are_up_to_date());
02120 PPL_ASSERT(is_necessarily_closed() || !has_pending_constraints());
02121
02122 bool changed = false;
02123 const dimension_type eps_index = space_dim + 1;
02124 PPL_DIRTY_TEMP_COEFFICIENT(gcd);
02125
02126 for (dimension_type j = con_sys.num_rows(); j-- > 0; ) {
02127 Constraint& c = con_sys[j];
02128 if (c.is_tautological())
02129 goto next_constraint;
02130
02131 if (pvars != 0) {
02132 for (dimension_type i = space_dim; i-- > 0; )
02133 if (c[i+1] != 0 && pvars->find(i) == pvars->end())
02134 goto next_constraint;
02135 }
02136
02137 if (!is_necessarily_closed()) {
02138
02139
02140 if (c[eps_index] < 0) {
02141 c[eps_index] = 0;
02142 --c[0];
02143
02144
02145 c.normalize();
02146 changed = true;
02147 }
02148 }
02149
02150 {
02151
02152 dimension_type i = space_dim+1;
02153 while (i > 1) {
02154 const Coefficient& c_i = c[--i];
02155 if (const int c_i_sign = sgn(c_i)) {
02156 gcd = c_i;
02157 if (c_i_sign < 0)
02158 neg_assign(gcd);
02159 goto compute_gcd;
02160 }
02161 }
02162
02163 goto next_constraint;
02164
02165 compute_gcd:
02166 if (gcd == 1)
02167 goto next_constraint;
02168 while (i > 1) {
02169 const Coefficient& c_i = c[--i];
02170 if (c_i != 0) {
02171
02172 gcd_assign(gcd, c_i, gcd);
02173 if (gcd == 1)
02174 goto next_constraint;
02175 }
02176 }
02177 PPL_ASSERT(gcd != 1);
02178 PPL_ASSERT(c[0] % gcd != 0);
02179
02180
02181 if (c.is_equality()) {
02182 set_empty();
02183 return;
02184 }
02185
02186
02187 for (dimension_type k = space_dim+1; --k > 0; ) {
02188 Coefficient& c_k = c[k];
02189 exact_div_assign(c_k, c_k, gcd);
02190 }
02191 Coefficient& c_0 = c[0];
02192 const int c_0_sign = sgn(c_0);
02193 c_0 /= gcd;
02194 if (c_0_sign < 0)
02195 --c_0;
02196 changed = true;
02197 }
02198
02199 next_constraint:
02200 ;
02201 }
02202
02203 if (changed) {
02204 if (!is_necessarily_closed()) {
02205 con_sys.insert(Constraint::epsilon_leq_one());
02206
02207
02208 con_sys.set_sorted(false);
02209 }
02210
02211
02212
02213
02214 clear_generators_up_to_date();
02215 clear_constraints_minimized();
02216 }
02217 PPL_ASSERT_HEAVY(OK());
02218 }
02219
02220 void
02221 PPL::Polyhedron::throw_runtime_error(const char* method) const {
02222 std::ostringstream s;
02223 s << "PPL::";
02224 if (is_necessarily_closed())
02225 s << "C_";
02226 else
02227 s << "NNC_";
02228 s << "Polyhedron::" << method << "." << std::endl;
02229 throw std::runtime_error(s.str());
02230 }
02231
02232 void
02233 PPL::Polyhedron::throw_invalid_argument(const char* method,
02234 const char* reason) const {
02235 std::ostringstream s;
02236 s << "PPL::";
02237 if (is_necessarily_closed())
02238 s << "C_";
02239 else
02240 s << "NNC_";
02241 s << "Polyhedron::" << method << ":" << std::endl
02242 << reason << ".";
02243 throw std::invalid_argument(s.str());
02244 }
02245
02246 void
02247 PPL::Polyhedron::throw_topology_incompatible(const char* method,
02248 const char* ph_name,
02249 const Polyhedron& ph) const {
02250 std::ostringstream s;
02251 s << "PPL::";
02252 if (is_necessarily_closed())
02253 s << "C_";
02254 else
02255 s << "NNC_";
02256 s << "Polyhedron::" << method << ":" << std::endl
02257 << ph_name << " is a ";
02258 if (ph.is_necessarily_closed())
02259 s << "C_";
02260 else
02261 s << "NNC_";
02262 s << "Polyhedron." << std::endl;
02263 throw std::invalid_argument(s.str());
02264 }
02265
02266 void
02267 PPL::Polyhedron::throw_topology_incompatible(const char* method,
02268 const char* c_name,
02269 const Constraint&) const {
02270 PPL_ASSERT(is_necessarily_closed());
02271 std::ostringstream s;
02272 s << "PPL::C_Polyhedron::" << method << ":" << std::endl
02273 << c_name << " is a strict inequality.";
02274 throw std::invalid_argument(s.str());
02275 }
02276
02277 void
02278 PPL::Polyhedron::throw_topology_incompatible(const char* method,
02279 const char* g_name,
02280 const Generator&) const {
02281 PPL_ASSERT(is_necessarily_closed());
02282 std::ostringstream s;
02283 s << "PPL::C_Polyhedron::" << method << ":" << std::endl
02284 << g_name << " is a closure point.";
02285 throw std::invalid_argument(s.str());
02286 }
02287
02288 void
02289 PPL::Polyhedron::throw_topology_incompatible(const char* method,
02290 const char* cs_name,
02291 const Constraint_System&) const {
02292 PPL_ASSERT(is_necessarily_closed());
02293 std::ostringstream s;
02294 s << "PPL::C_Polyhedron::" << method << ":" << std::endl
02295 << cs_name << " contains strict inequalities.";
02296 throw std::invalid_argument(s.str());
02297 }
02298
02299 void
02300 PPL::Polyhedron::throw_topology_incompatible(const char* method,
02301 const char* gs_name,
02302 const Generator_System&) const {
02303 std::ostringstream s;
02304 s << "PPL::C_Polyhedron::" << method << ":" << std::endl
02305 << gs_name << " contains closure points.";
02306 throw std::invalid_argument(s.str());
02307 }
02308
02309 void
02310 PPL::Polyhedron::throw_dimension_incompatible(const char* method,
02311 const char* other_name,
02312 dimension_type other_dim) const {
02313 std::ostringstream s;
02314 s << "PPL::"
02315 << (is_necessarily_closed() ? "C_" : "NNC_")
02316 << "Polyhedron::" << method << ":\n"
02317 << "this->space_dimension() == " << space_dimension() << ", "
02318 << other_name << ".space_dimension() == " << other_dim << ".";
02319 throw std::invalid_argument(s.str());
02320 }
02321
02322 void
02323 PPL::Polyhedron::throw_dimension_incompatible(const char* method,
02324 const char* ph_name,
02325 const Polyhedron& ph) const {
02326 throw_dimension_incompatible(method, ph_name, ph.space_dimension());
02327 }
02328
02329 void
02330 PPL::Polyhedron::throw_dimension_incompatible(const char* method,
02331 const char* e_name,
02332 const Linear_Expression& e) const {
02333 throw_dimension_incompatible(method, e_name, e.space_dimension());
02334 }
02335
02336 void
02337 PPL::Polyhedron::throw_dimension_incompatible(const char* method,
02338 const char* c_name,
02339 const Constraint& c) const {
02340 throw_dimension_incompatible(method, c_name, c.space_dimension());
02341 }
02342
02343 void
02344 PPL::Polyhedron::throw_dimension_incompatible(const char* method,
02345 const char* g_name,
02346 const Generator& g) const {
02347 throw_dimension_incompatible(method, g_name, g.space_dimension());
02348 }
02349
02350 void
02351 PPL::Polyhedron::throw_dimension_incompatible(const char* method,
02352 const char* cg_name,
02353 const Congruence& cg) const {
02354 throw_dimension_incompatible(method, cg_name, cg.space_dimension());
02355 }
02356
02357 void
02358 PPL::Polyhedron::throw_dimension_incompatible(const char* method,
02359 const char* cs_name,
02360 const Constraint_System& cs) const {
02361 throw_dimension_incompatible(method, cs_name, cs.space_dimension());
02362 }
02363
02364 void
02365 PPL::Polyhedron::throw_dimension_incompatible(const char* method,
02366 const char* gs_name,
02367 const Generator_System& gs) const {
02368 throw_dimension_incompatible(method, gs_name, gs.space_dimension());
02369 }
02370
02371 void
02372 PPL::Polyhedron::throw_dimension_incompatible(const char* method,
02373 const char* cgs_name,
02374 const Congruence_System& cgs) const {
02375 throw_dimension_incompatible(method, cgs_name, cgs.space_dimension());
02376 }
02377
02378 void
02379 PPL::Polyhedron::throw_dimension_incompatible(const char* method,
02380 const char* var_name,
02381 const Variable var) const {
02382 std::ostringstream s;
02383 s << "PPL::";
02384 if (is_necessarily_closed())
02385 s << "C_";
02386 else
02387 s << "NNC_";
02388 s << "Polyhedron::" << method << ":" << std::endl
02389 << "this->space_dimension() == " << space_dimension() << ", "
02390 << var_name << ".space_dimension() == " << var.space_dimension() << ".";
02391 throw std::invalid_argument(s.str());
02392 }
02393
02394 void
02395 PPL::Polyhedron::
02396 throw_dimension_incompatible(const char* method,
02397 dimension_type required_space_dim) const {
02398 std::ostringstream s;
02399 s << "PPL::";
02400 if (is_necessarily_closed())
02401 s << "C_";
02402 else
02403 s << "NNC_";
02404 s << "Polyhedron::" << method << ":" << std::endl
02405 << "this->space_dimension() == " << space_dimension()
02406 << ", required space dimension == " << required_space_dim << ".";
02407 throw std::invalid_argument(s.str());
02408 }
02409
02410 void
02411 PPL::Polyhedron::throw_space_dimension_overflow(const Topology topol,
02412 const char* method,
02413 const char* reason) {
02414 std::ostringstream s;
02415 s << "PPL::";
02416 if (topol == NECESSARILY_CLOSED)
02417 s << "C_";
02418 else
02419 s << "NNC_";
02420 s << "Polyhedron::" << method << ":" << std::endl
02421 << reason << ".";
02422 throw std::length_error(s.str());
02423 }
02424
02425 void
02426 PPL::Polyhedron::throw_invalid_generator(const char* method,
02427 const char* g_name) const {
02428 std::ostringstream s;
02429 s << "PPL::";
02430 if (is_necessarily_closed())
02431 s << "C_";
02432 else
02433 s << "NNC_";
02434 s << "Polyhedron::" << method << ":" << std::endl
02435 << "*this is an empty polyhedron and "
02436 << g_name << " is not a point.";
02437 throw std::invalid_argument(s.str());
02438 }
02439
02440 void
02441 PPL::Polyhedron::throw_invalid_generators(const char* method,
02442 const char* gs_name) const {
02443 std::ostringstream s;
02444 s << "PPL::";
02445 if (is_necessarily_closed())
02446 s << "C_";
02447 else
02448 s << "NNC_";
02449 s << "Polyhedron::" << method << ":" << std::endl
02450 << "*this is an empty polyhedron and" << std::endl
02451 << "the non-empty generator system " << gs_name << " contains no points.";
02452 throw std::invalid_argument(s.str());
02453 }