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 #include "Pointset_Powerset.defs.hh"
00026 #include "Grid.defs.hh"
00027 #include <utility>
00028
00029 namespace PPL = Parma_Polyhedra_Library;
00030
00031 template <>
00032 void
00033 PPL::Pointset_Powerset<PPL::NNC_Polyhedron>
00034 ::difference_assign(const Pointset_Powerset& y) {
00035 Pointset_Powerset& x = *this;
00036
00037 x.omega_reduce();
00038 y.omega_reduce();
00039 Sequence new_sequence = x.sequence;
00040 for (const_iterator yi = y.begin(), y_end = y.end(); yi != y_end; ++yi) {
00041 const NNC_Polyhedron& py = yi->pointset();
00042 Sequence tmp_sequence;
00043 for (Sequence_const_iterator nsi = new_sequence.begin(),
00044 ns_end = new_sequence.end(); nsi != ns_end; ++nsi) {
00045 std::pair<NNC_Polyhedron, Pointset_Powerset<NNC_Polyhedron> > partition
00046 = linear_partition(py, nsi->pointset());
00047 const Pointset_Powerset<NNC_Polyhedron>& residues = partition.second;
00048
00049 std::copy(residues.begin(), residues.end(), back_inserter(tmp_sequence));
00050 }
00051 std::swap(tmp_sequence, new_sequence);
00052 }
00053 std::swap(x.sequence, new_sequence);
00054 x.reduced = false;
00055 PPL_ASSERT_HEAVY(x.OK());
00056 }
00057
00058 template <>
00059 bool
00060 PPL::Pointset_Powerset<PPL::NNC_Polyhedron>
00061 ::geometrically_covers(const Pointset_Powerset& y) const {
00062 const Pointset_Powerset& x = *this;
00063 for (const_iterator yi = y.begin(), y_end = y.end(); yi != y_end; ++yi)
00064 if (!check_containment(yi->pointset(), x))
00065 return false;
00066 return true;
00067 }
00068
00070 bool
00071 PPL::check_containment(const NNC_Polyhedron& ph,
00072 const Pointset_Powerset<NNC_Polyhedron>& ps) {
00073 if (ph.is_empty())
00074 return true;
00075 Pointset_Powerset<NNC_Polyhedron> tmp(ph.space_dimension(), EMPTY);
00076 tmp.add_disjunct(ph);
00077 for (Pointset_Powerset<NNC_Polyhedron>::const_iterator
00078 i = ps.begin(), ps_end = ps.end(); i != ps_end; ++i) {
00079 const NNC_Polyhedron& pi = i->pointset();
00080 for (Pointset_Powerset<NNC_Polyhedron>::iterator
00081 j = tmp.begin(); j != tmp.end(); ) {
00082 const NNC_Polyhedron& pj = j->pointset();
00083 if (pi.contains(pj))
00084 j = tmp.drop_disjunct(j);
00085 else
00086 ++j;
00087 }
00088 if (tmp.empty())
00089 return true;
00090 else {
00091 Pointset_Powerset<NNC_Polyhedron> new_disjuncts(ph.space_dimension(),
00092 EMPTY);
00093 for (Pointset_Powerset<NNC_Polyhedron>::iterator
00094 j = tmp.begin(); j != tmp.end(); ) {
00095 const NNC_Polyhedron& pj = j->pointset();
00096 if (pj.is_disjoint_from(pi))
00097 ++j;
00098 else {
00099 std::pair<NNC_Polyhedron, Pointset_Powerset<NNC_Polyhedron> >
00100 partition = linear_partition(pi, pj);
00101 new_disjuncts.upper_bound_assign(partition.second);
00102 j = tmp.drop_disjunct(j);
00103 }
00104 }
00105 tmp.upper_bound_assign(new_disjuncts);
00106 }
00107 }
00108 return false;
00109 }
00110
00111
00112 namespace {
00113
00114 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
00115
00116
00122 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
00123 bool
00124 approximate_partition_aux(const PPL::Congruence& c,
00125 PPL::Grid& qq,
00126 PPL::Pointset_Powerset<PPL::Grid>& r) {
00127 using namespace PPL;
00128 const Coefficient& c_modulus = c.modulus();
00129 Grid qq_copy(qq);
00130 qq.add_congruence(c);
00131 if (qq.is_empty()) {
00132 r.add_disjunct(qq_copy);
00133 return true;
00134 }
00135
00136 Congruence_System cgs = qq.congruences();
00137 Congruence_System cgs_copy = qq_copy.congruences();
00138
00139
00140
00141 if (c_modulus == 0) {
00142 if (cgs.num_equalities() != cgs_copy.num_equalities()) {
00143 r.add_disjunct(qq_copy);
00144 return false;
00145 }
00146 return true;
00147 }
00148
00149
00150
00151
00152 if (cgs.num_proper_congruences() != cgs_copy.num_proper_congruences()) {
00153 r.add_disjunct(qq_copy);
00154 return false;
00155 }
00156
00157
00158
00159
00160 const Coefficient& c_inhomogeneous_term = c.inhomogeneous_term();
00161 Linear_Expression le(c);
00162 le -= c_inhomogeneous_term;
00163 PPL_DIRTY_TEMP_COEFFICIENT(n);
00164 rem_assign(n, c_inhomogeneous_term, c_modulus);
00165 if (n < 0)
00166 n += c_modulus;
00167 PPL_DIRTY_TEMP_COEFFICIENT(i);
00168 for (i = c_modulus; i-- > 0; )
00169 if (i != n) {
00170 Grid qqq(qq_copy);
00171 qqq.add_congruence((le+i %= 0) / c_modulus);
00172 if (!qqq.is_empty())
00173 r.add_disjunct(qqq);
00174 }
00175 return true;
00176 }
00177
00178 }
00179
00181 std::pair<PPL::Grid, PPL::Pointset_Powerset<PPL::Grid> >
00182 PPL::approximate_partition(const Grid& p, const Grid& q,
00183 bool& finite_partition) {
00184 using namespace PPL;
00185 finite_partition = true;
00186 Pointset_Powerset<Grid> r(p.space_dimension(), EMPTY);
00187
00188
00189 (void) q.minimized_congruences();
00190 Grid qq = q;
00191 const Congruence_System& pcs = p.congruences();
00192 for (Congruence_System::const_iterator i = pcs.begin(),
00193 pcs_end = pcs.end(); i != pcs_end; ++i)
00194 if (!approximate_partition_aux(*i, qq, r)) {
00195 finite_partition = false;
00196 Pointset_Powerset<Grid> s(q);
00197 return std::make_pair(qq, s);
00198 }
00199 return std::make_pair(qq, r);
00200 }
00201
00203 bool
00204 PPL::check_containment(const Grid& ph,
00205 const Pointset_Powerset<Grid>& ps) {
00206 if (ph.is_empty())
00207 return true;
00208 Pointset_Powerset<Grid> tmp(ph.space_dimension(), EMPTY);
00209 tmp.add_disjunct(ph);
00210 for (Pointset_Powerset<Grid>::const_iterator
00211 i = ps.begin(), ps_end = ps.end(); i != ps_end; ++i) {
00212 const Grid& pi = i->pointset();
00213 for (Pointset_Powerset<Grid>::iterator
00214 j = tmp.begin(); j != tmp.end(); ) {
00215 const Grid& pj = j->pointset();
00216 if (pi.contains(pj))
00217 j = tmp.drop_disjunct(j);
00218 else
00219 ++j;
00220 }
00221 if (tmp.empty())
00222 return true;
00223 else {
00224 Pointset_Powerset<Grid> new_disjuncts(ph.space_dimension(),
00225 EMPTY);
00226 for (Pointset_Powerset<Grid>::iterator
00227 j = tmp.begin(); j != tmp.end(); ) {
00228 const Grid& pj = j->pointset();
00229 if (pj.is_disjoint_from(pi))
00230 ++j;
00231 else {
00232 bool finite_partition;
00233 std::pair<Grid, Pointset_Powerset<Grid> >
00234 partition = approximate_partition(pi, pj, finite_partition);
00235
00236
00237
00238
00239
00240
00241
00242
00243 if (!finite_partition)
00244 break;
00245 new_disjuncts.upper_bound_assign(partition.second);
00246 j = tmp.drop_disjunct(j);
00247 }
00248 }
00249 tmp.upper_bound_assign(new_disjuncts);
00250 }
00251 }
00252 return false;
00253 }
00254
00255 template <>
00256 void
00257 PPL::Pointset_Powerset<PPL::Grid>
00258 ::difference_assign(const Pointset_Powerset& y) {
00259 Pointset_Powerset& x = *this;
00260
00261 x.omega_reduce();
00262 y.omega_reduce();
00263 Sequence new_sequence = x.sequence;
00264 for (const_iterator yi = y.begin(), y_end = y.end(); yi != y_end; ++yi) {
00265 const Grid& py = yi->pointset();
00266 Sequence tmp_sequence;
00267 for (Sequence_const_iterator nsi = new_sequence.begin(),
00268 ns_end = new_sequence.end(); nsi != ns_end; ++nsi) {
00269 bool finite_partition;
00270 std::pair<Grid, Pointset_Powerset<Grid> > partition
00271 = approximate_partition(py, nsi->pointset(), finite_partition);
00272 const Pointset_Powerset<Grid>& residues = partition.second;
00273
00274 std::copy(residues.begin(), residues.end(), back_inserter(tmp_sequence));
00275 }
00276 std::swap(tmp_sequence, new_sequence);
00277 }
00278 std::swap(x.sequence, new_sequence);
00279 x.reduced = false;
00280 PPL_ASSERT_HEAVY(x.OK());
00281 }
00282
00283 template <>
00284 bool
00285 PPL::Pointset_Powerset<PPL::Grid>
00286 ::geometrically_covers(const Pointset_Powerset& y) const {
00287 const Pointset_Powerset& x = *this;
00288 for (const_iterator yi = y.begin(), y_end = y.end(); yi != y_end; ++yi)
00289 if (!check_containment(yi->pointset(), x))
00290 return false;
00291 return true;
00292 }
00293
00294 template <>
00295 template <>
00296 PPL::Pointset_Powerset<PPL::NNC_Polyhedron>
00297 ::Pointset_Powerset(const Pointset_Powerset<C_Polyhedron>& y,
00298 Complexity_Class)
00299 : Base(), space_dim(y.space_dimension()) {
00300 Pointset_Powerset& x = *this;
00301 for (Pointset_Powerset<C_Polyhedron>::const_iterator i = y.begin(),
00302 y_end = y.end(); i != y_end; ++i)
00303 x.sequence.push_back(Determinate<NNC_Polyhedron>
00304 (NNC_Polyhedron(i->pointset())));
00305 x.reduced = y.reduced;
00306 PPL_ASSERT_HEAVY(x.OK());
00307 }
00308
00309 template <>
00310 template <>
00311 PPL::Pointset_Powerset<PPL::NNC_Polyhedron>
00312 ::Pointset_Powerset(const Pointset_Powerset<Grid>& y,
00313 Complexity_Class)
00314 : Base(), space_dim(y.space_dimension()) {
00315 Pointset_Powerset& x = *this;
00316 for (Pointset_Powerset<Grid>::const_iterator i = y.begin(),
00317 y_end = y.end(); i != y_end; ++i)
00318 x.sequence.push_back(Determinate<NNC_Polyhedron>
00319 (NNC_Polyhedron(i->pointset())));
00320 x.reduced = false;
00321 PPL_ASSERT_HEAVY(x.OK());
00322 }
00323
00324 template <>
00325 template <>
00326 PPL::Pointset_Powerset<PPL::C_Polyhedron>
00327 ::Pointset_Powerset(const Pointset_Powerset<NNC_Polyhedron>& y,
00328 Complexity_Class)
00329 : Base(), space_dim(y.space_dimension()) {
00330 Pointset_Powerset& x = *this;
00331 for (Pointset_Powerset<NNC_Polyhedron>::const_iterator i = y.begin(),
00332 y_end = y.end(); i != y_end; ++i)
00333 x.sequence.push_back(Determinate<C_Polyhedron>
00334 (C_Polyhedron(i->pointset())));
00335
00336
00337
00338
00339
00340 x.reduced = false;
00341 PPL_ASSERT_HEAVY(x.OK());
00342 }