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_Polyhedron_templates_hh
00025 #define PPL_Polyhedron_templates_hh 1
00026
00027 #include "Generator.defs.hh"
00028 #include "MIP_Problem.defs.hh"
00029 #include "Interval.defs.hh"
00030 #include <algorithm>
00031 #include <deque>
00032
00033 namespace Parma_Polyhedra_Library {
00034
00035 template <typename Interval>
00036 Polyhedron::Polyhedron(Topology topol,
00037 const Box<Interval>& box,
00038 Complexity_Class)
00039 : con_sys(topol),
00040 gen_sys(topol),
00041 sat_c(),
00042 sat_g() {
00043
00044 space_dim = box.space_dimension();
00045
00046
00047 if (box.is_empty()) {
00048 set_empty();
00049 return;
00050 }
00051
00052
00053 if (space_dim == 0) {
00054 set_zero_dim_univ();
00055 return;
00056 }
00057
00058
00059
00060
00061 con_sys.insert(Variable(space_dim - 1) >= 0);
00062
00063 PPL_DIRTY_TEMP_COEFFICIENT(l_n);
00064 PPL_DIRTY_TEMP_COEFFICIENT(l_d);
00065 PPL_DIRTY_TEMP_COEFFICIENT(u_n);
00066 PPL_DIRTY_TEMP_COEFFICIENT(u_d);
00067
00068 if (topol == NECESSARILY_CLOSED) {
00069 for (dimension_type k = space_dim; k-- > 0; ) {
00070
00071 bool l_closed = false;
00072 bool l_bounded = box.get_lower_bound(k, l_closed, l_n, l_d);
00073
00074 bool u_closed = false;
00075 bool u_bounded = box.get_upper_bound(k, u_closed, u_n, u_d);
00076
00077
00078 if (l_bounded && u_bounded
00079 && l_closed && u_closed
00080 && l_n == u_n && l_d == u_d) {
00081
00082 con_sys.insert(l_d * Variable(k) == l_n);
00083 }
00084 else {
00085 if (l_bounded)
00086
00087 con_sys.insert(l_d * Variable(k) >= l_n);
00088 if (u_bounded)
00089
00090 con_sys.insert(u_d * Variable(k) <= u_n);
00091 }
00092 }
00093 }
00094 else {
00095
00096 for (dimension_type k = space_dim; k-- > 0; ) {
00097
00098 bool l_closed = false;
00099 bool l_bounded = box.get_lower_bound(k, l_closed, l_n, l_d);
00100
00101 bool u_closed = false;
00102 bool u_bounded = box.get_upper_bound(k, u_closed, u_n, u_d);
00103
00104
00105 if (l_bounded && u_bounded
00106 && l_closed && u_closed
00107 && l_n == u_n && l_d == u_d) {
00108
00109 con_sys.insert(l_d * Variable(k) == l_n);
00110 }
00111 else {
00112
00113 if (l_bounded) {
00114 if (l_closed)
00115
00116 con_sys.insert(l_d * Variable(k) >= l_n);
00117 else
00118
00119 con_sys.insert(l_d * Variable(k) > l_n);
00120 }
00121
00122 if (u_bounded) {
00123 if (u_closed)
00124
00125 con_sys.insert(u_d * Variable(k) <= u_n);
00126 else
00127
00128 con_sys.insert(u_d * Variable(k) < u_n);
00129 }
00130 }
00131 }
00132 }
00133
00134
00135 con_sys.add_low_level_constraints();
00136
00137 dimension_type n_rows = con_sys.num_rows() - 1;
00138 con_sys[0].swap(con_sys[n_rows]);
00139 con_sys.set_sorted(false);
00140
00141 con_sys.set_index_first_pending_row(n_rows);
00142 con_sys.erase_to_end(n_rows);
00143
00144
00145 set_constraints_up_to_date();
00146 PPL_ASSERT_HEAVY(OK());
00147 }
00148
00149 template <typename Partial_Function>
00150 void
00151 Polyhedron::map_space_dimensions(const Partial_Function& pfunc) {
00152 if (space_dim == 0)
00153 return;
00154
00155 if (pfunc.has_empty_codomain()) {
00156
00157 if (marked_empty()
00158 || (has_pending_constraints()
00159 && !remove_pending_to_obtain_generators())
00160 || (!generators_are_up_to_date() && !update_generators())) {
00161
00162 space_dim = 0;
00163 con_sys.clear();
00164 }
00165 else
00166
00167 set_zero_dim_univ();
00168
00169 PPL_ASSERT_HEAVY(OK());
00170 return;
00171 }
00172
00173 const dimension_type new_space_dimension = pfunc.max_in_codomain() + 1;
00174
00175 if (new_space_dimension == space_dim) {
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 std::vector<dimension_type> cycles;
00192 cycles.reserve(space_dim + space_dim/2);
00193
00194
00195 std::deque<bool> visited(space_dim);
00196
00197 for (dimension_type i = space_dim; i-- > 0; ) {
00198 if (!visited[i]) {
00199 dimension_type j = i;
00200 do {
00201 visited[j] = true;
00202
00203 dimension_type k = 0;
00204 if (!pfunc.maps(j, k))
00205 throw_invalid_argument("map_space_dimensions(pfunc)",
00206 " pfunc is inconsistent");
00207 if (k == j)
00208
00209 goto skip;
00210
00211 cycles.push_back(j+1);
00212
00213 j = k;
00214 } while (!visited[j]);
00215
00216 cycles.push_back(0);
00217 skip:
00218 ;
00219 }
00220 }
00221
00222
00223 if (cycles.empty())
00224 return;
00225
00226
00227
00228
00229 if (constraints_are_up_to_date())
00230 con_sys.permute_columns(cycles);
00231
00232 if (generators_are_up_to_date())
00233 gen_sys.permute_columns(cycles);
00234
00235 PPL_ASSERT_HEAVY(OK());
00236 return;
00237 }
00238
00239
00240
00241
00242
00243 const Generator_System& old_gensys = generators();
00244
00245 if (old_gensys.has_no_rows()) {
00246
00247 Polyhedron new_polyhedron(topology(), new_space_dimension, EMPTY);
00248 std::swap(*this, new_polyhedron);
00249 PPL_ASSERT_HEAVY(OK());
00250 return;
00251 }
00252
00253
00254 std::vector<dimension_type> pfunc_maps(space_dim, not_a_dimension());
00255 for (dimension_type j = space_dim; j-- > 0; ) {
00256 dimension_type pfunc_j;
00257 if (pfunc.maps(j, pfunc_j))
00258 pfunc_maps[j] = pfunc_j;
00259 }
00260
00261 Generator_System new_gensys;
00262 for (Generator_System::const_iterator i = old_gensys.begin(),
00263 old_gensys_end = old_gensys.end(); i != old_gensys_end; ++i) {
00264 const Generator& old_g = *i;
00265 Linear_Expression e(0 * Variable(new_space_dimension-1));
00266 bool all_zeroes = true;
00267 for (dimension_type j = space_dim; j-- > 0; ) {
00268 if (old_g.coefficient(Variable(j)) != 0
00269 && pfunc_maps[j] != not_a_dimension()) {
00270 e += Variable(pfunc_maps[j]) * old_g.coefficient(Variable(j));
00271 all_zeroes = false;
00272 }
00273 }
00274 switch (old_g.type()) {
00275 case Generator::LINE:
00276 if (!all_zeroes)
00277 new_gensys.insert(line(e));
00278 break;
00279 case Generator::RAY:
00280 if (!all_zeroes)
00281 new_gensys.insert(ray(e));
00282 break;
00283 case Generator::POINT:
00284
00285 new_gensys.insert(point(e, old_g.divisor()));
00286 break;
00287 case Generator::CLOSURE_POINT:
00288
00289 new_gensys.insert(closure_point(e, old_g.divisor()));
00290 break;
00291 }
00292 }
00293 Polyhedron new_polyhedron(topology(), new_gensys);
00294 std::swap(*this, new_polyhedron);
00295 PPL_ASSERT_HEAVY(OK(true));
00296 }
00297
00298 }
00299
00300 #endif // !defined(PPL_Polyhedron_templates_hh)