Parma_Polyhedra_Library::Generator_System Class Reference
[C++ Language Interface]

A system of generators. More...

#include <Generator_System.defs.hh>

Inheritance diagram for Parma_Polyhedra_Library::Generator_System:
Inheritance graph
[legend]
Collaboration diagram for Parma_Polyhedra_Library::Generator_System:
Collaboration graph
[legend]

List of all members.

Classes

class  const_iterator
 An iterator over a system of generators. More...

Public Member Functions

 Generator_System ()
 Default constructor: builds an empty system of generators.
 Generator_System (const Generator &g)
 Builds the singleton system containing only generator g.
 Generator_System (const Generator_System &gs)
 Ordinary copy constructor.
 ~Generator_System ()
 Destructor.
Generator_Systemoperator= (const Generator_System &y)
 Assignment operator.
dimension_type space_dimension () const
 Returns the dimension of the vector space enclosing *this.
void clear ()
 Removes all the generators from the generator system and sets its space dimension to 0.
void insert (const Generator &g)
 Inserts in *this a copy of the generator g, increasing the number of space dimensions if needed.
bool empty () const
 Returns true if and only if *this has no generators.
const_iterator begin () const
 Returns the const_iterator pointing to the first generator, if *this is not empty; otherwise, returns the past-the-end const_iterator.
const_iterator end () const
 Returns the past-the-end const_iterator.
bool OK () const
 Checks if all the invariants are satisfied.
void ascii_dump () const
 Writes to std::cerr an ASCII representation of *this.
void ascii_dump (std::ostream &s) const
 Writes to s an ASCII representation of *this.
void print () const
 Prints *this to std::cerr using operator<<.
bool ascii_load (std::istream &s)
 Loads from s an ASCII representation (as produced by ascii_dump(std::ostream&) const) and sets *this accordingly. Returns true if successful, false otherwise.
memory_size_type total_memory_in_bytes () const
 Returns the total size in bytes of the memory occupied by *this.
memory_size_type external_memory_in_bytes () const
 Returns the size in bytes of the memory managed by *this.
void swap (Generator_System &y)
 Swaps *this with y.

Static Public Member Functions

static dimension_type max_space_dimension ()
 Returns the maximum space dimension a Generator_System can handle.
static void initialize ()
 Initializes the class.
static void finalize ()
 Finalizes the class.
static const Generator_Systemzero_dim_univ ()
 Returns the singleton system containing only Generator::zero_dim_point().

Private Member Functions

 Generator_System (Topology topol)
 Builds an empty system of generators having the specified topology.
 Generator_System (Topology topol, dimension_type n_rows, dimension_type n_columns)
 Builds a system of n_rows rays/points on a n_columns - 1 dimensional space (including the $\epsilon$ dimension, if topol is NOT_NECESSARILY_CLOSED).
bool adjust_topology_and_space_dimension (Topology topol, dimension_type num_dimensions)
 Adjusts *this so that it matches the topology and the number of space dimensions given as parameters (adding or removing columns if needed). Returns false if and only if topol is equal to NECESSARILY_CLOSED and *this contains closure points.
void add_corresponding_points ()
 For each unmatched closure point in *this, adds the corresponding point.
bool has_points () const
 Returns true if and only if *this contains one or more points.
void add_corresponding_closure_points ()
 For each unmatched point in *this, adds the corresponding closure point.
bool has_closure_points () const
 Returns true if and only if *this contains one or more closure points.
Generatoroperator[] (dimension_type k)
 Returns the k- th generator of the system.
const Generatoroperator[] (dimension_type k) const
 Returns a constant reference to the k- th generator of the system.
Parma_Polyhedra_Library::Poly_Con_Relation relation_with (const Constraint &c) const
 Returns the relations holding between the generator system and the constraint c.
bool satisfied_by_all_generators (const Constraint &c) const
 Returns true if all the generators satisfy c.
bool satisfied_by_all_generators_C (const Constraint &c) const
 Returns true if all the generators satisfy c.
bool satisfied_by_all_generators_NNC (const Constraint &c) const
 Returns true if all the generators satisfy c.
void affine_image (dimension_type v, const Linear_Expression &expr, Coefficient_traits::const_reference denominator)
 Assigns to a given variable an affine expression.
dimension_type num_lines () const
 Returns the number of lines of the system.
dimension_type num_rays () const
 Returns the number of rays of the system.
void remove_invalid_lines_and_rays ()
 Removes all the invalid lines and rays.
void simplify ()
 Applies Gaussian elimination and back-substitution so as to provide a partial simplification of the system of generators.
void insert_pending (const Generator &g)
 Inserts in *this a copy of the generator g, increasing the number of space dimensions if needed. It is a pending generator.

Static Private Attributes

static const Generator_Systemzero_dim_univ_p = 0
 Holds (between class initialization and finalization) a pointer to the singleton system containing only Generator::zero_dim_point().

Friends

class const_iterator
class Parma_Polyhedra_Library::Polyhedron
class Parma_Polyhedra_Library::Grid_Generator_System
bool operator== (const Polyhedron &x, const Polyhedron &y)

Related Functions

(Note that these are not member functions.)



std::ostream & operator<< (std::ostream &s, const Generator_System &gs)
 Output operator.
void swap (Parma_Polyhedra_Library::Generator_System &x, Parma_Polyhedra_Library::Generator_System &y)
 Specializes std::swap.

Detailed Description

A system of generators.

An object of the class Generator_System is a system of generators, i.e., a multiset of objects of the class Generator (lines, rays, points and closure points). When inserting generators in a system, space dimensions are automatically adjusted so that all the generators in the system are defined on the same vector space. A system of generators which is meant to define a non-empty polyhedron must include at least one point: the reason is that lines, rays and closure points need a supporting point (lines and rays only specify directions while closure points only specify points in the topological closure of the NNC polyhedron).

In all the examples it is assumed that variables x and y are defined as follows:
  Variable x(0);
  Variable y(1);
Example 1
The following code defines the line having the same direction as the $x$ axis (i.e., the first Cartesian axis) in $\Rset^2$:
  Generator_System gs;
  gs.insert(line(x + 0*y));
As said above, this system of generators corresponds to an empty polyhedron, because the line has no supporting point. To define a system of generators that does correspond to the $x$ axis, we can add the following code which inserts the origin of the space as a point:
  gs.insert(point(0*x + 0*y));
Since space dimensions are automatically adjusted, the following code obtains the same effect:
  gs.insert(point(0*x));
In contrast, if we had added the following code, we would have defined a line parallel to the $x$ axis through the point $(0, 1)^\transpose \in \Rset^2$.
  gs.insert(point(0*x + 1*y));
Example 2
The following code builds a ray having the same direction as the positive part of the $x$ axis in $\Rset^2$:
  Generator_System gs;
  gs.insert(ray(x + 0*y));
To define a system of generators indeed corresponding to the set

\[ \bigl\{\, (x, 0)^\transpose \in \Rset^2 \bigm| x \geq 0 \,\bigr\}, \]

one just has to add the origin:
  gs.insert(point(0*x + 0*y));
Example 3
The following code builds a system of generators having four points and corresponding to a square in $\Rset^2$ (the same as Example 1 for the system of constraints):
  Generator_System gs;
  gs.insert(point(0*x + 0*y));
  gs.insert(point(0*x + 3*y));
  gs.insert(point(3*x + 0*y));
  gs.insert(point(3*x + 3*y));
Example 4
By using closure points, we can define the kernel (i.e., the largest open set included in a given set) of the square defined in the previous example. Note that a supporting point is needed and, for that purpose, any inner point could be considered.
  Generator_System gs;
  gs.insert(point(x + y));
  gs.insert(closure_point(0*x + 0*y));
  gs.insert(closure_point(0*x + 3*y));
  gs.insert(closure_point(3*x + 0*y));
  gs.insert(closure_point(3*x + 3*y));
Example 5
The following code builds a system of generators having two points and a ray, corresponding to a half-strip in $\Rset^2$ (the same as Example 2 for the system of constraints):
  Generator_System gs;
  gs.insert(point(0*x + 0*y));
  gs.insert(point(0*x + 1*y));
  gs.insert(ray(x - y));
Note:
After inserting a multiset of generators in a generator system, there are no guarantees that an exact copy of them can be retrieved: in general, only an equivalent generator system will be available, where original generators may have been reordered, removed (if they are duplicate or redundant), etc.

Definition at line 183 of file Generator_System.defs.hh.


Constructor & Destructor Documentation

Parma_Polyhedra_Library::Generator_System::Generator_System (  )  [inline]

Default constructor: builds an empty system of generators.

Definition at line 32 of file Generator_System.inlines.hh.

Referenced by initialize().

00033   : Linear_System(NECESSARILY_CLOSED) {
00034 }

Parma_Polyhedra_Library::Generator_System::Generator_System ( const Generator g  )  [inline, explicit]

Builds the singleton system containing only generator g.

