|
PPL
0.12.1
|
00001 /* Pointset_Ask_Tell class implementation: non-inline template functions. 00002 Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it> 00003 Copyright (C) 2010-2012 BUGSENG srl (http://bugseng.com) 00004 00005 This file is part of the Parma Polyhedra Library (PPL). 00006 00007 The PPL is free software; you can redistribute it and/or modify it 00008 under the terms of the GNU General Public License as published by the 00009 Free Software Foundation; either version 3 of the License, or (at your 00010 option) any later version. 00011 00012 The PPL is distributed in the hope that it will be useful, but WITHOUT 00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 00015 for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program; if not, write to the Free Software Foundation, 00019 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA. 00020 00021 For the most up-to-date information see the Parma Polyhedra Library 00022 site: http://bugseng.com/products/ppl/ . */ 00023 00024 #ifndef PPL_Pointset_Ask_Tell_templates_hh 00025 #define PPL_Pointset_Ask_Tell_templates_hh 1 00026 00027 #include "Constraint.defs.hh" 00028 #include "Constraint_System.defs.hh" 00029 #include "Constraint_System.inlines.hh" 00030 #include "C_Polyhedron.defs.hh" 00031 #include "NNC_Polyhedron.defs.hh" 00032 #include "Variables_Set.defs.hh" 00033 #include <algorithm> 00034 #include <deque> 00035 #include <string> 00036 #include <iostream> 00037 #include <sstream> 00038 #include <stdexcept> 00039 00040 namespace Parma_Polyhedra_Library { 00041 00042 template <typename PSET> 00043 void 00044 Pointset_Ask_Tell<PSET>::add_disjunct(const PSET& ph) { 00045 Pointset_Ask_Tell& x = *this; 00046 if (x.space_dimension() != ph.space_dimension()) { 00047 std::ostringstream s; 00048 s << "PPL::Pointset_Ask_Tell<PSET>::add_disjunct(ph):\n" 00049 << "this->space_dimension() == " << x.space_dimension() << ", " 00050 << "ph.space_dimension() == " << ph.space_dimension() << "."; 00051 throw std::invalid_argument(s.str()); 00052 } 00053 x.sequence.push_back(Determinate<PSET>(ph)); 00054 x.reduced = false; 00055 PPL_ASSERT_HEAVY(x.OK()); 00056 } 00057 00058 template <> 00059 template <typename QH> 00060 Pointset_Ask_Tell<NNC_Polyhedron> 00061 ::Pointset_Ask_Tell(const Pointset_Ask_Tell<QH>& y) 00062 : Base(), space_dim(y.space_dimension()) { 00063 Pointset_Ask_Tell& x = *this; 00064 for (typename Pointset_Ask_Tell<QH>::const_iterator i = y.begin(), 00065 y_end = y.end(); i != y_end; ++i) { 00066 Determinate<NNC_Polyhedron> 00067 nnc_ask(NNC_Polyhedron(i->ask().pointset().constraints())); 00068 Determinate<NNC_Polyhedron> 00069 nnc_tell(NNC_Polyhedron(i->tell().pointset().constraints())); 00070 x.sequence.push_back(Pair(nnc_ask, nnc_tell)); 00071 } 00072 // FIXME: the following is a bug! 00073 x.normalized = y.normalized; 00074 PPL_ASSERT_HEAVY(x.OK()); 00075 } 00076 00077 template <> 00078 template <typename QH> 00079 Pointset_Ask_Tell<C_Polyhedron> 00080 ::Pointset_Ask_Tell(const Pointset_Ask_Tell<QH>& y) 00081 : Base(), space_dim(y.space_dimension()) { 00082 Pointset_Ask_Tell& x = *this; 00083 for (typename Pointset_Ask_Tell<QH>::const_iterator i = y.begin(), 00084 y_end = y.end(); i != y_end; ++i) { 00085 Determinate<C_Polyhedron> 00086 c_ask(C_Polyhedron(i->ask().pointset().constraints())); 00087 Determinate<C_Polyhedron> 00088 c_tell(C_Polyhedron(i->tell().pointset().constraints())); 00089 x.sequence.push_back(Pair(c_ask, c_tell)); 00090 } 00091 00092 // Note: in general, normalization of `y' does not propagate to `x', 00093 // because the approximation potentially introduced by the conversion 00094 // may have made uncomparable elements in `y' to become comparable in `x'. 00095 x.normalized = false; 00096 PPL_ASSERT_HEAVY(x.OK()); 00097 } 00098 00099 template <typename PSET> 00100 void 00101 Pointset_Ask_Tell<PSET>::concatenate_assign(const Pointset_Ask_Tell& y) { 00102 Pointset_Ask_Tell& x = *this; 00103 for (const_iterator yi = y.begin(), y_end = y.end(); yi != y_end; ++yi) { 00104 Det_PSET ask(PSET(space_dim, UNIVERSE)); 00105 ask.concatenate_assign(yi->ask()); 00106 Det_PSET tell(PSET(space_dim, UNIVERSE)); 00107 tell.concatenate_assign(yi->tell()); 00108 x.sequence.push_back(Pair(ask, tell)); 00109 } 00110 space_dim += y.space_dim; 00111 if (x.normalized) 00112 x.normalized = y.normalized; 00113 PPL_ASSERT_HEAVY(x.OK()); 00114 } 00115 00116 template <typename PSET> 00117 void 00118 Pointset_Ask_Tell<PSET>::add_constraint(const Constraint& c) { 00119 Pointset_Ask_Tell& x = *this; 00120 for (Sequence_iterator si = x.sequence.begin(), 00121 s_end = x.sequence.end(); si != s_end; ++si) 00122 si->pointset().add_constraint(c); 00123 x.reduced = false; 00124 PPL_ASSERT_HEAVY(x.OK()); 00125 } 00126 00127 template <typename PSET> 00128 void 00129 Pointset_Ask_Tell<PSET>::add_constraints(const Constraint_System& cs) { 00130 Pointset_Ask_Tell& x = *this; 00131 for (Sequence_iterator si = x.sequence.begin(), 00132 s_end = x.sequence.end(); si != s_end; ++si) 00133 si->pointset().add_constraints(cs); 00134 x.reduced = false; 00135 PPL_ASSERT_HEAVY(x.OK()); 00136 } 00137 00138 template <typename PSET> 00139 void 00140 Pointset_Ask_Tell<PSET>::unconstrain(const Variable var) { 00141 Pointset_Ask_Tell& x = *this; 00142 for (Sequence_iterator si = x.sequence.begin(), 00143 s_end = x.sequence.end(); si != s_end; ++si) 00144 si->pointset().unconstrain(var); 00145 x.reduced = false; 00146 PPL_ASSERT_HEAVY(x.OK()); 00147 } 00148 00149 template <typename PSET> 00150 void 00151 Pointset_Ask_Tell<PSET>::unconstrain(const Variables_Set& vars) { 00152 Pointset_Ask_Tell& x = *this; 00153 for (Sequence_iterator si = x.sequence.begin(), 00154 s_end = x.sequence.end(); si != s_end; ++si) 00155 si->pointset().unconstrain(vars); 00156 x.reduced = false; 00157 PPL_ASSERT_HEAVY(x.OK()); 00158 } 00159 00160 template <typename PSET> 00161 void 00162 Pointset_Ask_Tell<PSET>::add_space_dimensions_and_embed(dimension_type m) { 00163 Pointset_Ask_Tell& x = *this; 00164 for (Sequence_iterator si = x.sequence.begin(), 00165 s_end = x.sequence.end(); si != s_end; ++si) 00166 si->pointset().add_space_dimensions_and_embed(m); 00167 x.space_dim += m; 00168 PPL_ASSERT_HEAVY(x.OK()); 00169 } 00170 00171 template <typename PSET> 00172 void 00173 Pointset_Ask_Tell<PSET>::add_space_dimensions_and_project(dimension_type m) { 00174 Pointset_Ask_Tell& x = *this; 00175 for (Sequence_iterator si = x.sequence.begin(), 00176 s_end = x.sequence.end(); si != s_end; ++si) 00177 si->pointset().add_space_dimensions_and_project(m); 00178 x.space_dim += m; 00179 PPL_ASSERT_HEAVY(x.OK()); 00180 } 00181 00182 template <typename PSET> 00183 void 00184 Pointset_Ask_Tell<PSET>:: 00185 remove_space_dimensions(const Variables_Set& vars) { 00186 Pointset_Ask_Tell& x = *this; 00187 Variables_Set::size_type num_removed = vars.size(); 00188 if (num_removed > 0) { 00189 for (Sequence_iterator si = x.sequence.begin(), 00190 s_end = x.sequence.end(); si != s_end; ) { 00191 PSET& ask = si->ask().pointset(); 00192 PSET& tell = si->tell().pointset(); 00193 ask.remove_space_dimensions(vars); 00194 tell.remove_space_dimensions(vars); 00195 if (tell.contains(ask)) { 00196 si = x.sequence.erase(si); 00197 s_end = x.sequence.end(); 00198 } 00199 else { 00200 x.normalized = false; 00201 ++si; 00202 } 00203 } 00204 x.space_dim -= num_removed; 00205 PPL_ASSERT_HEAVY(x.OK()); 00206 } 00207 } 00208 00209 template <typename PSET> 00210 void 00211 Pointset_Ask_Tell<PSET>::remove_higher_space_dimensions(dimension_type 00212 new_dimension) { 00213 Pointset_Ask_Tell& x = *this; 00214 if (new_dimension < x.space_dim) { 00215 for (Sequence_iterator si = x.sequence.begin(), 00216 s_end = x.sequence.end(); si != s_end; ++si) { 00217 si->ask().pointset().remove_higher_space_dimensions(new_dimension); 00218 si->tell().pointset().remove_higher_space_dimensions(new_dimension); 00219 x.reduced = false; 00220 } 00221 x.space_dim = new_dimension; 00222 PPL_ASSERT_HEAVY(x.OK()); 00223 } 00224 } 00225 00226 template <typename PSET> 00227 template <typename Partial_Function> 00228 void 00229 Pointset_Ask_Tell<PSET>::map_space_dimensions(const Partial_Function& pfunc) { 00230 Pointset_Ask_Tell& x = *this; 00231 if (x.is_bottom()) { 00232 dimension_type n = 0; 00233 for (dimension_type i = x.space_dim; i-- > 0; ) { 00234 dimension_type new_i; 00235 if (pfunc.maps(i, new_i)) 00236 ++n; 00237 } 00238 x.space_dim = n; 00239 } 00240 else { 00241 Sequence_iterator s_begin = x.sequence.begin(); 00242 for (Sequence_iterator si = s_begin, 00243 s_end = x.sequence.end(); si != s_end; ++si) 00244 si->pointset().map_space_dimensions(pfunc); 00245 x.space_dim = s_begin->pointset().space_dimension(); 00246 x.reduced = false; 00247 } 00248 PPL_ASSERT_HEAVY(x.OK()); 00249 } 00250 00251 template <typename PSET> 00252 void 00253 Pointset_Ask_Tell<PSET>::ascii_dump(std::ostream& s) const { 00254 const Pointset_Ask_Tell& x = *this; 00255 s << "size " << x.size() 00256 << "\nspace_dim " << x.space_dim 00257 << "\n"; 00258 for (const_iterator xi = x.begin(), x_end = x.end(); xi != x_end; ++xi) 00259 xi->pointset().ascii_dump(s); 00260 } 00261 00262 PPL_OUTPUT_TEMPLATE_DEFINITIONS(PSET, Pointset_Ask_Tell<PSET>) 00263 00264 template <typename PSET> 00265 bool 00266 Pointset_Ask_Tell<PSET>::ascii_load(std::istream& s) { 00267 Pointset_Ask_Tell& x = *this; 00268 std::string str; 00269 00270 if (!(s >> str) || str != "size") 00271 return false; 00272 00273 size_type sz; 00274 00275 if (!(s >> sz)) 00276 return false; 00277 00278 if (!(s >> str) || str != "space_dim") 00279 return false; 00280 00281 if (!(s >> x.space_dim)) 00282 return false; 00283 00284 Pointset_Ask_Tell new_x(x.space_dim, EMPTY); 00285 while (sz-- > 0) { 00286 PSET ph; 00287 if (!ph.ascii_load(s)) 00288 return false; 00289 new_x.add_disjunct(ph); 00290 } 00291 swap(x, new_x); 00292 00293 // Check invariants. 00294 PPL_ASSERT_HEAVY(x.OK()); 00295 return true; 00296 } 00297 00298 template <typename PSET> 00299 bool 00300 Pointset_Ask_Tell<PSET>::OK() const { 00301 const Pointset_Ask_Tell& x = *this; 00302 for (const_iterator xi = x.begin(), x_end = x.end(); xi != x_end; ++xi) { 00303 const PSET& ask_i = xi->ask().pointset(); 00304 const PSET& tell_i = xi->tell().pointset(); 00305 if (ask_i.space_dimension() != x.space_dim 00306 || tell_i.space_dimension() != x.space_dim) { 00307 #ifndef NDEBUG 00308 std::cerr << "Space dimension mismatch: is (" 00309 << ask_i.space_dimension() 00310 << " -> " 00311 << tell_i.space_dimension() 00312 << ") in an element of the sequence,\nshould be " 00313 << x.space_dim << "." 00314 << std::endl; 00315 #endif 00316 return false; 00317 } 00318 } 00319 return x.Base::OK(); 00320 } 00321 00322 } // namespace Parma_Polyhedra_Library 00323 00324 #endif // !defined(PPL_Pointset_Ask_Tell_templates_hh)