00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef PPL_Partially_Reduced_Product_templates_hh
00026 #define PPL_Partially_Reduced_Product_templates_hh 1
00027
00028 #include "Grid_Generator.defs.hh"
00029 #include "Grid_Generator_System.defs.hh"
00030 #include "Grid_Generator_System.inlines.hh"
00031 #include <algorithm>
00032 #include <deque>
00033
00034 namespace Parma_Polyhedra_Library {
00035
00036 template <typename D1, typename D2, typename R>
00037 Constraint_System
00038 Partially_Reduced_Product<D1, D2, R>::constraints() const {
00039 reduce();
00040 Constraint_System cs = d2.constraints();
00041 const Constraint_System& cs1 = d1.constraints();
00042 for (Constraint_System::const_iterator i = cs1.begin(),
00043 cs_end = cs1.end(); i != cs_end; ++i)
00044 cs.insert(*i);
00045 return cs;
00046 }
00047
00048 template <typename D1, typename D2, typename R>
00049 Constraint_System
00050 Partially_Reduced_Product<D1, D2, R>::minimized_constraints() const {
00051 reduce();
00052 Constraint_System cs = d2.constraints();
00053 const Constraint_System& cs1 = d1.constraints();
00054 for (Constraint_System::const_iterator i = cs1.begin(),
00055 cs_end = cs1.end(); i != cs_end; ++i)
00056 cs.insert(*i);
00057 if (cs.has_strict_inequalities()) {
00058 NNC_Polyhedron ph(cs);
00059 return ph.minimized_constraints();
00060 }
00061 else {
00062 C_Polyhedron ph(cs);
00063 return ph.minimized_constraints();
00064 }
00065 }
00066
00067 template <typename D1, typename D2, typename R>
00068 Congruence_System
00069 Partially_Reduced_Product<D1, D2, R>::congruences() const {
00070 reduce();
00071 Congruence_System cgs = d2.congruences();
00072 const Congruence_System& cgs1 = d1.congruences();
00073 for (Congruence_System::const_iterator i = cgs1.begin(),
00074 cgs_end = cgs1.end(); i != cgs_end; ++i)
00075 cgs.insert(*i);
00076 return cgs;
00077 }
00078
00079 template <typename D1, typename D2, typename R>
00080 Congruence_System
00081 Partially_Reduced_Product<D1, D2, R>::minimized_congruences() const {
00082 reduce();
00083 Congruence_System cgs = d2.congruences();
00084 const Congruence_System& cgs1 = d1.congruences();
00085 for (Congruence_System::const_iterator i = cgs1.begin(),
00086 cgs_end = cgs1.end(); i != cgs_end; ++i)
00087 cgs.insert(*i);
00088 Grid gr(cgs);
00089 return gr.minimized_congruences();
00090 }
00091
00092 template <typename D1, typename D2, typename R>
00093 void
00094 Partially_Reduced_Product<D1, D2, R>
00095 ::add_recycled_constraints(Constraint_System& cs) {
00096 if (d1.can_recycle_constraint_systems()) {
00097 d2.refine_with_constraints(cs);
00098 d1.add_recycled_constraints(cs);
00099 }
00100 else
00101 if (d2.can_recycle_constraint_systems()) {
00102 d1.refine_with_constraints(cs);
00103 d2.add_recycled_constraints(cs);
00104 }
00105 else {
00106 d1.add_constraints(cs);
00107 d2.add_constraints(cs);
00108 }
00109 clear_reduced_flag();
00110 }
00111
00112 template <typename D1, typename D2, typename R>
00113 void
00114 Partially_Reduced_Product<D1, D2, R>
00115 ::add_recycled_congruences(Congruence_System& cgs) {
00116 if (d1.can_recycle_congruence_systems()) {
00117 d2.refine_with_congruences(cgs);
00118 d1.add_recycled_congruences(cgs);
00119 }
00120 else
00121 if (d2.can_recycle_congruence_systems()) {
00122 d1.refine_with_congruences(cgs);
00123 d2.add_recycled_congruences(cgs);
00124 }
00125 else {
00126 d1.add_congruences(cgs);
00127 d2.add_congruences(cgs);
00128 }
00129 clear_reduced_flag();
00130 }
00131
00132 template <typename D1, typename D2, typename R>
00133 Poly_Gen_Relation
00134 Partially_Reduced_Product<D1, D2, R>
00135 ::relation_with(const Generator& g) const {
00136 reduce();
00137 if (Poly_Gen_Relation::nothing() == d1.relation_with(g)
00138 || Poly_Gen_Relation::nothing() == d2.relation_with(g))
00139 return Poly_Gen_Relation::nothing();
00140 else
00141 return Poly_Gen_Relation::subsumes();
00142 }
00143
00144 template <typename D1, typename D2, typename R>
00145 Poly_Con_Relation
00146 Partially_Reduced_Product<D1, D2, R>
00147 ::relation_with(const Constraint& c) const {
00148 reduce();
00149 Poly_Con_Relation relation1 = d1.relation_with(c);
00150 Poly_Con_Relation relation2 = d2.relation_with(c);
00151
00152 Poly_Con_Relation result = Poly_Con_Relation::nothing();
00153
00154 if (relation1.implies(Poly_Con_Relation::is_included()))
00155 result = result && Poly_Con_Relation::is_included();
00156 else if (relation2.implies(Poly_Con_Relation::is_included()))
00157 result = result && Poly_Con_Relation::is_included();
00158 if (relation1.implies(Poly_Con_Relation::saturates()))
00159 result = result && Poly_Con_Relation::saturates();
00160 else if (relation2.implies(Poly_Con_Relation::saturates()))
00161 result = result && Poly_Con_Relation::saturates();
00162 if (relation1.implies(Poly_Con_Relation::is_disjoint()))
00163 result = result && Poly_Con_Relation::is_disjoint();
00164 else if (relation2.implies(Poly_Con_Relation::is_disjoint()))
00165 result = result && Poly_Con_Relation::is_disjoint();
00166
00167 return result;
00168 }
00169
00170 template <typename D1, typename D2, typename R>
00171 Poly_Con_Relation
00172 Partially_Reduced_Product<D1, D2, R>
00173 ::relation_with(const Congruence& cg) const {
00174 reduce();
00175 Poly_Con_Relation relation1 = d1.relation_with(cg);
00176 Poly_Con_Relation relation2 = d2.relation_with(cg);
00177
00178 Poly_Con_Relation result = Poly_Con_Relation::nothing();
00179
00180 if (relation1.implies(Poly_Con_Relation::is_included()))
00181 result = result && Poly_Con_Relation::is_included();
00182 else if (relation2.implies(Poly_Con_Relation::is_included()))
00183 result = result && Poly_Con_Relation::is_included();
00184 if (relation1.implies(Poly_Con_Relation::saturates()))
00185 result = result && Poly_Con_Relation::saturates();
00186 else if (relation2.implies(Poly_Con_Relation::saturates()))
00187 result = result && Poly_Con_Relation::saturates();
00188 if (relation1.implies(Poly_Con_Relation::is_disjoint()))
00189 result = result && Poly_Con_Relation::is_disjoint();
00190 else if (relation2.implies(Poly_Con_Relation::is_disjoint()))
00191 result = result && Poly_Con_Relation::is_disjoint();
00192
00193 return result;
00194 }
00195
00196 template <typename D1, typename D2, typename R>
00197 bool
00198 Partially_Reduced_Product<D1, D2, R>
00199 ::maximize(const Linear_Expression& expr,
00200 Coefficient& sup_n,
00201 Coefficient& sup_d,
00202 bool& maximum) const {
00203 reduce();
00204
00205 if (is_empty())
00206 return false;
00207
00208 PPL_DIRTY_TEMP_COEFFICIENT(sup1_n);
00209 PPL_DIRTY_TEMP_COEFFICIENT(sup1_d);
00210 PPL_DIRTY_TEMP_COEFFICIENT(sup2_n);
00211 PPL_DIRTY_TEMP_COEFFICIENT(sup2_d);
00212 bool maximum1;
00213 bool maximum2;
00214 bool r1 = d1.maximize(expr, sup1_n, sup1_d, maximum1);
00215 bool r2 = d2.maximize(expr, sup2_n, sup2_d, maximum2);
00216
00217 if (!r1 && !r2)
00218 return false;
00219
00220 if (!r1) {
00221 sup_n = sup2_n;
00222 sup_d = sup2_d;
00223 maximum = maximum2;
00224 return true;
00225 }
00226
00227 if (!r2) {
00228 sup_n = sup1_n;
00229 sup_d = sup1_d;
00230 maximum = maximum1;
00231 return true;
00232 }
00233
00234 if (sup2_d * sup1_n >= sup1_d * sup2_n) {
00235 sup_n = sup1_n;
00236 sup_d = sup1_d;
00237 maximum = maximum1;
00238 }
00239 else {
00240 sup_n = sup2_n;
00241 sup_d = sup2_d;
00242 maximum = maximum2;
00243 }
00244 return true;
00245 }
00246
00247 template <typename D1, typename D2, typename R>
00248 bool
00249 Partially_Reduced_Product<D1, D2, R>
00250 ::minimize(const Linear_Expression& expr,
00251 Coefficient& inf_n,
00252 Coefficient& inf_d,
00253 bool& minimum) const {
00254 reduce();
00255
00256 if (is_empty())
00257 return false;
00258 PPL_ASSERT(reduced);
00259
00260 PPL_DIRTY_TEMP_COEFFICIENT(inf1_n);
00261 PPL_DIRTY_TEMP_COEFFICIENT(inf1_d);
00262 PPL_DIRTY_TEMP_COEFFICIENT(inf2_n);
00263 PPL_DIRTY_TEMP_COEFFICIENT(inf2_d);
00264 bool minimum1;
00265 bool minimum2;
00266 bool r1 = d1.minimize(expr, inf1_n, inf1_d, minimum1);
00267 bool r2 = d2.minimize(expr, inf2_n, inf2_d, minimum2);
00268
00269 if (!r1 && !r2)
00270 return false;
00271
00272 if (!r1) {
00273 inf_n = inf2_n;
00274 inf_d = inf2_d;
00275 minimum = minimum2;
00276 return true;
00277 }
00278
00279 if (!r2) {
00280 inf_n = inf1_n;
00281 inf_d = inf1_d;
00282 minimum = minimum1;
00283 return true;
00284 }
00285
00286 if (inf2_d * inf1_n <= inf1_d * inf2_n) {
00287 inf_n = inf1_n;
00288 inf_d = inf1_d;
00289 minimum = minimum1;
00290 }
00291 else {
00292 inf_n = inf2_n;
00293 inf_d = inf2_d;
00294 minimum = minimum2;
00295 }
00296 return true;
00297 }
00298
00299 template <typename D1, typename D2, typename R>
00300 bool
00301 Partially_Reduced_Product<D1, D2, R>
00302 ::maximize(const Linear_Expression& expr,
00303 Coefficient& sup_n,
00304 Coefficient& sup_d,
00305 bool& maximum,
00306 Generator& pnt) const {
00307 reduce();
00308
00309 if (is_empty())
00310 return false;
00311 PPL_ASSERT(reduced);
00312
00313 PPL_DIRTY_TEMP_COEFFICIENT(sup1_n);
00314 PPL_DIRTY_TEMP_COEFFICIENT(sup1_d);
00315 PPL_DIRTY_TEMP_COEFFICIENT(sup2_n);
00316 PPL_DIRTY_TEMP_COEFFICIENT(sup2_d);
00317 bool maximum1;
00318 bool maximum2;
00319 Generator pnt1(point());
00320 Generator pnt2(point());
00321 bool r1 = d1.maximize(expr, sup1_n, sup1_d, maximum1, pnt1);
00322 bool r2 = d2.maximize(expr, sup2_n, sup2_d, maximum2, pnt2);
00323
00324 if (!r1 && !r2)
00325 return false;
00326
00327 if (!r1) {
00328 sup_n = sup2_n;
00329 sup_d = sup2_d;
00330 maximum = maximum2;
00331 pnt = pnt2;
00332 return true;
00333 }
00334
00335 if (!r2) {
00336 sup_n = sup1_n;
00337 sup_d = sup1_d;
00338 maximum = maximum1;
00339 pnt = pnt1;
00340 return true;
00341 }
00342
00343 if (sup2_d * sup1_n >= sup1_d * sup2_n) {
00344 sup_n = sup1_n;
00345 sup_d = sup1_d;
00346 maximum = maximum1;
00347 pnt = pnt1;
00348 }
00349 else {
00350 sup_n = sup2_n;
00351 sup_d = sup2_d;
00352 maximum = maximum2;
00353 pnt = pnt2;
00354 }
00355 return true;
00356 }
00357
00358 template <typename D1, typename D2, typename R>
00359 bool
00360 Partially_Reduced_Product<D1, D2, R>
00361 ::minimize(const Linear_Expression& expr,
00362 Coefficient& inf_n,
00363 Coefficient& inf_d,
00364 bool& minimum,
00365 Generator& pnt) const {
00366 reduce();
00367
00368 if (is_empty())
00369 return false;
00370 PPL_ASSERT(reduced);
00371
00372 PPL_DIRTY_TEMP_COEFFICIENT(inf1_n);
00373 PPL_DIRTY_TEMP_COEFFICIENT(inf1_d);
00374 PPL_DIRTY_TEMP_COEFFICIENT(inf2_n);
00375 PPL_DIRTY_TEMP_COEFFICIENT(inf2_d);
00376 bool minimum1;
00377 bool minimum2;
00378 Generator pnt1(point());
00379 Generator pnt2(point());
00380 bool r1 = d1.minimize(expr, inf1_n, inf1_d, minimum1, pnt1);
00381 bool r2 = d2.minimize(expr, inf2_n, inf2_d, minimum2, pnt2);
00382
00383 if (!r1 && !r2)
00384 return false;
00385
00386 if (!r1) {
00387 inf_n = inf2_n;
00388 inf_d = inf2_d;
00389 minimum = minimum2;
00390 pnt = pnt2;
00391 return true;
00392 }
00393
00394 if (!r2) {
00395 inf_n = inf1_n;
00396 inf_d = inf1_d;
00397 minimum = minimum1;
00398 pnt = pnt1;
00399 return true;
00400 }
00401
00402 if (inf2_d * inf1_n <= inf1_d * inf2_n) {
00403 inf_n = inf1_n;
00404 inf_d = inf1_d;
00405 minimum = minimum1;
00406 pnt = pnt1;
00407 }
00408 else {
00409 inf_n = inf2_n;
00410 inf_d = inf2_d;
00411 minimum = minimum2;
00412 pnt = pnt2;
00413 }
00414 return true;
00415 }
00416
00417 template <typename D1, typename D2, typename R>
00418 inline bool
00419 Partially_Reduced_Product<D1, D2, R>::OK() const {
00420 if (reduced) {
00421 Partially_Reduced_Product<D1, D2, R> pd1 = *this;
00422 Partially_Reduced_Product<D1, D2, R> pd2 = *this;
00423
00424 pd1.clear_reduced_flag();
00425 pd1.reduce();
00426 if (pd1 != pd2)
00427 return false;
00428 }
00429 return d1.OK() && d2.OK();
00430 }
00431
00432 template <typename D1, typename D2, typename R>
00433 bool
00434 Partially_Reduced_Product<D1, D2, R>::ascii_load(std::istream& s) {
00435 const char yes = '+';
00436 const char no = '-';
00437 std::string str;
00438 if (!(s >> str) || str != "Partially_Reduced_Product")
00439 return false;
00440 if (!(s >> str)
00441 || (str[0] != yes && str[0] != no)
00442 || str.substr(1) != "reduced")
00443 return false;
00444 reduced = (str[0] == yes);
00445 return ((s >> str) && str == "Domain"
00446 && (s >> str) && str == "1:"
00447 && d1.ascii_load(s)
00448 && (s >> str) && str == "Domain"
00449 && (s >> str) && str == "2:"
00450 && d2.ascii_load(s));
00451 }
00452
00453 template <typename D1, typename D2>
00454 void Smash_Reduction<D1, D2>::product_reduce(D1& d1, D2& d2) {
00455 if (d2.is_empty()) {
00456 if (!d1.is_empty()) {
00457 D1 new_d1(d1.space_dimension(), EMPTY);
00458 std::swap(d1, new_d1);
00459 }
00460 }
00461 else if (d1.is_empty()) {
00462 D2 new_d2(d2.space_dimension(), EMPTY);
00463 std::swap(d2, new_d2);
00464 }
00465 }
00466
00467 template <typename D1, typename D2>
00468 void Constraints_Reduction<D1, D2>::product_reduce(D1& d1, D2& d2) {
00469 if (d1.is_empty() || d2.is_empty()) {
00470
00471 Parma_Polyhedra_Library::Smash_Reduction<D1, D2> sr;
00472 sr.product_reduce(d1, d2);
00473 return;
00474 }
00475 else {
00476 dimension_type space_dim = d1.space_dimension();
00477 d1.refine_with_constraints(d2.minimized_constraints());
00478 if (d1.is_empty()) {
00479 D2 new_d2(space_dim, EMPTY);
00480 std::swap(d2, new_d2);
00481 return;
00482 }
00483 d2.refine_with_constraints(d1.minimized_constraints());
00484 if (d2.is_empty()) {
00485 D1 new_d1(space_dim, EMPTY);
00486 std::swap(d1, new_d1);
00487 }
00488 }
00489 }
00490
00491
00492
00493
00494
00495
00496 template <typename D1, typename D2>
00497 bool shrink_to_congruence_no_check(D1& d1, D2& d2, const Congruence& cg) {
00498
00499 PPL_ASSERT(cg.modulus() != 0);
00500
00501 PPL_ASSERT(d1.relation_with(cg) == Poly_Con_Relation::is_included());
00502
00503
00504 Linear_Expression e;
00505 for (dimension_type i = cg.space_dimension(); i-- > 0; )
00506 e += cg.coefficient(Variable(i)) * Variable(i);
00507 e += cg.inhomogeneous_term();
00508
00509
00510
00511 PPL_DIRTY_TEMP_COEFFICIENT(max_num);
00512 PPL_DIRTY_TEMP_COEFFICIENT(max_den);
00513 bool max_included;
00514 PPL_DIRTY_TEMP_COEFFICIENT(min_num);
00515 PPL_DIRTY_TEMP_COEFFICIENT(min_den);
00516 bool min_included;
00517 if (d2.maximize(e, max_num, max_den, max_included)) {
00518 if (d2.minimize(e, min_num, min_den, min_included)) {
00519
00520 max_num *= min_den;
00521 min_num *= max_den;
00522 PPL_DIRTY_TEMP_COEFFICIENT(den);
00523 PPL_DIRTY_TEMP_COEFFICIENT(mod);
00524 den = max_den * min_den;
00525 mod = cg.modulus() * den;
00526
00527
00528
00529
00530 PPL_DIRTY_TEMP_COEFFICIENT(mod2);
00531 mod2 = 2 * mod;
00532 if (max_num - min_num < mod2
00533 || (max_num - min_num == mod2 && (!max_included || !min_included)))
00534 {
00535 PPL_DIRTY_TEMP_COEFFICIENT(shrink_amount);
00536 PPL_DIRTY_TEMP_COEFFICIENT(max_decreased);
00537 PPL_DIRTY_TEMP_COEFFICIENT(min_increased);
00538
00539 shrink_amount = max_num % mod;
00540 if (!max_included && shrink_amount == 0)
00541 shrink_amount = mod;
00542 if (shrink_amount < 0)
00543 shrink_amount += mod;
00544 max_decreased = max_num - shrink_amount;
00545
00546 shrink_amount = min_num % mod;
00547 if (!min_included && shrink_amount == 0)
00548 shrink_amount = - mod;
00549 if (shrink_amount > 0)
00550 shrink_amount -= mod;
00551 min_increased = min_num - shrink_amount;
00552 if (max_decreased == min_increased) {
00553
00554
00555 Constraint new_c(den * e == min_increased);
00556 d1.refine_with_constraint(new_c);
00557 d2.refine_with_constraint(new_c);
00558 return true;
00559 }
00560 else {
00561 if (max_decreased < min_increased) {
00562
00563
00564 D1 new_d1(d1.space_dimension(), EMPTY);
00565 std::swap(d1, new_d1);
00566 D2 new_d2(d2.space_dimension(), EMPTY);
00567 std::swap(d2, new_d2);
00568 return false;
00569 }
00570 }
00571 }
00572 }
00573 }
00574 return true;
00575 }
00576
00577 template <typename D1, typename D2>
00578 void
00579 Congruences_Reduction<D1, D2>::product_reduce(D1& d1, D2& d2) {
00580 if (d1.is_empty() || d2.is_empty()) {
00581
00582 Parma_Polyhedra_Library::Smash_Reduction<D1, D2> sr;
00583 sr.product_reduce(d1, d2);
00584 return;
00585 }
00586
00587 const Congruence_System cgs1 = d1.minimized_congruences();
00588 for (Congruence_System::const_iterator i = cgs1.begin(),
00589 cgs_end = cgs1.end(); i != cgs_end; ++i) {
00590 const Congruence& cg1 = *i;
00591 if (cg1.is_equality())
00592 d2.refine_with_congruence(cg1);
00593 else
00594 if (!Parma_Polyhedra_Library::
00595 shrink_to_congruence_no_check(d1, d2, cg1))
00596
00597 return;
00598 }
00599
00600 const Congruence_System cgs2 = d2.minimized_congruences();
00601 for (Congruence_System::const_iterator i = cgs2.begin(),
00602 cgs_end = cgs2.end(); i != cgs_end; ++i) {
00603 const Congruence& cg2 = *i;
00604 if (cg2.is_equality())
00605 d1.refine_with_congruence(cg2);
00606 else
00607 if (!Parma_Polyhedra_Library::
00608 shrink_to_congruence_no_check(d2, d1, cg2))
00609
00610 return;
00611 }
00612 }
00613
00614 template <typename D1, typename D2>
00615 void
00616 Shape_Preserving_Reduction<D1, D2>::product_reduce(D1& d1, D2& d2) {
00617
00618 Parma_Polyhedra_Library::Congruences_Reduction<D1, D2> cgr;
00619 cgr.product_reduce(d1, d2);
00620 if (d1.is_empty())
00621 return;
00622
00623 PPL_DIRTY_TEMP_COEFFICIENT(freq_n);
00624 PPL_DIRTY_TEMP_COEFFICIENT(freq_d);
00625 PPL_DIRTY_TEMP_COEFFICIENT(val_n);
00626 PPL_DIRTY_TEMP_COEFFICIENT(val_d);
00627
00628
00629 Constraint_System cs = d2.minimized_constraints();
00630 Constraint_System refining_cs;
00631 for (Constraint_System::const_iterator i = cs.begin(),
00632 cs_end = cs.end(); i != cs_end; ++i) {
00633 const Constraint& c = *i;
00634 if (c.is_equality())
00635 continue;
00636
00637
00638 Linear_Expression le(c);
00639 if (!d1.frequency(le, freq_n, freq_d, val_n, val_d))
00640
00641 continue;
00642 if (val_n == 0)
00643
00644 continue;
00645
00646
00647 if (val_n < 0) {
00648 val_n = val_n*freq_d + val_d*freq_n;
00649 val_d *= freq_d;
00650 }
00651 le *= val_d;
00652 le -= val_n;
00653 refining_cs.insert(le >= 0);
00654 }
00655 d2.refine_with_constraints(refining_cs);
00656
00657
00658 cs = d1.minimized_constraints();
00659 refining_cs.clear();
00660 for (Constraint_System::const_iterator i = cs.begin(),
00661 cs_end = cs.end(); i != cs_end; ++i) {
00662 const Constraint& c = *i;
00663 if (c.is_equality())
00664
00665 continue;
00666
00667
00668 Linear_Expression le(c);
00669 if (!d2.frequency(le, freq_n, freq_d, val_n, val_d))
00670
00671 continue;
00672 if (val_n == 0)
00673
00674 continue;
00675
00676
00677 if (val_n < 0) {
00678 val_n = val_n*freq_d + val_d*freq_n;
00679 val_d *= freq_d;
00680 }
00681 le *= val_d;
00682 le -= val_n;
00683 refining_cs.insert(le >= 0);
00684 }
00685 d1.refine_with_constraints(refining_cs);
00686
00687
00688
00689 Parma_Polyhedra_Library::Constraints_Reduction<D1, D2> cr;
00690 cr.product_reduce(d1, d2);
00691 }
00692
00693 }
00694
00695 #endif // !defined(PPL_Partially_Reduced_Product_templates_hh)