diff options
Diffstat (limited to 'src/Grid.defs.hh')
-rw-r--r-- | src/Grid.defs.hh | 2640 |
1 files changed, 2640 insertions, 0 deletions
diff --git a/src/Grid.defs.hh b/src/Grid.defs.hh new file mode 100644 index 000000000..95d295246 --- /dev/null +++ b/src/Grid.defs.hh @@ -0,0 +1,2640 @@ +/* Grid class declaration. + Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it> + Copyright (C) 2010-2011 BUGSENG srl (http://bugseng.com) + +This file is part of the Parma Polyhedra Library (PPL). + +The PPL is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The PPL is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA. + +For the most up-to-date information see the Parma Polyhedra Library +site: http://www.cs.unipr.it/ppl/ . */ + +#ifndef PPL_Grid_defs_hh +#define PPL_Grid_defs_hh 1 + +#include "Grid.types.hh" +#include "globals.defs.hh" +#include "Variable.defs.hh" +#include "Variables_Set.types.hh" +#include "Linear_Expression.defs.hh" +#include "Constraint.types.hh" +#include "Constraint_System.defs.hh" +#include "Constraint_System.inlines.hh" +#include "Congruence_System.defs.hh" +#include "Congruence_System.inlines.hh" +#include "Grid_Generator_System.defs.hh" +#include "Grid_Generator_System.inlines.hh" +#include "Grid_Generator.types.hh" +#include "Poly_Con_Relation.defs.hh" +#include "Poly_Gen_Relation.defs.hh" +#include "Grid_Certificate.types.hh" +#include "Box.types.hh" +#include "Polyhedron.types.hh" +#include "BD_Shape.types.hh" +#include "Octagonal_Shape.types.hh" +#include <vector> +#include <iosfwd> + +namespace Parma_Polyhedra_Library { + +namespace IO_Operators { + +//! Output operator. +/*! + \relates Parma_Polyhedra_Library::Grid + Writes a textual representation of \p gr on \p s: <CODE>false</CODE> + is written if \p gr is an empty grid; <CODE>true</CODE> is written + if \p gr is a universe grid; a minimized system of congruences + defining \p gr is written otherwise, all congruences in one row + separated by ", "s. +*/ +std::ostream& +operator<<(std::ostream& s, const Grid& gr); + +} // namespace IO_Operators + +/*! \brief + Returns <CODE>true</CODE> if and only if \p x and \p y are the same + grid. + + \relates Grid + Note that \p x and \p y may be dimension-incompatible grids: in + those cases, the value <CODE>false</CODE> is returned. +*/ +bool operator==(const Grid& x, const Grid& y); + +/*! \brief + Returns <CODE>true</CODE> if and only if \p x and \p y are different + grids. + + \relates Grid + Note that \p x and \p y may be dimension-incompatible grids: in + those cases, the value <CODE>true</CODE> is returned. +*/ +bool operator!=(const Grid& x, const Grid& y); + +} // namespace Parma_Polyhedra_Library + + +//! A grid. +/*! \ingroup PPL_CXX_interface + An object of the class Grid represents a rational grid. + + The domain of grids <EM>optimally supports</EM>: + - all (proper and non-proper) congruences; + - tautological and inconsistent constraints; + - linear equality constraints (i.e., non-proper congruences). + + Depending on the method, using a constraint that is not optimally + supported by the domain will either raise an exception or + result in a (possibly non-optimal) upward approximation. + + The domain of grids support a concept of double description similar + to the one developed for polyhedra: hence, a grid can be specified + as either a finite system of congruences or a finite system of + generators (see Section \ref sect_rational_grids) and it is always + possible to obtain either representation. + That is, if we know the system of congruences, we can obtain + from this a system of generators that define the same grid + and vice versa. + These systems can contain redundant members, or they can be in the + minimal form. + + A key attribute of any grid is its space dimension (the dimension + \f$n \in \Nset\f$ of the enclosing vector space): + + - all grids, the empty ones included, are endowed with a space + dimension; + - most operations working on a grid and another object (another + grid, a congruence, a generator, a set of variables, etc.) will + throw an exception if the grid and the object are not + dimension-compatible (see Section \ref Grid_Space_Dimensions); + - the only ways in which the space dimension of a grid can be + changed are with <EM>explicit</EM> calls to operators provided for + that purpose, and with standard copy, assignment and swap + operators. + + Note that two different grids can be defined on the zero-dimension + space: the empty grid and the universe grid \f$R^0\f$. + + \par + In all the examples it is assumed that variables + <CODE>x</CODE> and <CODE>y</CODE> are defined (where they are + used) as follows: + \code + Variable x(0); + Variable y(1); + \endcode + + \par Example 1 + The following code builds a grid corresponding to the even integer + pairs in \f$\Rset^2\f$, given as a system of congruences: + \code + Congruence_System cgs; + cgs.insert((x %= 0) / 2); + cgs.insert((y %= 0) / 2); + Grid gr(cgs); + \endcode + The following code builds the same grid as above, but starting + from a system of generators specifying three of the points: + \code + Grid_Generator_System gs; + gs.insert(grid_point(0*x + 0*y)); + gs.insert(grid_point(0*x + 2*y)); + gs.insert(grid_point(2*x + 0*y)); + Grid gr(gs); + \endcode + + \par Example 2 + The following code builds a grid corresponding to a line in + \f$\Rset^2\f$ by adding a single congruence to the universe grid: + \code + Congruence_System cgs; + cgs.insert(x - y == 0); + Grid gr(cgs); + \endcode + The following code builds the same grid as above, but starting + from a system of generators specifying a point and a line: + \code + Grid_Generator_System gs; + gs.insert(grid_point(0*x + 0*y)); + gs.insert(grid_line(x + y)); + Grid gr(gs); + \endcode + + \par Example 3 + The following code builds a grid corresponding to the integral + points on the line \f$x = y\f$ in \f$\Rset^2\f$ constructed + by adding an equality and congruence to the universe grid: + \code + Congruence_System cgs; + cgs.insert(x - y == 0); + cgs.insert(x %= 0); + Grid gr(cgs); + \endcode + The following code builds the same grid as above, but starting + from a system of generators specifying a point and a parameter: + \code + Grid_Generator_System gs; + gs.insert(grid_point(0*x + 0*y)); + gs.insert(parameter(x + y)); + Grid gr(gs); + \endcode + + \par Example 4 + The following code builds the grid corresponding to a plane by + creating the universe grid in \f$\Rset^2\f$: + \code + Grid gr(2); + \endcode + The following code builds the same grid as above, but starting + from the empty grid in \f$\Rset^2\f$ and inserting the appropriate + generators (a point, and two lines). + \code + Grid gr(2, EMPTY); + gr.add_grid_generator(grid_point(0*x + 0*y)); + gr.add_grid_generator(grid_line(x)); + gr.add_grid_generator(grid_line(y)); + \endcode + Note that a generator system must contain a point when describing + a grid. To ensure that this is always the case it is required + that the first generator inserted in an empty grid is a point + (otherwise, an exception is thrown). + + \par Example 5 + The following code shows the use of the function + <CODE>add_space_dimensions_and_embed</CODE>: + \code + Grid gr(1); + gr.add_congruence(x == 2); + gr.add_space_dimensions_and_embed(1); + \endcode + We build the universe grid in the 1-dimension space \f$\Rset\f$. + Then we add a single equality congruence, + thus obtaining the grid corresponding to the singleton set + \f$\{ 2 \} \sseq \Rset\f$. + After the last line of code, the resulting grid is + \f[ + \bigl\{\, + (2, y)^\transpose \in \Rset^2 + \bigm| + y \in \Rset + \,\bigr\}. + \f] + + \par Example 6 + The following code shows the use of the function + <CODE>add_space_dimensions_and_project</CODE>: + \code + Grid gr(1); + gr.add_congruence(x == 2); + gr.add_space_dimensions_and_project(1); + \endcode + The first two lines of code are the same as in Example 4 for + <CODE>add_space_dimensions_and_embed</CODE>. + After the last line of code, the resulting grid is + the singleton set + \f$\bigl\{ (2, 0)^\transpose \bigr\} \sseq \Rset^2\f$. + + \par Example 7 + The following code shows the use of the function + <CODE>affine_image</CODE>: + \code + Grid gr(2, EMPTY); + gr.add_grid_generator(grid_point(0*x + 0*y)); + gr.add_grid_generator(grid_point(4*x + 0*y)); + gr.add_grid_generator(grid_point(0*x + 2*y)); + Linear_Expression expr = x + 3; + gr.affine_image(x, expr); + \endcode + In this example the starting grid is all the pairs of \f$x\f$ and + \f$y\f$ in \f$\Rset^2\f$ where \f$x\f$ is an integer multiple of 4 + and \f$y\f$ is an integer multiple of 2. The considered variable + is \f$x\f$ and the affine expression is \f$x+3\f$. The resulting + grid is the given grid translated 3 integers to the right (all the + pairs \f$(x, y)\f$ where \f$x\f$ is -1 plus an integer multiple of 4 + and \f$y\f$ is an integer multiple of 2). + Moreover, if the affine transformation for the same variable \p x + is instead \f$x+y\f$: + \code + Linear_Expression expr = x + y; + \endcode + the resulting grid is every second integral point along the \f$x=y\f$ + line, with this line of points repeated at every fourth integral value + along the \f$x\f$ axis. + Instead, if we do not use an invertible transformation for the + same variable; for example, the affine expression \f$y\f$: + \code + Linear_Expression expr = y; + \endcode + the resulting grid is every second point along the \f$x=y\f$ line. + + \par Example 8 + The following code shows the use of the function + <CODE>affine_preimage</CODE>: + \code + Grid gr(2, EMPTY); + gr.add_grid_generator(grid_point(0*x + 0*y)); + gr.add_grid_generator(grid_point(4*x + 0*y)); + gr.add_grid_generator(grid_point(0*x + 2*y)); + Linear_Expression expr = x + 3; + gr.affine_preimage(x, expr); + \endcode + In this example the starting grid, \p var and the affine + expression and the denominator are the same as in Example 6, while + the resulting grid is similar but translated 3 integers to the + left (all the pairs \f$(x, y)\f$ + where \f$x\f$ is -3 plus an integer multiple of 4 and + \f$y\f$ is an integer multiple of 2).. + Moreover, if the affine transformation for \p x is \f$x+y\f$ + \code + Linear_Expression expr = x + y; + \endcode + the resulting grid is a similar grid to the result in Example 6, + only the grid is slanted along \f$x=-y\f$. + Instead, if we do not use an invertible transformation for the same + variable \p x, for example, the affine expression \f$y\f$: + \code + Linear_Expression expr = y; + \endcode + the resulting grid is every fourth line parallel to the \f$x\f$ + axis. + + \par Example 9 + For this example we also use the variables: + \code + Variable z(2); + Variable w(3); + \endcode + The following code shows the use of the function + <CODE>remove_space_dimensions</CODE>: + \code + Grid_Generator_System gs; + gs.insert(grid_point(3*x + y +0*z + 2*w)); + Grid gr(gs); + Variables_Set vars; + vars.insert(y); + vars.insert(z); + gr.remove_space_dimensions(vars); + \endcode + The starting grid is the singleton set + \f$\bigl\{ (3, 1, 0, 2)^\transpose \bigr\} \sseq \Rset^4\f$, while + the resulting grid is + \f$\bigl\{ (3, 2)^\transpose \bigr\} \sseq \Rset^2\f$. + Be careful when removing space dimensions <EM>incrementally</EM>: + since dimensions are automatically renamed after each application + of the <CODE>remove_space_dimensions</CODE> operator, unexpected + results can be obtained. + For instance, by using the following code we would obtain + a different result: + \code + set<Variable> vars1; + vars1.insert(y); + gr.remove_space_dimensions(vars1); + set<Variable> vars2; + vars2.insert(z); + gr.remove_space_dimensions(vars2); + \endcode + In this case, the result is the grid + \f$\bigl\{(3, 0)^\transpose \bigr\} \sseq \Rset^2\f$: + when removing the set of dimensions \p vars2 + we are actually removing variable \f$w\f$ of the original grid. + For the same reason, the operator \p remove_space_dimensions + is not idempotent: removing twice the same non-empty set of dimensions + is never the same as removing them just once. +*/ + +class Parma_Polyhedra_Library::Grid { +public: + //! The numeric type of coefficients. + typedef Coefficient coefficient_type; + + //! Returns the maximum space dimension all kinds of Grid can handle. + static dimension_type max_space_dimension(); + + /*! \brief + Returns true indicating that this domain has methods that + can recycle congruences. + */ + static bool can_recycle_congruence_systems(); + + /*! \brief + Returns true indicating that this domain has methods that + can recycle constraints. + */ + static bool can_recycle_constraint_systems(); + + //! Builds a grid having the specified properties. + /*! + \param num_dimensions + The number of dimensions of the vector space enclosing the grid; + + \param kind + Specifies whether the universe or the empty grid has to be built. + + \exception std::length_error + Thrown if \p num_dimensions exceeds the maximum allowed space + dimension. + */ + explicit Grid(dimension_type num_dimensions = 0, + Degenerate_Element kind = UNIVERSE); + + //! Builds a grid, copying a system of congruences. + /*! + The grid inherits the space dimension of the congruence system. + + \param cgs + The system of congruences defining the grid. + + \exception std::length_error + Thrown if \p num_dimensions exceeds the maximum allowed space + dimension. + */ + explicit Grid(const Congruence_System& cgs); + + //! Builds a grid, recycling a system of congruences. + /*! + The grid inherits the space dimension of the congruence system. + + \param cgs + The system of congruences defining the grid. Its data-structures + may be recycled to build the grid. + + \param dummy + A dummy tag to syntactically differentiate this one + from the other constructors. + + \exception std::length_error + Thrown if \p num_dimensions exceeds the maximum allowed space + dimension. + */ + Grid(Congruence_System& cgs, Recycle_Input dummy); + + //! Builds a grid, copying a system of constraints. + /*! + The grid inherits the space dimension of the constraint system. + + \param cs + The system of constraints defining the grid. + + \exception std::invalid_argument + Thrown if the constraint system \p cs contains inequality constraints. + + \exception std::length_error + Thrown if \p num_dimensions exceeds the maximum allowed space + dimension. + */ + explicit Grid(const Constraint_System& cs); + + //! Builds a grid, recycling a system of constraints. + /*! + The grid inherits the space dimension of the constraint system. + + \param cs + The system of constraints defining the grid. Its data-structures + may be recycled to build the grid. + + \param dummy + A dummy tag to syntactically differentiate this one + from the other constructors. + + \exception std::invalid_argument + Thrown if the constraint system \p cs contains inequality constraints. + + \exception std::length_error + Thrown if \p num_dimensions exceeds the maximum allowed space + dimension. + */ + Grid(Constraint_System& cs, Recycle_Input dummy); + + //! Builds a grid, copying a system of grid generators. + /*! + The grid inherits the space dimension of the generator system. + + \param const_gs + The system of generators defining the grid. + + \exception std::invalid_argument + Thrown if the system of generators is not empty but has no points. + + \exception std::length_error + Thrown if \p num_dimensions exceeds the maximum allowed space + dimension. + */ + explicit Grid(const Grid_Generator_System& const_gs); + + //! Builds a grid, recycling a system of grid generators. + /*! + The grid inherits the space dimension of the generator system. + + \param gs + The system of generators defining the grid. Its data-structures + may be recycled to build the grid. + + \param dummy + A dummy tag to syntactically differentiate this one + from the other constructors. + + \exception std::invalid_argument + Thrown if the system of generators is not empty but has no points. + + \exception std::length_error + Thrown if \p num_dimensions exceeds the maximum allowed space dimension. + */ + Grid(Grid_Generator_System& gs, Recycle_Input dummy); + + //! Builds a grid out of a box. + /*! + The grid inherits the space dimension of the box. + The built grid is the most precise grid that includes the box. + + \param box + The box representing the grid to be built. + + \param complexity + This argument is ignored as the algorithm used has + polynomial complexity. + + \exception std::length_error + Thrown if the space dimension of \p box exceeds the maximum + allowed space dimension. + */ + template <typename Interval> + explicit Grid(const Box<Interval>& box, + Complexity_Class complexity = ANY_COMPLEXITY); + + //! Builds a grid out of a bounded-difference shape. + /*! + The grid inherits the space dimension of the BDS. + The built grid is the most precise grid that includes the BDS. + + \param bd + The BDS representing the grid to be built. + + \param complexity + This argument is ignored as the algorithm used has + polynomial complexity. + + \exception std::length_error + Thrown if the space dimension of \p bd exceeds the maximum + allowed space dimension. + */ + template <typename U> + explicit Grid(const BD_Shape<U>& bd, + Complexity_Class complexity = ANY_COMPLEXITY); + + //! Builds a grid out of an octagonal shape. + /*! + The grid inherits the space dimension of the octagonal shape. + The built grid is the most precise grid that includes the octagonal shape. + + \param os + The octagonal shape representing the grid to be built. + + \param complexity + This argument is ignored as the algorithm used has + polynomial complexity. + + \exception std::length_error + Thrown if the space dimension of \p os exceeds the maximum + allowed space dimension. + */ + template <typename U> + explicit Grid(const Octagonal_Shape<U>& os, + Complexity_Class complexity = ANY_COMPLEXITY); + + /*! \brief + Builds a grid from a polyhedron using algorithms whose complexity + does not exceed the one specified by \p complexity. + If \p complexity is \p ANY_COMPLEXITY, then the grid built is the + smallest one containing \p ph. + + The grid inherits the space dimension of polyhedron. + + \param ph + The polyhedron. + + \param complexity + The complexity class. + + \exception std::length_error + Thrown if \p num_dimensions exceeds the maximum allowed space + dimension. + */ + explicit Grid(const Polyhedron& ph, + Complexity_Class complexity = ANY_COMPLEXITY); + + //! Ordinary copy constructor. + /*! + The complexity argument is ignored. + */ + Grid(const Grid& y, + Complexity_Class complexity = ANY_COMPLEXITY); + + /*! \brief + The assignment operator. (\p *this and \p y can be + dimension-incompatible.) + */ + Grid& operator=(const Grid& y); + + //! \name Member Functions that Do Not Modify the Grid + //@{ + + //! Returns the dimension of the vector space enclosing \p *this. + dimension_type space_dimension() const; + + /*! \brief + Returns \f$0\f$, if \p *this is empty; otherwise, returns + the \ref Grid_Affine_Dimension "affine dimension" of \p *this. + */ + dimension_type affine_dimension() const; + + /*! \brief + Returns a system of equality constraints satisfied by \p *this + with the same affine dimension as \p *this. + */ + Constraint_System constraints() const; + + /*! \brief + Returns a minimal system of equality constraints satisfied by + \p *this with the same affine dimension as \p *this. + */ + Constraint_System minimized_constraints() const; + + //! Returns the system of congruences. + const Congruence_System& congruences() const; + + //! Returns the system of congruences in minimal form. + const Congruence_System& minimized_congruences() const; + + //! Returns the system of generators. + const Grid_Generator_System& grid_generators() const; + + //! Returns the minimized system of generators. + const Grid_Generator_System& minimized_grid_generators() const; + + //! Returns the relations holding between \p *this and \p cg. + /* + \exception std::invalid_argument + Thrown if \p *this and congruence \p cg are dimension-incompatible. + */ + // FIXME: Poly_Con_Relation seems to encode exactly what we want + // here. We must find a new name for that class. Temporarily, + // we keep using it without changing the name. + Poly_Con_Relation relation_with(const Congruence& cg) const; + + //! Returns the relations holding between \p *this and \p g. + /* + \exception std::invalid_argument + Thrown if \p *this and generator \p g are dimension-incompatible. + */ + // FIXME: see the comment for Poly_Con_Relation above. + Poly_Gen_Relation + relation_with(const Grid_Generator& g) const; + + //! Returns the relations holding between \p *this and \p g. + /* + \exception std::invalid_argument + Thrown if \p *this and generator \p g are dimension-incompatible. + */ + // FIXME: see the comment for Poly_Con_Relation above. + Poly_Gen_Relation + relation_with(const Generator& g) const; + + //! Returns the relations holding between \p *this and \p c. + /* + \exception std::invalid_argument + Thrown if \p *this and constraint \p c are dimension-incompatible. + */ + // FIXME: Poly_Con_Relation seems to encode exactly what we want + // here. We must find a new name for that class. Temporarily, + // we keep using it without changing the name. + Poly_Con_Relation relation_with(const Constraint& c) const; + + //! Returns \c true if and only if \p *this is an empty grid. + bool is_empty() const; + + //! Returns \c true if and only if \p *this is a universe grid. + bool is_universe() const; + + /*! \brief + Returns <CODE>true</CODE> if and only if \p *this is a + topologically closed subset of the vector space. + + A grid is always topologically closed. + */ + bool is_topologically_closed() const; + + /*! \brief + Returns <CODE>true</CODE> if and only if \p *this and \p y are + disjoint. + + \exception std::invalid_argument + Thrown if \p x and \p y are dimension-incompatible. + */ + bool is_disjoint_from(const Grid& y) const; + + //! Returns <CODE>true</CODE> if and only if \p *this is discrete. + /*! + A grid is discrete if it can be defined by a generator system which + contains only points and parameters. This includes the empty grid + and any grid in dimension zero. + */ + bool is_discrete() const; + + //! Returns <CODE>true</CODE> if and only if \p *this is bounded. + bool is_bounded() const; + + /*! \brief + Returns <CODE>true</CODE> if and only if \p *this + contains at least one integer point. + */ + bool contains_integer_point() const; + + /*! \brief + Returns <CODE>true</CODE> if and only if \p var is constrained in + \p *this. + + \exception std::invalid_argument + Thrown if \p var is not a space dimension of \p *this. + */ + bool constrains(Variable var) const; + + //! Returns <CODE>true</CODE> if and only if \p expr is bounded in \p *this. + /*! + This method is the same as bounds_from_below. + + \exception std::invalid_argument + Thrown if \p expr and \p *this are dimension-incompatible. + */ + bool bounds_from_above(const Linear_Expression& expr) const; + + //! Returns <CODE>true</CODE> if and only if \p expr is bounded in \p *this. + /*! + This method is the same as bounds_from_above. + + \exception std::invalid_argument + Thrown if \p expr and \p *this are dimension-incompatible. + */ + bool bounds_from_below(const Linear_Expression& expr) const; + + /*! \brief + Returns <CODE>true</CODE> if and only if \p *this is not empty and + \p expr is bounded from above in \p *this, in which case the + supremum value is computed. + + \param expr + The linear expression to be maximized subject to \p *this; + + \param sup_n + The numerator of the supremum value; + + \param sup_d + The denominator of the supremum value; + + \param maximum + <CODE>true</CODE> if the supremum value can be reached in \p this. + Always <CODE>true</CODE> when \p this bounds \p expr. Present for + interface compatibility with class Polyhedron, where closure + points can result in a value of false. + + \exception std::invalid_argument + Thrown if \p expr and \p *this are dimension-incompatible. + + If \p *this is empty or \p expr is not bounded by \p *this, + <CODE>false</CODE> is returned and \p sup_n, \p sup_d and \p + maximum are left untouched. + */ + bool maximize(const Linear_Expression& expr, + Coefficient& sup_n, Coefficient& sup_d, bool& maximum) const; + + /*! \brief + Returns <CODE>true</CODE> if and only if \p *this is not empty and + \p expr is bounded from above in \p *this, in which case the + supremum value and a point where \p expr reaches it are computed. + + \param expr + The linear expression to be maximized subject to \p *this; + + \param sup_n + The numerator of the supremum value; + + \param sup_d + The denominator of the supremum value; + + \param maximum + <CODE>true</CODE> if the supremum value can be reached in \p this. + Always <CODE>true</CODE> when \p this bounds \p expr. Present for + interface compatibility with class Polyhedron, where closure + points can result in a value of false; + + \param point + When maximization succeeds, will be assigned a point where \p expr + reaches its supremum value. + + \exception std::invalid_argument + Thrown if \p expr and \p *this are dimension-incompatible. + + If \p *this is empty or \p expr is not bounded by \p *this, + <CODE>false</CODE> is returned and \p sup_n, \p sup_d, \p maximum + and \p point are left untouched. + */ + bool maximize(const Linear_Expression& expr, + Coefficient& sup_n, Coefficient& sup_d, bool& maximum, + Generator& point) const; + + /*! \brief + Returns <CODE>true</CODE> if and only if \p *this is not empty and + \p expr is bounded from below in \p *this, in which case the + infimum value is computed. + + \param expr + The linear expression to be minimized subject to \p *this; + + \param inf_n + The numerator of the infimum value; + + \param inf_d + The denominator of the infimum value; + + \param minimum + <CODE>true</CODE> if the is the infimum value can be reached in \p + this. Always <CODE>true</CODE> when \p this bounds \p expr. + Present for interface compatibility with class Polyhedron, where + closure points can result in a value of false. + + \exception std::invalid_argument + Thrown if \p expr and \p *this are dimension-incompatible. + + If \p *this is empty or \p expr is not bounded from below, + <CODE>false</CODE> is returned and \p inf_n, \p inf_d + and \p minimum are left untouched. + */ + bool minimize(const Linear_Expression& expr, + Coefficient& inf_n, Coefficient& inf_d, bool& minimum) const; + + /*! \brief + Returns <CODE>true</CODE> if and only if \p *this is not empty and + \p expr is bounded from below in \p *this, in which case the + infimum value and a point where \p expr reaches it are computed. + + \param expr + The linear expression to be minimized subject to \p *this; + + \param inf_n + The numerator of the infimum value; + + \param inf_d + The denominator of the infimum value; + + \param minimum + <CODE>true</CODE> if the is the infimum value can be reached in \p + this. Always <CODE>true</CODE> when \p this bounds \p expr. + Present for interface compatibility with class Polyhedron, where + closure points can result in a value of false; + + \param point + When minimization succeeds, will be assigned a point where \p expr + reaches its infimum value. + + \exception std::invalid_argument + Thrown if \p expr and \p *this are dimension-incompatible. + + If \p *this is empty or \p expr is not bounded from below, + <CODE>false</CODE> is returned and \p inf_n, \p inf_d, \p minimum + and \p point are left untouched. + */ + bool minimize(const Linear_Expression& expr, + Coefficient& inf_n, Coefficient& inf_d, bool& minimum, + Generator& point) const; + + /*! \brief + Returns <CODE>true</CODE> if and only if \p *this is not empty and + \ref Grid_Frequency "frequency" for \p *this with respect to \p expr + is defined, in which case the frequency and the value for \p expr + that is closest to zero are computed. + + \param expr + The linear expression for which the frequency is needed; + + \param freq_n + The numerator of the maximum frequency of \p expr; + + \param freq_d + The denominator of the maximum frequency of \p expr; + + \param val_n + The numerator of them value of \p expr at a point in the grid + that is closest to zero; + + \param val_d + The denominator of a value of \p expr at a point in the grid + that is closest to zero; + + \exception std::invalid_argument + Thrown if \p expr and \p *this are dimension-incompatible. + + If \p *this is empty or frequency is undefined with respect to \p expr, + then <CODE>false</CODE> is returned and \p freq_n, \p freq_d, + \p val_n and \p val_d are left untouched. + */ + bool frequency(const Linear_Expression& expr, + Coefficient& freq_n, Coefficient& freq_d, + Coefficient& val_n, Coefficient& val_d) const; + + //! Returns <CODE>true</CODE> if and only if \p *this contains \p y. + /*! + \exception std::invalid_argument + Thrown if \p *this and \p y are dimension-incompatible. + */ + bool contains(const Grid& y) const; + + /*! \brief + Returns <CODE>true</CODE> if and only if \p *this strictly + contains \p y. + + \exception std::invalid_argument + Thrown if \p *this and \p y are dimension-incompatible. + */ + bool strictly_contains(const Grid& y) const; + + //! Checks if all the invariants are satisfied. + /*! + \return + <CODE>true</CODE> if and only if \p *this satisfies all the + invariants and either \p check_not_empty is <CODE>false</CODE> or + \p *this is not empty. + + \param check_not_empty + <CODE>true</CODE> if and only if, in addition to checking the + invariants, \p *this must be checked to be not empty. + + The check is performed so as to intrude as little as possible. If + the library has been compiled with run-time assertions enabled, + error messages are written on <CODE>std::cerr</CODE> in case + invariants are violated. This is useful for the purpose of + debugging the library. + */ + bool OK(bool check_not_empty = false) const; + + //@} // Member Functions that Do Not Modify the Grid + + //! \name Space Dimension Preserving Member Functions that May Modify the Grid + //@{ + + //! Adds a copy of congruence \p cg to \p *this. + /*! + \exception std::invalid_argument + Thrown if \p *this and congruence \p cg are + dimension-incompatible. + */ + void add_congruence(const Congruence& cg); + + /*! \brief + Adds a copy of grid generator \p g to the system of generators of + \p *this. + + \exception std::invalid_argument + Thrown if \p *this and generator \p g are dimension-incompatible, + or if \p *this is an empty grid and \p g is not a point. + */ + void add_grid_generator(const Grid_Generator& g); + + //! Adds a copy of each congruence in \p cgs to \p *this. + /*! + \param cgs + Contains the congruences that will be added to the system of + congruences of \p *this. + + \exception std::invalid_argument + Thrown if \p *this and \p cgs are dimension-incompatible. + */ + void add_congruences(const Congruence_System& cgs); + + //! Adds the congruences in \p cgs to *this. + /*! + \param cgs + The congruence system to be added to \p *this. The congruences in + \p cgs may be recycled. + + \exception std::invalid_argument + Thrown if \p *this and \p cgs are dimension-incompatible. + + \warning + The only assumption that can be made about \p cgs upon successful + or exceptional return is that it can be safely destroyed. + */ + void add_recycled_congruences(Congruence_System& cgs); + + /*! \brief + Adds to \p *this a congruence equivalent to constraint \p c. + + \param c + The constraint to be added. + + \exception std::invalid_argument + Thrown if \p *this and \p c are dimension-incompatible + or if constraint \p c is not optimally supported by the grid domain. + */ + void add_constraint(const Constraint& c); + + /*! \brief + Adds to \p *this congruences equivalent to the constraints in \p cs. + + \param cs + The constraints to be added. + + \exception std::invalid_argument + Thrown if \p *this and \p cs are dimension-incompatible + or if \p cs contains a constraint whcih is not optimally supported + by the grid domain. + */ + void add_constraints(const Constraint_System& cs); + + /*! \brief + Adds to \p *this congruences equivalent to the constraints in \p cs. + + \param cs + The constraints to be added. They may be recycled. + + \exception std::invalid_argument + Thrown if \p *this and \p cs are dimension-incompatible + or if \p cs contains a constraint whcih is not optimally supported + by the grid domain. + + \warning + The only assumption that can be made about \p cs upon successful + or exceptional return is that it can be safely destroyed. + */ + void add_recycled_constraints(Constraint_System& cs); + + //! Uses a copy of the congruence \p cg to refine \p *this. + /*! + \param cg + The congruence used. + + \exception std::invalid_argument + Thrown if \p *this and congruence \p cg are dimension-incompatible. + */ + void refine_with_congruence(const Congruence& cg); + + //! Uses a copy of the congruences in \p cgs to refine \p *this. + /*! + \param cgs + The congruences used. + + \exception std::invalid_argument + Thrown if \p *this and \p cgs are dimension-incompatible. + */ + void refine_with_congruences(const Congruence_System& cgs); + + //! Uses a copy of the constraint \p c to refine \p *this. + /*! + + \param c + The constraint used. If it is not an equality, it will be ignored + + \exception std::invalid_argument + Thrown if \p *this and \p c are dimension-incompatible. + */ + void refine_with_constraint(const Constraint& c); + + //! Uses a copy of the constraints in \p cs to refine \p *this. + /*! + \param cs + The constraints used. Constraints that are not equalities are ignored. + + \exception std::invalid_argument + Thrown if \p *this and \p cs are dimension-incompatible. + */ + void refine_with_constraints(const Constraint_System& cs); + + /*! \brief + Adds a copy of the generators in \p gs to the system of generators + of \p *this. + + \param gs + Contains the generators that will be added to the system of + generators of \p *this. + + \exception std::invalid_argument + Thrown if \p *this and \p gs are dimension-incompatible, or if + \p *this is empty and the system of generators \p gs is not empty, + but has no points. + */ + void add_grid_generators(const Grid_Generator_System& gs); + + /*! \brief + Adds the generators in \p gs to the system of generators of \p + *this. + + \param gs + The generator system to be added to \p *this. The generators in + \p gs may be recycled. + + \exception std::invalid_argument + Thrown if \p *this and \p gs are dimension-incompatible. + + \warning + The only assumption that can be made about \p gs upon successful + or exceptional return is that it can be safely destroyed. + */ + void add_recycled_grid_generators(Grid_Generator_System& gs); + + /*! \brief + Computes the \ref Cylindrification "cylindrification" of \p *this with + respect to space dimension \p var, assigning the result to \p *this. + + \param var + The space dimension that will be unconstrained. + + \exception std::invalid_argument + Thrown if \p var is not a space dimension of \p *this. + */ + void unconstrain(Variable var); + + /*! \brief + Computes the \ref Cylindrification "cylindrification" of \p *this with + respect to the set of space dimensions \p vars, + assigning the result to \p *this. + + \param vars + The set of space dimension that will be unconstrained. + + \exception std::invalid_argument + Thrown if \p *this is dimension-incompatible with one of the + Variable objects contained in \p vars. + */ + void unconstrain(const Variables_Set& vars); + + /*! \brief + Assigns to \p *this the intersection of \p *this and \p y. + + \exception std::invalid_argument + Thrown if \p *this and \p y are dimension-incompatible. + */ + void intersection_assign(const Grid& y); + + /*! \brief + Assigns to \p *this the least upper bound of \p *this and \p y. + + \exception std::invalid_argument + Thrown if \p *this and \p y are dimension-incompatible. + */ + void upper_bound_assign(const Grid& y); + + /*! \brief + If the upper bound of \p *this and \p y is exact it is assigned to \p + *this and <CODE>true</CODE> is returned, otherwise + <CODE>false</CODE> is returned. + + \exception std::invalid_argument + Thrown if \p *this and \p y are dimension-incompatible. + */ + bool upper_bound_assign_if_exact(const Grid& y); + + /*! \brief + Assigns to \p *this the \ref Convex_Polyhedral_Difference "grid-difference" + of \p *this and \p y. + + The grid difference between grids x and y is the smallest grid + containing all the points from x and y that are only in x. + + \exception std::invalid_argument + Thrown if \p *this and \p y are dimension-incompatible. + */ + void difference_assign(const Grid& y); + + /*! \brief + Assigns to \p *this a \ref Meet_Preserving_Simplification + "meet-preserving simplification" of \p *this with respect to \p y. + If \c false is returned, then the intersection is empty. + + \exception std::invalid_argument + Thrown if \p *this and \p y are topology-incompatible or + dimension-incompatible. + */ + bool simplify_using_context_assign(const Grid& y); + + /*! \brief + Assigns to \p *this the \ref Grid_Affine_Transformation + "affine image" of \p + *this under the function mapping variable \p var to the affine + expression specified by \p expr and \p denominator. + + \param var + The variable to which the affine expression is assigned; + + \param expr + The numerator of the affine expression; + + \param denominator + The denominator of the affine expression (optional argument with + default value 1). + + \exception std::invalid_argument + Thrown if \p denominator is zero or if \p expr and \p *this are + dimension-incompatible or if \p var is not a space dimension of + \p *this. + + \if Include_Implementation_Details + + When considering the generators of a grid, the + affine transformation + \f[ + \frac{\sum_{i=0}^{n-1} a_i x_i + b}{\mathrm{denominator}} + \f] + is assigned to \p var where \p expr is + \f$\sum_{i=0}^{n-1} a_i x_i + b\f$ + (\f$b\f$ is the inhomogeneous term). + + If congruences are up-to-date, it uses the specialized function + affine_preimage() (for the system of congruences) + and inverse transformation to reach the same result. + To obtain the inverse transformation we use the following observation. + + Observation: + -# The affine transformation is invertible if the coefficient + of \p var in this transformation (i.e., \f$a_\mathrm{var}\f$) + is different from zero. + -# If the transformation is invertible, then we can write + \f[ + \mathrm{denominator} * {x'}_\mathrm{var} + = \sum_{i = 0}^{n - 1} a_i x_i + b + = a_\mathrm{var} x_\mathrm{var} + + \sum_{i \neq var} a_i x_i + b, + \f] + so that the inverse transformation is + \f[ + a_\mathrm{var} x_\mathrm{var} + = \mathrm{denominator} * {x'}_\mathrm{var} + - \sum_{i \neq j} a_i x_i - b. + \f] + + Then, if the transformation is invertible, all the entities that + were up-to-date remain up-to-date. Otherwise only generators remain + up-to-date. + + \endif + */ + void affine_image(Variable var, + const Linear_Expression& expr, + Coefficient_traits::const_reference denominator + = Coefficient_one()); + + /*! \brief + Assigns to \p *this the \ref Grid_Affine_Transformation + "affine preimage" of + \p *this under the function mapping variable \p var to the affine + expression specified by \p expr and \p denominator. + + \param var + The variable to which the affine expression is substituted; + + \param expr + The numerator of the affine expression; + + \param denominator + The denominator of the affine expression (optional argument with + default value 1). + + \exception std::invalid_argument + Thrown if \p denominator is zero or if \p expr and \p *this are + dimension-incompatible or if \p var is not a space dimension of \p *this. + + \if Include_Implementation_Details + + When considering congruences of a grid, the affine transformation + \f[ + \frac{\sum_{i=0}^{n-1} a_i x_i + b}{denominator}, + \f] + is assigned to \p var where \p expr is + \f$\sum_{i=0}^{n-1} a_i x_i + b\f$ + (\f$b\f$ is the inhomogeneous term). + + If generators are up-to-date, then the specialized function + affine_image() is used (for the system of generators) + and inverse transformation to reach the same result. + To obtain the inverse transformation, we use the following observation. + + Observation: + -# The affine transformation is invertible if the coefficient + of \p var in this transformation (i.e. \f$a_\mathrm{var}\f$) + is different from zero. + -# If the transformation is invertible, then we can write + \f[ + \mathrm{denominator} * {x'}_\mathrm{var} + = \sum_{i = 0}^{n - 1} a_i x_i + b + = a_\mathrm{var} x_\mathrm{var} + + \sum_{i \neq \mathrm{var}} a_i x_i + b, + \f], + the inverse transformation is + \f[ + a_\mathrm{var} x_\mathrm{var} + = \mathrm{denominator} * {x'}_\mathrm{var} + - \sum_{i \neq j} a_i x_i - b. + \f]. + + Then, if the transformation is invertible, all the entities that + were up-to-date remain up-to-date. Otherwise only congruences remain + up-to-date. + + \endif + */ + void affine_preimage(Variable var, + const Linear_Expression& expr, + Coefficient_traits::const_reference denominator + = Coefficient_one()); + + /*! \brief + Assigns to \p *this the image of \p *this with respect to + the \ref Grid_Generalized_Image "generalized affine relation" + \f$\mathrm{var}' = \frac{\mathrm{expr}}{\mathrm{denominator}} + \pmod{\mathrm{modulus}}\f$. + + \param var + The left hand side variable of the generalized affine relation; + + \param relsym + The relation symbol where EQUAL is the symbol for a congruence + relation; + + \param expr + The numerator of the right hand side affine expression; + + \param denominator + The denominator of the right hand side affine expression. + Optional argument with an automatic value of one; + + \param modulus + The modulus of the congruence lhs %= rhs. A modulus of zero + indicates lhs == rhs. Optional argument with an automatic value + of zero. + + \exception std::invalid_argument + Thrown if \p denominator is zero or if \p expr and \p *this are + dimension-incompatible or if \p var is not a space dimension of \p + *this. + */ + void + generalized_affine_image(Variable var, + Relation_Symbol relsym, + const Linear_Expression& expr, + Coefficient_traits::const_reference denominator + = Coefficient_one(), + Coefficient_traits::const_reference modulus + = Coefficient_zero()); + + /*! \brief + Assigns to \p *this the preimage of \p *this with respect to the + \ref Grid_Generalized_Image "generalized affine relation" + \f$\mathrm{var}' = \frac{\mathrm{expr}}{\mathrm{denominator}} + \pmod{\mathrm{modulus}}\f$. + + \param var + The left hand side variable of the generalized affine relation; + + \param relsym + The relation symbol where EQUAL is the symbol for a congruence + relation; + + \param expr + The numerator of the right hand side affine expression; + + \param denominator + The denominator of the right hand side affine expression. + Optional argument with an automatic value of one; + + \param modulus + The modulus of the congruence lhs %= rhs. A modulus of zero + indicates lhs == rhs. Optional argument with an automatic value + of zero. + + \exception std::invalid_argument + Thrown if \p denominator is zero or if \p expr and \p *this are + dimension-incompatible or if \p var is not a space dimension of \p + *this. + */ + void + generalized_affine_preimage(Variable var, + Relation_Symbol relsym, + const Linear_Expression& expr, + Coefficient_traits::const_reference denominator + = Coefficient_one(), + Coefficient_traits::const_reference modulus + = Coefficient_zero()); + + /*! \brief + Assigns to \p *this the image of \p *this with respect to + the \ref Grid_Generalized_Image "generalized affine relation" + \f$\mathrm{lhs}' = \mathrm{rhs} \pmod{\mathrm{modulus}}\f$. + + \param lhs + The left hand side affine expression. + + \param relsym + The relation symbol where EQUAL is the symbol for a congruence + relation; + + \param rhs + The right hand side affine expression. + + \param modulus + The modulus of the congruence lhs %= rhs. A modulus of zero + indicates lhs == rhs. Optional argument with an automatic value + of zero. + + \exception std::invalid_argument + Thrown if \p *this is dimension-incompatible with \p lhs or \p + rhs. + */ + void + generalized_affine_image(const Linear_Expression& lhs, + Relation_Symbol relsym, + const Linear_Expression& rhs, + Coefficient_traits::const_reference modulus + = Coefficient_zero()); + + /*! \brief + Assigns to \p *this the preimage of \p *this with respect to the + \ref Grid_Generalized_Image "generalized affine relation" + \f$\mathrm{lhs}' = \mathrm{rhs} \pmod{\mathrm{modulus}}\f$. + + \param lhs + The left hand side affine expression; + + \param relsym + The relation symbol where EQUAL is the symbol for a congruence + relation; + + \param rhs + The right hand side affine expression; + + \param modulus + The modulus of the congruence lhs %= rhs. A modulus of zero + indicates lhs == rhs. Optional argument with an automatic value + of zero. + + \exception std::invalid_argument + Thrown if \p *this is dimension-incompatible with \p lhs or \p + rhs. + */ + void + generalized_affine_preimage(const Linear_Expression& lhs, + Relation_Symbol relsym, + const Linear_Expression& rhs, + Coefficient_traits::const_reference modulus + = Coefficient_zero()); + + /*! + \brief + Assigns to \p *this the image of \p *this with respect to the + \ref Single_Update_Bounded_Affine_Relations "bounded affine relation" + \f$\frac{\mathrm{lb\_expr}}{\mathrm{denominator}} + \leq \mathrm{var}' + \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}\f$. + + \param var + The variable updated by the affine relation; + + \param lb_expr + The numerator of the lower bounding affine expression; + + \param ub_expr + The numerator of the upper bounding affine expression; + + \param denominator + The (common) denominator for the lower and upper bounding + affine expressions (optional argument with default value 1). + + \exception std::invalid_argument + Thrown if \p denominator is zero or if \p lb_expr (resp., \p ub_expr) + and \p *this are dimension-incompatible or if \p var is not a space + dimension of \p *this. + */ + void bounded_affine_image(Variable var, + const Linear_Expression& lb_expr, + const Linear_Expression& ub_expr, + Coefficient_traits::const_reference denominator + = Coefficient_one()); + + /*! + \brief + Assigns to \p *this the preimage of \p *this with respect to the + \ref Single_Update_Bounded_Affine_Relations "bounded affine relation" + \f$\frac{\mathrm{lb\_expr}}{\mathrm{denominator}} + \leq \mathrm{var}' + \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}\f$. + + \param var + The variable updated by the affine relation; + + \param lb_expr + The numerator of the lower bounding affine expression; + + \param ub_expr + The numerator of the upper bounding affine expression; + + \param denominator + The (common) denominator for the lower and upper bounding + affine expressions (optional argument with default value 1). + + \exception std::invalid_argument + Thrown if \p denominator is zero or if \p lb_expr (resp., \p ub_expr) + and \p *this are dimension-incompatible or if \p var is not a space + dimension of \p *this. + */ + void bounded_affine_preimage(Variable var, + const Linear_Expression& lb_expr, + const Linear_Expression& ub_expr, + Coefficient_traits::const_reference denominator + = Coefficient_one()); + + /*! \brief + Assigns to \p *this the result of computing the \ref Grid_Time_Elapse + "time-elapse" between \p *this and \p y. + + \exception std::invalid_argument + Thrown if \p *this and \p y are dimension-incompatible. + */ + void time_elapse_assign(const Grid& y); + + /*! \brief + \ref Wrapping_Operator "Wraps" the specified dimensions of the + vector space. + + \param vars + The set of Variable objects corresponding to the space dimensions + to be wrapped. + + \param w + The width of the bounded integer type corresponding to + all the dimensions to be wrapped. + + \param r + The representation of the bounded integer type corresponding to + all the dimensions to be wrapped. + + \param o + The overflow behavior of the bounded integer type corresponding to + all the dimensions to be wrapped. + + \param pcs + Possibly null pointer to a constraint system. + This argument is for compatibility with wrap_assign() + for the other domains and only checked for dimension-compatibility. + + \param complexity_threshold + A precision parameter of the \ref Wrapping_Operator "wrapping operator". + This argument is for compatibility with wrap_assign() + for the other domains and is ignored. + + \param wrap_individually + <CODE>true</CODE> if the dimensions should be wrapped individually. + As wrapping dimensions collectively does not improve the precision, + this argument is ignored. + + \exception std::invalid_argument + Thrown if \p *this is dimension-incompatible with one of the + Variable objects contained in \p vars or with <CODE>*pcs</CODE>. + + \warning + It is assumed that variables in \p Vars represent integers. Thus, + where the extra cost is negligible, the integrality of these + variables is enforced; possibly causing a non-integral grid to + become empty. + */ + void wrap_assign(const Variables_Set& vars, + Bounded_Integer_Type_Width w, + Bounded_Integer_Type_Representation r, + Bounded_Integer_Type_Overflow o, + const Constraint_System* pcs = 0, + unsigned complexity_threshold = 16, + bool wrap_individually = true); + + /*! \brief + Possibly tightens \p *this by dropping all points with non-integer + coordinates. + + \param complexity + This argument is ignored as the algorithm used has polynomial + complexity. + */ + void drop_some_non_integer_points(Complexity_Class complexity + = ANY_COMPLEXITY); + + /*! \brief + Possibly tightens \p *this by dropping all points with non-integer + coordinates for the space dimensions corresponding to \p vars. + + \param vars + Points with non-integer coordinates for these variables/space-dimensions + can be discarded. + + \param complexity + This argument is ignored as the algorithm used has polynomial + complexity. + */ + void drop_some_non_integer_points(const Variables_Set& vars, + Complexity_Class complexity + = ANY_COMPLEXITY); + + //! Assigns to \p *this its topological closure. + void topological_closure_assign(); + + /*! \brief + Assigns to \p *this the result of computing the \ref Grid_Widening + "Grid widening" between \p *this and \p y using congruence systems. + + \param y + A grid that <EM>must</EM> be contained in \p *this; + + \param tp + An optional pointer to an unsigned variable storing the number of + available tokens (to be used when applying the + \ref Grid_Widening_with_Tokens "widening with tokens" delay technique). + + \exception std::invalid_argument + Thrown if \p *this and \p y are dimension-incompatible. + */ + void congruence_widening_assign(const Grid& y, unsigned* tp = NULL); + + /*! \brief + Assigns to \p *this the result of computing the \ref Grid_Widening + "Grid widening" between \p *this and \p y using generator systems. + + \param y + A grid that <EM>must</EM> be contained in \p *this; + + \param tp + An optional pointer to an unsigned variable storing the number of + available tokens (to be used when applying the + \ref Grid_Widening_with_Tokens "widening with tokens" delay technique). + + \exception std::invalid_argument + Thrown if \p *this and \p y are dimension-incompatible. + */ + void generator_widening_assign(const Grid& y, unsigned* tp = NULL); + + /*! \brief + Assigns to \p *this the result of computing the \ref Grid_Widening + "Grid widening" between \p *this and \p y. + + This widening uses either the congruence or generator systems + depending on which of the systems describing x and y + are up to date and minimized. + + \param y + A grid that <EM>must</EM> be contained in \p *this; + + \param tp + An optional pointer to an unsigned variable storing the number of + available tokens (to be used when applying the + \ref Grid_Widening_with_Tokens "widening with tokens" delay technique). + + \exception std::invalid_argument + Thrown if \p *this and \p y are dimension-incompatible. + */ + void widening_assign(const Grid& y, unsigned* tp = NULL); + + /*! \brief + Improves the result of the congruence variant of + \ref Grid_Widening "Grid widening" computation by also enforcing + those congruences in \p cgs that are satisfied by all the points + of \p *this. + + \param y + A grid that <EM>must</EM> be contained in \p *this; + + \param cgs + The system of congruences used to improve the widened grid; + + \param tp + An optional pointer to an unsigned variable storing the number of + available tokens (to be used when applying the + \ref Grid_Widening_with_Tokens "widening with tokens" delay technique). + + \exception std::invalid_argument + Thrown if \p *this, \p y and \p cgs are dimension-incompatible. + */ + void limited_congruence_extrapolation_assign(const Grid& y, + const Congruence_System& cgs, + unsigned* tp = NULL); + + /*! \brief + Improves the result of the generator variant of the + \ref Grid_Widening "Grid widening" + computation by also enforcing those congruences in \p cgs that are + satisfied by all the points of \p *this. + + \param y + A grid that <EM>must</EM> be contained in \p *this; + + \param cgs + The system of congruences used to improve the widened grid; + + \param tp + An optional pointer to an unsigned variable storing the number of + available tokens (to be used when applying the + \ref Grid_Widening_with_Tokens "widening with tokens" delay technique). + + \exception std::invalid_argument + Thrown if \p *this, \p y and \p cgs are dimension-incompatible. + */ + void limited_generator_extrapolation_assign(const Grid& y, + const Congruence_System& cgs, + unsigned* tp = NULL); + + /*! \brief + Improves the result of the \ref Grid_Widening "Grid widening" + computation by also enforcing those congruences in \p cgs that are + satisfied by all the points of \p *this. + + \param y + A grid that <EM>must</EM> be contained in \p *this; + + \param cgs + The system of congruences used to improve the widened grid; + + \param tp + An optional pointer to an unsigned variable storing the number of + available tokens (to be used when applying the + \ref Grid_Widening_with_Tokens "widening with tokens" delay technique). + + \exception std::invalid_argument + Thrown if \p *this, \p y and \p cgs are dimension-incompatible. + */ + void limited_extrapolation_assign(const Grid& y, + const Congruence_System& cgs, + unsigned* tp = NULL); + + //@} // Space Dimension Preserving Member Functions that May Modify [...] + + //! \name Member Functions that May Modify the Dimension of the Vector Space + //@{ + + /*! \brief + \ref Adding_New_Dimensions_to_the_Vector_Space "Adds" + \p m new space dimensions and embeds the old grid in the new + vector space. + + \param m + The number of dimensions to add. + + \exception std::length_error + Thrown if adding \p m new space dimensions would cause the vector + space to exceed dimension <CODE>max_space_dimension()</CODE>. + + The new space dimensions will be those having the highest indexes + in the new grid, which is characterized by a system of congruences + in which the variables which are the new dimensions can have any + value. For instance, when starting from the grid \f$\cL \sseq + \Rset^2\f$ and adding a third space dimension, the result will be + the grid + \f[ + \bigl\{\, + (x, y, z)^\transpose \in \Rset^3 + \bigm| + (x, y)^\transpose \in \cL + \,\bigr\}. + \f] + */ + void add_space_dimensions_and_embed(dimension_type m); + + /*! \brief + \ref Adding_New_Dimensions_to_the_Vector_Space "Adds" + \p m new space dimensions to the grid and does not embed it + in the new vector space. + + \param m + The number of space dimensions to add. + + \exception std::length_error + Thrown if adding \p m new space dimensions would cause the + vector space to exceed dimension <CODE>max_space_dimension()</CODE>. + + The new space dimensions will be those having the highest indexes + in the new grid, which is characterized by a system of congruences + in which the variables running through the new dimensions are all + constrained to be equal to 0. For instance, when starting from + the grid \f$\cL \sseq \Rset^2\f$ and adding a third space + dimension, the result will be the grid + \f[ + \bigl\{\, + (x, y, 0)^\transpose \in \Rset^3 + \bigm| + (x, y)^\transpose \in \cL + \,\bigr\}. + \f] + */ + void add_space_dimensions_and_project(dimension_type m); + + /*! \brief + Assigns to \p *this the \ref Concatenating_Polyhedra "concatenation" of + \p *this and \p y, taken in this order. + + \exception std::length_error + Thrown if the concatenation would cause the vector space + to exceed dimension <CODE>max_space_dimension()</CODE>. + */ + void concatenate_assign(const Grid& y); + + //! Removes all the specified dimensions from the vector space. + /*! + \param vars + The set of Variable objects corresponding to the space dimensions + to be removed. + + \exception std::invalid_argument + Thrown if \p *this is dimension-incompatible with one of the + Variable objects contained in \p vars. + */ + void remove_space_dimensions(const Variables_Set& vars); + + /*! \brief + Removes the higher dimensions of the vector space so that the + resulting space will have \ref Removing_Dimensions_from_the_Vector_Space + "dimension \p new_dimension." + + \exception std::invalid_argument + Thrown if \p new_dimensions is greater than the space dimension of + \p *this. + */ + void remove_higher_space_dimensions(dimension_type new_dimension); + + /*! \brief + Remaps the dimensions of the vector space according to + a \ref Mapping_the_Dimensions_of_the_Vector_Space "partial function". + + If \p pfunc maps only some of the dimensions of \p *this then the + rest will be projected away. + + If the highest dimension mapped to by \p pfunc is higher than the + highest dimension in \p *this then the number of dimensions in \p + *this will be increased to the highest dimension mapped to by \p + pfunc. + + \param pfunc + The partial function specifying the destiny of each space + dimension. + + The template type parameter Partial_Function must provide + the following methods. + \code + bool has_empty_codomain() const + \endcode + returns <CODE>true</CODE> if and only if the represented partial + function has an empty codomain (i.e., it is always undefined). + The <CODE>has_empty_codomain()</CODE> method will always be called + before the methods below. However, if + <CODE>has_empty_codomain()</CODE> returns <CODE>true</CODE>, none + of the functions below will be called. + \code + dimension_type max_in_codomain() const + \endcode + returns the maximum value that belongs to the codomain of the + partial function. + The <CODE>max_in_codomain()</CODE> method is called at most once. + \code + bool maps(dimension_type i, dimension_type& j) const + \endcode + Let \f$f\f$ be the represented function and \f$k\f$ be the value + of \p i. If \f$f\f$ is defined in \f$k\f$, then \f$f(k)\f$ is + assigned to \p j and <CODE>true</CODE> is returned. If \f$f\f$ is + undefined in \f$k\f$, then <CODE>false</CODE> is returned. + This method is called at most \f$n\f$ times, where \f$n\f$ is the + dimension of the vector space enclosing the grid. + + The result is undefined if \p pfunc does not encode a partial + function with the properties described in the + \ref Mapping_the_Dimensions_of_the_Vector_Space "specification of the mapping operator". + */ + template <typename Partial_Function> + void map_space_dimensions(const Partial_Function& pfunc); + + //! Creates \p m copies of the space dimension corresponding to \p var. + /*! + \param var + The variable corresponding to the space dimension to be replicated; + + \param m + The number of replicas to be created. + + \exception std::invalid_argument + Thrown if \p var does not correspond to a dimension of the vector + space. + + \exception std::length_error + Thrown if adding \p m new space dimensions would cause the vector + space to exceed dimension <CODE>max_space_dimension()</CODE>. + + If \p *this has space dimension \f$n\f$, with \f$n > 0\f$, + and <CODE>var</CODE> has space dimension \f$k \leq n\f$, + then the \f$k\f$-th space dimension is + \ref Expanding_One_Dimension_of_the_Vector_Space_to_Multiple_Dimensions + "expanded" to \p m new space dimensions + \f$n\f$, \f$n+1\f$, \f$\dots\f$, \f$n+m-1\f$. + */ + void expand_space_dimension(Variable var, dimension_type m); + + //! Folds the space dimensions in \p vars into \p dest. + /*! + \param vars + The set of Variable objects corresponding to the space dimensions + to be folded; + + \param dest + The variable corresponding to the space dimension that is the + destination of the folding operation. + + \exception std::invalid_argument + Thrown if \p *this is dimension-incompatible with \p dest or with + one of the Variable objects contained in \p vars. Also + thrown if \p dest is contained in \p vars. + + If \p *this has space dimension \f$n\f$, with \f$n > 0\f$, + <CODE>dest</CODE> has space dimension \f$k \leq n\f$, + \p vars is a set of variables whose maximum space dimension + is also less than or equal to \f$n\f$, and \p dest is not a member + of \p vars, then the space dimensions corresponding to + variables in \p vars are + \ref Folding_Multiple_Dimensions_of_the_Vector_Space_into_One_Dimension "folded" + into the \f$k\f$-th space dimension. + */ + void fold_space_dimensions(const Variables_Set& vars, Variable dest); + + //@} // Member Functions that May Modify the Dimension of the Vector Space + + friend bool operator==(const Grid& x, const Grid& y); + + friend class Parma_Polyhedra_Library::Grid_Certificate; + + template <typename Interval> friend class Parma_Polyhedra_Library::Box; + + //! \name Miscellaneous Member Functions + //@{ + + //! Destructor. + ~Grid(); + + /*! \brief + Swaps \p *this with grid \p y. (\p *this and \p y can be + dimension-incompatible.) + */ + void swap(Grid& y); + + PPL_OUTPUT_DECLARATIONS + + /*! \brief + Loads from \p s an ASCII representation (as produced by + ascii_dump(std::ostream&) const) and sets \p *this accordingly. + Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise. + */ + bool ascii_load(std::istream& s); + + //! Returns the total size in bytes of the memory occupied by \p *this. + memory_size_type total_memory_in_bytes() const; + + //! Returns the size in bytes of the memory managed by \p *this. + memory_size_type external_memory_in_bytes() const; + + /*! \brief + Returns a 32-bit hash code for \p *this. + + If \p x and \p y are such that <CODE>x == y</CODE>, + then <CODE>x.hash_code() == y.hash_code()</CODE>. + */ + int32_t hash_code() const; + + //@} // Miscellaneous Member Functions + +private: + + //! The system of congruences. + Congruence_System con_sys; + + //! The system of generators. + Grid_Generator_System gen_sys; + +#define PPL_IN_Grid_CLASS +#include "Grid_Status.idefs.hh" +#undef PPL_IN_Grid_CLASS + + //! The status flags to keep track of the grid's internal state. + Status status; + + //! The number of dimensions of the enclosing vector space. + dimension_type space_dim; + + enum Dimension_Kind { + PARAMETER, + LINE, + GEN_VIRTUAL, + PROPER_CONGRUENCE = PARAMETER, + CON_VIRTUAL = LINE, + EQUALITY = GEN_VIRTUAL + }; + + typedef std::vector<Dimension_Kind> Dimension_Kinds; + + // The type of row associated with each dimension. If the virtual + // rows existed then the reduced systems would be square and upper + // or lower triangular, and the rows in each would have the types + // given in this vector. As the congruence system is reduced to an + // upside-down lower triangular form the ordering of the congruence + // types is last to first. + Dimension_Kinds dim_kinds; + + //! Builds a grid universe or empty grid. + /*! + \param num_dimensions + The number of dimensions of the vector space enclosing the grid; + + \param kind + specifies whether the universe or the empty grid has to be built. + */ + void construct(dimension_type num_dimensions, Degenerate_Element kind); + + //! Builds a grid from a system of congruences. + /*! + The grid inherits the space dimension of the congruence system. + + \param cgs + The system of congruences defining the grid. Its data-structures + may be recycled to build the grid. + */ + void construct(Congruence_System& cgs); + + //! Builds a grid from a system of grid generators. + /*! + The grid inherits the space dimension of the generator system. + + \param ggs + The system of grid generators defining the grid. Its data-structures + may be recycled to build the grid. + */ + void construct(Grid_Generator_System& ggs); + + //! \name Private Verifiers: Verify if Individual Flags are Set + //@{ + + //! Returns <CODE>true</CODE> if the grid is known to be empty. + /*! + The return value <CODE>false</CODE> does not necessarily + implies that \p *this is non-empty. + */ + bool marked_empty() const; + + //! Returns <CODE>true</CODE> if the system of congruences is up-to-date. + bool congruences_are_up_to_date() const; + + //! Returns <CODE>true</CODE> if the system of generators is up-to-date. + bool generators_are_up_to_date() const; + + //! Returns <CODE>true</CODE> if the system of congruences is minimized. + bool congruences_are_minimized() const; + + //! Returns <CODE>true</CODE> if the system of generators is minimized. + bool generators_are_minimized() const; + + //@} // Private Verifiers: Verify if Individual Flags are Set + + //! \name State Flag Setters: Set Only the Specified Flags + //@{ + + /*! \brief + Sets \p status to express that the grid is the universe + 0-dimension vector space, clearing all corresponding matrices. + */ + void set_zero_dim_univ(); + + /*! \brief + Sets \p status to express that the grid is empty, clearing all + corresponding matrices. + */ + void set_empty(); + + //! Sets \p status to express that congruences are up-to-date. + void set_congruences_up_to_date(); + + //! Sets \p status to express that generators are up-to-date. + void set_generators_up_to_date(); + + //! Sets \p status to express that congruences are minimized. + void set_congruences_minimized(); + + //! Sets \p status to express that generators are minimized. + void set_generators_minimized(); + + //@} // State Flag Setters: Set Only the Specified Flags + + //! \name State Flag Cleaners: Clear Only the Specified Flag + //@{ + + //! Clears the \p status flag indicating that the grid is empty. + void clear_empty(); + + //! Sets \p status to express that congruences are out of date. + void clear_congruences_up_to_date(); + + //! Sets \p status to express that generators are out of date. + void clear_generators_up_to_date(); + + //! Sets \p status to express that congruences are no longer minimized. + void clear_congruences_minimized(); + + //! Sets \p status to express that generators are no longer minimized. + void clear_generators_minimized(); + + //@} // State Flag Cleaners: Clear Only the Specified Flag + + //! \name Updating Matrices + //@{ + + //! Updates and minimizes the congruences from the generators. + void update_congruences() const; + + //! Updates and minimizes the generators from the congruences. + /*! + \return + <CODE>false</CODE> if and only if \p *this turns out to be an + empty grid. + + It is illegal to call this method when the Status field already + declares the grid to be empty. + */ + bool update_generators() const; + + //@} // Updating Matrices + + //! \name Minimization of Descriptions + //@{ + + //! Minimizes both the congruences and the generators. + /*! + \return + <CODE>false</CODE> if and only if \p *this turns out to be an + empty grid. + + Minimization is performed on each system only if the minimized + Status field is clear. + */ + bool minimize() const; + + //@} // Minimization of Descriptions + + enum Three_Valued_Boolean { + TVB_TRUE, + TVB_FALSE, + TVB_DONT_KNOW + }; + + //! Polynomial but incomplete equivalence test between grids. + Three_Valued_Boolean quick_equivalence_test(const Grid& y) const; + + //! Returns <CODE>true</CODE> if and only if \p *this is included in \p y. + bool is_included_in(const Grid& y) const; + + //! Checks if and how \p expr is bounded in \p *this. + /*! + Returns <CODE>true</CODE> if and only if \p from_above is + <CODE>true</CODE> and \p expr is bounded from above in \p *this, + or \p from_above is <CODE>false</CODE> and \p expr is bounded + from below in \p *this. + + \param expr + The linear expression to test; + + \param method_call + The call description of the public parent method, for example + "bounded_from_above(e)". Passed to throw_dimension_incompatible, + as the first argument. + + \exception std::invalid_argument + Thrown if \p expr and \p *this are dimension-incompatible. + */ + bool bounds(const Linear_Expression& expr, const char* method_call) const; + + //! Maximizes or minimizes \p expr subject to \p *this. + /*! + \param expr + The linear expression to be maximized or minimized subject to \p + *this; + + \param method_call + The call description of the public parent method, for example + "maximize(e)". Passed to throw_dimension_incompatible, as the + first argument; + + \param ext_n + The numerator of the extremum value; + + \param ext_d + The denominator of the extremum value; + + \param included + <CODE>true</CODE> if and only if the extremum of \p expr in \p + *this can actually be reached (which is always the case); + + \param point + When maximization or minimization succeeds, will be assigned the + point where \p expr reaches the extremum value. + + \exception std::invalid_argument + Thrown if \p expr and \p *this are dimension-incompatible. + + If \p *this is empty or \p expr is not bounded in the appropriate + direction, <CODE>false</CODE> is returned and \p ext_n, \p ext_d, + \p included and \p point are left untouched. + */ + bool max_min(const Linear_Expression& expr, + const char* method_call, + Coefficient& ext_n, Coefficient& ext_d, bool& included, + Generator* point = NULL) const; + + /*! \brief + Returns <CODE>true</CODE> if and only if \p *this is not empty and + \ref Grid_Frequency "frequency" for \p *this with respect to \p expr + is defined, in which case the frequency and the value for \p expr + that is closest to zero are computed. + + \param expr + The linear expression for which the frequency is needed; + + \param freq_n + The numerator of the maximum frequency of \p expr; + + \param freq_d + The denominator of the maximum frequency of \p expr; + + \param val_n + The numerator of a value of \p expr at a point in the grid + that is closest to zero; + + \param val_d + The denominator of a value of \p expr at a point in the grid + that is closest to zero; + + If \p *this is empty or frequency is undefined with respect to \p expr, + then <CODE>false</CODE> is returned and \p freq_n, \p freq_d, + \p val_n and \p val_d are left untouched. + + \warning + If \p expr and \p *this are dimension-incompatible, + the grid generator system is not minimized or \p *this is + empty, then the behavior is undefined. + */ + bool frequency_no_check(const Linear_Expression& expr, + Coefficient& freq_n, Coefficient& freq_d, + Coefficient& val_n, Coefficient& val_d) const; + + //! Checks if and how \p expr is bounded in \p *this. + /*! + Returns <CODE>true</CODE> if and only if \p from_above is + <CODE>true</CODE> and \p expr is bounded from above in \p *this, + or \p from_above is <CODE>false</CODE> and \p expr is bounded + from below in \p *this. + + \param expr + The linear expression to test; + */ + bool bounds_no_check(const Linear_Expression& expr) const; + + /*! \brief + Adds the congruence \p cg to \p *this. + + \warning + If \p cg and \p *this are dimension-incompatible, + the grid generator system is not minimized or \p *this is + empty, then the behavior is undefined. + */ + void add_congruence_no_check(const Congruence& cg); + + /*! \brief + Uses the constraint \p c to refine \p *this. + + \param c + The constraint to be added. + + \exception std::invalid_argument + Thrown if c is a non-trivial inequality constraint. + + \warning + If \p c and \p *this are dimension-incompatible, + the behavior is undefined. + */ + void add_constraint_no_check(const Constraint& c); + + /*! \brief + Uses the constraint \p c to refine \p *this. + + \param c + The constraint to be added. + Non-trivial inequalities are ignored. + + \warning + If \p c and \p *this are dimension-incompatible, + the behavior is undefined. + */ + void refine_no_check(const Constraint& c); + + //! \name Widening- and Extrapolation-Related Functions + //@{ + + //! Copies a widened selection of congruences from \p y to \p selected_cgs. + void select_wider_congruences(const Grid& y, + Congruence_System& selected_cgs) const; + + //! Copies widened generators from \p y to \p widened_ggs. + void select_wider_generators(const Grid& y, + Grid_Generator_System& widened_ggs) const; + + //@} // Widening- and Extrapolation-Related Functions + + //! Adds new space dimensions to the given systems. + /*! + \param cgs + A congruence system, to which columns are added; + + \param gs + A generator system, to which rows and columns are added; + + \param dims + The number of space dimensions to add. + + This method is invoked only by + <CODE>add_space_dimensions_and_embed()</CODE>. + */ + void add_space_dimensions(Congruence_System& cgs, + Grid_Generator_System& gs, + dimension_type dims); + + //! Adds new space dimensions to the given systems. + /*! + \param gs + A generator system, to which columns are added; + + \param cgs + A congruence system, to which rows and columns are added; + + \param dims + The number of space dimensions to add. + + This method is invoked only by + <CODE>add_space_dimensions_and_project()</CODE>. + */ + void add_space_dimensions(Grid_Generator_System& gs, + Congruence_System& cgs, + dimension_type dims); + + //! \name Minimization-related Static Member Functions + //@{ + + //! Normalizes the divisors in \p sys. + /*! + Converts \p sys to an equivalent system in which the divisors are + of equal value. + + \param sys + The generator system to be normalized. It must have at least one + row. + + \param divisor + A reference to the initial value of the divisor. The resulting + value of this object is the new system divisor. + + \param first_point + If \p first_point has a value other than NULL then it is taken as + the first point in \p sys, and it is assumed that any following + points have the same divisor as \p first_point. + */ + static void + normalize_divisors(Grid_Generator_System& sys, + Coefficient& divisor, + const Grid_Generator* first_point = NULL); + + //! Normalizes the divisors in \p sys. + /*! + Converts \p sys to an equivalent system in which the divisors are + of equal value. + + \param sys + The generator system to be normalized. It must have at least one + row. + */ + static void + normalize_divisors(Grid_Generator_System& sys); + + //! Normalize all the divisors in \p sys and \p gen_sys. + /*! + Modify \p sys and \p gen_sys to use the same single divisor value + for all generators, leaving each system representing the grid it + represented originally. + + \param sys + The first of the generator systems to be normalized. + + \param gen_sys + The second of the generator systems to be normalized. This system + must have at least one row and the divisors of the generators in + this system must be equal. + + \exception std::runtime_error + Thrown if all rows in \p gen_sys are lines and/or parameters. + */ + static void normalize_divisors(Grid_Generator_System& sys, + Grid_Generator_System& gen_sys); + + /*! \brief + Converts generator system \p dest to be equivalent to congruence + system \p source. + */ + static void conversion(Congruence_System& source, + Grid_Generator_System& dest, + Dimension_Kinds& dim_kinds); + + /*! \brief + Converts congruence system \p dest to be equivalent to generator + system \p source. + */ + static void conversion(Grid_Generator_System& source, + Congruence_System& dest, + Dimension_Kinds& dim_kinds); + + //! Converts \p cgs to upper triangular (i.e. minimized) form. + /*! + Returns <CODE>true</CODE> if \p cgs represents the empty set, + otherwise returns <CODE>false</CODE>. + */ + static bool simplify(Congruence_System& cgs, + Dimension_Kinds& dim_kinds); + + //! Converts \p gs to lower triangular (i.e. minimized) form. + /*! + Expects \p gs to contain at least one point. + */ + static void simplify(Grid_Generator_System& gs, + Dimension_Kinds& dim_kinds); + + //! Reduces the line \p row using the line \p pivot. + /*! + Uses the line \p pivot to change the representation of the line \p + row so that the element at index \p col of \p row is zero. + */ + // A member of Grid for access to Matrix::rows. + static void reduce_line_with_line(Grid_Generator& row, + Grid_Generator& pivot, + dimension_type col); + + //! Reduces the equality \p row using the equality \p pivot. + /*! + Uses the equality \p pivot to change the representation of the + equality \p row so that the element at index \p col of \p row is + zero. + */ + // A member of Grid for access to Matrix::rows. + static void reduce_equality_with_equality(Congruence& row, + const Congruence& pivot, + dimension_type col); + + //! Reduces \p row using \p pivot. + /*! + Uses the point, parameter or proper congruence at \p pivot to + change the representation of the point, parameter or proper + congruence at \p row so that the element at index \p col of \p row + is zero. Only elements from index \p start to index \p end are + modified (i.e. it is assumed that all other elements are zero). + */ + // Part of Grid for access to Matrix::rows. + template <typename R> + static void reduce_pc_with_pc(R& row, + R& pivot, + dimension_type col, + dimension_type start, + dimension_type end); + + //! Reduce \p row using \p pivot. + /*! + Use the line \p pivot to change the representation of the + parameter \p row such that the element at index \p col of \p row + is zero. + */ + // A member of Grid for access to Matrix::rows. + static void reduce_parameter_with_line(Grid_Generator& row, + const Grid_Generator& pivot, + dimension_type col, + Grid_Generator_System& sys); + + //! Reduce \p row using \p pivot. + /*! + Use the equality \p pivot to change the representation of the + congruence \p row such that element at index \p col of \p row is + zero. + */ + // A member of Grid for access to Matrix::rows. + static void reduce_congruence_with_equality(Congruence& row, + const Congruence& pivot, + dimension_type col, + Congruence_System& sys); + + //! Reduce column \p dim in rows preceding \p pivot_index in \p sys. + /*! + Required when converting (or simplifying) a congruence or generator + system to "strong minimal form"; informally, strong minimal form means + that, not only is the system in minimal form (ie a triangular matrix), + but also the absolute values of the coefficients of the proper congruences + and parameters are minimal. As a simple example, the set of congruences + \f$\{3x \equiv_3 0, 4x + y \equiv_3 1\}\f$, + (which is in minimal form) is equivalent to the set + \f$\{3x \equiv_3 0, x + y \equiv_3 1\}\f$ + (which is in strong minimal form). + + Only consider from index \p start to index \p end of the row at \p + pivot_index. Flag \p generators indicates whether \p sys is a + congruence or generator system. + */ + template <typename M, typename R> + static void reduce_reduced(M& sys, dimension_type dim, + dimension_type pivot_index, + dimension_type start, dimension_type end, + const Dimension_Kinds& dim_kinds, + bool generators = true); + + //! Multiply the elements of \p dest by \p multiplier. + // A member of Grid for access to Matrix::rows and cgs::operator[]. + static void multiply_grid(const Coefficient& multiplier, + Congruence& cg, Congruence_System& dest, + dimension_type num_rows, + dimension_type num_dims); + + //! Multiply the elements of \p dest by \p multiplier. + // A member of Grid for access to Grid_Generator::operator[]. + static void multiply_grid(const Coefficient& multiplier, + Grid_Generator& gen, + Grid_Generator_System& dest, + dimension_type num_rows, + dimension_type num_dims); + + /*! \brief + If \p sys is lower triangular return <CODE>true</CODE>, else + return <CODE>false</CODE>. + */ + static bool lower_triangular(const Congruence_System& sys, + const Dimension_Kinds& dim_kinds); + + /*! \brief + If \p sys is upper triangular return <CODE>true</CODE>, else + return <CODE>false</CODE>. + */ + static bool upper_triangular(const Grid_Generator_System& sys, + const Dimension_Kinds& dim_kinds); + +#ifndef NDEBUG + //! Checks that trailing rows contain only zero terms. + /*! + If all columns contain zero in the rows of \p system from row + index \p first to row index \p last then return <code>true</code>, + else return <code>false</code>. \p row_size gives the number of + columns in each row. + + This method is only used in assertions in the simplify methods. + */ + template <typename M, typename R> + static bool rows_are_zero(M& system, + dimension_type first, + dimension_type last, + dimension_type row_size); +#endif + + //@} // Minimization-Related Static Member Functions + +#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS + //! \name Exception Throwers + //@{ +#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS) +protected: + void throw_runtime_error(const char* method) const; + void throw_invalid_argument(const char* method, const char* reason) const; + + void throw_dimension_incompatible(const char* method, + const char* other_name, + dimension_type other_dim) const; + void throw_dimension_incompatible(const char* method, + const char* gr_name, + const Grid& gr) const; + void throw_dimension_incompatible(const char* method, + const char* e_name, + const Linear_Expression& e) const; + void throw_dimension_incompatible(const char* method, + const char* cg_name, + const Congruence& cg) const; + void throw_dimension_incompatible(const char* method, + const char* c_name, + const Constraint& c) const; + void throw_dimension_incompatible(const char* method, + const char* g_name, + const Grid_Generator& g) const; + void throw_dimension_incompatible(const char* method, + const char* g_name, + const Generator& g) const; + void throw_dimension_incompatible(const char* method, + const char* cgs_name, + const Congruence_System& cgs) const; + void throw_dimension_incompatible(const char* method, + const char* cs_name, + const Constraint_System& cs) const; + void throw_dimension_incompatible(const char* method, + const char* gs_name, + const Grid_Generator_System& gs) const; + void throw_dimension_incompatible(const char* method, + const char* var_name, + Variable var) const; + void throw_dimension_incompatible(const char* method, + dimension_type required_space_dim) const; + + // Note: it has to be a static method, because it can be called inside + // constructors (before actually constructing the grid object). + static void throw_space_dimension_overflow(const char* method, + const char* reason); + + void throw_invalid_constraint(const char* method, + const char* c_name) const; + void throw_invalid_constraints(const char* method, + const char* cs_name) const; + void throw_invalid_generator(const char* method, + const char* g_name) const; + void throw_invalid_generators(const char* method, + const char* gs_name) const; +#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS + //@} // Exception Throwers +#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS) + +}; + + +namespace std { + +//! Specializes <CODE>std::swap</CODE>. +/*! \relates Parma_Polyhedra_Library::Grid */ +void swap(Parma_Polyhedra_Library::Grid& x, + Parma_Polyhedra_Library::Grid& y); + +} // namespace std + +#include "Grid_Status.inlines.hh" +#include "Grid.inlines.hh" +#include "Grid.templates.hh" + +#endif // !defined(PPL_Grid_defs_hh) |