Definition at line 37 of file Generator_System.inlines.hh.

References insert().

00038   : Linear_System(g.topology()) {
00039   Linear_System::insert(g);
00040 }

Parma_Polyhedra_Library::Generator_System::Generator_System ( const Generator_System gs  )  [inline]

Ordinary copy constructor.

Definition at line 43 of file Generator_System.inlines.hh.

00044   : Linear_System(gs) {
00045 }

Parma_Polyhedra_Library::Generator_System::~Generator_System (  )  [inline]

Destructor.

Definition at line 60 of file Generator_System.inlines.hh.

00060                                     {
00061 }

Parma_Polyhedra_Library::Generator_System::Generator_System ( Topology  topol  )  [inline, explicit, private]

Builds an empty system of generators having the specified topology.

Definition at line 48 of file Generator_System.inlines.hh.

00049   : Linear_System(topol) {
00050 }

Parma_Polyhedra_Library::Generator_System::Generator_System ( Topology  topol,
dimension_type  n_rows,
dimension_type  n_columns 
) [inline, private]

Builds a system of n_rows rays/points on a n_columns - 1 dimensional space (including the $\epsilon$ dimension, if topol is NOT_NECESSARILY_CLOSED).

Definition at line 53 of file Generator_System.inlines.hh.

00056   : Linear_System(topol, n_rows, n_columns) {
00057 }


Member Function Documentation

void Parma_Polyhedra_Library::Generator_System::add_corresponding_closure_points (  )  [private]

For each unmatched point in *this, adds the corresponding closure point.

It is assumed that the topology of *this is NOT_NECESSARILY_CLOSED.

Definition at line 187 of file Generator_System.cc.

References Parma_Polyhedra_Library::Linear_System::add_pending_row(), Parma_Polyhedra_Library::Linear_System::is_necessarily_closed(), Parma_Polyhedra_Library::Row::normalize(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), and OK().

Referenced by Parma_Polyhedra_Library::Polyhedron::add_recycled_generators(), and Parma_Polyhedra_Library::Polyhedron::Polyhedron().

00187                                                       {
00188   PPL_ASSERT(!is_necessarily_closed());
00189   // NOTE: we always add (pending) rows at the end of the generator system.
00190   // Updating `index_first_pending', if needed, is done by the caller.
00191   Generator_System& gs = *this;
00192   const dimension_type n_rows = gs.num_rows();
00193   const dimension_type eps_index = gs.num_columns() - 1;
00194   for (dimension_type i = n_rows; i-- > 0; ) {
00195     const Generator& g = gs[i];
00196     if (g[eps_index] > 0) {
00197       // `g' is a point: adding the closure point.
00198       Generator cp = g;
00199       cp[eps_index] = 0;
00200       // Enforcing normalization.
00201       cp.normalize();
00202       gs.add_pending_row(cp);
00203     }
00204   }
00205   PPL_ASSERT(OK());
00206 }

void Parma_Polyhedra_Library::Generator_System::add_corresponding_points (  )  [private]

For each unmatched closure point in *this, adds the corresponding point.

It is assumed that the topology of *this is NOT_NECESSARILY_CLOSED.

Definition at line 214 of file Generator_System.cc.

References Parma_Polyhedra_Library::Linear_System::add_pending_row(), Parma_Polyhedra_Library::Generator::is_line_or_ray(), Parma_Polyhedra_Library::Linear_System::is_necessarily_closed(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), and OK().

Referenced by Parma_Polyhedra_Library::Polyhedron::topological_closure_assign().

00214                                               {
00215   PPL_ASSERT(!is_necessarily_closed());
00216   // NOTE: we always add (pending) rows at the end of the generator system.
00217   // Updating `index_first_pending', if needed, is done by the caller.
00218   Generator_System& gs = *this;
00219   const dimension_type n_rows = gs.num_rows();
00220   const dimension_type eps_index = gs.num_columns() - 1;
00221   for (dimension_type i = 0; i < n_rows; i++) {
00222     const Generator& g = gs[i];
00223     if (!g.is_line_or_ray() && g[eps_index] == 0) {
00224       // `g' is a closure point: adding the point.
00225       // Note: normalization is preserved.
00226       Generator p = g;
00227       p[eps_index] = p[0];
00228       gs.add_pending_row(p);
00229     }
00230   }
00231   PPL_ASSERT(OK());
00232 }

bool Parma_Polyhedra_Library::Generator_System::adjust_topology_and_space_dimension ( Topology  topol,
dimension_type  num_dimensions 
) [private]

Adjusts *this so that it matches the topology and the number of space dimensions given as parameters (adding or removing columns if needed). Returns false if and only if topol is equal to NECESSARILY_CLOSED and *this contains closure points.

Definition at line 40 of file Generator_System.cc.

References Parma_Polyhedra_Library::Matrix::add_zero_columns(), Parma_Polyhedra_Library::Matrix::erase_to_end(), has_closure_points(), Parma_Polyhedra_Library::Matrix::has_no_rows(), Parma_Polyhedra_Library::NECESSARILY_CLOSED, Parma_Polyhedra_Library::Linear_System::normalize(), Parma_Polyhedra_Library::NOT_NECESSARILY_CLOSED, Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), Parma_Polyhedra_Library::Linear_System::remove_trailing_columns(), Parma_Polyhedra_Library::Linear_System::set_necessarily_closed(), Parma_Polyhedra_Library::Linear_System::set_not_necessarily_closed(), space_dimension(), swap(), Parma_Polyhedra_Library::Matrix::swap_columns(), and Parma_Polyhedra_Library::Linear_System::topology().

Referenced by Parma_Polyhedra_Library::Polyhedron::add_generator(), Parma_Polyhedra_Library::Polyhedron::add_recycled_generators(), Parma_Polyhedra_Library::Polyhedron::add_space_dimensions_and_project(), Parma_Polyhedra_Library::Polyhedron::generators(), Parma_Polyhedra_Library::Grid_Generator_System::Grid_Generator_System(), and Parma_Polyhedra_Library::Polyhedron::Polyhedron().

00041                                                                         {
00042   PPL_ASSERT(space_dimension() <= new_space_dim);
00043 
00044   const dimension_type old_space_dim = space_dimension();
00045   const Topology old_topology = topology();
00046   dimension_type cols_to_be_added = new_space_dim - old_space_dim;
00047 
00048   // Dealing with empty generator systems first.
00049   if (has_no_rows()) {
00050     if (num_columns() == 0)
00051       if (new_topology == NECESSARILY_CLOSED) {
00052         add_zero_columns(cols_to_be_added + 1);
00053         set_necessarily_closed();
00054       }
00055       else {
00056         add_zero_columns(cols_to_be_added + 2);
00057         set_not_necessarily_closed();
00058       }
00059     else
00060       // Here `num_columns() > 0'.
00061       if (old_topology != new_topology)
00062         if (new_topology == NECESSARILY_CLOSED) {
00063           switch (cols_to_be_added) {
00064           case 0:
00065             remove_trailing_columns(1);
00066             break;
00067           case 1:
00068             // Nothing to do.
00069             break;
00070           default:
00071             add_zero_columns(cols_to_be_added - 1);
00072           }
00073           set_necessarily_closed();
00074         }
00075         else {
00076           // Here old_topology == NECESSARILY_CLOSED
00077           //  and new_topology == NOT_NECESSARILY_CLOSED.
00078           add_zero_columns(cols_to_be_added + 1);
00079           set_not_necessarily_closed();
00080         }
00081       else
00082         // Here topologies agree.
00083         if (cols_to_be_added > 0)
00084           add_zero_columns(cols_to_be_added);
00085     PPL_ASSERT(OK());
00086     return true;
00087   }
00088 
00089   // Here the generator systen is not empty.
00090   if (cols_to_be_added > 0)
00091     if (old_topology != new_topology)
00092       if (new_topology == NECESSARILY_CLOSED) {
00093         // A NOT_NECESSARILY_CLOSED generator system
00094         // can be converted to a NECESSARILY_CLOSED one
00095         // only if it does not contain closure points.
00096         // This check has to be performed under the user viewpoint.
00097         if (has_closure_points())
00098           return false;
00099         // For a correct implementation, we have to remove those
00100         // closure points that were matching a point (i.e., those
00101         // that are in the generator system, but are invisible to
00102         // the user).
00103         Generator_System& gs = *this;
00104         dimension_type num_closure_points = 0;
00105         dimension_type gs_end = gs.num_rows();
00106         for (dimension_type i = 0; i < gs_end; ) {
00107           // All the closure points seen so far have consecutive
00108           // indices starting from `i'.
00109           if (num_closure_points > 0)
00110             // Let next generator have index `i'.
00111             std::swap(gs[i], gs[i+num_closure_points]);
00112           if (gs[i].is_closure_point()) {
00113             ++num_closure_points;
00114             --gs_end;
00115           }
00116           else
00117             ++i;
00118         }
00119         // We may have identified some closure points.
00120         if (num_closure_points > 0) {
00121           PPL_ASSERT(num_closure_points == num_rows() - gs_end);
00122           erase_to_end(gs_end);
00123         }
00124         // Remove the epsilon column, re-normalize and, after that,
00125         // add the missing dimensions. This ensures that
00126         // non-zero epsilon coefficients will be cleared.
00127         remove_trailing_columns(1);
00128         set_necessarily_closed();
00129         normalize();
00130         add_zero_columns(cols_to_be_added);
00131       }
00132       else {
00133         // A NECESSARILY_CLOSED generator system is converted to
00134         // a NOT_NECESSARILY_CLOSED one by adding a further column
00135         // and setting the epsilon coordinate of all points to 1.
00136         // Note: normalization is preserved.
00137         add_zero_columns(cols_to_be_added + 1);
00138         Generator_System& gs = *this;
00139         const dimension_type eps_index = new_space_dim + 1;
00140         for (dimension_type i = num_rows(); i-- > 0; )
00141           gs[i][eps_index] = gs[i][0];
00142         set_not_necessarily_closed();
00143       }
00144     else {
00145       // Topologies agree: first add the required zero columns ...
00146       add_zero_columns(cols_to_be_added);
00147       // ... and, if needed, move the epsilon coefficients
00148       // to the new last column.
00149       if (old_topology == NOT_NECESSARILY_CLOSED)
00150         swap_columns(old_space_dim + 1, new_space_dim + 1);
00151     }
00152   else
00153     // Here `cols_to_be_added == 0'.
00154     if (old_topology != new_topology) {
00155       if (new_topology == NECESSARILY_CLOSED) {
00156         // A NOT_NECESSARILY_CLOSED generator system
00157         // can be converted in to a NECESSARILY_CLOSED one
00158         // only if it does not contain closure points.
00159         if (has_closure_points())
00160           return false;
00161         // We just remove the column of the epsilon coefficients.
00162         remove_trailing_columns(1);
00163         set_necessarily_closed();
00164       }
00165       else {
00166         // Add the column of the epsilon coefficients
00167         // and set the epsilon coordinate of all points to 1.
00168         // Note: normalization is preserved.
00169         add_zero_columns(1);
00170         Generator_System& gs = *this;
00171         const dimension_type eps_index = new_space_dim + 1;
00172         for (dimension_type i = num_rows(); i-- > 0; )
00173           gs[i][eps_index] = gs[i][0];
00174         set_not_necessarily_closed();
00175       }
00176     }
00177   // We successfully adjusted dimensions and topology.
00178   PPL_ASSERT(OK());
00179   return true;
00180 }

