A bounded difference shape. More...
#include <BD_Shape.defs.hh>

Classes | |
| class | Status |
| A conjunctive assertion about a BD_Shape<T> object. More... | |
Public Types | |
| typedef T | coefficient_type_base |
| The numeric base type upon which bounded differences are built. | |
| typedef N | coefficient_type |
| The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS. | |
Public Member Functions | |
| 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. | |
Constructors, Assignment, Swap and Destructor | |
| BD_Shape (dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE) | |
| Builds a universe or empty BDS of the specified space dimension. | |
| BD_Shape (const BD_Shape &y, Complexity_Class complexity=ANY_COMPLEXITY) | |
| Ordinary copy constructor. | |
| template<typename U > | |
| BD_Shape (const BD_Shape< U > &y, Complexity_Class complexity=ANY_COMPLEXITY) | |
Builds a conservative, upward approximation of y. | |
| BD_Shape (const Constraint_System &cs) | |
Builds a BDS from the system of constraints cs. | |
| BD_Shape (const Congruence_System &cgs) | |
| Builds a BDS from a system of congruences. | |
| BD_Shape (const Generator_System &gs) | |
Builds a BDS from the system of generators gs. | |
| BD_Shape (const Polyhedron &ph, Complexity_Class complexity=ANY_COMPLEXITY) | |
Builds a BDS from the polyhedron ph. | |
| template<typename Interval > | |
| BD_Shape (const Box< Interval > &box, Complexity_Class complexity=ANY_COMPLEXITY) | |
| Builds a BDS out of a box. | |
| BD_Shape (const Grid &grid, Complexity_Class complexity=ANY_COMPLEXITY) | |
| Builds a BDS out of a grid. | |
| template<typename U > | |
| BD_Shape (const Octagonal_Shape< U > &os, Complexity_Class complexity=ANY_COMPLEXITY) | |
| Builds a BDS from an octagonal shape. | |
| BD_Shape & | operator= (const BD_Shape &y) |
The assignment operator (*this and y can be dimension-incompatible). | |
| void | swap (BD_Shape &y) |
Swaps *this with y (*this and y can be dimension-incompatible). | |
| ~BD_Shape () | |
| Destructor. | |
Member Functions that Do Not Modify the BD_Shape | |
| 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 constraints defining *this. | |
| Constraint_System | minimized_constraints () const |
Returns a minimized system of constraints defining *this. | |
| Congruence_System | congruences () const |
Returns a system of (equality) congruences satisfied by *this. | |
| Congruence_System | minimized_congruences () const |
Returns a minimal system of (equality) congruences satisfied by *this with the same affine dimension as *this. | |
| bool | bounds_from_above (const Linear_Expression &expr) const |
Returns true if and only if expr is bounded from above in *this. | |
| bool | bounds_from_below (const Linear_Expression &expr) const |
Returns true if and only if expr is bounded from below 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 &g) 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 &g) 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 there exist a unique value val such that *this saturates the equality expr = val. | |
| bool | contains (const BD_Shape &y) const |
Returns true if and only if *this contains y. | |
| bool | strictly_contains (const BD_Shape &y) const |
Returns true if and only if *this strictly contains y. | |
| bool | is_disjoint_from (const BD_Shape &y) const |
Returns true if and only if *this and y are disjoint. | |
| Poly_Con_Relation | relation_with (const Constraint &c) const |
Returns the relations holding between *this and the constraint c. | |
| Poly_Con_Relation | relation_with (const Congruence &cg) const |
Returns the relations holding between *this and the congruence cg. | |
| Poly_Gen_Relation | relation_with (const Generator &g) const |
Returns the relations holding between *this and the generator g. | |
| bool | is_empty () const |
Returns true if and only if *this is an empty BDS. | |
| bool | is_universe () const |
Returns true if and only if *this is a universe BDS. | |
| bool | is_discrete () const |
Returns true if and only if *this is discrete. | |
| bool | is_topologically_closed () const |
Returns true if and only if *this is a topologically closed subset of the vector space. | |
| bool | is_bounded () const |
Returns true if and only if *this is a bounded BDS. | |
| 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 | OK () const |
Returns true if and only if *this satisfies all its invariants. | |
Space-Dimension Preserving Member Functions that May Modify the BD_Shape | |
| void | add_constraint (const Constraint &c) |
Adds a copy of constraint c to the system of bounded differences defining *this. | |
| void | add_congruence (const Congruence &cg) |
Adds a copy of congruence cg to the system of congruences of *this. | |
| void | add_constraints (const Constraint_System &cs) |
Adds the constraints in cs to the system of bounded differences defining *this. | |
| void | add_recycled_constraints (Constraint_System &cs) |
Adds the constraints in cs to the system of constraints of *this. | |
| void | add_congruences (const Congruence_System &cgs) |
Adds to *this constraints equivalent to the congruences in cgs. | |
| void | add_recycled_congruences (Congruence_System &cgs) |
Adds to *this constraints equivalent to the congruences in cgs. | |
| void | refine_with_constraint (const Constraint &c) |
Uses a copy of constraint c to refine the system of bounded differences defining *this. | |
| void | refine_with_congruence (const Congruence &cg) |
Uses a copy of congruence cg to refine the system of bounded differences of *this. | |
| void | refine_with_constraints (const Constraint_System &cs) |
Uses a copy of the constraints in cs to refine the system of bounded differences defining *this. | |
| void | refine_with_congruences (const Congruence_System &cgs) |
Uses a copy of the congruences in cgs to refine the system of bounded differences defining *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 BD_Shape &y) |
Assigns to *this the intersection of *this and y. | |
| void | upper_bound_assign (const BD_Shape &y) |
Assigns to *this the smallest BDS containing the union of *this and y. | |
| bool | upper_bound_assign_if_exact (const BD_Shape &y) |
If the upper bound of *this and y is exact, it is assigned to *this and true is returned, otherwise false is returned. | |
| bool | integer_upper_bound_assign_if_exact (const BD_Shape &y) |
If the integer 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 BD_Shape &y) |
Assigns to *this the smallest BD shape containing the set difference of *this and y. | |
| bool | simplify_using_context_assign (const BD_Shape &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 into 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 into 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()) |
Assigns to *this the image of *this with respect to the affine relation , where is the relation symbol encoded by relsym. | |
| void | generalized_affine_image (const Linear_Expression &lhs, Relation_Symbol relsym, const Linear_Expression &rhs) |
Assigns to *this the image of *this with respect to the affine relation , where is the relation symbol encoded by relsym. | |
| void | generalized_affine_preimage (Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one()) |
Assigns to *this the preimage of *this with respect to the affine relation , where is the relation symbol encoded by relsym. | |
| void | generalized_affine_preimage (const Linear_Expression &lhs, Relation_Symbol relsym, const Linear_Expression &rhs) |
Assigns to *this the preimage of *this with respect to the affine relation , where is the relation symbol encoded by relsym. | |
| 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 BD_Shape &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 some 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 some points with non-integer coordinates for the space dimensions corresponding to vars. | |
| void | topological_closure_assign () |
Assigns to *this its topological closure. | |
| void | CC76_extrapolation_assign (const BD_Shape &y, unsigned *tp=0) |
Assigns to *this the result of computing the CC76-extrapolation between *this and y. | |
| template<typename Iterator > | |
| void | CC76_extrapolation_assign (const BD_Shape &y, Iterator first, Iterator last, unsigned *tp=0) |
Assigns to *this the result of computing the CC76-extrapolation between *this and y. | |
| void | BHMZ05_widening_assign (const BD_Shape &y, unsigned *tp=0) |
Assigns to *this the result of computing the BHMZ05-widening of *this and y. | |
| void | limited_BHMZ05_extrapolation_assign (const BD_Shape &y, const Constraint_System &cs, unsigned *tp=0) |
Improves the result of the BHMZ05-widening computation by also enforcing those constraints in cs that are satisfied by all the points of *this. | |
| void | CC76_narrowing_assign (const BD_Shape &y) |
Assigns to *this the result of restoring in y the constraints of *this that were lost by CC76-extrapolation applications. | |
| void | limited_CC76_extrapolation_assign (const BD_Shape &y, const Constraint_System &cs, unsigned *tp=0) |
Improves the result of the CC76-extrapolation computation by also enforcing those constraints in cs that are satisfied by all the points of *this. | |
| void | H79_widening_assign (const BD_Shape &y, unsigned *tp=0) |
Assigns to *this the result of computing the H79-widening between *this and y. | |
| void | widening_assign (const BD_Shape &y, unsigned *tp=0) |
| Same as H79_widening_assign(y, tp). | |
| void | limited_H79_extrapolation_assign (const BD_Shape &y, const Constraint_System &cs, unsigned *tp=0) |
Improves the result of the H79-widening computation by also enforcing those constraints in cs 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 dimensions and embeds the old BDS into the new space. | |
| void | add_space_dimensions_and_project (dimension_type m) |
Adds m new dimensions to the BDS and does not embed it in the new vector space. | |
| void | concatenate_assign (const BD_Shape &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. | |
| void | remove_higher_space_dimensions (dimension_type new_dimension) |
Removes the higher dimensions 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. | |
Static Public Member Functions | |
| static dimension_type | max_space_dimension () |
| Returns the maximum space dimension that a BDS can handle. | |
| static bool | can_recycle_constraint_systems () |
Returns false indicating that this domain cannot recycle constraints. | |
| static bool | can_recycle_congruence_systems () |
Returns false indicating that this domain cannot recycle congruences. | |
Private Types | |
| typedef Checked_Number< T, Debug_WRD_Extended_Number_Policy > | N |
| The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS. | |
Private Member Functions | |
| bool | marked_zero_dim_univ () const |
Returns true if the BDS is the zero-dimensional universe. | |
| bool | marked_empty () const |
Returns true if the BDS is known to be empty. | |
| bool | marked_shortest_path_closed () const |
Returns true if the system of bounded differences is known to be shortest-path closed. | |
| bool | marked_shortest_path_reduced () const |
Returns true if the system of bounded differences is known to be shortest-path reduced. | |
| void | set_empty () |
Turns *this into an empty BDS. | |
| void | set_zero_dim_univ () |
Turns *this into an zero-dimensional universe BDS. | |
| void | set_shortest_path_closed () |
Marks *this as shortest-path closed. | |
| void | set_shortest_path_reduced () |
Marks *this as shortest-path closed. | |
| void | reset_shortest_path_closed () |
Marks *this as possibly not shortest-path closed. | |
| void | reset_shortest_path_reduced () |
Marks *this as possibly not shortest-path reduced. | |
| void | shortest_path_closure_assign () const |
Assigns to this->dbm its shortest-path closure. | |
| void | shortest_path_reduction_assign () const |
Assigns to this->dbm its shortest-path closure and records into this->redundancy_dbm which of the entries in this->dbm are redundant. | |
| bool | is_shortest_path_reduced () const |
Returns true if and only if this->dbm is shortest-path closed and this->redundancy_dbm correctly flags the redundant entries in this->dbm. | |
| void | incremental_shortest_path_closure_assign (Variable var) const |
Incrementally computes shortest-path closure, assuming that only constraints affecting variable var need to be considered. | |
| bool | bounds (const Linear_Expression &expr, bool from_above) const |
Checks if and how expr is bounded in *this. | |
| bool | max_min (const Linear_Expression &expr, bool maximize, Coefficient &ext_n, Coefficient &ext_d, bool &included, Generator &g) const |
Maximizes or minimizes expr subject to *this. | |
| bool | max_min (const Linear_Expression &expr, bool maximize, Coefficient &ext_n, Coefficient &ext_d, bool &included) const |
Maximizes or minimizes expr subject to *this. | |
| bool | BFT00_upper_bound_assign_if_exact (const BD_Shape &y) |
If the upper bound of *this and y is exact it is assigned to *this and true is returned, otherwise false is returned. | |
| template<bool integer_upper_bound> | |
| bool | BHZ09_upper_bound_assign_if_exact (const BD_Shape &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 | refine_no_check (const Constraint &c) |
Uses the constraint c to refine *this. | |
| void | refine_no_check (const Congruence &cg) |
Uses the congruence cg to refine *this. | |
| void | add_dbm_constraint (dimension_type i, dimension_type j, const N &k) |
Adds the constraint dbm[i][j] <= k. | |
| void | add_dbm_constraint (dimension_type i, dimension_type j, Coefficient_traits::const_reference num, Coefficient_traits::const_reference den) |
Adds the constraint dbm[i][j] <= num/den. | |
| void | refine (Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one()) |
Adds to the BDS the constraint . | |
| void | forget_all_dbm_constraints (dimension_type v) |
Removes all the constraints on row/column v. | |
| void | forget_binary_dbm_constraints (dimension_type v) |
Removes all binary constraints on row/column v. | |
| void | deduce_v_minus_u_bounds (dimension_type v, dimension_type last_v, const Linear_Expression &sc_expr, Coefficient_traits::const_reference sc_den, const N &ub_v) |
| An helper function for the computation of affine relations. | |
| void | deduce_u_minus_v_bounds (dimension_type v, dimension_type last_v, const Linear_Expression &sc_expr, Coefficient_traits::const_reference sc_den, const N &minus_lb_v) |
| An helper function for the computation of affine relations. | |
| void | get_limiting_shape (const Constraint_System &cs, BD_Shape &limiting_shape) const |
Adds to limiting_shape the bounded differences in cs that are satisfied by *this. | |
| void | compute_predecessors (std::vector< dimension_type > &predecessor) const |
| Compute the (zero-equivalence classes) predecessor relation. | |
| void | compute_leaders (std::vector< dimension_type > &leaders) const |
| Compute the leaders of zero-equivalence classes. | |
| void | drop_some_non_integer_points_helper (N &elem) |
Private Attributes | |
| DB_Matrix< N > | dbm |
| The matrix representing the system of bounded differences. | |
| Status | status |
| The status flags to keep track of the internal state. | |
| Bit_Matrix | redundancy_dbm |
| A matrix indicating which constraints are redundant. | |
Friends | |
| class | Parma_Polyhedra_Library::BD_Shape |
| class | Parma_Polyhedra_Library::Box |
| bool | operator== (const BD_Shape< T > &x, const BD_Shape< T > &y) |
Returns true if and only if x and y are the same BDS. | |
| template<typename Temp , typename To , typename U > | |
| bool | Parma_Polyhedra_Library::rectilinear_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< U > &x, const BD_Shape< U > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2) |
| template<typename Temp , typename To , typename U > | |
| bool | Parma_Polyhedra_Library::euclidean_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< U > &x, const BD_Shape< U > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2) |
| template<typename Temp , typename To , typename U > | |
| bool | Parma_Polyhedra_Library::l_infinity_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< U > &x, const BD_Shape< U > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2) |
| std::ostream & | Parma_Polyhedra_Library::IO_Operators::operator<< (std::ostream &s, const BD_Shape< T > &c) |
Related Functions | |
(Note that these are not member functions.) | |
| template<typename T > | |
| std::ostream & | operator<< (std::ostream &s, const BD_Shape< T > &bds) |
| Output operator. | |
| template<typename T > | |
| bool | operator!= (const BD_Shape< T > &x, const BD_Shape< T > &y) |
Returns true if and only if x and y aren't the same BDS. | |
| template<typename To , typename T > | |
| bool | rectilinear_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, Rounding_Dir dir) |
Computes the rectilinear (or Manhattan) distance between x and y. | |
| template<typename Temp , typename To , typename T > | |
| bool | rectilinear_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2) |
Computes the rectilinear (or Manhattan) distance between x and y. | |
| template<typename To , typename T > | |
| bool | euclidean_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, Rounding_Dir dir) |
Computes the euclidean distance between x and y. | |
| template<typename Temp , typename To , typename T > | |
| bool | euclidean_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2) |
Computes the euclidean distance between x and y. | |
| template<typename To , typename T > | |
| bool | l_infinity_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, Rounding_Dir dir) |
Computes the distance between x and y. | |
| template<typename Temp , typename To , typename T > | |
| bool | l_infinity_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2) |
Computes the distance between x and y. | |
| bool | extract_bounded_difference (const Constraint &c, dimension_type c_space_dim, dimension_type &c_num_vars, dimension_type &c_first_var, dimension_type &c_second_var, Coefficient &c_coeff) |
Decodes the constraint c as a bounded difference. | |
| void | compute_leader_indices (const std::vector< dimension_type > &predecessor, std::vector< dimension_type > &indices) |
| Extracts leader indices from the predecessor relation. | |
| template<typename T > | |
| void | swap (Parma_Polyhedra_Library::BD_Shape< T > &x, Parma_Polyhedra_Library::BD_Shape< T > &y) |
Specializes std::swap. | |
Exception Throwers | |
|
| |
| void | throw_dimension_incompatible (const char *method, const BD_Shape &x) const |
| void | throw_dimension_incompatible (const char *method, dimension_type required_dim) const |
| void | throw_dimension_incompatible (const char *method, const Constraint &c) const |
| void | throw_dimension_incompatible (const char *method, const Congruence &cg) const |
| void | throw_dimension_incompatible (const char *method, const Generator &g) const |
| void | throw_dimension_incompatible (const char *method, const char *name_row, const Linear_Expression &y) const |
| static void | throw_expression_too_complex (const char *method, const Linear_Expression &e) |
| static void | throw_generic (const char *method, const char *reason) |
A bounded difference shape.
The class template BD_Shape<T> allows for the efficient representation of a restricted kind of topologically closed convex polyhedra called bounded difference shapes (BDSs, for short). The name comes from the fact that the closed affine half-spaces that characterize the polyhedron can be expressed by constraints of the form
or
, where the inhomogeneous term
is a rational number.
Based on the class template type parameter T, a family of extended numbers is built and used to approximate the inhomogeneous term of bounded differences. These extended numbers provide a representation for the value
, as well as rounding-aware implementations for several arithmetic functions. The value of the type parameter T may be one of the following:
int32_t or int64_t);float or double);mpz_class or mpq_class).The user interface for BDSs is meant to be as similar as possible to the one developed for the polyhedron class C_Polyhedron.
The domain of BD shapes optimally supports:
Depending on the method, using a constraint or congruence that is not optimally supported by the domain will either raise an exception or result in a (possibly non-optimal) upward approximation.
A constraint is a bounded difference if it has the form
where
and
,
,
are integer coefficients such that
, or
, or
. The user is warned that the above bounded difference Constraint object will be mapped into a correct and optimal approximation that, depending on the expressive power of the chosen template argument T, may loose some precision. Also note that strict constraints are not bounded differences.
For instance, a Constraint object encoding
will be approximated by:
, if T is a (bounded or unbounded) integer type;
, if T is the unbounded rational type mpq_class;
, where
, if T is a floating point type (having no exact representation for
).On the other hand, depending from the context, a Constraint object encoding
will be either upward approximated (e.g., by safely ignoring it) or it will cause an exception.
In the following examples it is assumed that the type argument T is one of the possible instances listed above and that variables x, y and z are defined (where they are used) as follows:
Variable x(0);
Variable y(1);
Variable z(2);
, given as a system of constraints: Constraint_System cs;
cs.insert(x >= 0);
cs.insert(x <= 1);
cs.insert(y >= 0);
cs.insert(y <= 1);
cs.insert(z >= 0);
cs.insert(z <= 1);
BD_Shape<T> bd(cs);
Constraint_System cs;
cs.insert(x >= 0);
cs.insert(x <= 1);
cs.insert(y >= 0);
cs.insert(y <= 1);
cs.insert(z >= 0);
cs.insert(z <= 1);
cs.insert(x + y <= 0); // 7
cs.insert(x - z + x >= 0); // 8
cs.insert(3*z - y <= 1); // 9
BD_Shape<T> bd(cs);
Definition at line 403 of file BD_Shape.defs.hh.
| typedef N Parma_Polyhedra_Library::BD_Shape< T >::coefficient_type |
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS.
Definition at line 423 of file BD_Shape.defs.hh.
| typedef T Parma_Polyhedra_Library::BD_Shape< T >::coefficient_type_base |
The numeric base type upon which bounded differences are built.
Definition at line 417 of file BD_Shape.defs.hh.
typedef Checked_Number<T, Debug_WRD_Extended_Number_Policy> Parma_Polyhedra_Library::BD_Shape< T >::N [private] |
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS.
Definition at line 410 of file BD_Shape.defs.hh.
| Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape | ( | dimension_type | num_dimensions = 0, |
|
| Degenerate_Element | kind = UNIVERSE | |||
| ) | [inline, explicit] |
Builds a universe or empty BDS of the specified space dimension.
| num_dimensions | The number of dimensions of the vector space enclosing the BDS; | |
| kind | Specifies whether the universe or the empty BDS has to be built. |
Definition at line 115 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), and Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed().
00117 : dbm(num_dimensions + 1), status(), redundancy_dbm() { 00118 if (kind == EMPTY) 00119 set_empty(); 00120 else { 00121 if (num_dimensions > 0) 00122 // A (non zero-dim) universe BDS is closed. 00123 set_shortest_path_closed(); 00124 } 00125 PPL_ASSERT(OK()); 00126 }
| Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape | ( | const BD_Shape< T > & | y, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) | [inline] |
Ordinary copy constructor.
The complexity argument is ignored.
Definition at line 130 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), and Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm.
00131 : dbm(y.dbm), status(y.status), redundancy_dbm() { 00132 if (y.marked_shortest_path_reduced()) 00133 redundancy_dbm = y.redundancy_dbm; 00134 }
| Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape | ( | const BD_Shape< U > & | y, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) | [inline, explicit] |
Builds a conservative, upward approximation of y.
The complexity argument is ignored.
Definition at line 139 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_zero_dim_univ(), Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), and Parma_Polyhedra_Library::BD_Shape< T >::set_zero_dim_univ().
00142 : dbm((y.shortest_path_closure_assign(), y.dbm)), 00143 status(), 00144 redundancy_dbm() { 00145 // TODO: handle flags properly, possibly taking special cases into account. 00146 if (y.marked_empty()) 00147 set_empty(); 00148 else if (y.marked_zero_dim_univ()) 00149 set_zero_dim_univ(); 00150 }
| Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape | ( | const Constraint_System & | cs | ) | [inline, explicit] |
Builds a BDS from the system of constraints cs.
The BDS inherits the space dimension of cs.
| cs | A system of BD constraints. |
| std::invalid_argument | Thrown if cs contains a constraint which is not optimally supported by the BD shape domain. |
Definition at line 269 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::add_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed(), and Parma_Polyhedra_Library::Constraint_System::space_dimension().
00270 : dbm(cs.space_dimension() + 1), status(), redundancy_dbm() { 00271 if (cs.space_dimension() > 0) 00272 // A (non zero-dim) universe BDS is shortest-path closed. 00273 set_shortest_path_closed(); 00274 add_constraints(cs); 00275 }
| Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape | ( | const Congruence_System & | cgs | ) | [inline, explicit] |
Builds a BDS from a system of congruences.
The BDS inherits the space dimension of cgs
| cgs | A system of congruences. |
| std::invalid_argument | Thrown if cgs contains congruences which are not optimally supported by the BD shape domain. |
Definition at line 48 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::add_congruences().
00049 : dbm(cgs.space_dimension() + 1), 00050 status(), 00051 redundancy_dbm() { 00052 add_congruences(cgs); 00053 }
| Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape | ( | const Generator_System & | gs | ) | [inline, explicit] |
Builds a BDS from the system of generators gs.
Builds the smallest BDS containing the polyhedron defined by gs. The BDS inherits the space dimension of gs.
| std::invalid_argument | Thrown if the system of generators is not empty but has no points. |
Definition at line 56 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Generator_System::begin(), Parma_Polyhedra_Library::Generator::CLOSURE_POINT, Parma_Polyhedra_Library::Generator::coefficient(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::Generator::divisor(), Parma_Polyhedra_Library::Generator_System::end(), Parma_Polyhedra_Library::Generator::LINE, Parma_Polyhedra_Library::max_assign(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::Generator::POINT, Parma_Polyhedra_Library::Generator::RAY, Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_generic(), and Parma_Polyhedra_Library::Generator::type().
00057 : dbm(gs.space_dimension() + 1), status(), redundancy_dbm() { 00058 const Generator_System::const_iterator gs_begin = gs.begin(); 00059 const Generator_System::const_iterator gs_end = gs.end(); 00060 if (gs_begin == gs_end) { 00061 // An empty generator system defines the empty BD shape. 00062 set_empty(); 00063 return; 00064 } 00065 00066 const dimension_type space_dim = space_dimension(); 00067 DB_Row<N>& dbm_0 = dbm[0]; 00068 PPL_DIRTY_TEMP(N, tmp); 00069 00070 bool dbm_initialized = false; 00071 bool point_seen = false; 00072 // Going through all the points and closure points. 00073 for (Generator_System::const_iterator gs_i = gs_begin; 00074 gs_i != gs_end; ++gs_i) { 00075 const Generator& g = *gs_i; 00076 switch (g.type()) { 00077 case Generator::POINT: 00078 point_seen = true; 00079 // Intentionally fall through. 00080 case Generator::CLOSURE_POINT: 00081 if (!dbm_initialized) { 00082 // When handling the first (closure) point, we initialize the DBM. 00083 dbm_initialized = true; 00084 const Coefficient& d = g.divisor(); 00085 for (dimension_type i = space_dim; i > 0; --i) { 00086 const Coefficient& g_i = g.coefficient(Variable(i-1)); 00087 DB_Row<N>& dbm_i = dbm[i]; 00088 for (dimension_type j = space_dim; j > 0; --j) 00089 if (i != j) 00090 div_round_up(dbm_i[j], g.coefficient(Variable(j-1)) - g_i, d); 00091 div_round_up(dbm_i[0], -g_i, d); 00092 } 00093 for (dimension_type j = space_dim; j > 0; --j) 00094 div_round_up(dbm_0[j], g.coefficient(Variable(j-1)), d); 00095 // Note: no need to initialize the first element of the main diagonal. 00096 } 00097 else { 00098 // This is not the first point: the DBM already contains 00099 // valid values and we must compute maxima. 00100 const Coefficient& d = g.divisor(); 00101 for (dimension_type i = space_dim; i > 0; --i) { 00102 const Coefficient& g_i = g.coefficient(Variable(i-1)); 00103 DB_Row<N>& dbm_i = dbm[i]; 00104 // The loop correctly handles the case when i == j. 00105 for (dimension_type j = space_dim; j > 0; --j) { 00106 div_round_up(tmp, g.coefficient(Variable(j-1)) - g_i, d); 00107 max_assign(dbm_i[j], tmp); 00108 } 00109 div_round_up(tmp, -g_i, d); 00110 max_assign(dbm_i[0], tmp); 00111 } 00112 for (dimension_type j = space_dim; j > 0; --j) { 00113 div_round_up(tmp, g.coefficient(Variable(j-1)), d); 00114 max_assign(dbm_0[j], tmp); 00115 } 00116 } 00117 break; 00118 default: 00119 // Lines and rays temporarily ignored. 00120 break; 00121 } 00122 } 00123 00124 if (!point_seen) 00125 // The generator system is not empty, but contains no points. 00126 throw_generic("BD_Shape(gs)", 00127 "the non-empty generator system gs contains no points."); 00128 00129 // Going through all the lines and rays. 00130 for (Generator_System::const_iterator gs_i = gs_begin; 00131 gs_i != gs_end; ++gs_i) { 00132 const Generator& g = *gs_i; 00133 switch (g.type()) { 00134 case Generator::LINE: 00135 for (dimension_type i = space_dim; i > 0; --i) { 00136 const Coefficient& g_i = g.coefficient(Variable(i-1)); 00137 DB_Row<N>& dbm_i = dbm[i]; 00138 // The loop correctly handles the case when i == j. 00139 for (dimension_type j = space_dim; j > 0; --j) 00140 if (g_i != g.coefficient(Variable(j-1))) 00141 assign_r(dbm_i[j], PLUS_INFINITY, ROUND_NOT_NEEDED); 00142 if (g_i != 0) 00143 assign_r(dbm_i[0], PLUS_INFINITY, ROUND_NOT_NEEDED); 00144 } 00145 for (dimension_type j = space_dim; j > 0; --j) 00146 if (g.coefficient(Variable(j-1)) != 0) 00147 assign_r(dbm_0[j], PLUS_INFINITY, ROUND_NOT_NEEDED); 00148 break; 00149 case Generator::RAY: 00150 for (dimension_type i = space_dim; i > 0; --i) { 00151 const Coefficient& g_i = g.coefficient(Variable(i-1)); 00152 DB_Row<N>& dbm_i = dbm[i]; 00153 // The loop correctly handles the case when i == j. 00154 for (dimension_type j = space_dim; j > 0; --j) 00155 if (g_i < g.coefficient(Variable(j-1))) 00156 assign_r(dbm_i[j], PLUS_INFINITY, ROUND_NOT_NEEDED); 00157 if (g_i < 0) 00158 assign_r(dbm_i[0], PLUS_INFINITY, ROUND_NOT_NEEDED); 00159 } 00160 for (dimension_type j = space_dim; j > 0; --j) 00161 if (g.coefficient(Variable(j-1)) > 0) 00162 assign_r(dbm_0[j], PLUS_INFINITY, ROUND_NOT_NEEDED); 00163 break; 00164 default: 00165 // Points and closure points already dealt with. 00166 break; 00167 } 00168 } 00169 set_shortest_path_closed(); 00170 PPL_ASSERT(OK()); 00171 }
| Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape | ( | const Polyhedron & | ph, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) | [inline, explicit] |
Builds a BDS from the polyhedron ph.
Builds a BDS containing ph using algorithms whose complexity does not exceed the one specified by complexity. If complexity is ANY_COMPLEXITY, then the BDS built is the smallest one containing ph.
Definition at line 174 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::MIP_Problem::add_constraint(), Parma_Polyhedra_Library::MIP_Problem::add_constraints(), Parma_Polyhedra_Library::ANY_COMPLEXITY, Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Polyhedron::con_sys, Parma_Polyhedra_Library::Polyhedron::constraints(), Parma_Polyhedra_Library::Polyhedron::constraints_are_minimized(), Parma_Polyhedra_Library::Polyhedron::constraints_are_up_to_date(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::MIP_Problem::evaluate_objective_function(), Parma_Polyhedra_Library::Polyhedron::generators(), Parma_Polyhedra_Library::Polyhedron::generators_are_up_to_date(), Parma_Polyhedra_Library::Polyhedron::has_pending_constraints(), Parma_Polyhedra_Library::Polyhedron::has_something_pending(), Parma_Polyhedra_Library::Constraint_System::has_strict_inequalities(), Parma_Polyhedra_Library::MIP_Problem::is_satisfiable(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Polyhedron::is_universe(), Parma_Polyhedra_Library::Polyhedron::marked_empty(), Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, Parma_Polyhedra_Library::MIP_Problem::optimizing_point(), Parma_Polyhedra_Library::POLYNOMIAL_COMPLEXITY, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::refine_with_constraints(), Parma_Polyhedra_Library::MIP_Problem::set_objective_function(), Parma_Polyhedra_Library::MIP_Problem::set_optimization_mode(), Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed(), Parma_Polyhedra_Library::SIMPLEX_COMPLEXITY, Parma_Polyhedra_Library::MIP_Problem::solve(), Parma_Polyhedra_Library::Polyhedron::space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.
00175 : dbm(), status(), redundancy_dbm() { 00176 const dimension_type num_dimensions = ph.space_dimension(); 00177 00178 if (ph.marked_empty()) { 00179 *this = BD_Shape<T>(num_dimensions, EMPTY); 00180 return; 00181 } 00182 00183 if (num_dimensions == 0) { 00184 *this = BD_Shape<T>(num_dimensions, UNIVERSE); 00185 return; 00186 } 00187 00188 // Build from generators when we do not care about complexity 00189 // or when the process has polynomial complexity. 00190 if (complexity == ANY_COMPLEXITY 00191 || (!ph.has_pending_constraints() && ph.generators_are_up_to_date())) { 00192 *this = BD_Shape<T>(ph.generators()); 00193 return; 00194 } 00195 00196 // We cannot afford exponential complexity, we do not have a complete set 00197 // of generators for the polyhedron, and the polyhedron is not trivially 00198 // empty or zero-dimensional. Constraints, however, are up to date. 00199 PPL_ASSERT(ph.constraints_are_up_to_date()); 00200 00201 if (!ph.has_something_pending() && ph.constraints_are_minimized()) { 00202 // If the constraint system of the polyhedron is minimized, 00203 // the test `is_universe()' has polynomial complexity. 00204 if (ph.is_universe()) { 00205 *this = BD_Shape<T>(num_dimensions, UNIVERSE); 00206 return; 00207 } 00208 } 00209 00210 // See if there is at least one inconsistent constraint in `ph.con_sys'. 00211 for (Constraint_System::const_iterator i = ph.con_sys.begin(), 00212 cs_end = ph.con_sys.end(); i != cs_end; ++i) 00213 if (i->is_inconsistent()) { 00214 *this = BD_Shape<T>(num_dimensions, EMPTY); 00215 return; 00216 } 00217 00218 // If `complexity' allows it, use simplex to derive the exact (modulo 00219 // the fact that our BDSs are topologically closed) variable bounds. 00220 if (complexity == SIMPLEX_COMPLEXITY) { 00221 MIP_Problem lp(num_dimensions); 00222 lp.set_optimization_mode(MAXIMIZATION); 00223 00224 const Constraint_System& ph_cs = ph.constraints(); 00225 if (!ph_cs.has_strict_inequalities()) 00226 lp.add_constraints(ph_cs); 00227 else 00228 // Adding to `lp' a topologically closed version of `ph_cs'. 00229 for (Constraint_System::const_iterator i = ph_cs.begin(), 00230 ph_cs_end = ph_cs.end(); i != ph_cs_end; ++i) { 00231 const Constraint& c = *i; 00232 if (c.is_strict_inequality()) 00233 lp.add_constraint(Linear_Expression(c) >= 0); 00234 else 00235 lp.add_constraint(c); 00236 } 00237 00238 // Check for unsatisfiability. 00239 if (!lp.is_satisfiable()) { 00240 *this = BD_Shape<T>(num_dimensions, EMPTY); 00241 return; 00242 } 00243 00244 // Start with a universe BDS that will be refined by the simplex. 00245 *this = BD_Shape<T>(num_dimensions, UNIVERSE); 00246 // Get all the upper bounds. 00247 Generator g(point()); 00248 PPL_DIRTY_TEMP_COEFFICIENT(num); 00249 PPL_DIRTY_TEMP_COEFFICIENT(den); 00250 for (dimension_type i = 1; i <= num_dimensions; ++i) { 00251 Variable x(i-1); 00252 // Evaluate optimal upper bound for `x <= ub'. 00253 lp.set_objective_function(x); 00254 if (lp.solve() == OPTIMIZED_MIP_PROBLEM) { 00255 g = lp.optimizing_point(); 00256 lp.evaluate_objective_function(g, num, den); 00257 div_round_up(dbm[0][i], num, den); 00258 } 00259 // Evaluate optimal upper bound for `x - y <= ub'. 00260 for (dimension_type j = 1; j <= num_dimensions; ++j) { 00261 if (i == j) 00262 continue; 00263 Variable y(j-1); 00264 lp.set_objective_function(x - y); 00265 if (lp.solve() == OPTIMIZED_MIP_PROBLEM) { 00266 g = lp.optimizing_point(); 00267 lp.evaluate_objective_function(g, num, den); 00268 div_round_up(dbm[j][i], num, den); 00269 } 00270 } 00271 // Evaluate optimal upper bound for `-x <= ub'. 00272 lp.set_objective_function(-x); 00273 if (lp.solve() == OPTIMIZED_MIP_PROBLEM) { 00274 g = lp.optimizing_point(); 00275 lp.evaluate_objective_function(g, num, den); 00276 div_round_up(dbm[i][0], num, den); 00277 } 00278 } 00279 set_shortest_path_closed(); 00280 PPL_ASSERT(OK()); 00281 return; 00282 } 00283 00284 // Extract easy-to-find bounds from constraints. 00285 PPL_ASSERT(complexity == POLYNOMIAL_COMPLEXITY); 00286 *this = BD_Shape<T>(num_dimensions, UNIVERSE); 00287 refine_with_constraints(ph.constraints()); 00288 }
| Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape | ( | const Box< Interval > & | box, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) | [inline, explicit] |
Builds a BDS out of a box.
The BDS inherits the space dimension of the box. The built BDS is the most precise BDS that includes the box.
| box | The box representing the BDS 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 280 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::constraints(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed(), and Parma_Polyhedra_Library::Box< ITV >::space_dimension().
00282 : dbm(box.space_dimension() + 1), status(), redundancy_dbm() { 00283 // Check for emptyness for maximum precision. 00284 if (box.is_empty()) 00285 set_empty(); 00286 else if (box.space_dimension() > 0) { 00287 // A (non zero-dim) universe BDS is shortest-path closed. 00288 set_shortest_path_closed(); 00289 refine_with_constraints(box.constraints()); 00290 } 00291 }
| Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape | ( | const Grid & | grid, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) | [inline, explicit] |
Builds a BDS out of a grid.
The BDS inherits the space dimension of the grid. The built BDS is the most precise BDS that includes the grid.
| grid | The grid used to build the BDS. | |
| complexity | This argument is ignored as the algorithm used has polynomial complexity. |
| std::length_error | Thrown if the space dimension of grid exceeds the maximum allowed space dimension. |
Definition at line 295 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::Grid::minimized_congruences(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_congruences(), Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed(), and Parma_Polyhedra_Library::Grid::space_dimension().
00297 : dbm(grid.space_dimension() + 1), status(), redundancy_dbm() { 00298 if (grid.space_dimension() > 0) 00299 // A (non zero-dim) universe BDS is shortest-path closed. 00300 set_shortest_path_closed(); 00301 // Taking minimized congruences ensures maximum precision. 00302 refine_with_congruences(grid.minimized_congruences()); 00303 }
| Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape | ( | const Octagonal_Shape< U > & | os, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) | [inline, explicit] |
Builds a BDS from an octagonal shape.
The BDS inherits the space dimension of the octagonal shape. The built BDS is the most precise BDS that includes the octagonal shape.
| os | The octagonal shape used to build the BDS. | |
| 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 308 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension().
00310 : dbm(os.space_dimension() + 1), status(), redundancy_dbm() { 00311 // Check for emptyness for maximum precision. 00312 if (os.is_empty()) 00313 set_empty(); 00314 else if (os.space_dimension() > 0) { 00315 // A (non zero-dim) universe BDS is shortest-path closed. 00316 set_shortest_path_closed(); 00317 refine_with_constraints(os.constraints()); 00318 // After refining, shortest-path closure is possibly lost 00319 // (even when `os' was strongly closed: recall that U 00320 // is possibly different from T). 00321 } 00322 }
| Parma_Polyhedra_Library::BD_Shape< T >::~BD_Shape | ( | ) | [inline] |
| void Parma_Polyhedra_Library::BD_Shape< T >::add_congruence | ( | const Congruence & | cg | ) | [inline] |
Adds a copy of congruence cg to the system of congruences of *this.
| cg | The congruence to be added. |
| std::invalid_argument | Thrown if *this and congruence cg are dimension-incompatible, or cg is not optimally supported by the BD shape domain. |
Definition at line 447 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), Parma_Polyhedra_Library::Congruence::is_proper_congruence(), Parma_Polyhedra_Library::Congruence::is_tautological(), Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Congruence::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_congruences().
00447 { 00448 const dimension_type cg_space_dim = cg.space_dimension(); 00449 // Dimension-compatibility check: 00450 // the dimension of `cg' can not be greater than space_dim. 00451 if (space_dimension() < cg_space_dim) 00452 throw_dimension_incompatible("add_congruence(cg)", cg); 00453 00454 // Handle the case of proper congruences first. 00455 if (cg.is_proper_congruence()) { 00456 if (cg.is_tautological()) 00457 return; 00458 if (cg.is_inconsistent()) { 00459 set_empty(); 00460 return; 00461 } 00462 // Non-trivial and proper congruences are not allowed. 00463 throw_generic("add_congruence(cg)", 00464 "cg is a non-trivial, proper congruence"); 00465 } 00466 00467 PPL_ASSERT(cg.is_equality()); 00468 Constraint c(cg); 00469 add_constraint(c); 00470 }
| void Parma_Polyhedra_Library::BD_Shape< T >::add_congruences | ( | const Congruence_System & | cgs | ) | [inline] |
Adds to *this constraints equivalent to the congruences in cgs.
| cgs | Contains the congruences that will be added to the system of constraints of *this. |
| std::invalid_argument | Thrown if *this and cgs are dimension-incompatible, or cgs contains a congruence which is not optimally supported by the BD shape domain. |
Definition at line 174 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::add_congruence(), Parma_Polyhedra_Library::Congruence_System::begin(), and Parma_Polyhedra_Library::Congruence_System::end().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_recycled_congruences(), and Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape().
00174 { 00175 for (Congruence_System::const_iterator i = cgs.begin(), 00176 cgs_end = cgs.end(); i != cgs_end; ++i) 00177 add_congruence(*i); 00178 }
| void Parma_Polyhedra_Library::BD_Shape< T >::add_constraint | ( | const Constraint & | c | ) | [inline] |
Adds a copy of constraint c to the system of bounded differences defining *this.
| c | The constraint to be added. |
| std::invalid_argument | Thrown if *this and constraint c are dimension-incompatible, or c is not optimally supported by the BD shape domain. |
Definition at line 374 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::BD_Shape< T >::extract_bounded_difference(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Constraint::is_inconsistent(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Constraint::is_tautological(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_congruence(), Parma_Polyhedra_Library::BD_Shape< T >::add_constraints(), and Parma_Polyhedra_Library::BD_Shape< T >::difference_assign().
00374 { 00375 const dimension_type c_space_dim = c.space_dimension(); 00376 // Dimension-compatibility check. 00377 if (c_space_dim > space_dimension()) 00378 throw_dimension_incompatible("add_constraint(c)", c); 00379 00380 // Get rid of strict inequalities. 00381 if (c.is_strict_inequality()) { 00382 if (c.is_inconsistent()) { 00383 set_empty(); 00384 return; 00385 } 00386 if (c.is_tautological()) 00387 return; 00388 // Nontrivial strict inequalities are not allowed. 00389 throw_generic("add_constraint(c)", "strict inequalities are not allowed"); 00390 } 00391 00392 dimension_type num_vars = 0; 00393 dimension_type i = 0; 00394 dimension_type j = 0; 00395 PPL_DIRTY_TEMP_COEFFICIENT(coeff); 00396 // Constraints that are not bounded differences are not allowed. 00397 if (!extract_bounded_difference(c, c_space_dim, num_vars, i, j, coeff)) 00398 throw_generic("add_constraint(c)", 00399 "c is not a bounded difference constraint"); 00400 00401 const Coefficient& inhomo = c.inhomogeneous_term(); 00402 if (num_vars == 0) { 00403 // Dealing with a trivial constraint (not a strict inequality). 00404 if (inhomo < 0 00405 || (inhomo != 0 && c.is_equality())) 00406 set_empty(); 00407 return; 00408 } 00409 00410 // Select the cell to be modified for the "<=" part of the constraint, 00411 // and set `coeff' to the absolute value of itself. 00412 const bool negative = (coeff < 0); 00413 N& x = negative ? dbm[i][j] : dbm[j][i]; 00414 N& y = negative ? dbm[j][i] : dbm[i][j]; 00415 if (negative) 00416 neg_assign(coeff); 00417 00418 bool changed = false; 00419 // Compute the bound for `x', rounding towards plus infinity. 00420 PPL_DIRTY_TEMP(N, d); 00421 div_round_up(d, inhomo, coeff); 00422 if (x > d) { 00423 x = d; 00424 changed = true; 00425 } 00426 00427 if (c.is_equality()) { 00428 // Also compute the bound for `y', rounding towards plus infinity. 00429 PPL_DIRTY_TEMP_COEFFICIENT(minus_c_term); 00430 neg_assign(minus_c_term, inhomo); 00431 div_round_up(d, minus_c_term, coeff); 00432 if (y > d) { 00433 y = d; 00434 changed = true; 00435 } 00436 } 00437 00438 // In general, adding a constraint does not preserve the shortest-path 00439 // closure or reduction of the bounded difference shape. 00440 if (changed && marked_shortest_path_closed()) 00441 reset_shortest_path_closed(); 00442 PPL_ASSERT(OK()); 00443 }
| void Parma_Polyhedra_Library::BD_Shape< T >::add_constraints | ( | const Constraint_System & | cs | ) | [inline] |
Adds the constraints in cs to the system of bounded differences defining *this.
| cs | The constraints that will be added. |
| std::invalid_argument | Thrown if *this and cs are dimension-incompatible, or cs contains a constraint which is not optimally supported by the BD shape domain. |
Definition at line 160 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Constraint_System::begin(), and Parma_Polyhedra_Library::Constraint_System::end().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_recycled_constraints(), and Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape().
00160 { 00161 for (Constraint_System::const_iterator i = cs.begin(), 00162 cs_end = cs.end(); i != cs_end; ++i) 00163 add_constraint(*i); 00164 }
| void Parma_Polyhedra_Library::BD_Shape< T >::add_dbm_constraint | ( | dimension_type | i, | |
| dimension_type | j, | |||
| Coefficient_traits::const_reference | num, | |||
| Coefficient_traits::const_reference | den | |||
| ) | [inline, private] |
Adds the constraint dbm[i][j] <= num/den.
Definition at line 672 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::add_dbm_constraint(), Parma_Polyhedra_Library::div_round_up(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().
00675 { 00676 // Private method: the caller has to ensure the following. 00677 PPL_ASSERT(i <= space_dimension() && j <= space_dimension() && i != j); 00678 PPL_ASSERT(den != 0); 00679 PPL_DIRTY_TEMP(N, k); 00680 div_round_up(k, num, den); 00681 add_dbm_constraint(i, j, k); 00682 }
| void Parma_Polyhedra_Library::BD_Shape< T >::add_dbm_constraint | ( | dimension_type | i, | |
| dimension_type | j, | |||
| const N & | k | |||
| ) | [inline, private] |
Adds the constraint dbm[i][j] <= k.
Definition at line 657 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_dbm_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::BD_Shape< T >::refine().
00659 { 00660 // Private method: the caller has to ensure the following. 00661 PPL_ASSERT(i <= space_dimension() && j <= space_dimension() && i != j); 00662 N& dbm_ij = dbm[i][j]; 00663 if (dbm_ij > k) { 00664 dbm_ij = k; 00665 if (marked_shortest_path_closed()) 00666 reset_shortest_path_closed(); 00667 } 00668 }
| void Parma_Polyhedra_Library::BD_Shape< T >::add_recycled_congruences | ( | Congruence_System & | cgs | ) | [inline] |
Adds to *this constraints equivalent to the congruences in cgs.
| cgs | Contains the congruences that will be added to the system of constraints of *this. Its elements may be recycled. |
| std::invalid_argument | Thrown if *this and cgs are dimension-incompatible, or cgs contains a congruence which is not optimally supported by the BD shape domain. |
cgs upon successful or exceptional return is that it can be safely destroyed. Definition at line 182 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::add_congruences().
00182 { 00183 add_congruences(cgs); 00184 }
| void Parma_Polyhedra_Library::BD_Shape< T >::add_recycled_constraints | ( | Constraint_System & | cs | ) | [inline] |
Adds the constraints in cs to the system of constraints of *this.
| cs | The constraint system to be added to *this. The constraints in cs may be recycled. |
| std::invalid_argument | Thrown if *this and cs are dimension-incompatible, or cs contains a constraint which is not optimally supported by the BD shape domain. |
cs upon successful or exceptional return is that it can be safely destroyed. Definition at line 168 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::add_constraints().
00168 { 00169 add_constraints(cs); 00170 }
| void Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_embed | ( | dimension_type | m | ) | [inline] |
Adds m new dimensions and embeds the old BDS into the new space.
| m | The number of dimensions to add. |
The new dimensions will be those having the highest indexes in the new BDS, which is defined by a system of bounded differences in which the variables running through the new dimensions are unconstrained. For instance, when starting from the BDS
and adding a third dimension, the result will be the BDS
Definition at line 2611 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::DB_Matrix< T >::grow(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::BD_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage().
02611 { 02612 // Adding no dimensions is a no-op. 02613 if (m == 0) 02614 return; 02615 02616 const dimension_type space_dim = space_dimension(); 02617 const dimension_type new_space_dim = space_dim + m; 02618 const bool was_zero_dim_univ = (!marked_empty() && space_dim == 0); 02619 02620 // To embed an n-dimension space BDS in a (n+m)-dimension space, 02621 // we just add `m' rows and columns in the bounded difference shape, 02622 // initialized to PLUS_INFINITY. 02623 dbm.grow(new_space_dim + 1); 02624 02625 // Shortest-path closure is maintained (if it was holding). 02626 // TODO: see whether reduction can be (efficiently!) maintained too. 02627 if (marked_shortest_path_reduced()) 02628 reset_shortest_path_reduced(); 02629 02630 // If `*this' was the zero-dim space universe BDS, 02631 // the we can set the shortest-path closure flag. 02632 if (was_zero_dim_univ) 02633 set_shortest_path_closed(); 02634 02635 PPL_ASSERT(OK()); 02636 }
| void Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_project | ( | dimension_type | m | ) | [inline] |
Adds m new dimensions to the BDS and does not embed it in the new vector space.
| m | The number of dimensions to add. |
The new dimensions will be those having the highest indexes in the new BDS, which is defined by a system of bounded differences in which the variables running through the new dimensions are all constrained to be equal to 0. For instance, when starting from the BDS
and adding a third dimension, the result will be the BDS
Definition at line 2640 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::DB_Matrix< T >::grow(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().
02640 { 02641 // Adding no dimensions is a no-op. 02642 if (m == 0) 02643 return; 02644 02645 const dimension_type space_dim = space_dimension(); 02646 02647 // If `*this' was zero-dimensional, then we add `m' rows and columns. 02648 // If it also was non-empty, then we zero all the added elements 02649 // and set the flag for shortest-path closure. 02650 if (space_dim == 0) { 02651 dbm.grow(m + 1); 02652 if (!marked_empty()) { 02653 for (dimension_type i = m + 1; i-- > 0; ) { 02654 DB_Row<N>& dbm_i = dbm[i]; 02655 for (dimension_type j = m + 1; j-- > 0; ) 02656 if (i != j) 02657 assign_r(dbm_i[j], 0, ROUND_NOT_NEEDED); 02658 } 02659 set_shortest_path_closed(); 02660 } 02661 PPL_ASSERT(OK()); 02662 return; 02663 } 02664 02665 // To project an n-dimension space bounded difference shape 02666 // in a (n+m)-dimension space, we add `m' rows and columns. 02667 // In the first row and column of the matrix we add `zero' from 02668 // the (n+1)-th position to the end. 02669 const dimension_type new_space_dim = space_dim + m; 02670 dbm.grow(new_space_dim + 1); 02671 02672 // Bottom of the matrix and first row. 02673 DB_Row<N>& dbm_0 = dbm[0]; 02674 for (dimension_type i = space_dim + 1; i <= new_space_dim; ++i) { 02675 assign_r(dbm[i][0], 0, ROUND_NOT_NEEDED); 02676 assign_r(dbm_0[i], 0, ROUND_NOT_NEEDED); 02677 } 02678 02679 if (marked_shortest_path_closed()) 02680 reset_shortest_path_closed(); 02681 PPL_ASSERT(OK()); 02682 }
| dimension_type Parma_Polyhedra_Library::BD_Shape< T >::affine_dimension | ( | ) | const [inline] |
Returns
, if *this is empty; otherwise, returns the affine dimension of *this.
Definition at line 292 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::compute_predecessors(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::is_discrete().
00292 { 00293 const dimension_type space_dim = space_dimension(); 00294 // A zero-space-dim shape always has affine dimension zero. 00295 if (space_dim == 0) 00296 return 0; 00297 00298 // Shortest-path closure is necessary to detect emptiness 00299 // and all (possibly implicit) equalities. 00300 shortest_path_closure_assign(); 00301 if (marked_empty()) 00302 return 0; 00303 00304 // The vector `predecessor' is used to represent equivalence classes: 00305 // `predecessor[i] == i' if and only if `i' is the leader of its 00306 // equivalence class (i.e., the minimum index in the class); 00307 std::vector<dimension_type> predecessor; 00308 compute_predecessors(predecessor); 00309 00310 // Due to the fictitious variable `0', the affine dimension is one 00311 // less the number of equivalence classes. 00312 dimension_type affine_dim = 0; 00313 // Note: disregard the first equivalence class. 00314 for (dimension_type i = 1; i <= space_dim; ++i) 00315 if (predecessor[i] == i) 00316 ++affine_dim; 00317 00318 return affine_dim; 00319 }
| void Parma_Polyhedra_Library::BD_Shape< T >::affine_image | ( | Variable | var, | |
| const Linear_Expression & | expr, | |||
| Coefficient_traits::const_reference | denominator = Coefficient_one() | |||
| ) | [inline] |
Assigns to *this the affine image of *this under the function mapping variable var into 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. |
| std::invalid_argument | Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a dimension of *this. |
Definition at line 3826 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::add_dbm_constraint(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::deduce_u_minus_v_bounds(), Parma_Polyhedra_Library::BD_Shape< T >::deduce_v_minus_u_bounds(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::BD_Shape< T >::forget_all_dbm_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::forget_binary_dbm_constraints(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::swap(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage().
03828 { 03829 // The denominator cannot be zero. 03830 if (denominator == 0) 03831 throw_generic("affine_image(v, e, d)", "d == 0"); 03832 03833 // Dimension-compatibility checks. 03834 // The dimension of `expr' should not be greater than the dimension 03835 // of `*this'. 03836 const dimension_type space_dim = space_dimension(); 03837 const dimension_type expr_space_dim = expr.space_dimension(); 03838 if (space_dim < expr_space_dim) 03839 throw_dimension_incompatible("affine_image(v, e, d)", "e", expr); 03840 03841 // `var' should be one of the dimensions of the shape. 03842 const dimension_type v = var.id() + 1; 03843 if (v > space_dim) 03844 throw_dimension_incompatible("affine_image(v, e, d)", var.id()); 03845 03846 // The image of an empty BDS is empty too. 03847 shortest_path_closure_assign(); 03848 if (marked_empty()) 03849 return; 03850 03851 const Coefficient& b = expr.inhomogeneous_term(); 03852 // Number of non-zero coefficients in `expr': will be set to 03853 // 0, 1, or 2, the latter value meaning any value greater than 1. 03854 dimension_type t = 0; 03855 // Index of the last non-zero coefficient in `expr', if any. 03856 dimension_type w = 0; 03857 // Get information about the number of non-zero coefficients in `expr'. 03858 for (dimension_type i = expr_space_dim; i-- > 0; ) 03859 if (expr.coefficient(Variable(i)) != 0) { 03860 if (t++ == 1) 03861 break; 03862 else 03863 w = i+1; 03864 } 03865 03866 // Now we know the form of `expr': 03867 // - If t == 0, then expr == b, with `b' a constant; 03868 // - If t == 1, then expr == a*w + b, where `w' can be `v' or another 03869 // variable; in this second case we have to check whether `a' is 03870 // equal to `denominator' or `-denominator', since otherwise we have 03871 // to fall back on the general form; 03872 // - If t == 2, the `expr' is of the general form. 03873 PPL_DIRTY_TEMP_COEFFICIENT(minus_den); 03874 neg_assign(minus_den, denominator); 03875 03876 if (t == 0) { 03877 // Case 1: expr == b. 03878 // Remove all constraints on `var'. 03879 forget_all_dbm_constraints(v); 03880 // Shortest-path closure is preserved, but not reduction. 03881 if (marked_shortest_path_reduced()) 03882 reset_shortest_path_reduced(); 03883 // Add the constraint `var == b/denominator'. 03884 add_dbm_constraint(0, v, b, denominator); 03885 add_dbm_constraint(v, 0, b, minus_den); 03886 PPL_ASSERT(OK()); 03887 return; 03888 } 03889 03890 if (t == 1) { 03891 // Value of the one and only non-zero coefficient in `expr'. 03892 const Coefficient& a = expr.coefficient(Variable(w-1)); 03893 if (a == denominator || a == minus_den) { 03894 // Case 2: expr == a*w + b, with a == +/- denominator. 03895 if (w == v) { 03896 // `expr' is of the form: a*v + b. 03897 if (a == denominator) { 03898 if (b == 0) 03899 // The transformation is the identity function. 03900 return; 03901 else { 03902 // Translate all the constraints on `var', 03903 // adding or subtracting the value `b/denominator'. 03904 PPL_DIRTY_TEMP(N, d); 03905 div_round_up(d, b, denominator); 03906 PPL_DIRTY_TEMP(N, c); 03907 div_round_up(c, b, minus_den); 03908 DB_Row<N>& dbm_v = dbm[v]; 03909 for (dimension_type i = space_dim + 1; i-- > 0; ) { 03910 N& dbm_vi = dbm_v[i]; 03911 add_assign_r(dbm_vi, dbm_vi, c, ROUND_UP); 03912 N& dbm_iv = dbm[i][v]; 03913 add_assign_r(dbm_iv, dbm_iv, d, ROUND_UP); 03914 } 03915 // Both shortest-path closure and reduction are preserved. 03916 } 03917 } 03918 else { 03919 // Here `a == -denominator'. 03920 // Remove the binary constraints on `var'. 03921 forget_binary_dbm_constraints(v); 03922 // Swap the unary constraints on `var'. 03923 std::swap(dbm[v][0], dbm[0][v]); 03924 // Shortest-path closure is not preserved. 03925 reset_shortest_path_closed(); 03926 if (b != 0) { 03927 // Translate the unary constraints on `var', 03928 // adding or subtracting the value `b/denominator'. 03929 PPL_DIRTY_TEMP(N, c); 03930 div_round_up(c, b, minus_den); 03931 N& dbm_v0 = dbm[v][0]; 03932 add_assign_r(dbm_v0, dbm_v0, c, ROUND_UP); 03933 PPL_DIRTY_TEMP(N, d); 03934 div_round_up(d, b, denominator); 03935 N& dbm_0v = dbm[0][v]; 03936 add_assign_r(dbm_0v, dbm_0v, d, ROUND_UP); 03937 } 03938 } 03939 } 03940 else { 03941 // Here `w != v', so that `expr' is of the form 03942 // +/-denominator * w + b. 03943 // Remove all constraints on `var'. 03944 forget_all_dbm_constraints(v); 03945 // Shortest-path closure is preserved, but not reduction. 03946 if (marked_shortest_path_reduced()) 03947 reset_shortest_path_reduced(); 03948 if (a == denominator) { 03949 // Add the new constraint `v - w == b/denominator'. 03950 add_dbm_constraint(w, v, b, denominator); 03951 add_dbm_constraint(v, w, b, minus_den); 03952 } 03953 else { 03954 // Here a == -denominator, so that we should be adding 03955 // the constraint `v + w == b/denominator'. 03956 // Approximate it by computing lower and upper bounds for `w'. 03957 const N& dbm_w0 = dbm[w][0]; 03958 if (!is_plus_infinity(dbm_w0)) { 03959 // Add the constraint `v <= b/denominator - lower_w'. 03960 PPL_DIRTY_TEMP(N, d); 03961 div_round_up(d, b, denominator); 03962 add_assign_r(dbm[0][v], d, dbm_w0, ROUND_UP); 03963 reset_shortest_path_closed(); 03964 } 03965 const N& dbm_0w = dbm[0][w]; 03966 if (!is_plus_infinity(dbm_0w)) { 03967 // Add the constraint `v >= b/denominator - upper_w'. 03968 PPL_DIRTY_TEMP(N, c); 03969 div_round_up(c, b, minus_den); 03970 add_assign_r(dbm[v][0], dbm_0w, c, ROUND_UP); 03971 reset_shortest_path_closed(); 03972 } 03973 } 03974 } 03975 PPL_ASSERT(OK()); 03976 return; 03977 } 03978 } 03979 03980 // General case. 03981 // Either t == 2, so that 03982 // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2, 03983 // or t == 1, expr == a*w + b, but a <> +/- denominator. 03984 // We will remove all the constraints on `var' and add back 03985 // constraints providing upper and lower bounds for `var'. 03986 03987 // Compute upper approximations for `expr' and `-expr' 03988 // into `pos_sum' and `neg_sum', respectively, taking into account 03989 // the sign of `denominator'. 03990 // Note: approximating `-expr' from above and then negating the 03991 // result is the same as approximating `expr' from below. 03992 const bool is_sc = (denominator > 0); 03993 PPL_DIRTY_TEMP_COEFFICIENT(minus_b); 03994 neg_assign(minus_b, b); 03995 const Coefficient& sc_b = is_sc ? b : minus_b; 03996 const Coefficient& minus_sc_b = is_sc ? minus_b : b; 03997 const Coefficient& sc_den = is_sc ? denominator : minus_den; 03998 const Coefficient& minus_sc_den = is_sc ? minus_den : denominator; 03999 // NOTE: here, for optimization purposes, `minus_expr' is only assigned 04000 // when `denominator' is negative. Do not use it unless you are sure 04001 // it has been correctly assigned. 04002 Linear_Expression minus_expr; 04003 if (!is_sc) 04004 minus_expr = -expr; 04005 const Linear_Expression& sc_expr = is_sc ? expr : minus_expr; 04006 04007 PPL_DIRTY_TEMP(N, pos_sum); 04008 PPL_DIRTY_TEMP(N, neg_sum); 04009 // Indices of the variables that are unbounded in `this->dbm'. 04010 PPL_UNINITIALIZED(dimension_type, pos_pinf_index); 04011 PPL_UNINITIALIZED(dimension_type, neg_pinf_index); 04012 // Number of unbounded variables found. 04013 dimension_type pos_pinf_count = 0; 04014 dimension_type neg_pinf_count = 0; 04015 04016 // Approximate the inhomogeneous term. 04017 assign_r(pos_sum, sc_b, ROUND_UP); 04018 assign_r(neg_sum, minus_sc_b, ROUND_UP); 04019 04020 // Approximate the homogeneous part of `sc_expr'. 04021 const DB_Row<N>& dbm_0 = dbm[0]; 04022 // Speculative allocation of temporaries to be used in the following loop. 04023 PPL_DIRTY_TEMP(N, coeff_i); 04024 PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i); 04025 // Note: indices above `w' can be disregarded, as they all have 04026 // a zero coefficient in `sc_expr'. 04027 for (dimension_type i = w; i > 0; --i) { 04028 const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1)); 04029 const int sign_i = sgn(sc_i); 04030 if (sign_i > 0) { 04031 assign_r(coeff_i, sc_i, ROUND_UP); 04032 // Approximating `sc_expr'. 04033 if (pos_pinf_count <= 1) { 04034 const N& up_approx_i = dbm_0[i]; 04035 if (!is_plus_infinity(up_approx_i)) 04036 add_mul_assign_r(pos_sum, coeff_i, up_approx_i, ROUND_UP); 04037 else { 04038 ++pos_pinf_count; 04039 pos_pinf_index = i; 04040 } 04041 } 04042 // Approximating `-sc_expr'. 04043 if (neg_pinf_count <= 1) { 04044 const N& up_approx_minus_i = dbm[i][0]; 04045 if (!is_plus_infinity(up_approx_minus_i)) 04046 add_mul_assign_r(neg_sum, coeff_i, up_approx_minus_i, ROUND_UP); 04047 else { 04048 ++neg_pinf_count; 04049 neg_pinf_index = i; 04050 } 04051 } 04052 } 04053 else if (sign_i < 0) { 04054 neg_assign(minus_sc_i, sc_i); 04055 // Note: using temporary named `coeff_i' to store -coeff_i. 04056 assign_r(coeff_i, minus_sc_i, ROUND_UP); 04057 // Approximating `sc_expr'. 04058 if (pos_pinf_count <= 1) { 04059 const N& up_approx_minus_i = dbm[i][0]; 04060 if (!is_plus_infinity(up_approx_minus_i)) 04061 add_mul_assign_r(pos_sum, coeff_i, up_approx_minus_i, ROUND_UP); 04062 else { 04063 ++pos_pinf_count; 04064 pos_pinf_index = i; 04065 } 04066 } 04067 // Approximating `-sc_expr'. 04068 if (neg_pinf_count <= 1) { 04069 const N& up_approx_i = dbm_0[i]; 04070 if (!is_plus_infinity(up_approx_i)) 04071 add_mul_assign_r(neg_sum, coeff_i, up_approx_i, ROUND_UP); 04072 else { 04073 ++neg_pinf_count; 04074 neg_pinf_index = i; 04075 } 04076 } 04077 } 04078 } 04079 04080 // Remove all constraints on 'v'. 04081 forget_all_dbm_constraints(v); 04082 // Shortest-path closure is maintained, but not reduction. 04083 if (marked_shortest_path_reduced()) 04084 reset_shortest_path_reduced(); 04085 // Return immediately if no approximation could be computed. 04086 if (pos_pinf_count > 1 && neg_pinf_count > 1) { 04087 PPL_ASSERT(OK()); 04088 return; 04089 } 04090 04091 // In the following, shortest-path closure will be definitely lost. 04092 reset_shortest_path_closed(); 04093 04094 // Exploit the upper approximation, if possible. 04095 if (pos_pinf_count <= 1) { 04096 // Compute quotient (if needed). 04097 if (sc_den != 1) { 04098 // Before computing quotients, the denominator should be approximated 04099 // towards zero. Since `sc_den' is known to be positive, this amounts to 04100 // rounding downwards, which is achieved as usual by rounding upwards 04101 // `minus_sc_den' and negating again the result. 04102 PPL_DIRTY_TEMP(N, down_sc_den); 04103 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 04104 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 04105 div_assign_r(pos_sum, pos_sum, down_sc_den, ROUND_UP); 04106 } 04107 // Add the upper bound constraint, if meaningful. 04108 if (pos_pinf_count == 0) { 04109 // Add the constraint `v <= pos_sum'. 04110 dbm[0][v] = pos_sum; 04111 // Deduce constraints of the form `v - u', where `u != v'. 04112 deduce_v_minus_u_bounds(v, w, sc_expr, sc_den, pos_sum); 04113 } 04114 else 04115 // Here `pos_pinf_count == 1'. 04116 if (pos_pinf_index != v 04117 && sc_expr.coefficient(Variable(pos_pinf_index-1)) == sc_den) 04118 // Add the constraint `v - pos_pinf_index <= pos_sum'. 04119 dbm[pos_pinf_index][v] = pos_sum; 04120 } 04121 04122 // Exploit the lower approximation, if possible. 04123 if (neg_pinf_count <= 1) { 04124 // Compute quotient (if needed). 04125 if (sc_den != 1) { 04126 // Before computing quotients, the denominator should be approximated 04127 // towards zero. Since `sc_den' is known to be positive, this amounts to 04128 // rounding downwards, which is achieved as usual by rounding upwards 04129 // `minus_sc_den' and negating again the result. 04130 PPL_DIRTY_TEMP(N, down_sc_den); 04131 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 04132 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 04133 div_assign_r(neg_sum, neg_sum, down_sc_den, ROUND_UP); 04134 } 04135 // Add the lower bound constraint, if meaningful. 04136 if (neg_pinf_count == 0) { 04137 // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'. 04138 DB_Row<N>& dbm_v = dbm[v]; 04139 dbm_v[0] = neg_sum; 04140 // Deduce constraints of the form `u - v', where `u != v'. 04141 deduce_u_minus_v_bounds(v, w, sc_expr, sc_den, neg_sum); 04142 } 04143 else 04144 // Here `neg_pinf_count == 1'. 04145 if (neg_pinf_index != v 04146 && sc_expr.coefficient(Variable(neg_pinf_index-1)) == sc_den) 04147 // Add the constraint `v - neg_pinf_index >= -neg_sum', 04148 // i.e., `neg_pinf_index - v <= neg_sum'. 04149 dbm[v][neg_pinf_index] = neg_sum; 04150 } 04151 04152 PPL_ASSERT(OK()); 04153 }
| void Parma_Polyhedra_Library::BD_Shape< T >::affine_preimage | ( | Variable | var, | |
| const Linear_Expression & | expr, | |||
| Coefficient_traits::const_reference | denominator = Coefficient_one() | |||
| ) | [inline] |
Assigns to *this the affine preimage of *this under the function mapping variable var into 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. |
| std::invalid_argument | Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a dimension of *this. |
Definition at line 4157 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::BD_Shape< T >::forget_all_dbm_constraints(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage().
04159 { 04160 // The denominator cannot be zero. 04161 if (denominator == 0) 04162 throw_generic("affine_preimage(v, e, d)", "d == 0"); 04163 04164 // Dimension-compatibility checks. 04165 // The dimension of `expr' should not be greater than the dimension 04166 // of `*this'. 04167 const dimension_type space_dim = space_dimension(); 04168 const dimension_type expr_space_dim = expr.space_dimension(); 04169 if (space_dim < expr_space_dim) 04170 throw_dimension_incompatible("affine_preimage(v, e, d)", "e", expr); 04171 04172 // `var' should be one of the dimensions of 04173 // the bounded difference shapes. 04174 const dimension_type v = var.id() + 1; 04175 if (v > space_dim) 04176 throw_dimension_incompatible("affine_preimage(v, e, d)", var.id()); 04177 04178 // The image of an empty BDS is empty too. 04179 shortest_path_closure_assign(); 04180 if (marked_empty()) 04181 return; 04182 04183 const Coefficient& b = expr.inhomogeneous_term(); 04184 // Number of non-zero coefficients in `expr': will be set to 04185 // 0, 1, or 2, the latter value meaning any value greater than 1. 04186 dimension_type t = 0; 04187 // Index of the last non-zero coefficient in `expr', if any. 04188 dimension_type j = 0; 04189 // Get information about the number of non-zero coefficients in `expr'. 04190 for (dimension_type i = expr_space_dim; i-- > 0; ) 04191 if (expr.coefficient(Variable(i)) != 0) { 04192 if (t++ == 1) 04193 break; 04194 else 04195 j = i; 04196 } 04197 04198 // Now we know the form of `expr': 04199 // - If t == 0, then expr = b, with `b' a constant; 04200 // - If t == 1, then expr = a*w + b, where `w' can be `v' or another 04201 // variable; in this second case we have to check whether `a' is 04202 // equal to `denominator' or `-denominator', since otherwise we have 04203 // to fall back on the general form; 04204 // - If t > 1, the `expr' is of the general form. 04205 if (t == 0) { 04206 // Case 1: expr = n; remove all constraints on `var'. 04207 forget_all_dbm_constraints(v); 04208 // Shortest-path closure is preserved, but not reduction. 04209 if (marked_shortest_path_reduced()) 04210 reset_shortest_path_reduced(); 04211 PPL_ASSERT(OK()); 04212 return; 04213 } 04214 04215 if (t == 1) { 04216 // Value of the one and only non-zero coefficient in `expr'. 04217 const Coefficient& a = expr.coefficient(Variable(j)); 04218 if (a == denominator || a == -denominator) { 04219 // Case 2: expr = a*w + b, with a = +/- denominator. 04220 if (j == var.id()) 04221 // Apply affine_image() on the inverse of this transformation. 04222 affine_image(var, denominator*var - b, a); 04223 else { 04224 // `expr == a*w + b', where `w != v'. 04225 // Remove all constraints on `var'. 04226 forget_all_dbm_constraints(v); 04227 // Shortest-path closure is preserved, but not reduction. 04228 if (marked_shortest_path_reduced()) 04229 reset_shortest_path_reduced(); 04230 PPL_ASSERT(OK()); 04231 } 04232 return; 04233 } 04234 } 04235 04236 // General case. 04237 // Either t == 2, so that 04238 // expr = a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2, 04239 // or t = 1, expr = a*w + b, but a <> +/- denominator. 04240 const Coefficient& expr_v = expr.coefficient(var); 04241 if (expr_v != 0) { 04242 // The transformation is invertible. 04243 Linear_Expression inverse((expr_v + denominator)*var); 04244 inverse -= expr; 04245 affine_image(var, inverse, expr_v); 04246 } 04247 else { 04248 // Transformation not invertible: all constraints on `var' are lost. 04249 forget_all_dbm_constraints(v); 04250 // Shortest-path closure is preserved, but not reduction. 04251 if (marked_shortest_path_reduced()) 04252 reset_shortest_path_reduced(); 04253 } 04254 PPL_ASSERT(OK()); 04255 }
| void Parma_Polyhedra_Library::BD_Shape< T >::ascii_dump | ( | std::ostream & | s | ) | const [inline] |
Writes to s an ASCII representation of *this.
Definition at line 5811 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::Bit_Matrix::ascii_dump(), Parma_Polyhedra_Library::DB_Matrix< T >::ascii_dump(), Parma_Polyhedra_Library::BD_Shape< T >::Status::ascii_dump(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm, and Parma_Polyhedra_Library::BD_Shape< T >::status.
05811 { 05812 status.ascii_dump(s); 05813 s << "\n"; 05814 dbm.ascii_dump(s); 05815 s << "\n"; 05816 redundancy_dbm.ascii_dump(s); 05817 }
| void Parma_Polyhedra_Library::BD_Shape< T >::ascii_dump | ( | ) | const |
Writes to std::cerr an ASCII representation of *this.
| bool Parma_Polyhedra_Library::BD_Shape< T >::ascii_load | ( | std::istream & | s | ) | [inline] |
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 5823 of file BD_Shape.templates.hh.
05823 { 05824 if (!status.ascii_load(s)) 05825 return false; 05826 if (!dbm.ascii_load(s)) 05827 return false; 05828 if (!redundancy_dbm.ascii_load(s)) 05829 return false; 05830 return true; 05831 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::BFT00_upper_bound_assign_if_exact | ( | const BD_Shape< T > & | y | ) | [inline, private] |
If the upper bound of *this and y is exact it is assigned to *this and true is returned, otherwise false is returned.
Current implementation is based on a variant of Algorithm 4.1 in A. Bemporad, K. Fukuda, and F. D. Torrisi Convexity Recognition of the Union of Polyhedra Technical Report AUT00-13, ETH Zurich, 2000 tailored to the special case of BD shapes.
*this and y are dimension-compatible; if the assumption does not hold, the behavior is undefined. Definition at line 2060 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::MIP_Problem::add_constraint(), Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::Constraint_System::empty(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::numer_denom(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::MIP_Problem::optimal_value(), Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign(), Parma_Polyhedra_Library::MIP_Problem::solve(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::UNBOUNDED_MIP_PROBLEM, Parma_Polyhedra_Library::UNFEASIBLE_MIP_PROBLEM, and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign_if_exact().
02060 { 02061 // Declare a const reference to *this (to avoid accidental modifications). 02062 const BD_Shape& x = *this; 02063 const dimension_type x_space_dim = x.space_dimension(); 02064 02065 // Private method: the caller must ensure the following. 02066 PPL_ASSERT(x_space_dim == y.space_dimension()); 02067 02068 // The zero-dim case is trivial. 02069 if (x_space_dim == 0) { 02070 upper_bound_assign(y); 02071 return true; 02072 } 02073 // If `x' or `y' is (known to be) empty, the upper bound is exact. 02074 if (x.marked_empty()) { 02075 *this = y; 02076 return true; 02077 } 02078 else if (y.is_empty()) 02079 return true; 02080 else if (x.is_empty()) { 02081 *this = y; 02082 return true; 02083 } 02084 02085 // Here both `x' and `y' are known to be non-empty. 02086 // Implementation based on Algorithm 4.1 (page 6) in [BemporadFT00TR], 02087 // tailored to the special case of BD shapes. 02088 02089 Variable eps(x_space_dim); 02090 Linear_Expression zero_expr = 0*eps; 02091 Linear_Expression db_expr; 02092 PPL_DIRTY_TEMP_COEFFICIENT(num); 02093 PPL_DIRTY_TEMP_COEFFICIENT(den); 02094 02095 // Step 1: compute the constraint system for the envelope env(x,y) 02096 // and put into x_cs_removed and y_cs_removed those non-redundant 02097 // constraints that are not in the constraint system for env(x,y). 02098 // While at it, also add the additional space dimension (eps). 02099 Constraint_System env_cs; 02100 Constraint_System x_cs_removed; 02101 Constraint_System y_cs_removed; 02102 x.shortest_path_reduction_assign(); 02103 y.shortest_path_reduction_assign(); 02104 for (dimension_type i = x_space_dim + 1; i-- > 0; ) { 02105 const Bit_Row& x_red_i = x.redundancy_dbm[i]; 02106 const Bit_Row& y_red_i = y.redundancy_dbm[i]; 02107 const DB_Row<N>& x_dbm_i = x.dbm[i]; 02108 const DB_Row<N>& y_dbm_i = y.dbm[i]; 02109 for (dimension_type j = x_space_dim + 1; j-- > 0; ) { 02110 if (x_red_i[j] && y_red_i[j]) 02111 continue; 02112 if (!x_red_i[j]) { 02113 const N& x_dbm_ij = x_dbm_i[j]; 02114 PPL_ASSERT(!is_plus_infinity(x_dbm_ij)); 02115 numer_denom(x_dbm_ij, num, den); 02116 // Build skeleton DB constraint (having the right space dimension). 02117 db_expr = zero_expr; 02118 if (i > 0) 02119 db_expr += Variable(i-1); 02120 if (j > 0) 02121 db_expr -= Variable(j-1); 02122 if (den != 1) 02123 db_expr *= den; 02124 db_expr += num; 02125 if (x_dbm_ij >= y_dbm_i[j]) 02126 env_cs.insert(db_expr >= 0); 02127 else { 02128 db_expr += eps; 02129 x_cs_removed.insert(db_expr == 0); 02130 } 02131 } 02132 if (!y_red_i[j]) { 02133 const N& y_dbm_ij = y_dbm_i[j]; 02134 const N& x_dbm_ij = x_dbm_i[j]; 02135 PPL_ASSERT(!is_plus_infinity(y_dbm_ij)); 02136 numer_denom(y_dbm_ij, num, den); 02137 // Build skeleton DB constraint (having the right space dimension). 02138 db_expr = zero_expr; 02139 if (i > 0) 02140 db_expr += Variable(i-1); 02141 if (j > 0) 02142 db_expr -= Variable(j-1); 02143 if (den != 1) 02144 db_expr *= den; 02145 db_expr += num; 02146 if (y_dbm_ij >= x_dbm_ij) { 02147 // Check if same constraint was added when considering x_dbm_ij. 02148 if (!x_red_i[j] && x_dbm_ij == y_dbm_ij) 02149 continue; 02150 env_cs.insert(db_expr >= 0); 02151 } 02152 else { 02153 db_expr += eps; 02154 y_cs_removed.insert(db_expr == 0); 02155 } 02156 } 02157 } 02158 } 02159 02160 if (x_cs_removed.empty()) 02161 // No constraint of x was removed: y is included in x. 02162 return true; 02163 if (y_cs_removed.empty()) { 02164 // No constraint of y was removed: x is included in y. 02165 *this = y; 02166 return true; 02167 } 02168 02169 // In preparation to Step 4: build the common part of LP problems, 02170 // i.e., the constraints corresponding to env(x,y), 02171 // where the additional space dimension (eps) has to be maximised. 02172 MIP_Problem env_lp(x_space_dim + 1, env_cs, eps, MAXIMIZATION); 02173 // Pre-solve `env_lp' to later exploit incrementality. 02174 env_lp.solve(); 02175 PPL_ASSERT(env_lp.solve() != UNFEASIBLE_MIP_PROBLEM); 02176 02177 // Implementing loop in Steps 3-6. 02178 for (Constraint_System::const_iterator i = x_cs_removed.begin(), 02179 i_end = x_cs_removed.end(); i != i_end; ++i) { 02180 MIP_Problem lp_i(env_lp); 02181 lp_i.add_constraint(*i); 02182 // Pre-solve to exploit incrementality. 02183 if (lp_i.solve() == UNFEASIBLE_MIP_PROBLEM) 02184 continue; 02185 for (Constraint_System::const_iterator j = y_cs_removed.begin(), 02186 j_end = y_cs_removed.end(); j != j_end; ++j) { 02187 MIP_Problem lp_ij(lp_i); 02188 lp_ij.add_constraint(*j); 02189 // Solve and check for a positive optimal value. 02190 switch (lp_ij.solve()) { 02191 case UNFEASIBLE_MIP_PROBLEM: 02192 // CHECKME: is the following actually impossible? 02193 throw std::runtime_error("PPL internal error"); 02194 case UNBOUNDED_MIP_PROBLEM: 02195 return false; 02196 case OPTIMIZED_MIP_PROBLEM: 02197 lp_ij.optimal_value(num, den); 02198 if (num > 0) 02199 return false; 02200 break; 02201 } 02202 } 02203 } 02204 02205 // The upper bound of x and y is indeed exact. 02206 upper_bound_assign(y); 02207 PPL_ASSERT(OK()); 02208 return true; 02209 }
| void Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign | ( | const BD_Shape< T > & | y, | |
| unsigned * | tp = 0 | |||
| ) | [inline] |
Assigns to *this the result of computing the BHMZ05-widening of *this and y.
| y | A BDS 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 3071 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::affine_dimension(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm, Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::limited_BHMZ05_extrapolation_assign().
03071 { 03072 const dimension_type space_dim = space_dimension(); 03073 03074 // Dimension-compatibility check. 03075 if (space_dim != y.space_dimension()) 03076 throw_dimension_incompatible("BHMZ05_widening_assign(y)", y); 03077 03078 #ifndef NDEBUG 03079 { 03080 // We assume that `y' is contained in or equal to `*this'. 03081 const BD_Shape x_copy = *this; 03082 const BD_Shape y_copy = y; 03083 PPL_ASSERT(x_copy.contains(y_copy)); 03084 } 03085 #endif 03086 03087 // Compute the affine dimension of `y'. 03088 const dimension_type y_affine_dim = y.affine_dimension(); 03089 // If the affine dimension of `y' is zero, then either `y' is 03090 // zero-dimensional, or it is empty, or it is a singleton. 03091 // In all cases, due to the inclusion hypothesis, the result is `*this'. 03092 if (y_affine_dim == 0) 03093 return; 03094 03095 // If the affine dimension has changed, due to the inclusion hypothesis, 03096 // the result is `*this'. 03097 const dimension_type x_affine_dim = affine_dimension(); 03098 PPL_ASSERT(x_affine_dim >= y_affine_dim); 03099 if (x_affine_dim != y_affine_dim) 03100 return; 03101 03102 // If there are tokens available, work on a temporary copy. 03103 if (tp != 0 && *tp > 0) { 03104 BD_Shape<T> x_tmp(*this); 03105 x_tmp.BHMZ05_widening_assign(y, 0); 03106 // If the widening was not precise, use one of the available tokens. 03107 if (!contains(x_tmp)) 03108 --(*tp); 03109 return; 03110 } 03111 03112 // Here no token is available. 03113 PPL_ASSERT(marked_shortest_path_closed() && y.marked_shortest_path_closed()); 03114 // Minimize `y'. 03115 y.shortest_path_reduction_assign(); 03116 03117 // Extrapolate unstable bounds, taking into account redundancy in `y'. 03118 for (dimension_type i = space_dim + 1; i-- > 0; ) { 03119 DB_Row<N>& dbm_i = dbm[i]; 03120 const DB_Row<N>& y_dbm_i = y.dbm[i]; 03121 const Bit_Row& y_redundancy_i = y.redundancy_dbm[i]; 03122 for (dimension_type j = space_dim + 1; j-- > 0; ) { 03123 N& dbm_ij = dbm_i[j]; 03124 // Note: in the following line the use of `!=' (as opposed to 03125 // the use of `<' that would seem -but is not- equivalent) is 03126 // intentional. 03127 if (y_redundancy_i[j] || y_dbm_i[j] != dbm_ij) 03128 assign_r(dbm_ij, PLUS_INFINITY, ROUND_NOT_NEEDED); 03129 } 03130 } 03131 // NOTE: this will also reset the shortest-path reduction flag, 03132 // even though the dbm is still in reduced form. However, the 03133 // current implementation invariant requires that any reduced dbm 03134 // is closed too. 03135 reset_shortest_path_closed(); 03136 PPL_ASSERT(OK()); 03137 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::BHZ09_upper_bound_assign_if_exact | ( | const BD_Shape< T > & | y | ) | [inline, private] |
If the upper bound of *this and y is exact it is assigned to *this and true is returned, otherwise false is returned.
Implementation for the rational (resp., integer) case is based on Theorem 5.2 (resp. Theorem 5.3) of [BHZ09b]. The Boolean template parameter integer_upper_bound allows for choosing between the rational and integer upper bound algorithms.
*this and y are dimension-compatible; if the assumption does not hold, the behavior is undefined.Definition at line 2214 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), PPL_COMPILE_TIME_CHECK, Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::swap(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign().
02214 { 02215 PPL_COMPILE_TIME_CHECK(!integer_upper_bound 02216 || std::numeric_limits<T>::is_integer, 02217 "BD_Shape<T>::BHZ09_upper_bound_assign_if_exact(y):" 02218 " instantiating for integer upper bound," 02219 " but T in not an integer datatype."); 02220 02221 // FIXME, CHECKME: what about inexact computations? 02222 // Declare a const reference to *this (to avoid accidental modifications). 02223 const BD_Shape& x = *this; 02224 const dimension_type x_space_dim = x.space_dimension(); 02225 02226 // Private method: the caller must ensure the following. 02227 PPL_ASSERT(x_space_dim == y.space_dimension()); 02228 02229 // The zero-dim case is trivial. 02230 if (x_space_dim == 0) { 02231 upper_bound_assign(y); 02232 return true; 02233 } 02234 // If `x' or `y' is (known to be) empty, the upper bound is exact. 02235 if (x.marked_empty()) { 02236 *this = y; 02237 return true; 02238 } 02239 else if (y.is_empty()) 02240 return true; 02241 else if (x.is_empty()) { 02242 *this = y; 02243 return true; 02244 } 02245 02246 // Here both `x' and `y' are known to be non-empty. 02247 x.shortest_path_reduction_assign(); 02248 y.shortest_path_reduction_assign(); 02249 PPL_ASSERT(x.marked_shortest_path_closed()); 02250 PPL_ASSERT(y.marked_shortest_path_closed()); 02251 // Pre-compute the upper bound of `x' and `y'. 02252 BD_Shape<T> ub(x); 02253 ub.upper_bound_assign(y); 02254 02255 PPL_DIRTY_TEMP(N, lhs); 02256 PPL_DIRTY_TEMP(N, rhs); 02257 PPL_DIRTY_TEMP(N, temp_zero); 02258 assign_r(temp_zero, 0, ROUND_NOT_NEEDED); 02259 PPL_DIRTY_TEMP(N, temp_one); 02260 if (integer_upper_bound) 02261 assign_r(temp_one, 1, ROUND_NOT_NEEDED); 02262 02263 for (dimension_type i = x_space_dim + 1; i-- > 0; ) { 02264 const DB_Row<N>& x_i = x.dbm[i]; 02265 const Bit_Row& x_red_i = x.redundancy_dbm[i]; 02266 const DB_Row<N>& y_i = y.dbm[i]; 02267 const DB_Row<N>& ub_i = ub.dbm[i]; 02268 for (dimension_type j = x_space_dim + 1; j-- > 0; ) { 02269 // Check redundancy of x_i_j. 02270 if (x_red_i[j]) 02271 continue; 02272 // By non-redundancy, we know that i != j. 02273 PPL_ASSERT(i != j); 02274 const N& x_i_j = x_i[j]; 02275 if (x_i_j < y_i[j]) { 02276 for (dimension_type k = x_space_dim + 1; k-- > 0; ) { 02277 const DB_Row<N>& x_k = x.dbm[k]; 02278 const DB_Row<N>& y_k = y.dbm[k]; 02279 const Bit_Row& y_red_k = y.redundancy_dbm[k]; 02280 const DB_Row<N>& ub_k = ub.dbm[k]; 02281 const N& ub_k_j = (k == j) ? temp_zero : ub_k[j]; 02282 for (dimension_type ell = x_space_dim + 1; ell-- > 0; ) { 02283 // Check redundancy of y_k_ell. 02284 if (y_red_k[ell]) 02285 continue; 02286 // By non-redundancy, we know that k != ell. 02287 PPL_ASSERT(k != ell); 02288 const N& y_k_ell = y_k[ell]; 02289 if (y_k_ell < x_k[ell]) { 02290 // The first condition in BHZ09 theorem holds; 02291 // now check for the second condition. 02292 add_assign_r(lhs, x_i_j, y_k_ell, ROUND_UP); 02293 const N& ub_i_ell = (i == ell) ? temp_zero : ub_i[ell]; 02294 add_assign_r(rhs, ub_i_ell, ub_k_j, ROUND_UP); 02295 if (integer_upper_bound) { 02296 // Note: adding 1 rather than 2 (as in Theorem 5.3) 02297 // so as to later test for < rather than <=. 02298 add_assign_r(lhs, lhs, temp_one, ROUND_NOT_NEEDED); 02299 } 02300 // Testing for < in both the rational and integer case. 02301 if (lhs < rhs) 02302 return false; 02303 } 02304 } 02305 } 02306 } 02307 } 02308 } 02309 // The upper bound of x and y is indeed exact. 02310 swap(ub); 02311 PPL_ASSERT(OK()); 02312 return true; 02313 }
| void Parma_Polyhedra_Library::BD_Shape< T >::bounded_affine_image | ( | Variable | var, | |
| const Linear_Expression & | lb_expr, | |||
| const Linear_Expression & | ub_expr, | |||
| Coefficient_traits::const_reference | denominator = Coefficient_one() | |||
| ) | [inline] |
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 4260 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::neg_assign(), PPL_DIRTY_TEMP_COEFFICIENT, and Parma_Polyhedra_Library::Linear_Expression::space_dimension().
04263 { 04264 // The denominator cannot be zero. 04265 if (denominator == 0) 04266 throw_generic("bounded_affine_image(v, lb, ub, d)", "d == 0"); 04267 04268 // Dimension-compatibility checks. 04269 // `var' should be one of the dimensions of the BD_Shape. 04270 const dimension_type bds_space_dim = space_dimension(); 04271 const dimension_type v = var.id() + 1; 04272 if (v > bds_space_dim) 04273 throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)", 04274 "v", var); 04275 // The dimension of `lb_expr' and `ub_expr' should not be 04276 // greater than the dimension of `*this'. 04277 const dimension_type lb_space_dim = lb_expr.space_dimension(); 04278 if (bds_space_dim < lb_space_dim) 04279 throw_dimension_incompatible("bounded_affine_image(v, lb, ub)", 04280 "lb", lb_expr); 04281 const dimension_type ub_space_dim = ub_expr.space_dimension(); 04282 if (bds_space_dim < ub_space_dim) 04283 throw_dimension_incompatible("bounded_affine_image(v, lb, ub)", 04284 "ub", ub_expr); 04285 04286 // Any image of an empty BDS is empty. 04287 shortest_path_closure_assign(); 04288 if (marked_empty()) 04289 return; 04290 04291 const Coefficient& b = ub_expr.inhomogeneous_term(); 04292 // Number of non-zero coefficients in `ub_expr': will be set to 04293 // 0, 1, or 2, the latter value meaning any value greater than 1. 04294 dimension_type t = 0; 04295 // Index of the last non-zero coefficient in `ub_expr', if any. 04296 dimension_type w = 0; 04297 // Get information about the number of non-zero coefficients in `expr'. 04298 for (dimension_type i = ub_space_dim; i-- > 0; ) 04299 if (ub_expr.coefficient(Variable(i)) != 0) { 04300 if (t++ == 1) 04301 break; 04302 else 04303 w = i+1; 04304 } 04305 04306 // Now we know the form of `ub_expr': 04307 // - If t == 0, then ub_expr == b, with `b' a constant; 04308 // - If t == 1, then ub_expr == a*w + b, where `w' can be `v' or another 04309 // variable; in this second case we have to check whether `a' is 04310 // equal to `denominator' or `-denominator', since otherwise we have 04311 // to fall back on the general form; 04312 // - If t == 2, the `ub_expr' is of the general form. 04313 PPL_DIRTY_TEMP_COEFFICIENT(minus_den); 04314 neg_assign(minus_den, denominator); 04315 04316 if (t == 0) { 04317 // Case 1: ub_expr == b. 04318 generalized_affine_image(var, 04319 GREATER_OR_EQUAL, 04320 lb_expr, 04321 denominator); 04322 // Add the constraint `var <= b/denominator'. 04323 add_dbm_constraint(0, v, b, denominator); 04324 PPL_ASSERT(OK()); 04325 return; 04326 } 04327 04328 if (t == 1) { 04329 // Value of the one and only non-zero coefficient in `ub_expr'. 04330 const Coefficient& a = ub_expr.coefficient(Variable(w-1)); 04331 if (a == denominator || a == minus_den) { 04332 // Case 2: expr == a*w + b, with a == +/- denominator. 04333 if (w == v) { 04334 // Here `var' occurs in `ub_expr'. 04335 // To ease the computation, we add an additional dimension. 04336 const Variable new_var = Variable(bds_space_dim); 04337 add_space_dimensions_and_embed(1); 04338 // Constrain the new dimension to be equal to `ub_expr'. 04339 affine_image(new_var, ub_expr, denominator); 04340 // NOTE: enforce shortest-path closure for precision. 04341 shortest_path_closure_assign(); 04342 PPL_ASSERT(!marked_empty()); 04343 // Apply the affine lower bound. 04344 generalized_affine_image(var, 04345 GREATER_OR_EQUAL, 04346 lb_expr, 04347 denominator); 04348 // Now apply the affine upper bound, as recorded in `new_var'. 04349 add_constraint(var <= new_var); 04350 // Remove the temporarily added dimension. 04351 remove_higher_space_dimensions(bds_space_dim); 04352 return; 04353 } 04354 else { 04355 // Here `w != v', so that `expr' is of the form 04356 // +/-denominator * w + b. 04357 // Apply the affine lower bound. 04358 generalized_affine_image(var, 04359 GREATER_OR_EQUAL, 04360 lb_expr, 04361 denominator); 04362 if (a == denominator) { 04363 // Add the new constraint `v - w == b/denominator'. 04364 add_dbm_constraint(w, v, b, denominator); 04365 } 04366 else { 04367 // Here a == -denominator, so that we should be adding 04368 // the constraint `v + w == b/denominator'. 04369 // Approximate it by computing lower and upper bounds for `w'. 04370 const N& dbm_w0 = dbm[w][0]; 04371 if (!is_plus_infinity(dbm_w0)) { 04372 // Add the constraint `v <= b/denominator - lower_w'. 04373 PPL_DIRTY_TEMP(N, d); 04374 div_round_up(d, b, denominator); 04375 add_assign_r(dbm[0][v], d, dbm_w0, ROUND_UP); 04376 reset_shortest_path_closed(); 04377 } 04378 } 04379 PPL_ASSERT(OK()); 04380 return; 04381 } 04382 } 04383 } 04384 04385 // General case. 04386 // Either t == 2, so that 04387 // ub_expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2, 04388 // or t == 1, ub_expr == a*w + b, but a <> +/- denominator. 04389 // We will remove all the constraints on `var' and add back 04390 // constraints providing upper and lower bounds for `var'. 04391 04392 // Compute upper approximations for `ub_expr' into `pos_sum' 04393 // taking into account the sign of `denominator'. 04394 const bool is_sc = (denominator > 0); 04395 PPL_DIRTY_TEMP_COEFFICIENT(minus_b); 04396 neg_assign(minus_b, b); 04397 const Coefficient& sc_b = is_sc ? b : minus_b; 04398 const Coefficient& sc_den = is_sc ? denominator : minus_den; 04399 const Coefficient& minus_sc_den = is_sc ? minus_den : denominator; 04400 // NOTE: here, for optimization purposes, `minus_expr' is only assigned 04401 // when `denominator' is negative. Do not use it unless you are sure 04402 // it has been correctly assigned. 04403 Linear_Expression minus_expr; 04404 if (!is_sc) 04405 minus_expr = -ub_expr; 04406 const Linear_Expression& sc_expr = is_sc ? ub_expr : minus_expr; 04407 04408 PPL_DIRTY_TEMP(N, pos_sum); 04409 // Index of the variable that are unbounded in `this->dbm'. 04410 PPL_UNINITIALIZED(dimension_type, pos_pinf_index); 04411 // Number of unbounded variables found. 04412 dimension_type pos_pinf_count = 0; 04413 04414 // Approximate the inhomogeneous term. 04415 assign_r(pos_sum, sc_b, ROUND_UP); 04416 04417 // Approximate the homogeneous part of `sc_expr'. 04418 const DB_Row<N>& dbm_0 = dbm[0]; 04419 // Speculative allocation of temporaries to be used in the following loop. 04420 PPL_DIRTY_TEMP(N, coeff_i); 04421 PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i); 04422 // Note: indices above `w' can be disregarded, as they all have 04423 // a zero coefficient in `sc_expr'. 04424 for (dimension_type i = w; i > 0; --i) { 04425 const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1)); 04426 const int sign_i = sgn(sc_i); 04427 if (sign_i > 0) { 04428 assign_r(coeff_i, sc_i, ROUND_UP); 04429 // Approximating `sc_expr'. 04430 if (pos_pinf_count <= 1) { 04431 const N& up_approx_i = dbm_0[i]; 04432 if (!is_plus_infinity(up_approx_i)) 04433 add_mul_assign_r(pos_sum, coeff_i, up_approx_i, ROUND_UP); 04434 else { 04435 ++pos_pinf_count; 04436 pos_pinf_index = i; 04437 } 04438 } 04439 } 04440 else if (sign_i < 0) { 04441 neg_assign(minus_sc_i, sc_i); 04442 // Note: using temporary named `coeff_i' to store -coeff_i. 04443 assign_r(coeff_i, minus_sc_i, ROUND_UP); 04444 // Approximating `sc_expr'. 04445 if (pos_pinf_count <= 1) { 04446 const N& up_approx_minus_i = dbm[i][0]; 04447 if (!is_plus_infinity(up_approx_minus_i)) 04448 add_mul_assign_r(pos_sum, coeff_i, up_approx_minus_i, ROUND_UP); 04449 else { 04450 ++pos_pinf_count; 04451 pos_pinf_index = i; 04452 } 04453 } 04454 } 04455 } 04456 // Apply the affine lower bound. 04457 generalized_affine_image(var, 04458 GREATER_OR_EQUAL, 04459 lb_expr, 04460 denominator); 04461 // Return immediately if no approximation could be computed. 04462 if (pos_pinf_count > 1) { 04463 return; 04464 } 04465 04466 // In the following, shortest-path closure will be definitely lost. 04467 reset_shortest_path_closed(); 04468 04469 // Exploit the upper approximation, if possible. 04470 if (pos_pinf_count <= 1) { 04471 // Compute quotient (if needed). 04472 if (sc_den != 1) { 04473 // Before computing quotients, the denominator should be approximated 04474 // towards zero. Since `sc_den' is known to be positive, this amounts to 04475 // rounding downwards, which is achieved as usual by rounding upwards 04476 // `minus_sc_den' and negating again the result. 04477 PPL_DIRTY_TEMP(N, down_sc_den); 04478 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 04479 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 04480 div_assign_r(pos_sum, pos_sum, down_sc_den, ROUND_UP); 04481 } 04482 // Add the upper bound constraint, if meaningful. 04483 if (pos_pinf_count == 0) { 04484 // Add the constraint `v <= pos_sum'. 04485 dbm[0][v] = pos_sum; 04486 // Deduce constraints of the form `v - u', where `u != v'. 04487 deduce_v_minus_u_bounds(v, w, sc_expr, sc_den, pos_sum); 04488 } 04489 else 04490 // Here `pos_pinf_count == 1'. 04491 if (pos_pinf_index != v 04492 && sc_expr.coefficient(Variable(pos_pinf_index-1)) == sc_den) 04493 // Add the constraint `v - pos_pinf_index <= pos_sum'. 04494 dbm[pos_pinf_index][v] = pos_sum; 04495 } 04496 PPL_ASSERT(OK()); 04497 }
| void Parma_Polyhedra_Library::BD_Shape< T >::bounded_affine_preimage | ( | Variable | var, | |
| const Linear_Expression & | lb_expr, | |||
| const Linear_Expression & | ub_expr, | |||
| Coefficient_traits::const_reference | denominator = Coefficient_one() | |||
| ) | [inline] |
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 4502 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::neg_assign(), PPL_DIRTY_TEMP_COEFFICIENT, and Parma_Polyhedra_Library::Linear_Expression::space_dimension().
04505 { 04506 // The denominator cannot be zero. 04507 if (denominator == 0) 04508 throw_generic("bounded_affine_preimage(v, lb, ub, d)", "d == 0"); 04509 04510 // Dimension-compatibility checks. 04511 // `var' should be one of the dimensions of the BD_Shape. 04512 const dimension_type space_dim = space_dimension(); 04513 const dimension_type v = var.id() + 1; 04514 if (v > space_dim) 04515 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)", 04516 "v", var); 04517 // The dimension of `lb_expr' and `ub_expr' should not be 04518 // greater than the dimension of `*this'. 04519 const dimension_type lb_space_dim = lb_expr.space_dimension(); 04520 if (space_dim < lb_space_dim) 04521 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)", 04522 "lb", lb_expr); 04523 const dimension_type ub_space_dim = ub_expr.space_dimension(); 04524 if (space_dim < ub_space_dim) 04525 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)", 04526 "ub", ub_expr); 04527 04528 // Any preimage of an empty BDS is empty. 04529 shortest_path_closure_assign(); 04530 if (marked_empty()) 04531 return; 04532 04533 if (ub_expr.coefficient(var) == 0) { 04534 refine(var, LESS_OR_EQUAL, ub_expr, denominator); 04535 generalized_affine_preimage(var, GREATER_OR_EQUAL, 04536 lb_expr, denominator); 04537 return; 04538 } 04539 if (lb_expr.coefficient(var) == 0) { 04540 refine(var, GREATER_OR_EQUAL, lb_expr, denominator); 04541 generalized_affine_preimage(var, LESS_OR_EQUAL, 04542 ub_expr, denominator); 04543 return; 04544 } 04545 04546 const Coefficient& lb_expr_v = lb_expr.coefficient(var); 04547 // Here `var' occurs in `lb_expr' and `ub_expr'. 04548 // To ease the computation, we add an additional dimension. 04549 const Variable new_var = Variable(space_dim); 04550 add_space_dimensions_and_embed(1); 04551 const Linear_Expression lb_inverse 04552 = lb_expr - (lb_expr_v + denominator)*var; 04553 PPL_DIRTY_TEMP_COEFFICIENT(lb_inverse_den); 04554 neg_assign(lb_inverse_den, lb_expr_v); 04555 affine_image(new_var, lb_inverse, lb_inverse_den); 04556 shortest_path_closure_assign(); 04557 PPL_ASSERT(!marked_empty()); 04558 generalized_affine_preimage(var, LESS_OR_EQUAL, 04559 ub_expr, denominator); 04560 if (sgn(denominator) == sgn(lb_inverse_den)) 04561 add_constraint(var >= new_var); 04562 else 04563 add_constraint(var <= new_var); 04564 // Remove the temporarily added dimension. 04565 remove_higher_space_dimensions(space_dim); 04566 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::bounds | ( | const Linear_Expression & | expr, | |
| bool | from_above | |||
| ) | const [inline, 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; | |
| from_above | true if and only if the boundedness of interest is "from above". |
| std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
Definition at line 1126 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::constraints(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::extract_bounded_difference(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::MINIMIZATION, Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::MIP_Problem::solve(), Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::bounds_from_above(), and Parma_Polyhedra_Library::BD_Shape< T >::bounds_from_below().
01127 { 01128 // The dimension of `expr' should not be greater than the dimension 01129 // of `*this'. 01130 const dimension_type expr_space_dim = expr.space_dimension(); 01131 const dimension_type space_dim = space_dimension(); 01132 if (space_dim < expr_space_dim) 01133 throw_dimension_incompatible((from_above 01134 ? "bounds_from_above(e)" 01135 : "bounds_from_below(e)"), "e", expr); 01136 01137 shortest_path_closure_assign(); 01138 // A zero-dimensional or empty BDS bounds everything. 01139 if (space_dim == 0 || marked_empty()) 01140 return true; 01141 01142 // The constraint `c' is used to check if `expr' is a difference 01143 // bounded and, in this case, to select the cell. 01144 const Constraint& c = from_above ? expr <= 0 : expr >= 0; 01145 const dimension_type c_space_dim = c.space_dimension(); 01146 dimension_type num_vars = 0; 01147 dimension_type i = 0; 01148 dimension_type j = 0; 01149 PPL_DIRTY_TEMP_COEFFICIENT(coeff); 01150 // Check if `c' is a BD constraint. 01151 if (extract_bounded_difference(c, c_space_dim, num_vars, i, j, coeff)) { 01152 if (num_vars == 0) 01153 // Dealing with a trivial constraint. 01154 return true; 01155 // Select the cell to be checked. 01156 const N& x = (coeff < 0) ? dbm[i][j] : dbm[j][i]; 01157 return !is_plus_infinity(x); 01158 } 01159 else { 01160 // Not a DB constraint: use the MIP solver. 01161 Optimization_Mode mode_bounds 01162 = from_above ? MAXIMIZATION : MINIMIZATION; 01163 MIP_Problem mip(space_dim, constraints(), expr, mode_bounds); 01164 // Problem is known to be feasible. 01165 return mip.solve() == OPTIMIZED_MIP_PROBLEM; 01166 } 01167 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::bounds_from_above | ( | const Linear_Expression & | expr | ) | const [inline] |
Returns true if and only if expr is bounded from above in *this.
| std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
Definition at line 362 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::bounds().
00362 { 00363 return bounds(expr, true); 00364 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::bounds_from_below | ( | const Linear_Expression & | expr | ) | const [inline] |
Returns true if and only if expr is bounded from below in *this.
| std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
Definition at line 368 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::bounds().
00368 { 00369 return bounds(expr, false); 00370 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::can_recycle_congruence_systems | ( | ) | [inline, static] |
Returns false indicating that this domain cannot recycle congruences.
Definition at line 263 of file BD_Shape.inlines.hh.
| bool Parma_Polyhedra_Library::BD_Shape< T >::can_recycle_constraint_systems | ( | ) | [inline, static] |
Returns false indicating that this domain cannot recycle constraints.
Definition at line 256 of file BD_Shape.inlines.hh.
| void Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign | ( | const BD_Shape< T > & | y, | |
| Iterator | first, | |||
| Iterator | last, | |||
| unsigned * | tp = 0 | |||
| ) | [inline] |
Assigns to *this the result of computing the CC76-extrapolation between *this and y.
| y | A BDS that must be contained in *this. | |
| first | An iterator referencing the first stop-point. | |
| last | An iterator referencing one past the last stop-point. | |
| 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 2885 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().
02887 { 02888 const dimension_type space_dim = space_dimension(); 02889 02890 // Dimension-compatibility check. 02891 if (space_dim != y.space_dimension()) 02892 throw_dimension_incompatible("CC76_extrapolation_assign(y)", y); 02893 02894 #ifndef NDEBUG 02895 { 02896 // We assume that `y' is contained in or equal to `*this'. 02897 const BD_Shape x_copy = *this; 02898 const BD_Shape y_copy = y; 02899 PPL_ASSERT(x_copy.contains(y_copy)); 02900 } 02901 #endif 02902 02903 // If both bounded difference shapes are zero-dimensional, 02904 // since `*this' contains `y', we simply return `*this'. 02905 if (space_dim == 0) 02906 return; 02907 02908 shortest_path_closure_assign(); 02909 // If `*this' is empty, since `*this' contains `y', `y' is empty too. 02910 if (marked_empty()) 02911 return; 02912 y.shortest_path_closure_assign(); 02913 // If `y' is empty, we return. 02914 if (y.marked_empty()) 02915 return; 02916 02917 // If there are tokens available, work on a temporary copy. 02918 if (tp != 0 && *tp > 0) { 02919 BD_Shape<T> x_tmp(*this); 02920 x_tmp.CC76_extrapolation_assign(y, first, last, 0); 02921 // If the widening was not precise, use one of the available tokens. 02922 if (!contains(x_tmp)) 02923 --(*tp); 02924 return; 02925 } 02926 02927 // Compare each constraint in `y' to the corresponding one in `*this'. 02928 // The constraint in `*this' is kept as is if it is stronger than or 02929 // equal to the constraint in `y'; otherwise, the inhomogeneous term 02930 // of the constraint in `*this' is further compared with elements taken 02931 // from a sorted container (the stop-points, provided by the user), and 02932 // is replaced by the first entry, if any, which is greater than or equal 02933 // to the inhomogeneous term. If no such entry exists, the constraint 02934 // is removed altogether. 02935 for (dimension_type i = space_dim + 1; i-- > 0; ) { 02936 DB_Row<N>& dbm_i = dbm[i]; 02937 const DB_Row<N>& y_dbm_i = y.dbm[i]; 02938 for (dimension_type j = space_dim + 1; j-- > 0; ) { 02939 N& dbm_ij = dbm_i[j]; 02940 const N& y_dbm_ij = y_dbm_i[j]; 02941 if (y_dbm_ij < dbm_ij) { 02942 Iterator k = std::lower_bound(first, last, dbm_ij); 02943 if (k != last) { 02944 if (dbm_ij < *k) 02945 assign_r(dbm_ij, *k, ROUND_UP); 02946 } 02947 else 02948 assign_r(dbm_ij, PLUS_INFINITY, ROUND_NOT_NEEDED); 02949 } 02950 } 02951 } 02952 reset_shortest_path_closed(); 02953 PPL_ASSERT(OK()); 02954 }
| void Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign | ( | const BD_Shape< T > & | y, | |
| unsigned * | tp = 0 | |||
| ) | [inline] |
Assigns to *this the result of computing the CC76-extrapolation between *this and y.
| y | A BDS 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 781 of file BD_Shape.inlines.hh.
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::limited_CC76_extrapolation_assign().
00781 { 00782 static N stop_points[] = { 00783 N(-2, ROUND_UP), 00784 N(-1, ROUND_UP), 00785 N( 0, ROUND_UP), 00786 N( 1, ROUND_UP), 00787 N( 2, ROUND_UP) 00788 }; 00789 CC76_extrapolation_assign(y, 00790 stop_points, 00791 stop_points 00792 + sizeof(stop_points)/sizeof(stop_points[0]), 00793 tp); 00794 }
| void Parma_Polyhedra_Library::BD_Shape< T >::CC76_narrowing_assign | ( | const BD_Shape< T > & | y | ) | [inline] |
Assigns to *this the result of restoring in y the constraints of *this that were lost by CC76-extrapolation applications.
| y | A BDS that must contain *this. |
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
y is meant to denote the value computed in the previous iteration step, whereas *this denotes the value computed in the current iteration step (in the decreasing iteration sequence). Hence, the call x.CC76_narrowing_assign(y) will assign to x the result of the computation
. Definition at line 3191 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().
03191 { 03192 const dimension_type space_dim = space_dimension(); 03193 03194 // Dimension-compatibility check. 03195 if (space_dim != y.space_dimension()) 03196 throw_dimension_incompatible("CC76_narrowing_assign(y)", y); 03197 03198 #ifndef NDEBUG 03199 { 03200 // We assume that `*this' is contained in or equal to `y'. 03201 const BD_Shape x_copy = *this; 03202 const BD_Shape y_copy = y; 03203 PPL_ASSERT(y_copy.contains(x_copy)); 03204 } 03205 #endif 03206 03207 // If both bounded difference shapes are zero-dimensional, 03208 // since `y' contains `*this', we simply return `*this'. 03209 if (space_dim == 0) 03210 return; 03211 03212 y.shortest_path_closure_assign(); 03213 // If `y' is empty, since `y' contains `this', `*this' is empty too. 03214 if (y.marked_empty()) 03215 return; 03216 shortest_path_closure_assign(); 03217 // If `*this' is empty, we return. 03218 if (marked_empty()) 03219 return; 03220 03221 // Replace each constraint in `*this' by the corresponding constraint 03222 // in `y' if the corresponding inhomogeneous terms are both finite. 03223 bool changed = false; 03224 for (dimension_type i = space_dim + 1; i-- > 0; ) { 03225 DB_Row<N>& dbm_i = dbm[i]; 03226 const DB_Row<N>& y_dbm_i = y.dbm[i]; 03227 for (dimension_type j = space_dim + 1; j-- > 0; ) { 03228 N& dbm_ij = dbm_i[j]; 03229 const N& y_dbm_ij = y_dbm_i[j]; 03230 if (!is_plus_infinity(dbm_ij) 03231 && !is_plus_infinity(y_dbm_ij) 03232 && dbm_ij != y_dbm_ij) { 03233 dbm_ij = y_dbm_ij; 03234 changed = true; 03235 } 03236 } 03237 } 03238 if (changed && marked_shortest_path_closed()) 03239 reset_shortest_path_closed(); 03240 PPL_ASSERT(OK()); 03241 }
| void Parma_Polyhedra_Library::BD_Shape< T >::compute_leaders | ( | std::vector< dimension_type > & | leaders | ) | const [inline, private] |
Compute the leaders of zero-equivalence classes.
It is assumed that the BDS is not empty and shortest-path closed.
Definition at line 935 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::compute_predecessors(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), and Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::BD_Shape< T >::minimized_constraints(), and Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign().
00935 { 00936 PPL_ASSERT(!marked_empty() && marked_shortest_path_closed()); 00937 PPL_ASSERT(leaders.size() == 0); 00938 // Compute predecessor information. 00939 compute_predecessors(leaders); 00940 // Flatten the predecessor chains so as to obtain leaders. 00941 PPL_ASSERT(leaders[0] == 0); 00942 for (dimension_type i = 1, l_size = leaders.size(); i != l_size; ++i) { 00943 const dimension_type l_i = leaders[i]; 00944 PPL_ASSERT(l_i <= i); 00945 if (l_i != i) { 00946 const dimension_type ll_i = leaders[l_i]; 00947 PPL_ASSERT(ll_i == leaders[ll_i]); 00948 leaders[i] = ll_i; 00949 } 00950 } 00951 }
| void Parma_Polyhedra_Library::BD_Shape< T >::compute_predecessors | ( | std::vector< dimension_type > & | predecessor | ) | const [inline, private] |
Compute the (zero-equivalence classes) predecessor relation.
It is assumed that the BDS is not empty and shortest-path closed.
Definition at line 906 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::is_additive_inverse().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::affine_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::compute_leaders(), and Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign().
00906 { 00907 PPL_ASSERT(!marked_empty() && marked_shortest_path_closed()); 00908 PPL_ASSERT(predecessor.size() == 0); 00909 // Variables are ordered according to their index. 00910 // The vector `predecessor' is used to indicate which variable 00911 // immediately precedes a given one in the corresponding equivalence class. 00912 // The `leader' of an equivalence class is the element having minimum 00913 // index: leaders are their own predecessors. 00914 const dimension_type pred_size = dbm.num_rows(); 00915 // Initially, each variable is leader of its own zero-equivalence class. 00916 predecessor.reserve(pred_size); 00917 for (dimension_type i = 0; i < pred_size; ++i) 00918 predecessor.push_back(i); 00919 // Now compute actual predecessors. 00920 for (dimension_type i = pred_size; i-- > 1; ) 00921 if (i == predecessor[i]) { 00922 const DB_Row<N>& dbm_i = dbm[i]; 00923 for (dimension_type j = i; j-- > 0; ) 00924 if (j == predecessor[j] 00925 && is_additive_inverse(dbm[j][i], dbm_i[j])) { 00926 // Choose as predecessor the variable having the smaller index. 00927 predecessor[i] = j; 00928 break; 00929 } 00930 } 00931 }
| void Parma_Polyhedra_Library::BD_Shape< T >::concatenate_assign | ( | const BD_Shape< T > & | y | ) | [inline] |
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 534 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::DB_Matrix< T >::grow(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().
00534 { 00535 BD_Shape& x = *this; 00536 00537 const dimension_type x_space_dim = x.space_dimension(); 00538 const dimension_type y_space_dim = y.space_dimension(); 00539 00540 // If `y' is an empty 0-dim space bounded difference shape, 00541 // let `*this' become empty. 00542 if (y_space_dim == 0 && y.marked_empty()) { 00543 set_empty(); 00544 return; 00545 } 00546 00547 // If `x' is an empty 0-dim space BDS, then it is sufficient to adjust 00548 // the dimension of the vector space. 00549 if (x_space_dim == 0 && marked_empty()) { 00550 dbm.grow(y_space_dim + 1); 00551 PPL_ASSERT(OK()); 00552 return; 00553 } 00554 // First we increase the space dimension of `x' by adding 00555 // `y.space_dimension()' new dimensions. 00556 // The matrix for the new system of constraints is obtained 00557 // by leaving the old system of constraints in the upper left-hand side 00558 // and placing the constraints of `y' in the lower right-hand side, 00559 // except the constraints as `y(i) >= cost' or `y(i) <= cost', that are 00560 // placed in the right position on the new matrix. 00561 add_space_dimensions_and_embed(y_space_dim); 00562 const dimension_type new_space_dim = x_space_dim + y_space_dim; 00563 for (dimension_type i = x_space_dim + 1; i <= new_space_dim; ++i) { 00564 DB_Row<N>& dbm_i = dbm[i]; 00565 dbm_i[0] = y.dbm[i - x_space_dim][0]; 00566 dbm[0][i] = y.dbm[0][i - x_space_dim]; 00567 for (dimension_type j = x_space_dim + 1; j <= new_space_dim; ++j) 00568 dbm_i[j] = y.dbm[i - x_space_dim][j - x_space_dim]; 00569 } 00570 00571 if (marked_shortest_path_closed()) 00572 reset_shortest_path_closed(); 00573 PPL_ASSERT(OK()); 00574 }
| Congruence_System Parma_Polyhedra_Library::BD_Shape< T >::congruences | ( | ) | const [inline] |
Returns a system of (equality) congruences satisfied by *this.
Definition at line 154 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::minimized_congruences().
Referenced by Parma_Polyhedra_Library::Grid::Grid().
00154 { 00155 return minimized_congruences(); 00156 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::constrains | ( | Variable | var | ) | const [inline] |
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 878 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::DB_Matrix< T >::num_rows(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().
00878 { 00879 // `var' should be one of the dimensions of the BD shape. 00880 const dimension_type var_space_dim = var.space_dimension(); 00881 if (space_dimension() < var_space_dim) 00882 throw_dimension_incompatible("constrains(v)", "v", var); 00883 00884 shortest_path_closure_assign(); 00885 // A BD shape known to be empty constrains all variables. 00886 // (Note: do not force emptiness check _yet_) 00887 if (marked_empty()) 00888 return true; 00889 00890 // Check whether `var' is syntactically constrained. 00891 const DB_Row<N>& dbm_v = dbm[var_space_dim]; 00892 for (dimension_type i = dbm.num_rows(); i-- > 0; ) { 00893 if (!is_plus_infinity(dbm_v[i]) 00894 || !is_plus_infinity(dbm[i][var_space_dim])) 00895 return true; 00896 } 00897 00898 // `var' is not syntactically constrained: 00899 // now force an emptiness check. 00900 return is_empty(); 00901 }
| Constraint_System Parma_Polyhedra_Library::BD_Shape< T >::constraints | ( | ) | const [inline] |
Returns a system of constraints defining *this.
Definition at line 5393 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::minimized_constraints(), Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::Constraint_System::zero_dim_empty().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::bounds(), Parma_Polyhedra_Library::C_Polyhedron::C_Polyhedron(), Parma_Polyhedra_Library::BD_Shape< T >::difference_assign(), Parma_Polyhedra_Library::BD_Shape< T >::H79_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::limited_H79_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::max_min(), Parma_Polyhedra_Library::NNC_Polyhedron::NNC_Polyhedron(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), and Parma_Polyhedra_Library::BD_Shape< T >::time_elapse_assign().
05393 { 05394 Constraint_System cs; 05395 const dimension_type space_dim = space_dimension(); 05396 if (space_dim == 0) { 05397 if (marked_empty()) 05398 cs = Constraint_System::zero_dim_empty(); 05399 } 05400 else if (marked_empty()) 05401 cs.insert(0*Variable(space_dim-1) <= -1); 05402 else if (marked_shortest_path_reduced()) 05403 // Disregard redundant constraints. 05404 cs = minimized_constraints(); 05405 else { 05406 // KLUDGE: in the future `cs' will be constructed of the right dimension. 05407 // For the time being, we force the dimension with the following line. 05408 cs.insert(0*Variable(space_dim-1) <= 0); 05409 05410 PPL_DIRTY_TEMP_COEFFICIENT(a); 05411 PPL_DIRTY_TEMP_COEFFICIENT(b); 05412 // Go through all the unary constraints in `dbm'. 05413 const DB_Row<N>& dbm_0 = dbm[0]; 05414 for (dimension_type j = 1; j <= space_dim; ++j) { 05415 const Variable x(j-1); 05416 const N& dbm_0j = dbm_0[j]; 05417 const N& dbm_j0 = dbm[j][0]; 05418 if (is_additive_inverse(dbm_j0, dbm_0j)) { 05419 // We have a unary equality constraint. 05420 numer_denom(dbm_0j, b, a); 05421 cs.insert(a*x == b); 05422 } 05423 else { 05424 // We have 0, 1 or 2 unary inequality constraints. 05425 if (!is_plus_infinity(dbm_0j)) { 05426 numer_denom(dbm_0j, b, a); 05427 cs.insert(a*x <= b); 05428 } 05429 if (!is_plus_infinity(dbm_j0)) { 05430 numer_denom(dbm_j0, b, a); 05431 cs.insert(-a*x <= b); 05432 } 05433 } 05434 } 05435 05436 // Go through all the binary constraints in `dbm'. 05437 for (dimension_type i = 1; i <= space_dim; ++i) { 05438 const Variable y(i-1); 05439 const DB_Row<N>& dbm_i = dbm[i]; 05440 for (dimension_type j = i + 1; j <= space_dim; ++j) { 05441 const Variable x(j-1); 05442 const N& dbm_ij = dbm_i[j]; 05443 const N& dbm_ji = dbm[j][i]; 05444 if (is_additive_inverse(dbm_ji, dbm_ij)) { 05445 // We have a binary equality constraint. 05446 numer_denom(dbm_ij, b, a); 05447 cs.insert(a*x - a*y == b); 05448 } 05449 else { 05450 // We have 0, 1 or 2 binary inequality constraints. 05451 if (!is_plus_infinity(dbm_ij)) { 05452 numer_denom(dbm_ij, b, a); 05453 cs.insert(a*x - a*y <= b); 05454 } 05455 if (!is_plus_infinity(dbm_ji)) { 05456 numer_denom(dbm_ji, b, a); 05457 cs.insert(a*y - a*x <= b); 05458 } 05459 } 05460 } 05461 } 05462 } 05463 return cs; 05464 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::contains | ( | const BD_Shape< T > & | y | ) | const [inline] |
Returns true if and only if *this contains y.
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 578 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::BD_Shape< T >::difference_assign(), Parma_Polyhedra_Library::BD_Shape< T >::limited_BHMZ05_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::strictly_contains().
00578 { 00579 const BD_Shape<T>& x = *this; 00580 const dimension_type x_space_dim = x.space_dimension(); 00581 00582 // Dimension-compatibility check. 00583 if (x_space_dim != y.space_dimension()) 00584 throw_dimension_incompatible("contains(y)", y); 00585 00586 // The zero-dimensional universe shape contains any other 00587 // dimension-compatible shape. 00588 // The zero-dimensional empty shape only contains another 00589 // zero-dimensional empty shape. 00590 if (x_space_dim == 0) { 00591 if (!marked_empty()) 00592 return true; 00593 else 00594 return y.marked_empty(); 00595 } 00596 00597 /* 00598 The `y' bounded difference shape need be closed. 00599 In fact if, for example, in `*this' we have the constraints: 00600 00601 x1 - x2 <= 1; 00602 x1 <= 3; 00603 x2 <= 2; 00604 00605 in `y' the constraints are: 00606 00607 x1 - x2 <= 0; 00608 x2 <= 1; 00609 00610 without closure it returns "false", instead if we close `y' we have 00611 the implicit constraint 00612 00613 x1 <= 1; 00614 00615 and so we obtain the right result "true". 00616 */ 00617 y.shortest_path_closure_assign(); 00618 00619 // An empty shape is contained in any other dimension-compatible shapes. 00620 if (y.marked_empty()) 00621 return true; 00622 00623 // `*this' contains `y' if and only if every cell of `dbm' 00624 // is greater than or equal to the correspondent one of `y.dbm'. 00625 for (dimension_type i = x_space_dim + 1; i-- > 0; ) { 00626 const DB_Row<N>& x_dbm_i = x.dbm[i]; 00627 const DB_Row<N>& y_dbm_i = y.dbm[i]; 00628 for (dimension_type j = x_space_dim + 1; j-- > 0; ) 00629 if (x_dbm_i[j] < y_dbm_i[j]) 00630 return false; 00631 } 00632 return true; 00633 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::contains_integer_point | ( | ) | const [inline] |
Returns true if and only if *this contains at least one integer point.
Definition at line 724 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().
00724 { 00725 // Force shortest-path closure. 00726 if (is_empty()) 00727 return false; 00728 00729 const dimension_type space_dim = space_dimension(); 00730 if (space_dim == 0) 00731 return true; 00732 00733 // A non-empty BD_Shape defined by integer constraints 00734 // necessarily contains an integer point. 00735 if (std::numeric_limits<T>::is_integer) 00736 return true; 00737 00738 // Build an integer BD_Shape z with bounds at least as tight as 00739 // those in *this and then recheck for emptiness. 00740 BD_Shape<mpz_class> bds_z(space_dim); 00741 typedef BD_Shape<mpz_class>::N Z; 00742 bds_z.reset_shortest_path_closed(); 00743 PPL_DIRTY_TEMP(N, tmp); 00744 bool all_integers = true; 00745 for (dimension_type i = space_dim + 1; i-- > 0; ) { 00746 DB_Row<Z>& z_i = bds_z.dbm[i]; 00747 const DB_Row<N>& dbm_i = dbm[i]; 00748 for (dimension_type j = space_dim + 1; j-- > 0; ) { 00749 const N& dbm_i_j = dbm_i[j]; 00750 if (is_plus_infinity(dbm_i_j)) 00751 continue; 00752 if (is_integer(dbm_i_j)) 00753 assign_r(z_i[j], dbm_i_j, ROUND_NOT_NEEDED); 00754 else { 00755 all_integers = false; 00756 Z& z_i_j = z_i[j]; 00757 // Copy dbm_i_j into z_i_j, but rounding downwards. 00758 neg_assign_r(tmp, dbm_i_j, ROUND_NOT_NEEDED); 00759 assign_r(z_i_j, tmp, ROUND_UP); 00760 neg_assign_r(z_i_j, z_i_j, ROUND_NOT_NEEDED); 00761 } 00762 } 00763 } 00764 return all_integers || !bds_z.is_empty(); 00765 }
| void Parma_Polyhedra_Library::BD_Shape< T >::deduce_u_minus_v_bounds | ( | dimension_type | v, | |
| dimension_type | last_v, | |||
| const Linear_Expression & | sc_expr, | |||
| Coefficient_traits::const_reference | sc_den, | |||
| const N & | minus_lb_v | |||
| ) | [inline, private] |
An helper function for the computation of affine relations.
For each dbm index u (less than or equal to last_v and different from v), deduce constraints of the form u - v <= c, starting from minus_lb_v which is a lower bound for v.
The shortest-path closure is able to deduce the constraint u - v <= ub_u - lb_v. We can be more precise if variable u played an active role in the computation of the lower bound for v, i.e., if the corresponding coefficient q == sc_expr[u]/sc_den is greater than zero. In particular:
q >= 1, then u - v <= lb_u - lb_v;0 < q < 1, then u - v <= (q*lb_u + (1-q)*ub_u) - lb_v. Definition at line 3307 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), and Parma_Polyhedra_Library::is_plus_infinity().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::BD_Shape< T >::refine().
03311 { 03312 PPL_ASSERT(sc_den > 0); 03313 PPL_ASSERT(!is_plus_infinity(minus_lb_v)); 03314 // Deduce constraints of the form `u - v', where `u != v'. 03315 // Note: the shortest-path closure is able to deduce the constraint 03316 // `u - v <= ub_u - lb_v'. We can be more precise if variable `u' 03317 // played an active role in the computation of the lower bound for `v', 03318 // i.e., if the corresponding coefficient `q == expr_u/den' is 03319 // greater than zero. In particular: 03320 // if `q >= 1', then `u - v <= lb_u - lb_v'; 03321 // if `0 < q < 1', then `u - v <= (q*lb_u + (1-q)*ub_u) - lb_v'. 03322 PPL_DIRTY_TEMP0(mpq_class, mpq_sc_den); 03323 assign_r(mpq_sc_den, sc_den, ROUND_NOT_NEEDED); 03324 DB_Row<N>& dbm_0 = dbm[0]; 03325 DB_Row<N>& dbm_v = dbm[v]; 03326 // Speculative allocation of temporaries to be used in the following loop. 03327 PPL_DIRTY_TEMP0(mpq_class, ub_u); 03328 PPL_DIRTY_TEMP0(mpq_class, q); 03329 PPL_DIRTY_TEMP0(mpq_class, minus_lb_u); 03330 PPL_DIRTY_TEMP(N, up_approx); 03331 // No need to consider indices greater than `last_v'. 03332 for (dimension_type u = last_v; u > 0; --u) 03333 if (u != v) { 03334 const Coefficient& expr_u = sc_expr.coefficient(Variable(u-1)); 03335 if (expr_u > 0) { 03336 if (expr_u >= sc_den) 03337 // Deducing `u - v <= lb_u - lb_v', 03338 // i.e., `u - v <= (-lb_v) - (-lb_u)'. 03339 sub_assign_r(dbm_v[u], minus_lb_v, dbm[u][0], ROUND_UP); 03340 else { 03341 const N& dbm_0u = dbm_0[u]; 03342 if (!is_plus_infinity(dbm_0u)) { 03343 // Let `ub_u' and `lb_u' be the known upper and lower bound 03344 // for `u', respectively. Letting `q = expr_u/sc_den' be the 03345 // rational coefficient of `u' in `sc_expr/sc_den', 03346 // the upper bound for `u - v' is computed as 03347 // `(q * lb_u + (1-q) * ub_u) - lb_v', i.e., 03348 // `ub_u - q * (ub_u + (-lb_u)) + minus_lb_v'. 03349 assign_r(ub_u, dbm_0u, ROUND_NOT_NEEDED); 03350 assign_r(q, expr_u, ROUND_NOT_NEEDED); 03351 div_assign_r(q, q, mpq_sc_den, ROUND_NOT_NEEDED); 03352 assign_r(minus_lb_u, dbm[u][0], ROUND_NOT_NEEDED); 03353 // Compute `ub_u - lb_u'. 03354 add_assign_r(minus_lb_u, minus_lb_u, ub_u, ROUND_NOT_NEEDED); 03355 // Compute `ub_u - q * (ub_u - lb_u)'. 03356 sub_mul_assign_r(ub_u, q, minus_lb_u, ROUND_NOT_NEEDED); 03357 assign_r(up_approx, ub_u, ROUND_UP); 03358 // Deducing `u - v <= (q*lb_u + (1-q)*ub_u) - lb_v'. 03359 add_assign_r(dbm_v[u], up_approx, minus_lb_v, ROUND_UP); 03360 } 03361 } 03362 } 03363 } 03364 }
| void Parma_Polyhedra_Library::BD_Shape< T >::deduce_v_minus_u_bounds | ( | dimension_type | v, | |
| dimension_type | last_v, | |||
| const Linear_Expression & | sc_expr, | |||
| Coefficient_traits::const_reference | sc_den, | |||
| const N & | ub_v | |||
| ) | [inline, private] |
An helper function for the computation of affine relations.
For each dbm index u (less than or equal to last_v and different from v), deduce constraints of the form v - u <= c, starting from ub_v which is an upper bound for v.
The shortest-path closure is able to deduce the constraint v - u <= ub_v - lb_u. We can be more precise if variable u played an active role in the computation of the upper bound for v, i.e., if the corresponding coefficient q == sc_expr[u]/sc_den is greater than zero. In particular:
q >= 1, then v - u <= ub_v - ub_u;0 < q < 1, then v - u <= ub_v - (q*ub_u + (1-q)*lb_u). Definition at line 3246 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), and Parma_Polyhedra_Library::is_plus_infinity().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::BD_Shape< T >::refine().
03250 { 03251 PPL_ASSERT(sc_den > 0); 03252 PPL_ASSERT(!is_plus_infinity(ub_v)); 03253 // Deduce constraints of the form `v - u', where `u != v'. 03254 // Note: the shortest-path closure is able to deduce the constraint 03255 // `v - u <= ub_v - lb_u'. We can be more precise if variable `u' 03256 // played an active role in the computation of the upper bound for `v', 03257 // i.e., if the corresponding coefficient `q == expr_u/den' is 03258 // greater than zero. In particular: 03259 // if `q >= 1', then `v - u <= ub_v - ub_u'; 03260 // if `0 < q < 1', then `v - u <= ub_v - (q*ub_u + (1-q)*lb_u)'. 03261 PPL_DIRTY_TEMP0(mpq_class, mpq_sc_den); 03262 assign_r(mpq_sc_den, sc_den, ROUND_NOT_NEEDED); 03263 const DB_Row<N>& dbm_0 = dbm[0]; 03264 // Speculative allocation of temporaries to be used in the following loop. 03265 PPL_DIRTY_TEMP0(mpq_class, minus_lb_u); 03266 PPL_DIRTY_TEMP0(mpq_class, q); 03267 PPL_DIRTY_TEMP0(mpq_class, ub_u); 03268 PPL_DIRTY_TEMP(N, up_approx); 03269 // No need to consider indices greater than `last_v'. 03270 for (dimension_type u = last_v; u > 0; --u) 03271 if (u != v) { 03272 const Coefficient& expr_u = sc_expr.coefficient(Variable(u-1)); 03273 if (expr_u > 0) { 03274 if (expr_u >= sc_den) 03275 // Deducing `v - u <= ub_v - ub_u'. 03276 sub_assign_r(dbm[u][v], ub_v, dbm_0[u], ROUND_UP); 03277 else { 03278 DB_Row<N>& dbm_u = dbm[u]; 03279 const N& dbm_u0 = dbm_u[0]; 03280 if (!is_plus_infinity(dbm_u0)) { 03281 // Let `ub_u' and `lb_u' be the known upper and lower bound 03282 // for `u', respectively. Letting `q = expr_u/sc_den' be the 03283 // rational coefficient of `u' in `sc_expr/sc_den', 03284 // the upper bound for `v - u' is computed as 03285 // `ub_v - (q * ub_u + (1-q) * lb_u)', i.e., 03286 // `ub_v + (-lb_u) - q * (ub_u + (-lb_u))'. 03287 assign_r(minus_lb_u, dbm_u0, ROUND_NOT_NEEDED); 03288 assign_r(q, expr_u, ROUND_NOT_NEEDED); 03289 div_assign_r(q, q, mpq_sc_den, ROUND_NOT_NEEDED); 03290 assign_r(ub_u, dbm_0[u], ROUND_NOT_NEEDED); 03291 // Compute `ub_u - lb_u'. 03292 add_assign_r(ub_u, ub_u, minus_lb_u, ROUND_NOT_NEEDED); 03293 // Compute `(-lb_u) - q * (ub_u - lb_u)'. 03294 sub_mul_assign_r(minus_lb_u, q, ub_u, ROUND_NOT_NEEDED); 03295 assign_r(up_approx, minus_lb_u, ROUND_UP); 03296 // Deducing `v - u <= ub_v - (q * ub_u + (1-q) * lb_u)'. 03297 add_assign_r(dbm_u[v], ub_v, up_approx, ROUND_UP); 03298 } 03299 } 03300 } 03301 } 03302 }
| void Parma_Polyhedra_Library::BD_Shape< T >::difference_assign | ( | const BD_Shape< T > & | y | ) | [inline] |
Assigns to *this the smallest BD shape containing the set difference of *this and y.
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 2317 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::BD_Shape< T >::constraints(), Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Poly_Con_Relation::implies(), Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::relation_with(), Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign().
02317 { 02318 const dimension_type space_dim = space_dimension(); 02319 02320 // Dimension-compatibility check. 02321 if (space_dim != y.space_dimension()) 02322 throw_dimension_incompatible("difference_assign(y)", y); 02323 02324 BD_Shape new_bd_shape(space_dim, EMPTY); 02325 02326 BD_Shape& x = *this; 02327 02328 x.shortest_path_closure_assign(); 02329 // The difference of an empty bounded difference shape 02330 // and of a bounded difference shape `p' is empty. 02331 if (x.marked_empty()) 02332 return; 02333 y.shortest_path_closure_assign(); 02334 // The difference of a bounded difference shape `p' 02335 // and an empty bounded difference shape is `p'. 02336 if (y.marked_empty()) 02337 return; 02338 02339 // If both bounded difference shapes are zero-dimensional, 02340 // then at this point they are necessarily universe system of 02341 // bounded differences, so that their difference is empty. 02342 if (space_dim == 0) { 02343 x.set_empty(); 02344 return; 02345 } 02346 02347 // TODO: This is just an executable specification. 02348 // Have to find a more efficient method. 02349 if (y.contains(x)) { 02350 x.set_empty(); 02351 return; 02352 } 02353 02354 // We take a constraint of the system y at the time and we 02355 // consider its complementary. Then we intersect the union 02356 // of these complementaries with the system x. 02357 const Constraint_System& y_cs = y.constraints(); 02358 for (Constraint_System::const_iterator i = y_cs.begin(), 02359 y_cs_end = y_cs.end(); i != y_cs_end; ++i) { 02360 const Constraint& c = *i; 02361 // If the bounded difference shape `x' is included 02362 // in the bounded difference shape defined by `c', 02363 // then `c' _must_ be skipped, as adding its complement to `x' 02364 // would result in the empty bounded difference shape, 02365 // and as we would obtain a result that is less precise 02366 // than the bds-difference. 02367 if (x.relation_with(c).implies(Poly_Con_Relation::is_included())) 02368 continue; 02369 BD_Shape z = x; 02370 const Linear_Expression e = Linear_Expression(c); 02371 z.add_constraint(e <= 0); 02372 if (!z.is_empty()) 02373 new_bd_shape.upper_bound_assign(z); 02374 if (c.is_equality()) { 02375 z = x; 02376 z.add_constraint(e >= 0); 02377 if (!z.is_empty()) 02378 new_bd_shape.upper_bound_assign(z); 02379 } 02380 } 02381 *this = new_bd_shape; 02382 PPL_ASSERT(OK()); 02383 }
| void Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points | ( | const Variables_Set & | vars, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) | [inline] |
Possibly tightens *this by dropping some 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 | The maximal complexity of any algorithms used. |
complexity is ANY_COMPLEXITY. Definition at line 5659 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points_helper(), Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::Variables_Set::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().
05660 { 05661 // Dimension-compatibility check. 05662 const dimension_type space_dim = space_dimension(); 05663 const dimension_type min_space_dim = vars.space_dimension(); 05664 if (space_dim < min_space_dim) 05665 throw_dimension_incompatible("drop_some_non_integer_points(vs, cmpl)", 05666 min_space_dim); 05667 05668 if (std::numeric_limits<T>::is_integer || min_space_dim == 0) 05669 return; 05670 05671 shortest_path_closure_assign(); 05672 if (marked_empty()) 05673 return; 05674 05675 const Variables_Set::const_iterator v_begin = vars.begin(); 05676 const Variables_Set::const_iterator v_end = vars.end(); 05677 PPL_ASSERT(v_begin != v_end); 05678 // Unary constraints on a variable occurring in `vars'. 05679 DB_Row<N>& dbm_0 = dbm[0]; 05680 for (Variables_Set::const_iterator v_i = v_begin; v_i != v_end; ++v_i) { 05681 const dimension_type i = *v_i + 1; 05682 drop_some_non_integer_points_helper(dbm_0[i]); 05683 drop_some_non_integer_points_helper(dbm[i][0]); 05684 } 05685 05686 // Binary constraints where both variables occur in `vars'. 05687 for (Variables_Set::const_iterator v_i = v_begin; v_i != v_end; ++v_i) { 05688 const dimension_type i = *v_i + 1; 05689 DB_Row<N>& dbm_i = dbm[i]; 05690 for (Variables_Set::const_iterator v_j = v_begin; v_j != v_end; ++v_j) { 05691 const dimension_type j = *v_j + 1; 05692 if (i != j) 05693 drop_some_non_integer_points_helper(dbm_i[j]); 05694 } 05695 } 05696 PPL_ASSERT(OK()); 05697 }
| void Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points | ( | Complexity_Class | complexity = ANY_COMPLEXITY |
) | [inline] |
Possibly tightens *this by dropping some points with non-integer coordinates.
| complexity | The maximal complexity of any algorithms used. |
complexity is ANY_COMPLEXITY. Definition at line 5639 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points_helper(), Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().
05639 { 05640 if (std::numeric_limits<T>::is_integer) 05641 return; 05642 05643 const dimension_type space_dim = space_dimension(); 05644 shortest_path_closure_assign(); 05645 if (space_dim == 0 || marked_empty()) 05646 return; 05647 05648 for (dimension_type i = space_dim + 1; i-- > 0; ) { 05649 DB_Row<N>& dbm_i = dbm[i]; 05650 for (dimension_type j = space_dim + 1; j-- > 0; ) 05651 if (i != j) 05652 drop_some_non_integer_points_helper(dbm_i[j]); 05653 } 05654 PPL_ASSERT(OK()); 05655 }
| void Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points_helper | ( | N & | elem | ) | [inline, private] |
Definition at line 842 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), and Parma_Polyhedra_Library::Checked::Result.
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points().
00842 { 00843 if (!is_integer(elem)) { 00844 Result r = floor_assign_r(elem, elem, ROUND_DOWN); 00845 used(r); 00846 PPL_ASSERT(r == V_EQ); 00847 reset_shortest_path_closed(); 00848 } 00849 }
| void Parma_Polyhedra_Library::BD_Shape< T >::expand_space_dimension | ( | Variable | var, | |
| dimension_type | m | |||
| ) | [inline] |
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 5551 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::max_space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().
05551 { 05552 dimension_type old_dim = space_dimension(); 05553 // `var' should be one of the dimensions of the vector space. 05554 if (var.space_dimension() > old_dim) 05555 throw_dimension_incompatible("expand_space_dimension(v, m)", "v", var); 05556 05557 // The space dimension of the resulting BDS should not 05558 // overflow the maximum allowed space dimension. 05559 if (m > max_space_dimension() - space_dimension()) 05560 throw_generic("expand_dimension(v, m)", 05561 "adding m new space dimensions exceeds " 05562 "the maximum allowed space dimension"); 05563 05564 // Nothing to do, if no dimensions must be added. 05565 if (m == 0) 05566 return; 05567 05568 // Add the required new dimensions. 05569 add_space_dimensions_and_embed(m); 05570 05571 // For each constraints involving variable `var', we add a 05572 // similar constraint with the new variable substituted for 05573 // variable `var'. 05574 const dimension_type v_id = var.id() + 1; 05575 const DB_Row<N>& dbm_v = dbm[v_id]; 05576 for (dimension_type i = old_dim + 1; i-- > 0; ) { 05577 DB_Row<N>& dbm_i = dbm[i]; 05578 const N& dbm_i_v = dbm[i][v_id]; 05579 const N& dbm_v_i = dbm_v[i]; 05580 for (dimension_type j = old_dim+1; j < old_dim+m+1; ++j) { 05581 dbm_i[j] = dbm_i_v; 05582 dbm[j][i] = dbm_v_i; 05583 } 05584 } 05585 // In general, adding a constraint does not preserve the shortest-path 05586 // closure or reduction of the bounded difference shape. 05587 if (marked_shortest_path_closed()) 05588 reset_shortest_path_closed(); 05589 PPL_ASSERT(OK()); 05590 }
| memory_size_type Parma_Polyhedra_Library::BD_Shape< T >::external_memory_in_bytes | ( | ) | const [inline] |
Returns the size in bytes of the memory managed by *this.
Definition at line 5835 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::Bit_Matrix::external_memory_in_bytes(), Parma_Polyhedra_Library::DB_Matrix< T >::external_memory_in_bytes(), and Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm.
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::total_memory_in_bytes().
05835 { 05836 return dbm.external_memory_in_bytes() 05837 + redundancy_dbm.external_memory_in_bytes(); 05838 }
| void Parma_Polyhedra_Library::BD_Shape< T >::fold_space_dimensions | ( | const Variables_Set & | vars, | |
| Variable | dest | |||
| ) | [inline] |
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 5594 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::max_assign(), Parma_Polyhedra_Library::BD_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::Variables_Set::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().
05595 { 05596 const dimension_type space_dim = space_dimension(); 05597 // `dest' should be one of the dimensions of the BDS. 05598 if (dest.space_dimension() > space_dim) 05599 throw_dimension_incompatible("fold_space_dimensions(vs, v)", 05600 "v", dest); 05601 05602 // The folding of no dimensions is a no-op. 05603 if (vars.empty()) 05604 return; 05605 05606 // All variables in `vars' should be dimensions of the BDS. 05607 if (vars.space_dimension() > space_dim) 05608 throw_dimension_incompatible("fold_space_dimensions(vs, v)", 05609 vars.space_dimension()); 05610 05611 // Moreover, `dest.id()' should not occur in `vars'. 05612 if (vars.find(dest.id()) != vars.end()) 05613 throw_generic("fold_space_dimensions(vs, v)", 05614 "v should not occur in vs"); 05615 05616 shortest_path_closure_assign(); 05617 if (!marked_empty()) { 05618 // Recompute the elements of the row and the column corresponding 05619 // to variable `dest' by taking the join of their value with the 05620 // value of the corresponding elements in the row and column of the 05621 // variable `vars'. 05622 const dimension_type v_id = dest.id() + 1; 05623 DB_Row<N>& dbm_v = dbm[v_id]; 05624 for (Variables_Set::const_iterator i = vars.begin(), 05625 vs_end = vars.end(); i != vs_end; ++i) { 05626 const dimension_type tbf_id = *i + 1; 05627 const DB_Row<N>& dbm_tbf = dbm[tbf_id]; 05628 for (dimension_type j = space_dim + 1; j-- > 0; ) { 05629 max_assign(dbm[j][v_id], dbm[j][tbf_id]); 05630 max_assign(dbm_v[j], dbm_tbf[j]); 05631 } 05632 } 05633 } 05634 remove_space_dimensions(vars); 05635 }
| void Parma_Polyhedra_Library::BD_Shape< T >::forget_all_dbm_constraints | ( | dimension_type | v | ) | [inline, private] |
Removes all the constraints on row/column v.
Definition at line 3368 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::DB_Matrix< T >::num_rows(), and Parma_Polyhedra_Library::PLUS_INFINITY.
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), and Parma_Polyhedra_Library::BD_Shape< T >::unconstrain().
03368 { 03369 PPL_ASSERT(0 < v && v <= dbm.num_rows()); 03370 DB_Row<N>& dbm_v = dbm[v]; 03371 for (dimension_type i = dbm.num_rows(); i-- > 0; ) { 03372 assign_r(dbm_v[i], PLUS_INFINITY, ROUND_NOT_NEEDED); 03373 assign_r(dbm[i][v], PLUS_INFINITY, ROUND_NOT_NEEDED); 03374 } 03375 }
| void Parma_Polyhedra_Library::BD_Shape< T >::forget_binary_dbm_constraints | ( | dimension_type | v | ) | [inline, private] |
Removes all binary constraints on row/column v.
Definition at line 3379 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::DB_Matrix< T >::num_rows(), and Parma_Polyhedra_Library::PLUS_INFINITY.
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), and Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image().
03379 { 03380 PPL_ASSERT(0 < v && v <= dbm.num_rows()); 03381 DB_Row<N>& dbm_v = dbm[v]; 03382 for (dimension_type i = dbm.num_rows()-1; i > 0; --i) { 03383 assign_r(dbm_v[i], PLUS_INFINITY, ROUND_NOT_NEEDED); 03384 assign_r(dbm[i][v], PLUS_INFINITY, ROUND_NOT_NEEDED); 03385 } 03386 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::frequency | ( | const Linear_Expression & | expr, | |
| Coefficient & | freq_n, | |||
| Coefficient & | freq_d, | |||
| Coefficient & | val_n, | |||
| Coefficient & | val_d | |||
| ) | const [inline] |
Returns true if and only if there exist a unique value val such that *this saturates the equality expr = val.
| expr | The linear expression for which the frequency is needed; | |
| freq_n | If true is returned, the value is set to ; Present for interface compatibility with class Grid, where the frequency can have a non-zero value; | |
| freq_d | If true is returned, the value is set to ; | |
| val_n | The numerator of val; | |
| val_d | The denominator of val; |
| std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
If false is returned, then freq_n, freq_d, val_n and val_d are left untouched.
Definition at line 769 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::Checked::le, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::normalize2(), Parma_Polyhedra_Library::DB_Matrix< T >::num_rows(), Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().
00771 { 00772 dimension_type space_dim = space_dimension(); 00773 // The dimension of `expr' must be at most the dimension of *this. 00774 if (space_dim < expr.space_dimension()) 00775 throw_dimension_incompatible("frequency(e, ...)", "e", expr); 00776 00777 // Check if `expr' has a constant value. 00778 // If it is constant, set the frequency `freq_n' to 0 00779 // and return true. Otherwise the values for \p expr 00780 // are not discrete so return false. 00781 00782 // Space dimension = 0: if empty, then return false; 00783 // otherwise the frequency is 0 and the value is the inhomogeneous term. 00784 if (space_dim == 0) { 00785 if (is_empty()) 00786 return false; 00787 freq_n = 0; 00788 freq_d = 1; 00789 val_n = expr.inhomogeneous_term(); 00790 val_d = 1; 00791 return true; 00792 } 00793 00794 shortest_path_closure_assign(); 00795 // For an empty BD shape, we simply return false. 00796 if (marked_empty()) 00797 return false; 00798 00799 // The BD shape has at least 1 dimension and is not empty. 00800 PPL_DIRTY_TEMP_COEFFICIENT(coeff); 00801 PPL_DIRTY_TEMP_COEFFICIENT(num); 00802 PPL_DIRTY_TEMP_COEFFICIENT(den); 00803 PPL_DIRTY_TEMP(N, tmp); 00804 Linear_Expression le = expr; 00805 // Boolean to keep track of a variable `v' in expression `le'. 00806 // If we can replace `v' by an expression using variables other 00807 // than `v' and are already in `le', then this is set to true. 00808 bool constant_v = false; 00809 00810 PPL_DIRTY_TEMP_COEFFICIENT(val_den); 00811 val_den = 1; 00812 00813 for (dimension_type i = dbm.num_rows(); i-- > 1; ) { 00814 constant_v = false; 00815 const Variable v(i-1); 00816 coeff = le.coefficient(v); 00817 if (coeff == 0) { 00818 constant_v = true; 00819 continue; 00820 } 00821 00822 const DB_Row<N>& dbm_i = dbm[i]; 00823 // Check if `v' is constant in the BD shape. 00824 assign_r(tmp, dbm_i[0], ROUND_NOT_NEEDED); 00825 if (is_additive_inverse(dbm[0][i], tmp)) { 00826 // If `v' is constant, replace it in `le' by the value. 00827 numer_denom(tmp, num, den); 00828 le -= coeff*v; 00829 le *= den; 00830 le -= num*coeff; 00831 val_den *= den; 00832 constant_v = true; 00833 continue; 00834 } 00835 // Check the bounded differences with the other dimensions that 00836 // have non-zero coefficient in `le'. 00837 else { 00838 PPL_ASSERT(!constant_v); 00839 for (dimension_type j = i; j-- > 1; ) { 00840 const Variable vj(j-1); 00841 if (le.coefficient(vj) == 0) 00842 // The coefficient in `le' is 0, so do nothing. 00843 continue; 00844 assign_r(tmp, dbm_i[j], ROUND_NOT_NEEDED); 00845 if (is_additive_inverse(dbm[j][i], tmp)) { 00846 // The coefficient for `vj' in `le' is not 0 00847 // and the difference with `v' in the BD shape is constant. 00848 // So apply this equality to eliminate `v' in `le'. 00849 numer_denom(tmp, num, den); 00850 le -= coeff*v - coeff*vj; 00851 le *= den; 00852 le -= num*coeff; 00853 val_den *= den; 00854 constant_v = true; 00855 break; 00856 } 00857 } 00858 if (!constant_v) 00859 // The expression `expr' is not constant. 00860 return false; 00861 } 00862 } 00863 if (!constant_v) 00864 // The expression `expr' is not constant. 00865 return false; 00866 00867 // The expression `expr' is constant. 00868 freq_n = 0; 00869 freq_d = 1; 00870 00871 // Reduce `val_n' and `val_d'. 00872 normalize2(le.inhomogeneous_term(), val_den, val_n, val_d); 00873 return true; 00874 }
| void Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image | ( | const Linear_Expression & | lhs, | |
| Relation_Symbol | relsym, | |||
| const Linear_Expression & | rhs | |||
| ) | [inline] |
Assigns to *this the image of *this with respect to the affine relation
, where
is the relation symbol encoded by relsym.
| lhs | The left hand side affine expression. | |
| relsym | The relation symbol. | |
| rhs | The right hand side affine expression. |
| std::invalid_argument | Thrown if *this is dimension-incompatible with lhs or rhs or if relsym is a strict relation symbol. |
Definition at line 4967 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::BD_Shape< T >::forget_all_dbm_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::NOT_EQUAL, Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().
04969 { 04970 // Dimension-compatibility checks. 04971 // The dimension of `lhs' should not be greater than the dimension 04972 // of `*this'. 04973 const dimension_type space_dim = space_dimension(); 04974 const dimension_type lhs_space_dim = lhs.space_dimension(); 04975 if (space_dim < lhs_space_dim) 04976 throw_dimension_incompatible("generalized_affine_image(e1, r, e2)", 04977 "e1", lhs); 04978 04979 // The dimension of `rhs' should not be greater than the dimension 04980 // of `*this'. 04981 const dimension_type rhs_space_dim = rhs.space_dimension(); 04982 if (space_dim < rhs_space_dim) 04983 throw_dimension_incompatible("generalized_affine_image(e1, r, e2)", 04984 "e2", rhs); 04985 04986 // Strict relation symbols are not admitted for BDSs. 04987 if (relsym == LESS_THAN || relsym == GREATER_THAN) 04988 throw_generic("generalized_affine_image(e1, r, e2)", 04989 "r is a strict relation symbol and " 04990 "*this is a BD_Shape"); 04991 // The relation symbol cannot be a disequality. 04992 if (relsym == NOT_EQUAL) 04993 throw_generic("generalized_affine_image(e1, r, e2)", 04994 "r is the disequality relation symbol and " 04995 "*this is a BD_Shape"); 04996 04997 // The image of an empty BDS is empty. 04998 shortest_path_closure_assign(); 04999 if (marked_empty()) 05000 return; 05001 05002 // Number of non-zero coefficients in `lhs': will be set to 05003 // 0, 1, or 2, the latter value meaning any value greater than 1. 05004 dimension_type t_lhs = 0; 05005 // Index of the last non-zero coefficient in `lhs', if any. 05006 dimension_type j_lhs = 0; 05007 // Compute the number of the non-zero components of `lhs'. 05008 for (dimension_type i = lhs_space_dim; i-- > 0; ) 05009 if (lhs.coefficient(Variable(i)) != 0) { 05010 if (t_lhs++ == 1) 05011 break; 05012 else 05013 j_lhs = i; 05014 } 05015 05016 const Coefficient& b_lhs = lhs.inhomogeneous_term(); 05017 05018 if (t_lhs == 0) { 05019 // `lhs' is a constant. 05020 // In principle, it is sufficient to add the constraint `lhs relsym rhs'. 05021 // Note that this constraint is a bounded difference if `t_rhs <= 1' 05022 // or `t_rhs > 1' and `rhs == a*v - a*w + b_rhs'. If `rhs' is of a 05023 // more general form, it will be simply ignored. 05024 // TODO: if it is not a bounded difference, should we compute 05025 // approximations for this constraint? 05026 switch (relsym) { 05027 case LESS_OR_EQUAL: 05028 refine_no_check(lhs <= rhs); 05029 break; 05030 case EQUAL: 05031 refine_no_check(lhs == rhs); 05032 break; 05033 case GREATER_OR_EQUAL: 05034 refine_no_check(lhs >= rhs); 05035 break; 05036 default: 05037 // We already dealt with the other cases. 05038 throw std::runtime_error("PPL internal error"); 05039 } 05040 } 05041 else if (t_lhs == 1) { 05042 // Here `lhs == a_lhs * v + b_lhs'. 05043 // Independently from the form of `rhs', we can exploit the 05044 // method computing generalized affine images for a single variable. 05045 Variable v(j_lhs); 05046 // Compute a sign-corrected relation symbol. 05047 const Coefficient& den = lhs.coefficient(v); 05048 Relation_Symbol new_relsym = relsym; 05049 if (den < 0) { 05050 if (relsym == LESS_OR_EQUAL) 05051 new_relsym = GREATER_OR_EQUAL; 05052 else if (relsym == GREATER_OR_EQUAL) 05053 new_relsym = LESS_OR_EQUAL; 05054 } 05055 Linear_Expression expr = rhs - b_lhs; 05056 generalized_affine_image(v, new_relsym, expr, den); 05057 } 05058 else { 05059 // Here `lhs' is of the general form, having at least two variables. 05060 // Compute the set of variables occurring in `lhs'. 05061 bool lhs_vars_intersects_rhs_vars = false; 05062 std::vector<Variable> lhs_vars; 05063 for (dimension_type i = lhs_space_dim; i-- > 0; ) 05064 if (lhs.coefficient(Variable(i)) != 0) { 05065 lhs_vars.push_back(Variable(i)); 05066 if (rhs.coefficient(Variable(i)) != 0) 05067 lhs_vars_intersects_rhs_vars = true; 05068 } 05069 05070 if (!lhs_vars_intersects_rhs_vars) { 05071 // `lhs' and `rhs' variables are disjoint. 05072 // Existentially quantify all variables in the lhs. 05073 for (dimension_type i = lhs_vars.size(); i-- > 0; ) 05074 forget_all_dbm_constraints(lhs_vars[i].id() + 1); 05075 // Constrain the left hand side expression so that it is related to 05076 // the right hand side expression as dictated by `relsym'. 05077 // TODO: if the following constraint is NOT a bounded difference, 05078 // it will be simply ignored. Should we compute approximations for it? 05079 switch (relsym) { 05080 case LESS_OR_EQUAL: 05081 refine_no_check(lhs <= rhs); 05082 break; 05083 case EQUAL: 05084 refine_no_check(lhs == rhs); 05085 break; 05086 case GREATER_OR_EQUAL: 05087 refine_no_check(lhs >= rhs); 05088 break; 05089 default: 05090 // We already dealt with the other cases. 05091 throw std::runtime_error("PPL internal error"); 05092 } 05093 } 05094 else { 05095 // Some variables in `lhs' also occur in `rhs'. 05096 05097 #if 1 // Simplified computation (see the TODO note below). 05098 05099 for (dimension_type i = lhs_vars.size(); i-- > 0; ) 05100 forget_all_dbm_constraints(lhs_vars[i].id() + 1); 05101 05102 #else // Currently unnecessarily complex computation. 05103 05104 // More accurate computation that is worth doing only if 05105 // the following TODO note is accurately dealt with. 05106 05107 // To ease the computation, we add an additional dimension. 05108 const Variable new_var = Variable(space_dim); 05109 add_space_dimensions_and_embed(1); 05110 // Constrain the new dimension to be equal to `rhs'. 05111 // NOTE: calling affine_image() instead of refine_no_check() 05112 // ensures some approximation is tried even when the constraint 05113 // is not a bounded difference. 05114 affine_image(new_var, rhs); 05115 // Existentially quantify all variables in the lhs. 05116 // NOTE: enforce shortest-path closure for precision. 05117 shortest_path_closure_assign(); 05118 PPL_ASSERT(!marked_empty()); 05119 for (dimension_type i = lhs_vars.size(); i-- > 0; ) 05120 forget_all_dbm_constraints(lhs_vars[i].id() + 1); 05121 // Constrain the new dimension so that it is related to 05122 // the left hand side as dictated by `relsym'. 05123 // TODO: each one of the following constraints is definitely NOT 05124 // a bounded differences (since it has 3 variables at least). 05125 // Thus, the method refine_no_check() will simply ignore it. 05126 // Should we compute approximations for this constraint? 05127 switch (relsym) { 05128 case LESS_OR_EQUAL: 05129 refine_no_check(lhs <= new_var); 05130 break; 05131 case EQUAL: 05132 refine_no_check(lhs == new_var); 05133 break; 05134 case GREATER_OR_EQUAL: 05135 refine_no_check(lhs >= new_var); 05136 break; 05137 default: 05138 // We already dealt with the other cases. 05139 throw std::runtime_error("PPL internal error"); 05140 } 05141 // Remove the temporarily added dimension. 05142 remove_higher_space_dimensions(space_dim-1); 05143 #endif // Currently unnecessarily complex computation. 05144 } 05145 } 05146 05147 PPL_ASSERT(OK()); 05148 }
| void Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image | ( | Variable | var, | |
| Relation_Symbol | relsym, | |||
| const Linear_Expression & | expr, | |||
| Coefficient_traits::const_reference | denominator = Coefficient_one() | |||
| ) | [inline] |
Assigns to *this the image of *this with respect to the affine relation
, where
is the relation symbol encoded by relsym.
| var | The left hand side variable of the generalized affine transfer function. | |
| relsym | The relation symbol. | |
| expr | The numerator of the right hand side affine expression. | |
| denominator | The denominator of the right hand side affine expression. |
| std::invalid_argument | Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a dimension of *this or if relsym is a strict relation symbol. |
Definition at line 4570 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::add_dbm_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::deduce_u_minus_v_bounds(), Parma_Polyhedra_Library::BD_Shape< T >::deduce_v_minus_u_bounds(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::BD_Shape< T >::forget_all_dbm_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::forget_binary_dbm_constraints(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::NOT_EQUAL, Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::PLUS_INFINITY, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage().
04574 { 04575 // The denominator cannot be zero. 04576 if (denominator == 0) 04577 throw_generic("generalized_affine_image(v, r, e, d)", "d == 0"); 04578 04579 // Dimension-compatibility checks. 04580 // The dimension of `expr' should not be greater than the dimension 04581 // of `*this'. 04582 const dimension_type space_dim = space_dimension(); 04583 const dimension_type expr_space_dim = expr.space_dimension(); 04584 if (space_dim < expr_space_dim) 04585 throw_dimension_incompatible("generalized_affine_image(v, r, e, d)", 04586 "e", expr); 04587 04588 // `var' should be one of the dimensions of the BDS. 04589 const dimension_type v = var.id() + 1; 04590 if (v > space_dim) 04591 throw_dimension_incompatible("generalized_affine_image(v, r, e, d)", 04592 var.id()); 04593 04594 // The relation symbol cannot be a strict relation symbol. 04595 if (relsym == LESS_THAN || relsym == GREATER_THAN) 04596 throw_generic("generalized_affine_image(v, r, e, d)", 04597 "r is a strict relation symbol and " 04598 "*this is a BD_Shape"); 04599 // The relation symbol cannot be a disequality. 04600 if (relsym == NOT_EQUAL) 04601 throw_generic("generalized_affine_image(v, r, e, d)", 04602 "r is the disequality relation symbol and " 04603 "*this is a BD_Shape"); 04604 04605 if (relsym == EQUAL) { 04606 // The relation symbol is "=": 04607 // this is just an affine image computation. 04608 affine_image(var, expr, denominator); 04609 return; 04610 } 04611 04612 // The image of an empty BDS is empty too. 04613 shortest_path_closure_assign(); 04614 if (marked_empty()) 04615 return; 04616 04617 const Coefficient& b = expr.inhomogeneous_term(); 04618 // Number of non-zero coefficients in `expr': will be set to 04619 // 0, 1, or 2, the latter value meaning any value greater than 1. 04620 dimension_type t = 0; 04621 // Index of the last non-zero coefficient in `expr', if any. 04622 dimension_type w = 0; 04623 // Get information about the number of non-zero coefficients in `expr'. 04624 for (dimension_type i = expr_space_dim; i-- > 0; ) 04625 if (expr.coefficient(Variable(i)) != 0) { 04626 if (t++ == 1) 04627 break; 04628 else 04629 w = i+1; 04630 } 04631 04632 // Now we know the form of `expr': 04633 // - If t == 0, then expr == b, with `b' a constant; 04634 // - If t == 1, then expr == a*w + b, where `w' can be `v' or another 04635 // variable; in this second case we have to check whether `a' is 04636 // equal to `denominator' or `-denominator', since otherwise we have 04637 // to fall back on the general form; 04638 // - If t == 2, the `expr' is of the general form. 04639 DB_Row<N>& dbm_0 = dbm[0]; 04640 DB_Row<N>& dbm_v = dbm[v]; 04641 PPL_DIRTY_TEMP_COEFFICIENT(minus_den); 04642 neg_assign(minus_den, denominator); 04643 04644 if (t == 0) { 04645 // Case 1: expr == b. 04646 // Remove all constraints on `var'. 04647 forget_all_dbm_constraints(v); 04648 // Both shortest-path closure and reduction are lost. 04649 reset_shortest_path_closed(); 04650 switch (relsym) { 04651 case LESS_OR_EQUAL: 04652 // Add the constraint `var <= b/denominator'. 04653 add_dbm_constraint(0, v, b, denominator); 04654 break; 04655 case GREATER_OR_EQUAL: 04656 // Add the constraint `var >= b/denominator', 04657 // i.e., `-var <= -b/denominator', 04658 add_dbm_constraint(v, 0, b, minus_den); 04659 break; 04660 default: 04661 // We already dealt with the other cases. 04662 throw std::runtime_error("PPL internal error"); 04663 } 04664 PPL_ASSERT(OK()); 04665 return; 04666 } 04667 04668 if (t == 1) { 04669 // Value of the one and only non-zero coefficient in `expr'. 04670 const Coefficient& a = expr.coefficient(Variable(w-1)); 04671 if (a == denominator || a == minus_den) { 04672 // Case 2: expr == a*w + b, with a == +/- denominator. 04673 PPL_DIRTY_TEMP(N, d); 04674 switch (relsym) { 04675 case LESS_OR_EQUAL: 04676 div_round_up(d, b, denominator); 04677 if (w == v) { 04678 // `expr' is of the form: a*v + b. 04679 // Shortest-path closure and reduction are not preserved. 04680 reset_shortest_path_closed(); 04681 if (a == denominator) { 04682 // Translate each constraint `v - w <= dbm_wv' 04683 // into the constraint `v - w <= dbm_wv + b/denominator'; 04684 // forget each constraint `w - v <= dbm_vw'. 04685 for (dimension_type i = space_dim + 1; i-- > 0; ) { 04686 N& dbm_iv = dbm[i][v]; 04687 add_assign_r(dbm_iv, dbm_iv, d, ROUND_UP); 04688 assign_r(dbm_v[i], PLUS_INFINITY, ROUND_NOT_NEEDED); 04689 } 04690 } 04691 else { 04692 // Here `a == -denominator'. 04693 // Translate the constraint `0 - v <= dbm_v0' 04694 // into the constraint `0 - v <= dbm_v0 + b/denominator'. 04695 N& dbm_v0 = dbm_v[0]; 04696 add_assign_r(dbm_0[v], dbm_v0, d, ROUND_UP); 04697 // Forget all the other constraints on `v'. 04698 assign_r(dbm_v0, PLUS_INFINITY, ROUND_NOT_NEEDED); 04699 forget_binary_dbm_constraints(v); 04700 } 04701 } 04702 else { 04703 // Here `w != v', so that `expr' is of the form 04704 // +/-denominator * w + b, with `w != v'. 04705 // Remove all constraints on `v'. 04706 forget_all_dbm_constraints(v); 04707 // Shortest-path closure is preserved, but not reduction. 04708 if (marked_shortest_path_reduced()) 04709 reset_shortest_path_reduced(); 04710 if (a == denominator) 04711 // Add the new constraint `v - w <= b/denominator'. 04712 add_dbm_constraint(w, v, d); 04713 else { 04714 // Here a == -denominator, so that we should be adding 04715 // the constraint `v <= b/denominator - w'. 04716 // Approximate it by computing a lower bound for `w'. 04717 const N& dbm_w0 = dbm[w][0]; 04718 if (!is_plus_infinity(dbm_w0)) { 04719 // Add the constraint `v <= b/denominator - lb_w'. 04720 add_assign_r(dbm_0[v], d, dbm_w0, ROUND_UP); 04721 // Shortest-path closure is not preserved. 04722 reset_shortest_path_closed(); 04723 } 04724 } 04725 } 04726 break; 04727 04728 case GREATER_OR_EQUAL: 04729 div_round_up(d, b, minus_den); 04730 if (w == v) { 04731 // `expr' is of the form: a*w + b. 04732 // Shortest-path closure and reduction are not preserved. 04733 reset_shortest_path_closed(); 04734 if (a == denominator) { 04735 // Translate each constraint `w - v <= dbm_vw' 04736 // into the constraint `w - v <= dbm_vw - b/denominator'; 04737 // forget each constraint `v - w <= dbm_wv'. 04738 for (dimension_type i = space_dim + 1; i-- > 0; ) { 04739 N& dbm_vi = dbm_v[i]; 04740 add_assign_r(dbm_vi, dbm_vi, d, ROUND_UP); 04741 assign_r(dbm[i][v], PLUS_INFINITY, ROUND_NOT_NEEDED); 04742 } 04743 } 04744 else { 04745 // Here `a == -denominator'. 04746 // Translate the constraint `0 - v <= dbm_v0' 04747 // into the constraint `0 - v <= dbm_0v - b/denominator'. 04748 N& dbm_0v = dbm_0[v]; 04749 add_assign_r(dbm_v[0], dbm_0v, d, ROUND_UP); 04750 // Forget all the other constraints on `v'. 04751 assign_r(dbm_0v, PLUS_INFINITY, ROUND_NOT_NEEDED); 04752 forget_binary_dbm_constraints(v); 04753 } 04754 } 04755 else { 04756 // Here `w != v', so that `expr' is of the form 04757 // +/-denominator * w + b, with `w != v'. 04758 // Remove all constraints on `v'. 04759 forget_all_dbm_constraints(v); 04760 // Shortest-path closure is preserved, but not reduction. 04761 if (marked_shortest_path_reduced()) 04762 reset_shortest_path_reduced(); 04763 if (a == denominator) 04764 // Add the new constraint `v - w >= b/denominator', 04765 // i.e., `w - v <= -b/denominator'. 04766 add_dbm_constraint(v, w, d); 04767 else { 04768 // Here a == -denominator, so that we should be adding 04769 // the constraint `v >= -w + b/denominator', 04770 // i.e., `-v <= w - b/denominator'. 04771 // Approximate it by computing an upper bound for `w'. 04772 const N& dbm_0w = dbm_0[w]; 04773 if (!is_plus_infinity(dbm_0w)) { 04774 // Add the constraint `-v <= ub_w - b/denominator'. 04775 add_assign_r(dbm_v[0], dbm_0w, d, ROUND_UP); 04776 // Shortest-path closure is not preserved. 04777 reset_shortest_path_closed(); 04778 } 04779 } 04780 } 04781 break; 04782 04783 default: 04784 // We already dealt with the other cases. 04785 throw std::runtime_error("PPL internal error"); 04786 } 04787 PPL_ASSERT(OK()); 04788 return; 04789 } 04790 } 04791 04792 // General case. 04793 // Either t == 2, so that 04794 // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2, 04795 // or t == 1, expr == a*w + b, but a <> +/- denominator. 04796 // We will remove all the constraints on `v' and add back 04797 // a constraint providing an upper or a lower bound for `v' 04798 // (depending on `relsym'). 04799 const bool is_sc = (denominator > 0); 04800 PPL_DIRTY_TEMP_COEFFICIENT(minus_b); 04801 neg_assign(minus_b, b); 04802 const Coefficient& sc_b = is_sc ? b : minus_b; 04803 const Coefficient& minus_sc_b = is_sc ? minus_b : b; 04804 const Coefficient& sc_den = is_sc ? denominator : minus_den; 04805 const Coefficient& minus_sc_den = is_sc ? minus_den : denominator; 04806 // NOTE: here, for optimization purposes, `minus_expr' is only assigned 04807 // when `denominator' is negative. Do not use it unless you are sure 04808 // it has been correctly assigned. 04809 Linear_Expression minus_expr; 04810 if (!is_sc) 04811 minus_expr = -expr; 04812 const Linear_Expression& sc_expr = is_sc ? expr : minus_expr; 04813 04814 PPL_DIRTY_TEMP(N, sum); 04815 // Index of variable that is unbounded in `this->dbm'. 04816 PPL_UNINITIALIZED(dimension_type, pinf_index); 04817 // Number of unbounded variables found. 04818 dimension_type pinf_count = 0; 04819 04820 // Speculative allocation of temporaries to be used in the following loops. 04821 PPL_DIRTY_TEMP(N, coeff_i); 04822 PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i); 04823 04824 switch (relsym) { 04825 case LESS_OR_EQUAL: 04826 // Compute an upper approximation for `sc_expr' into `sum'. 04827 04828 // Approximate the inhomogeneous term. 04829 assign_r(sum, sc_b, ROUND_UP); 04830 // Approximate the homogeneous part of `sc_expr'. 04831 // Note: indices above `w' can be disregarded, as they all have 04832 // a zero coefficient in `sc_expr'. 04833 for (dimension_type i = w; i > 0; --i) { 04834 const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1)); 04835 const int sign_i = sgn(sc_i); 04836 if (sign_i == 0) 04837 continue; 04838 // Choose carefully: we are approximating `sc_expr'. 04839 const N& approx_i = (sign_i > 0) ? dbm_0[i] : dbm[i][0]; 04840 if (is_plus_infinity(approx_i)) { 04841 if (++pinf_count > 1) 04842 break; 04843 pinf_index = i; 04844 continue; 04845 } 04846 if (sign_i > 0) 04847 assign_r(coeff_i, sc_i, ROUND_UP); 04848 else { 04849 neg_assign(minus_sc_i, sc_i); 04850 assign_r(coeff_i, minus_sc_i, ROUND_UP); 04851 } 04852 add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP); 04853 } 04854 04855 // Remove all constraints on `v'. 04856 forget_all_dbm_constraints(v); 04857 // Shortest-path closure is preserved, but not reduction. 04858 if (marked_shortest_path_reduced()) 04859 reset_shortest_path_reduced(); 04860 // Return immediately if no approximation could be computed. 04861 if (pinf_count > 1) { 04862 PPL_ASSERT(OK()); 04863 return; 04864 } 04865 04866 // Divide by the (sign corrected) denominator (if needed). 04867 if (sc_den != 1) { 04868 // Before computing the quotient, the denominator should be approximated 04869 // towards zero. Since `sc_den' is known to be positive, this amounts to 04870 // rounding downwards, which is achieved as usual by rounding upwards 04871 // `minus_sc_den' and negating again the result. 04872 PPL_DIRTY_TEMP(N, down_sc_den); 04873 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 04874 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 04875 div_assign_r(sum, sum, down_sc_den, ROUND_UP); 04876 } 04877 04878 if (pinf_count == 0) { 04879 // Add the constraint `v <= sum'. 04880 add_dbm_constraint(0, v, sum); 04881 // Deduce constraints of the form `v - u', where `u != v'. 04882 deduce_v_minus_u_bounds(v, w, sc_expr, sc_den, sum); 04883 } 04884 else if (pinf_count == 1) 04885 if (pinf_index != v 04886 && expr.coefficient(Variable(pinf_index-1)) == denominator) 04887 // Add the constraint `v - pinf_index <= sum'. 04888 add_dbm_constraint(pinf_index, v, sum); 04889 break; 04890 04891 case GREATER_OR_EQUAL: 04892 // Compute an upper approximation for `-sc_expr' into `sum'. 04893 // Note: approximating `-sc_expr' from above and then negating the 04894 // result is the same as approximating `sc_expr' from below. 04895 04896 // Approximate the inhomogeneous term. 04897 assign_r(sum, minus_sc_b, ROUND_UP); 04898 // Approximate the homogeneous part of `-sc_expr'. 04899 for (dimension_type i = expr_space_dim + 1; i > 0; --i) { 04900 const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1)); 04901 const int sign_i = sgn(sc_i); 04902 if (sign_i == 0) 04903 continue; 04904 // Choose carefully: we are approximating `-sc_expr'. 04905 const N& approx_i = (sign_i > 0) ? dbm[i][0] : dbm_0[i]; 04906 if (is_plus_infinity(approx_i)) { 04907 if (++pinf_count > 1) 04908 break; 04909 pinf_index = i; 04910 continue; 04911 } 04912 if (sign_i > 0) 04913 assign_r(coeff_i, sc_i, ROUND_UP); 04914 else { 04915 neg_assign(minus_sc_i, sc_i); 04916 assign_r(coeff_i, minus_sc_i, ROUND_UP); 04917 } 04918 add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP); 04919 } 04920 04921 // Remove all constraints on `var'. 04922 forget_all_dbm_constraints(v); 04923 // Shortest-path closure is preserved, but not reduction. 04924 if (marked_shortest_path_reduced()) 04925 reset_shortest_path_reduced(); 04926 // Return immediately if no approximation could be computed. 04927 if (pinf_count > 1) { 04928 PPL_ASSERT(OK()); 04929 return; 04930 } 04931 04932 // Divide by the (sign corrected) denominator (if needed). 04933 if (sc_den != 1) { 04934 // Before computing the quotient, the denominator should be approximated 04935 // towards zero. Since `sc_den' is known to be positive, this amounts to 04936 // rounding downwards, which is achieved as usual by rounding upwards 04937 // `minus_sc_den' and negating again the result. 04938 PPL_DIRTY_TEMP(N, down_sc_den); 04939 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 04940 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 04941 div_assign_r(sum, sum, down_sc_den, ROUND_UP); 04942 } 04943 04944 if (pinf_count == 0) { 04945 // Add the constraint `v >= -sum', i.e., `-v <= sum'. 04946 add_dbm_constraint(v, 0, sum); 04947 // Deduce constraints of the form `u - v', where `u != v'. 04948 deduce_u_minus_v_bounds(v, w, sc_expr, sc_den, sum); 04949 } 04950 else if (pinf_count == 1) 04951 if (pinf_index != v 04952 && expr.coefficient(Variable(pinf_index-1)) == denominator) 04953 // Add the constraint `v - pinf_index >= -sum', 04954 // i.e., `pinf_index - v <= sum'. 04955 add_dbm_constraint(v, pinf_index, sum); 04956 break; 04957 04958 default: 04959 // We already dealt with the other cases. 04960 throw std::runtime_error("PPL internal error"); 04961 } 04962 PPL_ASSERT(OK()); 04963 }
| void Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage | ( | const Linear_Expression & | lhs, | |
| Relation_Symbol | relsym, | |||
| const Linear_Expression & | rhs | |||
| ) | [inline] |
Assigns to *this the preimage of *this with respect to the affine relation
, where
is the relation symbol encoded by relsym.
| lhs | The left hand side affine expression. | |
| relsym | The relation symbol. | |
| rhs | The right hand side affine expression. |
| std::invalid_argument | Thrown if *this is dimension-incompatible with lhs or rhs or if relsym is a strict relation symbol. |
Definition at line 5230 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::BD_Shape< T >::forget_all_dbm_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::NOT_EQUAL, Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().
05232 { 05233 // Dimension-compatibility checks. 05234 // The dimension of `lhs' should not be greater than the dimension 05235 // of `*this'. 05236 const dimension_type bds_space_dim = space_dimension(); 05237 const dimension_type lhs_space_dim = lhs.space_dimension(); 05238 if (bds_space_dim < lhs_space_dim) 05239 throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)", 05240 "e1", lhs); 05241 05242 // The dimension of `rhs' should not be greater than the dimension 05243 // of `*this'. 05244 const dimension_type rhs_space_dim = rhs.space_dimension(); 05245 if (bds_space_dim < rhs_space_dim) 05246 throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)", 05247 "e2", rhs); 05248 05249 // Strict relation symbols are not admitted for BDSs. 05250 if (relsym == LESS_THAN || relsym == GREATER_THAN) 05251 throw_generic("generalized_affine_preimage(e1, r, e2)", 05252 "r is a strict relation symbol and " 05253 "*this is a BD_Shape"); 05254 // The relation symbol cannot be a disequality. 05255 if (relsym == NOT_EQUAL) 05256 throw_generic("generalized_affine_preimage(e1, r, e2)", 05257 "r is the disequality relation symbol and " 05258 "*this is a BD_Shape"); 05259 05260 // The preimage of an empty BDS is empty. 05261 shortest_path_closure_assign(); 05262 if (marked_empty()) 05263 return; 05264 05265 // Number of non-zero coefficients in `lhs': will be set to 05266 // 0, 1, or 2, the latter value meaning any value greater than 1. 05267 dimension_type t_lhs = 0; 05268 // Index of the last non-zero coefficient in `lhs', if any. 05269 dimension_type j_lhs = 0; 05270 // Compute the number of the non-zero components of `lhs'. 05271 for (dimension_type i = lhs_space_dim; i-- > 0; ) 05272 if (lhs.coefficient(Variable(i)) != 0) { 05273 if (t_lhs++ == 1) 05274 break; 05275 else 05276 j_lhs = i; 05277 } 05278 05279 const Coefficient& b_lhs = lhs.inhomogeneous_term(); 05280 05281 if (t_lhs == 0) { 05282 // `lhs' is a constant. 05283 // In this case, preimage and image happen to be the same. 05284 generalized_affine_image(lhs, relsym, rhs); 05285 return; 05286 } 05287 else if (t_lhs == 1) { 05288 // Here `lhs == a_lhs * v + b_lhs'. 05289 // Independently from the form of `rhs', we can exploit the 05290 // method computing generalized affine preimages for a single variable. 05291 Variable v(j_lhs); 05292 // Compute a sign-corrected relation symbol. 05293 const Coefficient& den = lhs.coefficient(v); 05294 Relation_Symbol new_relsym = relsym; 05295 if (den < 0) { 05296 if (relsym == LESS_OR_EQUAL) 05297 new_relsym = GREATER_OR_EQUAL; 05298 else if (relsym == GREATER_OR_EQUAL) 05299 new_relsym = LESS_OR_EQUAL; 05300 } 05301 Linear_Expression expr = rhs - b_lhs; 05302 generalized_affine_preimage(v, new_relsym, expr, den); 05303 } 05304 else { 05305 // Here `lhs' is of the general form, having at least two variables. 05306 // Compute the set of variables occurring in `lhs'. 05307 bool lhs_vars_intersects_rhs_vars = false; 05308 std::vector<Variable> lhs_vars; 05309 for (dimension_type i = lhs_space_dim; i-- > 0; ) 05310 if (lhs.coefficient(Variable(i)) != 0) { 05311 lhs_vars.push_back(Variable(i)); 05312 if (rhs.coefficient(Variable(i)) != 0) 05313 lhs_vars_intersects_rhs_vars = true; 05314 } 05315 05316 if (!lhs_vars_intersects_rhs_vars) { 05317 // `lhs' and `rhs' variables are disjoint. 05318 05319 // Constrain the left hand side expression so that it is related to 05320 // the right hand side expression as dictated by `relsym'. 05321 // TODO: if the following constraint is NOT a bounded difference, 05322 // it will be simply ignored. Should we compute approximations for it? 05323 switch (relsym) { 05324 case LESS_OR_EQUAL: 05325 refine_no_check(lhs <= rhs); 05326 break; 05327 case EQUAL: 05328 refine_no_check(lhs == rhs); 05329 break; 05330 case GREATER_OR_EQUAL: 05331 refine_no_check(lhs >= rhs); 05332 break; 05333 default: 05334 // We already dealt with the other cases. 05335 throw std::runtime_error("PPL internal error"); 05336 } 05337 05338 // If the shrunk BD_Shape is empty, its preimage is empty too; ... 05339 if (is_empty()) 05340 return; 05341 // Existentially quantify all variables in the lhs. 05342 for (dimension_type i = lhs_vars.size(); i-- > 0; ) 05343 forget_all_dbm_constraints(lhs_vars[i].id() + 1); 05344 } 05345 else { 05346 05347 // Some variables in `lhs' also occur in `rhs'. 05348 // To ease the computation, we add an additional dimension. 05349 const Variable new_var = Variable(bds_space_dim); 05350 add_space_dimensions_and_embed(1); 05351 // Constrain the new dimension to be equal to `lhs'. 05352 // NOTE: calling affine_image() instead of refine_no_check() 05353 // ensures some approximation is tried even when the constraint 05354 // is not a bounded difference. 05355 affine_image(new_var, lhs); 05356 // Existentiallly quantify all variables in the lhs. 05357 // NOTE: enforce shortest-path closure for precision. 05358 shortest_path_closure_assign(); 05359 PPL_ASSERT(!marked_empty()); 05360 for (dimension_type i = lhs_vars.size(); i-- > 0; ) 05361 forget_all_dbm_constraints(lhs_vars[i].id() + 1); 05362 // Constrain the new dimension so that it is related to 05363 // the left hand side as dictated by `relsym'. 05364 // Note: if `rhs == a_rhs*v + b_rhs' where `a_rhs' is in {0, 1}, 05365 // then one of the following constraints will be added, 05366 // since it is a bounded difference. Else the method 05367 // refine_no_check() will ignore it, because the 05368 // constraint is NOT a bounded difference. 05369 switch (relsym) { 05370 case LESS_OR_EQUAL: 05371 refine_no_check(new_var <= rhs); 05372 break; 05373 case EQUAL: 05374 refine_no_check(new_var == rhs); 05375 break; 05376 case GREATER_OR_EQUAL: 05377 refine_no_check(new_var >= rhs); 05378 break; 05379 default: 05380 // We already dealt with the other cases. 05381 throw std::runtime_error("PPL internal error"); 05382 } 05383 // Remove the temporarily added dimension. 05384 remove_higher_space_dimensions(bds_space_dim); 05385 } 05386 } 05387 05388 PPL_ASSERT(OK()); 05389 }
| void Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage | ( | Variable | var, | |
| Relation_Symbol | relsym, | |||
| const Linear_Expression & | expr, | |||
| Coefficient_traits::const_reference | denominator = Coefficient_one() | |||
| ) | [inline] |
Assigns to *this the preimage of *this with respect to the affine relation
, where
is the relation symbol encoded by relsym.
| var | The left hand side variable of the generalized affine transfer function. | |
| relsym | The relation symbol. | |
| expr | The numerator of the right hand side affine expression. | |
| denominator | The denominator of the right hand side affine expression. |
| std::invalid_argument | Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a dimension of *this or if relsym is a strict relation symbol. |
Definition at line 5152 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::BD_Shape< T >::forget_all_dbm_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::NOT_EQUAL, Parma_Polyhedra_Library::BD_Shape< T >::OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::refine(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage().
05156 { 05157 // The denominator cannot be zero. 05158 if (denominator == 0) 05159 throw_generic("generalized_affine_preimage(v, r, e, d)", "d == 0"); 05160 05161 // Dimension-compatibility checks. 05162 // The dimension of `expr' should not be greater than the dimension 05163 // of `*this'. 05164 const dimension_type space_dim = space_dimension(); 05165 const dimension_type expr_space_dim = expr.space_dimension(); 05166 if (space_dim < expr_space_dim) 05167 throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)", 05168 "e", expr); 05169 05170 // `var' should be one of the dimensions of the BDS. 05171 const dimension_type v = var.id() + 1; 05172 if (v > space_dim) 05173 throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)", 05174 var.id()); 05175 05176 // The relation symbol cannot be a strict relation symbol. 05177 if (relsym == LESS_THAN || relsym == GREATER_THAN) 05178 throw_generic("generalized_affine_preimage(v, r, e, d)", 05179 "r is a strict relation symbol and " 05180 "*this is a BD_Shape"); 05181 // The relation symbol cannot be a disequality. 05182 if (relsym == NOT_EQUAL) 05183 throw_generic("generalized_affine_preimage(v, r, e, d)", 05184 "r is the disequality relation symbol and " 05185 "*this is a BD_Shape"); 05186 05187 if (relsym == EQUAL) { 05188 // The relation symbol is "=": 05189 // this is just an affine preimage computation. 05190 affine_preimage(var, expr, denominator); 05191 return; 05192 } 05193 05194 // The preimage of an empty BDS is empty too. 05195 shortest_path_closure_assign(); 05196 if (marked_empty()) 05197 return; 05198 05199 // Check whether the preimage of this affine relation can be easily 05200 // computed as the image of its inverse relation. 05201 const Coefficient& expr_v = expr.coefficient(var); 05202 if (expr_v != 0) { 05203 const Relation_Symbol reversed_relsym = (relsym == LESS_OR_EQUAL) 05204 ? GREATER_OR_EQUAL : LESS_OR_EQUAL; 05205 const Linear_Expression inverse 05206 = expr - (expr_v + denominator)*var; 05207 PPL_DIRTY_TEMP_COEFFICIENT(inverse_den); 05208 neg_assign(inverse_den, expr_v); 05209 const Relation_Symbol inverse_relsym 05210 = (sgn(denominator) == sgn(inverse_den)) ? relsym : reversed_relsym; 05211 generalized_affine_image(var, inverse_relsym, inverse, inverse_den); 05212 return; 05213 } 05214 05215 refine(var, relsym, expr, denominator); 05216 // If the shrunk BD_Shape is empty, its preimage is empty too; ... 05217 if (is_empty()) 05218 return; 05219 // ... otherwise, since the relation was not invertible, 05220 // we just forget all constraints on `v'. 05221 forget_all_dbm_constraints(v); 05222 // Shortest-path closure is preserved, but not reduction. 05223 if (marked_shortest_path_reduced()) 05224 reset_shortest_path_reduced(); 05225 PPL_ASSERT(OK()); 05226 }
| void Parma_Polyhedra_Library::BD_Shape< T >::get_limiting_shape | ( | const Constraint_System & | cs, | |
| BD_Shape< T > & | limiting_shape | |||
| ) | const [inline, private] |
Adds to limiting_shape the bounded differences in cs that are satisfied by *this.
Definition at line 2958 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::BD_Shape< T >::extract_bounded_difference(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Constraint::is_inequality(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::neg_assign(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::Constraint_System::space_dimension().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::limited_BHMZ05_extrapolation_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::limited_CC76_extrapolation_assign().
02959 { 02960 const dimension_type cs_space_dim = cs.space_dimension(); 02961 // Private method: the caller has to ensure the following. 02962 PPL_ASSERT(cs_space_dim <= space_dimension()); 02963 02964 shortest_path_closure_assign(); 02965 bool changed = false; 02966 PPL_DIRTY_TEMP_COEFFICIENT(coeff); 02967 PPL_DIRTY_TEMP_COEFFICIENT(minus_c_term); 02968 PPL_DIRTY_TEMP(N, d); 02969 PPL_DIRTY_TEMP(N, d1); 02970 for (Constraint_System::const_iterator cs_i = cs.begin(), 02971 cs_end = cs.end(); cs_i != cs_end; ++cs_i) { 02972 const Constraint& c = *cs_i; 02973 dimension_type num_vars = 0; 02974 dimension_type i = 0; 02975 dimension_type j = 0; 02976 // Constraints that are not bounded differences are ignored. 02977 if (extract_bounded_difference(c, cs_space_dim, num_vars, i, j, coeff)) { 02978 // Select the cell to be modified for the "<=" part of the constraint, 02979 // and set `coeff' to the absolute value of itself. 02980 const bool negative = (coeff < 0); 02981 const N& x = negative ? dbm[i][j] : dbm[j][i]; 02982 const N& y = negative ? dbm[j][i] : dbm[i][j]; 02983 DB_Matrix<N>& ls_dbm = limiting_shape.dbm; 02984 N& ls_x = negative ? ls_dbm[i][j] : ls_dbm[j][i]; 02985 N& ls_y = negative ? ls_dbm[j][i] : ls_dbm[i][j]; 02986 if (negative) 02987 neg_assign(coeff); 02988 // Compute the bound for `x', rounding towards plus infinity. 02989 div_round_up(d, c.inhomogeneous_term(), coeff); 02990 if (x <= d) { 02991 if (c.is_inequality()) { 02992 if (ls_x > d) { 02993 ls_x = d; 02994 changed = true; 02995 } 02996 } 02997 else { 02998 // Compute the bound for `y', rounding towards plus infinity. 02999 neg_assign(minus_c_term, c.inhomogeneous_term()); 03000 div_round_up(d1, minus_c_term, coeff); 03001 if (y <= d1) 03002 if ((ls_x >= d && ls_y > d1) || (ls_x > d && ls_y >= d1)) { 03003 ls_x = d; 03004 ls_y = d1; 03005 changed = true; 03006 } 03007 } 03008 } 03009 } 03010 } 03011 03012 // In general, adding a constraint does not preserve the shortest-path 03013 // closure of the bounded difference shape. 03014 if (changed && limiting_shape.marked_shortest_path_closed()) 03015 limiting_shape.reset_shortest_path_closed(); 03016 }
| void Parma_Polyhedra_Library::BD_Shape< T >::H79_widening_assign | ( | const BD_Shape< T > & | y, | |
| unsigned * | tp = 0 | |||
| ) | [inline] |
Assigns to *this the result of computing the H79-widening between *this and y.
| y | A BDS 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 798 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::constraints(), Parma_Polyhedra_Library::Polyhedron::H79_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), and Parma_Polyhedra_Library::BD_Shape< T >::swap().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::widening_assign().
00798 { 00799 // See the documentation for polyhedra. 00800 C_Polyhedron px(constraints()); 00801 C_Polyhedron py(y.constraints()); 00802 px.H79_widening_assign(py, tp); 00803 BD_Shape x(px); 00804 swap(x); 00805 PPL_ASSERT(OK()); 00806 }
| int32_t Parma_Polyhedra_Library::BD_Shape< T >::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 836 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().
00836 { 00837 return space_dimension() & 0x7fffffff; 00838 }
| void Parma_Polyhedra_Library::BD_Shape< T >::incremental_shortest_path_closure_assign | ( | Variable | var | ) | const [inline, private] |
Incrementally computes shortest-path closure, assuming that only constraints affecting variable var need to be considered.
*this, which was shortest-path closed, has only been modified by adding constraints affecting variable var. If this assumption is not satisfied, i.e., if a non-redundant constraint not affecting variable var has been added, the behavior is undefined. Definition at line 1813 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::min_assign(), Parma_Polyhedra_Library::PLUS_INFINITY, and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign().
01813 { 01814 // Do something only if necessary. 01815 if (marked_empty() || marked_shortest_path_closed()) 01816 return; 01817 const dimension_type num_dimensions = space_dimension(); 01818 PPL_ASSERT(var.id() < num_dimensions); 01819 01820 // Even though the BDS will not change, its internal representation 01821 // is going to be modified by the incremental Floyd-Warshall algorithm. 01822 BD_Shape& x = const_cast<BD_Shape&>(*this); 01823 01824 // Fill the main diagonal with zeros. 01825 for (dimension_type h = num_dimensions + 1; h-- > 0; ) { 01826 PPL_ASSERT(is_plus_infinity(x.dbm[h][h])); 01827 assign_r(x.dbm[h][h], 0, ROUND_NOT_NEEDED); 01828 } 01829 01830 // Using the incremental Floyd-Warshall algorithm. 01831 PPL_DIRTY_TEMP(N, sum); 01832 const dimension_type v = var.id() + 1; 01833 DB_Row<N>& x_v = x.dbm[v]; 01834 // Step 1: Improve all constraints on variable `var'. 01835 for (dimension_type k = num_dimensions + 1; k-- > 0; ) { 01836 DB_Row<N>& x_k = x.dbm[k]; 01837 const N& x_v_k = x_v[k]; 01838 const N& x_k_v = x_k[v]; 01839 const bool x_v_k_finite = !is_plus_infinity(x_v_k); 01840 const bool x_k_v_finite = !is_plus_infinity(x_k_v); 01841 // Specialize inner loop based on finiteness info. 01842 if (x_v_k_finite) { 01843 if (x_k_v_finite) { 01844 // Here both x_v_k and x_k_v are finite. 01845 for (dimension_type i = num_dimensions + 1; i-- > 0; ) { 01846 DB_Row<N>& x_i = x.dbm[i]; 01847 const N& x_i_k = x_i[k]; 01848 if (!is_plus_infinity(x_i_k)) { 01849 add_assign_r(sum, x_i_k, x_k_v, ROUND_UP); 01850 min_assign(x_i[v], sum); 01851 } 01852 const N& x_k_i = x_k[i]; 01853 if (!is_plus_infinity(x_k_i)) { 01854 add_assign_r(sum, x_v_k, x_k_i, ROUND_UP); 01855 min_assign(x_v[i], sum); 01856 } 01857 } 01858 } 01859 else { 01860 // Here x_v_k is finite, but x_k_v is not. 01861 for (dimension_type i = num_dimensions + 1; i-- > 0; ) { 01862 const N& x_k_i = x_k[i]; 01863 if (!is_plus_infinity(x_k_i)) { 01864 add_assign_r(sum, x_v_k, x_k_i, ROUND_UP); 01865 min_assign(x_v[i], sum); 01866 } 01867 } 01868 } 01869 } 01870 else if (x_k_v_finite) { 01871 // Here x_v_k is infinite, but x_k_v is finite. 01872 for (dimension_type i = num_dimensions + 1; i-- > 0; ) { 01873 DB_Row<N>& x_i = x.dbm[i]; 01874 const N& x_i_k = x_i[k]; 01875 if (!is_plus_infinity(x_i_k)) { 01876 add_assign_r(sum, x_i_k, x_k_v, ROUND_UP); 01877 min_assign(x_i[v], sum); 01878 } 01879 } 01880 } 01881 else 01882 // Here both x_v_k and x_k_v are infinite. 01883 continue; 01884 } 01885 01886 // Step 2: improve the other bounds by using the precise bounds 01887 // for the constraints on `var'. 01888 for (dimension_type i = num_dimensions + 1; i-- > 0; ) { 01889 DB_Row<N>& x_i = x.dbm[i]; 01890 const N& x_i_v = x_i[v]; 01891 if (!is_plus_infinity(x_i_v)) { 01892 for (dimension_type j = num_dimensions + 1; j-- > 0; ) { 01893 const N& x_v_j = x_v[j]; 01894 if (!is_plus_infinity(x_v_j)) { 01895 add_assign_r(sum, x_i_v, x_v_j, ROUND_UP); 01896 min_assign(x_i[j], sum); 01897 } 01898 } 01899 } 01900 } 01901 01902 // Check for emptiness: the BDS is empty if and only if there is a 01903 // negative value on the main diagonal of `dbm'. 01904 for (dimension_type h = num_dimensions + 1; h-- > 0; ) { 01905 N& x_dbm_hh = x.dbm[h][h]; 01906 if (sgn(x_dbm_hh) < 0) { 01907 x.set_empty(); 01908 return; 01909 } 01910 else { 01911 PPL_ASSERT(sgn(x_dbm_hh) == 0); 01912 // Restore PLUS_INFINITY on the main diagonal. 01913 assign_r(x_dbm_hh, PLUS_INFINITY, ROUND_NOT_NEEDED); 01914 } 01915 } 01916 01917 // The BDS is not empty and it is now shortest-path closed. 01918 x.set_shortest_path_closed(); 01919 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::integer_upper_bound_assign_if_exact | ( | const BD_Shape< T > & | y | ) | [inline] |
If the integer 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. |
T is an integral type. Definition at line 721 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::is_integer(), PPL_COMPILE_TIME_CHECK, Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().
00721 { 00722 PPL_COMPILE_TIME_CHECK(std::numeric_limits<T>::is_integer, 00723 "BD_Shape<T>::integer_upper_bound_assign_if_exact(y):" 00724 " T in not an integer datatype."); 00725 if (space_dimension() != y.space_dimension()) 00726 throw_dimension_incompatible("integer_upper_bound_assign_if_exact(y)", y); 00727 const bool integer_upper_bound = true; 00728 return BHZ09_upper_bound_assign_if_exact<integer_upper_bound>(y); 00729 }
| void Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign | ( | const BD_Shape< T > & | y | ) | [inline] |
Assigns to *this the intersection of *this and y.
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 2839 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::limited_BHMZ05_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::limited_CC76_extrapolation_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign().
02839 { 02840 const dimension_type space_dim = space_dimension(); 02841 02842 // Dimension-compatibility check. 02843 if (space_dim != y.space_dimension()) 02844 throw_dimension_incompatible("intersection_assign(y)", y); 02845 02846 // If one of the two bounded difference shapes is empty, 02847 // the intersection is empty. 02848 if (marked_empty()) 02849 return; 02850 if (y.marked_empty()) { 02851 set_empty(); 02852 return; 02853 } 02854 02855 // If both bounded difference shapes are zero-dimensional, 02856 // then at this point they are necessarily non-empty, 02857 // so that their intersection is non-empty too. 02858 if (space_dim == 0) 02859 return; 02860 02861 // To intersect two bounded difference shapes we compare 02862 // the constraints and we choose the less values. 02863 bool changed = false; 02864 for (dimension_type i = space_dim + 1; i-- > 0; ) { 02865 DB_Row<N>& dbm_i = dbm[i]; 02866 const DB_Row<N>& y_dbm_i = y.dbm[i]; 02867 for (dimension_type j = space_dim + 1; j-- > 0; ) { 02868 N& dbm_ij = dbm_i[j]; 02869 const N& y_dbm_ij = y_dbm_i[j]; 02870 if (dbm_ij > y_dbm_ij) { 02871 dbm_ij = y_dbm_ij; 02872 changed = true; 02873 } 02874 } 02875 } 02876 02877 if (changed && marked_shortest_path_closed()) 02878 reset_shortest_path_closed(); 02879 PPL_ASSERT(OK()); 02880 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::is_bounded | ( | ) | const [inline] |
Returns true if and only if *this is a bounded BDS.
Definition at line 702 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().
00702 { 00703 shortest_path_closure_assign(); 00704 const dimension_type space_dim = space_dimension(); 00705 // A zero-dimensional or empty BDS is bounded. 00706 if (marked_empty() || space_dim == 0) 00707 return true; 00708 00709 // A bounded difference shape defining the bounded BDS never can 00710 // contain trivial constraints. 00711 for (dimension_type i = space_dim + 1; i-- > 0; ) { 00712 const DB_Row<N>& dbm_i = dbm[i]; 00713 for (dimension_type j = space_dim + 1; j-- > 0; ) 00714 if (i != j) 00715 if (is_plus_infinity(dbm_i[j])) 00716 return false; 00717 } 00718 00719 return true; 00720 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::is_discrete | ( | ) | const [inline] |
Returns true if and only if *this is discrete.
Definition at line 412 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::affine_dimension().
00412 { 00413 return affine_dimension() == 0; 00414 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::is_disjoint_from | ( | const BD_Shape< T > & | y | ) | const [inline] |
Returns true if and only if *this and y are disjoint.
| std::invalid_argument | Thrown if x and y are topology-incompatible or dimension-incompatible. |
Definition at line 637 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().
00637 { 00638 const dimension_type space_dim = space_dimension(); 00639 // Dimension-compatibility check. 00640 if (space_dim != y.space_dimension()) 00641 throw_dimension_incompatible("is_disjoint_from(y)", y); 00642 00643 // If one of the two bounded difference shape is empty, 00644 // then the two bounded difference shape are disjoint. 00645 shortest_path_closure_assign(); 00646 if (marked_empty()) 00647 return true; 00648 y.shortest_path_closure_assign(); 00649 if (y.marked_empty()) 00650 return true; 00651 00652 // Two BDSs are disjoint when their intersection is empty. 00653 // That is if and only if there exists at least a bounded difference 00654 // such that the upper bound of the bounded difference in the first 00655 // BD_Shape is strictly less than the lower bound of 00656 // the corresponding bounded difference in the second BD_Shape 00657 // or vice versa. 00658 // For example: let be 00659 // in `*this': -a_j_i <= v_j - v_i <= a_i_j; 00660 // and in `y': -b_j_i <= v_j - v_i <= b_i_j; 00661 // `*this' and `y' are disjoint if 00662 // 1.) a_i_j < -b_j_i or 00663 // 2.) b_i_j < -a_j_i. 00664 PPL_DIRTY_TEMP(N, tmp); 00665 for (dimension_type i = space_dim+1; i-- > 0; ) { 00666 const DB_Row<N>& x_i = dbm[i]; 00667 for (dimension_type j = space_dim+1; j-- > 0; ) { 00668 neg_assign_r(tmp, y.dbm[j][i], ROUND_UP); 00669 if (x_i[j] < tmp) 00670 return true; 00671 } 00672 } 00673 00674 return false; 00675 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::is_empty | ( | ) | const [inline] |
Returns true if and only if *this is an empty BDS.
Definition at line 355 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), and Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BFT00_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::BHZ09_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::constrains(), Parma_Polyhedra_Library::BD_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::BD_Shape< T >::difference_assign(), Parma_Polyhedra_Library::BD_Shape< T >::frequency(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::Pointset_Powerset< PSET >::Pointset_Powerset(), and Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign().
00355 { 00356 shortest_path_closure_assign(); 00357 return marked_empty(); 00358 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::is_shortest_path_reduced | ( | ) | const [inline, private] |
Returns true if and only if this->dbm is shortest-path closed and this->redundancy_dbm correctly flags the redundant entries in this->dbm.
Definition at line 955 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign().
00955 { 00956 // If the BDS is empty, it is also reduced. 00957 if (marked_empty()) 00958 return true; 00959 00960 const dimension_type space_dim = space_dimension(); 00961 // Zero-dimensional BDSs are necessarily reduced. 00962 if (space_dim == 0) 00963 return true; 00964 00965 // A shortest-path reduced dbm is just a dbm with an indication of 00966 // those constraints that are redundant. If there is no indication 00967 // of the redundant constraints, then it cannot be reduced. 00968 if (!marked_shortest_path_reduced()) 00969 return false; 00970 00971 const BD_Shape x_copy = *this; 00972 x_copy.shortest_path_closure_assign(); 00973 // If we just discovered emptiness, it cannot be reduced. 00974 if (x_copy.marked_empty()) 00975 return false; 00976 00977 // The vector `leader' is used to indicate which variables are equivalent. 00978 std::vector<dimension_type> leader(space_dim + 1); 00979 00980 // We store the leader. 00981 for (dimension_type i = space_dim + 1; i-- > 0; ) 00982 leader[i] = i; 00983 00984 // Step 1: we store really the leader with the corrected value. 00985 // We search for the equivalent or zero-equivalent variables. 00986 // The variable(i-1) and variable(j-1) are equivalent if and only if 00987 // m_i_j == -(m_j_i). 00988 for (dimension_type i = 0; i < space_dim; ++i) { 00989 const DB_Row<N>& x_copy_dbm_i = x_copy.dbm[i]; 00990 for (dimension_type j = i + 1; j <= space_dim; ++j) 00991 if (is_additive_inverse(x_copy.dbm[j][i], x_copy_dbm_i[j])) 00992 // Two equivalent variables have got the same leader 00993 // (the smaller variable). 00994 leader[j] = leader[i]; 00995 } 00996 00997 // Step 2: we check if there are redundant constraints in the zero_cycle 00998 // free bounded difference shape, considering only the leaders. 00999 // A constraint `c' is redundant, when there are two constraints such that 01000 // their sum is the same constraint with the inhomogeneous term 01001 // less than or equal to the `c' one. 01002 PPL_DIRTY_TEMP(N, c); 01003 for (dimension_type k = 0; k <= space_dim; ++k) 01004 if (leader[k] == k) { 01005 const DB_Row<N>& x_k = x_copy.dbm[k]; 01006 for (dimension_type i = 0; i <= space_dim; ++i) 01007 if (leader[i] == i) { 01008 const DB_Row<N>& x_i = x_copy.dbm[i]; 01009 const Bit_Row& redundancy_i = redundancy_dbm[i]; 01010 const N& x_i_k = x_i[k]; 01011 for (dimension_type j = 0; j <= space_dim; ++j) 01012 if (leader[j] == j) { 01013 const N& x_i_j = x_i[j]; 01014 if (!is_plus_infinity(x_i_j)) { 01015 add_assign_r(c, x_i_k, x_k[j], ROUND_UP); 01016 if (x_i_j >= c && !redundancy_i[j]) 01017 return false; 01018 } 01019 } 01020 } 01021 } 01022 01023 // The vector `var_conn' is used to check if there is a single cycle 01024 // that connected all zero-equivalent variables between them. 01025 // The value `space_dim + 1' is used to indicate that the equivalence 01026 // class contains a single variable. 01027 std::vector<dimension_type> var_conn(space_dim + 1); 01028 for (dimension_type i = space_dim + 1; i-- > 0; ) 01029 var_conn[i] = space_dim + 1; 01030 01031 // Step 3: we store really the `var_conn' with the right value, putting 01032 // the variable with the selected variable is connected: 01033 // we check the row of each variable: 01034 // a- each leader could be connected with only zero-equivalent one, 01035 // b- each no-leader with only another zero-equivalent one. 01036 for (dimension_type i = 0; i <= space_dim; ++i) { 01037 // It count with how many variables the selected variable is 01038 // connected. 01039 dimension_type t = 0; 01040 dimension_type ld_i = leader[i]; 01041 // Case a: leader. 01042 if (ld_i == i) { 01043 for (dimension_type j = 0; j <= space_dim; ++j) { 01044 dimension_type ld_j = leader[j]; 01045 // Only the connectedness with equivalent variables 01046 // is considered. 01047 if (j != ld_j) 01048 if (!redundancy_dbm[i][j]) { 01049 if (t == 1) 01050 // Two no-leaders couldn't connected with the same leader. 01051 return false; 01052 else 01053 if (ld_j != i) 01054 // The variables isn't in the same equivalence class. 01055 return false; 01056 else { 01057 ++t; 01058 var_conn[i] = j; 01059 } 01060 } 01061 } 01062 } 01063 // Case b: no-leader. 01064 else { 01065 for (dimension_type j = 0; j <= space_dim; ++j) { 01066 if (!redundancy_dbm[i][j]) { 01067 dimension_type ld_j = leader[j]; 01068 if (ld_i != ld_j) 01069 // The variables isn't in the same equivalence class. 01070 return false; 01071 else { 01072 if (t == 1) 01073 // Two variables couldn't connected with the same leader. 01074 return false; 01075 else { 01076 ++t; 01077 var_conn[i] = j; 01078 } 01079 } 01080 // A no-leader must be connected with 01081 // another variable. 01082 if (t == 0) 01083 return false; 01084 } 01085 } 01086 } 01087 } 01088 01089 // The vector `just_checked' is used to check if 01090 // a variable is already checked. 01091 std::vector<bool> just_checked(space_dim + 1); 01092 for (dimension_type i = space_dim + 1; i-- > 0; ) 01093 just_checked[i] = false; 01094 01095 // Step 4: we check if there are single cycles that 01096 // connected all the zero-equivalent variables between them. 01097 for (dimension_type i = 0; i <= space_dim; ++i) { 01098 bool jc_i = just_checked[i]; 01099 // We do not re-check the already considered single cycles. 01100 if (!jc_i) { 01101 dimension_type v_con = var_conn[i]; 01102 // We consider only the equivalence classes with 01103 // 2 or plus variables. 01104 if (v_con != space_dim + 1) { 01105 // There is a single cycle if taken a variable, 01106 // we return to this same variable. 01107 while (v_con != i) { 01108 just_checked[v_con] = true; 01109 v_con = var_conn[v_con]; 01110 // If we re-pass to an already considered variable, 01111 // then we haven't a single cycle. 01112 if (just_checked[v_con]) 01113 return false; 01114 } 01115 } 01116 } 01117 just_checked[i] = true; 01118 } 01119 01120 // The system bounded differences is just reduced. 01121 return true; 01122 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::is_topologically_closed | ( | ) | const [inline] |
Returns true if and only if *this is a topologically closed subset of the vector space.
Definition at line 406 of file BD_Shape.inlines.hh.
| bool Parma_Polyhedra_Library::BD_Shape< T >::is_universe | ( | ) | const [inline] |
Returns true if and only if *this is a universe BDS.
Definition at line 679 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().
00679 { 00680 if (marked_empty()) 00681 return false; 00682 00683 const dimension_type space_dim = space_dimension(); 00684 // If the BDS is non-empty and zero-dimensional, 00685 // then it is necessarily the universe BDS. 00686 if (space_dim == 0) 00687 return true; 00688 00689 // A bounded difference shape defining the universe BDS can only 00690 // contain trivial constraints. 00691 for (dimension_type i = space_dim + 1; i-- > 0; ) { 00692 const DB_Row<N>& dbm_i = dbm[i]; 00693 for (dimension_type j = space_dim + 1; j-- > 0; ) 00694 if (!is_plus_infinity(dbm_i[j])) 00695 return false; 00696 } 00697 return true; 00698 }
| void Parma_Polyhedra_Library::BD_Shape< T >::limited_BHMZ05_extrapolation_assign | ( | const BD_Shape< T > & | y, | |
| const Constraint_System & | cs, | |||
| unsigned * | tp = 0 | |||
| ) | [inline] |
Improves the result of the BHMZ05-widening computation by also enforcing those constraints in cs that are satisfied by all the points of *this.
| y | A BDS that must be contained in *this. | |
| cs | The system of constraints used to improve the widened BDS. | |
| 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 cs are dimension-incompatible or if cs contains a strict inequality. |
Definition at line 3141 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::get_limiting_shape(), Parma_Polyhedra_Library::Constraint_System::has_strict_inequalities(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), Parma_Polyhedra_Library::BD_Shape< T >::throw_generic(), and Parma_Polyhedra_Library::UNIVERSE.
03143 { 03144 // Dimension-compatibility check. 03145 const dimension_type space_dim = space_dimension(); 03146 if (space_dim != y.space_dimension()) 03147 throw_dimension_incompatible("limited_BHMZ05_extrapolation_assign(y, cs)", 03148 y); 03149 // `cs' must be dimension-compatible with the two systems 03150 // of bounded differences. 03151 const dimension_type cs_space_dim = cs.space_dimension(); 03152 if (space_dim < cs_space_dim) 03153 throw_generic("limited_BHMZ05_extrapolation_assign(y, cs)", 03154 "cs is space-dimension incompatible"); 03155 03156 // Strict inequalities are not allowed. 03157 if (cs.has_strict_inequalities()) 03158 throw_generic("limited_BHMZ05_extrapolation_assign(y, cs)", 03159 "cs has strict inequalities"); 03160 03161 // The limited BHMZ05-extrapolation between two systems of bounded 03162 // differences in a zero-dimensional space is a system of bounded 03163 // differences in a zero-dimensional space, too. 03164 if (space_dim == 0) 03165 return; 03166 03167 #ifndef NDEBUG 03168 { 03169 // We assume that `y' is contained in or equal to `*this'. 03170 const BD_Shape x_copy = *this; 03171 const BD_Shape y_copy = y; 03172 PPL_ASSERT(x_copy.contains(y_copy)); 03173 } 03174 #endif 03175 03176 // If `*this' is empty, since `*this' contains `y', `y' is empty too. 03177 if (marked_empty()) 03178 return; 03179 // If `y' is empty, we return. 03180 if (y.marked_empty()) 03181 return; 03182 03183 BD_Shape<T> limiting_shape(space_dim, UNIVERSE); 03184 get_limiting_shape(cs, limiting_shape); 03185 BHMZ05_widening_assign(y, tp); 03186 intersection_assign(limiting_shape); 03187 }
| void Parma_Polyhedra_Library::BD_Shape< T >::limited_CC76_extrapolation_assign | ( | const BD_Shape< T > & | y, | |
| const Constraint_System & | cs, | |||
| unsigned * | tp = 0 | |||
| ) | [inline] |
Improves the result of the CC76-extrapolation computation by also enforcing those constraints in cs that are satisfied by all the points of *this.
| y | A BDS that must be contained in *this. | |
| cs | The system of constraints used to improve the widened BDS. | |
| 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 cs are dimension-incompatible or if cs contains a strict inequality. |
Definition at line 3020 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::get_limiting_shape(), Parma_Polyhedra_Library::Constraint_System::has_strict_inequalities(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), Parma_Polyhedra_Library::BD_Shape< T >::throw_generic(), and Parma_Polyhedra_Library::UNIVERSE.
03022 { 03023 // Dimension-compatibility check. 03024 const dimension_type space_dim = space_dimension(); 03025 if (space_dim != y.space_dimension()) 03026 throw_dimension_incompatible("limited_CC76_extrapolation_assign(y, cs)", 03027 y); 03028 03029 // `cs' must be dimension-compatible with the two systems 03030 // of bounded differences. 03031 const dimension_type cs_space_dim = cs.space_dimension(); 03032 if (space_dim < cs_space_dim) 03033 throw_generic("limited_CC76_extrapolation_assign(y, cs)", 03034 "cs is space_dimension incompatible"); 03035 03036 // Strict inequalities not allowed. 03037 if (cs.has_strict_inequalities()) 03038 throw_generic("limited_CC76_extrapolation_assign(y, cs)", 03039 "cs has strict inequalities"); 03040 03041 // The limited CC76-extrapolation between two systems of bounded 03042 // differences in a zero-dimensional space is a system of bounded 03043 // differences in a zero-dimensional space, too. 03044 if (space_dim == 0) 03045 return; 03046 03047 #ifndef NDEBUG 03048 { 03049 // We assume that `y' is contained in or equal to `*this'. 03050 const BD_Shape x_copy = *this; 03051 const BD_Shape y_copy = y; 03052 PPL_ASSERT(x_copy.contains(y_copy)); 03053 } 03054 #endif 03055 03056 // If `*this' is empty, since `*this' contains `y', `y' is empty too. 03057 if (marked_empty()) 03058 return; 03059 // If `y' is empty, we return. 03060 if (y.marked_empty()) 03061 return; 03062 03063 BD_Shape<T> limiting_shape(space_dim, UNIVERSE); 03064 get_limiting_shape(cs, limiting_shape); 03065 CC76_extrapolation_assign(y, tp); 03066 intersection_assign(limiting_shape); 03067 }
| void Parma_Polyhedra_Library::BD_Shape< T >::limited_H79_extrapolation_assign | ( | const BD_Shape< T > & | y, | |
| const Constraint_System & | cs, | |||
| unsigned * | tp = 0 | |||
| ) | [inline] |
Improves the result of the H79-widening computation by also enforcing those constraints in cs that are satisfied by all the points of *this.
| y | A BDS that must be contained in *this. | |
| cs | The system of constraints used to improve the widened BDS. | |
| 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 cs are dimension-incompatible. |
Definition at line 816 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::constraints(), Parma_Polyhedra_Library::Polyhedron::limited_H79_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), and Parma_Polyhedra_Library::BD_Shape< T >::swap().
00818 { 00819 // See the documentation for polyhedra. 00820 C_Polyhedron px(constraints()); 00821 C_Polyhedron py(y.constraints()); 00822 px.limited_H79_extrapolation_assign(py, cs, tp); 00823 BD_Shape x(px); 00824 swap(x); 00825 PPL_ASSERT(OK()); 00826 }
| void Parma_Polyhedra_Library::BD_Shape< T >::map_space_dimensions | ( | const Partial_Function & | pfunc | ) | [inline] |
Remaps the dimensions of the vector space according to a partial function.
| pfunc | The partial function specifying the destiny of each 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 co-domain (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 co-domain of the partial function.
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.
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 2771 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::swap().
02771 { 02772 const dimension_type space_dim = space_dimension(); 02773 // TODO: this implementation is just an executable specification. 02774 if (space_dim == 0) 02775 return; 02776 02777 if (pfunc.has_empty_codomain()) { 02778 // All dimensions vanish: the BDS becomes zero_dimensional. 02779 remove_higher_space_dimensions(0); 02780 return; 02781 } 02782 02783 const dimension_type new_space_dim = pfunc.max_in_codomain() + 1; 02784 // If we are going to actually reduce the space dimension, 02785 // then shortest-path closure is required to keep precision. 02786 if (new_space_dim < space_dim) 02787 shortest_path_closure_assign(); 02788 02789 // If the BDS is empty, then it is sufficient to adjust the 02790 // space dimension of the bounded difference shape. 02791 if (marked_empty()) { 02792 remove_higher_space_dimensions(new_space_dim); 02793 return; 02794 } 02795 02796 // Shortest-path closure is maintained (if it was holding). 02797 // TODO: see whether reduction can be (efficiently!) maintained too. 02798 if (marked_shortest_path_reduced()) 02799 reset_shortest_path_reduced(); 02800 02801 // We create a new matrix with the new space dimension. 02802 DB_Matrix<N> x(new_space_dim+1); 02803 // First of all we must map the unary constraints, because 02804 // there is the fictitious variable `zero', that can't be mapped 02805 // at all. 02806 DB_Row<N>& dbm_0 = dbm[0]; 02807 DB_Row<N>& x_0 = x[0]; 02808 for (dimension_type j = 1; j <= space_dim; ++j) { 02809 dimension_type new_j; 02810 if (pfunc.maps(j - 1, new_j)) { 02811 assign_or_swap(x_0[new_j + 1], dbm_0[j]); 02812 assign_or_swap(x[new_j + 1][0], dbm[j][0]); 02813 } 02814 } 02815 // Now we map the binary constraints, exchanging the indexes. 02816 for (dimension_type i = 1; i <= space_dim; ++i) { 02817 dimension_type new_i; 02818 if (pfunc.maps(i - 1, new_i)) { 02819 DB_Row<N>& dbm_i = dbm[i]; 02820 ++new_i; 02821 DB_Row<N>& x_new_i = x[new_i]; 02822 for (dimension_type j = i+1; j <= space_dim; ++j) { 02823 dimension_type new_j; 02824 if (pfunc.maps(j - 1, new_j)) { 02825 ++new_j; 02826 assign_or_swap(x_new_i[new_j], dbm_i[j]); 02827 assign_or_swap(x[new_j][new_i], dbm[j][i]); 02828 } 02829 } 02830 } 02831 } 02832 02833 std::swap(dbm, x); 02834 PPL_ASSERT(OK()); 02835 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::marked_empty | ( | ) | const [inline, private] |
Returns true if the BDS is known to be empty.
The return value false does not necessarily implies that *this is non-empty.
Definition at line 61 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::status, and Parma_Polyhedra_Library::BD_Shape< T >::Status::test_empty().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::BD_Shape< T >::affine_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::BD_Shape< T >::BFT00_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::BHZ09_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::BD_Shape< T >::compute_leaders(), Parma_Polyhedra_Library::BD_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::BD_Shape< T >::constrains(), Parma_Polyhedra_Library::BD_Shape< T >::constraints(), Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::difference_assign(), Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::BD_Shape< T >::euclidean_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::frequency(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::incremental_shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::BD_Shape< T >::is_bounded(), Parma_Polyhedra_Library::BD_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::BD_Shape< T >::is_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::is_universe(), Parma_Polyhedra_Library::BD_Shape< T >::l_infinity_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::limited_BHMZ05_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::max_min(), Parma_Polyhedra_Library::BD_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::BD_Shape< T >::minimized_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::rectilinear_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_congruence(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_congruences(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::relation_with(), Parma_Polyhedra_Library::BD_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign(), Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign(), Parma_Polyhedra_Library::BD_Shape< T >::unconstrain(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign().
00061 { 00062 return status.test_empty(); 00063 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed | ( | ) | const [inline, private] |
Returns true if the system of bounded differences is known to be shortest-path closed.
The return value false does not necessarily implies that this->dbm is not shortest-path closed.
Definition at line 67 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::status, and Parma_Polyhedra_Library::BD_Shape< T >::Status::test_shortest_path_closed().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::add_dbm_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::BHZ09_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::BD_Shape< T >::compute_leaders(), Parma_Polyhedra_Library::BD_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::BD_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::get_limiting_shape(), Parma_Polyhedra_Library::BD_Shape< T >::incremental_shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign().
00067 { 00068 return status.test_shortest_path_closed(); 00069 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced | ( | ) | const [inline, private] |
Returns true if the system of bounded differences is known to be shortest-path reduced.
The return value false does not necessarily implies that this->dbm is not shortest-path reduced.
Definition at line 73 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::status, and Parma_Polyhedra_Library::BD_Shape< T >::Status::test_shortest_path_reduced().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::BD_Shape< T >::constraints(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::is_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::operator=(), Parma_Polyhedra_Library::BD_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign().
00073 { 00074 return status.test_shortest_path_reduced(); 00075 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::marked_zero_dim_univ | ( | ) | const [inline, private] |
Returns true if the BDS is the zero-dimensional universe.
Definition at line 55 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::status, and Parma_Polyhedra_Library::BD_Shape< T >::Status::test_zero_dim_univ().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape().
00055 { 00056 return status.test_zero_dim_univ(); 00057 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::max_min | ( | const Linear_Expression & | expr, | |
| bool | maximize, | |||
| Coefficient & | ext_n, | |||
| Coefficient & | ext_d, | |||
| bool & | included | |||
| ) | const [inline, private] |
Maximizes or minimizes expr subject to *this.
| expr | The linear expression to be maximized or minimized subject to this; | |
| maximize | true if maximization is what is wanted; | |
| 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 can actually be reached in * this; |
| 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 1171 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::BD_Shape< T >::constraints(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::extract_bounded_difference(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::MINIMIZATION, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::numer_denom(), Parma_Polyhedra_Library::MIP_Problem::optimal_value(), Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::MIP_Problem::solve(), Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().
01174 { 01175 // The dimension of `expr' should not be greater than the dimension 01176 // of `*this'. 01177 const dimension_type space_dim = space_dimension(); 01178 const dimension_type expr_space_dim = expr.space_dimension(); 01179 if (space_dim < expr_space_dim) 01180 throw_dimension_incompatible((maximize 01181 ? "maximize(e, ...)" 01182 : "minimize(e, ...)"), "e", expr); 01183 // Deal with zero-dim BDS first. 01184 if (space_dim == 0) { 01185 if (marked_empty()) 01186 return false; 01187 else { 01188 ext_n = expr.inhomogeneous_term(); 01189 ext_d = 1; 01190 included = true; 01191 return true; 01192 } 01193 } 01194 01195 shortest_path_closure_assign(); 01196 // For an empty BDS we simply return false. 01197 if (marked_empty()) 01198 return false; 01199 01200 // The constraint `c' is used to check if `expr' is a difference 01201 // bounded and, in this case, to select the cell. 01202 const Constraint& c = maximize ? expr <= 0 : expr >= 0; 01203 const dimension_type c_space_dim = c.space_dimension(); 01204 dimension_type num_vars = 0; 01205 dimension_type i = 0; 01206 dimension_type j = 0; 01207 PPL_DIRTY_TEMP_COEFFICIENT(coeff); 01208 // Check if `c' is a BD constraint. 01209 if (!extract_bounded_difference(c, c_space_dim, num_vars, i, j, coeff)) { 01210 Optimization_Mode mode_max_min 01211 = maximize ? MAXIMIZATION : MINIMIZATION; 01212 MIP_Problem mip(space_dim, constraints(), expr, mode_max_min); 01213 if (mip.solve() == OPTIMIZED_MIP_PROBLEM) { 01214 mip.optimal_value(ext_n, ext_d); 01215 included = true; 01216 return true; 01217 } 01218 else 01219 // Here`expr' is unbounded in `*this'. 01220 return false; 01221 } 01222 else { 01223 // Here `expr' is a bounded difference. 01224 if (num_vars == 0) { 01225 // Dealing with a trivial expression. 01226 ext_n = expr.inhomogeneous_term(); 01227 ext_d = 1; 01228 included = true; 01229 return true; 01230 } 01231 01232 // Select the cell to be checked. 01233 const N& x = (coeff < 0) ? dbm[i][j] : dbm[j][i]; 01234 if (!is_plus_infinity(x)) { 01235 // Compute the maximize/minimize of `expr'. 01236 PPL_DIRTY_TEMP(N, d); 01237 const Coefficient& b = expr.inhomogeneous_term(); 01238 PPL_DIRTY_TEMP_COEFFICIENT(minus_b); 01239 neg_assign(minus_b, b); 01240 const Coefficient& sc_b = maximize ? b : minus_b; 01241 assign_r(d, sc_b, ROUND_UP); 01242 // Set `coeff_expr' to the absolute value of coefficient of 01243 // a variable in `expr'. 01244 PPL_DIRTY_TEMP(N, coeff_expr); 01245 const Coefficient& coeff_i = expr.coefficient(Variable(i-1)); 01246 const int sign_i = sgn(coeff_i); 01247 if (sign_i > 0) 01248 assign_r(coeff_expr, coeff_i, ROUND_UP); 01249 else { 01250 PPL_DIRTY_TEMP_COEFFICIENT(minus_coeff_i); 01251 neg_assign(minus_coeff_i, coeff_i); 01252 assign_r(coeff_expr, minus_coeff_i, ROUND_UP); 01253 } 01254 // Approximating the maximum/minimum of `expr'. 01255 add_mul_assign_r(d, coeff_expr, x, ROUND_UP); 01256 numer_denom(d, ext_n, ext_d); 01257 if (!maximize) 01258 neg_assign(ext_n); 01259 included = true; 01260 return true; 01261 } 01262 01263 // `expr' is unbounded. 01264 return false; 01265 } 01266 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::max_min | ( | const Linear_Expression & | expr, | |
| bool | maximize, | |||
| Coefficient & | ext_n, | |||
| Coefficient & | ext_d, | |||
| bool & | included, | |||
| Generator & | g | |||
| ) | const [inline, private] |
Maximizes or minimizes expr subject to *this.
| expr | The linear expression to be maximized or minimized subject to this; | |
| maximize | true if maximization is what is wanted; | |
| 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 can actually be reached in * this; | |
| g | When maximization or minimization succeeds, will be assigned a point or closure point where expr reaches the corresponding 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 g are left untouched.
Definition at line 1270 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::constraints(), Parma_Polyhedra_Library::MIP_Problem::evaluate_objective_function(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::MINIMIZATION, Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, Parma_Polyhedra_Library::MIP_Problem::optimizing_point(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::MIP_Problem::solve(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::maximize(), and Parma_Polyhedra_Library::BD_Shape< T >::minimize().
01274 { 01275 // The dimension of `expr' should not be greater than the dimension 01276 // of `*this'. 01277 const dimension_type space_dim = space_dimension(); 01278 const dimension_type expr_space_dim = expr.space_dimension(); 01279 if (space_dim < expr_space_dim) 01280 throw_dimension_incompatible((maximize 01281 ? "maximize(e, ...)" 01282 : "minimize(e, ...)"), "e", expr); 01283 // Deal with zero-dim BDS first. 01284 if (space_dim == 0) { 01285 if (marked_empty()) 01286 return false; 01287 else { 01288 ext_n = expr.inhomogeneous_term(); 01289 ext_d = 1; 01290 included = true; 01291 g = point(); 01292 return true; 01293 } 01294 } 01295 01296 shortest_path_closure_assign(); 01297 // For an empty BDS we simply return false. 01298 if (marked_empty()) 01299 return false; 01300 01301 Optimization_Mode mode_max_min 01302 = maximize ? MAXIMIZATION : MINIMIZATION; 01303 MIP_Problem mip(space_dim, constraints(), expr, mode_max_min); 01304 if (mip.solve() == OPTIMIZED_MIP_PROBLEM) { 01305 g = mip.optimizing_point(); 01306 mip.evaluate_objective_function(g, ext_n, ext_d); 01307 included = true; 01308 return true; 01309 } 01310 // Here `expr' is unbounded in `*this'. 01311 return false; 01312 }
| dimension_type Parma_Polyhedra_Library::BD_Shape< T >::max_space_dimension | ( | ) | [inline, static] |
Returns the maximum space dimension that a BDS can handle.
Definition at line 46 of file BD_Shape.inlines.hh.
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::expand_space_dimension().
00046 { 00047 // One dimension is reserved to have a value of type dimension_type 00048 // that does not represent a legal dimension. 00049 return std::min(DB_Matrix<N>::max_num_rows() - 1, 00050 DB_Matrix<N>::max_num_columns() - 1); 00051 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::maximize | ( | const Linear_Expression & | expr, | |
| Coefficient & | sup_n, | |||
| Coefficient & | sup_d, | |||
| bool & | maximum, | |||
| Generator & | g | |||
| ) | 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 and only if the supremum is also the maximum value; | |
| g | When maximization succeeds, will be assigned the point or closure 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 from above, false is returned and sup_n, sup_d, maximum and g are left untouched.
Definition at line 382 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::max_min().
00384 { 00385 return max_min(expr, true, sup_n, sup_d, maximum, g); 00386 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::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 and only if the supremum is also the maximum value. |
| std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
If *this is empty or expr is not bounded from above, false is returned and sup_n, sup_d and maximum are left untouched.
Definition at line 374 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::max_min().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::relation_with().
00376 { 00377 return max_min(expr, true, sup_n, sup_d, maximum); 00378 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::minimize | ( | const Linear_Expression & | expr, | |
| Coefficient & | inf_n, | |||
| Coefficient & | inf_d, | |||
| bool & | minimum, | |||
| Generator & | g | |||
| ) | 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 and only if the infimum is also the minimum value; | |
| g | When minimization succeeds, will be assigned a point or closure 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 g are left untouched.
Definition at line 398 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::max_min().
00400 { 00401 return max_min(expr, false, inf_n, inf_d, minimum, g); 00402 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::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 and only if the infimum is also the minimum 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 and minimum are left untouched.
Definition at line 390 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::max_min().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::relation_with().
00392 { 00393 return max_min(expr, false, inf_n, inf_d, minimum); 00394 }
| Congruence_System Parma_Polyhedra_Library::BD_Shape< T >::minimized_congruences | ( | ) | const [inline] |
Returns a minimal system of (equality) congruences satisfied by *this with the same affine dimension as *this.
Definition at line 323 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::compute_leaders(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::Congruence_System::insert(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::Congruence_System::zero_dim_empty().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::congruences().
00323 { 00324 // Shortest-path closure is necessary to detect emptiness 00325 // and all (possibly implicit) equalities. 00326 shortest_path_closure_assign(); 00327 00328 const dimension_type space_dim = space_dimension(); 00329 Congruence_System cgs; 00330 if (space_dim == 0) { 00331 if (marked_empty()) 00332 cgs = Congruence_System::zero_dim_empty(); 00333 } 00334 else if (marked_empty()) 00335 cgs.insert((0*Variable(space_dim-1) %= 1) / 0); 00336 else { 00337 // KLUDGE: in the future `cgs' will be constructed of the right dimension. 00338 // For the time being, we force the dimension with the following line. 00339 cgs.insert(0*Variable(space_dim-1) == 0); 00340 00341 PPL_DIRTY_TEMP_COEFFICIENT(num); 00342 PPL_DIRTY_TEMP_COEFFICIENT(den); 00343 00344 // Compute leader information. 00345 std::vector<dimension_type> leaders; 00346 compute_leaders(leaders); 00347 00348 // Go through the non-leaders to generate equality constraints. 00349 const DB_Row<N>& dbm_0 = dbm[0]; 00350 for (dimension_type i = 1; i <= space_dim; ++i) { 00351 const dimension_type leader = leaders[i]; 00352 if (i != leader) { 00353 // Generate the constraint relating `i' and its leader. 00354 if (leader == 0) { 00355 // A unary equality has to be generated. 00356 PPL_ASSERT(!is_plus_infinity(dbm_0[i])); 00357 numer_denom(dbm_0[i], num, den); 00358 cgs.insert(den*Variable(i-1) == num); 00359 } 00360 else { 00361 // A binary equality has to be generated. 00362 PPL_ASSERT(!is_plus_infinity(dbm[i][leader])); 00363 numer_denom(dbm[i][leader], num, den); 00364 cgs.insert(den*Variable(leader-1) - den*Variable(i-1) == num); 00365 } 00366 } 00367 } 00368 } 00369 return cgs; 00370 }
| Constraint_System Parma_Polyhedra_Library::BD_Shape< T >::minimized_constraints | ( | ) | const [inline] |
Returns a minimized system of constraints defining *this.
Definition at line 5468 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::compute_leader_indices(), Parma_Polyhedra_Library::BD_Shape< T >::compute_leaders(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::Constraint_System::zero_dim_empty().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::constraints().
05468 { 05469 shortest_path_reduction_assign(); 05470 Constraint_System cs; 05471 const dimension_type space_dim = space_dimension(); 05472 if (space_dim == 0) { 05473 if (marked_empty()) 05474 cs = Constraint_System::zero_dim_empty(); 05475 } 05476 else if (marked_empty()) 05477 cs.insert(0*Variable(space_dim-1) <= -1); 05478 else { 05479 // KLUDGE: in the future `cs' will be constructed of the right dimension. 05480 // For the time being, we force the dimension with the following line. 05481 cs.insert(0*Variable(space_dim-1) <= 0); 05482 05483 PPL_DIRTY_TEMP_COEFFICIENT(num); 05484 PPL_DIRTY_TEMP_COEFFICIENT(den); 05485 05486 // Compute leader information. 05487 std::vector<dimension_type> leaders; 05488 compute_leaders(leaders); 05489 std::vector<dimension_type> leader_indices; 05490 compute_leader_indices(leaders, leader_indices); 05491 const dimension_type num_leaders = leader_indices.size(); 05492 05493 // Go through the non-leaders to generate equality constraints. 05494 const DB_Row<N>& dbm_0 = dbm[0]; 05495 for (dimension_type i = 1; i <= space_dim; ++i) { 05496 const dimension_type leader = leaders[i]; 05497 if (i != leader) { 05498 // Generate the constraint relating `i' and its leader. 05499 if (leader == 0) { 05500 // A unary equality has to be generated. 05501 PPL_ASSERT(!is_plus_infinity(dbm_0[i])); 05502 numer_denom(dbm_0[i], num, den); 05503 cs.insert(den*Variable(i-1) == num); 05504 } 05505 else { 05506 // A binary equality has to be generated. 05507 PPL_ASSERT(!is_plus_infinity(dbm[i][leader])); 05508 numer_denom(dbm[i][leader], num, den); 05509 cs.insert(den*Variable(leader-1) - den*Variable(i-1) == num); 05510 } 05511 } 05512 } 05513 05514 // Go through the leaders to generate inequality constraints. 05515 // First generate all the unary inequalities. 05516 const Bit_Row& red_0 = redundancy_dbm[0]; 05517 for (dimension_type l_i = 1; l_i < num_leaders; ++l_i) { 05518 const dimension_type i = leader_indices[l_i]; 05519 if (!red_0[i]) { 05520 numer_denom(dbm_0[i], num, den); 05521 cs.insert(den*Variable(i-1) <= num); 05522 } 05523 if (!redundancy_dbm[i][0]) { 05524 numer_denom(dbm[i][0], num, den); 05525 cs.insert(-den*Variable(i-1) <= num); 05526 } 05527 } 05528 // Then generate all the binary inequalities. 05529 for (dimension_type l_i = 1; l_i < num_leaders; ++l_i) { 05530 const dimension_type i = leader_indices[l_i]; 05531 const DB_Row<N>& dbm_i = dbm[i]; 05532 const Bit_Row& red_i = redundancy_dbm[i]; 05533 for (dimension_type l_j = l_i + 1; l_j < num_leaders; ++l_j) { 05534 const dimension_type j = leader_indices[l_j]; 05535 if (!red_i[j]) { 05536 numer_denom(dbm_i[j], num, den); 05537 cs.insert(den*Variable(j-1) - den*Variable(i-1) <= num); 05538 } 05539 if (!redundancy_dbm[j][i]) { 05540 numer_denom(dbm[j][i], num, den); 05541 cs.insert(den*Variable(i-1) - den*Variable(j-1) <= num); 05542 } 05543 } 05544 } 05545 } 05546 return cs; 05547 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::OK | ( | ) | const [inline] |
Returns true if and only if *this satisfies all its invariants.
Definition at line 5842 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::is_minus_infinity(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::DB_Matrix< T >::num_rows(), Parma_Polyhedra_Library::BD_Shape< T >::Status::OK(), Parma_Polyhedra_Library::DB_Matrix< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm, Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::status.
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::BD_Shape< T >::BFT00_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::BHZ09_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::BD_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::BD_Shape< T >::difference_assign(), Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::BD_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::H79_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::BD_Shape< T >::limited_H79_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::refine(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::time_elapse_assign(), Parma_Polyhedra_Library::BD_Shape< T >::unconstrain(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign().
05842 { 05843 // Check whether the difference-bound matrix is well-formed. 05844 if (!dbm.OK()) 05845 return false; 05846 05847 // Check whether the status information is legal. 05848 if (!status.OK()) 05849 return false; 05850 05851 // An empty BDS is OK. 05852 if (marked_empty()) 05853 return true; 05854 05855 // MINUS_INFINITY cannot occur at all. 05856 for (dimension_type i = dbm.num_rows(); i-- > 0; ) 05857 for (dimension_type j = dbm.num_rows(); j-- > 0; ) 05858 if (is_minus_infinity(dbm[i][j])) { 05859 #ifndef NDEBUG 05860 using namespace Parma_Polyhedra_Library::IO_Operators; 05861 std::cerr << "BD_Shape::dbm[" << i << "][" << j << "] = " 05862 << dbm[i][j] << "!" 05863 << std::endl; 05864 #endif 05865 return false; 05866 } 05867 05868 // On the main diagonal only PLUS_INFINITY can occur. 05869 for (dimension_type i = dbm.num_rows(); i-- > 0; ) 05870 if (!is_plus_infinity(dbm[i][i])) { 05871 #ifndef NDEBUG 05872 using namespace Parma_Polyhedra_Library::IO_Operators; 05873 std::cerr << "BD_Shape::dbm[" << i << "][" << i << "] = " 05874 << dbm[i][i] << "! (+inf was expected.)" 05875 << std::endl; 05876 #endif 05877 return false; 05878 } 05879 05880 // Check whether the shortest-path closure information is legal. 05881 if (marked_shortest_path_closed()) { 05882 BD_Shape x = *this; 05883 x.reset_shortest_path_closed(); 05884 x.shortest_path_closure_assign(); 05885 if (x.dbm != dbm) { 05886 #ifndef NDEBUG 05887 std::cerr << "BD_Shape is marked as closed but it is not!" 05888 << std::endl; 05889 #endif 05890 return false; 05891 } 05892 } 05893 05894 // The following tests might result in false alarms when using floating 05895 // point coefficients: they are only meaningful if the coefficient type 05896 // base is exact (since otherwise shortest-path closure is approximated). 05897 if (std::numeric_limits<coefficient_type_base>::is_exact) { 05898 05899 // Check whether the shortest-path reduction information is legal. 05900 if (marked_shortest_path_reduced()) { 05901 // A non-redundant constraint cannot be equal to PLUS_INFINITY. 05902 for (dimension_type i = dbm.num_rows(); i-- > 0; ) 05903 for (dimension_type j = dbm.num_rows(); j-- > 0; ) 05904 if (!redundancy_dbm[i][j] && is_plus_infinity(dbm[i][j])) { 05905 #ifndef NDEBUG 05906 using namespace Parma_Polyhedra_Library::IO_Operators; 05907 std::cerr << "BD_Shape::dbm[" << i << "][" << j << "] = " 05908 << dbm[i][j] << " is marked as non-redundant!" 05909 << std::endl; 05910 #endif 05911 return false; 05912 } 05913 05914 BD_Shape x = *this; 05915 x.reset_shortest_path_reduced(); 05916 x.shortest_path_reduction_assign(); 05917 if (x.redundancy_dbm != redundancy_dbm) { 05918 #ifndef NDEBUG 05919 std::cerr << "BD_Shape is marked as reduced but it is not!" 05920 << std::endl; 05921 #endif 05922 return false; 05923 } 05924 } 05925 } 05926 05927 // All checks passed. 05928 return true; 05929 }
| BD_Shape< T > & Parma_Polyhedra_Library::BD_Shape< T >::operator= | ( | const BD_Shape< T > & | y | ) | [inline] |
The assignment operator (*this and y can be dimension-incompatible).
Definition at line 326 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm, and Parma_Polyhedra_Library::BD_Shape< T >::status.
00326 { 00327 dbm = y.dbm; 00328 status = y.status; 00329 if (y.marked_shortest_path_reduced()) 00330 redundancy_dbm = y.redundancy_dbm; 00331 return *this; 00332 }
| void Parma_Polyhedra_Library::BD_Shape< T >::print | ( | ) | const |
Prints *this to std::cerr using operator<<.
| void Parma_Polyhedra_Library::BD_Shape< T >::refine | ( | Variable | var, | |
| Relation_Symbol | relsym, | |||
| const Linear_Expression & | expr, | |||
| Coefficient_traits::const_reference | denominator = Coefficient_one() | |||
| ) | [inline, private] |
Adds to the BDS the constraint
.
Note that the coefficient of var in expr is null.
Definition at line 3441 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::add_dbm_constraint(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::deduce_u_minus_v_bounds(), Parma_Polyhedra_Library::BD_Shape< T >::deduce_v_minus_u_bounds(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::Linear_Expression::space_dimension().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage().
03444 { 03445 PPL_ASSERT(denominator != 0); 03446 const dimension_type expr_space_dim = expr.space_dimension(); 03447 PPL_ASSERT(space_dimension() >= expr_space_dim); 03448 const dimension_type v = var.id() + 1; 03449 PPL_ASSERT(v <= space_dimension()); 03450 PPL_ASSERT(expr.coefficient(var) == 0); 03451 PPL_ASSERT(relsym != LESS_THAN && relsym != GREATER_THAN); 03452 03453 const Coefficient& b = expr.inhomogeneous_term(); 03454 // Number of non-zero coefficients in `expr': will be set to 03455 // 0, 1, or 2, the latter value meaning any value greater than 1. 03456 dimension_type t = 0; 03457 // Index of the last non-zero coefficient in `expr', if any. 03458 dimension_type w = 0; 03459 // Get information about the number of non-zero coefficients in `expr'. 03460 for (dimension_type i = expr_space_dim; i-- > 0; ) 03461 if (expr.coefficient(Variable(i)) != 0) { 03462 if (t++ == 1) 03463 break; 03464 else 03465 w = i+1; 03466 } 03467 03468 // Since we are only able to record bounded differences, we can 03469 // precisely deal with the case of a single variable only if its 03470 // coefficient (taking into account the denominator) is 1. 03471 // If this is not the case, we fall back to the general case 03472 // so as to over-approximate the constraint. 03473 if (t == 1 && expr.coefficient(Variable(w-1)) != denominator) 03474 t = 2; 03475 03476 // Now we know the form of `expr': 03477 // - If t == 0, then expr == b, with `b' a constant; 03478 // - If t == 1, then expr == a*w + b, where `w != v' and `a == denominator'; 03479 // - If t == 2, the `expr' is of the general form. 03480 const DB_Row<N>& dbm_0 = dbm[0]; 03481 PPL_DIRTY_TEMP_COEFFICIENT(minus_den); 03482 neg_assign(minus_den, denominator); 03483 03484 if (t == 0) { 03485 // Case 1: expr == b. 03486 switch (relsym) { 03487 case EQUAL: 03488 // Add the constraint `var == b/denominator'. 03489 add_dbm_constraint(0, v, b, denominator); 03490 add_dbm_constraint(v, 0, b, minus_den); 03491 break; 03492 case LESS_OR_EQUAL: 03493 // Add the constraint `var <= b/denominator'. 03494 add_dbm_constraint(0, v, b, denominator); 03495 break; 03496 case GREATER_OR_EQUAL: 03497 // Add the constraint `var >= b/denominator', 03498 // i.e., `-var <= -b/denominator', 03499 add_dbm_constraint(v, 0, b, minus_den); 03500 break; 03501 default: 03502 // We already dealt with the other cases. 03503 throw std::runtime_error("PPL internal error"); 03504 } 03505 return; 03506 } 03507 03508 if (t == 1) { 03509 // Case 2: expr == a*w + b, w != v, a == denominator. 03510 PPL_ASSERT(expr.coefficient(Variable(w-1)) == denominator); 03511 PPL_DIRTY_TEMP(N, d); 03512 switch (relsym) { 03513 case EQUAL: 03514 // Add the new constraint `v - w <= b/denominator'. 03515 div_round_up(d, b, denominator); 03516 add_dbm_constraint(w, v, d); 03517 // Add the new constraint `v - w >= b/denominator', 03518 // i.e., `w - v <= -b/denominator'. 03519 div_round_up(d, b, minus_den); 03520 add_dbm_constraint(v, w, d); 03521 break; 03522 case LESS_OR_EQUAL: 03523 // Add the new constraint `v - w <= b/denominator'. 03524 div_round_up(d, b, denominator); 03525 add_dbm_constraint(w, v, d); 03526 break; 03527 case GREATER_OR_EQUAL: 03528 // Add the new constraint `v - w >= b/denominator', 03529 // i.e., `w - v <= -b/denominator'. 03530 div_round_up(d, b, minus_den); 03531 add_dbm_constraint(v, w, d); 03532 break; 03533 default: 03534 // We already dealt with the other cases. 03535 throw std::runtime_error("PPL internal error"); 03536 } 03537 return; 03538 } 03539 03540 // Here t == 2, so that either 03541 // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2, or 03542 // expr == a*w + b, w != v and a != denominator. 03543 const bool is_sc = (denominator > 0); 03544 PPL_DIRTY_TEMP_COEFFICIENT(minus_b); 03545 neg_assign(minus_b, b); 03546 const Coefficient& sc_b = is_sc ? b : minus_b; 03547 const Coefficient& minus_sc_b = is_sc ? minus_b : b; 03548 const Coefficient& sc_den = is_sc ? denominator : minus_den; 03549 const Coefficient& minus_sc_den = is_sc ? minus_den : denominator; 03550 // NOTE: here, for optimization purposes, `minus_expr' is only assigned 03551 // when `denominator' is negative. Do not use it unless you are sure 03552 // it has been correctly assigned. 03553 Linear_Expression minus_expr; 03554 if (!is_sc) 03555 minus_expr = -expr; 03556 const Linear_Expression& sc_expr = is_sc ? expr : minus_expr; 03557 03558 PPL_DIRTY_TEMP(N, sum); 03559 // Indices of the variables that are unbounded in `this->dbm'. 03560 PPL_UNINITIALIZED(dimension_type, pinf_index); 03561 // Number of unbounded variables found. 03562 dimension_type pinf_count = 0; 03563 03564 // Speculative allocation of temporaries that are used in most 03565 // of the computational traces starting from this point (also loops). 03566 PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i); 03567 PPL_DIRTY_TEMP(N, coeff_i); 03568 03569 switch (relsym) { 03570 case EQUAL: 03571 { 03572 PPL_DIRTY_TEMP(N, neg_sum); 03573 // Indices of the variables that are unbounded in `this->dbm'. 03574 PPL_UNINITIALIZED(dimension_type, neg_pinf_index); 03575 // Number of unbounded variables found. 03576 dimension_type neg_pinf_count = 0; 03577 03578 // Compute an upper approximation for `expr' into `sum', 03579 // taking into account the sign of `denominator'. 03580 03581 // Approximate the inhomogeneous term. 03582 assign_r(sum, sc_b, ROUND_UP); 03583 assign_r(neg_sum, minus_sc_b, ROUND_UP); 03584 03585 // Approximate the homogeneous part of `sc_expr'. 03586 // Note: indices above `w' can be disregarded, as they all have 03587 // a zero coefficient in `expr'. 03588 for (dimension_type i = w; i > 0; --i) { 03589 const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1)); 03590 const int sign_i = sgn(sc_i); 03591 if (sign_i == 0) 03592 continue; 03593 if (sign_i > 0) { 03594 assign_r(coeff_i, sc_i, ROUND_UP); 03595 // Approximating `sc_expr'. 03596 if (pinf_count <= 1) { 03597 const N& approx_i = dbm_0[i]; 03598 if (!is_plus_infinity(approx_i)) 03599 add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP); 03600 else { 03601 ++pinf_count; 03602 pinf_index = i; 03603 } 03604 } 03605 // Approximating `-sc_expr'. 03606 if (neg_pinf_count <= 1) { 03607 const N& approx_minus_i = dbm[i][0]; 03608 if (!is_plus_infinity(approx_minus_i)) 03609 add_mul_assign_r(neg_sum, coeff_i, approx_minus_i, ROUND_UP); 03610 else { 03611 ++neg_pinf_count; 03612 neg_pinf_index = i; 03613 } 03614 } 03615 } 03616 else if (sign_i < 0) { 03617 neg_assign(minus_sc_i, sc_i); 03618 // Note: using temporary named `coeff_i' to store -coeff_i. 03619 assign_r(coeff_i, minus_sc_i, ROUND_UP); 03620 // Approximating `sc_expr'. 03621 if (pinf_count <= 1) { 03622 const N& approx_minus_i = dbm[i][0]; 03623 if (!is_plus_infinity(approx_minus_i)) 03624 add_mul_assign_r(sum, coeff_i, approx_minus_i, ROUND_UP); 03625 else { 03626 ++pinf_count; 03627 pinf_index = i; 03628 } 03629 } 03630 // Approximating `-sc_expr'. 03631 if (neg_pinf_count <= 1) { 03632 const N& approx_i = dbm_0[i]; 03633 if (!is_plus_infinity(approx_i)) 03634 add_mul_assign_r(neg_sum, coeff_i, approx_i, ROUND_UP); 03635 else { 03636 ++neg_pinf_count; 03637 neg_pinf_index = i; 03638 } 03639 } 03640 } 03641 } 03642 // Return immediately if no approximation could be computed. 03643 if (pinf_count > 1 && neg_pinf_count > 1) { 03644 PPL_ASSERT(OK()); 03645 return; 03646 } 03647 03648 // In the following, shortest-path closure will be definitely lost. 03649 reset_shortest_path_closed(); 03650 03651 // Before computing quotients, the denominator should be approximated 03652 // towards zero. Since `sc_den' is known to be positive, this amounts to 03653 // rounding downwards, which is achieved as usual by rounding upwards 03654 // `minus_sc_den' and negating again the result. 03655 PPL_DIRTY_TEMP(N, down_sc_den); 03656 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 03657 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 03658 03659 // Exploit the upper approximation, if possible. 03660 if (pinf_count <= 1) { 03661 // Compute quotient (if needed). 03662 if (down_sc_den != 1) 03663 div_assign_r(sum, sum, down_sc_den, ROUND_UP); 03664 // Add the upper bound constraint, if meaningful. 03665 if (pinf_count == 0) { 03666 // Add the constraint `v <= sum'. 03667 dbm[0][v] = sum; 03668 // Deduce constraints of the form `v - u', where `u != v'. 03669 deduce_v_minus_u_bounds(v, w, sc_expr, sc_den, sum); 03670 } 03671 else 03672 // Here `pinf_count == 1'. 03673 if (pinf_index != v 03674 && sc_expr.coefficient(Variable(pinf_index-1)) == sc_den) 03675 // Add the constraint `v - pinf_index <= sum'. 03676 dbm[pinf_index][v] = sum; 03677 } 03678 03679 // Exploit the lower approximation, if possible. 03680 if (neg_pinf_count <= 1) { 03681 // Compute quotient (if needed). 03682 if (down_sc_den != 1) 03683 div_assign_r(neg_sum, neg_sum, down_sc_den, ROUND_UP); 03684 // Add the lower bound constraint, if meaningful. 03685 if (neg_pinf_count == 0) { 03686 // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'. 03687 DB_Row<N>& dbm_v = dbm[v]; 03688 dbm_v[0] = neg_sum; 03689 // Deduce constraints of the form `u - v', where `u != v'. 03690 deduce_u_minus_v_bounds(v, w, sc_expr, sc_den, neg_sum); 03691 } 03692 else 03693 // Here `neg_pinf_count == 1'. 03694 if (neg_pinf_index != v 03695 && sc_expr.coefficient(Variable(neg_pinf_index-1)) == sc_den) 03696 // Add the constraint `v - neg_pinf_index >= -neg_sum', 03697 // i.e., `neg_pinf_index - v <= neg_sum'. 03698 dbm[v][neg_pinf_index] = neg_sum; 03699 } 03700 } 03701 break; 03702 03703 case LESS_OR_EQUAL: 03704 // Compute an upper approximation for `expr' into `sum', 03705 // taking into account the sign of `denominator'. 03706 03707 // Approximate the inhomogeneous term. 03708 assign_r(sum, sc_b, ROUND_UP); 03709 03710 // Approximate the homogeneous part of `sc_expr'. 03711 // Note: indices above `w' can be disregarded, as they all have 03712 // a zero coefficient in `expr'. 03713 for (dimension_type i = w; i > 0; --i) { 03714 const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1)); 03715 const int sign_i = sgn(sc_i); 03716 if (sign_i == 0) 03717 continue; 03718 // Choose carefully: we are approximating `sc_expr'. 03719 const N& approx_i = (sign_i > 0) ? dbm_0[i] : dbm[i][0]; 03720 if (is_plus_infinity(approx_i)) { 03721 if (++pinf_count > 1) 03722 break; 03723 pinf_index = i; 03724 continue; 03725 } 03726 if (sign_i > 0) 03727 assign_r(coeff_i, sc_i, ROUND_UP); 03728 else { 03729 neg_assign(minus_sc_i, sc_i); 03730 assign_r(coeff_i, minus_sc_i, ROUND_UP); 03731 } 03732 add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP); 03733 } 03734 03735 // Divide by the (sign corrected) denominator (if needed). 03736 if (sc_den != 1) { 03737 // Before computing the quotient, the denominator should be 03738 // approximated towards zero. Since `sc_den' is known to be 03739 // positive, this amounts to rounding downwards, which is achieved 03740 // by rounding upwards `minus_sc-den' and negating again the result. 03741 PPL_DIRTY_TEMP(N, down_sc_den); 03742 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 03743 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 03744 div_assign_r(sum, sum, down_sc_den, ROUND_UP); 03745 } 03746 03747 if (pinf_count == 0) { 03748 // Add the constraint `v <= sum'. 03749 add_dbm_constraint(0, v, sum); 03750 // Deduce constraints of the form `v - u', where `u != v'. 03751 deduce_v_minus_u_bounds(v, w, sc_expr, sc_den, sum); 03752 } 03753 else if (pinf_count == 1) 03754 if (expr.coefficient(Variable(pinf_index-1)) == denominator) 03755 // Add the constraint `v - pinf_index <= sum'. 03756 add_dbm_constraint(pinf_index, v, sum); 03757 break; 03758 03759 case GREATER_OR_EQUAL: 03760 // Compute an upper approximation for `-sc_expr' into `sum'. 03761 // Note: approximating `-sc_expr' from above and then negating the 03762 // result is the same as approximating `sc_expr' from below. 03763 03764 // Approximate the inhomogeneous term. 03765 assign_r(sum, minus_sc_b, ROUND_UP); 03766 03767 // Approximate the homogeneous part of `-sc_expr'. 03768 for (dimension_type i = w; i > 0; --i) { 03769 const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1)); 03770 const int sign_i = sgn(sc_i); 03771 if (sign_i == 0) 03772 continue; 03773 // Choose carefully: we are approximating `-sc_expr'. 03774 const N& approx_i = (sign_i > 0) ? dbm[i][0] : dbm_0[i]; 03775 if (is_plus_infinity(approx_i)) { 03776 if (++pinf_count > 1) 03777 break; 03778 pinf_index = i; 03779 continue; 03780 } 03781 if (sign_i > 0) 03782 assign_r(coeff_i, sc_i, ROUND_UP); 03783 else { 03784 neg_assign(minus_sc_i, sc_i); 03785 assign_r(coeff_i, minus_sc_i, ROUND_UP); 03786 } 03787 add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP); 03788 } 03789 03790 // Divide by the (sign corrected) denominator (if needed). 03791 if (sc_den != 1) { 03792 // Before computing the quotient, the denominator should be 03793 // approximated towards zero. Since `sc_den' is known to be positive, 03794 // this amounts to rounding downwards, which is achieved by rounding 03795 // upwards `minus_sc_den' and negating again the result. 03796 PPL_DIRTY_TEMP(N, down_sc_den); 03797 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 03798 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 03799 div_assign_r(sum, sum, down_sc_den, ROUND_UP); 03800 } 03801 03802 if (pinf_count == 0) { 03803 // Add the constraint `v >= -sum', i.e., `-v <= sum'. 03804 add_dbm_constraint(v, 0, sum); 03805 // Deduce constraints of the form `u - v', where `u != v'. 03806 deduce_u_minus_v_bounds(v, w, sc_expr, sc_den, sum); 03807 } 03808 else if (pinf_count == 1) 03809 if (pinf_index != v 03810 && expr.coefficient(Variable(pinf_index-1)) == denominator) 03811 // Add the constraint `v - pinf_index >= -sum', 03812 // i.e., `pinf_index - v <= sum'. 03813 add_dbm_constraint(v, pinf_index, sum); 03814 break; 03815 03816 default: 03817 // We already dealt with the other cases. 03818 throw std::runtime_error("PPL internal error"); 03819 } 03820 03821 PPL_ASSERT(OK()); 03822 }
| void Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check | ( | const Congruence & | cg | ) | [inline, private] |
Uses the congruence cg to refine *this.
| cg | The congruence to be added. Nontrivial proper congruences are ignored. Non BD equalities are ignored. |
cg and *this are dimension-incompatible, the behavior is undefined. Definition at line 238 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), Parma_Polyhedra_Library::Congruence::is_proper_congruence(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::Congruence::space_dimension().
00238 { 00239 PPL_ASSERT(!marked_empty()); 00240 PPL_ASSERT(cg.space_dimension() <= space_dimension()); 00241 00242 if (cg.is_proper_congruence()) { 00243 if (cg.is_inconsistent()) 00244 set_empty(); 00245 // Other proper congruences are just ignored. 00246 return; 00247 } 00248 00249 PPL_ASSERT(cg.is_equality()); 00250 Constraint c(cg); 00251 refine_no_check(c); 00252 }
| void Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check | ( | const Constraint & | c | ) | [inline, private] |
Uses the constraint c to refine *this.
| c | The constraint to be added. Non BD constraints are ignored. |
c and *this are dimension-incompatible, the behavior is undefined. Definition at line 474 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::BD_Shape< T >::extract_bounded_difference(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::Constraint::space_dimension().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_congruence(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_congruences(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_constraint(), and Parma_Polyhedra_Library::BD_Shape< T >::refine_with_constraints().
00474 { 00475 PPL_ASSERT(!marked_empty()); 00476 const dimension_type c_space_dim = c.space_dimension(); 00477 PPL_ASSERT(c_space_dim <= space_dimension()); 00478 00479 dimension_type num_vars = 0; 00480 dimension_type i = 0; 00481 dimension_type j = 0; 00482 PPL_DIRTY_TEMP_COEFFICIENT(coeff); 00483 // Constraints that are not bounded differences are ignored. 00484 if (!extract_bounded_difference(c, c_space_dim, num_vars, i, j, coeff)) 00485 return; 00486 00487 const Coefficient& inhomo = c.inhomogeneous_term(); 00488 if (num_vars == 0) { 00489 // Dealing with a trivial constraint (might be a strict inequality). 00490 if (inhomo < 0 00491 || (c.is_equality() && inhomo != 0) 00492 || (c.is_strict_inequality() && inhomo == 0)) 00493 set_empty(); 00494 return; 00495 } 00496 00497 // Select the cell to be modified for the "<=" part of the constraint, 00498 // and set `coeff' to the absolute value of itself. 00499 const bool negative = (coeff < 0); 00500 N& x = negative ? dbm[i][j] : dbm[j][i]; 00501 N& y = negative ? dbm[j][i] : dbm[i][j]; 00502 if (negative) 00503 neg_assign(coeff); 00504 00505 bool changed = false; 00506 // Compute the bound for `x', rounding towards plus infinity. 00507 PPL_DIRTY_TEMP(N, d); 00508 div_round_up(d, inhomo, coeff); 00509 if (x > d) { 00510 x = d; 00511 changed = true; 00512 } 00513 00514 if (c.is_equality()) { 00515 // Also compute the bound for `y', rounding towards plus infinity. 00516 PPL_DIRTY_TEMP_COEFFICIENT(minus_c_term); 00517 neg_assign(minus_c_term, inhomo); 00518 div_round_up(d, minus_c_term, coeff); 00519 if (y > d) { 00520 y = d; 00521 changed = true; 00522 } 00523 } 00524 00525 // In general, adding a constraint does not preserve the shortest-path 00526 // closure or reduction of the bounded difference shape. 00527 if (changed && marked_shortest_path_closed()) 00528 reset_shortest_path_closed(); 00529 PPL_ASSERT(OK()); 00530 }
| void Parma_Polyhedra_Library::BD_Shape< T >::refine_with_congruence | ( | const Congruence & | cg | ) | [inline] |
Uses a copy of congruence cg to refine the system of bounded differences of *this.
| cg | The congruence. If it is not a bounded difference equality, it will be ignored. |
| std::invalid_argument | Thrown if *this and congruence cg are dimension-incompatible. |
Definition at line 213 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Congruence::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().
00213 { 00214 const dimension_type cg_space_dim = cg.space_dimension(); 00215 // Dimension-compatibility check. 00216 if (cg_space_dim > space_dimension()) 00217 throw_dimension_incompatible("refine_with_congruence(cg)", cg); 00218 00219 if (!marked_empty()) 00220 refine_no_check(cg); 00221 }
| void Parma_Polyhedra_Library::BD_Shape< T >::refine_with_congruences | ( | const Congruence_System & | cgs | ) | [inline] |
Uses a copy of the congruences in cgs to refine the system of bounded differences defining *this.
| cgs | The congruence system to be used. Congruences that are not bounded difference equalities are ignored. |
| std::invalid_argument | Thrown if *this and cgs are dimension-incompatible. |
Definition at line 225 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::Congruence_System::begin(), Parma_Polyhedra_Library::Congruence_System::end(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Congruence_System::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape().
00225 { 00226 // Dimension-compatibility check. 00227 if (cgs.space_dimension() > space_dimension()) 00228 throw_generic("refine_with_congruences(cgs)", 00229 "cgs and *this are space-dimension incompatible"); 00230 00231 for (Congruence_System::const_iterator i = cgs.begin(), 00232 cgs_end = cgs.end(); !marked_empty() && i != cgs_end; ++i) 00233 refine_no_check(*i); 00234 }
| void Parma_Polyhedra_Library::BD_Shape< T >::refine_with_constraint | ( | const Constraint & | c | ) | [inline] |
Uses a copy of constraint c to refine the system of bounded differences defining *this.
| c | The constraint. If it is not a bounded difference, it will be ignored. |
| std::invalid_argument | Thrown if *this and constraint c are dimension-incompatible. |
Definition at line 188 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Constraint::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().
00188 { 00189 const dimension_type c_space_dim = c.space_dimension(); 00190 // Dimension-compatibility check. 00191 if (c_space_dim > space_dimension()) 00192 throw_dimension_incompatible("refine_with_constraint(c)", c); 00193 00194 if (!marked_empty()) 00195 refine_no_check(c); 00196 }
| void Parma_Polyhedra_Library::BD_Shape< T >::refine_with_constraints | ( | const Constraint_System & | cs | ) | [inline] |
Uses a copy of the constraints in cs to refine the system of bounded differences defining *this.
| cs | The constraint system to be used. Constraints that are not bounded differences are ignored. |
| std::invalid_argument | Thrown if *this and cs are dimension-incompatible. |
Definition at line 200 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape().
00200 { 00201 // Dimension-compatibility check. 00202 if (cs.space_dimension() > space_dimension()) 00203 throw_generic("refine_with_constraints(cs)", 00204 "cs and *this are space-dimension incompatible"); 00205 00206 for (Constraint_System::const_iterator i = cs.begin(), 00207 cs_end = cs.end(); !marked_empty() && i != cs_end; ++i) 00208 refine_no_check(*i); 00209 }
| Poly_Gen_Relation Parma_Polyhedra_Library::BD_Shape< T >::relation_with | ( | const Generator & | g | ) | const [inline] |
Returns the relations holding between *this and the generator g.
| std::invalid_argument | Thrown if *this and generator g are dimension-incompatible. |
Definition at line 1651 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::add_mul_assign(), Parma_Polyhedra_Library::Generator::coefficient(), Parma_Polyhedra_Library::Coefficient_zero(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::Generator::divisor(), Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::Generator::is_line(), Parma_Polyhedra_Library::Generator::is_line_or_ray(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Poly_Gen_Relation::nothing(), Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::Generator::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Poly_Gen_Relation::subsumes(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().
01651 { 01652 const dimension_type space_dim = space_dimension(); 01653 const dimension_type g_space_dim = g.space_dimension(); 01654 01655 // Dimension-compatibility check. 01656 if (space_dim < g_space_dim) 01657 throw_dimension_incompatible("relation_with(g)", g); 01658 01659 shortest_path_closure_assign(); 01660 // The empty BDS cannot subsume a generator. 01661 if (marked_empty()) 01662 return Poly_Gen_Relation::nothing(); 01663 01664 // A universe BDS in a zero-dimensional space subsumes 01665 // all the generators of a zero-dimensional space. 01666 if (space_dim == 0) 01667 return Poly_Gen_Relation::subsumes(); 01668 01669 const bool is_line = g.is_line(); 01670 const bool is_line_or_ray = g.is_line_or_ray(); 01671 01672 // The relation between the BDS and the given generator is obtained 01673 // checking if the generator satisfies all the constraints in the BDS. 01674 // To check if the generator satisfies all the constraints it's enough 01675 // studying the sign of the scalar product between the generator and 01676 // all the constraints in the BDS. 01677 01678 // Allocation of temporaries done once and for all. 01679 PPL_DIRTY_TEMP_COEFFICIENT(num); 01680 PPL_DIRTY_TEMP_COEFFICIENT(den); 01681 PPL_DIRTY_TEMP_COEFFICIENT(product); 01682 // We find in `*this' all the constraints. 01683 for (dimension_type i = 0; i <= space_dim; ++i) { 01684 const Coefficient& g_coeff_y = (i > g_space_dim || i == 0) 01685 ? Coefficient_zero() : g.coefficient(Variable(i-1)); 01686 const DB_Row<N>& dbm_i = dbm[i]; 01687 for (dimension_type j = i + 1; j <= space_dim; ++j) { 01688 const Coefficient& g_coeff_x = (j > g_space_dim) 01689 ? Coefficient_zero() : g.coefficient(Variable(j-1)); 01690 const N& dbm_ij = dbm_i[j]; 01691 const N& dbm_ji = dbm[j][i]; 01692 if (is_additive_inverse(dbm_ji, dbm_ij)) { 01693 // We have one equality constraint: den*x - den*y = num. 01694 // Compute the scalar product. 01695 numer_denom(dbm_ij, num, den); 01696 product = 0; 01697 add_mul_assign(product, den, g_coeff_y); 01698 add_mul_assign(product, -den, g_coeff_x); 01699 if (!is_line_or_ray) 01700 add_mul_assign(product, num, g.divisor()); 01701 if (product != 0) 01702 return Poly_Gen_Relation::nothing(); 01703 } 01704 else { 01705 // We have 0, 1 or 2 binary inequality constraint/s. 01706 if (!is_plus_infinity(dbm_ij)) { 01707 // We have the binary inequality constraint: den*x - den*y <= num. 01708 // Compute the scalar product. 01709 numer_denom(dbm_ij, num, den); 01710 product = 0; 01711 add_mul_assign(product, den, g_coeff_y); 01712 add_mul_assign(product, -den, g_coeff_x); 01713 if (!is_line_or_ray) 01714 add_mul_assign(product, num, g.divisor()); 01715 if (is_line) { 01716 if (product != 0) 01717 // Lines must saturate all constraints. 01718 return Poly_Gen_Relation::nothing(); 01719 } 01720 else 01721 // `g' is either a ray, a point or a closure point. 01722 if (product < 0) 01723 return Poly_Gen_Relation::nothing(); 01724 } 01725 01726 if (!is_plus_infinity(dbm_ji)) { 01727 // We have the binary inequality constraint: den*y - den*x <= b. 01728 // Compute the scalar product. 01729 numer_denom(dbm_ji, num, den); 01730 product = 0; 01731 add_mul_assign(product, den, g_coeff_x); 01732 add_mul_assign(product, -den, g_coeff_y); 01733 if (!is_line_or_ray) 01734 add_mul_assign(product, num, g.divisor()); 01735 if (is_line) { 01736 if (product != 0) 01737 // Lines must saturate all constraints. 01738 return Poly_Gen_Relation::nothing(); 01739 } 01740 else 01741 // `g' is either a ray, a point or a closure point. 01742 if (product < 0) 01743 return Poly_Gen_Relation::nothing(); 01744 } 01745 } 01746 } 01747 } 01748 01749 // The generator satisfies all the constraints. 01750 return Poly_Gen_Relation::subsumes(); 01751 }
| Poly_Con_Relation Parma_Polyhedra_Library::BD_Shape< T >::relation_with | ( | const Congruence & | cg | ) | const [inline] |
Returns the relations holding between *this and the congruence cg.
| std::invalid_argument | Thrown if *this and congruence cg are dimension-incompatible. |
Definition at line 1316 of file BD_Shape.templates.hh.
References 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::Checked::le, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::maximize(), Parma_Polyhedra_Library::BD_Shape< T >::minimize(), Parma_Polyhedra_Library::Congruence::modulus(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::relation_with(), Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::Congruence::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Poly_Con_Relation::strictly_intersects(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().
01316 { 01317 const dimension_type space_dim = space_dimension(); 01318 01319 // Dimension-compatibility check. 01320 if (cg.space_dimension() > space_dim) 01321 throw_dimension_incompatible("relation_with(cg)", cg); 01322 01323 // If the congruence is an equality, find the relation with 01324 // the equivalent equality constraint. 01325 if (cg.is_equality()) { 01326 Constraint c(cg); 01327 return relation_with(c); 01328 } 01329 01330 shortest_path_closure_assign(); 01331 01332 if (marked_empty()) 01333 return Poly_Con_Relation::saturates() 01334 && Poly_Con_Relation::is_included() 01335 && Poly_Con_Relation::is_disjoint(); 01336 01337 if (space_dim == 0) { 01338 if (cg.is_inconsistent()) 01339 return Poly_Con_Relation::is_disjoint(); 01340 else 01341 return Poly_Con_Relation::saturates() 01342 && Poly_Con_Relation::is_included(); 01343 } 01344 01345 // Find the lower bound for a hyperplane with direction 01346 // defined by the congruence. 01347 Linear_Expression le = Linear_Expression(cg); 01348 PPL_DIRTY_TEMP_COEFFICIENT(min_num); 01349 PPL_DIRTY_TEMP_COEFFICIENT(min_den); 01350 bool min_included; 01351 bool bounded_below = minimize(le, min_num, min_den, min_included); 01352 01353 // If there is no lower bound, then some of the hyperplanes defined by 01354 // the congruence will strictly intersect the shape. 01355 if (!bounded_below) 01356 return Poly_Con_Relation::strictly_intersects(); 01357 01358 // TODO: Consider adding a max_and_min() method, performing both 01359 // maximization and minimization so as to possibly exploit 01360 // incrementality of the MIP solver. 01361 01362 // Find the upper bound for a hyperplane with direction 01363 // defined by the congruence. 01364 PPL_DIRTY_TEMP_COEFFICIENT(max_num); 01365 PPL_DIRTY_TEMP_COEFFICIENT(max_den); 01366 bool max_included; 01367 bool bounded_above = maximize(le, max_num, max_den, max_included); 01368 01369 // If there is no upper bound, then some of the hyperplanes defined by 01370 // the congruence will strictly intersect the shape. 01371 if (!bounded_above) 01372 return Poly_Con_Relation::strictly_intersects(); 01373 01374 PPL_DIRTY_TEMP_COEFFICIENT(signed_distance); 01375 01376 // Find the position value for the hyperplane that satisfies the congruence 01377 // and is above the lower bound for the shape. 01378 PPL_DIRTY_TEMP_COEFFICIENT(min_value); 01379 min_value = min_num / min_den; 01380 const Coefficient& modulus = cg.modulus(); 01381 signed_distance = min_value % modulus; 01382 min_value -= signed_distance; 01383 if (min_value * min_den < min_num) 01384 min_value += modulus; 01385 01386 // Find the position value for the hyperplane that satisfies the congruence 01387 // and is below the upper bound for the shape. 01388 PPL_DIRTY_TEMP_COEFFICIENT(max_value); 01389 max_value = max_num / max_den; 01390 signed_distance = max_value % modulus; 01391 max_value += signed_distance; 01392 if (max_value * max_den > max_num) 01393 max_value -= modulus; 01394 01395 // If the upper bound value is less than the lower bound value, 01396 // then there is an empty intersection with the congruence; 01397 // otherwise it will strictly intersect. 01398 if (max_value < min_value) 01399 return Poly_Con_Relation::is_disjoint(); 01400 else 01401 return Poly_Con_Relation::strictly_intersects(); 01402 }
| Poly_Con_Relation Parma_Polyhedra_Library::BD_Shape< T >::relation_with | ( | const Constraint & | c | ) | const [inline] |
Returns the relations holding between *this and the constraint c.
| std::invalid_argument | Thrown if *this and constraint c are dimension-incompatible. |
Definition at line 1407 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::extract_bounded_difference(), 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_inequality(), Parma_Polyhedra_Library::Constraint::is_nonstrict_inequality(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Checked::le, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::maximize(), Parma_Polyhedra_Library::BD_Shape< T >::minimize(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::Poly_Con_Relation::strictly_intersects(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::difference_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::relation_with().
01407 { 01408 const dimension_type c_space_dim = c.space_dimension(); 01409 const dimension_type space_dim = space_dimension(); 01410 01411 // Dimension-compatibility check. 01412 if (c_space_dim > space_dim) 01413 throw_dimension_incompatible("relation_with(c)", c); 01414 01415 shortest_path_closure_assign(); 01416 01417 if (marked_empty()) 01418 return Poly_Con_Relation::saturates() 01419 && Poly_Con_Relation::is_included() 01420 && Poly_Con_Relation::is_disjoint(); 01421 01422 if (space_dim == 0) { 01423 if ((c.is_equality() && c.inhomogeneous_term() != 0) 01424 || (c.is_inequality() && c.inhomogeneous_term() < 0)) 01425 return Poly_Con_Relation::is_disjoint(); 01426 else if (c.is_strict_inequality() && c.inhomogeneous_term() == 0) 01427 // The constraint 0 > 0 implicitly defines the hyperplane 0 = 0; 01428 // thus, the zero-dimensional point also saturates it. 01429 return Poly_Con_Relation::saturates() 01430 && Poly_Con_Relation::is_disjoint(); 01431 else if (c.is_equality() || c.inhomogeneous_term() == 0) 01432 return Poly_Con_Relation::saturates() 01433 && Poly_Con_Relation::is_included(); 01434 else 01435 // The zero-dimensional point saturates 01436 // neither the positivity constraint 1 >= 0, 01437 // nor the strict positivity constraint 1 > 0. 01438 return Poly_Con_Relation::is_included(); 01439 } 01440 01441 dimension_type num_vars = 0; 01442 dimension_type i = 0; 01443 dimension_type j = 0; 01444 PPL_DIRTY_TEMP_COEFFICIENT(coeff); 01445 if (!extract_bounded_difference(c, c_space_dim, num_vars, i, j, coeff)) { 01446 // Constraints that are not bounded differences. 01447 // Use maximize() and minimize() to do much of the work. 01448 01449 // Find the linear expression for the constraint and use that to 01450 // find if the expression is bounded from above or below and if it 01451 // is, find the maximum and minimum values. 01452 Linear_Expression le; 01453 for (dimension_type k = c_space_dim; k-- > 0; ) { 01454 Variable vk(k); 01455 le += c.coefficient(vk) * vk; 01456 } 01457 PPL_DIRTY_TEMP(Coefficient, max_num); 01458 PPL_DIRTY_TEMP(Coefficient, max_den); 01459 bool max_included; 01460 PPL_DIRTY_TEMP(Coefficient, min_num); 01461 PPL_DIRTY_TEMP(Coefficient, min_den); 01462 bool min_included; 01463 bool bounded_above = maximize(le, max_num, max_den, max_included); 01464 bool bounded_below = minimize(le, min_num, min_den, min_included); 01465 if (!bounded_above) { 01466 if (!bounded_below) 01467 return Poly_Con_Relation::strictly_intersects(); 01468 min_num += c.inhomogeneous_term() * min_den; 01469 switch (sgn(min_num)) { 01470 case 1: 01471 if (c.is_equality()) 01472 return Poly_Con_Relation::is_disjoint(); 01473 return Poly_Con_Relation::is_included(); 01474 case 0: 01475 if (c.is_strict_inequality() || c.is_equality()) 01476 return Poly_Con_Relation::strictly_intersects(); 01477 return Poly_Con_Relation::is_included(); 01478 case -1: 01479 return Poly_Con_Relation::strictly_intersects(); 01480 } 01481 } 01482 if (!bounded_below) { 01483 max_num += c.inhomogeneous_term() * max_den; 01484 switch (sgn(max_num)) { 01485 case 1: 01486 return Poly_Con_Relation::strictly_intersects(); 01487 case 0: 01488 if (c.is_strict_inequality()) 01489 return Poly_Con_Relation::is_disjoint(); 01490 return Poly_Con_Relation::strictly_intersects(); 01491 case -1: 01492 return Poly_Con_Relation::is_disjoint(); 01493 } 01494 } 01495 else { 01496 max_num += c.inhomogeneous_term() * max_den; 01497 min_num += c.inhomogeneous_term() * min_den; 01498 switch (sgn(max_num)) { 01499 case 1: 01500 switch (sgn(min_num)) { 01501 case 1: 01502 if (c.is_equality()) 01503 return Poly_Con_Relation::is_disjoint(); 01504 return Poly_Con_Relation::is_included(); 01505 case 0: 01506 if (c.is_equality()) 01507 return Poly_Con_Relation::strictly_intersects(); 01508 if (c.is_strict_inequality()) 01509 return Poly_Con_Relation::strictly_intersects(); 01510 return Poly_Con_Relation::is_included(); 01511 case -1: 01512 return Poly_Con_Relation::strictly_intersects(); 01513 } 01514 case 0: 01515 if (min_num == 0) { 01516 if (c.is_strict_inequality()) 01517 return Poly_Con_Relation::is_disjoint() 01518 && Poly_Con_Relation::saturates(); 01519 return Poly_Con_Relation::is_included() 01520 && Poly_Con_Relation::saturates(); 01521 } 01522 if (c.is_strict_inequality()) 01523 return Poly_Con_Relation::is_disjoint(); 01524 return Poly_Con_Relation::strictly_intersects(); 01525 case -1: 01526 return Poly_Con_Relation::is_disjoint(); 01527 } 01528 } 01529 } 01530 01531 // Constraints that are bounded differences. 01532 if (num_vars == 0) { 01533 // Dealing with a trivial constraint. 01534 switch (sgn(c.inhomogeneous_term())) { 01535 case -1: 01536 return Poly_Con_Relation::is_disjoint(); 01537 case 0: 01538 if (c.is_strict_inequality()) 01539 return Poly_Con_Relation::saturates() 01540 && Poly_Con_Relation::is_disjoint(); 01541 else 01542 return Poly_Con_Relation::saturates() 01543 && Poly_Con_Relation::is_included(); 01544 case 1: 01545 if (c.is_equality()) 01546 return Poly_Con_Relation::is_disjoint(); 01547 else 01548 return Poly_Con_Relation::is_included(); 01549 } 01550 } 01551 01552 // Select the cell to be checked for the "<=" part of the constraint, 01553 // and set `coeff' to the absolute value of itself. 01554 const bool negative = (coeff < 0); 01555 const N& x = negative ? dbm[i][j] : dbm[j][i]; 01556 const N& y = negative ? dbm[j][i] : dbm[i][j]; 01557 if (negative) 01558 neg_assign(coeff); 01559 // Deduce the relation/s of the constraint `c' of the form 01560 // `coeff*v - coeff*u </<=/== c.inhomogeneous_term()' 01561 // with the respectively constraints in `*this' 01562 // `-y <= v - u <= x'. 01563 // Let `d == c.inhomogeneous_term()/coeff' 01564 // and `d1 == -c.inhomogeneous_term()/coeff'. 01565 // The following variables of mpq_class type are used to be precise 01566 // when the bds is defined by integer constraints. 01567 PPL_DIRTY_TEMP0(mpq_class, q_x); 01568 PPL_DIRTY_TEMP0(mpq_class, q_y); 01569 PPL_DIRTY_TEMP0(mpq_class, d); 01570 PPL_DIRTY_TEMP0(mpq_class, d1); 01571 PPL_DIRTY_TEMP0(mpq_class, c_den); 01572 PPL_DIRTY_TEMP0(mpq_class, q_den); 01573 assign_r(c_den, coeff, ROUND_NOT_NEEDED); 01574 assign_r(d, c.inhomogeneous_term(), ROUND_NOT_NEEDED); 01575 neg_assign_r(d1, d, ROUND_NOT_NEEDED); 01576 div_assign_r(d, d, c_den, ROUND_NOT_NEEDED); 01577 div_assign_r(d1, d1, c_den, ROUND_NOT_NEEDED); 01578 01579 if (is_plus_infinity(x)) { 01580 if (!is_plus_infinity(y)) { 01581 // `*this' is in the following form: 01582 // `-y <= v - u'. 01583 // In this case `*this' is disjoint from `c' if 01584 // `-y > d' (`-y >= d' if c is a strict equality), i.e. if 01585 // `y < d1' (`y <= d1' if c is a strict equality). 01586 PPL_DIRTY_TEMP_COEFFICIENT(numer); 01587 PPL_DIRTY_TEMP_COEFFICIENT(denom); 01588 numer_denom(y, numer, denom); 01589 assign_r(q_den, denom, ROUND_NOT_NEEDED); 01590 assign_r(q_y, numer, ROUND_NOT_NEEDED); 01591 div_assign_r(q_y, q_y, q_den, ROUND_NOT_NEEDED); 01592 if (q_y < d1) 01593 return Poly_Con_Relation::is_disjoint(); 01594 if (q_y == d1 && c.is_strict_inequality()) 01595 return Poly_Con_Relation::is_disjoint(); 01596 } 01597 01598 // In all other cases `*this' intersects `c'. 01599 return Poly_Con_Relation::strictly_intersects(); 01600 } 01601 01602 // Here `x' is not plus-infinity. 01603 PPL_DIRTY_TEMP_COEFFICIENT(numer); 01604 PPL_DIRTY_TEMP_COEFFICIENT(denom); 01605 numer_denom(x, numer, denom); 01606 assign_r(q_den, denom, ROUND_NOT_NEEDED); 01607 assign_r(q_x, numer, ROUND_NOT_NEEDED); 01608 div_assign_r(q_x, q_x, q_den, ROUND_NOT_NEEDED); 01609 01610 if (!is_plus_infinity(y)) { 01611 numer_denom(y, numer, denom); 01612 assign_r(q_den, denom, ROUND_NOT_NEEDED); 01613 assign_r(q_y, numer, ROUND_NOT_NEEDED); 01614 div_assign_r(q_y, q_y, q_den, ROUND_NOT_NEEDED); 01615 if (q_x == d && q_y == d1) { 01616 if (c.is_strict_inequality()) 01617 return Poly_Con_Relation::saturates() 01618 && Poly_Con_Relation::is_disjoint(); 01619 else 01620 return Poly_Con_Relation::saturates() 01621 && Poly_Con_Relation::is_included(); 01622 } 01623 // `*this' is disjoint from `c' when 01624 // `-y > d' (`-y >= d' if c is a strict equality), i.e. if 01625 // `y < d1' (`y <= d1' if c is a strict equality). 01626 if (q_y < d1) 01627 return Poly_Con_Relation::is_disjoint(); 01628 if (q_y == d1 && c.is_strict_inequality()) 01629 return Poly_Con_Relation::is_disjoint(); 01630 } 01631 01632 // Here `y' can be also plus-infinity. 01633 // If `c' is an equality, `*this' is disjoint from `c' if 01634 // `x < d'. 01635 if (d > q_x) { 01636 if (c.is_equality()) 01637 return Poly_Con_Relation::is_disjoint(); 01638 else 01639 return Poly_Con_Relation::is_included(); 01640 } 01641 01642 if (d == q_x && c.is_nonstrict_inequality()) 01643 return Poly_Con_Relation::is_included(); 01644 01645 // In all other cases `*this' intersects `c'. 01646 return Poly_Con_Relation::strictly_intersects(); 01647 }
| void Parma_Polyhedra_Library::BD_Shape< T >::remove_higher_space_dimensions | ( | dimension_type | new_dimension | ) | [inline] |
Removes the higher dimensions so that the resulting space will have dimension new_dimension.
| std::invalid_argument | Thrown if new_dimension is greater than the space dimension of *this. |
Definition at line 733 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::DB_Matrix< T >::resize_no_copy(), Parma_Polyhedra_Library::BD_Shape< T >::set_zero_dim_univ(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), and Parma_Polyhedra_Library::BD_Shape< T >::map_space_dimensions().
00733 { 00734 // Dimension-compatibility check: the variable having 00735 // maximum index is the one occurring last in the set. 00736 if (new_dim > space_dimension()) 00737 throw_dimension_incompatible("remove_higher_space_dimensions(nd)", 00738 new_dim); 00739 00740 // The removal of no dimensions from any BDS is a no-op. 00741 // Note that this case also captures the only legal removal of 00742 // dimensions from a zero-dim space BDS. 00743 if (new_dim == space_dimension()) { 00744 PPL_ASSERT(OK()); 00745 return; 00746 } 00747 00748 // Shortest-path closure is necessary as in remove_space_dimensions(). 00749 shortest_path_closure_assign(); 00750 dbm.resize_no_copy(new_dim + 1); 00751 00752 // Shortest-path closure is maintained. 00753 // TODO: see whether or not reduction can be (efficiently!) maintained too. 00754 if (marked_shortest_path_reduced()) 00755 reset_shortest_path_reduced(); 00756 00757 // If we removed _all_ dimensions from a non-empty BDS, 00758 // the zero-dim universe BDS has been obtained. 00759 if (new_dim == 0 && !marked_empty()) 00760 set_zero_dim_univ(); 00761 PPL_ASSERT(OK()); 00762 }
| void Parma_Polyhedra_Library::BD_Shape< T >::remove_space_dimensions | ( | const Variables_Set & | vars | ) | [inline] |
Removes all the specified dimensions.
| vars | The set of Variable objects corresponding to the 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 2686 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::DB_Matrix< T >::resize_no_copy(), Parma_Polyhedra_Library::BD_Shape< T >::set_zero_dim_univ(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::Variables_Set::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::swap(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::fold_space_dimensions().
02686 { 02687 // The removal of no dimensions from any BDS is a no-op. 02688 // Note that this case also captures the only legal removal of 02689 // space dimensions from a BDS in a 0-dim space. 02690 if (vars.empty()) { 02691 PPL_ASSERT(OK()); 02692 return; 02693 } 02694 02695 const dimension_type old_space_dim = space_dimension(); 02696 02697 // Dimension-compatibility check. 02698 const dimension_type min_space_dim = vars.space_dimension(); 02699 if (old_space_dim < min_space_dim) 02700 throw_dimension_incompatible("remove_space_dimensions(vs)", min_space_dim); 02701 02702 // Shortest-path closure is necessary to keep precision. 02703 shortest_path_closure_assign(); 02704 02705 // When removing _all_ dimensions from a BDS, we obtain the 02706 // zero-dimensional BDS. 02707 const dimension_type new_space_dim = old_space_dim - vars.size(); 02708 if (new_space_dim == 0) { 02709 dbm.resize_no_copy(1); 02710 if (!marked_empty()) 02711 // We set the zero_dim_univ flag. 02712 set_zero_dim_univ(); 02713 PPL_ASSERT(OK()); 02714 return; 02715 } 02716 02717 // Handle the case of an empty BD_Shape. 02718 if (marked_empty()) { 02719 dbm.resize_no_copy(new_space_dim + 1); 02720 PPL_ASSERT(OK()); 02721 return; 02722 } 02723 02724 // Shortest-path closure is maintained. 02725 // TODO: see whether reduction can be (efficiently!) maintained too. 02726 if (marked_shortest_path_reduced()) 02727 reset_shortest_path_reduced(); 02728 02729 // For each variable to remove, we fill the corresponding column and 02730 // row by shifting respectively left and above those 02731 // columns and rows, that will not be removed. 02732 Variables_Set::const_iterator vsi = vars.begin(); 02733 Variables_Set::const_iterator vsi_end = vars.end(); 02734 dimension_type dst = *vsi + 1; 02735 dimension_type src = dst + 1; 02736 for (++vsi; vsi != vsi_end; ++vsi) { 02737 const dimension_type vsi_next = *vsi + 1; 02738 // All other columns and rows are moved respectively to the left 02739 // and above. 02740 while (src < vsi_next) { 02741 std::swap(dbm[dst], dbm[src]); 02742 for (dimension_type i = old_space_dim + 1; i-- > 0; ) { 02743 DB_Row<N>& dbm_i = dbm[i]; 02744 assign_or_swap(dbm_i[dst], dbm_i[src]); 02745 } 02746 ++dst; 02747 ++src; 02748 } 02749 ++src; 02750 } 02751 02752 // Moving the remaining rows and columns. 02753 while (src <= old_space_dim) { 02754 std::swap(dbm[dst], dbm[src]); 02755 for (dimension_type i = old_space_dim + 1; i-- > 0; ) { 02756 DB_Row<N>& dbm_i = dbm[i]; 02757 assign_or_swap(dbm_i[dst], dbm_i[src]); 02758 } 02759 ++src; 02760 ++dst; 02761 } 02762 02763 // Update the space dimension. 02764 dbm.resize_no_copy(new_space_dim + 1); 02765 PPL_ASSERT(OK()); 02766 }
| void Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed | ( | ) | [inline, private] |
Marks *this as possibly not shortest-path closed.
Definition at line 103 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::Status::reset_shortest_path_closed(), and Parma_Polyhedra_Library::BD_Shape< T >::status.
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::add_dbm_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::BD_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::BD_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points_helper(), Parma_Polyhedra_Library::BD_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::get_limiting_shape(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::refine(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), and Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign().
00103 { 00104 status.reset_shortest_path_closed(); 00105 }
| void Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced | ( | ) | [inline, private] |
Marks *this as possibly not shortest-path reduced.
Definition at line 109 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::Status::reset_shortest_path_reduced(), and Parma_Polyhedra_Library::BD_Shape< T >::status.
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::unconstrain(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign().
00109 { 00110 status.reset_shortest_path_reduced(); 00111 }
| void Parma_Polyhedra_Library::BD_Shape< T >::set_empty | ( | ) | [inline, private] |
Turns *this into an empty BDS.
Definition at line 85 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::Status::set_empty(), and Parma_Polyhedra_Library::BD_Shape< T >::status.
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_congruence(), Parma_Polyhedra_Library::BD_Shape< T >::add_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::BD_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::BD_Shape< T >::difference_assign(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), and Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign().
| void Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed | ( | ) | [inline, private] |
Marks *this as shortest-path closed.
Definition at line 91 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::Status::set_shortest_path_closed(), and Parma_Polyhedra_Library::BD_Shape< T >::status.
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), and Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign().
00091 { 00092 status.set_shortest_path_closed(); 00093 }
| void Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_reduced | ( | ) | [inline, private] |
Marks *this as shortest-path closed.
Definition at line 97 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::Status::set_shortest_path_reduced(), and Parma_Polyhedra_Library::BD_Shape< T >::status.
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign().
00097 { 00098 status.set_shortest_path_reduced(); 00099 }
| void Parma_Polyhedra_Library::BD_Shape< T >::set_zero_dim_univ | ( | ) | [inline, private] |
Turns *this into an zero-dimensional universe BDS.
Definition at line 79 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::Status::set_zero_dim_univ(), and Parma_Polyhedra_Library::BD_Shape< T >::status.
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::BD_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::remove_space_dimensions(), and Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign().
00079 { 00080 status.set_zero_dim_univ(); 00081 }
| void Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign | ( | ) | const [inline, private] |
Assigns to this->dbm its shortest-path closure.
Definition at line 1755 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::min_assign(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::affine_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::BD_Shape< T >::constrains(), Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::difference_assign(), Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::BD_Shape< T >::euclidean_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::frequency(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::get_limiting_shape(), Parma_Polyhedra_Library::BD_Shape< T >::is_bounded(), Parma_Polyhedra_Library::BD_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::BD_Shape< T >::is_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::l_infinity_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::max_min(), Parma_Polyhedra_Library::BD_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::rectilinear_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::relation_with(), Parma_Polyhedra_Library::BD_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign(), Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign(), Parma_Polyhedra_Library::BD_Shape< T >::unconstrain(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign().
01755 { 01756 // Do something only if necessary. 01757 if (marked_empty() || marked_shortest_path_closed()) 01758 return; 01759 const dimension_type num_dimensions = space_dimension(); 01760 // Zero-dimensional BDSs are necessarily shortest-path closed. 01761 if (num_dimensions == 0) 01762 return; 01763 01764 // Even though the BDS will not change, its internal representation 01765 // is going to be modified by the Floyd-Warshall algorithm. 01766 BD_Shape& x = const_cast<BD_Shape<T>&>(*this); 01767 01768 // Fill the main diagonal with zeros. 01769 for (dimension_type h = num_dimensions + 1; h-- > 0; ) { 01770 PPL_ASSERT(is_plus_infinity(x.dbm[h][h])); 01771 assign_r(x.dbm[h][h], 0, ROUND_NOT_NEEDED); 01772 } 01773 01774 PPL_DIRTY_TEMP(N, sum); 01775 for (dimension_type k = num_dimensions + 1; k-- > 0; ) { 01776 const DB_Row<N>& x_dbm_k = x.dbm[k]; 01777 for (dimension_type i = num_dimensions + 1; i-- > 0; ) { 01778 DB_Row<N>& x_dbm_i = x.dbm[i]; 01779 const N& x_dbm_i_k = x_dbm_i[k]; 01780 if (!is_plus_infinity(x_dbm_i_k)) 01781 for (dimension_type j = num_dimensions + 1; j-- > 0; ) { 01782 const N& x_dbm_k_j = x_dbm_k[j]; 01783 if (!is_plus_infinity(x_dbm_k_j)) { 01784 // Rounding upward for correctness. 01785 add_assign_r(sum, x_dbm_i_k, x_dbm_k_j, ROUND_UP); 01786 min_assign(x_dbm_i[j], sum); 01787 } 01788 } 01789 } 01790 } 01791 01792 // Check for emptiness: the BDS is empty if and only if there is a 01793 // negative value on the main diagonal of `dbm'. 01794 for (dimension_type h = num_dimensions + 1; h-- > 0; ) { 01795 N& x_dbm_hh = x.dbm[h][h]; 01796 if (sgn(x_dbm_hh) < 0) { 01797 x.set_empty(); 01798 return; 01799 } 01800 else { 01801 PPL_ASSERT(sgn(x_dbm_hh) == 0); 01802 // Restore PLUS_INFINITY on the main diagonal. 01803 assign_r(x_dbm_hh, PLUS_INFINITY, ROUND_NOT_NEEDED); 01804 } 01805 } 01806 01807 // The BDS is not empty and it is now shortest-path closed. 01808 x.set_shortest_path_closed(); 01809 }
| void Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign | ( | ) | const [inline, private] |
Assigns to this->dbm its shortest-path closure and records into this->redundancy_dbm which of the entries in this->dbm are redundant.
Definition at line 1923 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::Bit_Matrix::clear(), Parma_Polyhedra_Library::Bit_Row::clear(), Parma_Polyhedra_Library::BD_Shape< T >::compute_leader_indices(), Parma_Polyhedra_Library::BD_Shape< T >::compute_predecessors(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::is_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm, Parma_Polyhedra_Library::Bit_Row::set(), Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::swap().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BFT00_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::BHZ09_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::minimized_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), and Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign().
01923 { 01924 // Do something only if necessary. 01925 if (marked_shortest_path_reduced()) 01926 return; 01927 01928 const dimension_type space_dim = space_dimension(); 01929 // Zero-dimensional BDSs are necessarily reduced. 01930 if (space_dim == 0) 01931 return; 01932 01933 // First find the tightest constraints for this BDS. 01934 shortest_path_closure_assign(); 01935 01936 // If `*this' is empty, then there is nothing to reduce. 01937 if (marked_empty()) 01938 return; 01939 01940 // Step 1: compute zero-equivalence classes. 01941 // Variables corresponding to indices `i' and `j' are zero-equivalent 01942 // if they lie on a zero-weight loop; since the matrix is shortest-path 01943 // closed, this happens if and only if dbm[i][j] == -dbm[j][i]. 01944 std::vector<dimension_type> predecessor; 01945 compute_predecessors(predecessor); 01946 std::vector<dimension_type> leaders; 01947 compute_leader_indices(predecessor, leaders); 01948 const dimension_type num_leaders = leaders.size(); 01949 01950 Bit_Matrix redundancy(space_dim + 1, space_dim + 1); 01951 // Init all constraints to be redundant. 01952 // TODO: provide an appropriate method to set multiple bits. 01953 Bit_Row& red_0 = redundancy[0]; 01954 for (dimension_type j = space_dim + 1; j-- > 0; ) 01955 red_0.set(j); 01956 for (dimension_type i = space_dim + 1; i-- > 0; ) 01957 redundancy[i] = red_0; 01958 01959 // Step 2: flag non-redundant constraints in the (zero-cycle-free) 01960 // subsystem of bounded differences having only leaders as variables. 01961 PPL_DIRTY_TEMP(N, c); 01962 for (dimension_type l_i = 0; l_i < num_leaders; ++l_i) { 01963 const dimension_type i = leaders[l_i]; 01964 const DB_Row<N>& dbm_i = dbm[i]; 01965 Bit_Row& redundancy_i = redundancy[i]; 01966 for (dimension_type l_j = 0; l_j < num_leaders; ++l_j) { 01967 const dimension_type j = leaders[l_j]; 01968 if (redundancy_i[j]) { 01969 const N& dbm_i_j = dbm_i[j]; 01970 redundancy_i.clear(j); 01971 for (dimension_type l_k = 0; l_k < num_leaders; ++l_k) { 01972 const dimension_type k = leaders[l_k]; 01973 add_assign_r(c, dbm_i[k], dbm[k][j], ROUND_UP); 01974 if (dbm_i_j >= c) { 01975 redundancy_i.set(j); 01976 break; 01977 } 01978 } 01979 } 01980 } 01981 } 01982 01983 // Step 3: flag non-redundant constraints in zero-equivalence classes. 01984 // Each equivalence class must have a single 0-cycle connecting 01985 // all the equivalent variables in increasing order. 01986 std::deque<bool> dealt_with(space_dim + 1, false); 01987 for (dimension_type i = space_dim + 1; i-- > 0; ) 01988 // We only need to deal with non-singleton zero-equivalence classes 01989 // that haven't already been dealt with. 01990 if (i != predecessor[i] && !dealt_with[i]) { 01991 dimension_type j = i; 01992 while (true) { 01993 const dimension_type pred_j = predecessor[j]; 01994 if (j == pred_j) { 01995 // We finally found the leader of `i'. 01996 PPL_ASSERT(redundancy[i][j]); 01997 redundancy[i].clear(j); 01998 // Here we dealt with `j' (i.e., `pred_j'), but it is useless 01999 // to update `dealt_with' because `j' is a leader. 02000 break; 02001 } 02002 // We haven't found the leader of `i' yet. 02003 PPL_ASSERT(redundancy[pred_j][j]); 02004 redundancy[pred_j].clear(j); 02005 dealt_with[pred_j] = true; 02006 j = pred_j; 02007 } 02008 } 02009 02010 // Even though shortest-path reduction is not going to change the BDS, 02011 // it might change its internal representation. 02012 BD_Shape<T>& x = const_cast<BD_Shape<T>&>(*this); 02013 std::swap(x.redundancy_dbm, redundancy); 02014 x.set_shortest_path_reduced(); 02015 02016 PPL_ASSERT(is_shortest_path_reduced()); 02017 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign | ( | const BD_Shape< T > & | y | ) | [inline] |
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 2387 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::BD_Shape< T >::compute_leaders(), Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::incremental_shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm, Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::set_zero_dim_univ(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::swap(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::UNIVERSE.
02387 { 02388 BD_Shape& x = *this; 02389 const dimension_type dim = x.space_dimension(); 02390 // Dimension-compatibility check. 02391 if (dim != y.space_dimension()) 02392 throw_dimension_incompatible("simplify_using_context_assign(y)", y); 02393 02394 // Filter away the zero-dimensional case. 02395 if (dim == 0) { 02396 if (y.marked_empty()) { 02397 x.set_zero_dim_univ(); 02398 return false; 02399 } 02400 else 02401 return !x.marked_empty(); 02402 } 02403 02404 // Filter away the case where `x' contains `y' 02405 // (this subsumes the case when `y' is empty). 02406 y.shortest_path_closure_assign(); 02407 if (x.contains(y)) { 02408 BD_Shape<T> res(dim, UNIVERSE); 02409 x.swap(res); 02410 return false; 02411 } 02412 02413 // Filter away the case where `x' is empty. 02414 x.shortest_path_closure_assign(); 02415 if (x.marked_empty()) { 02416 // Search for a constraint of `y' that is not a tautology. 02417 dimension_type i; 02418 dimension_type j; 02419 // Prefer unary constraints. 02420 i = 0; 02421 const DB_Row<N>& y_dbm_0 = y.dbm[0]; 02422 for (j = 1; j <= dim; ++j) { 02423 if (!is_plus_infinity(y_dbm_0[j])) 02424 // FIXME: if N is a float or bounded integer type, then 02425 // we also need to check that we are actually able to construct 02426 // a constraint inconsistent wrt this one. 02427 goto found; 02428 } 02429 j = 0; 02430 for (i = 1; i <= dim; ++i) { 02431 if (!is_plus_infinity(y.dbm[i][0])) 02432 // FIXME: if N is a float or bounded intefer type, then 02433 // we also need to check that we are actually able to construct 02434 // a constraint inconsistent wrt this one. 02435 goto found; 02436 } 02437 // Then search binary constraints. 02438 for (i = 1; i <= dim; ++i) { 02439 const DB_Row<N>& y_dbm_i = y.dbm[i]; 02440 for (j = 1; j <= dim; ++j) 02441 if (!is_plus_infinity(y_dbm_i[j])) 02442 // FIXME: if N is a float or bounded intefer type, then 02443 // we also need to check that we are actually able to construct 02444 // a constraint inconsistent wrt this one. 02445 goto found; 02446 } 02447 // Not found: we were not able to build a constraint contradicting 02448 // one of the constraints in `y': `x' cannot be enlarged. 02449 return false; 02450 02451 found: 02452 // Found: build a new BDS contradicting the constraint found. 02453 PPL_ASSERT(i <= dim && j <= dim && (i > 0 || j > 0)); 02454 BD_Shape<T> res(dim, UNIVERSE); 02455 PPL_DIRTY_TEMP(N, tmp); 02456 assign_r(tmp, 1, ROUND_UP); 02457 add_assign_r(tmp, tmp, y.dbm[i][j], ROUND_UP); 02458 PPL_ASSERT(!is_plus_infinity(tmp)); 02459 // CHECKME: round down is really meant. 02460 neg_assign_r(res.dbm[j][i], tmp, ROUND_DOWN); 02461 x.swap(res); 02462 return false; 02463 } 02464 02465 // Here `x' and `y' are not empty and shortest-path closed; 02466 // also, `x' does not contain `y'. 02467 // Let `target' be the intersection of `x' and `y'. 02468 BD_Shape<T> target = x; 02469 target.intersection_assign(y); 02470 const bool bool_result = !target.is_empty(); 02471 02472 // Compute a reduced dbm for `x' and ... 02473 x.shortest_path_reduction_assign(); 02474 // ... count the non-redundant constraints. 02475 dimension_type x_num_nonredundant = (dim+1)*(dim+1); 02476 for (dimension_type i = dim + 1; i-- > 0; ) 02477 x_num_nonredundant -= x.redundancy_dbm[i].count_ones(); 02478 PPL_ASSERT(x_num_nonredundant > 0); 02479 02480 // Let `yy' be a copy of `y': we will keep adding to `yy' 02481 // the non-redundant constraints of `x', 02482 // stopping as soon as `yy' becomes equal to `target'. 02483 BD_Shape<T> yy = y; 02484 02485 // The constraints added to `yy' will be recorded in `res' ... 02486 BD_Shape<T> res(dim, UNIVERSE); 02487 // ... and we will count them too. 02488 dimension_type res_num_nonredundant = 0; 02489 02490 // Compute leader information for `x'. 02491 std::vector<dimension_type> x_leaders; 02492 x.compute_leaders(x_leaders); 02493 02494 // First go through the unary equality constraints. 02495 const DB_Row<N>& x_dbm_0 = x.dbm[0]; 02496 DB_Row<N>& yy_dbm_0 = yy.dbm[0]; 02497 DB_Row<N>& res_dbm_0 = res.dbm[0]; 02498 for (dimension_type j = 1; j <= dim; ++j) { 02499 // Unary equality constraints are encoded in entries dbm_0j and dbm_j0 02500 // provided index j has special variable index 0 as its leader. 02501 if (x_leaders[j] != 0) 02502 continue; 02503 PPL_ASSERT(!is_plus_infinity(x_dbm_0[j])); 02504 if (x_dbm_0[j] < yy_dbm_0[j]) { 02505 res_dbm_0[j] = x_dbm_0[j]; 02506 ++res_num_nonredundant; 02507 // Tighten context `yy' using the newly added constraint. 02508 yy_dbm_0[j] = x_dbm_0[j]; 02509 yy.reset_shortest_path_closed(); 02510 } 02511 PPL_ASSERT(!is_plus_infinity(x.dbm[j][0])); 02512 if (x.dbm[j][0] < yy.dbm[j][0]) { 02513 res.dbm[j][0] = x.dbm[j][0]; 02514 ++res_num_nonredundant; 02515 // Tighten context `yy' using the newly added constraint. 02516 yy.dbm[j][0] = x.dbm[j][0]; 02517 yy.reset_shortest_path_closed(); 02518 } 02519 // Restore shortest-path closure, if it was lost. 02520 if (!yy.marked_shortest_path_closed()) { 02521 Variable var_j(j-1); 02522 yy.incremental_shortest_path_closure_assign(var_j); 02523 if (target.contains(yy)) { 02524 // Target reached: swap `x' and `res' if needed. 02525 if (res_num_nonredundant < x_num_nonredundant) { 02526 res.reset_shortest_path_closed(); 02527 x.swap(res); 02528 } 02529 return bool_result; 02530 } 02531 } 02532 } 02533 02534 // Go through the binary equality constraints. 02535 // Note: no need to consider the case i == 1. 02536 for (dimension_type i = 2; i <= dim; ++i) { 02537 const dimension_type j = x_leaders[i]; 02538 if (j == i || j == 0) 02539 continue; 02540 PPL_ASSERT(!is_plus_infinity(x.dbm[i][j])); 02541 if (x.dbm[i][j] < yy.dbm[i][j]) { 02542 res.dbm[i][j] = x.dbm[i][j]; 02543 ++res_num_nonredundant; 02544 // Tighten context `yy' using the newly added constraint. 02545 yy.dbm[i][j] = x.dbm[i][j]; 02546 yy.reset_shortest_path_closed(); 02547 } 02548 PPL_ASSERT(!is_plus_infinity(x.dbm[j][i])); 02549 if (x.dbm[j][i] < yy.dbm[j][i]) { 02550 res.dbm[j][i] = x.dbm[j][i]; 02551 ++res_num_nonredundant; 02552 // Tighten context `yy' using the newly added constraint. 02553 yy.dbm[j][i] = x.dbm[j][i]; 02554 yy.reset_shortest_path_closed(); 02555 } 02556 // Restore shortest-path closure, if it was lost. 02557 if (!yy.marked_shortest_path_closed()) { 02558 Variable var_j(j-1); 02559 yy.incremental_shortest_path_closure_assign(var_j); 02560 if (target.contains(yy)) { 02561 // Target reached: swap `x' and `res' if needed. 02562 if (res_num_nonredundant < x_num_nonredundant) { 02563 res.reset_shortest_path_closed(); 02564 x.swap(res); 02565 } 02566 return bool_result; 02567 } 02568 } 02569 } 02570 02571 // Finally go through the (proper) inequality constraints: 02572 // both indices i and j should be leaders. 02573 for (dimension_type i = 0; i <= dim; ++i) { 02574 if (i != x_leaders[i]) 02575 continue; 02576 const DB_Row<N>& x_dbm_i = x.dbm[i]; 02577 const Bit_Row& x_redundancy_dbm_i = x.redundancy_dbm[i]; 02578 DB_Row<N>& yy_dbm_i = yy.dbm[i]; 02579 DB_Row<N>& res_dbm_i = res.dbm[i]; 02580 for (dimension_type j = 0; j <= dim; ++j) { 02581 if (j != x_leaders[j] || x_redundancy_dbm_i[j]) 02582 continue; 02583 N& yy_dbm_ij = yy_dbm_i[j]; 02584 const N& x_dbm_ij = x_dbm_i[j]; 02585 if (x_dbm_ij < yy_dbm_ij) { 02586 res_dbm_i[j] = x_dbm_ij; 02587 ++res_num_nonredundant; 02588 // Tighten context `yy' using the newly added constraint. 02589 yy_dbm_ij = x_dbm_ij; 02590 yy.reset_shortest_path_closed(); 02591 PPL_ASSERT(i > 0 || j > 0); 02592 Variable var((i > 0 ? i : j) - 1); 02593 yy.incremental_shortest_path_closure_assign(var); 02594 if (target.contains(yy)) { 02595 // Target reached: swap `x' and `res' if needed. 02596 if (res_num_nonredundant < x_num_nonredundant) { 02597 res.reset_shortest_path_closed(); 02598 x.swap(res); 02599 } 02600 return bool_result; 02601 } 02602 } 02603 } 02604 } 02605 // This point should be unreachable. 02606 throw std::runtime_error("PPL internal error"); 02607 }
| dimension_type Parma_Polyhedra_Library::BD_Shape< T >::space_dimension | ( | ) | const [inline] |
Returns the dimension of the vector space enclosing *this.
Definition at line 349 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::dbm, and Parma_Polyhedra_Library::DB_Matrix< T >::num_rows().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_congruence(), Parma_Polyhedra_Library::BD_Shape< T >::add_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::add_dbm_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::BD_Shape< T >::affine_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::BD_Shape< T >::BFT00_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::BHZ09_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::bounds(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::BD_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::BD_Shape< T >::constrains(), Parma_Polyhedra_Library::BD_Shape< T >::constraints(), Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::BD_Shape< T >::difference_assign(), Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::BD_Shape< T >::euclidean_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::frequency(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::get_limiting_shape(), Parma_Polyhedra_Library::BD_Shape< T >::hash_code(), Parma_Polyhedra_Library::BD_Shape< T >::incremental_shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::integer_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::BD_Shape< T >::is_bounded(), Parma_Polyhedra_Library::BD_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::BD_Shape< T >::is_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::is_universe(), Parma_Polyhedra_Library::BD_Shape< T >::l_infinity_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::limited_BHMZ05_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::max_min(), Parma_Polyhedra_Library::BD_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::BD_Shape< T >::minimized_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::BD_Shape< T >::rectilinear_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::refine(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_congruence(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_congruences(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::relation_with(), Parma_Polyhedra_Library::BD_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign(), Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), Parma_Polyhedra_Library::BD_Shape< T >::time_elapse_assign(), Parma_Polyhedra_Library::BD_Shape< T >::unconstrain(), Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign_if_exact().
00349 { 00350 return dbm.num_rows() - 1; 00351 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::strictly_contains | ( | const BD_Shape< T > & | 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 701 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::contains().
| void Parma_Polyhedra_Library::BD_Shape< T >::swap | ( | BD_Shape< T > & | y | ) | [inline] |
Swaps *this with y (*this and y can be dimension-incompatible).
Definition at line 341 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm, and Parma_Polyhedra_Library::BD_Shape< T >::status.
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::BHZ09_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::H79_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::limited_H79_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign(), Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign(), Parma_Polyhedra_Library::BD_Shape< T >::swap(), and Parma_Polyhedra_Library::BD_Shape< T >::time_elapse_assign().
| void Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible | ( | const char * | method, | |
| const char * | name_row, | |||
| const Linear_Expression & | y | |||
| ) | const [inline, private] |
Definition at line 6000 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().
06002 { 06003 std::ostringstream s; 06004 s << "PPL::BD_Shape::" << method << ":" << std::endl 06005 << "this->space_dimension() == " << space_dimension() 06006 << ", " << name_row << "->space_dimension() == " 06007 << y.space_dimension() << "."; 06008 throw std::invalid_argument(s.str()); 06009 }
| void Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible | ( | const char * | method, | |
| const Generator & | g | |||
| ) | const [inline, private] |
Definition at line 5977 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::Generator::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().
05978 { 05979 std::ostringstream s; 05980 s << "PPL::BD_Shape::" << method << ":" << std::endl 05981 << "this->space_dimension() == " << space_dimension() 05982 << ", g->space_dimension == " << g.space_dimension() << "."; 05983 throw std::invalid_argument(s.str()); 05984 }
| void Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible | ( | const char * | method, | |
| const Congruence & | cg | |||
| ) | const [inline, private] |
Definition at line 5966 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::Congruence::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().
05967 { 05968 std::ostringstream s; 05969 s << "PPL::BD_Shape::" << method << ":" << std::endl 05970 << "this->space_dimension() == " << space_dimension() 05971 << ", cg->space_dimension == " << cg.space_dimension() << "."; 05972 throw std::invalid_argument(s.str()); 05973 }
| void Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible | ( | const char * | method, | |
| const Constraint & | c | |||
| ) | const [inline, private] |
Definition at line 5955 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::Constraint::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().
05956 { 05957 std::ostringstream s; 05958 s << "PPL::BD_Shape::" << method << ":" << std::endl 05959 << "this->space_dimension() == " << space_dimension() 05960 << ", c->space_dimension == " << c.space_dimension() << "."; 05961 throw std::invalid_argument(s.str()); 05962 }
| void Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible | ( | const char * | method, | |
| dimension_type | required_dim | |||
| ) | const [inline, private] |
Definition at line 5944 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().
05945 { 05946 std::ostringstream s; 05947 s << "PPL::BD_Shape::" << method << ":" << std::endl 05948 << "this->space_dimension() == " << space_dimension() 05949 << ", required dimension == " << required_dim << "."; 05950 throw std::invalid_argument(s.str()); 05951 }
| void Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible | ( | const char * | method, | |
| const BD_Shape< T > & | x | |||
| ) | const [inline, private] |
Definition at line 5933 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_congruence(), Parma_Polyhedra_Library::BD_Shape< T >::add_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::bounds(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::BD_Shape< T >::constrains(), Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::difference_assign(), Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::BD_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::frequency(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::integer_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::BD_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::BD_Shape< T >::limited_BHMZ05_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::max_min(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_congruence(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::relation_with(), Parma_Polyhedra_Library::BD_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign(), Parma_Polyhedra_Library::BD_Shape< T >::time_elapse_assign(), Parma_Polyhedra_Library::BD_Shape< T >::unconstrain(), Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign_if_exact().
05934 { 05935 std::ostringstream s; 05936 s << "PPL::BD_Shape::" << method << ":" << std::endl 05937 << "this->space_dimension() == " << space_dimension() 05938 << ", y->space_dimension() == " << y.space_dimension() << "."; 05939 throw std::invalid_argument(s.str()); 05940 }
| void Parma_Polyhedra_Library::BD_Shape< T >::throw_expression_too_complex | ( | const char * | method, | |
| const Linear_Expression & | e | |||
| ) | [inline, static, private] |
Definition at line 5988 of file BD_Shape.templates.hh.
| void Parma_Polyhedra_Library::BD_Shape< T >::throw_generic | ( | const char * | method, | |
| const char * | reason | |||
| ) | [inline, static, private] |
Definition at line 6013 of file BD_Shape.templates.hh.
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_congruence(), Parma_Polyhedra_Library::BD_Shape< T >::add_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::BD_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::limited_BHMZ05_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_congruences(), and Parma_Polyhedra_Library::BD_Shape< T >::refine_with_constraints().
| void Parma_Polyhedra_Library::BD_Shape< T >::time_elapse_assign | ( | const BD_Shape< T > & | y | ) | [inline] |
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 686 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::constraints(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::swap(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Polyhedron::time_elapse_assign().
00686 { 00687 // Dimension-compatibility check. 00688 if (space_dimension() != y.space_dimension()) 00689 throw_dimension_incompatible("time_elapse_assign(y)", y); 00690 // See the polyhedra documentation. 00691 C_Polyhedron px(constraints()); 00692 C_Polyhedron py(y.constraints()); 00693 px.time_elapse_assign(py); 00694 BD_Shape<T> x(px); 00695 swap(x); 00696 PPL_ASSERT(OK()); 00697 }
| void Parma_Polyhedra_Library::BD_Shape< T >::topological_closure_assign | ( | ) | [inline] |
Assigns to *this its topological closure.
Definition at line 418 of file BD_Shape.inlines.hh.
| memory_size_type Parma_Polyhedra_Library::BD_Shape< T >::total_memory_in_bytes | ( | ) | const [inline] |
Returns the total size in bytes of the memory occupied by *this.
Definition at line 830 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::external_memory_in_bytes().
00830 { 00831 return sizeof(*this) + external_memory_in_bytes(); 00832 }
| void Parma_Polyhedra_Library::BD_Shape< T >::unconstrain | ( | const Variables_Set & | vars | ) | [inline] |
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 3412 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::forget_all_dbm_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Variables_Set::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().
03412 { 03413 // The cylindrification wrt no dimensions is a no-op. 03414 // This case captures the only legal cylindrification in a 0-dim space. 03415 if (vars.empty()) 03416 return; 03417 03418 // Dimension-compatibility check. 03419 const dimension_type min_space_dim = vars.space_dimension(); 03420 if (space_dimension() < min_space_dim) 03421 throw_dimension_incompatible("unconstrain(vs)", min_space_dim); 03422 03423 // Shortest-path closure is necessary to detect emptiness 03424 // and all (possibly implicit) constraints. 03425 shortest_path_closure_assign(); 03426 03427 // If the shape is empty, this is a no-op. 03428 if (marked_empty()) 03429 return; 03430 03431 for (Variables_Set::const_iterator vsi = vars.begin(), 03432 vsi_end = vars.end(); vsi != vsi_end; ++vsi) 03433 forget_all_dbm_constraints(*vsi + 1); 03434 // Shortest-path closure is preserved, but not reduction. 03435 reset_shortest_path_reduced(); 03436 PPL_ASSERT(OK()); 03437 }
| void Parma_Polyhedra_Library::BD_Shape< T >::unconstrain | ( | Variable | var | ) | [inline] |
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 3390 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::forget_all_dbm_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().
03390 { 03391 // Dimension-compatibility check. 03392 const dimension_type var_space_dim = var.space_dimension(); 03393 if (space_dimension() < var_space_dim) 03394 throw_dimension_incompatible("unconstrain(var)", var_space_dim); 03395 03396 // Shortest-path closure is necessary to detect emptiness 03397 // and all (possibly implicit) constraints. 03398 shortest_path_closure_assign(); 03399 03400 // If the shape is empty, this is a no-op. 03401 if (marked_empty()) 03402 return; 03403 03404 forget_all_dbm_constraints(var_space_dim); 03405 // Shortest-path closure is preserved, but not reduction. 03406 reset_shortest_path_reduced(); 03407 PPL_ASSERT(OK()); 03408 }
| void Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign | ( | const BD_Shape< T > & | y | ) | [inline] |
Assigns to *this the smallest BDS containing the union of *this and y.
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 2021 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BFT00_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::BHZ09_upper_bound_assign_if_exact(), and Parma_Polyhedra_Library::BD_Shape< T >::difference_assign().
02021 { 02022 const dimension_type space_dim = space_dimension(); 02023 02024 // Dimension-compatibility check. 02025 if (space_dim != y.space_dimension()) 02026 throw_dimension_incompatible("upper_bound_assign(y)", y); 02027 02028 // The upper bound of a BD shape `bd' with an empty shape is `bd'. 02029 y.shortest_path_closure_assign(); 02030 if (y.marked_empty()) 02031 return; 02032 shortest_path_closure_assign(); 02033 if (marked_empty()) { 02034 *this = y; 02035 return; 02036 } 02037 02038 // The bds-hull consists in constructing `*this' with the maximum 02039 // elements selected from `*this' and `y'. 02040 PPL_ASSERT(space_dim == 0 || marked_shortest_path_closed()); 02041 for (dimension_type i = space_dim + 1; i-- > 0; ) { 02042 DB_Row<N>& dbm_i = dbm[i]; 02043 const DB_Row<N>& y_dbm_i = y.dbm[i]; 02044 for (dimension_type j = space_dim + 1; j-- > 0; ) { 02045 N& dbm_ij = dbm_i[j]; 02046 const N& y_dbm_ij = y_dbm_i[j]; 02047 if (dbm_ij < y_dbm_ij) 02048 dbm_ij = y_dbm_ij; 02049 } 02050 } 02051 // Shortest-path closure is maintained (if it was holding). 02052 // TODO: see whether reduction can be (efficiently!) maintained too. 02053 if (marked_shortest_path_reduced()) 02054 reset_shortest_path_reduced(); 02055 PPL_ASSERT(OK()); 02056 }
| bool Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign_if_exact | ( | const BD_Shape< T > & | y | ) | [inline] |
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 708 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::BFT00_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().
00708 { 00709 if (space_dimension() != y.space_dimension()) 00710 throw_dimension_incompatible("upper_bound_assign_if_exact(y)", y); 00711 #if 0 00712 return BFT00_upper_bound_assign_if_exact(y); 00713 #else 00714 const bool integer_upper_bound = false; 00715 return BHZ09_upper_bound_assign_if_exact<integer_upper_bound>(y); 00716 #endif 00717 }
| void Parma_Polyhedra_Library::BD_Shape< T >::widening_assign | ( | const BD_Shape< T > & | y, | |
| unsigned * | tp = 0 | |||
| ) | [inline] |
Same as H79_widening_assign(y, tp).
Definition at line 810 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::H79_widening_assign().
00810 { 00811 H79_widening_assign(y, tp); 00812 }
| void Parma_Polyhedra_Library::BD_Shape< T >::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 | |||
| ) | [inline] |
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 whose variables are contained in vars. If *pcs depends on variables not in vars, the behavior is undefined. When non-null, the pointed-to constraint system is assumed to represent the conditional or looping construct guard with respect to which wrapping is performed. Since wrapping requires the computation of upper bounds and due to non-distributivity of constraint refinement over upper bounds, passing a constraint system in this way can be more precise than refining the result of the wrapping operation with the constraints in *pcs. | |
| complexity_threshold | A precision parameter of the wrapping operator: higher values result in possibly improved precision. | |
| wrap_individually | true if the dimensions should be wrapped individually (something that results in much greater efficiency to the detriment of precision). |
| std::invalid_argument | Thrown if *pcs is dimension-incompatible with vars, or if *this is dimension-incompatible vars or with *pcs. |
Definition at line 766 of file BD_Shape.inlines.hh.
00772 { 00773 Implementation::wrap_assign(*this, 00774 vars, w, r, o, pcs, 00775 complexity_threshold, wrap_individually, 00776 "BD_Shape"); 00777 }
| void compute_leader_indices | ( | const std::vector< dimension_type > & | predecessor, | |
| std::vector< dimension_type > & | indices | |||
| ) | [related] |
Extracts leader indices from the predecessor relation.
Definition at line 87 of file BD_Shape.cc.
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::minimized_constraints(), and Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign().
00088 { 00089 // The vector `indices' contains one entry for each equivalence 00090 // class, storing the index of the corresponding leader in 00091 // increasing order: it is used to avoid repeated tests for leadership. 00092 PPL_ASSERT(indices.size() == 0); 00093 PPL_ASSERT(0 == predecessor[0]); 00094 indices.push_back(0); 00095 for (dimension_type i = 1, p_size = predecessor.size(); i != p_size; ++i) 00096 if (i == predecessor[i]) 00097 indices.push_back(i); 00098 }
| bool euclidean_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const BD_Shape< T > & | x, | |||
| const BD_Shape< T > & | y, | |||
| Rounding_Dir | dir, | |||
| Temp & | tmp0, | |||
| Temp & | tmp1, | |||
| Temp & | tmp2 | |||
| ) | [related] |
Computes the euclidean distance between x and y.
If the euclidean distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.
The direction of the approximation is specified by dir.
All computations are performed using the temporary variables tmp0, tmp1 and tmp2.
Definition at line 528 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().
00534 { 00535 const dimension_type x_space_dim = x.space_dimension(); 00536 // Dimension-compatibility check. 00537 if (x_space_dim != y.space_dimension()) 00538 return false; 00539 00540 // Zero-dim BDSs are equal if and only if they are both empty or universe. 00541 if (x_space_dim == 0) { 00542 if (x.marked_empty() == y.marked_empty()) 00543 assign_r(r, 0, ROUND_NOT_NEEDED); 00544 else 00545 assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED); 00546 return true; 00547 } 00548 00549 // The distance computation requires shortest-path closure. 00550 x.shortest_path_closure_assign(); 00551 y.shortest_path_closure_assign(); 00552 00553 // If one of two BDSs is empty, then they are equal if and only if 00554 // the other BDS is empty too. 00555 if (x.marked_empty() || y.marked_empty()) { 00556 if (x.marked_empty() == y.marked_empty()) 00557 assign_r(r, 0, ROUND_NOT_NEEDED); 00558 else 00559 assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED); 00560 return true; 00561 } 00562 00563 return euclidean_distance_assign(r, x.dbm, y.dbm, dir, tmp0, tmp1, tmp2); 00564 }
| bool euclidean_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const BD_Shape< T > & | x, | |||
| const BD_Shape< T > & | y, | |||
| Rounding_Dir | dir | |||
| ) | [related] |
Computes the euclidean distance between x and y.
If the euclidean distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.
The direction of the approximation is specified by dir.
All computations are performed using variables of type Checked_Number<To, Extended_Number_Policy>.
If the euclidean distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.
The direction of the approximation is specified by dir.
All computations are performed using variables of type Checked_Number<Temp, Extended_Number_Policy>.
Definition at line 569 of file BD_Shape.inlines.hh.
00572 { 00573 typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp; 00574 PPL_DIRTY_TEMP(Checked_Temp, tmp0); 00575 PPL_DIRTY_TEMP(Checked_Temp, tmp1); 00576 PPL_DIRTY_TEMP(Checked_Temp, tmp2); 00577 return euclidean_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2); 00578 }
| bool extract_bounded_difference | ( | const Constraint & | c, | |
| dimension_type | c_space_dim, | |||
| dimension_type & | c_num_vars, | |||
| dimension_type & | c_first_var, | |||
| dimension_type & | c_second_var, | |||
| Coefficient & | c_coeff | |||
| ) | [related] |
Decodes the constraint c as a bounded difference.
true if the constraint c is a bounded difference; false otherwise.| c | The constraint to be decoded. | |
| c_space_dim | The space dimension of the constraint c (it is assumed to match the actual space dimension of c). | |
| c_num_vars | If true is returned, then it will be set to the number of variables having a non-zero coefficient. The only legal values will therefore be 0, 1 and 2. | |
| c_first_var | If true is returned and if c_num_vars is not set to 0, then it will be set to the index of the first variable having a non-zero coefficient in c. | |
| c_second_var | If true is returned and if c_num_vars is set to 2, then it will be set to the index of the second variable having a non-zero coefficient in c. | |
| c_coeff | If true is returned and if c_num_vars is not set to 0, then it will be set to the value of the first non-zero coefficient in c. |
Definition at line 33 of file BD_Shape.cc.
References Parma_Polyhedra_Library::Constraint::coefficient(), and Parma_Polyhedra_Library::Constraint::space_dimension().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::bounds(), Parma_Polyhedra_Library::BD_Shape< T >::get_limiting_shape(), Parma_Polyhedra_Library::BD_Shape< T >::max_min(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), and Parma_Polyhedra_Library::BD_Shape< T >::relation_with().
00038 { 00039 // Check for preconditions. 00040 PPL_ASSERT(c.space_dimension() == c_space_dim); 00041 PPL_ASSERT(c_num_vars == 0 && c_first_var == 0 && c_second_var == 0); 00042 // Store the indices of the non-zero components of `c', 00043 dimension_type non_zero_index[2] = { 0, 0 }; 00044 // Collect the non-zero components of `c'. 00045 for (dimension_type i = c_space_dim; i-- > 0; ) 00046 if (c.coefficient(Variable(i)) != 0) { 00047 if (c_num_vars <= 1) 00048 non_zero_index[c_num_vars++] = i + 1; 00049 else 00050 // Constraint `c' is not a bounded difference. 00051 return false; 00052 } 00053 00054 // Make sure that `c' is indeed a bounded difference, 00055 // i.e., it has one of the following forms: 00056 // 0 <=/= b, if c_num_vars == 0; 00057 // a*x <=/= b, if c_num_vars == 1; 00058 // a*x - a*y <=/= b, if c_num_vars == 2. 00059 switch (c_num_vars) { 00060 case 2: 00061 { 00062 const Coefficient& c0 = c.coefficient(Variable(non_zero_index[0]-1)); 00063 const Coefficient& c1 = c.coefficient(Variable(non_zero_index[1]-1)); 00064 if (sgn(c0) == sgn(c1) || c0 != -c1) 00065 // Constraint `c' is not a bounded difference. 00066 return false; 00067 c_coeff = c1; 00068 } 00069 c_first_var = non_zero_index[0]; 00070 c_second_var = non_zero_index[1]; 00071 break; 00072 case 1: 00073 c_coeff = -c.coefficient(Variable(non_zero_index[0]-1)); 00074 c_first_var = non_zero_index[0]; 00075 break; 00076 default: 00077 PPL_ASSERT(c_num_vars == 0); 00078 break; 00079 } 00080 return true; 00081 }
| bool l_infinity_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const BD_Shape< T > & | x, | |||
| const BD_Shape< T > & | y, | |||
| Rounding_Dir | dir, | |||
| Temp & | tmp0, | |||
| Temp & | tmp1, | |||
| Temp & | tmp2 | |||
| ) | [related] |
Computes the
distance between x and y.
If the
distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.
The direction of the approximation is specified by dir.
All computations are performed using the temporary variables tmp0, tmp1 and tmp2.
Definition at line 593 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().
00599 { 00600 const dimension_type x_space_dim = x.space_dimension(); 00601 // Dimension-compatibility check. 00602 if (x_space_dim != y.space_dimension()) 00603 return false; 00604 00605 // Zero-dim BDSs are equal if and only if they are both empty or universe. 00606 if (x_space_dim == 0) { 00607 if (x.marked_empty() == y.marked_empty()) 00608 assign_r(r, 0, ROUND_NOT_NEEDED); 00609 else 00610 assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED); 00611 return true; 00612 } 00613 00614 // The distance computation requires shortest-path closure. 00615 x.shortest_path_closure_assign(); 00616 y.shortest_path_closure_assign(); 00617 00618 // If one of two BDSs is empty, then they are equal if and only if 00619 // the other BDS is empty too. 00620 if (x.marked_empty() || y.marked_empty()) { 00621 if (x.marked_empty() == y.marked_empty()) 00622 assign_r(r, 0, ROUND_NOT_NEEDED); 00623 else 00624 assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED); 00625 return true; 00626 } 00627 00628 return l_infinity_distance_assign(r, x.dbm, y.dbm, dir, tmp0, tmp1, tmp2); 00629 }
| bool l_infinity_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const BD_Shape< T > & | x, | |||
| const BD_Shape< T > & | y, | |||
| Rounding_Dir | dir | |||
| ) | [related] |
Computes the
distance between x and y.
If the
distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.
The direction of the approximation is specified by dir.
All computations are performed using variables of type Checked_Number<To, Extended_Number_Policy>.
If the
distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.
The direction of the approximation is specified by dir.
All computations are performed using variables of type Checked_Number<Temp, Extended_Number_Policy>.
Definition at line 634 of file BD_Shape.inlines.hh.
00637 { 00638 typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp; 00639 PPL_DIRTY_TEMP(Checked_Temp, tmp0); 00640 PPL_DIRTY_TEMP(Checked_Temp, tmp1); 00641 PPL_DIRTY_TEMP(Checked_Temp, tmp2); 00642 return l_infinity_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2); 00643 }
| bool operator!= | ( | const BD_Shape< T > & | x, | |
| const BD_Shape< T > & | y | |||
| ) | [related] |
Returns true if and only if x and y aren't the same BDS.
Note that x and y may be dimension-incompatible shapes: in this case, the value true is returned.
Definition at line 456 of file BD_Shape.inlines.hh.
| std::ostream & operator<< | ( | std::ostream & | s, | |
| const BD_Shape< T > & | c | |||
| ) | [related] |
Output operator.
Writes a textual representation of bds on s: false is written if bds is an empty polyhedron; true is written if bds is the universe polyhedron; a system of constraints defining bds is written otherwise, all constraints separated by ", ".
Definition at line 5702 of file BD_Shape.templates.hh.
References Parma_Polyhedra_Library::is_additive_inverse(), and Parma_Polyhedra_Library::is_plus_infinity().
05702 { 05703 typedef typename BD_Shape<T>::coefficient_type N; 05704 if (c.is_universe()) 05705 s << "true"; 05706 else { 05707 // We control empty bounded difference shape. 05708 dimension_type n = c.space_dimension(); 05709 if (c.marked_empty()) 05710 s << "false"; 05711 else { 05712 PPL_DIRTY_TEMP(N, v); 05713 bool first = true; 05714 for (dimension_type i = 0; i <= n; ++i) 05715 for (dimension_type j = i + 1; j <= n; ++j) { 05716 const N& c_i_j = c.dbm[i][j]; 05717 const N& c_j_i = c.dbm[j][i]; 05718 if (is_additive_inverse(c_j_i, c_i_j)) { 05719 // We will print an equality. 05720 if (first) 05721 first = false; 05722 else 05723 s << ", "; 05724 if (i == 0) { 05725 // We have got a equality constraint with one variable. 05726 s << Variable(j - 1); 05727 s << " = " << c_i_j; 05728 } 05729 else { 05730 // We have got a equality constraint with two variables. 05731 if (sgn(c_i_j) >= 0) { 05732 s << Variable(j - 1); 05733 s << " - "; 05734 s << Variable(i - 1); 05735 s << " = " << c_i_j; 05736 } 05737 else { 05738 s << Variable(i - 1); 05739 s << " - "; 05740 s << Variable(j - 1); 05741 s << " = " << c_j_i; 05742 } 05743 } 05744 } 05745 else { 05746 // We will print a non-strict inequality. 05747 if (!is_plus_infinity(c_j_i)) { 05748 if (first) 05749 first = false; 05750 else 05751 s << ", "; 05752 if (i == 0) { 05753 // We have got a constraint with only one variable. 05754 s << Variable(j - 1); 05755 neg_assign_r(v, c_j_i, ROUND_DOWN); 05756 s << " >= " << v; 05757 } 05758 else { 05759 // We have got a constraint with two variables. 05760 if (sgn(c_j_i) >= 0) { 05761 s << Variable(i - 1); 05762 s << " - "; 05763 s << Variable(j - 1); 05764 s << " <= " << c_j_i; 05765 } 05766 else { 05767 s << Variable(j - 1); 05768 s << " - "; 05769 s << Variable(i - 1); 05770 neg_assign_r(v, c_j_i, ROUND_DOWN); 05771 s << " >= " << v; 05772 } 05773 } 05774 } 05775 if (!is_plus_infinity(c_i_j)) { 05776 if (first) 05777 first = false; 05778 else 05779 s << ", "; 05780 if (i == 0) { 05781 // We have got a constraint with only one variable. 05782 s << Variable(j - 1); 05783 s << " <= " << c_i_j; 05784 } 05785 else { 05786 // We have got a constraint with two variables. 05787 if (sgn(c_i_j) >= 0) { 05788 s << Variable(j - 1); 05789 s << " - "; 05790 s << Variable(i - 1); 05791 s << " <= " << c_i_j; 05792 } 05793 else { 05794 s << Variable(i - 1); 05795 s << " - "; 05796 s << Variable(j - 1); 05797 neg_assign_r(v, c_i_j, ROUND_DOWN); 05798 s << " >= " << v; 05799 } 05800 } 05801 } 05802 } 05803 } 05804 } 05805 } 05806 return s; 05807 }
Returns true if and only if x and y are the same BDS.
Note that x and y may be dimension-incompatible shapes: in this case, the value false is returned.
Definition at line 424 of file BD_Shape.inlines.hh.
00424 { 00425 const dimension_type x_space_dim = x.space_dimension(); 00426 // Dimension-compatibility check. 00427 if (x_space_dim != y.space_dimension()) 00428 return false; 00429 00430 // Zero-dim BDSs are equal if and only if they are both empty or universe. 00431 if (x_space_dim == 0) { 00432 if (x.marked_empty()) 00433 return y.marked_empty(); 00434 else 00435 return !y.marked_empty(); 00436 } 00437 00438 // The exact equivalence test requires shortest-path closure. 00439 x.shortest_path_closure_assign(); 00440 y.shortest_path_closure_assign(); 00441 00442 // If one of two BDSs is empty, then they are equal 00443 // if and only if the other BDS is empty too. 00444 if (x.marked_empty()) 00445 return y.marked_empty(); 00446 if (y.marked_empty()) 00447 return false; 00448 // Check for syntactic equivalence of the two (shortest-path closed) 00449 // systems of bounded differences. 00450 return x.dbm == y.dbm; 00451 }
friend class Parma_Polyhedra_Library::BD_Shape [friend] |
Definition at line 1800 of file BD_Shape.defs.hh.
friend class Parma_Polyhedra_Library::Box [friend] |
Definition at line 1801 of file BD_Shape.defs.hh.
| bool Parma_Polyhedra_Library::euclidean_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const BD_Shape< U > & | x, | |||
| const BD_Shape< U > & | y, | |||
| const Rounding_Dir | dir, | |||
| Temp & | tmp0, | |||
| Temp & | tmp1, | |||
| Temp & | tmp2 | |||
| ) | [friend] |
| std::ostream& Parma_Polyhedra_Library::IO_Operators::operator<< | ( | std::ostream & | s, | |
| const BD_Shape< T > & | c | |||
| ) | [friend] |
| bool Parma_Polyhedra_Library::l_infinity_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const BD_Shape< U > & | x, | |||
| const BD_Shape< U > & | y, | |||
| const Rounding_Dir | dir, | |||
| Temp & | tmp0, | |||
| Temp & | tmp1, | |||
| Temp & | tmp2 | |||
| ) | [friend] |
| bool Parma_Polyhedra_Library::rectilinear_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const BD_Shape< U > & | x, | |||
| const BD_Shape< U > & | y, | |||
| const Rounding_Dir | dir, | |||
| Temp & | tmp0, | |||
| Temp & | tmp1, | |||
| Temp & | tmp2 | |||
| ) | [friend] |
| bool rectilinear_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const BD_Shape< T > & | x, | |||
| const BD_Shape< T > & | y, | |||
| Rounding_Dir | dir, | |||
| Temp & | tmp0, | |||
| Temp & | tmp1, | |||
| Temp & | tmp2 | |||
| ) | [related] |
Computes the rectilinear (or Manhattan) distance between x and y.
If the rectilinear distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.
The direction of the approximation is specified by dir.
All computations are performed using the temporary variables tmp0, tmp1 and tmp2.
Definition at line 463 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().
00469 { 00470 const dimension_type x_space_dim = x.space_dimension(); 00471 // Dimension-compatibility check. 00472 if (x_space_dim != y.space_dimension()) 00473 return false; 00474 00475 // Zero-dim BDSs are equal if and only if they are both empty or universe. 00476 if (x_space_dim == 0) { 00477 if (x.marked_empty() == y.marked_empty()) 00478 assign_r(r, 0, ROUND_NOT_NEEDED); 00479 else 00480 assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED); 00481 return true; 00482 } 00483 00484 // The distance computation requires shortest-path closure. 00485 x.shortest_path_closure_assign(); 00486 y.shortest_path_closure_assign(); 00487 00488 // If one of two BDSs is empty, then they are equal if and only if 00489 // the other BDS is empty too. 00490 if (x.marked_empty() || y.marked_empty()) { 00491 if (x.marked_empty() == y.marked_empty()) 00492 assign_r(r, 0, ROUND_NOT_NEEDED); 00493 else 00494 assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED); 00495 return true; 00496 } 00497 00498 return rectilinear_distance_assign(r, x.dbm, y.dbm, dir, tmp0, tmp1, tmp2); 00499 }
| bool rectilinear_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const BD_Shape< T > & | x, | |||
| const BD_Shape< T > & | y, | |||
| Rounding_Dir | dir | |||
| ) | [related] |
Computes the rectilinear (or Manhattan) distance between x and y.
If the rectilinear distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.
The direction of the approximation is specified by dir.
All computations are performed using variables of type Checked_Number<To, Extended_Number_Policy>.
If the rectilinear distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.
The direction of the approximation is specified by dir.
All computations are performed using variables of type Checked_Number<Temp, Extended_Number_Policy>.
Definition at line 504 of file BD_Shape.inlines.hh.
00507 { 00508 typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp; 00509 PPL_DIRTY_TEMP(Checked_Temp, tmp0); 00510 PPL_DIRTY_TEMP(Checked_Temp, tmp1); 00511 PPL_DIRTY_TEMP(Checked_Temp, tmp2); 00512 return rectilinear_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2); 00513 }
| void swap | ( | Parma_Polyhedra_Library::BD_Shape< T > & | x, | |
| Parma_Polyhedra_Library::BD_Shape< T > & | y | |||
| ) | [related] |
Specializes std::swap.
Definition at line 858 of file BD_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::swap().
00859 { 00860 x.swap(y); 00861 }
DB_Matrix<N> Parma_Polyhedra_Library::BD_Shape< T >::dbm [private] |
The matrix representing the system of bounded differences.
Definition at line 1804 of file BD_Shape.defs.hh.
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::add_dbm_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::ascii_dump(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::BD_Shape< T >::BFT00_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::BHZ09_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::BD_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::BD_Shape< T >::constrains(), Parma_Polyhedra_Library::BD_Shape< T >::constraints(), Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::BD_Shape< T >::euclidean_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::external_memory_in_bytes(), Parma_Polyhedra_Library::BD_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::forget_all_dbm_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::forget_binary_dbm_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::frequency(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::get_limiting_shape(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::BD_Shape< T >::is_bounded(), Parma_Polyhedra_Library::BD_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::BD_Shape< T >::is_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::is_universe(), Parma_Polyhedra_Library::BD_Shape< T >::l_infinity_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::max_min(), Parma_Polyhedra_Library::BD_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::BD_Shape< T >::minimized_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::operator=(), Parma_Polyhedra_Library::BD_Shape< T >::rectilinear_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::refine(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::relation_with(), Parma_Polyhedra_Library::BD_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign(), Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::swap(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign().
Bit_Matrix Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm [private] |
A matrix indicating which constraints are redundant.
Definition at line 1814 of file BD_Shape.defs.hh.
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::ascii_dump(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::BD_Shape< T >::BFT00_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::BHZ09_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::external_memory_in_bytes(), Parma_Polyhedra_Library::BD_Shape< T >::is_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::minimized_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::operator=(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign(), Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::swap().
Status Parma_Polyhedra_Library::BD_Shape< T >::status [private] |
The status flags to keep track of the internal state.
Definition at line 1811 of file BD_Shape.defs.hh.
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::ascii_dump(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::marked_zero_dim_univ(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::operator=(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::set_zero_dim_univ(), and Parma_Polyhedra_Library::BD_Shape< T >::swap().
1.6.3