00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <ppl-config.h>
00025
00026 #include "Constraint_System.defs.hh"
00027 #include "Constraint_System.inlines.hh"
00028 #include "Generator.defs.hh"
00029 #include "Scalar_Products.defs.hh"
00030 #include "Congruence_System.defs.hh"
00031 #include "Congruence_System.inlines.hh"
00032 #include "assert.hh"
00033 #include <string>
00034 #include <vector>
00035 #include <iostream>
00036 #include <stdexcept>
00037
00038 namespace PPL = Parma_Polyhedra_Library;
00039
00040 PPL::Constraint_System::Constraint_System(const Congruence_System& cgs)
00041 : Linear_System(NECESSARILY_CLOSED, 0, cgs.space_dimension() + 1) {
00042 for (Congruence_System::const_iterator i = cgs.begin(),
00043 cgs_end = cgs.end(); i != cgs_end; ++i)
00044 if (i->is_equality())
00045
00046 insert(Constraint(*i));
00047 }
00048
00049 bool
00050 PPL::Constraint_System::
00051 adjust_topology_and_space_dimension(const Topology new_topology,
00052 const dimension_type new_space_dim) {
00053 PPL_ASSERT(space_dimension() <= new_space_dim);
00054
00055 const dimension_type old_space_dim = space_dimension();
00056 const Topology old_topology = topology();
00057 dimension_type cols_to_be_added = new_space_dim - old_space_dim;
00058
00059
00060 if (num_rows() == 0) {
00061 if (num_columns() == 0)
00062 if (new_topology == NECESSARILY_CLOSED) {
00063 add_zero_columns(++cols_to_be_added);
00064 set_necessarily_closed();
00065 }
00066 else {
00067 cols_to_be_added += 2;
00068 add_zero_columns(cols_to_be_added);
00069 set_not_necessarily_closed();
00070 }
00071 else
00072
00073 if (old_topology != new_topology)
00074 if (new_topology == NECESSARILY_CLOSED) {
00075 switch (cols_to_be_added) {
00076 case 0:
00077 remove_trailing_columns(1);
00078 break;
00079 case 1:
00080
00081 break;
00082 default:
00083 add_zero_columns(--cols_to_be_added);
00084 }
00085 set_necessarily_closed();
00086 }
00087 else {
00088
00089
00090 add_zero_columns(++cols_to_be_added);
00091 set_not_necessarily_closed();
00092 }
00093 else {
00094
00095 if (cols_to_be_added > 0)
00096 add_zero_columns(cols_to_be_added);
00097 }
00098 PPL_ASSERT(OK());
00099 return true;
00100 }
00101
00102
00103 if (cols_to_be_added > 0)
00104 if (old_topology != new_topology)
00105 if (new_topology == NECESSARILY_CLOSED) {
00106
00107
00108
00109 if (has_strict_inequalities())
00110 return false;
00111
00112
00113
00114
00115
00116
00117 Constraint_System& cs = *this;
00118 const dimension_type eps_index = old_space_dim + 1;
00119 dimension_type cs_num_rows = cs.num_rows();
00120 bool was_sorted = cs.is_sorted();
00121 if (was_sorted)
00122 cs.set_sorted(false);
00123
00124
00125
00126 if (cs.num_pending_rows() == 0) {
00127 for (dimension_type i = cs_num_rows; i-- > 0; )
00128 if (cs[i][eps_index] != 0) {
00129 --cs_num_rows;
00130 std::swap(cs[i], cs[cs_num_rows]);
00131 }
00132 cs.erase_to_end(cs_num_rows);
00133 cs.unset_pending_rows();
00134 }
00135 else {
00136
00137
00138
00139
00140 const dimension_type old_first_pending = cs.first_pending_row();
00141 dimension_type new_first_pending = old_first_pending;
00142 for (dimension_type i = new_first_pending; i-- > 0; )
00143 if (cs[i][eps_index] != 0) {
00144 --new_first_pending;
00145 std::swap(cs[i], cs[new_first_pending]);
00146 }
00147 const dimension_type num_swaps
00148 = old_first_pending - new_first_pending;
00149 cs.set_index_first_pending_row(new_first_pending);
00150
00151 for (dimension_type i = num_swaps; i-- > 0; )
00152 std::swap(cs[old_first_pending - i], cs[cs_num_rows - i]);
00153 cs_num_rows -= num_swaps;
00154
00155 for (dimension_type i = cs_num_rows; i-- > new_first_pending; )
00156 if (cs[i][eps_index] != 0) {
00157 --cs_num_rows;
00158 std::swap(cs[i], cs[cs_num_rows]);
00159 }
00160 cs.erase_to_end(cs_num_rows);
00161 }
00162
00163
00164 if (was_sorted)
00165 cs.sort_rows();
00166 if (--cols_to_be_added > 0)
00167 add_zero_columns(cols_to_be_added);
00168 set_necessarily_closed();
00169 }
00170 else {
00171
00172
00173
00174 add_zero_columns(++cols_to_be_added);
00175 set_not_necessarily_closed();
00176 }
00177 else {
00178
00179 add_zero_columns(cols_to_be_added);
00180
00181
00182 if (old_topology == NOT_NECESSARILY_CLOSED)
00183 swap_columns(old_space_dim + 1, new_space_dim + 1);
00184 }
00185 else
00186
00187 if (old_topology != new_topology) {
00188 if (new_topology == NECESSARILY_CLOSED) {
00189
00190
00191
00192 if (has_strict_inequalities())
00193 return false;
00194
00195 remove_trailing_columns(1);
00196 set_necessarily_closed();
00197 }
00198 else {
00199
00200 add_zero_columns(1);
00201 set_not_necessarily_closed();
00202 }
00203 }
00204
00205 PPL_ASSERT(OK());
00206 return true;
00207 }
00208
00209 bool
00210 PPL::Constraint_System::has_equalities() const {
00211 const Constraint_System& cs = *this;
00212
00213 for (dimension_type i = cs.num_rows(); i-- > 0; )
00214 if (cs[i].is_equality())
00215 return true;
00216 return false;
00217 }
00218
00219 bool
00220 PPL::Constraint_System::has_strict_inequalities() const {
00221 if (is_necessarily_closed())
00222 return false;
00223 const Constraint_System& cs = *this;
00224 const dimension_type eps_index = cs.num_columns() - 1;
00225
00226
00227 for (dimension_type i = cs.num_rows(); i-- > 0; ) {
00228 const Constraint& c = cs[i];
00229
00230
00231
00232
00233 if (c[eps_index] < 0 && !c.is_tautological())
00234 return true;
00235 }
00236 return false;
00237 }
00238
00239 void
00240 PPL::Constraint_System::insert(const Constraint& c) {
00241
00242
00243 PPL_ASSERT(num_pending_rows() == 0);
00244 if (topology() == c.topology())
00245 Linear_System::insert(c);
00246 else
00247
00248 if (is_necessarily_closed()) {
00249
00250
00251 add_zero_columns(1);
00252 set_not_necessarily_closed();
00253 Linear_System::insert(c);
00254 }
00255 else {
00256
00257
00258
00259
00260
00261 const dimension_type new_size = 2 + std::max(c.space_dimension(),
00262 space_dimension());
00263 Constraint tmp_c(c, new_size);
00264 tmp_c.set_not_necessarily_closed();
00265 Linear_System::insert(tmp_c);
00266 }
00267 PPL_ASSERT(OK());
00268 }
00269
00270 void
00271 PPL::Constraint_System::insert_pending(const Constraint& c) {
00272 if (topology() == c.topology())
00273 Linear_System::insert_pending(c);
00274 else
00275
00276 if (is_necessarily_closed()) {
00277
00278
00279 add_zero_columns(1);
00280 set_not_necessarily_closed();
00281 Linear_System::insert_pending(c);
00282 }
00283 else {
00284
00285
00286
00287 const dimension_type new_size = 2 + std::max(c.space_dimension(),
00288 space_dimension());
00289 Constraint tmp_c(c, new_size);
00290 tmp_c.set_not_necessarily_closed();
00291 Linear_System::insert_pending(tmp_c);
00292 }
00293 PPL_ASSERT(OK());
00294 }
00295
00296 PPL::dimension_type
00297 PPL::Constraint_System::num_inequalities() const {
00298
00299
00300 PPL_ASSERT(num_pending_rows() == 0);
00301 const Constraint_System& cs = *this;
00302 dimension_type n = 0;
00303
00304
00305 if (is_sorted())
00306 for (dimension_type i = num_rows(); i > 0 && cs[--i].is_inequality(); )
00307 ++n;
00308 else
00309 for (dimension_type i = num_rows(); i-- > 0 ; )
00310 if (cs[i].is_inequality())
00311 ++n;
00312 return n;
00313 }
00314
00315 PPL::dimension_type
00316 PPL::Constraint_System::num_equalities() const {
00317
00318
00319 PPL_ASSERT(num_pending_rows() == 0);
00320 return num_rows() - num_inequalities();
00321 }
00322
00323 void
00324 PPL::Constraint_System::const_iterator::skip_forward() {
00325 const Linear_System::const_iterator csp_end = csp->end();
00326 while (i != csp_end && (*this)->is_tautological())
00327 ++i;
00328 }
00329
00330 bool
00331 PPL::Constraint_System::satisfies_all_constraints(const Generator& g) const {
00332 PPL_ASSERT(g.space_dimension() <= space_dimension());
00333
00334
00335
00336
00337 Topology_Adjusted_Scalar_Product_Sign sps(g);
00338
00339 const Constraint_System& cs = *this;
00340 if (cs.is_necessarily_closed()) {
00341 if (g.is_line()) {
00342
00343 for (dimension_type i = cs.num_rows(); i-- > 0; )
00344 if (sps(g, cs[i]) != 0)
00345 return false;
00346 }
00347 else
00348
00349 for (dimension_type i = cs.num_rows(); i-- > 0; ) {
00350 const Constraint& c = cs[i];
00351 const int sp_sign = sps(g, c);
00352 if (c.is_inequality()) {
00353
00354
00355 if (sp_sign < 0)
00356 return false;
00357 }
00358 else
00359
00360 if (sp_sign != 0)
00361 return false;
00362 }
00363 }
00364 else
00365
00366 switch (g.type()) {
00367
00368 case Generator::LINE:
00369
00370 for (dimension_type i = cs.num_rows(); i-- > 0; )
00371 if (sps(g, cs[i]) != 0)
00372 return false;
00373 break;
00374
00375 case Generator::POINT:
00376
00377
00378 for (dimension_type i = cs.num_rows(); i-- > 0; ) {
00379 const Constraint& c = cs[i];
00380 const int sp_sign = sps(g, c);
00381 switch (c.type()) {
00382 case Constraint::EQUALITY:
00383 if (sp_sign != 0)
00384 return false;
00385 break;
00386 case Constraint::NONSTRICT_INEQUALITY:
00387 if (sp_sign < 0)
00388 return false;
00389 break;
00390 case Constraint::STRICT_INEQUALITY:
00391 if (sp_sign <= 0)
00392 return false;
00393 break;
00394 }
00395 }
00396 break;
00397
00398 case Generator::RAY:
00399
00400 case Generator::CLOSURE_POINT:
00401 for (dimension_type i = cs.num_rows(); i-- > 0; ) {
00402 const Constraint& c = cs[i];
00403 const int sp_sign = sps(g, c);
00404 if (c.is_inequality()) {
00405
00406 if (sp_sign < 0)
00407 return false;
00408 }
00409 else
00410
00411 if (sp_sign != 0)
00412 return false;
00413 }
00414 break;
00415 }
00416
00417
00418 return true;
00419 }
00420
00421
00422 void
00423 PPL::Constraint_System
00424 ::affine_preimage(const dimension_type v,
00425 const Linear_Expression& expr,
00426 Coefficient_traits::const_reference denominator) {
00427 Constraint_System& x = *this;
00428
00429
00430
00431 PPL_ASSERT(v > 0 && v <= x.space_dimension());
00432 PPL_ASSERT(expr.space_dimension() <= x.space_dimension());
00433 PPL_ASSERT(denominator > 0);
00434
00435 const dimension_type n_columns = x.num_columns();
00436 const dimension_type n_rows = x.num_rows();
00437 const dimension_type expr_size = expr.size();
00438 const bool not_invertible = (v >= expr_size || expr[v] == 0);
00439
00440 if (denominator != 1)
00441 for (dimension_type i = n_rows; i-- > 0; ) {
00442 Constraint& row = x[i];
00443 Coefficient& row_v = row[v];
00444 if (row_v != 0) {
00445 for (dimension_type j = n_columns; j-- > 0; )
00446 if (j != v) {
00447 Coefficient& row_j = row[j];
00448 row_j *= denominator;
00449 if (j < expr_size)
00450 add_mul_assign(row_j, row_v, expr[j]);
00451 }
00452 if (not_invertible)
00453 row_v = 0;
00454 else
00455 row_v *= expr[v];
00456 }
00457 }
00458 else
00459
00460
00461 for (dimension_type i = n_rows; i-- > 0; ) {
00462 Constraint& row = x[i];
00463 Coefficient& row_v = row[v];
00464 if (row_v != 0) {
00465 for (dimension_type j = expr_size; j-- > 0; )
00466 if (j != v)
00467 add_mul_assign(row[j], row_v, expr[j]);
00468 if (not_invertible)
00469 row_v = 0;
00470 else
00471 row_v *= expr[v];
00472 }
00473 }
00474
00475 x.strong_normalize();
00476 }
00477
00478 void
00479 PPL::Constraint_System::ascii_dump(std::ostream& s) const {
00480 const Constraint_System& x = *this;
00481 const dimension_type x_num_rows = x.num_rows();
00482 const dimension_type x_num_columns = x.num_columns();
00483 s << "topology " << (is_necessarily_closed()
00484 ? "NECESSARILY_CLOSED"
00485 : "NOT_NECESSARILY_CLOSED")
00486 << "\n"
00487 << x_num_rows << " x " << x_num_columns << ' '
00488 << (x.is_sorted() ? "(sorted)" : "(not_sorted)")
00489 << "\n"
00490 << "index_first_pending " << x.first_pending_row()
00491 << "\n";
00492 for (dimension_type i = 0; i < x_num_rows; ++i) {
00493 const Constraint& c = x[i];
00494 for (dimension_type j = 0; j < x_num_columns; ++j)
00495 s << c[j] << ' ';
00496 switch (c.type()) {
00497 case Constraint::EQUALITY:
00498 s << "=";
00499 break;
00500 case Constraint::NONSTRICT_INEQUALITY:
00501 s << ">=";
00502 break;
00503 case Constraint::STRICT_INEQUALITY:
00504 s << ">";
00505 break;
00506 }
00507 s << "\n";
00508 }
00509 }
00510
00511 PPL_OUTPUT_DEFINITIONS(Constraint_System)
00512
00513 bool
00514 PPL::Constraint_System::ascii_load(std::istream& s) {
00515 std::string str;
00516 if (!(s >> str) || str != "topology")
00517 return false;
00518 if (!(s >> str))
00519 return false;
00520 if (str == "NECESSARILY_CLOSED")
00521 set_necessarily_closed();
00522 else {
00523 if (str != "NOT_NECESSARILY_CLOSED")
00524 return false;
00525 set_not_necessarily_closed();
00526 }
00527
00528 dimension_type nrows;
00529 dimension_type ncols;
00530 if (!(s >> nrows))
00531 return false;
00532 if (!(s >> str) || str != "x")
00533 return false;
00534 if (!(s >> ncols))
00535 return false;
00536 resize_no_copy(nrows, ncols);
00537
00538 if (!(s >> str) || (str != "(sorted)" && str != "(not_sorted)"))
00539 return false;
00540 set_sorted(str == "(sorted)");
00541 dimension_type index;
00542 if (!(s >> str) || str != "index_first_pending")
00543 return false;
00544 if (!(s >> index))
00545 return false;
00546 set_index_first_pending_row(index);
00547
00548 Constraint_System& x = *this;
00549 for (dimension_type i = 0; i < x.num_rows(); ++i) {
00550 for (dimension_type j = 0; j < x.num_columns(); ++j)
00551 if (!(s >> x[i][j]))
00552 return false;
00553
00554 if (!(s >> str))
00555 return false;
00556 if (str == "=")
00557 x[i].set_is_equality();
00558 else if (str == ">=" || str == ">")
00559 x[i].set_is_inequality();
00560 else
00561 return false;
00562
00563
00564 switch (x[i].type()) {
00565 case Constraint::EQUALITY:
00566 if (str == "=")
00567 continue;
00568 break;
00569 case Constraint::NONSTRICT_INEQUALITY:
00570 if (str == ">=")
00571 continue;
00572 break;
00573 case Constraint::STRICT_INEQUALITY:
00574 if (str == ">")
00575 continue;
00576 break;
00577 }
00578
00579 return false;
00580 }
00581
00582 PPL_ASSERT(OK());
00583 return true;
00584 }
00585
00586 const PPL::Constraint_System* PPL::Constraint_System::zero_dim_empty_p = 0;
00587
00588 void
00589 PPL::Constraint_System::initialize() {
00590 PPL_ASSERT(zero_dim_empty_p == 0);
00591 zero_dim_empty_p
00592 = new Constraint_System(Constraint::zero_dim_false());
00593 }
00594
00595 void
00596 PPL::Constraint_System::finalize() {
00597 PPL_ASSERT(zero_dim_empty_p != 0);
00598 delete zero_dim_empty_p;
00599 zero_dim_empty_p = 0;
00600 }
00601
00602 bool
00603 PPL::Constraint_System::OK() const {
00604
00605
00606
00607 if (!Linear_System::OK(false))
00608 return false;
00609
00610
00611 const Constraint_System& x = *this;
00612 for (dimension_type i = num_rows(); i-- > 0; )
00613 if (!x[i].OK())
00614 return false;
00615
00616
00617 return true;
00618 }
00619
00621 std::ostream&
00622 PPL::IO_Operators::operator<<(std::ostream& s, const Constraint_System& cs) {
00623 Constraint_System::const_iterator i = cs.begin();
00624 const Constraint_System::const_iterator cs_end = cs.end();
00625 if (i == cs_end)
00626 s << "true";
00627 else {
00628 while (i != cs_end) {
00629 s << *i++;
00630 if (i != cs_end)
00631 s << ", ";
00632 }
00633 }
00634 return s;
00635 }