void Parma_Polyhedra_Library::Generator_System::affine_image ( dimension_type  v,
const Linear_Expression expr,
Coefficient_traits::const_reference  denominator 
) [private]

Assigns to a given variable an affine expression.

Parameters:
v Index of the column to which the affine transformation is assigned;
expr The numerator of the affine transformation: $\sum_{i = 0}^{n - 1} a_i x_i + b$;
denominator The denominator of the affine transformation.

We want to allow affine transformations (see the Introduction) having any rational coefficients. Since the coefficients of the constraints are integers we must also provide an integer denominator that will be used as denominator of the affine transformation. The denominator is required to be a positive integer.

The affine transformation assigns to each element of v -th column the follow expression:

\[ \frac{\sum_{i = 0}^{n - 1} a_i x_i + b} {\mathrm{denominator}}. \]

expr is a constant parameter and unaltered by this computation.

Reimplemented in Parma_Polyhedra_Library::Grid_Generator_System.

Definition at line 788 of file Generator_System.cc.

References Parma_Polyhedra_Library::Scalar_Products::assign(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), PPL_DIRTY_TEMP_COEFFICIENT, remove_invalid_lines_and_rays(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), space_dimension(), Parma_Polyhedra_Library::Linear_System::strong_normalize(), and swap().

Referenced by Parma_Polyhedra_Library::Polyhedron::affine_image(), and Parma_Polyhedra_Library::Polyhedron::affine_preimage().

00790                                                               {
00791   Generator_System& x = *this;
00792   // `v' is the index of a column corresponding to
00793   // a "user" variable (i.e., it cannot be the inhomogeneous term,
00794   // nor the epsilon dimension of NNC polyhedra).
00795   PPL_ASSERT(v > 0 && v <= x.space_dimension());
00796   PPL_ASSERT(expr.space_dimension() <= x.space_dimension());
00797   PPL_ASSERT(denominator > 0);
00798 
00799   const dimension_type n_columns = x.num_columns();
00800   const dimension_type n_rows = x.num_rows();
00801 
00802   // Compute the numerator of the affine transformation and assign it
00803   // to the column of `*this' indexed by `v'.
00804   PPL_DIRTY_TEMP_COEFFICIENT(numerator);
00805   for (dimension_type i = n_rows; i-- > 0; ) {
00806     Generator& row = x[i];
00807     Scalar_Products::assign(numerator, expr, row);
00808     std::swap(numerator, row[v]);
00809   }
00810 
00811   if (denominator != 1) {
00812     // Since we want integer elements in the matrix,
00813     // we multiply by `denominator' all the columns of `*this'
00814     // having an index different from `v'.
00815     for (dimension_type i = n_rows; i-- > 0; ) {
00816       Generator& row = x[i];
00817       for (dimension_type j = n_columns; j-- > 0; )
00818         if (j != v)
00819           row[j] *= denominator;
00820     }
00821   }
00822 
00823   // If the mapping is not invertible we may have transformed
00824   // valid lines and rays into the origin of the space.
00825   const bool not_invertible = (v > expr.space_dimension() || expr[v] == 0);
00826   if (not_invertible)
00827     x.remove_invalid_lines_and_rays();
00828 
00829   // Strong normalization also resets the sortedness flag.
00830   x.strong_normalize();
00831 }

void Parma_Polyhedra_Library::Generator_System::ascii_dump ( std::ostream &  s  )  const

Writes to s an ASCII representation of *this.

Reimplemented from Parma_Polyhedra_Library::Linear_System.

Reimplemented in Parma_Polyhedra_Library::Grid_Generator_System.

Definition at line 834 of file Generator_System.cc.

References Parma_Polyhedra_Library::Generator::CLOSURE_POINT, Parma_Polyhedra_Library::Linear_System::first_pending_row(), Parma_Polyhedra_Library::Linear_System::is_necessarily_closed(), Parma_Polyhedra_Library::Linear_System::is_sorted(), Parma_Polyhedra_Library::Generator::LINE, Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Generator::POINT, Parma_Polyhedra_Library::Generator::RAY, and Parma_Polyhedra_Library::Generator::type().

00834                                                    {
00835   const Generator_System& x = *this;
00836   const dimension_type x_num_rows = x.num_rows();
00837   const dimension_type x_num_columns = x.num_columns();
00838   s << "topology " << (is_necessarily_closed()
00839                        ? "NECESSARILY_CLOSED"
00840                        : "NOT_NECESSARILY_CLOSED")
00841     << "\n"
00842     << x_num_rows << " x " << x_num_columns << ' '
00843     << (x.is_sorted() ? "(sorted)" : "(not_sorted)")
00844     << "\n"
00845     << "index_first_pending " << x.first_pending_row()
00846     << "\n";
00847   for (dimension_type i = 0; i < x_num_rows; ++i) {
00848     const Generator& g = x[i];
00849     for (dimension_type j = 0; j < x_num_columns; ++j)
00850       s << g[j] << ' ';
00851     switch (g.type()) {
00852     case Generator::LINE:
00853       s << "L";
00854       break;
00855     case Generator::RAY:
00856       s << "R";
00857       break;
00858     case Generator::POINT:
00859       s << "P";
00860       break;
00861     case Generator::CLOSURE_POINT:
00862       s << "C";
00863       break;
00864     }
00865     s << "\n";
00866   }
00867 }

void Parma_Polyhedra_Library::Generator_System::ascii_dump (  )  const

Writes to std::cerr an ASCII representation of *this.

Reimplemented from Parma_Polyhedra_Library::Linear_System.

Reimplemented in Parma_Polyhedra_Library::Grid_Generator_System.

Referenced by Parma_Polyhedra_Library::Polyhedron::ascii_dump(), and Parma_Polyhedra_Library::Polyhedron::OK().

bool Parma_Polyhedra_Library::Generator_System::ascii_load ( std::istream &  s  ) 

Loads from s an ASCII representation (as produced by ascii_dump(std::ostream&) const) and sets *this accordingly. Returns true if successful, false otherwise.

Resizes the matrix of generators using the numbers of rows and columns read from s, then initializes the coordinates of each generator and its type reading the contents from s.

Reimplemented from Parma_Polyhedra_Library::Linear_System.

Reimplemented in Parma_Polyhedra_Library::Grid_Generator_System.

