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_Powerset_templates_hh
00025 #define PPL_Powerset_templates_hh 1
00026
00027 #include "globals.defs.hh"
00028 #include <algorithm>
00029 #include "assert.hh"
00030 #include <iostream>
00031
00032 namespace Parma_Polyhedra_Library {
00033
00034 template <typename D>
00035 void
00036 Powerset<D>::collapse(const Sequence_iterator sink) {
00037 PPL_ASSERT(sink != sequence.end());
00038 D& d = *sink;
00039 iterator x_sink = sink;
00040 iterator next_x_sink = x_sink;
00041 ++next_x_sink;
00042 iterator x_end = end();
00043 for (const_iterator xi = next_x_sink; xi != x_end; ++xi)
00044 d.upper_bound_assign(*xi);
00045
00046 drop_disjuncts(next_x_sink, x_end);
00047
00048
00049 for (iterator xi = begin(); xi != x_sink; )
00050 if (xi->definitely_entails(d))
00051 xi = drop_disjunct(xi);
00052 else
00053 ++xi;
00054
00055 PPL_ASSERT_HEAVY(OK());
00056 }
00057
00058 template <typename D>
00059 void
00060 Powerset<D>::omega_reduce() const {
00061 if (reduced)
00062 return;
00063
00064 Powerset& x = const_cast<Powerset&>(*this);
00065
00066 for (iterator xi = x.begin(), x_end = x.end(); xi != x_end; )
00067 if (xi->is_bottom())
00068 xi = x.drop_disjunct(xi);
00069 else
00070 ++xi;
00071
00072 for (iterator xi = x.begin(); xi != x.end(); ) {
00073 const D& xv = *xi;
00074 bool dropping_xi = false;
00075 for (iterator yi = x.begin(); yi != x.end(); )
00076 if (xi == yi)
00077 ++yi;
00078 else {
00079 const D& yv = *yi;
00080 if (yv.definitely_entails(xv))
00081 yi = x.drop_disjunct(yi);
00082 else if (xv.definitely_entails(yv)) {
00083 dropping_xi = true;
00084 break;
00085 }
00086 else
00087 ++yi;
00088 }
00089 if (dropping_xi)
00090 xi = x.drop_disjunct(xi);
00091 else
00092 ++xi;
00093 if (abandon_expensive_computations && xi != x.end()) {
00094
00095 x.collapse(xi.base);
00096 break;
00097 }
00098 }
00099 reduced = true;
00100 PPL_ASSERT_HEAVY(OK());
00101 }
00102
00103 template <typename D>
00104 void
00105 Powerset<D>::collapse(const unsigned max_disjuncts) {
00106 PPL_ASSERT(max_disjuncts > 0);
00107
00108 omega_reduce();
00109 size_type n = size();
00110 if (n > max_disjuncts) {
00111
00112 iterator i = begin();
00113 std::advance(i, max_disjuncts-1);
00114
00115
00116 collapse(i.base);
00117 }
00118 PPL_ASSERT_HEAVY(OK());
00119 PPL_ASSERT(is_omega_reduced());
00120 }
00121
00122 template <typename D>
00123 bool
00124 Powerset<D>::check_omega_reduced() const {
00125 for (const_iterator x_begin = begin(), x_end = end(),
00126 xi = x_begin; xi != x_end; ++xi) {
00127 const D& xv = *xi;
00128 if (xv.is_bottom())
00129 return false;
00130 for (const_iterator yi = x_begin; yi != x_end; ++yi) {
00131 if (xi == yi)
00132 continue;
00133 const D& yv = *yi;
00134 if (xv.definitely_entails(yv) || yv.definitely_entails(xv))
00135 return false;
00136 }
00137 }
00138 return true;
00139 }
00140
00141 template <typename D>
00142 bool
00143 Powerset<D>::is_omega_reduced() const {
00144 if (!reduced && check_omega_reduced())
00145 reduced = true;
00146 return reduced;
00147 }
00148
00149 template <typename D>
00150 typename Powerset<D>::iterator
00151 Powerset<D>::add_non_bottom_disjunct_preserve_reduction(const D& d,
00152 iterator first,
00153 iterator last) {
00154 PPL_ASSERT_HEAVY(!d.is_bottom());
00155 for (iterator xi = first; xi != last; ) {
00156 const D& xv = *xi;
00157 if (d.definitely_entails(xv))
00158 return first;
00159 else if (xv.definitely_entails(d)) {
00160 if (xi == first)
00161 ++first;
00162 xi = drop_disjunct(xi);
00163 }
00164 else
00165 ++xi;
00166 }
00167 sequence.push_back(d);
00168 PPL_ASSERT_HEAVY(OK());
00169 return first;
00170 }
00171
00172 template <typename D>
00173 bool
00174 Powerset<D>::definitely_entails(const Powerset& y) const {
00175 const Powerset<D>& x = *this;
00176 bool found = true;
00177 for (const_iterator xi = x.begin(),
00178 x_end = x.end(); found && xi != x_end; ++xi) {
00179 found = false;
00180 for (const_iterator yi = y.begin(),
00181 y_end = y.end(); !found && yi != y_end; ++yi)
00182 found = (*xi).definitely_entails(*yi);
00183 }
00184 return found;
00185 }
00186
00188 template <typename D>
00189 bool
00190 operator==(const Powerset<D>& x, const Powerset<D>& y) {
00191 x.omega_reduce();
00192 y.omega_reduce();
00193 if (x.size() != y.size())
00194 return false;
00195
00196 Powerset<D> yy = y;
00197 for (typename Powerset<D>::const_iterator xi = x.begin(),
00198 x_end = x.end(); xi != x_end; ++xi) {
00199 typename Powerset<D>::iterator yyi = yy.begin();
00200 typename Powerset<D>::iterator yy_end = yy.end();
00201 yyi = std::find(yyi, yy_end, *xi);
00202 if (yyi == yy_end)
00203 return false;
00204 else
00205 yy.drop_disjunct(yyi);
00206 }
00207 return true;
00208 }
00209
00210 template <typename D>
00211 template <typename Binary_Operator_Assign>
00212 void
00213 Powerset<D>::pairwise_apply_assign(const Powerset& y,
00214 Binary_Operator_Assign op_assign) {
00215
00216 omega_reduce();
00217 y.omega_reduce();
00218 Sequence new_sequence;
00219 for (const_iterator xi = begin(), x_end = end(),
00220 y_begin = y.begin(), y_end = y.end(); xi != x_end; ++xi)
00221 for (const_iterator yi = y_begin; yi != y_end; ++yi) {
00222 D zi = *xi;
00223 op_assign(zi, *yi);
00224 if (!zi.is_bottom())
00225 new_sequence.push_back(zi);
00226 }
00227
00228 std::swap(sequence, new_sequence);
00229 reduced = false;
00230 PPL_ASSERT_HEAVY(OK());
00231 }
00232
00233 template <typename D>
00234 void
00235 Powerset<D>::least_upper_bound_assign(const Powerset& y) {
00236
00237 omega_reduce();
00238 y.omega_reduce();
00239 iterator old_begin = begin();
00240 iterator old_end = end();
00241 for (const_iterator i = y.begin(), y_end = y.end(); i != y_end; ++i)
00242 old_begin = add_non_bottom_disjunct_preserve_reduction(*i,
00243 old_begin,
00244 old_end);
00245 PPL_ASSERT_HEAVY(OK());
00246 }
00247
00248 namespace IO_Operators {
00249
00251 template <typename D>
00252 std::ostream&
00253 operator<<(std::ostream& s, const Powerset<D>& x) {
00254 if (x.is_bottom())
00255 s << "false";
00256 else if (x.is_top())
00257 s << "true";
00258 else
00259 for (typename Powerset<D>::const_iterator i = x.begin(),
00260 x_end = x.end(); i != x_end; ) {
00261 s << "{ " << *i++ << " }";
00262 if (i != x_end)
00263 s << ", ";
00264 }
00265 return s;
00266 }
00267
00268 }
00269
00270 template <typename D>
00271 memory_size_type
00272 Powerset<D>::external_memory_in_bytes() const {
00273 memory_size_type bytes = 0;
00274 for (const_iterator xi = begin(), x_end = end(); xi != x_end; ++xi) {
00275 bytes += xi->total_memory_in_bytes();
00276
00277
00278
00279 bytes += 2*sizeof(D*);
00280 }
00281 return bytes;
00282 }
00283
00284 template <typename D>
00285 bool
00286 Powerset<D>::OK(const bool disallow_bottom) const {
00287 for (const_iterator xi = begin(), x_end = end(); xi != x_end; ++xi) {
00288 if (!xi->OK())
00289 return false;
00290 if (disallow_bottom && xi->is_bottom()) {
00291 #ifndef NDEBUG
00292 std::cerr << "Bottom element in powerset!"
00293 << std::endl;
00294 #endif
00295 return false;
00296 }
00297 }
00298 if (reduced && !check_omega_reduced()) {
00299 #ifndef NDEBUG
00300 std::cerr << "Powerset claims to be reduced, but it is not!"
00301 << std::endl;
00302 #endif
00303 return false;
00304 }
00305 return true;
00306 }
00307
00308 }
00309
00310 #endif // !defined(PPL_Powerset_templates_hh)