A grid. More...
#include <Grid.defs.hh>

Classes | |
| class | Status |
| A conjunctive assertion about a grid. More... | |
Public Types | |
| typedef Coefficient | coefficient_type |
| The numeric type of coefficients. | |
Public Member Functions | |
| Grid (dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE) | |
| Builds a grid having the specified properties. | |
| Grid (const Congruence_System &cgs) | |
| Builds a grid, copying a system of congruences. | |
| Grid (Congruence_System &cgs, Recycle_Input dummy) | |
| Builds a grid, recycling a system of congruences. | |
| Grid (const Constraint_System &cs) | |
| Builds a grid, copying a system of constraints. | |
| Grid (Constraint_System &cs, Recycle_Input dummy) | |
| Builds a grid, recycling a system of constraints. | |
| Grid (const Grid_Generator_System &const_gs) | |
| Builds a grid, copying a system of grid generators. | |
| Grid (Grid_Generator_System &gs, Recycle_Input dummy) | |
| Builds a grid, recycling a system of grid generators. | |
| template<typename Interval > | |
| Grid (const Box< Interval > &box, Complexity_Class complexity=ANY_COMPLEXITY) | |
| Builds a grid out of a box. | |
| template<typename U > | |
| Grid (const BD_Shape< U > &bd, Complexity_Class complexity=ANY_COMPLEXITY) | |
| Builds a grid out of a bounded-difference shape. | |
| template<typename U > | |
| Grid (const Octagonal_Shape< U > &os, Complexity_Class complexity=ANY_COMPLEXITY) | |
| Builds a grid out of an octagonal shape. | |
| Grid (const Polyhedron &ph, Complexity_Class complexity=ANY_COMPLEXITY) | |
Builds a grid from a polyhedron using algorithms whose complexity does not exceed the one specified by complexity. If complexity is ANY_COMPLEXITY, then the grid built is the smallest one containing ph. | |
| Grid (const Grid &y, Complexity_Class complexity=ANY_COMPLEXITY) | |
| Ordinary copy constructor. | |
| Grid & | operator= (const Grid &y) |
The assignment operator. (*this and y can be dimension-incompatible.). | |
Member Functions that Do Not Modify the Grid | |
| dimension_type | space_dimension () const |
Returns the dimension of the vector space enclosing *this. | |
| dimension_type | affine_dimension () const |
Returns , if *this is empty; otherwise, returns the affine dimension of *this. | |
| Constraint_System | constraints () const |
Returns a system of equality constraints satisfied by *this with the same affine dimension as *this. | |
| Constraint_System | minimized_constraints () const |
Returns a minimal system of equality constraints satisfied by *this with the same affine dimension as *this. | |
| const Congruence_System & | congruences () const |
| Returns the system of congruences. | |
| const Congruence_System & | minimized_congruences () const |
| Returns the system of congruences in minimal form. | |
| const Grid_Generator_System & | grid_generators () const |
| Returns the system of generators. | |
| const Grid_Generator_System & | minimized_grid_generators () const |
| Returns the minimized system of generators. | |
| Poly_Con_Relation | relation_with (const Congruence &cg) const |
Returns the relations holding between *this and cg. | |
| Poly_Gen_Relation | relation_with (const Grid_Generator &g) const |
Returns the relations holding between *this and g. | |
| Poly_Gen_Relation | relation_with (const Generator &g) const |
Returns the relations holding between *this and g. | |
| Poly_Con_Relation | relation_with (const Constraint &c) const |
Returns the relations holding between *this and c. | |
| bool | is_empty () const |
Returns true if and only if *this is an empty grid. | |
| bool | is_universe () const |
Returns true if and only if *this is a universe grid. | |
| bool | is_topologically_closed () const |
Returns true if and only if *this is a topologically closed subset of the vector space. | |
| bool | is_disjoint_from (const Grid &y) const |
Returns true if and only if *this and y are disjoint. | |
| bool | is_discrete () const |
Returns true if and only if *this is discrete. | |
| bool | is_bounded () const |
Returns true if and only if *this is bounded. | |
| bool | contains_integer_point () const |
Returns true if and only if *this contains at least one integer point. | |
| bool | constrains (Variable var) const |
Returns true if and only if var is constrained in *this. | |
| bool | bounds_from_above (const Linear_Expression &expr) const |
Returns true if and only if expr is bounded in *this. | |
| bool | bounds_from_below (const Linear_Expression &expr) const |
Returns true if and only if expr is bounded in *this. | |
| bool | maximize (const Linear_Expression &expr, Coefficient &sup_n, Coefficient &sup_d, bool &maximum) const |
Returns true if and only if *this is not empty and expr is bounded from above in *this, in which case the supremum value is computed. | |
| bool | maximize (const Linear_Expression &expr, Coefficient &sup_n, Coefficient &sup_d, bool &maximum, Generator &point) const |
Returns true if and only if *this is not empty and expr is bounded from above in *this, in which case the supremum value and a point where expr reaches it are computed. | |
| bool | minimize (const Linear_Expression &expr, Coefficient &inf_n, Coefficient &inf_d, bool &minimum) const |
Returns true if and only if *this is not empty and expr is bounded from below in *this, in which case the infimum value is computed. | |
| bool | minimize (const Linear_Expression &expr, Coefficient &inf_n, Coefficient &inf_d, bool &minimum, Generator &point) const |
Returns true if and only if *this is not empty and expr is bounded from below in *this, in which case the infimum value and a point where expr reaches it are computed. | |
| bool | frequency (const Linear_Expression &expr, Coefficient &freq_n, Coefficient &freq_d, Coefficient &val_n, Coefficient &val_d) const |
Returns true if and only if *this is not empty and frequency for *this with respect to expr is defined, in which case the frequency and the value for expr that is closest to zero are computed. | |
| bool | contains (const Grid &y) const |
Returns true if and only if *this contains y. | |
| bool | strictly_contains (const Grid &y) const |
Returns true if and only if *this strictly contains y. | |
| bool | OK (bool check_not_empty=false) const |
| Checks if all the invariants are satisfied. | |
Space Dimension Preserving Member Functions that May Modify the Grid | |
| void | add_congruence (const Congruence &cg) |
Adds a copy of congruence cg to *this. | |
| void | add_grid_generator (const Grid_Generator &g) |
Adds a copy of grid generator g to the system of generators of *this. | |
| void | add_congruences (const Congruence_System &cgs) |
Adds a copy of each congruence in cgs to *this. | |
| void | add_recycled_congruences (Congruence_System &cgs) |
Adds the congruences in cgs to *this. | |
| void | add_constraint (const Constraint &c) |
Adds to *this a congruence equivalent to constraint c. | |
| void | add_constraints (const Constraint_System &cs) |
Adds to *this congruences equivalent to the constraints in cs. | |
| void | add_recycled_constraints (Constraint_System &cs) |
Adds to *this congruences equivalent to the constraints in cs. | |
| void | refine_with_congruence (const Congruence &cg) |
Uses a copy of the congruence cg to refine *this. | |
| void | refine_with_congruences (const Congruence_System &cgs) |
Uses a copy of the congruences in cgs to refine *this. | |
| void | refine_with_constraint (const Constraint &c) |
Uses a copy of the constraint c to refine *this. | |
| void | refine_with_constraints (const Constraint_System &cs) |
Uses a copy of the constraints in cs to refine *this. | |
| void | add_grid_generators (const Grid_Generator_System &gs) |
Adds a copy of the generators in gs to the system of generators of *this. | |
| void | add_recycled_grid_generators (Grid_Generator_System &gs) |
Adds the generators in gs to the system of generators of this. | |
| void | unconstrain (Variable var) |
Computes the cylindrification of *this with respect to space dimension var, assigning the result to *this. | |
| void | unconstrain (const Variables_Set &vars) |
Computes the cylindrification of *this with respect to the set of space dimensions vars, assigning the result to *this. | |
| void | intersection_assign (const Grid &y) |
Assigns to *this the intersection of *this and y. | |
| void | upper_bound_assign (const Grid &y) |
Assigns to *this the least upper bound of *this and y. | |
| bool | upper_bound_assign_if_exact (const Grid &y) |
If the upper bound of *this and y is exact it is assigned to this and true is returned, otherwise false is returned. | |
| void | difference_assign (const Grid &y) |
Assigns to *this the grid-difference of *this and y. | |
| bool | simplify_using_context_assign (const Grid &y) |
Assigns to *this a meet-preserving simplification of *this with respect to y. If false is returned, then the intersection is empty. | |
| void | affine_image (Variable var, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one()) |
Assigns to *this the affine image of this under the function mapping variable var to the affine expression specified by expr and denominator. | |
| void | affine_preimage (Variable var, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one()) |
Assigns to *this the affine preimage of *this under the function mapping variable var to the affine expression specified by expr and denominator. | |
| 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()) |
Assigns to *this the image of *this with respect to the generalized affine relation . | |
| 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()) |
Assigns to *this the preimage of *this with respect to the generalized affine relation . | |
| void | generalized_affine_image (const Linear_Expression &lhs, Relation_Symbol relsym, const Linear_Expression &rhs, Coefficient_traits::const_reference modulus=Coefficient_zero()) |
Assigns to *this the image of *this with respect to the generalized affine relation . | |
| void | generalized_affine_preimage (const Linear_Expression &lhs, Relation_Symbol relsym, const Linear_Expression &rhs, Coefficient_traits::const_reference modulus=Coefficient_zero()) |
Assigns to *this the preimage of *this with respect to the generalized affine relation . | |
| void | bounded_affine_image (Variable var, const Linear_Expression &lb_expr, const Linear_Expression &ub_expr, Coefficient_traits::const_reference denominator=Coefficient_one()) |
Assigns to *this the image of *this with respect to the bounded affine relation . | |
| void | bounded_affine_preimage (Variable var, const Linear_Expression &lb_expr, const Linear_Expression &ub_expr, Coefficient_traits::const_reference denominator=Coefficient_one()) |
Assigns to *this the preimage of *this with respect to the bounded affine relation . | |
| void | time_elapse_assign (const Grid &y) |
Assigns to *this the result of computing the time-elapse between *this and y. | |
| 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) |
| Wraps the specified dimensions of the vector space. | |
| void | drop_some_non_integer_points (Complexity_Class complexity=ANY_COMPLEXITY) |
Possibly tightens *this by dropping all points with non-integer coordinates. | |
| void | drop_some_non_integer_points (const Variables_Set &vars, Complexity_Class complexity=ANY_COMPLEXITY) |
Possibly tightens *this by dropping all points with non-integer coordinates for the space dimensions corresponding to vars. | |
| void | topological_closure_assign () |
Assigns to *this its topological closure. | |
| void | congruence_widening_assign (const Grid &y, unsigned *tp=NULL) |
Assigns to *this the result of computing the Grid widening between *this and y using congruence systems. | |
| void | generator_widening_assign (const Grid &y, unsigned *tp=NULL) |
Assigns to *this the result of computing the Grid widening between *this and y using generator systems. | |
| void | widening_assign (const Grid &y, unsigned *tp=NULL) |
Assigns to *this the result of computing the Grid widening between *this and y. | |
| void | limited_congruence_extrapolation_assign (const Grid &y, const Congruence_System &cgs, unsigned *tp=NULL) |
Improves the result of the congruence variant of Grid widening computation by also enforcing those congruences in cgs that are satisfied by all the points of *this. | |
| void | limited_generator_extrapolation_assign (const Grid &y, const Congruence_System &cgs, unsigned *tp=NULL) |
Improves the result of the generator variant of the Grid widening computation by also enforcing those congruences in cgs that are satisfied by all the points of *this. | |
| void | limited_extrapolation_assign (const Grid &y, const Congruence_System &cgs, unsigned *tp=NULL) |
Improves the result of the Grid widening computation by also enforcing those congruences in cgs that are satisfied by all the points of *this. | |
Member Functions that May Modify the Dimension of the Vector Space | |
| void | add_space_dimensions_and_embed (dimension_type m) |
Adds m new space dimensions and embeds the old grid in the new vector space. | |
| void | add_space_dimensions_and_project (dimension_type m) |
Adds m new space dimensions to the grid and does not embed it in the new vector space. | |
| void | concatenate_assign (const Grid &y) |
Assigns to *this the concatenation of *this and y, taken in this order. | |
| void | remove_space_dimensions (const Variables_Set &vars) |
| Removes all the specified dimensions from the vector space. | |
| void | remove_higher_space_dimensions (dimension_type new_dimension) |
Removes the higher dimensions of the vector space so that the resulting space will have dimension new_dimension.. | |
| template<typename Partial_Function > | |
| void | map_space_dimensions (const Partial_Function &pfunc) |
| Remaps the dimensions of the vector space according to a partial function. | |
| void | expand_space_dimension (Variable var, dimension_type m) |
Creates m copies of the space dimension corresponding to var. | |
| void | fold_space_dimensions (const Variables_Set &vars, Variable dest) |
Folds the space dimensions in vars into dest. | |
Miscellaneous Member Functions | |
| ~Grid () | |
| Destructor. | |
| void | swap (Grid &y) |
Swaps *this with grid y. (*this and y can be dimension-incompatible.). | |
| 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. | |
| int32_t | hash_code () const |
Returns a 32-bit hash code for *this. | |
Static Public Member Functions | |
| static dimension_type | max_space_dimension () |
| Returns the maximum space dimension all kinds of Grid can handle. | |
| static bool | can_recycle_congruence_systems () |
| Returns true indicating that this domain has methods that can recycle congruences. | |
| static bool | can_recycle_constraint_systems () |
| Returns true indicating that this domain has methods that can recycle constraints. | |
Private Types | |
| enum | Dimension_Kind { PARAMETER, LINE, GEN_VIRTUAL, PROPER_CONGRUENCE = PARAMETER, CON_VIRTUAL = LINE, EQUALITY = GEN_VIRTUAL } |
| enum | Three_Valued_Boolean { TVB_TRUE, TVB_FALSE, TVB_DONT_KNOW } |
| typedef std::vector < Dimension_Kind > | Dimension_Kinds |
Private Member Functions | |
| void | construct (dimension_type num_dimensions, Degenerate_Element kind) |
| Builds a grid universe or empty grid. | |
| void | construct (Congruence_System &cgs) |
| Builds a grid from a system of congruences. | |
| void | construct (Grid_Generator_System &ggs) |
| Builds a grid from a system of grid generators. | |
| Three_Valued_Boolean | quick_equivalence_test (const Grid &y) const |
| Polynomial but incomplete equivalence test between grids. | |
| bool | is_included_in (const Grid &y) const |
Returns true if and only if *this is included in y. | |
| bool | bounds (const Linear_Expression &expr, const char *method_call) const |
Checks if and how expr is bounded in *this. | |
| bool | max_min (const Linear_Expression &expr, const char *method_call, Coefficient &ext_n, Coefficient &ext_d, bool &included, Generator *point=NULL) const |
Maximizes or minimizes expr subject to *this. | |
| bool | frequency_no_check (const Linear_Expression &expr, Coefficient &freq_n, Coefficient &freq_d, Coefficient &val_n, Coefficient &val_d) const |
Returns true if and only if *this is not empty and frequency for *this with respect to expr is defined, in which case the frequency and the value for expr that is closest to zero are computed. | |
| bool | bounds_no_check (const Linear_Expression &expr) const |
Checks if and how expr is bounded in *this. | |
| void | add_congruence_no_check (const Congruence &cg) |
Adds the congruence cg to *this. | |
| void | add_constraint_no_check (const Constraint &c) |
Uses the constraint c to refine *this. | |
| void | refine_no_check (const Constraint &c) |
Uses the constraint c to refine *this. | |
| void | add_space_dimensions (Congruence_System &cgs, Grid_Generator_System &gs, dimension_type dims) |
| Adds new space dimensions to the given systems. | |
| void | add_space_dimensions (Grid_Generator_System &gs, Congruence_System &cgs, dimension_type dims) |
| Adds new space dimensions to the given systems. | |
Private Verifiers: Verify if Individual Flags are Set | |
| bool | marked_empty () const |
Returns true if the grid is known to be empty. | |
| bool | congruences_are_up_to_date () const |
Returns true if the system of congruences is up-to-date. | |
| bool | generators_are_up_to_date () const |
Returns true if the system of generators is up-to-date. | |
| bool | congruences_are_minimized () const |
Returns true if the system of congruences is minimized. | |
| bool | generators_are_minimized () const |
Returns true if the system of generators is minimized. | |
State Flag Setters: Set Only the Specified Flags | |
| void | set_zero_dim_univ () |
Sets status to express that the grid is the universe 0-dimension vector space, clearing all corresponding matrices. | |
| void | set_empty () |
Sets status to express that the grid is empty, clearing all corresponding matrices. | |
| void | set_congruences_up_to_date () |
Sets status to express that congruences are up-to-date. | |
| void | set_generators_up_to_date () |
Sets status to express that generators are up-to-date. | |
| void | set_congruences_minimized () |
Sets status to express that congruences are minimized. | |
| void | set_generators_minimized () |
Sets status to express that generators are minimized. | |
State Flag Cleaners: Clear Only the Specified Flag | |
| void | clear_empty () |
Clears the status flag indicating that the grid is empty. | |
| void | clear_congruences_up_to_date () |
Sets status to express that congruences are out of date. | |
| void | clear_generators_up_to_date () |
Sets status to express that generators are out of date. | |
| void | clear_congruences_minimized () |
Sets status to express that congruences are no longer minimized. | |
| void | clear_generators_minimized () |
Sets status to express that generators are no longer minimized. | |
Updating Matrices | |
| void | update_congruences () const |
| Updates and minimizes the congruences from the generators. | |
| bool | update_generators () const |
| Updates and minimizes the generators from the congruences. | |
Minimization of Descriptions | |
| bool | minimize () const |
| Minimizes both the congruences and the generators. | |
Widening- and Extrapolation-Related Functions | |
| void | select_wider_congruences (const Grid &y, Congruence_System &selected_cgs) const |
Copies a widened selection of congruences from y to selected_cgs. | |
| void | select_wider_generators (const Grid &y, Grid_Generator_System &widened_ggs) const |
Copies widened generators from y to widened_ggs. | |
Static Private Member Functions | |
Minimization-related Static Member Functions | |
| static void | normalize_divisors (Grid_Generator_System &sys, Coefficient &divisor, const Grid_Generator *first_point=NULL) |
Normalizes the divisors in sys. | |
| static void | normalize_divisors (Grid_Generator_System &sys) |
Normalizes the divisors in sys. | |
| static void | normalize_divisors (Grid_Generator_System &sys, Grid_Generator_System &gen_sys) |
Normalize all the divisors in sys and gen_sys. | |
| static void | conversion (Congruence_System &source, Grid_Generator_System &dest, Dimension_Kinds &dim_kinds) |
Converts generator system dest to be equivalent to congruence system source. | |
| static void | conversion (Grid_Generator_System &source, Congruence_System &dest, Dimension_Kinds &dim_kinds) |
Converts congruence system dest to be equivalent to generator system source. | |
| static bool | simplify (Congruence_System &cgs, Dimension_Kinds &dim_kinds) |
Converts cgs to upper triangular (i.e. minimized) form. | |
| static void | simplify (Grid_Generator_System &gs, Dimension_Kinds &dim_kinds) |
Converts gs to lower triangular (i.e. minimized) form. | |
| static void | reduce_line_with_line (Grid_Generator &row, Grid_Generator &pivot, dimension_type col) |
Reduces the line row using the line pivot. | |
| static void | reduce_equality_with_equality (Congruence &row, const Congruence &pivot, dimension_type col) |
Reduces the equality row using the equality pivot. | |
| template<typename R > | |
| static void | reduce_pc_with_pc (R &row, R &pivot, dimension_type col, dimension_type start, dimension_type end) |
Reduces row using pivot. | |
| static void | reduce_parameter_with_line (Grid_Generator &row, const Grid_Generator &pivot, dimension_type col, Grid_Generator_System &sys) |
Reduce row using pivot. | |
| static void | reduce_congruence_with_equality (Congruence &row, const Congruence &pivot, dimension_type col, Congruence_System &sys) |
Reduce row using pivot. | |
| 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) |
Reduce column dim in rows preceding pivot_index in sys. | |
| static void | multiply_grid (const Coefficient &multiplier, Congruence &cg, Congruence_System &dest, dimension_type num_rows, dimension_type num_dims) |
Multiply the elements of dest by multiplier. | |
| static void | multiply_grid (const Coefficient &multiplier, Grid_Generator &gen, Grid_Generator_System &dest, dimension_type num_rows, dimension_type num_dims) |
Multiply the elements of dest by multiplier. | |
| static bool | lower_triangular (const Congruence_System &sys, const Dimension_Kinds &dim_kinds) |
If sys is lower triangular return true, else return false. | |
| static bool | upper_triangular (const Grid_Generator_System &sys, const Dimension_Kinds &dim_kinds) |
If sys is upper triangular return true, else return false. | |
| template<typename M , typename R > | |
| static bool | rows_are_zero (M &system, dimension_type first, dimension_type last, dimension_type row_size) |
| Checks that trailing rows contain only zero terms. | |
Private Attributes | |
| Congruence_System | con_sys |
| The system of congruences. | |
| Grid_Generator_System | gen_sys |
| The system of generators. | |
| Status | status |
| The status flags to keep track of the grid's internal state. | |
| dimension_type | space_dim |
| The number of dimensions of the enclosing vector space. | |
| Dimension_Kinds | dim_kinds |
Friends | |
| class | Parma_Polyhedra_Library::Grid_Certificate |
| class | Parma_Polyhedra_Library::Box |
| bool | operator== (const Grid &x, const Grid &y) |
Returns true if and only if x and y are the same grid. | |
Related Functions | |
(Note that these are not member functions.) | |
| std::ostream & | operator<< (std::ostream &s, const Grid &gr) |
| Output operator. | |
| bool | operator!= (const Grid &x, const Grid &y) |
Returns true if and only if x and y are different grids. | |
| void | swap (Parma_Polyhedra_Library::Grid &x, Parma_Polyhedra_Library::Grid &y) |
Specializes std::swap. | |
Exception Throwers | |
|
| |
| 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 |
| 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 |
| static void | throw_space_dimension_overflow (const char *method, const char *reason) |
A grid.
An object of the class Grid represents a rational grid.
The domain of grids optimally supports:
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 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
of the enclosing vector space):
Note that two different grids can be defined on the zero-dimension space: the empty grid and the universe grid
.
x and y are defined (where they are used) as follows: Variable x(0); Variable y(1);
, given as a system of congruences: Congruence_System cgs; cgs.insert((x %= 0) / 2); cgs.insert((y %= 0) / 2); Grid gr(cgs);
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);
by adding a single congruence to the universe grid: Congruence_System cgs; cgs.insert(x - y == 0); Grid gr(cgs);
Grid_Generator_System gs; gs.insert(grid_point(0*x + 0*y)); gs.insert(grid_line(x + y)); Grid gr(gs);
in
constructed by adding an equality and congruence to the universe grid: Congruence_System cgs; cgs.insert(x - y == 0); cgs.insert(x %= 0); Grid gr(cgs);
Grid_Generator_System gs; gs.insert(grid_point(0*x + 0*y)); gs.insert(parameter(x + y)); Grid gr(gs);
: Grid gr(2);
and inserting the appropriate generators (a point, and two lines). 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).add_space_dimensions_and_embed: Grid gr(1); gr.add_congruence(x == 2); gr.add_space_dimensions_and_embed(1);
. Then we add a single equality congruence, thus obtaining the grid corresponding to the singleton set
. After the last line of code, the resulting grid is
add_space_dimensions_and_project: Grid gr(1); gr.add_congruence(x == 2); gr.add_space_dimensions_and_project(1);
add_space_dimensions_and_embed. After the last line of code, the resulting grid is the singleton set
.affine_image: 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);
and
in
where
is an integer multiple of 4 and
is an integer multiple of 2. The considered variable is
and the affine expression is
. The resulting grid is the given grid translated 3 integers to the right (all the pairs
where
is -1 plus an integer multiple of 4 and
is an integer multiple of 2). Moreover, if the affine transformation for the same variable x is instead
: Linear_Expression expr = x + y;
line, with this line of points repeated at every fourth integral value along the
axis. Instead, if we do not use an invertible transformation for the same variable; for example, the affine expression
: Linear_Expression expr = y;
line.affine_preimage: 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);
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
where
is -3 plus an integer multiple of 4 and
is an integer multiple of 2).. Moreover, if the affine transformation for x is
Linear_Expression expr = x + y;
. Instead, if we do not use an invertible transformation for the same variable x, for example, the affine expression
: Linear_Expression expr = y;
axis.Variable z(2); Variable w(3);
remove_space_dimensions: 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);
, while the resulting grid is
. Be careful when removing space dimensions incrementally: since dimensions are automatically renamed after each application of the remove_space_dimensions operator, unexpected results can be obtained. For instance, by using the following code we would obtain a different result: set<Variable> vars1; vars1.insert(y); gr.remove_space_dimensions(vars1); set<Variable> vars2; vars2.insert(z); gr.remove_space_dimensions(vars2);
: when removing the set of dimensions vars2 we are actually removing variable
of the original grid. For the same reason, the operator remove_space_dimensions is not idempotent: removing twice the same non-empty set of dimensions is never the same as removing them just once. Definition at line 359 of file Grid.defs.hh.
The numeric type of coefficients.
Definition at line 362 of file Grid.defs.hh.
typedef std::vector<Dimension_Kind> Parma_Polyhedra_Library::Grid::Dimension_Kinds [private] |
Definition at line 1990 of file Grid.defs.hh.
enum Parma_Polyhedra_Library::Grid::Dimension_Kind [private] |
Definition at line 1981 of file Grid.defs.hh.
01981 { 01982 PARAMETER, 01983 LINE, 01984 GEN_VIRTUAL, 01985 PROPER_CONGRUENCE = PARAMETER, 01986 CON_VIRTUAL = LINE, 01987 EQUALITY = GEN_VIRTUAL 01988 };
enum Parma_Polyhedra_Library::Grid::Three_Valued_Boolean [private] |
Definition at line 2138 of file Grid.defs.hh.
02138 { 02139 TVB_TRUE, 02140 TVB_FALSE, 02141 TVB_DONT_KNOW 02142 };
| Parma_Polyhedra_Library::Grid::Grid | ( | dimension_type | num_dimensions = 0, |
|
| Degenerate_Element | kind = UNIVERSE | |||
| ) | [inline, explicit] |
Builds a grid having the specified properties.
| num_dimensions | The number of dimensions of the vector space enclosing the grid; | |
| kind | Specifies whether the universe or the empty grid has to be built. |
| std::length_error | Thrown if num_dimensions exceeds the maximum allowed space dimension. |
Definition at line 122 of file Grid.inlines.hh.
References construct(), and OK().
00124 : con_sys(), 00125 gen_sys(num_dimensions > max_space_dimension() 00126 ? (throw_space_dimension_overflow("Grid(n, k)", 00127 "n exceeds the maximum " 00128 "allowed space dimension"), 00129 0) 00130 : num_dimensions) { 00131 construct(num_dimensions, kind); 00132 PPL_ASSERT(OK()); 00133 }
| Parma_Polyhedra_Library::Grid::Grid | ( | const Congruence_System & | cgs | ) | [inline, explicit] |
Builds a grid, copying a system of congruences.
The grid inherits the space dimension of the congruence system.
| cgs | The system of congruences defining the grid. |
| std::length_error | Thrown if num_dimensions exceeds the maximum allowed space dimension. |
Definition at line 136 of file Grid.inlines.hh.
References construct().
00137 : con_sys(cgs.space_dimension() > max_space_dimension() 00138 ? throw_space_dimension_overflow("Grid(cgs)", 00139 "the space dimension of cgs " 00140 "exceeds the maximum allowed " 00141 "space dimension"), 0 00142 : cgs.space_dimension()), 00143 gen_sys(cgs.space_dimension()) { 00144 Congruence_System cgs_copy(cgs); 00145 construct(cgs_copy); 00146 }
| Parma_Polyhedra_Library::Grid::Grid | ( | Congruence_System & | cgs, | |
| Recycle_Input | dummy | |||
| ) | [inline] |
Builds a grid, recycling a system of congruences.
The grid inherits the space dimension of the congruence system.
| cgs | The system of congruences defining the grid. Its data-structures may be recycled to build the grid. | |
| dummy | A dummy tag to syntactically differentiate this one from the other constructors. |
| std::length_error | Thrown if num_dimensions exceeds the maximum allowed space dimension. |
Definition at line 149 of file Grid.inlines.hh.
References construct().
00150 : con_sys(cgs.space_dimension() > max_space_dimension() 00151 ? throw_space_dimension_overflow("Grid(cgs, recycle)", 00152 "the space dimension of cgs " 00153 "exceeds the maximum allowed " 00154 "space dimension"), 0 00155 : cgs.space_dimension()), 00156 gen_sys(cgs.space_dimension()) { 00157 construct(cgs); 00158 }
| Parma_Polyhedra_Library::Grid::Grid | ( | const Constraint_System & | cs | ) | [explicit] |
Builds a grid, copying a system of constraints.
The grid inherits the space dimension of the constraint system.
| cs | The system of constraints defining the grid. |
| std::invalid_argument | Thrown if the constraint system cs contains inequality constraints. | |
| std::length_error | Thrown if num_dimensions exceeds the maximum allowed space dimension. |
Definition at line 60 of file Grid_public.cc.
References Parma_Polyhedra_Library::Constraint_System::begin(), con_sys, construct(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Congruence_System::insert(), OK(), Parma_Polyhedra_Library::Grid::Status::set_empty(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), status, throw_invalid_constraints(), and Parma_Polyhedra_Library::Congruence::zero_dim_false().
00061 : con_sys(cs.space_dimension() > max_space_dimension() 00062 ? throw_space_dimension_overflow("Grid(cs)", 00063 "the space dimension of cs " 00064 "exceeds the maximum allowed " 00065 "space dimension"), 0 00066 : cs.space_dimension()), 00067 gen_sys(cs.space_dimension()) { 00068 space_dim = cs.space_dimension(); 00069 00070 if (space_dim == 0) { 00071 // See if an inconsistent constraint has been passed. 00072 for (Constraint_System::const_iterator i = cs.begin(), 00073 cs_end = cs.end(); i != cs_end; ++i) 00074 if (i->is_inconsistent()) { 00075 // Inconsistent constraint found: the grid is empty. 00076 status.set_empty(); 00077 // Insert the zero dim false congruence system into `con_sys'. 00078 // `gen_sys' is already in empty form. 00079 con_sys.insert(Congruence::zero_dim_false()); 00080 PPL_ASSERT(OK()); 00081 return; 00082 } 00083 set_zero_dim_univ(); 00084 PPL_ASSERT(OK()); 00085 return; 00086 } 00087 00088 Congruence_System cgs; 00089 cgs.insert(0*Variable(space_dim - 1) %= 1); 00090 for (Constraint_System::const_iterator i = cs.begin(), 00091 cs_end = cs.end(); i != cs_end; ++i) 00092 if (i->is_equality()) 00093 cgs.insert(*i); 00094 else 00095 throw_invalid_constraints("Grid(cs)", "cs"); 00096 construct(cgs); 00097 }
| Parma_Polyhedra_Library::Grid::Grid | ( | Constraint_System & | cs, | |
| Recycle_Input | dummy | |||
| ) |
Builds a grid, recycling a system of constraints.
The grid inherits the space dimension of the constraint system.
| cs | The system of constraints defining the grid. Its data-structures may be recycled to build the grid. | |
| dummy | A dummy tag to syntactically differentiate this one from the other constructors. |
| std::invalid_argument | Thrown if the constraint system cs contains inequality constraints. | |
| std::length_error | Thrown if num_dimensions exceeds the maximum allowed space dimension. |
Definition at line 99 of file Grid_public.cc.
References Parma_Polyhedra_Library::Constraint_System::begin(), con_sys, construct(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Congruence_System::insert(), OK(), Parma_Polyhedra_Library::Grid::Status::set_empty(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), status, throw_invalid_constraint(), and Parma_Polyhedra_Library::Congruence::zero_dim_false().
00100 : con_sys(cs.space_dimension() > max_space_dimension() 00101 ? throw_space_dimension_overflow("Grid(cs, recycle)", 00102 "the space dimension of cs " 00103 "exceeds the maximum allowed " 00104 "space dimension"), 0 00105 : cs.space_dimension()), 00106 gen_sys(cs.space_dimension()) { 00107 space_dim = cs.space_dimension(); 00108 00109 if (space_dim == 0) { 00110 // See if an inconsistent constraint has been passed. 00111 for (Constraint_System::const_iterator i = cs.begin(), 00112 cs_end = cs.end(); i != cs_end; ++i) 00113 if (i->is_inconsistent()) { 00114 // Inconsistent constraint found: the grid is empty. 00115 status.set_empty(); 00116 // Insert the zero dim false congruence system into `con_sys'. 00117 // `gen_sys' is already in empty form. 00118 con_sys.insert(Congruence::zero_dim_false()); 00119 PPL_ASSERT(OK()); 00120 return; 00121 } 00122 set_zero_dim_univ(); 00123 PPL_ASSERT(OK()); 00124 return; 00125 } 00126 00127 Congruence_System cgs; 00128 cgs.insert(0*Variable(space_dim - 1) %= 1); 00129 for (Constraint_System::const_iterator i = cs.begin(), 00130 cs_end = cs.end(); i != cs_end; ++i) 00131 if (i->is_equality()) 00132 cgs.insert(*i); 00133 else 00134 throw_invalid_constraint("Grid(cs)", "cs"); 00135 construct(cgs); 00136 }
| Parma_Polyhedra_Library::Grid::Grid | ( | const Grid_Generator_System & | const_gs | ) | [inline, explicit] |
Builds a grid, copying a system of grid generators.
The grid inherits the space dimension of the generator system.
| const_gs | The system of generators defining the grid. |
| std::invalid_argument | Thrown if the system of generators is not empty but has no points. | |
| std::length_error | Thrown if num_dimensions exceeds the maximum allowed space dimension. |
Definition at line 161 of file Grid.inlines.hh.
References construct().
00162 : con_sys(ggs.space_dimension() > max_space_dimension() 00163 ? throw_space_dimension_overflow("Grid(ggs)", 00164 "the space dimension of ggs " 00165 "exceeds the maximum allowed " 00166 "space dimension"), 0 00167 : ggs.space_dimension()), 00168 gen_sys(ggs.space_dimension()) { 00169 Grid_Generator_System ggs_copy(ggs); 00170 construct(ggs_copy); 00171 }
| Parma_Polyhedra_Library::Grid::Grid | ( | Grid_Generator_System & | gs, | |
| Recycle_Input | dummy | |||
| ) | [inline] |
Builds a grid, recycling a system of grid generators.
The grid inherits the space dimension of the generator system.
| gs | The system of generators defining the grid. Its data-structures may be recycled to build the grid. | |
| dummy | A dummy tag to syntactically differentiate this one from the other constructors. |
| std::invalid_argument | Thrown if the system of generators is not empty but has no points. | |
| std::length_error | Thrown if num_dimensions exceeds the maximum allowed space dimension. |
Definition at line 174 of file Grid.inlines.hh.
References construct().
00175 : con_sys(ggs.space_dimension() > max_space_dimension() 00176 ? throw_space_dimension_overflow("Grid(ggs, recycle)", 00177 "the space dimension of ggs " 00178 "exceeds the maximum allowed " 00179 "space dimension"), 0 00180 : ggs.space_dimension()), 00181 gen_sys(ggs.space_dimension()) { 00182 construct(ggs); 00183 }
| Parma_Polyhedra_Library::Grid::Grid | ( | const Box< Interval > & | box, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) | [inline, explicit] |
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.
| box | The box representing the grid to be built. | |
| complexity | This argument is ignored as the algorithm used has polynomial complexity. |
| std::length_error | Thrown if the space dimension of box exceeds the maximum allowed space dimension. |
Definition at line 36 of file Grid.templates.hh.
References con_sys, Parma_Polyhedra_Library::Grid_Generator::divisor(), Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::gcd_assign(), gen_sys, Parma_Polyhedra_Library::Box< ITV >::get_lower_bound(), Parma_Polyhedra_Library::Box< ITV >::get_upper_bound(), Parma_Polyhedra_Library::Congruence_System::increase_space_dimension(), Parma_Polyhedra_Library::Congruence_System::insert(), Parma_Polyhedra_Library::Grid_Generator_System::insert(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), max_space_dimension(), Parma_Polyhedra_Library::neg_assign(), OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Grid_Generator::scale_to_divisor(), set_congruences_up_to_date(), set_empty(), set_generators_up_to_date(), Parma_Polyhedra_Library::Grid_Generator_System::set_sorted(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), throw_space_dimension_overflow(), and Parma_Polyhedra_Library::Grid_Generator_System::unset_pending_rows().
00038 : con_sys(), 00039 gen_sys() { 00040 if (box.space_dimension() > max_space_dimension()) 00041 throw_space_dimension_overflow("Grid(box, from_bounding_box)", 00042 "the space dimension of box " 00043 "exceeds the maximum allowed " 00044 "space dimension"); 00045 00046 space_dim = box.space_dimension(); 00047 00048 if (box.is_empty()) { 00049 // Empty grid. 00050 set_empty(); 00051 PPL_ASSERT(OK()); 00052 return; 00053 } 00054 00055 if (space_dim == 0) 00056 set_zero_dim_univ(); 00057 else { 00058 // Initialize the space dimension as indicated by the box. 00059 con_sys.increase_space_dimension(space_dim); 00060 // Add congruences and generators according to `box'. 00061 PPL_DIRTY_TEMP_COEFFICIENT(l_n); 00062 PPL_DIRTY_TEMP_COEFFICIENT(l_d); 00063 PPL_DIRTY_TEMP_COEFFICIENT(u_n); 00064 PPL_DIRTY_TEMP_COEFFICIENT(u_d); 00065 gen_sys.insert(grid_point(0*Variable(space_dim-1))); 00066 for (dimension_type k = space_dim; k-- > 0; ) { 00067 // This is declared here because it may be invalidated by the call to 00068 // gen_sys.insert() at the end of the loop. 00069 Grid_Generator& point = gen_sys[0]; 00070 bool closed = false; 00071 // TODO: Consider producing the system(s) in minimized form. 00072 if (box.get_lower_bound(k, closed, l_n, l_d)) { 00073 if (box.get_upper_bound(k, closed, u_n, u_d)) 00074 if (l_n * u_d == u_n * l_d) { 00075 // A point interval sets dimension k of every point to a 00076 // single value. 00077 con_sys.insert(l_d * Variable(k) == l_n); 00078 00079 // Scale the point to use as divisor the lcm of the 00080 // divisors of the existing point and the lower bound. 00081 const Coefficient& point_divisor = point.divisor(); 00082 gcd_assign(u_n, l_d, point_divisor); 00083 // `u_n' now holds the gcd. 00084 exact_div_assign(u_n, point_divisor, u_n); 00085 if (l_d < 0) 00086 neg_assign(u_n); 00087 // l_d * u_n == abs(l_d * (point_divisor / gcd(l_d, point_divisor))) 00088 point.scale_to_divisor(l_d * u_n); 00089 // Set dimension k of the point to the lower bound. 00090 if (l_d < 0) 00091 neg_assign(u_n); 00092 // point[k + 1] = l_n * point_divisor / gcd(l_d, point_divisor) 00093 point[k + 1] = l_n * u_n; 00094 00095 continue; 00096 } 00097 } 00098 // A universe interval allows any value in dimension k. 00099 gen_sys.insert(grid_line(Variable(k))); 00100 } 00101 set_congruences_up_to_date(); 00102 set_generators_up_to_date(); 00103 gen_sys.unset_pending_rows(); 00104 gen_sys.set_sorted(false); 00105 } 00106 00107 PPL_ASSERT(OK()); 00108 }
| Parma_Polyhedra_Library::Grid::Grid | ( | const BD_Shape< U > & | bd, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) | [inline, explicit] |
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.
| bd | The BDS representing the grid to be built. | |
| complexity | This argument is ignored as the algorithm used has polynomial complexity. |
| std::length_error | Thrown if the space dimension of bd exceeds the maximum allowed space dimension. |
Definition at line 187 of file Grid.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::congruences(), and construct().
00189 : con_sys(bd.space_dimension() > max_space_dimension() 00190 ? throw_space_dimension_overflow("Grid(bd)", 00191 "the space dimension of bd " 00192 "exceeds the maximum allowed " 00193 "space dimension"), 0 00194 : bd.space_dimension()), 00195 gen_sys(bd.space_dimension()) { 00196 Congruence_System cgs = bd.congruences(); 00197 construct(cgs); 00198 }
| Parma_Polyhedra_Library::Grid::Grid | ( | const Octagonal_Shape< U > & | os, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) | [inline, explicit] |
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.
| os | The octagonal shape representing the grid to be built. | |
| complexity | This argument is ignored as the algorithm used has polynomial complexity. |
| std::length_error | Thrown if the space dimension of os exceeds the maximum allowed space dimension. |
Definition at line 202 of file Grid.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::congruences(), and construct().
00204 : con_sys(os.space_dimension() > max_space_dimension() 00205 ? throw_space_dimension_overflow("Grid(os)", 00206 "the space dimension of os " 00207 "exceeds the maximum allowed " 00208 "space dimension"), 0 00209 : os.space_dimension()), 00210 gen_sys(os.space_dimension()) { 00211 Congruence_System cgs = os.congruences(); 00212 construct(cgs); 00213 }
| Parma_Polyhedra_Library::Grid::Grid | ( | const Polyhedron & | ph, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) | [explicit] |
Builds a grid from a polyhedron using algorithms whose complexity does not exceed the one specified by complexity. If complexity is ANY_COMPLEXITY, then the grid built is the smallest one containing ph.
The grid inherits the space dimension of polyhedron.
| ph | The polyhedron. | |
| complexity | The complexity class. |
| std::length_error | Thrown if num_dimensions exceeds the maximum allowed space dimension. |
Definition at line 138 of file Grid_public.cc.
References Parma_Polyhedra_Library::Linear_Expression::all_homogeneous_terms_are_zero(), Parma_Polyhedra_Library::ANY_COMPLEXITY, Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Polyhedron::constraints(), Parma_Polyhedra_Library::Polyhedron::constraints_are_minimized(), Parma_Polyhedra_Library::Polyhedron::constraints_are_up_to_date(), construct(), Parma_Polyhedra_Library::Polyhedron::generators(), Parma_Polyhedra_Library::Polyhedron::generators_are_up_to_date(), Parma_Polyhedra_Library::Grid_Generator_System::insert(), Parma_Polyhedra_Library::Congruence_System::insert(), Parma_Polyhedra_Library::Polyhedron::is_empty(), Parma_Polyhedra_Library::Polyhedron::marked_empty(), Parma_Polyhedra_Library::Polyhedron::minimize(), OK(), PPL_DIRTY_TEMP_COEFFICIENT, set_empty(), set_zero_dim_univ(), space_dim, and Parma_Polyhedra_Library::Polyhedron::space_dimension().
00140 : con_sys(ph.space_dimension() > max_space_dimension() 00141 ? throw_space_dimension_overflow("Grid(ph)", 00142 "the space dimension of ph " 00143 "exceeds the maximum allowed " 00144 "space dimension"), 0 00145 : ph.space_dimension()), 00146 gen_sys(ph.space_dimension()) { 00147 space_dim = ph.space_dimension(); 00148 00149 // A zero-dim polyhedron causes no complexity problems. 00150 if (space_dim == 0) { 00151 if (ph.is_empty()) 00152 set_empty(); 00153 else 00154 set_zero_dim_univ(); 00155 return; 00156 } 00157 00158 // A polyhedron known to be empty causes no complexity problems. 00159 if (ph.marked_empty()) { 00160 set_empty(); 00161 return; 00162 } 00163 00164 bool use_constraints = ph.constraints_are_minimized() 00165 || !ph.generators_are_up_to_date(); 00166 00167 // Minimize the constraint description if it is needed and 00168 // the complexity allows it. 00169 if (use_constraints && complexity == ANY_COMPLEXITY) 00170 if (!ph.minimize()) { 00171 set_empty(); 00172 return; 00173 } 00174 00175 if (use_constraints) { 00176 // Only the equality constraints need be used. 00177 PPL_ASSERT(ph.constraints_are_up_to_date()); 00178 const Constraint_System& cs = ph.constraints(); 00179 Congruence_System cgs; 00180 cgs.insert(0*Variable(space_dim - 1) %= 1); 00181 for (Constraint_System::const_iterator i = cs.begin(), 00182 cs_end = cs.end(); i != cs_end; ++i) 00183 if (i->is_equality()) 00184 cgs.insert(*i); 00185 construct(cgs); 00186 } 00187 else { 00188 // First find a point or closure point and convert it to a 00189 // grid point and add to the (initially empty) set of grid generators. 00190 PPL_ASSERT(ph.generators_are_up_to_date()); 00191 const Generator_System& gs = ph.generators(); 00192 Grid_Generator_System ggs(space_dim); 00193 Linear_Expression point_expr; 00194 PPL_DIRTY_TEMP_COEFFICIENT(point_divisor); 00195 for (Generator_System::const_iterator g = gs.begin(), 00196 gs_end = gs.end(); g != gs_end; ++g) { 00197 if (g->is_point() || g->is_closure_point()) { 00198 for (dimension_type i = space_dim; i-- > 0; ) { 00199 const Variable v(i); 00200 point_expr += g->coefficient(v) * v; 00201 point_divisor = g->divisor(); 00202 } 00203 ggs.insert(grid_point(point_expr, point_divisor)); 00204 break; 00205 } 00206 } 00207 // Add grid lines for all the other generators. 00208 // If the polyhedron's generator is a (closure) point, the grid line must 00209 // have the direction given by a line that joins the grid point already 00210 // inserted and the new point. 00211 PPL_DIRTY_TEMP_COEFFICIENT(coeff); 00212 PPL_DIRTY_TEMP_COEFFICIENT(g_divisor); 00213 for (Generator_System::const_iterator g = gs.begin(), 00214 gs_end = gs.end(); g != gs_end; ++g) { 00215 Linear_Expression e; 00216 if (g->is_point() || g->is_closure_point()) { 00217 g_divisor = g->divisor(); 00218 for (dimension_type i = space_dim; i-- > 0; ) { 00219 const Variable v(i); 00220 coeff = point_expr.coefficient(v) * g_divisor; 00221 coeff -= g->coefficient(v) * point_divisor; 00222 e += coeff * v; 00223 } 00224 if (e.all_homogeneous_terms_are_zero()) 00225 continue; 00226 } 00227 else 00228 for (dimension_type i = space_dim; i-- > 0; ) { 00229 const Variable v(i); 00230 e += g->coefficient(v) * v; 00231 } 00232 ggs.insert(grid_line(e)); 00233 } 00234 construct(ggs); 00235 } 00236 PPL_ASSERT(OK()); 00237 }
| Parma_Polyhedra_Library::Grid::Grid | ( | const Grid & | y, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) |
Ordinary copy constructor.
The complexity argument is ignored.
Definition at line 38 of file Grid_public.cc.
References con_sys, congruences_are_up_to_date(), gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Congruence_System::increase_space_dimension(), and space_dim.
00039 : con_sys(), 00040 gen_sys(), 00041 status(y.status), 00042 space_dim(y.space_dim), 00043 dim_kinds(y.dim_kinds) { 00044 if (space_dim == 0) { 00045 con_sys = y.con_sys; 00046 gen_sys = y.gen_sys; 00047 } 00048 else { 00049 if (y.congruences_are_up_to_date()) 00050 con_sys = y.con_sys; 00051 else 00052 con_sys.increase_space_dimension(space_dim); 00053 if (y.generators_are_up_to_date()) 00054 gen_sys = y.gen_sys; 00055 else 00056 gen_sys = Grid_Generator_System(y.space_dim); 00057 } 00058 }
| Parma_Polyhedra_Library::Grid::~Grid | ( | ) | [inline] |
| void Parma_Polyhedra_Library::Grid::add_congruence | ( | const Congruence & | cg | ) | [inline] |
Adds a copy of congruence cg to *this.
| std::invalid_argument | Thrown if *this and congruence cg are dimension-incompatible. |
Definition at line 254 of file Grid.inlines.hh.
References add_congruence_no_check(), marked_empty(), space_dim, Parma_Polyhedra_Library::Congruence::space_dimension(), and throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Pointset_Powerset< PSET >::approximate_partition_aux(), drop_some_non_integer_points(), refine_with_congruence(), simplify_using_context_assign(), and wrap_assign().
00254 { 00255 // Dimension-compatibility check. 00256 if (space_dim < cg.space_dimension()) 00257 throw_dimension_incompatible("add_congruence(cg)", "cg", cg); 00258 00259 if (!marked_empty()) 00260 add_congruence_no_check(cg); 00261 }
| void Parma_Polyhedra_Library::Grid::add_congruence_no_check | ( | const Congruence & | cg | ) | [private] |
Adds the congruence cg to *this.
cg and *this are dimension-incompatible, the grid generator system is not minimized or *this is empty, then the behavior is undefined. Definition at line 647 of file Grid_nonpublic.cc.
References clear_congruences_minimized(), clear_generators_up_to_date(), con_sys, congruences_are_up_to_date(), Parma_Polyhedra_Library::Congruence_System::insert(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), marked_empty(), OK(), set_congruences_up_to_date(), set_empty(), space_dim, Parma_Polyhedra_Library::Congruence::space_dimension(), and update_congruences().
Referenced by add_congruence(), add_constraint_no_check(), difference_assign(), generalized_affine_image(), generalized_affine_preimage(), and refine_no_check().
00647 { 00648 PPL_ASSERT(!marked_empty()); 00649 PPL_ASSERT(space_dim >= cg.space_dimension()); 00650 00651 // Dealing with a zero-dimensional space grid first. 00652 if (space_dim == 0) { 00653 if (cg.is_inconsistent()) 00654 set_empty(); 00655 return; 00656 } 00657 00658 if (!congruences_are_up_to_date()) 00659 update_congruences(); 00660 00661 con_sys.insert(cg); 00662 00663 clear_congruences_minimized(); 00664 set_congruences_up_to_date(); 00665 clear_generators_up_to_date(); 00666 00667 // Note: the congruence system may have become unsatisfiable, thus 00668 // we do not check for satisfiability. 00669 PPL_ASSERT(OK()); 00670 }
| void Parma_Polyhedra_Library::Grid::add_congruences | ( | const Congruence_System & | cgs | ) | [inline] |
Adds a copy of each congruence in cgs to *this.
| cgs | Contains the congruences that will be added to the system of congruences of *this. |
| std::invalid_argument | Thrown if *this and cgs are dimension-incompatible. |
Definition at line 264 of file Grid.inlines.hh.
References add_recycled_congruences(), marked_empty(), space_dim, Parma_Polyhedra_Library::Congruence_System::space_dimension(), and throw_dimension_incompatible().
Referenced by refine_with_congruences(), and simplify_using_context_assign().
00264 { 00265 // TODO: this is just an executable specification. 00266 // Space dimension compatibility check. 00267 if (space_dim < cgs.space_dimension()) 00268 throw_dimension_incompatible("add_congruences(cgs)", "cgs", cgs); 00269 00270 if (!marked_empty()) { 00271 Congruence_System cgs_copy = cgs; 00272 add_recycled_congruences(cgs_copy); 00273 } 00274 }
| void Parma_Polyhedra_Library::Grid::add_constraint | ( | const Constraint & | c | ) | [inline] |
Adds to *this a congruence equivalent to constraint c.
| c | The constraint to be added. |
| std::invalid_argument | Thrown if *this and c are dimension-incompatible or if constraint c is not optimally supported by the grid domain. |
Definition at line 297 of file Grid.inlines.hh.
References add_constraint_no_check(), marked_empty(), space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), and throw_dimension_incompatible().
Referenced by wrap_assign().
00297 { 00298 // Space dimension compatibility check. 00299 if (space_dim < c.space_dimension()) 00300 throw_dimension_incompatible("add_constraint(c)", "c", c); 00301 if (!marked_empty()) 00302 add_constraint_no_check(c); 00303 }
| void Parma_Polyhedra_Library::Grid::add_constraint_no_check | ( | const Constraint & | c | ) | [private] |
Uses the constraint c to refine *this.
| c | The constraint to be added. |
| std::invalid_argument | Thrown if c is a non-trivial inequality constraint. |
c and *this are dimension-incompatible, the behavior is undefined. Definition at line 673 of file Grid_nonpublic.cc.
References add_congruence_no_check(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Constraint::is_inconsistent(), Parma_Polyhedra_Library::Constraint::is_inequality(), Parma_Polyhedra_Library::Constraint::is_tautological(), marked_empty(), set_empty(), space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), and throw_invalid_constraint().
Referenced by add_constraint(), and add_constraints().
00673 { 00674 PPL_ASSERT(!marked_empty()); 00675 PPL_ASSERT(space_dim >= c.space_dimension()); 00676 00677 if (c.is_inequality()) { 00678 // Only trivial inequalities can be handled. 00679 if (c.is_inconsistent()) { 00680 set_empty(); 00681 return; 00682 } 00683 if (c.is_tautological()) 00684 return; 00685 // Non-trivial inequality constraints are not allowed. 00686 throw_invalid_constraint("add_constraint(c)", "c"); 00687 } 00688 00689 PPL_ASSERT(c.is_equality()); 00690 Congruence cg(c); 00691 add_congruence_no_check(cg); 00692 }
| void Parma_Polyhedra_Library::Grid::add_constraints | ( | const Constraint_System & | cs | ) |
Adds to *this congruences equivalent to the constraints in cs.
| cs | The constraints to be added. |
| std::invalid_argument | Thrown if *this and cs are dimension-incompatible or if cs contains a constraint whcih is not optimally supported by the grid domain. |
Definition at line 1130 of file Grid_public.cc.
References add_constraint_no_check(), Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Constraint_System::end(), marked_empty(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), and throw_dimension_incompatible().
Referenced by add_recycled_constraints().
01130 { 01131 // The dimension of `cs' must be at most `space_dim'. 01132 if (space_dim < cs.space_dimension()) 01133 throw_dimension_incompatible("add_constraints(cs)", "cs", cs); 01134 if (marked_empty()) 01135 return; 01136 01137 for (Constraint_System::const_iterator i = cs.begin(), 01138 cs_end = cs.end(); i != cs_end; ++i) { 01139 add_constraint_no_check(*i); 01140 if (marked_empty()) 01141 return; 01142 } 01143 }
| void Parma_Polyhedra_Library::Grid::add_grid_generator | ( | const Grid_Generator & | g | ) |
Adds a copy of grid generator g to the system of generators of *this.
| std::invalid_argument | Thrown if *this and generator g are dimension-incompatible, or if *this is an empty grid and g is not a point. |
Definition at line 1146 of file Grid_public.cc.
References clear_congruences_up_to_date(), clear_empty(), clear_generators_minimized(), gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Grid_Generator_System::insert(), Parma_Polyhedra_Library::Grid_Generator::is_line_or_parameter(), Parma_Polyhedra_Library::Grid_Generator::is_parameter(), Parma_Polyhedra_Library::Grid_Generator::is_parameter_or_point(), marked_empty(), normalize_divisors(), OK(), set_generators_up_to_date(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Grid_Generator::space_dimension(), throw_dimension_incompatible(), throw_invalid_generator(), and update_generators().
Referenced by generalized_affine_image(), generalized_affine_preimage(), and wrap_assign().
01146 { 01147 // The dimension of `g' must be at most space_dim. 01148 const dimension_type g_space_dim = g.space_dimension(); 01149 if (space_dim < g_space_dim) 01150 throw_dimension_incompatible("add_grid_generator(g)", "g", g); 01151 01152 // Deal with zero-dimension case first. 01153 if (space_dim == 0) { 01154 // Points and parameters are the only zero-dimension generators 01155 // that can be created. 01156 if (marked_empty()) { 01157 if (g.is_parameter()) 01158 throw_invalid_generator("add_grid_generator(g)", "g"); 01159 set_zero_dim_univ(); 01160 } 01161 PPL_ASSERT(OK()); 01162 return; 01163 } 01164 01165 if (marked_empty() 01166 || (!generators_are_up_to_date() && !update_generators())) { 01167 // Here the grid is empty: the specification says we can only 01168 // insert a point. 01169 if (g.is_line_or_parameter()) 01170 throw_invalid_generator("add_grid_generator(g)", "g"); 01171 gen_sys.insert(g); 01172 clear_empty(); 01173 } 01174 else { 01175 PPL_ASSERT(generators_are_up_to_date()); 01176 gen_sys.insert(g); 01177 if (g.is_parameter_or_point()) 01178 normalize_divisors(gen_sys); 01179 } 01180 01181 // With the added generator, congruences are out of date. 01182 clear_congruences_up_to_date(); 01183 01184 clear_generators_minimized(); 01185 set_generators_up_to_date(); 01186 PPL_ASSERT(OK()); 01187 }
| void Parma_Polyhedra_Library::Grid::add_grid_generators | ( | const Grid_Generator_System & | gs | ) |
Adds a copy of the generators in gs to the system of generators of *this.
| gs | Contains the generators that will be added to the system of generators of *this. |
| std::invalid_argument | Thrown if *this and gs are dimension-incompatible, or if *this is empty and the system of generators gs is not empty, but has no points. |
Definition at line 1290 of file Grid_public.cc.
References add_recycled_grid_generators().
01290 { 01291 // TODO: this is just an executable specification. 01292 Grid_Generator_System gs_copy = gs; 01293 add_recycled_grid_generators(gs_copy); 01294 }
| void Parma_Polyhedra_Library::Grid::add_recycled_congruences | ( | Congruence_System & | cgs | ) |
Adds the congruences in cgs to *this.
| cgs | The congruence system to be added to *this. The congruences in cgs may be recycled. |
| std::invalid_argument | Thrown if *this and cgs are dimension-incompatible. |
cgs upon successful or exceptional return is that it can be safely destroyed. Definition at line 1190 of file Grid_public.cc.
References Parma_Polyhedra_Library::Congruence_System::begin(), clear_congruences_minimized(), clear_generators_up_to_date(), con_sys, congruences_are_up_to_date(), Parma_Polyhedra_Library::Congruence_System::end(), Parma_Polyhedra_Library::Matrix::has_no_rows(), marked_empty(), OK(), Parma_Polyhedra_Library::Congruence_System::recycling_insert(), set_empty(), space_dim, Parma_Polyhedra_Library::Congruence_System::space_dimension(), throw_dimension_incompatible(), and update_congruences().
Referenced by add_congruences(), congruence_widening_assign(), contains_integer_point(), expand_space_dimension(), generalized_affine_image(), generalized_affine_preimage(), limited_congruence_extrapolation_assign(), limited_extrapolation_assign(), limited_generator_extrapolation_assign(), and simplify_using_context_assign().
01190 { 01191 // Dimension-compatibility check. 01192 const dimension_type cgs_space_dim = cgs.space_dimension(); 01193 if (space_dim < cgs_space_dim) 01194 throw_dimension_incompatible("add_recycled_congruences(cgs)", "cgs", cgs); 01195 01196 if (cgs.has_no_rows()) 01197 return; 01198 01199 if (marked_empty()) 01200 return; 01201 01202 if (space_dim == 0) { 01203 // In a 0-dimensional space the congruences are trivial (e.g., 0 01204 // == 0 or 1 %= 0) or false (e.g., 1 == 0). In a system of 01205 // congruences `begin()' and `end()' are equal if and only if the 01206 // system contains only trivial congruences. 01207 if (cgs.begin() != cgs.end()) 01208 // There is a congruence, it must be false, the grid becomes empty. 01209 set_empty(); 01210 return; 01211 } 01212 01213 // The congruences are required. 01214 if (!congruences_are_up_to_date()) 01215 update_congruences(); 01216 01217 // Swap (instead of copying) the coefficients of `cgs' (which is 01218 // writable). 01219 con_sys.recycling_insert(cgs); 01220 01221 // Congruences may not be minimized and generators are out of date. 01222 clear_congruences_minimized(); 01223 clear_generators_up_to_date(); 01224 // Note: the congruence system may have become unsatisfiable, thus 01225 // we do not check for satisfiability. 01226 PPL_ASSERT(OK()); 01227 }
| void Parma_Polyhedra_Library::Grid::add_recycled_constraints | ( | Constraint_System & | cs | ) | [inline] |
Adds to *this congruences equivalent to the constraints in cs.
| cs | The constraints to be added. They may be recycled. |
| std::invalid_argument | Thrown if *this and cs are dimension-incompatible or if cs contains a constraint whcih is not optimally supported by the grid domain. |
cs upon successful or exceptional return is that it can be safely destroyed. Definition at line 306 of file Grid.inlines.hh.
References add_constraints().
00306 { 00307 // TODO: really recycle the constraints. 00308 add_constraints(cs); 00309 }
| void Parma_Polyhedra_Library::Grid::add_recycled_grid_generators | ( | Grid_Generator_System & | gs | ) |
Adds the generators in gs to the system of generators of this.
| gs | The generator system to be added to *this. The generators in gs may be recycled. |
| std::invalid_argument | Thrown if *this and gs are dimension-incompatible. |
gs upon successful or exceptional return is that it can be safely destroyed. Definition at line 1230 of file Grid_public.cc.
References clear_congruences_up_to_date(), clear_empty(), clear_generators_minimized(), gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Matrix::has_no_rows(), Parma_Polyhedra_Library::Grid_Generator_System::has_points(), Parma_Polyhedra_Library::Grid_Generator_System::insert(), marked_empty(), normalize_divisors(), OK(), Parma_Polyhedra_Library::Grid_Generator_System::recycling_insert(), set_generators_up_to_date(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), swap(), throw_dimension_incompatible(), throw_invalid_generators(), and update_generators().
Referenced by add_grid_generators(), generalized_affine_image(), generalized_affine_preimage(), and generator_widening_assign().
01230 { 01231 // Dimension-compatibility check. 01232 const dimension_type gs_space_dim = gs.space_dimension(); 01233 if (space_dim < gs_space_dim) 01234 throw_dimension_incompatible("add_recycled_grid_generators(gs)", "gs", gs); 01235 01236 // Adding no generators leaves the grid the same. 01237 if (gs.has_no_rows()) 01238 return; 01239 01240 // Adding valid generators to a zero-dimensional grid transforms it 01241 // to the zero-dimensional universe grid. 01242 if (space_dim == 0) { 01243 if (marked_empty()) 01244 set_zero_dim_univ(); 01245 else { 01246 PPL_ASSERT(gs.has_points()); 01247 } 01248 PPL_ASSERT(OK(true)); 01249 return; 01250 } 01251 01252 if (!marked_empty()) { 01253 // The grid contains at least one point. 01254 01255 if (!generators_are_up_to_date()) 01256 update_generators(); 01257 normalize_divisors(gs, gen_sys); 01258 01259 gen_sys.recycling_insert(gs); 01260 01261 // Congruences are out of date and generators are not minimized. 01262 clear_congruences_up_to_date(); 01263 clear_generators_minimized(); 01264 01265 PPL_ASSERT(OK(true)); 01266 return; 01267 } 01268 01269 // The grid is empty. 01270 01271 // `gs' must contain at least one point. 01272 if (!gs.has_points()) 01273 throw_invalid_generators("add_recycled_grid_generators(gs)", "gs"); 01274 01275 // Adjust `gs' to the right dimension. 01276 gs.insert(parameter(0*Variable(space_dim-1))); 01277 01278 std::swap(gen_sys, gs); 01279 01280 normalize_divisors(gen_sys); 01281 01282 // The grid is no longer empty and generators are up-to-date. 01283 set_generators_up_to_date(); 01284 clear_empty(); 01285 01286 PPL_ASSERT(OK()); 01287 }
| void Parma_Polyhedra_Library::Grid::add_space_dimensions | ( | Grid_Generator_System & | gs, | |
| Congruence_System & | cgs, | |||
| dimension_type | dims | |||
| ) | [private] |
Adds new space dimensions to the given systems.
| gs | A generator system, to which columns are added; | |
| cgs | A congruence system, to which rows and columns are added; | |
| dims | The number of space dimensions to add. |
This method is invoked only by add_space_dimensions_and_project().
Definition at line 54 of file Grid_chdims.cc.
References Parma_Polyhedra_Library::Congruence_System::add_unit_rows_and_columns(), dim_kinds, EQUALITY, Parma_Polyhedra_Library::Grid_Generator_System::insert(), normalize_divisors(), Parma_Polyhedra_Library::Matrix::num_columns(), space_dim, and Parma_Polyhedra_Library::Grid_Generator_System::space_dimension().
00056 { 00057 PPL_ASSERT(cgs.num_columns() - 1 == gs.space_dimension() + 1); 00058 PPL_ASSERT(dims > 0); 00059 00060 cgs.add_unit_rows_and_columns(dims); 00061 00062 // Add `dims' zero columns onto gs. 00063 gs.insert(parameter(0*Variable(space_dim + dims - 1))); 00064 00065 normalize_divisors(gs); 00066 00067 dim_kinds.resize(cgs.num_columns() - 1, EQUALITY /* a.k.a GEN_VIRTUAL */); 00068 }
| void Parma_Polyhedra_Library::Grid::add_space_dimensions | ( | Congruence_System & | cgs, | |
| Grid_Generator_System & | gs, | |||
| dimension_type | dims | |||
| ) | [private] |
Adds new space dimensions to the given systems.
| cgs | A congruence system, to which columns are added; | |
| gs | A generator system, to which rows and columns are added; | |
| dims | The number of space dimensions to add. |
This method is invoked only by add_space_dimensions_and_embed().
Definition at line 35 of file Grid_chdims.cc.
References Parma_Polyhedra_Library::Grid_Generator_System::add_universe_rows_and_columns(), Parma_Polyhedra_Library::Matrix::add_zero_columns(), CON_VIRTUAL, congruences_are_minimized(), dim_kinds, generators_are_minimized(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), and Parma_Polyhedra_Library::Matrix::swap_columns().
Referenced by add_space_dimensions_and_embed(), and add_space_dimensions_and_project().
00037 { 00038 PPL_ASSERT(cgs.num_columns() - 1 == gs.space_dimension() + 1); 00039 PPL_ASSERT(dims > 0); 00040 00041 const dimension_type old_modulus_index = cgs.num_columns() - 1; 00042 cgs.add_zero_columns(dims); 00043 // Move the moduli. 00044 cgs.swap_columns(old_modulus_index, old_modulus_index + dims); 00045 00046 if (congruences_are_minimized() || generators_are_minimized()) 00047 dim_kinds.resize(old_modulus_index + dims, CON_VIRTUAL /* a.k.a. LINE */); 00048 00049 gs.add_universe_rows_and_columns(dims); 00050 }
| void Parma_Polyhedra_Library::Grid::add_space_dimensions_and_embed | ( | dimension_type | m | ) |
Adds m new space dimensions and embeds the old grid in the new vector space.
| m | The number of dimensions to add. |
| std::length_error | Thrown if adding m new space dimensions would cause the vector space to exceed dimension max_space_dimension(). |
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
and adding a third space dimension, the result will be the grid
Definition at line 79 of file Grid_chdims.cc.
References add_space_dimensions(), Parma_Polyhedra_Library::Grid_Generator_System::add_universe_rows_and_columns(), Parma_Polyhedra_Library::Matrix::add_zero_columns(), con_sys, CON_VIRTUAL, congruences_are_minimized(), congruences_are_up_to_date(), dim_kinds, gen_sys, generators_are_minimized(), generators_are_up_to_date(), LINE, marked_empty(), max_space_dimension(), Parma_Polyhedra_Library::Matrix::num_columns(), OK(), set_empty(), space_dim, Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), space_dimension(), status, swap(), Parma_Polyhedra_Library::Matrix::swap_columns(), Parma_Polyhedra_Library::Grid::Status::test_zero_dim_univ(), throw_space_dimension_overflow(), and Parma_Polyhedra_Library::UNIVERSE.
Referenced by expand_space_dimension(), generalized_affine_image(), generalized_affine_preimage(), and simplify_using_context_assign().
00079 { 00080 if (m == 0) 00081 return; 00082 00083 // The space dimension of the resulting grid must be at most the 00084 // maximum allowed space dimension. 00085 if (m > max_space_dimension() - space_dimension()) 00086 throw_space_dimension_overflow("add_space_dimensions_and_embed(m)", 00087 "adding m new space dimensions exceeds " 00088 "the maximum allowed space dimension"); 00089 00090 // Adding dimensions to an empty grid is obtained by adjusting 00091 // `space_dim' and clearing `con_sys' (since it can contain the 00092 // integrality congruence of the current dimension). 00093 if (marked_empty()) { 00094 space_dim += m; 00095 set_empty(); 00096 return; 00097 } 00098 00099 // The case of a zero-dimension space grid. 00100 if (space_dim == 0) { 00101 // Since it is not empty, it has to be the universe grid. 00102 PPL_ASSERT(status.test_zero_dim_univ()); 00103 // Swap *this with a newly created `m'-dimensional universe grid. 00104 Grid gr(m, UNIVERSE); 00105 swap(gr); 00106 return; 00107 } 00108 00109 // To embed an n-dimension space grid in a (n+m)-dimension space, we 00110 // add `m' zero-columns to the rows in the system of congruences; in 00111 // contrast, the system of generators needs additional rows, 00112 // corresponding to the vectors of the canonical basis for the added 00113 // dimensions. That is, for each new dimension we add the line 00114 // having that direction. This is done by invoking the function 00115 // add_space_dimensions(). 00116 if (congruences_are_up_to_date()) 00117 if (generators_are_up_to_date()) 00118 // Adds rows and/or columns to both matrices. 00119 add_space_dimensions(con_sys, gen_sys, m); 00120 else { 00121 // Only congruences are up-to-date, so modify only them. 00122 con_sys.add_zero_columns(m); 00123 dimension_type size = con_sys.num_columns() - 1; 00124 // Move the moduli. 00125 con_sys.swap_columns(size - m, size); 00126 if (congruences_are_minimized()) 00127 dim_kinds.resize(size, CON_VIRTUAL); 00128 } 00129 else { 00130 // Only generators are up-to-date, so modify only them. 00131 PPL_ASSERT(generators_are_up_to_date()); 00132 gen_sys.add_universe_rows_and_columns(m); 00133 if (generators_are_minimized()) 00134 dim_kinds.resize(gen_sys.space_dimension() + 1, LINE); 00135 } 00136 // Update the space dimension. 00137 space_dim += m; 00138 00139 // Note: we do not check for satisfiability, because the system of 00140 // congruences may be unsatisfiable. 00141 PPL_ASSERT(OK()); 00142 }
| void Parma_Polyhedra_Library::Grid::add_space_dimensions_and_project | ( | dimension_type | m | ) |
Adds m new space dimensions to the grid and does not embed it in the new vector space.
| m | The number of space dimensions to add. |
| std::length_error | Thrown if adding m new space dimensions would cause the vector space to exceed dimension max_space_dimension(). |
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
and adding a third space dimension, the result will be the grid
Definition at line 153 of file Grid_chdims.cc.
References add_space_dimensions(), Parma_Polyhedra_Library::Congruence_System::add_unit_rows_and_columns(), con_sys, congruences_are_minimized(), congruences_are_up_to_date(), dim_kinds, EQUALITY, gen_sys, generators_are_minimized(), generators_are_up_to_date(), Parma_Polyhedra_Library::Grid_Generator_System::insert(), marked_empty(), max_space_dimension(), normalize_divisors(), Parma_Polyhedra_Library::Matrix::num_columns(), OK(), set_empty(), space_dim, Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), space_dimension(), status, swap(), Parma_Polyhedra_Library::Grid::Status::test_zero_dim_univ(), throw_space_dimension_overflow(), and Parma_Polyhedra_Library::UNIVERSE.
00153 { 00154 if (m == 0) 00155 return; 00156 00157 // The space dimension of the resulting grid should be at most the 00158 // maximum allowed space dimension. 00159 if (m > max_space_dimension() - space_dimension()) 00160 throw_space_dimension_overflow("add_space_dimensions_and_project(m)", 00161 "adding m new space dimensions exceeds " 00162 "the maximum allowed space dimension"); 00163 00164 // Adding dimensions to an empty grid is obtained by merely 00165 // adjusting `space_dim'. 00166 if (marked_empty()) { 00167 space_dim += m; 00168 set_empty(); 00169 return; 00170 } 00171 00172 if (space_dim == 0) { 00173 PPL_ASSERT(status.test_zero_dim_univ()); 00174 // Swap *this with a newly created `n'-dimensional universe grid. 00175 Grid gr(m, UNIVERSE); 00176 swap(gr); 00177 return; 00178 } 00179 00180 // To project an n-dimension space grid in a (n+m)-dimension space, 00181 // we just add to the system of generators `m' zero-columns; in 00182 // contrast, in the system of congruences, new rows are needed in 00183 // order to avoid embedding the old grid in the new space. Thus, 00184 // for each new dimensions `x[k]', we add the constraint x[k] = 0; 00185 // this is done by invoking the function add_space_dimensions() 00186 // giving the system of constraints as the second argument. 00187 if (congruences_are_up_to_date()) 00188 if (generators_are_up_to_date()) 00189 // Add rows and/or columns to both matrices. 00190 add_space_dimensions(gen_sys, con_sys, m); 00191 else { 00192 // Only congruences are up-to-date so modify only them. 00193 con_sys.add_unit_rows_and_columns(m); 00194 if (congruences_are_minimized()) 00195 dim_kinds.resize(con_sys.num_columns() - 1, EQUALITY); 00196 } 00197 else { 00198 // Only generators are up-to-date so modify only them. 00199 PPL_ASSERT(generators_are_up_to_date()); 00200 00201 // Add m zero columns onto gs. 00202 gen_sys.insert(parameter(0*Variable(space_dim + m - 1))); 00203 00204 normalize_divisors(gen_sys); 00205 00206 if (generators_are_minimized()) 00207 dim_kinds.resize(gen_sys.space_dimension() + 1, EQUALITY); 00208 } 00209 // Now update the space dimension. 00210 space_dim += m; 00211 00212 // Note: we do not check for satisfiability, because the system of 00213 // congruences may be unsatisfiable. 00214 PPL_ASSERT(OK()); 00215 }
| PPL::dimension_type Parma_Polyhedra_Library::Grid::affine_dimension | ( | ) | const |
Returns
, if *this is empty; otherwise, returns the affine dimension of *this.
Definition at line 258 of file Grid_public.cc.
References con_sys, congruences_are_minimized(), congruences_are_up_to_date(), gen_sys, generators_are_minimized(), generators_are_up_to_date(), is_empty(), minimized_congruences(), minimized_grid_generators(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), and space_dim.
00258 { 00259 if (space_dim == 0 || is_empty()) 00260 return 0; 00261 00262 if (generators_are_up_to_date()) { 00263 if (generators_are_minimized()) 00264 return gen_sys.num_rows() - 1; 00265 if (!(congruences_are_up_to_date() && congruences_are_minimized())) 00266 return minimized_grid_generators().num_rows() - 1; 00267 } 00268 else 00269 minimized_congruences(); 00270 PPL_ASSERT(congruences_are_minimized()); 00271 dimension_type d = space_dim; 00272 for (dimension_type i = con_sys.num_rows(); i-- > 0; ) 00273 if (con_sys[i].is_equality()) 00274 --d; 00275 return d; 00276 }
| void Parma_Polyhedra_Library::Grid::affine_image | ( | Variable | var, | |
| const Linear_Expression & | expr, | |||
| Coefficient_traits::const_reference | denominator = Coefficient_one() | |||
| ) |
Assigns to *this the affine image of this under the function mapping variable var to the affine expression specified by expr and denominator.
| var | The variable to which the affine expression is assigned; | |
| expr | The numerator of the affine expression; | |
| denominator | The denominator of the affine expression (optional argument with default value 1). |
| std::invalid_argument | Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a space dimension of *this. |
When considering the generators of a grid, the affine transformation
is assigned to var where expr is
(
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:
var in this transformation (i.e.,
) is different from zero.
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.
Definition at line 1757 of file Grid_public.cc.
References Parma_Polyhedra_Library::Grid_Generator_System::affine_image(), Parma_Polyhedra_Library::Congruence_System::affine_preimage(), clear_congruences_minimized(), clear_congruences_up_to_date(), clear_generators_minimized(), con_sys, congruences_are_up_to_date(), gen_sys, generators_are_up_to_date(), marked_empty(), minimize(), Parma_Polyhedra_Library::neg_assign(), normalize_divisors(), OK(), space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
Referenced by fold_space_dimensions(), and generalized_affine_image().
01759 { 01760 // The denominator cannot be zero. 01761 if (denominator == 0) 01762 throw_invalid_argument("affine_image(v, e, d)", "d == 0"); 01763 01764 // Dimension-compatibility checks. 01765 // The dimension of `expr' must be at most the dimension of `*this'. 01766 const dimension_type expr_space_dim = expr.space_dimension(); 01767 if (space_dim < expr_space_dim) 01768 throw_dimension_incompatible("affine_image(v, e, d)", "e", expr); 01769 // `var' must be one of the dimensions of the grid. 01770 const dimension_type var_space_dim = var.space_dimension(); 01771 if (space_dim < var_space_dim) 01772 throw_dimension_incompatible("affine_image(v, e, d)", "v", var); 01773 01774 if (marked_empty()) 01775 return; 01776 01777 if (var_space_dim <= expr_space_dim && expr[var_space_dim] != 0) { 01778 // The transformation is invertible. 01779 if (generators_are_up_to_date()) { 01780 // Grid_Generator_System::affine_image() requires the third argument 01781 // to be a positive Coefficient. 01782 if (denominator > 0) 01783 gen_sys.affine_image(var_space_dim, expr, denominator); 01784 else 01785 gen_sys.affine_image(var_space_dim, -expr, -denominator); 01786 clear_generators_minimized(); 01787 // Strong normalization in gs::affine_image may have modified 01788 // divisors. 01789 normalize_divisors(gen_sys); 01790 } 01791 if (congruences_are_up_to_date()) { 01792 // To build the inverse transformation, 01793 // after copying and negating `expr', 01794 // we exchange the roles of `expr[var_space_dim]' and `denominator'. 01795 Linear_Expression inverse; 01796 if (expr[var_space_dim] > 0) { 01797 inverse = -expr; 01798 inverse[var_space_dim] = denominator; 01799 con_sys.affine_preimage(var_space_dim, inverse, expr[var_space_dim]); 01800 } 01801 else { 01802 // The new denominator is negative: we negate everything once 01803 // more, as Congruence_System::affine_preimage() requires the 01804 // third argument to be positive. 01805 inverse = expr; 01806 inverse[var_space_dim] = denominator; 01807 neg_assign(inverse[var_space_dim]); 01808 con_sys.affine_preimage(var_space_dim, inverse, -expr[var_space_dim]); 01809 } 01810 clear_congruences_minimized(); 01811 } 01812 } 01813 else { 01814 // The transformation is not invertible. 01815 // We need an up-to-date system of generators. 01816 if (!generators_are_up_to_date()) 01817 minimize(); 01818 if (!marked_empty()) { 01819 // Grid_Generator_System::affine_image() requires the third argument 01820 // to be a positive Coefficient. 01821 if (denominator > 0) 01822 gen_sys.affine_image(var_space_dim, expr, denominator); 01823 else 01824 gen_sys.affine_image(var_space_dim, -expr, -denominator); 01825 01826 clear_congruences_up_to_date(); 01827 clear_generators_minimized(); 01828 // Strong normalization in gs::affine_image may have modified 01829 // divisors. 01830 normalize_divisors(gen_sys); 01831 } 01832 } 01833 PPL_ASSERT(OK()); 01834 }
| void Parma_Polyhedra_Library::Grid::affine_preimage | ( | Variable | var, | |
| const Linear_Expression & | expr, | |||
| Coefficient_traits::const_reference | denominator = Coefficient_one() | |||
| ) |
Assigns to *this the affine preimage of *this under the function mapping variable var to the affine expression specified by expr and denominator.
| var | The variable to which the affine expression is substituted; | |
| expr | The numerator of the affine expression; | |
| denominator | The denominator of the affine expression (optional argument with default value 1). |
| std::invalid_argument | Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a space dimension of *this. |
When considering congruences of a grid, the affine transformation
is assigned to var where expr is
(
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:
var in this transformation (i.e.
) is different from zero.
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.
Definition at line 1838 of file Grid_public.cc.
References Parma_Polyhedra_Library::Grid_Generator_System::affine_image(), Parma_Polyhedra_Library::Congruence_System::affine_preimage(), clear_congruences_minimized(), clear_generators_minimized(), clear_generators_up_to_date(), con_sys, congruences_are_up_to_date(), gen_sys, generators_are_up_to_date(), marked_empty(), minimize(), Parma_Polyhedra_Library::neg_assign(), OK(), space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
Referenced by generalized_affine_preimage().
01840 { 01841 // The denominator cannot be zero. 01842 if (denominator == 0) 01843 throw_invalid_argument("affine_preimage(v, e, d)", "d == 0"); 01844 01845 // Dimension-compatibility checks. 01846 // The dimension of `expr' should not be greater than the dimension 01847 // of `*this'. 01848 const dimension_type expr_space_dim = expr.space_dimension(); 01849 if (space_dim < expr_space_dim) 01850 throw_dimension_incompatible("affine_preimage(v, e, d)", "e", expr); 01851 // `var' should be one of the dimensions of the grid. 01852 const dimension_type var_space_dim = var.space_dimension(); 01853 if (space_dim < var_space_dim) 01854 throw_dimension_incompatible("affine_preimage(v, e, d)", "v", var); 01855 01856 if (marked_empty()) 01857 return; 01858 01859 if (var_space_dim <= expr_space_dim && expr[var_space_dim] != 0) { 01860 // The transformation is invertible. 01861 if (congruences_are_up_to_date()) { 01862 // Congruence_System::affine_preimage() requires the third argument 01863 // to be a positive Coefficient. 01864 if (denominator > 0) 01865 con_sys.affine_preimage(var_space_dim, expr, denominator); 01866 else 01867 con_sys.affine_preimage(var_space_dim, -expr, -denominator); 01868 clear_congruences_minimized(); 01869 } 01870 if (generators_are_up_to_date()) { 01871 // To build the inverse transformation, 01872 // after copying and negating `expr', 01873 // we exchange the roles of `expr[var_space_dim]' and `denominator'. 01874 Linear_Expression inverse; 01875 if (expr[var_space_dim] > 0) { 01876 inverse = -expr; 01877 inverse[var_space_dim] = denominator; 01878 gen_sys.affine_image(var_space_dim, inverse, expr[var_space_dim]); 01879 } 01880 else { 01881 // The new denominator is negative: we negate everything once 01882 // more, as Grid_Generator_System::affine_image() requires the 01883 // third argument to be positive. 01884 inverse = expr; 01885 inverse[var_space_dim] = denominator; 01886 neg_assign(inverse[var_space_dim]); 01887 gen_sys.affine_image(var_space_dim, inverse, -expr[var_space_dim]); 01888 } 01889 clear_generators_minimized(); 01890 } 01891 } 01892 else { 01893 // The transformation is not invertible. 01894 // We need an up-to-date system of congruences. 01895 if (!congruences_are_up_to_date()) 01896 minimize(); 01897 // Congruence_System::affine_preimage() requires the third argument 01898 // to be a positive Coefficient. 01899 if (denominator > 0) 01900 con_sys.affine_preimage(var_space_dim, expr, denominator); 01901 else 01902 con_sys.affine_preimage(var_space_dim, -expr, -denominator); 01903 01904 clear_generators_up_to_date(); 01905 clear_congruences_minimized(); 01906 } 01907 PPL_ASSERT(OK()); 01908 }
| void Parma_Polyhedra_Library::Grid::ascii_dump | ( | std::ostream & | s | ) | const |
Writes to s an ASCII representation of *this.
Definition at line 2572 of file Grid_public.cc.
References Parma_Polyhedra_Library::Grid_Generator_System::ascii_dump(), Parma_Polyhedra_Library::Congruence_System::ascii_dump(), Parma_Polyhedra_Library::Grid::Status::ascii_dump(), con_sys, congruences_are_minimized(), congruences_are_up_to_date(), dim_kinds, gen_sys, generators_are_minimized(), generators_are_up_to_date(), space_dim, and status.
02572 { 02573 using std::endl; 02574 02575 s << "space_dim " 02576 << space_dim 02577 << endl; 02578 status.ascii_dump(s); 02579 s << "con_sys (" 02580 << (congruences_are_up_to_date() ? "" : "not_") 02581 << "up-to-date)" 02582 << endl; 02583 con_sys.ascii_dump(s); 02584 s << "gen_sys (" 02585 << (generators_are_up_to_date() ? "" : "not_") 02586 << "up-to-date)" 02587 << endl; 02588 gen_sys.ascii_dump(s); 02589 s << "dimension_kinds"; 02590 if ((generators_are_up_to_date() && generators_are_minimized()) 02591 || (congruences_are_up_to_date() && congruences_are_minimized())) 02592 for (Dimension_Kinds::const_iterator i = dim_kinds.begin(); 02593 i != dim_kinds.end(); 02594 ++i) 02595 s << " " << *i; 02596 s << endl; 02597 }
| void Parma_Polyhedra_Library::Grid::ascii_dump | ( | ) | const |
Writes to std::cerr an ASCII representation of *this.
Referenced by OK().
| bool Parma_Polyhedra_Library::Grid::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.
Definition at line 2602 of file Grid_public.cc.
02602 { 02603 std::string str; 02604 02605 if (!(s >> str) || str != "space_dim") 02606 return false; 02607 02608 if (!(s >> space_dim)) 02609 return false; 02610 02611 if (!status.ascii_load(s)) 02612 return false; 02613 02614 if (!(s >> str) || str != "con_sys") 02615 return false; 02616 02617 if (s >> str) { 02618 if (str == "(up-to-date)") 02619 set_congruences_up_to_date(); 02620 else if (str != "(not_up-to-date)") 02621 return false; 02622 } 02623 else 02624 return false; 02625 02626 if (!con_sys.ascii_load(s)) 02627 return false; 02628 02629 if (!(s >> str) || str != "gen_sys") 02630 return false; 02631 02632 if (s >> str) { 02633 if (str == "(up-to-date)") 02634 set_generators_up_to_date(); 02635 else if (str != "(not_up-to-date)") 02636 return false; 02637 } 02638 else 02639 return false; 02640 02641 if (!gen_sys.ascii_load(s)) 02642 return false; 02643 02644 if (!(s >> str) || str != "dimension_kinds") 02645 return false; 02646 02647 if (!marked_empty() 02648 && ((generators_are_up_to_date() && generators_are_minimized()) 02649 || (congruences_are_up_to_date() && congruences_are_minimized()))) { 02650 dim_kinds.resize(space_dim + 1); 02651 for (Dimension_Kinds::size_type dim = 0; dim <= space_dim; ++dim) { 02652 short unsigned int dim_kind; 02653 if (!(s >> dim_kind)) 02654 return false; 02655 switch(dim_kind) { 02656 case 0: dim_kinds[dim] = PARAMETER; break; 02657 case 1: dim_kinds[dim] = LINE; break; 02658 case 2: dim_kinds[dim] = GEN_VIRTUAL; break; 02659 default: return false; 02660 } 02661 } 02662 } 02663 02664 // Check invariants. 02665 PPL_ASSERT(OK()); 02666 return true; 02667 }
| void Parma_Polyhedra_Library::Grid::bounded_affine_image | ( | Variable | var, | |
| const Linear_Expression & | lb_expr, | |||
| const Linear_Expression & | ub_expr, | |||
| Coefficient_traits::const_reference | denominator = Coefficient_one() | |||
| ) |
Assigns to *this the image of *this with respect to the bounded affine relation
.
| var | The variable updated by the affine relation; | |
| lb_expr | The numerator of the lower bounding affine expression; | |
| ub_expr | The numerator of the upper bounding affine expression; | |
| denominator | The (common) denominator for the lower and upper bounding affine expressions (optional argument with default value 1). |
| std::invalid_argument | Thrown if denominator is zero or if lb_expr (resp., ub_expr) and *this are dimension-incompatible or if var is not a space dimension of *this. |
Definition at line 2351 of file Grid_public.cc.
References generalized_affine_image(), Parma_Polyhedra_Library::LESS_OR_EQUAL, marked_empty(), OK(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
02354 { 02355 02356 // The denominator cannot be zero. 02357 if (denominator == 0) 02358 throw_invalid_argument("bounded_affine_image(v, lb, ub, d)", "d == 0"); 02359 02360 // Dimension-compatibility checks. 02361 // `var' should be one of the dimensions of the grid. 02362 const dimension_type var_space_dim = var.space_dimension(); 02363 if (space_dim < var_space_dim) 02364 throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)", 02365 "v", var); 02366 // The dimension of `lb_expr' and `ub_expr' should not be 02367 // greater than the dimension of `*this'. 02368 const dimension_type lb_space_dim = lb_expr.space_dimension(); 02369 if (space_dim < lb_space_dim) 02370 throw_dimension_incompatible("bounded_affine_image(v, lb, ub)", 02371 "lb", lb_expr); 02372 const dimension_type ub_space_dim = ub_expr.space_dimension(); 02373 if (space_dim < ub_space_dim) 02374 throw_dimension_incompatible("bounded_affine_image(v, lb, ub)", 02375 "ub", ub_expr); 02376 02377 // Any image of an empty grid is empty. 02378 if (marked_empty()) 02379 return; 02380 02381 // In all other cases, generalized_affine_preimage() must 02382 // just add a line in the direction of var. 02383 generalized_affine_image(var, 02384 LESS_OR_EQUAL, 02385 ub_expr, 02386 denominator); 02387 02388 PPL_ASSERT(OK()); 02389 }
| void Parma_Polyhedra_Library::Grid::bounded_affine_preimage | ( | Variable | var, | |
| const Linear_Expression & | lb_expr, | |||
| const Linear_Expression & | ub_expr, | |||
| Coefficient_traits::const_reference | denominator = Coefficient_one() | |||
| ) |
Assigns to *this the preimage of *this with respect to the bounded affine relation
.
| var | The variable updated by the affine relation; | |
| lb_expr | The numerator of the lower bounding affine expression; | |
| ub_expr | The numerator of the upper bounding affine expression; | |
| denominator | The (common) denominator for the lower and upper bounding affine expressions (optional argument with default value 1). |
| std::invalid_argument | Thrown if denominator is zero or if lb_expr (resp., ub_expr) and *this are dimension-incompatible or if var is not a space dimension of *this. |
Definition at line 2394 of file Grid_public.cc.
References generalized_affine_preimage(), Parma_Polyhedra_Library::LESS_OR_EQUAL, marked_empty(), OK(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
02397 { 02398 02399 // The denominator cannot be zero. 02400 if (denominator == 0) 02401 throw_invalid_argument("bounded_affine_preimage(v, lb, ub, d)", "d == 0"); 02402 02403 // Dimension-compatibility checks. 02404 // `var' should be one of the dimensions of the grid. 02405 const dimension_type var_space_dim = var.space_dimension(); 02406 if (space_dim < var_space_dim) 02407 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)", 02408 "v", var); 02409 // The dimension of `lb_expr' and `ub_expr' should not be 02410 // greater than the dimension of `*this'. 02411 const dimension_type lb_space_dim = lb_expr.space_dimension(); 02412 if (space_dim < lb_space_dim) 02413 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)", 02414 "lb", lb_expr); 02415 const dimension_type ub_space_dim = ub_expr.space_dimension(); 02416 if (space_dim < ub_space_dim) 02417 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)", 02418 "ub", ub_expr); 02419 02420 // Any preimage of an empty grid is empty. 02421 if (marked_empty()) 02422 return; 02423 02424 // In all other cases, generalized_affine_preimage() must 02425 // just add a line in the direction of var. 02426 generalized_affine_preimage(var, 02427 LESS_OR_EQUAL, 02428 ub_expr, 02429 denominator); 02430 02431 PPL_ASSERT(OK()); 02432 }
| bool Parma_Polyhedra_Library::Grid::bounds | ( | const Linear_Expression & | expr, | |
| const char * | method_call | |||
| ) | const [private] |
Checks if and how expr is bounded in *this.
Returns true if and only if from_above is true and expr is bounded from above in *this, or from_above is false and expr is bounded from below in *this.
| expr | The linear expression to test; | |
| 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. |
| std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
Definition at line 275 of file Grid_nonpublic.cc.
References bounds_no_check(), generators_are_minimized(), generators_are_up_to_date(), marked_empty(), minimize(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and update_generators().
Referenced by bounds_from_above(), bounds_from_below(), and max_min().
00276 { 00277 // The dimension of `expr' must be at most the dimension of *this. 00278 if (space_dim < expr.space_dimension()) 00279 throw_dimension_incompatible(method_call, "e", expr); 00280 00281 // A zero-dimensional or empty grid bounds everything. 00282 if (space_dim == 0 00283 || marked_empty() 00284 || (!generators_are_up_to_date() && !update_generators())) 00285 return true; 00286 if (!generators_are_minimized() && !minimize()) 00287 // Minimizing found `this' empty. 00288 return true; 00289 00290 return bounds_no_check(expr); 00291 }
| bool Parma_Polyhedra_Library::Grid::bounds_from_above | ( | const Linear_Expression & | expr | ) | const [inline] |
Returns true if and only if expr is bounded in *this.
This method is the same as bounds_from_below.
| std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
Definition at line 312 of file Grid.inlines.hh.
References bounds().
00312 { 00313 return bounds(expr, "bounds_from_above(e)"); 00314 }
| bool Parma_Polyhedra_Library::Grid::bounds_from_below | ( | const Linear_Expression & | expr | ) | const [inline] |
Returns true if and only if expr is bounded in *this.
This method is the same as bounds_from_above.
| std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
Definition at line 317 of file Grid.inlines.hh.
References bounds().
00317 { 00318 return bounds(expr, "bounds_from_below(e)"); 00319 }
| bool Parma_Polyhedra_Library::Grid::bounds_no_check | ( | const Linear_Expression & | expr | ) | const [private] |
Checks if and how expr is bounded in *this.
Returns true if and only if from_above is true and expr is bounded from above in *this, or from_above is false and expr is bounded from below in *this.
| expr | The linear expression to test; |
Definition at line 294 of file Grid_nonpublic.cc.
References gen_sys, generators_are_minimized(), Parma_Polyhedra_Library::Scalar_Products::homogeneous_sign(), Parma_Polyhedra_Library::Grid_Generator::is_line_or_parameter(), marked_empty(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), space_dim, and Parma_Polyhedra_Library::Linear_Expression::space_dimension().
Referenced by bounds(), frequency_no_check(), and wrap_assign().
00294 { 00295 // The dimension of `expr' must be at most the dimension of *this. 00296 PPL_ASSERT(space_dim > 0 && space_dim >= expr.space_dimension()); 00297 PPL_ASSERT(generators_are_minimized() && !marked_empty()); 00298 00299 // The generators are up to date and minimized. 00300 for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) { 00301 const Grid_Generator& g = gen_sys[i]; 00302 // Only lines and parameters in `*this' can cause `expr' to be 00303 // unbounded. 00304 if (g.is_line_or_parameter()) { 00305 const int sp_sign = Scalar_Products::homogeneous_sign(expr, g); 00306 if (sp_sign != 0) 00307 // `*this' does not bound `expr'. 00308 return false; 00309 } 00310 } 00311 return true; 00312 }
| bool Parma_Polyhedra_Library::Grid::can_recycle_congruence_systems | ( | ) | [inline, static] |
Returns true indicating that this domain has methods that can recycle congruences.
Definition at line 292 of file Grid.inlines.hh.
| bool Parma_Polyhedra_Library::Grid::can_recycle_constraint_systems | ( | ) | [inline, static] |
Returns true indicating that this domain has methods that can recycle constraints.
Definition at line 287 of file Grid.inlines.hh.
| void Parma_Polyhedra_Library::Grid::clear_congruences_minimized | ( | ) | [inline, private] |
Sets status to express that congruences are no longer minimized.
Definition at line 87 of file Grid.inlines.hh.
References Parma_Polyhedra_Library::Grid::Status::reset_c_minimized(), and status.
Referenced by add_congruence_no_check(), add_recycled_congruences(), affine_image(), affine_preimage(), clear_congruences_up_to_date(), concatenate_assign(), intersection_assign(), and map_space_dimensions().
00087 { 00088 status.reset_c_minimized(); 00089 }
| void Parma_Polyhedra_Library::Grid::clear_congruences_up_to_date | ( | ) | [inline, private] |
Sets status to express that congruences are out of date.
Definition at line 97 of file Grid.inlines.hh.
References clear_congruences_minimized(), Parma_Polyhedra_Library::Grid::Status::reset_c_up_to_date(), and status.
Referenced by add_grid_generator(), add_recycled_grid_generators(), affine_image(), generalized_affine_image(), generalized_affine_preimage(), remove_higher_space_dimensions(), remove_space_dimensions(), time_elapse_assign(), unconstrain(), and upper_bound_assign().
00097 { 00098 clear_congruences_minimized(); 00099 status.reset_c_up_to_date(); 00100 // Can get rid of con_sys here. 00101 }
| void Parma_Polyhedra_Library::Grid::clear_empty | ( | ) | [inline, private] |
Clears the status flag indicating that the grid is empty.
Definition at line 82 of file Grid.inlines.hh.
References Parma_Polyhedra_Library::Grid::Status::reset_empty(), and status.
Referenced by add_grid_generator(), and add_recycled_grid_generators().
00082 { 00083 status.reset_empty(); 00084 }
| void Parma_Polyhedra_Library::Grid::clear_generators_minimized | ( | ) | [inline, private] |
Sets status to express that generators are no longer minimized.
Definition at line 92 of file Grid.inlines.hh.
References Parma_Polyhedra_Library::Grid::Status::reset_g_minimized(), and status.
Referenced by add_grid_generator(), add_recycled_grid_generators(), affine_image(), affine_preimage(), clear_generators_up_to_date(), generalized_affine_image(), generalized_affine_preimage(), map_space_dimensions(), remove_space_dimensions(), time_elapse_assign(), unconstrain(), and upper_bound_assign().
00092 { 00093 status.reset_g_minimized(); 00094 }
| void Parma_Polyhedra_Library::Grid::clear_generators_up_to_date | ( | ) | [inline, private] |
Sets status to express that generators are out of date.
Definition at line 104 of file Grid.inlines.hh.
References clear_generators_minimized(), Parma_Polyhedra_Library::Grid::Status::reset_g_up_to_date(), and status.
Referenced by add_congruence_no_check(), add_recycled_congruences(), affine_preimage(), concatenate_assign(), intersection_assign(), OK(), and remove_higher_space_dimensions().
00104 { 00105 clear_generators_minimized(); 00106 status.reset_g_up_to_date(); 00107 // Can get rid of gen_sys here. 00108 }
| void Parma_Polyhedra_Library::Grid::concatenate_assign | ( | const Grid & | y | ) |
Assigns to *this the concatenation of *this and y, taken in this order.
| std::length_error | Thrown if the concatenation would cause the vector space to exceed dimension max_space_dimension(). |
Definition at line 218 of file Grid_chdims.cc.
References clear_congruences_minimized(), clear_generators_up_to_date(), con_sys, Parma_Polyhedra_Library::Congruence_System::concatenate(), congruences(), congruences_are_up_to_date(), marked_empty(), max_space_dimension(), OK(), set_empty(), space_dim, space_dimension(), throw_space_dimension_overflow(), and update_congruences().
00218 { 00219 // The space dimension of the resulting grid must be at most the 00220 // maximum allowed space dimension. 00221 if (y.space_dim > max_space_dimension() - space_dimension()) 00222 throw_space_dimension_overflow("concatenate_assign(y)", 00223 "concatenation exceeds the maximum " 00224 "allowed space dimension"); 00225 00226 const dimension_type added_columns = y.space_dim; 00227 00228 // If `*this' or `y' are empty grids just adjust the space 00229 // dimension. 00230 if (marked_empty() || y.marked_empty()) { 00231 space_dim += added_columns; 00232 set_empty(); 00233 return; 00234 } 00235 00236 // If `y' is a universe 0-dim grid, the result is `*this'. 00237 if (added_columns == 0) 00238 return; 00239 00240 // If `*this' is a universe 0-dim space grid, the result is `y'. 00241 if (space_dim == 0) { 00242 *this = y; 00243 return; 00244 } 00245 00246 if (!congruences_are_up_to_date()) 00247 update_congruences(); 00248 00249 con_sys.concatenate(y.congruences()); 00250 00251 space_dim += added_columns; 00252 00253 clear_congruences_minimized(); 00254 clear_generators_up_to_date(); 00255 00256 // Check that the system is OK, taking into account that the system 00257 // of congruences may now be empty. 00258 PPL_ASSERT(OK()); 00259 }
| void Parma_Polyhedra_Library::Grid::congruence_widening_assign | ( | const Grid & | y, | |
| unsigned * | tp = NULL | |||
| ) |
Assigns to *this the result of computing the Grid widening between *this and y using congruence systems.
| y | A grid that must be contained in *this; | |
| tp | An optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique). |
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 76 of file Grid_widenings.cc.
References add_recycled_congruences(), con_sys, congruences_are_minimized(), congruences_are_up_to_date(), contains(), dim_kinds, marked_empty(), Parma_Polyhedra_Library::Congruence_System::num_equalities(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), select_wider_congruences(), set_congruences_minimized(), set_empty(), simplify(), space_dim, swap(), throw_dimension_incompatible(), and update_congruences().
Referenced by limited_congruence_extrapolation_assign(), and widening_assign().
00076 { 00077 Grid& x = *this; 00078 Grid& y = const_cast<Grid&>(const_y); 00079 // Dimension-compatibility check. 00080 if (x.space_dim != y.space_dim) 00081 throw_dimension_incompatible("widening_assign(y)", "y", y); 00082 00083 // Stable behavior is only guaranteed if y is contained in or equal 00084 // to x. 00085 #ifndef NDEBUG 00086 { 00087 // Assume y is contained in or equal to x. 00088 const Grid x_copy = x; 00089 const Grid y_copy = y; 00090 PPL_ASSERT(x_copy.contains(y_copy)); 00091 } 00092 #endif 00093 00094 // Leave `x' the same if `x' or `y' is zero-dimensional or empty. 00095 if (x.space_dim == 0 || x.marked_empty() || y.marked_empty()) 00096 return; 00097 00098 // Ensure that the `x' congruences are in minimal form. 00099 if (x.congruences_are_up_to_date()) { 00100 if (!x.congruences_are_minimized()) { 00101 if (simplify(x.con_sys, x.dim_kinds)) { 00102 // `x' is empty. 00103 x.set_empty(); 00104 return; 00105 } 00106 x.set_congruences_minimized(); 00107 } 00108 } 00109 else 00110 x.update_congruences(); 00111 00112 // Ensure that the `y' congruences are in minimal form. 00113 if (y.congruences_are_up_to_date()) { 00114 if (!y.congruences_are_minimized()) { 00115 if (simplify(y.con_sys, y.dim_kinds)) { 00116 // `y' is empty. 00117 y.set_empty(); 00118 return; 00119 } 00120 y.set_congruences_minimized(); 00121 } 00122 } 00123 else 00124 y.update_congruences(); 00125 00126 if (con_sys.num_equalities() < y.con_sys.num_equalities()) 00127 return; 00128 00129 // Copy into `cgs' the congruences of `x' that are common to `y', 00130 // according to the grid widening. 00131 Congruence_System cgs; 00132 x.select_wider_congruences(y, cgs); 00133 00134 if (cgs.num_rows() == con_sys.num_rows()) 00135 // All congruences were selected, thus the result is `x'. 00136 return; 00137 00138 // A strict subset of the congruences was selected. 00139 00140 Grid result(x.space_dim); 00141 result.add_recycled_congruences(cgs); 00142 00143 // Check whether we are using the widening-with-tokens technique 00144 // and there are still tokens available. 00145 if (tp && *tp > 0) { 00146 // There are tokens available. If `result' is not a subset of 00147 // `x', then it is less precise and we use one of the available 00148 // tokens. 00149 if (!x.contains(result)) 00150 --(*tp); 00151 } 00152 else 00153 // No tokens. 00154 std::swap(x, result); 00155 00156 PPL_ASSERT(x.OK(true)); 00157 }
| const PPL::Congruence_System & Parma_Polyhedra_Library::Grid::congruences | ( | ) | const |
Returns the system of congruences.
Definition at line 279 of file Grid_public.cc.
References con_sys, congruences_are_up_to_date(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), space_dim, and update_congruences().
Referenced by Parma_Polyhedra_Library::Pointset_Powerset< PSET >::approximate_partition(), Parma_Polyhedra_Library::Pointset_Powerset< PSET >::approximate_partition_aux(), concatenate_assign(), constraints(), difference_assign(), expand_space_dimension(), and minimized_congruences().
00279 { 00280 if (marked_empty()) 00281 return con_sys; 00282 00283 if (space_dim == 0) { 00284 // Zero-dimensional universe. 00285 PPL_ASSERT(con_sys.num_rows() == 0 && con_sys.num_columns() == 2); 00286 return con_sys; 00287 } 00288 00289 if (!congruences_are_up_to_date()) 00290 update_congruences(); 00291 00292 return con_sys; 00293 }
| bool Parma_Polyhedra_Library::Grid::congruences_are_minimized | ( | ) | const [inline, private] |
Returns true if the system of congruences is minimized.
Definition at line 50 of file Grid.inlines.hh.
References status, and Parma_Polyhedra_Library::Grid::Status::test_c_minimized().
Referenced by add_space_dimensions(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_dimension(), ascii_dump(), congruence_widening_assign(), Parma_Polyhedra_Library::Grid_Certificate::Grid_Certificate(), is_empty(), is_included_in(), is_universe(), minimize(), minimized_congruences(), OK(), quick_equivalence_test(), remove_higher_space_dimensions(), select_wider_congruences(), simplify_using_context_assign(), and update_generators().
00050 { 00051 return status.test_c_minimized(); 00052 }
| bool Parma_Polyhedra_Library::Grid::congruences_are_up_to_date | ( | ) | const [inline, private] |
Returns true if the system of congruences is up-to-date.
Definition at line 40 of file Grid.inlines.hh.
References status, and Parma_Polyhedra_Library::Grid::Status::test_c_up_to_date().
Referenced by add_congruence_no_check(), add_recycled_congruences(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_dimension(), affine_image(), affine_preimage(), ascii_dump(), concatenate_assign(), congruence_widening_assign(), congruences(), constrains(), Grid(), Parma_Polyhedra_Library::Grid_Certificate::Grid_Certificate(), intersection_assign(), is_included_in(), is_universe(), map_space_dimensions(), minimize(), minimized_congruences(), OK(), operator=(), relation_with(), simplify_using_context_assign(), update_generators(), and widening_assign().
00040 { 00041 return status.test_c_up_to_date(); 00042 }
| bool Parma_Polyhedra_Library::Grid::constrains | ( | Variable | var | ) | const |
Returns true if and only if var is constrained in *this.
| std::invalid_argument | Thrown if var is not a space dimension of *this. |
Definition at line 800 of file Grid_public.cc.
References Parma_Polyhedra_Library::Grid_Generator::coefficient(), con_sys, congruences_are_up_to_date(), gen_sys, generators_are_minimized(), generators_are_up_to_date(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Grid_Generator::is_line(), marked_empty(), minimize(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), throw_dimension_incompatible(), and update_congruences().
00800 { 00801 // `var' should be one of the dimensions of the grid. 00802 const dimension_type var_space_dim = var.space_dimension(); 00803 if (space_dim < var_space_dim) 00804 throw_dimension_incompatible("constrains(v)", "v", var); 00805 00806 // An empty grid constrains all variables. 00807 if (marked_empty()) 00808 return true; 00809 00810 if (generators_are_up_to_date()) { 00811 // Since generators are up-to-date, the generator system (since it is 00812 // well formed) contains a point. Hence the grid is not empty. 00813 if (congruences_are_up_to_date()) 00814 // Here a variable is constrained if and only if it is 00815 // syntactically constrained. 00816 goto syntactic_check; 00817 00818 if (generators_are_minimized()) { 00819 // Try a quick, incomplete check for the universe grid: 00820 // a universe grid constrains no variable. 00821 // Count the number of lines (they are linearly independent). 00822 dimension_type num_lines = 0; 00823 for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) 00824 if (gen_sys[i].is_line()) 00825 ++num_lines; 00826 00827 if (num_lines == space_dim) 00828 return false; 00829 } 00830 00831 // Scan generators: perhaps we will find line(var). 00832 const dimension_type var_id = var.id(); 00833 for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) { 00834 const Grid_Generator& g_i = gen_sys[i]; 00835 if (g_i.is_line()) { 00836 if (sgn(g_i.coefficient(var)) != 0) { 00837 for (dimension_type j = 0; j < space_dim; ++j) 00838 if (g_i.coefficient(Variable(j)) != 0 && j != var_id) 00839 goto next; 00840 return true; 00841 } 00842 } 00843 next: 00844 ; 00845 } 00846 00847 // We are still here: at least we know that the grid is not empty. 00848 update_congruences(); 00849 goto syntactic_check; 00850 } 00851 00852 // We must minimize to detect emptiness and obtain constraints. 00853 if (!minimize()) 00854 return true; 00855 00856 syntactic_check: 00857 for (dimension_type i = con_sys.num_rows(); i-- > 0; ) 00858 if (con_sys[i].coefficient(var) != 0) 00859 return true; 00860 return false; 00861 }
| Constraint_System Parma_Polyhedra_Library::Grid::constraints | ( | ) | const [inline] |
Returns a system of equality constraints satisfied by *this with the same affine dimension as *this.
Definition at line 235 of file Grid.inlines.hh.
References congruences().
Referenced by Parma_Polyhedra_Library::C_Polyhedron::C_Polyhedron(), and Parma_Polyhedra_Library::NNC_Polyhedron::NNC_Polyhedron().
00235 { 00236 return Constraint_System(congruences());; 00237 }
| void Parma_Polyhedra_Library::Grid::construct | ( | Grid_Generator_System & | ggs | ) | [private] |
Builds a grid from a system of grid generators.
The grid inherits the space dimension of the generator system.
| ggs | The system of grid generators defining the grid. Its data-structures may be recycled to build the grid. |
Definition at line 143 of file Grid_nonpublic.cc.
References con_sys, gen_sys, Parma_Polyhedra_Library::Matrix::has_no_rows(), Parma_Polyhedra_Library::Grid_Generator_System::has_points(), Parma_Polyhedra_Library::Congruence_System::insert(), max_space_dimension(), normalize_divisors(), OK(), Parma_Polyhedra_Library::Grid::Status::set_empty(), set_generators_up_to_date(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Congruence_System::space_dimension(), Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), status, swap(), throw_invalid_generators(), and Parma_Polyhedra_Library::Congruence::zero_dim_false().
00143 { 00144 // Protecting against space dimension overflow is up to the caller. 00145 PPL_ASSERT(ggs.space_dimension() <= max_space_dimension()); 00146 // Preparing con_sys and gen_sys is up to the caller. 00147 PPL_ASSERT(ggs.space_dimension() == con_sys.space_dimension()); 00148 PPL_ASSERT(ggs.space_dimension() == gen_sys.space_dimension()); 00149 PPL_ASSERT(con_sys.has_no_rows()); 00150 PPL_ASSERT(gen_sys.has_no_rows()); 00151 00152 // Set the space dimension. 00153 space_dim = ggs.space_dimension(); 00154 00155 // An empty set of generators defines the empty grid. 00156 if (ggs.has_no_rows()) { 00157 status.set_empty(); 00158 // Insert the zero dim false congruence system into `con_sys'. 00159 // `gen_sys' is already in empty form. 00160 con_sys.insert(Congruence::zero_dim_false()); 00161 return; 00162 } 00163 00164 // Non-empty valid generator systems have a supporting point, at least. 00165 if (!ggs.has_points()) 00166 throw_invalid_generators("Grid(ggs)", "ggs"); 00167 00168 if (space_dim == 0) 00169 set_zero_dim_univ(); 00170 else { 00171 // Steal the rows from `ggs'. 00172 std::swap(gen_sys, ggs); 00173 normalize_divisors(gen_sys); 00174 // Generators are now up-to-date. 00175 set_generators_up_to_date(); 00176 } 00177 00178 PPL_ASSERT(OK()); 00179 }
| void Parma_Polyhedra_Library::Grid::construct | ( | Congruence_System & | cgs | ) | [private] |
Builds a grid from a system of congruences.
The grid inherits the space dimension of the congruence system.
| cgs | The system of congruences defining the grid. Its data-structures may be recycled to build the grid. |
Definition at line 105 of file Grid_nonpublic.cc.
References con_sys, gen_sys, Parma_Polyhedra_Library::Matrix::has_no_rows(), Parma_Polyhedra_Library::Congruence_System::insert(), max_space_dimension(), Parma_Polyhedra_Library::Congruence_System::normalize_moduli(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), set_congruences_up_to_date(), Parma_Polyhedra_Library::Grid::Status::set_empty(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), Parma_Polyhedra_Library::Congruence_System::space_dimension(), status, swap(), and Parma_Polyhedra_Library::Congruence::zero_dim_false().
00105 { 00106 // Protecting against space dimension overflow is up to the caller. 00107 PPL_ASSERT(cgs.space_dimension() <= max_space_dimension()); 00108 // Preparing con_sys and gen_sys is up to the caller. 00109 PPL_ASSERT(cgs.space_dimension() == con_sys.space_dimension()); 00110 PPL_ASSERT(cgs.space_dimension() == gen_sys.space_dimension()); 00111 PPL_ASSERT(con_sys.has_no_rows()); 00112 PPL_ASSERT(gen_sys.has_no_rows()); 00113 00114 // Set the space dimension. 00115 space_dim = cgs.space_dimension(); 00116 00117 if (space_dim > 0) { 00118 // Stealing the rows from `cgs'. 00119 std::swap(con_sys, cgs); 00120 con_sys.normalize_moduli(); 00121 set_congruences_up_to_date(); 00122 } 00123 else { 00124 // Here `space_dim == 0'. 00125 if (cgs.num_columns() > 1) 00126 // See if an inconsistent congruence has been passed. 00127 for (dimension_type i = cgs.num_rows(); i-- > 0; ) 00128 if (cgs[i].is_inconsistent()) { 00129 // Inconsistent congruence found: the grid is empty. 00130 status.set_empty(); 00131 // Insert the zero dim false congruence system into `con_sys'. 00132 // `gen_sys' is already in empty form. 00133 con_sys.insert(Congruence::zero_dim_false()); 00134 PPL_ASSERT(OK()); 00135 return; 00136 } 00137 set_zero_dim_univ(); 00138 } 00139 PPL_ASSERT(OK()); 00140 }
| void Parma_Polyhedra_Library::Grid::construct | ( | dimension_type | num_dimensions, | |
| Degenerate_Element | kind | |||
| ) | [private] |
Builds a grid universe or empty grid.
| num_dimensions | The number of dimensions of the vector space enclosing the grid; | |
| kind | specifies whether the universe or the empty grid has to be built. |
Definition at line 52 of file Grid_nonpublic.cc.
References con_sys, CON_VIRTUAL, dim_kinds, Parma_Polyhedra_Library::EMPTY, gen_sys, Parma_Polyhedra_Library::Congruence_System::increase_space_dimension(), Parma_Polyhedra_Library::Grid_Generator_System::insert(), OK(), PROPER_CONGRUENCE, set_congruences_minimized(), Parma_Polyhedra_Library::Grid::Status::set_empty(), set_generators_minimized(), set_zero_dim_univ(), space_dim, status, Parma_Polyhedra_Library::Congruence_System::swap(), swap(), Parma_Polyhedra_Library::Congruence::zero_dim_false(), and Parma_Polyhedra_Library::Congruence::zero_dim_integrality().
Referenced by Grid().
00053 { 00054 space_dim = num_dimensions; 00055 00056 if (kind == EMPTY) { 00057 // Set emptiness directly instead of with set_empty, as gen_sys is 00058 // already correctly initialized. 00059 00060 status.set_empty(); 00061 00062 // Extend the zero dim false congruence system to the appropriate 00063 // dimension and then store it in `con_sys'. 00064 Congruence_System cgs(Congruence::zero_dim_false()); 00065 cgs.increase_space_dimension(space_dim); 00066 const_cast<Congruence_System&>(con_sys).swap(cgs); 00067 00068 PPL_ASSERT(OK()); 00069 return; 00070 } 00071 00072 if (num_dimensions > 0) { 00073 con_sys.increase_space_dimension(num_dimensions); 00074 00075 // Initialize both systems to universe representations. 00076 00077 set_congruences_minimized(); 00078 set_generators_minimized(); 00079 dim_kinds.resize(num_dimensions + 1); 00080 00081 // Extend the zero dim integrality congruence system to the 00082 // appropriate dimension and then store it in `con_sys'. 00083 Congruence_System cgs(Congruence::zero_dim_integrality()); 00084 cgs.increase_space_dimension(space_dim); 00085 cgs[0][0] = 1; // Recover minimal form after cgs(zdi) normalization. 00086 con_sys.swap(cgs); 00087 00088 dim_kinds[0] = PROPER_CONGRUENCE /* a.k.a. PARAMETER */; 00089 00090 // Trivially true point. 00091 gen_sys.insert(grid_point(0*(Variable(0)))); 00092 00093 // A line for each dimension. 00094 dimension_type dim = 0; 00095 while (dim < num_dimensions) { 00096 gen_sys.insert(grid_line(Variable(dim))); 00097 dim_kinds[++dim] = CON_VIRTUAL /* a.k.a. LINE */; 00098 } 00099 } 00100 else 00101 set_zero_dim_univ(); 00102 }
| bool Parma_Polyhedra_Library::Grid::contains | ( | const Grid & | y | ) | const |
Returns true if and only if *this contains y.
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 2543 of file Grid_public.cc.
References is_empty(), is_included_in(), marked_empty(), quick_equivalence_test(), space_dim, throw_dimension_incompatible(), and TVB_TRUE.
Referenced by Parma_Polyhedra_Library::Pointset_Powerset< PSET >::check_containment(), congruence_widening_assign(), difference_assign(), generator_widening_assign(), limited_congruence_extrapolation_assign(), limited_extrapolation_assign(), limited_generator_extrapolation_assign(), strictly_contains(), and widening_assign().
02543 { 02544 const Grid& x = *this; 02545 02546 // Dimension-compatibility check. 02547 if (x.space_dim != y.space_dim) 02548 throw_dimension_incompatible("contains(y)", "y", y); 02549 02550 if (y.marked_empty()) 02551 return true; 02552 if (x.marked_empty()) 02553 return y.is_empty(); 02554 if (y.space_dim == 0) 02555 return true; 02556 if (x.quick_equivalence_test(y) == Grid::TVB_TRUE) 02557 return true; 02558 return y.is_included_in(x); 02559 }
| bool Parma_Polyhedra_Library::Grid::contains_integer_point | ( | ) | const |
Returns true if and only if *this contains at least one integer point.
Definition at line 778 of file Grid_public.cc.
References add_recycled_congruences(), Parma_Polyhedra_Library::Congruence_System::insert(), is_empty(), marked_empty(), and space_dim.
00778 { 00779 // Empty grids have no points. 00780 if (marked_empty()) 00781 return false; 00782 00783 // A zero-dimensional, universe grid has, by convention, an 00784 // integer point. 00785 if (space_dim == 0) 00786 return true; 00787 00788 // A grid has an integer point if its intersection with the integer 00789 // grid is non-empty. 00790 Congruence_System cgs; 00791 for (dimension_type var_index = space_dim; var_index-- > 0; ) 00792 cgs.insert(Variable(var_index) %= 0); 00793 00794 Grid gr = *this; 00795 gr.add_recycled_congruences(cgs); 00796 return !gr.is_empty(); 00797 }
| void Parma_Polyhedra_Library::Grid::conversion | ( | Grid_Generator_System & | source, | |
| Congruence_System & | dest, | |||
| Dimension_Kinds & | dim_kinds | |||
| ) | [static, private] |
Converts congruence system dest to be equivalent to generator system source.
Definition at line 155 of file Grid_conversion.cc.
References CON_VIRTUAL, Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::gcd_assign(), GEN_VIRTUAL, Parma_Polyhedra_Library::lcm_assign(), LINE, lower_triangular(), multiply_grid(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), PARAMETER, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Congruence_System::resize_no_copy(), Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), Parma_Polyhedra_Library::sub_mul_assign(), and upper_triangular().
00156 { 00157 // Quite similar to the congruence to generator version below. 00158 // Changes here may be needed there too. 00159 00160 PPL_ASSERT(upper_triangular(source, dim_kinds)); 00161 00162 // Initialize matrix row number counters and compute the LCM of the 00163 // diagonal entries of the parameters in `source'. 00164 // 00165 // The top-down order of the generator system rows corresponds to 00166 // the left-right order of the dimensions, while the congruence 00167 // system rows have a bottom-up ordering. 00168 dimension_type dest_num_rows = 0; 00169 PPL_DIRTY_TEMP_COEFFICIENT(diagonal_lcm); 00170 diagonal_lcm = 1; 00171 const dimension_type dims = source.space_dimension() + 1; 00172 dimension_type source_index = source.num_rows(); 00173 for (dimension_type dim = dims; dim-- > 0; ) 00174 if (dim_kinds[dim] == GEN_VIRTUAL) 00175 // Virtual generators map to equalities. 00176 ++dest_num_rows; 00177 else { 00178 --source_index; 00179 if (dim_kinds[dim] == PARAMETER) { 00180 // Dimension `dim' has a parameter row at `source_index' in 00181 // `source', so include in `diagonal_lcm' the `dim'th element 00182 // of that row. 00183 lcm_assign(diagonal_lcm, diagonal_lcm, source[source_index][dim]); 00184 // Parameters map to proper congruences. 00185 ++dest_num_rows; 00186 } 00187 // Lines map to virtual congruences. 00188 } 00189 PPL_ASSERT(source_index == 0); 00190 00191 // `source' must be regular. 00192 if (diagonal_lcm == 0) 00193 throw std::runtime_error("PPL internal error: Grid::conversion:" 00194 " source matrix is singular."); 00195 00196 dest.resize_no_copy(dest_num_rows, dims + 1 /* moduli */); 00197 00198 // In `dest' initialize row types and elements, including setting 00199 // the diagonal elements to the inverse ratio of the `source' 00200 // diagonal elements. 00201 dimension_type dest_index = 0; 00202 source_index = source.num_rows(); 00203 for (dimension_type dim = dims; dim-- > 0; ) { 00204 if (dim_kinds[dim] == LINE) 00205 --source_index; 00206 else { 00207 Congruence& cg = dest[dest_index]; 00208 for (dimension_type j = dim; j-- > 0; ) 00209 cg[j] = 0; 00210 for (dimension_type j = dim + 1; j < dims; ++j) 00211 cg[j] = 0; 00212 00213 if (dim_kinds[dim] == GEN_VIRTUAL) { 00214 cg[dims] = 0; // An equality. 00215 cg[dim] = 1; 00216 } 00217 else { 00218 PPL_ASSERT(dim_kinds[dim] == PARAMETER); 00219 --source_index; 00220 cg[dims] = 1; // A proper congruence. 00221 exact_div_assign(cg[dim], diagonal_lcm, source[source_index][dim]); 00222 } 00223 ++dest_index; 00224 } 00225 } 00226 00227 PPL_ASSERT(source_index == 0); 00228 PPL_ASSERT(dest_index == dest_num_rows); 00229 PPL_ASSERT(lower_triangular(dest, dim_kinds)); 00230 00231 // Convert. 00232 // 00233 // `source_index' and `dest_index' hold the positions of pivot rows 00234 // in `source' and `dest'. The order of the rows in `dest' is the 00235 // reverse of the order in `source', so the rows are iterated from 00236 // last to first (index 0) in `source' and from first to last in 00237 // `dest'. 00238 source_index = source.num_rows(); 00239 dest_index = 0; 00240 PPL_DIRTY_TEMP_COEFFICIENT(multiplier); 00241 00242 for (dimension_type dim = dims; dim-- > 0; ) { 00243 if (dim_kinds[dim] != GEN_VIRTUAL) { 00244 --source_index; 00245 const Coefficient& source_dim = source[source_index][dim]; 00246 00247 // In the rows in `dest' above `dest_index' divide each element 00248 // at column `dim' by `source_dim'. 00249 for (dimension_type row = dest_index; row-- > 0; ) { 00250 Congruence& cg = dest[row]; 00251 00252 // Multiply the representation of `dest' such that entry `dim' 00253 // of `g' is a multiple of `source_dim'. This ensures that 00254 // the result of the division that follows is a whole number. 00255 gcd_assign(multiplier, cg[dim], source_dim); 00256 exact_div_assign(multiplier, source_dim, multiplier); 00257 multiply_grid(multiplier, cg, dest, dest_num_rows, dims); 00258 00259 Coefficient& cg_dim = cg[dim]; 00260 exact_div_assign(cg_dim, cg_dim, source_dim); 00261 } 00262 } 00263 00264 // Invert and transpose the source row at `source_index' into the 00265 // destination row at `dest_index'. 00266 // 00267 // Consider each dimension `dim_prec' that precedes `dim', as the 00268 // rows in `dest' that follow `dim_index' have zeroes at index 00269 // `dim'. 00270 dimension_type tmp_source_index = source_index; 00271 if (dim_kinds[dim] != LINE) 00272 ++dest_index; 00273 for (dimension_type dim_prec = dim; dim_prec-- > 0; ) { 00274 if (dim_kinds[dim_prec] != GEN_VIRTUAL) { 00275 --tmp_source_index; 00276 const Coefficient& source_dim = source[tmp_source_index][dim]; 00277 // In order to compute the transpose of the inverse of 00278 // `source', subtract source[tmp_source_index][dim] times the 00279 // column vector in `dest' at `dim' from the column vector in 00280 // `dest' at `dim_prec'. 00281 // 00282 // I.e., for each row `dest_index' in `dest' that is above the 00283 // row `dest_index', subtract dest[tmp_source_index][dim] 00284 // times the entry `dim' from the entry at `dim_prec'. 00285 for (dimension_type row = dest_index; row-- > 0; ) { 00286 PPL_ASSERT(row < dest_num_rows); 00287 Congruence& cg = dest[row]; 00288 sub_mul_assign(cg[dim_prec], source_dim, cg[dim]); 00289 } 00290 } 00291 } 00292 } 00293 // Set the modulus in every congruence. 00294 const Coefficient& modulus = dest[dest_num_rows - 1][0]; 00295 for (dimension_type row = dest_num_rows; row-- > 0; ) { 00296 Congruence& cg = dest[row]; 00297 if (cg[dims] > 0) 00298 // `cg' is a proper congruence. 00299 cg[dims] = modulus; 00300 } 00301 00302 PPL_ASSERT(lower_triangular(dest, dim_kinds)); 00303 00304 // Since we are reducing the system to "strong minimal form", 00305 // reduce the coefficients in the congruence system 00306 // using "diagonal" values. 00307 for (dimension_type dim = dims, i = 0; dim-- > 0; ) 00308 if (dim_kinds[dim] != CON_VIRTUAL) 00309 // Factor the "diagonal" congruence out of the preceding rows. 00310 reduce_reduced<Congruence_System, Congruence> 00311 (dest, dim, i++, 0, dim, dim_kinds, false); 00312 }
| void Parma_Polyhedra_Library::Grid::conversion | ( | Congruence_System & | source, | |
| Grid_Generator_System & | dest, | |||
| Dimension_Kinds & | dim_kinds | |||
| ) | [static, private] |
Converts generator system dest to be equivalent to congruence system source.
Definition at line 315 of file Grid_conversion.cc.
References CON_VIRTUAL, EQUALITY, Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::gcd_assign(), GEN_VIRTUAL, Parma_Polyhedra_Library::lcm_assign(), LINE, lower_triangular(), multiply_grid(), Parma_Polyhedra_Library::Matrix::num_columns(), PARAMETER, PPL_DIRTY_TEMP_COEFFICIENT, PROPER_CONGRUENCE, Parma_Polyhedra_Library::Grid_Generator_System::resize_no_copy(), Parma_Polyhedra_Library::Grid_Generator_System::set_index_first_pending_row(), Parma_Polyhedra_Library::Grid_Generator::set_is_line(), Parma_Polyhedra_Library::Grid_Generator::set_is_parameter_or_point(), Parma_Polyhedra_Library::sub_mul_assign(), and upper_triangular().
Referenced by update_generators().
00316 { 00317 // Quite similar to the generator to congruence version above. 00318 // Changes here may be needed there too. 00319 00320 PPL_ASSERT(lower_triangular(source, dim_kinds)); 00321 00322 // Initialize matrix row number counters and compute the LCM of the 00323 // diagonal entries of the proper congruences in `source'. 00324 dimension_type source_num_rows = 0, dest_num_rows = 0; 00325 PPL_DIRTY_TEMP_COEFFICIENT(diagonal_lcm); 00326 diagonal_lcm = 1; 00327 dimension_type dims = source.num_columns() - 1; 00328 for (dimension_type dim = dims; dim-- > 0; ) 00329 if (dim_kinds[dim] == CON_VIRTUAL) 00330 // Virtual congruences map to lines. 00331 ++dest_num_rows; 00332 else { 00333 if (dim_kinds[dim] == PROPER_CONGRUENCE) { 00334 // Dimension `dim' has a proper congruence row at 00335 // `source_num_rows' in `source', so include in `diagonal_lcm' 00336 // the `dim'th element of that row. 00337 lcm_assign(diagonal_lcm, diagonal_lcm, source[source_num_rows][dim]); 00338 // Proper congruences map to parameters. 00339 ++dest_num_rows; 00340 } 00341 // Equalities map to virtual generators. 00342 ++source_num_rows; 00343 } 00344 00345 // `source' must be regular. 00346 if (diagonal_lcm == 0) 00347 throw std::runtime_error("PPL internal error: Grid::conversion:" 00348 " source matrix is singular."); 00349 00350 dest.set_index_first_pending_row(dest_num_rows); 00351 dest.resize_no_copy(dest_num_rows, dims + 1 /* parameter divisor */); 00352 00353 // In `dest' initialize row types and elements, including setting 00354 // the diagonal elements to the inverse ratio of the `source' 00355 // diagonal elements. 00356 // 00357 // The top-down order of the congruence system rows corresponds to 00358 // the right-left order of the dimensions. 00359 dimension_type source_index = 0; 00360 // The generator system has a bottom-up ordering. 00361 dimension_type dest_index = dest_num_rows - 1; 00362 for (dimension_type dim = dims; dim-- > 0; ) { 00363 if (dim_kinds[dim] == EQUALITY) { 00364 ++source_index; 00365 } 00366 else { 00367 Grid_Generator& g = dest[dest_index]; 00368 for (dimension_type j = dim; j-- > 0; ) 00369 g[j] = 0; 00370 for (dimension_type j = dim + 1; j < dims; ++j) 00371 g[j] = 0; 00372 00373 if (dim_kinds[dim] == CON_VIRTUAL) { 00374 g.set_is_line(); 00375 g[dim] = 1; 00376 } 00377 else { 00378 PPL_ASSERT(dim_kinds[dim] == PROPER_CONGRUENCE); 00379 g.set_is_parameter_or_point(); 00380 exact_div_assign(g[dim], diagonal_lcm, source[source_index][dim]); 00381 ++source_index; 00382 } 00383 --dest_index; 00384 } 00385 } 00386 00387 PPL_ASSERT(upper_triangular(dest, dim_kinds)); 00388 00389 // Convert. 00390 // 00391 // `source_index' and `dest_index' hold the positions of pivot rows 00392 // in `source' and `dest'. The order of the rows in `dest' is the 00393 // reverse of the order in `source', so the rows are iterated from 00394 // last to first (index 0) in `source' and from first to last in 00395 // `dest'. 00396 source_index = source_num_rows; 00397 dest_index = 0; 00398 PPL_DIRTY_TEMP_COEFFICIENT(reduced_source_dim); 00399 00400 for (dimension_type dim = 0; dim < dims; ++dim) { 00401 if (dim_kinds[dim] != CON_VIRTUAL) { 00402 --source_index; 00403 const Coefficient& source_dim = source[source_index][dim]; 00404 00405 // In the rows in `dest' above `dest_index' divide each element 00406 // at column `dim' by `source_dim'. 00407 for (dimension_type row = dest_index; row-- > 0; ) { 00408 Grid_Generator& g = dest[row]; 00409 00410 // Multiply the representation of `dest' such that entry `dim' 00411 // of `g' is a multiple of `source_dim'. This ensures that 00412 // the result of the division that follows is a whole number. 00413 gcd_assign(reduced_source_dim, g[dim], source_dim); 00414 exact_div_assign(reduced_source_dim, source_dim, reduced_source_dim); 00415 multiply_grid(reduced_source_dim, g, dest, dest_num_rows, 00416 dims + 1 /* parameter divisor */); 00417 00418 Coefficient& g_dim = g[dim]; 00419 exact_div_assign(g_dim, g_dim, source_dim); 00420 } 00421 } 00422 00423 // Invert and transpose the source row at `source_index' into the 00424 // destination row at `dest_index'. 00425 // 00426 // Consider each dimension `dim_fol' that follows `dim', as the 00427 // rows in `dest' that follow row `dest_index' are zero at index 00428 // `dim'. 00429 dimension_type tmp_source_index = source_index; 00430 if (dim_kinds[dim] != EQUALITY) 00431 ++dest_index; 00432 for (dimension_type dim_fol = dim + 1; dim_fol < dims; ++dim_fol) { 00433 if (dim_kinds[dim_fol] != CON_VIRTUAL) { 00434 --tmp_source_index; 00435 const Coefficient& source_dim = source[tmp_source_index][dim]; 00436 // In order to compute the transpose of the inverse of 00437 // `source', subtract source[tmp_source_index][dim] times the 00438 // column vector in `dest' at `dim' from the column vector in 00439 // `dest' at `dim_fol'. 00440 // 00441 // I.e., for each row `dest_index' in `dest' that is above the 00442 // row `dest_index', subtract dest[tmp_source_index][dim] 00443 // times the entry `dim' from the entry at `dim_fol'. 00444 for (dimension_type row = dest_index; row-- > 0; ) { 00445 PPL_ASSERT(row < dest_num_rows); 00446 Grid_Generator& g = dest[row]; 00447 sub_mul_assign(g[dim_fol], source_dim, g[dim]); 00448 } 00449 } 00450 } 00451 } 00452 00453 PPL_ASSERT(upper_triangular(dest, dim_kinds)); 00454 00455 // Since we are reducing the system to "strong minimal form", 00456 // reduce the coordinates in the grid_generator system 00457 // using "diagonal" values. 00458 for (dimension_type dim = 0, i = 0; dim < dims; ++dim) 00459 if (dim_kinds[dim] != GEN_VIRTUAL) 00460 // Factor the "diagonal" generator out of the preceding rows. 00461 reduce_reduced<Grid_Generator_System, Grid_Generator> 00462 (dest, dim, i++, dim, dims - 1, dim_kinds); 00463 00464 // Ensure that the parameter divisors are the same as the divisor of 00465 // the point. 00466 const Coefficient& system_divisor = dest[0][0]; 00467 for (dimension_type row = dest.num_rows() - 1, dim = dims; 00468 dim-- > 1; ) 00469 switch (dim_kinds[dim]) { 00470 case PARAMETER: 00471 dest[row].set_divisor(system_divisor); 00472 case LINE: 00473 --row; 00474 case GEN_VIRTUAL: 00475 break; 00476 } 00477 }
| void Parma_Polyhedra_Library::Grid::difference_assign | ( | const Grid & | y | ) |
Assigns to *this the grid-difference of *this and 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.
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 1484 of file Grid_public.cc.
References add_congruence_no_check(), Parma_Polyhedra_Library::Congruence_System::begin(), congruences(), contains(), Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::Congruence_System::end(), Parma_Polyhedra_Library::Poly_Con_Relation::implies(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Congruence::is_proper_congruence(), marked_empty(), Parma_Polyhedra_Library::Congruence::modulus(), OK(), relation_with(), set_empty(), space_dim, throw_dimension_incompatible(), and upper_bound_assign().
Referenced by upper_bound_assign_if_exact().
01484 { 01485 Grid& x = *this; 01486 // Dimension-compatibility check. 01487 if (x.space_dim != y.space_dim) 01488 throw_dimension_incompatible("difference_assign(y)", "y", y); 01489 01490 if (y.marked_empty() || x.marked_empty()) 01491 return; 01492 01493 // If both grids are zero-dimensional, then they are necessarily 01494 // universe grids, so the result is empty. 01495 if (x.space_dim == 0) { 01496 x.set_empty(); 01497 return; 01498 } 01499 01500 if (y.contains(x)) { 01501 x.set_empty(); 01502 return; 01503 } 01504 01505 Grid new_grid(x.space_dim, EMPTY); 01506 01507 const Congruence_System& y_cgs = y.congruences(); 01508 for (Congruence_System::const_iterator i = y_cgs.begin(), 01509 y_cgs_end = y_cgs.end(); i != y_cgs_end; ++i) { 01510 const Congruence& cg = *i; 01511 01512 // The 2-complement cg2 of cg = ((e %= 0) / m) is the congruence 01513 // defining the sets of points exactly half-way between successive 01514 // hyperplanes e = km and e = (k+1)m, for any integer k; that is, 01515 // the hyperplanes defined by 2e = (2k + 1)m, for any integer k. 01516 // Thus `cg2' is the congruence ((2e %= m) / 2m). 01517 01518 // As the grid difference must be a grid, only add the 01519 // 2-complement congruence to x if the resulting grid includes all 01520 // the points in x that did not satisfy `cg'. 01521 01522 // The 2-complement of cg can be included in the result only if x 01523 // holds points other than those in cg. 01524 if (x.relation_with(cg).implies(Poly_Con_Relation::is_included())) 01525 continue; 01526 01527 if (cg.is_proper_congruence()) { 01528 const Linear_Expression e = Linear_Expression(cg); 01529 // Congruence cg is ((e %= 0) / m). 01530 const Coefficient& m = cg.modulus(); 01531 // If x is included in the grid defined by the congruences cg 01532 // and its 2-complement (i.e. the grid defined by the congruence 01533 // (2e %= 0) / m) then add the 2-complement to the potential 01534 // result. 01535 if (x.relation_with((2*e %= 0) / m) 01536 .implies(Poly_Con_Relation::is_included())) { 01537 Grid z = x; 01538 z.add_congruence_no_check((2*e %= m) / (2*m)); 01539 new_grid.upper_bound_assign(z); 01540 continue; 01541 } 01542 } 01543 return; 01544 } 01545 01546 *this = new_grid; 01547 01548 PPL_ASSERT(OK()); 01549 }
| void Parma_Polyhedra_Library::Grid::drop_some_non_integer_points | ( | const Variables_Set & | vars, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) |
Possibly tightens *this by dropping all points with non-integer coordinates for the space dimensions corresponding to vars.
| vars | Points with non-integer coordinates for these variables/space-dimensions can be discarded. | |
| complexity | This argument is ignored as the algorithm used has polynomial complexity. |
Definition at line 2872 of file Grid_public.cc.
References add_congruence(), marked_empty(), OK(), space_dimension(), Parma_Polyhedra_Library::Variables_Set::space_dimension(), and throw_dimension_incompatible().
02873 { 02874 // Dimension-compatibility check. 02875 const dimension_type min_space_dim = vars.space_dimension(); 02876 if (space_dimension() < min_space_dim) 02877 throw_dimension_incompatible("drop_some_non_integer_points(vs, cmpl)", 02878 min_space_dim); 02879 02880 if (marked_empty() || min_space_dim == 0) 02881 return; 02882 02883 // By adding the integral congruences for each dimension in vars to 02884 // the congruence system defining \p *this, the grid will keep only 02885 // those points that have integer coordinates for all the dimensions 02886 // in vars. All points in \p *this with non-integral coordinates for 02887 // the dimensions in vars are removed. 02888 for (Variables_Set::const_iterator i = vars.begin(), 02889 vars_end = vars.end(); i != vars.end(); ++i) 02890 add_congruence(Variable(*i) %= 0); 02891 02892 PPL_ASSERT(OK()); 02893 }
| void Parma_Polyhedra_Library::Grid::drop_some_non_integer_points | ( | Complexity_Class | complexity = ANY_COMPLEXITY |
) |
Possibly tightens *this by dropping all points with non-integer coordinates.
| complexity | This argument is ignored as the algorithm used has polynomial complexity. |
Definition at line 2857 of file Grid_public.cc.
References add_congruence(), marked_empty(), OK(), and space_dim.
02857 { 02858 if (marked_empty() || space_dim == 0) 02859 return; 02860 02861 // By adding integral congruences for each dimension to the 02862 // congruence system, defining \p *this, the grid will keep only 02863 // those points that have integral coordinates. All points in \p 02864 // *this with non-integral coordinates are removed. 02865 for (dimension_type i = space_dim; i-- > 0; ) 02866 add_congruence(Variable(i) %= 0); 02867 02868 PPL_ASSERT(OK()); 02869 }
| void Parma_Polyhedra_Library::Grid::expand_space_dimension | ( | Variable | var, | |
| dimension_type | m | |||
| ) |
Creates m copies of the space dimension corresponding to var.
| var | The variable corresponding to the space dimension to be replicated; | |
| m | The number of replicas to be created. |
| std::invalid_argument | Thrown if var does not correspond to a dimension of the vector space. | |
| std::length_error | Thrown if adding m new space dimensions would cause the vector space to exceed dimension max_space_dimension(). |
If *this has space dimension
, with
, and var has space dimension
, then the
-th space dimension is expanded to m new space dimensions
,
,
,
.
Definition at line 395 of file Grid_chdims.cc.
References add_recycled_congruences(), add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Congruence_System::begin(), Parma_Polyhedra_Library::Congruence::coefficient(), congruences(), Parma_Polyhedra_Library::Congruence_System::end(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Congruence::inhomogeneous_term(), Parma_Polyhedra_Library::Congruence_System::insert_verbatim(), max_space_dimension(), Parma_Polyhedra_Library::Congruence::modulus(), OK(), space_dim, space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), throw_dimension_incompatible(), and throw_space_dimension_overflow().
00395 { 00396 // TODO: this implementation is _really_ an executable specification. 00397 00398 // `var' must be one of the dimensions of the vector space. 00399 if (var.space_dimension() > space_dim) 00400 throw_dimension_incompatible("expand_space_dimension(v, m)", "v", var); 00401 00402 // Adding 0 dimensions leaves the same grid. 00403 if (m == 0) 00404 return; 00405 00406 // The resulting space dimension must be at most the maximum. 00407 if (m > max_space_dimension() - space_dimension()) 00408 throw_space_dimension_overflow("expand_space_dimension(v, m)", 00409 "adding m new space dimensions exceeds " 00410 "the maximum allowed space dimension"); 00411 00412 // Save the number of dimensions before adding new ones. 00413 dimension_type old_dim = space_dim; 00414 00415 // Add the required new dimensions. 00416 add_space_dimensions_and_embed(m); 00417 00418 const dimension_type src_d = var.id(); 00419 const Congruence_System& cgs = congruences(); 00420 Congruence_System new_congruences; 00421 for (Congruence_System::const_iterator i = cgs.begin(), 00422 cgs_end = cgs.end(); i != cgs_end; ++i) { 00423 const Congruence& cg = *i; 00424 00425 // Only consider congruences that constrain `var'. 00426 if (cg.coefficient(var) == 0) 00427 continue; 00428 00429 // Each relevant congruence results in `m' new congruences. 00430 for (dimension_type dst_d = old_dim; dst_d < old_dim+m; ++dst_d) { 00431 Linear_Expression e; 00432 for (dimension_type j = old_dim; j-- > 0; ) 00433 e += 00434 cg.coefficient(Variable(j)) 00435 * (j == src_d ? Variable(dst_d) : Variable(j)); 00436 new_congruences.insert_verbatim((e + cg.inhomogeneous_term() %= 0) 00437 / cg.modulus()); 00438 } 00439 } 00440 add_recycled_congruences(new_congruences); 00441 PPL_ASSERT(OK()); 00442 }
| PPL::memory_size_type Parma_Polyhedra_Library::Grid::external_memory_in_bytes | ( | ) | const |
Returns the size in bytes of the memory managed by *this.
Definition at line 2670 of file Grid_public.cc.
References con_sys, Parma_Polyhedra_Library::Grid_Generator_System::external_memory_in_bytes(), Parma_Polyhedra_Library::Congruence_System::external_memory_in_bytes(), and gen_sys.
Referenced by total_memory_in_bytes().
| void Parma_Polyhedra_Library::Grid::fold_space_dimensions | ( | const Variables_Set & | vars, | |
| Variable | dest | |||
| ) |
Folds the space dimensions in vars into dest.
| vars | The set of Variable objects corresponding to the space dimensions to be folded; | |
| dest | The variable corresponding to the space dimension that is the destination of the folding operation. |
| std::invalid_argument | Thrown if *this is dimension-incompatible with dest or with one of the Variable objects contained in vars. Also thrown if dest is contained in vars. |
If *this has space dimension
, with
, dest has space dimension
, vars is a set of variables whose maximum space dimension is also less than or equal to
, and dest is not a member of vars, then the space dimensions corresponding to variables in vars are folded into the
-th space dimension.
Definition at line 445 of file Grid_chdims.cc.
References affine_image(), grid_generators(), Parma_Polyhedra_Library::Variable::id(), marked_empty(), OK(), remove_space_dimensions(), space_dim, Parma_Polyhedra_Library::Variables_Set::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), throw_dimension_incompatible(), throw_invalid_argument(), and upper_bound_assign().
00445 { 00446 // TODO: this implementation is _really_ an executable specification. 00447 00448 // `dest' should be one of the dimensions of the grid. 00449 if (dest.space_dimension() > space_dim) 00450 throw_dimension_incompatible("fold_space_dimensions(vs, v)", "v", dest); 00451 00452 // Folding only has effect if dimensions are given. 00453 if (vars.empty()) 00454 return; 00455 00456 // All variables in `vars' must be dimensions of the grid. 00457 if (vars.space_dimension() > space_dim) 00458 throw_dimension_incompatible("fold_space_dimensions(vs, v)", 00459 "vs.space_dimension()", 00460 vars.space_dimension()); 00461 00462 // Moreover, `dest.id()' must not occur in `vars'. 00463 if (vars.find(dest.id()) != vars.end()) 00464 throw_invalid_argument("fold_space_dimensions(vs, v)", 00465 "v should not occur in vs"); 00466 // All of the affine images we are going to compute are not invertible, 00467 // hence we will need to compute the grid generators of the polyhedron. 00468 // Since we keep taking copies, make sure that a single conversion 00469 // from congruences to grid generators is computed. 00470 (void) grid_generators(); 00471 // Having grid generators, we now know if the grid is empty: 00472 // in that case, folding is equivalent to just removing space dimensions. 00473 if (!marked_empty()) { 00474 for (Variables_Set::const_iterator i = vars.begin(), 00475 vs_end = vars.end(); i != vs_end; ++i) { 00476 Grid copy = *this; 00477 copy.affine_image(dest, Linear_Expression(Variable(*i))); 00478 upper_bound_assign(copy); 00479 } 00480 } 00481 remove_space_dimensions(vars); 00482 PPL_ASSERT(OK()); 00483 }
| bool Parma_Polyhedra_Library::Grid::frequency | ( | const Linear_Expression & | expr, | |
| Coefficient & | freq_n, | |||
| Coefficient & | freq_d, | |||
| Coefficient & | val_n, | |||
| Coefficient & | val_d | |||
| ) | const |
Returns true if and only if *this is not empty and frequency for *this with respect to expr is defined, in which case the frequency and the value for expr that is closest to zero are computed.
| expr | The linear expression for which the frequency is needed; | |
| freq_n | The numerator of the maximum frequency of expr; | |
| freq_d | The denominator of the maximum frequency of expr; | |
| val_n | The numerator of them value of expr at a point in the grid that is closest to zero; | |
| val_d | The denominator of a value of expr at a point in the grid that is closest to zero; |
| std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
If *this is empty or frequency is undefined with respect to expr, then false is returned and freq_n, freq_d, val_n and val_d are left untouched.
Definition at line 2487 of file Grid_public.cc.
References frequency_no_check(), generators_are_minimized(), is_empty(), minimize(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and throw_dimension_incompatible().
02489 { 02490 // The dimension of `expr' must be at most the dimension of *this. 02491 if (space_dim < expr.space_dimension()) 02492 throw_dimension_incompatible("frequency(e, ...)", "e", expr); 02493 02494 // Space dimension = 0: if empty, then return false; 02495 // otherwise the frequency is 1 and the value is 0 02496 if (space_dim == 0) { 02497 if (is_empty()) 02498 return false; 02499 freq_n = 0; 02500 freq_d = 1; 02501 val_n = 0; 02502 val_d = 1; 02503 return true; 02504 } 02505 if (!generators_are_minimized() && !minimize()) 02506 // Minimizing found `this' empty. 02507 return false; 02508 02509 return frequency_no_check(expr, freq_n, freq_d, val_n, val_d); 02510 }
| bool Parma_Polyhedra_Library::Grid::frequency_no_check | ( | const Linear_Expression & | expr, | |
| Coefficient & | freq_n, | |||
| Coefficient & | freq_d, | |||
| Coefficient & | val_n, | |||
| Coefficient & | val_d | |||
| ) | const [private] |
Returns true if and only if *this is not empty and frequency for *this with respect to expr is defined, in which case the frequency and the value for expr that is closest to zero are computed.
| expr | The linear expression for which the frequency is needed; | |
| freq_n | The numerator of the maximum frequency of expr; | |
| freq_d | The denominator of the maximum frequency of expr; | |
| val_n | The numerator of a value of expr at a point in the grid that is closest to zero; | |
| val_d | The denominator of a value of expr at a point in the grid that is closest to zero; |
If *this is empty or frequency is undefined with respect to expr, then false is returned and freq_n, freq_d, val_n and val_d are left untouched.
expr and *this are dimension-incompatible, the grid generator system is not minimized or *this is empty, then the behavior is undefined. Definition at line 315 of file Grid_nonpublic.cc.
References bounds_no_check(), Parma_Polyhedra_Library::Grid_Generator::divisor(), Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::gcd_assign(), gen_sys, generators_are_minimized(), Parma_Polyhedra_Library::Scalar_Products::homogeneous_assign(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Grid_Generator::is_line(), Parma_Polyhedra_Library::Grid_Generator::is_parameter(), Parma_Polyhedra_Library::Grid_Generator::is_point(), marked_empty(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), PPL_DIRTY_TEMP_COEFFICIENT, space_dim, and Parma_Polyhedra_Library::Linear_Expression::space_dimension().
Referenced by frequency(), and wrap_assign().
00317 { 00318 00319 // The dimension of `expr' must be at most the dimension of *this. 00320 PPL_ASSERT(space_dim >= expr.space_dimension()); 00321 PPL_ASSERT(generators_are_minimized() && !marked_empty()); 00322 00323 // The generators are up to date and minimized and the grid is non-empty. 00324 00325 // If the grid is bounded for the expression `expr', 00326 // then `expr' has a constant value and the frequency is 0. 00327 if (bounds_no_check(expr)) { 00328 freq_n = 0; 00329 freq_d = 1; 00330 // Find the value of the constant expression. 00331 const Grid_Generator& point = gen_sys[0]; 00332 val_d = point.divisor(); 00333 Scalar_Products::homogeneous_assign(val_n, expr, point); 00334 val_n += expr.inhomogeneous_term() * val_d; 00335 // Reduce `val_n' and `val_d'. 00336 PPL_DIRTY_TEMP_COEFFICIENT(gcd); 00337 gcd_assign(gcd, val_n, val_d); 00338 exact_div_assign(val_n, val_n, gcd); 00339 exact_div_assign(val_d, val_d, gcd); 00340 return true; 00341 } 00342 00343 // The frequency is the gcd of the scalar products of the parameters 00344 // in `gen_sys'. 00345 dimension_type num_rows = gen_sys.num_rows(); 00346 PPL_DIRTY_TEMP_COEFFICIENT(sp); 00347 freq_n = 0; 00348 00349 // As the generators are minimized, `gen_sys[0]' is a point 00350 // and considered later. 00351 for (dimension_type row = 1; row < num_rows; ++row) { 00352 const Grid_Generator& gen = gen_sys[row]; 00353 Scalar_Products::homogeneous_assign(sp, expr, gen); 00354 if (gen.is_line()) { 00355 if (sgn(sp) != 0) 00356 return false; 00357 continue; 00358 } 00359 // `gen' must be a parameter. 00360 PPL_ASSERT(gen.is_parameter()); 00361 if (sgn(sp) != 0) 00362 gcd_assign(freq_n, freq_n, sp); 00363 } 00364 const Grid_Generator& point = gen_sys[0]; 00365 PPL_ASSERT(point.is_point()); 00366 00367 // The denominator of the frequency and of the value is 00368 // the divisor for the generators. 00369 freq_d = point.divisor(); 00370 val_d = freq_d; 00371 00372 // As point is a grid generator, homogeneous_assign() must be used. 00373 Scalar_Products::homogeneous_assign(val_n, expr, point); 00374 val_n += expr.inhomogeneous_term() * val_d; 00375 00376 // Reduce `val_n' by the frequency `freq_n'. 00377 val_n %= freq_n; 00378 00379 PPL_DIRTY_TEMP_COEFFICIENT(gcd); 00380 // Reduce `freq_n' and `freq_d'. 00381 gcd_assign(gcd, freq_n, freq_d); 00382 exact_div_assign(freq_n, freq_n, gcd); 00383 exact_div_assign(freq_d, freq_d, gcd); 00384 00385 // Reduce `val_n' and `val_d'. 00386 gcd_assign(gcd, val_n, val_d); 00387 exact_div_assign(val_n, val_n, gcd); 00388 exact_div_assign(val_d, val_d, gcd); 00389 00390 return true; 00391 }
| void Parma_Polyhedra_Library::Grid::generalized_affine_image | ( | const Linear_Expression & | lhs, | |
| Relation_Symbol | relsym, | |||
| const Linear_Expression & | rhs, | |||
| Coefficient_traits::const_reference | modulus = Coefficient_zero() | |||
| ) |
Assigns to *this the image of *this with respect to the generalized affine relation
.
| lhs | The left hand side affine expression. | |
| relsym | The relation symbol where EQUAL is the symbol for a congruence relation; | |
| rhs | The right hand side affine expression. | |
| modulus | The modulus of the congruence lhs = rhs. A modulus of zero indicates lhs == rhs. Optional argument with an automatic value of zero. |
| std::invalid_argument | Thrown if *this is dimension-incompatible with lhs or rhs. |
Definition at line 2086 of file Grid_public.cc.
References add_congruence_no_check(), add_grid_generator(), add_recycled_congruences(), add_recycled_grid_generators(), add_space_dimensions_and_embed(), clear_congruences_up_to_date(), clear_generators_minimized(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Grid_Generator_System::insert(), is_empty(), marked_empty(), minimize(), Parma_Polyhedra_Library::neg_assign(), normalize_divisors(), OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Grid_Generator_System::recycling_insert(), remove_higher_space_dimensions(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), throw_invalid_argument(), and update_generators().
02089 { 02090 // Dimension-compatibility checks. 02091 // The dimension of `lhs' should be at most the dimension of 02092 // `*this'. 02093 dimension_type lhs_space_dim = lhs.space_dimension(); 02094 if (space_dim < lhs_space_dim) 02095 throw_dimension_incompatible("generalized_affine_image(e1, r, e2)", 02096 "e1", lhs); 02097 // The dimension of `rhs' should be at most the dimension of 02098 // `*this'. 02099 const dimension_type rhs_space_dim = rhs.space_dimension(); 02100 if (space_dim < rhs_space_dim) 02101 throw_dimension_incompatible("generalized_affine_image(e1, r, e2)", 02102 "e2", rhs); 02103 02104 // Any image of an empty grid is empty. 02105 if (marked_empty()) 02106 return; 02107 02108 // If relsym is not EQUAL, then we return a safe approximation 02109 // by adding a line in the direction of var. 02110 if (relsym != EQUAL) { 02111 02112 if (modulus != 0) 02113 throw_invalid_argument("generalized_affine_image(e1, r, e2, m)", 02114 "r != EQUAL && m != 0"); 02115 02116 if (!generators_are_up_to_date()) 02117 minimize(); 02118 02119 // Any image of an empty grid is empty. 02120 if (marked_empty()) 02121 return; 02122 02123 for (dimension_type i = space_dim; i-- > 0; ) 02124 if (lhs.coefficient(Variable(i)) != 0) 02125 add_grid_generator(grid_line(Variable(i))); 02126 02127 PPL_ASSERT(OK()); 02128 return; 02129 } 02130 02131 PPL_ASSERT(relsym == EQUAL); 02132 02133 PPL_DIRTY_TEMP_COEFFICIENT(tmp_modulus); 02134 tmp_modulus = modulus; 02135 if (tmp_modulus < 0) 02136 neg_assign(tmp_modulus); 02137 02138 // Compute the actual space dimension of `lhs', 02139 // i.e., the highest dimension having a non-zero coefficient in `lhs'. 02140 do { 02141 if (lhs_space_dim == 0) { 02142 // All variables have zero coefficients, so `lhs' is a constant. 02143 add_congruence_no_check((lhs %= rhs) / tmp_modulus); 02144 return; 02145 } 02146 } 02147 while (lhs.coefficient(Variable(--lhs_space_dim)) == 0); 02148 02149 // Gather in `new_lines' the collections of all the lines having the 02150 // direction of variables occurring in `lhs'. While at it, check 02151 // whether there exists a variable occurring in both `lhs' and 02152 // `rhs'. 02153 Grid_Generator_System new_lines; 02154 bool lhs_vars_intersect_rhs_vars = false; 02155 for (dimension_type i = lhs_space_dim + 1; i-- > 0; ) 02156 if (lhs.coefficient(Variable(i)) != 0) { 02157 new_lines.insert(grid_line(Variable(i))); 02158 if (rhs.coefficient(Variable(i)) != 0) 02159 lhs_vars_intersect_rhs_vars = true; 02160 } 02161 02162 if (lhs_vars_intersect_rhs_vars) { 02163 // Some variables in `lhs' also occur in `rhs'. 02164 // To ease the computation, add an additional dimension. 02165 const Variable new_var = Variable(space_dim); 02166 add_space_dimensions_and_embed(1); 02167 02168 // Constrain the new dimension to be equal to the right hand side. 02169 // TODO: Use add_congruence() when it has been updated. 02170 Congruence_System new_cgs1(new_var == rhs); 02171 add_recycled_congruences(new_cgs1); 02172 if (!is_empty()) { 02173 // The grid still contains points. 02174 02175 // Existentially quantify all the variables occurring in the left 02176 // hand side expression. 02177 02178 // Adjust `new_lines' to the right dimension. 02179 new_lines.insert(parameter(0*Variable(space_dim-1))); 02180 // Add the lines to `gen_sys' (first make sure they are up-to-date). 02181 update_generators(); 02182 gen_sys.recycling_insert(new_lines); 02183 normalize_divisors(gen_sys); 02184 // Update the flags. 02185 clear_congruences_up_to_date(); 02186 clear_generators_minimized(); 02187 02188 // Constrain the new dimension so that it is congruent to the left 02189 // hand side expression modulo `modulus'. 02190 // TODO: Use add_congruence() when it has been updated. 02191 Congruence_System new_cgs2((lhs %= new_var) / tmp_modulus); 02192 add_recycled_congruences(new_cgs2); 02193 } 02194 02195 // Remove the temporarily added dimension. 02196 remove_higher_space_dimensions(space_dim-1); 02197 } 02198 else { 02199 // `lhs' and `rhs' variables are disjoint: 02200 // there is no need to add a further dimension. 02201 02202 // Only add the lines and congruence if there are points. 02203 if (is_empty()) 02204 return; 02205 02206 // Existentially quantify all the variables occurring in the left hand 02207 // side expression. 02208 add_recycled_grid_generators(new_lines); 02209 02210 // Constrain the left hand side expression so that it is congruent to 02211 // the right hand side expression modulo `modulus'. 02212 add_congruence_no_check((lhs %= rhs) / tmp_modulus); 02213 } 02214 02215 PPL_ASSERT(OK()); 02216 }
| void Parma_Polyhedra_Library::Grid::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() | |||
| ) |
Assigns to *this the image of *this with respect to the generalized affine relation
.
| var | The left hand side variable of the generalized affine relation; | |
| relsym | The relation symbol where EQUAL is the symbol for a congruence relation; | |
| expr | The numerator of the right hand side affine expression; | |
| denominator | The denominator of the right hand side affine expression. Optional argument with an automatic value of one; | |
| modulus | The modulus of the congruence lhs = rhs. A modulus of zero indicates lhs == rhs. Optional argument with an automatic value of zero. |
| std::invalid_argument | Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a space dimension of this. |
Definition at line 1912 of file Grid_public.cc.
References add_grid_generator(), affine_image(), clear_congruences_up_to_date(), clear_generators_minimized(), Parma_Polyhedra_Library::EQUAL, gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Grid_Generator_System::insert(), marked_empty(), minimize(), normalize_divisors(), OK(), space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
Referenced by bounded_affine_image(), and generalized_affine_preimage().
01916 { 01917 01918 // The denominator cannot be zero. 01919 if (denominator == 0) 01920 throw_invalid_argument("generalized_affine_image(v, r, e, d, m)", 01921 "d == 0"); 01922 01923 // Dimension-compatibility checks. 01924 // The dimension of `expr' should not be greater than the dimension 01925 // of `*this'. 01926 const dimension_type expr_space_dim = expr.space_dimension(); 01927 if (space_dim < expr_space_dim) 01928 throw_dimension_incompatible("generalized_affine_image(v, r, e, d, m)", 01929 "e", expr); 01930 // `var' should be one of the dimensions of the grid. 01931 const dimension_type var_space_dim = var.space_dimension(); 01932 if (space_dim < var_space_dim) 01933 throw_dimension_incompatible("generalized_affine_image(v, r, e, d, m)", 01934 "v", var); 01935 01936 // Any image of an empty grid is empty. 01937 if (marked_empty()) 01938 return; 01939 01940 // If relsym is not EQUAL, then we return a safe approximation 01941 // by adding a line in the direction of var. 01942 if (relsym != EQUAL) { 01943 01944 if (modulus != 0) 01945 throw_invalid_argument("generalized_affine_image(v, r, e, d, m)", 01946 "r != EQUAL && m != 0"); 01947 01948 if (!generators_are_up_to_date()) 01949 minimize(); 01950 01951 // Any image of an empty grid is empty. 01952 if (marked_empty()) 01953 return; 01954 01955 add_grid_generator(grid_line(var)); 01956 01957 PPL_ASSERT(OK()); 01958 return; 01959 } 01960 01961 PPL_ASSERT(relsym == EQUAL); 01962 01963 affine_image(var, expr, denominator); 01964 01965 if (modulus == 0) 01966 return; 01967 01968 // Modulate dimension `var' according to `modulus'. 01969 01970 if (!generators_are_up_to_date()) 01971 minimize(); 01972 01973 // Test if minimization, possibly in affine_image, found an empty 01974 // grid. 01975 if (marked_empty()) 01976 return; 01977 01978 if (modulus < 0) 01979 gen_sys.insert(parameter(-modulus * var)); 01980 else 01981 gen_sys.insert(parameter(modulus * var)); 01982 01983 normalize_divisors(gen_sys); 01984 01985 clear_generators_minimized(); 01986 clear_congruences_up_to_date(); 01987 01988 PPL_ASSERT(OK()); 01989 }
| void Parma_Polyhedra_Library::Grid::generalized_affine_preimage | ( | const Linear_Expression & | lhs, | |
| Relation_Symbol | relsym, | |||
| const Linear_Expression & | rhs, | |||
| Coefficient_traits::const_reference | modulus = Coefficient_zero() | |||
| ) |
Assigns to *this the preimage of *this with respect to the generalized affine relation
.
| lhs | The left hand side affine expression; | |
| relsym | The relation symbol where EQUAL is the symbol for a congruence relation; | |
| rhs | The right hand side affine expression; | |
| modulus | The modulus of the congruence lhs = rhs. A modulus of zero indicates lhs == rhs. Optional argument with an automatic value of zero. |
| std::invalid_argument | Thrown if *this is dimension-incompatible with lhs or rhs. |
Definition at line 2220 of file Grid_public.cc.
References add_congruence_no_check(), add_grid_generator(), add_recycled_congruences(), add_recycled_grid_generators(), add_space_dimensions_and_embed(), clear_congruences_up_to_date(), clear_generators_minimized(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Grid_Generator_System::insert(), is_empty(), marked_empty(), minimize(), Parma_Polyhedra_Library::neg_assign(), normalize_divisors(), OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Grid_Generator_System::recycling_insert(), remove_higher_space_dimensions(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), throw_invalid_argument(), and update_generators().
02223 { 02224 02225 // The dimension of `lhs' must be at most the dimension of `*this'. 02226 dimension_type lhs_space_dim = lhs.space_dimension(); 02227 if (space_dim < lhs_space_dim) 02228 throw_dimension_incompatible("generalized_affine_preimage(e1, e2, m)", 02229 "lhs", lhs); 02230 // The dimension of `rhs' must be at most the dimension of `*this'. 02231 const dimension_type rhs_space_dim = rhs.space_dimension(); 02232 if (space_dim < rhs_space_dim) 02233 throw_dimension_incompatible("generalized_affine_preimage(e1, e2, m)", 02234 "e2", rhs); 02235 02236 // Any preimage of an empty grid is empty. 02237 if (marked_empty()) 02238 return; 02239 02240 // If relsym is not EQUAL, then we return a safe approximation 02241 // by adding a line in the direction of var. 02242 if (relsym != EQUAL) { 02243 02244 if (modulus != 0) 02245 throw_invalid_argument("generalized_affine_preimage(e1, r, e2, m)", 02246 "r != EQUAL && m != 0"); 02247 02248 if (!generators_are_up_to_date()) 02249 minimize(); 02250 02251 // Any image of an empty grid is empty. 02252 if (marked_empty()) 02253 return; 02254 02255 for (dimension_type i = lhs_space_dim + 1; i-- > 0; ) 02256 if (lhs.coefficient(Variable(i)) != 0) 02257 add_grid_generator(grid_line(Variable(i))); 02258 02259 PPL_ASSERT(OK()); 02260 return; 02261 } 02262 02263 PPL_ASSERT(relsym == EQUAL); 02264 02265 PPL_DIRTY_TEMP_COEFFICIENT(tmp_modulus); 02266 tmp_modulus = modulus; 02267 if (tmp_modulus < 0) 02268 neg_assign(tmp_modulus); 02269 02270 // Compute the actual space dimension of `lhs', 02271 // i.e., the highest dimension having a non-zero coefficient in `lhs'. 02272 do { 02273 if (lhs_space_dim == 0) { 02274 // All variables have zero coefficients, so `lhs' is a constant. 02275 // In this case, preimage and image happen to be the same. 02276 add_congruence_no_check((lhs %= rhs) / tmp_modulus); 02277 return; 02278 } 02279 } 02280 while (lhs.coefficient(Variable(--lhs_space_dim)) == 0); 02281 02282 // Gather in `new_lines' the collections of all the lines having 02283 // the direction of variables occurring in `lhs'. 02284 // While at it, check whether or not there exists a variable 02285 // occurring in both `lhs' and `rhs'. 02286 Grid_Generator_System new_lines; 02287 bool lhs_vars_intersect_rhs_vars = false; 02288 for (dimension_type i = lhs_space_dim + 1; i-- > 0; ) 02289 if (lhs.coefficient(Variable(i)) != 0) { 02290 new_lines.insert(grid_line(Variable(i))); 02291 if (rhs.coefficient(Variable(i)) != 0) 02292 lhs_vars_intersect_rhs_vars = true; 02293 } 02294 02295 if (lhs_vars_intersect_rhs_vars) { 02296 // Some variables in `lhs' also occur in `rhs'. 02297 // To ease the computation, add an additional dimension. 02298 const Variable new_var = Variable(space_dim); 02299 add_space_dimensions_and_embed(1); 02300 02301 // Constrain the new dimension to be equal to `lhs' 02302 // TODO: Use add_congruence() when it has been updated. 02303 Congruence_System new_cgs1(new_var == lhs); 02304 add_recycled_congruences(new_cgs1); 02305 if (!is_empty()) { 02306 // The grid still contains points. 02307 02308 // Existentially quantify all the variables occurring in the left 02309 // hand side 02310 02311 // Adjust `new_lines' to the right dimension. 02312 new_lines.insert(parameter(0*Variable(space_dim-1))); 02313 // Add the lines to `gen_sys' (first make sure they are up-to-date). 02314 update_generators(); 02315 gen_sys.recycling_insert(new_lines); 02316 normalize_divisors(gen_sys); 02317 // Update the flags. 02318 clear_congruences_up_to_date(); 02319 clear_generators_minimized(); 02320 02321 // Constrain the new dimension so that it is related to 02322 // the right hand side modulo `modulus'. 02323 // TODO: Use add_congruence() when it has been updated. 02324 Congruence_System new_cgs2((rhs %= new_var) / tmp_modulus); 02325 add_recycled_congruences(new_cgs2); 02326 } 02327 02328 // Remove the temporarily added dimension. 02329 remove_higher_space_dimensions(space_dim-1); 02330 } 02331 else { 02332 // `lhs' and `rhs' variables are disjoint: 02333 // there is no need to add a further dimension. 02334 02335 // Constrain the left hand side expression so that it is congruent to 02336 // the right hand side expression modulo `mod'. 02337 add_congruence_no_check((lhs %= rhs) / tmp_modulus); 02338 02339 // Any image of an empty grid is empty. 02340 if (is_empty()) 02341 return; 02342 02343 // Existentially quantify all the variables occurring in `lhs'. 02344 add_recycled_grid_generators(new_lines); 02345 } 02346 PPL_ASSERT(OK()); 02347 }
| void Parma_Polyhedra_Library::Grid::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() | |||
| ) |
Assigns to *this the preimage of *this with respect to the generalized affine relation
.
| var | The left hand side variable of the generalized affine relation; | |
| relsym | The relation symbol where EQUAL is the symbol for a congruence relation; | |
| expr | The numerator of the right hand side affine expression; | |
| denominator | The denominator of the right hand side affine expression. Optional argument with an automatic value of one; | |
| modulus | The modulus of the congruence lhs = rhs. A modulus of zero indicates lhs == rhs. Optional argument with an automatic value of zero. |
| std::invalid_argument | Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a space dimension of this. |
Definition at line 1993 of file Grid_public.cc.
References add_congruence_no_check(), add_grid_generator(), affine_preimage(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, generalized_affine_image(), generators_are_up_to_date(), is_empty(), marked_empty(), minimize(), Parma_Polyhedra_Library::neg_assign(), OK(), PPL_DIRTY_TEMP_COEFFICIENT, space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
Referenced by bounded_affine_preimage().
01997 { 01998 // The denominator cannot be zero. 01999 if (denominator == 0) 02000 throw_invalid_argument("generalized_affine_preimage(v, e, d, m)", 02001 "d == 0"); 02002 02003 // The dimension of `expr' should be at most the dimension of 02004 // `*this'. 02005 const dimension_type expr_space_dim = expr.space_dimension(); 02006 if (space_dim < expr_space_dim) 02007 throw_dimension_incompatible("generalized_affine_preimage(v, e, d, m)", 02008 "e", expr); 02009 // `var' should be one of the dimensions of the grid. 02010 const dimension_type var_space_dim = var.space_dimension(); 02011 if (space_dim < var_space_dim) 02012 throw_dimension_incompatible("generalized_affine_preimage(v, e, d, m)", 02013 "v", var); 02014 02015 // If relsym is not EQUAL, then we return a safe approximation 02016 // by adding a line in the direction of var. 02017 if (relsym != EQUAL) { 02018 02019 if (modulus != 0) 02020 throw_invalid_argument("generalized_affine_preimage(v, r, e, d, m)", 02021 "r != EQUAL && m != 0"); 02022 02023 if (!generators_are_up_to_date()) 02024 minimize(); 02025 02026 // Any image of an empty grid is empty. 02027 if (marked_empty()) 02028 return; 02029 02030 add_grid_generator(grid_line(var)); 02031 02032 PPL_ASSERT(OK()); 02033 return; 02034 } 02035 02036 PPL_ASSERT(relsym == EQUAL); 02037 // Any image of an empty grid is empty. 02038 if (marked_empty()) 02039 return; 02040 02041 // Check whether the affine relation is an affine function. 02042 if (modulus == 0) { 02043 affine_preimage(var, expr, denominator); 02044 return; 02045 } 02046 02047 // Check whether the preimage of this affine relation can be easily 02048 // computed as the image of its inverse relation. 02049 const Coefficient& var_coefficient = expr.coefficient(var); 02050 if (var_space_dim <= expr_space_dim && var_coefficient != 0) { 02051 Linear_Expression inverse_expr 02052 = expr - (denominator + var_coefficient) * var; 02053 PPL_DIRTY_TEMP_COEFFICIENT(inverse_denominator); 02054 neg_assign(inverse_denominator, var_coefficient); 02055 if (modulus < 0) 02056 generalized_affine_image(var, EQUAL, inverse_expr, inverse_denominator, 02057 - modulus); 02058 else 02059 generalized_affine_image(var, EQUAL, inverse_expr, inverse_denominator, 02060 modulus); 02061 return; 02062 } 02063 02064 // Here `var_coefficient == 0', so that the preimage cannot be 02065 // easily computed by inverting the affine relation. Add the 02066 // congruence induced by the affine relation. 02067 { 02068 Congruence cg((denominator*var %= expr) / denominator); 02069 if (modulus < 0) 02070 cg /= -modulus; 02071 else 02072 cg /= modulus; 02073 add_congruence_no_check(cg); 02074 } 02075 02076 // If the resulting grid is empty, its preimage is empty too. 02077 // Note: DO check for emptiness here, as we will later add a line. 02078 if (is_empty()) 02079 return; 02080 add_grid_generator(grid_line(var)); 02081 PPL_ASSERT(OK()); 02082 }
| void Parma_Polyhedra_Library::Grid::generator_widening_assign | ( | const Grid & | y, | |
| unsigned * | tp = NULL | |||
| ) |
Assigns to *this the result of computing the Grid widening between *this and y using generator systems.
| y | A grid that must be contained in *this; | |
| tp | An optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique). |
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 278 of file Grid_widenings.cc.
References add_recycled_grid_generators(), contains(), dim_kinds, Parma_Polyhedra_Library::EMPTY, gen_sys, generators_are_minimized(), generators_are_up_to_date(), Parma_Polyhedra_Library::Matrix::has_no_rows(), marked_empty(), Parma_Polyhedra_Library::Grid_Generator_System::num_lines(), Parma_Polyhedra_Library::Grid_Generator_System::num_parameters(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), OK(), select_wider_generators(), set_generators_minimized(), simplify(), space_dim, swap(), throw_dimension_incompatible(), and update_generators().
Referenced by limited_generator_extrapolation_assign(), and widening_assign().
00278 { 00279 Grid& x = *this; 00280 Grid& y = const_cast<Grid&>(const_y); 00281 // Dimension-compatibility check. 00282 if (x.space_dim != y.space_dim) 00283 throw_dimension_incompatible("generator_widening_assign(y)", "y", y); 00284 00285 // Stable behavior is only guaranteed if y is contained in or equal 00286 // to x. 00287 #ifndef NDEBUG 00288 { 00289 // Assume y is contained in or equal to x. 00290 const Grid x_copy = x; 00291 const Grid y_copy = y; 00292 PPL_ASSERT(x_copy.contains(y_copy)); 00293 } 00294 #endif 00295 00296 // Leave `x' the same if `x' or `y' is zero-dimensional or empty. 00297 if (x.space_dim == 0 || x.marked_empty() || y.marked_empty()) 00298 return; 00299 00300 // Ensure that the `x' generators are in minimal form. 00301 if (x.generators_are_up_to_date()) { 00302 if (!x.generators_are_minimized()) { 00303 simplify(x.gen_sys, x.dim_kinds); 00304 PPL_ASSERT(!x.gen_sys.has_no_rows()); 00305 x.set_generators_minimized(); 00306 } 00307 } 00308 else 00309 x.update_generators(); 00310 00311 if (x.marked_empty()) 00312 return; 00313 00314 // Ensure that the `y' generators are in minimal form. 00315 if (y.generators_are_up_to_date()) { 00316 if (!y.generators_are_minimized()) { 00317 simplify(y.gen_sys, y.dim_kinds); 00318 PPL_ASSERT(!y.gen_sys.has_no_rows()); 00319 y.set_generators_minimized(); 00320 } 00321 } 00322 else 00323 y.update_generators(); 00324 00325 if (gen_sys.num_rows() > y.gen_sys.num_rows()) 00326 return; 00327 00328 if (gen_sys.num_lines() > y.gen_sys.num_lines()) 00329 return; 00330 00331 // Copy into `ggs' the generators of `x' that are common to `y', 00332 // according to the grid widening. 00333 Grid_Generator_System ggs; 00334 x.select_wider_generators(y, ggs); 00335 00336 if (ggs.num_parameters() == gen_sys.num_parameters()) 00337 // All parameters are kept as parameters, thus the result is `x'. 00338 return; 00339 00340 // A strict subset of the parameters was selected. 00341 00342 Grid result(x.space_dim, EMPTY); 00343 result.add_recycled_grid_generators(ggs); 00344 00345 // Check whether we are using the widening-with-tokens technique 00346 // and there are still tokens available. 00347 if (tp && *tp > 0) { 00348 // There are tokens available. If `result' is not a subset of 00349 // `x', then it is less precise and we use one of the available 00350 // tokens. 00351 if (!x.contains(result)) 00352 --(*tp); 00353 } 00354 else 00355 // No tokens. 00356 std::swap(x, result); 00357 00358 PPL_ASSERT(x.OK(true)); 00359 }
| bool Parma_Polyhedra_Library::Grid::generators_are_minimized | ( | ) | const [inline, private] |
Returns true if the system of generators is minimized.
Definition at line 55 of file Grid.inlines.hh.
References status, and Parma_Polyhedra_Library::Grid::Status::test_g_minimized().
Referenced by add_space_dimensions(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_dimension(), ascii_dump(), bounds(), bounds_no_check(), constrains(), frequency(), frequency_no_check(), generator_widening_assign(), Parma_Polyhedra_Library::Grid_Certificate::Grid_Certificate(), max_min(), minimize(), minimized_grid_generators(), OK(), quick_equivalence_test(), remove_higher_space_dimensions(), select_wider_generators(), simplify_using_context_assign(), update_congruences(), and wrap_assign().
00055 { 00056 return status.test_g_minimized(); 00057 }
| bool Parma_Polyhedra_Library::Grid::generators_are_up_to_date | ( | ) | const [inline, private] |
Returns true if the system of generators is up-to-date.
Definition at line 45 of file Grid.inlines.hh.
References status, and Parma_Polyhedra_Library::Grid::Status::test_g_up_to_date().
Referenced by add_grid_generator(), add_recycled_grid_generators(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_dimension(), affine_image(), affine_preimage(), ascii_dump(), bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), constrains(), generalized_affine_image(), generalized_affine_preimage(), generator_widening_assign(), Grid(), Parma_Polyhedra_Library::Grid_Certificate::Grid_Certificate(), grid_generators(), is_bounded(), is_discrete(), is_empty(), limited_congruence_extrapolation_assign(), limited_extrapolation_assign(), limited_generator_extrapolation_assign(), map_space_dimensions(), minimize(), minimized_grid_generators(), OK(), operator=(), relation_with(), remove_higher_space_dimensions(), remove_space_dimensions(), time_elapse_assign(), unconstrain(), upper_bound_assign(), upper_bound_assign_if_exact(), and widening_assign().
00045 { 00046 return status.test_g_up_to_date(); 00047 }
| const PPL::Grid_Generator_System & Parma_Polyhedra_Library::Grid::grid_generators | ( | ) | const |
Returns the system of generators.
Definition at line 309 of file Grid_public.cc.
References gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Matrix::has_no_rows(), marked_empty(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), space_dim, Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), and update_generators().
Referenced by fold_space_dimensions(), and map_space_dimensions().
00309 { 00310 if (space_dim == 0) { 00311 PPL_ASSERT(gen_sys.space_dimension() == 0 00312 && gen_sys.num_rows() == (marked_empty() ? 0 : 1)); 00313 return gen_sys; 00314 } 00315 00316 if (marked_empty()) { 00317 PPL_ASSERT(gen_sys.has_no_rows()); 00318 return gen_sys; 00319 } 00320 00321 if (!generators_are_up_to_date() && !update_generators()) { 00322 // Updating found the grid empty. 00323 const_cast<Grid&>(*this).set_empty(); 00324 return gen_sys; 00325 } 00326 00327 return gen_sys; 00328 }
| int32_t Parma_Polyhedra_Library::Grid::hash_code | ( | ) | const [inline] |
Returns a 32-bit hash code for *this.
If x and y are such that x == y, then x.hash_code() == y.hash_code().
Definition at line 230 of file Grid.inlines.hh.
References space_dimension().
00230 { 00231 return space_dimension() & 0x7fffffff; 00232 }
| void Parma_Polyhedra_Library::Grid::intersection_assign | ( | const Grid & | y | ) |
Assigns to *this the intersection of *this and y.
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 1372 of file Grid_public.cc.
References clear_congruences_minimized(), clear_generators_up_to_date(), con_sys, congruences_are_up_to_date(), Parma_Polyhedra_Library::Matrix::has_no_rows(), Parma_Polyhedra_Library::Congruence_System::insert(), marked_empty(), OK(), set_empty(), space_dim, throw_dimension_incompatible(), and update_congruences().
Referenced by is_disjoint_from().
01372 { 01373 Grid& x = *this; 01374 // Dimension-compatibility check. 01375 if (x.space_dim != y.space_dim) 01376 throw_dimension_incompatible("intersection_assign(y)", "y", y); 01377 01378 // If one of the two grids is empty, the intersection is empty. 01379 if (x.marked_empty()) 01380 return; 01381 if (y.marked_empty()) { 01382 x.set_empty(); 01383 return; 01384 } 01385 01386 // If both grids are zero-dimensional, then at this point they are 01387 // necessarily universe, so the intersection is also universe. 01388 if (x.space_dim == 0) 01389 return; 01390 01391 // The congruences must be up-to-date. 01392 if (!x.congruences_are_up_to_date()) 01393 x.update_congruences(); 01394 if (!y.congruences_are_up_to_date()) 01395 y.update_congruences(); 01396 01397 if (!y.con_sys.has_no_rows()) { 01398 x.con_sys.insert(y.con_sys); 01399 // Grid_Generators may be out of date and congruences may have changed 01400 // from minimal form. 01401 x.clear_generators_up_to_date(); 01402 x.clear_congruences_minimized(); 01403 } 01404 01405 PPL_ASSERT(x.OK() && y.OK()); 01406 }
| bool Parma_Polyhedra_Library::Grid::is_bounded | ( | ) | const |
Returns true if and only if *this is bounded.
Definition at line 731 of file Grid_public.cc.
References gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Grid_Generator::is_line_or_parameter(), marked_empty(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), space_dim, and update_generators().
00731 { 00732 // A zero-dimensional or empty grid is bounded. 00733 if (space_dim == 0 00734 || marked_empty() 00735 || (!generators_are_up_to_date() && !update_generators())) 00736 return true; 00737 00738 // TODO: Consider using con_sys when gen_sys is out of date. 00739 00740 if (gen_sys.num_rows() > 1) { 00741 // Check if all generators are the same point. 00742 const Grid_Generator& first_point = gen_sys[0]; 00743 if (first_point.is_line_or_parameter()) 00744 return false; 00745 for (dimension_type row = gen_sys.num_rows(); row-- > 0; ) { 00746 const Grid_Generator& gen = gen_sys[row]; 00747 if (gen.is_line_or_parameter() || gen != first_point) 00748 return false; 00749 } 00750 } 00751 return true; 00752 }
| bool Parma_Polyhedra_Library::Grid::is_discrete | ( | ) | const |
Returns true if and only if *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.
Definition at line 755 of file Grid_public.cc.
References gen_sys, generators_are_up_to_date(), marked_empty(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), space_dim, and update_generators().
00755 { 00756 // A zero-dimensional or empty grid is discrete. 00757 if (space_dim == 0 00758 || marked_empty() 00759 || (!generators_are_up_to_date() && !update_generators())) 00760 return true; 00761 00762 // Search for lines in the generator system. 00763 for (dimension_type row = gen_sys.num_rows(); row-- > 1; ) 00764 if (gen_sys[row].is_line()) 00765 return false; 00766 00767 // The system of generators is composed only by 00768 // points and parameters: the grid is discrete. 00769 return true; 00770 }
| bool Parma_Polyhedra_Library::Grid::is_disjoint_from | ( | const Grid & | y | ) | const |
Returns true if and only if *this and y are disjoint.
| std::invalid_argument | Thrown if x and y are dimension-incompatible. |
Definition at line 2562 of file Grid_public.cc.
References intersection_assign(), is_empty(), space_dim, and throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Pointset_Powerset< PSET >::check_containment().
02562 { 02563 // Dimension-compatibility check. 02564 if (space_dim != y.space_dim) 02565 throw_dimension_incompatible("is_disjoint_from(y)", "y", y); 02566 Grid z = *this; 02567 z.intersection_assign(y); 02568 return z.is_empty(); 02569 }
| bool Parma_Polyhedra_Library::Grid::is_empty | ( | ) | const |
Returns true if and only if *this is an empty grid.
Definition at line 678 of file Grid_public.cc.
References con_sys, congruences_are_minimized(), dim_kinds, generators_are_up_to_date(), marked_empty(), set_congruences_minimized(), set_empty(), simplify(), and space_dim.
Referenced by affine_dimension(), Parma_Polyhedra_Library::Pointset_Powerset< PSET >::approximate_partition_aux(), Parma_Polyhedra_Library::Pointset_Powerset< PSET >::check_containment(), contains(), contains_integer_point(), frequency(), generalized_affine_image(), generalized_affine_preimage(), is_disjoint_from(), operator<<(), Parma_Polyhedra_Library::Pointset_Powerset< PSET >::Pointset_Powerset(), remove_higher_space_dimensions(), and simplify_using_context_assign().
00678 { 00679 if (marked_empty()) 00680 return true; 00681 // Try a fast-fail test: if generators are up-to-date then the 00682 // generator system (since it is well formed) contains a point. 00683 if (generators_are_up_to_date()) 00684 return false; 00685 if (space_dim == 0) 00686 return false; 00687 if (congruences_are_minimized()) 00688 // If the grid was empty it would be marked empty. 00689 return false; 00690 // Minimize the congruences to check if the grid is empty. 00691 Grid& gr = const_cast<Grid&>(*this); 00692 if (gr.simplify(gr.con_sys, gr.dim_kinds)) { 00693 gr.set_empty(); 00694 return true; 00695 } 00696 gr.set_congruences_minimized(); 00697 return false; 00698 }
| bool Parma_Polyhedra_Library::Grid::is_included_in | ( | const Grid & | y | ) | const [private] |
Returns true if and only if *this is included in y.
Definition at line 238 of file Grid_nonpublic.cc.
References con_sys, congruences_are_minimized(), congruences_are_up_to_date(), marked_empty(), minimize(), OK(), Parma_Polyhedra_Library::Congruence_System::satisfies_all_congruences(), space_dim, and update_congruences().
Referenced by contains(), simplify_using_context_assign(), and upper_bound_assign_if_exact().
00238 { 00239 // Private method: the caller must ensure the following. 00240 PPL_ASSERT(space_dim == y.space_dim); 00241 PPL_ASSERT(!marked_empty() && !y.marked_empty() && space_dim > 0); 00242 00243 const Grid& x = *this; 00244 00245 #if BE_LAZY 00246 if (!x.generators_are_up_to_date() && !x.update_generators()) 00247 // Updating found `x' empty. 00248 return true; 00249 if (!y.congruences_are_up_to_date()) 00250 y.update_congruences(); 00251 #else 00252 if (!x.generators_are_minimized() && !x.minimize()) 00253 // Minimizing found `x' empty. 00254 return true; 00255 if (!y.congruences_are_minimized()) 00256 y.minimize(); 00257 #endif 00258 00259 PPL_ASSERT(x.OK()); 00260 PPL_ASSERT(y.OK()); 00261 00262 const Grid_Generator_System& gs = x.gen_sys; 00263 const Congruence_System& cgs = y.con_sys; 00264 00265 dimension_type num_rows = gs.num_rows(); 00266 for (dimension_type i = num_rows; i-- > 0; ) 00267 if (!cgs.satisfies_all_congruences(gs[i])) 00268 return false; 00269 00270 // Inclusion holds. 00271 return true; 00272 }
| bool Parma_Polyhedra_Library::Grid::is_topologically_closed | ( | ) | const |
Returns true if and only if *this is a topologically closed subset of the vector space.
A grid is always topologically closed.
Definition at line 773 of file Grid_public.cc.
| bool Parma_Polyhedra_Library::Grid::is_universe | ( | ) | const |
Returns true if and only if *this is a universe grid.
Definition at line 701 of file Grid_public.cc.
References con_sys, congruences_are_minimized(), congruences_are_up_to_date(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Congruence_System::satisfies_all_congruences(), space_dim, and update_congruences().
Referenced by operator<<().
00701 { 00702 if (marked_empty()) 00703 return false; 00704 00705 if (space_dim == 0) 00706 return true; 00707 00708 if (congruences_are_up_to_date()) { 00709 if (congruences_are_minimized()) 00710 // The minimized universe congruence system has only one row, 00711 // the integrality congruence. 00712 return con_sys.num_rows() == 1 && con_sys[0].is_tautological(); 00713 } 00714 else { 00715 update_congruences(); 00716 return con_sys.num_rows() == 1 && con_sys[0].is_tautological(); 00717 } 00718 00719 // Test con_sys's inclusion in a universe generator system. 00720 00721 // The zero dimension cases are handled above. 00722 Variable var(space_dim - 1); 00723 for (dimension_type i = space_dim; i-- > 0; ) 00724 if (!con_sys.satisfies_all_congruences(grid_line(Variable(i) + var))) 00725 return false; 00726 PPL_ASSERT(con_sys.satisfies_all_congruences(grid_point(0*var))); 00727 return true; 00728 }
| void Parma_Polyhedra_Library::Grid::limited_congruence_extrapolation_assign | ( | const Grid & | y, | |
| const Congruence_System & | cgs, | |||
| unsigned * | tp = NULL | |||
| ) |
Improves the result of the congruence variant of Grid widening computation by also enforcing those congruences in cgs that are satisfied by all the points of *this.
| y | A grid that must be contained in *this; | |
| cgs | The system of congruences used to improve the widened grid; | |
| tp | An optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique). |
| std::invalid_argument | Thrown if *this, y and cgs are dimension-incompatible. |
Definition at line 160 of file Grid_widenings.cc.
References add_recycled_congruences(), congruence_widening_assign(), contains(), generators_are_up_to_date(), Parma_Polyhedra_Library::Congruence_System::insert(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), relation_with(), space_dim, Parma_Polyhedra_Library::Congruence_System::space_dimension(), throw_dimension_incompatible(), update_generators(), and widening_assign().
00162 { 00163 Grid& x = *this; 00164 00165 // Check dimension compatibility. 00166 if (x.space_dim != y.space_dim) 00167 throw_dimension_incompatible("limited_extrapolation_assign(y, cgs)", 00168 "y", y); 00169 // `cgs' must be dimension-compatible with the two grids. 00170 const dimension_type cgs_space_dim = cgs.space_dimension(); 00171 if (x.space_dim < cgs_space_dim) 00172 throw_dimension_incompatible("limited_extrapolation_assign(y, cgs)", 00173 "cgs", cgs); 00174 00175 const dimension_type cgs_num_rows = cgs.num_rows(); 00176 // If `cgs' is empty (of rows), fall back to ordinary widening. 00177 if (cgs_num_rows == 0) { 00178 x.widening_assign(y, tp); 00179 return; 00180 } 00181 00182 #ifndef NDEBUG 00183 { 00184 // Assume that y is contained in or equal to x. 00185 const Grid x_copy = x; 00186 const Grid y_copy = y; 00187 PPL_ASSERT(x_copy.contains(y_copy)); 00188 } 00189 #endif 00190 00191 if (y.marked_empty()) 00192 return; 00193 if (x.marked_empty()) 00194 return; 00195 00196 // The limited widening between two grids in a zero-dimensional 00197 // space is also a grid in a zero-dimensional space. 00198 if (x.space_dim == 0) 00199 return; 00200 00201 // Update the generators of `x': these are used to select, from the 00202 // congruences in `cgs', those that must be added to the widened 00203 // grid. 00204 if (!x.generators_are_up_to_date() && !x.update_generators()) 00205 // `x' is empty. 00206 return; 00207 00208 if (tp == NULL || *tp == 0) { 00209 // Widening may change the grid, so add the congruences. 00210 Congruence_System new_cgs; 00211 // The congruences to be added need only be satisfied by all the 00212 // generators of `x', as `y <= x'. Iterate upwards here, to keep 00213 // the relative ordering of congruences (just for aesthetics). 00214 for (dimension_type i = 0; i < cgs_num_rows; ++i) { 00215 const Congruence& cg = cgs[i]; 00216 if (x.relation_with(cg) == Poly_Con_Relation::is_included()) 00217 new_cgs.insert(cg); 00218 } 00219 x.congruence_widening_assign(y, tp); 00220 x.add_recycled_congruences(new_cgs); 00221 } 00222 else 00223 // There are tokens, so widening will leave the grid the same. 00224 x.congruence_widening_assign(y, tp); 00225 00226 PPL_ASSERT(OK()); 00227 }
| void Parma_Polyhedra_Library::Grid::limited_extrapolation_assign | ( | const Grid & | y, | |
| const Congruence_System & | cgs, | |||
| unsigned * | tp = NULL | |||
| ) |
Improves the result of the Grid widening computation by also enforcing those congruences in cgs that are satisfied by all the points of *this.
| y | A grid that must be contained in *this; | |
| cgs | The system of congruences used to improve the widened grid; | |
| tp | An optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique). |
| std::invalid_argument | Thrown if *this, y and cgs are dimension-incompatible. |
Definition at line 468 of file Grid_widenings.cc.
References add_recycled_congruences(), contains(), generators_are_up_to_date(), Parma_Polyhedra_Library::Congruence_System::insert(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), relation_with(), space_dim, Parma_Polyhedra_Library::Congruence_System::space_dimension(), throw_dimension_incompatible(), update_generators(), and widening_assign().
00470 { 00471 Grid& x = *this; 00472 00473 // Check dimension compatibility. 00474 if (x.space_dim != y.space_dim) 00475 throw_dimension_incompatible("limited_extrapolation_assign(y, cgs)", 00476 "y", y); 00477 // `cgs' must be dimension-compatible with the two grids. 00478 const dimension_type cgs_space_dim = cgs.space_dimension(); 00479 if (x.space_dim < cgs_space_dim) 00480 throw_dimension_incompatible("limited_extrapolation_assign(y, cgs)", 00481 "cgs", cgs); 00482 00483 const dimension_type cgs_num_rows = cgs.num_rows(); 00484 // If `cgs' is empty (of rows), fall back to ordinary widening. 00485 if (cgs_num_rows == 0) { 00486 x.widening_assign(y, tp); 00487 return; 00488 } 00489 00490 #ifndef NDEBUG 00491 { 00492 // Assume that y is contained in or equal to x. 00493 const Grid x_copy = x; 00494 const Grid y_copy = y; 00495 PPL_ASSERT(x_copy.contains(y_copy)); 00496 } 00497 #endif 00498 00499 if (y.marked_empty()) 00500 return; 00501 if (x.marked_empty()) 00502 return; 00503 00504 // The limited widening between two grids in a zero-dimensional 00505 // space is also a grid in a zero-dimensional space. 00506 if (x.space_dim == 0) 00507 return; 00508 00509 // Update the generators of `x': these are used to select, from the 00510 // congruences in `cgs', those that must be added to the widened 00511 // grid. 00512 if (!x.generators_are_up_to_date() && !x.update_generators()) 00513 // `x' is empty. 00514 return; 00515 00516 if (tp == NULL || *tp == 0) { 00517 // Widening may change the grid, so add the congruences. 00518 Congruence_System new_cgs; 00519 // The congruences to be added need only be satisfied by all the 00520 // generators of `x', as `y <= x'. Iterate upwards here, to keep 00521 // the relative ordering of congruences (just for aesthetics). 00522 for (dimension_type i = 0; i < cgs_num_rows; ++i) { 00523 const Congruence& cg = cgs[i]; 00524 if (x.relation_with(cg) == Poly_Con_Relation::is_included()) 00525 new_cgs.insert(cg); 00526 } 00527 x.widening_assign(y, tp); 00528 x.add_recycled_congruences(new_cgs); 00529 } 00530 else 00531 // There are tokens, so widening will leave the grid the same. 00532 x.widening_assign(y, tp); 00533 00534 PPL_ASSERT(OK()); 00535 }
| void Parma_Polyhedra_Library::Grid::limited_generator_extrapolation_assign | ( | const Grid & | y, | |
| const Congruence_System & | cgs, | |||
| unsigned * | tp = NULL | |||
| ) |
Improves the result of the generator variant of the Grid widening computation by also enforcing those congruences in cgs that are satisfied by all the points of *this.
| y | A grid that must be contained in *this; | |
| cgs | The system of congruences used to improve the widened grid; | |
| tp | An optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique). |
| std::invalid_argument | Thrown if *this, y and cgs are dimension-incompatible. |
Definition at line 362 of file Grid_widenings.cc.
References add_recycled_congruences(), contains(), generator_widening_assign(), generators_are_up_to_date(), Parma_Polyhedra_Library::Congruence_System::insert(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), relation_with(), space_dim, Parma_Polyhedra_Library::Congruence_System::space_dimension(), throw_dimension_incompatible(), and update_generators().
00364 { 00365 Grid& x = *this; 00366 00367 // Check dimension compatibility. 00368 if (x.space_dim != y.space_dim) 00369 throw_dimension_incompatible("limited_extrapolation_assign(y, cgs)", 00370 "y", y); 00371 // `cgs' must be dimension-compatible with the two grids. 00372 const dimension_type cgs_space_dim = cgs.space_dimension(); 00373 if (x.space_dim < cgs_space_dim) 00374 throw_dimension_incompatible("limited_extrapolation_assign(y, cgs)", 00375 "cgs", cgs); 00376 00377 const dimension_type cgs_num_rows = cgs.num_rows(); 00378 // If `cgs' is empty (of rows), fall back to ordinary widening. 00379 if (cgs_num_rows == 0) { 00380 x.generator_widening_assign(y, tp); 00381 return; 00382 } 00383 00384 #ifndef NDEBUG 00385 { 00386 // Assume that y is contained in or equal to x. 00387 const Grid x_copy = x; 00388 const Grid y_copy = y; 00389 PPL_ASSERT(x_copy.contains(y_copy)); 00390 } 00391 #endif 00392 00393 if (y.marked_empty()) 00394 return; 00395 if (x.marked_empty()) 00396 return; 00397 00398 // The limited widening between two grids in a zero-dimensional 00399 // space is also a grid in a zero-dimensional space. 00400 if (x.space_dim == 0) 00401 return; 00402 00403 // Update the generators of `x': these are used to select, from the 00404 // congruences in `cgs', those that must be added to the widened 00405 // grid. 00406 if (!x.generators_are_up_to_date() && !x.update_generators()) 00407 // `x' is empty. 00408 return; 00409 00410 if (tp == NULL || *tp == 0) { 00411 // Widening may change the grid, so add the congruences. 00412 Congruence_System new_cgs; 00413 // The congruences to be added need only be satisfied by all the 00414 // generators of `x', as `y <= x'. Iterate upwards here, to keep 00415 // the relative ordering of congruences (just for aesthetics). 00416 for (dimension_type i = 0; i < cgs_num_rows; ++i) { 00417 const Congruence& cg = cgs[i]; 00418 if (x.relation_with(cg) == Poly_Con_Relation::is_included()) 00419 new_cgs.insert(cg); 00420 } 00421 x.generator_widening_assign(y, tp); 00422 x.add_recycled_congruences(new_cgs); 00423 } 00424 else 00425 // There are tokens, so widening will leave the grid the same. 00426 x.generator_widening_assign(y, tp); 00427 00428 PPL_ASSERT(OK()); 00429 }
| bool Parma_Polyhedra_Library::Grid::lower_triangular | ( | const Congruence_System & | sys, | |
| const Dimension_Kinds & | dim_kinds | |||
| ) | [static, private] |
If sys is lower triangular return true, else return false.
Definition at line 38 of file Grid_conversion.cc.
References CON_VIRTUAL, Parma_Polyhedra_Library::Matrix::num_columns(), and Parma_Polyhedra_Library::Matrix::num_rows().
Referenced by conversion(), and OK().
00039 { 00040 const dimension_type num_columns = sys.num_columns() - 1; 00041 00042 // Check for easy square failure case. 00043 if (sys.num_rows() > num_columns) 00044 return false; 00045 00046 // Check triangularity. 00047 00048 dimension_type row = 0; 00049 for (dimension_type dim = num_columns; dim-- > 0; ) { 00050 if (dim_kinds[dim] == CON_VIRTUAL) 00051 continue; 00052 const Congruence& cg = sys[row]; 00053 ++row; 00054 // Check diagonal. 00055 if (cg[dim] <= 0) 00056 return false; 00057 // Check elements following diagonal. 00058 dimension_type col = dim; 00059 while (++col < num_columns) 00060 if (cg[col] != 0) 00061 return false; 00062 } 00063 00064 // Check squareness. 00065 return row == sys.num_rows(); 00066 }
| void Parma_Polyhedra_Library::Grid::map_space_dimensions | ( | const Partial_Function & | pfunc | ) | [inline] |
Remaps the dimensions of the vector space according to a partial function.
If pfunc maps only some of the dimensions of *this then the rest will be projected away.
If the highest dimension mapped to by pfunc is higher than the highest dimension in *this then the number of dimensions in this will be increased to the highest dimension mapped to by pfunc.
| pfunc | The partial function specifying the destiny of each space dimension. |
The template type parameter Partial_Function must provide the following methods.
bool has_empty_codomain() const
returns true if and only if the represented partial function has an empty codomain (i.e., it is always undefined). The has_empty_codomain() method will always be called before the methods below. However, if has_empty_codomain() returns true, none of the functions below will be called.
dimension_type max_in_codomain() const
returns the maximum value that belongs to the codomain of the partial function. The max_in_codomain() method is called at most once.
bool maps(dimension_type i, dimension_type& j) const
Let
be the represented function and
be the value of i. If
is defined in
, then
is assigned to j and true is returned. If
is undefined in
, then false is returned. This method is called at most
times, where
is the dimension of the vector space enclosing the grid.
The result is undefined if pfunc does not encode a partial function with the properties described in the specification of the mapping operator.
Definition at line 112 of file Grid.templates.hh.
References Parma_Polyhedra_Library::Grid_Generator_System::begin(), clear_congruences_minimized(), clear_generators_minimized(), Parma_Polyhedra_Library::Grid_Generator::coefficient(), con_sys, congruences_are_up_to_date(), Parma_Polyhedra_Library::Grid_Generator::divisor(), Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::Grid_Generator_System::end(), gen_sys, generators_are_up_to_date(), grid_generators(), Parma_Polyhedra_Library::Matrix::has_no_rows(), Parma_Polyhedra_Library::Grid_Generator_System::insert(), Parma_Polyhedra_Library::Grid_Generator::LINE, marked_empty(), Parma_Polyhedra_Library::not_a_dimension(), OK(), Parma_Polyhedra_Library::Grid_Generator::PARAMETER, Parma_Polyhedra_Library::Grid_Generator_System::permute_columns(), Parma_Polyhedra_Library::Matrix::permute_columns(), Parma_Polyhedra_Library::Grid_Generator::POINT, set_empty(), Parma_Polyhedra_Library::Grid_Generator_System::set_sorted(), set_zero_dim_univ(), space_dim, swap(), throw_invalid_argument(), Parma_Polyhedra_Library::Grid_Generator::type(), and update_generators().
00112 { 00113 if (space_dim == 0) 00114 return; 00115 00116 if (pfunc.has_empty_codomain()) { 00117 // All dimensions vanish: the grid becomes zero_dimensional. 00118 if (marked_empty() 00119 || (!generators_are_up_to_date() && !update_generators())) { 00120 // Removing all dimensions from the empty grid. 00121 space_dim = 0; 00122 set_empty(); 00123 } 00124 else 00125 // Removing all dimensions from a non-empty grid. 00126 set_zero_dim_univ(); 00127 00128 PPL_ASSERT(OK()); 00129 return; 00130 } 00131 00132 dimension_type new_space_dimension = pfunc.max_in_codomain() + 1; 00133 00134 if (new_space_dimension == space_dim) { 00135 // The partial function `pfunc' is indeed total and thus specifies 00136 // a permutation, that is, a renaming of the dimensions. For 00137 // maximum efficiency, we will simply permute the columns of the 00138 // constraint system and/or the generator system. 00139 00140 // We first compute suitable permutation cycles for the columns of 00141 // the `con_sys' and `gen_sys' matrices. We will represent them 00142 // with a linear array, using 0 as a terminator for each cycle 00143 // (notice that the columns with index 0 of `con_sys' and 00144 // `gen_sys' represent the inhomogeneous terms, and thus are 00145 // unaffected by the permutation of dimensions). 00146 // Cycles of length 1 will be omitted so that, in the worst case, 00147 // we will have `space_dim' elements organized in `space_dim/2' 00148 // cycles, which means we will have at most `space_dim/2' 00149 // terminators. 00150 std::vector<dimension_type> cycles; 00151 cycles.reserve(space_dim + space_dim/2); 00152 00153 // Used to mark elements as soon as they are inserted in a cycle. 00154 std::deque<bool> visited(space_dim); 00155 00156 for (dimension_type i = space_dim; i-- > 0; ) { 00157 if (!visited[i]) { 00158 dimension_type j = i; 00159 do { 00160 visited[j] = true; 00161 // The following initialization is only to make the compiler happy. 00162 dimension_type k = 0; 00163 if (!pfunc.maps(j, k)) 00164 throw_invalid_argument("map_space_dimensions(pfunc)", 00165 " pfunc is inconsistent"); 00166 if (k == j) 00167 // Cycle of length 1: skip it. 00168 goto skip; 00169 00170 cycles.push_back(j+1); 00171 // Go along the cycle. 00172 j = k; 00173 } while (!visited[j]); 00174 // End of cycle: mark it. 00175 cycles.push_back(0); 00176 skip: 00177 ; 00178 } 00179 } 00180 00181 // If `cycles' is empty then `pfunc' is the identity. 00182 if (cycles.empty()) 00183 return; 00184 00185 // Permute all that is up-to-date. 00186 if (congruences_are_up_to_date()) { 00187 con_sys.permute_columns(cycles); 00188 clear_congruences_minimized(); 00189 } 00190 00191 if (generators_are_up_to_date()) { 00192 gen_sys.permute_columns(cycles); 00193 clear_generators_minimized(); 00194 } 00195 00196 PPL_ASSERT(OK()); 00197 return; 00198 } 00199 00200 // If control gets here, then `pfunc' is not a permutation and some 00201 // dimensions must be projected away. 00202 00203 const Grid_Generator_System& old_gensys = grid_generators(); 00204 00205 if (old_gensys.has_no_rows()) { 00206 // The grid is empty. 00207 Grid new_grid(new_space_dimension, EMPTY); 00208 std::swap(*this, new_grid); 00209 PPL_ASSERT(OK()); 00210 return; 00211 } 00212 00213 // Make a local copy of the partial function. 00214 std::vector<dimension_type> pfunc_maps(space_dim, not_a_dimension()); 00215 for (dimension_type j = space_dim; j-- > 0; ) { 00216 dimension_type pfunc_j; 00217 if (pfunc.maps(j, pfunc_j)) 00218 pfunc_maps[j] = pfunc_j; 00219 } 00220 00221 Grid_Generator_System new_gensys; 00222 // Set sortedness, for the assertion met via gs::insert. 00223 new_gensys.set_sorted(false); 00224 // Get the divisor of the first point. 00225 Grid_Generator_System::const_iterator i; 00226 Grid_Generator_System::const_iterator old_gensys_end = old_gensys.end(); 00227 for (i = old_gensys.begin(); i != old_gensys_end; ++i) 00228 if (i->is_point()) 00229 break; 00230 PPL_ASSERT(i != old_gensys_end); 00231 const Coefficient& system_divisor = i->divisor(); 00232 for (i = old_gensys.begin(); i != old_gensys_end; ++i) { 00233 const Grid_Generator& old_g = *i; 00234 Linear_Expression e(0 * Variable(new_space_dimension-1)); 00235 bool all_zeroes = true; 00236 for (dimension_type j = space_dim; j-- > 0; ) { 00237 if (old_g.coefficient(Variable(j)) != 0 00238 && pfunc_maps[j] != not_a_dimension()) { 00239 e += Variable(pfunc_maps[j]) * old_g.coefficient(Variable(j)); 00240 all_zeroes = false; 00241 } 00242 } 00243 switch (old_g.type()) { 00244 case Grid_Generator::LINE: 00245 if (!all_zeroes) 00246 new_gensys.insert(grid_line(e)); 00247 break; 00248 case Grid_Generator::PARAMETER: 00249 if (!all_zeroes) 00250 new_gensys.insert(parameter(e, system_divisor)); 00251 break; 00252 case Grid_Generator::POINT: 00253 new_gensys.insert(grid_point(e, old_g.divisor())); 00254 break; 00255 default: 00256 PPL_ASSERT(0); 00257 } 00258 } 00259 00260 Grid new_grid(new_gensys); 00261 std::swap(*this, new_grid); 00262 00263 PPL_ASSERT(OK(true)); 00264 }
| bool Parma_Polyhedra_Library::Grid::marked_empty | ( | ) | const [inline, private] |
Returns true if the grid is known to be empty.
The return value false does not necessarily implies that *this is non-empty.
Definition at line 35 of file Grid.inlines.hh.
References status, and Parma_Polyhedra_Library::Grid::Status::test_empty().
Referenced by add_congruence(), add_congruence_no_check(), add_congruences(), add_constraint(), add_constraint_no_check(), add_constraints(), add_grid_generator(), add_recycled_congruences(), add_recycled_grid_generators(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_image(), affine_preimage(), bounded_affine_image(), bounded_affine_preimage(), bounds(), bounds_no_check(), Parma_Polyhedra_Library::Box< ITV >::Box(), concatenate_assign(), congruence_widening_assign(), congruences(), constrains(), contains(), contains_integer_point(), difference_assign(), drop_some_non_integer_points(), fold_space_dimensions(), frequency_no_check(), generalized_affine_image(), generalized_affine_preimage(), generator_widening_assign(), Parma_Polyhedra_Library::Grid_Certificate::Grid_Certificate(), grid_generators(), intersection_assign(), is_bounded(), is_discrete(), is_empty(), is_included_in(), is_universe(), limited_congruence_extrapolation_assign(), limited_extrapolation_assign(), limited_generator_extrapolation_assign(), map_space_dimensions(), max_min(), minimize(), minimized_grid_generators(), OK(), operator=(), quick_equivalence_test(), refine_no_check(), refine_with_constraint(), refine_with_constraints(), relation_with(), remove_space_dimensions(), select_wider_congruences(), select_wider_generators(), time_elapse_assign(), unconstrain(), update_congruences(), update_generators(), upper_bound_assign(), upper_bound_assign_if_exact(), and wrap_assign().
00035 { 00036 return status.test_empty(); 00037 }
| bool Parma_Polyhedra_Library::Grid::max_min | ( | const Linear_Expression & | expr, | |
| const char * | method_call, | |||
| Coefficient & | ext_n, | |||
| Coefficient & | ext_d, | |||
| bool & | included, | |||
| Generator * | point = NULL | |||
| ) | const [private] |
Maximizes or minimizes expr subject to *this.
| expr | The linear expression to be maximized or minimized subject to this; | |
| method_call | The call description of the public parent method, for example "maximize(e)". Passed to throw_dimension_incompatible, as the first argument; | |
| ext_n | The numerator of the extremum value; | |
| ext_d | The denominator of the extremum value; | |
| included | true if and only if the extremum of expr in this can actually be reached (which is always the case); | |
| point | When maximization or minimization succeeds, will be assigned the point where expr reaches the extremum value. |
| std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
If *this is empty or expr is not bounded in the appropriate direction, false is returned and ext_n, ext_d, included and point are left untouched.
Definition at line 394 of file Grid_nonpublic.cc.
References bounds(), Parma_Polyhedra_Library::Grid_Generator::coefficient(), dim_kinds, Parma_Polyhedra_Library::Grid_Generator::divisor(), Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::gcd_assign(), gen_sys, generators_are_minimized(), Parma_Polyhedra_Library::Scalar_Products::homogeneous_assign(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), marked_empty(), Parma_Polyhedra_Library::Generator::point(), PPL_DIRTY_TEMP_COEFFICIENT, set_generators_minimized(), simplify(), and space_dim.
Referenced by maximize(), and minimize().
00397 { 00398 if (bounds(expr, method_call)) { 00399 if (marked_empty()) 00400 return false; 00401 if (space_dim == 0) { 00402 ext_n = 0; 00403 ext_d = 1; 00404 included = true; 00405 if (point) 00406 *point = Generator::point(); 00407 return true; 00408 } 00409 // Grid::bounds above ensures the generators are up to date. 00410 if (!generators_are_minimized()) { 00411 // Minimize the generator system. 00412 Grid& gr = const_cast<Grid&>(*this); 00413 gr.simplify(gr.gen_sys, gr.dim_kinds); 00414 gr.set_generators_minimized(); 00415 } 00416 00417 const Grid_Generator& gen = gen_sys[0]; 00418 Scalar_Products::homogeneous_assign(ext_n, expr, gen); 00419 ext_n += expr.inhomogeneous_term(); 00420 ext_d = gen.divisor(); 00421 // Reduce ext_n and ext_d. 00422 PPL_DIRTY_TEMP_COEFFICIENT(gcd); 00423 gcd_assign(gcd, ext_n, ext_d); 00424 exact_div_assign(ext_n, ext_n, gcd); 00425 exact_div_assign(ext_d, ext_d, gcd); 00426 00427 included = true; 00428 if (point) { 00429 Linear_Expression e; 00430 for (dimension_type i = space_dim; i-- > 0; ) 00431 e += gen.coefficient(Variable(i)) * Variable(i); 00432 *point = Generator::point(e, gen.divisor()); 00433 } 00434 return true; 00435 } 00436 return false; 00437 }
| dimension_type Parma_Polyhedra_Library::Grid::max_space_dimension | ( | ) | [inline, static] |
Returns the maximum space dimension all kinds of Grid can handle.
Definition at line 111 of file Grid.inlines.hh.
References Parma_Polyhedra_Library::Grid_Generator_System::max_space_dimension(), and Parma_Polyhedra_Library::Congruence_System::max_space_dimension().
Referenced by add_space_dimensions_and_embed(), add_space_dimensions_and_project(), concatenate_assign(), construct(), expand_space_dimension(), and Grid().
00111 { 00112 // One dimension is reserved to have a value of type dimension_type 00113 // that does not represent a legal dimension. 00114 return std::min(std::numeric_limits<dimension_type>::max() - 1, 00115 std::min(Congruence_System::max_space_dimension(), 00116 Grid_Generator_System::max_space_dimension() 00117 ) 00118 ); 00119 }
| bool Parma_Polyhedra_Library::Grid::maximize | ( | const Linear_Expression & | expr, | |
| Coefficient & | sup_n, | |||
| Coefficient & | sup_d, | |||
| bool & | maximum, | |||
| Generator & | point | |||
| ) | const [inline] |
Returns true if and only if *this is not empty and expr is bounded from above in *this, in which case the supremum value and a point where expr reaches it are computed.
| expr | The linear expression to be maximized subject to *this; | |
| sup_n | The numerator of the supremum value; | |
| sup_d | The denominator of the supremum value; | |
| maximum | true if the supremum value can be reached in this. Always true when this bounds expr. Present for interface compatibility with class Polyhedron, where closure points can result in a value of false; | |
| point | When maximization succeeds, will be assigned a point where expr reaches its supremum value. |
| std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
If *this is empty or expr is not bounded by *this, false is returned and sup_n, sup_d, maximum and point are left untouched.
Definition at line 328 of file Grid.inlines.hh.
References max_min().
00330 { 00331 return max_min(expr, "maximize(e, ...)", sup_n, sup_d, maximum, &point); 00332 }
| bool Parma_Polyhedra_Library::Grid::maximize | ( | const Linear_Expression & | expr, | |
| Coefficient & | sup_n, | |||
| Coefficient & | sup_d, | |||
| bool & | maximum | |||
| ) | const [inline] |
Returns true if and only if *this is not empty and expr is bounded from above in *this, in which case the supremum value is computed.
| expr | The linear expression to be maximized subject to *this; | |
| sup_n | The numerator of the supremum value; | |
| sup_d | The denominator of the supremum value; | |
| maximum | true if the supremum value can be reached in this. Always true when this bounds expr. Present for interface compatibility with class Polyhedron, where closure points can result in a value of false. |
| std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
If *this is empty or expr is not bounded by *this, false is returned and sup_n, sup_d and maximum are left untouched.
Definition at line 322 of file Grid.inlines.hh.
References max_min().
Referenced by Parma_Polyhedra_Library::Box< ITV >::Box().
00323 { 00324 return max_min(expr, "maximize(e, ...)", sup_n, sup_d, maximum); 00325 }
| bool Parma_Polyhedra_Library::Grid::minimize | ( | ) | const [private] |
Minimizes both the congruences and the generators.
false if and only if *this turns out to be an empty grid.Minimization is performed on each system only if the minimized Status field is clear.
Definition at line 516 of file Grid_nonpublic.cc.
References con_sys, congruences_are_minimized(), congruences_are_up_to_date(), dim_kinds, gen_sys, generators_are_minimized(), generators_are_up_to_date(), marked_empty(), OK(), set_congruences_minimized(), set_generators_minimized(), simplify(), space_dim, update_congruences(), and update_generators().
Referenced by affine_image(), affine_preimage(), bounds(), constrains(), frequency(), generalized_affine_image(), generalized_affine_preimage(), and wrap_assign().
00516 { 00517 // 0-dimension and empty grids are already minimized. 00518 if (marked_empty()) 00519 return false; 00520 if (space_dim == 0) 00521 return true; 00522 00523 // Are both systems already minimized? 00524 if (congruences_are_minimized() && generators_are_minimized()) 00525 return true; 00526 00527 // Invoke update_generators, update_congruences or simplify, 00528 // depending on the state of the systems. 00529 if (congruences_are_up_to_date()) { 00530 if (generators_are_up_to_date()) { 00531 Grid& gr = const_cast<Grid&>(*this); 00532 // Only one of the systems can be minimized here. 00533 if (congruences_are_minimized()) { 00534 // Minimize the generator system. 00535 gr.simplify(gr.gen_sys, gr.dim_kinds); 00536 gr.set_generators_minimized(); 00537 } 00538 else { 00539 #ifndef NDEBUG 00540 // Both systems are up to date, and the empty case is handled 00541 // above, so the grid should contain points. 00542 bool empty = simplify(gr.con_sys, gr.dim_kinds); 00543 PPL_ASSERT(!empty); 00544 #else 00545 simplify(gr.con_sys, gr.dim_kinds); 00546 #endif 00547 gr.set_congruences_minimized(); 00548 if (!generators_are_minimized()) { 00549 // Minimize the generator system. 00550 gr.simplify(gr.gen_sys, gr.dim_kinds); 00551 gr.set_generators_minimized(); 00552 } 00553 } 00554 } 00555 else { 00556 // Updating the generators may reveal that `*this' is empty. 00557 const bool ret = update_generators(); 00558 PPL_ASSERT(OK()); 00559 return ret; 00560 } 00561 } 00562 else { 00563 PPL_ASSERT(generators_are_up_to_date()); 00564 update_congruences(); 00565 } 00566 PPL_ASSERT(OK()); 00567 return true; 00568 }
| bool Parma_Polyhedra_Library::Grid::minimize | ( | const Linear_Expression & | expr, | |
| Coefficient & | inf_n, | |||
| Coefficient & | inf_d, | |||
| bool & | minimum, | |||
| Generator & | point | |||
| ) | const [inline] |
Returns true if and only if *this is not empty and expr is bounded from below in *this, in which case the infimum value and a point where expr reaches it are computed.
| expr | The linear expression to be minimized subject to *this; | |
| inf_n | The numerator of the infimum value; | |
| inf_d | The denominator of the infimum value; | |
| minimum | true if the is the infimum value can be reached in this. Always true when this bounds expr. Present for interface compatibility with class Polyhedron, where closure points can result in a value of false; | |
| point | When minimization succeeds, will be assigned a point where expr reaches its infimum value. |
| std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
If *this is empty or expr is not bounded from below, false is returned and inf_n, inf_d, minimum and point are left untouched.
Definition at line 341 of file Grid.inlines.hh.
References max_min().
00343 { 00344 return max_min(expr, "minimize(e, ...)", inf_n, inf_d, minimum, &point); 00345 }
| bool Parma_Polyhedra_Library::Grid::minimize | ( | const Linear_Expression & | expr, | |
| Coefficient & | inf_n, | |||
| Coefficient & | inf_d, | |||
| bool & | minimum | |||
| ) | const [inline] |
Returns true if and only if *this is not empty and expr is bounded from below in *this, in which case the infimum value is computed.
| expr | The linear expression to be minimized subject to *this; | |
| inf_n | The numerator of the infimum value; | |
| inf_d | The denominator of the infimum value; | |
| minimum | true if the is the infimum value can be reached in this. Always true when this bounds expr. Present for interface compatibility with class Polyhedron, where closure points can result in a value of false. |
| std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
If *this is empty or expr is not bounded from below, false is returned and inf_n, inf_d and minimum are left untouched.
Definition at line 335 of file Grid.inlines.hh.
References max_min().
Referenced by is_included_in(), and simplify_using_context_assign().
00336 { 00337 return max_min(expr, "minimize(e, ...)", inf_n, inf_d, minimum); 00338 }
| const PPL::Congruence_System & Parma_Polyhedra_Library::Grid::minimized_congruences | ( | ) | const |
Returns the system of congruences in minimal form.
Definition at line 296 of file Grid_public.cc.
References con_sys, congruences(), congruences_are_minimized(), congruences_are_up_to_date(), dim_kinds, set_congruences_minimized(), set_empty(), and simplify().
Referenced by affine_dimension(), Parma_Polyhedra_Library::Pointset_Powerset< PSET >::approximate_partition(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::Partially_Reduced_Product< D1, D2, R >::minimized_congruences(), minimized_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), and operator<<().
00296 { 00297 if (congruences_are_up_to_date() && !congruences_are_minimized()) { 00298 // Minimize the congruences. 00299 Grid& gr = const_cast<Grid&>(*this); 00300 if (gr.simplify(gr.con_sys, gr.dim_kinds)) 00301 gr.set_empty(); 00302 else 00303 gr.set_congruences_minimized(); 00304 } 00305 return congruences(); 00306 }
| Constraint_System Parma_Polyhedra_Library::Grid::minimized_constraints | ( | ) | const [inline] |
Returns a minimal system of equality constraints satisfied by *this with the same affine dimension as *this.
Definition at line 240 of file Grid.inlines.hh.
References minimized_congruences().
00240 { 00241 return Constraint_System(minimized_congruences());; 00242 }
| const PPL::Grid_Generator_System & Parma_Polyhedra_Library::Grid::minimized_grid_generators | ( | ) | const |
Returns the minimized system of generators.
Definition at line 331 of file Grid_public.cc.
References dim_kinds, gen_sys, generators_are_minimized(), generators_are_up_to_date(), Parma_Polyhedra_Library::Matrix::has_no_rows(), marked_empty(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), set_generators_minimized(), simplify(), space_dim, Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), and update_generators().
Referenced by affine_dimension().
00331 { 00332 if (space_dim == 0) { 00333 PPL_ASSERT(gen_sys.space_dimension() == 0 00334 && gen_sys.num_rows() == (marked_empty() ? 0 : 1)); 00335 return gen_sys; 00336 } 00337 00338 if (marked_empty()) { 00339 PPL_ASSERT(gen_sys.has_no_rows()); 00340 return gen_sys; 00341 } 00342 00343 if (generators_are_up_to_date()) { 00344 if (!generators_are_minimized()) { 00345 // Minimize the generators. 00346 Grid& gr = const_cast<Grid&>(*this); 00347 gr.simplify(gr.gen_sys, gr.dim_kinds); 00348 gr.set_generators_minimized(); 00349 } 00350 } 00351 else if (!update_generators()) { 00352 // Updating found the grid empty. 00353 const_cast<Grid&>(*this).set_empty(); 00354 return gen_sys; 00355 } 00356 00357 return gen_sys; 00358 }
| void Parma_Polyhedra_Library::Grid::multiply_grid | ( | const Coefficient & | multiplier, | |
| Grid_Generator & | gen, | |||
| Grid_Generator_System & | dest, | |||
| dimension_type | num_rows, | |||
| dimension_type | num_dims | |||
| ) | [static, private] |
Multiply the elements of dest by multiplier.
Definition at line 105 of file Grid_conversion.cc.
References Parma_Polyhedra_Library::Grid_Generator::is_line(), and Parma_Polyhedra_Library::Grid_Generator::is_parameter_or_point().
00107 { 00108 if (multiplier == 1) 00109 return; 00110 00111 if (gen.is_line()) 00112 // Multiply every element of the line. 00113 for (dimension_type column = num_dims; column-- > 0; ) 00114 gen[column] *= multiplier; 00115 else { 00116 PPL_ASSERT(gen.is_parameter_or_point()); 00117 // Multiply every element of every parameter. 00118 for (dimension_type index = num_rows; index-- > 0; ) { 00119 Grid_Generator& generator = dest[index]; 00120 if (generator.is_parameter_or_point()) 00121 for (dimension_type column = num_dims; column-- > 0; ) 00122 generator[column] *= multiplier; 00123 } 00124 } 00125 }
| void Parma_Polyhedra_Library::Grid::multiply_grid | ( | const Coefficient & | multiplier, | |
| Congruence & | cg, | |||
| Congruence_System & | dest, | |||
| dimension_type | num_rows, | |||
| dimension_type | num_dims | |||
| ) | [static, private] |
Multiply the elements of dest by multiplier.
Definition at line 128 of file Grid_conversion.cc.
References Parma_Polyhedra_Library::Congruence::is_equality(), and Parma_Polyhedra_Library::Congruence::is_proper_congruence().
Referenced by conversion().
00130 { 00131 if (multiplier == 1) 00132 return; 00133 00134 if (cg.is_proper_congruence()) 00135 // Multiply every element of every congruence. 00136 for (dimension_type index = num_rows; index-- > 0; ) { 00137 Congruence& congruence = dest[index]; 00138 if (congruence.is_proper_congruence()) 00139 for (dimension_type column = num_dims; column-- > 0; ) 00140 congruence[column] *= multiplier; 00141 } 00142 else { 00143 PPL_ASSERT(cg.is_equality()); 00144 // Multiply every element of the equality. 00145 for (dimension_type column = num_dims; column-- > 0; ) 00146 cg[column] *= multiplier; 00147 } 00148 }
| void Parma_Polyhedra_Library::Grid::normalize_divisors | ( | Grid_Generator_System & | sys, | |
| Grid_Generator_System & | gen_sys | |||
| ) | [static, private] |
Normalize all the divisors in sys and gen_sys.
Modify sys and gen_sys to use the same single divisor value for all generators, leaving each system representing the grid it represented originally.
| sys | The first of the generator systems to be normalized. | |
| 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. |
| std::runtime_error | Thrown if all rows in gen_sys are lines and/or parameters. |
Definition at line 571 of file Grid_nonpublic.cc.
References Parma_Polyhedra_Library::Grid_Generator::divisor(), Parma_Polyhedra_Library::Grid_Generator::is_parameter_or_point(), normalize_divisors(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), and PPL_DIRTY_TEMP_COEFFICIENT.
00572 { 00573 #ifndef NDEBUG 00574 const dimension_type num_rows = gen_sys.num_rows(); 00575 #endif 00576 PPL_ASSERT(num_rows > 0); 00577 00578 // Find the first point in gen_sys. 00579 dimension_type row = 0; 00580 while (gen_sys[row].is_line_or_parameter()) { 00581 ++row; 00582 // gen_sys should have at least one point. 00583 PPL_ASSERT(row < num_rows); 00584 } 00585 Grid_Generator& first_point = gen_sys[row]; 00586 const Coefficient& gen_sys_divisor = first_point.divisor(); 00587 00588 #ifndef NDEBUG 00589 // Check that the divisors in gen_sys are equal. 00590 for (dimension_type i = row + 1; i < num_rows; ++i) { 00591 Grid_Generator& g = gen_sys[i]; 00592 if (g.is_parameter_or_point()) 00593 PPL_ASSERT(gen_sys_divisor == g.divisor()); 00594 } 00595 #endif // !defined(NDEBUG) 00596 00597 PPL_DIRTY_TEMP_COEFFICIENT(divisor); 00598 divisor = gen_sys_divisor; 00599 // Adjust sys to include the gen_sys divisor. 00600 normalize_divisors(sys, divisor); 00601 if (divisor != gen_sys_divisor) 00602 // Adjust gen_sys to use the new divisor. 00603 // 00604 // The points and parameters in gen_sys share a common divisor 00605 // value, so the new divisor will be the LCM of this common 00606 // divisor and `divisor', hence the third argument. 00607 normalize_divisors(gen_sys, divisor, &first_point); 00608 }
| void Parma_Polyhedra_Library::Grid::normalize_divisors | ( | Grid_Generator_System & | sys | ) | [inline, static, private] |
Normalizes the divisors in sys.
Converts sys to an equivalent system in which the divisors are of equal value.
| sys | The generator system to be normalized. It must have at least one row. |
Definition at line 348 of file Grid.inlines.hh.
References normalize_divisors(), and PPL_DIRTY_TEMP_COEFFICIENT.
00348 { 00349 PPL_DIRTY_TEMP_COEFFICIENT(divisor); 00350 divisor = 1; 00351 normalize_divisors(sys, divisor); 00352 }
| void Parma_Polyhedra_Library::Grid::normalize_divisors | ( | Grid_Generator_System & | sys, | |
| Coefficient & | divisor, | |||
| const Grid_Generator * | first_point = NULL | |||
| ) | [static, private] |
Normalizes the divisors in sys.
Converts sys to an equivalent system in which the divisors are of equal value.
| sys | The generator system to be normalized. It must have at least one row. | |
| divisor | A reference to the initial value of the divisor. The resulting value of this object is the new system divisor. | |
| first_point | If first_point has a value other than NULL then it is taken as the first point in sys, and it is assumed that any following points have the same divisor as first_point. |
Definition at line 611 of file Grid_nonpublic.cc.
References Parma_Polyhedra_Library::Grid_Generator::divisor(), Parma_Polyhedra_Library::Grid_Generator::is_parameter_or_point(), Parma_Polyhedra_Library::lcm_assign(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), and Parma_Polyhedra_Library::Grid_Generator_System::space_dimension().
Referenced by add_grid_generator(), add_recycled_grid_generators(), add_space_dimensions(), add_space_dimensions_and_project(), affine_image(), construct(), generalized_affine_image(), generalized_affine_preimage(), normalize_divisors(), time_elapse_assign(), and upper_bound_assign().
00613 { 00614 PPL_ASSERT(divisor >= 0); 00615 if (sys.space_dimension() > 0 && divisor > 0) { 00616 dimension_type row = 0; 00617 dimension_type num_rows = sys.num_rows(); 00618 00619 if (first_point) 00620 lcm_assign(divisor, divisor, (*first_point).divisor()); 00621 else { 00622 PPL_ASSERT(num_rows > 0); 00623 // Move to the first point or parameter. 00624 while (sys[row].is_line()) 00625 if (++row == num_rows) 00626 // All rows are lines. 00627 return; 00628 00629 // Calculate the LCM of the given divisor and the divisor of 00630 // every point or parameter. 00631 while (row < num_rows) { 00632 const Grid_Generator& g = sys[row]; 00633 if (g.is_parameter_or_point()) 00634 lcm_assign(divisor, divisor, g.divisor()); 00635 ++row; 00636 } 00637 } 00638 00639 // Represent every point and every parameter using the newly 00640 // calculated divisor. 00641 for (row = num_rows; row-- > 0; ) 00642 sys[row].scale_to_divisor(divisor); 00643 } 00644 }
| bool Parma_Polyhedra_Library::Grid::OK | ( | bool | check_not_empty = false |
) | const |
Checks if all the invariants are satisfied.
true if and only if *this satisfies all the invariants and either check_not_empty is false or *this is not empty.| check_not_empty | true if and only if, in addition to checking the invariants, *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 std::cerr in case invariants are violated. This is useful for the purpose of debugging the library.
Definition at line 864 of file Grid_public.cc.
References ascii_dump(), Parma_Polyhedra_Library::Congruence_System::ascii_dump(), Parma_Polyhedra_Library::Grid_Generator_System::ascii_dump(), clear_generators_up_to_date(), con_sys, CON_VIRTUAL, congruences_are_minimized(), congruences_are_up_to_date(), dim_kinds, EQUALITY, gen_sys, GEN_VIRTUAL, generators_are_minimized(), generators_are_up_to_date(), Parma_Polyhedra_Library::Matrix::has_no_rows(), Parma_Polyhedra_Library::Grid_Generator_System::has_points(), Parma_Polyhedra_Library::Congruence_System::is_equal_to(), Parma_Polyhedra_Library::Grid_Generator::is_equal_to(), LINE, lower_triangular(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), Parma_Polyhedra_Library::Congruence_System::OK(), Parma_Polyhedra_Library::Grid_Generator_System::OK(), Parma_Polyhedra_Library::Grid::Status::OK(), PARAMETER, PROPER_CONGRUENCE, simplify(), Parma_Polyhedra_Library::Grid_Generator::size(), space_dim, Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), Parma_Polyhedra_Library::Congruence_System::space_dimension(), status, swap(), update_generators(), and upper_triangular().
Referenced by add_congruence_no_check(), add_grid_generator(), add_recycled_congruences(), add_recycled_grid_generators(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_image(), affine_preimage(), bounded_affine_image(), bounded_affine_preimage(), concatenate_assign(), congruence_widening_assign(), construct(), difference_assign(), drop_some_non_integer_points(), expand_space_dimension(), fold_space_dimensions(), generalized_affine_image(), generalized_affine_preimage(), generator_widening_assign(), Grid(), intersection_assign(), is_included_in(), limited_congruence_extrapolation_assign(), limited_extrapolation_assign(), limited_generator_extrapolation_assign(), map_space_dimensions(), minimize(), remove_higher_space_dimensions(), remove_space_dimensions(), simplify_using_context_assign(), time_elapse_assign(), unconstrain(), and upper_bound_assign().
00864 { 00865 #ifndef NDEBUG 00866 using std::endl; 00867 using std::cerr; 00868 #endif 00869 00870 // Check whether the status information is legal. 00871 if (!status.OK()) 00872 goto fail; 00873 00874 if (marked_empty()) { 00875 if (check_not_empty) { 00876 // The caller does not want the grid to be empty. 00877 #ifndef NDEBUG 00878 cerr << "Empty grid!" << endl; 00879 #endif 00880 goto fail; 00881 } 00882 00883 if (con_sys.space_dimension() != space_dim) { 00884 #ifndef NDEBUG 00885 cerr << "The grid is in a space of dimension " << space_dim 00886 << " while the system of congruences is in a space of dimension " 00887 << con_sys.space_dimension() 00888 << endl; 00889 #endif 00890 goto fail; 00891 } 00892 return true; 00893 } 00894 00895 // A zero-dimensional universe grid is legal only if the system of 00896 // congruences `con_sys' is empty, and the generator system contains 00897 // one point. 00898 if (space_dim == 0) { 00899 if (con_sys.has_no_rows()) 00900 if (gen_sys.num_rows() == 1 && gen_sys[0].is_point()) 00901 return true; 00902 #ifndef NDEBUG 00903 cerr << "Zero-dimensional grid should have an empty congruence" << endl 00904 << "system and a generator system of a single point." << endl; 00905 #endif 00906 goto fail; 00907 } 00908 00909 // A grid is defined by a system of congruences or a system of 00910 // generators. At least one of them must be up to date. 00911 if (!congruences_are_up_to_date() && !generators_are_up_to_date()) { 00912 #ifndef NDEBUG 00913 cerr << "Grid not empty, not zero-dimensional" << endl 00914 << "and with neither congruences nor generators up-to-date!" 00915 << endl; 00916 #endif 00917 goto fail; 00918 } 00919 00920 { 00921 // The expected number of columns in the congruence and generator 00922 // systems, if they are not empty. 00923 const dimension_type num_columns = space_dim + 1; 00924 00925 // Here we check if the size of the matrices is consistent. 00926 // Let us suppose that all the matrices are up-to-date; this means: 00927 // `con_sys' : number of congruences x poly_num_columns 00928 // `gen_sys' : number of generators x poly_num_columns 00929 if (congruences_are_up_to_date()) 00930 if (con_sys.num_columns() != num_columns + 1 /* moduli */) { 00931 #ifndef NDEBUG 00932 cerr << "Incompatible size! (con_sys and space_dim)" 00933 << endl; 00934 #endif 00935 goto fail; 00936 } 00937 00938 if (generators_are_up_to_date()) { 00939 if (gen_sys.space_dimension() + 1 != num_columns) { 00940 #ifndef NDEBUG 00941 cerr << "Incompatible size! (gen_sys and space_dim)" 00942 << endl; 00943 #endif 00944 goto fail; 00945 } 00946 00947 // Check if the system of generators is well-formed. 00948 if (!gen_sys.OK()) 00949 goto fail; 00950 00951 // Check each generator in the system. 00952 for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) { 00953 const Grid_Generator& g = gen_sys[i]; 00954 00955 if (g.size() < 1) { 00956 #ifndef NDEBUG 00957 cerr << "Parameter should have coefficients." << endl; 00958 #endif 00959 goto fail; 00960 } 00961 } 00962 00963 // A non-empty system of generators describing a grid is valid 00964 // if and only if it contains a point. 00965 if (!gen_sys.has_no_rows() && !gen_sys.has_points()) { 00966 #ifndef NDEBUG 00967 cerr << "Non-empty generator system declared up-to-date " 00968 << "has no points!" 00969 << endl; 00970 #endif 00971 goto fail; 00972 } 00973 00974 if (generators_are_minimized()) { 00975 Grid_Generator_System gs = gen_sys; 00976 00977 if (dim_kinds.size() != num_columns) { 00978 #ifndef NDEBUG 00979 cerr << "Size of dim_kinds should equal the number of columns." 00980 << endl; 00981 #endif 00982 goto fail; 00983 } 00984 00985 if (!upper_triangular(gs, dim_kinds)) { 00986 #ifndef NDEBUG 00987 cerr << "Reduced generators should be upper triangular." 00988 << endl; 00989 #endif 00990 goto fail; 00991 } 00992 00993 // Check that dim_kinds corresponds to the row kinds in gen_sys. 00994 for (dimension_type dim = space_dim, 00995 row = gen_sys.num_rows(); dim > 0; --dim) { 00996 if (dim_kinds[dim] == GEN_VIRTUAL) 00997 goto ok; 00998 if (gen_sys[--row].is_parameter_or_point() 00999 && dim_kinds[dim] == PARAMETER) 01000 goto ok; 01001 PPL_ASSERT(gen_sys[row].is_line()); 01002 if (dim_kinds[dim] == LINE) 01003 goto ok; 01004 #ifndef NDEBUG 01005 cerr << "Kinds in dim_kinds should match those in gen_sys." 01006 << endl; 01007 #endif 01008 goto fail; 01009 ok: 01010 PPL_ASSERT(row <= dim); 01011 } 01012 01013 // A reduced generator system must be the same as a temporary 01014 // reduced copy. 01015 Dimension_Kinds dk = dim_kinds; 01016 // `gs' is minimized and marked_empty returned false, so `gs' 01017 // should contain rows. 01018 PPL_ASSERT(!gs.has_no_rows()); 01019 simplify(gs, dk); 01020 // gs contained rows before being reduced, so it should 01021 // contain at least a single point afterward. 01022 PPL_ASSERT(!gs.has_no_rows()); 01023 for (dimension_type row = gen_sys.num_rows(); row-- > 0; ) { 01024 Grid_Generator& g = gs[row]; 01025 const Grid_Generator& g_copy = gen_sys[row]; 01026 if (g.is_equal_to(g_copy)) 01027 continue; 01028 #ifndef NDEBUG 01029 cerr << "Generators are declared minimized," 01030 " but they change under reduction.\n" 01031 << "Here is the generator system:\n"; 01032 gen_sys.ascii_dump(cerr); 01033 cerr << "and here is the minimized form of the temporary copy:\n"; 01034 gs.ascii_dump(cerr); 01035 #endif 01036 goto fail; 01037 } 01038 } 01039 01040 } // if (congruences_are_up_to_date()) 01041 } 01042 01043 if (congruences_are_up_to_date()) { 01044 // Check if the system of congruences is well-formed. 01045 if (!con_sys.OK()) 01046 goto fail; 01047 01048 Grid tmp_gr = *this; 01049 Congruence_System cs_copy = tmp_gr.con_sys; 01050 01051 // Clear the generators in tmp_gr. 01052 Grid_Generator_System gs(space_dim); 01053 std::swap(tmp_gr.gen_sys, gs); 01054 tmp_gr.clear_generators_up_to_date(); 01055 01056 if (!tmp_gr.update_generators()) { 01057 if (check_not_empty) { 01058 // Want to know the satisfiability of the congruences. 01059 #ifndef NDEBUG 01060 cerr << "Unsatisfiable system of congruences!" 01061 << endl; 01062 #endif 01063 goto fail; 01064 } 01065 // The grid is empty, all checks are done. 01066 return true; 01067 } 01068 01069 if (congruences_are_minimized()) { 01070 // A reduced congruence system must be lower triangular. 01071 if (!lower_triangular(con_sys, dim_kinds)) { 01072 #ifndef NDEBUG 01073 cerr << "Reduced congruences should be lower triangular." << endl; 01074 #endif 01075 goto fail; 01076 } 01077 01078 // If the congruences are minimized, all the elements in the 01079 // congruence system must be the same as those in the temporary, 01080 // minimized system `cs_copy'. 01081 if (!con_sys.is_equal_to(cs_copy)) { 01082 #ifndef NDEBUG 01083 cerr << "Congruences are declared minimized, but they change under reduction!" 01084 << endl 01085 << "Here is the minimized form of the congruence system:" 01086 << endl; 01087 cs_copy.ascii_dump(cerr); 01088 cerr << endl; 01089 #endif 01090 goto fail; 01091 } 01092 01093 if (dim_kinds.size() != con_sys.num_columns() - 1 /* modulus */) { 01094 #ifndef NDEBUG 01095 cerr << "Size of dim_kinds should equal the number of columns." 01096 << endl; 01097 #endif 01098 goto fail; 01099 } 01100 01101 // Check that dim_kinds corresponds to the row kinds in con_sys. 01102 for (dimension_type dim = space_dim, row = 0; dim > 0; --dim) { 01103 if (dim_kinds[dim] == CON_VIRTUAL) 01104 continue; 01105 if (con_sys[row++].is_proper_congruence() 01106 && dim_kinds[dim] == PROPER_CONGRUENCE) 01107 continue; 01108 PPL_ASSERT(con_sys[row-1].is_equality()); 01109 if (dim_kinds[dim] == EQUALITY) 01110 continue; 01111 #ifndef NDEBUG 01112 cerr << "Kinds in dim_kinds should match those in con_sys." << endl; 01113 #endif 01114 goto fail; 01115 } 01116 } 01117 } 01118 01119 return true; 01120 01121 fail: 01122 #ifndef NDEBUG 01123 cerr << "Here is the grid under check:" << endl; 01124 ascii_dump(cerr); 01125 #endif 01126 return false; 01127 }
The assignment operator. (*this and y can be dimension-incompatible.).
Definition at line 240 of file Grid_public.cc.
References con_sys, congruences_are_up_to_date(), dim_kinds, gen_sys, generators_are_up_to_date(), marked_empty(), set_empty(), set_zero_dim_univ(), space_dim, and status.
00240 { 00241 space_dim = y.space_dim; 00242 dim_kinds = y.dim_kinds; 00243 if (y.marked_empty()) 00244 set_empty(); 00245 else if (space_dim == 0) 00246 set_zero_dim_univ(); 00247 else { 00248 status = y.status; 00249 if (y.congruences_are_up_to_date()) 00250 con_sys = y.con_sys; 00251 if (y.generators_are_up_to_date()) 00252 gen_sys = y.gen_sys; 00253 } 00254 return *this; 00255 }
| void Parma_Polyhedra_Library::Grid::print | ( | ) | const |
Prints *this to std::cerr using operator<<.
| PPL::Grid::Three_Valued_Boolean Parma_Polyhedra_Library::Grid::quick_equivalence_test | ( | const Grid & | y | ) | const [private] |
Polynomial but incomplete equivalence test between grids.
Definition at line 182 of file Grid_nonpublic.cc.
References con_sys, congruences_are_minimized(), gen_sys, generators_are_minimized(), marked_empty(), Parma_Polyhedra_Library::Congruence_System::num_equalities(), Parma_Polyhedra_Library::Grid_Generator_System::num_lines(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), Parma_Polyhedra_Library::Matrix::num_rows(), space_dim, TVB_DONT_KNOW, TVB_FALSE, and TVB_TRUE.
Referenced by contains().
00182 { 00183 // Private method: the caller must ensure the following. 00184 PPL_ASSERT(space_dim == y.space_dim); 00185 PPL_ASSERT(!marked_empty() && !y.marked_empty() && space_dim > 0); 00186 00187 const Grid& x = *this; 00188 00189 bool css_normalized = false; 00190 00191 if (x.congruences_are_minimized() && y.congruences_are_minimized()) { 00192 // Equivalent minimized congruence systems have: 00193 // - the same number of congruences; ... 00194 if (x.con_sys.num_rows() != y.con_sys.num_rows()) 00195 return Grid::TVB_FALSE; 00196 // - the same number of equalities; ... 00197 dimension_type x_num_equalities = x.con_sys.num_equalities(); 00198 if (x_num_equalities != y.con_sys.num_equalities()) 00199 return Grid::TVB_FALSE; 00200 // - and if there are no equalities, the same congruences. 00201 // Delay this test: try cheaper tests on generators first. 00202 css_normalized = (x_num_equalities == 0); 00203 } 00204 00205 if (x.generators_are_minimized() && y.generators_are_minimized()) { 00206 // Equivalent minimized generator systems have: 00207 // - the same number of generators; ... 00208 if (x.gen_sys.num_rows() != y.gen_sys.num_rows()) 00209 return Grid::TVB_FALSE; 00210 // - the same number of lines; ... 00211 const dimension_type x_num_lines = x.gen_sys.num_lines(); 00212 if (x_num_lines != y.gen_sys.num_lines()) 00213 return Grid::TVB_FALSE; 00214 // - and if there are no lines, the same generators. 00215 if (x_num_lines == 0) { 00216 // Check for syntactic identity. 00217 if (x.gen_sys == y.gen_sys) 00218 return Grid::TVB_TRUE; 00219 else 00220 return Grid::TVB_FALSE; 00221 } 00222 } 00223 00224 // TODO: Consider minimizing the systems and re-performing these 00225 // checks. 00226 00227 if (css_normalized) { 00228 if (x.con_sys == y.con_sys) 00229 return Grid::TVB_TRUE; 00230 else 00231 return Grid::TVB_FALSE; 00232 } 00233 00234 return Grid::TVB_DONT_KNOW; 00235 }
| void Parma_Polyhedra_Library::Grid::reduce_congruence_with_equality | ( | Congruence & | row, | |
| const Congruence & | pivot, | |||
| dimension_type | col, | |||
| Congruence_System & | sys | |||
| ) | [static, private] |
Reduce row using pivot.
Use the equality pivot to change the representation of the congruence row such that element at index col of row is zero.
Definition at line 182 of file Grid_simplify.cc.
References Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::gcd_assign(), Parma_Polyhedra_Library::Congruence::is_proper_congruence(), Parma_Polyhedra_Library::Congruence::modulus(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), PPL_DIRTY_TEMP_COEFFICIENT, and Parma_Polyhedra_Library::sub_mul_assign().
Referenced by simplify().
00185 { 00186 // Very similar to reduce_parameter_with_line above. Any change 00187 // here may be needed there too. 00188 PPL_ASSERT(row.modulus() > 0 && pivot.modulus() == 0); 00189 00190 const Coefficient& pivot_column = pivot[column]; 00191 Coefficient& row_column = row[column]; 00192 00193 dimension_type num_columns = sys.num_columns(); 00194 00195 // If the elements at `column' in row and pivot are the same, then 00196 // just subtract `pivot' from `row'. 00197 if (row_column == pivot_column) { 00198 for (dimension_type col = num_columns; col-- > 0; ) 00199 row[col] -= pivot[col]; 00200 return; 00201 } 00202 00203 PPL_DIRTY_TEMP_COEFFICIENT(reduced_row_col); 00204 // Use reduced_row_col temporarily to hold the gcd. 00205 gcd_assign(reduced_row_col, pivot_column, row_column); 00206 PPL_DIRTY_TEMP_COEFFICIENT(reduced_pivot_col); 00207 exact_div_assign(reduced_pivot_col, pivot_column, reduced_row_col); 00208 exact_div_assign(reduced_row_col, row_column, reduced_row_col); 00209 // Ensure that `reduced_pivot_col' is positive, so that the modulus 00210 // remains positive when multiplying the proper congruences below. 00211 // It's safe to swap the signs as row[column] will still come out 0. 00212 if (reduced_pivot_col < 0) { 00213 neg_assign(reduced_pivot_col); 00214 neg_assign(reduced_row_col); 00215 } 00216 // Multiply `row', including the modulus, by reduced_pivot_col. To 00217 // keep all the moduli the same this requires multiplying all the 00218 // other proper congruences in the same way. 00219 for (dimension_type index = sys.num_rows(); index-- > 0; ) { 00220 Congruence& cg = sys[index]; 00221 if (cg.is_proper_congruence()) 00222 for (dimension_type col = num_columns; col-- > 0; ) 00223 cg[col] *= reduced_pivot_col; 00224 } 00225 // Column num_columns contains the modulus, so start at the next 00226 // column. 00227 --num_columns; 00228 row_column = 0; 00229 // Subtract from row a multiple of pivot such that the result in 00230 // row[column] is zero. 00231 for (dimension_type col = column; col-- > 0; ) 00232 sub_mul_assign(row[col], reduced_row_col, pivot[col]); 00233 }
| void Parma_Polyhedra_Library::Grid::reduce_equality_with_equality | ( | Congruence & | row, | |
| const Congruence & | pivot, | |||
| dimension_type | col | |||
| ) | [static, private] |
Reduces the equality row using the equality pivot.
Uses the equality pivot to change the representation of the equality row so that the element at index col of row is zero.
Definition at line 58 of file Grid_simplify.cc.
References Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::gcd_assign(), Parma_Polyhedra_Library::Congruence::modulus(), PPL_DIRTY_TEMP_COEFFICIENT, and Parma_Polyhedra_Library::sub_mul_assign().
Referenced by simplify().
00060 { 00061 // Assume two equalities. 00062 PPL_ASSERT(row.modulus() == 0 && pivot.modulus() == 0); 00063 00064 const Coefficient& pivot_column = pivot[column]; 00065 Coefficient& row_column = row[column]; 00066 PPL_DIRTY_TEMP_COEFFICIENT(reduced_row_col); 00067 // Use reduced_row_col temporarily to hold the gcd. 00068 gcd_assign(reduced_row_col, pivot_column, row_column); 00069 // Store the reduced ratio between pivot[column] and row[column]. 00070 PPL_DIRTY_TEMP_COEFFICIENT(reduced_pivot_col); 00071 exact_div_assign(reduced_pivot_col, pivot_column, reduced_row_col); 00072 exact_div_assign(reduced_row_col, row_column, reduced_row_col); 00073 // Multiply row, then subtract from it a multiple of pivot such that 00074 // the result in row[column] is zero. 00075 row_column = 0; 00076 for (dimension_type col = column; col-- > 0; ) { 00077 Coefficient& row_col = row[col]; 00078 row_col *= reduced_pivot_col; 00079 sub_mul_assign(row_col, reduced_row_col, pivot[col]); 00080 } 00081 }
| void Parma_Polyhedra_Library::Grid::reduce_line_with_line | ( | Grid_Generator & | row, | |
| Grid_Generator & | pivot, | |||
| dimension_type | col | |||
| ) | [static, private] |
Reduces the line row using the line pivot.
Uses the line pivot to change the representation of the line row so that the element at index col of row is zero.
Definition at line 32 of file Grid_simplify.cc.
References Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::gcd_assign(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Grid_Generator::size(), and Parma_Polyhedra_Library::sub_mul_assign().
Referenced by simplify().
00033 { 00034 const Coefficient& pivot_column = pivot[column]; 00035 Coefficient& row_column = row[column]; 00036 PPL_DIRTY_TEMP_COEFFICIENT(reduced_row_col); 00037 // Use reduced_row_col temporarily to hold the gcd. 00038 gcd_assign(reduced_row_col, pivot_column, row_column); 00039 // Store the reduced ratio between pivot[column] and row[column]. 00040 PPL_DIRTY_TEMP_COEFFICIENT(reduced_pivot_col); 00041 exact_div_assign(reduced_pivot_col, pivot_column, reduced_row_col); 00042 exact_div_assign(reduced_row_col, row_column, reduced_row_col); 00043 // Multiply row, then subtract from it a multiple of pivot such that 00044 // the result in row[column] is zero. 00045 row_column = 0; 00046 // pivot.size() - 1 is the index for the parameter divisor so we 00047 // start reducing the line at index pivot.size() - 2. 00048 for (dimension_type col = pivot.size() - 2; 00049 col > column; 00050 --col) { 00051 Coefficient& row_col = row[col]; 00052 row_col *= reduced_pivot_col; 00053 sub_mul_assign(row_col, reduced_row_col, pivot[col]); 00054 } 00055 }
| void Parma_Polyhedra_Library::Grid::reduce_parameter_with_line | ( | Grid_Generator & | row, | |
| const Grid_Generator & | pivot, | |||
| dimension_type | col, | |||
| Grid_Generator_System & | sys | |||
| ) | [static, private] |
Reduce row using pivot.
Use the line pivot to change the representation of the parameter row such that the element at index col of row is zero.
Definition at line 126 of file Grid_simplify.cc.
References Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::gcd_assign(), Parma_Polyhedra_Library::Grid_Generator::is_parameter_or_point(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Grid_Generator_System::num_columns(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), PPL_DIRTY_TEMP_COEFFICIENT, and Parma_Polyhedra_Library::sub_mul_assign().
Referenced by simplify().
00129 { 00130 // Very similar to reduce_congruence_with_equality below. Any 00131 // change here may be needed there too. 00132 00133 const Coefficient& pivot_column = pivot[column]; 00134 Coefficient& row_column = row[column]; 00135 00136 // Subtract one to allow for the parameter divisor column 00137 const dimension_type num_columns = sys.num_columns() - 1; 00138 00139 // If the elements at column in row and pivot are the same, then 00140 // just subtract pivot from row. 00141 if (row_column == pivot_column) { 00142 for (dimension_type col = num_columns; col-- > 0; ) 00143 row[col] -= pivot[col]; 00144 return; 00145 } 00146 00147 PPL_DIRTY_TEMP_COEFFICIENT(reduced_row_col); 00148 // Use reduced_row_col temporarily to hold the gcd. 00149 gcd_assign(reduced_row_col, pivot_column, row_column); 00150 // Store the reduced ratio between pivot[column] and row[column]. 00151 PPL_DIRTY_TEMP_COEFFICIENT(reduced_pivot_col); 00152 exact_div_assign(reduced_pivot_col, pivot_column, reduced_row_col); 00153 exact_div_assign(reduced_row_col, row_column, reduced_row_col); 00154 00155 00156 // Since we are reducing the system to "strong minimal form", 00157 // ensure that the multiplier is positive, so that the preceding 00158 // diagonals (including the divisor) remain positive. It's safe to 00159 // swap the signs as row[column] will still come out 0. 00160 if (reduced_pivot_col < 0) { 00161 neg_assign(reduced_pivot_col); 00162 neg_assign(reduced_row_col); 00163 } 00164 00165 // Multiply row such that a multiple of pivot can be subtracted from 00166 // it below to render row[column] zero. This requires multiplying 00167 // all other parameters to match. 00168 for (dimension_type index = sys.num_rows(); index-- > 0; ) { 00169 Grid_Generator& gen = sys[index]; 00170 if (gen.is_parameter_or_point()) 00171 for (dimension_type col = num_columns; col-- > 0; ) 00172 gen[col] *= reduced_pivot_col; 00173 } 00174 // Subtract from row a multiple of pivot such that the result in 00175 // row[column] is zero. 00176 row_column = 0; 00177 for (dimension_type col = num_columns - 1; col > column; --col) 00178 sub_mul_assign(row[col], reduced_row_col, pivot[col]); 00179 }
| void Parma_Polyhedra_Library::Grid::reduce_pc_with_pc | ( | R & | row, | |
| R & | pivot, | |||
| dimension_type | col, | |||
| dimension_type | start, | |||
| dimension_type | end | |||
| ) | [inline, static, private] |
Reduces row using pivot.
Uses the point, parameter or proper congruence at pivot to change the representation of the point, parameter or proper congruence at row so that the element at index col of row is zero. Only elements from index start to index end are modified (i.e. it is assumed that all other elements are zero).
Definition at line 85 of file Grid_simplify.cc.
References Parma_Polyhedra_Library::add_mul_assign(), Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::gcdext_assign(), PPL_DIRTY_TEMP_COEFFICIENT, and Parma_Polyhedra_Library::sub_mul_assign().
Referenced by simplify().
00088 { 00089 Coefficient& pivot_column = pivot[column]; 00090 Coefficient& row_column = row[column]; 00091 00092 PPL_DIRTY_TEMP_COEFFICIENT(s); 00093 PPL_DIRTY_TEMP_COEFFICIENT(t); 00094 PPL_DIRTY_TEMP_COEFFICIENT(reduced_row_col); 00095 // Use reduced_row_col temporarily to hold the gcd. 00096 gcdext_assign(reduced_row_col, s, t, pivot_column, row_column); 00097 // Now pivot[column] * s + row[column] * t == gcd. 00098 00099 // Store the reduced ratio between pivot[column] and row[column]. 00100 PPL_DIRTY_TEMP_COEFFICIENT(reduced_pivot_col); 00101 exact_div_assign(reduced_pivot_col, pivot_column, reduced_row_col); 00102 pivot_column = reduced_row_col /* gcd */; 00103 exact_div_assign(reduced_row_col, row_column, reduced_row_col); 00104 00105 // Multiply row, then subtract from it a multiple of pivot such that 00106 // the result in row[column] is zero. Afterward, multiply pivot, 00107 // then add to it a (possibly negative) multiple of row such that 00108 // the result in pivot[column] is the smallest possible positive 00109 // integer. 00110 PPL_ASSERT(pivot.size() > 0); 00111 PPL_ASSERT(row.size() > 0); 00112 row_column = 0; 00113 PPL_DIRTY_TEMP_COEFFICIENT(old_pivot_col); 00114 for (dimension_type col = start; col < end; ++col) { 00115 Coefficient& pivot_col = pivot[col]; 00116 old_pivot_col = pivot_col; 00117 pivot_col *= s; 00118 Coefficient& row_col = row[col]; 00119 add_mul_assign(pivot_col, t, row_col); 00120 row_col *= reduced_pivot_col; 00121 sub_mul_assign(row_col, reduced_row_col, old_pivot_col); 00122 } 00123 }
| void Parma_Polyhedra_Library::Grid::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 | |||
| ) | [inline, static, private] |
Reduce column dim in rows preceding pivot_index in 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
, (which is in minimal form) is equivalent to the set
(which is in strong minimal form).
Only consider from index start to index end of the row at pivot_index. Flag generators indicates whether sys is a congruence or generator system.
Definition at line 270 of file Grid.templates.hh.
References CON_VIRTUAL, EQUALITY, GEN_VIRTUAL, LINE, PARAMETER, PPL_DIRTY_TEMP_COEFFICIENT, and Parma_Polyhedra_Library::sub_mul_assign().
00276 { 00277 R& pivot = sys[pivot_index]; 00278 00279 const Coefficient& pivot_dim = pivot[dim]; 00280 00281 if (pivot_dim == 0) 00282 return; 00283 00284 PPL_DIRTY_TEMP_COEFFICIENT(pivot_dim_half); 00285 pivot_dim_half = (pivot_dim + 1) / 2; 00286 Dimension_Kind row_kind = dim_kinds[dim]; 00287 Dimension_Kind line_or_equality, virtual_kind; 00288 int jump; 00289 if (generators) { 00290 line_or_equality = LINE; 00291 virtual_kind = GEN_VIRTUAL; 00292 jump = -1; 00293 } 00294 else { 00295 line_or_equality = EQUALITY; 00296 virtual_kind = CON_VIRTUAL; 00297 jump = 1; 00298 } 00299 00300 PPL_DIRTY_TEMP_COEFFICIENT(num_rows_to_subtract); 00301 PPL_DIRTY_TEMP_COEFFICIENT(row_dim_remainder); 00302 for (dimension_type row_index = pivot_index, kinds_index = dim + jump; 00303 row_index-- > 0; 00304 kinds_index += jump) { 00305 // Move over any virtual rows. 00306 while (dim_kinds[kinds_index] == virtual_kind) 00307 kinds_index += jump; 00308 00309 // row_kind CONGRUENCE is included as PARAMETER 00310 if (row_kind == line_or_equality 00311 || (row_kind == PARAMETER 00312 && dim_kinds[kinds_index] == PARAMETER)) { 00313 R& row = sys[row_index]; 00314 00315 const Coefficient& row_dim = row[dim]; 00316 // num_rows_to_subtract may be positive or negative. 00317 num_rows_to_subtract = row_dim / pivot_dim; 00318 00319 // Ensure that after subtracting num_rows_to_subtract * r_dim 00320 // from row_dim, -pivot_dim_half < row_dim <= pivot_dim_half. 00321 // E.g., if pivot[dim] = 9, then after this reduction 00322 // -5 < row_dim <= 5. 00323 row_dim_remainder = row_dim % pivot_dim; 00324 if (row_dim_remainder < 0) { 00325 if (row_dim_remainder <= -pivot_dim_half) 00326 --num_rows_to_subtract; 00327 } 00328 else if (row_dim_remainder > 0 && row_dim_remainder > pivot_dim_half) 00329 ++num_rows_to_subtract; 00330 00331 // Subtract num_rows_to_subtract copies of pivot from row i. Only the 00332 // entries from dim need to be subtracted, as the preceding 00333 // entries are all zero. 00334 // If num_rows_to_subtract is negative, these copies of pivot are 00335 // added to row i. 00336 if (num_rows_to_subtract != 0) 00337 for (dimension_type col = start; col <= end; ++col) 00338 sub_mul_assign(row[col], num_rows_to_subtract, pivot[col]); 00339 } 00340 } 00341 }
| void Parma_Polyhedra_Library::Grid::refine_no_check | ( | const Constraint & | c | ) | [private] |
Uses the constraint c to refine *this.
| c | The constraint to be added. Non-trivial inequalities are ignored. |
c and *this are dimension-incompatible, the behavior is undefined. Definition at line 695 of file Grid_nonpublic.cc.
References add_congruence_no_check(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Constraint::is_inconsistent(), marked_empty(), set_empty(), space_dim, and Parma_Polyhedra_Library::Constraint::space_dimension().
Referenced by refine_with_constraint(), and refine_with_constraints().
00695 { 00696 PPL_ASSERT(!marked_empty()); 00697 PPL_ASSERT(space_dim >= c.space_dimension()); 00698 00699 if (c.is_equality()) { 00700 Congruence cg(c); 00701 add_congruence_no_check(cg); 00702 } 00703 else if (c.is_inconsistent()) 00704 set_empty(); 00705 }
| void Parma_Polyhedra_Library::Grid::refine_with_congruence | ( | const Congruence & | cg | ) | [inline] |
Uses a copy of the congruence cg to refine *this.
| cg | The congruence used. |
| std::invalid_argument | Thrown if *this and congruence cg are dimension-incompatible. |
Definition at line 277 of file Grid.inlines.hh.
References add_congruence().
00277 { 00278 add_congruence(cg); 00279 }
| void Parma_Polyhedra_Library::Grid::refine_with_congruences | ( | const Congruence_System & | cgs | ) | [inline] |
Uses a copy of the congruences in cgs to refine *this.
| cgs | The congruences used. |
| std::invalid_argument | Thrown if *this and cgs are dimension-incompatible. |
Definition at line 282 of file Grid.inlines.hh.
References add_congruences().
00282 { 00283 add_congruences(cgs); 00284 }
| void Parma_Polyhedra_Library::Grid::refine_with_constraint | ( | const Constraint & | c | ) |
Uses a copy of the constraint c to refine *this.
| c | The constraint used. If it is not an equality, it will be ignored |
| std::invalid_argument | Thrown if *this and c are dimension-incompatible. |
Definition at line 1297 of file Grid_public.cc.
References marked_empty(), refine_no_check(), space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), and throw_dimension_incompatible().
01297 { 01298 // The dimension of `c' must be at most `space_dim'. 01299 if (space_dim < c.space_dimension()) 01300 throw_dimension_incompatible("refine_with_constraint(c)", "c", c); 01301 if (marked_empty()) 01302 return; 01303 refine_no_check(c); 01304 }
| void Parma_Polyhedra_Library::Grid::refine_with_constraints | ( | const Constraint_System & | cs | ) |
Uses a copy of the constraints in cs to refine *this.
| cs | The constraints used. Constraints that are not equalities are ignored. |
| std::invalid_argument | Thrown if *this and cs are dimension-incompatible. |
Definition at line 1307 of file Grid_public.cc.
References Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Constraint_System::end(), marked_empty(), refine_no_check(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), and throw_dimension_incompatible().
01307 { 01308 // The dimension of `cs' must be at most `space_dim'. 01309 if (space_dim < cs.space_dimension()) 01310 throw_dimension_incompatible("refine_with_constraints(cs)", "cs", cs); 01311 01312 for (Constraint_System::const_iterator i = cs.begin(), 01313 cs_end = cs.end(); !marked_empty() && i != cs_end; ++i) 01314 refine_no_check(*i); 01315 }
| PPL::Poly_Con_Relation Parma_Polyhedra_Library::Grid::relation_with | ( | const Constraint & | c | ) | const |
Returns the relations holding between *this and c.
Definition at line 578 of file Grid_public.cc.
References Parma_Polyhedra_Library::Grid_Generator_System::begin(), Parma_Polyhedra_Library::Grid_Generator::coefficient(), Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::Grid_Generator_System::end(), gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Constraint::is_inconsistent(), Parma_Polyhedra_Library::Grid_Generator::is_line_or_parameter(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Grid_Generator::LINE, marked_empty(), Parma_Polyhedra_Library::Constraint::NONSTRICT_INEQUALITY, Parma_Polyhedra_Library::Grid_Generator::PARAMETER, Parma_Polyhedra_Library::Grid_Generator::POINT, relation_with(), Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), Parma_Polyhedra_Library::Grid_Generator::set_is_parameter(), Parma_Polyhedra_Library::Scalar_Products::sign(), Parma_Polyhedra_Library::Grid_Generator::size(), space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::Poly_Con_Relation::strictly_intersects(), throw_dimension_incompatible(), Parma_Polyhedra_Library::Constraint::type(), and update_generators().
00578 { 00579 // Dimension-compatibility check. 00580 if (space_dim < c.space_dimension()) 00581 throw_dimension_incompatible("relation_with(c)", "c", c); 00582 00583 if (c.is_equality()) { 00584 Congruence cg(c); 00585 return relation_with(cg); 00586 } 00587 00588 if (marked_empty()) 00589 return Poly_Con_Relation::saturates() 00590 && Poly_Con_Relation::is_included() 00591 && Poly_Con_Relation::is_disjoint(); 00592 00593 if (space_dim == 0) { 00594 if (c.is_inconsistent()) 00595 if (c.is_strict_inequality() && c.inhomogeneous_term() == 0) 00596 // The constraint 0 > 0 implicitly defines the hyperplane 0 = 0; 00597 // thus, the zero-dimensional point also saturates it. 00598 return Poly_Con_Relation::saturates() 00599 && Poly_Con_Relation::is_disjoint(); 00600 else 00601 return Poly_Con_Relation::is_disjoint(); 00602 else if (c.inhomogeneous_term() == 0) 00603 return Poly_Con_Relation::saturates() 00604 && Poly_Con_Relation::is_included(); 00605 else 00606 // The zero-dimensional point saturates 00607 // neither the positivity constraint 1 >= 0, 00608 // nor the strict positivity constraint 1 > 0. 00609 return Poly_Con_Relation::is_included(); 00610 } 00611 00612 if (!generators_are_up_to_date() && !update_generators()) 00613 // Updating found the grid empty. 00614 return Poly_Con_Relation::saturates() 00615 && Poly_Con_Relation::is_included() 00616 && Poly_Con_Relation::is_disjoint(); 00617 00618 // Return one of the relations 00619 // 'strictly_intersects' a strict subset of the grid points satisfy c 00620 // 'is_included' every grid point satisfies c 00621 // 'is_disjoint' c and the grid occupy separate spaces. 00622 00623 // There is always a point. 00624 00625 bool point_is_included = false; 00626 bool point_saturates = false; 00627 const Grid_Generator* first_point = NULL; 00628 00629 for (Grid_Generator_System::const_iterator g = gen_sys.begin(), 00630 gen_sys_end = gen_sys.end(); g != gen_sys_end; ++g) 00631 switch (g->type()) { 00632 00633 case Grid_Generator::POINT: 00634 { 00635 Grid_Generator& gen = const_cast<Grid_Generator&>(*g); 00636 if (first_point == NULL) { 00637 first_point = &gen; 00638 const int sign = Scalar_Products::sign(c, gen); 00639 Constraint::Type type = c.type(); 00640 if ((type == Constraint::NONSTRICT_INEQUALITY && sign == 0)) { 00641 point_saturates = true; 00642 } 00643 else if (sign > 0) 00644 point_is_included = true; 00645 break; 00646 } 00647 // Else convert g to a parameter, and continue into the 00648 // parameter case. 00649 gen.set_is_parameter(); 00650 const Grid_Generator& first = *first_point; 00651 for (dimension_type i = gen.size() - 1; i-- > 0; ) 00652 gen[i] -= first[i]; 00653 } 00654 00655 case Grid_Generator::PARAMETER: 00656 case Grid_Generator::LINE: 00657 Grid_Generator& gen = const_cast<Grid_Generator&>(*g); 00658 if (gen.is_line_or_parameter()) 00659 for (dimension_type i = c.space_dimension(); i-- > 0; ) { 00660 Variable v(i); 00661 if (c.coefficient(v) != 0 && gen.coefficient(v) != 0) 00662 return Poly_Con_Relation::strictly_intersects(); 00663 } 00664 break; 00665 } 00666 00667 if (point_saturates) 00668 // Any parameters and lines are also included. 00669 return Poly_Con_Relation::saturates() 00670 && Poly_Con_Relation::is_included(); 00671 if (point_is_included) 00672 // Any parameters and lines are also included. 00673 return Poly_Con_Relation::is_included(); 00674 return Poly_Con_Relation::is_disjoint(); 00675 }
| PPL::Poly_Gen_Relation Parma_Polyhedra_Library::Grid::relation_with | ( | const Generator & | g | ) | const |
Returns the relations holding between *this and g.
Definition at line 538 of file Grid_public.cc.
References Parma_Polyhedra_Library::Generator::coefficient(), con_sys, congruences_are_up_to_date(), Parma_Polyhedra_Library::Generator::divisor(), Parma_Polyhedra_Library::Generator::is_closure_point(), Parma_Polyhedra_Library::Generator::is_point(), marked_empty(), Parma_Polyhedra_Library::Poly_Gen_Relation::nothing(), Parma_Polyhedra_Library::Congruence_System::satisfies_all_congruences(), space_dim, Parma_Polyhedra_Library::Generator::space_dimension(), Parma_Polyhedra_Library::Poly_Gen_Relation::subsumes(), throw_dimension_incompatible(), and update_congruences().
00538 { 00539 dimension_type g_space_dim = g.space_dimension(); 00540 00541 // Dimension-compatibility check. 00542 if (space_dim < g_space_dim) 00543 throw_dimension_incompatible("relation_with(g)", "g", g); 00544 00545 // The empty grid cannot subsume a generator. 00546 if (marked_empty()) 00547 return Poly_Gen_Relation::nothing(); 00548 00549 // A universe grid in a zero-dimensional space subsumes all the 00550 // generators of a zero-dimensional space. 00551 if (space_dim == 0) 00552 return Poly_Gen_Relation::subsumes(); 00553 00554 if (!congruences_are_up_to_date()) 00555 update_congruences(); 00556 00557 Linear_Expression expr; 00558 for (dimension_type i = g_space_dim; i-- > 0; ) { 00559 const Variable v(i); 00560 expr += g.coefficient(v) * v; 00561 } 00562 Grid_Generator gg(grid_point()); 00563 if (g.is_point() || g.is_closure_point()) 00564 // Points and closure points are converted to grid points. 00565 gg = grid_point(expr, g.divisor()); 00566 else 00567 // The generator is a ray or line. 00568 // In both cases, we convert it to a grid line 00569 gg = grid_line(expr); 00570 00571 return 00572 con_sys.satisfies_all_congruences(gg) 00573 ? Poly_Gen_Relation::subsumes() 00574 : Poly_Gen_Relation::nothing(); 00575 }
| PPL::Poly_Gen_Relation Parma_Polyhedra_Library::Grid::relation_with | ( | const Grid_Generator & | g | ) | const |
Returns the relations holding between *this and g.
Definition at line 514 of file Grid_public.cc.
References con_sys, congruences_are_up_to_date(), marked_empty(), Parma_Polyhedra_Library::Poly_Gen_Relation::nothing(), Parma_Polyhedra_Library::Congruence_System::satisfies_all_congruences(), space_dim, Parma_Polyhedra_Library::Grid_Generator::space_dimension(), Parma_Polyhedra_Library::Poly_Gen_Relation::subsumes(), throw_dimension_incompatible(), and update_congruences().
00514 { 00515 // Dimension-compatibility check. 00516 if (space_dim < g.space_dimension()) 00517 throw_dimension_incompatible("relation_with(g)", "g", g); 00518 00519 // The empty grid cannot subsume a generator. 00520 if (marked_empty()) 00521 return Poly_Gen_Relation::nothing(); 00522 00523 // A universe grid in a zero-dimensional space subsumes all the 00524 // generators of a zero-dimensional space. 00525 if (space_dim == 0) 00526 return Poly_Gen_Relation::subsumes(); 00527 00528 if (!congruences_are_up_to_date()) 00529 update_congruences(); 00530 00531 return 00532 con_sys.satisfies_all_congruences(g) 00533 ? Poly_Gen_Relation::subsumes() 00534 : Poly_Gen_Relation::nothing(); 00535 }
| PPL::Poly_Con_Relation Parma_Polyhedra_Library::Grid::relation_with | ( | const Congruence & | cg | ) | const |
Returns the relations holding between *this and cg.
Definition at line 361 of file Grid_public.cc.
References Parma_Polyhedra_Library::Scalar_Products::assign(), Parma_Polyhedra_Library::Grid_Generator_System::begin(), Parma_Polyhedra_Library::Grid_Generator_System::end(), Parma_Polyhedra_Library::gcd_assign(), gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Congruence::inhomogeneous_term(), Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), Parma_Polyhedra_Library::Congruence::is_proper_congruence(), Parma_Polyhedra_Library::Grid_Generator::LINE, marked_empty(), Parma_Polyhedra_Library::Congruence::modulus(), Parma_Polyhedra_Library::Grid_Generator::PARAMETER, Parma_Polyhedra_Library::Grid_Generator::POINT, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), space_dim, Parma_Polyhedra_Library::Congruence::space_dimension(), Parma_Polyhedra_Library::Poly_Con_Relation::strictly_intersects(), throw_dimension_incompatible(), and update_generators().
Referenced by difference_assign(), limited_congruence_extrapolation_assign(), limited_extrapolation_assign(), limited_generator_extrapolation_assign(), relation_with(), and simplify_using_context_assign().
00361 { 00362 // Dimension-compatibility check. 00363 if (space_dim < cg.space_dimension()) 00364 throw_dimension_incompatible("relation_with(cg)", "cg", cg); 00365 00366 if (marked_empty()) 00367 return Poly_Con_Relation::saturates() 00368 && Poly_Con_Relation::is_included() 00369 && Poly_Con_Relation::is_disjoint(); 00370 00371 if (space_dim == 0) { 00372 if (cg.is_inconsistent()) 00373 return Poly_Con_Relation::is_disjoint(); 00374 else if (cg.is_equality()) 00375 return Poly_Con_Relation::saturates() 00376 && Poly_Con_Relation::is_included(); 00377 else if (cg.inhomogeneous_term() % cg.modulus() == 0) 00378 return Poly_Con_Relation::saturates() 00379 && Poly_Con_Relation::is_included(); 00380 } 00381 00382 if (!generators_are_up_to_date() && !update_generators()) 00383 // Updating found the grid empty. 00384 return Poly_Con_Relation::saturates() 00385 && Poly_Con_Relation::is_included() 00386 && Poly_Con_Relation::is_disjoint(); 00387 00388 // Return one of the relations 00389 // 'strictly_intersects' a strict subset of the grid points satisfy cg 00390 // 'is_included' every grid point satisfies cg 00391 // 'is_disjoint' cg and the grid occupy separate spaces. 00392 00393 // There is always a point. 00394 00395 // Scalar product of the congruence and the first point that 00396 // satisfies the congruence. 00397 PPL_DIRTY_TEMP_COEFFICIENT(point_sp); 00398 point_sp = 0; 00399 00400 const Coefficient& modulus = cg.modulus(); 00401 00402 PPL_DIRTY_TEMP_COEFFICIENT(div); 00403 div = modulus; 00404 00405 PPL_DIRTY_TEMP_COEFFICIENT(sp); 00406 00407 bool known_to_intersect = false; 00408 00409 for (Grid_Generator_System::const_iterator g = gen_sys.begin(), 00410 gen_sys_end = gen_sys.end(); g != gen_sys_end; ++g) { 00411 Scalar_Products::assign(sp, cg, *g); 00412 00413 switch (g->type()) { 00414 00415 case Grid_Generator::POINT: 00416 if (cg.is_proper_congruence()) 00417 sp %= div; 00418 if (sp == 0) 00419 // The point satisfies the congruence. 00420 if (point_sp == 0) 00421 // Any previous points satisfied the congruence. 00422 known_to_intersect = true; 00423 else 00424 return Poly_Con_Relation::strictly_intersects(); 00425 else 00426 if (point_sp == 0) { 00427 if (known_to_intersect) 00428 return Poly_Con_Relation::strictly_intersects(); 00429 // Assign `sp' to `point_sp' as `sp' is the scalar product 00430 // of cg and a point g and is non-zero. 00431 point_sp = sp; 00432 } 00433 else { 00434 // A previously considered point p failed to satisfy cg such that 00435 // `point_sp' = `scalar_prod(p, cg)' 00436 // so, if we consider the parameter g-p instead of g, we have 00437 // scalar_prod(g-p, cg) = scalar_prod(g, cg) - scalar_prod(p, cg) 00438 // = sp - point_sp 00439 sp -= point_sp; 00440 00441 if (sp != 0) { 00442 // Find the GCD between sp and the previous GCD. 00443 gcd_assign(div, div, sp); 00444 if (point_sp % div == 0) 00445 // There is a point in the grid satisfying cg. 00446 return Poly_Con_Relation::strictly_intersects(); 00447 } 00448 } 00449 break; 00450 00451 case Grid_Generator::PARAMETER: 00452 if (cg.is_proper_congruence()) 00453 sp %= (div * g->divisor()); 00454 if (sp == 0) 00455 // Parameter g satisfies the cg so the relation depends 00456 // entirely on the other generators. 00457 break; 00458 00459 if (known_to_intersect) 00460 // At least one point satisfies cg. However, the sum of such 00461 // a point and the parameter g fails to satisfy cg (due to g). 00462 return Poly_Con_Relation::strictly_intersects(); 00463 00464 // Find the GCD between sp and the previous GCD. 00465 gcd_assign(div, div, sp); 00466 if (point_sp != 0) 00467 // At least one of any previously encountered points fails to 00468 // satisfy cg. 00469 if (point_sp % div == 0) 00471 // There is also a grid point that satisfies cg. 00472 return Poly_Con_Relation::strictly_intersects(); 00473 00474 break; 00475 00476 case Grid_Generator::LINE: 00477 if (sp == 0) 00478 // Line g satisfies the cg so the relation depends entirely on 00479 // the other generators. 00480 break; 00481 00482 // Line g intersects the congruence. 00483 // 00484 // There is a point p in the grid. Suppose <p*cg> = p_sp. Then 00485 // (-p_sp/sp)*g + p is a point that satisfies cg: <((-p_sp/sp)*g 00486 // + p).cg> = -(p_sp/sp)*sp + p_sp) = 0. If p does not satisfy 00487 // `cg' and hence is not in the grid defined by `cg', the grid 00488 // `*this' strictly intersects the `cg' grid. On the other 00489 // hand, if `p' is in the grid defined by `cg' so that p_sp = 0, 00490 // then <p+g.cg> = p_sp + sp != 0; thus `p+g' is a point in 00491 // *this that does not satisfy `cg' and hence `p+g' is a point 00492 // in *this not in the grid defined by `cg'; therefore `*this' 00493 // strictly intersects the `cg' grid. 00494 00495 return Poly_Con_Relation::strictly_intersects(); 00496 } 00497 } 00498 00499 if (point_sp == 0) { 00500 if (cg.is_equality()) 00501 // Every generator satisfied the cg. 00502 return Poly_Con_Relation::is_included() 00503 && Poly_Con_Relation::saturates(); 00504 else 00505 // Every generator satisfied the cg. 00506 return Poly_Con_Relation::is_included(); 00507 } 00508 00509 PPL_ASSERT(!known_to_intersect); 00510 return Poly_Con_Relation::is_disjoint(); 00511 }
| void Parma_Polyhedra_Library::Grid::remove_higher_space_dimensions | ( | dimension_type | new_dimension | ) |
Removes the higher dimensions of the vector space so that the resulting space will have dimension new_dimension..
| std::invalid_argument | Thrown if new_dimensions is greater than the space dimension of *this. |
Definition at line 306 of file Grid_chdims.cc.
References clear_congruences_up_to_date(), clear_generators_up_to_date(), con_sys, CON_VIRTUAL, congruences_are_minimized(), dim_kinds, Parma_Polyhedra_Library::Matrix::erase_to_end(), Parma_Polyhedra_Library::Grid_Generator_System::erase_to_end(), gen_sys, GEN_VIRTUAL, generators_are_minimized(), generators_are_up_to_date(), Parma_Polyhedra_Library::Congruence_System::increase_space_dimension(), is_empty(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), OK(), Parma_Polyhedra_Library::Congruence_System::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Grid_Generator_System::remove_higher_space_dimensions(), set_empty(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Grid_Generator_System::swap(), Parma_Polyhedra_Library::swap(), Parma_Polyhedra_Library::Congruence_System::swap(), throw_dimension_incompatible(), Parma_Polyhedra_Library::Grid_Generator_System::unset_pending_rows(), and Parma_Polyhedra_Library::Congruence::zero_dim_false().
Referenced by generalized_affine_image(), and generalized_affine_preimage().
00306 { 00307 // Dimension-compatibility check. 00308 if (new_dimension > space_dim) 00309 throw_dimension_incompatible("remove_higher_space_dimensions(nd)", 00310 new_dimension); 00311 00312 // The removal of no dimensions from any grid is a no-op. 00313 // Note that this case also captures the only legal removal of 00314 // dimensions from a grid in a 0-dim space. 00315 if (new_dimension == space_dim) { 00316 PPL_ASSERT(OK()); 00317 return; 00318 } 00319 00320 if (is_empty()) { 00321 // Removing dimensions from the empty grid just updates the space 00322 // dimension. 00323 space_dim = new_dimension; 00324 set_empty(); 00325 PPL_ASSERT(OK()); 00326 return; 00327 } 00328 00329 if (new_dimension == 0) { 00330 // Removing all dimensions from a non-empty grid just returns the 00331 // zero-dimensional universe grid. 00332 set_zero_dim_univ(); 00333 return; 00334 } 00335 00336 // Favor the generators, as is done by is_empty(). 00337 if (generators_are_up_to_date()) { 00338 gen_sys.remove_higher_space_dimensions(new_dimension); 00339 if (generators_are_minimized()) { 00340 // Count the actual number of rows that are now redundant. 00341 dimension_type num_redundant = 0; 00342 const dimension_type num_old_gs = space_dim - new_dimension; 00343 for (dimension_type row = 0; row < num_old_gs; ++row) 00344 dim_kinds[row] == GEN_VIRTUAL || ++num_redundant; 00345 if (num_redundant > 0) { 00346 // Chop zero rows from end of system, to keep minimal form. 00347 gen_sys.erase_to_end(gen_sys.num_rows() - num_redundant); 00348 gen_sys.unset_pending_rows(); 00349 } 00350 dim_kinds.erase(dim_kinds.begin() + new_dimension + 1, dim_kinds.end()); 00351 // TODO: Consider if it is worth also preserving the congruences 00352 // if they are also in minimal form. 00353 } 00354 clear_congruences_up_to_date(); 00355 // Extend the zero dim false congruence system to the appropriate 00356 // dimension and then swap it with `con_sys'. 00357 Congruence_System cgs(Congruence::zero_dim_false()); 00358 // Extra 2 columns for inhomogeneous term and modulus. 00359 cgs.increase_space_dimension(new_dimension + 2); 00360 con_sys.swap(cgs); 00361 } 00362 else { 00363 PPL_ASSERT(congruences_are_minimized()); 00364 con_sys.remove_higher_space_dimensions(new_dimension); 00365 // Count the actual number of rows that are now redundant. 00366 dimension_type num_redundant = 0; 00367 for (dimension_type row = space_dim; row > new_dimension; --row) 00368 dim_kinds[row] == CON_VIRTUAL || ++num_redundant; 00369 if (num_redundant > 0) { 00370 dimension_type rows = con_sys.num_rows(); 00371 // Shuffle the remaining rows upwards. 00372 for (dimension_type low = 0, high = num_redundant; 00373 high < rows; 00374 ++high, ++low) 00375 std::swap(con_sys[low], con_sys[high]); 00376 // Chop newly redundant rows from end of system, to keep minimal 00377 // form. 00378 con_sys.erase_to_end(rows - num_redundant); 00379 } 00380 dim_kinds.erase(dim_kinds.begin() + new_dimension + 1, dim_kinds.end()); 00381 clear_generators_up_to_date(); 00382 // Replace gen_sys with an empty system of the right dimension. 00383 // Extra 2 columns for inhomogeneous term and modulus. 00384 Grid_Generator_System gs(new_dimension + 2); 00385 gen_sys.swap(gs); 00386 } 00387 00388 // Update the space dimension. 00389 space_dim = new_dimension; 00390 00391 PPL_ASSERT(OK(true)); 00392 }
| void Parma_Polyhedra_Library::Grid::remove_space_dimensions | ( | const Variables_Set & | vars | ) |
Removes all the specified dimensions from the vector space.
| vars | The set of Variable objects corresponding to the space dimensions to be removed. |
| std::invalid_argument | Thrown if *this is dimension-incompatible with one of the Variable objects contained in vars. |
Definition at line 262 of file Grid_chdims.cc.
References clear_congruences_up_to_date(), clear_generators_minimized(), gen_sys, generators_are_up_to_date(), marked_empty(), OK(), Parma_Polyhedra_Library::Grid_Generator_System::remove_space_dimensions(), set_empty(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Variables_Set::space_dimension(), throw_dimension_incompatible(), and update_generators().
Referenced by fold_space_dimensions().
00262 { 00263 // The removal of no dimensions from any grid is a no-op. This case 00264 // also captures the only legal removal of dimensions from a grid in 00265 // a 0-dim space. 00266 if (vars.empty()) { 00267 PPL_ASSERT(OK()); 00268 return; 00269 } 00270 00271 // Dimension-compatibility check. 00272 const dimension_type min_space_dim = vars.space_dimension(); 00273 if (space_dim < min_space_dim) 00274 throw_dimension_incompatible("remove_space_dimensions(vs)", min_space_dim); 00275 00276 const dimension_type new_space_dim = space_dim - vars.size(); 00277 00278 if (marked_empty() 00279 || (!generators_are_up_to_date() && !update_generators())) { 00280 // Update the space dimension. 00281 space_dim = new_space_dim; 00282 set_empty(); 00283 PPL_ASSERT(OK()); 00284 return; 00285 } 00286 00287 // Removing _all_ dimensions from a non-empty grid obtains the 00288 // zero-dimensional universe grid. 00289 if (new_space_dim == 0) { 00290 set_zero_dim_univ(); 00291 return; 00292 } 00293 00294 gen_sys.remove_space_dimensions(vars); 00295 00296 clear_congruences_up_to_date(); 00297 clear_generators_minimized(); 00298 00299 // Update the space dimension. 00300 space_dim = new_space_dim; 00301 00302 PPL_ASSERT(OK(true)); 00303 }
| bool Parma_Polyhedra_Library::Grid::rows_are_zero | ( | M & | system, | |
| dimension_type | first, | |||
| dimension_type | last, | |||
| dimension_type | row_size | |||
| ) | [inline, static, private] |
Checks that trailing rows contain only zero terms.
If all columns contain zero in the rows of system from row index first to row index last then return true, else return false. row_size gives the number of columns in each row.
This method is only used in assertions in the simplify methods.
Definition at line 238 of file Grid_simplify.cc.
00239 { 00240 while (first <= last) { 00241 const R& row = system[first++]; 00242 for (dimension_type col = 0; col < row_size; ++col) 00243 if (row[col] != 0) 00244 return false; 00245 } 00246 return true; 00247 }
| void Parma_Polyhedra_Library::Grid::select_wider_congruences | ( | const Grid & | y, | |
| Congruence_System & | selected_cgs | |||
| ) | const [private] |
Copies a widened selection of congruences from y to selected_cgs.
Definition at line 35 of file Grid_widenings.cc.
References con_sys, CON_VIRTUAL, congruences_are_minimized(), dim_kinds, EQUALITY, Parma_Polyhedra_Library::Congruence_System::insert(), Parma_Polyhedra_Library::Congruence::is_equal_at_dimension(), marked_empty(), PROPER_CONGRUENCE, space_dim, and Parma_Polyhedra_Library::Congruence_System::space_dimension().
Referenced by congruence_widening_assign().
00036 { 00037 // Private method: the caller must ensure the following conditions 00038 // (beside the inclusion `y <= x'). 00039 PPL_ASSERT(space_dim == y.space_dim); 00040 PPL_ASSERT(!marked_empty()); 00041 PPL_ASSERT(!y.marked_empty()); 00042 PPL_ASSERT(congruences_are_minimized()); 00043 PPL_ASSERT(y.congruences_are_minimized()); 00044 00045 // Note: row counters start at 0, to preserve the original order in 00046 // the selected congruences. 00047 for (dimension_type dim = con_sys.space_dimension(), x_row = 0, y_row = 0; 00048 dim > 0; --dim) { 00049 PPL_ASSERT(dim_kinds[dim] == CON_VIRTUAL 00050 || dim_kinds[dim] == y.dim_kinds[dim]); 00051 switch (dim_kinds[dim]) { 00052 case PROPER_CONGRUENCE: 00053 { 00054 const Congruence& cg = con_sys[x_row]; 00055 const Congruence& y_cg = y.con_sys[y_row]; 00056 if (cg.is_equal_at_dimension(dim, y_cg)) 00057 // The leading diagonal entries are equal. 00058 cgs_selected.insert(cg); 00059 ++x_row; 00060 ++y_row; 00061 } 00062 break; 00063 case EQUALITY: 00064 cgs_selected.insert(con_sys[x_row]); 00065 ++x_row; 00066 ++y_row; 00067 break; 00068 case CON_VIRTUAL: 00069 y.dim_kinds[dim] == CON_VIRTUAL || ++y_row; 00070 break; 00071 } 00072 } 00073 }
| void Parma_Polyhedra_Library::Grid::select_wider_generators | ( | const Grid & | y, | |
| Grid_Generator_System & | widened_ggs | |||
| ) | const [private] |
Copies widened generators from y to widened_ggs.
Definition at line 230 of file Grid_widenings.cc.
References Parma_Polyhedra_Library::Grid_Generator::coefficient(), dim_kinds, gen_sys, GEN_VIRTUAL, generators_are_minimized(), Parma_Polyhedra_Library::Grid_Generator_System::insert(), Parma_Polyhedra_Library::Grid_Generator::is_equal_at_dimension(), LINE, marked_empty(), PARAMETER, space_dim, Parma_Polyhedra_Library::Grid_Generator::space_dimension(), and Parma_Polyhedra_Library::Grid_Generator_System::space_dimension().
Referenced by generator_widening_assign().
00231 { 00232 // Private method: the caller must ensure the following conditions 00233 // (beside the inclusion `y <= x'). 00234 PPL_ASSERT(space_dim == y.space_dim); 00235 PPL_ASSERT(!marked_empty()); 00236 PPL_ASSERT(!y.marked_empty()); 00237 PPL_ASSERT(generators_are_minimized()); 00238 PPL_ASSERT(y.generators_are_minimized()); 00239 00240 // Note: row counters start at 0, to preserve the original order in 00241 // the selected generators. 00242 for (dimension_type dim = 0, x_row = 0, y_row = 0; 00243 dim <= gen_sys.space_dimension(); ++dim) { 00244 PPL_ASSERT(dim_kinds[dim] == LINE 00245 || y.dim_kinds[dim] == GEN_VIRTUAL 00246 || dim_kinds[dim] == y.dim_kinds[dim]); 00247 switch (dim_kinds[dim]) { 00248 case PARAMETER: 00249 { 00250 const Grid_Generator& gg = gen_sys[x_row]; 00251 const Grid_Generator& y_gg = y.gen_sys[y_row]; 00252 if (gg.is_equal_at_dimension(dim, y_gg)) 00253 // The leading diagonal entry is equal. 00254 ggs_selected.insert(gg); 00255 else { 00256 Linear_Expression e; 00257 for (dimension_type i = gg.space_dimension(); i-- > 0; ) 00258 e += gg.coefficient(Variable(i)) * Variable(i); 00259 ggs_selected.insert(grid_line(e)); 00260 } 00261 ++x_row; 00262 ++y_row; 00263 } 00264 break; 00265 case LINE: 00266 ggs_selected.insert(gen_sys[x_row]); 00267 ++x_row; 00268 ++y_row; 00269 break; 00270 case GEN_VIRTUAL: 00271 y.dim_kinds[dim] == GEN_VIRTUAL || ++y_row; 00272 break; 00273 } 00274 } 00275 }
| void Parma_Polyhedra_Library::Grid::set_congruences_minimized | ( | ) | [inline, private] |
Sets status to express that congruences are minimized.
Definition at line 70 of file Grid.inlines.hh.
References Parma_Polyhedra_Library::Grid::Status::set_c_minimized(), set_congruences_up_to_date(), and status.
Referenced by congruence_widening_assign(), construct(), Parma_Polyhedra_Library::Grid_Certificate::Grid_Certificate(), is_empty(), minimize(), minimized_congruences(), and update_generators().
00070 { 00071 set_congruences_up_to_date(); 00072 status.set_c_minimized(); 00073 }
| void Parma_Polyhedra_Library::Grid::set_congruences_up_to_date | ( | ) | [inline, private] |
Sets status to express that congruences are up-to-date.
Definition at line 65 of file Grid.inlines.hh.
References Parma_Polyhedra_Library::Grid::Status::set_c_up_to_date(), and status.
Referenced by add_congruence_no_check(), construct(), Grid(), and set_congruences_minimized().
00065 { 00066 status.set_c_up_to_date(); 00067 }
| void Parma_Polyhedra_Library::Grid::set_empty | ( | ) | [private] |
Sets status to express that the grid is empty, clearing all corresponding matrices.
Definition at line 449 of file Grid_nonpublic.cc.
References con_sys, gen_sys, Parma_Polyhedra_Library::Congruence_System::increase_space_dimension(), Parma_Polyhedra_Library::Grid::Status::set_empty(), space_dim, status, swap(), Parma_Polyhedra_Library::Grid_Generator_System::swap(), and Parma_Polyhedra_Library::Congruence::zero_dim_false().
Referenced by add_congruence_no_check(), add_constraint_no_check(), add_recycled_congruences(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), concatenate_assign(), congruence_widening_assign(), difference_assign(), Grid(), intersection_assign(), is_empty(), map_space_dimensions(), minimized_congruences(), operator=(), refine_no_check(), remove_higher_space_dimensions(), remove_space_dimensions(), time_elapse_assign(), update_generators(), and wrap_assign().
00449 { 00450 status.set_empty(); 00451 00452 // Replace gen_sys with an empty system of the right dimension. 00453 Grid_Generator_System gs(space_dim); 00454 gen_sys.swap(gs); 00455 00456 // Extend the zero dim false congruence system to the appropriate 00457 // dimension and then swap it with `con_sys'. 00458 Congruence_System cgs(Congruence::zero_dim_false()); 00459 cgs.increase_space_dimension(space_dim); 00460 const_cast<Congruence_System&>(con_sys).swap(cgs); 00461 }
| void Parma_Polyhedra_Library::Grid::set_generators_minimized | ( | ) | [inline, private] |
Sets status to express that generators are minimized.
Definition at line 76 of file Grid.inlines.hh.
References Parma_Polyhedra_Library::Grid::Status::set_g_minimized(), set_generators_up_to_date(), and status.
Referenced by construct(), generator_widening_assign(), Parma_Polyhedra_Library::Grid_Certificate::Grid_Certificate(), max_min(), minimize(), minimized_grid_generators(), and update_generators().
00076 { 00077 set_generators_up_to_date(); 00078 status.set_g_minimized(); 00079 }
| void Parma_Polyhedra_Library::Grid::set_generators_up_to_date | ( | ) | [inline, private] |
Sets status to express that generators are up-to-date.
Definition at line 60 of file Grid.inlines.hh.
References Parma_Polyhedra_Library::Grid::Status::set_g_up_to_date(), and status.
Referenced by add_grid_generator(), add_recycled_grid_generators(), construct(), Grid(), and set_generators_minimized().
00060 { 00061 status.set_g_up_to_date(); 00062 }
| void Parma_Polyhedra_Library::Grid::set_zero_dim_univ | ( | ) | [private] |
Sets status to express that the grid is the universe 0-dimension vector space, clearing all corresponding matrices.
Definition at line 440 of file Grid_nonpublic.cc.
References Parma_Polyhedra_Library::Grid_Generator_System::clear(), Parma_Polyhedra_Library::Congruence_System::clear(), con_sys, gen_sys, Parma_Polyhedra_Library::Grid_Generator_System::insert(), Parma_Polyhedra_Library::Grid::Status::set_zero_dim_univ(), space_dim, and status.
Referenced by add_grid_generator(), add_recycled_grid_generators(), construct(), Grid(), map_space_dimensions(), operator=(), remove_higher_space_dimensions(), remove_space_dimensions(), and simplify_using_context_assign().
| void Parma_Polyhedra_Library::Grid::simplify | ( | Grid_Generator_System & | gs, | |
| Dimension_Kinds & | dim_kinds | |||
| ) | [static, private] |
Converts gs to lower triangular (i.e. minimized) form.
Expects gs to contain at least one point.
Definition at line 251 of file Grid_simplify.cc.
References GEN_VIRTUAL, Parma_Polyhedra_Library::Matrix::has_no_rows(), Parma_Polyhedra_Library::Grid_Generator::is_line(), Parma_Polyhedra_Library::Grid_Generator::is_parameter_or_point(), LINE, Parma_Polyhedra_Library::Grid_Generator::negate(), Parma_Polyhedra_Library::Grid_Generator_System::num_columns(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), Parma_Polyhedra_Library::Grid_Generator_System::OK(), PARAMETER, reduce_line_with_line(), reduce_parameter_with_line(), reduce_pc_with_pc(), swap(), and Parma_Polyhedra_Library::Grid_Generator_System::unset_pending_rows().
00251 { 00252 PPL_ASSERT(!sys.has_no_rows()); 00253 // For reduce_pc_with_pc. 00254 PPL_ASSERT(sys.num_columns() > 0); 00255 00256 // Changes here may also be required in the congruence version 00257 // below. 00258 00259 // Subtract one to allow for the parameter divisor column 00260 const dimension_type num_columns = sys.num_columns() - 1; 00261 00262 if (dim_kinds.size() != num_columns) 00263 dim_kinds.resize(num_columns); 00264 00265 const dimension_type num_rows = sys.num_rows(); 00266 00267 // For each dimension `dim' move or construct a row into position 00268 // `pivot_index' such that the row has zero in all elements 00269 // following column `dim' and a value other than zero in column 00270 // `dim'. 00271 dimension_type pivot_index = 0; 00272 for (dimension_type dim = 0; dim < num_columns; ++dim) { 00273 // Consider the pivot and following rows. 00274 dimension_type row_index = pivot_index; 00275 00276 // Move down over rows which have zero in column `dim'. 00277 while (row_index < num_rows && sys[row_index][dim] == 0) 00278 ++row_index; 00279 00280 if (row_index == num_rows) 00281 // Element in column `dim' is zero in all rows from the pivot. 00282 dim_kinds[dim] = GEN_VIRTUAL; 00283 else { 00284 if (row_index != pivot_index) 00285 std::swap(sys[row_index], sys[pivot_index]); 00286 Grid_Generator& pivot = sys[pivot_index]; 00287 bool pivot_is_line = pivot.is_line(); 00288 00289 // Change the matrix so that the value at `dim' in every row 00290 // following `pivot_index' is 0, leaving an equivalent grid. 00291 while (row_index < num_rows - 1) { 00292 ++row_index; 00293 00294 Grid_Generator& row = sys[row_index]; 00295 00296 if (row[dim] == 0) 00297 continue; 00298 00299 if (row.is_line()) 00300 if (pivot_is_line) 00301 reduce_line_with_line(row, pivot, dim); 00302 else { 00303 PPL_ASSERT(pivot.is_parameter_or_point()); 00304 std::swap(row, pivot); 00305 pivot_is_line = true; 00306 reduce_parameter_with_line(row, pivot, dim, sys); 00307 } 00308 else { 00309 PPL_ASSERT(row.is_parameter_or_point()); 00310 if (pivot_is_line) 00311 reduce_parameter_with_line(row, pivot, dim, sys); 00312 else { 00313 PPL_ASSERT(pivot.is_parameter_or_point()); 00314 reduce_pc_with_pc(row, pivot, dim, dim + 1, num_columns); 00315 } 00316 } 00317 } 00318 00319 if (pivot_is_line) 00320 dim_kinds[dim] = LINE; 00321 else { 00322 PPL_ASSERT(pivot.is_parameter_or_point()); 00323 dim_kinds[dim] = PARAMETER; 00324 } 00325 00326 // Since we are reducing the system to "strong minimal form", 00327 // ensure that a positive value follows the leading zeros. 00328 if (pivot[dim] < 0) 00329 pivot.negate(dim, num_columns - 1); 00330 00331 // Factor this row out of the preceding rows. 00332 reduce_reduced<Grid_Generator_System, Grid_Generator> 00333 (sys, dim, pivot_index, dim, num_columns - 1, dim_kinds); 00334 00335 ++pivot_index; 00336 } 00337 } 00338 00339 // Clip any zero rows from the end of the matrix. 00340 if (num_rows > pivot_index) { 00341 #ifndef NDEBUG 00342 const bool ret = rows_are_zero<Grid_Generator_System, Grid_Generator> 00343 (sys, 00344 // index of first 00345 pivot_index, 00346 // index of last 00347 sys.num_rows() - 1, 00348 // row size 00349 sys.num_columns() - 1); 00350 PPL_ASSERT(ret == true); 00351 #endif 00352 sys.erase_to_end(pivot_index); 00353 } 00354 00355 sys.unset_pending_rows(); 00356 00357 // Ensure that the parameter divisors are the same as the system 00358 // divisor. 00359 const Coefficient& system_divisor = sys[0][0]; 00360 for (dimension_type row = sys.num_rows() - 1, 00361 dim = sys.num_columns() - 2; 00362 dim > 0; --dim) 00363 switch (dim_kinds[dim]) { 00364 case PARAMETER: 00365 sys[row].set_divisor(system_divisor); 00366 case LINE: 00367 --row; 00368 case GEN_VIRTUAL: 00369 break; 00370 } 00371 00372 PPL_ASSERT(sys.OK()); 00373 }
| bool Parma_Polyhedra_Library::Grid::simplify | ( | Congruence_System & | cgs, | |
| Dimension_Kinds & | dim_kinds | |||
| ) | [static, private] |
Converts cgs to upper triangular (i.e. minimized) form.
Returns true if cgs represents the empty set, otherwise returns false.
Definition at line 376 of file Grid_simplify.cc.
References Parma_Polyhedra_Library::Matrix::add_zero_rows(), CON_VIRTUAL, EQUALITY, Parma_Polyhedra_Library::Matrix::erase_to_end(), Parma_Polyhedra_Library::Congruence::inhomogeneous_term(), Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Congruence::is_proper_congruence(), Parma_Polyhedra_Library::Congruence::modulus(), Parma_Polyhedra_Library::NECESSARILY_CLOSED, Parma_Polyhedra_Library::Congruence::negate(), Parma_Polyhedra_Library::Congruence_System::normalize_moduli(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Congruence_System::OK(), PROPER_CONGRUENCE, Parma_Polyhedra_Library::Linear_Row::RAY_OR_POINT_OR_INEQUALITY, reduce_congruence_with_equality(), reduce_equality_with_equality(), reduce_pc_with_pc(), Parma_Polyhedra_Library::Matrix::rows, Parma_Polyhedra_Library::Congruence::set_is_equality(), and swap().
Referenced by congruence_widening_assign(), generator_widening_assign(), Parma_Polyhedra_Library::Grid_Certificate::Grid_Certificate(), is_empty(), max_min(), minimize(), minimized_congruences(), minimized_grid_generators(), OK(), and update_generators().
00376 { 00377 PPL_ASSERT(sys.num_columns() > 2); 00378 00379 // Changes here may also be required in the generator version above. 00380 00381 // TODO: Consider normalizing the moduli only when congruences are 00382 // added to con_sys. 00383 sys.normalize_moduli(); 00384 00385 const dimension_type num_columns = sys.num_columns() - 1 /* modulus */; 00386 00387 if (dim_kinds.size() != num_columns) 00388 dim_kinds.resize(num_columns); 00389 00390 const dimension_type num_rows = sys.num_rows(); 00391 00392 // For each dimension `dim' move or construct a row into position 00393 // `pivot_index' such that the row has a value of zero in all 00394 // elements preceding column `dim' and some other value in column 00395 // `dim'. 00396 dimension_type pivot_index = 0; 00397 for (dimension_type dim = num_columns; dim-- > 0; ) { 00398 // Consider the pivot and following rows. 00399 dimension_type row_index = pivot_index; 00400 00401 // Move down over rows which have zero in column `dim'. 00402 while (row_index < num_rows && sys[row_index][dim] == 0) 00403 ++row_index; 00404 00405 if (row_index == num_rows) 00406 // Element in column `dim' is zero in all rows from the pivot, 00407 // or `sys' is empty of rows. 00408 dim_kinds[dim] = CON_VIRTUAL; 00409 else { 00410 // row_index != num_rows 00411 if (row_index != pivot_index) 00412 std::swap(sys[row_index], sys[pivot_index]); 00413 Congruence& pivot = sys[pivot_index]; 00414 bool pivot_is_equality = pivot.is_equality(); 00415 00416 // Change the matrix so that the value at `dim' in every row 00417 // following `pivot_index' is 0, leaving an equivalent grid. 00418 while (row_index < num_rows - 1) { 00419 ++row_index; 00420 00421 Congruence& row = sys[row_index]; 00422 00423 if (row[dim] == 0) 00424 continue; 00425 00426 if (row.is_equality()) 00427 if (pivot_is_equality) 00428 reduce_equality_with_equality(row, pivot, dim); 00429 else { 00430 PPL_ASSERT(pivot.is_proper_congruence()); 00431 std::swap(row, pivot); 00432 pivot_is_equality = true; 00433 reduce_congruence_with_equality(row, pivot, dim, sys); 00434 } 00435 else { 00436 PPL_ASSERT(row.is_proper_congruence()); 00437 if (pivot_is_equality) 00438 reduce_congruence_with_equality(row, pivot, dim, sys); 00439 else { 00440 PPL_ASSERT(pivot.is_proper_congruence()); 00441 reduce_pc_with_pc(row, pivot, dim, 0, dim); 00442 } 00443 } 00444 } 00445 00446 if (pivot_is_equality) 00447 dim_kinds[dim] = EQUALITY; 00448 else { 00449 PPL_ASSERT(pivot.is_proper_congruence()); 00450 dim_kinds[dim] = PROPER_CONGRUENCE; 00451 } 00452 00453 // Since we are reducing the system to "strong minimal form", 00454 // ensure that a positive value follows the leading zeros. 00455 if (pivot[dim] < 0) 00456 pivot.negate(0, dim); 00457 // Factor this row out of the preceding ones. 00458 reduce_reduced<Congruence_System, Congruence> 00459 (sys, dim, pivot_index, 0, dim, dim_kinds, false); 00460 00461 ++pivot_index; 00462 } 00463 } // end for (dimension_type dim = num_columns; dim-- > 0; ) 00464 00465 // For clearer naming. 00466 dimension_type& reduced_num_rows = pivot_index; 00467 00468 if (reduced_num_rows > 0) { 00469 // If the last row is false then make it the equality 1 = 0, and 00470 // make it the only row. 00471 Congruence& last_row = sys[reduced_num_rows - 1]; 00472 if (dim_kinds[0] == PROPER_CONGRUENCE) { 00473 if (last_row.inhomogeneous_term() % last_row.modulus() != 0) { 00474 // The last row is a false proper congruence. 00475 last_row.set_is_equality(); 00476 dim_kinds[0] = EQUALITY; 00477 goto return_empty; 00478 } 00479 } 00480 else if (dim_kinds[0] == EQUALITY) { 00481 // The last row is a false equality, as all the coefficient terms 00482 // are zero while the inhomogeneous term (as a result of the 00483 // reduced form) is some other value. 00484 return_empty: 00485 last_row[0] = 1; 00486 dim_kinds.resize(1); 00487 std::swap(sys.rows[0], sys.rows.back()); 00488 sys.erase_to_end(1); 00489 00490 PPL_ASSERT(sys.OK()); 00491 return true; 00492 } 00493 } 00494 else { 00495 // Either sys is empty (it defines the universe) or every column 00496 // before the modulus column contains only zeroes. 00497 00498 // Set up the integrality congruence. 00499 dim_kinds[0] = PROPER_CONGRUENCE; 00500 if (num_rows == 0) { 00501 sys.add_zero_rows(1, 00502 Linear_Row::Flags(NECESSARILY_CLOSED, 00503 Linear_Row::RAY_OR_POINT_OR_INEQUALITY)); 00504 Congruence& cg = sys[0]; 00505 cg[num_columns] = 1; 00506 cg[0] = 1; 00507 00508 PPL_ASSERT(sys.OK()); 00509 return false; 00510 } 00511 sys[0][num_columns] = 1; 00512 // Ensure that, after any zero row clipping below, a single row 00513 // will remain for the integrality congruence. 00514 reduced_num_rows = 1; 00515 } 00516 00517 // Clip any zero rows from the end of the matrix. 00518 if (num_rows > 1 && num_rows > reduced_num_rows) { 00519 #ifndef NDEBUG 00520 const bool ret = rows_are_zero<Congruence_System, Congruence> 00521 (sys, 00522 // index of first 00523 reduced_num_rows, 00524 // index of last 00525 num_rows - 1, 00526 // row size 00527 num_columns); 00528 PPL_ASSERT(ret == true); 00529 #endif 00530 sys.erase_to_end(reduced_num_rows); 00531 } 00532 00533 PPL_ASSERT(sys.num_rows() == reduced_num_rows); 00534 00535 // Ensure that the last row is the integrality congruence. 00536 const dimension_type mod_index = num_columns; 00537 if (dim_kinds[0] == CON_VIRTUAL) { 00538 // The last row is virtual, append the integrality congruence. 00539 dim_kinds[0] = PROPER_CONGRUENCE; 00540 sys.add_zero_rows(1, 00541 Linear_Row::Flags(NECESSARILY_CLOSED, 00542 Linear_Row::RAY_OR_POINT_OR_INEQUALITY)); 00543 Congruence& new_last_row = sys[reduced_num_rows]; 00544 new_last_row[mod_index] = 1; 00545 // Try use an existing modulus. 00546 dimension_type row_index = reduced_num_rows; 00547 while (row_index-- > 0) { 00548 Congruence& row = sys[row_index]; 00549 if (row[mod_index] > 0) { 00550 new_last_row[mod_index] = row[mod_index]; 00551 break; 00552 } 00553 } 00554 new_last_row[0] = new_last_row[mod_index]; 00555 // Since we are reducing the system to "strong minimal form", 00556 // increment the number of reduced rows. 00557 ++reduced_num_rows; 00558 } 00559 else { 00560 Congruence& last_row = sys[reduced_num_rows - 1]; 00561 last_row[0] = last_row[mod_index]; 00562 } 00563 00564 // Since we are reducing the system to "strong minimal form", 00565 // factor the modified integrality congruence out of the other rows; 00566 reduce_reduced<Congruence_System, Congruence> 00567 (sys, 0, reduced_num_rows - 1, 0, 0, dim_kinds, false); 00568 00569 PPL_ASSERT(sys.OK()); 00570 return false; 00571 }
| bool Parma_Polyhedra_Library::Grid::simplify_using_context_assign | ( | const Grid & | y | ) |
Assigns to *this a meet-preserving simplification of *this with respect to y. If false is returned, then the intersection is empty.
| std::invalid_argument | Thrown if *this and y are topology-incompatible or dimension-incompatible. |
Definition at line 1568 of file Grid_public.cc.
References add_congruence(), add_congruences(), add_recycled_congruences(), add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Scalar_Products::assign(), Parma_Polyhedra_Library::Grid_Generator_System::begin(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), con_sys, congruences_are_minimized(), congruences_are_up_to_date(), Parma_Polyhedra_Library::Grid_Generator::divisor(), Parma_Polyhedra_Library::Grid_Generator_System::end(), gen_sys, generators_are_minimized(), Parma_Polyhedra_Library::Poly_Con_Relation::implies(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Congruence_System::insert(), is_empty(), Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), is_included_in(), Parma_Polyhedra_Library::Grid_Generator::is_parameter(), Parma_Polyhedra_Library::Grid_Generator::is_point(), Parma_Polyhedra_Library::Congruence::is_proper_congruence(), Parma_Polyhedra_Library::Congruence::is_tautological(), Parma_Polyhedra_Library::Checked::le, minimize(), Parma_Polyhedra_Library::Congruence::modulus(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), PPL_DIRTY_TEMP_COEFFICIENT, relation_with(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), swap(), throw_dimension_incompatible(), and Parma_Polyhedra_Library::UNIVERSE.
01568 { 01569 Grid& x = *this; 01570 // Dimension-compatibility check. 01571 if (x.space_dim != y.space_dim) 01572 throw_dimension_incompatible("simplify_using_context_assign(y)", "y", y); 01573 01574 // Filter away the zero-dimensional case. 01575 if (x.space_dim == 0) { 01576 if (y.is_empty()) { 01577 set_zero_dim_univ(); 01578 PPL_ASSERT(OK()); 01579 return false; 01580 } 01581 else 01582 return !x.is_empty(); 01583 } 01584 01585 // If `y' is empty, the biggest enlargement for `x' is the universe. 01586 if (!y.minimize()) { 01587 Grid gr(x.space_dim, UNIVERSE); 01588 swap(gr); 01589 return false; 01590 } 01591 01592 // If `x' is empty, the intersection is empty. 01593 if (!x.minimize()) { 01594 // Search for a congruence of `y' that is not a tautology. 01595 PPL_ASSERT(y.congruences_are_up_to_date()); 01596 Grid gr(x.space_dim, UNIVERSE); 01597 for (dimension_type i = y.con_sys.num_rows(); i-- > 0; ) { 01598 const Congruence& y_con_sys_i = y.con_sys[i]; 01599 if (!y_con_sys_i.is_tautological()) { 01600 // Found: we obtain a congruence `c' contradicting the one we 01601 // found, and assign to `x' the grid `gr' with `c' as 01602 // the only congruence. 01603 const Linear_Expression le(y_con_sys_i); 01604 if (y_con_sys_i.is_equality()) { 01605 gr.refine_no_check(le == 1); 01606 break; 01607 } 01608 else { 01609 const Coefficient& y_modulus_i = y_con_sys_i.modulus(); 01610 if (y_modulus_i > 1) 01611 gr.refine_no_check(le == 1); 01612 else { 01613 Linear_Expression le2; 01614 for (dimension_type j = le.space_dimension(); j-- > 0; ) 01615 le2 += 2 * le.coefficient(Variable(j)) * Variable(j); 01616 le2 += 2 * le.inhomogeneous_term(); 01617 gr.refine_no_check(le2 == y_modulus_i); 01618 } 01619 break; 01620 } 01621 } 01622 } 01623 swap(gr); 01624 PPL_ASSERT(OK()); 01625 return false; 01626 } 01627 01628 PPL_ASSERT(x.congruences_are_minimized() 01629 && y.generators_are_minimized()); 01630 01631 const Congruence_System& x_cs = x.con_sys; 01632 const dimension_type x_cs_num_rows = x_cs.num_rows(); 01633 const Grid_Generator_System& y_gs = y.gen_sys; 01634 01635 // Record into `redundant_by_y' the info about which congruences of 01636 // `x' are redundant in the context `y'. Count the number of 01637 // redundancies found. 01638 std::vector<bool> redundant_by_y(x_cs_num_rows, false); 01639 dimension_type num_redundant_by_y = 0; 01640 for (dimension_type i = 0; i < x_cs_num_rows; ++i) 01641 if (y.relation_with(x_cs[i]) 01642 .implies(Poly_Con_Relation::is_included())) { 01643 redundant_by_y[i] = true; 01644 ++num_redundant_by_y; 01645 } 01646 01647 if (num_redundant_by_y < x_cs_num_rows) { 01648 01649 // Some congruences were not identified as redundant. 01650 01651 Congruence_System result_cs; 01652 const Congruence_System& y_cs = y.con_sys; 01653 const dimension_type y_cs_num_rows = y_cs.num_rows(); 01654 // Compute into `z' the intersection of `x' and `y'. 01655 const bool x_first = (x_cs_num_rows > y_cs_num_rows); 01656 Grid z(x_first ? x : y); 01657 if (x_first) 01658 z.add_congruences(y_cs); 01659 else { 01660 // Only copy (and then recycle) the non-redundant congruences. 01661 Congruence_System tmp_cs; 01662 for (dimension_type i = 0; i < x_cs_num_rows; ++i) { 01663 if (!redundant_by_y[i]) 01664 tmp_cs.insert(x_cs[i]); 01665 } 01666 z.add_recycled_congruences(tmp_cs); 01667 } 01668 01669 // Congruences are added to `w' until it equals `z'. 01670 // We do not care about minimization or maximization, since 01671 // we are only interested in satisfiability. 01672 Grid w; 01673 w.add_space_dimensions_and_embed(x.space_dim); 01674 // First add the congruences for `y'. 01675 w.add_congruences(y_cs); 01676 01677 // We apply the following heuristics here: congruences of `x' that 01678 // are not made redundant by `y' are added to `w' depending on 01679 // the number of generators of `y' they rule out (the more generators) 01680 // (they rule out, the sooner they are added). Of course, as soon 01681 // as `w' becomes empty, we stop adding. 01682 std::vector<Ruled_Out_Pair> 01683 ruled_out_vec(x_cs_num_rows - num_redundant_by_y); 01684 01685 PPL_DIRTY_TEMP_COEFFICIENT(sp); 01686 PPL_DIRTY_TEMP_COEFFICIENT(div); 01687 01688 for (dimension_type i = 0, j = 0; i < x_cs_num_rows; ++i) { 01689 if (!redundant_by_y[i]) { 01690 const Congruence& c = x_cs[i]; 01691 const Coefficient& modulus = c.modulus(); 01692 div = modulus; 01693 01694 dimension_type num_ruled_out_generators = 0; 01695 for (Grid_Generator_System::const_iterator k = y_gs.begin(), 01696 y_gs_end = y_gs.end(); k != y_gs_end; ++k) { 01697 const Grid_Generator& g = *k; 01698 // If the generator is not to be ruled out, 01699 // it must saturate the congruence. 01700 Scalar_Products::assign(sp, c, g); 01701 // If `c' is a proper congruence the scalar product must be 01702 // reduced modulo a (possibly scaled) modulus. 01703 if (c.is_proper_congruence()) { 01704 // If `g' is a parameter the congruence modulus must be scaled 01705 // up by the divisor of the generator. 01706 if (g.is_parameter()) 01707 sp %= (div * g.divisor()); 01708 else 01709 if (g.is_point()) 01710 sp %= div; 01711 } 01712 if (sp == 0) 01713 continue; 01714 ++num_ruled_out_generators; 01715 } 01716 ruled_out_vec[j].congruence_index = i; 01717 ruled_out_vec[j].num_ruled_out = num_ruled_out_generators; 01718 ++j; 01719 } 01720 } 01721 std::sort(ruled_out_vec.begin(), ruled_out_vec.end(), 01722 Ruled_Out_Less_Than()); 01723 01724 bool empty_intersection = (!z.minimize()); 01725 01726 // Add the congruences in the "ruled out" order to `w' 01727 // until the result is the intersection. 01728 for (std::vector<Ruled_Out_Pair>::const_iterator 01729 j = ruled_out_vec.begin(), rov_end = ruled_out_vec.end(); 01730 j != rov_end; 01731 ++j) { 01732 const Congruence& c = x_cs[j->congruence_index]; 01733 result_cs.insert(c); 01734 w.add_congruence(c); 01735 if ((empty_intersection && w.is_empty()) 01736 || (!empty_intersection && w.is_included_in(z))) { 01737 Grid result_gr(x.space_dim, UNIVERSE); 01738 result_gr.add_congruences(result_cs); 01739 x.swap(result_gr); 01740 PPL_ASSERT(x.OK()); 01741 return !empty_intersection; 01742 } 01743 } 01744 // Cannot exit from here. 01745 PPL_ASSERT(false); 01746 } 01747 01748 // All the congruences are redundant so that the simplified grid 01749 // is the universe. 01750 Grid result_gr(x.space_dim, UNIVERSE); 01751 x.swap(result_gr); 01752 PPL_ASSERT(x.OK()); 01753 return true; 01754 }
| dimension_type Parma_Polyhedra_Library::Grid::space_dimension | ( | ) | const [inline] |
Returns the dimension of the vector space enclosing *this.
Definition at line 220 of file Grid.inlines.hh.
References space_dim.
Referenced by add_space_dimensions_and_embed(), add_space_dimensions_and_project(), Parma_Polyhedra_Library::Pointset_Powerset< PSET >::approximate_partition(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::Pointset_Powerset< PSET >::check_containment(), concatenate_assign(), drop_some_non_integer_points(), expand_space_dimension(), Parma_Polyhedra_Library::Grid_Certificate::Grid_Certificate(), hash_code(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), and throw_dimension_incompatible().
00220 { 00221 return space_dim; 00222 }
| bool Parma_Polyhedra_Library::Grid::strictly_contains | ( | const Grid & | y | ) | const [inline] |
Returns true if and only if *this strictly contains y.
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 361 of file Grid.inlines.hh.
References contains().
00361 { 00362 const Grid& x = *this; 00363 return x.contains(y) && !y.contains(x); 00364 }
| void Parma_Polyhedra_Library::Grid::swap | ( | Grid & | y | ) | [inline] |
Swaps *this with grid y. (*this and y can be dimension-incompatible.).
Definition at line 245 of file Grid.inlines.hh.
References con_sys, dim_kinds, gen_sys, space_dim, and status.
Referenced by add_recycled_grid_generators(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), congruence_widening_assign(), construct(), generator_widening_assign(), map_space_dimensions(), OK(), set_empty(), simplify(), simplify_using_context_assign(), and swap().
| void Parma_Polyhedra_Library::Grid::throw_dimension_incompatible | ( | const char * | method, | |
| dimension_type | required_space_dim | |||
| ) | const [protected] |
Definition at line 810 of file Grid_nonpublic.cc.
References space_dimension().
00811 { 00812 std::ostringstream s; 00813 s << "PPL::Grid::" << method << ":" << std::endl 00814 << "this->space_dimension() == " << space_dimension() 00815 << ", required space dimension == " << required_space_dim << "."; 00816 throw std::invalid_argument(s.str()); 00817 }
| void Parma_Polyhedra_Library::Grid::throw_dimension_incompatible | ( | const char * | method, | |
| const char * | var_name, | |||
| Variable | var | |||
| ) | const [protected] |
Definition at line 798 of file Grid_nonpublic.cc.
References Parma_Polyhedra_Library::Variable::space_dimension(), and space_dimension().
00800 { 00801 std::ostringstream s; 00802 s << "PPL::Grid::" << method << ":" << std::endl 00803 << "this->space_dimension() == " << space_dimension() << ", " 00804 << var_name << ".space_dimension() == " << var.space_dimension() << "."; 00805 throw std::invalid_argument(s.str()); 00806 }
| void Parma_Polyhedra_Library::Grid::throw_dimension_incompatible | ( | const char * | method, | |
| const char * | gs_name, | |||
| const Grid_Generator_System & | gs | |||
| ) | const [protected] |
Definition at line 791 of file Grid_nonpublic.cc.
References Parma_Polyhedra_Library::Grid_Generator_System::space_dimension(), and throw_dimension_incompatible().
00793 { 00794 throw_dimension_incompatible(method, gs_name, gs.space_dimension()); 00795 }
| void Parma_Polyhedra_Library::Grid::throw_dimension_incompatible | ( | const char * | method, | |
| const char * | cs_name, | |||
| const Constraint_System & | cs | |||
| ) | const [protected] |
Definition at line 784 of file Grid_nonpublic.cc.
References Parma_Polyhedra_Library::Constraint_System::space_dimension(), and throw_dimension_incompatible().
00786 { 00787 throw_dimension_incompatible(method, cs_name, cs.space_dimension()); 00788 }
| void Parma_Polyhedra_Library::Grid::throw_dimension_incompatible | ( | const char * | method, | |
| const char * | cgs_name, | |||
| const Congruence_System & | cgs | |||
| ) | const [protected] |
Definition at line 777 of file Grid_nonpublic.cc.
References Parma_Polyhedra_Library::Congruence_System::space_dimension(), and throw_dimension_incompatible().
00779 { 00780 throw_dimension_incompatible(method, cgs_name, cgs.space_dimension()); 00781 }
| void Parma_Polyhedra_Library::Grid::throw_dimension_incompatible | ( | const char * | method, | |
| const char * | g_name, | |||
| const Generator & | g | |||
| ) | const [protected] |
Definition at line 770 of file Grid_nonpublic.cc.
References Parma_Polyhedra_Library::Generator::space_dimension(), and throw_dimension_incompatible().
00772 { 00773 throw_dimension_incompatible(method, g_name, g.space_dimension()); 00774 }
| void Parma_Polyhedra_Library::Grid::throw_dimension_incompatible | ( | const char * | method, | |
| const char * | g_name, | |||
| const Grid_Generator & | g | |||
| ) | const [protected] |
Definition at line 763 of file Grid_nonpublic.cc.
References Parma_Polyhedra_Library::Grid_Generator::space_dimension(), and throw_dimension_incompatible().
00765 { 00766 throw_dimension_incompatible(method, g_name, g.space_dimension()); 00767 }
| void Parma_Polyhedra_Library::Grid::throw_dimension_incompatible | ( | const char * | method, | |
| const char * | c_name, | |||
| const Constraint & | c | |||
| ) | const [protected] |
Definition at line 756 of file Grid_nonpublic.cc.
References Parma_Polyhedra_Library::Constraint::space_dimension(), and throw_dimension_incompatible().
00758 { 00759 throw_dimension_incompatible(method, c_name, c.space_dimension()); 00760 }
| void Parma_Polyhedra_Library::Grid::throw_dimension_incompatible | ( | const char * | method, | |
| const char * | cg_name, | |||
| const Congruence & | cg | |||
| ) | const [protected] |
Definition at line 749 of file Grid_nonpublic.cc.
References Parma_Polyhedra_Library::Congruence::space_dimension(), and throw_dimension_incompatible().
00751 { 00752 throw_dimension_incompatible(method, cg_name, cg.space_dimension()); 00753 }
| void Parma_Polyhedra_Library::Grid::throw_dimension_incompatible | ( | const char * | method, | |
| const char * | e_name, | |||
| const Linear_Expression & | e | |||
| ) | const [protected] |
Definition at line 742 of file Grid_nonpublic.cc.
References Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and throw_dimension_incompatible().
00744 { 00745 throw_dimension_incompatible(method, e_name, e.space_dimension()); 00746 }
| void Parma_Polyhedra_Library::Grid::throw_dimension_incompatible | ( | const char * | method, | |
| const char * | gr_name, | |||
| const Grid & | gr | |||
| ) | const [protected] |
Definition at line 735 of file Grid_nonpublic.cc.
References space_dimension(), and throw_dimension_incompatible().
00737 { 00738 throw_dimension_incompatible(method, gr_name, gr.space_dimension()); 00739 }
| void Parma_Polyhedra_Library::Grid::throw_dimension_incompatible | ( | const char * | method, | |
| const char * | other_name, | |||
| dimension_type | other_dim | |||
| ) | const [protected] |
Definition at line 724 of file Grid_nonpublic.cc.
References space_dimension().
Referenced by add_congruence(), add_congruences(), add_constraint(), add_constraints(), add_grid_generator(), add_recycled_congruences(), add_recycled_grid_generators(), affine_image(), affine_preimage(), bounded_affine_image(), bounded_affine_preimage(), bounds(), congruence_widening_assign(), constrains(), contains(), difference_assign(), drop_some_non_integer_points(), expand_space_dimension(), fold_space_dimensions(), frequency(), generalized_affine_image(), generalized_affine_preimage(), generator_widening_assign(), intersection_assign(), is_disjoint_from(), limited_congruence_extrapolation_assign(), limited_extrapolation_assign(), limited_generator_extrapolation_assign(), refine_with_constraint(), refine_with_constraints(), relation_with(), remove_higher_space_dimensions(), remove_space_dimensions(), simplify_using_context_assign(), throw_dimension_incompatible(), time_elapse_assign(), unconstrain(), upper_bound_assign(), upper_bound_assign_if_exact(), widening_assign(), and wrap_assign().
00726 { 00727 std::ostringstream s; 00728 s << "PPL::Grid::" << method << ":\n" 00729 << "this->space_dimension() == " << space_dimension() << ", " 00730 << other_name << ".space_dimension() == " << other_dim << "."; 00731 throw std::invalid_argument(s.str()); 00732 }
| void Parma_Polyhedra_Library::Grid::throw_invalid_argument | ( | const char * | method, | |
| const char * | reason | |||
| ) | const [protected] |
Definition at line 715 of file Grid_nonpublic.cc.
Referenced by affine_image(), affine_preimage(), bounded_affine_image(), bounded_affine_preimage(), fold_space_dimensions(), generalized_affine_image(), generalized_affine_preimage(), and map_space_dimensions().
| void Parma_Polyhedra_Library::Grid::throw_invalid_constraint | ( | const char * | method, | |
| const char * | c_name | |||
| ) | const [protected] |
Definition at line 829 of file Grid_nonpublic.cc.
Referenced by add_constraint_no_check(), and Grid().
| void Parma_Polyhedra_Library::Grid::throw_invalid_constraints | ( | const char * | method, | |
| const char * | cs_name | |||
| ) | const [protected] |
Definition at line 838 of file Grid_nonpublic.cc.
Referenced by Grid().
| void Parma_Polyhedra_Library::Grid::throw_invalid_generator | ( | const char * | method, | |
| const char * | g_name | |||
| ) | const [protected] |
Definition at line 848 of file Grid_nonpublic.cc.
Referenced by add_grid_generator().
| void Parma_Polyhedra_Library::Grid::throw_invalid_generators | ( | const char * | method, | |
| const char * | gs_name | |||
| ) | const [protected] |
Definition at line 858 of file Grid_nonpublic.cc.
Referenced by add_recycled_grid_generators(), and construct().
| void Parma_Polyhedra_Library::Grid::throw_runtime_error | ( | const char * | method | ) | const [protected] |
Definition at line 708 of file Grid_nonpublic.cc.
| void Parma_Polyhedra_Library::Grid::throw_space_dimension_overflow | ( | const char * | method, | |
| const char * | reason | |||
| ) | [static, protected] |
Definition at line 820 of file Grid_nonpublic.cc.
Referenced by add_space_dimensions_and_embed(), add_space_dimensions_and_project(), concatenate_assign(), expand_space_dimension(), and Grid().
| void Parma_Polyhedra_Library::Grid::time_elapse_assign | ( | const Grid & | y | ) |
Assigns to *this the result of computing the time-elapse between *this and y.
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 2435 of file Grid_public.cc.
References clear_congruences_up_to_date(), clear_generators_minimized(), gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Grid_Generator::is_point(), marked_empty(), normalize_divisors(), Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), OK(), Parma_Polyhedra_Library::Grid_Generator_System::recycling_insert(), set_empty(), Parma_Polyhedra_Library::Grid_Generator::set_is_parameter(), space_dim, throw_dimension_incompatible(), and update_generators().
02435 { 02436 Grid& x = *this; 02437 // Check dimension-compatibility. 02438 if (x.space_dim != y.space_dim) 02439 throw_dimension_incompatible("time_elapse_assign(y)", "y", y); 02440 02441 // Deal with the zero-dimensional case. 02442 if (x.space_dim == 0) { 02443 if (y.marked_empty()) 02444 x.set_empty(); 02445 return; 02446 } 02447 02448 // If either one of `x' or `y' is empty, the result is empty too. 02449 if (x.marked_empty()) 02450 return; 02451 if (y.marked_empty() 02452 || (!x.generators_are_up_to_date() && !x.update_generators()) 02453 || (!y.generators_are_up_to_date() && !y.update_generators())) { 02454 x.set_empty(); 02455 return; 02456 } 02457 02458 // At this point both generator systems are up-to-date. 02459 Grid_Generator_System gs = y.gen_sys; 02460 dimension_type gs_num_rows = gs.num_rows(); 02461 02462 normalize_divisors(gs, gen_sys); 02463 02464 for (dimension_type i = gs_num_rows; i-- > 0; ) { 02465 Grid_Generator& g = gs[i]; 02466 if (g.is_point()) 02467 // Transform the point into a parameter. 02468 g.set_is_parameter(); 02469 } 02470 02471 if (gs_num_rows == 0) 02472 // `y' was the grid containing a single point at the origin, so 02473 // the result is `x'. 02474 return; 02475 02476 // Append `gs' to the generators of `x'. 02477 02478 gen_sys.recycling_insert(gs); 02479 02480 x.clear_congruences_up_to_date(); 02481 x.clear_generators_minimized(); 02482 02483 PPL_ASSERT(x.OK(true) && y.OK(true)); 02484 }
| void Parma_Polyhedra_Library::Grid::topological_closure_assign | ( | ) | [inline] |
Assigns to *this its topological closure.
Definition at line 367 of file Grid.inlines.hh.
| memory_size_type Parma_Polyhedra_Library::Grid::total_memory_in_bytes | ( | ) | const [inline] |
Returns the total size in bytes of the memory occupied by *this.
Definition at line 225 of file Grid.inlines.hh.
References external_memory_in_bytes().
00225 { 00226 return sizeof(*this) + external_memory_in_bytes(); 00227 }
| void Parma_Polyhedra_Library::Grid::unconstrain | ( | const Variables_Set & | vars | ) |
Computes the cylindrification of *this with respect to the set of space dimensions vars, assigning the result to *this.
| vars | The set of space dimension that will be unconstrained. |
| std::invalid_argument | Thrown if *this is dimension-incompatible with one of the Variable objects contained in vars. |
Definition at line 1339 of file Grid_public.cc.
References clear_congruences_up_to_date(), clear_generators_minimized(), gen_sys, generators_are_up_to_date(), marked_empty(), OK(), Parma_Polyhedra_Library::Grid_Generator_System::recycling_insert(), space_dim, Parma_Polyhedra_Library::Variables_Set::space_dimension(), throw_dimension_incompatible(), and update_generators().
01339 { 01340 // The cylindrification wrt no dimensions is a no-op. 01341 // This case also captures the only legal cylindrification 01342 // of a grid in a 0-dim space. 01343 if (vars.empty()) 01344 return; 01345 01346 // Dimension-compatibility check. 01347 const dimension_type min_space_dim = vars.space_dimension(); 01348 if (space_dim < min_space_dim) 01349 throw_dimension_incompatible("unconstrain(vs)", min_space_dim); 01350 01351 // Do something only if the grid is non-empty. 01352 if (marked_empty() 01353 || (!generators_are_up_to_date() && !update_generators())) 01354 // Empty: do nothing. 01355 return; 01356 01357 PPL_ASSERT(generators_are_up_to_date()); 01358 // Since `gen_sys' is not empty, the space dimension of the inserted 01359 // generators are automatically adjusted. 01360 for (Variables_Set::const_iterator vsi = vars.begin(), 01361 vsi_end = vars.end(); vsi != vsi_end; ++vsi) { 01362 Grid_Generator l = grid_line(Variable(*vsi)); 01363 gen_sys.recycling_insert(l); 01364 } 01365 // Constraints are no longer up-to-date. 01366 clear_generators_minimized(); 01367 clear_congruences_up_to_date(); 01368 PPL_ASSERT(OK()); 01369 }
| void Parma_Polyhedra_Library::Grid::unconstrain | ( | Variable | var | ) |
Computes the cylindrification of *this with respect to space dimension var, assigning the result to *this.
| var | The space dimension that will be unconstrained. |
| std::invalid_argument | Thrown if var is not a space dimension of *this. |
Definition at line 1318 of file Grid_public.cc.
References clear_congruences_up_to_date(), clear_generators_minimized(), gen_sys, generators_are_up_to_date(), marked_empty(), OK(), Parma_Polyhedra_Library::Grid_Generator_System::recycling_insert(), space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), throw_dimension_incompatible(), and update_generators().
Referenced by wrap_assign().
01318 { 01319 // Dimension-compatibility check. 01320 if (space_dim < var.space_dimension()) 01321 throw_dimension_incompatible("unconstrain(var)", var.space_dimension()); 01322 01323 // Do something only if the grid is non-empty. 01324 if (marked_empty() 01325 || (!generators_are_up_to_date() && !update_generators())) 01326 // Empty: do nothing. 01327 return; 01328 01329 PPL_ASSERT(generators_are_up_to_date()); 01330 Grid_Generator l = grid_line(var); 01331 gen_sys.recycling_insert(l); 01332 // With the added generator, congruences are out of date. 01333 clear_congruences_up_to_date(); 01334 clear_generators_minimized(); 01335 PPL_ASSERT(OK()); 01336 }
| void Parma_Polyhedra_Library::Grid::update_congruences | ( | ) | const [private] |
Updates and minimizes the congruences from the generators.
Definition at line 464 of file Grid_nonpublic.cc.
References gen_sys, generators_are_minimized(), Parma_Polyhedra_Library::Matrix::has_no_rows(), marked_empty(), space_dim, and Parma_Polyhedra_Library::Grid_Generator_System::space_dimension().
Referenced by add_congruence_no_check(), add_recycled_congruences(), concatenate_assign(), congruence_widening_assign(), congruences(), constrains(), intersection_assign(), is_included_in(), is_universe(), minimize(), and relation_with().
00464 { 00465 // The caller must ensure that the generators are up to date. 00466 PPL_ASSERT(space_dim > 0); 00467 PPL_ASSERT(!marked_empty()); 00468 PPL_ASSERT(!gen_sys.has_no_rows()); 00469 PPL_ASSERT(gen_sys.space_dimension() > 0); 00470 00471 Grid& gr = const_cast<Grid&>(*this); 00472 00473 if (!generators_are_minimized()) 00474 gr.simplify(gr.gen_sys, gr.dim_kinds); 00475 00476 // `gen_sys' contained rows before being reduced, so it should 00477 // contain at least a single point afterward. 00478 PPL_ASSERT(!gen_sys.has_no_rows()); 00479 00480 // Populate `con_sys' with congruences characterizing the grid 00481 // described by `gen_sys'. 00482 gr.conversion(gr.gen_sys, gr.con_sys, gr.dim_kinds); 00483 00484 // Both systems are minimized. 00485 gr.set_congruences_minimized(); 00486 gr.set_generators_minimized(); 00487 }
| bool Parma_Polyhedra_Library::Grid::update_generators | ( | ) | const [private] |
Updates and minimizes the generators from the congruences.
false if and only if *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.
Definition at line 490 of file Grid_nonpublic.cc.
References con_sys, congruences_are_minimized(), congruences_are_up_to_date(), conversion(), dim_kinds, gen_sys, marked_empty(), set_congruences_minimized(), set_empty(), set_generators_minimized(), simplify(), and space_dim.
Referenced by add_grid_generator(), add_recycled_grid_generators(), bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), generalized_affine_image(), generalized_affine_preimage(), generator_widening_assign(), grid_generators(), is_bounded(), is_discrete(), limited_congruence_extrapolation_assign(), limited_extrapolation_assign(), limited_generator_extrapolation_assign(), map_space_dimensions(), minimize(), minimized_grid_generators(), OK(), relation_with(), remove_space_dimensions(), time_elapse_assign(), unconstrain(), and upper_bound_assign().
00490 { 00491 PPL_ASSERT(space_dim > 0); 00492 PPL_ASSERT(!marked_empty()); 00493 PPL_ASSERT(congruences_are_up_to_date()); 00494 00495 Grid& x = const_cast<Grid&>(*this); 00496 00497 if (!congruences_are_minimized()) 00498 // Either the system of congruences is consistent, or the grid is 00499 // empty. 00500 if (simplify(x.con_sys, x.dim_kinds)) { 00501 x.set_empty(); 00502 return false; 00503 } 00504 00505 // Populate gen_sys with generators characterizing the grid 00506 // described by con_sys. 00507 conversion(x.con_sys, x.gen_sys, x.dim_kinds); 00508 00509 // Both systems are minimized. 00510 x.set_congruences_minimized(); 00511 x.set_generators_minimized(); 00512 return true; 00513 }
| void Parma_Polyhedra_Library::Grid::upper_bound_assign | ( | const Grid & | y | ) |
Assigns to *this the least upper bound of *this and y.
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 1409 of file Grid_public.cc.
References clear_congruences_up_to_date(), clear_generators_minimized(), gen_sys, generators_are_up_to_date(), marked_empty(), normalize_divisors(), OK(), Parma_Polyhedra_Library::Grid_Generator_System::recycling_insert(), space_dim, throw_dimension_incompatible(), and update_generators().
Referenced by difference_assign(), fold_space_dimensions(), and upper_bound_assign_if_exact().
01409 { 01410 Grid& x = *this; 01411 // Dimension-compatibility check. 01412 if (x.space_dim != y.space_dim) 01413 throw_dimension_incompatible("upper_bound_assign(y)", "y", y); 01414 01415 // The join of a grid `gr' with an empty grid is `gr'. 01416 if (y.marked_empty()) 01417 return; 01418 if (x.marked_empty()) { 01419 x = y; 01420 return; 01421 } 01422 01423 // If both grids are zero-dimensional, then they are necessarily 01424 // universe grids, and so is their join. 01425 if (x.space_dim == 0) 01426 return; 01427 01428 // The generators must be up-to-date. 01429 if (!x.generators_are_up_to_date() && !x.update_generators()) { 01430 // Discovered `x' empty when updating generators. 01431 x = y; 01432 return; 01433 } 01434 if (!y.generators_are_up_to_date() && !y.update_generators()) 01435 // Discovered `y' empty when updating generators. 01436 return; 01437 01438 // Match the divisors of the x and y generator systems. 01439 Grid_Generator_System gs(y.gen_sys); 01440 normalize_divisors(x.gen_sys, gs); 01441 x.gen_sys.recycling_insert(gs); 01442 // Congruences may be out of date and generators may have lost 01443 // minimal form. 01444 x.clear_congruences_up_to_date(); 01445 x.clear_generators_minimized(); 01446 01447 // At this point both `x' and `y' are not empty. 01448 PPL_ASSERT(x.OK(true) && y.OK(true)); 01449 }
| bool Parma_Polyhedra_Library::Grid::upper_bound_assign_if_exact | ( | const Grid & | y | ) |
If the upper bound of *this and y is exact it is assigned to this and true is returned, otherwise false is returned.
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 1452 of file Grid_public.cc.
References difference_assign(), generators_are_up_to_date(), is_included_in(), marked_empty(), space_dim, throw_dimension_incompatible(), and upper_bound_assign().
01452 { 01453 Grid& x = *this; 01454 01455 // Dimension-compatibility check. 01456 if (x.space_dim != y.space_dim) 01457 throw_dimension_incompatible("upper_bound_assign_if_exact(y)", "y", y); 01458 01459 if (x.marked_empty() 01460 || y.marked_empty() 01461 || x.space_dim == 0 01462 || x.is_included_in(y) 01463 || y.is_included_in(x)) { 01464 upper_bound_assign(y); 01465 return true; 01466 } 01467 01468 // The above test 'x.is_included_in(y)' will ensure the generators of x 01469 // are up to date. 01470 PPL_ASSERT(generators_are_up_to_date()); 01471 01472 Grid x_copy = x; 01473 x_copy.upper_bound_assign(y); 01474 x_copy.difference_assign(y); 01475 if (x_copy.is_included_in(x)) { 01476 upper_bound_assign(y); 01477 return true; 01478 } 01479 01480 return false; 01481 }
| bool Parma_Polyhedra_Library::Grid::upper_triangular | ( | const Grid_Generator_System & | sys, | |
| const Dimension_Kinds & | dim_kinds | |||
| ) | [static, private] |
If sys is upper triangular return true, else return false.
Definition at line 75 of file Grid_conversion.cc.
References GEN_VIRTUAL, Parma_Polyhedra_Library::Grid_Generator_System::num_rows(), and Parma_Polyhedra_Library::Grid_Generator_System::space_dimension().
Referenced by conversion(), and OK().
00076 { 00077 dimension_type num_columns = sys.space_dimension() + 1; 00078 dimension_type row = sys.num_rows(); 00079 00080 // Check for easy square fail case. 00081 if (row > num_columns) 00082 return false; 00083 00084 // Check triangularity. 00085 while (num_columns > 0) { 00086 --num_columns; 00087 if (dim_kinds[num_columns] == GEN_VIRTUAL) 00088 continue; 00089 const Grid_Generator& gen = sys[--row]; 00090 // Check diagonal. 00091 if (gen[num_columns] <= 0) 00092 return false; 00093 // Check elements preceding diagonal. 00094 dimension_type col = num_columns; 00095 while (col-- > 0) 00096 if (gen[col] != 0) 00097 return false; 00098 } 00099 00100 // Check for squareness. 00101 return num_columns == row; 00102 }
| void Parma_Polyhedra_Library::Grid::widening_assign | ( | const Grid & | y, | |
| unsigned * | tp = NULL | |||
| ) |
Assigns to *this the result of computing the Grid widening between *this and 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.
| y | A grid that must be contained in *this; | |
| tp | An optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique). |
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 432 of file Grid_widenings.cc.
References congruence_widening_assign(), congruences_are_up_to_date(), contains(), generator_widening_assign(), generators_are_up_to_date(), space_dim, and throw_dimension_incompatible().
Referenced by limited_congruence_extrapolation_assign(), and limited_extrapolation_assign().
00432 { 00433 Grid& x = *this; 00434 Grid& y = const_cast<Grid&>(const_y); 00435 // Dimension-compatibility check. 00436 if (x.space_dim != y.space_dim) 00437 throw_dimension_incompatible("widening_assign(y)", "y", y); 00438 00439 // Stable behavior is only guaranteed if y is contained in or equal 00440 // to x. 00441 #ifndef NDEBUG 00442 { 00443 // Assume y is contained in or equal to x. 00444 const Grid x_copy = x; 00445 const Grid y_copy = y; 00446 PPL_ASSERT(x_copy.contains(y_copy)); 00447 } 00448 #endif 00449 00450 // If the `x' congruences are up to date and `y' congruences are up 00451 // to date use the congruence widening. 00452 if (x.congruences_are_up_to_date() && y.congruences_are_up_to_date()) { 00453 x.congruence_widening_assign(y, tp); 00454 return; 00455 } 00456 00457 // If the `x' generators are up to date and `y' generators are up to 00458 // date use the generator widening. 00459 if (x.generators_are_up_to_date() && y.generators_are_up_to_date()) { 00460 x.generator_widening_assign(y, tp); 00461 return; 00462 } 00463 00464 x.congruence_widening_assign(y, tp); 00465 }
| void Parma_Polyhedra_Library::Grid::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 | |||
| ) |
Wraps the specified dimensions of the vector space.
| vars | The set of Variable objects corresponding to the space dimensions to be wrapped. | |
| w | The width of the bounded integer type corresponding to all the dimensions to be wrapped. | |
| r | The representation of the bounded integer type corresponding to all the dimensions to be wrapped. | |
| o | The overflow behavior of the bounded integer type corresponding to all the dimensions to be wrapped. | |
| 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. | |
| complexity_threshold | A precision parameter of the wrapping operator. This argument is for compatibility with wrap_assign() for the other domains and is ignored. | |
| wrap_individually | true if the dimensions should be wrapped individually. As wrapping dimensions collectively does not improve the precision, this argument is ignored. |
| std::invalid_argument | Thrown if *this is dimension-incompatible with one of the Variable objects contained in vars or with *pcs. |
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. Definition at line 2677 of file Grid_public.cc.
References add_congruence(), add_constraint(), add_grid_generator(), bounds_no_check(), Parma_Polyhedra_Library::Grid_Generator::coefficient(), Parma_Polyhedra_Library::Coefficient_one(), Parma_Polyhedra_Library::Grid_Generator::divisor(), frequency_no_check(), gen_sys, generators_are_minimized(), marked_empty(), minimize(), Parma_Polyhedra_Library::mul_2exp_assign(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::OVERFLOW_IMPOSSIBLE, Parma_Polyhedra_Library::OVERFLOW_UNDEFINED, Parma_Polyhedra_Library::OVERFLOW_WRAPS, PPL_DIRTY_TEMP_COEFFICIENT, set_empty(), Parma_Polyhedra_Library::SIGNED_2_COMPLEMENT, space_dim, Parma_Polyhedra_Library::Variables_Set::space_dimension(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), throw_dimension_incompatible(), unconstrain(), and Parma_Polyhedra_Library::UNSIGNED.
02683 { 02684 02685 // Dimension-compatibility check of `*pcs', if any. 02686 if (pcs != 0) { 02687 const dimension_type pcs_space_dim = pcs->space_dimension(); 02688 if (pcs->space_dimension() > space_dim) 02689 throw_dimension_incompatible("wrap_assign(vs, ...)", pcs_space_dim); 02690 } 02691 02692 // Wrapping no variable is a no-op. 02693 if (vars.empty()) 02694 return; 02695 02696 // Dimension-compatibility check of `vars'. 02697 const dimension_type min_space_dim = vars.space_dimension(); 02698 if (space_dim < min_space_dim) 02699 throw_dimension_incompatible("wrap_assign(vs, ...)", min_space_dim); 02700 02701 // Wrapping an empty grid is a no-op. 02702 if (marked_empty()) 02703 return; 02704 if (!generators_are_minimized() && !minimize()) 02705 // Minimizing found `this' empty. 02706 return; 02707 02708 // Set the wrap frequency for variables of width `w'. 02709 // This is independent of the signedness `s'. 02710 PPL_DIRTY_TEMP_COEFFICIENT(wrap_frequency); 02711 mul_2exp_assign(wrap_frequency, Coefficient_one(), w); 02712 // Set `min_value' and `max_value' to the minimum and maximum values 02713 // a variable of width `w' and signedness `s' can take. 02714 PPL_DIRTY_TEMP_COEFFICIENT(min_value); 02715 PPL_DIRTY_TEMP_COEFFICIENT(max_value); 02716 if (r == UNSIGNED) { 02717 min_value = 0; 02718 mul_2exp_assign(max_value, Coefficient_one(), w); 02719 --max_value; 02720 } 02721 else { 02722 PPL_ASSERT(r == SIGNED_2_COMPLEMENT); 02723 mul_2exp_assign(max_value, Coefficient_one(), w-1); 02724 neg_assign(min_value, max_value); 02725 --max_value; 02726 } 02727 02728 // Generators are up-to-date and minimized. 02729 const Grid gr = *this; 02730 02731 // Overflow is impossible or wraps. 02732 if (o == OVERFLOW_IMPOSSIBLE || o == OVERFLOW_WRAPS) { 02733 PPL_DIRTY_TEMP_COEFFICIENT(f_n); 02734 PPL_DIRTY_TEMP_COEFFICIENT(f_d); 02735 PPL_DIRTY_TEMP_COEFFICIENT(v_n); 02736 PPL_DIRTY_TEMP_COEFFICIENT(v_d); 02737 for (Variables_Set::const_iterator i = vars.begin(), 02738 vars_end = vars.end(); i != vars.end(); ++i) { 02739 const Variable x = Variable(*i); 02740 // Find the frequency and a value for `x' in `gr'. 02741 if (!gr.frequency_no_check(x, f_n, f_d, v_n, v_d)) 02742 continue; 02743 if (f_n == 0) { 02744 02745 // `x' is a constant in `gr'. 02746 if (v_d != 1) { 02747 // The value for `x' is not integral (`frequency_no_check()' 02748 // ensures that `v_n' and `v_d' have no common divisors). 02749 set_empty(); 02750 return; 02751 } 02752 02753 // `x' is a constant and has an integral value. 02754 if ((v_n > max_value) || (v_n < min_value)) { 02755 // The value is outside the range of the bounded integer type. 02756 if (o == OVERFLOW_IMPOSSIBLE) { 02757 // Then `x' has no possible value and hence set empty. 02758 set_empty(); 02759 return; 02760 } 02761 PPL_ASSERT(o == OVERFLOW_WRAPS); 02762 // The value v_n for `x' is wrapped modulo the 'wrap_frequency'. 02763 v_n %= wrap_frequency; 02764 // `v_n' is the value closest to 0 and may be negative. 02765 if (r == UNSIGNED && v_n < 0) 02766 v_n += wrap_frequency; 02767 unconstrain(x); 02768 add_constraint(x == v_n); 02769 } 02770 continue; 02771 } 02772 02773 // `x' is not a constant in `gr'. 02774 PPL_ASSERT(f_n != 0); 02775 02776 if (f_d % v_d != 0) { 02777 // Then `x' has no integral value and hence `gr' is set empty. 02778 set_empty(); 02779 return; 02780 } 02781 if (f_d != 1) { 02782 // `x' has non-integral values, so add the integrality 02783 // congruence for `x'. 02784 add_congruence((x %= 0) / 1); 02785 } 02786 if (o == OVERFLOW_WRAPS && f_n != wrap_frequency) 02787 // We know that `x' is not a constant, so, if overflow wraps, 02788 // `x' may wrap to a value modulo the `wrap_frequency'. 02789 add_grid_generator(parameter(wrap_frequency * x)); 02790 else if ((o == OVERFLOW_IMPOSSIBLE && 2*f_n >= wrap_frequency) 02791 || (f_n == wrap_frequency)) { 02792 // In these cases, `x' can only take a unique (ie constant) 02793 // value. 02794 if (r == UNSIGNED && v_n < 0) { 02795 // `v_n' is the value closest to 0 and may be negative. 02796 v_n += f_n; 02797 } 02798 unconstrain(x); 02799 add_constraint(x == v_n); 02800 } 02801 else { 02802 // If overflow is impossible but the grid frequency is less than 02803 // half the wrap frequency, then there is more than one possible 02804 // value for `x' in the range of the bounded integer type, 02805 // so the grid is unchanged. 02806 PPL_ASSERT(o == OVERFLOW_IMPOSSIBLE && 2*f_n < wrap_frequency); 02807 } 02808 } 02809 return; 02810 } 02811 02812 PPL_ASSERT(o == OVERFLOW_UNDEFINED); 02813 // If overflow is undefined, then all we know is that the variable 02814 // may take any integer within the range of the bounded integer type. 02815 const Grid_Generator& point = gr.gen_sys[0]; 02816 const Coefficient& div = point.divisor(); 02817 max_value *= div; 02818 min_value *= div; 02819 for (Variables_Set::const_iterator i = vars.begin(), 02820 vars_end = vars.end(); i != vars.end(); ++i) { 02821 const Variable x = Variable(*i); 02822 if (!gr.bounds_no_check(x)) { 02823 // `x' is not a constant in `gr'. 02824 // We know that `x' is not a constant, so `x' may wrap to any 02825 // value `x + z' where z is an integer. 02826 if (point.coefficient(x) % div != 0) { 02827 // We know that `x' can take non-integral values, so enforce 02828 // integrality. 02829 unconstrain(x); 02830 add_congruence(x %= 0); 02831 } 02832 else 02833 // `x' has at least one integral value. 02834 // `x' may also take other non-integral values, 02835 // but checking could be costly so we ignore this. 02836 add_grid_generator(parameter(x)); 02837 } 02838 else { 02839 // `x' is a constant `v' in `gr'. 02840 const Coefficient& coeff_x = point.coefficient(x); 02841 // `x' should be integral. 02842 if (coeff_x % div != 0) { 02843 set_empty(); 02844 return; 02845 } 02846 // If the value `v' for `x' is not within the range for the 02847 // bounded integer type, then `x' may wrap to any value `v + z' 02848 // where `z' is an integer; otherwise `x' is unchanged. 02849 if (coeff_x > max_value || coeff_x < min_value) { 02850 add_grid_generator(parameter(x)); 02851 } 02852 } 02853 } 02854 }
Returns true if and only if x and y are different grids.
Note that x and y may be dimension-incompatible grids: in those cases, the value true is returned.
Definition at line 356 of file Grid.inlines.hh.
| std::ostream & operator<< | ( | std::ostream & | s, | |
| const Grid & | gr | |||
| ) | [related] |
Output operator.
Writes a textual representation of gr on s: false is written if gr is an empty grid; true is written if gr is a universe grid; a minimized system of congruences defining gr is written otherwise, all congruences in one row separated by ", "s.
Definition at line 2897 of file Grid_public.cc.
References is_empty(), is_universe(), and minimized_congruences().
Returns true if and only if x and y are the same grid.
Note that x and y may be dimension-incompatible grids: in those cases, the value false is returned.
Definition at line 2514 of file Grid_public.cc.
02514 { 02515 if (x.space_dim != y.space_dim) 02516 return false; 02517 02518 if (x.marked_empty()) 02519 return y.is_empty(); 02520 if (y.marked_empty()) 02521 return x.is_empty(); 02522 if (x.space_dim == 0) 02523 return true; 02524 02525 switch (x.quick_equivalence_test(y)) { 02526 case Grid::TVB_TRUE: 02527 return true; 02528 02529 case Grid::TVB_FALSE: 02530 return false; 02531 02532 default: 02533 if (x.is_included_in(y)) { 02534 if (x.marked_empty()) 02535 return y.is_empty(); 02536 return y.is_included_in(x); 02537 } 02538 return false; 02539 } 02540 }
friend class Parma_Polyhedra_Library::Box [friend] |
Definition at line 1924 of file Grid.defs.hh.
friend class Parma_Polyhedra_Library::Grid_Certificate [friend] |
Definition at line 1922 of file Grid.defs.hh.
| void swap | ( | Parma_Polyhedra_Library::Grid & | x, | |
| Parma_Polyhedra_Library::Grid & | y | |||
| ) | [related] |
Specializes std::swap.
Definition at line 376 of file Grid.inlines.hh.
References swap().
00377 { 00378 x.swap(y); 00379 }
The system of congruences.
Definition at line 1966 of file Grid.defs.hh.
Referenced by add_congruence_no_check(), add_recycled_congruences(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_dimension(), affine_image(), affine_preimage(), ascii_dump(), concatenate_assign(), congruence_widening_assign(), congruences(), constrains(), construct(), external_memory_in_bytes(), Grid(), Parma_Polyhedra_Library::Grid_Certificate::Grid_Certificate(), intersection_assign(), is_empty(), is_included_in(), is_universe(), map_space_dimensions(), minimize(), minimized_congruences(), OK(), operator=(), quick_equivalence_test(), relation_with(), remove_higher_space_dimensions(), select_wider_congruences(), set_empty(), set_zero_dim_univ(), simplify_using_context_assign(), swap(), and update_generators().
Definition at line 1998 of file Grid.defs.hh.
Referenced by add_space_dimensions(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), ascii_dump(), congruence_widening_assign(), construct(), generator_widening_assign(), Parma_Polyhedra_Library::Grid_Certificate::Grid_Certificate(), is_empty(), max_min(), minimize(), minimized_congruences(), minimized_grid_generators(), OK(), operator=(), remove_higher_space_dimensions(), select_wider_congruences(), select_wider_generators(), swap(), and update_generators().
The system of generators.
Definition at line 1969 of file Grid.defs.hh.
Referenced by add_grid_generator(), add_recycled_grid_generators(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_dimension(), affine_image(), affine_preimage(), ascii_dump(), bounds_no_check(), Parma_Polyhedra_Library::Box< ITV >::Box(), constrains(), construct(), external_memory_in_bytes(), frequency_no_check(), generalized_affine_image(), generalized_affine_preimage(), generator_widening_assign(), Grid(), Parma_Polyhedra_Library::Grid_Certificate::Grid_Certificate(), grid_generators(), is_bounded(), is_discrete(), map_space_dimensions(), max_min(), minimize(), minimized_grid_generators(), OK(), operator=(), quick_equivalence_test(), relation_with(), remove_higher_space_dimensions(), remove_space_dimensions(), select_wider_generators(), set_empty(), set_zero_dim_univ(), simplify_using_context_assign(), swap(), time_elapse_assign(), unconstrain(), update_congruences(), update_generators(), upper_bound_assign(), and wrap_assign().
The number of dimensions of the enclosing vector space.
Definition at line 1979 of file Grid.defs.hh.
Referenced by add_congruence(), add_congruence_no_check(), add_congruences(), add_constraint(), add_constraint_no_check(), add_constraints(), add_grid_generator(), add_recycled_congruences(), add_recycled_grid_generators(), add_space_dimensions(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_dimension(), affine_image(), affine_preimage(), ascii_dump(), bounded_affine_image(), bounded_affine_preimage(), bounds(), bounds_no_check(), concatenate_assign(), congruence_widening_assign(), congruences(), constrains(), construct(), contains(), contains_integer_point(), difference_assign(), drop_some_non_integer_points(), expand_space_dimension(), fold_space_dimensions(), frequency(), frequency_no_check(), generalized_affine_image(), generalized_affine_preimage(), generator_widening_assign(), Grid(), grid_generators(), intersection_assign(), is_bounded(), is_discrete(), is_disjoint_from(), is_empty(), is_included_in(), is_universe(), limited_congruence_extrapolation_assign(), limited_extrapolation_assign(), limited_generator_extrapolation_assign(), map_space_dimensions(), max_min(), minimize(), minimized_grid_generators(), OK(), operator=(), quick_equivalence_test(), refine_no_check(), refine_with_constraint(), refine_with_constraints(), relation_with(), remove_higher_space_dimensions(), remove_space_dimensions(), select_wider_congruences(), select_wider_generators(), set_empty(), set_zero_dim_univ(), simplify_using_context_assign(), space_dimension(), swap(), time_elapse_assign(), unconstrain(), update_congruences(), update_generators(), upper_bound_assign(), upper_bound_assign_if_exact(), widening_assign(), and wrap_assign().
Status Parma_Polyhedra_Library::Grid::status [private] |
The status flags to keep track of the grid's internal state.
Definition at line 1976 of file Grid.defs.hh.
Referenced by add_space_dimensions_and_embed(), add_space_dimensions_and_project(), ascii_dump(), clear_congruences_minimized(), clear_congruences_up_to_date(), clear_empty(), clear_generators_minimized(), clear_generators_up_to_date(), congruences_are_minimized(), congruences_are_up_to_date(), construct(), generators_are_minimized(), generators_are_up_to_date(), Grid(), marked_empty(), OK(), operator=(), set_congruences_minimized(), set_congruences_up_to_date(), set_empty(), set_generators_minimized(), set_generators_up_to_date(), set_zero_dim_univ(), and swap().
1.6.3