Definition at line 872 of file Generator_System.cc.

References Parma_Polyhedra_Library::Generator::CLOSURE_POINT, Parma_Polyhedra_Library::Generator::LINE, Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Generator::POINT, and Parma_Polyhedra_Library::Generator::RAY.

00872                                              {
00873   std::string str;
00874   if (!(s >> str) || str != "topology")
00875     return false;
00876   if (!(s >> str))
00877     return false;
00878   if (str == "NECESSARILY_CLOSED")
00879     set_necessarily_closed();
00880   else {
00881     if (str != "NOT_NECESSARILY_CLOSED")
00882       return false;
00883     set_not_necessarily_closed();
00884   }
00885 
00886   dimension_type nrows;
00887   dimension_type ncols;
00888   if (!(s >> nrows))
00889     return false;
00890   if (!(s >> str) || str != "x")
00891     return false;
00892   if (!(s >> ncols))
00893       return false;
00894   resize_no_copy(nrows, ncols);
00895 
00896   if (!(s >> str) || (str != "(sorted)" && str != "(not_sorted)"))
00897     return false;
00898   set_sorted(str == "(sorted)");
00899   dimension_type index;
00900   if (!(s >> str) || str != "index_first_pending")
00901     return false;
00902   if (!(s >> index))
00903     return false;
00904   set_index_first_pending_row(index);
00905 
00906   Generator_System& x = *this;
00907   for (dimension_type i = 0; i < x.num_rows(); ++i) {
00908     for (dimension_type j = 0; j < x.num_columns(); ++j)
00909       if (!(s >> x[i][j]))
00910         return false;
00911 
00912     if (!(s >> str))
00913       return false;
00914     if (str == "L")
00915       x[i].set_is_line();
00916     else if (str == "R" || str == "P" || str == "C")
00917       x[i].set_is_ray_or_point();
00918     else
00919       return false;
00920 
00921     // Checking for equality of actual and declared types.
00922     switch (x[i].type()) {
00923     case Generator::LINE:
00924       if (str == "L")
00925         continue;
00926       break;
00927     case Generator::RAY:
00928       if (str == "R")
00929         continue;
00930       break;
00931     case Generator::POINT:
00932       if (str == "P")
00933         continue;
00934       break;
00935     case Generator::CLOSURE_POINT:
00936       if (str == "C")
00937         continue;
00938       break;
00939     }
00940     // Reaching this point means that the input was illegal.
00941     return false;
00942   }
00943 
00944   // Check invariants.
00945   PPL_ASSERT(OK());
00946   return true;
00947 }

Generator_System::const_iterator Parma_Polyhedra_Library::Generator_System::begin (  )  const [inline]
void Parma_Polyhedra_Library::Generator_System::clear (  )  [inline]

Removes all the generators from the generator system and sets its space dimension to 0.

Reimplemented from Parma_Polyhedra_Library::Linear_System.

Reimplemented in Parma_Polyhedra_Library::Grid_Generator_System.

Definition at line 80 of file Generator_System.inlines.hh.

Referenced by Parma_Polyhedra_Library::Polyhedron::set_empty(), and Parma_Polyhedra_Library::Polyhedron::set_zero_dim_univ().

00080                         {
00081   Linear_System::clear();
00082 }

bool Parma_Polyhedra_Library::Generator_System::empty (  )  const [inline]

Returns true if and only if *this has no generators.

Reimplemented in Parma_Polyhedra_Library::Grid_Generator_System.

Definition at line 159 of file Generator_System.inlines.hh.

References Parma_Polyhedra_Library::Matrix::has_no_rows().

00159                               {
00160   return Linear_System::has_no_rows();
00161 }

Generator_System::const_iterator Parma_Polyhedra_Library::Generator_System::end (  )  const [inline]
memory_size_type Parma_Polyhedra_Library::Generator_System::external_memory_in_bytes (  )  const [inline]

Returns the size in bytes of the memory managed by *this.

Reimplemented from Parma_Polyhedra_Library::Linear_System.

Reimplemented in Parma_Polyhedra_Library::Grid_Generator_System.

Definition at line 189 of file Generator_System.inlines.hh.

Referenced by Parma_Polyhedra_Library::Polyhedron::external_memory_in_bytes().

00189                                                  {
00190   return Linear_System::external_memory_in_bytes();
00191 }

void Parma_Polyhedra_Library::Generator_System::finalize (  )  [static]

Finalizes the class.

Reimplemented in Parma_Polyhedra_Library::Grid_Generator_System.

Definition at line 1017 of file Generator_System.cc.

References zero_dim_univ_p.

01017                               {
01018   PPL_ASSERT(zero_dim_univ_p != 0);
01019   delete zero_dim_univ_p;
01020   zero_dim_univ_p = 0;
01021 }

bool Parma_Polyhedra_Library::Generator_System::has_closure_points (  )  const [private]

Returns true if and only if *this contains one or more closure points.

Note: the check for the presence of closure points is done under the point of view of the user. Namely, we scan the generator system using high-level iterators, so that closure points that are matching the corresponding points will be disregarded.

Definition at line 235 of file Generator_System.cc.

References begin(), end(), and Parma_Polyhedra_Library::Linear_System::is_necessarily_closed().

Referenced by Parma_Polyhedra_Library::Polyhedron::add_recycled_generators(), and adjust_topology_and_space_dimension().

00235                                               {
00236   if (is_necessarily_closed())
00237     return false;
00238   // Adopt the point of view of the user.
00239   for (Generator_System::const_iterator i = begin(),
00240          this_end = end(); i != this_end; ++i)
00241     if (i->is_closure_point())
00242       return true;
00243   return false;
00244 }

bool Parma_Polyhedra_Library::Generator_System::has_points (  )  const [private]

Returns true if and only if *this contains one or more points.

Reimplemented in Parma_Polyhedra_Library::Grid_Generator_System.

Definition at line 247 of file Generator_System.cc.

References Parma_Polyhedra_Library::Linear_System::is_necessarily_closed(), Parma_Polyhedra_Library::Matrix::num_columns(), and Parma_Polyhedra_Library::Matrix::num_rows().

Referenced by Parma_Polyhedra_Library::Polyhedron::add_recycled_generators(), Parma_Polyhedra_Library::Polyhedron::OK(), and Parma_Polyhedra_Library::Polyhedron::Polyhedron().

00247                                       {
00248   const Generator_System& gs = *this;
00249   // Avoiding the repeated tests on topology.
00250   if (is_necessarily_closed())
00251     for (dimension_type i = num_rows(); i-- > 0; ) {
00252       if (!gs[i].is_line_or_ray())
00253         return true;
00254     }
00255   else {
00256     // !is_necessarily_closed()
00257     const dimension_type eps_index = gs.num_columns() - 1;
00258     for (dimension_type i = num_rows(); i-- > 0; )
00259     if (gs[i][eps_index] != 0)
00260       return true;
00261   }
00262   return false;
00263 }

void Parma_Polyhedra_Library::Generator_System::initialize (  )  [static]

Initializes the class.

Reimplemented in Parma_Polyhedra_Library::Grid_Generator_System.

Definition at line 1010 of file Generator_System.cc.

References Generator_System(), Parma_Polyhedra_Library::Generator::zero_dim_point(), and zero_dim_univ_p.

01010                                 {
01011   PPL_ASSERT(zero_dim_univ_p == 0);
01012   zero_dim_univ_p
01013     = new Generator_System(Generator::zero_dim_point());
01014 }

void Parma_Polyhedra_Library::Generator_System::insert ( const Generator g  ) 

Inserts in *this a copy of the generator g, increasing the number of space dimensions if needed.

Definition at line 283 of file Generator_System.cc.

