|
PPL
0.12.1
|
00001 /* Utilities for termination analysis: non-inline, non-template functions. 00002 Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it> 00003 Copyright (C) 2010-2012 BUGSENG srl (http://bugseng.com) 00004 00005 This file is part of the Parma Polyhedra Library (PPL). 00006 00007 The PPL is free software; you can redistribute it and/or modify it 00008 under the terms of the GNU General Public License as published by the 00009 Free Software Foundation; either version 3 of the License, or (at your 00010 option) any later version. 00011 00012 The PPL is distributed in the hope that it will be useful, but WITHOUT 00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 00015 for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program; if not, write to the Free Software Foundation, 00019 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA. 00020 00021 For the most up-to-date information see the Parma Polyhedra Library 00022 site: http://bugseng.com/products/ppl/ . */ 00023 00024 #include "ppl-config.h" 00025 #include "termination.defs.hh" 00026 #include "NNC_Polyhedron.defs.hh" 00027 00028 namespace Parma_Polyhedra_Library { 00029 00030 namespace Implementation { 00031 00032 namespace Termination { 00033 00034 void 00035 assign_all_inequalities_approximation(const Constraint_System& cs_in, 00036 Constraint_System& cs_out) { 00037 if (cs_in.has_strict_inequalities() || cs_in.has_equalities()) { 00038 // Here we have some strict inequality and/or equality constraints: 00039 // translate them into non-strict inequality constraints. 00040 for (Constraint_System::const_iterator i = cs_in.begin(), 00041 i_end = cs_in.end(); i != i_end; ++i) { 00042 const Constraint& c = *i; 00043 if (c.is_equality()) { 00044 // Insert the two corresponding opposing inequalities. 00045 cs_out.insert(Linear_Expression(c) >= 0); 00046 cs_out.insert(Linear_Expression(c) <= 0); 00047 } 00048 else if (c.is_strict_inequality()) 00049 // Insert the non-strict approximation. 00050 cs_out.insert(Linear_Expression(c) >= 0); 00051 else 00052 // Insert as is. 00053 cs_out.insert(c); 00054 } 00055 } 00056 else 00057 // No strict inequality and no equality constraints. 00058 cs_out = cs_in; 00059 } 00060 00061 template <> 00062 void 00063 assign_all_inequalities_approximation(const C_Polyhedron& ph, 00064 Constraint_System& cs) { 00065 const Constraint_System& ph_cs = ph.minimized_constraints(); 00066 if (ph_cs.has_equalities()) { 00067 // Translate equalities into inequalities. 00068 for (Constraint_System::const_iterator i = ph_cs.begin(), 00069 i_end = ph_cs.end(); i != i_end; ++i) { 00070 const Constraint& c = *i; 00071 if (c.is_equality()) { 00072 // Insert the two corresponding opposing inequalities. 00073 cs.insert(Linear_Expression(c) >= 0); 00074 cs.insert(Linear_Expression(c) <= 0); 00075 } 00076 else 00077 // Insert as is. 00078 cs.insert(c); 00079 } 00080 } 00081 else 00082 // No equality constraints (and no strict inequalities). 00083 cs = ph_cs; 00084 } 00085 00086 void 00087 shift_unprimed_variables(Constraint_System& cs) { 00088 const dimension_type cs_space_dim = cs.space_dimension(); 00089 Constraint_System cs_shifted; 00090 for (Constraint_System::const_iterator i = cs.begin(), 00091 cs_end = cs.end(); i != cs_end; ++i) { 00092 const Constraint& c_i = *i; 00093 Linear_Expression le_i_shifted; 00094 for (dimension_type j = cs_space_dim; j-- > 0; ) { 00095 Coefficient_traits::const_reference a_i_j 00096 = c_i.coefficient(Variable(j)); 00097 if (a_i_j != 0) 00098 add_mul_assign(le_i_shifted, a_i_j, Variable(cs_space_dim + j)); 00099 } 00100 le_i_shifted += c_i.inhomogeneous_term(); 00101 cs_shifted.insert(le_i_shifted >= 0); 00102 } 00103 cs.m_swap(cs_shifted); 00104 } 00105 00145 void 00146 fill_constraint_systems_MS(const Constraint_System& cs, 00147 Constraint_System& cs_out1, 00148 Constraint_System& cs_out2) { 00149 PPL_ASSERT(cs.space_dimension() % 2 == 0); 00150 const dimension_type n = cs.space_dimension() / 2; 00151 const dimension_type m = num_constraints(cs); 00152 00153 #if PRINT_DEBUG_INFO 00154 Variable::output_function_type* p_default_output_function 00155 = Variable::get_output_function(); 00156 Variable::set_output_function(output_function_MS); 00157 00158 output_function_MS_n = n; 00159 output_function_MS_m = m; 00160 00161 std::cout << "*** cs ***" << std::endl; 00162 output_function_MS_which = 0; 00163 using namespace IO_Operators; 00164 std::cout << cs << std::endl; 00165 #endif 00166 00167 dimension_type y_begin = n+1; 00168 dimension_type z_begin = y_begin + ((&cs_out1 == &cs_out2) ? m : 0); 00169 00170 // Make sure linear expressions are not reallocated multiple times. 00171 Linear_Expression y_le(0*Variable(y_begin + m - 1)); 00172 Linear_Expression z_le(0*Variable(z_begin + m + 2 - 1)); 00173 std::vector<Linear_Expression> y_les(2*n, y_le); 00174 std::vector<Linear_Expression> z_les(2*n + 1, z_le); 00175 00176 dimension_type y = y_begin; 00177 dimension_type z = z_begin; 00178 for (Constraint_System::const_iterator i = cs.begin(), 00179 cs_end = cs.end(); i != cs_end; ++i) { 00180 Variable v_y(y); 00181 Variable v_z(z); 00182 ++y; 00183 ++z; 00184 cs_out1.insert(v_y >= 0); 00185 cs_out2.insert(v_z >= 0); 00186 const Constraint& c_i = *i; 00187 Coefficient_traits::const_reference b_i = c_i.inhomogeneous_term(); 00188 if (b_i != 0) { 00189 // Note that b_i is to the left ot the relation sign, hence here 00190 // we have -= and not += just to avoid negating b_i. 00191 sub_mul_assign(y_le, b_i, v_y); 00192 sub_mul_assign(z_le, b_i, v_z); 00193 } 00194 for (dimension_type j = 2*n; j-- > 0; ) { 00195 Coefficient_traits::const_reference a_i_j = c_i.coefficient(Variable(j)); 00196 if (a_i_j != 0) { 00197 add_mul_assign(y_les[j], a_i_j, v_y); 00198 add_mul_assign(z_les[j], a_i_j, v_z); 00199 } 00200 } 00201 } 00202 z_le += Variable(z); 00203 z_les[2*n] += Variable(z); 00204 cs_out2.insert(Variable(z) >= 0); 00205 ++z; 00206 z_le -= Variable(z); 00207 z_les[2*n] -= Variable(z); 00208 cs_out2.insert(Variable(z) >= 0); 00209 cs_out1.insert(y_le >= 1); 00210 cs_out2.insert(z_le >= 0); 00211 dimension_type j = 2*n; 00212 while (j-- > n) { 00213 cs_out1.insert(y_les[j] == Variable(j-n)); 00214 cs_out2.insert(z_les[j] == Variable(j-n)); 00215 } 00216 ++j; 00217 while (j-- > 0) { 00218 cs_out1.insert(y_les[j] == -Variable(j)); 00219 cs_out2.insert(z_les[j] == 0); 00220 } 00221 cs_out2.insert(z_les[2*n] == Variable(n)); 00222 00223 #if PRINT_DEBUG_INFO 00224 if (&cs_out1 == &cs_out2) { 00225 std::cout << "*** cs_mip ***" << std::endl; 00226 output_function_MS_which = 3; 00227 using namespace IO_Operators; 00228 std::cout << cs_mip << std::endl; 00229 } 00230 else { 00231 std::cout << "*** cs_out1 ***" << std::endl; 00232 output_function_MS_which = 1; 00233 using namespace IO_Operators; 00234 std::cout << cs_out1 << std::endl; 00235 00236 std::cout << "*** cs_out2 ***" << std::endl; 00237 output_function_MS_which = 2; 00238 using namespace IO_Operators; 00239 std::cout << cs_out2 << std::endl; 00240 } 00241 00242 Variable::set_output_function(p_default_output_function); 00243 #endif 00244 } 00245 00357 void 00358 fill_constraint_system_PR(const Constraint_System& cs_before, 00359 const Constraint_System& cs_after, 00360 Constraint_System& cs_out, 00361 Linear_Expression& le_out) { 00362 PPL_ASSERT(cs_after.space_dimension() % 2 == 0); 00363 PPL_ASSERT(2*cs_before.space_dimension() == cs_after.space_dimension()); 00364 const dimension_type n = cs_before.space_dimension(); 00365 const dimension_type r = num_constraints(cs_before); 00366 const dimension_type s = num_constraints(cs_after); 00367 const dimension_type m = r + s; 00368 00369 // Make sure linear expressions are not reallocated multiple times. 00370 if (m > 0) 00371 le_out = 0 * Variable(m + r - 1); 00372 std::vector<Linear_Expression> les_eq(2*n, le_out); 00373 00374 dimension_type row_index = 0; 00375 for (Constraint_System::const_iterator i = cs_before.begin(), 00376 cs_before_end = cs_before.end(); 00377 i != cs_before_end; 00378 ++i, ++row_index) { 00379 Variable u1_i(m + row_index); 00380 Variable u2_i(s + row_index); 00381 const Constraint& c_i = *i; 00382 for (dimension_type j = n; j-- > 0; ) { 00383 Coefficient_traits::const_reference A_ij_B = c_i.coefficient(Variable(j)); 00384 if (A_ij_B != 0) { 00385 // (u1 - u2) A_B, in the context of j-th constraint. 00386 add_mul_assign(les_eq[j], A_ij_B, u1_i); 00387 sub_mul_assign(les_eq[j], A_ij_B, u2_i); 00388 // u2 A_B, in the context of (j+n)-th constraint. 00389 add_mul_assign(les_eq[j + n], A_ij_B, u2_i); 00390 } 00391 } 00392 Coefficient_traits::const_reference b_B = c_i.inhomogeneous_term(); 00393 if (b_B != 0) 00394 // u2 b_B, in the context of the strict inequality constraint. 00395 add_mul_assign(le_out, b_B, u2_i); 00396 } 00397 00398 row_index = 0; 00399 for (Constraint_System::const_iterator i = cs_after.begin(), 00400 cs_after_end = cs_after.end(); 00401 i != cs_after_end; 00402 ++i, ++row_index) { 00403 Variable u3_i(row_index); 00404 const Constraint& c_i = *i; 00405 for (dimension_type j = n; j-- > 0; ) { 00406 Coefficient_traits::const_reference 00407 A_ij_C = c_i.coefficient(Variable(j + n)); 00408 if (A_ij_C != 0) { 00409 // - u3 A_C, in the context of the j-th constraint. 00410 sub_mul_assign(les_eq[j], A_ij_C, u3_i); 00411 // u3 A_C, in the context of the (j+n)-th constraint. 00412 add_mul_assign(les_eq[j+n], A_ij_C, u3_i); 00413 } 00414 Coefficient_traits::const_reference 00415 Ap_ij_C = c_i.coefficient(Variable(j)); 00416 if (Ap_ij_C != 0) 00417 // u3 Ap_C, in the context of the (j+n)-th constraint. 00418 add_mul_assign(les_eq[j+n], Ap_ij_C, u3_i); 00419 } 00420 Coefficient_traits::const_reference b_C = c_i.inhomogeneous_term(); 00421 if (b_C != 0) 00422 // u3 b_C, in the context of the strict inequality constraint. 00423 add_mul_assign(le_out, b_C, u3_i); 00424 } 00425 00426 // Add the nonnegativity constraints for u_1, u_2 and u_3. 00427 for (dimension_type i = s + 2*r; i-- > 0; ) 00428 cs_out.insert(Variable(i) >= 0); 00429 00430 for (dimension_type j = 2*n; j-- > 0; ) 00431 cs_out.insert(les_eq[j] == 0); 00432 } 00433 00434 void 00435 fill_constraint_system_PR_original(const Constraint_System& cs, 00436 Constraint_System& cs_out, 00437 Linear_Expression& le_out) { 00438 PPL_ASSERT(cs.space_dimension() % 2 == 0); 00439 const dimension_type n = cs.space_dimension() / 2; 00440 const dimension_type m = num_constraints(cs); 00441 00442 // Make sure linear expressions are not reallocated multiple times. 00443 if (m > 0) 00444 le_out = 0 * Variable(2*m - 1); 00445 std::vector<Linear_Expression> les_eq(3*n, le_out); 00446 00447 dimension_type row_index = 0; 00448 for (Constraint_System::const_iterator i = cs.begin(), 00449 cs_end = cs.end(); i != cs_end; ++i, ++row_index) { 00450 const Constraint& c_i = *i; 00451 const Variable lambda1_i(row_index); 00452 const Variable lambda2_i(m + row_index); 00453 for (dimension_type j = n; j-- > 0; ) { 00454 Coefficient_traits::const_reference Ap_ij = c_i.coefficient(Variable(j)); 00455 if (Ap_ij != 0) { 00456 // lambda_1 A' 00457 add_mul_assign(les_eq[j], Ap_ij, lambda1_i); 00458 // lambda_2 A' 00459 add_mul_assign(les_eq[j+n+n], Ap_ij, lambda2_i); 00460 } 00461 Coefficient_traits::const_reference A_ij = c_i.coefficient(Variable(j+n)); 00462 if (A_ij != 0) { 00463 // (lambda_1 - lambda_2) A 00464 add_mul_assign(les_eq[j+n], A_ij, lambda1_i); 00465 sub_mul_assign(les_eq[j+n], A_ij, lambda2_i); 00466 // lambda_2 A 00467 add_mul_assign(les_eq[j+n+n], A_ij, lambda2_i); 00468 } 00469 } 00470 Coefficient_traits::const_reference b = c_i.inhomogeneous_term(); 00471 if (b != 0) 00472 // lambda2 b 00473 add_mul_assign(le_out, b, lambda2_i); 00474 } 00475 00476 // Add the non-negativity constraints for lambda_1 and lambda_2. 00477 for (dimension_type i = 2*m; i-- > 0; ) 00478 cs_out.insert(Variable(i) >= 0); 00479 00480 for (dimension_type j = 3*n; j-- > 0; ) 00481 cs_out.insert(les_eq[j] == 0); 00482 } 00483 00484 bool 00485 termination_test_MS(const Constraint_System& cs) { 00486 Constraint_System cs_mip; 00487 fill_constraint_systems_MS(cs, cs_mip, cs_mip); 00488 00489 MIP_Problem mip = MIP_Problem(cs_mip.space_dimension(), cs_mip); 00490 return mip.is_satisfiable(); 00491 } 00492 00493 bool 00494 one_affine_ranking_function_MS(const Constraint_System& cs, Generator& mu) { 00495 Constraint_System cs_mip; 00496 fill_constraint_systems_MS(cs, cs_mip, cs_mip); 00497 00498 MIP_Problem mip = MIP_Problem(cs_mip.space_dimension(), cs_mip); 00499 if (!mip.is_satisfiable()) 00500 return false; 00501 00502 Generator fp = mip.feasible_point(); 00503 PPL_ASSERT(fp.is_point()); 00504 Linear_Expression le; 00505 const dimension_type n = cs.space_dimension() / 2; 00506 for (dimension_type i = n+1; i-- > 0; ) { 00507 Variable vi(i); 00508 add_mul_assign(le, fp.coefficient(vi), vi); 00509 } 00510 mu = point(le, fp.divisor()); 00511 return true; 00512 } 00513 00514 void 00515 all_affine_ranking_functions_MS(const Constraint_System& cs, 00516 C_Polyhedron& mu_space) { 00517 Constraint_System cs_out1; 00518 Constraint_System cs_out2; 00519 fill_constraint_systems_MS(cs, cs_out1, cs_out2); 00520 00521 C_Polyhedron ph1(cs_out1); 00522 C_Polyhedron ph2(cs_out2); 00523 const dimension_type n = cs.space_dimension() / 2; 00524 ph1.remove_higher_space_dimensions(n); 00525 ph1.add_space_dimensions_and_embed(1); 00526 ph2.remove_higher_space_dimensions(n+1); 00527 00528 #if PRINT_DEBUG_INFO 00529 Variable::output_function_type* p_default_output_function 00530 = Variable::get_output_function(); 00531 Variable::set_output_function(output_function_MS); 00532 00533 output_function_MS_n = n; 00534 output_function_MS_m = num_constraints(cs); 00535 00536 std::cout << "*** ph1 projected ***" << std::endl; 00537 output_function_MS_which = 4; 00538 using namespace IO_Operators; 00539 std::cout << ph1.minimized_constraints() << std::endl; 00540 00541 std::cout << "*** ph2 projected ***" << std::endl; 00542 std::cout << ph2.minimized_constraints() << std::endl; 00543 #endif 00544 00545 ph1.intersection_assign(ph2); 00546 00547 #if PRINT_DEBUG_INFO 00548 std::cout << "*** intersection ***" << std::endl; 00549 using namespace IO_Operators; 00550 std::cout << ph1.minimized_constraints() << std::endl; 00551 00552 Variable::set_output_function(p_default_output_function); 00553 #endif 00554 00555 mu_space.m_swap(ph1); 00556 } 00557 00558 void 00559 all_affine_quasi_ranking_functions_MS(const Constraint_System& cs, 00560 C_Polyhedron& decreasing_mu_space, 00561 C_Polyhedron& bounded_mu_space) { 00562 Constraint_System cs_out1; 00563 Constraint_System cs_out2; 00564 fill_constraint_systems_MS(cs, cs_out1, cs_out2); 00565 00566 C_Polyhedron ph1(cs_out1); 00567 C_Polyhedron ph2(cs_out2); 00568 const dimension_type n = cs.space_dimension() / 2; 00569 ph1.remove_higher_space_dimensions(n); 00570 ph1.add_space_dimensions_and_embed(1); 00571 ph2.remove_higher_space_dimensions(n+1); 00572 00573 #if PRINT_DEBUG_INFO 00574 Variable::output_function_type* p_default_output_function 00575 = Variable::get_output_function(); 00576 Variable::set_output_function(output_function_MS); 00577 00578 output_function_MS_n = n; 00579 output_function_MS_m = num_constraints(cs); 00580 00581 std::cout << "*** ph1 projected ***" << std::endl; 00582 output_function_MS_which = 4; 00583 using namespace IO_Operators; 00584 std::cout << ph1.minimized_constraints() << std::endl; 00585 00586 std::cout << "*** ph2 projected ***" << std::endl; 00587 std::cout << ph2.minimized_constraints() << std::endl; 00588 00589 Variable::set_output_function(p_default_output_function); 00590 #endif 00591 00592 decreasing_mu_space.m_swap(ph1); 00593 bounded_mu_space.m_swap(ph2); 00594 } 00595 00596 bool 00597 termination_test_PR_original(const Constraint_System& cs) { 00598 PPL_ASSERT(cs.space_dimension() % 2 == 0); 00599 00600 Constraint_System cs_mip; 00601 Linear_Expression le_ineq; 00602 fill_constraint_system_PR_original(cs, cs_mip, le_ineq); 00603 00604 // Turn minimization problem into satisfiability. 00605 cs_mip.insert(le_ineq <= -1); 00606 00607 MIP_Problem mip(cs_mip.space_dimension(), cs_mip); 00608 return mip.is_satisfiable(); 00609 } 00610 00611 bool 00612 termination_test_PR(const Constraint_System& cs_before, 00613 const Constraint_System& cs_after) { 00614 Constraint_System cs_mip; 00615 Linear_Expression le_ineq; 00616 fill_constraint_system_PR(cs_before, cs_after, cs_mip, le_ineq); 00617 00618 #if PRINT_DEBUG_INFO 00619 Variable::output_function_type* p_default_output_function 00620 = Variable::get_output_function(); 00621 Variable::set_output_function(output_function_PR); 00622 00623 output_function_PR_r = num_constraints(cs_before); 00624 output_function_PR_s = num_constraints(cs_after); 00625 00626 std::cout << "*** cs_mip ***" << std::endl; 00627 using namespace IO_Operators; 00628 std::cout << cs_mip << std::endl; 00629 std::cout << "*** le_ineq ***" << std::endl; 00630 std::cout << le_ineq << std::endl; 00631 00632 Variable::set_output_function(p_default_output_function); 00633 #endif 00634 00635 // Turn minimization problem into satisfiability. 00636 cs_mip.insert(le_ineq <= -1); 00637 00638 MIP_Problem mip(cs_mip.space_dimension(), cs_mip); 00639 return mip.is_satisfiable(); 00640 } 00641 00642 bool 00643 one_affine_ranking_function_PR(const Constraint_System& cs_before, 00644 const Constraint_System& cs_after, 00645 Generator& mu) { 00646 Constraint_System cs_mip; 00647 Linear_Expression le_ineq; 00648 fill_constraint_system_PR(cs_before, cs_after, cs_mip, le_ineq); 00649 00650 #if PRINT_DEBUG_INFO 00651 Variable::output_function_type* p_default_output_function 00652 = Variable::get_output_function(); 00653 Variable::set_output_function(output_function_PR); 00654 00655 output_function_PR_r = num_constraints(cs_before); 00656 output_function_PR_s = num_constraints(cs_after); 00657 00658 std::cout << "*** cs_mip ***" << std::endl; 00659 using namespace IO_Operators; 00660 std::cout << cs_mip << std::endl; 00661 std::cout << "*** le_ineq ***" << std::endl; 00662 std::cout << le_ineq << std::endl; 00663 00664 Variable::set_output_function(p_default_output_function); 00665 #endif 00666 00667 // Turn minimization problem into satisfiability. 00668 cs_mip.insert(le_ineq <= -1); 00669 00670 MIP_Problem mip(cs_mip.space_dimension(), cs_mip); 00671 if (!mip.is_satisfiable()) 00672 return false; 00673 00674 Generator fp = mip.feasible_point(); 00675 PPL_ASSERT(fp.is_point()); 00676 00677 // u_3 corresponds to space dimensions 0, ..., s - 1. 00678 const dimension_type n = cs_before.space_dimension(); 00679 Linear_Expression le; 00680 // mu_0 is zero: do this first to avoid reallocations. 00681 le += 0*Variable(n); 00682 // Multiply u_3 by E'_C to obtain mu_1, ..., mu_n. 00683 dimension_type row_index = 0; 00684 PPL_DIRTY_TEMP_COEFFICIENT(k); 00685 for (Constraint_System::const_iterator i = cs_after.begin(), 00686 cs_after_end = cs_after.end(); 00687 i != cs_after_end; 00688 ++i, ++row_index) { 00689 Variable vi(row_index); 00690 Coefficient_traits::const_reference fp_i = fp.coefficient(vi); 00691 const Constraint& c_i = *i; 00692 for (dimension_type j = n; j-- > 0; ) { 00693 Variable vj(j); 00694 k = fp_i * c_i.coefficient(vj); 00695 sub_mul_assign(le, k, vj); 00696 } 00697 } 00698 // Note that we can neglect the divisor of `fp' since it is positive. 00699 mu = point(le); 00700 return true; 00701 } 00702 00703 bool 00704 one_affine_ranking_function_PR_original(const Constraint_System& cs, 00705 Generator& mu) { 00706 PPL_ASSERT(cs.space_dimension() % 2 == 0); 00707 const dimension_type n = cs.space_dimension() / 2; 00708 const dimension_type m = num_constraints(cs); 00709 00710 Constraint_System cs_mip; 00711 Linear_Expression le_ineq; 00712 fill_constraint_system_PR_original(cs, cs_mip, le_ineq); 00713 00714 #if PRINT_DEBUG_INFO 00715 std::cout << "*** cs_mip ***" << std::endl; 00716 using namespace IO_Operators; 00717 std::cout << cs_mip << std::endl; 00718 std::cout << "*** le_ineq ***" << std::endl; 00719 std::cout << le_ineq << std::endl; 00720 #endif 00721 00722 // Turn minimization problem into satisfiability. 00723 cs_mip.insert(le_ineq <= -1); 00724 00725 MIP_Problem mip = MIP_Problem(cs_mip.space_dimension(), cs_mip); 00726 if (!mip.is_satisfiable()) 00727 return false; 00728 00729 Generator fp = mip.feasible_point(); 00730 PPL_ASSERT(fp.is_point()); 00731 Linear_Expression le; 00732 // mu_0 is zero: do this first to avoid reallocations. 00733 le += 0*Variable(n); 00734 // Multiply -lambda_2 by A' to obtain mu_1, ..., mu_n. 00735 // lambda_2 corresponds to space dimensions m, ..., 2*m - 1. 00736 dimension_type row_index = m; 00737 PPL_DIRTY_TEMP_COEFFICIENT(k); 00738 for (Constraint_System::const_iterator i = cs.begin(), 00739 cs_end = cs.end(); i != cs_end; ++i, ++row_index) { 00740 Variable lambda_2(row_index); 00741 Coefficient_traits::const_reference fp_i = fp.coefficient(lambda_2); 00742 if (fp_i != 0) { 00743 const Constraint& c_i = *i; 00744 for (dimension_type j = n; j-- > 0; ) { 00745 Variable vj(j); 00746 Coefficient_traits::const_reference Ap_ij = c_i.coefficient(vj); 00747 k = fp_i * Ap_ij; 00748 sub_mul_assign(le, k, vj); 00749 } 00750 } 00751 } 00752 // Note that we can neglect the divisor of `fp' since it is positive. 00753 mu = point(le); 00754 return true; 00755 } 00756 00757 void 00758 all_affine_ranking_functions_PR(const Constraint_System& cs_before, 00759 const Constraint_System& cs_after, 00760 NNC_Polyhedron& mu_space) { 00761 Constraint_System cs_eqs; 00762 Linear_Expression le_ineq; 00763 fill_constraint_system_PR(cs_before, cs_after, cs_eqs, le_ineq); 00764 00765 #if PRINT_DEBUG_INFO 00766 Variable::output_function_type* p_default_output_function 00767 = Variable::get_output_function(); 00768 Variable::set_output_function(output_function_PR); 00769 00770 output_function_PR_r = num_constraints(cs_before); 00771 output_function_PR_s = num_constraints(cs_after); 00772 00773 std::cout << "*** cs_eqs ***" << std::endl; 00774 using namespace IO_Operators; 00775 std::cout << cs_eqs << std::endl; 00776 std::cout << "*** le_ineq ***" << std::endl; 00777 std::cout << le_ineq << std::endl; 00778 #endif 00779 00780 NNC_Polyhedron ph(cs_eqs); 00781 ph.add_constraint(le_ineq < 0); 00782 // u_3 corresponds to space dimensions 0, ..., s - 1. 00783 const dimension_type s = num_constraints(cs_after); 00784 ph.remove_higher_space_dimensions(s); 00785 00786 #if PRINT_DEBUG_INFO 00787 std::cout << "*** ph ***" << std::endl; 00788 std::cout << ph << std::endl; 00789 00790 Variable::set_output_function(p_default_output_function); 00791 #endif 00792 00793 const dimension_type n = cs_before.space_dimension(); 00794 00795 const Generator_System& gs_in = ph.generators(); 00796 Generator_System gs_out; 00797 Generator_System::const_iterator gs_in_it = gs_in.begin(); 00798 Generator_System::const_iterator gs_in_end = gs_in.end(); 00799 if (gs_in_it == gs_in_end) 00800 // The system is unsatisfiable. 00801 mu_space = NNC_Polyhedron(n + 1, EMPTY); 00802 else { 00803 for ( ; gs_in_it != gs_in_end; ++gs_in_it) { 00804 const Generator& g = *gs_in_it; 00805 Linear_Expression le; 00806 // Set le to the multiplication of Linear_Expression(g) by E'_C. 00807 dimension_type row_index = 0; 00808 PPL_DIRTY_TEMP_COEFFICIENT(k); 00809 for (Constraint_System::const_iterator i = cs_after.begin(), 00810 cs_after_end = cs_after.end(); 00811 i != cs_after_end; 00812 ++i, ++row_index) { 00813 Variable vi(row_index); 00814 Coefficient_traits::const_reference g_i = g.coefficient(vi); 00815 if (g_i != 0) { 00816 const Constraint& c_i = *i; 00817 for (dimension_type j = n; j-- > 0; ) { 00818 Variable vj(j); 00819 k = g_i * c_i.coefficient(vj); 00820 sub_mul_assign(le, k, vj); 00821 } 00822 } 00823 } 00824 00825 // Add to gs_out the transformed generator. 00826 switch (g.type()) { 00827 case Generator::LINE: 00828 if (!le.all_homogeneous_terms_are_zero()) 00829 gs_out.insert(line(le)); 00830 break; 00831 case Generator::RAY: 00832 if (!le.all_homogeneous_terms_are_zero()) 00833 gs_out.insert(ray(le)); 00834 break; 00835 case Generator::POINT: 00836 gs_out.insert(point(le, g.divisor())); 00837 break; 00838 case Generator::CLOSURE_POINT: 00839 gs_out.insert(closure_point(le, g.divisor())); 00840 break; 00841 } 00842 } 00843 00844 mu_space = NNC_Polyhedron(gs_out); 00845 // mu_0 is zero. 00846 mu_space.add_space_dimensions_and_embed(1); 00847 } 00848 } 00849 00850 void 00851 all_affine_ranking_functions_PR_original(const Constraint_System& cs, 00852 NNC_Polyhedron& mu_space) { 00853 PPL_ASSERT(cs.space_dimension() % 2 == 0); 00854 const dimension_type n = cs.space_dimension() / 2; 00855 const dimension_type m = num_constraints(cs); 00856 00857 if (m == 0) { 00858 // If there are no constraints at all, we have non-termination, 00859 // i.e., no affine ranking function at all. 00860 mu_space = NNC_Polyhedron(n + 1, EMPTY); 00861 return; 00862 } 00863 00864 Constraint_System cs_eqs; 00865 Linear_Expression le_ineq; 00866 fill_constraint_system_PR_original(cs, cs_eqs, le_ineq); 00867 00868 NNC_Polyhedron ph(cs_eqs); 00869 ph.add_constraint(le_ineq < 0); 00870 // lambda_2 corresponds to space dimensions m, ..., 2*m-1. 00871 Variables_Set lambda1(Variable(0), Variable(m-1)); 00872 ph.remove_space_dimensions(lambda1); 00873 00874 #if PRINT_DEBUG_INFO 00875 std::cout << "*** ph ***" << std::endl; 00876 std::cout << ph << std::endl; 00877 00878 Variable::set_output_function(p_default_output_function); 00879 #endif 00880 00881 const Generator_System& gs_in = ph.generators(); 00882 Generator_System::const_iterator gs_in_it = gs_in.begin(); 00883 Generator_System::const_iterator gs_in_end = gs_in.end(); 00884 if (gs_in_it == gs_in_end) 00885 // The system is unsatisfiable. 00886 mu_space = NNC_Polyhedron(n + 1, EMPTY); 00887 else { 00888 Generator_System gs_out; 00889 for ( ; gs_in_it != gs_in_end; ++gs_in_it) { 00890 const Generator& g = *gs_in_it; 00891 Linear_Expression le; 00892 // Set le to the multiplication of Linear_Expression(g) by E'_C. 00893 dimension_type row_index = 0; 00894 PPL_DIRTY_TEMP_COEFFICIENT(k); 00895 for (Constraint_System::const_iterator i = cs.begin(), 00896 cs_end = cs.end(); i != cs_end; ++i, ++row_index) { 00897 Variable lambda2_i(row_index); 00898 Coefficient_traits::const_reference g_i = g.coefficient(lambda2_i); 00899 if (g_i != 0) { 00900 const Constraint& c_i = *i; 00901 for (dimension_type j = n; j-- > 0; ) { 00902 Variable vj(j); 00903 Coefficient_traits::const_reference Ap_ij = c_i.coefficient(vj); 00904 k = g_i * Ap_ij; 00905 sub_mul_assign(le, k, vj); 00906 } 00907 } 00908 } 00909 00910 // Add to gs_out the transformed generator. 00911 switch (g.type()) { 00912 case Generator::LINE: 00913 if (!le.all_homogeneous_terms_are_zero()) 00914 gs_out.insert(line(le)); 00915 break; 00916 case Generator::RAY: 00917 if (!le.all_homogeneous_terms_are_zero()) 00918 gs_out.insert(ray(le)); 00919 break; 00920 case Generator::POINT: 00921 gs_out.insert(point(le, g.divisor())); 00922 break; 00923 case Generator::CLOSURE_POINT: 00924 gs_out.insert(closure_point(le, g.divisor())); 00925 break; 00926 } 00927 } 00928 00929 mu_space = NNC_Polyhedron(gs_out); 00930 // mu_0 is zero. 00931 mu_space.add_space_dimensions_and_embed(1); 00932 } 00933 } 00934 00935 } // namespace Termination 00936 00937 } // namespace Implementation 00938 00939 } // namespace Parma_Polyhedra_Library