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 #include <ppl-config.h>
00026
00027 #include "Polyhedron.defs.hh"
00028 #include "Variables_Set.defs.hh"
00029 #include "assert.hh"
00030
00031 #define BE_LAZY 1
00032
00033 namespace PPL = Parma_Polyhedra_Library;
00034
00035 void
00036 PPL::Polyhedron::add_space_dimensions(Linear_System& sys1,
00037 Linear_System& sys2,
00038 Bit_Matrix& sat1,
00039 Bit_Matrix& sat2,
00040 dimension_type add_dim) {
00041 PPL_ASSERT(sys1.topology() == sys2.topology());
00042 PPL_ASSERT(sys1.num_columns() == sys2.num_columns());
00043 PPL_ASSERT(add_dim != 0);
00044
00045 sys1.add_zero_columns(add_dim);
00046 dimension_type old_index = sys2.first_pending_row();
00047 sys2.add_rows_and_columns(add_dim);
00048
00049 sys2.set_index_first_pending_row(old_index + add_dim);
00050
00051
00052
00053
00054
00055
00056
00057 sat1.resize(sat1.num_rows() + add_dim, sat1.num_columns());
00058
00059 for (dimension_type i = sat1.num_rows() - add_dim; i-- > 0; )
00060 std::swap(sat1[i], sat1[i+add_dim]);
00061
00062 sat2.transpose_assign(sat1);
00063
00064 if (!sys1.is_necessarily_closed()) {
00065
00066 dimension_type new_eps_index = sys1.num_columns() - 1;
00067 dimension_type old_eps_index = new_eps_index - add_dim;
00068
00069 sys1.swap_columns(old_eps_index, new_eps_index);
00070
00071
00072 if (!sys2.is_sorted())
00073 sys2.swap_columns(old_eps_index, new_eps_index);
00074 else {
00075 for (dimension_type i = sys2.num_rows(); i-- > add_dim; ) {
00076 Linear_Row& r = sys2[i];
00077 std::swap(r[old_eps_index], r[new_eps_index]);
00078 }
00079
00080
00081 for (dimension_type i = add_dim; i-- > 0; ++old_eps_index) {
00082 Linear_Row& r = sys2[i];
00083 std::swap(r[old_eps_index], r[old_eps_index + 1]);
00084 }
00085 }
00086
00087
00088 }
00089 }
00090
00091 void
00092 PPL::Polyhedron::add_space_dimensions_and_embed(dimension_type m) {
00093
00094
00095 if (m > max_space_dimension() - space_dimension())
00096 throw_space_dimension_overflow(topology(),
00097 "add_space_dimensions_and_embed(m)",
00098 "adding m new space dimensions exceeds "
00099 "the maximum allowed space dimension");
00100
00101
00102 if (m == 0)
00103 return;
00104
00105
00106
00107
00108 if (marked_empty()) {
00109 space_dim += m;
00110 con_sys.clear();
00111 return;
00112 }
00113
00114
00115 if (space_dim == 0) {
00116
00117 PPL_ASSERT(status.test_zero_dim_univ());
00118
00119
00120 Polyhedron ph(topology(), m, UNIVERSE);
00121 swap(ph);
00122 return;
00123 }
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 if (constraints_are_up_to_date())
00134 if (generators_are_up_to_date()) {
00135
00136 if (!sat_c_is_up_to_date())
00137 update_sat_c();
00138
00139
00140
00141 add_space_dimensions(con_sys, gen_sys, sat_c, sat_g, m);
00142 }
00143 else {
00144
00145 con_sys.add_zero_columns(m);
00146
00147
00148 if (!is_necessarily_closed())
00149 con_sys.swap_columns(space_dim + 1, space_dim + 1 + m);
00150 }
00151 else {
00152
00153 PPL_ASSERT(generators_are_up_to_date());
00154 gen_sys.add_rows_and_columns(m);
00155
00156 gen_sys.unset_pending_rows();
00157
00158
00159 if (!is_necessarily_closed()) {
00160
00161 if (!gen_sys.is_sorted())
00162 gen_sys.swap_columns(space_dim + 1, space_dim + 1 + m);
00163 else {
00164 dimension_type old_eps_index = space_dim + 1;
00165 dimension_type new_eps_index = old_eps_index + m;
00166 for (dimension_type i = gen_sys.num_rows(); i-- > m; ) {
00167 Generator& r = gen_sys[i];
00168 std::swap(r[old_eps_index], r[new_eps_index]);
00169 }
00170
00171
00172 for (dimension_type i = m; i-- > 0; ++old_eps_index) {
00173 Generator& r = gen_sys[i];
00174 std::swap(r[old_eps_index], r[old_eps_index + 1]);
00175 }
00176 }
00177 }
00178 }
00179
00180 space_dim += m;
00181
00182
00183
00184 PPL_ASSERT_HEAVY(OK());
00185 }
00186
00187 void
00188 PPL::Polyhedron::add_space_dimensions_and_project(dimension_type m) {
00189
00190
00191 if (m > max_space_dimension() - space_dimension())
00192 throw_space_dimension_overflow(topology(),
00193 "add_space_dimensions_and_project(m)",
00194 "adding m new space dimensions exceeds "
00195 "the maximum allowed space dimension");
00196
00197
00198 if (m == 0)
00199 return;
00200
00201
00202
00203 if (marked_empty()) {
00204 space_dim += m;
00205 con_sys.clear();
00206 return;
00207 }
00208
00209 if (space_dim == 0) {
00210 PPL_ASSERT(status.test_zero_dim_univ() && gen_sys.has_no_rows());
00211
00212
00213
00214
00215
00216 if (!is_necessarily_closed())
00217 gen_sys.insert(Generator::zero_dim_closure_point());
00218 gen_sys.insert(Generator::zero_dim_point());
00219 gen_sys.adjust_topology_and_space_dimension(topology(), m);
00220 set_generators_minimized();
00221 space_dim = m;
00222 PPL_ASSERT_HEAVY(OK());
00223 return;
00224 }
00225
00226
00227
00228
00229
00230
00231
00232
00233 if (constraints_are_up_to_date())
00234 if (generators_are_up_to_date()) {
00235
00236 if (!sat_g_is_up_to_date())
00237 update_sat_g();
00238
00239
00240
00241 add_space_dimensions(gen_sys, con_sys, sat_g, sat_c, m);
00242 }
00243 else {
00244
00245 con_sys.add_rows_and_columns(m);
00246
00247 con_sys.unset_pending_rows();
00248
00249
00250 if (!is_necessarily_closed()) {
00251
00252 if (!con_sys.is_sorted())
00253 con_sys.swap_columns(space_dim + 1, space_dim + 1 + m);
00254 else {
00255 dimension_type old_eps_index = space_dim + 1;
00256 dimension_type new_eps_index = old_eps_index + m;
00257 for (dimension_type i = con_sys.num_rows(); i-- > m; ) {
00258 Constraint& r = con_sys[i];
00259 std::swap(r[old_eps_index], r[new_eps_index]);
00260 }
00261
00262
00263 for (dimension_type i = m; i-- > 0; ++old_eps_index) {
00264 Constraint& r = con_sys[i];
00265 std::swap(r[old_eps_index], r[old_eps_index + 1]);
00266 }
00267 }
00268 }
00269 }
00270 else {
00271
00272 PPL_ASSERT(generators_are_up_to_date());
00273 gen_sys.add_zero_columns(m);
00274
00275
00276 if (!is_necessarily_closed())
00277 gen_sys.swap_columns(space_dim + 1, space_dim + 1 + m);
00278 }
00279
00280 space_dim += m;
00281
00282
00283
00284 PPL_ASSERT_HEAVY(OK());
00285 }
00286
00287 void
00288 PPL::Polyhedron::concatenate_assign(const Polyhedron& y) {
00289 if (topology() != y.topology())
00290 throw_topology_incompatible("concatenate_assign(y)", "y", y);
00291
00292
00293
00294 const dimension_type added_columns = y.space_dim;
00295 if (added_columns > max_space_dimension() - space_dim)
00296 throw_space_dimension_overflow(topology(),
00297 "concatenate_assign(y)",
00298 "concatenation exceeds the maximum "
00299 "allowed space dimension");
00300
00301
00302
00303 if (marked_empty() || y.marked_empty()) {
00304 space_dim += added_columns;
00305 set_empty();
00306 return;
00307 }
00308
00309
00310 if (added_columns == 0)
00311 return;
00312
00313
00314 if (space_dim == 0) {
00315 *this = y;
00316 return;
00317 }
00318
00319
00320 Constraint_System cs = y.constraints();
00321
00322
00323 if (has_pending_generators())
00324 process_pending_generators();
00325 else if (!constraints_are_up_to_date())
00326 update_constraints();
00327
00328
00329
00330
00331
00332 dimension_type old_num_rows = con_sys.num_rows();
00333 dimension_type old_num_columns = con_sys.num_columns();
00334 dimension_type added_rows = cs.num_rows();
00335
00336
00337
00338 PPL_ASSERT(added_rows > 0 && added_columns > 0);
00339
00340 con_sys.add_zero_rows_and_columns(added_rows, added_columns,
00341 Linear_Row::Flags(topology(),
00342 Linear_Row::RAY_OR_POINT_OR_INEQUALITY));
00343
00344 if (!is_necessarily_closed())
00345 con_sys.swap_columns(old_num_columns - 1,
00346 old_num_columns - 1 + added_columns);
00347 dimension_type cs_num_columns = cs.num_columns();
00348
00349
00350 for (dimension_type i = added_rows; i-- > 0; ) {
00351 Constraint& c_old = cs[i];
00352 Constraint& c_new = con_sys[old_num_rows + i];
00353
00354 if (c_old.is_equality())
00355 c_new.set_is_equality();
00356
00357 std::swap(c_new[0], c_old[0]);
00358
00359
00360 for (dimension_type j = 1; j < cs_num_columns; ++j)
00361 std::swap(c_old[j], c_new[space_dim + j]);
00362 }
00363
00364 if (can_have_something_pending()) {
00365
00366
00367
00368
00369
00370 gen_sys.add_rows_and_columns(added_columns);
00371 gen_sys.set_sorted(false);
00372 if (!is_necessarily_closed())
00373 gen_sys.swap_columns(old_num_columns - 1,
00374 old_num_columns - 1 + added_columns);
00375
00376 gen_sys.unset_pending_rows();
00377
00378
00379
00380
00381 if (!sat_c_is_up_to_date()) {
00382 sat_c.transpose_assign(sat_g);
00383 set_sat_c_up_to_date();
00384 }
00385 clear_sat_g_up_to_date();
00386 sat_c.resize(sat_c.num_rows() + added_columns, sat_c.num_columns());
00387
00388
00389
00390 for (dimension_type i = sat_c.num_rows() - added_columns; i-- > 0; )
00391 std::swap(sat_c[i], sat_c[i+added_columns]);
00392
00393 set_constraints_pending();
00394 }
00395 else {
00396
00397 con_sys.unset_pending_rows();
00398 #if BE_LAZY
00399 con_sys.set_sorted(false);
00400 #else
00401 con_sys.sort_rows();
00402 #endif
00403 clear_constraints_minimized();
00404 clear_generators_up_to_date();
00405 clear_sat_g_up_to_date();
00406 clear_sat_c_up_to_date();
00407 }
00408
00409 space_dim += added_columns;
00410
00411
00412
00413 PPL_ASSERT_HEAVY(OK());
00414 }
00415
00416 void
00417 PPL::Polyhedron::remove_space_dimensions(const Variables_Set& vars) {
00418
00419
00420
00421 if (vars.empty()) {
00422 PPL_ASSERT_HEAVY(OK());
00423 return;
00424 }
00425
00426
00427 const dimension_type min_space_dim = vars.space_dimension();
00428 if (space_dim < min_space_dim)
00429 throw_dimension_incompatible("remove_space_dimensions(vs)", min_space_dim);
00430
00431 const dimension_type new_space_dim = space_dim - vars.size();
00432
00433
00434
00435 if (marked_empty()
00436 || (has_something_pending() && !remove_pending_to_obtain_generators())
00437 || (!generators_are_up_to_date() && !update_generators())) {
00438
00439
00440
00441 con_sys.clear();
00442
00443 space_dim = new_space_dim;
00444 PPL_ASSERT_HEAVY(OK());
00445 return;
00446 }
00447
00448
00449
00450 if (new_space_dim == 0) {
00451 set_zero_dim_univ();
00452 return;
00453 }
00454
00455
00456
00457 Variables_Set::const_iterator vsi = vars.begin();
00458 Variables_Set::const_iterator vsi_end = vars.end();
00459 dimension_type dst_col = *vsi + 1;
00460 dimension_type src_col = dst_col + 1;
00461 for (++vsi; vsi != vsi_end; ++vsi) {
00462 const dimension_type vsi_col = *vsi + 1;
00463
00464 while (src_col < vsi_col)
00465 gen_sys.Matrix::swap_columns(dst_col++, src_col++);
00466 ++src_col;
00467 }
00468
00469 const dimension_type gen_sys_num_columns = gen_sys.num_columns();
00470 while (src_col < gen_sys_num_columns)
00471 gen_sys.Matrix::swap_columns(dst_col++, src_col++);
00472
00473
00474
00475 gen_sys.remove_trailing_columns(gen_sys_num_columns - dst_col);
00476
00477 gen_sys.remove_invalid_lines_and_rays();
00478
00479
00480 clear_constraints_up_to_date();
00481 clear_generators_minimized();
00482
00483
00484 space_dim = new_space_dim;
00485
00486 PPL_ASSERT_HEAVY(OK(true));
00487 }
00488
00489 void
00490 PPL::Polyhedron::remove_higher_space_dimensions(dimension_type new_dimension) {
00491
00492 if (new_dimension > space_dim)
00493 throw_dimension_incompatible("remove_higher_space_dimensions(nd)",
00494 new_dimension);
00495
00496
00497
00498
00499 if (new_dimension == space_dim) {
00500 PPL_ASSERT_HEAVY(OK());
00501 return;
00502 }
00503
00504
00505
00506 if (marked_empty()
00507 || (has_something_pending() && !remove_pending_to_obtain_generators())
00508 || (!generators_are_up_to_date() && !update_generators())) {
00509
00510
00511 space_dim = new_dimension;
00512 con_sys.clear();
00513 PPL_ASSERT_HEAVY(OK());
00514 return;
00515 }
00516
00517 if (new_dimension == 0) {
00518
00519
00520 set_zero_dim_univ();
00521 return;
00522 }
00523
00524 dimension_type new_num_cols = new_dimension + 1;
00525 if (!is_necessarily_closed()) {
00526
00527
00528 gen_sys.swap_columns(gen_sys.num_columns() - 1, new_num_cols);
00529
00530 ++new_num_cols;
00531 }
00532
00533 gen_sys.remove_trailing_columns(space_dim - new_dimension);
00534
00535 gen_sys.remove_invalid_lines_and_rays();
00536
00537
00538 clear_constraints_up_to_date();
00539 clear_generators_minimized();
00540
00541
00542 space_dim = new_dimension;
00543
00544 PPL_ASSERT_HEAVY(OK(true));
00545 }
00546
00547 void
00548 PPL::Polyhedron::expand_space_dimension(Variable var, dimension_type m) {
00549
00550
00551
00552 if (var.space_dimension() > space_dim)
00553 throw_dimension_incompatible("expand_space_dimension(v, m)", "v", var);
00554
00555
00556
00557 if (m > max_space_dimension() - space_dimension())
00558 throw_space_dimension_overflow(topology(),
00559 "expand_dimension(v, m)",
00560 "adding m new space dimensions exceeds "
00561 "the maximum allowed space dimension");
00562
00563
00564 if (m == 0)
00565 return;
00566
00567
00568 dimension_type old_dim = space_dim;
00569
00570
00571 add_space_dimensions_and_embed(m);
00572
00573 const dimension_type src_d = var.id();
00574 const Constraint_System& cs = constraints();
00575 Constraint_System new_constraints;
00576 for (Constraint_System::const_iterator i = cs.begin(),
00577 cs_end = cs.end(); i != cs_end; ++i) {
00578 const Constraint& c = *i;
00579
00580
00581 if (c.coefficient(var) == 0)
00582 continue;
00583
00584
00585 for (dimension_type dst_d = old_dim; dst_d < old_dim+m; ++dst_d) {
00586 Linear_Expression e;
00587 for (dimension_type j = old_dim; j-- > 0; )
00588 e +=
00589 c.coefficient(Variable(j))
00590 * (j == src_d ? Variable(dst_d) : Variable(j));
00591 e += c.inhomogeneous_term();
00592 new_constraints.insert(c.is_equality()
00593 ? (e == 0)
00594 : (c.is_nonstrict_inequality()
00595 ? (e >= 0)
00596 : (e > 0)));
00597 }
00598 }
00599 add_recycled_constraints(new_constraints);
00600 PPL_ASSERT_HEAVY(OK());
00601 }
00602
00603 void
00604 PPL::Polyhedron::fold_space_dimensions(const Variables_Set& vars,
00605 Variable dest) {
00606
00607
00608
00609 if (dest.space_dimension() > space_dim)
00610 throw_dimension_incompatible("fold_space_dimensions(vs, v)", "v", dest);
00611
00612
00613 if (vars.empty())
00614 return;
00615
00616
00617 if (vars.space_dimension() > space_dim)
00618 throw_dimension_incompatible("fold_space_dimensions(vs, v)",
00619 "vs.space_dimension()",
00620 vars.space_dimension());
00621
00622
00623 if (vars.find(dest.id()) != vars.end())
00624 throw_invalid_argument("fold_space_dimensions(vs, v)",
00625 "v should not occur in vs");
00626
00627
00628
00629
00630
00631 (void) generators();
00632
00633
00634 if (!marked_empty()) {
00635 for (Variables_Set::const_iterator i = vars.begin(),
00636 vs_end = vars.end(); i != vs_end; ++i) {
00637 Polyhedron copy = *this;
00638 copy.affine_image(dest, Linear_Expression(Variable(*i)));
00639 poly_hull_assign(copy);
00640 }
00641 }
00642 remove_space_dimensions(vars);
00643 PPL_ASSERT_HEAVY(OK());
00644 }