References Parma_Polyhedra_Library::Matrix::add_zero_columns(), Parma_Polyhedra_Library::Linear_System::insert(), Parma_Polyhedra_Library::Generator::is_line_or_ray(), Parma_Polyhedra_Library::Linear_System::is_necessarily_closed(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Linear_System::num_pending_rows(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), Parma_Polyhedra_Library::Linear_System::set_not_necessarily_closed(), space_dimension(), Parma_Polyhedra_Library::Generator::space_dimension(), Parma_Polyhedra_Library::Linear_Row::topology(), and Parma_Polyhedra_Library::Linear_System::topology().

Referenced by Parma_Polyhedra_Library::Polyhedron::add_generator(), Parma_Polyhedra_Library::Polyhedron::add_space_dimensions_and_project(), Parma_Polyhedra_Library::Polyhedron::BHRZ03_evolving_rays(), Parma_Polyhedra_Library::Polyhedron::generalized_affine_image(), Parma_Polyhedra_Library::Polyhedron::generalized_affine_preimage(), Generator_System(), Parma_Polyhedra_Library::Polyhedron::map_space_dimensions(), and Parma_Polyhedra_Library::Polyhedron::unconstrain().

00283                                               {
00284   // We are sure that the matrix has no pending rows
00285   // and that the new row is not a pending generator.
00286   PPL_ASSERT(num_pending_rows() == 0);
00287   if (topology() == g.topology())
00288     Linear_System::insert(g);
00289   else
00290     // `*this' and `g' have different topologies.
00291     if (is_necessarily_closed()) {
00292       // Padding the matrix with the column
00293       // corresponding to the epsilon coefficients:
00294       // all points must have epsilon coordinate equal to 1
00295       // (i.e., the epsilon coefficient is equal to the divisor);
00296       // rays and lines must have epsilon coefficient equal to 0.
00297       // Note: normalization is preserved.
00298       const dimension_type eps_index = num_columns();
00299       add_zero_columns(1);
00300       Generator_System& gs = *this;
00301       for (dimension_type i = num_rows(); i-- > 0; ) {
00302         Generator& gen = gs[i];
00303         if (!gen.is_line_or_ray())
00304           gen[eps_index] = gen[0];
00305       }
00306       set_not_necessarily_closed();
00307       // Inserting the new generator.
00308       Linear_System::insert(g);
00309     }
00310     else {
00311       // The generator system is NOT necessarily closed:
00312       // copy the generator, adding the missing dimensions
00313       // and the epsilon coefficient.
00314       const dimension_type new_size = 2 + std::max(g.space_dimension(),
00315                                                    space_dimension());
00316       Generator tmp_g(g, new_size);
00317       // If it was a point, set the epsilon coordinate to 1
00318       // (i.e., set the coefficient equal to the divisor).
00319       // Note: normalization is preserved.
00320       if (!tmp_g.is_line_or_ray())
00321         tmp_g[new_size - 1] = tmp_g[0];
00322       tmp_g.set_not_necessarily_closed();
00323       // Inserting the new generator.
00324       Linear_System::insert(tmp_g);
00325     }
00326   PPL_ASSERT(OK());
00327 }

void Parma_Polyhedra_Library::Generator_System::insert_pending ( const Generator g  )  [private]

Inserts in *this a copy of the generator g, increasing the number of space dimensions if needed. It is a pending generator.

Definition at line 330 of file Generator_System.cc.

References Parma_Polyhedra_Library::Matrix::add_zero_columns(), Parma_Polyhedra_Library::Linear_System::insert_pending(), Parma_Polyhedra_Library::Generator::is_line_or_ray(), Parma_Polyhedra_Library::Linear_System::is_necessarily_closed(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), Parma_Polyhedra_Library::Linear_System::set_not_necessarily_closed(), space_dimension(), Parma_Polyhedra_Library::Generator::space_dimension(), Parma_Polyhedra_Library::Linear_Row::topology(), and Parma_Polyhedra_Library::Linear_System::topology().

Referenced by Parma_Polyhedra_Library::Polyhedron::add_generator(), and Parma_Polyhedra_Library::Polyhedron::unconstrain().

00330                                                       {
00331   if (topology() == g.topology())
00332     Linear_System::insert_pending(g);
00333   else
00334     // `*this' and `g' have different topologies.
00335     if (is_necessarily_closed()) {
00336       // Padding the matrix with the column
00337       // corresponding to the epsilon coefficients:
00338       // all points must have epsilon coordinate equal to 1
00339       // (i.e., the epsilon coefficient is equal to the divisor);
00340       // rays and lines must have epsilon coefficient equal to 0.
00341       // Note: normalization is preserved.
00342       const dimension_type eps_index = num_columns();
00343       add_zero_columns(1);
00344       Generator_System& gs = *this;
00345       for (dimension_type i = num_rows(); i-- > 0; ) {
00346         Generator& gen = gs[i];
00347         if (!gen.is_line_or_ray())
00348           gen[eps_index] = gen[0];
00349       }
00350       set_not_necessarily_closed();
00351       // Inserting the new generator.
00352       Linear_System::insert_pending(g);
00353     }
00354     else {
00355       // The generator system is NOT necessarily closed:
00356       // copy the generator, adding the missing dimensions
00357       // and the epsilon coefficient.
00358       const dimension_type new_size = 2 + std::max(g.space_dimension(),
00359                                                    space_dimension());
00360       Generator tmp_g(g, new_size);
00361       // If it was a point, set the epsilon coordinate to 1
00362       // (i.e., set the coefficient equal to the divisor).
00363       // Note: normalization is preserved.
00364       if (!tmp_g.is_line_or_ray())
00365         tmp_g[new_size - 1] = tmp_g[0];
00366       tmp_g.set_not_necessarily_closed();
00367       // Inserting the new generator.
00368       Linear_System::insert_pending(tmp_g);
00369     }
00370   PPL_ASSERT(OK());
00371 }

dimension_type Parma_Polyhedra_Library::Generator_System::max_space_dimension (  )  [inline, static]

Returns the maximum space dimension a Generator_System can handle.

Reimplemented from Parma_Polyhedra_Library::Linear_System.

Reimplemented in Parma_Polyhedra_Library::Grid_Generator_System.

Definition at line 70 of file Generator_System.inlines.hh.

Referenced by Parma_Polyhedra_Library::Polyhedron::max_space_dimension().

00070                                       {
00071   return Linear_System::max_space_dimension();
00072 }

PPL::dimension_type Parma_Polyhedra_Library::Generator_System::num_lines (  )  const [private]

Returns the number of lines of the system.

Reimplemented in Parma_Polyhedra_Library::Grid_Generator_System.

Definition at line 374 of file Generator_System.cc.

References Parma_Polyhedra_Library::Linear_System::is_sorted(), Parma_Polyhedra_Library::Linear_System::num_pending_rows(), and Parma_Polyhedra_Library::Matrix::num_rows().

Referenced by Parma_Polyhedra_Library::Polyhedron::is_topologically_closed(), Parma_Polyhedra_Library::Polyhedron::OK(), Parma_Polyhedra_Library::Polyhedron::quick_equivalence_test(), Parma_Polyhedra_Library::Polyhedron::strongly_minimize_constraints(), and Parma_Polyhedra_Library::Polyhedron::strongly_minimize_generators().

00374                                      {
00375   // We are sure that this method is applied only to a matrix
00376   // that does not contain pending rows.
00377   PPL_ASSERT(num_pending_rows() == 0);
00378   const Generator_System& gs = *this;
00379   dimension_type n = 0;
00380   // If the Linear_System happens to be sorted, take advantage of the fact
00381   // that lines are at the top of the system.
00382   if (is_sorted()) {
00383     dimension_type nrows = num_rows();
00384     for (dimension_type i = 0; i < nrows && gs[i].is_line(); ++i)
00385       ++n;
00386   }
00387   else
00388     for (dimension_type i = num_rows(); i-- > 0 ; )
00389       if (gs[i].is_line())
00390         ++n;
00391   return n;
00392 }

PPL::dimension_type Parma_Polyhedra_Library::Generator_System::num_rays (  )  const [private]

Returns the number of rays of the system.

Definition at line 395 of file Generator_System.cc.

References Parma_Polyhedra_Library::Linear_System::is_sorted(), Parma_Polyhedra_Library::Linear_System::num_pending_rows(), and Parma_Polyhedra_Library::Matrix::num_rows().

Referenced by Parma_Polyhedra_Library::Grid_Generator_System::num_parameters(), and Parma_Polyhedra_Library::Polyhedron::OK().

00395                                     {
00396   // We are sure that this method is applied only to a matrix
00397   // that does not contain pending rows.
00398   PPL_ASSERT(num_pending_rows() == 0);
00399   const Generator_System& gs = *this;
00400   dimension_type n = 0;
00401   // If the Linear_System happens to be sorted, take advantage of the fact
00402   // that rays and points are at the bottom of the system and
00403   // rays have the inhomogeneous term equal to zero.
00404   if (is_sorted()) {
00405     for (dimension_type i = num_rows(); i != 0 && gs[--i].is_ray_or_point(); )
00406       if (gs[i].is_line_or_ray())
00407         ++n;
00408   }
00409   else
00410     for (dimension_type i = num_rows(); i-- > 0 ; )
00411       if (gs[i].is_ray())
00412         ++n;
00413   return n;
00414 }

bool Parma_Polyhedra_Library::Generator_System::OK (  )  const

Checks if all the invariants are satisfied.

Returns true if and only if *this is a valid Linear_System and each row in the system is a valid Generator.

Reimplemented from Parma_Polyhedra_Library::Matrix.

Reimplemented in Parma_Polyhedra_Library::Grid_Generator_System.

Definition at line 1024 of file Generator_System.cc.

References Parma_Polyhedra_Library::Matrix::num_rows(), and Parma_Polyhedra_Library::Matrix::OK().

Referenced by add_corresponding_closure_points(), add_corresponding_points(), adjust_topology_and_space_dimension(), insert(), insert_pending(), and Parma_Polyhedra_Library::Polyhedron::OK().

01024                               {
01025   // A Generator_System must be a valid Linear_System; do not check for
01026   // strong normalization, since this will be done when
01027   // checking each individual generator.
01028   if (!Linear_System::OK(false))
01029     return false;
01030 
01031   // Checking each generator in the system.
01032   const Generator_System& x = *this;
01033   for (dimension_type i = num_rows(); i-- > 0; )
01034     if (!x[i].OK())
01035       return false;
01036 
01037   // All checks passed.
01038   return true;
01039 }

Generator_System & Parma_Polyhedra_Library::Generator_System::operator= ( const Generator_System y  )  [inline]

Assignment operator.

Definition at line 64 of file Generator_System.inlines.hh.

00064                                                      {
00065   Linear_System::operator=(y);
00066   return *this;
00067 }

const Generator & Parma_Polyhedra_Library::Generator_System::operator[] ( dimension_type  k  )  const [inline, private]

Returns a constant reference to the k- th generator of the system.

Reimplemented from Parma_Polyhedra_Library::Linear_System.

Reimplemented in Parma_Polyhedra_Library::Grid_Generator_System.

Definition at line 90 of file Generator_System.inlines.hh.

References operator[]().

00090                                                          {
00091   return static_cast<const Generator&>(Linear_System::operator[](k));
00092 }

Generator & Parma_Polyhedra_Library::Generator_System::operator[] ( dimension_type  k  )  [inline, private]

Returns the k- th generator of the system.

Reimplemented from Parma_Polyhedra_Library::Linear_System.

Reimplemented in Parma_Polyhedra_Library::Grid_Generator_System.

Definition at line 85 of file Generator_System.inlines.hh.

Referenced by operator[]().

00085                                                    {
00086   return static_cast<Generator&>(Linear_System::operator[](k));
00087 }

void Parma_Polyhedra_Library::Generator_System::print (  )  const

Prints *this to std::cerr using operator<<.

Reimplemented from Parma_Polyhedra_Library::Linear_System.

Reimplemented in Parma_Polyhedra_Library::Grid_Generator_System.

PPL::Poly_Con_Relation Parma_Polyhedra_Library::Generator_System::relation_with ( const Constraint c  )  const [private]

Returns the relations holding between the generator system and the constraint c.

Definition at line 417 of file Generator_System.cc.

References Parma_Polyhedra_Library::Generator::CLOSURE_POINT, Parma_Polyhedra_Library::Constraint::EQUALITY, Parma_Polyhedra_Library::Poly_Con_Relation::implies(), Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Generator::is_point(), Parma_Polyhedra_Library::Generator::LINE, Parma_Polyhedra_Library::Constraint::NONSTRICT_INEQUALITY, Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Generator::POINT, Parma_Polyhedra_Library::Generator::RAY, Parma_Polyhedra_Library::Scalar_Products::reduced_sign(), Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), Parma_Polyhedra_Library::Scalar_Products::sign(), Parma_Polyhedra_Library::Constraint::space_dimension(), space_dimension(), Parma_Polyhedra_Library::Constraint::STRICT_INEQUALITY, Parma_Polyhedra_Library::Poly_Con_Relation::strictly_intersects(), Parma_Polyhedra_Library::Generator::type(), and Parma_Polyhedra_Library::Constraint::type().

