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_termination_templates_hh
00025 #define PPL_termination_templates_hh 1
00026
00027 #include "globals.defs.hh"
00028 #include "Variable.defs.hh"
00029 #include "Generator.defs.hh"
00030 #include "Constraint_System.defs.hh"
00031 #include "C_Polyhedron.defs.hh"
00032 #include "NNC_Polyhedron.defs.hh"
00033
00034 #include <stdexcept>
00035
00036 #define PRINT_DEBUG_INFO 0
00037
00038 #if PRINT_DEBUG_INFO
00039 #include <iostream>
00040 #endif
00041
00042 namespace Parma_Polyhedra_Library {
00043
00044 namespace Implementation {
00045
00046 namespace Termination {
00047
00048 #if PRINT_DEBUG_INFO
00049 static dimension_type output_function_MS_n;
00050 static dimension_type output_function_MS_m;
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 static int output_function_MS_which = -1;
00062
00063
00064
00065
00066
00067 inline void
00068 output_function_MS(std::ostream& s, const Variable& v) {
00069 dimension_type id = v.id();
00070 switch (output_function_MS_which) {
00071 case 0:
00072 if (id < output_function_MS_n)
00073 s << "x'" << id + 1;
00074 else if (id < 2*output_function_MS_n)
00075 s << "x" << id - output_function_MS_n + 1;
00076 else
00077 s << "WHAT?";
00078 break;
00079 case 1:
00080 if (id < output_function_MS_n)
00081 s << "mu" << id + 1;
00082 else if (id == output_function_MS_n)
00083 s << "WHAT?";
00084 else if (id <= output_function_MS_n + output_function_MS_m)
00085 s << "y" << id - output_function_MS_n;
00086 else
00087 s << "WHAT?";
00088 break;
00089 case 2:
00090 case 4:
00091 if (id < output_function_MS_n)
00092 s << "mu" << id + 1;
00093 else if (id == output_function_MS_n)
00094 s << "mu0";
00095 else if (output_function_MS_which == 2
00096 && id <= output_function_MS_n + output_function_MS_m + 2)
00097 s << "z" << id - output_function_MS_n;
00098 else
00099 s << "WHAT?";
00100 break;
00101 case 3:
00102 if (id < output_function_MS_n)
00103 s << "mu" << id + 1;
00104 else if (id == output_function_MS_n)
00105 s << "mu0";
00106 else if (id <= output_function_MS_n + output_function_MS_m)
00107 s << "y" << id - output_function_MS_n;
00108 else if (id <= output_function_MS_n + 2*output_function_MS_m + 2)
00109 s << "z" << id - (output_function_MS_n + output_function_MS_m);
00110 else
00111 s << "WHAT?";
00112 break;
00113 default:
00114 abort();
00115 break;
00116 }
00117 }
00118
00119 static dimension_type output_function_PR_s;
00120 static dimension_type output_function_PR_r;
00121
00122
00123
00124
00125
00126 inline void
00127 output_function_PR(std::ostream& s, const Variable& v) {
00128 dimension_type id = v.id();
00129 if (id < output_function_PR_s)
00130 s << "u3_" << id + 1;
00131 else if (id < output_function_PR_s + output_function_PR_r)
00132 s << "u2_" << id - output_function_PR_s + 1;
00133 else if (id < output_function_PR_s + 2*output_function_PR_r)
00134 s << "u1_" << id - (output_function_PR_s + output_function_PR_r) + 1;
00135 else
00136 s << "WHAT?";
00137 }
00138 #endif
00139
00140 void
00141 assign_all_inequalities_approximation(const Constraint_System& cs_in,
00142 Constraint_System& cs_out);
00143
00144 template <typename PSET>
00145 inline void
00146 assign_all_inequalities_approximation(const PSET& pset,
00147 Constraint_System& cs) {
00148 assign_all_inequalities_approximation(pset.minimized_constraints(), cs);
00149 }
00150
00151 template <>
00152 void
00153 assign_all_inequalities_approximation(const C_Polyhedron& ph,
00154 Constraint_System& cs);
00155
00156 void
00157 shift_unprimed_variables(Constraint_System& cs);
00158
00159 template <typename PSET>
00160 void
00161 assign_all_inequalities_approximation(const PSET& pset_before,
00162 const PSET& pset_after,
00163 Constraint_System& cs) {
00164 assign_all_inequalities_approximation(pset_before, cs);
00165 shift_unprimed_variables(cs);
00166 Constraint_System cs_after;
00167 assign_all_inequalities_approximation(pset_after, cs_after);
00168
00169 for (Constraint_System::const_iterator i = cs_after.begin(),
00170 cs_after_end = cs_after.end(); i != cs_after_end; ++i)
00171 cs.insert(*i);
00172 }
00173
00174 bool
00175 termination_test_MS(const Constraint_System& cs);
00176
00177 bool
00178 one_affine_ranking_function_MS(const Constraint_System& cs,
00179 Generator& mu);
00180
00181 void
00182 all_affine_ranking_functions_MS(const Constraint_System& cs,
00183 C_Polyhedron& mu_space);
00184
00185 void
00186 all_affine_quasi_ranking_functions_MS(const Constraint_System& cs,
00187 C_Polyhedron& decreasing_mu_space,
00188 C_Polyhedron& bounded_mu_space);
00189
00190 bool
00191 termination_test_PR(const Constraint_System& cs_before,
00192 const Constraint_System& cs_after);
00193
00194 bool
00195 one_affine_ranking_function_PR(const Constraint_System& cs_before,
00196 const Constraint_System& cs_after,
00197 Generator& mu);
00198
00199 void
00200 all_affine_ranking_functions_PR(const Constraint_System& cs_before,
00201 const Constraint_System& cs_after,
00202 NNC_Polyhedron& mu_space);
00203
00204 bool
00205 termination_test_PR_original(const Constraint_System& cs);
00206
00207 bool
00208 one_affine_ranking_function_PR_original(const Constraint_System& cs,
00209 Generator& mu);
00210
00211 void
00212 all_affine_ranking_functions_PR_original(const Constraint_System& cs,
00213 NNC_Polyhedron& mu_space);
00214
00215 }
00216
00217 }
00218
00219 template <typename PSET>
00220 bool
00221 termination_test_MS(const PSET& pset) {
00222 const dimension_type space_dim = pset.space_dimension();
00223 if (space_dim % 2 != 0) {
00224 std::ostringstream s;
00225 s << "PPL::termination_test_MS(pset):\n"
00226 "pset.space_dimension() == " << space_dim
00227 << " is odd.";
00228 throw std::invalid_argument(s.str());
00229 }
00230
00231 using namespace Implementation::Termination;
00232 Constraint_System cs;
00233 assign_all_inequalities_approximation(pset, cs);
00234 return termination_test_MS(cs);
00235 }
00236
00237 template <typename PSET>
00238 bool
00239 termination_test_MS_2(const PSET& pset_before, const PSET& pset_after) {
00240 const dimension_type before_space_dim = pset_before.space_dimension();
00241 const dimension_type after_space_dim = pset_after.space_dimension();
00242 if (after_space_dim != 2*before_space_dim) {
00243 std::ostringstream s;
00244 s << "PPL::termination_test_MS_2(pset_before, pset_after):\n"
00245 "pset_before.space_dimension() == " << before_space_dim
00246 << ", pset_after.space_dimension() == " << after_space_dim
00247 << ";\nthe latter should be twice the former.";
00248 throw std::invalid_argument(s.str());
00249 }
00250
00251 using namespace Implementation::Termination;
00252 Constraint_System cs;
00253 assign_all_inequalities_approximation(pset_before, pset_after, cs);
00254 return termination_test_MS(cs);
00255 }
00256
00257 template <typename PSET>
00258 bool
00259 one_affine_ranking_function_MS(const PSET& pset, Generator& mu) {
00260 const dimension_type space_dim = pset.space_dimension();
00261 if (space_dim % 2 != 0) {
00262 std::ostringstream s;
00263 s << "PPL::one_affine_ranking_function_MS(pset, mu):\n"
00264 "pset.space_dimension() == " << space_dim
00265 << " is odd.";
00266 throw std::invalid_argument(s.str());
00267 }
00268
00269 using namespace Implementation::Termination;
00270 Constraint_System cs;
00271 assign_all_inequalities_approximation(pset, cs);
00272 return one_affine_ranking_function_MS(cs, mu);
00273 }
00274
00275 template <typename PSET>
00276 bool
00277 one_affine_ranking_function_MS_2(const PSET& pset_before,
00278 const PSET& pset_after,
00279 Generator& mu) {
00280 const dimension_type before_space_dim = pset_before.space_dimension();
00281 const dimension_type after_space_dim = pset_after.space_dimension();
00282 if (after_space_dim != 2*before_space_dim) {
00283 std::ostringstream s;
00284 s << "PPL::one_affine_ranking_function_MS_2(pset_before, pset_after, mu):\n"
00285 "pset_before.space_dimension() == " << before_space_dim
00286 << ", pset_after.space_dimension() == " << after_space_dim
00287 << ";\nthe latter should be twice the former.";
00288 throw std::invalid_argument(s.str());
00289 }
00290
00291 using namespace Implementation::Termination;
00292 Constraint_System cs;
00293 assign_all_inequalities_approximation(pset_before, pset_after, cs);
00294 return one_affine_ranking_function_MS(cs, mu);
00295 }
00296
00297 template <typename PSET>
00298 void
00299 all_affine_ranking_functions_MS(const PSET& pset, C_Polyhedron& mu_space) {
00300 const dimension_type space_dim = pset.space_dimension();
00301 if (space_dim % 2 != 0) {
00302 std::ostringstream s;
00303 s << "PPL::all_affine_ranking_functions_MS(pset, mu_space):\n"
00304 "pset.space_dimension() == " << space_dim
00305 << " is odd.";
00306 throw std::invalid_argument(s.str());
00307 }
00308
00309 if (pset.is_empty()) {
00310 mu_space = C_Polyhedron(1 + space_dim/2, UNIVERSE);
00311 return;
00312 }
00313
00314 using namespace Implementation::Termination;
00315 Constraint_System cs;
00316 assign_all_inequalities_approximation(pset, cs);
00317 all_affine_ranking_functions_MS(cs, mu_space);
00318 }
00319
00320 template <typename PSET>
00321 void
00322 all_affine_ranking_functions_MS_2(const PSET& pset_before,
00323 const PSET& pset_after,
00324 C_Polyhedron& mu_space) {
00325 const dimension_type before_space_dim = pset_before.space_dimension();
00326 const dimension_type after_space_dim = pset_after.space_dimension();
00327 if (after_space_dim != 2*before_space_dim) {
00328 std::ostringstream s;
00329 s << "PPL::all_affine_ranking_functions_MS_2"
00330 << "(pset_before, pset_after, mu_space):\n"
00331 << "pset_before.space_dimension() == " << before_space_dim
00332 << ", pset_after.space_dimension() == " << after_space_dim
00333 << ";\nthe latter should be twice the former.";
00334 throw std::invalid_argument(s.str());
00335 }
00336
00337 if (pset_before.is_empty()) {
00338 mu_space = C_Polyhedron(1 + before_space_dim, UNIVERSE);
00339 return;
00340 }
00341
00342 using namespace Implementation::Termination;
00343 Constraint_System cs;
00344 assign_all_inequalities_approximation(pset_before, pset_after, cs);
00345 all_affine_ranking_functions_MS(cs, mu_space);
00346 }
00347
00348 template <typename PSET>
00349 void
00350 all_affine_quasi_ranking_functions_MS(const PSET& pset,
00351 C_Polyhedron& decreasing_mu_space,
00352 C_Polyhedron& bounded_mu_space) {
00353 const dimension_type space_dim = pset.space_dimension();
00354 if (space_dim % 2 != 0) {
00355 std::ostringstream s;
00356 s << "PPL::all_affine_quasi_ranking_functions_MS"
00357 << "(pset, decr_space, bounded_space):\n"
00358 << "pset.space_dimension() == " << space_dim
00359 << " is odd.";
00360 throw std::invalid_argument(s.str());
00361 }
00362
00363 if (pset.is_empty()) {
00364 decreasing_mu_space = C_Polyhedron(1 + space_dim/2, UNIVERSE);
00365 bounded_mu_space = decreasing_mu_space;
00366 return;
00367 }
00368
00369 using namespace Implementation::Termination;
00370 Constraint_System cs;
00371 assign_all_inequalities_approximation(pset, cs);
00372 all_affine_quasi_ranking_functions_MS(cs,
00373 decreasing_mu_space,
00374 bounded_mu_space);
00375 }
00376
00377 template <typename PSET>
00378 void
00379 all_affine_quasi_ranking_functions_MS_2(const PSET& pset_before,
00380 const PSET& pset_after,
00381 C_Polyhedron& decreasing_mu_space,
00382 C_Polyhedron& bounded_mu_space) {
00383 const dimension_type before_space_dim = pset_before.space_dimension();
00384 const dimension_type after_space_dim = pset_after.space_dimension();
00385 if (after_space_dim != 2*before_space_dim) {
00386 std::ostringstream s;
00387 s << "PPL::all_affine_quasi_ranking_functions_MS_2"
00388 << "(pset_before, pset_after, decr_space, bounded_space):\n"
00389 << "pset_before.space_dimension() == " << before_space_dim
00390 << ", pset_after.space_dimension() == " << after_space_dim
00391 << ";\nthe latter should be twice the former.";
00392 throw std::invalid_argument(s.str());
00393 }
00394
00395 if (pset_before.is_empty()) {
00396 decreasing_mu_space = C_Polyhedron(1 + before_space_dim, UNIVERSE);
00397 bounded_mu_space = decreasing_mu_space;
00398 return;
00399 }
00400
00401 using namespace Implementation::Termination;
00402 Constraint_System cs;
00403 assign_all_inequalities_approximation(pset_before, pset_after, cs);
00404 all_affine_quasi_ranking_functions_MS(cs,
00405 decreasing_mu_space,
00406 bounded_mu_space);
00407 }
00408
00409 template <typename PSET>
00410 bool
00411 termination_test_PR_2(const PSET& pset_before, const PSET& pset_after) {
00412 const dimension_type before_space_dim = pset_before.space_dimension();
00413 const dimension_type after_space_dim = pset_after.space_dimension();
00414 if (after_space_dim != 2*before_space_dim) {
00415 std::ostringstream s;
00416 s << "PPL::termination_test_PR_2(pset_before, pset_after):\n"
00417 << "pset_before.space_dimension() == " << before_space_dim
00418 << ", pset_after.space_dimension() == " << after_space_dim
00419 << ";\nthe latter should be twice the former.";
00420 throw std::invalid_argument(s.str());
00421 }
00422
00423 using namespace Implementation::Termination;
00424 Constraint_System cs_before;
00425 Constraint_System cs_after;
00426 assign_all_inequalities_approximation(pset_before, cs_before);
00427 assign_all_inequalities_approximation(pset_after, cs_after);
00428 return termination_test_PR(cs_before, cs_after);
00429 }
00430
00431 template <typename PSET>
00432 bool
00433 termination_test_PR(const PSET& pset_after) {
00434 const dimension_type space_dim = pset_after.space_dimension();
00435 if (space_dim % 2 != 0) {
00436 std::ostringstream s;
00437 s << "PPL::termination_test_PR(pset):\n"
00438 << "pset.space_dimension() == " << space_dim
00439 << " is odd.";
00440 throw std::invalid_argument(s.str());
00441 }
00442
00443 using namespace Implementation::Termination;
00444 Constraint_System cs;
00445 assign_all_inequalities_approximation(pset_after, cs);
00446 return termination_test_PR_original(cs);
00447 }
00448
00449 template <typename PSET>
00450 bool
00451 one_affine_ranking_function_PR_2(const PSET& pset_before,
00452 const PSET& pset_after,
00453 Generator& mu) {
00454 const dimension_type before_space_dim = pset_before.space_dimension();
00455 const dimension_type after_space_dim = pset_after.space_dimension();
00456 if (after_space_dim != 2*before_space_dim) {
00457 std::ostringstream s;
00458 s << "PPL::one_affine_ranking_function_PR_2"
00459 << "(pset_before, pset_after, mu):\n"
00460 << "pset_before.space_dimension() == " << before_space_dim
00461 << ", pset_after.space_dimension() == " << after_space_dim
00462 << ";\nthe latter should be twice the former.";
00463 throw std::invalid_argument(s.str());
00464 }
00465
00466 using namespace Implementation::Termination;
00467 Constraint_System cs_before;
00468 Constraint_System cs_after;
00469 assign_all_inequalities_approximation(pset_before, cs_before);
00470 assign_all_inequalities_approximation(pset_after, cs_after);
00471 return one_affine_ranking_function_PR(cs_before, cs_after, mu);
00472 }
00473
00474 template <typename PSET>
00475 bool
00476 one_affine_ranking_function_PR(const PSET& pset_after, Generator& mu) {
00477 const dimension_type space_dim = pset_after.space_dimension();
00478 if (space_dim % 2 != 0) {
00479 std::ostringstream s;
00480 s << "PPL::one_affine_ranking_function_PR(pset, mu):\n"
00481 << "pset.space_dimension() == " << space_dim
00482 << " is odd.";
00483 throw std::invalid_argument(s.str());
00484 }
00485
00486 using namespace Implementation::Termination;
00487 Constraint_System cs;
00488 assign_all_inequalities_approximation(pset_after, cs);
00489 return one_affine_ranking_function_PR_original(cs, mu);
00490 }
00491
00492 template <typename PSET>
00493 void
00494 all_affine_ranking_functions_PR_2(const PSET& pset_before,
00495 const PSET& pset_after,
00496 NNC_Polyhedron& mu_space) {
00497 const dimension_type before_space_dim = pset_before.space_dimension();
00498 const dimension_type after_space_dim = pset_after.space_dimension();
00499 if (after_space_dim != 2*before_space_dim) {
00500 std::ostringstream s;
00501 s << "PPL::all_affine_ranking_functions_MS_2"
00502 << "(pset_before, pset_after, mu_space):\n"
00503 << "pset_before.space_dimension() == " << before_space_dim
00504 << ", pset_after.space_dimension() == " << after_space_dim
00505 << ";\nthe latter should be twice the former.";
00506 throw std::invalid_argument(s.str());
00507 }
00508
00509 if (pset_before.is_empty()) {
00510 mu_space = NNC_Polyhedron(1 + before_space_dim);
00511 return;
00512 }
00513
00514 using namespace Implementation::Termination;
00515 Constraint_System cs_before;
00516 Constraint_System cs_after;
00517 assign_all_inequalities_approximation(pset_before, cs_before);
00518 assign_all_inequalities_approximation(pset_after, cs_after);
00519 all_affine_ranking_functions_PR(cs_before, cs_after, mu_space);
00520 }
00521
00522 template <typename PSET>
00523 void
00524 all_affine_ranking_functions_PR(const PSET& pset_after,
00525 NNC_Polyhedron& mu_space) {
00526 const dimension_type space_dim = pset_after.space_dimension();
00527 if (space_dim % 2 != 0) {
00528 std::ostringstream s;
00529 s << "PPL::all_affine_ranking_functions_PR(pset, mu_space):\n"
00530 << "pset.space_dimension() == " << space_dim
00531 << " is odd.";
00532 throw std::invalid_argument(s.str());
00533 }
00534
00535 if (pset_after.is_empty()) {
00536 mu_space = NNC_Polyhedron(1 + space_dim/2);
00537 return;
00538 }
00539
00540 using namespace Implementation::Termination;
00541 Constraint_System cs;
00542 assign_all_inequalities_approximation(pset_after, cs);
00543 all_affine_ranking_functions_PR_original(cs, mu_space);
00544 }
00545
00546 }
00547
00548 #endif // !defined(PPL_termination_templates_hh)