A system of generators. More...
#include <Generator_System.defs.hh>


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_System & | operator= (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_System & | zero_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 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. | |
| Generator & | operator[] (dimension_type k) |
Returns the k- th generator of the system. | |
| const Generator & | operator[] (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_System * | zero_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. | |
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).
x and y are defined as follows: Variable x(0); Variable y(1);
axis (i.e., the first Cartesian axis) in
: Generator_System gs; gs.insert(line(x + 0*y));
axis, we can add the following code which inserts the origin of the space as a point: gs.insert(point(0*x + 0*y));
gs.insert(point(0*x));
axis through the point
. gs.insert(point(0*x + 1*y));
axis in
: Generator_System gs; gs.insert(ray(x + 0*y));
gs.insert(point(0*x + 0*y));
(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));
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));
(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));
Definition at line 183 of file Generator_System.defs.hh.
| 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] |
| 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
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 }
| 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.
| v | Index of the column to which the affine transformation is assigned; | |
| expr | The numerator of the affine transformation: ; | |
| 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:
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] |
Returns the const_iterator pointing to the first generator, if *this is not empty; otherwise, returns the past-the-end const_iterator.
Reimplemented from Parma_Polyhedra_Library::Matrix.
Reimplemented in Parma_Polyhedra_Library::Grid_Generator_System.
Definition at line 164 of file Generator_System.inlines.hh.
References Parma_Polyhedra_Library::Matrix::begin(), and Parma_Polyhedra_Library::Linear_System::is_necessarily_closed().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::BHRZ03_Certificate::BHRZ03_Certificate(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::BHRZ03_Certificate::compare(), has_closure_points(), Parma_Polyhedra_Library::Polyhedron::map_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), operator<<(), Parma_Polyhedra_Library::Polyhedron::relation_with(), and Parma_Polyhedra_Library::Polyhedron::simplify_using_context_assign().
00164 { 00165 const_iterator i(Linear_System::begin(), *this); 00166 if (!is_necessarily_closed()) 00167 i.skip_forward(); 00168 return i; 00169 }
| 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] |
Returns the past-the-end const_iterator.
Reimplemented from Parma_Polyhedra_Library::Matrix.
Reimplemented in Parma_Polyhedra_Library::Grid_Generator_System.
Definition at line 172 of file Generator_System.inlines.hh.
References Parma_Polyhedra_Library::Matrix::end().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::BHRZ03_Certificate::BHRZ03_Certificate(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::BHRZ03_Certificate::compare(), has_closure_points(), Parma_Polyhedra_Library::Polyhedron::map_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), operator<<(), Parma_Polyhedra_Library::Polyhedron::relation_with(), and Parma_Polyhedra_Library::Polyhedron::simplify_using_context_assign().
00172 { 00173 const const_iterator i(Linear_System::end(), *this); 00174 return i; 00175 }
| 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] |
Returns the dimension of the vector space enclosing *this.
Reimplemented from Parma_Polyhedra_Library::Linear_System.
Reimplemented in Parma_Polyhedra_Library::Grid_Generator_System.
Definition at line 75 of file Generator_System.inlines.hh.
Referenced by Parma_Polyhedra_Library::Polyhedron::add_recycled_generators(), adjust_topology_and_space_dimension(), affine_image(), Parma_Polyhedra_Library::Polyhedron::generators(), insert(), insert_pending(), Parma_Polyhedra_Library::Polyhedron::Polyhedron(), relation_with(), satisfied_by_all_generators(), Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), and Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible().
00075 { 00076 return Linear_System::space_dimension(); 00077 }
| 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 }
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] |
friend class Parma_Polyhedra_Library::Grid_Generator_System [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.
| void swap | ( | Parma_Polyhedra_Library::Generator_System & | x, | |
| Parma_Polyhedra_Library::Generator_System & | y | |||
| ) | [related] |
Specializes std::swap.
Definition at line 211 of file Generator_System.inlines.hh.
References swap().
00212 { 00213 x.swap(y); 00214 }
const PPL::Generator_System * Parma_Polyhedra_Library::Generator_System::zero_dim_univ_p = 0 [static, private] |
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().
1.6.3