PPL  0.12.1
Pointset_Ask_Tell.templates.hh
Go to the documentation of this file.
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)