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_BD_Shape_templates_hh
00025 #define PPL_BD_Shape_templates_hh 1
00026
00027 #include "Generator_System.defs.hh"
00028 #include "Generator_System.inlines.hh"
00029 #include "Congruence_System.inlines.hh"
00030 #include "Congruence_System.defs.hh"
00031 #include "Poly_Con_Relation.defs.hh"
00032 #include "Poly_Gen_Relation.defs.hh"
00033 #include "MIP_Problem.defs.hh"
00034 #include "Variables_Set.defs.hh"
00035 #include "Bit_Row.defs.hh"
00036 #include "Temp.defs.hh"
00037 #include "assert.hh"
00038 #include <vector>
00039 #include <deque>
00040 #include <iostream>
00041 #include <sstream>
00042 #include <stdexcept>
00043 #include <algorithm>
00044
00045 namespace Parma_Polyhedra_Library {
00046
00047 template <typename T>
00048 BD_Shape<T>::BD_Shape(const Congruence_System& cgs)
00049 : dbm(cgs.space_dimension() + 1),
00050 status(),
00051 redundancy_dbm() {
00052 add_congruences(cgs);
00053 }
00054
00055 template <typename T>
00056 BD_Shape<T>::BD_Shape(const Generator_System& gs)
00057 : dbm(gs.space_dimension() + 1), status(), redundancy_dbm() {
00058 const Generator_System::const_iterator gs_begin = gs.begin();
00059 const Generator_System::const_iterator gs_end = gs.end();
00060 if (gs_begin == gs_end) {
00061
00062 set_empty();
00063 return;
00064 }
00065
00066 const dimension_type space_dim = space_dimension();
00067 DB_Row<N>& dbm_0 = dbm[0];
00068 PPL_DIRTY_TEMP(N, tmp);
00069
00070 bool dbm_initialized = false;
00071 bool point_seen = false;
00072
00073 for (Generator_System::const_iterator gs_i = gs_begin;
00074 gs_i != gs_end; ++gs_i) {
00075 const Generator& g = *gs_i;
00076 switch (g.type()) {
00077 case Generator::POINT:
00078 point_seen = true;
00079
00080 case Generator::CLOSURE_POINT:
00081 if (!dbm_initialized) {
00082
00083 dbm_initialized = true;
00084 const Coefficient& d = g.divisor();
00085 for (dimension_type i = space_dim; i > 0; --i) {
00086 const Coefficient& g_i = g.coefficient(Variable(i-1));
00087 DB_Row<N>& dbm_i = dbm[i];
00088 for (dimension_type j = space_dim; j > 0; --j)
00089 if (i != j)
00090 div_round_up(dbm_i[j], g.coefficient(Variable(j-1)) - g_i, d);
00091 div_round_up(dbm_i[0], -g_i, d);
00092 }
00093 for (dimension_type j = space_dim; j > 0; --j)
00094 div_round_up(dbm_0[j], g.coefficient(Variable(j-1)), d);
00095
00096 }
00097 else {
00098
00099
00100 const Coefficient& d = g.divisor();
00101 for (dimension_type i = space_dim; i > 0; --i) {
00102 const Coefficient& g_i = g.coefficient(Variable(i-1));
00103 DB_Row<N>& dbm_i = dbm[i];
00104
00105 for (dimension_type j = space_dim; j > 0; --j) {
00106 div_round_up(tmp, g.coefficient(Variable(j-1)) - g_i, d);
00107 max_assign(dbm_i[j], tmp);
00108 }
00109 div_round_up(tmp, -g_i, d);
00110 max_assign(dbm_i[0], tmp);
00111 }
00112 for (dimension_type j = space_dim; j > 0; --j) {
00113 div_round_up(tmp, g.coefficient(Variable(j-1)), d);
00114 max_assign(dbm_0[j], tmp);
00115 }
00116 }
00117 break;
00118 default:
00119
00120 break;
00121 }
00122 }
00123
00124 if (!point_seen)
00125
00126 throw_generic("BD_Shape(gs)",
00127 "the non-empty generator system gs contains no points.");
00128
00129
00130 for (Generator_System::const_iterator gs_i = gs_begin;
00131 gs_i != gs_end; ++gs_i) {
00132 const Generator& g = *gs_i;
00133 switch (g.type()) {
00134 case Generator::LINE:
00135 for (dimension_type i = space_dim; i > 0; --i) {
00136 const Coefficient& g_i = g.coefficient(Variable(i-1));
00137 DB_Row<N>& dbm_i = dbm[i];
00138
00139 for (dimension_type j = space_dim; j > 0; --j)
00140 if (g_i != g.coefficient(Variable(j-1)))
00141 assign_r(dbm_i[j], PLUS_INFINITY, ROUND_NOT_NEEDED);
00142 if (g_i != 0)
00143 assign_r(dbm_i[0], PLUS_INFINITY, ROUND_NOT_NEEDED);
00144 }
00145 for (dimension_type j = space_dim; j > 0; --j)
00146 if (g.coefficient(Variable(j-1)) != 0)
00147 assign_r(dbm_0[j], PLUS_INFINITY, ROUND_NOT_NEEDED);
00148 break;
00149 case Generator::RAY:
00150 for (dimension_type i = space_dim; i > 0; --i) {
00151 const Coefficient& g_i = g.coefficient(Variable(i-1));
00152 DB_Row<N>& dbm_i = dbm[i];
00153
00154 for (dimension_type j = space_dim; j > 0; --j)
00155 if (g_i < g.coefficient(Variable(j-1)))
00156 assign_r(dbm_i[j], PLUS_INFINITY, ROUND_NOT_NEEDED);
00157 if (g_i < 0)
00158 assign_r(dbm_i[0], PLUS_INFINITY, ROUND_NOT_NEEDED);
00159 }
00160 for (dimension_type j = space_dim; j > 0; --j)
00161 if (g.coefficient(Variable(j-1)) > 0)
00162 assign_r(dbm_0[j], PLUS_INFINITY, ROUND_NOT_NEEDED);
00163 break;
00164 default:
00165
00166 break;
00167 }
00168 }
00169 set_shortest_path_closed();
00170 PPL_ASSERT(OK());
00171 }
00172
00173 template <typename T>
00174 BD_Shape<T>::BD_Shape(const Polyhedron& ph, const Complexity_Class complexity)
00175 : dbm(), status(), redundancy_dbm() {
00176 const dimension_type num_dimensions = ph.space_dimension();
00177
00178 if (ph.marked_empty()) {
00179 *this = BD_Shape<T>(num_dimensions, EMPTY);
00180 return;
00181 }
00182
00183 if (num_dimensions == 0) {
00184 *this = BD_Shape<T>(num_dimensions, UNIVERSE);
00185 return;
00186 }
00187
00188
00189
00190 if (complexity == ANY_COMPLEXITY
00191 || (!ph.has_pending_constraints() && ph.generators_are_up_to_date())) {
00192 *this = BD_Shape<T>(ph.generators());
00193 return;
00194 }
00195
00196
00197
00198
00199 PPL_ASSERT(ph.constraints_are_up_to_date());
00200
00201 if (!ph.has_something_pending() && ph.constraints_are_minimized()) {
00202
00203
00204 if (ph.is_universe()) {
00205 *this = BD_Shape<T>(num_dimensions, UNIVERSE);
00206 return;
00207 }
00208 }
00209
00210
00211 for (Constraint_System::const_iterator i = ph.con_sys.begin(),
00212 cs_end = ph.con_sys.end(); i != cs_end; ++i)
00213 if (i->is_inconsistent()) {
00214 *this = BD_Shape<T>(num_dimensions, EMPTY);
00215 return;
00216 }
00217
00218
00219
00220 if (complexity == SIMPLEX_COMPLEXITY) {
00221 MIP_Problem lp(num_dimensions);
00222 lp.set_optimization_mode(MAXIMIZATION);
00223
00224 const Constraint_System& ph_cs = ph.constraints();
00225 if (!ph_cs.has_strict_inequalities())
00226 lp.add_constraints(ph_cs);
00227 else
00228
00229 for (Constraint_System::const_iterator i = ph_cs.begin(),
00230 ph_cs_end = ph_cs.end(); i != ph_cs_end; ++i) {
00231 const Constraint& c = *i;
00232 if (c.is_strict_inequality())
00233 lp.add_constraint(Linear_Expression(c) >= 0);
00234 else
00235 lp.add_constraint(c);
00236 }
00237
00238
00239 if (!lp.is_satisfiable()) {
00240 *this = BD_Shape<T>(num_dimensions, EMPTY);
00241 return;
00242 }
00243
00244
00245 *this = BD_Shape<T>(num_dimensions, UNIVERSE);
00246
00247 Generator g(point());
00248 PPL_DIRTY_TEMP_COEFFICIENT(num);
00249 PPL_DIRTY_TEMP_COEFFICIENT(den);
00250 for (dimension_type i = 1; i <= num_dimensions; ++i) {
00251 Variable x(i-1);
00252
00253 lp.set_objective_function(x);
00254 if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
00255 g = lp.optimizing_point();
00256 lp.evaluate_objective_function(g, num, den);
00257 div_round_up(dbm[0][i], num, den);
00258 }
00259
00260 for (dimension_type j = 1; j <= num_dimensions; ++j) {
00261 if (i == j)
00262 continue;
00263 Variable y(j-1);
00264 lp.set_objective_function(x - y);
00265 if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
00266 g = lp.optimizing_point();
00267 lp.evaluate_objective_function(g, num, den);
00268 div_round_up(dbm[j][i], num, den);
00269 }
00270 }
00271
00272 lp.set_objective_function(-x);
00273 if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
00274 g = lp.optimizing_point();
00275 lp.evaluate_objective_function(g, num, den);
00276 div_round_up(dbm[i][0], num, den);
00277 }
00278 }
00279 set_shortest_path_closed();
00280 PPL_ASSERT(OK());
00281 return;
00282 }
00283
00284
00285 PPL_ASSERT(complexity == POLYNOMIAL_COMPLEXITY);
00286 *this = BD_Shape<T>(num_dimensions, UNIVERSE);
00287 refine_with_constraints(ph.constraints());
00288 }
00289
00290 template <typename T>
00291 dimension_type
00292 BD_Shape<T>::affine_dimension() const {
00293 const dimension_type space_dim = space_dimension();
00294
00295 if (space_dim == 0)
00296 return 0;
00297
00298
00299
00300 shortest_path_closure_assign();
00301 if (marked_empty())
00302 return 0;
00303
00304
00305
00306
00307 std::vector<dimension_type> predecessor;
00308 compute_predecessors(predecessor);
00309
00310
00311
00312 dimension_type affine_dim = 0;
00313
00314 for (dimension_type i = 1; i <= space_dim; ++i)
00315 if (predecessor[i] == i)
00316 ++affine_dim;
00317
00318 return affine_dim;
00319 }
00320
00321 template <typename T>
00322 Congruence_System
00323 BD_Shape<T>::minimized_congruences() const {
00324
00325
00326 shortest_path_closure_assign();
00327
00328 const dimension_type space_dim = space_dimension();
00329 Congruence_System cgs;
00330 if (space_dim == 0) {
00331 if (marked_empty())
00332 cgs = Congruence_System::zero_dim_empty();
00333 }
00334 else if (marked_empty())
00335 cgs.insert((0*Variable(space_dim-1) %= 1) / 0);
00336 else {
00337
00338
00339 cgs.insert(0*Variable(space_dim-1) == 0);
00340
00341 PPL_DIRTY_TEMP_COEFFICIENT(num);
00342 PPL_DIRTY_TEMP_COEFFICIENT(den);
00343
00344
00345 std::vector<dimension_type> leaders;
00346 compute_leaders(leaders);
00347
00348
00349 const DB_Row<N>& dbm_0 = dbm[0];
00350 for (dimension_type i = 1; i <= space_dim; ++i) {
00351 const dimension_type leader = leaders[i];
00352 if (i != leader) {
00353
00354 if (leader == 0) {
00355
00356 PPL_ASSERT(!is_plus_infinity(dbm_0[i]));
00357 numer_denom(dbm_0[i], num, den);
00358 cgs.insert(den*Variable(i-1) == num);
00359 }
00360 else {
00361
00362 PPL_ASSERT(!is_plus_infinity(dbm[i][leader]));
00363 numer_denom(dbm[i][leader], num, den);
00364 cgs.insert(den*Variable(leader-1) - den*Variable(i-1) == num);
00365 }
00366 }
00367 }
00368 }
00369 return cgs;
00370 }
00371
00372 template <typename T>
00373 void
00374 BD_Shape<T>::add_constraint(const Constraint& c) {
00375 const dimension_type c_space_dim = c.space_dimension();
00376
00377 if (c_space_dim > space_dimension())
00378 throw_dimension_incompatible("add_constraint(c)", c);
00379
00380
00381 if (c.is_strict_inequality()) {
00382 if (c.is_inconsistent()) {
00383 set_empty();
00384 return;
00385 }
00386 if (c.is_tautological())
00387 return;
00388
00389 throw_generic("add_constraint(c)", "strict inequalities are not allowed");
00390 }
00391
00392 dimension_type num_vars = 0;
00393 dimension_type i = 0;
00394 dimension_type j = 0;
00395 PPL_DIRTY_TEMP_COEFFICIENT(coeff);
00396
00397 if (!extract_bounded_difference(c, c_space_dim, num_vars, i, j, coeff))
00398 throw_generic("add_constraint(c)",
00399 "c is not a bounded difference constraint");
00400
00401 const Coefficient& inhomo = c.inhomogeneous_term();
00402 if (num_vars == 0) {
00403
00404 if (inhomo < 0
00405 || (inhomo != 0 && c.is_equality()))
00406 set_empty();
00407 return;
00408 }
00409
00410
00411
00412 const bool negative = (coeff < 0);
00413 N& x = negative ? dbm[i][j] : dbm[j][i];
00414 N& y = negative ? dbm[j][i] : dbm[i][j];
00415 if (negative)
00416 neg_assign(coeff);
00417
00418 bool changed = false;
00419
00420 PPL_DIRTY_TEMP(N, d);
00421 div_round_up(d, inhomo, coeff);
00422 if (x > d) {
00423 x = d;
00424 changed = true;
00425 }
00426
00427 if (c.is_equality()) {
00428
00429 PPL_DIRTY_TEMP_COEFFICIENT(minus_c_term);
00430 neg_assign(minus_c_term, inhomo);
00431 div_round_up(d, minus_c_term, coeff);
00432 if (y > d) {
00433 y = d;
00434 changed = true;
00435 }
00436 }
00437
00438
00439
00440 if (changed && marked_shortest_path_closed())
00441 reset_shortest_path_closed();
00442 PPL_ASSERT(OK());
00443 }
00444
00445 template <typename T>
00446 void
00447 BD_Shape<T>::add_congruence(const Congruence& cg) {
00448 const dimension_type cg_space_dim = cg.space_dimension();
00449
00450
00451 if (space_dimension() < cg_space_dim)
00452 throw_dimension_incompatible("add_congruence(cg)", cg);
00453
00454
00455 if (cg.is_proper_congruence()) {
00456 if (cg.is_tautological())
00457 return;
00458 if (cg.is_inconsistent()) {
00459 set_empty();
00460 return;
00461 }
00462
00463 throw_generic("add_congruence(cg)",
00464 "cg is a non-trivial, proper congruence");
00465 }
00466
00467 PPL_ASSERT(cg.is_equality());
00468 Constraint c(cg);
00469 add_constraint(c);
00470 }
00471
00472 template <typename T>
00473 void
00474 BD_Shape<T>::refine_no_check(const Constraint& c) {
00475 PPL_ASSERT(!marked_empty());
00476 const dimension_type c_space_dim = c.space_dimension();
00477 PPL_ASSERT(c_space_dim <= space_dimension());
00478
00479 dimension_type num_vars = 0;
00480 dimension_type i = 0;
00481 dimension_type j = 0;
00482 PPL_DIRTY_TEMP_COEFFICIENT(coeff);
00483
00484 if (!extract_bounded_difference(c, c_space_dim, num_vars, i, j, coeff))
00485 return;
00486
00487 const Coefficient& inhomo = c.inhomogeneous_term();
00488 if (num_vars == 0) {
00489
00490 if (inhomo < 0
00491 || (c.is_equality() && inhomo != 0)
00492 || (c.is_strict_inequality() && inhomo == 0))
00493 set_empty();
00494 return;
00495 }
00496
00497
00498
00499 const bool negative = (coeff < 0);
00500 N& x = negative ? dbm[i][j] : dbm[j][i];
00501 N& y = negative ? dbm[j][i] : dbm[i][j];
00502 if (negative)
00503 neg_assign(coeff);
00504
00505 bool changed = false;
00506
00507 PPL_DIRTY_TEMP(N, d);
00508 div_round_up(d, inhomo, coeff);
00509 if (x > d) {
00510 x = d;
00511 changed = true;
00512 }
00513
00514 if (c.is_equality()) {
00515
00516 PPL_DIRTY_TEMP_COEFFICIENT(minus_c_term);
00517 neg_assign(minus_c_term, inhomo);
00518 div_round_up(d, minus_c_term, coeff);
00519 if (y > d) {
00520 y = d;
00521 changed = true;
00522 }
00523 }
00524
00525
00526
00527 if (changed && marked_shortest_path_closed())
00528 reset_shortest_path_closed();
00529 PPL_ASSERT(OK());
00530 }
00531
00532 template <typename T>
00533 void
00534 BD_Shape<T>::concatenate_assign(const BD_Shape& y) {
00535 BD_Shape& x = *this;
00536
00537 const dimension_type x_space_dim = x.space_dimension();
00538 const dimension_type y_space_dim = y.space_dimension();
00539
00540
00541
00542 if (y_space_dim == 0 && y.marked_empty()) {
00543 set_empty();
00544 return;
00545 }
00546
00547
00548
00549 if (x_space_dim == 0 && marked_empty()) {
00550 dbm.grow(y_space_dim + 1);
00551 PPL_ASSERT(OK());
00552 return;
00553 }
00554
00555
00556
00557
00558
00559
00560
00561 add_space_dimensions_and_embed(y_space_dim);
00562 const dimension_type new_space_dim = x_space_dim + y_space_dim;
00563 for (dimension_type i = x_space_dim + 1; i <= new_space_dim; ++i) {
00564 DB_Row<N>& dbm_i = dbm[i];
00565 dbm_i[0] = y.dbm[i - x_space_dim][0];
00566 dbm[0][i] = y.dbm[0][i - x_space_dim];
00567 for (dimension_type j = x_space_dim + 1; j <= new_space_dim; ++j)
00568 dbm_i[j] = y.dbm[i - x_space_dim][j - x_space_dim];
00569 }
00570
00571 if (marked_shortest_path_closed())
00572 reset_shortest_path_closed();
00573 PPL_ASSERT(OK());
00574 }
00575
00576 template <typename T>
00577 bool
00578 BD_Shape<T>::contains(const BD_Shape& y) const {
00579 const BD_Shape<T>& x = *this;
00580 const dimension_type x_space_dim = x.space_dimension();
00581
00582
00583 if (x_space_dim != y.space_dimension())
00584 throw_dimension_incompatible("contains(y)", y);
00585
00586
00587
00588
00589
00590 if (x_space_dim == 0) {
00591 if (!marked_empty())
00592 return true;
00593 else
00594 return y.marked_empty();
00595 }
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617 y.shortest_path_closure_assign();
00618
00619
00620 if (y.marked_empty())
00621 return true;
00622
00623
00624
00625 for (dimension_type i = x_space_dim + 1; i-- > 0; ) {
00626 const DB_Row<N>& x_dbm_i = x.dbm[i];
00627 const DB_Row<N>& y_dbm_i = y.dbm[i];
00628 for (dimension_type j = x_space_dim + 1; j-- > 0; )
00629 if (x_dbm_i[j] < y_dbm_i[j])
00630 return false;
00631 }
00632 return true;
00633 }
00634
00635 template <typename T>
00636 bool
00637 BD_Shape<T>::is_disjoint_from(const BD_Shape& y) const {
00638 const dimension_type space_dim = space_dimension();
00639
00640 if (space_dim != y.space_dimension())
00641 throw_dimension_incompatible("is_disjoint_from(y)", y);
00642
00643
00644
00645 shortest_path_closure_assign();
00646 if (marked_empty())
00647 return true;
00648 y.shortest_path_closure_assign();
00649 if (y.marked_empty())
00650 return true;
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664 PPL_DIRTY_TEMP(N, tmp);
00665 for (dimension_type i = space_dim+1; i-- > 0; ) {
00666 const DB_Row<N>& x_i = dbm[i];
00667 for (dimension_type j = space_dim+1; j-- > 0; ) {
00668 neg_assign_r(tmp, y.dbm[j][i], ROUND_UP);
00669 if (x_i[j] < tmp)
00670 return true;
00671 }
00672 }
00673
00674 return false;
00675 }
00676
00677 template <typename T>
00678 bool
00679 BD_Shape<T>::is_universe() const {
00680 if (marked_empty())
00681 return false;
00682
00683 const dimension_type space_dim = space_dimension();
00684
00685
00686 if (space_dim == 0)
00687 return true;
00688
00689
00690
00691 for (dimension_type i = space_dim + 1; i-- > 0; ) {
00692 const DB_Row<N>& dbm_i = dbm[i];
00693 for (dimension_type j = space_dim + 1; j-- > 0; )
00694 if (!is_plus_infinity(dbm_i[j]))
00695 return false;
00696 }
00697 return true;
00698 }
00699
00700 template <typename T>
00701 bool
00702 BD_Shape<T>::is_bounded() const {
00703 shortest_path_closure_assign();
00704 const dimension_type space_dim = space_dimension();
00705
00706 if (marked_empty() || space_dim == 0)
00707 return true;
00708
00709
00710
00711 for (dimension_type i = space_dim + 1; i-- > 0; ) {
00712 const DB_Row<N>& dbm_i = dbm[i];
00713 for (dimension_type j = space_dim + 1; j-- > 0; )
00714 if (i != j)
00715 if (is_plus_infinity(dbm_i[j]))
00716 return false;
00717 }
00718
00719 return true;
00720 }
00721
00722 template <typename T>
00723 bool
00724 BD_Shape<T>::contains_integer_point() const {
00725
00726 if (is_empty())
00727 return false;
00728
00729 const dimension_type space_dim = space_dimension();
00730 if (space_dim == 0)
00731 return true;
00732
00733
00734
00735 if (std::numeric_limits<T>::is_integer)
00736 return true;
00737
00738
00739
00740 BD_Shape<mpz_class> bds_z(space_dim);
00741 typedef BD_Shape<mpz_class>::N Z;
00742 bds_z.reset_shortest_path_closed();
00743 PPL_DIRTY_TEMP(N, tmp);
00744 bool all_integers = true;
00745 for (dimension_type i = space_dim + 1; i-- > 0; ) {
00746 DB_Row<Z>& z_i = bds_z.dbm[i];
00747 const DB_Row<N>& dbm_i = dbm[i];
00748 for (dimension_type j = space_dim + 1; j-- > 0; ) {
00749 const N& dbm_i_j = dbm_i[j];
00750 if (is_plus_infinity(dbm_i_j))
00751 continue;
00752 if (is_integer(dbm_i_j))
00753 assign_r(z_i[j], dbm_i_j, ROUND_NOT_NEEDED);
00754 else {
00755 all_integers = false;
00756 Z& z_i_j = z_i[j];
00757
00758 neg_assign_r(tmp, dbm_i_j, ROUND_NOT_NEEDED);
00759 assign_r(z_i_j, tmp, ROUND_UP);
00760 neg_assign_r(z_i_j, z_i_j, ROUND_NOT_NEEDED);
00761 }
00762 }
00763 }
00764 return all_integers || !bds_z.is_empty();
00765 }
00766
00767 template <typename T>
00768 bool
00769 BD_Shape<T>::frequency(const Linear_Expression& expr,
00770 Coefficient& freq_n, Coefficient& freq_d,
00771 Coefficient& val_n, Coefficient& val_d) const {
00772 dimension_type space_dim = space_dimension();
00773
00774 if (space_dim < expr.space_dimension())
00775 throw_dimension_incompatible("frequency(e, ...)", "e", expr);
00776
00777
00778
00779
00780
00781
00782
00783
00784 if (space_dim == 0) {
00785 if (is_empty())
00786 return false;
00787 freq_n = 0;
00788 freq_d = 1;
00789 val_n = expr.inhomogeneous_term();
00790 val_d = 1;
00791 return true;
00792 }
00793
00794 shortest_path_closure_assign();
00795
00796 if (marked_empty())
00797 return false;
00798
00799
00800 PPL_DIRTY_TEMP_COEFFICIENT(coeff);
00801 PPL_DIRTY_TEMP_COEFFICIENT(num);
00802 PPL_DIRTY_TEMP_COEFFICIENT(den);
00803 PPL_DIRTY_TEMP(N, tmp);
00804 Linear_Expression le = expr;
00805
00806
00807
00808 bool constant_v = false;
00809
00810 PPL_DIRTY_TEMP_COEFFICIENT(val_den);
00811 val_den = 1;
00812
00813 for (dimension_type i = dbm.num_rows(); i-- > 1; ) {
00814 constant_v = false;
00815 const Variable v(i-1);
00816 coeff = le.coefficient(v);
00817 if (coeff == 0) {
00818 constant_v = true;
00819 continue;
00820 }
00821
00822 const DB_Row<N>& dbm_i = dbm[i];
00823
00824 assign_r(tmp, dbm_i[0], ROUND_NOT_NEEDED);
00825 if (is_additive_inverse(dbm[0][i], tmp)) {
00826
00827 numer_denom(tmp, num, den);
00828 le -= coeff*v;
00829 le *= den;
00830 le -= num*coeff;
00831 val_den *= den;
00832 constant_v = true;
00833 continue;
00834 }
00835
00836
00837 else {
00838 PPL_ASSERT(!constant_v);
00839 for (dimension_type j = i; j-- > 1; ) {
00840 const Variable vj(j-1);
00841 if (le.coefficient(vj) == 0)
00842
00843 continue;
00844 assign_r(tmp, dbm_i[j], ROUND_NOT_NEEDED);
00845 if (is_additive_inverse(dbm[j][i], tmp)) {
00846
00847
00848
00849 numer_denom(tmp, num, den);
00850 le -= coeff*v - coeff*vj;
00851 le *= den;
00852 le -= num*coeff;
00853 val_den *= den;
00854 constant_v = true;
00855 break;
00856 }
00857 }
00858 if (!constant_v)
00859
00860 return false;
00861 }
00862 }
00863 if (!constant_v)
00864
00865 return false;
00866
00867
00868 freq_n = 0;
00869 freq_d = 1;
00870
00871
00872 normalize2(le.inhomogeneous_term(), val_den, val_n, val_d);
00873 return true;
00874 }
00875
00876 template <typename T>
00877 bool
00878 BD_Shape<T>::constrains(const Variable var) const {
00879
00880 const dimension_type var_space_dim = var.space_dimension();
00881 if (space_dimension() < var_space_dim)
00882 throw_dimension_incompatible("constrains(v)", "v", var);
00883
00884 shortest_path_closure_assign();
00885
00886
00887 if (marked_empty())
00888 return true;
00889
00890
00891 const DB_Row<N>& dbm_v = dbm[var_space_dim];
00892 for (dimension_type i = dbm.num_rows(); i-- > 0; ) {
00893 if (!is_plus_infinity(dbm_v[i])
00894 || !is_plus_infinity(dbm[i][var_space_dim]))
00895 return true;
00896 }
00897
00898
00899
00900 return is_empty();
00901 }
00902
00903 template <typename T>
00904 void
00905 BD_Shape<T>
00906 ::compute_predecessors(std::vector<dimension_type>& predecessor) const {
00907 PPL_ASSERT(!marked_empty() && marked_shortest_path_closed());
00908 PPL_ASSERT(predecessor.size() == 0);
00909
00910
00911
00912
00913
00914 const dimension_type pred_size = dbm.num_rows();
00915
00916 predecessor.reserve(pred_size);
00917 for (dimension_type i = 0; i < pred_size; ++i)
00918 predecessor.push_back(i);
00919
00920 for (dimension_type i = pred_size; i-- > 1; )
00921 if (i == predecessor[i]) {
00922 const DB_Row<N>& dbm_i = dbm[i];
00923 for (dimension_type j = i; j-- > 0; )
00924 if (j == predecessor[j]
00925 && is_additive_inverse(dbm[j][i], dbm_i[j])) {
00926
00927 predecessor[i] = j;
00928 break;
00929 }
00930 }
00931 }
00932
00933 template <typename T>
00934 void
00935 BD_Shape<T>::compute_leaders(std::vector<dimension_type>& leaders) const {
00936 PPL_ASSERT(!marked_empty() && marked_shortest_path_closed());
00937 PPL_ASSERT(leaders.size() == 0);
00938
00939 compute_predecessors(leaders);
00940
00941 PPL_ASSERT(leaders[0] == 0);
00942 for (dimension_type i = 1, l_size = leaders.size(); i != l_size; ++i) {
00943 const dimension_type l_i = leaders[i];
00944 PPL_ASSERT(l_i <= i);
00945 if (l_i != i) {
00946 const dimension_type ll_i = leaders[l_i];
00947 PPL_ASSERT(ll_i == leaders[ll_i]);
00948 leaders[i] = ll_i;
00949 }
00950 }
00951 }
00952
00953 template <typename T>
00954 bool
00955 BD_Shape<T>::is_shortest_path_reduced() const {
00956
00957 if (marked_empty())
00958 return true;
00959
00960 const dimension_type space_dim = space_dimension();
00961
00962 if (space_dim == 0)
00963 return true;
00964
00965
00966
00967
00968 if (!marked_shortest_path_reduced())
00969 return false;
00970
00971 const BD_Shape x_copy = *this;
00972 x_copy.shortest_path_closure_assign();
00973
00974 if (x_copy.marked_empty())
00975 return false;
00976
00977
00978 std::vector<dimension_type> leader(space_dim + 1);
00979
00980
00981 for (dimension_type i = space_dim + 1; i-- > 0; )
00982 leader[i] = i;
00983
00984
00985
00986
00987
00988 for (dimension_type i = 0; i < space_dim; ++i) {
00989 const DB_Row<N>& x_copy_dbm_i = x_copy.dbm[i];
00990 for (dimension_type j = i + 1; j <= space_dim; ++j)
00991 if (is_additive_inverse(x_copy.dbm[j][i], x_copy_dbm_i[j]))
00992
00993
00994 leader[j] = leader[i];
00995 }
00996
00997
00998
00999
01000
01001
01002 PPL_DIRTY_TEMP(N, c);
01003 for (dimension_type k = 0; k <= space_dim; ++k)
01004 if (leader[k] == k) {
01005 const DB_Row<N>& x_k = x_copy.dbm[k];
01006 for (dimension_type i = 0; i <= space_dim; ++i)
01007 if (leader[i] == i) {
01008 const DB_Row<N>& x_i = x_copy.dbm[i];
01009 const Bit_Row& redundancy_i = redundancy_dbm[i];
01010 const N& x_i_k = x_i[k];
01011 for (dimension_type j = 0; j <= space_dim; ++j)
01012 if (leader[j] == j) {
01013 const N& x_i_j = x_i[j];
01014 if (!is_plus_infinity(x_i_j)) {
01015 add_assign_r(c, x_i_k, x_k[j], ROUND_UP);
01016 if (x_i_j >= c && !redundancy_i[j])
01017 return false;
01018 }
01019 }
01020 }
01021 }
01022
01023
01024
01025
01026
01027 std::vector<dimension_type> var_conn(space_dim + 1);
01028 for (dimension_type i = space_dim + 1; i-- > 0; )
01029 var_conn[i] = space_dim + 1;
01030
01031
01032
01033
01034
01035
01036 for (dimension_type i = 0; i <= space_dim; ++i) {
01037
01038
01039 dimension_type t = 0;
01040 dimension_type ld_i = leader[i];
01041
01042 if (ld_i == i) {
01043 for (dimension_type j = 0; j <= space_dim; ++j) {
01044 dimension_type ld_j = leader[j];
01045
01046
01047 if (j != ld_j)
01048 if (!redundancy_dbm[i][j]) {
01049 if (t == 1)
01050
01051 return false;
01052 else
01053 if (ld_j != i)
01054
01055 return false;
01056 else {
01057 ++t;
01058 var_conn[i] = j;
01059 }
01060 }
01061 }
01062 }
01063
01064 else {
01065 for (dimension_type j = 0; j <= space_dim; ++j) {
01066 if (!redundancy_dbm[i][j]) {
01067 dimension_type ld_j = leader[j];
01068 if (ld_i != ld_j)
01069
01070 return false;
01071 else {
01072 if (t == 1)
01073
01074 return false;
01075 else {
01076 ++t;
01077 var_conn[i] = j;
01078 }
01079 }
01080
01081
01082 if (t == 0)
01083 return false;
01084 }
01085 }
01086 }
01087 }
01088
01089
01090
01091 std::vector<bool> just_checked(space_dim + 1);
01092 for (dimension_type i = space_dim + 1; i-- > 0; )
01093 just_checked[i] = false;
01094
01095
01096
01097 for (dimension_type i = 0; i <= space_dim; ++i) {
01098 bool jc_i = just_checked[i];
01099
01100 if (!jc_i) {
01101 dimension_type v_con = var_conn[i];
01102
01103
01104 if (v_con != space_dim + 1) {
01105
01106
01107 while (v_con != i) {
01108 just_checked[v_con] = true;
01109 v_con = var_conn[v_con];
01110
01111
01112 if (just_checked[v_con])
01113 return false;
01114 }
01115 }
01116 }
01117 just_checked[i] = true;
01118 }
01119
01120
01121 return true;
01122 }
01123
01124 template <typename T>
01125 bool
01126 BD_Shape<T>::bounds(const Linear_Expression& expr,
01127 const bool from_above) const {
01128
01129
01130 const dimension_type expr_space_dim = expr.space_dimension();
01131 const dimension_type space_dim = space_dimension();
01132 if (space_dim < expr_space_dim)
01133 throw_dimension_incompatible((from_above
01134 ? "bounds_from_above(e)"
01135 : "bounds_from_below(e)"), "e", expr);
01136
01137 shortest_path_closure_assign();
01138
01139 if (space_dim == 0 || marked_empty())
01140 return true;
01141
01142
01143
01144 const Constraint& c = from_above ? expr <= 0 : expr >= 0;
01145 const dimension_type c_space_dim = c.space_dimension();
01146 dimension_type num_vars = 0;
01147 dimension_type i = 0;
01148 dimension_type j = 0;
01149 PPL_DIRTY_TEMP_COEFFICIENT(coeff);
01150
01151 if (extract_bounded_difference(c, c_space_dim, num_vars, i, j, coeff)) {
01152 if (num_vars == 0)
01153
01154 return true;
01155
01156 const N& x = (coeff < 0) ? dbm[i][j] : dbm[j][i];
01157 return !is_plus_infinity(x);
01158 }
01159 else {
01160
01161 Optimization_Mode mode_bounds
01162 = from_above ? MAXIMIZATION : MINIMIZATION;
01163 MIP_Problem mip(space_dim, constraints(), expr, mode_bounds);
01164
01165 return mip.solve() == OPTIMIZED_MIP_PROBLEM;
01166 }
01167 }
01168
01169 template <typename T>
01170 bool
01171 BD_Shape<T>::max_min(const Linear_Expression& expr,
01172 const bool maximize,
01173 Coefficient& ext_n, Coefficient& ext_d,
01174 bool& included) const {
01175
01176
01177 const dimension_type space_dim = space_dimension();
01178 const dimension_type expr_space_dim = expr.space_dimension();
01179 if (space_dim < expr_space_dim)
01180 throw_dimension_incompatible((maximize
01181 ? "maximize(e, ...)"
01182 : "minimize(e, ...)"), "e", expr);
01183
01184 if (space_dim == 0) {
01185 if (marked_empty())
01186 return false;
01187 else {
01188 ext_n = expr.inhomogeneous_term();
01189 ext_d = 1;
01190 included = true;
01191 return true;
01192 }
01193 }
01194
01195 shortest_path_closure_assign();
01196
01197 if (marked_empty())
01198 return false;
01199
01200
01201
01202 const Constraint& c = maximize ? expr <= 0 : expr >= 0;
01203 const dimension_type c_space_dim = c.space_dimension();
01204 dimension_type num_vars = 0;
01205 dimension_type i = 0;
01206 dimension_type j = 0;
01207 PPL_DIRTY_TEMP_COEFFICIENT(coeff);
01208
01209 if (!extract_bounded_difference(c, c_space_dim, num_vars, i, j, coeff)) {
01210 Optimization_Mode mode_max_min
01211 = maximize ? MAXIMIZATION : MINIMIZATION;
01212 MIP_Problem mip(space_dim, constraints(), expr, mode_max_min);
01213 if (mip.solve() == OPTIMIZED_MIP_PROBLEM) {
01214 mip.optimal_value(ext_n, ext_d);
01215 included = true;
01216 return true;
01217 }
01218 else
01219
01220 return false;
01221 }
01222 else {
01223
01224 if (num_vars == 0) {
01225
01226 ext_n = expr.inhomogeneous_term();
01227 ext_d = 1;
01228 included = true;
01229 return true;
01230 }
01231
01232
01233 const N& x = (coeff < 0) ? dbm[i][j] : dbm[j][i];
01234 if (!is_plus_infinity(x)) {
01235
01236 PPL_DIRTY_TEMP(N, d);
01237 const Coefficient& b = expr.inhomogeneous_term();
01238 PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
01239 neg_assign(minus_b, b);
01240 const Coefficient& sc_b = maximize ? b : minus_b;
01241 assign_r(d, sc_b, ROUND_UP);
01242
01243
01244 PPL_DIRTY_TEMP(N, coeff_expr);
01245 const Coefficient& coeff_i = expr.coefficient(Variable(i-1));
01246 const int sign_i = sgn(coeff_i);
01247 if (sign_i > 0)
01248 assign_r(coeff_expr, coeff_i, ROUND_UP);
01249 else {
01250 PPL_DIRTY_TEMP_COEFFICIENT(minus_coeff_i);
01251 neg_assign(minus_coeff_i, coeff_i);
01252 assign_r(coeff_expr, minus_coeff_i, ROUND_UP);
01253 }
01254
01255 add_mul_assign_r(d, coeff_expr, x, ROUND_UP);
01256 numer_denom(d, ext_n, ext_d);
01257 if (!maximize)
01258 neg_assign(ext_n);
01259 included = true;
01260 return true;
01261 }
01262
01263
01264 return false;
01265 }
01266 }
01267
01268 template <typename T>
01269 bool
01270 BD_Shape<T>::max_min(const Linear_Expression& expr,
01271 const bool maximize,
01272 Coefficient& ext_n, Coefficient& ext_d,
01273 bool& included,
01274 Generator& g) const {
01275
01276
01277 const dimension_type space_dim = space_dimension();
01278 const dimension_type expr_space_dim = expr.space_dimension();
01279 if (space_dim < expr_space_dim)
01280 throw_dimension_incompatible((maximize
01281 ? "maximize(e, ...)"
01282 : "minimize(e, ...)"), "e", expr);
01283
01284 if (space_dim == 0) {
01285 if (marked_empty())
01286 return false;
01287 else {
01288 ext_n = expr.inhomogeneous_term();
01289 ext_d = 1;
01290 included = true;
01291 g = point();
01292 return true;
01293 }
01294 }
01295
01296 shortest_path_closure_assign();
01297
01298 if (marked_empty())
01299 return false;
01300
01301 Optimization_Mode mode_max_min
01302 = maximize ? MAXIMIZATION : MINIMIZATION;
01303 MIP_Problem mip(space_dim, constraints(), expr, mode_max_min);
01304 if (mip.solve() == OPTIMIZED_MIP_PROBLEM) {
01305 g = mip.optimizing_point();
01306 mip.evaluate_objective_function(g, ext_n, ext_d);
01307 included = true;
01308 return true;
01309 }
01310
01311 return false;
01312 }
01313
01314 template <typename T>
01315 Poly_Con_Relation
01316 BD_Shape<T>::relation_with(const Congruence& cg) const {
01317 const dimension_type space_dim = space_dimension();
01318
01319
01320 if (cg.space_dimension() > space_dim)
01321 throw_dimension_incompatible("relation_with(cg)", cg);
01322
01323
01324
01325 if (cg.is_equality()) {
01326 Constraint c(cg);
01327 return relation_with(c);
01328 }
01329
01330 shortest_path_closure_assign();
01331
01332 if (marked_empty())
01333 return Poly_Con_Relation::saturates()
01334 && Poly_Con_Relation::is_included()
01335 && Poly_Con_Relation::is_disjoint();
01336
01337 if (space_dim == 0) {
01338 if (cg.is_inconsistent())
01339 return Poly_Con_Relation::is_disjoint();
01340 else
01341 return Poly_Con_Relation::saturates()
01342 && Poly_Con_Relation::is_included();
01343 }
01344
01345
01346
01347 Linear_Expression le = Linear_Expression(cg);
01348 PPL_DIRTY_TEMP_COEFFICIENT(min_num);
01349 PPL_DIRTY_TEMP_COEFFICIENT(min_den);
01350 bool min_included;
01351 bool bounded_below = minimize(le, min_num, min_den, min_included);
01352
01353
01354
01355 if (!bounded_below)
01356 return Poly_Con_Relation::strictly_intersects();
01357
01358
01359
01360
01361
01362
01363
01364 PPL_DIRTY_TEMP_COEFFICIENT(max_num);
01365 PPL_DIRTY_TEMP_COEFFICIENT(max_den);
01366 bool max_included;
01367 bool bounded_above = maximize(le, max_num, max_den, max_included);
01368
01369
01370
01371 if (!bounded_above)
01372 return Poly_Con_Relation::strictly_intersects();
01373
01374 PPL_DIRTY_TEMP_COEFFICIENT(signed_distance);
01375
01376
01377
01378 PPL_DIRTY_TEMP_COEFFICIENT(min_value);
01379 min_value = min_num / min_den;
01380 const Coefficient& modulus = cg.modulus();
01381 signed_distance = min_value % modulus;
01382 min_value -= signed_distance;
01383 if (min_value * min_den < min_num)
01384 min_value += modulus;
01385
01386
01387
01388 PPL_DIRTY_TEMP_COEFFICIENT(max_value);
01389 max_value = max_num / max_den;
01390 signed_distance = max_value % modulus;
01391 max_value += signed_distance;
01392 if (max_value * max_den > max_num)
01393 max_value -= modulus;
01394
01395
01396
01397
01398 if (max_value < min_value)
01399 return Poly_Con_Relation::is_disjoint();
01400 else
01401 return Poly_Con_Relation::strictly_intersects();
01402 }
01403
01404
01405 template <typename T>
01406 Poly_Con_Relation
01407 BD_Shape<T>::relation_with(const Constraint& c) const {
01408 const dimension_type c_space_dim = c.space_dimension();
01409 const dimension_type space_dim = space_dimension();
01410
01411
01412 if (c_space_dim > space_dim)
01413 throw_dimension_incompatible("relation_with(c)", c);
01414
01415 shortest_path_closure_assign();
01416
01417 if (marked_empty())
01418 return Poly_Con_Relation::saturates()
01419 && Poly_Con_Relation::is_included()
01420 && Poly_Con_Relation::is_disjoint();
01421
01422 if (space_dim == 0) {
01423 if ((c.is_equality() && c.inhomogeneous_term() != 0)
01424 || (c.is_inequality() && c.inhomogeneous_term() < 0))
01425 return Poly_Con_Relation::is_disjoint();
01426 else if (c.is_strict_inequality() && c.inhomogeneous_term() == 0)
01427
01428
01429 return Poly_Con_Relation::saturates()
01430 && Poly_Con_Relation::is_disjoint();
01431 else if (c.is_equality() || c.inhomogeneous_term() == 0)
01432 return Poly_Con_Relation::saturates()
01433 && Poly_Con_Relation::is_included();
01434 else
01435
01436
01437
01438 return Poly_Con_Relation::is_included();
01439 }
01440
01441 dimension_type num_vars = 0;
01442 dimension_type i = 0;
01443 dimension_type j = 0;
01444 PPL_DIRTY_TEMP_COEFFICIENT(coeff);
01445 if (!extract_bounded_difference(c, c_space_dim, num_vars, i, j, coeff)) {
01446
01447
01448
01449
01450
01451
01452 Linear_Expression le;
01453 for (dimension_type k = c_space_dim; k-- > 0; ) {
01454 Variable vk(k);
01455 le += c.coefficient(vk) * vk;
01456 }
01457 PPL_DIRTY_TEMP(Coefficient, max_num);
01458 PPL_DIRTY_TEMP(Coefficient, max_den);
01459 bool max_included;
01460 PPL_DIRTY_TEMP(Coefficient, min_num);
01461 PPL_DIRTY_TEMP(Coefficient, min_den);
01462 bool min_included;
01463 bool bounded_above = maximize(le, max_num, max_den, max_included);
01464 bool bounded_below = minimize(le, min_num, min_den, min_included);
01465 if (!bounded_above) {
01466 if (!bounded_below)
01467 return Poly_Con_Relation::strictly_intersects();
01468 min_num += c.inhomogeneous_term() * min_den;
01469 switch (sgn(min_num)) {
01470 case 1:
01471 if (c.is_equality())
01472 return Poly_Con_Relation::is_disjoint();
01473 return Poly_Con_Relation::is_included();
01474 case 0:
01475 if (c.is_strict_inequality() || c.is_equality())
01476 return Poly_Con_Relation::strictly_intersects();
01477 return Poly_Con_Relation::is_included();
01478 case -1:
01479 return Poly_Con_Relation::strictly_intersects();
01480 }
01481 }
01482 if (!bounded_below) {
01483 max_num += c.inhomogeneous_term() * max_den;
01484 switch (sgn(max_num)) {
01485 case 1:
01486 return Poly_Con_Relation::strictly_intersects();
01487 case 0:
01488 if (c.is_strict_inequality())
01489 return Poly_Con_Relation::is_disjoint();
01490 return Poly_Con_Relation::strictly_intersects();
01491 case -1:
01492 return Poly_Con_Relation::is_disjoint();
01493 }
01494 }
01495 else {
01496 max_num += c.inhomogeneous_term() * max_den;
01497 min_num += c.inhomogeneous_term() * min_den;
01498 switch (sgn(max_num)) {
01499 case 1:
01500 switch (sgn(min_num)) {
01501 case 1:
01502 if (c.is_equality())
01503 return Poly_Con_Relation::is_disjoint();
01504 return Poly_Con_Relation::is_included();
01505 case 0:
01506 if (c.is_equality())
01507 return Poly_Con_Relation::strictly_intersects();
01508 if (c.is_strict_inequality())
01509 return Poly_Con_Relation::strictly_intersects();
01510 return Poly_Con_Relation::is_included();
01511 case -1:
01512 return Poly_Con_Relation::strictly_intersects();
01513 }
01514 case 0:
01515 if (min_num == 0) {
01516 if (c.is_strict_inequality())
01517 return Poly_Con_Relation::is_disjoint()
01518 && Poly_Con_Relation::saturates();
01519 return Poly_Con_Relation::is_included()
01520 && Poly_Con_Relation::saturates();
01521 }
01522 if (c.is_strict_inequality())
01523 return Poly_Con_Relation::is_disjoint();
01524 return Poly_Con_Relation::strictly_intersects();
01525 case -1:
01526 return Poly_Con_Relation::is_disjoint();
01527 }
01528 }
01529 }
01530
01531
01532 if (num_vars == 0) {
01533
01534 switch (sgn(c.inhomogeneous_term())) {
01535 case -1:
01536 return Poly_Con_Relation::is_disjoint();
01537 case 0:
01538 if (c.is_strict_inequality())
01539 return Poly_Con_Relation::saturates()
01540 && Poly_Con_Relation::is_disjoint();
01541 else
01542 return Poly_Con_Relation::saturates()
01543 && Poly_Con_Relation::is_included();
01544 case 1:
01545 if (c.is_equality())
01546 return Poly_Con_Relation::is_disjoint();
01547 else
01548 return Poly_Con_Relation::is_included();
01549 }
01550 }
01551
01552
01553
01554 const bool negative = (coeff < 0);
01555 const N& x = negative ? dbm[i][j] : dbm[j][i];
01556 const N& y = negative ? dbm[j][i] : dbm[i][j];
01557 if (negative)
01558 neg_assign(coeff);
01559
01560
01561
01562
01563
01564
01565
01566
01567 PPL_DIRTY_TEMP0(mpq_class, q_x);
01568 PPL_DIRTY_TEMP0(mpq_class, q_y);
01569 PPL_DIRTY_TEMP0(mpq_class, d);
01570 PPL_DIRTY_TEMP0(mpq_class, d1);
01571 PPL_DIRTY_TEMP0(mpq_class, c_den);
01572 PPL_DIRTY_TEMP0(mpq_class, q_den);
01573 assign_r(c_den, coeff, ROUND_NOT_NEEDED);
01574 assign_r(d, c.inhomogeneous_term(), ROUND_NOT_NEEDED);
01575 neg_assign_r(d1, d, ROUND_NOT_NEEDED);
01576 div_assign_r(d, d, c_den, ROUND_NOT_NEEDED);
01577 div_assign_r(d1, d1, c_den, ROUND_NOT_NEEDED);
01578
01579 if (is_plus_infinity(x)) {
01580 if (!is_plus_infinity(y)) {
01581
01582
01583
01584
01585
01586 PPL_DIRTY_TEMP_COEFFICIENT(numer);
01587 PPL_DIRTY_TEMP_COEFFICIENT(denom);
01588 numer_denom(y, numer, denom);
01589 assign_r(q_den, denom, ROUND_NOT_NEEDED);
01590 assign_r(q_y, numer, ROUND_NOT_NEEDED);
01591 div_assign_r(q_y, q_y, q_den, ROUND_NOT_NEEDED);
01592 if (q_y < d1)
01593 return Poly_Con_Relation::is_disjoint();
01594 if (q_y == d1 && c.is_strict_inequality())
01595 return Poly_Con_Relation::is_disjoint();
01596 }
01597
01598
01599 return Poly_Con_Relation::strictly_intersects();
01600 }
01601
01602
01603 PPL_DIRTY_TEMP_COEFFICIENT(numer);
01604 PPL_DIRTY_TEMP_COEFFICIENT(denom);
01605 numer_denom(x, numer, denom);
01606 assign_r(q_den, denom, ROUND_NOT_NEEDED);
01607 assign_r(q_x, numer, ROUND_NOT_NEEDED);
01608 div_assign_r(q_x, q_x, q_den, ROUND_NOT_NEEDED);
01609
01610 if (!is_plus_infinity(y)) {
01611 numer_denom(y, numer, denom);
01612 assign_r(q_den, denom, ROUND_NOT_NEEDED);
01613 assign_r(q_y, numer, ROUND_NOT_NEEDED);
01614 div_assign_r(q_y, q_y, q_den, ROUND_NOT_NEEDED);
01615 if (q_x == d && q_y == d1) {
01616 if (c.is_strict_inequality())
01617 return Poly_Con_Relation::saturates()
01618 && Poly_Con_Relation::is_disjoint();
01619 else
01620 return Poly_Con_Relation::saturates()
01621 && Poly_Con_Relation::is_included();
01622 }
01623
01624
01625
01626 if (q_y < d1)
01627 return Poly_Con_Relation::is_disjoint();
01628 if (q_y == d1 && c.is_strict_inequality())
01629 return Poly_Con_Relation::is_disjoint();
01630 }
01631
01632
01633
01634
01635 if (d > q_x) {
01636 if (c.is_equality())
01637 return Poly_Con_Relation::is_disjoint();
01638 else
01639 return Poly_Con_Relation::is_included();
01640 }
01641
01642 if (d == q_x && c.is_nonstrict_inequality())
01643 return Poly_Con_Relation::is_included();
01644
01645
01646 return Poly_Con_Relation::strictly_intersects();
01647 }
01648
01649 template <typename T>
01650 Poly_Gen_Relation
01651 BD_Shape<T>::relation_with(const Generator& g) const {
01652 const dimension_type space_dim = space_dimension();
01653 const dimension_type g_space_dim = g.space_dimension();
01654
01655
01656 if (space_dim < g_space_dim)
01657 throw_dimension_incompatible("relation_with(g)", g);
01658
01659 shortest_path_closure_assign();
01660
01661 if (marked_empty())
01662 return Poly_Gen_Relation::nothing();
01663
01664
01665
01666 if (space_dim == 0)
01667 return Poly_Gen_Relation::subsumes();
01668
01669 const bool is_line = g.is_line();
01670 const bool is_line_or_ray = g.is_line_or_ray();
01671
01672
01673
01674
01675
01676
01677
01678
01679 PPL_DIRTY_TEMP_COEFFICIENT(num);
01680 PPL_DIRTY_TEMP_COEFFICIENT(den);
01681 PPL_DIRTY_TEMP_COEFFICIENT(product);
01682
01683 for (dimension_type i = 0; i <= space_dim; ++i) {
01684 const Coefficient& g_coeff_y = (i > g_space_dim || i == 0)
01685 ? Coefficient_zero() : g.coefficient(Variable(i-1));
01686 const DB_Row<N>& dbm_i = dbm[i];
01687 for (dimension_type j = i + 1; j <= space_dim; ++j) {
01688 const Coefficient& g_coeff_x = (j > g_space_dim)
01689 ? Coefficient_zero() : g.coefficient(Variable(j-1));
01690 const N& dbm_ij = dbm_i[j];
01691 const N& dbm_ji = dbm[j][i];
01692 if (is_additive_inverse(dbm_ji, dbm_ij)) {
01693
01694
01695 numer_denom(dbm_ij, num, den);
01696 product = 0;
01697 add_mul_assign(product, den, g_coeff_y);
01698 add_mul_assign(product, -den, g_coeff_x);
01699 if (!is_line_or_ray)
01700 add_mul_assign(product, num, g.divisor());
01701 if (product != 0)
01702 return Poly_Gen_Relation::nothing();
01703 }
01704 else {
01705
01706 if (!is_plus_infinity(dbm_ij)) {
01707
01708
01709 numer_denom(dbm_ij, num, den);
01710 product = 0;
01711 add_mul_assign(product, den, g_coeff_y);
01712 add_mul_assign(product, -den, g_coeff_x);
01713 if (!is_line_or_ray)
01714 add_mul_assign(product, num, g.divisor());
01715 if (is_line) {
01716 if (product != 0)
01717
01718 return Poly_Gen_Relation::nothing();
01719 }
01720 else
01721
01722 if (product < 0)
01723 return Poly_Gen_Relation::nothing();
01724 }
01725
01726 if (!is_plus_infinity(dbm_ji)) {
01727
01728
01729 numer_denom(dbm_ji, num, den);
01730 product = 0;
01731 add_mul_assign(product, den, g_coeff_x);
01732 add_mul_assign(product, -den, g_coeff_y);
01733 if (!is_line_or_ray)
01734 add_mul_assign(product, num, g.divisor());
01735 if (is_line) {
01736 if (product != 0)
01737
01738 return Poly_Gen_Relation::nothing();
01739 }
01740 else
01741
01742 if (product < 0)
01743 return Poly_Gen_Relation::nothing();
01744 }
01745 }
01746 }
01747 }
01748
01749
01750 return Poly_Gen_Relation::subsumes();
01751 }
01752
01753 template <typename T>
01754 void
01755 BD_Shape<T>::shortest_path_closure_assign() const {
01756
01757 if (marked_empty() || marked_shortest_path_closed())
01758 return;
01759 const dimension_type num_dimensions = space_dimension();
01760
01761 if (num_dimensions == 0)
01762 return;
01763
01764
01765
01766 BD_Shape& x = const_cast<BD_Shape<T>&>(*this);
01767
01768
01769 for (dimension_type h = num_dimensions + 1; h-- > 0; ) {
01770 PPL_ASSERT(is_plus_infinity(x.dbm[h][h]));
01771 assign_r(x.dbm[h][h], 0, ROUND_NOT_NEEDED);
01772 }
01773
01774 PPL_DIRTY_TEMP(N, sum);
01775 for (dimension_type k = num_dimensions + 1; k-- > 0; ) {
01776 const DB_Row<N>& x_dbm_k = x.dbm[k];
01777 for (dimension_type i = num_dimensions + 1; i-- > 0; ) {
01778 DB_Row<N>& x_dbm_i = x.dbm[i];
01779 const N& x_dbm_i_k = x_dbm_i[k];
01780 if (!is_plus_infinity(x_dbm_i_k))
01781 for (dimension_type j = num_dimensions + 1; j-- > 0; ) {
01782 const N& x_dbm_k_j = x_dbm_k[j];
01783 if (!is_plus_infinity(x_dbm_k_j)) {
01784
01785 add_assign_r(sum, x_dbm_i_k, x_dbm_k_j, ROUND_UP);
01786 min_assign(x_dbm_i[j], sum);
01787 }
01788 }
01789 }
01790 }
01791
01792
01793
01794 for (dimension_type h = num_dimensions + 1; h-- > 0; ) {
01795 N& x_dbm_hh = x.dbm[h][h];
01796 if (sgn(x_dbm_hh) < 0) {
01797 x.set_empty();
01798 return;
01799 }
01800 else {
01801 PPL_ASSERT(sgn(x_dbm_hh) == 0);
01802
01803 assign_r(x_dbm_hh, PLUS_INFINITY, ROUND_NOT_NEEDED);
01804 }
01805 }
01806
01807
01808 x.set_shortest_path_closed();
01809 }
01810
01811 template <typename T>
01812 void
01813 BD_Shape<T>::incremental_shortest_path_closure_assign(Variable var) const {
01814
01815 if (marked_empty() || marked_shortest_path_closed())
01816 return;
01817 const dimension_type num_dimensions = space_dimension();
01818 PPL_ASSERT(var.id() < num_dimensions);
01819
01820
01821
01822 BD_Shape& x = const_cast<BD_Shape&>(*this);
01823
01824
01825 for (dimension_type h = num_dimensions + 1; h-- > 0; ) {
01826 PPL_ASSERT(is_plus_infinity(x.dbm[h][h]));
01827 assign_r(x.dbm[h][h], 0, ROUND_NOT_NEEDED);
01828 }
01829
01830
01831 PPL_DIRTY_TEMP(N, sum);
01832 const dimension_type v = var.id() + 1;
01833 DB_Row<N>& x_v = x.dbm[v];
01834
01835 for (dimension_type k = num_dimensions + 1; k-- > 0; ) {
01836 DB_Row<N>& x_k = x.dbm[k];
01837 const N& x_v_k = x_v[k];
01838 const N& x_k_v = x_k[v];
01839 const bool x_v_k_finite = !is_plus_infinity(x_v_k);
01840 const bool x_k_v_finite = !is_plus_infinity(x_k_v);
01841
01842 if (x_v_k_finite) {
01843 if (x_k_v_finite) {
01844
01845 for (dimension_type i = num_dimensions + 1; i-- > 0; ) {
01846 DB_Row<N>& x_i = x.dbm[i];
01847 const N& x_i_k = x_i[k];
01848 if (!is_plus_infinity(x_i_k)) {
01849 add_assign_r(sum, x_i_k, x_k_v, ROUND_UP);
01850 min_assign(x_i[v], sum);
01851 }
01852 const N& x_k_i = x_k[i];
01853 if (!is_plus_infinity(x_k_i)) {
01854 add_assign_r(sum, x_v_k, x_k_i, ROUND_UP);
01855 min_assign(x_v[i], sum);
01856 }
01857 }
01858 }
01859 else {
01860
01861 for (dimension_type i = num_dimensions + 1; i-- > 0; ) {
01862 const N& x_k_i = x_k[i];
01863 if (!is_plus_infinity(x_k_i)) {
01864 add_assign_r(sum, x_v_k, x_k_i, ROUND_UP);
01865 min_assign(x_v[i], sum);
01866 }
01867 }
01868 }
01869 }
01870 else if (x_k_v_finite) {
01871
01872 for (dimension_type i = num_dimensions + 1; i-- > 0; ) {
01873 DB_Row<N>& x_i = x.dbm[i];
01874 const N& x_i_k = x_i[k];
01875 if (!is_plus_infinity(x_i_k)) {
01876 add_assign_r(sum, x_i_k, x_k_v, ROUND_UP);
01877 min_assign(x_i[v], sum);
01878 }
01879 }
01880 }
01881 else
01882
01883 continue;
01884 }
01885
01886
01887
01888 for (dimension_type i = num_dimensions + 1; i-- > 0; ) {
01889 DB_Row<N>& x_i = x.dbm[i];
01890 const N& x_i_v = x_i[v];
01891 if (!is_plus_infinity(x_i_v)) {
01892 for (dimension_type j = num_dimensions + 1; j-- > 0; ) {
01893 const N& x_v_j = x_v[j];
01894 if (!is_plus_infinity(x_v_j)) {
01895 add_assign_r(sum, x_i_v, x_v_j, ROUND_UP);
01896 min_assign(x_i[j], sum);
01897 }
01898 }
01899 }
01900 }
01901
01902
01903
01904 for (dimension_type h = num_dimensions + 1; h-- > 0; ) {
01905 N& x_dbm_hh = x.dbm[h][h];
01906 if (sgn(x_dbm_hh) < 0) {
01907 x.set_empty();
01908 return;
01909 }
01910 else {
01911 PPL_ASSERT(sgn(x_dbm_hh) == 0);
01912
01913 assign_r(x_dbm_hh, PLUS_INFINITY, ROUND_NOT_NEEDED);
01914 }
01915 }
01916
01917
01918 x.set_shortest_path_closed();
01919 }
01920
01921 template <typename T>
01922 void
01923 BD_Shape<T>::shortest_path_reduction_assign() const {
01924
01925 if (marked_shortest_path_reduced())
01926 return;
01927
01928 const dimension_type space_dim = space_dimension();
01929
01930 if (space_dim == 0)
01931 return;
01932
01933
01934 shortest_path_closure_assign();
01935
01936
01937 if (marked_empty())
01938 return;
01939
01940
01941
01942
01943
01944 std::vector<dimension_type> predecessor;
01945 compute_predecessors(predecessor);
01946 std::vector<dimension_type> leaders;
01947 compute_leader_indices(predecessor, leaders);
01948 const dimension_type num_leaders = leaders.size();
01949
01950 Bit_Matrix redundancy(space_dim + 1, space_dim + 1);
01951
01952
01953 Bit_Row& red_0 = redundancy[0];
01954 for (dimension_type j = space_dim + 1; j-- > 0; )
01955 red_0.set(j);
01956 for (dimension_type i = space_dim + 1; i-- > 0; )
01957 redundancy[i] = red_0;
01958
01959
01960
01961 PPL_DIRTY_TEMP(N, c);
01962 for (dimension_type l_i = 0; l_i < num_leaders; ++l_i) {
01963 const dimension_type i = leaders[l_i];
01964 const DB_Row<N>& dbm_i = dbm[i];
01965 Bit_Row& redundancy_i = redundancy[i];
01966 for (dimension_type l_j = 0; l_j < num_leaders; ++l_j) {
01967 const dimension_type j = leaders[l_j];
01968 if (redundancy_i[j]) {
01969 const N& dbm_i_j = dbm_i[j];
01970 redundancy_i.clear(j);
01971 for (dimension_type l_k = 0; l_k < num_leaders; ++l_k) {
01972 const dimension_type k = leaders[l_k];
01973 add_assign_r(c, dbm_i[k], dbm[k][j], ROUND_UP);
01974 if (dbm_i_j >= c) {
01975 redundancy_i.set(j);
01976 break;
01977 }
01978 }
01979 }
01980 }
01981 }
01982
01983
01984
01985
01986 std::deque<bool> dealt_with(space_dim + 1, false);
01987 for (dimension_type i = space_dim + 1; i-- > 0; )
01988
01989
01990 if (i != predecessor[i] && !dealt_with[i]) {
01991 dimension_type j = i;
01992 while (true) {
01993 const dimension_type pred_j = predecessor[j];
01994 if (j == pred_j) {
01995
01996 PPL_ASSERT(redundancy[i][j]);
01997 redundancy[i].clear(j);
01998
01999
02000 break;
02001 }
02002
02003 PPL_ASSERT(redundancy[pred_j][j]);
02004 redundancy[pred_j].clear(j);
02005 dealt_with[pred_j] = true;
02006 j = pred_j;
02007 }
02008 }
02009
02010
02011
02012 BD_Shape<T>& x = const_cast<BD_Shape<T>&>(*this);
02013 std::swap(x.redundancy_dbm, redundancy);
02014 x.set_shortest_path_reduced();
02015
02016 PPL_ASSERT(is_shortest_path_reduced());
02017 }
02018
02019 template <typename T>
02020 void
02021 BD_Shape<T>::upper_bound_assign(const BD_Shape& y) {
02022 const dimension_type space_dim = space_dimension();
02023
02024
02025 if (space_dim != y.space_dimension())
02026 throw_dimension_incompatible("upper_bound_assign(y)", y);
02027
02028
02029 y.shortest_path_closure_assign();
02030 if (y.marked_empty())
02031 return;
02032 shortest_path_closure_assign();
02033 if (marked_empty()) {
02034 *this = y;
02035 return;
02036 }
02037
02038
02039
02040 PPL_ASSERT(space_dim == 0 || marked_shortest_path_closed());
02041 for (dimension_type i = space_dim + 1; i-- > 0; ) {
02042 DB_Row<N>& dbm_i = dbm[i];
02043 const DB_Row<N>& y_dbm_i = y.dbm[i];
02044 for (dimension_type j = space_dim + 1; j-- > 0; ) {
02045 N& dbm_ij = dbm_i[j];
02046 const N& y_dbm_ij = y_dbm_i[j];
02047 if (dbm_ij < y_dbm_ij)
02048 dbm_ij = y_dbm_ij;
02049 }
02050 }
02051
02052
02053 if (marked_shortest_path_reduced())
02054 reset_shortest_path_reduced();
02055 PPL_ASSERT(OK());
02056 }
02057
02058 template <typename T>
02059 bool
02060 BD_Shape<T>::BFT00_upper_bound_assign_if_exact(const BD_Shape& y) {
02061
02062 const BD_Shape& x = *this;
02063 const dimension_type x_space_dim = x.space_dimension();
02064
02065
02066 PPL_ASSERT(x_space_dim == y.space_dimension());
02067
02068
02069 if (x_space_dim == 0) {
02070 upper_bound_assign(y);
02071 return true;
02072 }
02073
02074 if (x.marked_empty()) {
02075 *this = y;
02076 return true;
02077 }
02078 else if (y.is_empty())
02079 return true;
02080 else if (x.is_empty()) {
02081 *this = y;
02082 return true;
02083 }
02084
02085
02086
02087
02088
02089 Variable eps(x_space_dim);
02090 Linear_Expression zero_expr = 0*eps;
02091 Linear_Expression db_expr;
02092 PPL_DIRTY_TEMP_COEFFICIENT(num);
02093 PPL_DIRTY_TEMP_COEFFICIENT(den);
02094
02095
02096
02097
02098
02099 Constraint_System env_cs;
02100 Constraint_System x_cs_removed;
02101 Constraint_System y_cs_removed;
02102 x.shortest_path_reduction_assign();
02103 y.shortest_path_reduction_assign();
02104 for (dimension_type i = x_space_dim + 1; i-- > 0; ) {
02105 const Bit_Row& x_red_i = x.redundancy_dbm[i];
02106 const Bit_Row& y_red_i = y.redundancy_dbm[i];
02107 const DB_Row<N>& x_dbm_i = x.dbm[i];
02108 const DB_Row<N>& y_dbm_i = y.dbm[i];
02109 for (dimension_type j = x_space_dim + 1; j-- > 0; ) {
02110 if (x_red_i[j] && y_red_i[j])
02111 continue;
02112 if (!x_red_i[j]) {
02113 const N& x_dbm_ij = x_dbm_i[j];
02114 PPL_ASSERT(!is_plus_infinity(x_dbm_ij));
02115 numer_denom(x_dbm_ij, num, den);
02116
02117 db_expr = zero_expr;
02118 if (i > 0)
02119 db_expr += Variable(i-1);
02120 if (j > 0)
02121 db_expr -= Variable(j-1);
02122 if (den != 1)
02123 db_expr *= den;
02124 db_expr += num;
02125 if (x_dbm_ij >= y_dbm_i[j])
02126 env_cs.insert(db_expr >= 0);
02127 else {
02128 db_expr += eps;
02129 x_cs_removed.insert(db_expr == 0);
02130 }
02131 }
02132 if (!y_red_i[j]) {
02133 const N& y_dbm_ij = y_dbm_i[j];
02134 const N& x_dbm_ij = x_dbm_i[j];
02135 PPL_ASSERT(!is_plus_infinity(y_dbm_ij));
02136 numer_denom(y_dbm_ij, num, den);
02137
02138 db_expr = zero_expr;
02139 if (i > 0)
02140 db_expr += Variable(i-1);
02141 if (j > 0)
02142 db_expr -= Variable(j-1);
02143 if (den != 1)
02144 db_expr *= den;
02145 db_expr += num;
02146 if (y_dbm_ij >= x_dbm_ij) {
02147
02148 if (!x_red_i[j] && x_dbm_ij == y_dbm_ij)
02149 continue;
02150 env_cs.insert(db_expr >= 0);
02151 }
02152 else {
02153 db_expr += eps;
02154 y_cs_removed.insert(db_expr == 0);
02155 }
02156 }
02157 }
02158 }
02159
02160 if (x_cs_removed.empty())
02161
02162 return true;
02163 if (y_cs_removed.empty()) {
02164
02165 *this = y;
02166 return true;
02167 }
02168
02169
02170
02171
02172 MIP_Problem env_lp(x_space_dim + 1, env_cs, eps, MAXIMIZATION);
02173
02174 env_lp.solve();
02175 PPL_ASSERT(env_lp.solve() != UNFEASIBLE_MIP_PROBLEM);
02176
02177
02178 for (Constraint_System::const_iterator i = x_cs_removed.begin(),
02179 i_end = x_cs_removed.end(); i != i_end; ++i) {
02180 MIP_Problem lp_i(env_lp);
02181 lp_i.add_constraint(*i);
02182
02183 if (lp_i.solve() == UNFEASIBLE_MIP_PROBLEM)
02184 continue;
02185 for (Constraint_System::const_iterator j = y_cs_removed.begin(),
02186 j_end = y_cs_removed.end(); j != j_end; ++j) {
02187 MIP_Problem lp_ij(lp_i);
02188 lp_ij.add_constraint(*j);
02189
02190 switch (lp_ij.solve()) {
02191 case UNFEASIBLE_MIP_PROBLEM:
02192
02193 throw std::runtime_error("PPL internal error");
02194 case UNBOUNDED_MIP_PROBLEM:
02195 return false;
02196 case OPTIMIZED_MIP_PROBLEM:
02197 lp_ij.optimal_value(num, den);
02198 if (num > 0)
02199 return false;
02200 break;
02201 }
02202 }
02203 }
02204
02205
02206 upper_bound_assign(y);
02207 PPL_ASSERT(OK());
02208 return true;
02209 }
02210
02211 template <typename T>
02212 template <bool integer_upper_bound>
02213 bool
02214 BD_Shape<T>::BHZ09_upper_bound_assign_if_exact(const BD_Shape& y) {
02215 PPL_COMPILE_TIME_CHECK(!integer_upper_bound
02216 || std::numeric_limits<T>::is_integer,
02217 "BD_Shape<T>::BHZ09_upper_bound_assign_if_exact(y):"
02218 " instantiating for integer upper bound,"
02219 " but T in not an integer datatype.");
02220
02221
02222
02223 const BD_Shape& x = *this;
02224 const dimension_type x_space_dim = x.space_dimension();
02225
02226
02227 PPL_ASSERT(x_space_dim == y.space_dimension());
02228
02229
02230 if (x_space_dim == 0) {
02231 upper_bound_assign(y);
02232 return true;
02233 }
02234
02235 if (x.marked_empty()) {
02236 *this = y;
02237 return true;
02238 }
02239 else if (y.is_empty())
02240 return true;
02241 else if (x.is_empty()) {
02242 *this = y;
02243 return true;
02244 }
02245
02246
02247 x.shortest_path_reduction_assign();
02248 y.shortest_path_reduction_assign();
02249 PPL_ASSERT(x.marked_shortest_path_closed());
02250 PPL_ASSERT(y.marked_shortest_path_closed());
02251
02252 BD_Shape<T> ub(x);
02253 ub.upper_bound_assign(y);
02254
02255 PPL_DIRTY_TEMP(N, lhs);
02256 PPL_DIRTY_TEMP(N, rhs);
02257 PPL_DIRTY_TEMP(N, temp_zero);
02258 assign_r(temp_zero, 0, ROUND_NOT_NEEDED);
02259 PPL_DIRTY_TEMP(N, temp_one);
02260 if (integer_upper_bound)
02261 assign_r(temp_one, 1, ROUND_NOT_NEEDED);
02262
02263 for (dimension_type i = x_space_dim + 1; i-- > 0; ) {
02264 const DB_Row<N>& x_i = x.dbm[i];
02265 const Bit_Row& x_red_i = x.redundancy_dbm[i];
02266 const DB_Row<N>& y_i = y.dbm[i];
02267 const DB_Row<N>& ub_i = ub.dbm[i];
02268 for (dimension_type j = x_space_dim + 1; j-- > 0; ) {
02269
02270 if (x_red_i[j])
02271 continue;
02272
02273 PPL_ASSERT(i != j);
02274 const N& x_i_j = x_i[j];
02275 if (x_i_j < y_i[j]) {
02276 for (dimension_type k = x_space_dim + 1; k-- > 0; ) {
02277 const DB_Row<N>& x_k = x.dbm[k];
02278 const DB_Row<N>& y_k = y.dbm[k];
02279 const Bit_Row& y_red_k = y.redundancy_dbm[k];
02280 const DB_Row<N>& ub_k = ub.dbm[k];
02281 const N& ub_k_j = (k == j) ? temp_zero : ub_k[j];
02282 for (dimension_type ell = x_space_dim + 1; ell-- > 0; ) {
02283
02284 if (y_red_k[ell])
02285 continue;
02286
02287 PPL_ASSERT(k != ell);
02288 const N& y_k_ell = y_k[ell];
02289 if (y_k_ell < x_k[ell]) {
02290
02291
02292 add_assign_r(lhs, x_i_j, y_k_ell, ROUND_UP);
02293 const N& ub_i_ell = (i == ell) ? temp_zero : ub_i[ell];
02294 add_assign_r(rhs, ub_i_ell, ub_k_j, ROUND_UP);
02295 if (integer_upper_bound) {
02296
02297
02298 add_assign_r(lhs, lhs, temp_one, ROUND_NOT_NEEDED);
02299 }
02300
02301 if (lhs < rhs)
02302 return false;
02303 }
02304 }
02305 }
02306 }
02307 }
02308 }
02309
02310 swap(ub);
02311 PPL_ASSERT(OK());
02312 return true;
02313 }
02314
02315 template <typename T>
02316 void
02317 BD_Shape<T>::difference_assign(const BD_Shape& y) {
02318 const dimension_type space_dim = space_dimension();
02319
02320
02321 if (space_dim != y.space_dimension())
02322 throw_dimension_incompatible("difference_assign(y)", y);
02323
02324 BD_Shape new_bd_shape(space_dim, EMPTY);
02325
02326 BD_Shape& x = *this;
02327
02328 x.shortest_path_closure_assign();
02329
02330
02331 if (x.marked_empty())
02332 return;
02333 y.shortest_path_closure_assign();
02334
02335
02336 if (y.marked_empty())
02337 return;
02338
02339
02340
02341
02342 if (space_dim == 0) {
02343 x.set_empty();
02344 return;
02345 }
02346
02347
02348
02349 if (y.contains(x)) {
02350 x.set_empty();
02351 return;
02352 }
02353
02354
02355
02356
02357 const Constraint_System& y_cs = y.constraints();
02358 for (Constraint_System::const_iterator i = y_cs.begin(),
02359 y_cs_end = y_cs.end(); i != y_cs_end; ++i) {
02360 const Constraint& c = *i;
02361
02362
02363
02364
02365
02366
02367 if (x.relation_with(c).implies(Poly_Con_Relation::is_included()))
02368 continue;
02369 BD_Shape z = x;
02370 const Linear_Expression e = Linear_Expression(c);
02371 z.add_constraint(e <= 0);
02372 if (!z.is_empty())
02373 new_bd_shape.upper_bound_assign(z);
02374 if (c.is_equality()) {
02375 z = x;
02376 z.add_constraint(e >= 0);
02377 if (!z.is_empty())
02378 new_bd_shape.upper_bound_assign(z);
02379 }
02380 }
02381 *this = new_bd_shape;
02382 PPL_ASSERT(OK());
02383 }
02384
02385 template <typename T>
02386 bool
02387 BD_Shape<T>::simplify_using_context_assign(const BD_Shape& y) {
02388 BD_Shape& x = *this;
02389 const dimension_type dim = x.space_dimension();
02390
02391 if (dim != y.space_dimension())
02392 throw_dimension_incompatible("simplify_using_context_assign(y)", y);
02393
02394
02395 if (dim == 0) {
02396 if (y.marked_empty()) {
02397 x.set_zero_dim_univ();
02398 return false;
02399 }
02400 else
02401 return !x.marked_empty();
02402 }
02403
02404
02405
02406 y.shortest_path_closure_assign();
02407 if (x.contains(y)) {
02408 BD_Shape<T> res(dim, UNIVERSE);
02409 x.swap(res);
02410 return false;
02411 }
02412
02413
02414 x.shortest_path_closure_assign();
02415 if (x.marked_empty()) {
02416
02417 dimension_type i;
02418 dimension_type j;
02419
02420 i = 0;
02421 const DB_Row<N>& y_dbm_0 = y.dbm[0];
02422 for (j = 1; j <= dim; ++j) {
02423 if (!is_plus_infinity(y_dbm_0[j]))
02424
02425
02426
02427 goto found;
02428 }
02429 j = 0;
02430 for (i = 1; i <= dim; ++i) {
02431 if (!is_plus_infinity(y.dbm[i][0]))
02432
02433
02434
02435 goto found;
02436 }
02437
02438 for (i = 1; i <= dim; ++i) {
02439 const DB_Row<N>& y_dbm_i = y.dbm[i];
02440 for (j = 1; j <= dim; ++j)
02441 if (!is_plus_infinity(y_dbm_i[j]))
02442
02443
02444
02445 goto found;
02446 }
02447
02448
02449 return false;
02450
02451 found:
02452
02453 PPL_ASSERT(i <= dim && j <= dim && (i > 0 || j > 0));
02454 BD_Shape<T> res(dim, UNIVERSE);
02455 PPL_DIRTY_TEMP(N, tmp);
02456 assign_r(tmp, 1, ROUND_UP);
02457 add_assign_r(tmp, tmp, y.dbm[i][j], ROUND_UP);
02458 PPL_ASSERT(!is_plus_infinity(tmp));
02459
02460 neg_assign_r(res.dbm[j][i], tmp, ROUND_DOWN);
02461 x.swap(res);
02462 return false;
02463 }
02464
02465
02466
02467
02468 BD_Shape<T> target = x;
02469 target.intersection_assign(y);
02470 const bool bool_result = !target.is_empty();
02471
02472
02473 x.shortest_path_reduction_assign();
02474
02475 dimension_type x_num_nonredundant = (dim+1)*(dim+1);
02476 for (dimension_type i = dim + 1; i-- > 0; )
02477 x_num_nonredundant -= x.redundancy_dbm[i].count_ones();
02478 PPL_ASSERT(x_num_nonredundant > 0);
02479
02480
02481
02482
02483 BD_Shape<T> yy = y;
02484
02485
02486 BD_Shape<T> res(dim, UNIVERSE);
02487
02488 dimension_type res_num_nonredundant = 0;
02489
02490
02491 std::vector<dimension_type> x_leaders;
02492 x.compute_leaders(x_leaders);
02493
02494
02495 const DB_Row<N>& x_dbm_0 = x.dbm[0];
02496 DB_Row<N>& yy_dbm_0 = yy.dbm[0];
02497 DB_Row<N>& res_dbm_0 = res.dbm[0];
02498 for (dimension_type j = 1; j <= dim; ++j) {
02499
02500
02501 if (x_leaders[j] != 0)
02502 continue;
02503 PPL_ASSERT(!is_plus_infinity(x_dbm_0[j]));
02504 if (x_dbm_0[j] < yy_dbm_0[j]) {
02505 res_dbm_0[j] = x_dbm_0[j];
02506 ++res_num_nonredundant;
02507
02508 yy_dbm_0[j] = x_dbm_0[j];
02509 yy.reset_shortest_path_closed();
02510 }
02511 PPL_ASSERT(!is_plus_infinity(x.dbm[j][0]));
02512 if (x.dbm[j][0] < yy.dbm[j][0]) {
02513 res.dbm[j][0] = x.dbm[j][0];
02514 ++res_num_nonredundant;
02515
02516 yy.dbm[j][0] = x.dbm[j][0];
02517 yy.reset_shortest_path_closed();
02518 }
02519
02520 if (!yy.marked_shortest_path_closed()) {
02521 Variable var_j(j-1);
02522 yy.incremental_shortest_path_closure_assign(var_j);
02523 if (target.contains(yy)) {
02524
02525 if (res_num_nonredundant < x_num_nonredundant) {
02526 res.reset_shortest_path_closed();
02527 x.swap(res);
02528 }
02529 return bool_result;
02530 }
02531 }
02532 }
02533
02534
02535
02536 for (dimension_type i = 2; i <= dim; ++i) {
02537 const dimension_type j = x_leaders[i];
02538 if (j == i || j == 0)
02539 continue;
02540 PPL_ASSERT(!is_plus_infinity(x.dbm[i][j]));
02541 if (x.dbm[i][j] < yy.dbm[i][j]) {
02542 res.dbm[i][j] = x.dbm[i][j];
02543 ++res_num_nonredundant;
02544
02545 yy.dbm[i][j] = x.dbm[i][j];
02546 yy.reset_shortest_path_closed();
02547 }
02548 PPL_ASSERT(!is_plus_infinity(x.dbm[j][i]));
02549 if (x.dbm[j][i] < yy.dbm[j][i]) {
02550 res.dbm[j][i] = x.dbm[j][i];
02551 ++res_num_nonredundant;
02552
02553 yy.dbm[j][i] = x.dbm[j][i];
02554 yy.reset_shortest_path_closed();
02555 }
02556
02557 if (!yy.marked_shortest_path_closed()) {
02558 Variable var_j(j-1);
02559 yy.incremental_shortest_path_closure_assign(var_j);
02560 if (target.contains(yy)) {
02561
02562 if (res_num_nonredundant < x_num_nonredundant) {
02563 res.reset_shortest_path_closed();
02564 x.swap(res);
02565 }
02566 return bool_result;
02567 }
02568 }
02569 }
02570
02571
02572
02573 for (dimension_type i = 0; i <= dim; ++i) {
02574 if (i != x_leaders[i])
02575 continue;
02576 const DB_Row<N>& x_dbm_i = x.dbm[i];
02577 const Bit_Row& x_redundancy_dbm_i = x.redundancy_dbm[i];
02578 DB_Row<N>& yy_dbm_i = yy.dbm[i];
02579 DB_Row<N>& res_dbm_i = res.dbm[i];
02580 for (dimension_type j = 0; j <= dim; ++j) {
02581 if (j != x_leaders[j] || x_redundancy_dbm_i[j])
02582 continue;
02583 N& yy_dbm_ij = yy_dbm_i[j];
02584 const N& x_dbm_ij = x_dbm_i[j];
02585 if (x_dbm_ij < yy_dbm_ij) {
02586 res_dbm_i[j] = x_dbm_ij;
02587 ++res_num_nonredundant;
02588
02589 yy_dbm_ij = x_dbm_ij;
02590 yy.reset_shortest_path_closed();
02591 PPL_ASSERT(i > 0 || j > 0);
02592 Variable var((i > 0 ? i : j) - 1);
02593 yy.incremental_shortest_path_closure_assign(var);
02594 if (target.contains(yy)) {
02595
02596 if (res_num_nonredundant < x_num_nonredundant) {
02597 res.reset_shortest_path_closed();
02598 x.swap(res);
02599 }
02600 return bool_result;
02601 }
02602 }
02603 }
02604 }
02605
02606 throw std::runtime_error("PPL internal error");
02607 }
02608
02609 template <typename T>
02610 void
02611 BD_Shape<T>::add_space_dimensions_and_embed(const dimension_type m) {
02612
02613 if (m == 0)
02614 return;
02615
02616 const dimension_type space_dim = space_dimension();
02617 const dimension_type new_space_dim = space_dim + m;
02618 const bool was_zero_dim_univ = (!marked_empty() && space_dim == 0);
02619
02620
02621
02622
02623 dbm.grow(new_space_dim + 1);
02624
02625
02626
02627 if (marked_shortest_path_reduced())
02628 reset_shortest_path_reduced();
02629
02630
02631
02632 if (was_zero_dim_univ)
02633 set_shortest_path_closed();
02634
02635 PPL_ASSERT(OK());
02636 }
02637
02638 template <typename T>
02639 void
02640 BD_Shape<T>::add_space_dimensions_and_project(const dimension_type m) {
02641
02642 if (m == 0)
02643 return;
02644
02645 const dimension_type space_dim = space_dimension();
02646
02647
02648
02649
02650 if (space_dim == 0) {
02651 dbm.grow(m + 1);
02652 if (!marked_empty()) {
02653 for (dimension_type i = m + 1; i-- > 0; ) {
02654 DB_Row<N>& dbm_i = dbm[i];
02655 for (dimension_type j = m + 1; j-- > 0; )
02656 if (i != j)
02657 assign_r(dbm_i[j], 0, ROUND_NOT_NEEDED);
02658 }
02659 set_shortest_path_closed();
02660 }
02661 PPL_ASSERT(OK());
02662 return;
02663 }
02664
02665
02666
02667
02668
02669 const dimension_type new_space_dim = space_dim + m;
02670 dbm.grow(new_space_dim + 1);
02671
02672
02673 DB_Row<N>& dbm_0 = dbm[0];
02674 for (dimension_type i = space_dim + 1; i <= new_space_dim; ++i) {
02675 assign_r(dbm[i][0], 0, ROUND_NOT_NEEDED);
02676 assign_r(dbm_0[i], 0, ROUND_NOT_NEEDED);
02677 }
02678
02679 if (marked_shortest_path_closed())
02680 reset_shortest_path_closed();
02681 PPL_ASSERT(OK());
02682 }
02683
02684 template <typename T>
02685 void
02686 BD_Shape<T>::remove_space_dimensions(const Variables_Set& vars) {
02687
02688
02689
02690 if (vars.empty()) {
02691 PPL_ASSERT(OK());
02692 return;
02693 }
02694
02695 const dimension_type old_space_dim = space_dimension();
02696
02697
02698 const dimension_type min_space_dim = vars.space_dimension();
02699 if (old_space_dim < min_space_dim)
02700 throw_dimension_incompatible("remove_space_dimensions(vs)", min_space_dim);
02701
02702
02703 shortest_path_closure_assign();
02704
02705
02706
02707 const dimension_type new_space_dim = old_space_dim - vars.size();
02708 if (new_space_dim == 0) {
02709 dbm.resize_no_copy(1);
02710 if (!marked_empty())
02711
02712 set_zero_dim_univ();
02713 PPL_ASSERT(OK());
02714 return;
02715 }
02716
02717
02718 if (marked_empty()) {
02719 dbm.resize_no_copy(new_space_dim + 1);
02720 PPL_ASSERT(OK());
02721 return;
02722 }
02723
02724
02725
02726 if (marked_shortest_path_reduced())
02727 reset_shortest_path_reduced();
02728
02729
02730
02731
02732 Variables_Set::const_iterator vsi = vars.begin();
02733 Variables_Set::const_iterator vsi_end = vars.end();
02734 dimension_type dst = *vsi + 1;
02735 dimension_type src = dst + 1;
02736 for (++vsi; vsi != vsi_end; ++vsi) {
02737 const dimension_type vsi_next = *vsi + 1;
02738
02739
02740 while (src < vsi_next) {
02741 std::swap(dbm[dst], dbm[src]);
02742 for (dimension_type i = old_space_dim + 1; i-- > 0; ) {
02743 DB_Row<N>& dbm_i = dbm[i];
02744 assign_or_swap(dbm_i[dst], dbm_i[src]);
02745 }
02746 ++dst;
02747 ++src;
02748 }
02749 ++src;
02750 }
02751
02752
02753 while (src <= old_space_dim) {
02754 std::swap(dbm[dst], dbm[src]);
02755 for (dimension_type i = old_space_dim + 1; i-- > 0; ) {
02756 DB_Row<N>& dbm_i = dbm[i];
02757 assign_or_swap(dbm_i[dst], dbm_i[src]);
02758 }
02759 ++src;
02760 ++dst;
02761 }
02762
02763
02764 dbm.resize_no_copy(new_space_dim + 1);
02765 PPL_ASSERT(OK());
02766 }
02767
02768 template <typename T>
02769 template <typename Partial_Function>
02770 void
02771 BD_Shape<T>::map_space_dimensions(const Partial_Function& pfunc) {
02772 const dimension_type space_dim = space_dimension();
02773
02774 if (space_dim == 0)
02775 return;
02776
02777 if (pfunc.has_empty_codomain()) {
02778
02779 remove_higher_space_dimensions(0);
02780 return;
02781 }
02782
02783 const dimension_type new_space_dim = pfunc.max_in_codomain() + 1;
02784
02785
02786 if (new_space_dim < space_dim)
02787 shortest_path_closure_assign();
02788
02789
02790
02791 if (marked_empty()) {
02792 remove_higher_space_dimensions(new_space_dim);
02793 return;
02794 }
02795
02796
02797
02798 if (marked_shortest_path_reduced())
02799 reset_shortest_path_reduced();
02800
02801
02802 DB_Matrix<N> x(new_space_dim+1);
02803
02804
02805
02806 DB_Row<N>& dbm_0 = dbm[0];
02807 DB_Row<N>& x_0 = x[0];
02808 for (dimension_type j = 1; j <= space_dim; ++j) {
02809 dimension_type new_j;
02810 if (pfunc.maps(j - 1, new_j)) {
02811 assign_or_swap(x_0[new_j + 1], dbm_0[j]);
02812 assign_or_swap(x[new_j + 1][0], dbm[j][0]);
02813 }
02814 }
02815
02816 for (dimension_type i = 1; i <= space_dim; ++i) {
02817 dimension_type new_i;
02818 if (pfunc.maps(i - 1, new_i)) {
02819 DB_Row<N>& dbm_i = dbm[i];
02820 ++new_i;
02821 DB_Row<N>& x_new_i = x[new_i];
02822 for (dimension_type j = i+1; j <= space_dim; ++j) {
02823 dimension_type new_j;
02824 if (pfunc.maps(j - 1, new_j)) {
02825 ++new_j;
02826 assign_or_swap(x_new_i[new_j], dbm_i[j]);
02827 assign_or_swap(x[new_j][new_i], dbm[j][i]);
02828 }
02829 }
02830 }
02831 }
02832
02833 std::swap(dbm, x);
02834 PPL_ASSERT(OK());
02835 }
02836
02837 template <typename T>
02838 void
02839 BD_Shape<T>::intersection_assign(const BD_Shape& y) {
02840 const dimension_type space_dim = space_dimension();
02841
02842
02843 if (space_dim != y.space_dimension())
02844 throw_dimension_incompatible("intersection_assign(y)", y);
02845
02846
02847
02848 if (marked_empty())
02849 return;
02850 if (y.marked_empty()) {
02851 set_empty();
02852 return;
02853 }
02854
02855
02856
02857
02858 if (space_dim == 0)
02859 return;
02860
02861
02862
02863 bool changed = false;
02864 for (dimension_type i = space_dim + 1; i-- > 0; ) {
02865 DB_Row<N>& dbm_i = dbm[i];
02866 const DB_Row<N>& y_dbm_i = y.dbm[i];
02867 for (dimension_type j = space_dim + 1; j-- > 0; ) {
02868 N& dbm_ij = dbm_i[j];
02869 const N& y_dbm_ij = y_dbm_i[j];
02870 if (dbm_ij > y_dbm_ij) {
02871 dbm_ij = y_dbm_ij;
02872 changed = true;
02873 }
02874 }
02875 }
02876
02877 if (changed && marked_shortest_path_closed())
02878 reset_shortest_path_closed();
02879 PPL_ASSERT(OK());
02880 }
02881
02882 template <typename T>
02883 template <typename Iterator>
02884 void
02885 BD_Shape<T>::CC76_extrapolation_assign(const BD_Shape& y,
02886 Iterator first, Iterator last,
02887 unsigned* tp) {
02888 const dimension_type space_dim = space_dimension();
02889
02890
02891 if (space_dim != y.space_dimension())
02892 throw_dimension_incompatible("CC76_extrapolation_assign(y)", y);
02893
02894 #ifndef NDEBUG
02895 {
02896
02897 const BD_Shape x_copy = *this;
02898 const BD_Shape y_copy = y;
02899 PPL_ASSERT(x_copy.contains(y_copy));
02900 }
02901 #endif
02902
02903
02904
02905 if (space_dim == 0)
02906 return;
02907
02908 shortest_path_closure_assign();
02909
02910 if (marked_empty())
02911 return;
02912 y.shortest_path_closure_assign();
02913
02914 if (y.marked_empty())
02915 return;
02916
02917
02918 if (tp != 0 && *tp > 0) {
02919 BD_Shape<T> x_tmp(*this);
02920 x_tmp.CC76_extrapolation_assign(y, first, last, 0);
02921
02922 if (!contains(x_tmp))
02923 --(*tp);
02924 return;
02925 }
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935 for (dimension_type i = space_dim + 1; i-- > 0; ) {
02936 DB_Row<N>& dbm_i = dbm[i];
02937 const DB_Row<N>& y_dbm_i = y.dbm[i];
02938 for (dimension_type j = space_dim + 1; j-- > 0; ) {
02939 N& dbm_ij = dbm_i[j];
02940 const N& y_dbm_ij = y_dbm_i[j];
02941 if (y_dbm_ij < dbm_ij) {
02942 Iterator k = std::lower_bound(first, last, dbm_ij);
02943 if (k != last) {
02944 if (dbm_ij < *k)
02945 assign_r(dbm_ij, *k, ROUND_UP);
02946 }
02947 else
02948 assign_r(dbm_ij, PLUS_INFINITY, ROUND_NOT_NEEDED);
02949 }
02950 }
02951 }
02952 reset_shortest_path_closed();
02953 PPL_ASSERT(OK());
02954 }
02955
02956 template <typename T>
02957 void
02958 BD_Shape<T>::get_limiting_shape(const Constraint_System& cs,
02959 BD_Shape& limiting_shape) const {
02960 const dimension_type cs_space_dim = cs.space_dimension();
02961
02962 PPL_ASSERT(cs_space_dim <= space_dimension());
02963
02964 shortest_path_closure_assign();
02965 bool changed = false;
02966 PPL_DIRTY_TEMP_COEFFICIENT(coeff);
02967 PPL_DIRTY_TEMP_COEFFICIENT(minus_c_term);
02968 PPL_DIRTY_TEMP(N, d);
02969 PPL_DIRTY_TEMP(N, d1);
02970 for (Constraint_System::const_iterator cs_i = cs.begin(),
02971 cs_end = cs.end(); cs_i != cs_end; ++cs_i) {
02972 const Constraint& c = *cs_i;
02973 dimension_type num_vars = 0;
02974 dimension_type i = 0;
02975 dimension_type j = 0;
02976
02977 if (extract_bounded_difference(c, cs_space_dim, num_vars, i, j, coeff)) {
02978
02979
02980 const bool negative = (coeff < 0);
02981 const N& x = negative ? dbm[i][j] : dbm[j][i];
02982 const N& y = negative ? dbm[j][i] : dbm[i][j];
02983 DB_Matrix<N>& ls_dbm = limiting_shape.dbm;
02984 N& ls_x = negative ? ls_dbm[i][j] : ls_dbm[j][i];
02985 N& ls_y = negative ? ls_dbm[j][i] : ls_dbm[i][j];
02986 if (negative)
02987 neg_assign(coeff);
02988
02989 div_round_up(d, c.inhomogeneous_term(), coeff);
02990 if (x <= d) {
02991 if (c.is_inequality()) {
02992 if (ls_x > d) {
02993 ls_x = d;
02994 changed = true;
02995 }
02996 }
02997 else {
02998
02999 neg_assign(minus_c_term, c.inhomogeneous_term());
03000 div_round_up(d1, minus_c_term, coeff);
03001 if (y <= d1)
03002 if ((ls_x >= d && ls_y > d1) || (ls_x > d && ls_y >= d1)) {
03003 ls_x = d;
03004 ls_y = d1;
03005 changed = true;
03006 }
03007 }
03008 }
03009 }
03010 }
03011
03012
03013
03014 if (changed && limiting_shape.marked_shortest_path_closed())
03015 limiting_shape.reset_shortest_path_closed();
03016 }
03017
03018 template <typename T>
03019 void
03020 BD_Shape<T>::limited_CC76_extrapolation_assign(const BD_Shape& y,
03021 const Constraint_System& cs,
03022 unsigned* tp) {
03023
03024 const dimension_type space_dim = space_dimension();
03025 if (space_dim != y.space_dimension())
03026 throw_dimension_incompatible("limited_CC76_extrapolation_assign(y, cs)",
03027 y);
03028
03029
03030
03031 const dimension_type cs_space_dim = cs.space_dimension();
03032 if (space_dim < cs_space_dim)
03033 throw_generic("limited_CC76_extrapolation_assign(y, cs)",
03034 "cs is space_dimension incompatible");
03035
03036
03037 if (cs.has_strict_inequalities())
03038 throw_generic("limited_CC76_extrapolation_assign(y, cs)",
03039 "cs has strict inequalities");
03040
03041
03042
03043
03044 if (space_dim == 0)
03045 return;
03046
03047 #ifndef NDEBUG
03048 {
03049
03050 const BD_Shape x_copy = *this;
03051 const BD_Shape y_copy = y;
03052 PPL_ASSERT(x_copy.contains(y_copy));
03053 }
03054 #endif
03055
03056
03057 if (marked_empty())
03058 return;
03059
03060 if (y.marked_empty())
03061 return;
03062
03063 BD_Shape<T> limiting_shape(space_dim, UNIVERSE);
03064 get_limiting_shape(cs, limiting_shape);
03065 CC76_extrapolation_assign(y, tp);
03066 intersection_assign(limiting_shape);
03067 }
03068
03069 template <typename T>
03070 void
03071 BD_Shape<T>::BHMZ05_widening_assign(const BD_Shape& y, unsigned* tp) {
03072 const dimension_type space_dim = space_dimension();
03073
03074
03075 if (space_dim != y.space_dimension())
03076 throw_dimension_incompatible("BHMZ05_widening_assign(y)", y);
03077
03078 #ifndef NDEBUG
03079 {
03080
03081 const BD_Shape x_copy = *this;
03082 const BD_Shape y_copy = y;
03083 PPL_ASSERT(x_copy.contains(y_copy));
03084 }
03085 #endif
03086
03087
03088 const dimension_type y_affine_dim = y.affine_dimension();
03089
03090
03091
03092 if (y_affine_dim == 0)
03093 return;
03094
03095
03096
03097 const dimension_type x_affine_dim = affine_dimension();
03098 PPL_ASSERT(x_affine_dim >= y_affine_dim);
03099 if (x_affine_dim != y_affine_dim)
03100 return;
03101
03102
03103 if (tp != 0 && *tp > 0) {
03104 BD_Shape<T> x_tmp(*this);
03105 x_tmp.BHMZ05_widening_assign(y, 0);
03106
03107 if (!contains(x_tmp))
03108 --(*tp);
03109 return;
03110 }
03111
03112
03113 PPL_ASSERT(marked_shortest_path_closed() && y.marked_shortest_path_closed());
03114
03115 y.shortest_path_reduction_assign();
03116
03117
03118 for (dimension_type i = space_dim + 1; i-- > 0; ) {
03119 DB_Row<N>& dbm_i = dbm[i];
03120 const DB_Row<N>& y_dbm_i = y.dbm[i];
03121 const Bit_Row& y_redundancy_i = y.redundancy_dbm[i];
03122 for (dimension_type j = space_dim + 1; j-- > 0; ) {
03123 N& dbm_ij = dbm_i[j];
03124
03125
03126
03127 if (y_redundancy_i[j] || y_dbm_i[j] != dbm_ij)
03128 assign_r(dbm_ij, PLUS_INFINITY, ROUND_NOT_NEEDED);
03129 }
03130 }
03131
03132
03133
03134
03135 reset_shortest_path_closed();
03136 PPL_ASSERT(OK());
03137 }
03138
03139 template <typename T>
03140 void
03141 BD_Shape<T>::limited_BHMZ05_extrapolation_assign(const BD_Shape& y,
03142 const Constraint_System& cs,
03143 unsigned* tp) {
03144
03145 const dimension_type space_dim = space_dimension();
03146 if (space_dim != y.space_dimension())
03147 throw_dimension_incompatible("limited_BHMZ05_extrapolation_assign(y, cs)",
03148 y);
03149
03150
03151 const dimension_type cs_space_dim = cs.space_dimension();
03152 if (space_dim < cs_space_dim)
03153 throw_generic("limited_BHMZ05_extrapolation_assign(y, cs)",
03154 "cs is space-dimension incompatible");
03155
03156
03157 if (cs.has_strict_inequalities())
03158 throw_generic("limited_BHMZ05_extrapolation_assign(y, cs)",
03159 "cs has strict inequalities");
03160
03161
03162
03163
03164 if (space_dim == 0)
03165 return;
03166
03167 #ifndef NDEBUG
03168 {
03169
03170 const BD_Shape x_copy = *this;
03171 const BD_Shape y_copy = y;
03172 PPL_ASSERT(x_copy.contains(y_copy));
03173 }
03174 #endif
03175
03176
03177 if (marked_empty())
03178 return;
03179
03180 if (y.marked_empty())
03181 return;
03182
03183 BD_Shape<T> limiting_shape(space_dim, UNIVERSE);
03184 get_limiting_shape(cs, limiting_shape);
03185 BHMZ05_widening_assign(y, tp);
03186 intersection_assign(limiting_shape);
03187 }
03188
03189 template <typename T>
03190 void
03191 BD_Shape<T>::CC76_narrowing_assign(const BD_Shape& y) {
03192 const dimension_type space_dim = space_dimension();
03193
03194
03195 if (space_dim != y.space_dimension())
03196 throw_dimension_incompatible("CC76_narrowing_assign(y)", y);
03197
03198 #ifndef NDEBUG
03199 {
03200
03201 const BD_Shape x_copy = *this;
03202 const BD_Shape y_copy = y;
03203 PPL_ASSERT(y_copy.contains(x_copy));
03204 }
03205 #endif
03206
03207
03208
03209 if (space_dim == 0)
03210 return;
03211
03212 y.shortest_path_closure_assign();
03213
03214 if (y.marked_empty())
03215 return;
03216 shortest_path_closure_assign();
03217
03218 if (marked_empty())
03219 return;
03220
03221
03222
03223 bool changed = false;
03224 for (dimension_type i = space_dim + 1; i-- > 0; ) {
03225 DB_Row<N>& dbm_i = dbm[i];
03226 const DB_Row<N>& y_dbm_i = y.dbm[i];
03227 for (dimension_type j = space_dim + 1; j-- > 0; ) {
03228 N& dbm_ij = dbm_i[j];
03229 const N& y_dbm_ij = y_dbm_i[j];
03230 if (!is_plus_infinity(dbm_ij)
03231 && !is_plus_infinity(y_dbm_ij)
03232 && dbm_ij != y_dbm_ij) {
03233 dbm_ij = y_dbm_ij;
03234 changed = true;
03235 }
03236 }
03237 }
03238 if (changed && marked_shortest_path_closed())
03239 reset_shortest_path_closed();
03240 PPL_ASSERT(OK());
03241 }
03242
03243 template <typename T>
03244 void
03245 BD_Shape<T>
03246 ::deduce_v_minus_u_bounds(const dimension_type v,
03247 const dimension_type last_v,
03248 const Linear_Expression& sc_expr,
03249 Coefficient_traits::const_reference sc_den,
03250 const N& ub_v) {
03251 PPL_ASSERT(sc_den > 0);
03252 PPL_ASSERT(!is_plus_infinity(ub_v));
03253
03254
03255
03256
03257
03258
03259
03260
03261 PPL_DIRTY_TEMP0(mpq_class, mpq_sc_den);
03262 assign_r(mpq_sc_den, sc_den, ROUND_NOT_NEEDED);
03263 const DB_Row<N>& dbm_0 = dbm[0];
03264
03265 PPL_DIRTY_TEMP0(mpq_class, minus_lb_u);
03266 PPL_DIRTY_TEMP0(mpq_class, q);
03267 PPL_DIRTY_TEMP0(mpq_class, ub_u);
03268 PPL_DIRTY_TEMP(N, up_approx);
03269
03270 for (dimension_type u = last_v; u > 0; --u)
03271 if (u != v) {
03272 const Coefficient& expr_u = sc_expr.coefficient(Variable(u-1));
03273 if (expr_u > 0) {
03274 if (expr_u >= sc_den)
03275
03276 sub_assign_r(dbm[u][v], ub_v, dbm_0[u], ROUND_UP);
03277 else {
03278 DB_Row<N>& dbm_u = dbm[u];
03279 const N& dbm_u0 = dbm_u[0];
03280 if (!is_plus_infinity(dbm_u0)) {
03281
03282
03283
03284
03285
03286
03287 assign_r(minus_lb_u, dbm_u0, ROUND_NOT_NEEDED);
03288 assign_r(q, expr_u, ROUND_NOT_NEEDED);
03289 div_assign_r(q, q, mpq_sc_den, ROUND_NOT_NEEDED);
03290 assign_r(ub_u, dbm_0[u], ROUND_NOT_NEEDED);
03291
03292 add_assign_r(ub_u, ub_u, minus_lb_u, ROUND_NOT_NEEDED);
03293
03294 sub_mul_assign_r(minus_lb_u, q, ub_u, ROUND_NOT_NEEDED);
03295 assign_r(up_approx, minus_lb_u, ROUND_UP);
03296
03297 add_assign_r(dbm_u[v], ub_v, up_approx, ROUND_UP);
03298 }
03299 }
03300 }
03301 }
03302 }
03303
03304 template <typename T>
03305 void
03306 BD_Shape<T>
03307 ::deduce_u_minus_v_bounds(const dimension_type v,
03308 const dimension_type last_v,
03309 const Linear_Expression& sc_expr,
03310 Coefficient_traits::const_reference sc_den,
03311 const N& minus_lb_v) {
03312 PPL_ASSERT(sc_den > 0);
03313 PPL_ASSERT(!is_plus_infinity(minus_lb_v));
03314
03315
03316
03317
03318
03319
03320
03321
03322 PPL_DIRTY_TEMP0(mpq_class, mpq_sc_den);
03323 assign_r(mpq_sc_den, sc_den, ROUND_NOT_NEEDED);
03324 DB_Row<N>& dbm_0 = dbm[0];
03325 DB_Row<N>& dbm_v = dbm[v];
03326
03327 PPL_DIRTY_TEMP0(mpq_class, ub_u);
03328 PPL_DIRTY_TEMP0(mpq_class, q);
03329 PPL_DIRTY_TEMP0(mpq_class, minus_lb_u);
03330 PPL_DIRTY_TEMP(N, up_approx);
03331
03332 for (dimension_type u = last_v; u > 0; --u)
03333 if (u != v) {
03334 const Coefficient& expr_u = sc_expr.coefficient(Variable(u-1));
03335 if (expr_u > 0) {
03336 if (expr_u >= sc_den)
03337
03338
03339 sub_assign_r(dbm_v[u], minus_lb_v, dbm[u][0], ROUND_UP);
03340 else {
03341 const N& dbm_0u = dbm_0[u];
03342 if (!is_plus_infinity(dbm_0u)) {
03343
03344
03345
03346
03347
03348
03349 assign_r(ub_u, dbm_0u, ROUND_NOT_NEEDED);
03350 assign_r(q, expr_u, ROUND_NOT_NEEDED);
03351 div_assign_r(q, q, mpq_sc_den, ROUND_NOT_NEEDED);
03352 assign_r(minus_lb_u, dbm[u][0], ROUND_NOT_NEEDED);
03353
03354 add_assign_r(minus_lb_u, minus_lb_u, ub_u, ROUND_NOT_NEEDED);
03355
03356 sub_mul_assign_r(ub_u, q, minus_lb_u, ROUND_NOT_NEEDED);
03357 assign_r(up_approx, ub_u, ROUND_UP);
03358
03359 add_assign_r(dbm_v[u], up_approx, minus_lb_v, ROUND_UP);
03360 }
03361 }
03362 }
03363 }
03364 }
03365
03366 template <typename T>
03367 void
03368 BD_Shape<T>::forget_all_dbm_constraints(const dimension_type v) {
03369 PPL_ASSERT(0 < v && v <= dbm.num_rows());
03370 DB_Row<N>& dbm_v = dbm[v];
03371 for (dimension_type i = dbm.num_rows(); i-- > 0; ) {
03372 assign_r(dbm_v[i], PLUS_INFINITY, ROUND_NOT_NEEDED);
03373 assign_r(dbm[i][v], PLUS_INFINITY, ROUND_NOT_NEEDED);
03374 }
03375 }
03376
03377 template <typename T>
03378 void
03379 BD_Shape<T>::forget_binary_dbm_constraints(const dimension_type v) {
03380 PPL_ASSERT(0 < v && v <= dbm.num_rows());
03381 DB_Row<N>& dbm_v = dbm[v];
03382 for (dimension_type i = dbm.num_rows()-1; i > 0; --i) {
03383 assign_r(dbm_v[i], PLUS_INFINITY, ROUND_NOT_NEEDED);
03384 assign_r(dbm[i][v], PLUS_INFINITY, ROUND_NOT_NEEDED);
03385 }
03386 }
03387
03388 template <typename T>
03389 void
03390 BD_Shape<T>::unconstrain(const Variable var) {
03391
03392 const dimension_type var_space_dim = var.space_dimension();
03393 if (space_dimension() < var_space_dim)
03394 throw_dimension_incompatible("unconstrain(var)", var_space_dim);
03395
03396
03397
03398 shortest_path_closure_assign();
03399
03400
03401 if (marked_empty())
03402 return;
03403
03404 forget_all_dbm_constraints(var_space_dim);
03405
03406 reset_shortest_path_reduced();
03407 PPL_ASSERT(OK());
03408 }
03409
03410 template <typename T>
03411 void
03412 BD_Shape<T>::unconstrain(const Variables_Set& vars) {
03413
03414
03415 if (vars.empty())
03416 return;
03417
03418
03419 const dimension_type min_space_dim = vars.space_dimension();
03420 if (space_dimension() < min_space_dim)
03421 throw_dimension_incompatible("unconstrain(vs)", min_space_dim);
03422
03423
03424
03425 shortest_path_closure_assign();
03426
03427
03428 if (marked_empty())
03429 return;
03430
03431 for (Variables_Set::const_iterator vsi = vars.begin(),
03432 vsi_end = vars.end(); vsi != vsi_end; ++vsi)
03433 forget_all_dbm_constraints(*vsi + 1);
03434
03435 reset_shortest_path_reduced();
03436 PPL_ASSERT(OK());
03437 }
03438
03439 template <typename T>
03440 void
03441 BD_Shape<T>::refine(const Variable var,
03442 const Relation_Symbol relsym,
03443 const Linear_Expression& expr,
03444 Coefficient_traits::const_reference denominator) {
03445 PPL_ASSERT(denominator != 0);
03446 const dimension_type expr_space_dim = expr.space_dimension();
03447 PPL_ASSERT(space_dimension() >= expr_space_dim);
03448 const dimension_type v = var.id() + 1;
03449 PPL_ASSERT(v <= space_dimension());
03450 PPL_ASSERT(expr.coefficient(var) == 0);
03451 PPL_ASSERT(relsym != LESS_THAN && relsym != GREATER_THAN);
03452
03453 const Coefficient& b = expr.inhomogeneous_term();
03454
03455
03456 dimension_type t = 0;
03457
03458 dimension_type w = 0;
03459
03460 for (dimension_type i = expr_space_dim; i-- > 0; )
03461 if (expr.coefficient(Variable(i)) != 0) {
03462 if (t++ == 1)
03463 break;
03464 else
03465 w = i+1;
03466 }
03467
03468
03469
03470
03471
03472
03473 if (t == 1 && expr.coefficient(Variable(w-1)) != denominator)
03474 t = 2;
03475
03476
03477
03478
03479
03480 const DB_Row<N>& dbm_0 = dbm[0];
03481 PPL_DIRTY_TEMP_COEFFICIENT(minus_den);
03482 neg_assign(minus_den, denominator);
03483
03484 if (t == 0) {
03485
03486 switch (relsym) {
03487 case EQUAL:
03488
03489 add_dbm_constraint(0, v, b, denominator);
03490 add_dbm_constraint(v, 0, b, minus_den);
03491 break;
03492 case LESS_OR_EQUAL:
03493
03494 add_dbm_constraint(0, v, b, denominator);
03495 break;
03496 case GREATER_OR_EQUAL:
03497
03498
03499 add_dbm_constraint(v, 0, b, minus_den);
03500 break;
03501 default:
03502
03503 throw std::runtime_error("PPL internal error");
03504 }
03505 return;
03506 }
03507
03508 if (t == 1) {
03509
03510 PPL_ASSERT(expr.coefficient(Variable(w-1)) == denominator);
03511 PPL_DIRTY_TEMP(N, d);
03512 switch (relsym) {
03513 case EQUAL:
03514
03515 div_round_up(d, b, denominator);
03516 add_dbm_constraint(w, v, d);
03517
03518
03519 div_round_up(d, b, minus_den);
03520 add_dbm_constraint(v, w, d);
03521 break;
03522 case LESS_OR_EQUAL:
03523
03524 div_round_up(d, b, denominator);
03525 add_dbm_constraint(w, v, d);
03526 break;
03527 case GREATER_OR_EQUAL:
03528
03529
03530 div_round_up(d, b, minus_den);
03531 add_dbm_constraint(v, w, d);
03532 break;
03533 default:
03534
03535 throw std::runtime_error("PPL internal error");
03536 }
03537 return;
03538 }
03539
03540
03541
03542
03543 const bool is_sc = (denominator > 0);
03544 PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
03545 neg_assign(minus_b, b);
03546 const Coefficient& sc_b = is_sc ? b : minus_b;
03547 const Coefficient& minus_sc_b = is_sc ? minus_b : b;
03548 const Coefficient& sc_den = is_sc ? denominator : minus_den;
03549 const Coefficient& minus_sc_den = is_sc ? minus_den : denominator;
03550
03551
03552
03553 Linear_Expression minus_expr;
03554 if (!is_sc)
03555 minus_expr = -expr;
03556 const Linear_Expression& sc_expr = is_sc ? expr : minus_expr;
03557
03558 PPL_DIRTY_TEMP(N, sum);
03559
03560 PPL_UNINITIALIZED(dimension_type, pinf_index);
03561
03562 dimension_type pinf_count = 0;
03563
03564
03565
03566 PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
03567 PPL_DIRTY_TEMP(N, coeff_i);
03568
03569 switch (relsym) {
03570 case EQUAL:
03571 {
03572 PPL_DIRTY_TEMP(N, neg_sum);
03573
03574 PPL_UNINITIALIZED(dimension_type, neg_pinf_index);
03575
03576 dimension_type neg_pinf_count = 0;
03577
03578
03579
03580
03581
03582 assign_r(sum, sc_b, ROUND_UP);
03583 assign_r(neg_sum, minus_sc_b, ROUND_UP);
03584
03585
03586
03587
03588 for (dimension_type i = w; i > 0; --i) {
03589 const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1));
03590 const int sign_i = sgn(sc_i);
03591 if (sign_i == 0)
03592 continue;
03593 if (sign_i > 0) {
03594 assign_r(coeff_i, sc_i, ROUND_UP);
03595
03596 if (pinf_count <= 1) {
03597 const N& approx_i = dbm_0[i];
03598 if (!is_plus_infinity(approx_i))
03599 add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
03600 else {
03601 ++pinf_count;
03602 pinf_index = i;
03603 }
03604 }
03605
03606 if (neg_pinf_count <= 1) {
03607 const N& approx_minus_i = dbm[i][0];
03608 if (!is_plus_infinity(approx_minus_i))
03609 add_mul_assign_r(neg_sum, coeff_i, approx_minus_i, ROUND_UP);
03610 else {
03611 ++neg_pinf_count;
03612 neg_pinf_index = i;
03613 }
03614 }
03615 }
03616 else if (sign_i < 0) {
03617 neg_assign(minus_sc_i, sc_i);
03618
03619 assign_r(coeff_i, minus_sc_i, ROUND_UP);
03620
03621 if (pinf_count <= 1) {
03622 const N& approx_minus_i = dbm[i][0];
03623 if (!is_plus_infinity(approx_minus_i))
03624 add_mul_assign_r(sum, coeff_i, approx_minus_i, ROUND_UP);
03625 else {
03626 ++pinf_count;
03627 pinf_index = i;
03628 }
03629 }
03630
03631 if (neg_pinf_count <= 1) {
03632 const N& approx_i = dbm_0[i];
03633 if (!is_plus_infinity(approx_i))
03634 add_mul_assign_r(neg_sum, coeff_i, approx_i, ROUND_UP);
03635 else {
03636 ++neg_pinf_count;
03637 neg_pinf_index = i;
03638 }
03639 }
03640 }
03641 }
03642
03643 if (pinf_count > 1 && neg_pinf_count > 1) {
03644 PPL_ASSERT(OK());
03645 return;
03646 }
03647
03648
03649 reset_shortest_path_closed();
03650
03651
03652
03653
03654
03655 PPL_DIRTY_TEMP(N, down_sc_den);
03656 assign_r(down_sc_den, minus_sc_den, ROUND_UP);
03657 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
03658
03659
03660 if (pinf_count <= 1) {
03661
03662 if (down_sc_den != 1)
03663 div_assign_r(sum, sum, down_sc_den, ROUND_UP);
03664
03665 if (pinf_count == 0) {
03666
03667 dbm[0][v] = sum;
03668
03669 deduce_v_minus_u_bounds(v, w, sc_expr, sc_den, sum);
03670 }
03671 else
03672
03673 if (pinf_index != v
03674 && sc_expr.coefficient(Variable(pinf_index-1)) == sc_den)
03675
03676 dbm[pinf_index][v] = sum;
03677 }
03678
03679
03680 if (neg_pinf_count <= 1) {
03681
03682 if (down_sc_den != 1)
03683 div_assign_r(neg_sum, neg_sum, down_sc_den, ROUND_UP);
03684
03685 if (neg_pinf_count == 0) {
03686
03687 DB_Row<N>& dbm_v = dbm[v];
03688 dbm_v[0] = neg_sum;
03689
03690 deduce_u_minus_v_bounds(v, w, sc_expr, sc_den, neg_sum);
03691 }
03692 else
03693
03694 if (neg_pinf_index != v
03695 && sc_expr.coefficient(Variable(neg_pinf_index-1)) == sc_den)
03696
03697
03698 dbm[v][neg_pinf_index] = neg_sum;
03699 }
03700 }
03701 break;
03702
03703 case LESS_OR_EQUAL:
03704
03705
03706
03707
03708 assign_r(sum, sc_b, ROUND_UP);
03709
03710
03711
03712
03713 for (dimension_type i = w; i > 0; --i) {
03714 const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1));
03715 const int sign_i = sgn(sc_i);
03716 if (sign_i == 0)
03717 continue;
03718
03719 const N& approx_i = (sign_i > 0) ? dbm_0[i] : dbm[i][0];
03720 if (is_plus_infinity(approx_i)) {
03721 if (++pinf_count > 1)
03722 break;
03723 pinf_index = i;
03724 continue;
03725 }
03726 if (sign_i > 0)
03727 assign_r(coeff_i, sc_i, ROUND_UP);
03728 else {
03729 neg_assign(minus_sc_i, sc_i);
03730 assign_r(coeff_i, minus_sc_i, ROUND_UP);
03731 }
03732 add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
03733 }
03734
03735
03736 if (sc_den != 1) {
03737
03738
03739
03740
03741 PPL_DIRTY_TEMP(N, down_sc_den);
03742 assign_r(down_sc_den, minus_sc_den, ROUND_UP);
03743 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
03744 div_assign_r(sum, sum, down_sc_den, ROUND_UP);
03745 }
03746
03747 if (pinf_count == 0) {
03748
03749 add_dbm_constraint(0, v, sum);
03750
03751 deduce_v_minus_u_bounds(v, w, sc_expr, sc_den, sum);
03752 }
03753 else if (pinf_count == 1)
03754 if (expr.coefficient(Variable(pinf_index-1)) == denominator)
03755
03756 add_dbm_constraint(pinf_index, v, sum);
03757 break;
03758
03759 case GREATER_OR_EQUAL:
03760
03761
03762
03763
03764
03765 assign_r(sum, minus_sc_b, ROUND_UP);
03766
03767
03768 for (dimension_type i = w; i > 0; --i) {
03769 const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1));
03770 const int sign_i = sgn(sc_i);
03771 if (sign_i == 0)
03772 continue;
03773
03774 const N& approx_i = (sign_i > 0) ? dbm[i][0] : dbm_0[i];
03775 if (is_plus_infinity(approx_i)) {
03776 if (++pinf_count > 1)
03777 break;
03778 pinf_index = i;
03779 continue;
03780 }
03781 if (sign_i > 0)
03782 assign_r(coeff_i, sc_i, ROUND_UP);
03783 else {
03784 neg_assign(minus_sc_i, sc_i);
03785 assign_r(coeff_i, minus_sc_i, ROUND_UP);
03786 }
03787 add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
03788 }
03789
03790
03791 if (sc_den != 1) {
03792
03793
03794
03795
03796 PPL_DIRTY_TEMP(N, down_sc_den);
03797 assign_r(down_sc_den, minus_sc_den, ROUND_UP);
03798 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
03799 div_assign_r(sum, sum, down_sc_den, ROUND_UP);
03800 }
03801
03802 if (pinf_count == 0) {
03803
03804 add_dbm_constraint(v, 0, sum);
03805
03806 deduce_u_minus_v_bounds(v, w, sc_expr, sc_den, sum);
03807 }
03808 else if (pinf_count == 1)
03809 if (pinf_index != v
03810 && expr.coefficient(Variable(pinf_index-1)) == denominator)
03811
03812
03813 add_dbm_constraint(v, pinf_index, sum);
03814 break;
03815
03816 default:
03817
03818 throw std::runtime_error("PPL internal error");
03819 }
03820
03821 PPL_ASSERT(OK());
03822 }
03823
03824 template <typename T>
03825 void
03826 BD_Shape<T>::affine_image(const Variable var,
03827 const Linear_Expression& expr,
03828 Coefficient_traits::const_reference denominator) {
03829
03830 if (denominator == 0)
03831 throw_generic("affine_image(v, e, d)", "d == 0");
03832
03833
03834
03835
03836 const dimension_type space_dim = space_dimension();
03837 const dimension_type expr_space_dim = expr.space_dimension();
03838 if (space_dim < expr_space_dim)
03839 throw_dimension_incompatible("affine_image(v, e, d)", "e", expr);
03840
03841
03842 const dimension_type v = var.id() + 1;
03843 if (v > space_dim)
03844 throw_dimension_incompatible("affine_image(v, e, d)", var.id());
03845
03846
03847 shortest_path_closure_assign();
03848 if (marked_empty())
03849 return;
03850
03851 const Coefficient& b = expr.inhomogeneous_term();
03852
03853
03854 dimension_type t = 0;
03855
03856 dimension_type w = 0;
03857
03858 for (dimension_type i = expr_space_dim; i-- > 0; )
03859 if (expr.coefficient(Variable(i)) != 0) {
03860 if (t++ == 1)
03861 break;
03862 else
03863 w = i+1;
03864 }
03865
03866
03867
03868
03869
03870
03871
03872
03873 PPL_DIRTY_TEMP_COEFFICIENT(minus_den);
03874 neg_assign(minus_den, denominator);
03875
03876 if (t == 0) {
03877
03878
03879 forget_all_dbm_constraints(v);
03880
03881 if (marked_shortest_path_reduced())
03882 reset_shortest_path_reduced();
03883
03884 add_dbm_constraint(0, v, b, denominator);
03885 add_dbm_constraint(v, 0, b, minus_den);
03886 PPL_ASSERT(OK());
03887 return;
03888 }
03889
03890 if (t == 1) {
03891
03892 const Coefficient& a = expr.coefficient(Variable(w-1));
03893 if (a == denominator || a == minus_den) {
03894
03895 if (w == v) {
03896
03897 if (a == denominator) {
03898 if (b == 0)
03899
03900 return;
03901 else {
03902
03903
03904 PPL_DIRTY_TEMP(N, d);
03905 div_round_up(d, b, denominator);
03906 PPL_DIRTY_TEMP(N, c);
03907 div_round_up(c, b, minus_den);
03908 DB_Row<N>& dbm_v = dbm[v];
03909 for (dimension_type i = space_dim + 1; i-- > 0; ) {
03910 N& dbm_vi = dbm_v[i];
03911 add_assign_r(dbm_vi, dbm_vi, c, ROUND_UP);
03912 N& dbm_iv = dbm[i][v];
03913 add_assign_r(dbm_iv, dbm_iv, d, ROUND_UP);
03914 }
03915
03916 }
03917 }
03918 else {
03919
03920
03921 forget_binary_dbm_constraints(v);
03922
03923 std::swap(dbm[v][0], dbm[0][v]);
03924
03925 reset_shortest_path_closed();
03926 if (b != 0) {
03927
03928
03929 PPL_DIRTY_TEMP(N, c);
03930 div_round_up(c, b, minus_den);
03931 N& dbm_v0 = dbm[v][0];
03932 add_assign_r(dbm_v0, dbm_v0, c, ROUND_UP);
03933 PPL_DIRTY_TEMP(N, d);
03934 div_round_up(d, b, denominator);
03935 N& dbm_0v = dbm[0][v];
03936 add_assign_r(dbm_0v, dbm_0v, d, ROUND_UP);
03937 }
03938 }
03939 }
03940 else {
03941
03942
03943
03944 forget_all_dbm_constraints(v);
03945
03946 if (marked_shortest_path_reduced())
03947 reset_shortest_path_reduced();
03948 if (a == denominator) {
03949
03950 add_dbm_constraint(w, v, b, denominator);
03951 add_dbm_constraint(v, w, b, minus_den);
03952 }
03953 else {
03954
03955
03956
03957 const N& dbm_w0 = dbm[w][0];
03958 if (!is_plus_infinity(dbm_w0)) {
03959
03960 PPL_DIRTY_TEMP(N, d);
03961 div_round_up(d, b, denominator);
03962 add_assign_r(dbm[0][v], d, dbm_w0, ROUND_UP);
03963 reset_shortest_path_closed();
03964 }
03965 const N& dbm_0w = dbm[0][w];
03966 if (!is_plus_infinity(dbm_0w)) {
03967
03968 PPL_DIRTY_TEMP(N, c);
03969 div_round_up(c, b, minus_den);
03970 add_assign_r(dbm[v][0], dbm_0w, c, ROUND_UP);
03971 reset_shortest_path_closed();
03972 }
03973 }
03974 }
03975 PPL_ASSERT(OK());
03976 return;
03977 }
03978 }
03979
03980
03981
03982
03983
03984
03985
03986
03987
03988
03989
03990
03991
03992 const bool is_sc = (denominator > 0);
03993 PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
03994 neg_assign(minus_b, b);
03995 const Coefficient& sc_b = is_sc ? b : minus_b;
03996 const Coefficient& minus_sc_b = is_sc ? minus_b : b;
03997 const Coefficient& sc_den = is_sc ? denominator : minus_den;
03998 const Coefficient& minus_sc_den = is_sc ? minus_den : denominator;
03999
04000
04001
04002 Linear_Expression minus_expr;
04003 if (!is_sc)
04004 minus_expr = -expr;
04005 const Linear_Expression& sc_expr = is_sc ? expr : minus_expr;
04006
04007 PPL_DIRTY_TEMP(N, pos_sum);
04008 PPL_DIRTY_TEMP(N, neg_sum);
04009
04010 PPL_UNINITIALIZED(dimension_type, pos_pinf_index);
04011 PPL_UNINITIALIZED(dimension_type, neg_pinf_index);
04012
04013 dimension_type pos_pinf_count = 0;
04014 dimension_type neg_pinf_count = 0;
04015
04016
04017 assign_r(pos_sum, sc_b, ROUND_UP);
04018 assign_r(neg_sum, minus_sc_b, ROUND_UP);
04019
04020
04021 const DB_Row<N>& dbm_0 = dbm[0];
04022
04023 PPL_DIRTY_TEMP(N, coeff_i);
04024 PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
04025
04026
04027 for (dimension_type i = w; i > 0; --i) {
04028 const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1));
04029 const int sign_i = sgn(sc_i);
04030 if (sign_i > 0) {
04031 assign_r(coeff_i, sc_i, ROUND_UP);
04032
04033 if (pos_pinf_count <= 1) {
04034 const N& up_approx_i = dbm_0[i];
04035 if (!is_plus_infinity(up_approx_i))
04036 add_mul_assign_r(pos_sum, coeff_i, up_approx_i, ROUND_UP);
04037 else {
04038 ++pos_pinf_count;
04039 pos_pinf_index = i;
04040 }
04041 }
04042
04043 if (neg_pinf_count <= 1) {
04044 const N& up_approx_minus_i = dbm[i][0];
04045 if (!is_plus_infinity(up_approx_minus_i))
04046 add_mul_assign_r(neg_sum, coeff_i, up_approx_minus_i, ROUND_UP);
04047 else {
04048 ++neg_pinf_count;
04049 neg_pinf_index = i;
04050 }
04051 }
04052 }
04053 else if (sign_i < 0) {
04054 neg_assign(minus_sc_i, sc_i);
04055
04056 assign_r(coeff_i, minus_sc_i, ROUND_UP);
04057
04058 if (pos_pinf_count <= 1) {
04059 const N& up_approx_minus_i = dbm[i][0];
04060 if (!is_plus_infinity(up_approx_minus_i))
04061 add_mul_assign_r(pos_sum, coeff_i, up_approx_minus_i, ROUND_UP);
04062 else {
04063 ++pos_pinf_count;
04064 pos_pinf_index = i;
04065 }
04066 }
04067
04068 if (neg_pinf_count <= 1) {
04069 const N& up_approx_i = dbm_0[i];
04070 if (!is_plus_infinity(up_approx_i))
04071 add_mul_assign_r(neg_sum, coeff_i, up_approx_i, ROUND_UP);
04072 else {
04073 ++neg_pinf_count;
04074 neg_pinf_index = i;
04075 }
04076 }
04077 }
04078 }
04079
04080
04081 forget_all_dbm_constraints(v);
04082
04083 if (marked_shortest_path_reduced())
04084 reset_shortest_path_reduced();
04085
04086 if (pos_pinf_count > 1 && neg_pinf_count > 1) {
04087 PPL_ASSERT(OK());
04088 return;
04089 }
04090
04091
04092 reset_shortest_path_closed();
04093
04094
04095 if (pos_pinf_count <= 1) {
04096
04097 if (sc_den != 1) {
04098
04099
04100
04101
04102 PPL_DIRTY_TEMP(N, down_sc_den);
04103 assign_r(down_sc_den, minus_sc_den, ROUND_UP);
04104 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
04105 div_assign_r(pos_sum, pos_sum, down_sc_den, ROUND_UP);
04106 }
04107
04108 if (pos_pinf_count == 0) {
04109
04110 dbm[0][v] = pos_sum;
04111
04112 deduce_v_minus_u_bounds(v, w, sc_expr, sc_den, pos_sum);
04113 }
04114 else
04115
04116 if (pos_pinf_index != v
04117 && sc_expr.coefficient(Variable(pos_pinf_index-1)) == sc_den)
04118
04119 dbm[pos_pinf_index][v] = pos_sum;
04120 }
04121
04122
04123 if (neg_pinf_count <= 1) {
04124
04125 if (sc_den != 1) {
04126
04127
04128
04129
04130 PPL_DIRTY_TEMP(N, down_sc_den);
04131 assign_r(down_sc_den, minus_sc_den, ROUND_UP);
04132 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
04133 div_assign_r(neg_sum, neg_sum, down_sc_den, ROUND_UP);
04134 }
04135
04136 if (neg_pinf_count == 0) {
04137
04138 DB_Row<N>& dbm_v = dbm[v];
04139 dbm_v[0] = neg_sum;
04140
04141 deduce_u_minus_v_bounds(v, w, sc_expr, sc_den, neg_sum);
04142 }
04143 else
04144
04145 if (neg_pinf_index != v
04146 && sc_expr.coefficient(Variable(neg_pinf_index-1)) == sc_den)
04147
04148
04149 dbm[v][neg_pinf_index] = neg_sum;
04150 }
04151
04152 PPL_ASSERT(OK());
04153 }
04154
04155 template <typename T>
04156 void
04157 BD_Shape<T>::affine_preimage(const Variable var,
04158 const Linear_Expression& expr,
04159 Coefficient_traits::const_reference denominator) {
04160
04161 if (denominator == 0)
04162 throw_generic("affine_preimage(v, e, d)", "d == 0");
04163
04164
04165
04166
04167 const dimension_type space_dim = space_dimension();
04168 const dimension_type expr_space_dim = expr.space_dimension();
04169 if (space_dim < expr_space_dim)
04170 throw_dimension_incompatible("affine_preimage(v, e, d)", "e", expr);
04171
04172
04173
04174 const dimension_type v = var.id() + 1;
04175 if (v > space_dim)
04176 throw_dimension_incompatible("affine_preimage(v, e, d)", var.id());
04177
04178
04179 shortest_path_closure_assign();
04180 if (marked_empty())
04181 return;
04182
04183 const Coefficient& b = expr.inhomogeneous_term();
04184
04185
04186 dimension_type t = 0;
04187
04188 dimension_type j = 0;
04189
04190 for (dimension_type i = expr_space_dim; i-- > 0; )
04191 if (expr.coefficient(Variable(i)) != 0) {
04192 if (t++ == 1)
04193 break;
04194 else
04195 j = i;
04196 }
04197
04198
04199
04200
04201
04202
04203
04204
04205 if (t == 0) {
04206
04207 forget_all_dbm_constraints(v);
04208
04209 if (marked_shortest_path_reduced())
04210 reset_shortest_path_reduced();
04211 PPL_ASSERT(OK());
04212 return;
04213 }
04214
04215 if (t == 1) {
04216
04217 const Coefficient& a = expr.coefficient(Variable(j));
04218 if (a == denominator || a == -denominator) {
04219
04220 if (j == var.id())
04221
04222 affine_image(var, denominator*var - b, a);
04223 else {
04224
04225
04226 forget_all_dbm_constraints(v);
04227
04228 if (marked_shortest_path_reduced())
04229 reset_shortest_path_reduced();
04230 PPL_ASSERT(OK());
04231 }
04232 return;
04233 }
04234 }
04235
04236
04237
04238
04239
04240 const Coefficient& expr_v = expr.coefficient(var);
04241 if (expr_v != 0) {
04242
04243 Linear_Expression inverse((expr_v + denominator)*var);
04244 inverse -= expr;
04245 affine_image(var, inverse, expr_v);
04246 }
04247 else {
04248
04249 forget_all_dbm_constraints(v);
04250
04251 if (marked_shortest_path_reduced())
04252 reset_shortest_path_reduced();
04253 }
04254 PPL_ASSERT(OK());
04255 }
04256
04257 template <typename T>
04258 void
04259 BD_Shape<T>
04260 ::bounded_affine_image(const Variable var,
04261 const Linear_Expression& lb_expr,
04262 const Linear_Expression& ub_expr,
04263 Coefficient_traits::const_reference denominator) {
04264
04265 if (denominator == 0)
04266 throw_generic("bounded_affine_image(v, lb, ub, d)", "d == 0");
04267
04268
04269
04270 const dimension_type bds_space_dim = space_dimension();
04271 const dimension_type v = var.id() + 1;
04272 if (v > bds_space_dim)
04273 throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)",
04274 "v", var);
04275
04276
04277 const dimension_type lb_space_dim = lb_expr.space_dimension();
04278 if (bds_space_dim < lb_space_dim)
04279 throw_dimension_incompatible("bounded_affine_image(v, lb, ub)",
04280 "lb", lb_expr);
04281 const dimension_type ub_space_dim = ub_expr.space_dimension();
04282 if (bds_space_dim < ub_space_dim)
04283 throw_dimension_incompatible("bounded_affine_image(v, lb, ub)",
04284 "ub", ub_expr);
04285
04286
04287 shortest_path_closure_assign();
04288 if (marked_empty())
04289 return;
04290
04291 const Coefficient& b = ub_expr.inhomogeneous_term();
04292
04293
04294 dimension_type t = 0;
04295
04296 dimension_type w = 0;
04297
04298 for (dimension_type i = ub_space_dim; i-- > 0; )
04299 if (ub_expr.coefficient(Variable(i)) != 0) {
04300 if (t++ == 1)
04301 break;
04302 else
04303 w = i+1;
04304 }
04305
04306
04307
04308
04309
04310
04311
04312
04313 PPL_DIRTY_TEMP_COEFFICIENT(minus_den);
04314 neg_assign(minus_den, denominator);
04315
04316 if (t == 0) {
04317
04318 generalized_affine_image(var,
04319 GREATER_OR_EQUAL,
04320 lb_expr,
04321 denominator);
04322
04323 add_dbm_constraint(0, v, b, denominator);
04324 PPL_ASSERT(OK());
04325 return;
04326 }
04327
04328 if (t == 1) {
04329
04330 const Coefficient& a = ub_expr.coefficient(Variable(w-1));
04331 if (a == denominator || a == minus_den) {
04332
04333 if (w == v) {
04334
04335
04336 const Variable new_var = Variable(bds_space_dim);
04337 add_space_dimensions_and_embed(1);
04338
04339 affine_image(new_var, ub_expr, denominator);
04340
04341 shortest_path_closure_assign();
04342 PPL_ASSERT(!marked_empty());
04343
04344 generalized_affine_image(var,
04345 GREATER_OR_EQUAL,
04346 lb_expr,
04347 denominator);
04348
04349 add_constraint(var <= new_var);
04350
04351 remove_higher_space_dimensions(bds_space_dim);
04352 return;
04353 }
04354 else {
04355
04356
04357
04358 generalized_affine_image(var,
04359 GREATER_OR_EQUAL,
04360 lb_expr,
04361 denominator);
04362 if (a == denominator) {
04363
04364 add_dbm_constraint(w, v, b, denominator);
04365 }
04366 else {
04367
04368
04369
04370 const N& dbm_w0 = dbm[w][0];
04371 if (!is_plus_infinity(dbm_w0)) {
04372
04373 PPL_DIRTY_TEMP(N, d);
04374 div_round_up(d, b, denominator);
04375 add_assign_r(dbm[0][v], d, dbm_w0, ROUND_UP);
04376 reset_shortest_path_closed();
04377 }
04378 }
04379 PPL_ASSERT(OK());
04380 return;
04381 }
04382 }
04383 }
04384
04385
04386
04387
04388
04389
04390
04391
04392
04393
04394 const bool is_sc = (denominator > 0);
04395 PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
04396 neg_assign(minus_b, b);
04397 const Coefficient& sc_b = is_sc ? b : minus_b;
04398 const Coefficient& sc_den = is_sc ? denominator : minus_den;
04399 const Coefficient& minus_sc_den = is_sc ? minus_den : denominator;
04400
04401
04402
04403 Linear_Expression minus_expr;
04404 if (!is_sc)
04405 minus_expr = -ub_expr;
04406 const Linear_Expression& sc_expr = is_sc ? ub_expr : minus_expr;
04407
04408 PPL_DIRTY_TEMP(N, pos_sum);
04409
04410 PPL_UNINITIALIZED(dimension_type, pos_pinf_index);
04411
04412 dimension_type pos_pinf_count = 0;
04413
04414
04415 assign_r(pos_sum, sc_b, ROUND_UP);
04416
04417
04418 const DB_Row<N>& dbm_0 = dbm[0];
04419
04420 PPL_DIRTY_TEMP(N, coeff_i);
04421 PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
04422
04423
04424 for (dimension_type i = w; i > 0; --i) {
04425 const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1));
04426 const int sign_i = sgn(sc_i);
04427 if (sign_i > 0) {
04428 assign_r(coeff_i, sc_i, ROUND_UP);
04429
04430 if (pos_pinf_count <= 1) {
04431 const N& up_approx_i = dbm_0[i];
04432 if (!is_plus_infinity(up_approx_i))
04433 add_mul_assign_r(pos_sum, coeff_i, up_approx_i, ROUND_UP);
04434 else {
04435 ++pos_pinf_count;
04436 pos_pinf_index = i;
04437 }
04438 }
04439 }
04440 else if (sign_i < 0) {
04441 neg_assign(minus_sc_i, sc_i);
04442
04443 assign_r(coeff_i, minus_sc_i, ROUND_UP);
04444
04445 if (pos_pinf_count <= 1) {
04446 const N& up_approx_minus_i = dbm[i][0];
04447 if (!is_plus_infinity(up_approx_minus_i))
04448 add_mul_assign_r(pos_sum, coeff_i, up_approx_minus_i, ROUND_UP);
04449 else {
04450 ++pos_pinf_count;
04451 pos_pinf_index = i;
04452 }
04453 }
04454 }
04455 }
04456
04457 generalized_affine_image(var,
04458 GREATER_OR_EQUAL,
04459 lb_expr,
04460 denominator);
04461
04462 if (pos_pinf_count > 1) {
04463 return;
04464 }
04465
04466
04467 reset_shortest_path_closed();
04468
04469
04470 if (pos_pinf_count <= 1) {
04471
04472 if (sc_den != 1) {
04473
04474
04475
04476
04477 PPL_DIRTY_TEMP(N, down_sc_den);
04478 assign_r(down_sc_den, minus_sc_den, ROUND_UP);
04479 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
04480 div_assign_r(pos_sum, pos_sum, down_sc_den, ROUND_UP);
04481 }
04482
04483 if (pos_pinf_count == 0) {
04484
04485 dbm[0][v] = pos_sum;
04486
04487 deduce_v_minus_u_bounds(v, w, sc_expr, sc_den, pos_sum);
04488 }
04489 else
04490
04491 if (pos_pinf_index != v
04492 && sc_expr.coefficient(Variable(pos_pinf_index-1)) == sc_den)
04493
04494 dbm[pos_pinf_index][v] = pos_sum;
04495 }
04496 PPL_ASSERT(OK());
04497 }
04498
04499 template <typename T>
04500 void
04501 BD_Shape<T>
04502 ::bounded_affine_preimage(const Variable var,
04503 const Linear_Expression& lb_expr,
04504 const Linear_Expression& ub_expr,
04505 Coefficient_traits::const_reference denominator) {
04506
04507 if (denominator == 0)
04508 throw_generic("bounded_affine_preimage(v, lb, ub, d)", "d == 0");
04509
04510
04511
04512 const dimension_type space_dim = space_dimension();
04513 const dimension_type v = var.id() + 1;
04514 if (v > space_dim)
04515 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
04516 "v", var);
04517
04518
04519 const dimension_type lb_space_dim = lb_expr.space_dimension();
04520 if (space_dim < lb_space_dim)
04521 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)",
04522 "lb", lb_expr);
04523 const dimension_type ub_space_dim = ub_expr.space_dimension();
04524 if (space_dim < ub_space_dim)
04525 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)",
04526 "ub", ub_expr);
04527
04528
04529 shortest_path_closure_assign();
04530 if (marked_empty())
04531 return;
04532
04533 if (ub_expr.coefficient(var) == 0) {
04534 refine(var, LESS_OR_EQUAL, ub_expr, denominator);
04535 generalized_affine_preimage(var, GREATER_OR_EQUAL,
04536 lb_expr, denominator);
04537 return;
04538 }
04539 if (lb_expr.coefficient(var) == 0) {
04540 refine(var, GREATER_OR_EQUAL, lb_expr, denominator);
04541 generalized_affine_preimage(var, LESS_OR_EQUAL,
04542 ub_expr, denominator);
04543 return;
04544 }
04545
04546 const Coefficient& lb_expr_v = lb_expr.coefficient(var);
04547
04548
04549 const Variable new_var = Variable(space_dim);
04550 add_space_dimensions_and_embed(1);
04551 const Linear_Expression lb_inverse
04552 = lb_expr - (lb_expr_v + denominator)*var;
04553 PPL_DIRTY_TEMP_COEFFICIENT(lb_inverse_den);
04554 neg_assign(lb_inverse_den, lb_expr_v);
04555 affine_image(new_var, lb_inverse, lb_inverse_den);
04556 shortest_path_closure_assign();
04557 PPL_ASSERT(!marked_empty());
04558 generalized_affine_preimage(var, LESS_OR_EQUAL,
04559 ub_expr, denominator);
04560 if (sgn(denominator) == sgn(lb_inverse_den))
04561 add_constraint(var >= new_var);
04562 else
04563 add_constraint(var <= new_var);
04564
04565 remove_higher_space_dimensions(space_dim);
04566 }
04567
04568 template <typename T>
04569 void
04570 BD_Shape<T>::generalized_affine_image(const Variable var,
04571 const Relation_Symbol relsym,
04572 const Linear_Expression& expr,
04573 Coefficient_traits::const_reference
04574 denominator) {
04575
04576 if (denominator == 0)
04577 throw_generic("generalized_affine_image(v, r, e, d)", "d == 0");
04578
04579
04580
04581
04582 const dimension_type space_dim = space_dimension();
04583 const dimension_type expr_space_dim = expr.space_dimension();
04584 if (space_dim < expr_space_dim)
04585 throw_dimension_incompatible("generalized_affine_image(v, r, e, d)",
04586 "e", expr);
04587
04588
04589 const dimension_type v = var.id() + 1;
04590 if (v > space_dim)
04591 throw_dimension_incompatible("generalized_affine_image(v, r, e, d)",
04592 var.id());
04593
04594
04595 if (relsym == LESS_THAN || relsym == GREATER_THAN)
04596 throw_generic("generalized_affine_image(v, r, e, d)",
04597 "r is a strict relation symbol and "
04598 "*this is a BD_Shape");
04599
04600 if (relsym == NOT_EQUAL)
04601 throw_generic("generalized_affine_image(v, r, e, d)",
04602 "r is the disequality relation symbol and "
04603 "*this is a BD_Shape");
04604
04605 if (relsym == EQUAL) {
04606
04607
04608 affine_image(var, expr, denominator);
04609 return;
04610 }
04611
04612
04613 shortest_path_closure_assign();
04614 if (marked_empty())
04615 return;
04616
04617 const Coefficient& b = expr.inhomogeneous_term();
04618
04619
04620 dimension_type t = 0;
04621
04622 dimension_type w = 0;
04623
04624 for (dimension_type i = expr_space_dim; i-- > 0; )
04625 if (expr.coefficient(Variable(i)) != 0) {
04626 if (t++ == 1)
04627 break;
04628 else
04629 w = i+1;
04630 }
04631
04632
04633
04634
04635
04636
04637
04638
04639 DB_Row<N>& dbm_0 = dbm[0];
04640 DB_Row<N>& dbm_v = dbm[v];
04641 PPL_DIRTY_TEMP_COEFFICIENT(minus_den);
04642 neg_assign(minus_den, denominator);
04643
04644 if (t == 0) {
04645
04646
04647 forget_all_dbm_constraints(v);
04648
04649 reset_shortest_path_closed();
04650 switch (relsym) {
04651 case LESS_OR_EQUAL:
04652
04653 add_dbm_constraint(0, v, b, denominator);
04654 break;
04655 case GREATER_OR_EQUAL:
04656
04657
04658 add_dbm_constraint(v, 0, b, minus_den);
04659 break;
04660 default:
04661
04662 throw std::runtime_error("PPL internal error");
04663 }
04664 PPL_ASSERT(OK());
04665 return;
04666 }
04667
04668 if (t == 1) {
04669
04670 const Coefficient& a = expr.coefficient(Variable(w-1));
04671 if (a == denominator || a == minus_den) {
04672
04673 PPL_DIRTY_TEMP(N, d);
04674 switch (relsym) {
04675 case LESS_OR_EQUAL:
04676 div_round_up(d, b, denominator);
04677 if (w == v) {
04678
04679
04680 reset_shortest_path_closed();
04681 if (a == denominator) {
04682
04683
04684
04685 for (dimension_type i = space_dim + 1; i-- > 0; ) {
04686 N& dbm_iv = dbm[i][v];
04687 add_assign_r(dbm_iv, dbm_iv, d, ROUND_UP);
04688 assign_r(dbm_v[i], PLUS_INFINITY, ROUND_NOT_NEEDED);
04689 }
04690 }
04691 else {
04692
04693
04694
04695 N& dbm_v0 = dbm_v[0];
04696 add_assign_r(dbm_0[v], dbm_v0, d, ROUND_UP);
04697
04698 assign_r(dbm_v0, PLUS_INFINITY, ROUND_NOT_NEEDED);
04699 forget_binary_dbm_constraints(v);
04700 }
04701 }
04702 else {
04703
04704
04705
04706 forget_all_dbm_constraints(v);
04707
04708 if (marked_shortest_path_reduced())
04709 reset_shortest_path_reduced();
04710 if (a == denominator)
04711
04712 add_dbm_constraint(w, v, d);
04713 else {
04714
04715
04716
04717 const N& dbm_w0 = dbm[w][0];
04718 if (!is_plus_infinity(dbm_w0)) {
04719
04720 add_assign_r(dbm_0[v], d, dbm_w0, ROUND_UP);
04721
04722 reset_shortest_path_closed();
04723 }
04724 }
04725 }
04726 break;
04727
04728 case GREATER_OR_EQUAL:
04729 div_round_up(d, b, minus_den);
04730 if (w == v) {
04731
04732
04733 reset_shortest_path_closed();
04734 if (a == denominator) {
04735
04736
04737
04738 for (dimension_type i = space_dim + 1; i-- > 0; ) {
04739 N& dbm_vi = dbm_v[i];
04740 add_assign_r(dbm_vi, dbm_vi, d, ROUND_UP);
04741 assign_r(dbm[i][v], PLUS_INFINITY, ROUND_NOT_NEEDED);
04742 }
04743 }
04744 else {
04745
04746
04747
04748 N& dbm_0v = dbm_0[v];
04749 add_assign_r(dbm_v[0], dbm_0v, d, ROUND_UP);
04750
04751 assign_r(dbm_0v, PLUS_INFINITY, ROUND_NOT_NEEDED);
04752 forget_binary_dbm_constraints(v);
04753 }
04754 }
04755 else {
04756
04757
04758
04759 forget_all_dbm_constraints(v);
04760
04761 if (marked_shortest_path_reduced())
04762 reset_shortest_path_reduced();
04763 if (a == denominator)
04764
04765
04766 add_dbm_constraint(v, w, d);
04767 else {
04768
04769
04770
04771
04772 const N& dbm_0w = dbm_0[w];
04773 if (!is_plus_infinity(dbm_0w)) {
04774
04775 add_assign_r(dbm_v[0], dbm_0w, d, ROUND_UP);
04776
04777 reset_shortest_path_closed();
04778 }
04779 }
04780 }
04781 break;
04782
04783 default:
04784
04785 throw std::runtime_error("PPL internal error");
04786 }
04787 PPL_ASSERT(OK());
04788 return;
04789 }
04790 }
04791
04792
04793
04794
04795
04796
04797
04798
04799 const bool is_sc = (denominator > 0);
04800 PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
04801 neg_assign(minus_b, b);
04802 const Coefficient& sc_b = is_sc ? b : minus_b;
04803 const Coefficient& minus_sc_b = is_sc ? minus_b : b;
04804 const Coefficient& sc_den = is_sc ? denominator : minus_den;
04805 const Coefficient& minus_sc_den = is_sc ? minus_den : denominator;
04806
04807
04808
04809 Linear_Expression minus_expr;
04810 if (!is_sc)
04811 minus_expr = -expr;
04812 const Linear_Expression& sc_expr = is_sc ? expr : minus_expr;
04813
04814 PPL_DIRTY_TEMP(N, sum);
04815
04816 PPL_UNINITIALIZED(dimension_type, pinf_index);
04817
04818 dimension_type pinf_count = 0;
04819
04820
04821 PPL_DIRTY_TEMP(N, coeff_i);
04822 PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
04823
04824 switch (relsym) {
04825 case LESS_OR_EQUAL:
04826
04827
04828
04829 assign_r(sum, sc_b, ROUND_UP);
04830
04831
04832
04833 for (dimension_type i = w; i > 0; --i) {
04834 const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1));
04835 const int sign_i = sgn(sc_i);
04836 if (sign_i == 0)
04837 continue;
04838
04839 const N& approx_i = (sign_i > 0) ? dbm_0[i] : dbm[i][0];
04840 if (is_plus_infinity(approx_i)) {
04841 if (++pinf_count > 1)
04842 break;
04843 pinf_index = i;
04844 continue;
04845 }
04846 if (sign_i > 0)
04847 assign_r(coeff_i, sc_i, ROUND_UP);
04848 else {
04849 neg_assign(minus_sc_i, sc_i);
04850 assign_r(coeff_i, minus_sc_i, ROUND_UP);
04851 }
04852 add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
04853 }
04854
04855
04856 forget_all_dbm_constraints(v);
04857
04858 if (marked_shortest_path_reduced())
04859 reset_shortest_path_reduced();
04860
04861 if (pinf_count > 1) {
04862 PPL_ASSERT(OK());
04863 return;
04864 }
04865
04866
04867 if (sc_den != 1) {
04868
04869
04870
04871
04872 PPL_DIRTY_TEMP(N, down_sc_den);
04873 assign_r(down_sc_den, minus_sc_den, ROUND_UP);
04874 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
04875 div_assign_r(sum, sum, down_sc_den, ROUND_UP);
04876 }
04877
04878 if (pinf_count == 0) {
04879
04880 add_dbm_constraint(0, v, sum);
04881
04882 deduce_v_minus_u_bounds(v, w, sc_expr, sc_den, sum);
04883 }
04884 else if (pinf_count == 1)
04885 if (pinf_index != v
04886 && expr.coefficient(Variable(pinf_index-1)) == denominator)
04887
04888 add_dbm_constraint(pinf_index, v, sum);
04889 break;
04890
04891 case GREATER_OR_EQUAL:
04892
04893
04894
04895
04896
04897 assign_r(sum, minus_sc_b, ROUND_UP);
04898
04899 for (dimension_type i = expr_space_dim + 1; i > 0; --i) {
04900 const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1));
04901 const int sign_i = sgn(sc_i);
04902 if (sign_i == 0)
04903 continue;
04904
04905 const N& approx_i = (sign_i > 0) ? dbm[i][0] : dbm_0[i];
04906 if (is_plus_infinity(approx_i)) {
04907 if (++pinf_count > 1)
04908 break;
04909 pinf_index = i;
04910 continue;
04911 }
04912 if (sign_i > 0)
04913 assign_r(coeff_i, sc_i, ROUND_UP);
04914 else {
04915 neg_assign(minus_sc_i, sc_i);
04916 assign_r(coeff_i, minus_sc_i, ROUND_UP);
04917 }
04918 add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
04919 }
04920
04921
04922 forget_all_dbm_constraints(v);
04923
04924 if (marked_shortest_path_reduced())
04925 reset_shortest_path_reduced();
04926
04927 if (pinf_count > 1) {
04928 PPL_ASSERT(OK());
04929 return;
04930 }
04931
04932
04933 if (sc_den != 1) {
04934
04935
04936
04937
04938 PPL_DIRTY_TEMP(N, down_sc_den);
04939 assign_r(down_sc_den, minus_sc_den, ROUND_UP);
04940 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
04941 div_assign_r(sum, sum, down_sc_den, ROUND_UP);
04942 }
04943
04944 if (pinf_count == 0) {
04945
04946 add_dbm_constraint(v, 0, sum);
04947
04948 deduce_u_minus_v_bounds(v, w, sc_expr, sc_den, sum);
04949 }
04950 else if (pinf_count == 1)
04951 if (pinf_index != v
04952 && expr.coefficient(Variable(pinf_index-1)) == denominator)
04953
04954
04955 add_dbm_constraint(v, pinf_index, sum);
04956 break;
04957
04958 default:
04959
04960 throw std::runtime_error("PPL internal error");
04961 }
04962 PPL_ASSERT(OK());
04963 }
04964
04965 template <typename T>
04966 void
04967 BD_Shape<T>::generalized_affine_image(const Linear_Expression& lhs,
04968 const Relation_Symbol relsym,
04969 const Linear_Expression& rhs) {
04970
04971
04972
04973 const dimension_type space_dim = space_dimension();
04974 const dimension_type lhs_space_dim = lhs.space_dimension();
04975 if (space_dim < lhs_space_dim)
04976 throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
04977 "e1", lhs);
04978
04979
04980
04981 const dimension_type rhs_space_dim = rhs.space_dimension();
04982 if (space_dim < rhs_space_dim)
04983 throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
04984 "e2", rhs);
04985
04986
04987 if (relsym == LESS_THAN || relsym == GREATER_THAN)
04988 throw_generic("generalized_affine_image(e1, r, e2)",
04989 "r is a strict relation symbol and "
04990 "*this is a BD_Shape");
04991
04992 if (relsym == NOT_EQUAL)
04993 throw_generic("generalized_affine_image(e1, r, e2)",
04994 "r is the disequality relation symbol and "
04995 "*this is a BD_Shape");
04996
04997
04998 shortest_path_closure_assign();
04999 if (marked_empty())
05000 return;
05001
05002
05003
05004 dimension_type t_lhs = 0;
05005
05006 dimension_type j_lhs = 0;
05007
05008 for (dimension_type i = lhs_space_dim; i-- > 0; )
05009 if (lhs.coefficient(Variable(i)) != 0) {
05010 if (t_lhs++ == 1)
05011 break;
05012 else
05013 j_lhs = i;
05014 }
05015
05016 const Coefficient& b_lhs = lhs.inhomogeneous_term();
05017
05018 if (t_lhs == 0) {
05019
05020
05021
05022
05023
05024
05025
05026 switch (relsym) {
05027 case LESS_OR_EQUAL:
05028 refine_no_check(lhs <= rhs);
05029 break;
05030 case EQUAL:
05031 refine_no_check(lhs == rhs);
05032 break;
05033 case GREATER_OR_EQUAL:
05034 refine_no_check(lhs >= rhs);
05035 break;
05036 default:
05037
05038 throw std::runtime_error("PPL internal error");
05039 }
05040 }
05041 else if (t_lhs == 1) {
05042
05043
05044
05045 Variable v(j_lhs);
05046
05047 const Coefficient& den = lhs.coefficient(v);
05048 Relation_Symbol new_relsym = relsym;
05049 if (den < 0) {
05050 if (relsym == LESS_OR_EQUAL)
05051 new_relsym = GREATER_OR_EQUAL;
05052 else if (relsym == GREATER_OR_EQUAL)
05053 new_relsym = LESS_OR_EQUAL;
05054 }
05055 Linear_Expression expr = rhs - b_lhs;
05056 generalized_affine_image(v, new_relsym, expr, den);
05057 }
05058 else {
05059
05060
05061 bool lhs_vars_intersects_rhs_vars = false;
05062 std::vector<Variable> lhs_vars;
05063 for (dimension_type i = lhs_space_dim; i-- > 0; )
05064 if (lhs.coefficient(Variable(i)) != 0) {
05065 lhs_vars.push_back(Variable(i));
05066 if (rhs.coefficient(Variable(i)) != 0)
05067 lhs_vars_intersects_rhs_vars = true;
05068 }
05069
05070 if (!lhs_vars_intersects_rhs_vars) {
05071
05072
05073 for (dimension_type i = lhs_vars.size(); i-- > 0; )
05074 forget_all_dbm_constraints(lhs_vars[i].id() + 1);
05075
05076
05077
05078
05079 switch (relsym) {
05080 case LESS_OR_EQUAL:
05081 refine_no_check(lhs <= rhs);
05082 break;
05083 case EQUAL:
05084 refine_no_check(lhs == rhs);
05085 break;
05086 case GREATER_OR_EQUAL:
05087 refine_no_check(lhs >= rhs);
05088 break;
05089 default:
05090
05091 throw std::runtime_error("PPL internal error");
05092 }
05093 }
05094 else {
05095
05096
05097 #if 1 // Simplified computation (see the TODO note below).
05098
05099 for (dimension_type i = lhs_vars.size(); i-- > 0; )
05100 forget_all_dbm_constraints(lhs_vars[i].id() + 1);
05101
05102 #else // Currently unnecessarily complex computation.
05103
05104
05105
05106
05107
05108 const Variable new_var = Variable(space_dim);
05109 add_space_dimensions_and_embed(1);
05110
05111
05112
05113
05114 affine_image(new_var, rhs);
05115
05116
05117 shortest_path_closure_assign();
05118 PPL_ASSERT(!marked_empty());
05119 for (dimension_type i = lhs_vars.size(); i-- > 0; )
05120 forget_all_dbm_constraints(lhs_vars[i].id() + 1);
05121
05122
05123
05124
05125
05126
05127 switch (relsym) {
05128 case LESS_OR_EQUAL:
05129 refine_no_check(lhs <= new_var);
05130 break;
05131 case EQUAL:
05132 refine_no_check(lhs == new_var);
05133 break;
05134 case GREATER_OR_EQUAL:
05135 refine_no_check(lhs >= new_var);
05136 break;
05137 default:
05138
05139 throw std::runtime_error("PPL internal error");
05140 }
05141
05142 remove_higher_space_dimensions(space_dim-1);
05143 #endif // Currently unnecessarily complex computation.
05144 }
05145 }
05146
05147 PPL_ASSERT(OK());
05148 }
05149
05150 template <typename T>
05151 void
05152 BD_Shape<T>::generalized_affine_preimage(const Variable var,
05153 const Relation_Symbol relsym,
05154 const Linear_Expression& expr,
05155 Coefficient_traits::const_reference
05156 denominator) {
05157
05158 if (denominator == 0)
05159 throw_generic("generalized_affine_preimage(v, r, e, d)", "d == 0");
05160
05161
05162
05163
05164 const dimension_type space_dim = space_dimension();
05165 const dimension_type expr_space_dim = expr.space_dimension();
05166 if (space_dim < expr_space_dim)
05167 throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)",
05168 "e", expr);
05169
05170
05171 const dimension_type v = var.id() + 1;
05172 if (v > space_dim)
05173 throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)",
05174 var.id());
05175
05176
05177 if (relsym == LESS_THAN || relsym == GREATER_THAN)
05178 throw_generic("generalized_affine_preimage(v, r, e, d)",
05179 "r is a strict relation symbol and "
05180 "*this is a BD_Shape");
05181
05182 if (relsym == NOT_EQUAL)
05183 throw_generic("generalized_affine_preimage(v, r, e, d)",
05184 "r is the disequality relation symbol and "
05185 "*this is a BD_Shape");
05186
05187 if (relsym == EQUAL) {
05188
05189
05190 affine_preimage(var, expr, denominator);
05191 return;
05192 }
05193
05194
05195 shortest_path_closure_assign();
05196 if (marked_empty())
05197 return;
05198
05199
05200
05201 const Coefficient& expr_v = expr.coefficient(var);
05202 if (expr_v != 0) {
05203 const Relation_Symbol reversed_relsym = (relsym == LESS_OR_EQUAL)
05204 ? GREATER_OR_EQUAL : LESS_OR_EQUAL;
05205 const Linear_Expression inverse
05206 = expr - (expr_v + denominator)*var;
05207 PPL_DIRTY_TEMP_COEFFICIENT(inverse_den);
05208 neg_assign(inverse_den, expr_v);
05209 const Relation_Symbol inverse_relsym
05210 = (sgn(denominator) == sgn(inverse_den)) ? relsym : reversed_relsym;
05211 generalized_affine_image(var, inverse_relsym, inverse, inverse_den);
05212 return;
05213 }
05214
05215 refine(var, relsym, expr, denominator);
05216
05217 if (is_empty())
05218 return;
05219
05220
05221 forget_all_dbm_constraints(v);
05222
05223 if (marked_shortest_path_reduced())
05224 reset_shortest_path_reduced();
05225 PPL_ASSERT(OK());
05226 }
05227
05228 template <typename T>
05229 void
05230 BD_Shape<T>::generalized_affine_preimage(const Linear_Expression& lhs,
05231 const Relation_Symbol relsym,
05232 const Linear_Expression& rhs) {
05233
05234
05235
05236 const dimension_type bds_space_dim = space_dimension();
05237 const dimension_type lhs_space_dim = lhs.space_dimension();
05238 if (bds_space_dim < lhs_space_dim)
05239 throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)",
05240 "e1", lhs);
05241
05242
05243
05244 const dimension_type rhs_space_dim = rhs.space_dimension();
05245 if (bds_space_dim < rhs_space_dim)
05246 throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)",
05247 "e2", rhs);
05248
05249
05250 if (relsym == LESS_THAN || relsym == GREATER_THAN)
05251 throw_generic("generalized_affine_preimage(e1, r, e2)",
05252 "r is a strict relation symbol and "
05253 "*this is a BD_Shape");
05254
05255 if (relsym == NOT_EQUAL)
05256 throw_generic("generalized_affine_preimage(e1, r, e2)",
05257 "r is the disequality relation symbol and "
05258 "*this is a BD_Shape");
05259
05260
05261 shortest_path_closure_assign();
05262 if (marked_empty())
05263 return;
05264
05265
05266
05267 dimension_type t_lhs = 0;
05268
05269 dimension_type j_lhs = 0;
05270
05271 for (dimension_type i = lhs_space_dim; i-- > 0; )
05272 if (lhs.coefficient(Variable(i)) != 0) {
05273 if (t_lhs++ == 1)
05274 break;
05275 else
05276 j_lhs = i;
05277 }
05278
05279 const Coefficient& b_lhs = lhs.inhomogeneous_term();
05280
05281 if (t_lhs == 0) {
05282
05283
05284 generalized_affine_image(lhs, relsym, rhs);
05285 return;
05286 }
05287 else if (t_lhs == 1) {
05288
05289
05290
05291 Variable v(j_lhs);
05292
05293 const Coefficient& den = lhs.coefficient(v);
05294 Relation_Symbol new_relsym = relsym;
05295 if (den < 0) {
05296 if (relsym == LESS_OR_EQUAL)
05297 new_relsym = GREATER_OR_EQUAL;
05298 else if (relsym == GREATER_OR_EQUAL)
05299 new_relsym = LESS_OR_EQUAL;
05300 }
05301 Linear_Expression expr = rhs - b_lhs;
05302 generalized_affine_preimage(v, new_relsym, expr, den);
05303 }
05304 else {
05305
05306
05307 bool lhs_vars_intersects_rhs_vars = false;
05308 std::vector<Variable> lhs_vars;
05309 for (dimension_type i = lhs_space_dim; i-- > 0; )
05310 if (lhs.coefficient(Variable(i)) != 0) {
05311 lhs_vars.push_back(Variable(i));
05312 if (rhs.coefficient(Variable(i)) != 0)
05313 lhs_vars_intersects_rhs_vars = true;
05314 }
05315
05316 if (!lhs_vars_intersects_rhs_vars) {
05317
05318
05319
05320
05321
05322
05323 switch (relsym) {
05324 case LESS_OR_EQUAL:
05325 refine_no_check(lhs <= rhs);
05326 break;
05327 case EQUAL:
05328 refine_no_check(lhs == rhs);
05329 break;
05330 case GREATER_OR_EQUAL:
05331 refine_no_check(lhs >= rhs);
05332 break;
05333 default:
05334
05335 throw std::runtime_error("PPL internal error");
05336 }
05337
05338
05339 if (is_empty())
05340 return;
05341
05342 for (dimension_type i = lhs_vars.size(); i-- > 0; )
05343 forget_all_dbm_constraints(lhs_vars[i].id() + 1);
05344 }
05345 else {
05346
05347
05348
05349 const Variable new_var = Variable(bds_space_dim);
05350 add_space_dimensions_and_embed(1);
05351
05352
05353
05354
05355 affine_image(new_var, lhs);
05356
05357
05358 shortest_path_closure_assign();
05359 PPL_ASSERT(!marked_empty());
05360 for (dimension_type i = lhs_vars.size(); i-- > 0; )
05361 forget_all_dbm_constraints(lhs_vars[i].id() + 1);
05362
05363
05364
05365
05366
05367
05368
05369 switch (relsym) {
05370 case LESS_OR_EQUAL:
05371 refine_no_check(new_var <= rhs);
05372 break;
05373 case EQUAL:
05374 refine_no_check(new_var == rhs);
05375 break;
05376 case GREATER_OR_EQUAL:
05377 refine_no_check(new_var >= rhs);
05378 break;
05379 default:
05380
05381 throw std::runtime_error("PPL internal error");
05382 }
05383
05384 remove_higher_space_dimensions(bds_space_dim);
05385 }
05386 }
05387
05388 PPL_ASSERT(OK());
05389 }
05390
05391 template <typename T>
05392 Constraint_System
05393 BD_Shape<T>::constraints() const {
05394 Constraint_System cs;
05395 const dimension_type space_dim = space_dimension();
05396 if (space_dim == 0) {
05397 if (marked_empty())
05398 cs = Constraint_System::zero_dim_empty();
05399 }
05400 else if (marked_empty())
05401 cs.insert(0*Variable(space_dim-1) <= -1);
05402 else if (marked_shortest_path_reduced())
05403
05404 cs = minimized_constraints();
05405 else {
05406
05407
05408 cs.insert(0*Variable(space_dim-1) <= 0);
05409
05410 PPL_DIRTY_TEMP_COEFFICIENT(a);
05411 PPL_DIRTY_TEMP_COEFFICIENT(b);
05412
05413 const DB_Row<N>& dbm_0 = dbm[0];
05414 for (dimension_type j = 1; j <= space_dim; ++j) {
05415 const Variable x(j-1);
05416 const N& dbm_0j = dbm_0[j];
05417 const N& dbm_j0 = dbm[j][0];
05418 if (is_additive_inverse(dbm_j0, dbm_0j)) {
05419
05420 numer_denom(dbm_0j, b, a);
05421 cs.insert(a*x == b);
05422 }
05423 else {
05424
05425 if (!is_plus_infinity(dbm_0j)) {
05426 numer_denom(dbm_0j, b, a);
05427 cs.insert(a*x <= b);
05428 }
05429 if (!is_plus_infinity(dbm_j0)) {
05430 numer_denom(dbm_j0, b, a);
05431 cs.insert(-a*x <= b);
05432 }
05433 }
05434 }
05435
05436
05437 for (dimension_type i = 1; i <= space_dim; ++i) {
05438 const Variable y(i-1);
05439 const DB_Row<N>& dbm_i = dbm[i];
05440 for (dimension_type j = i + 1; j <= space_dim; ++j) {
05441 const Variable x(j-1);
05442 const N& dbm_ij = dbm_i[j];
05443 const N& dbm_ji = dbm[j][i];
05444 if (is_additive_inverse(dbm_ji, dbm_ij)) {
05445
05446 numer_denom(dbm_ij, b, a);
05447 cs.insert(a*x - a*y == b);
05448 }
05449 else {
05450
05451 if (!is_plus_infinity(dbm_ij)) {
05452 numer_denom(dbm_ij, b, a);
05453 cs.insert(a*x - a*y <= b);
05454 }
05455 if (!is_plus_infinity(dbm_ji)) {
05456 numer_denom(dbm_ji, b, a);
05457 cs.insert(a*y - a*x <= b);
05458 }
05459 }
05460 }
05461 }
05462 }
05463 return cs;
05464 }
05465
05466 template <typename T>
05467 Constraint_System
05468 BD_Shape<T>::minimized_constraints() const {
05469 shortest_path_reduction_assign();
05470 Constraint_System cs;
05471 const dimension_type space_dim = space_dimension();
05472 if (space_dim == 0) {
05473 if (marked_empty())
05474 cs = Constraint_System::zero_dim_empty();
05475 }
05476 else if (marked_empty())
05477 cs.insert(0*Variable(space_dim-1) <= -1);
05478 else {
05479
05480
05481 cs.insert(0*Variable(space_dim-1) <= 0);
05482
05483 PPL_DIRTY_TEMP_COEFFICIENT(num);
05484 PPL_DIRTY_TEMP_COEFFICIENT(den);
05485
05486
05487 std::vector<dimension_type> leaders;
05488 compute_leaders(leaders);
05489 std::vector<dimension_type> leader_indices;
05490 compute_leader_indices(leaders, leader_indices);
05491 const dimension_type num_leaders = leader_indices.size();
05492
05493
05494 const DB_Row<N>& dbm_0 = dbm[0];
05495 for (dimension_type i = 1; i <= space_dim; ++i) {
05496 const dimension_type leader = leaders[i];
05497 if (i != leader) {
05498
05499 if (leader == 0) {
05500
05501 PPL_ASSERT(!is_plus_infinity(dbm_0[i]));
05502 numer_denom(dbm_0[i], num, den);
05503 cs.insert(den*Variable(i-1) == num);
05504 }
05505 else {
05506
05507 PPL_ASSERT(!is_plus_infinity(dbm[i][leader]));
05508 numer_denom(dbm[i][leader], num, den);
05509 cs.insert(den*Variable(leader-1) - den*Variable(i-1) == num);
05510 }
05511 }
05512 }
05513
05514
05515
05516 const Bit_Row& red_0 = redundancy_dbm[0];
05517 for (dimension_type l_i = 1; l_i < num_leaders; ++l_i) {
05518 const dimension_type i = leader_indices[l_i];
05519 if (!red_0[i]) {
05520 numer_denom(dbm_0[i], num, den);
05521 cs.insert(den*Variable(i-1) <= num);
05522 }
05523 if (!redundancy_dbm[i][0]) {
05524 numer_denom(dbm[i][0], num, den);
05525 cs.insert(-den*Variable(i-1) <= num);
05526 }
05527 }
05528
05529 for (dimension_type l_i = 1; l_i < num_leaders; ++l_i) {
05530 const dimension_type i = leader_indices[l_i];
05531 const DB_Row<N>& dbm_i = dbm[i];
05532 const Bit_Row& red_i = redundancy_dbm[i];
05533 for (dimension_type l_j = l_i + 1; l_j < num_leaders; ++l_j) {
05534 const dimension_type j = leader_indices[l_j];
05535 if (!red_i[j]) {
05536 numer_denom(dbm_i[j], num, den);
05537 cs.insert(den*Variable(j-1) - den*Variable(i-1) <= num);
05538 }
05539 if (!redundancy_dbm[j][i]) {
05540 numer_denom(dbm[j][i], num, den);
05541 cs.insert(den*Variable(i-1) - den*Variable(j-1) <= num);
05542 }
05543 }
05544 }
05545 }
05546 return cs;
05547 }
05548
05549 template <typename T>
05550 void
05551 BD_Shape<T>::expand_space_dimension(Variable var, dimension_type m) {
05552 dimension_type old_dim = space_dimension();
05553
05554 if (var.space_dimension() > old_dim)
05555 throw_dimension_incompatible("expand_space_dimension(v, m)", "v", var);
05556
05557
05558
05559 if (m > max_space_dimension() - space_dimension())
05560 throw_generic("expand_dimension(v, m)",
05561 "adding m new space dimensions exceeds "
05562 "the maximum allowed space dimension");
05563
05564
05565 if (m == 0)
05566 return;
05567
05568
05569 add_space_dimensions_and_embed(m);
05570
05571
05572
05573
05574 const dimension_type v_id = var.id() + 1;
05575 const DB_Row<N>& dbm_v = dbm[v_id];
05576 for (dimension_type i = old_dim + 1; i-- > 0; ) {
05577 DB_Row<N>& dbm_i = dbm[i];
05578 const N& dbm_i_v = dbm[i][v_id];
05579 const N& dbm_v_i = dbm_v[i];
05580 for (dimension_type j = old_dim+1; j < old_dim+m+1; ++j) {
05581 dbm_i[j] = dbm_i_v;
05582 dbm[j][i] = dbm_v_i;
05583 }
05584 }
05585
05586
05587 if (marked_shortest_path_closed())
05588 reset_shortest_path_closed();
05589 PPL_ASSERT(OK());
05590 }
05591
05592 template <typename T>
05593 void
05594 BD_Shape<T>::fold_space_dimensions(const Variables_Set& vars,
05595 Variable dest) {
05596 const dimension_type space_dim = space_dimension();
05597
05598 if (dest.space_dimension() > space_dim)
05599 throw_dimension_incompatible("fold_space_dimensions(vs, v)",
05600 "v", dest);
05601
05602
05603 if (vars.empty())
05604 return;
05605
05606
05607 if (vars.space_dimension() > space_dim)
05608 throw_dimension_incompatible("fold_space_dimensions(vs, v)",
05609 vars.space_dimension());
05610
05611
05612 if (vars.find(dest.id()) != vars.end())
05613 throw_generic("fold_space_dimensions(vs, v)",
05614 "v should not occur in vs");
05615
05616 shortest_path_closure_assign();
05617 if (!marked_empty()) {
05618
05619
05620
05621
05622 const dimension_type v_id = dest.id() + 1;
05623 DB_Row<N>& dbm_v = dbm[v_id];
05624 for (Variables_Set::const_iterator i = vars.begin(),
05625 vs_end = vars.end(); i != vs_end; ++i) {
05626 const dimension_type tbf_id = *i + 1;
05627 const DB_Row<N>& dbm_tbf = dbm[tbf_id];
05628 for (dimension_type j = space_dim + 1; j-- > 0; ) {
05629 max_assign(dbm[j][v_id], dbm[j][tbf_id]);
05630 max_assign(dbm_v[j], dbm_tbf[j]);
05631 }
05632 }
05633 }
05634 remove_space_dimensions(vars);
05635 }
05636
05637 template <typename T>
05638 void
05639 BD_Shape<T>::drop_some_non_integer_points(Complexity_Class) {
05640 if (std::numeric_limits<T>::is_integer)
05641 return;
05642
05643 const dimension_type space_dim = space_dimension();
05644 shortest_path_closure_assign();
05645 if (space_dim == 0 || marked_empty())
05646 return;
05647
05648 for (dimension_type i = space_dim + 1; i-- > 0; ) {
05649 DB_Row<N>& dbm_i = dbm[i];
05650 for (dimension_type j = space_dim + 1; j-- > 0; )
05651 if (i != j)
05652 drop_some_non_integer_points_helper(dbm_i[j]);
05653 }
05654 PPL_ASSERT(OK());
05655 }
05656
05657 template <typename T>
05658 void
05659 BD_Shape<T>::drop_some_non_integer_points(const Variables_Set& vars,
05660 Complexity_Class) {
05661
05662 const dimension_type space_dim = space_dimension();
05663 const dimension_type min_space_dim = vars.space_dimension();
05664 if (space_dim < min_space_dim)
05665 throw_dimension_incompatible("drop_some_non_integer_points(vs, cmpl)",
05666 min_space_dim);
05667
05668 if (std::numeric_limits<T>::is_integer || min_space_dim == 0)
05669 return;
05670
05671 shortest_path_closure_assign();
05672 if (marked_empty())
05673 return;
05674
05675 const Variables_Set::const_iterator v_begin = vars.begin();
05676 const Variables_Set::const_iterator v_end = vars.end();
05677 PPL_ASSERT(v_begin != v_end);
05678
05679 DB_Row<N>& dbm_0 = dbm[0];
05680 for (Variables_Set::const_iterator v_i = v_begin; v_i != v_end; ++v_i) {
05681 const dimension_type i = *v_i + 1;
05682 drop_some_non_integer_points_helper(dbm_0[i]);
05683 drop_some_non_integer_points_helper(dbm[i][0]);
05684 }
05685
05686
05687 for (Variables_Set::const_iterator v_i = v_begin; v_i != v_end; ++v_i) {
05688 const dimension_type i = *v_i + 1;
05689 DB_Row<N>& dbm_i = dbm[i];
05690 for (Variables_Set::const_iterator v_j = v_begin; v_j != v_end; ++v_j) {
05691 const dimension_type j = *v_j + 1;
05692 if (i != j)
05693 drop_some_non_integer_points_helper(dbm_i[j]);
05694 }
05695 }
05696 PPL_ASSERT(OK());
05697 }
05698
05700 template <typename T>
05701 std::ostream&
05702 IO_Operators::operator<<(std::ostream& s, const BD_Shape<T>& c) {
05703 typedef typename BD_Shape<T>::coefficient_type N;
05704 if (c.is_universe())
05705 s << "true";
05706 else {
05707
05708 dimension_type n = c.space_dimension();
05709 if (c.marked_empty())
05710 s << "false";
05711 else {
05712 PPL_DIRTY_TEMP(N, v);
05713 bool first = true;
05714 for (dimension_type i = 0; i <= n; ++i)
05715 for (dimension_type j = i + 1; j <= n; ++j) {
05716 const N& c_i_j = c.dbm[i][j];
05717 const N& c_j_i = c.dbm[j][i];
05718 if (is_additive_inverse(c_j_i, c_i_j)) {
05719
05720 if (first)
05721 first = false;
05722 else
05723 s << ", ";
05724 if (i == 0) {
05725
05726 s << Variable(j - 1);
05727 s << " = " << c_i_j;
05728 }
05729 else {
05730
05731 if (sgn(c_i_j) >= 0) {
05732 s << Variable(j - 1);
05733 s << " - ";
05734 s << Variable(i - 1);
05735 s << " = " << c_i_j;
05736 }
05737 else {
05738 s << Variable(i - 1);
05739 s << " - ";
05740 s << Variable(j - 1);
05741 s << " = " << c_j_i;
05742 }
05743 }
05744 }
05745 else {
05746
05747 if (!is_plus_infinity(c_j_i)) {
05748 if (first)
05749 first = false;
05750 else
05751 s << ", ";
05752 if (i == 0) {
05753
05754 s << Variable(j - 1);
05755 neg_assign_r(v, c_j_i, ROUND_DOWN);
05756 s << " >= " << v;
05757 }
05758 else {
05759
05760 if (sgn(c_j_i) >= 0) {
05761 s << Variable(i - 1);
05762 s << " - ";
05763 s << Variable(j - 1);
05764 s << " <= " << c_j_i;
05765 }
05766 else {
05767 s << Variable(j - 1);
05768 s << " - ";
05769 s << Variable(i - 1);
05770 neg_assign_r(v, c_j_i, ROUND_DOWN);
05771 s << " >= " << v;
05772 }
05773 }
05774 }
05775 if (!is_plus_infinity(c_i_j)) {
05776 if (first)
05777 first = false;
05778 else
05779 s << ", ";
05780 if (i == 0) {
05781
05782 s << Variable(j - 1);
05783 s << " <= " << c_i_j;
05784 }
05785 else {
05786
05787 if (sgn(c_i_j) >= 0) {
05788 s << Variable(j - 1);
05789 s << " - ";
05790 s << Variable(i - 1);
05791 s << " <= " << c_i_j;
05792 }
05793 else {
05794 s << Variable(i - 1);
05795 s << " - ";
05796 s << Variable(j - 1);
05797 neg_assign_r(v, c_i_j, ROUND_DOWN);
05798 s << " >= " << v;
05799 }
05800 }
05801 }
05802 }
05803 }
05804 }
05805 }
05806 return s;
05807 }
05808
05809 template <typename T>
05810 void
05811 BD_Shape<T>::ascii_dump(std::ostream& s) const {
05812 status.ascii_dump(s);
05813 s << "\n";
05814 dbm.ascii_dump(s);
05815 s << "\n";
05816 redundancy_dbm.ascii_dump(s);
05817 }
05818
05819 PPL_OUTPUT_TEMPLATE_DEFINITIONS(T, BD_Shape<T>)
05820
05821 template <typename T>
05822 bool
05823 BD_Shape<T>::ascii_load(std::istream& s) {
05824 if (!status.ascii_load(s))
05825 return false;
05826 if (!dbm.ascii_load(s))
05827 return false;
05828 if (!redundancy_dbm.ascii_load(s))
05829 return false;
05830 return true;
05831 }
05832
05833 template <typename T>
05834 memory_size_type
05835 BD_Shape<T>::external_memory_in_bytes() const {
05836 return dbm.external_memory_in_bytes()
05837 + redundancy_dbm.external_memory_in_bytes();
05838 }
05839
05840 template <typename T>
05841 bool
05842 BD_Shape<T>::OK() const {
05843
05844 if (!dbm.OK())
05845 return false;
05846
05847
05848 if (!status.OK())
05849 return false;
05850
05851
05852 if (marked_empty())
05853 return true;
05854
05855
05856 for (dimension_type i = dbm.num_rows(); i-- > 0; )
05857 for (dimension_type j = dbm.num_rows(); j-- > 0; )
05858 if (is_minus_infinity(dbm[i][j])) {
05859 #ifndef NDEBUG
05860 using namespace Parma_Polyhedra_Library::IO_Operators;
05861 std::cerr << "BD_Shape::dbm[" << i << "][" << j << "] = "
05862 << dbm[i][j] << "!"
05863 << std::endl;
05864 #endif
05865 return false;
05866 }
05867
05868
05869 for (dimension_type i = dbm.num_rows(); i-- > 0; )
05870 if (!is_plus_infinity(dbm[i][i])) {
05871 #ifndef NDEBUG
05872 using namespace Parma_Polyhedra_Library::IO_Operators;
05873 std::cerr << "BD_Shape::dbm[" << i << "][" << i << "] = "
05874 << dbm[i][i] << "! (+inf was expected.)"
05875 << std::endl;
05876 #endif
05877 return false;
05878 }
05879
05880
05881 if (marked_shortest_path_closed()) {
05882 BD_Shape x = *this;
05883 x.reset_shortest_path_closed();
05884 x.shortest_path_closure_assign();
05885 if (x.dbm != dbm) {
05886 #ifndef NDEBUG
05887 std::cerr << "BD_Shape is marked as closed but it is not!"
05888 << std::endl;
05889 #endif
05890 return false;
05891 }
05892 }
05893
05894
05895
05896
05897 if (std::numeric_limits<coefficient_type_base>::is_exact) {
05898
05899
05900 if (marked_shortest_path_reduced()) {
05901
05902 for (dimension_type i = dbm.num_rows(); i-- > 0; )
05903 for (dimension_type j = dbm.num_rows(); j-- > 0; )
05904 if (!redundancy_dbm[i][j] && is_plus_infinity(dbm[i][j])) {
05905 #ifndef NDEBUG
05906 using namespace Parma_Polyhedra_Library::IO_Operators;
05907 std::cerr << "BD_Shape::dbm[" << i << "][" << j << "] = "
05908 << dbm[i][j] << " is marked as non-redundant!"
05909 << std::endl;
05910 #endif
05911 return false;
05912 }
05913
05914 BD_Shape x = *this;
05915 x.reset_shortest_path_reduced();
05916 x.shortest_path_reduction_assign();
05917 if (x.redundancy_dbm != redundancy_dbm) {
05918 #ifndef NDEBUG
05919 std::cerr << "BD_Shape is marked as reduced but it is not!"
05920 << std::endl;
05921 #endif
05922 return false;
05923 }
05924 }
05925 }
05926
05927
05928 return true;
05929 }
05930
05931 template <typename T>
05932 void
05933 BD_Shape<T>::throw_dimension_incompatible(const char* method,
05934 const BD_Shape& y) const {
05935 std::ostringstream s;
05936 s << "PPL::BD_Shape::" << method << ":" << std::endl
05937 << "this->space_dimension() == " << space_dimension()
05938 << ", y->space_dimension() == " << y.space_dimension() << ".";
05939 throw std::invalid_argument(s.str());
05940 }
05941
05942 template <typename T>
05943 void
05944 BD_Shape<T>::throw_dimension_incompatible(const char* method,
05945 dimension_type required_dim) const {
05946 std::ostringstream s;
05947 s << "PPL::BD_Shape::" << method << ":" << std::endl
05948 << "this->space_dimension() == " << space_dimension()
05949 << ", required dimension == " << required_dim << ".";
05950 throw std::invalid_argument(s.str());
05951 }
05952
05953 template <typename T>
05954 void
05955 BD_Shape<T>::throw_dimension_incompatible(const char* method,
05956 const Constraint& c) const {
05957 std::ostringstream s;
05958 s << "PPL::BD_Shape::" << method << ":" << std::endl
05959 << "this->space_dimension() == " << space_dimension()
05960 << ", c->space_dimension == " << c.space_dimension() << ".";
05961 throw std::invalid_argument(s.str());
05962 }
05963
05964 template <typename T>
05965 void
05966 BD_Shape<T>::throw_dimension_incompatible(const char* method,
05967 const Congruence& cg) const {
05968 std::ostringstream s;
05969 s << "PPL::BD_Shape::" << method << ":" << std::endl
05970 << "this->space_dimension() == " << space_dimension()
05971 << ", cg->space_dimension == " << cg.space_dimension() << ".";
05972 throw std::invalid_argument(s.str());
05973 }
05974
05975 template <typename T>
05976 void
05977 BD_Shape<T>::throw_dimension_incompatible(const char* method,
05978 const Generator& g) const {
05979 std::ostringstream s;
05980 s << "PPL::BD_Shape::" << method << ":" << std::endl
05981 << "this->space_dimension() == " << space_dimension()
05982 << ", g->space_dimension == " << g.space_dimension() << ".";
05983 throw std::invalid_argument(s.str());
05984 }
05985
05986 template <typename T>
05987 void
05988 BD_Shape<T>::throw_expression_too_complex(const char* method,
05989 const Linear_Expression& e) {
05990 using namespace IO_Operators;
05991 std::ostringstream s;
05992 s << "PPL::BD_Shape::" << method << ":" << std::endl
05993 << e << " is too complex.";
05994 throw std::invalid_argument(s.str());
05995 }
05996
05997
05998 template <typename T>
05999 void
06000 BD_Shape<T>::throw_dimension_incompatible(const char* method,
06001 const char* name_row,
06002 const Linear_Expression& y) const {
06003 std::ostringstream s;
06004 s << "PPL::BD_Shape::" << method << ":" << std::endl
06005 << "this->space_dimension() == " << space_dimension()
06006 << ", " << name_row << "->space_dimension() == "
06007 << y.space_dimension() << ".";
06008 throw std::invalid_argument(s.str());
06009 }
06010
06011 template <typename T>
06012 void
06013 BD_Shape<T>::throw_generic(const char* method, const char* reason) {
06014 std::ostringstream s;
06015 s << "PPL::BD_Shape::" << method << ":" << std::endl
06016 << reason << ".";
06017 throw std::invalid_argument(s.str());
06018 }
06019
06020 }
06021
06022 #endif // !defined(PPL_BD_Shape_templates_hh)