Referenced by Parma_Polyhedra_Library::Polyhedron::relation_with().

00417                                                             {
00418   // Note: this method is not public and it is the responsibility
00419   // of the caller to actually test for dimension compatibility.
00420   // We simply assert it.
00421   PPL_ASSERT(space_dimension() >= c.space_dimension());
00422   // Number of generators: the case of an empty polyhedron
00423   // has already been filtered out by the caller.
00424   const dimension_type n_rows = num_rows();
00425   PPL_ASSERT(n_rows > 0);
00426   const Generator_System& gs = *this;
00427 
00428   // `result' will keep the relation holding between the generators
00429   // we have seen so far and the constraint `c'.
00430   Poly_Con_Relation result = Poly_Con_Relation::saturates();
00431 
00432   switch (c.type()) {
00433 
00434   case Constraint::EQUALITY:
00435     {
00436       // The hyperplane defined by the equality `c' is included
00437       // in the set of points satisfying `c' (it is the same set!).
00438       result = result && Poly_Con_Relation::is_included();
00439       // The following integer variable will hold the scalar product sign
00440       // of either the first point or the first non-saturating ray we find.
00441       // If it is equal to 2, then it means that we haven't found such
00442       // a generator yet.
00443       int first_point_or_nonsaturating_ray_sign = 2;
00444 
00445       for (dimension_type i = n_rows; i-- > 0; ) {
00446         const Generator& g = gs[i];
00447         const int sp_sign = Scalar_Products::sign(c, g);
00448         // Checking whether the generator saturates the equality.
00449         // If that is the case, then we have to do something only if
00450         // the generator is a point.
00451         if (sp_sign == 0) {
00452           if (g.is_point()) {
00453             if (first_point_or_nonsaturating_ray_sign == 2)
00454               // It is the first time that we find a point and
00455               // we have not found a non-saturating ray yet.
00456               first_point_or_nonsaturating_ray_sign = 0;
00457             else
00458               // We already found a point or a non-saturating ray.
00459               if (first_point_or_nonsaturating_ray_sign != 0)
00460                 return Poly_Con_Relation::strictly_intersects();
00461           }
00462         }
00463         else
00464           // Here we know that sp_sign != 0.
00465           switch (g.type()) {
00466 
00467           case Generator::LINE:
00468             // If a line does not saturate `c', then there is a strict
00469             // intersection between the points satisfying `c'
00470             // and the points generated by `gs'.
00471             return Poly_Con_Relation::strictly_intersects();
00472 
00473           case Generator::RAY:
00474             if (first_point_or_nonsaturating_ray_sign == 2) {
00475               // It is the first time that we have a non-saturating ray
00476               // and we have not found any point yet.
00477               first_point_or_nonsaturating_ray_sign = sp_sign;
00478               result = Poly_Con_Relation::is_disjoint();
00479             }
00480             else
00481               // We already found a point or a non-saturating ray.
00482               if (sp_sign != first_point_or_nonsaturating_ray_sign)
00483                 return Poly_Con_Relation::strictly_intersects();
00484             break;
00485 
00486           case Generator::POINT:
00487           case Generator::CLOSURE_POINT:
00488             // NOTE: a non-saturating closure point is treated as
00489             // a normal point.
00490             if (first_point_or_nonsaturating_ray_sign == 2) {
00491               // It is the first time that we find a point and
00492               // we have not found a non-saturating ray yet.
00493               first_point_or_nonsaturating_ray_sign = sp_sign;
00494               result = Poly_Con_Relation::is_disjoint();
00495             }
00496             else
00497               // We already found a point or a non-saturating ray.
00498               if (sp_sign != first_point_or_nonsaturating_ray_sign)
00499                 return Poly_Con_Relation::strictly_intersects();
00500             break;
00501           }
00502       }
00503     }
00504     break;
00505 
00506   case Constraint::NONSTRICT_INEQUALITY:
00507     {
00508       // The hyperplane implicitly defined by the non-strict inequality `c'
00509       // is included in the set of points satisfying `c'.
00510       result = result && Poly_Con_Relation::is_included();
00511       // The following Boolean variable will be set to `false'
00512       // as soon as either we find (any) point or we find a
00513       // non-saturating ray.
00514       bool first_point_or_nonsaturating_ray = true;
00515 
00516       for (dimension_type i = n_rows; i-- > 0; ) {
00517         const Generator& g = gs[i];
00518         const int sp_sign = Scalar_Products::sign(c, g);
00519         // Checking whether the generator saturates the non-strict
00520         // inequality. If that is the case, then we have to do something
00521         // only if the generator is a point.
00522         if (sp_sign == 0) {
00523           if (g.is_point()) {
00524             if (first_point_or_nonsaturating_ray)
00525               // It is the first time that we have a point and
00526               // we have not found a non-saturating ray yet.
00527               first_point_or_nonsaturating_ray = false;
00528             else
00529               // We already found a point or a non-saturating ray before.
00530               if (result == Poly_Con_Relation::is_disjoint())
00531                 // Since g saturates c, we have a strict intersection if
00532                 // none of the generators seen so far are included in `c'.
00533                 return Poly_Con_Relation::strictly_intersects();
00534           }
00535         }
00536         else
00537           // Here we know that sp_sign != 0.
00538           switch (g.type()) {
00539 
00540           case Generator::LINE:
00541             // If a line does not saturate `c', then there is a strict
00542             // intersection between the points satisfying `c' and
00543             // the points generated by `gs'.
00544             return Poly_Con_Relation::strictly_intersects();
00545 
00546           case Generator::RAY:
00547             if (first_point_or_nonsaturating_ray) {
00548               // It is the first time that we have a non-saturating ray
00549               // and we have not found any point yet.
00550               first_point_or_nonsaturating_ray = false;
00551               result = (sp_sign > 0)
00552                 ? Poly_Con_Relation::is_included()
00553                 : Poly_Con_Relation::is_disjoint();
00554             }
00555             else {
00556               // We already found a point or a non-saturating ray.
00557               if ((sp_sign > 0
00558                    && result == Poly_Con_Relation::is_disjoint())
00559                   || (sp_sign < 0
00560                       && result.implies(Poly_Con_Relation::is_included())))
00561                 // We have a strict intersection if either:
00562                 // - `g' satisfies `c' but none of the generators seen
00563                 //    so far are included in `c'; or
00564                 // - `g' does not satisfy `c' and all the generators
00565                 //    seen so far are included in `c'.
00566                 return Poly_Con_Relation::strictly_intersects();
00567               if (sp_sign > 0)
00568                 // Here all the generators seen so far either saturate
00569                 // or are included in `c'.
00570                 // Since `g' does not saturate `c' ...
00571                 result = Poly_Con_Relation::is_included();
00572             }
00573             break;
00574 
00575           case Generator::POINT:
00576           case Generator::CLOSURE_POINT:
00577             // NOTE: a non-saturating closure point is treated as
00578             // a normal point.
00579             if (first_point_or_nonsaturating_ray) {
00580               // It is the first time that we have a point and
00581               // we have not found a non-saturating ray yet.
00582               // - If point `g' saturates `c', then all the generators
00583               //   seen so far saturate `c'.
00584               // - If point `g' is included (but does not saturate) `c',
00585               //   then all the generators seen so far are included in `c'.
00586               // - If point `g' does not satisfy `c', then all the
00587               //   generators seen so far are disjoint from `c'.
00588               first_point_or_nonsaturating_ray = false;
00589               if (sp_sign > 0)
00590                 result = Poly_Con_Relation::is_included();
00591               else if (sp_sign < 0)
00592                 result = Poly_Con_Relation::is_disjoint();
00593             }
00594             else {
00595               // We already found a point or a non-saturating ray before.
00596               if ((sp_sign > 0
00597                    && result == Poly_Con_Relation::is_disjoint())
00598                   || (sp_sign < 0
00599                       && result.implies(Poly_Con_Relation::is_included())))
00600                 // We have a strict intersection if either:
00601                 // - `g' satisfies or saturates `c' but none of the
00602                 //    generators seen so far are included in `c'; or
00603                 // - `g' does not satisfy `c' and all the generators
00604                 //    seen so far are included in `c'.
00605                 return Poly_Con_Relation::strictly_intersects();
00606               if (sp_sign > 0)
00607                 // Here all the generators seen so far either saturate
00608                 // or are included in `c'.
00609                 // Since `g' does not saturate `c' ...
00610                 result = Poly_Con_Relation::is_included();
00611             }
00612             break;
00613           }
00614       }
00615     }
00616     break;
00617 
00618   case Constraint::STRICT_INEQUALITY:
00619     {
00620       // The hyperplane implicitly defined by the strict inequality `c'
00621       // is disjoint from the set of points satisfying `c'.
00622       result = result && Poly_Con_Relation::is_disjoint();
00623       // The following Boolean variable will be set to `false'
00624       // as soon as either we find (any) point or we find a
00625       // non-saturating ray.
00626       bool first_point_or_nonsaturating_ray = true;
00627       for (dimension_type i = n_rows; i-- > 0; ) {
00628         const Generator& g = gs[i];
00629         // Using the reduced scalar product operator to avoid
00630         // both topology and num_columns mismatches.
00631         const int sp_sign = Scalar_Products::reduced_sign(c, g);
00632         // Checking whether the generator saturates the strict inequality.
00633         // If that is the case, then we have to do something
00634         // only if the generator is a point.
00635         if (sp_sign == 0) {
00636           if (g.is_point()) {
00637             if (first_point_or_nonsaturating_ray)
00638               // It is the first time that we have a point and
00639               // we have not found a non-saturating ray yet.
00640               first_point_or_nonsaturating_ray = false;
00641             else
00642               // We already found a point or a non-saturating ray before.
00643               if (result == Poly_Con_Relation::is_included())
00644                 return Poly_Con_Relation::strictly_intersects();
00645           }
00646         }
00647         else
00648           // Here we know that sp_sign != 0.
00649           switch (g.type()) {
00650 
00651           case Generator::LINE:
00652             // If a line does not saturate `c', then there is a strict
00653             // intersection between the points satisfying `c' and the points
00654             // generated by `gs'.
00655             return Poly_Con_Relation::strictly_intersects();
00656 
00657           case Generator::RAY:
00658             if (first_point_or_nonsaturating_ray) {
00659               // It is the first time that we have a non-saturating ray
00660               // and we have not found any point yet.
00661               first_point_or_nonsaturating_ray = false;
00662               result = (sp_sign > 0)
00663                 ? Poly_Con_Relation::is_included()
00664                 : Poly_Con_Relation::is_disjoint();
00665             }
00666             else {
00667               // We already found a point or a non-saturating ray before.
00668               if ((sp_sign > 0
00669                    && result.implies(Poly_Con_Relation::is_disjoint()))
00670                   ||
00671                   (sp_sign <= 0
00672                    && result == Poly_Con_Relation::is_included()))
00673                 return Poly_Con_Relation::strictly_intersects();
00674               if (sp_sign < 0)
00675                 // Here all the generators seen so far either saturate
00676                 // or are disjoint from `c'.
00677                 // Since `g' does not saturate `c' ...
00678                 result = Poly_Con_Relation::is_disjoint();
00679             }
00680             break;
00681 
00682           case Generator::POINT:
00683           case Generator::CLOSURE_POINT:
00684             if (first_point_or_nonsaturating_ray) {
00685               // It is the first time that we have a point and
00686               // we have not found a non-saturating ray yet.
00687               // - If point `g' saturates `c', then all the generators
00688               //   seen so far saturate `c'.
00689               // - If point `g' is included in (but does not saturate) `c',
00690               //   then all the generators seen so far are included in `c'.
00691               // - If point `g' strictly violates `c', then all the
00692               //   generators seen so far are disjoint from `c'.
00693               first_point_or_nonsaturating_ray = false;
00694               if (sp_sign > 0)
00695                 result = Poly_Con_Relation::is_included();
00696               else if (sp_sign < 0)
00697                 result = Poly_Con_Relation::is_disjoint();
00698             }
00699             else {
00700               // We already found a point or a non-saturating ray before.
00701               if ((sp_sign > 0
00702                    && result.implies(Poly_Con_Relation::is_disjoint()))
00703                   ||
00704                   (sp_sign <= 0
00705                    && result == Poly_Con_Relation::is_included()))
00706                 return Poly_Con_Relation::strictly_intersects();
00707               if (sp_sign < 0)
00708                 // Here all the generators seen so far either saturate
00709                 // or are disjoint from `c'.
00710                 // Since `g' does not saturate `c' ...
00711                 result = Poly_Con_Relation::is_disjoint();
00712             }
00713             break;
00714           }
00715       }
00716     }
00717     break;
00718   }
00719   // We have seen all generators.
00720   return result;
00721 }

void Parma_Polyhedra_Library::Generator_System::remove_invalid_lines_and_rays (  )  [private]

Removes all the invalid lines and rays.

The invalid lines and rays are those with all the homogeneous terms set to zero.

Definition at line 950 of file Generator_System.cc.

References Parma_Polyhedra_Library::Linear_Row::all_homogeneous_terms_are_zero(), Parma_Polyhedra_Library::Matrix::erase_to_end(), Parma_Polyhedra_Library::Linear_System::first_pending_row(), Parma_Polyhedra_Library::Generator::is_line_or_ray(), Parma_Polyhedra_Library::Linear_System::num_pending_rows(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Linear_System::set_index_first_pending_row(), Parma_Polyhedra_Library::Linear_System::set_sorted(), Parma_Polyhedra_Library::swap(), and swap().

Referenced by affine_image(), Parma_Polyhedra_Library::Polyhedron::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Polyhedron::remove_space_dimensions(), and simplify().

00950                                                    {
00951   // The origin of the vector space cannot be a valid line/ray.
00952   // NOTE: the following swaps will mix generators without even trying
00953   // to preserve sortedness: as a matter of fact, it will almost always
00954   // be the case that the input generator system is NOT sorted.
00955   Generator_System& gs = *this;
00956   dimension_type n_rows = gs.num_rows();
00957   if (num_pending_rows() == 0) {
00958     for (dimension_type i = n_rows; i-- > 0; ) {
00959       Generator& g = gs[i];
00960       if (g.is_line_or_ray() && g.all_homogeneous_terms_are_zero()) {
00961         // An invalid line/ray has been found.
00962         --n_rows;
00963         std::swap(g, gs[n_rows]);
00964         gs.set_sorted(false);
00965       }
00966     }
00967     set_index_first_pending_row(n_rows);
00968   }
00969   else {
00970     // If the matrix has some pending rows, we can not
00971     // swap the "normal" rows with the pending rows. So
00972     // we must put at the end of the "normal" rows
00973     // the invalid "normal" rows, put them at the end
00974     // of the matrix, find the invalid rows in the pending
00975     // part and then erase the invalid rows that now
00976     // are in the bottom part of the matrix.
00977     PPL_ASSERT(num_pending_rows() > 0);
00978     dimension_type first_pending = first_pending_row();
00979     for (dimension_type i = first_pending; i-- > 0; ) {
00980       Generator& g = gs[i];
00981       if (g.is_line_or_ray() && g.all_homogeneous_terms_are_zero()) {
00982         // An invalid line/ray has been found.
00983         --first_pending;
00984         std::swap(g, gs[first_pending]);
00985         gs.set_sorted(false);
00986       }
00987     }
00988     const dimension_type num_invalid_rows
00989       = first_pending_row() - first_pending;
00990     set_index_first_pending_row(first_pending);
00991     for (dimension_type i = 0; i < num_invalid_rows; ++i)
00992       std::swap(gs[n_rows - i], gs[first_pending + i]);
00993     n_rows -= num_invalid_rows;
00994     for (dimension_type i = n_rows; i-- > first_pending; ) {
00995       Generator& g = gs[i];
00996       if (g.is_line_or_ray() && g.all_homogeneous_terms_are_zero()) {
00997         // An invalid line/ray has been found.
00998         --n_rows;
00999         std::swap(g, gs[n_rows]);
01000         gs.set_sorted(false);
01001       }
01002     }
01003   }
01004   gs.erase_to_end(n_rows);
01005 }

bool Parma_Polyhedra_Library::Generator_System::satisfied_by_all_generators ( const Constraint c  )  const [private]

Returns true if all the generators satisfy c.

Definition at line 725 of file Generator_System.cc.

References Parma_Polyhedra_Library::Constraint::EQUALITY, Parma_Polyhedra_Library::Generator::is_line(), Parma_Polyhedra_Library::Generator::LINE, Parma_Polyhedra_Library::Constraint::NONSTRICT_INEQUALITY, Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Generator::POINT, space_dimension(), Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::Constraint::STRICT_INEQUALITY, Parma_Polyhedra_Library::Generator::type(), and Parma_Polyhedra_Library::Constraint::type().

Referenced by Parma_Polyhedra_Library::Polyhedron::limited_BHRZ03_extrapolation_assign(), Parma_Polyhedra_Library::Polyhedron::limited_H79_extrapolation_assign(), Parma_Polyhedra_Library::Polyhedron::select_CH78_constraints(), and Parma_Polyhedra_Library::Polyhedron::simplify_using_context_assign().

00725                                                                           {
00726   PPL_ASSERT(c.space_dimension() <= space_dimension());
00727 
00728   // Setting `sps' to the appropriate scalar product sign operator.
00729   // This also avoids problems when having _legal_ topology mismatches
00730   // (which could also cause a mismatch in the number of columns).
00731   Topology_Adjusted_Scalar_Product_Sign sps(c);
00732 
00733   const Generator_System& gs = *this;
00734   switch (c.type()) {
00735   case Constraint::EQUALITY:
00736     // Equalities must be saturated by all generators.
00737     for (dimension_type i = gs.num_rows(); i-- > 0; )
00738       if (sps(c, gs[i]) != 0)
00739         return false;
00740     break;
00741   case Constraint::NONSTRICT_INEQUALITY:
00742     // Non-strict inequalities must be saturated by lines and
00743     // satisfied by all the other generators.
00744     for (dimension_type i = gs.num_rows(); i-- > 0; ) {
00745       const Generator& g = gs[i];
00746       const int sp_sign = sps(c, g);
00747       if (g.is_line()) {
00748         if (sp_sign != 0)
00749           return false;
00750       }
00751       else
00752         // `g' is a ray, point or closure point.
00753         if (sp_sign < 0)
00754           return false;
00755     }
00756     break;
00757   case Constraint::STRICT_INEQUALITY:
00758     // Strict inequalities must be saturated by lines,
00759     // satisfied by all generators, and must not be saturated by points.
00760     for (dimension_type i = gs.num_rows(); i-- > 0; ) {
00761       const Generator& g = gs[i];
00762       const int sp_sign = sps(c, g);
00763       switch (g.type()) {
00764       case Generator::POINT:
00765         if (sp_sign <= 0)
00766           return false;
00767         break;
00768       case Generator::LINE:
00769         if (sp_sign != 0)
00770           return false;
00771         break;
00772       default:
00773         // `g' is a ray or closure point.
00774         if (sp_sign < 0)
00775           return false;
00776         break;
00777       }
00778     }
00779     break;
00780   }
00781   // If we reach this point, `c' is satisfied by all generators.
00782   return true;
00783 }

bool Parma_Polyhedra_Library::Generator_System::satisfied_by_all_generators_C ( const Constraint c  )  const [private]

Returns true if all the generators satisfy c.

It is assumed that c.is_necessarily_closed() holds.

bool Parma_Polyhedra_Library::Generator_System::satisfied_by_all_generators_NNC ( const Constraint c  )  const [private]

Returns true if all the generators satisfy c.

It is assumed that c.is_necessarily_closed() does not hold.

void Parma_Polyhedra_Library::Generator_System::simplify (  )  [inline, private]

Applies Gaussian elimination and back-substitution so as to provide a partial simplification of the system of generators.

It is assumed that the system has no pending generators.

Reimplemented from Parma_Polyhedra_Library::Linear_System.

Definition at line 199 of file Generator_System.inlines.hh.

References remove_invalid_lines_and_rays().

00199                            {
00200   Linear_System::simplify();
00201   remove_invalid_lines_and_rays();
00202 }

dimension_type Parma_Polyhedra_Library::Generator_System::space_dimension (  )  const [inline]
void Parma_Polyhedra_Library::Generator_System::swap ( Generator_System y  )  [inline]

Swaps *this with y.

Definition at line 184 of file Generator_System.inlines.hh.

Referenced by adjust_topology_and_space_dimension(), affine_image(), remove_invalid_lines_and_rays(), and swap().

00184                                           {
00185   Linear_System::swap(y);
00186 }

memory_size_type Parma_Polyhedra_Library::Generator_System::total_memory_in_bytes (  )  const [inline]

Returns the total size in bytes of the memory occupied by *this.

Reimplemented from Parma_Polyhedra_Library::Linear_System.

Reimplemented in Parma_Polyhedra_Library::Grid_Generator_System.

Definition at line 194 of file Generator_System.inlines.hh.

00194                                               {
00195   return Linear_System::total_memory_in_bytes();
00196 }

const Generator_System & Parma_Polyhedra_Library::Generator_System::zero_dim_univ (  )  [inline, static]

Returns the singleton system containing only Generator::zero_dim_point().

Reimplemented in Parma_Polyhedra_Library::Grid_Generator_System.

Definition at line 178 of file Generator_System.inlines.hh.

References zero_dim_univ_p.

Referenced by Parma_Polyhedra_Library::Polyhedron::generators().

00178                                 {
00179   PPL_ASSERT(zero_dim_univ_p != 0);
00180   return *zero_dim_univ_p;
00181 }


Friends And Related Function Documentation

friend class const_iterator [friend]

Definition at line 362 of file Generator_System.defs.hh.

std::ostream & operator<< ( std::ostream &  s,
const Generator_System gs 
) [related]

Output operator.

Writes false if gs is empty. Otherwise, writes on s the generators of gs, all in one row and separated by ", ".

Definition at line 1043 of file Generator_System.cc.

References begin(), and end().

01043                                                                      {
01044   Generator_System::const_iterator i = gs.begin();
01045   const Generator_System::const_iterator gs_end = gs.end();
01046   if (i == gs_end)
01047     return s << "false";
01048   while (true) {
01049     s << *i++;
01050     if (i == gs_end)
01051       return s;
01052     s << ", ";
01053   }
01054 }

bool operator== ( const Polyhedron x,
const Polyhedron y 
) [friend]

Definition at line 364 of file Generator_System.defs.hh.

friend class Parma_Polyhedra_Library::Polyhedron [friend]

Definition at line 363 of file Generator_System.defs.hh.

Specializes std::swap.

Definition at line 211 of file Generator_System.inlines.hh.

References swap().

00212                                                  {
00213   x.swap(y);
00214 }


Member Data Documentation

Holds (between class initialization and finalization) a pointer to the singleton system containing only Generator::zero_dim_point().

Reimplemented in Parma_Polyhedra_Library::Grid_Generator_System.

Definition at line 360 of file Generator_System.defs.hh.

Referenced by finalize(), initialize(), and zero_dim_univ().


The documentation for this class was generated from the following files:
Generated on Sun Feb 27 16:20:25 2011 for PPL by  doxygen 1.6.3