#include <Octagonal_Shape.defs.hh>

Public Types | |
| typedef T | coefficient_type_base |
| The numeric base type upon which OSs are built. | |
| typedef N | coefficient_type |
| The (extended) numeric type of the inhomogeneous term of the inequalities defining an OS. | |
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 | |
| Octagonal_Shape (dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE) | |
| Builds an universe or empty OS of the specified space dimension. | |
| Octagonal_Shape (const Octagonal_Shape &x, Complexity_Class complexity=ANY_COMPLEXITY) | |
| Ordinary copy-constructor. | |
| template<typename U> | |
| Octagonal_Shape (const Octagonal_Shape< U > &y, Complexity_Class complexity=ANY_COMPLEXITY) | |
Builds a conservative, upward approximation of y. | |
| Octagonal_Shape (const Constraint_System &cs) | |
Builds an OS from the system of constraints cs. | |
| Octagonal_Shape (const Congruence_System &cgs) | |
| Builds an OS from a system of congruences. | |
| Octagonal_Shape (const Generator_System &gs) | |
Builds an OS from the system of generators gs. | |
| Octagonal_Shape (const Polyhedron &ph, Complexity_Class complexity=ANY_COMPLEXITY) | |
Builds an OS from the polyhedron ph. | |
| template<typename Interval> | |
| Octagonal_Shape (const Box< Interval > &box, Complexity_Class complexity=ANY_COMPLEXITY) | |
| Builds an OS out of a box. | |
| Octagonal_Shape (const Grid &grid, Complexity_Class complexity=ANY_COMPLEXITY) | |
| Builds an OS that approximates a grid. | |
| template<typename U> | |
| Octagonal_Shape (const BD_Shape< U > &bd, Complexity_Class complexity=ANY_COMPLEXITY) | |
| Builds an OS from a BD shape. | |
| Octagonal_Shape & | operator= (const Octagonal_Shape &y) |
The assignment operator. (*this and y can be dimension-incompatible.). | |
| void | swap (Octagonal_Shape &y) |
Swaps *this with octagon y. (*this and y can be dimension-incompatible.). | |
| ~Octagonal_Shape () | |
| Destructor. | |
Member Functions that Do Not Modify the Octagonal_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 the 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 | contains (const Octagonal_Shape &y) const |
Returns true if and only if *this contains y. | |
| bool | strictly_contains (const Octagonal_Shape &y) const |
Returns true if and only if *this strictly contains y. | |
| bool | is_disjoint_from (const Octagonal_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 OS. | |
| bool | is_universe () const |
Returns true if and only if *this is a universe OS. | |
| bool | is_discrete () const |
Returns true if and only if *this is discrete. | |
| bool | is_bounded () const |
Returns true if and only if *this is a bounded OS. | |
| bool | is_topologically_closed () const |
Returns true if and only if *this is a topologically closed subset of the vector space. | |
| bool | contains_integer_point () const |
Returns true if and only if *this contains (at least) an integer point. | |
| bool | constrains (Variable var) const |
Returns true if and only if var is constrained in *this. | |
| bool | bounds_from_above (const Linear_Expression &expr) const |
Returns true if and only if expr is bounded 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 | OK () const |
| Checks if all the invariants are satisfied. | |
Space-Dimension Preserving Member Functions that May Modify the Octagonal_Shape | |
| void | add_constraint (const Constraint &c) |
Adds a copy of constraint c to the system of constraints defining *this. | |
| void | add_constraints (const Constraint_System &cs) |
Adds the constraints in cs to the system of constraints defining *this. | |
| void | add_recycled_constraints (Constraint_System &cs) |
Adds the constraints in cs to the system of constraints of *this (without minimizing the result). | |
| void | add_congruence (const Congruence &cg) |
Adds a copy of congruence cg to the system of congruences of this (without minimizing the result). | |
| void | add_congruences (const Congruence_System &cgs) |
Adds to *this constraints equivalent to the congruences in cgs (without minimizing the result). | |
| void | add_recycled_congruences (Congruence_System &cgs) |
Adds the congruences in cs to the system of congruences of *this (without minimizing the result). | |
| void | refine_with_constraint (const Constraint &c) |
Uses a copy of constraint c to refine the system of octagonal constraints defining *this. | |
| void | refine_with_congruence (const Congruence &cg) |
Uses a copy of congruence cg to refine the system of octagonal constraints of *this. | |
| void | refine_with_constraints (const Constraint_System &cs) |
Uses a copy of the constraints in cs to refine the system of octagonal constraints defining *this. | |
| void | refine_with_congruences (const Congruence_System &cgs) |
Uses a copy of the congruences in cgs to refine the system of octagonal constraints 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 &to_be_unconstrained) |
Computes the cylindrification of *this with respect to the set of space dimensions to_be_unconstrained, assigning the result to *this. | |
| void | intersection_assign (const Octagonal_Shape &y) |
Assigns to *this the intersection of *this and y. | |
| void | upper_bound_assign (const Octagonal_Shape &y) |
Assigns to *this the smallest OS that contains the convex union of *this and y. | |
| bool | upper_bound_assign_if_exact (const Octagonal_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 | difference_assign (const Octagonal_Shape &y) |
Assigns to *this the smallest octagon containing the set difference of *this and y. | |
| bool | simplify_using_context_assign (const Octagonal_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 generalized affine transfer function , 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 generalized affine transfer function , 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 | 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 generalized affine relation , where is the relation symbol encoded by relsym. | |
| 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 Octagonal_Shape &y) |
Assigns to *this the result of computing the time-elapse between *this and y. | |
| void | topological_closure_assign () |
Assigns to *this its topological closure. | |
| void | CC76_extrapolation_assign (const Octagonal_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 Octagonal_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 Octagonal_Shape &y, unsigned *tp=0) |
Assigns to *this the result of computing the BHMZ05-widening between *this and y. | |
| void | widening_assign (const Octagonal_Shape &y, unsigned *tp=0) |
| Same as BHMZ05_widening_assign(y, tp). | |
| void | limited_BHMZ05_extrapolation_assign (const Octagonal_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 Octagonal_Shape &y) |
Restores from y the constraints of *this, lost by CC76-extrapolation applications. | |
| void | limited_CC76_extrapolation_assign (const Octagonal_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. | |
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 OS into the new space. | |
| void | add_space_dimensions_and_project (dimension_type m) |
Adds m new dimensions to the OS and does not embed it in the new space. | |
| void | concatenate_assign (const Octagonal_Shape &y) |
Assigns to *this the concatenation of *this and y, taken in this order. | |
| void | remove_space_dimensions (const Variables_Set &to_be_removed) |
| 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 &to_be_folded, Variable var) |
Folds the space dimensions in to_be_folded into var. | |
Static Public Member Functions | |
| static dimension_type | max_space_dimension () |
| Returns the maximum space dimension that an OS 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, Extended_Number_Policy > | N |
| The (extended) numeric type of the inhomogeneous term of the inequalities defining an OS. | |
Private Member Functions | |
| bool | marked_zero_dim_univ () const |
Returns true if the OS is the zero-dimensional universe. | |
| bool | marked_empty () const |
Returns true if the OS is known to be empty. | |
| bool | marked_strongly_closed () const |
Returns true if this->matrix is known to be strongly closed. | |
| void | set_zero_dim_univ () |
Turns *this into a zero-dimensional universe OS. | |
| void | set_empty () |
Turns *this into an empty OS. | |
| void | set_strongly_closed () |
Marks *this as strongly closed. | |
| void | reset_strongly_closed () |
Marks *this as possibly not strongly closed. | |
| N & | matrix_at (dimension_type i, dimension_type j) |
| const N & | matrix_at (dimension_type i, dimension_type j) const |
| 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_octagonal_constraint (dimension_type i, dimension_type j, const N &k) |
Adds the constraint matrix[i][j] <= k. | |
| void | add_octagonal_constraint (dimension_type i, dimension_type j, Coefficient_traits::const_reference num, Coefficient_traits::const_reference den) |
Adds the constraint matrix[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 Octagonal_Shape the constraint . | |
| void | forget_all_octagonal_constraints (dimension_type v_id) |
Removes all the constraints on variable v_id. | |
| void | forget_binary_octagonal_constraints (dimension_type v_id) |
Removes all binary constraints on variable v_id. | |
| void | deduce_v_pm_u_bounds (dimension_type v_id, dimension_type last_id, 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_minus_v_pm_u_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_octagon (const Constraint_System &cs, Octagonal_Shape &limiting_octagon) const |
Adds to limiting_octagon the octagonal differences in cs that are satisfied by *this. | |
| void | compute_successors (std::vector< dimension_type > &successor) const |
| Compute the (zero-equivalence classes) successor relation. | |
| void | compute_leaders (std::vector< dimension_type > &successor, std::vector< dimension_type > &no_sing_leaders, bool &exist_sing_class, dimension_type &sing_leader) const |
| Compute the leaders of zero-equivalence classes. | |
| void | compute_leaders (std::vector< dimension_type > &leaders) const |
| Compute the leaders of zero-equivalence classes. | |
| void | strong_reduction_assign () const |
Removes the redundant constraints from this->matrix. | |
| bool | is_strongly_reduced () const |
Returns true if and only if this->matrix is strongly reduced. | |
| bool | is_strong_coherent () const |
Returns true if in the octagon taken two at a time unary constraints, there is also the constraint that represent their sum. | |
| bool | tight_coherence_would_make_empty () const |
| void | strong_closure_assign () const |
Assigns to this->matrix its strong closure. | |
| void | strong_coherence_assign () |
Applies the strong-coherence step to this->matrix. | |
| void | incremental_strong_closure_assign (Variable var) const |
Puts in *this all implicit constraints and computes the tighter ones. | |
| 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) 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, Generator &g) const |
Maximizes or minimizes expr subject to *this. | |
Exception Throwers | |
| void | throw_dimension_incompatible (const char *method, const Octagonal_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 |
| void | throw_constraint_incompatible (const char *method) const |
| void | throw_expression_too_complex (const char *method, const Linear_Expression &e) const |
| void | throw_generic (const char *method, const char *reason) const |
Private Attributes | |
| OR_Matrix< N > | matrix |
| The matrix that represents the octagonal shape. | |
| dimension_type | space_dim |
| Dimension of the space of the octagonal shape. | |
| Status | status |
| The status flags to keep track of the internal state. | |
Static Private Attributes | |
| static T | default_stop_points [] |
Friends | |
| class | Parma_Polyhedra_Library::Octagonal_Shape |
| class | Parma_Polyhedra_Library::Box |
| bool | operator== (const Octagonal_Shape< T > &x, const Octagonal_Shape< T > &y) |
Returns true if and only if x and y are the same octagon. | |
| template<typename Temp, typename To, typename U> | |
| bool | rectilinear_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Octagonal_Shape< U > &x, const Octagonal_Shape< U > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2) |
| template<typename Temp, typename To, typename U> | |
| bool | euclidean_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Octagonal_Shape< U > &x, const Octagonal_Shape< U > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2) |
| template<typename Temp, typename To, typename U> | |
| bool | l_infinity_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Octagonal_Shape< U > &x, const Octagonal_Shape< U > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2) |
| std::ostream & | operator<< (std::ostream &s, const Octagonal_Shape< T > &c) |
| Output operator. | |
Related Functions | |
| (Note that these are not member functions.) | |
| template<typename T> | |
| bool | operator!= (const Octagonal_Shape< T > &x, const Octagonal_Shape< T > &y) |
Returns true if and only if x and y are different shapes. | |
| template<typename To, typename T> | |
| bool | rectilinear_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const Octagonal_Shape< T > &x, const Octagonal_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 Octagonal_Shape< T > &x, const Octagonal_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 Octagonal_Shape< T > &x, const Octagonal_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 Octagonal_Shape< T > &x, const Octagonal_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 Octagonal_Shape< T > &x, const Octagonal_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 Octagonal_Shape< T > &x, const Octagonal_Shape< T > &y, Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2) |
Computes the distance between x and y. | |
| bool | extract_octagonal_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, Coefficient &c_term) |
Decodes the constraint c as an octagonal difference. | |
| dimension_type | coherent_index (dimension_type i) |
Returns the index coherent to i. | |
| template<typename T> | |
| void | swap (Parma_Polyhedra_Library::Octagonal_Shape< T > &x, Parma_Polyhedra_Library::Octagonal_Shape< T > &y) |
Specializes std::swap. | |
Classes | |
| class | Status |
| A conjunctive assertion about a Octagonal_Shape<T> object. More... | |
The class template Octagonal_Shape<T> allows for the efficient representation of a restricted kind of topologically closed convex polyhedra called octagonal shapes (OSs, for short). The name comes from the fact that, in a vector space of dimension 2, bounded OSs are polygons with at most eight sides. The closed affine half-spaces that characterize the OS can be expressed by constraints of the form
where
and
is a rational number, which are called octagonal constraints.
Based on the class template type parameter T, a family of extended numbers is built and used to approximate the inhomogeneous term of octagonal constraints. 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 OSs is meant to be as similar as possible to the one developed for the polyhedron class C_Polyhedron. At the interface level, octagonal constraints are specified using objects of type Constraint: such a constraint is an octagonal constraint if it is of the form
where
and
,
,
are integer coefficients such that
, or
, or
. The user is warned that the above Constraint object will be mapped into a correct approximation that, depending on the expressive power of the chosen template argument T, may loose some precision. In particular, constraint objects that do not encode an octagonal constraint will be simply (and safely) ignored.
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, a Constraint object encoding
will be safely ignored in all of the above cases.
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 <= 3);
cs.insert(y >= 0);
cs.insert(y <= 3);
cs.insert(z >= 0);
cs.insert(z <= 3);
Octagonal_Shape<T> oct(cs);
Constraint_System cs;
cs.insert(x >= 0);
cs.insert(x <= 3);
cs.insert(y >= 0);
cs.insert(y <= 3);
cs.insert(z >= 0);
cs.insert(z <= 3);
cs.insert(x - 3*y <= 5); // (7)
cs.insert(x - y + z <= 5); // (8)
cs.insert(x + y + z <= 5); // (9)
Octagonal_Shape<T> oct(cs);
Definition at line 404 of file Octagonal_Shape.defs.hh.
typedef Checked_Number<T, Extended_Number_Policy> Parma_Polyhedra_Library::Octagonal_Shape< T >::N [private] |
The (extended) numeric type of the inhomogeneous term of the inequalities defining an OS.
Definition at line 411 of file Octagonal_Shape.defs.hh.
| typedef T Parma_Polyhedra_Library::Octagonal_Shape< T >::coefficient_type_base |
The numeric base type upon which OSs are built.
Definition at line 418 of file Octagonal_Shape.defs.hh.
| typedef N Parma_Polyhedra_Library::Octagonal_Shape< T >::coefficient_type |
The (extended) numeric type of the inhomogeneous term of the inequalities defining an OS.
Definition at line 424 of file Octagonal_Shape.defs.hh.
| Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape | ( | dimension_type | num_dimensions = 0, |
|
| Degenerate_Element | kind = UNIVERSE | |||
| ) | [inline, explicit] |
Builds an universe or empty OS of the specified space dimension.
| num_dimensions | The number of dimensions of the vector space enclosing the OS; | |
| kind | Specifies whether the universe or the empty OS has to be built. |
Definition at line 96 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape().
00098 : matrix(num_dimensions), space_dim(num_dimensions), status() { 00099 if (kind == EMPTY) 00100 set_empty(); 00101 else if (num_dimensions > 0) 00102 // A (non zero-dim) universe octagon is strongly closed. 00103 set_strongly_closed(); 00104 assert(OK()); 00105 }
| Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape | ( | const Octagonal_Shape< T > & | x, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) | [inline] |
Ordinary copy-constructor.
The complexity argument is ignored.
Definition at line 109 of file Octagonal_Shape.inlines.hh.
| Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape | ( | const Octagonal_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 116 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_zero_dim_univ(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::set_zero_dim_univ().
00120 : matrix((y.strong_closure_assign(), y.matrix)), 00121 space_dim(y.space_dim), 00122 status() { 00123 // TODO: handle flags properly, possibly taking special cases into account. 00124 if (y.marked_empty()) 00125 set_empty(); 00126 else if (y.marked_zero_dim_univ()) 00127 set_zero_dim_univ(); 00128 }
| Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape | ( | const Constraint_System & | cs | ) | [inline, explicit] |
Builds an OS from the system of constraints cs.
The OS inherits the space dimension of cs.
| cs | A system of constraints: constraints that are not octagonal constraints are ignored (even though they may have contributed to the space dimension). |
| std::invalid_argument | Thrown if the system of constraints cs contains strict inequalities. |
Definition at line 132 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), and Parma_Polyhedra_Library::Constraint_System::space_dimension().
00133 : matrix(cs.space_dimension()), 00134 space_dim(cs.space_dimension()), 00135 status() { 00136 if (cs.space_dimension() > 0) 00137 // A (non zero-dim) universe octagon is strongly closed. 00138 set_strongly_closed(); 00139 add_constraints(cs); 00140 }
| Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape | ( | const Congruence_System & | cgs | ) | [inline, explicit] |
Builds an OS from a system of congruences.
The OS inherits the space dimension of cgs
| cgs | A system of congruences: some elements may be safely ignored. |
Definition at line 144 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), and Parma_Polyhedra_Library::Congruence_System::space_dimension().
00145 : matrix(cgs.space_dimension()), 00146 space_dim(cgs.space_dimension()), 00147 status() { 00148 if (cgs.space_dimension() > 0) 00149 // A (non zero-dim) universe octagon is strongly closed. 00150 set_strongly_closed(); 00151 add_congruences(cgs); 00152 }
| Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape | ( | const Generator_System & | gs | ) | [inline, explicit] |
Builds an OS from the system of generators gs.
Builds the smallest OS containing the polyhedron defined by gs. The OS 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 196 of file Octagonal_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::div_round_up(), Parma_Polyhedra_Library::Generator::divisor(), Parma_Polyhedra_Library::Generator_System::end(), Parma_Polyhedra_Library::Generator::LINE, Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::max_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), PLUS_INFINITY, Parma_Polyhedra_Library::Generator::POINT, Parma_Polyhedra_Library::Generator::RAY, Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic(), and Parma_Polyhedra_Library::Generator::type().
00197 : matrix(gs.space_dimension()), 00198 space_dim(gs.space_dimension()), 00199 status() { 00200 const Generator_System::const_iterator gs_begin = gs.begin(); 00201 const Generator_System::const_iterator gs_end = gs.end(); 00202 if (gs_begin == gs_end) { 00203 // An empty generator system defines the empty polyhedron. 00204 set_empty(); 00205 return; 00206 } 00207 00208 typedef typename OR_Matrix<N>::row_reference_type Row_Reference; 00209 typename OR_Matrix<N>::row_iterator mat_begin = matrix.row_begin(); 00210 00211 DIRTY_TEMP(N, tmp); 00212 bool mat_initialized = false; 00213 bool point_seen = false; 00214 // Going through all the points and closure points. 00215 for (Generator_System::const_iterator k = gs_begin; k != gs_end; ++k) { 00216 const Generator& g = *k; 00217 switch (g.type()) { 00218 case Generator::POINT: 00219 point_seen = true; 00220 // Intentionally fall through. 00221 case Generator::CLOSURE_POINT: 00222 if (!mat_initialized) { 00223 // When handling the first (closure) point, we initialize the matrix. 00224 mat_initialized = true; 00225 const Coefficient& d = g.divisor(); 00226 for (dimension_type i = 0; i < space_dim; ++i) { 00227 const Coefficient& g_i = g.coefficient(Variable(i)); 00228 const dimension_type di = 2*i; 00229 Row_Reference x_i = *(mat_begin+di); 00230 Row_Reference x_ii = *(mat_begin+di+1); 00231 for (dimension_type j = 0; j < i; ++j) { 00232 const Coefficient& g_j = g.coefficient(Variable(j)); 00233 const dimension_type dj = 2*j; 00234 // Set for any point the hyperplanes passing in the point 00235 // and having the octagonal gradient. 00236 // Let be P = [P_1, P_2, ..., P_n] point. 00237 // Hyperplanes: X_i - X_j = P_i - P_j. 00238 div_round_up(x_i[dj], g_j - g_i, d); 00239 div_round_up(x_ii[dj+1], g_i - g_j, d); 00240 // Hyperplanes: X_i + X_j = P_i + P_j. 00241 div_round_up(x_i[dj+1], -g_j - g_i, d); 00242 div_round_up(x_ii[dj], g_i + g_j, d); 00243 } 00244 // Hyperplanes: X_i = P_i. 00245 div_round_up(x_i[di+1], -g_i - g_i, d); 00246 div_round_up(x_ii[di], g_i + g_i, d); 00247 } 00248 } 00249 else { 00250 // This is not the first point: the matrix already contains 00251 // valid values and we must compute maxima. 00252 const Coefficient& d = g.divisor(); 00253 for (dimension_type i = 0; i < space_dim; ++i) { 00254 const Coefficient& g_i = g.coefficient(Variable(i)); 00255 const dimension_type di = 2*i; 00256 Row_Reference x_i = *(mat_begin+di); 00257 Row_Reference x_ii = *(mat_begin+di+1); 00258 for (dimension_type j = 0; j < i; ++j) { 00259 const Coefficient& g_j = g.coefficient(Variable(j)); 00260 const dimension_type dj = 2*j; 00261 // Set for any point the straight lines passing in the point 00262 // and having the octagonal gradient; compute maxima values. 00263 // Let be P = [P_1, P_2, ..., P_n] point. 00264 // Hyperplane: X_i - X_j = max (P_i - P_j, const). 00265 div_round_up(tmp, g_j - g_i, d); 00266 max_assign(x_i[dj], tmp); 00267 div_round_up(tmp, g_i - g_j, d); 00268 max_assign(x_ii[dj+1], tmp); 00269 // Hyperplane: X_i + X_j = max (P_i + P_j, const). 00270 div_round_up(tmp, -g_j - g_i, d); 00271 max_assign(x_i[dj+1], tmp); 00272 div_round_up(tmp, g_i + g_j, d); 00273 max_assign(x_ii[dj], tmp); 00274 } 00275 // Hyperplane: X_i = max (P_i, const). 00276 div_round_up(tmp, -g_i - g_i, d); 00277 max_assign(x_i[di+1], tmp); 00278 div_round_up(tmp, g_i + g_i, d); 00279 max_assign(x_ii[di], tmp); 00280 } 00281 } 00282 break; 00283 default: 00284 // Lines and rays temporarily ignored. 00285 break; 00286 } 00287 } 00288 00289 if (!point_seen) 00290 // The generator system is not empty, but contains no points. 00291 throw_generic("Octagonal_Shape(gs)", 00292 "the non-empty generator system gs contains no points."); 00293 00294 // Going through all the lines and rays. 00295 for (Generator_System::const_iterator k = gs_begin; k != gs_end; ++k) { 00296 const Generator& g = *k; 00297 switch (g.type()) { 00298 case Generator::LINE: 00299 for (dimension_type i = 0; i < space_dim; ++i) { 00300 const Coefficient& g_i = g.coefficient(Variable(i)); 00301 const dimension_type di = 2*i; 00302 Row_Reference x_i = *(mat_begin+di); 00303 Row_Reference x_ii = *(mat_begin+di+1); 00304 for (dimension_type j = 0; j < i; ++j) { 00305 const Coefficient& g_j = g.coefficient(Variable(j)); 00306 const dimension_type dj = 2*j; 00307 // Set for any line the right limit. 00308 if (g_i != g_j) { 00309 // Hyperplane: X_i - X_j <=/>= +Inf. 00310 assign_r(x_i[dj], PLUS_INFINITY, ROUND_NOT_NEEDED); 00311 assign_r(x_ii[dj+1], PLUS_INFINITY, ROUND_NOT_NEEDED); 00312 } 00313 if (g_i != -g_j) { 00314 // Hyperplane: X_i + X_j <=/>= +Inf. 00315 assign_r(x_i[dj+1], PLUS_INFINITY, ROUND_NOT_NEEDED); 00316 assign_r(x_ii[dj], PLUS_INFINITY, ROUND_NOT_NEEDED); 00317 } 00318 } 00319 if (g_i != 0) { 00320 // Hyperplane: X_i <=/>= +Inf. 00321 assign_r(x_i[di+1], PLUS_INFINITY, ROUND_NOT_NEEDED); 00322 assign_r(x_ii[di], PLUS_INFINITY, ROUND_NOT_NEEDED); 00323 } 00324 } 00325 break; 00326 case Generator::RAY: 00327 for (dimension_type i = 0; i < space_dim; ++i) { 00328 const Coefficient& g_i = g.coefficient(Variable(i)); 00329 const dimension_type di = 2*i; 00330 Row_Reference x_i = *(mat_begin+di); 00331 Row_Reference x_ii = *(mat_begin+di+1); 00332 for (dimension_type j = 0; j < i; ++j) { 00333 const Coefficient& g_j = g.coefficient(Variable(j)); 00334 const dimension_type dj = 2*j; 00335 // Set for any ray the right limit in the case 00336 // of the binary constraints. 00337 if (g_i < g_j) 00338 // Hyperplane: X_i - X_j >= +Inf. 00339 assign_r(x_i[dj], PLUS_INFINITY, ROUND_NOT_NEEDED); 00340 if (g_i > g_j) 00341 // Hyperplane: X_i - X_j <= +Inf. 00342 assign_r(x_ii[dj+1], PLUS_INFINITY, ROUND_NOT_NEEDED); 00343 if (g_i < -g_j) 00344 // Hyperplane: X_i + X_j >= +Inf. 00345 assign_r(x_i[dj+1], PLUS_INFINITY, ROUND_NOT_NEEDED); 00346 if (g_i > -g_j) 00347 // Hyperplane: X_i + X_j <= +Inf. 00348 assign_r(x_ii[dj], PLUS_INFINITY, ROUND_NOT_NEEDED); 00349 } 00350 // Case: unary constraints. 00351 if (g_i < 0) 00352 // Hyperplane: X_i = +Inf. 00353 assign_r(x_i[di+1], PLUS_INFINITY, ROUND_NOT_NEEDED); 00354 if (g_i > 0) 00355 // Hyperplane: X_i = +Inf. 00356 assign_r(x_ii[di], PLUS_INFINITY, ROUND_NOT_NEEDED); 00357 } 00358 break; 00359 default: 00360 // Points and closure points already dealt with. 00361 break; 00362 } 00363 } 00364 set_strongly_closed(); 00365 assert(OK()); 00366 }
| Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape | ( | const Polyhedron & | ph, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) | [inline, explicit] |
Builds an OS from the polyhedron ph.
Builds an OS containing ph using algorithms whose complexity does not exceed the one specified by complexity. If complexity is ANY_COMPLEXITY, then the OS built is the smallest one containing ph.
Definition at line 42 of file Octagonal_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::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::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, Parma_Polyhedra_Library::MIP_Problem::optimizing_point(), Parma_Polyhedra_Library::POLYNOMIAL_COMPLEXITY, Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraints(), Parma_Polyhedra_Library::MIP_Problem::set_objective_function(), Parma_Polyhedra_Library::MIP_Problem::set_optimization_mode(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), Parma_Polyhedra_Library::SIMPLEX_COMPLEXITY, Parma_Polyhedra_Library::MIP_Problem::solve(), Parma_Polyhedra_Library::Polyhedron::space_dimension(), TEMP_INTEGER, and Parma_Polyhedra_Library::UNIVERSE.
00044 : matrix(0), space_dim(0), status() { 00045 const dimension_type num_dimensions = ph.space_dimension(); 00046 00047 if (ph.marked_empty()) { 00048 *this = Octagonal_Shape(num_dimensions, EMPTY); 00049 return; 00050 } 00051 00052 if (num_dimensions == 0) { 00053 *this = Octagonal_Shape(num_dimensions, UNIVERSE); 00054 return; 00055 } 00056 00057 // Build from generators when we do not care about complexity 00058 // or when the process has polynomial complexity. 00059 if (complexity == ANY_COMPLEXITY 00060 || (!ph.has_pending_constraints() && ph.generators_are_up_to_date())) { 00061 *this = Octagonal_Shape(ph.generators()); 00062 return; 00063 } 00064 00065 // We cannot afford exponential complexity, we do not have a complete set 00066 // of generators for the polyhedron, and the polyhedron is not trivially 00067 // empty or zero-dimensional. Constraints, however, are up to date. 00068 assert(ph.constraints_are_up_to_date()); 00069 00070 if (!ph.has_something_pending() && ph.constraints_are_minimized()) { 00071 // If the constraint system of the polyhedron is minimized, 00072 // the test `is_universe()' has polynomial complexity. 00073 if (ph.is_universe()) { 00074 *this = Octagonal_Shape(num_dimensions, UNIVERSE); 00075 return; 00076 } 00077 } 00078 00079 // See if there is at least one inconsistent constraint in `ph.con_sys'. 00080 for (Constraint_System::const_iterator i = ph.con_sys.begin(), 00081 cs_end = ph.con_sys.end(); i != cs_end; ++i) 00082 if (i->is_inconsistent()) { 00083 *this = Octagonal_Shape(num_dimensions, EMPTY); 00084 return; 00085 } 00086 00087 // If `complexity' allows it, use simplex to derive the exact (modulo 00088 // the fact that our OSs are topologically closed) variable bounds. 00089 if (complexity == SIMPLEX_COMPLEXITY) { 00090 MIP_Problem lp(num_dimensions); 00091 lp.set_optimization_mode(MAXIMIZATION); 00092 00093 const Constraint_System& ph_cs = ph.constraints(); 00094 if (!ph_cs.has_strict_inequalities()) 00095 lp.add_constraints(ph_cs); 00096 else 00097 // Adding to `lp' a topologically closed version of `ph_cs'. 00098 for (Constraint_System::const_iterator i = ph_cs.begin(), 00099 ph_cs_end = ph_cs.end(); i != ph_cs_end; ++i) { 00100 const Constraint& c = *i; 00101 if (c.is_strict_inequality()) 00102 lp.add_constraint(Linear_Expression(c) >= 0); 00103 else 00104 lp.add_constraint(c); 00105 } 00106 00107 // Check for unsatisfiability. 00108 if (!lp.is_satisfiable()) { 00109 *this = Octagonal_Shape<T>(num_dimensions, EMPTY); 00110 return; 00111 } 00112 00113 // Start with a universe OS that will be refined by the simplex. 00114 *this = Octagonal_Shape<T>(num_dimensions, UNIVERSE); 00115 // Get all the upper bounds. 00116 Generator g(point()); 00117 TEMP_INTEGER(num); 00118 TEMP_INTEGER(den); 00119 for (dimension_type i = 0; i < num_dimensions; ++i) { 00120 Variable x(i); 00121 // Evaluate optimal upper bound for `x <= ub'. 00122 lp.set_objective_function(x); 00123 if (lp.solve() == OPTIMIZED_MIP_PROBLEM) { 00124 g = lp.optimizing_point(); 00125 lp.evaluate_objective_function(g, num, den); 00126 num *= 2; 00127 div_round_up(matrix[2*i+1][2*i], num, den); 00128 } 00129 // Evaluate optimal upper bounds for `x + y <= ub'. 00130 for (dimension_type j = 0; j < i; ++j) { 00131 Variable y(j); 00132 lp.set_objective_function(x + y); 00133 if (lp.solve() == OPTIMIZED_MIP_PROBLEM) { 00134 g = lp.optimizing_point(); 00135 lp.evaluate_objective_function(g, num, den); 00136 div_round_up(matrix[2*i+1][2*j], num, den); 00137 } 00138 } 00139 // Evaluate optimal upper bound for `x - y <= ub'. 00140 for (dimension_type j = 0; j < num_dimensions; ++j) { 00141 if (i == j) 00142 continue; 00143 Variable y(j); 00144 lp.set_objective_function(x - y); 00145 if (lp.solve() == OPTIMIZED_MIP_PROBLEM) { 00146 g = lp.optimizing_point(); 00147 lp.evaluate_objective_function(g, num, den); 00148 div_round_up((i < j ? matrix[2*j][2*i] : matrix[2*i+1][2*j+1]), 00149 num, den); 00150 } 00151 } 00152 // Evaluate optimal upper bound for `y - x <= ub'. 00153 for (dimension_type j = 0; j < num_dimensions; ++j) { 00154 if (i == j) 00155 continue; 00156 Variable y(j); 00157 lp.set_objective_function(x - y); 00158 if (lp.solve() == OPTIMIZED_MIP_PROBLEM) { 00159 g = lp.optimizing_point(); 00160 lp.evaluate_objective_function(g, num, den); 00161 div_round_up((i < j ? matrix[2*j][2*i] : matrix[2*i+1][2*j+1]), 00162 num, den); 00163 } 00164 } 00165 // Evaluate optimal upper bound for `-x - y <= ub'. 00166 for (dimension_type j = 0; j < i; ++j) { 00167 Variable y(j); 00168 lp.set_objective_function(-x - y); 00169 if (lp.solve() == OPTIMIZED_MIP_PROBLEM) { 00170 g = lp.optimizing_point(); 00171 lp.evaluate_objective_function(g, num, den); 00172 div_round_up(matrix[2*i][2*j+1], num, den); 00173 } 00174 } 00175 // Evaluate optimal upper bound for `-x <= ub'. 00176 lp.set_objective_function(-x); 00177 if (lp.solve() == OPTIMIZED_MIP_PROBLEM) { 00178 g = lp.optimizing_point(); 00179 lp.evaluate_objective_function(g, num, den); 00180 num *= 2; 00181 div_round_up(matrix[2*i][2*i+1], num, den); 00182 } 00183 } 00184 set_strongly_closed(); 00185 assert(OK()); 00186 return; 00187 } 00188 00189 // Extract easy-to-find bounds from constraints. 00190 assert(complexity == POLYNOMIAL_COMPLEXITY); 00191 *this = Octagonal_Shape(num_dimensions, UNIVERSE); 00192 refine_with_constraints(ph.constraints()); 00193 }
| Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape | ( | const Box< Interval > & | box, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) | [inline, explicit] |
Builds an OS out of a box.
The OS inherits the space dimension of the box. The built OS is the most precise OS 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 157 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Box< ITV >::constraints(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), and Parma_Polyhedra_Library::Box< ITV >::space_dimension().
00159 : matrix(box.space_dimension()), 00160 space_dim(box.space_dimension()), 00161 status() { 00162 // Check for emptyness for maximum precision. 00163 if (box.is_empty()) 00164 set_empty(); 00165 else if (box.space_dimension() > 0) { 00166 // A (non zero-dim) universe OS is strongly closed. 00167 set_strongly_closed(); 00168 refine_with_constraints(box.constraints()); 00169 } 00170 }
| Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape | ( | const Grid & | grid, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) | [inline, explicit] |
Builds an OS that approximates a grid.
The OS inherits the space dimension of the grid. The built OS is the most precise OS that includes the grid.
| grid | The grid used to build the OS. | |
| 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 174 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Grid::minimized_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), and Parma_Polyhedra_Library::Grid::space_dimension().
00176 : matrix(grid.space_dimension()), 00177 space_dim(grid.space_dimension()), 00178 status() { 00179 if (grid.space_dimension() > 0) 00180 // A (non zero-dim) universe OS is strongly closed. 00181 set_strongly_closed(); 00182 // Taking minimized congruences ensures maximum precision. 00183 refine_with_congruences(grid.minimized_congruences()); 00184 }
| Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape | ( | const BD_Shape< U > & | bd, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) | [inline, explicit] |
Builds an OS from a BD shape.
The OS inherits the space dimension of the BD shape. The built OS is the most precise OS that includes the BD shape.
| bd | The BD shape used to build the OS. | |
| complexity | This argument is ignored as the algorithm used has polynomial complexity. |
| std::length_error | Thrown if the space dimension of bd exceeds the maximum allowed space dimension. |
Definition at line 189 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::BD_Shape< T >::constraints(), Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().
00191 : matrix(bd.space_dimension()), 00192 space_dim(bd.space_dimension()), 00193 status() { 00194 // Check for emptyness for maximum precision. 00195 if (bd.is_empty()) 00196 set_empty(); 00197 else if (bd.space_dimension() > 0) { 00198 // A (non zero-dim) universe OS is strongly closed. 00199 set_strongly_closed(); 00200 refine_with_constraints(bd.constraints()); 00201 } 00202 }
| Parma_Polyhedra_Library::Octagonal_Shape< T >::~Octagonal_Shape | ( | ) | [inline] |
| dimension_type Parma_Polyhedra_Library::Octagonal_Shape< T >::max_space_dimension | ( | ) | [inline, static] |
Returns the maximum space dimension that an OS can handle.
Definition at line 48 of file Octagonal_Shape.inlines.hh.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension().
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::can_recycle_constraint_systems | ( | ) | [inline, static] |
Returns false indicating that this domain cannot recycle constraints.
Definition at line 507 of file Octagonal_Shape.inlines.hh.
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::can_recycle_congruence_systems | ( | ) | [inline, static] |
Returns false indicating that this domain cannot recycle congruences.
Definition at line 513 of file Octagonal_Shape.inlines.hh.
| Octagonal_Shape< T > & Parma_Polyhedra_Library::Octagonal_Shape< T >::operator= | ( | const Octagonal_Shape< T > & | y | ) | [inline] |
The assignment operator. (*this and y can be dimension-incompatible.).
Definition at line 212 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::status.
00212 { 00213 matrix = y.matrix; 00214 space_dim = y.space_dim; 00215 status = y.status; 00216 return *this; 00217 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::swap | ( | Octagonal_Shape< T > & | y | ) | [inline] |
Swaps *this with octagon y. (*this and y can be dimension-incompatible.).
Definition at line 226 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::status, and Parma_Polyhedra_Library::swap().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::swap(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::time_elapse_assign().
00226 { 00227 std::swap(matrix, y.matrix); 00228 std::swap(space_dim, y.space_dim); 00229 std::swap(status, y.status); 00230 }
| dimension_type Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension | ( | ) | const [inline] |
Returns the dimension of the vector space enclosing *this.
Definition at line 234 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruence(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constrains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::Octagonal_Shape< T >::hash_code(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruence(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_coherence_would_make_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::time_elapse_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::unconstrain().
00234 { 00235 return space_dim; 00236 }
| dimension_type Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_dimension | ( | ) | const [inline] |
Returns
, if *this is empty; otherwise, returns the affine dimension of *this.
Definition at line 547 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_leaders(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::is_discrete().
00547 { 00548 const dimension_type n_rows = matrix.num_rows(); 00549 // A zero-space-dim shape always has affine dimension zero. 00550 if (n_rows == 0) 00551 return 0; 00552 00553 // Strong closure is necessary to detect emptiness 00554 // and all (possibly implicit) equalities. 00555 strong_closure_assign(); 00556 if (marked_empty()) 00557 return 0; 00558 00559 // The vector `leaders' is used to represent non-singular 00560 // equivalence classes: 00561 // `leaders[i] == i' if and only if `i' is the leader of its 00562 // equivalence class (i.e., the minimum index in the class); 00563 std::vector<dimension_type> leaders; 00564 compute_leaders(leaders); 00565 00566 // Due to the splitting of variables, the affine dimension is the 00567 // number of non-singular positive zero-equivalence classes. 00568 dimension_type affine_dim = 0; 00569 for (dimension_type i = 0; i < n_rows; i += 2) 00570 // Note: disregard the singular equivalence class. 00571 if (leaders[i] == i && leaders[i+1] == i+1) 00572 ++affine_dim; 00573 00574 return affine_dim; 00575 }
| Constraint_System Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints | ( | ) | const [inline] |
Returns the system of constraints defining *this.
Definition at line 5735 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::numer_denom(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, TEMP_INTEGER, and Parma_Polyhedra_Library::Constraint_System::zero_dim_empty().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds(), Parma_Polyhedra_Library::C_Polyhedron::C_Polyhedron(), Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_constraints(), Parma_Polyhedra_Library::NNC_Polyhedron::NNC_Polyhedron(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::time_elapse_assign().
05735 { 05736 Constraint_System cs; 05737 if (space_dim == 0) { 05738 if (marked_empty()) 05739 cs = Constraint_System::zero_dim_empty(); 05740 } 05741 else if (marked_empty()) 05742 cs.insert(0*Variable(space_dim-1) <= -1); 05743 else { 05744 // KLUDGE: in the future `cs' will be constructed of the right dimension. 05745 // For the time being, we force the dimension with the following line. 05746 cs.insert(0*Variable(space_dim-1) <= 0); 05747 05748 typedef typename OR_Matrix<N>::const_row_iterator Row_Iterator; 05749 typedef typename OR_Matrix<N>::const_row_reference_type Row_Reference; 05750 05751 Row_Iterator m_begin = matrix.row_begin(); 05752 Row_Iterator m_end = matrix.row_end(); 05753 05754 TEMP_INTEGER(a); 05755 TEMP_INTEGER(b); 05756 05757 // Go through all the unary constraints in `matrix'. 05758 for (Row_Iterator i_iter = m_begin; i_iter != m_end; ) { 05759 const dimension_type i = i_iter.index(); 05760 const Variable x(i/2); 05761 const N& c_i_ii = (*i_iter)[i+1]; 05762 ++i_iter; 05763 const N& c_ii_i = (*i_iter)[i]; 05764 ++i_iter; 05765 // Go through unary constraints. 05766 if (is_additive_inverse(c_i_ii, c_ii_i)) { 05767 // We have a unary equality constraint. 05768 numer_denom(c_ii_i, b, a); 05769 a *= 2; 05770 cs.insert(a*x == b); 05771 } 05772 else { 05773 // We have 0, 1 or 2 inequality constraints. 05774 if (!is_plus_infinity(c_i_ii)) { 05775 numer_denom(c_i_ii, b, a); 05776 a *= 2; 05777 cs.insert(-a*x <= b); 05778 } 05779 if (!is_plus_infinity(c_ii_i)) { 05780 numer_denom(c_ii_i, b, a); 05781 a *= 2; 05782 cs.insert(a*x <= b); 05783 } 05784 } 05785 } 05786 // Go through all the binary constraints in `matrix'. 05787 for (Row_Iterator i_iter = m_begin; i_iter != m_end; ) { 05788 const dimension_type i = i_iter.index(); 05789 Row_Reference r_i = *i_iter; 05790 ++i_iter; 05791 Row_Reference r_ii = *i_iter; 05792 ++i_iter; 05793 const Variable y(i/2); 05794 for (dimension_type j = 0; j < i; j += 2) { 05795 const N& c_i_j = r_i[j]; 05796 const N& c_ii_jj = r_ii[j+1]; 05797 const Variable x(j/2); 05798 if (is_additive_inverse(c_ii_jj, c_i_j)) { 05799 // We have an equality constraint of the form ax - ay = b. 05800 numer_denom(c_i_j, b, a); 05801 cs.insert(a*x - a*y == b); 05802 } 05803 else { 05804 // We have 0, 1 or 2 inequality constraints. 05805 if (!is_plus_infinity(c_i_j)) { 05806 numer_denom(c_i_j, b, a); 05807 cs.insert(a*x - a*y <= b); 05808 } 05809 if (!is_plus_infinity(c_ii_jj)) { 05810 numer_denom(c_ii_jj, b, a); 05811 cs.insert(a*y - a*x <= b); 05812 } 05813 } 05814 05815 const N& c_ii_j = r_ii[j]; 05816 const N& c_i_jj = r_i[j+1]; 05817 if (is_additive_inverse(c_i_jj, c_ii_j)) { 05818 // We have an equality constraint of the form ax + ay = b. 05819 numer_denom(c_ii_j, b, a); 05820 cs.insert(a*x + a*y == b); 05821 } 05822 else { 05823 // We have 0, 1 or 2 inequality constraints. 05824 if (!is_plus_infinity(c_i_jj)) { 05825 numer_denom(c_i_jj, b, a); 05826 cs.insert(-a*x - a*y <= b); 05827 } 05828 if (!is_plus_infinity(c_ii_j)) { 05829 numer_denom(c_ii_j, b, a); 05830 cs.insert(a*x + a*y <= b); 05831 } 05832 } 05833 } 05834 } 05835 } 05836 return cs; 05837 }
| Constraint_System Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_constraints | ( | ) | const [inline] |
Returns a minimized system of constraints defining *this.
Definition at line 367 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign().
00367 { 00368 strong_reduction_assign(); 00369 return constraints(); 00370 }
| Congruence_System Parma_Polyhedra_Library::Octagonal_Shape< T >::congruences | ( | ) | const [inline] |
Returns a system of (equality) congruences satisfied by *this.
Definition at line 206 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_congruences().
Referenced by Parma_Polyhedra_Library::Grid::Grid().
00206 { 00207 return minimized_congruences(); 00208 }
| Congruence_System Parma_Polyhedra_Library::Octagonal_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 579 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_leaders(), Parma_Polyhedra_Library::Congruence_System::insert(), Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::numer_denom(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), TEMP_INTEGER, and Parma_Polyhedra_Library::Congruence_System::zero_dim_empty().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::congruences().
00579 { 00580 // Strong closure is necessary to detect emptiness 00581 // and all (possibly implicit) equalities. 00582 strong_closure_assign(); 00583 const dimension_type space_dim = space_dimension(); 00584 Congruence_System cgs; 00585 if (space_dim == 0) { 00586 if (marked_empty()) 00587 cgs = Congruence_System::zero_dim_empty(); 00588 } 00589 else if (marked_empty()) 00590 cgs.insert((0*Variable(space_dim-1) %= 1) / 0); 00591 else { 00592 // KLUDGE: in the future `cgs' will be constructed of the right dimension. 00593 // For the time being, we force the dimension with the following line. 00594 cgs.insert(0*Variable(space_dim-1) == 0); 00595 00596 // The vector `leaders' is used to represent equivalence classes: 00597 // `leaders[i] == i' if and only if `i' is the leader of its 00598 // equivalence class (i.e., the minimum index in the class); 00599 std::vector<dimension_type> leaders; 00600 compute_leaders(leaders); 00601 00602 TEMP_INTEGER(num); 00603 TEMP_INTEGER(den); 00604 for (dimension_type i = 0, i_end = 2*space_dim; i != i_end; i += 2) { 00605 const dimension_type lead_i = leaders[i]; 00606 if (i == lead_i) { 00607 if (leaders[i+1] == i) 00608 // `i' is the leader of the singular equivalence class. 00609 goto singular; 00610 else 00611 // `i' is the leader of a non-singular equivalence class. 00612 continue; 00613 } 00614 else { 00615 // `i' is not a leader. 00616 if (leaders[i+1] == lead_i) 00617 // `i' belongs to the singular equivalence class. 00618 goto singular; 00619 else 00620 // `i' does not belong to the singular equivalence class. 00621 goto non_singular; 00622 } 00623 00624 singular: 00625 // `i' belongs to the singular equivalence class: 00626 // we have a unary equality constraint. 00627 { 00628 const Variable x(i/2); 00629 const N& c_ii_i = matrix[i+1][i]; 00630 #ifndef NDEBUG 00631 const N& c_i_ii = matrix[i][i+1]; 00632 assert(is_additive_inverse(c_i_ii, c_ii_i)); 00633 #endif 00634 numer_denom(c_ii_i, num, den); 00635 den *= 2; 00636 cgs.insert(den*x == num); 00637 } 00638 continue; 00639 00640 non_singular: 00641 // `i' does not belong to the singular equivalence class. 00642 // we have a binary equality constraint. 00643 { 00644 const N& c_i_li = matrix[i][lead_i]; 00645 #ifndef NDEBUG 00646 const N& c_ii_lii = matrix[i+1][coherent_index(lead_i)]; 00647 assert(is_additive_inverse(c_ii_lii, c_i_li)); 00648 #endif 00649 const Variable x(lead_i/2); 00650 const Variable y(i/2); 00651 numer_denom(c_i_li, num, den); 00652 if (lead_i % 2 == 0) 00653 cgs.insert(den*x - den*y == num); 00654 else 00655 cgs.insert(den*x + den*y + num == 0); 00656 } 00657 continue; 00658 } 00659 } 00660 return cgs; 00661 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::contains | ( | const Octagonal_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 709 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_BHMZ05_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_CC76_extrapolation_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strictly_contains().
00709 { 00710 // Dimension-compatibility check. 00711 if (space_dim != y.space_dim) 00712 throw_dimension_incompatible("contains(y)", y); 00713 00714 // The zero-dimensional universe octagon contains any other 00715 // dimension-compatible octagon. 00716 // The zero-dimensional empty octagon only contains another 00717 // zero-dimensional empty octagon. 00718 if (space_dim == 0) { 00719 if (!marked_empty()) 00720 return true; 00721 else 00722 return y.marked_empty(); 00723 } 00724 00725 // `y' needs to be transitively closed. 00726 y.strong_closure_assign(); 00727 // An empty octagon is in any other dimension-compatible octagons. 00728 if (y.marked_empty()) 00729 return true; 00730 00731 // `*this' contains `y' if and only if every element of `*this' 00732 // is greater than or equal to the correspondent one of `y'. 00733 for (typename OR_Matrix<N>::const_element_iterator 00734 i = matrix.element_begin(), j = y.matrix.element_begin(), 00735 matrix_element_end = matrix.element_end(); i != matrix_element_end; ++i, ++j) 00736 if (*i < *j) 00737 return false; 00738 return true; 00739 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::strictly_contains | ( | const Octagonal_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 584 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::contains().
00584 { 00585 const Octagonal_Shape<T>& x = *this; 00586 return x.contains(y) && !y.contains(x); 00587 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::is_disjoint_from | ( | const Octagonal_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 743 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
00743 { 00744 // Dimension-compatibility check. 00745 if (space_dim != y.space_dim) 00746 throw_dimension_incompatible("is_disjoint_from(y)", y); 00747 00748 // If one Octagonal_Shape is empty, the Octagonal_Shapes are disjoint. 00749 strong_closure_assign(); 00750 if (marked_empty()) 00751 return true; 00752 y.strong_closure_assign(); 00753 if (y.marked_empty()) 00754 return true; 00755 00756 // Two Octagonal_Shapes are disjoint if and only if their intersection 00757 // is empty, i.e., if and only if there exists a variable such that 00758 // the upper bound of the constraint on that variable in the first 00759 // Octagonal_Shape is strictly less than the lower bound of 00760 // the correspomding constraint in the second Octagonal_Shape or vice versa. 00761 00762 const dimension_type n_rows = matrix.num_rows(); 00763 00764 typedef typename OR_Matrix<N>::const_row_iterator Row_Iterator; 00765 typedef typename OR_Matrix<N>::const_row_reference_type Row_Reference; 00766 00767 const Row_Iterator m_begin = matrix.row_begin(); 00768 const Row_Iterator m_end = matrix.row_end(); 00769 00770 const Row_Iterator y_begin = y.matrix.row_begin(); 00771 const Row_Iterator y_end = y.matrix.row_end(); 00772 00773 DIRTY_TEMP(N, neg_y_ci_cj); 00774 for (Row_Iterator i_iter = m_begin; i_iter != m_end; ++i_iter) { 00775 const dimension_type i = i_iter.index(); 00776 const dimension_type ci = coherent_index(i); 00777 const dimension_type rs_i = i_iter.row_size(); 00778 Row_Reference m_i = *i_iter; 00779 Row_Reference m_ci = (i%2) ? *(i_iter-1) : *(i_iter+1); 00780 for (dimension_type j = 0; j < n_rows; ++j) { 00781 const dimension_type cj = coherent_index(j); 00782 Row_Reference m_cj = *(m_begin + cj); 00783 const N& m_i_j = (j < rs_i) ? m_i[j] : m_cj[ci]; 00784 Row_Reference y_ci = *(y_begin + ci); 00785 Row_Reference y_j = *(y_begin + j); 00786 const N& y_ci_cj = (j < rs_i) ? y_ci[cj] : y_j[i]; 00787 neg_assign_r(neg_y_ci_cj, y_ci_cj, ROUND_UP); 00788 if (m_i_j < neg_y_ci_cj) 00789 return true; 00790 } 00791 } 00792 return false; 00793 }
| Poly_Con_Relation Parma_Polyhedra_Library::Octagonal_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 1249 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::Octagonal_Shape< T >::extract_octagonal_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::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::maximize(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimize(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::numer_denom(), Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::Poly_Con_Relation::strictly_intersects(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), TEMP_INTEGER, and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with().
01249 { 01250 dimension_type c_space_dim = c.space_dimension(); 01251 01252 // Dimension-compatibility check. 01253 if (c_space_dim > space_dim) 01254 throw_dimension_incompatible("relation_with(c)", c); 01255 01256 // The closure needs to make explicit the implicit constraints. 01257 strong_closure_assign(); 01258 01259 if (marked_empty()) 01260 return Poly_Con_Relation::saturates() 01261 && Poly_Con_Relation::is_included() 01262 && Poly_Con_Relation::is_disjoint(); 01263 01264 if (space_dim == 0) { 01265 // Trivially false zero-dimensional constraint. 01266 if ((c.is_equality() && c.inhomogeneous_term() != 0) 01267 || (c.is_inequality() && c.inhomogeneous_term() < 0)) 01268 return Poly_Con_Relation::is_disjoint(); 01269 else if (c.is_strict_inequality() && c.inhomogeneous_term() == 0) 01270 // The constraint 0 > 0 implicitly defines the hyperplane 0 = 0; 01271 // thus, the zero-dimensional point also saturates it. 01272 return Poly_Con_Relation::saturates() 01273 && Poly_Con_Relation::is_disjoint(); 01274 01275 // Trivially true zero-dimensional constraint. 01276 else if (c.is_equality() || c.inhomogeneous_term() == 0) 01277 return Poly_Con_Relation::saturates() 01278 && Poly_Con_Relation::is_included(); 01279 else 01280 // The zero-dimensional point saturates 01281 // neither the positivity constraint 1 >= 0, 01282 // nor the strict positivity constraint 1 > 0. 01283 return Poly_Con_Relation::is_included(); 01284 } 01285 01286 dimension_type num_vars = 0; 01287 dimension_type i = 0; 01288 dimension_type j = 0; 01289 TEMP_INTEGER(coeff); 01290 TEMP_INTEGER(c_term); 01291 if (!extract_octagonal_difference(c, c_space_dim, num_vars, 01292 i, j, coeff, c_term)) { 01293 // Constraints that are not octagonal differences. 01294 // Use maximize() and minimize() to do much of the work. 01295 01296 // Find the linear expression for the constraint and use that to 01297 // find if the expression is bounded from above or below and if it 01298 // is, find the maximum and minimum values. 01299 Linear_Expression le; 01300 for (dimension_type k = c_space_dim; k-- > 0; ) { 01301 Variable vk(k); 01302 le += c.coefficient(vk) * vk; 01303 } 01304 DIRTY_TEMP(Coefficient, max_num); 01305 DIRTY_TEMP(Coefficient, max_den); 01306 bool max_included; 01307 DIRTY_TEMP(Coefficient, min_num); 01308 DIRTY_TEMP(Coefficient, min_den); 01309 bool min_included; 01310 bool bounded_above = maximize(le, max_num, max_den, max_included); 01311 bool bounded_below = minimize(le, min_num, min_den, min_included); 01312 if (!bounded_above) { 01313 if (!bounded_below) 01314 return Poly_Con_Relation::strictly_intersects(); 01315 min_num += c.inhomogeneous_term() * min_den; 01316 switch (sgn(min_num)) { 01317 case 1: 01318 if (c.is_equality()) 01319 return Poly_Con_Relation::is_disjoint(); 01320 return Poly_Con_Relation::is_included(); 01321 case 0: 01322 if (c.is_strict_inequality() || c.is_equality()) 01323 return Poly_Con_Relation::strictly_intersects(); 01324 return Poly_Con_Relation::is_included(); 01325 case -1: 01326 return Poly_Con_Relation::strictly_intersects(); 01327 } 01328 } 01329 if (!bounded_below) { 01330 max_num += c.inhomogeneous_term() * max_den; 01331 switch (sgn(max_num)) { 01332 case 1: 01333 return Poly_Con_Relation::strictly_intersects(); 01334 case 0: 01335 if (c.is_strict_inequality()) 01336 return Poly_Con_Relation::is_disjoint(); 01337 return Poly_Con_Relation::strictly_intersects(); 01338 case -1: 01339 return Poly_Con_Relation::is_disjoint(); 01340 } 01341 } 01342 else { 01343 max_num += c.inhomogeneous_term() * max_den; 01344 min_num += c.inhomogeneous_term() * min_den; 01345 switch (sgn(max_num)) { 01346 case 1: 01347 switch (sgn(min_num)) { 01348 case 1: 01349 if (c.is_equality()) 01350 return Poly_Con_Relation::is_disjoint(); 01351 return Poly_Con_Relation::is_included(); 01352 case 0: 01353 if (c.is_equality()) 01354 return Poly_Con_Relation::strictly_intersects(); 01355 if (c.is_strict_inequality()) 01356 return Poly_Con_Relation::strictly_intersects(); 01357 return Poly_Con_Relation::is_included(); 01358 case -1: 01359 return Poly_Con_Relation::strictly_intersects(); 01360 } 01361 case 0: 01362 if (min_num == 0) { 01363 if (c.is_strict_inequality()) 01364 return Poly_Con_Relation::is_disjoint() 01365 && Poly_Con_Relation::saturates(); 01366 return Poly_Con_Relation::is_included() 01367 && Poly_Con_Relation::saturates(); 01368 } 01369 if (c.is_strict_inequality()) 01370 return Poly_Con_Relation::is_disjoint(); 01371 return Poly_Con_Relation::strictly_intersects(); 01372 case -1: 01373 return Poly_Con_Relation::is_disjoint(); 01374 } 01375 } 01376 } 01377 01378 if (num_vars == 0) { 01379 // Dealing with a trivial constraint. 01380 switch (sgn(c.inhomogeneous_term())) { 01381 case -1: 01382 return Poly_Con_Relation::is_disjoint(); 01383 case 0: 01384 if (c.is_strict_inequality()) 01385 return Poly_Con_Relation::saturates() 01386 && Poly_Con_Relation::is_disjoint(); 01387 else 01388 return Poly_Con_Relation::saturates() 01389 && Poly_Con_Relation::is_included(); 01390 case 1: 01391 if (c.is_equality()) 01392 return Poly_Con_Relation::is_disjoint(); 01393 else 01394 return Poly_Con_Relation::is_included(); 01395 } 01396 } 01397 01398 // Select the cell to be checked for the "<=" part of constraint. 01399 typename OR_Matrix<N>::const_row_iterator i_iter = matrix.row_begin() + i; 01400 typename OR_Matrix<N>::const_row_reference_type m_i = *i_iter; 01401 const N& m_i_j = m_i[j]; 01402 // Set `coeff' to the absolute value of itself. 01403 if (coeff < 0) 01404 neg_assign(coeff); 01405 01406 // Select the cell to be checked for the ">=" part of constraint. 01407 // Select the right row of the cell. 01408 if (i%2 == 0) 01409 ++i_iter; 01410 else 01411 --i_iter; 01412 typename OR_Matrix<N>::const_row_reference_type m_ci = *i_iter; 01413 const N& m_ci_cj = m_ci[coherent_index(j)]; 01414 TEMP_INTEGER(numer); 01415 TEMP_INTEGER(denom); 01416 // The following variables of mpq_class type are used to be precise 01417 // when the octagon is defined by integer constraints. 01418 DIRTY_TEMP0(mpq_class, q_x); 01419 DIRTY_TEMP0(mpq_class, q_y); 01420 DIRTY_TEMP0(mpq_class, d); 01421 DIRTY_TEMP0(mpq_class, d1); 01422 DIRTY_TEMP0(mpq_class, c_den); 01423 DIRTY_TEMP0(mpq_class, q_den); 01424 assign_r(c_den, coeff, ROUND_NOT_NEEDED); 01425 assign_r(d, c_term, ROUND_NOT_NEEDED); 01426 neg_assign_r(d1, d, ROUND_NOT_NEEDED); 01427 div_assign_r(d, d, c_den, ROUND_NOT_NEEDED); 01428 div_assign_r(d1, d1, c_den, ROUND_NOT_NEEDED); 01429 01430 if (is_plus_infinity(m_i_j)) { 01431 if (!is_plus_infinity(m_ci_cj)) { 01432 // `*this' is in the following form: 01433 // `-m_ci_cj <= v - u'. 01434 // In this case `*this' is disjoint from `c' if 01435 // `-m_ci_cj > d' (`-m_ci_cj >= d' if c is a strict inequality), 01436 // i.e. if `m_ci_cj < d1' (`m_ci_cj <= d1' if c is a strict inequality). 01437 numer_denom(m_ci_cj, numer, denom); 01438 assign_r(q_den, denom, ROUND_NOT_NEEDED); 01439 assign_r(q_y, numer, ROUND_NOT_NEEDED); 01440 div_assign_r(q_y, q_y, q_den, ROUND_NOT_NEEDED); 01441 if (q_y < d1) 01442 return Poly_Con_Relation::is_disjoint(); 01443 if (q_y == d1 && c.is_strict_inequality()) 01444 return Poly_Con_Relation::is_disjoint(); 01445 } 01446 01447 // In all other cases `*this' intersects `c'. 01448 return Poly_Con_Relation::strictly_intersects(); 01449 } 01450 01451 // Here `m_i_j' is not plus-infinity. 01452 numer_denom(m_i_j, numer, denom); 01453 assign_r(q_den, denom, ROUND_NOT_NEEDED); 01454 assign_r(q_x, numer, ROUND_NOT_NEEDED); 01455 div_assign_r(q_x, q_x, q_den, ROUND_NOT_NEEDED); 01456 01457 if (!is_plus_infinity(m_ci_cj)) { 01458 numer_denom(m_ci_cj, numer, denom); 01459 assign_r(q_den, denom, ROUND_NOT_NEEDED); 01460 assign_r(q_y, numer, ROUND_NOT_NEEDED); 01461 div_assign_r(q_y, q_y, q_den, ROUND_NOT_NEEDED); 01462 if (q_x == d && q_y == d1) { 01463 if (c.is_strict_inequality()) 01464 return Poly_Con_Relation::saturates() 01465 && Poly_Con_Relation::is_disjoint(); 01466 else 01467 return Poly_Con_Relation::saturates() 01468 && Poly_Con_Relation::is_included(); 01469 } 01470 // `*this' is disjoint from `c' when 01471 // `m_ci_cj < d1' (`m_ci_cj <= d1' if `c' is a strict inequality). 01472 if (q_y < d1) 01473 return Poly_Con_Relation::is_disjoint(); 01474 if (q_y == d1 && c.is_strict_inequality()) 01475 return Poly_Con_Relation::is_disjoint(); 01476 } 01477 01478 // Here `m_ci_cj' can be also plus-infinity. 01479 // If `c' is an equality, `*this' is disjoint from `c' if 01480 // `m_i_j < d'. 01481 if (d > q_x) { 01482 if (c.is_equality()) 01483 return Poly_Con_Relation::is_disjoint(); 01484 else 01485 return Poly_Con_Relation::is_included(); 01486 } 01487 01488 if (d == q_x && c.is_nonstrict_inequality()) 01489 return Poly_Con_Relation::is_included(); 01490 01491 // In all other cases `*this' intersects `c'. 01492 return Poly_Con_Relation::strictly_intersects(); 01493 }
| Poly_Con_Relation Parma_Polyhedra_Library::Octagonal_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 cg are dimension-incompatible. |
Definition at line 1189 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Congruence::coefficient(), Parma_Polyhedra_Library::Congruence::inhomogeneous_term(), Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), Parma_Polyhedra_Library::Checked::le(), Parma_Polyhedra_Library::lower(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimize(), Parma_Polyhedra_Library::Congruence::modulus(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with(), Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Congruence::space_dimension(), Parma_Polyhedra_Library::Poly_Con_Relation::strictly_intersects(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), TEMP_INTEGER, and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
01189 { 01190 dimension_type cg_space_dim = cg.space_dimension(); 01191 01192 // Dimension-compatibility check. 01193 if (cg_space_dim > space_dim) { 01194 throw_dimension_incompatible("relation_with(cg)", cg); 01195 } 01196 01197 // If the congruence is an equality, 01198 // find the relation with the equivalent equality constraint. 01199 if (cg.is_equality()) { 01200 Constraint c(cg); 01201 return relation_with(c); 01202 } 01203 01204 strong_closure_assign(); 01205 01206 if (marked_empty()) 01207 return Poly_Con_Relation::saturates() 01208 && Poly_Con_Relation::is_included() 01209 && Poly_Con_Relation::is_disjoint(); 01210 01211 if (space_dim == 0) { 01212 if (cg.is_inconsistent()) 01213 return Poly_Con_Relation::is_disjoint(); 01214 else if (cg.inhomogeneous_term() % cg.modulus() == 0) 01215 return Poly_Con_Relation::saturates() 01216 && Poly_Con_Relation::is_included(); 01217 } 01218 01219 DIRTY_TEMP(Coefficient, min_num); 01220 DIRTY_TEMP(Coefficient, min_den); 01221 bool min_included; 01222 TEMP_INTEGER(mod); 01223 mod = cg.modulus(); 01224 Linear_Expression le; 01225 for (dimension_type i = cg_space_dim; i-- > 0; ) 01226 le += cg.coefficient(Variable(i)) * Variable(i); 01227 bool bounded_below = minimize(le, min_num, min_den, min_included); 01228 01229 if (!bounded_below) 01230 return Poly_Con_Relation::strictly_intersects(); 01231 01232 TEMP_INTEGER(v); 01233 TEMP_INTEGER(lower_num); 01234 TEMP_INTEGER(lower_den); 01235 TEMP_INTEGER(lower); 01236 assign_r(lower_num, min_num, ROUND_NOT_NEEDED); 01237 assign_r(lower_den, min_den, ROUND_NOT_NEEDED); 01238 neg_assign(v, cg.inhomogeneous_term()); 01239 lower = lower_num / lower_den; 01240 v += ((lower / mod) * mod); 01241 if (v * lower_den < lower_num) 01242 v += mod; 01243 const Constraint& c(le == v); 01244 return relation_with(c); 01245 }
| Poly_Gen_Relation Parma_Polyhedra_Library::Octagonal_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 1497 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::add_mul_assign(), Parma_Polyhedra_Library::Generator::coefficient(), 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::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Poly_Gen_Relation::nothing(), Parma_Polyhedra_Library::numer_denom(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Generator::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Poly_Gen_Relation::subsumes(), TEMP_INTEGER, and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
01497 { 01498 const dimension_type g_space_dim = g.space_dimension(); 01499 01500 // Dimension-compatibility check. 01501 if (space_dim < g_space_dim) 01502 throw_dimension_incompatible("relation_with(g)", g); 01503 01504 // The closure needs to make explicit the implicit constraints and if the 01505 // octagon is empty. 01506 strong_closure_assign(); 01507 01508 // The empty octagon cannot subsume a generator. 01509 if (marked_empty()) 01510 return Poly_Gen_Relation::nothing(); 01511 01512 // A universe octagon in a zero-dimensional space subsumes 01513 // all the generators of a zero-dimensional space. 01514 if (space_dim == 0) 01515 return Poly_Gen_Relation::subsumes(); 01516 01517 const bool is_line = g.is_line(); 01518 const bool is_line_or_ray = g.is_line_or_ray(); 01519 01520 // The relation between the octagon and the given generator is obtained 01521 // checking if the generator satisfies all the constraints in the octagon. 01522 // To check if the generator satisfies all the constraints it's enough 01523 // studying the sign of the scalar product between the generator and 01524 // all the constraints in the octagon. 01525 01526 typedef typename OR_Matrix<N>::const_row_iterator Row_Iterator; 01527 typedef typename OR_Matrix<N>::const_row_reference_type Row_Reference; 01528 01529 const Row_Iterator m_begin = matrix.row_begin(); 01530 const Row_Iterator m_end = matrix.row_end(); 01531 01532 TEMP_INTEGER(num); 01533 TEMP_INTEGER(den); 01534 TEMP_INTEGER(product); 01535 01536 // We find in `*this' all the constraints. 01537 for (Row_Iterator i_iter = m_begin; i_iter != m_end; i_iter += 2) { 01538 dimension_type i = i_iter.index(); 01539 Row_Reference m_i = *i_iter; 01540 Row_Reference m_ii = *(i_iter+1); 01541 const N& m_i_ii = m_i[i+1]; 01542 const N& m_ii_i = m_ii[i]; 01543 // We have the unary constraints. 01544 const Variable x(i/2); 01545 const Coefficient& g_coeff_x = (x.space_dimension() > g_space_dim) 01546 ? Coefficient(0) : g.coefficient(x); 01547 if (is_additive_inverse(m_i_ii, m_ii_i)) { 01548 // The constraint has form ax = b. 01549 // To satisfy the constraint it's necessary that the scalar product 01550 // is not zero. The scalar product has the form: 01551 // 'den * g_coeff_x - num * g.divisor()'. 01552 numer_denom(m_ii_i, num, den); 01553 den *= 2; 01554 product = den * g_coeff_x; 01555 // Note that if the generator `g' is a line or a ray, 01556 // its divisor is zero. 01557 if (!is_line_or_ray) { 01558 neg_assign(num); 01559 add_mul_assign(product, num, g.divisor()); 01560 } 01561 if (product != 0) 01562 return Poly_Gen_Relation::nothing(); 01563 } 01564 // We have 0, 1 or 2 inequality constraints. 01565 else { 01566 if (!is_plus_infinity(m_i_ii)) { 01567 // The constraint has form -ax <= b. 01568 // If the generator is a line it's necessary to check if 01569 // the scalar product is not zero, if it is positive otherwise. 01570 numer_denom(m_i_ii, num, den); 01571 den *= -2; 01572 product = den * g_coeff_x; 01573 // Note that if the generator `g' is a line or a ray, 01574 // its divisor is zero. 01575 if (!is_line_or_ray) { 01576 neg_assign(num); 01577 add_mul_assign(product, num, g.divisor()); 01578 } 01579 if (is_line && product != 0) 01580 return Poly_Gen_Relation::nothing(); 01581 else 01582 // If the generator is not a line it's necessary to check 01583 // that the scalar product sign is not positive and the scalar 01584 // product has the form: 01585 // '-den * g.coeff_x - num * g.divisor()'. 01586 if (product > 0) 01587 return Poly_Gen_Relation::nothing(); 01588 } 01589 if (!is_plus_infinity(m_ii_i)) { 01590 // The constraint has form ax <= b. 01591 numer_denom(m_ii_i, num, den); 01592 den *= 2; 01593 product = den * g_coeff_x; 01594 // Note that if the generator `g' is a line or a ray, 01595 // its divisor is zero. 01596 if (!is_line_or_ray) { 01597 neg_assign(num); 01598 add_mul_assign(product, num , g.divisor()); 01599 } 01600 if (is_line && product != 0) 01601 return Poly_Gen_Relation::nothing(); 01602 else 01603 // If the generator is not a line it's necessary to check 01604 // that the scalar product sign is not positive and the scalar 01605 // product has the form: 01606 // 'den * g_coeff_x - num * g.divisor()'. 01607 if (product > 0) 01608 return Poly_Gen_Relation::nothing(); 01609 } 01610 } 01611 } 01612 01613 // We have the binary constraints. 01614 for (Row_Iterator i_iter = m_begin ; i_iter != m_end; i_iter += 2) { 01615 dimension_type i = i_iter.index(); 01616 Row_Reference m_i = *i_iter; 01617 Row_Reference m_ii = *(i_iter+1); 01618 for (dimension_type j = 0; j < i; j += 2) { 01619 const N& m_i_j = m_i[j]; 01620 const N& m_ii_jj = m_ii[j+1]; 01621 const N& m_ii_j = m_ii[j]; 01622 const N& m_i_jj = m_i[j+1]; 01623 const Variable x(j/2); 01624 const Variable y(i/2); 01625 const Coefficient& g_coeff_x = (x.space_dimension() > g_space_dim) 01626 ? Coefficient(0) : g.coefficient(x); 01627 const Coefficient& g_coeff_y = (y.space_dimension() > g_space_dim) 01628 ? Coefficient(0) : g.coefficient(y); 01629 01630 // FIXME! Find better names. 01631 const bool is_binary_equality = is_additive_inverse(m_ii_jj, m_i_j); 01632 const bool is_a_binary_equality = is_additive_inverse(m_i_jj, m_ii_j); 01633 if (is_binary_equality) { 01634 // The constraint has form ax - ay = b. 01635 // The scalar product has the form 01636 // 'den * coeff_x - den * coeff_y - num * g.divisor()'. 01637 // To satisfy the constraint it's necessary that the scalar product 01638 // is not zero. 01639 numer_denom(m_i_j, num, den); 01640 product = den * g_coeff_x; 01641 neg_assign(den); 01642 add_mul_assign(product, den, g_coeff_y); 01643 // Note that if the generator `g' is a line or a ray, 01644 // its divisor is zero. 01645 if (!is_line_or_ray) { 01646 neg_assign(num); 01647 add_mul_assign(product, num, g.divisor()); 01648 } 01649 if (product != 0) 01650 return Poly_Gen_Relation::nothing(); 01651 } 01652 else { 01653 if (!is_plus_infinity(m_i_j)) { 01654 // The constraint has form ax - ay <= b. 01655 // The scalar product has the form 01656 // 'den * coeff_x - den * coeff_y - num * g.divisor()'. 01657 // If the generator is not a line it's necessary to check 01658 // that the scalar product sign is not positive. 01659 numer_denom(m_i_j, num, den); 01660 product = den * g_coeff_x; 01661 neg_assign(den); 01662 add_mul_assign(product, den, g_coeff_y); 01663 // Note that if the generator `g' is a line or a ray, 01664 // its divisor is zero. 01665 if (!is_line_or_ray) { 01666 neg_assign(num); 01667 add_mul_assign(product, num, g.divisor()); 01668 } 01669 if (is_line && product != 0) 01670 return Poly_Gen_Relation::nothing(); 01671 else if (product > 0) 01672 return Poly_Gen_Relation::nothing(); 01673 } 01674 if (!is_plus_infinity(m_ii_jj)) { 01675 // The constraint has form -ax + ay <= b. 01676 // The scalar product has the form 01677 // '-den * coeff_x + den * coeff_y - num * g.divisor()'. 01678 // If the generator is not a line it's necessary to check 01679 // that the scalar product sign is not positive. 01680 numer_denom(m_ii_jj, num, den); 01681 product = den * g_coeff_y; 01682 neg_assign(den); 01683 add_mul_assign(product, den, g_coeff_x); 01684 // Note that if the generator `g' is a line or a ray, 01685 // its divisor is zero. 01686 if (!is_line_or_ray) { 01687 neg_assign(num); 01688 add_mul_assign(product, num, g.divisor()); 01689 } 01690 if (is_line && product != 0) 01691 return Poly_Gen_Relation::nothing(); 01692 else if (product > 0) 01693 return Poly_Gen_Relation::nothing(); 01694 } 01695 } 01696 01697 if (is_a_binary_equality) { 01698 // The constraint has form ax + ay = b. 01699 // The scalar product has the form 01700 // 'den * coeff_x + den * coeff_y - num * g.divisor()'. 01701 // To satisfy the constraint it's necessary that the scalar product 01702 // is not zero. 01703 numer_denom(m_ii_j, num, den); 01704 product = den * g_coeff_x; 01705 add_mul_assign(product, den, g_coeff_y); 01706 // Note that if the generator `g' is a line or a ray, 01707 // its divisor is zero. 01708 if (!is_line_or_ray) { 01709 neg_assign(num); 01710 add_mul_assign(product, num, g.divisor()); 01711 } 01712 if (product != 0) 01713 return Poly_Gen_Relation::nothing(); 01714 } 01715 else { 01716 if (!is_plus_infinity(m_i_jj)) { 01717 // The constraint has form -ax - ay <= b. 01718 // The scalar product has the form 01719 // '-den * coeff_x - den * coeff_y - num * g.divisor()'. 01720 // If the generator is not a line it's necessary to check 01721 // that the scalar product sign is not positive. 01722 numer_denom(m_i_jj, num, den); 01723 neg_assign(den); 01724 product = den * g_coeff_x; 01725 add_mul_assign(product, den, g_coeff_y); 01726 // Note that if the generator `g' is a line or a ray, 01727 // its divisor is zero. 01728 if (!is_line_or_ray) { 01729 neg_assign(num); 01730 add_mul_assign(product, num, g.divisor()); 01731 } 01732 if (is_line && product != 0) 01733 return Poly_Gen_Relation::nothing(); 01734 else if (product > 0) 01735 return Poly_Gen_Relation::nothing(); 01736 } 01737 if (!is_plus_infinity(m_ii_j)) { 01738 // The constraint has form ax + ay <= b. 01739 // The scalar product has the form 01740 // 'den * coeff_x + den * coeff_y - num * g.divisor()'. 01741 // If the generator is not a line it's necessary to check 01742 // that the scalar product sign is not positive. 01743 numer_denom(m_ii_j, num, den); 01744 product = den * g_coeff_x; 01745 add_mul_assign(product, den, g_coeff_y); 01746 // Note that if the generator `g' is a line or a ray, 01747 // its divisor is zero. 01748 if (!is_line_or_ray) { 01749 neg_assign(num); 01750 add_mul_assign(product, num, g.divisor()); 01751 } 01752 if (is_line && product != 0) 01753 return Poly_Gen_Relation::nothing(); 01754 else if (product > 0) 01755 return Poly_Gen_Relation::nothing(); 01756 } 01757 } 01758 } 01759 } 01760 // If this point is reached the constraint 'g' satisfies 01761 // all the constraints in the octagon. 01762 return Poly_Gen_Relation::subsumes(); 01763 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty | ( | ) | const [inline] |
Returns true if and only if *this is an empty OS.
Definition at line 246 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constrains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage(), and Parma_Polyhedra_Library::Pointset_Powerset< PS >::Pointset_Powerset().
00246 { 00247 strong_closure_assign(); 00248 return marked_empty(); 00249 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::is_universe | ( | ) | const [inline] |
Returns true if and only if *this is a universe OS.
Definition at line 797 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min().
00797 { 00798 // An empty octagon isn't, of course, universe. 00799 if (marked_empty()) 00800 return false; 00801 00802 // If the octagon is non-empty and zero-dimensional, 00803 // then it is necessarily the universe octagon. 00804 if (space_dim == 0) 00805 return true; 00806 00807 // An universe octagon can only contains trivial constraints. 00808 for (typename OR_Matrix<N>::const_element_iterator 00809 i = matrix.element_begin(), matrix_element_end = matrix.element_end(); 00810 i != matrix_element_end; 00811 ++i) 00812 if (!is_plus_infinity(*i)) 00813 return false; 00814 00815 return true; 00816 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::is_discrete | ( | ) | const [inline] |
Returns true if and only if *this is discrete.
Definition at line 240 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_dimension().
00240 { 00241 return affine_dimension() == 0; 00242 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::is_bounded | ( | ) | const [inline] |
Returns true if and only if *this is a bounded OS.
Definition at line 820 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().
00820 { 00821 strong_closure_assign(); 00822 // A zero-dimensional or empty octagon is bounded. 00823 if (marked_empty() || space_dim == 0) 00824 return true; 00825 00826 // A bounded octagon never can contains trivial constraints. 00827 for (typename OR_Matrix<N>::const_row_iterator i = matrix.row_begin(), 00828 matrix_row_end = matrix.row_end(); i != matrix_row_end; ++i) { 00829 typename OR_Matrix<N>::const_row_reference_type x_i = *i; 00830 const dimension_type i_index = i.index(); 00831 for (dimension_type j = i.row_size(); j-- > 0; ) 00832 if (i_index != j) 00833 if (is_plus_infinity(x_i[j])) 00834 return false; 00835 } 00836 00837 return true; 00838 }
| bool Parma_Polyhedra_Library::Octagonal_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 299 of file Octagonal_Shape.inlines.hh.
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point | ( | ) | const [inline] |
Returns true if and only if *this contains (at least) an integer point.
Definition at line 842 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_coherence_would_make_empty().
00842 { 00843 // Force strong closure. 00844 if (is_empty()) 00845 return false; 00846 const dimension_type space_dim = space_dimension(); 00847 if (space_dim == 0) 00848 return true; 00849 00850 // A strongly closed and consistent Octagonal_Shape defined by 00851 // integer constraints can only be empty due to tight coeherence. 00852 if (std::numeric_limits<T>::is_integer) 00853 return !tight_coherence_would_make_empty(); 00854 00855 // Build an integer Octagonal_Shape oct_z with bounds at least as 00856 // tight as those in *this and then recheck for emptiness, also 00857 // exploiting tight-coherence. 00858 Octagonal_Shape<mpz_class> oct_z(space_dim); 00859 oct_z.reset_strongly_closed(); 00860 00861 typedef Octagonal_Shape<mpz_class>::N Z; 00862 DIRTY_TEMP(N, tmp); 00863 bool all_integers = true; 00864 typename OR_Matrix<N>::const_element_iterator x_i = matrix.element_begin(); 00865 for (typename OR_Matrix<Z>::element_iterator 00866 z_i = oct_z.matrix.element_begin(), 00867 z_end = oct_z.matrix.element_end(); z_i != z_end; ++z_i, ++x_i) { 00868 const N& d = *x_i; 00869 if (is_plus_infinity(d)) 00870 continue; 00871 if (is_integer(d)) 00872 assign_r(*z_i, d, ROUND_NOT_NEEDED); 00873 else { 00874 all_integers = false; 00875 Z& d_z = *z_i; 00876 // Copy d into d_z, but rounding downwards. 00877 neg_assign_r(tmp, d, ROUND_NOT_NEEDED); 00878 assign_r(d_z, tmp, ROUND_UP); 00879 neg_assign_r(d_z, d_z, ROUND_NOT_NEEDED); 00880 } 00881 } 00882 // Restore strong closure. 00883 if (all_integers) 00884 // oct_z unchanged, so it is still strongly closed. 00885 oct_z.set_strongly_closed(); 00886 else { 00887 // oct_z changed: recompute strong closure. 00888 oct_z.strong_closure_assign(); 00889 if (oct_z.marked_empty()) 00890 return false; 00891 } 00892 return !oct_z.tight_coherence_would_make_empty(); 00893 }
| bool Parma_Polyhedra_Library::Octagonal_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 897 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::OR_Matrix< T >::row_size(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
00897 { 00898 // `var' should be one of the dimensions of the polyhedron. 00899 const dimension_type var_space_dim = var.space_dimension(); 00900 if (space_dimension() < var_space_dim) 00901 throw_dimension_incompatible("constrains(v)", "v", var); 00902 00903 // A polyhedron known to be empty constrains all variables. 00904 // (Note: do not force emptiness check _yet_) 00905 if (marked_empty()) 00906 return true; 00907 00908 // Check whether `var' is syntactically constrained. 00909 const dimension_type n_v = 2*(var_space_dim - 1); 00910 typename OR_Matrix<N>::const_row_iterator m_iter = matrix.row_begin() + n_v; 00911 typename OR_Matrix<N>::const_row_reference_type r_v = *m_iter; 00912 typename OR_Matrix<N>::const_row_reference_type r_cv = *(++m_iter); 00913 for (dimension_type h = m_iter.row_size(); h-- > 0; ) { 00914 if (!is_plus_infinity(r_v[h]) || !is_plus_infinity(r_cv[h])) 00915 return true; 00916 } 00917 ++m_iter; 00918 for (typename OR_Matrix<N>::const_row_iterator m_end = matrix.row_end(); 00919 m_iter != m_end; ++m_iter) { 00920 typename OR_Matrix<N>::const_row_reference_type r = *m_iter; 00921 if (!is_plus_infinity(r[n_v]) || !is_plus_infinity(r[n_v+1])) 00922 return true; 00923 } 00924 00925 // `var' is not syntactically constrained: 00926 // now force an emptiness check. 00927 return is_empty(); 00928 }
| bool Parma_Polyhedra_Library::Octagonal_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 253 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds().
00253 { 00254 return bounds(expr, true); 00255 }
| bool Parma_Polyhedra_Library::Octagonal_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 259 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds().
00259 { 00260 return bounds(expr, false); 00261 }
| bool Parma_Polyhedra_Library::Octagonal_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. |
*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 265 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with().
00267 { 00268 return max_min(expr, true, sup_n, sup_d, maximum); 00269 }
| bool Parma_Polyhedra_Library::Octagonal_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. |
*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 273 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min().
00276 { 00277 return max_min(expr, true, sup_n, sup_d, maximum, g); 00278 }
| bool Parma_Polyhedra_Library::Octagonal_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. |
*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 282 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with().
00284 { 00285 return max_min(expr, false, inf_n, inf_d, minimum); 00286 }
| bool Parma_Polyhedra_Library::Octagonal_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. |
*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 290 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min().
00293 { 00294 return max_min(expr, false, inf_n, inf_d, minimum, g); 00295 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::OK | ( | ) | const [inline] |
Checks if all the invariants are satisfied.
Definition at line 6209 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::is_minus_infinity(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_strong_coherent(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::Status::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::status, and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::ascii_load(), Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::time_elapse_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::unconstrain(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign().
06209 { 06210 // Check whether the matrix is well-formed. 06211 if (!matrix.OK()) 06212 return false; 06213 06214 // Check whether the status information is legal. 06215 if (!status.OK()) 06216 return false; 06217 06218 // All empty octagons are OK. 06219 if (marked_empty()) 06220 return true; 06221 06222 // 0-dim universe octagon is OK. 06223 if (space_dim == 0) 06224 return true; 06225 06226 // MINUS_INFINITY cannot occur at all. 06227 for (typename OR_Matrix<N>::const_row_iterator i = matrix.row_begin(), 06228 matrix_row_end = matrix.row_end(); i != matrix_row_end; ++i) { 06229 typename OR_Matrix<N>::const_row_reference_type x_i = *i; 06230 for (dimension_type j = i.row_size(); j-- > 0; ) 06231 if (is_minus_infinity(x_i[j])) { 06232 #ifndef NDEBUG 06233 using namespace Parma_Polyhedra_Library::IO_Operators; 06234 std::cerr << "Octagonal_Shape::" 06235 << "matrix[" << i.index() << "][" << j << "] = " 06236 << x_i[j] << "!" 06237 << std::endl; 06238 #endif 06239 return false; 06240 } 06241 } 06242 06243 // On the main diagonal only PLUS_INFINITY can occur. 06244 for (typename OR_Matrix<N>::const_row_iterator i = matrix.row_begin(), 06245 m_end = matrix.row_end(); i != m_end; ++i) { 06246 typename OR_Matrix<N>::const_row_reference_type r = *i; 06247 const N& m_i_i = r[i.index()]; 06248 if (!is_plus_infinity(m_i_i)) { 06249 #ifndef NDEBUG 06250 const dimension_type j = i.index(); 06251 using namespace Parma_Polyhedra_Library::IO_Operators; 06252 std::cerr << "Octagonal_Shape::matrix[" << j << "][" << j << "] = " 06253 << m_i_i << "! (+inf was expected.)\n"; 06254 #endif 06255 return false; 06256 } 06257 } 06258 06259 // The following tests might result in false alarms when using floating 06260 // point coefficients: they are only meaningful if the coefficient type 06261 // base is exact (since otherwise strong closure is approximated). 06262 if (std::numeric_limits<coefficient_type_base>::is_exact) { 06263 06264 // Check whether the closure information is legal. 06265 if (marked_strongly_closed()) { 06266 Octagonal_Shape x = *this; 06267 x.reset_strongly_closed(); 06268 x.strong_closure_assign(); 06269 if (x.matrix != matrix) { 06270 #ifndef NDEBUG 06271 std::cerr << "Octagonal_Shape is marked as strongly closed " 06272 << "but it is not!\n"; 06273 #endif 06274 return false; 06275 } 06276 } 06277 06278 // A closed octagon must be strong-coherent. 06279 if (marked_strongly_closed()) 06280 if (!is_strong_coherent()) { 06281 #ifndef NDEBUG 06282 std::cerr << "Octagonal_Shape is not strong-coherent!\n"; 06283 #endif 06284 return false; 06285 } 06286 } 06287 06288 // All checks passed. 06289 return true; 06290 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint | ( | const Constraint & | c | ) | [inline] |
Adds a copy of constraint c to the system of constraints defining *this.
| c | The constraint to be added. If it is not an octagonal constraint, it will be simply ignored. |
| std::invalid_argument | Thrown if *this and constraint c are dimension-incompatible, or c is a strict inequality. |
Definition at line 370 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::Octagonal_Shape< T >::extract_octagonal_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::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), TEMP_INTEGER, Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruence(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraints(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign().
00370 { 00371 const dimension_type c_space_dim = c.space_dimension(); 00372 // Dimension-compatibility check. 00373 if (c_space_dim > space_dim) 00374 throw_dimension_incompatible("add_constraint(c)", c); 00375 00376 // Get rid of strict inequalities. 00377 if (c.is_strict_inequality()) { 00378 if (c.is_inconsistent()) { 00379 set_empty(); 00380 return; 00381 } 00382 if (c.is_tautological()) 00383 return; 00384 // Nontrivial strict inequalities are not allowed. 00385 throw_generic("add_constraint(c)", "strict inequalities are not allowed"); 00386 } 00387 00388 dimension_type num_vars = 0; 00389 dimension_type i = 0; 00390 dimension_type j = 0; 00391 TEMP_INTEGER(coeff); 00392 TEMP_INTEGER(term); 00393 // Constraints that are not octagonal differences are not allowed. 00394 if (!extract_octagonal_difference(c, c_space_dim, num_vars, 00395 i, j, coeff, term)) 00396 throw_generic("add_constraint(c)", 00397 "c is not an octagonal constraint"); 00398 00399 if (num_vars == 0) { 00400 // Dealing with a trivial constraint (not a strict inequality). 00401 if (c.inhomogeneous_term() < 0 00402 || (c.is_equality() && c.inhomogeneous_term() != 0)) 00403 set_empty(); 00404 return; 00405 } 00406 00407 // Select the cell to be modified for the "<=" part of constraint. 00408 typename OR_Matrix<N>::row_iterator i_iter = matrix.row_begin() + i; 00409 typename OR_Matrix<N>::row_reference_type m_i = *i_iter; 00410 N& m_i_j = m_i[j]; 00411 // Set `coeff' to the absolute value of itself. 00412 if (coeff < 0) 00413 neg_assign(coeff); 00414 00415 bool is_oct_changed = false; 00416 // Compute the bound for `m_i_j', rounding towards plus infinity. 00417 DIRTY_TEMP(N, d); 00418 div_round_up(d, term, coeff); 00419 if (m_i_j > d) { 00420 m_i_j = d; 00421 is_oct_changed = true; 00422 } 00423 00424 if (c.is_equality()) { 00425 // Select the cell to be modified for the ">=" part of constraint. 00426 if (i%2 == 0) 00427 ++i_iter; 00428 else 00429 --i_iter; 00430 00431 typename OR_Matrix<N>::row_reference_type m_ci = *i_iter; 00432 dimension_type cj = coherent_index(j); 00433 N& m_ci_cj = m_ci[cj]; 00434 // Also compute the bound for `m_ci_cj', rounding towards plus infinity. 00435 neg_assign(term); 00436 div_round_up(d, term, coeff); 00437 if (m_ci_cj > d) { 00438 m_ci_cj = d; 00439 is_oct_changed = true; 00440 } 00441 } 00442 00443 // This method does not preserve closure. 00444 if (is_oct_changed && marked_strongly_closed()) 00445 reset_strongly_closed(); 00446 assert(OK()); 00447 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraints | ( | const Constraint_System & | cs | ) | [inline] |
Adds the constraints in cs to the system of constraints defining *this.
| cs | The constraints that will be added. Constraints that are not octagonal constraints will be simply ignored. |
| std::invalid_argument | Thrown if *this and cs are dimension-incompatible, or if cs contains a strict inequality. |
Definition at line 412 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Constraint_System::begin(), and Parma_Polyhedra_Library::Constraint_System::end().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_recycled_constraints(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape().
00412 { 00413 for (Constraint_System::const_iterator i = cs.begin(), 00414 i_end = cs.end(); i != i_end; ++i) 00415 add_constraint(*i); 00416 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::add_recycled_constraints | ( | Constraint_System & | cs | ) | [inline] |
Adds the constraints in cs to the system of constraints of *this (without minimizing the result).
| 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 topology-incompatible or dimension-incompatible. |
cs upon successful or exceptional return is that it can be safely destroyed. Definition at line 420 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraints().
00420 { 00421 add_constraints(cs); 00422 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruence | ( | const Congruence & | cg | ) | [inline] |
Adds a copy of congruence cg to the system of congruences of this (without minimizing the result).
| std::invalid_argument | Thrown if *this and congruence cg are dimension-incompatible. |
Definition at line 451 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_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::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Congruence::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruences().
00451 { 00452 const dimension_type cg_space_dim = cg.space_dimension(); 00453 // Dimension-compatibility check: 00454 // the dimension of `cg' can not be greater than space_dim. 00455 if (space_dimension() < cg_space_dim) 00456 throw_dimension_incompatible("add_congruence(cg)", cg); 00457 00458 // Handle the case of proper congruences first. 00459 if (cg.is_proper_congruence()) { 00460 if (cg.is_tautological()) 00461 return; 00462 if (cg.is_inconsistent()) { 00463 set_empty(); 00464 return; 00465 } 00466 // Non-trivial and proper congruences are not allowed. 00467 throw_generic("add_congruence(cg)", 00468 "cg is a non-trivial, proper congruence"); 00469 } 00470 00471 assert(cg.is_equality()); 00472 Constraint c(cg); 00473 add_constraint(c); 00474 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruences | ( | const Congruence_System & | cgs | ) | [inline] |
Adds to *this constraints equivalent to the congruences in cgs (without minimizing the result).
| cgs | Contains the congruences that will be added to the system of constraints of *this. |
| std::invalid_argument | Thrown if *this and cgs are topology-incompatible or dimension-incompatible. |
Definition at line 432 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruence(), Parma_Polyhedra_Library::Congruence_System::begin(), and Parma_Polyhedra_Library::Congruence_System::end().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_recycled_congruences(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape().
00432 { 00433 for (Congruence_System::const_iterator i = cgs.begin(), 00434 cgs_end = cgs.end(); i != cgs_end; ++i) 00435 add_congruence(*i); 00436 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::add_recycled_congruences | ( | Congruence_System & | cgs | ) | [inline] |
Adds the congruences in cs to the system of congruences of *this (without minimizing the result).
| cgs | The congruence system to be added to *this. The congruences in cgs may be recycled. |
| std::invalid_argument | Thrown if *this and cs are dimension-incompatible. |
cgs upon successful or exceptional return is that it can be safely destroyed. Definition at line 426 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruences().
00426 { 00427 add_congruences(cgs); 00428 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraint | ( | const Constraint & | c | ) | [inline] |
Uses a copy of constraint c to refine the system of octagonal constraints defining *this.
| c | The constraint. If it is not a octagonal constraint, it will be ignored. |
| std::invalid_argument | Thrown if *this and constraint c are dimension-incompatible. |
Definition at line 440 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Constraint::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
00440 { 00441 // Dimension-compatibility check. 00442 if (c.space_dimension() > space_dimension()) 00443 throw_dimension_incompatible("refine_with_constraint(c)", c); 00444 00445 if (!marked_empty()) 00446 refine_no_check(c); 00447 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruence | ( | const Congruence & | cg | ) | [inline] |
Uses a copy of congruence cg to refine the system of octagonal constraints of *this.
| cg | The congruence. If it is not a octagonal equality, it will be ignored. |
| std::invalid_argument | Thrown if *this and congruence cg are dimension-incompatible. |
Definition at line 464 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Congruence::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
00464 { 00465 const dimension_type cg_space_dim = cg.space_dimension(); 00466 // Dimension-compatibility check. 00467 if (cg_space_dim > space_dimension()) 00468 throw_dimension_incompatible("refine_with_congruence(cg)", cg); 00469 00470 if (!marked_empty()) 00471 refine_no_check(cg); 00472 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraints | ( | const Constraint_System & | cs | ) | [inline] |
Uses a copy of the constraints in cs to refine the system of octagonal constraints defining *this.
| cs | The constraint system to be used. Constraints that are not octagonal are ignored. |
| std::invalid_argument | Thrown if *this and cs are dimension-incompatible. |
Definition at line 451 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape().
00451 { 00452 // Dimension-compatibility check. 00453 if (cs.space_dimension() > space_dimension()) 00454 throw_generic("refine_with_constraints(cs)", 00455 "cs and *this are space-dimension incompatible"); 00456 00457 for (Constraint_System::const_iterator i = cs.begin(), 00458 cs_end = cs.end(); !marked_empty() && i != cs_end; ++i) 00459 refine_no_check(*i); 00460 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruences | ( | const Congruence_System & | cgs | ) | [inline] |
Uses a copy of the congruences in cgs to refine the system of octagonal constraints defining *this.
| cgs | The congruence system to be used. Congruences that are not octagonal equalities are ignored. |
| std::invalid_argument | Thrown if *this and cgs are dimension-incompatible. |
Definition at line 476 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Congruence_System::begin(), Parma_Polyhedra_Library::Congruence_System::end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Congruence_System::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape().
00476 { 00477 // Dimension-compatibility check. 00478 if (cgs.space_dimension() > space_dimension()) 00479 throw_generic("refine_with_congruences(cgs)", 00480 "cgs and *this are space-dimension incompatible"); 00481 00482 for (Congruence_System::const_iterator i = cgs.begin(), 00483 cgs_end = cgs.end(); !marked_empty() && i != cgs_end; ++i) 00484 refine_no_check(*i); 00485 }
| void Parma_Polyhedra_Library::Octagonal_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 3341 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_all_octagonal_constraints(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
03341 { 03342 // Dimension-compatibility check. 03343 const dimension_type dim = var.id(); 03344 if (space_dimension() < dim) 03345 throw_dimension_incompatible("unconstrain(var)", dim); 03346 03347 // Enforce strong closure for precision. 03348 strong_closure_assign(); 03349 03350 // If the shape is empty, this is a no-op. 03351 if (marked_empty()) 03352 return; 03353 03354 forget_all_octagonal_constraints(dim); 03355 // Strong closure is preserved. 03356 assert(OK()); 03357 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::unconstrain | ( | const Variables_Set & | to_be_unconstrained | ) | [inline] |
Computes the cylindrification of *this with respect to the set of space dimensions to_be_unconstrained, assigning the result to *this.
| to_be_unconstrained | 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 to_be_removed. |
Definition at line 3361 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_all_octagonal_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
03361 { 03362 // The cylindrification wrt no dimensions is a no-op. 03363 // This case captures the only legal cylindrification in a 0-dim space. 03364 if (to_be_unconstrained.empty()) 03365 return; 03366 03367 // Dimension-compatibility check. 03368 const dimension_type min_space_dim = to_be_unconstrained.space_dimension(); 03369 if (space_dimension() < min_space_dim) 03370 throw_dimension_incompatible("unconstrain(vs)", min_space_dim); 03371 03372 // Enforce strong closure for precision. 03373 strong_closure_assign(); 03374 03375 // If the shape is empty, this is a no-op. 03376 if (marked_empty()) 03377 return; 03378 03379 for (Variables_Set::const_iterator tbu = to_be_unconstrained.begin(), 03380 tbu_end = to_be_unconstrained.end(); tbu != tbu_end; ++tbu) 03381 forget_all_octagonal_constraints(*tbu); 03382 // Strong closure is preserved. 03383 assert(OK()); 03384 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign | ( | const Octagonal_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 2654 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_BHMZ05_extrapolation_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_CC76_extrapolation_assign().
02654 { 02655 // Dimension-compatibility check. 02656 if (space_dim != y.space_dim) 02657 throw_dimension_incompatible("intersection_assign(y)", y); 02658 02659 // If one of the two octagons is empty, the intersection is empty. 02660 if (marked_empty()) 02661 return; 02662 if (y.marked_empty()) { 02663 set_empty(); 02664 return; 02665 } 02666 // If both octagons are zero-dimensional,then at this point 02667 // they are necessarily non-empty, 02668 // so that their intersection is non-empty too. 02669 if (space_dim == 0) 02670 return; 02671 02672 // To intersect two octagons we compare the constraints 02673 // and we choose the less values. 02674 bool changed = false; 02675 02676 typename OR_Matrix<N>::const_element_iterator j = y.matrix.element_begin(); 02677 for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(), 02678 matrix_element_end = matrix.element_end(); 02679 i != matrix_element_end; 02680 ++i, ++j) { 02681 N& elem = *i; 02682 const N& y_elem = *j; 02683 if (y_elem < elem) { 02684 elem = y_elem; 02685 changed = true; 02686 } 02687 } 02688 02689 // This method not preserve the closure. 02690 if (changed && marked_strongly_closed()) 02691 reset_strongly_closed(); 02692 assert(OK()); 02693 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign | ( | const Octagonal_Shape< T > & | y | ) | [inline] |
Assigns to *this the smallest OS that contains the convex union of *this and y.
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 2341 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::max_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign().
02341 { 02342 // Dimension-compatibility check. 02343 if (space_dim != y.space_dim) 02344 throw_dimension_incompatible("upper_bound_assign(y)", y); 02345 02346 // The hull of an octagon `x' with an empty octagon is `x'. 02347 y.strong_closure_assign(); 02348 if (y.marked_empty()) 02349 return; 02350 strong_closure_assign(); 02351 if (marked_empty()) { 02352 *this = y; 02353 return; 02354 } 02355 02356 // The oct-hull is obtained by computing maxima. 02357 typename OR_Matrix<N>::const_element_iterator j = y.matrix.element_begin(); 02358 for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(), 02359 matrix_element_end = matrix.element_end(); 02360 i != matrix_element_end; ++i, ++j) 02361 max_assign(*i, *j); 02362 02363 // The result is still closed. 02364 assert(OK()); 02365 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign_if_exact | ( | const Octagonal_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 591 of file Octagonal_Shape.inlines.hh.
00591 { 00592 // TODO: this must be properly implemented. 00593 used(y); 00594 return false; 00595 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign | ( | const Octagonal_Shape< T > & | y | ) | [inline] |
Assigns to *this the smallest octagon containing the set difference of *this and y.
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 2369 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Poly_Con_Relation::implies(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign().
02369 { 02370 // Dimension-compatibility check. 02371 if (space_dim != y.space_dim) 02372 throw_dimension_incompatible("difference_assign(y)", y); 02373 02374 Octagonal_Shape& x = *this; 02375 02376 // Being lazy here is only harmful. 02377 // We close. 02378 x.strong_closure_assign(); 02379 // The difference of an empty octagon and of an octagon `p' is empty. 02380 if (x.marked_empty()) 02381 return; 02382 // The difference of a octagon `p' and an empty octagon is `p'. 02383 if (y.marked_empty()) 02384 return; 02385 02386 // If both octagons are zero-dimensional, 02387 // then at this point they are necessarily universe octagons, 02388 // so that their difference is empty. 02389 if (x.space_dim == 0) { 02390 x.set_empty(); 02391 return; 02392 } 02393 02394 // TODO: This is just an executable specification. 02395 // Have to find a more efficient method. 02396 if (y.contains(x)) { 02397 x.set_empty(); 02398 return; 02399 } 02400 02401 Octagonal_Shape new_oct(space_dim, EMPTY); 02402 // We take a constraint of the octagon y at the time and we 02403 // consider its complementary. Then we intersect the union 02404 // of these complementaries with the octagon x. 02405 const Constraint_System& y_cs = y.constraints(); 02406 for (Constraint_System::const_iterator i = y_cs.begin(), 02407 y_cs_end = y_cs.end(); i != y_cs_end; ++i) { 02408 const Constraint& c = *i; 02409 // If the octagon `x' is included the octagon defined by `c', 02410 // then `c' _must_ be skipped, as adding its complement to `x' 02411 // would result in the empty octagon, and as we would obtain 02412 // a result that is less precise than the difference. 02413 if (x.relation_with(c).implies(Poly_Con_Relation::is_included())) 02414 continue; 02415 Octagonal_Shape z = x; 02416 const Linear_Expression e = Linear_Expression(c); 02417 z.add_constraint(e <= 0); 02418 if (!z.is_empty()) 02419 new_oct.upper_bound_assign(z); 02420 if (c.is_equality()) { 02421 z = x; 02422 z.add_constraint(e >= 0); 02423 if (!z.is_empty()) 02424 new_oct.upper_bound_assign(z); 02425 } 02426 } 02427 *this = new_oct; 02428 assert(OK()); 02429 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::simplify_using_context_assign | ( | const Octagonal_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 2434 of file Octagonal_Shape.templates.hh.
| void Parma_Polyhedra_Library::Octagonal_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 3942 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Octagonal_Shape< T >::deduce_minus_v_pm_u_bounds(), Parma_Polyhedra_Library::Octagonal_Shape< T >::deduce_v_pm_u_bounds(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_all_octagonal_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_binary_octagonal_constraints(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::swap(), TEMP_INTEGER, Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage().
03945 { 03946 // The denominator cannot be zero. 03947 if (denominator == 0) 03948 throw_generic("affine_image(v, e, d)", "d == 0"); 03949 03950 // Dimension-compatibility checks. 03951 // The dimension of `expr' should not be greater than the dimension 03952 // of `*this'. 03953 const dimension_type expr_space_dim = expr.space_dimension(); 03954 if (space_dim < expr_space_dim) 03955 throw_dimension_incompatible("affine_image(v, e, d)", "e", expr); 03956 03957 // `var' should be one of the dimensions of the octagon. 03958 const dimension_type var_id = var.id(); 03959 if (space_dim < var_id + 1) 03960 throw_dimension_incompatible("affine_image(v, e, d)", var.id()+1); 03961 03962 strong_closure_assign(); 03963 // The image of an empty octagon is empty too. 03964 if (marked_empty()) 03965 return; 03966 03967 // Number of non-zero coefficients in `expr': will be set to 03968 // 0, 1, or 2, the latter value meaning any value greater than 1. 03969 dimension_type t = 0; 03970 // Variable-index of the last non-zero coefficient in `expr', if any. 03971 dimension_type w_id = 0; 03972 03973 // Get information about the number of non-zero coefficients in `expr'. 03974 // The `expr' must not be in two or plus variables. 03975 for (dimension_type i = expr_space_dim; i-- > 0; ) 03976 if (expr.coefficient(Variable(i)) != 0) { 03977 if (t++ == 1) 03978 break; 03979 else 03980 w_id = i; 03981 } 03982 03983 typedef typename OR_Matrix<N>::row_iterator Row_Iterator; 03984 typedef typename OR_Matrix<N>::row_reference_type Row_Reference; 03985 typedef typename OR_Matrix<N>::const_row_iterator Row_iterator; 03986 typedef typename OR_Matrix<N>::const_row_reference_type Row_reference; 03987 03988 const Row_Iterator m_begin = matrix.row_begin(); 03989 const Row_Iterator m_end = matrix.row_end(); 03990 const dimension_type n_var = 2*var_id; 03991 const Coefficient& b = expr.inhomogeneous_term(); 03992 TEMP_INTEGER(minus_den); 03993 neg_assign_r(minus_den, denominator, ROUND_NOT_NEEDED); 03994 03995 // `w' is the variable with index `w_id'. 03996 // Now we know the form of `expr': 03997 // - If t == 0, then expr == b, with `b' a constant; 03998 // - If t == 1, then expr == a*w + b, where `w' can be `v' or another 03999 // variable; in this second case we have to check whether `a' is 04000 // equal to `denominator' or `-denominator', since otherwise we have 04001 // to fall back on the general form; 04002 // - If t == 2, the `expr' is of the general form. 04003 04004 if (t == 0) { 04005 // Case 1: expr == b. 04006 // Remove all constraints on `var'. 04007 forget_all_octagonal_constraints(var_id); 04008 TEMP_INTEGER(two_b); 04009 two_b = 2*b; 04010 // Add the constraint `var == b/denominator'. 04011 add_octagonal_constraint(n_var+1, n_var, two_b, denominator); 04012 add_octagonal_constraint(n_var, n_var+1, two_b, minus_den); 04013 assert(OK()); 04014 return; 04015 } 04016 04017 if (t == 1) { 04018 // The one and only non-zero homogeneous coefficient in `expr'. 04019 const Coefficient& w_coeff = expr.coefficient(Variable(w_id)); 04020 if (w_coeff == denominator || w_coeff == minus_den) { 04021 // Case 2: expr = w_coeff*w + b, with w_coeff = +/- denominator. 04022 if (w_id == var_id) { 04023 // Here `expr' is of the form: +/- denominator * v + b. 04024 if (w_coeff == denominator) { 04025 if (b == 0) 04026 // The transformation is the identity function. 04027 return; 04028 else { 04029 // Translate all the constraints on `var' adding or 04030 // subtracting the value `b/denominator'. 04031 DIRTY_TEMP(N, d); 04032 div_round_up(d, b, denominator); 04033 DIRTY_TEMP(N, minus_d); 04034 div_round_up(minus_d, b, minus_den); 04035 Row_Iterator m_iter = m_begin + n_var; 04036 N& m_v_cv = (*m_iter)[n_var+1]; 04037 ++m_iter; 04038 N& m_cv_v = (*m_iter)[n_var]; 04039 ++m_iter; 04040 // NOTE: delay update of m_v_cv and m_cv_v. 04041 for ( ; m_iter != m_end; ++m_iter) { 04042 Row_Reference m_i = *m_iter; 04043 N& m_i_v = m_i[n_var]; 04044 add_assign_r(m_i_v, m_i_v, d, ROUND_UP); 04045 N& m_i_cv = m_i[n_var+1]; 04046 add_assign_r(m_i_cv, m_i_cv, minus_d, ROUND_UP); 04047 } 04048 // Now update m_v_cv and m_cv_v. 04049 mul2exp_assign_r(d, d, 1, ROUND_IGNORE); 04050 add_assign_r(m_cv_v, m_cv_v, d, ROUND_UP); 04051 mul2exp_assign_r(minus_d, minus_d, 1, ROUND_IGNORE); 04052 add_assign_r(m_v_cv, m_v_cv, minus_d, ROUND_UP); 04053 } 04054 reset_strongly_closed(); 04055 } 04056 04057 else { 04058 // Here `w_coeff == -denominator'. 04059 // Remove the binary constraints on `var'. 04060 forget_binary_octagonal_constraints(var_id); 04061 Row_Iterator m_iter = m_begin + n_var; 04062 N& m_v_cv = (*m_iter)[n_var+1]; 04063 ++m_iter; 04064 N& m_cv_v = (*m_iter)[n_var]; 04065 // Swap the unary constraints on `var'. 04066 std::swap(m_v_cv, m_cv_v); 04067 // Strong closure is not preserved. 04068 reset_strongly_closed(); 04069 if (b != 0) { 04070 // Translate all the constraints on `var' adding or 04071 // subtracting the value `b/denominator'. 04072 DIRTY_TEMP(N, d); 04073 div_round_up(d, b, denominator); 04074 DIRTY_TEMP(N, minus_d); 04075 div_round_up(minus_d, b, minus_den); 04076 ++m_iter; 04077 for ( ; m_iter != m_end; ++m_iter) { 04078 Row_Reference m_i = *m_iter; 04079 N& m_i_v = m_i[n_var]; 04080 add_assign_r(m_i_v, m_i_v, d, ROUND_UP); 04081 N& m_i_cv = m_i[n_var+1]; 04082 add_assign_r(m_i_cv, m_i_cv, minus_d, ROUND_UP); 04083 } 04084 mul2exp_assign_r(d, d, 1, ROUND_IGNORE); 04085 add_assign_r(m_cv_v, m_cv_v, d, ROUND_UP); 04086 mul2exp_assign_r(minus_d, minus_d, 1, ROUND_IGNORE); 04087 add_assign_r(m_v_cv, m_v_cv, minus_d, ROUND_UP); 04088 } 04089 incremental_strong_closure_assign(var); 04090 } 04091 } 04092 04093 else { 04094 // Here `w != var', so that `expr' is of the form 04095 // +/-denominator * w + b. 04096 // Remove all constraints on `var'. 04097 forget_all_octagonal_constraints(var_id); 04098 const dimension_type n_w = 2*w_id; 04099 // Add the new constraint `var - w = b/denominator'. 04100 if (w_coeff == denominator) 04101 if (var_id < w_id) { 04102 add_octagonal_constraint(n_w, n_var, b, denominator); 04103 add_octagonal_constraint(n_w+1, n_var+1, b, minus_den); 04104 } 04105 else { 04106 add_octagonal_constraint(n_var+1, n_w+1, b, denominator); 04107 add_octagonal_constraint(n_var, n_w, b, minus_den); 04108 } 04109 else 04110 // Add the new constraint `var + w = b/denominator'. 04111 if (var_id < w_id) { 04112 add_octagonal_constraint(n_w+1, n_var, b, denominator); 04113 add_octagonal_constraint(n_w, n_var+1, b, minus_den); 04114 } 04115 else { 04116 add_octagonal_constraint(n_var+1, n_w, b, denominator); 04117 add_octagonal_constraint(n_var, n_w+1, b, minus_den); 04118 } 04119 incremental_strong_closure_assign(var); 04120 } 04121 assert(OK()); 04122 return; 04123 } 04124 } 04125 04126 // General case. 04127 // Either t == 2, so that 04128 // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2, 04129 // or t == 1, expr == a*w + b, but a <> +/- denominator. 04130 // We will remove all the constraints on `var' and add back 04131 // constraints providing upper and lower bounds for `var'. 04132 04133 // Compute upper approximations for `expr' and `-expr' 04134 // into `pos_sum' and `neg_sum', respectively, taking into account 04135 // the sign of `denominator'. 04136 // Note: approximating `-expr' from above and then negating the 04137 // result is the same as approximating `expr' from below. 04138 const bool is_sc = (denominator > 0); 04139 TEMP_INTEGER(minus_b); 04140 neg_assign_r(minus_b, b, ROUND_NOT_NEEDED); 04141 04142 const Coefficient& sc_b = is_sc ? b : minus_b; 04143 const Coefficient& minus_sc_b = is_sc ? minus_b : b; 04144 const Coefficient& sc_den = is_sc ? denominator : minus_den; 04145 const Coefficient& minus_sc_den = is_sc ? minus_den : denominator; 04146 // NOTE: here, for optimization purposes, `minus_expr' is only assigned 04147 // when `denominator' is negative. Do not use it unless you are sure 04148 // it has been correctly assigned. 04149 Linear_Expression minus_expr; 04150 if (!is_sc) 04151 minus_expr = -expr; 04152 const Linear_Expression& sc_expr = is_sc ? expr : minus_expr; 04153 04154 DIRTY_TEMP(N, pos_sum); 04155 DIRTY_TEMP(N, neg_sum); 04156 // Indices of the variables that are unbounded in `this->matrix'. 04157 PPL_UNINITIALIZED(dimension_type, pos_pinf_index); 04158 PPL_UNINITIALIZED(dimension_type, neg_pinf_index); 04159 // Number of unbounded variables found. 04160 dimension_type pos_pinf_count = 0; 04161 dimension_type neg_pinf_count = 0; 04162 04163 // Approximate the inhomogeneous term. 04164 assign_r(pos_sum, sc_b, ROUND_UP); 04165 assign_r(neg_sum, minus_sc_b, ROUND_UP); 04166 04167 // Approximate the homogeneous part of `sc_expr'. 04168 DIRTY_TEMP(N, coeff_i); 04169 DIRTY_TEMP(N, minus_coeff_i); 04170 DIRTY_TEMP(N, half); 04171 TEMP_INTEGER(minus_sc_i); 04172 // Note: indices above `w' can be disregarded, as they all have 04173 // a zero coefficient in `sc_expr'. 04174 for (Row_iterator m_iter = m_begin, m_iter_end = m_iter + (2*w_id) + 2; 04175 m_iter != m_iter_end; ) { 04176 const dimension_type n_i = m_iter.index(); 04177 const dimension_type id = n_i/2; 04178 Row_reference m_i = *m_iter; 04179 ++m_iter; 04180 Row_reference m_ci = *m_iter; 04181 ++m_iter; 04182 const Coefficient& sc_i = sc_expr.coefficient(Variable(id)); 04183 const int sign_i = sgn(sc_i); 04184 if (sign_i > 0) { 04185 assign_r(coeff_i, sc_i, ROUND_UP); 04186 // Approximating `sc_expr'. 04187 if (pos_pinf_count <= 1) { 04188 const N& double_up_approx_i = m_ci[n_i]; 04189 if (!is_plus_infinity(double_up_approx_i)) { 04190 // Let half = double_up_approx_i / 2. 04191 div2exp_assign_r(half, double_up_approx_i, 1, ROUND_UP); 04192 add_mul_assign_r(pos_sum, coeff_i, half, ROUND_UP); 04193 } 04194 else { 04195 ++pos_pinf_count; 04196 pos_pinf_index = id; 04197 } 04198 } 04199 // Approximating `-sc_expr'. 04200 if (neg_pinf_count <= 1) { 04201 const N& double_up_approx_minus_i = m_i[n_i+1]; 04202 if (!is_plus_infinity(double_up_approx_minus_i)) { 04203 // Let half = double_up_approx_minus_i / 2. 04204 div2exp_assign_r(half, double_up_approx_minus_i, 1, ROUND_UP); 04205 add_mul_assign_r(neg_sum, coeff_i, half, ROUND_UP); 04206 } 04207 else { 04208 ++neg_pinf_count; 04209 neg_pinf_index = id; 04210 } 04211 } 04212 } 04213 else if (sign_i < 0) { 04214 neg_assign_r(minus_sc_i, sc_i, ROUND_NOT_NEEDED); 04215 assign_r(minus_coeff_i, minus_sc_i, ROUND_UP); 04216 // Approximating `sc_expr'. 04217 if (pos_pinf_count <= 1) { 04218 const N& double_up_approx_minus_i = m_i[n_i+1]; 04219 if (!is_plus_infinity(double_up_approx_minus_i)) { 04220 // Let half = double_up_approx_minus_i / 2. 04221 div2exp_assign_r(half, double_up_approx_minus_i, 1, ROUND_UP); 04222 add_mul_assign_r(pos_sum, minus_coeff_i, half, ROUND_UP); 04223 } 04224 else { 04225 ++pos_pinf_count; 04226 pos_pinf_index = id; 04227 } 04228 } 04229 // Approximating `-sc_expr'. 04230 if (neg_pinf_count <= 1) { 04231 const N& double_up_approx_i = m_ci[n_i]; 04232 if (!is_plus_infinity(double_up_approx_i)) { 04233 // Let half = double_up_approx_i / 2. 04234 div2exp_assign_r(half, double_up_approx_i, 1, ROUND_UP); 04235 add_mul_assign_r(neg_sum, minus_coeff_i, half, ROUND_UP); 04236 } 04237 else { 04238 ++neg_pinf_count; 04239 neg_pinf_index = id; 04240 } 04241 } 04242 } 04243 } 04244 04245 // Remove all constraints on `var'. 04246 forget_all_octagonal_constraints(var_id); 04247 // Return immediately if no approximation could be computed. 04248 if (pos_pinf_count > 1 && neg_pinf_count > 1) { 04249 assert(OK()); 04250 return; 04251 } 04252 04253 // In the following, strong closure will be definitely lost. 04254 reset_strongly_closed(); 04255 04256 // Exploit the upper approximation, if possible. 04257 if (pos_pinf_count <= 1) { 04258 // Compute quotient (if needed). 04259 if (sc_den != 1) { 04260 // Before computing quotients, the denominator should be approximated 04261 // towards zero. Since `sc_den' is known to be positive, this amounts to 04262 // rounding downwards, which is achieved as usual by rounding upwards 04263 // `minus_sc_den' and negating again the result. 04264 DIRTY_TEMP(N, down_sc_den); 04265 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 04266 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 04267 div_assign_r(pos_sum, pos_sum, down_sc_den, ROUND_UP); 04268 } 04269 // Add the upper bound constraint, if meaningful. 04270 if (pos_pinf_count == 0) { 04271 // Add the constraint `v <= pos_sum'. 04272 DIRTY_TEMP(N, double_pos_sum); 04273 mul2exp_assign_r(double_pos_sum, pos_sum, 1, ROUND_IGNORE); 04274 matrix[n_var+1][n_var] = double_pos_sum; 04275 // Deduce constraints of the form `v +/- u', where `u != v'. 04276 deduce_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, pos_sum); 04277 } 04278 else 04279 // Here `pos_pinf_count == 1'. 04280 if (pos_pinf_index != var_id) { 04281 const Coefficient& ppi = sc_expr.coefficient(Variable(pos_pinf_index)); 04282 if (ppi == sc_den) 04283 // Add the constraint `v - pos_pinf_index <= pos_sum'. 04284 if (var_id < pos_pinf_index) 04285 matrix[2*pos_pinf_index][n_var] = pos_sum; 04286 else 04287 matrix[n_var+1][2*pos_pinf_index+1] = pos_sum; 04288 else 04289 if (ppi == minus_sc_den) { 04290 // Add the constraint `v + pos_pinf_index <= pos_sum'. 04291 if (var_id < pos_pinf_index) 04292 matrix[2*pos_pinf_index+1][n_var] = pos_sum; 04293 else 04294 matrix[n_var+1][2*pos_pinf_index] = pos_sum; 04295 } 04296 } 04297 } 04298 04299 // Exploit the lower approximation, if possible. 04300 if (neg_pinf_count <= 1) { 04301 // Compute quotient (if needed). 04302 if (sc_den != 1) { 04303 // Before computing quotients, the denominator should be approximated 04304 // towards zero. Since `sc_den' is known to be positive, this amounts to 04305 // rounding downwards, which is achieved as usual by rounding upwards 04306 // `minus_sc_den' and negating again the result. 04307 DIRTY_TEMP(N, down_sc_den); 04308 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 04309 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 04310 div_assign_r(neg_sum, neg_sum, down_sc_den, ROUND_UP); 04311 } 04312 // Add the lower bound constraint, if meaningful. 04313 if (neg_pinf_count == 0) { 04314 // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'. 04315 DIRTY_TEMP(N, double_neg_sum); 04316 mul2exp_assign_r(double_neg_sum, neg_sum, 1, ROUND_IGNORE); 04317 matrix[n_var][n_var+1] = double_neg_sum; 04318 // Deduce constraints of the form `-v +/- u', where `u != v'. 04319 deduce_minus_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, neg_sum); 04320 } 04321 else 04322 // Here `neg_pinf_count == 1'. 04323 if (neg_pinf_index != var_id) { 04324 const Coefficient& npi = sc_expr.coefficient(Variable(neg_pinf_index)); 04325 if (npi == sc_den) 04326 // Add the constraint `v - neg_pinf_index >= -neg_sum', 04327 // i.e., `neg_pinf_index - v <= neg_sum'. 04328 if (neg_pinf_index < var_id) 04329 matrix[n_var][2*neg_pinf_index] = neg_sum; 04330 else 04331 matrix[2*neg_pinf_index+1][n_var+1] = neg_sum; 04332 else 04333 if (npi == minus_sc_den) { 04334 // Add the constraint `v + neg_pinf_index >= -neg_sum', 04335 // i.e., `-neg_pinf_index - v <= neg_sum'. 04336 if (neg_pinf_index < var_id) 04337 matrix[n_var][2*neg_pinf_index+1] = neg_sum; 04338 else 04339 matrix[2*neg_pinf_index][n_var+1] = neg_sum; 04340 } 04341 } 04342 } 04343 04344 incremental_strong_closure_assign(var); 04345 assert(OK()); 04346 }
| void Parma_Polyhedra_Library::Octagonal_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 4350 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_all_octagonal_constraints(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), TEMP_INTEGER, Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage().
04353 { 04354 04355 // The denominator cannot be zero. 04356 if (denominator == 0) 04357 throw_generic("affine_preimage(v, e, d)", "d == 0"); 04358 04359 // Dimension-compatibility checks. 04360 // The dimension of `expr' should not be greater than the dimension 04361 // of `*this'. 04362 const dimension_type expr_space_dim = expr.space_dimension(); 04363 if (space_dim < expr_space_dim) 04364 throw_dimension_incompatible("affine_preimage(v, e, d)", "e", expr); 04365 04366 // `var' should be one of the dimensions of the octagon. 04367 dimension_type var_id = var.id(); 04368 if (space_dim < var_id + 1) 04369 throw_dimension_incompatible("affine_preimage(v, e, d)", var.id()+1); 04370 04371 strong_closure_assign(); 04372 // The image of an empty octagon is empty too. 04373 if (marked_empty()) 04374 return; 04375 04376 const Coefficient& b = expr.inhomogeneous_term(); 04377 04378 // Number of non-zero coefficients in `expr': will be set to 04379 // 0, 1, or 2, the latter value meaning any value greater than 1. 04380 dimension_type t = 0; 04381 04382 // Variable-index of the last non-zero coefficient in `expr', if any. 04383 dimension_type w_id = 0; 04384 04385 // Get information about the number of the non-zero coefficients of `expr'. 04386 for (dimension_type i = expr_space_dim; i-- > 0; ) 04387 if (expr.coefficient(Variable(i)) != 0) { 04388 if (t++ == 1) 04389 break; 04390 else 04391 w_id = i; 04392 } 04393 04394 // `w' is the variable with index `w_id'. 04395 // Now we know the form of `expr': 04396 // - If t == 0, then expr == b, with `b' a constant; 04397 // - If t == 1, then expr == a*w + b, where `w' can be `v' or another 04398 // variable; in this second case we have to check whether `a' is 04399 // equal to `denominator' or `-denominator', since otherwise we have 04400 // to fall back on the general form; 04401 // - If t == 2, the `expr' is of the general form. 04402 04403 if (t == 0) { 04404 // Case 1: expr = n; remove all constraints on `var'. 04405 forget_all_octagonal_constraints(var_id); 04406 assert(OK()); 04407 return; 04408 } 04409 04410 if (t == 1) { 04411 // Value of the one and only non-zero coefficient in `expr'. 04412 const Coefficient& w_coeff = expr.coefficient(Variable(w_id)); 04413 if (w_coeff == denominator || w_coeff == -denominator) { 04414 // Case 2: expr = w_coeff*w + b, with w_coeff = +/- denominator. 04415 if (w_id == var_id) { 04416 // Apply affine_image() on the inverse of this transformation. 04417 affine_image(var, denominator*var - b, w_coeff); 04418 } 04419 else { 04420 // `expr == w_coeff*w + b', where `w != var'. 04421 // Remove all constraints on `var'. 04422 forget_all_octagonal_constraints(var_id); 04423 assert(OK()); 04424 } 04425 return; 04426 } 04427 } 04428 // General case. 04429 // Either t == 2, so that 04430 // expr = a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2, 04431 // or t = 1, expr = a*w + b, but a <> +/- denominator. 04432 const Coefficient& coeff_v = expr.coefficient(var); 04433 if (coeff_v != 0) { 04434 if (coeff_v > 0) { 04435 // The transformation is invertible. 04436 Linear_Expression inverse = ((coeff_v + denominator)*var); 04437 inverse -= expr; 04438 affine_image(var, inverse, coeff_v); 04439 } 04440 else { 04441 // The transformation is invertible. 04442 TEMP_INTEGER(minus_coeff_v); 04443 neg_assign(minus_coeff_v, coeff_v); 04444 Linear_Expression inverse = ((minus_coeff_v - denominator)*var); 04445 inverse += expr; 04446 affine_image(var, inverse, minus_coeff_v); 04447 } 04448 } 04449 else { 04450 // The transformation is not invertible: all constraints on `var' are lost. 04451 forget_all_octagonal_constraints(var_id); 04452 assert(OK()); 04453 } 04454 }
| void Parma_Polyhedra_Library::Octagonal_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 generalized affine transfer function
, 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 4459 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Octagonal_Shape< T >::deduce_minus_v_pm_u_bounds(), Parma_Polyhedra_Library::Octagonal_Shape< T >::deduce_v_pm_u_bounds(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_all_octagonal_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_binary_octagonal_constraints(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign(), 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::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), PLUS_INFINITY, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), TEMP_INTEGER, Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage().
04462 { 04463 // The denominator cannot be zero. 04464 if (denominator == 0) 04465 throw_generic("generalized_affine_image(v, r, e, d)", "d == 0"); 04466 04467 // Dimension-compatibility checks. 04468 // The dimension of `expr' should not be greater than the dimension 04469 // of `*this'. 04470 const dimension_type expr_space_dim = expr.space_dimension(); 04471 if (space_dim < expr_space_dim) 04472 throw_dimension_incompatible("generalized_affine_image(v, r, e, d)", "e", 04473 expr); 04474 04475 // `var' should be one of the dimensions of the octagon. 04476 dimension_type var_id = var.id(); 04477 if (space_dim < var_id + 1) 04478 throw_dimension_incompatible("generalized_affine_image(v, r, e, d)", 04479 var.id()+1); 04480 04481 // The relation symbol cannot be a strict relation symbol. 04482 if (relsym == LESS_THAN || relsym == GREATER_THAN) 04483 throw_generic("generalized_affine_image(v, r, e, d)", 04484 "r is a strict relation symbol and " 04485 "*this is an Octagonal_Shape"); 04486 04487 if (relsym == EQUAL) { 04488 // The relation symbol is "==": 04489 // this is just an affine image computation. 04490 affine_image(var, expr, denominator); 04491 return; 04492 } 04493 04494 strong_closure_assign(); 04495 // The image of an empty octagon is empty too. 04496 if (marked_empty()) 04497 return; 04498 04499 // Number of non-zero coefficients in `expr': will be set to 04500 // 0, 1, or 2, the latter value meaning any value greater than 1. 04501 dimension_type t = 0; 04502 // Variable-index of the last non-zero coefficient in `expr', if any. 04503 dimension_type w_id = 0; 04504 04505 // Get information about the number of non-zero coefficients in `expr'. 04506 // The `expr' must not be in two or plus variables. 04507 for (dimension_type i = expr_space_dim; i-- > 0; ) 04508 if (expr.coefficient(Variable(i)) != 0) { 04509 if (t++ == 1) 04510 break; 04511 else 04512 w_id = i; 04513 } 04514 04515 typedef typename OR_Matrix<N>::row_iterator Row_Iterator; 04516 typedef typename OR_Matrix<N>::row_reference_type Row_Reference; 04517 typedef typename OR_Matrix<N>::const_row_iterator Row_iterator; 04518 typedef typename OR_Matrix<N>::const_row_reference_type Row_reference; 04519 04520 const Row_Iterator m_begin = matrix.row_begin(); 04521 const Row_Iterator m_end = matrix.row_end(); 04522 const dimension_type n_var = 2*var_id; 04523 const Coefficient& b = expr.inhomogeneous_term(); 04524 TEMP_INTEGER(minus_den); 04525 neg_assign_r(minus_den, denominator, ROUND_NOT_NEEDED); 04526 04527 // `w' is the variable with index `w_id'. 04528 // Now we know the form of `expr': 04529 // - If t == 0, then expr == b, with `b' a constant; 04530 // - If t == 1, then expr == a*w + b, where `w' can be `v' or another 04531 // variable; in this second case we have to check whether `a' is 04532 // equal to `denominator' or `-denominator', since otherwise we have 04533 // to fall back on the general form; 04534 // - If t == 2, the `expr' is of the general form. 04535 04536 if (t == 0) { 04537 // Case 1: expr = b. 04538 TEMP_INTEGER(two_b); 04539 two_b = 2*b; 04540 // Remove all constraints on `var'. 04541 forget_all_octagonal_constraints(var_id); 04542 // Strong closure is lost. 04543 reset_strongly_closed(); 04544 switch (relsym) { 04545 case LESS_OR_EQUAL: 04546 // Add the constraint `var <= b/denominator'. 04547 add_octagonal_constraint(n_var+1, n_var, two_b, denominator); 04548 break; 04549 case GREATER_OR_EQUAL: 04550 // Add the constraint `var >= n/denominator', 04551 // i.e., `-var <= -b/denominator'. 04552 add_octagonal_constraint(n_var, n_var+1, two_b, minus_den); 04553 break; 04554 default: 04555 // We already dealt with the other cases. 04556 throw std::runtime_error("PPL internal error"); 04557 } 04558 assert(OK()); 04559 return; 04560 } 04561 04562 if (t == 1) { 04563 // The one and only non-zero homogeneous coefficient in `expr'. 04564 const Coefficient& w_coeff = expr.coefficient(Variable(w_id)); 04565 if (w_coeff == denominator || w_coeff == minus_den) { 04566 // Case 2: expr == w_coeff*w + b, with w_coeff == +/- denominator. 04567 switch (relsym) { 04568 case LESS_OR_EQUAL: 04569 { 04570 DIRTY_TEMP(N, d); 04571 div_round_up(d, b, denominator); 04572 if (w_id == var_id) { 04573 // Here `expr' is of the form: +/- denominator * v + b. 04574 // Strong closure is not preserved. 04575 reset_strongly_closed(); 04576 if (w_coeff == denominator) { 04577 // Translate all the constraints of the form `v - w <= cost' 04578 // into the constraint `v - w <= cost + b/denominator'; 04579 // forget each constraint `w - v <= cost1'. 04580 Row_Iterator m_iter = m_begin + n_var; 04581 Row_Reference m_v = *m_iter; 04582 N& m_v_cv = m_v[n_var+1]; 04583 ++m_iter; 04584 Row_Reference m_cv = *m_iter; 04585 N& m_cv_v = m_cv[n_var]; 04586 ++m_iter; 04587 // NOTE: delay update of m_v_cv and m_cv_v. 04588 for ( ; m_iter != m_end; ++m_iter) { 04589 Row_Reference m_i = *m_iter; 04590 N& m_i_v = m_i[n_var]; 04591 add_assign_r(m_i_v, m_i_v, d, ROUND_UP); 04592 assign_r(m_i[n_var+1], PLUS_INFINITY, ROUND_NOT_NEEDED); 04593 } 04594 for (dimension_type k = n_var; k-- > 0; ) { 04595 assign_r(m_v[k], PLUS_INFINITY, ROUND_NOT_NEEDED); 04596 add_assign_r(m_cv[k], m_cv[k], d, ROUND_UP); 04597 } 04598 mul2exp_assign_r(d, d, 1, ROUND_IGNORE); 04599 add_assign_r(m_cv_v, m_cv_v, d, ROUND_UP); 04600 assign_r(m_v_cv, PLUS_INFINITY, ROUND_NOT_NEEDED); 04601 } 04602 else { 04603 // Here `w_coeff == -denominator'. 04604 // `expr' is of the form: -a*var + b. 04605 N& m_v_cv = matrix[n_var][n_var+1]; 04606 mul2exp_assign_r(d, d, 1, ROUND_IGNORE); 04607 add_assign_r(matrix[n_var+1][n_var], m_v_cv, d, ROUND_UP); 04608 assign_r(m_v_cv, PLUS_INFINITY, ROUND_NOT_NEEDED); 04609 forget_binary_octagonal_constraints(var_id); 04610 } 04611 } 04612 else { 04613 // Here `w != v', so that `expr' is the form 04614 // +/- denominator*w + b. 04615 // Remove all constraints on `v'. 04616 forget_all_octagonal_constraints(var_id); 04617 const dimension_type n_w = 2*w_id; 04618 if (w_coeff == denominator) { 04619 // Add the new constraint `v - w <= b/denominator'. 04620 if (var_id < w_id) 04621 add_octagonal_constraint(n_w, n_var, b, denominator); 04622 else 04623 add_octagonal_constraint(n_var+1, n_w+1, b, denominator); 04624 } 04625 else { 04626 // Add the new constraint `v + w <= b/denominator'. 04627 if (var_id < w_id) 04628 add_octagonal_constraint(n_w+1, n_var, b, denominator); 04629 else 04630 add_octagonal_constraint(n_var+1, n_w, b, denominator); 04631 } 04632 } 04633 break; 04634 } 04635 04636 case GREATER_OR_EQUAL: 04637 { 04638 DIRTY_TEMP(N, d); 04639 div_round_up(d, b, minus_den); 04640 if (w_id == var_id) { 04641 // Here `expr' is of the form: +/- denominator * v + b. 04642 // Strong closure is not preserved. 04643 reset_strongly_closed(); 04644 if (w_coeff == denominator) { 04645 // Translate each constraint `w - v <= cost' 04646 // into the constraint `w - v <= cost - b/denominator'; 04647 // forget each constraint `v - w <= cost1'. 04648 Row_Iterator m_iter = m_begin + n_var; 04649 Row_Reference m_v = *m_iter; 04650 N& m_v_cv = m_v[n_var+1]; 04651 ++m_iter; 04652 Row_Reference m_cv = *m_iter; 04653 N& m_cv_v = m_cv[n_var]; 04654 ++m_iter; 04655 // NOTE: delay update of m_v_cv and m_cv_v. 04656 for ( ; m_iter != m_end; ++m_iter) { 04657 Row_Reference m_i = *m_iter; 04658 assign_r(m_i[n_var], PLUS_INFINITY, ROUND_NOT_NEEDED); 04659 add_assign_r(m_i[n_var+1], m_i[n_var+1], d, ROUND_UP); 04660 } 04661 for (dimension_type k = n_var; k-- > 0; ) { 04662 add_assign_r(m_v[k], m_v[k], d, ROUND_UP); 04663 assign_r(m_cv[k], PLUS_INFINITY, ROUND_NOT_NEEDED); 04664 } 04665 mul2exp_assign_r(d, d, 1, ROUND_IGNORE); 04666 add_assign_r(m_v_cv, m_v_cv, d, ROUND_UP); 04667 assign_r(m_cv_v, PLUS_INFINITY, ROUND_NOT_NEEDED); 04668 } 04669 else { 04670 // Here `w_coeff == -denominator'. 04671 // `expr' is of the form: -a*var + b. 04672 N& m_cv_v = matrix[n_var+1][n_var]; 04673 mul2exp_assign_r(d, d, 1, ROUND_IGNORE); 04674 add_assign_r(matrix[n_var][n_var+1], m_cv_v, d, ROUND_UP); 04675 assign_r(m_cv_v, PLUS_INFINITY, ROUND_NOT_NEEDED); 04676 forget_binary_octagonal_constraints(var_id); 04677 } 04678 } 04679 else { 04680 // Here `w != v', so that `expr' is of the form 04681 // +/-denominator * w + b, with `w != v'. 04682 // Remove all constraints on `v'. 04683 forget_all_octagonal_constraints(var_id); 04684 const dimension_type n_w = 2*w_id; 04685 // We have got an expression of the following form: 04686 // var1 + n, with `var1' != `var'. 04687 // We remove all constraints of the form `var (+/- var1) >= const' 04688 // and we add the new constraint `var +/- var1 >= n/denominator'. 04689 if (w_coeff == denominator) { 04690 // Add the new constraint `var - w >= b/denominator', 04691 // i.e., `w - var <= -b/denominator'. 04692 if (var_id < w_id) 04693 add_octagonal_constraint(n_w+1, n_var+1, b, minus_den); 04694 else 04695 add_octagonal_constraint(n_var, n_w, b, minus_den); 04696 } 04697 else { 04698 // Add the new constraint `var + w >= b/denominator', 04699 // i.e., `-w - var <= -b/denominator'. 04700 if (var_id < w_id) 04701 add_octagonal_constraint(n_w, n_var+1, b, minus_den); 04702 else 04703 add_octagonal_constraint(n_var, n_w+1, b, minus_den); 04704 } 04705 } 04706 break; 04707 } 04708 04709 default: 04710 // We already dealt with the other cases. 04711 throw std::runtime_error("PPL internal error"); 04712 } 04713 assert(OK()); 04714 return; 04715 } 04716 } 04717 04718 // General case. 04719 // Either t == 2, so that 04720 // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2, 04721 // or t == 1, expr == a*w + b, but a <> +/- denominator. 04722 // We will remove all the constraints on `v' and add back 04723 // a constraint providing an upper or a lower bound for `v' 04724 // (depending on `relsym'). 04725 const bool is_sc = (denominator > 0); 04726 TEMP_INTEGER(minus_b); 04727 neg_assign(minus_b, b); 04728 const Coefficient& sc_b = is_sc ? b : minus_b; 04729 const Coefficient& minus_sc_b = is_sc ? minus_b : b; 04730 const Coefficient& sc_den = is_sc ? denominator : minus_den; 04731 const Coefficient& minus_sc_den = is_sc ? minus_den : denominator; 04732 // NOTE: here, for optimization purposes, `minus_expr' is only assigned 04733 // when `denominator' is negative. Do not use it unless you are sure 04734 // it has been correctly assigned. 04735 Linear_Expression minus_expr; 04736 if (!is_sc) 04737 minus_expr = -expr; 04738 const Linear_Expression& sc_expr = is_sc ? expr : minus_expr; 04739 04740 DIRTY_TEMP(N, sum); 04741 // Index of variable that is unbounded in `this->matrix'. 04742 PPL_UNINITIALIZED(dimension_type, pinf_index); 04743 // Number of unbounded variables found. 04744 dimension_type pinf_count = 0; 04745 04746 switch (relsym) { 04747 case LESS_OR_EQUAL: 04748 { 04749 // Compute an upper approximation for `sc_expr' into `sum'. 04750 04751 // Approximate the inhomogeneous term. 04752 assign_r(sum, sc_b, ROUND_UP); 04753 // Approximate the homogeneous part of `sc_expr'. 04754 DIRTY_TEMP(N, coeff_i); 04755 DIRTY_TEMP(N, approx_i); 04756 TEMP_INTEGER(minus_sc_i); 04757 // Note: indices above `w' can be disregarded, as they all have 04758 // a zero coefficient in `sc_expr'. 04759 for (Row_iterator m_iter = m_begin, m_iter_end = m_iter + (2*w_id) + 2; 04760 m_iter != m_iter_end; ) { 04761 const dimension_type n_i = m_iter.index(); 04762 const dimension_type id = n_i/2; 04763 Row_reference m_i = *m_iter; 04764 ++m_iter; 04765 Row_reference m_ci = *m_iter; 04766 ++m_iter; 04767 const Coefficient& sc_i = sc_expr.coefficient(Variable(id)); 04768 const int sign_i = sgn(sc_i); 04769 if (sign_i == 0) 04770 continue; 04771 // Choose carefully: we are approximating `sc_expr'. 04772 const N& double_approx_i = (sign_i > 0) ? m_ci[n_i] : m_i[n_i+1]; 04773 if (is_plus_infinity(double_approx_i)) { 04774 if (++pinf_count > 1) 04775 break; 04776 pinf_index = id; 04777 continue; 04778 } 04779 if (sign_i > 0) 04780 assign_r(coeff_i, sc_i, ROUND_UP); 04781 else { 04782 neg_assign(minus_sc_i, sc_i); 04783 assign_r(coeff_i, minus_sc_i, ROUND_UP); 04784 } 04785 div2exp_assign_r(approx_i, double_approx_i, 1, ROUND_UP); 04786 add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP); 04787 } 04788 // Remove all constraints on `v'. 04789 forget_all_octagonal_constraints(var_id); 04790 reset_strongly_closed(); 04791 // Return immediately if no approximation could be computed. 04792 if (pinf_count > 1) { 04793 assert(OK()); 04794 return; 04795 } 04796 04797 // Divide by the (sign corrected) denominator (if needed). 04798 if (sc_den != 1) { 04799 // Before computing the quotient, the denominator should be 04800 // approximated towards zero. Since `sc_den' is known to be 04801 // positive, this amounts to rounding downwards, which is 04802 // achieved as usual by rounding upwards 04803 // `minus_sc_den' and negating again the result. 04804 DIRTY_TEMP(N, down_sc_den); 04805 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 04806 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 04807 div_assign_r(sum, sum, down_sc_den, ROUND_UP); 04808 } 04809 04810 if (pinf_count == 0) { 04811 // Add the constraint `v <= pos_sum'. 04812 DIRTY_TEMP(N, double_sum); 04813 mul2exp_assign_r(double_sum, sum, 1, ROUND_IGNORE); 04814 matrix[n_var+1][n_var] = double_sum; 04815 // Deduce constraints of the form `v +/- u', where `u != v'. 04816 deduce_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, sum); 04817 } 04818 else if (pinf_count == 1) 04819 if (pinf_index != var_id) { 04820 const Coefficient& pi = expr.coefficient(Variable(pinf_index)); 04821 if (pi == denominator ) { 04822 // Add the constraint `v - pinf_index <= sum'. 04823 if (var_id < pinf_index) 04824 matrix[2*pinf_index][n_var] = sum; 04825 else 04826 matrix[n_var+1][2*pinf_index+1] = sum; 04827 } 04828 else { 04829 if (pi == minus_den) { 04830 // Add the constraint `v + pinf_index <= sum'. 04831 if (var_id < pinf_index) 04832 matrix[2*pinf_index+1][n_var] = sum; 04833 else 04834 matrix[n_var+1][2*pinf_index] = sum; 04835 } 04836 } 04837 } 04838 break; 04839 } 04840 04841 case GREATER_OR_EQUAL: 04842 { 04843 // Compute an upper approximation for `-sc_expr' into `sum'. 04844 // Note: approximating `-sc_expr' from above and then negating the 04845 // result is the same as approximating `sc_expr' from below. 04846 04847 // Approximate the inhomogeneous term. 04848 assign_r(sum, minus_sc_b, ROUND_UP); 04849 DIRTY_TEMP(N, coeff_i); 04850 TEMP_INTEGER(minus_sc_i); 04851 DIRTY_TEMP(N, approx_i); 04852 // Approximate the homogeneous part of `-sc_expr'. 04853 for (Row_iterator m_iter = m_begin, m_iter_end = m_iter + (2*w_id) + 2; 04854 m_iter != m_iter_end; ) { 04855 const dimension_type n_i = m_iter.index(); 04856 const dimension_type id = n_i/2; 04857 Row_reference m_i = *m_iter; 04858 ++m_iter; 04859 Row_reference m_ci = *m_iter; 04860 ++m_iter; 04861 const Coefficient& sc_i = sc_expr.coefficient(Variable(id)); 04862 const int sign_i = sgn(sc_i); 04863 if (sign_i == 0) 04864 continue; 04865 // Choose carefully: we are approximating `-sc_expr'. 04866 const N& double_approx_i = (sign_i > 0) ? m_i[n_i+1] : m_ci[n_i]; 04867 if (is_plus_infinity(double_approx_i)) { 04868 if (++pinf_count > 1) 04869 break; 04870 pinf_index = id; 04871 continue; 04872 } 04873 if (sign_i > 0) 04874 assign_r(coeff_i, sc_i, ROUND_UP); 04875 else { 04876 neg_assign(minus_sc_i, sc_i); 04877 assign_r(coeff_i, minus_sc_i, ROUND_UP); 04878 } 04879 div2exp_assign_r(approx_i, double_approx_i, 1, ROUND_UP); 04880 add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP); 04881 } 04882 04883 // Remove all constraints on `var'. 04884 forget_all_octagonal_constraints(var_id); 04885 reset_strongly_closed(); 04886 // Return immediately if no approximation could be computed. 04887 if (pinf_count > 1) { 04888 assert(OK()); 04889 return; 04890 } 04891 04892 // Divide by the (sign corrected) denominator (if needed). 04893 if (sc_den != 1) { 04894 // Before computing the quotient, the denominator should be 04895 // approximated towards zero. Since `sc_den' is known to be 04896 // positive, this amounts to rounding downwards, which is 04897 // achieved as usual by rounding upwards 04898 // `minus_sc_den' and negating again the result. 04899 DIRTY_TEMP(N, down_sc_den); 04900 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 04901 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 04902 div_assign_r(sum, sum, down_sc_den, ROUND_UP); 04903 } 04904 04905 if (pinf_count == 0) { 04906 // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'. 04907 DIRTY_TEMP(N, double_sum); 04908 mul2exp_assign_r(double_sum, sum, 1, ROUND_IGNORE); 04909 matrix[n_var][n_var+1] = double_sum; 04910 // Deduce constraints of the form `-v +/- u', where `u != v'. 04911 deduce_minus_v_pm_u_bounds(var_id, pinf_index, sc_expr, sc_den, sum); 04912 } 04913 else if (pinf_count == 1) 04914 if (pinf_index != var_id) { 04915 const Coefficient& pi = expr.coefficient(Variable(pinf_index)); 04916 if (pi == denominator) { 04917 // Add the constraint `v - pinf_index >= -sum', 04918 // i.e., `pinf_index - v <= sum'. 04919 if (pinf_index < var_id) 04920 matrix[n_var][2*pinf_index] = sum; 04921 else 04922 matrix[2*pinf_index+1][n_var+1] = sum; 04923 } 04924 else { 04925 if (pi == minus_den) { 04926 // Add the constraint `v + pinf_index >= -sum', 04927 // i.e., `-pinf_index - v <= sum'. 04928 if (pinf_index < var_id) 04929 matrix[n_var][2*pinf_index+1] = sum; 04930 else 04931 matrix[2*pinf_index][n_var+1] = sum; 04932 } 04933 } 04934 } 04935 break; 04936 } 04937 04938 default: 04939 // We already dealt with the other cases. 04940 throw std::runtime_error("PPL internal error"); 04941 } 04942 incremental_strong_closure_assign(var); 04943 assert(OK()); 04944 }
| void Parma_Polyhedra_Library::Octagonal_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 generalized affine transfer function
, 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 4948 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_all_octagonal_constraints(), Parma_Polyhedra_Library::Octagonal_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::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().
04950 { 04951 // Dimension-compatibility checks. 04952 // The dimension of `lhs' should not be greater than the dimension 04953 // of `*this'. 04954 dimension_type lhs_space_dim = lhs.space_dimension(); 04955 if (space_dim < lhs_space_dim) 04956 throw_dimension_incompatible("generalized_affine_image(e1, r, e2)", 04957 "e1", lhs); 04958 04959 // The dimension of `rhs' should not be greater than the dimension 04960 // of `*this'. 04961 const dimension_type rhs_space_dim = rhs.space_dimension(); 04962 if (space_dim < rhs_space_dim) 04963 throw_dimension_incompatible("generalized_affine_image(e1, r, e2)", 04964 "e2", rhs); 04965 04966 // Strict relation symbols are not admitted for octagons. 04967 if (relsym == LESS_THAN || relsym == GREATER_THAN) 04968 throw_generic("generalized_affine_image(e1, r, e2)", 04969 "r is a strict relation symbol and " 04970 "*this is an Octagonal_Shape"); 04971 04972 strong_closure_assign(); 04973 // The image of an empty octagon is empty. 04974 if (marked_empty()) 04975 return; 04976 04977 // Number of non-zero coefficients in `lhs': will be set to 04978 // 0, 1, or 2, the latter value meaning any value greater than 1. 04979 dimension_type t_lhs = 0; 04980 // Index of the last non-zero coefficient in `lhs', if any. 04981 dimension_type j_lhs = 0; 04982 04983 // Compute the number of the non-zero components of `lhs'. 04984 for (dimension_type i = lhs_space_dim; i-- > 0; ) 04985 if (lhs.coefficient(Variable(i)) != 0) { 04986 if (t_lhs++ == 1) 04987 break; 04988 else 04989 j_lhs = i; 04990 } 04991 04992 const Coefficient& b_lhs = lhs.inhomogeneous_term(); 04993 04994 if (t_lhs == 0) { 04995 // `lhs' is a constant. 04996 // In principle, it is sufficient to add the constraint `lhs relsym rhs'. 04997 // Note that this constraint is an octagonal difference if `t_rhs <= 1' 04998 // or `t_rhs > 1' and `rhs == a*v - a*w + b_rhs' or 04999 // `rhs == a*v + a*w + b_rhs'. If `rhs' is of a 05000 // more general form, it will be simply ignored. 05001 // TODO: if it is not an octagonal difference, should we compute 05002 // approximations for this constraint? 05003 switch (relsym) { 05004 case LESS_OR_EQUAL: 05005 refine_no_check(lhs <= rhs); 05006 break; 05007 case EQUAL: 05008 refine_no_check(lhs == rhs); 05009 break; 05010 case GREATER_OR_EQUAL: 05011 refine_no_check(lhs >= rhs); 05012 break; 05013 default: 05014 // We already dealt with the other cases. 05015 throw std::runtime_error("PPL internal error"); 05016 } 05017 } 05018 05019 else if (t_lhs == 1) { 05020 // Here `lhs == a_lhs * v + b_lhs'. 05021 // Independently from the form of `rhs', we can exploit the 05022 // method computing generalized affine images for a single variable. 05023 Variable v(j_lhs); 05024 // Compute a sign-corrected relation symbol. 05025 const Coefficient& den = lhs.coefficient(v); 05026 Relation_Symbol new_relsym = relsym; 05027 if (den < 0) { 05028 if (relsym == LESS_OR_EQUAL) 05029 new_relsym = GREATER_OR_EQUAL; 05030 else if (relsym == GREATER_OR_EQUAL) 05031 new_relsym = LESS_OR_EQUAL; 05032 } 05033 Linear_Expression expr = rhs - b_lhs; 05034 generalized_affine_image(v, new_relsym, expr, den); 05035 } 05036 else { 05037 // Here `lhs' is of the general form, having at least two variables. 05038 // Compute the set of variables occurring in `lhs'. 05039 bool lhs_vars_intersects_rhs_vars = false; 05040 std::vector<Variable> lhs_vars; 05041 for (dimension_type i = lhs_space_dim; i-- > 0; ) 05042 if (lhs.coefficient(Variable(i)) != 0) { 05043 lhs_vars.push_back(Variable(i)); 05044 if (rhs.coefficient(Variable(i)) != 0) 05045 lhs_vars_intersects_rhs_vars = true; 05046 } 05047 05048 if (!lhs_vars_intersects_rhs_vars) { 05049 // `lhs' and `rhs' variables are disjoint. 05050 // Existentially quantify all variables in the lhs. 05051 for (dimension_type i = lhs_vars.size(); i-- > 0; ) { 05052 dimension_type lhs_vars_i = lhs_vars[i].id(); 05053 forget_all_octagonal_constraints(lhs_vars_i); 05054 } 05055 // Constrain the left hand side expression so that it is related to 05056 // the right hand side expression as dictated by `relsym'. 05057 // TODO: if the following constraint is NOT an octagonal difference, 05058 // it will be simply ignored. Should we compute approximations for it? 05059 switch (relsym) { 05060 case LESS_OR_EQUAL: 05061 refine_no_check(lhs <= rhs); 05062 break; 05063 case EQUAL: 05064 refine_no_check(lhs == rhs); 05065 break; 05066 case GREATER_OR_EQUAL: 05067 refine_no_check(lhs >= rhs); 05068 break; 05069 default: 05070 // We already dealt with the other cases. 05071 throw std::runtime_error("PPL internal error"); 05072 } 05073 } 05074 else { 05075 // Some variables in `lhs' also occur in `rhs'. 05076 05077 #if 1 // Simplified computation (see the TODO note below). 05078 05079 for (dimension_type i = lhs_vars.size(); i-- > 0; ) { 05080 dimension_type lhs_vars_i = lhs_vars[i].id(); 05081 forget_all_octagonal_constraints(lhs_vars_i); 05082 } 05083 05084 #else // Currently unnecessarily complex computation. 05085 05086 // More accurate computation that is worth doing only if 05087 // the following TODO note is accurately dealt with. 05088 05089 // To ease the computation, we add an additional dimension. 05090 const Variable new_var = Variable(space_dim); 05091 add_space_dimensions_and_embed(1); 05092 // Constrain the new dimension to be equal to `rhs'. 05093 // NOTE: calling affine_image() instead of refine_no_check() 05094 // ensures some approximation is tried even when the constraint 05095 // is not an octagonal constraint. 05096 affine_image(new_var, rhs); 05097 // Existentially quantify all variables in the lhs. 05098 // NOTE: enforce strong closure for precision. 05099 strong_closure_assign(); 05100 assert(!marked_empty()); 05101 for (dimension_type i = lhs_vars.size(); i-- > 0; ) { 05102 dimension_type lhs_vars_i = lhs_vars[i].id(); 05103 forget_all_octagonal_constraints(lhs_vars_i); 05104 } 05105 // Constrain the new dimension so that it is related to 05106 // the left hand side as dictated by `relsym'. 05107 // TODO: each one of the following constraints is definitely NOT 05108 // an octagonal difference (since it has 3 variables at least). 05109 // Thus, the method refine_no_check() will simply ignore it. 05110 // Should we compute approximations for this constraint? 05111 switch (relsym) { 05112 case LESS_OR_EQUAL: 05113 refine_no_check(lhs <= new_var); 05114 break; 05115 case EQUAL: 05116 refine_no_check(lhs == new_var); 05117 break; 05118 case GREATER_OR_EQUAL: 05119 refine_no_check(lhs >= new_var); 05120 break; 05121 default: 05122 // We already dealt with the other cases. 05123 throw std::runtime_error("PPL internal error"); 05124 } 05125 // Remove the temporarily added dimension. 05126 remove_higher_space_dimensions(space_dim-1); 05127 #endif // Currently unnecessarily complex computation. 05128 } 05129 } 05130 05131 assert(OK()); 05132 }
| void Parma_Polyhedra_Library::Octagonal_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 5136 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Octagonal_Shape< T >::deduce_minus_v_pm_u_bounds(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), 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::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), TEMP_INTEGER, Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().
05140 { 05141 // The denominator cannot be zero. 05142 if (denominator == 0) 05143 throw_generic("bounded_affine_image(v, lb, ub, d)", "d == 0"); 05144 05145 // `var' should be one of the dimensions of the octagon. 05146 const dimension_type var_id = var.id(); 05147 if (space_dim < var_id + 1) 05148 throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)", 05149 var.id()+1); 05150 05151 // The dimension of `lb_expr' and `ub_expr' should not be 05152 // greater than the dimension of `*this'. 05153 const dimension_type lb_space_dim = lb_expr.space_dimension(); 05154 if (space_dim < lb_space_dim) 05155 throw_dimension_incompatible("bounded_affine_image(v, lb, ub)", 05156 "lb", lb_expr); 05157 const dimension_type ub_space_dim = ub_expr.space_dimension(); 05158 if (space_dim < ub_space_dim) 05159 throw_dimension_incompatible("bounded_affine_image(v, lb, ub)", 05160 "ub", ub_expr); 05161 05162 strong_closure_assign(); 05163 // The image of an empty octagon is empty too. 05164 if (marked_empty()) 05165 return; 05166 05167 // Number of non-zero coefficients in `lb_expr': will be set to 05168 // 0, 1, or 2, the latter value meaning any value greater than 1. 05169 dimension_type t = 0; 05170 // Variable-index of the last non-zero coefficient in `lb_expr', if any. 05171 dimension_type w_id = 0; 05172 05173 // Get information about the number of non-zero coefficients in `lb_expr'. 05174 // The `expr' must not be in two or plus variables. 05175 for (dimension_type i = lb_space_dim; i-- > 0; ) 05176 if (lb_expr.coefficient(Variable(i)) != 0) { 05177 if (t++ == 1) 05178 break; 05179 else 05180 w_id = i; 05181 } 05182 05183 typedef typename OR_Matrix<N>::row_iterator Row_Iterator; 05184 typedef typename OR_Matrix<N>::row_reference_type Row_Reference; 05185 typedef typename OR_Matrix<N>::const_row_iterator Row_iterator; 05186 typedef typename OR_Matrix<N>::const_row_reference_type Row_reference; 05187 05188 const Row_Iterator m_begin = matrix.row_begin(); 05189 const Row_Iterator m_end = matrix.row_end(); 05190 const dimension_type n_var = 2*var_id; 05191 const Coefficient& b = lb_expr.inhomogeneous_term(); 05192 TEMP_INTEGER(minus_den); 05193 neg_assign_r(minus_den, denominator, ROUND_NOT_NEEDED); 05194 05195 // `w' is the variable with index `w_id'. 05196 // Now we know the form of `lb_expr': 05197 // - If t == 0, then lb_expr == b, with `b' a constant; 05198 // - If t == 1, then lb_expr == a*w + b, where `w' can be `v' or another 05199 // variable; in this second case we have to check whether `a' is 05200 // equal to `denominator' or `-denominator', since otherwise we have 05201 // to fall back on the general form; 05202 // - If t == 2, the `lb_expr' is of the general form. 05203 05204 if (t == 0) { 05205 // Case 1: lb_expr == b. 05206 generalized_affine_image(var, 05207 LESS_OR_EQUAL, 05208 ub_expr, 05209 denominator); 05210 TEMP_INTEGER(two_b); 05211 two_b = 2*b; 05212 // Add the constraint `var >= b/denominator'. 05213 add_octagonal_constraint(n_var, n_var+1, two_b, minus_den); 05214 assert(OK()); 05215 return; 05216 } 05217 05218 if (t == 1) { 05219 // The one and only non-zero homogeneous coefficient in `lb_expr'. 05220 const Coefficient& w_coeff = lb_expr.coefficient(Variable(w_id)); 05221 if (w_coeff == denominator || w_coeff == minus_den) { 05222 // Case 2: lb_expr = w_coeff*w + b, with w_coeff = +/- denominator. 05223 if (w_id == var_id) { 05224 // Here `var' occurs in `lb_expr'. 05225 // To ease the computation, we add an additional dimension. 05226 const Variable new_var = Variable(space_dim); 05227 add_space_dimensions_and_embed(1); 05228 // Constrain the new dimension to be equal to `lb_expr'. 05229 // Here `lb_expr' is of the form: +/- denominator * v + b. 05230 affine_image(new_var, lb_expr, denominator); 05231 // Enforce the strong closure for precision. 05232 strong_closure_assign(); 05233 assert(!marked_empty()); 05234 // Apply the affine upper bound. 05235 generalized_affine_image(var, 05236 LESS_OR_EQUAL, 05237 ub_expr, 05238 denominator); 05239 // Now apply the affine lower bound, as recorded in `new_var' 05240 refine_no_check(var >= new_var); 05241 // Remove the temporarily added dimension. 05242 remove_higher_space_dimensions(space_dim-1); 05243 return; 05244 } 05245 else { 05246 // Apply the affine upper bound. 05247 generalized_affine_image(var, 05248 LESS_OR_EQUAL, 05249 ub_expr, 05250 denominator); 05251 // Here `w != var', so that `lb_expr' is of the form 05252 // +/-denominator * w + b. 05253 const dimension_type n_w = 2*w_id; 05254 // Add the new constraint `var - w >= b/denominator'. 05255 if (w_coeff == denominator) 05256 if (var_id < w_id) 05257 add_octagonal_constraint(n_w+1, n_var+1, b, minus_den); 05258 else 05259 add_octagonal_constraint(n_var, n_w, b, minus_den); 05260 else { 05261 // Add the new constraint `var + w >= b/denominator'. 05262 if (var_id < w_id) 05263 add_octagonal_constraint(n_w, n_var+1, b, minus_den); 05264 else 05265 add_octagonal_constraint(n_var, n_w+1, b, minus_den); 05266 } 05267 assert(OK()); 05268 return; 05269 } 05270 } 05271 } 05272 05273 // General case. 05274 // Either t == 2, so that 05275 // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2, 05276 // or t == 1, expr == a*w + b, but a <> +/- denominator. 05277 // We will remove all the constraints on `var' and add back 05278 // constraints providing upper and lower bounds for `var'. 05279 05280 // Compute upper approximations for `expr' and `-expr' 05281 // into `pos_sum' and `neg_sum', respectively, taking into account 05282 // the sign of `denominator'. 05283 // Note: approximating `-expr' from above and then negating the 05284 // result is the same as approximating `expr' from below. 05285 const bool is_sc = (denominator > 0); 05286 TEMP_INTEGER(minus_b); 05287 neg_assign_r(minus_b, b, ROUND_NOT_NEEDED); 05288 05289 const Coefficient& minus_sc_b = is_sc ? minus_b : b; 05290 const Coefficient& sc_den = is_sc ? denominator : minus_den; 05291 const Coefficient& minus_sc_den = is_sc ? minus_den : denominator; 05292 // NOTE: here, for optimization purposes, `minus_expr' is only assigned 05293 // when `denominator' is negative. Do not use it unless you are sure 05294 // it has been correctly assigned. 05295 Linear_Expression minus_expr; 05296 if (!is_sc) 05297 minus_expr = -lb_expr; 05298 const Linear_Expression& sc_expr = is_sc ? lb_expr : minus_expr; 05299 05300 DIRTY_TEMP(N, neg_sum); 05301 // Indices of the variables that are unbounded in `this->matrix'. 05302 PPL_UNINITIALIZED(dimension_type, neg_pinf_index); 05303 // Number of unbounded variables found. 05304 dimension_type neg_pinf_count = 0; 05305 05306 // Approximate the inhomogeneous term. 05307 assign_r(neg_sum, minus_sc_b, ROUND_UP); 05308 05309 // Approximate the homogeneous part of `sc_expr'. 05310 DIRTY_TEMP(N, coeff_i); 05311 DIRTY_TEMP(N, minus_coeff_i); 05312 DIRTY_TEMP(N, half); 05313 TEMP_INTEGER(minus_sc_i); 05314 // Note: indices above `w' can be disregarded, as they all have 05315 // a zero coefficient in `sc_expr'. 05316 for (Row_iterator m_iter = m_begin, m_iter_end = m_iter + (2*w_id) + 2; 05317 m_iter != m_iter_end; ) { 05318 const dimension_type n_i = m_iter.index(); 05319 const dimension_type id = n_i/2; 05320 Row_reference m_i = *m_iter; 05321 ++m_iter; 05322 Row_reference m_ci = *m_iter; 05323 ++m_iter; 05324 const Coefficient& sc_i = sc_expr.coefficient(Variable(id)); 05325 const int sign_i = sgn(sc_i); 05326 if (sign_i > 0) { 05327 assign_r(coeff_i, sc_i, ROUND_UP); 05328 // Approximating `-sc_expr'. 05329 if (neg_pinf_count <= 1) { 05330 const N& double_up_approx_minus_i = m_i[n_i+1]; 05331 if (!is_plus_infinity(double_up_approx_minus_i)) { 05332 // Let half = double_up_approx_minus_i / 2. 05333 div2exp_assign_r(half, double_up_approx_minus_i, 1, ROUND_UP); 05334 add_mul_assign_r(neg_sum, coeff_i, half, ROUND_UP); 05335 } 05336 else { 05337 ++neg_pinf_count; 05338 neg_pinf_index = id; 05339 } 05340 } 05341 } 05342 else if (sign_i < 0) { 05343 neg_assign_r(minus_sc_i, sc_i, ROUND_NOT_NEEDED); 05344 assign_r(minus_coeff_i, minus_sc_i, ROUND_UP); 05345 // Approximating `-sc_expr'. 05346 if (neg_pinf_count <= 1) { 05347 const N& double_up_approx_i = m_ci[n_i]; 05348 if (!is_plus_infinity(double_up_approx_i)) { 05349 // Let half = double_up_approx_i / 2. 05350 div2exp_assign_r(half, double_up_approx_i, 1, ROUND_UP); 05351 add_mul_assign_r(neg_sum, minus_coeff_i, half, ROUND_UP); 05352 } 05353 else { 05354 ++neg_pinf_count; 05355 neg_pinf_index = id; 05356 } 05357 } 05358 } 05359 } 05360 05361 // Apply the affine upper bound. 05362 generalized_affine_image(var, 05363 LESS_OR_EQUAL, 05364 ub_expr, 05365 denominator); 05366 05367 // Return immediately if no approximation could be computed. 05368 if (neg_pinf_count > 1) { 05369 return; 05370 } 05371 05372 // In the following, strong closure will be definitely lost. 05373 reset_strongly_closed(); 05374 05375 // Exploit the lower approximation, if possible. 05376 if (neg_pinf_count <= 1) { 05377 // Compute quotient (if needed). 05378 if (sc_den != 1) { 05379 // Before computing quotients, the denominator should be approximated 05380 // towards zero. Since `sc_den' is known to be positive, this amounts to 05381 // rounding downwards, which is achieved as usual by rounding upwards 05382 // `minus_sc_den' and negating again the result. 05383 DIRTY_TEMP(N, down_sc_den); 05384 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 05385 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 05386 div_assign_r(neg_sum, neg_sum, down_sc_den, ROUND_UP); 05387 } 05388 // Add the lower bound constraint, if meaningful. 05389 if (neg_pinf_count == 0) { 05390 // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'. 05391 DIRTY_TEMP(N, double_neg_sum); 05392 mul2exp_assign_r(double_neg_sum, neg_sum, 1, ROUND_IGNORE); 05393 matrix[n_var][n_var+1] = double_neg_sum; 05394 // Deduce constraints of the form `-v +/- u', where `u != v'. 05395 deduce_minus_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, neg_sum); 05396 } 05397 else 05398 // Here `neg_pinf_count == 1'. 05399 if (neg_pinf_index != var_id) { 05400 const Coefficient& npi = sc_expr.coefficient(Variable(neg_pinf_index)); 05401 if (npi == sc_den) 05402 // Add the constraint `v - neg_pinf_index >= -neg_sum', 05403 // i.e., `neg_pinf_index - v <= neg_sum'. 05404 if (neg_pinf_index < var_id) 05405 matrix[n_var][2*neg_pinf_index] = neg_sum; 05406 else 05407 matrix[2*neg_pinf_index+1][n_var+1] = neg_sum; 05408 else 05409 if (npi == minus_sc_den) { 05410 // Add the constraint `v + neg_pinf_index >= -neg_sum', 05411 // i.e., `-neg_pinf_index - v <= neg_sum'. 05412 if (neg_pinf_index < var_id) 05413 matrix[n_var][2*neg_pinf_index+1] = neg_sum; 05414 else 05415 matrix[2*neg_pinf_index][n_var+1] = neg_sum; 05416 } 05417 } 05418 } 05419 05420 assert(OK()); 05421 }
| void Parma_Polyhedra_Library::Octagonal_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 5427 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_all_octagonal_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), TEMP_INTEGER, Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage().
05431 { 05432 // The denominator cannot be zero. 05433 if (denominator == 0) 05434 throw_generic("generalized_affine_preimage(v, r, e, d)", "d == 0"); 05435 05436 // Dimension-compatibility checks. 05437 // The dimension of `expr' should not be greater than the dimension 05438 // of `*this'. 05439 const dimension_type expr_space_dim = expr.space_dimension(); 05440 if (space_dim < expr_space_dim) 05441 throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)", 05442 "e", expr); 05443 05444 // `var' should be one of the dimensions of the octagon. 05445 const dimension_type var_id = var.id(); 05446 if (space_dim < var_id + 1) 05447 throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)", 05448 var.id()+1); 05449 05450 // The relation symbol cannot be a strict relation symbol. 05451 if (relsym == LESS_THAN || relsym == GREATER_THAN) 05452 throw_generic("generalized_affine_preimage(v, r, e, d)", 05453 "r is a strict relation symbol and " 05454 "*this is an Octagonal_Shape"); 05455 05456 if (relsym == EQUAL) { 05457 // The relation symbol is "==": 05458 // this is just an affine preimage computation. 05459 affine_preimage(var, expr, denominator); 05460 return; 05461 } 05462 05463 // The image of an empty octagon is empty too. 05464 strong_closure_assign(); 05465 if (marked_empty()) 05466 return; 05467 05468 // Check whether the preimage of this affine relation can be easily 05469 // computed as the image of its inverse relation. 05470 const Coefficient& expr_v = expr.coefficient(var); 05471 if (expr_v != 0) { 05472 const Relation_Symbol reversed_relsym = (relsym == LESS_OR_EQUAL) 05473 ? GREATER_OR_EQUAL : LESS_OR_EQUAL; 05474 const Linear_Expression inverse 05475 = expr - (expr_v + denominator)*var; 05476 TEMP_INTEGER(inverse_den); 05477 neg_assign(inverse_den, expr_v); 05478 const Relation_Symbol inverse_relsym 05479 = (sgn(denominator) == sgn(inverse_den)) ? relsym : reversed_relsym; 05480 generalized_affine_image(var, inverse_relsym, inverse, inverse_den); 05481 return; 05482 } 05483 05484 // Here `var_coefficient == 0', so that the preimage cannot 05485 // be easily computed by inverting the affine relation. 05486 // Shrink the Octagonal_Shape by adding the constraint induced 05487 // by the affine relation. 05488 refine(var, relsym, expr, denominator); 05489 05490 // If the shrunk OS is empty, its preimage is empty too; ... 05491 if (is_empty()) 05492 return; 05493 // ... otherwise, since the relation was not invertible, 05494 // we just forget all constraints on `var'. 05495 forget_all_octagonal_constraints(var_id); 05496 assert(OK()); 05497 }
| void Parma_Polyhedra_Library::Octagonal_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 generalized 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 5502 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_all_octagonal_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_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::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().
05504 { 05505 // Dimension-compatibility checks. 05506 // The dimension of `lhs' should not be greater than the dimension 05507 // of `*this'. 05508 dimension_type lhs_space_dim = lhs.space_dimension(); 05509 if (space_dim < lhs_space_dim) 05510 throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)", 05511 "e1", lhs); 05512 05513 // The dimension of `rhs' should not be greater than the dimension 05514 // of `*this'. 05515 const dimension_type rhs_space_dim = rhs.space_dimension(); 05516 if (space_dim < rhs_space_dim) 05517 throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)", 05518 "e2", rhs); 05519 05520 // Strict relation symbols are not admitted for octagons. 05521 if (relsym == LESS_THAN || relsym == GREATER_THAN) 05522 throw_generic("generalized_affine_preimage(e1, r, e2)", 05523 "r is a strict relation symbol and " 05524 "*this is an Octagonal_Shape"); 05525 05526 strong_closure_assign(); 05527 // The image of an empty octagon is empty. 05528 if (marked_empty()) 05529 return; 05530 05531 // Number of non-zero coefficients in `lhs': will be set to 05532 // 0, 1, or 2, the latter value meaning any value greater than 1. 05533 dimension_type t_lhs = 0; 05534 // Index of the last non-zero coefficient in `lhs', if any. 05535 dimension_type j_lhs = 0; 05536 05537 // Compute the number of the non-zero components of `lhs'. 05538 for (dimension_type i = lhs_space_dim; i-- > 0; ) 05539 if (lhs.coefficient(Variable(i)) != 0) { 05540 if (t_lhs++ == 1) 05541 break; 05542 else 05543 j_lhs = i; 05544 } 05545 05546 const Coefficient& b_lhs = lhs.inhomogeneous_term(); 05547 05548 // If all variables have a zero coefficient, then `lhs' is a constant: 05549 // in this case, preimage and image happen to be the same. 05550 if (t_lhs == 0) { 05551 generalized_affine_image(lhs, relsym, rhs); 05552 return; 05553 } 05554 05555 else if (t_lhs == 1) { 05556 // Here `lhs == a_lhs * v + b_lhs'. 05557 // Independently from the form of `rhs', we can exploit the 05558 // method computing generalized affine preimages for a single variable. 05559 Variable v(j_lhs); 05560 // Compute a sign-corrected relation symbol. 05561 const Coefficient& den = lhs.coefficient(v); 05562 Relation_Symbol new_relsym = relsym; 05563 if (den < 0) { 05564 if (relsym == LESS_OR_EQUAL) 05565 new_relsym = GREATER_OR_EQUAL; 05566 else if (relsym == GREATER_OR_EQUAL) 05567 new_relsym = LESS_OR_EQUAL; 05568 } 05569 Linear_Expression expr = rhs - b_lhs; 05570 generalized_affine_preimage(v, new_relsym, expr, den); 05571 } 05572 05573 else { 05574 // Here `lhs' is of the general form, having at least two variables. 05575 // Compute the set of variables occurring in `lhs'. 05576 bool lhs_vars_intersects_rhs_vars = false; 05577 std::vector<Variable> lhs_vars; 05578 for (dimension_type i = lhs_space_dim; i-- > 0; ) 05579 if (lhs.coefficient(Variable(i)) != 0) { 05580 lhs_vars.push_back(Variable(i)); 05581 if (rhs.coefficient(Variable(i)) != 0) 05582 lhs_vars_intersects_rhs_vars = true; 05583 } 05584 05585 if (!lhs_vars_intersects_rhs_vars) { 05586 // `lhs' and `rhs' variables are disjoint. 05587 // Constrain the left hand side expression so that it is related to 05588 // the right hand side expression as dictated by `relsym'. 05589 // TODO: if the following constraint is NOT an octagonal difference, 05590 // it will be simply ignored. Should we compute approximations for it? 05591 switch (relsym) { 05592 case LESS_OR_EQUAL: 05593 refine_no_check(lhs <= rhs); 05594 break; 05595 case EQUAL: 05596 refine_no_check(lhs == rhs); 05597 break; 05598 case GREATER_OR_EQUAL: 05599 refine_no_check(lhs >= rhs); 05600 break; 05601 default: 05602 // We already dealt with the other cases. 05603 throw std::runtime_error("PPL internal error"); 05604 } 05605 05606 // Any image of an empty octagon is empty. 05607 if (is_empty()) 05608 return; 05609 // Existentially quantify all variables in the lhs. 05610 for (dimension_type i = lhs_vars.size(); i-- > 0; ) { 05611 dimension_type lhs_vars_i = lhs_vars[i].id(); 05612 forget_all_octagonal_constraints(lhs_vars_i); 05613 } 05614 } 05615 else { 05616 // Some variables in `lhs' also occur in `rhs'. 05617 05618 // More accurate computation that is worth doing only if 05619 // the following TODO note is accurately dealt with. 05620 05621 // To ease the computation, we add an additional dimension. 05622 const Variable new_var = Variable(space_dim); 05623 add_space_dimensions_and_embed(1); 05624 // Constrain the new dimension to be equal to `rhs'. 05625 // NOTE: calling affine_image() instead of refine_no_check() 05626 // ensures some approximation is tried even when the constraint 05627 // is not an octagonal difference. 05628 affine_image(new_var, lhs); 05629 // Existentially quantify all variables in the lhs. 05630 // NOTE: enforce strong closure for precision. 05631 strong_closure_assign(); 05632 assert(!marked_empty()); 05633 for (dimension_type i = lhs_vars.size(); i-- > 0; ) { 05634 dimension_type lhs_vars_i = lhs_vars[i].id(); 05635 forget_all_octagonal_constraints(lhs_vars_i); 05636 } 05637 // Constrain the new dimension so that it is related to 05638 // the left hand side as dictated by `relsym'. 05639 // Note: if `rhs == v + b_rhs' or `rhs == -v + b_rhs' or `rhs == b_rhs', 05640 // one of the following constraints will be added, because they 05641 // are octagonal differences. 05642 // Else the following constraints are NOT octagonal differences, 05643 // so the method refine_no_check() will ignore them. 05644 switch (relsym) { 05645 case LESS_OR_EQUAL: 05646 refine_no_check(new_var <= rhs); 05647 break; 05648 case EQUAL: 05649 refine_no_check(new_var == rhs); 05650 break; 05651 case GREATER_OR_EQUAL: 05652 refine_no_check(new_var >= rhs); 05653 break; 05654 default: 05655 // We already dealt with the other cases. 05656 throw std::runtime_error("PPL internal error"); 05657 } 05658 // Remove the temporarily added dimension. 05659 remove_higher_space_dimensions(space_dim-1); 05660 } 05661 } 05662 assert(OK()); 05663 }
| void Parma_Polyhedra_Library::Octagonal_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 5667 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), TEMP_INTEGER, Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().
05671 { 05672 // The denominator cannot be zero. 05673 if (denominator == 0) 05674 throw_generic("bounded_affine_preimage(v, lb, ub, d)", "d == 0"); 05675 05676 // `var' should be one of the dimensions of the octagon. 05677 const dimension_type var_id = var.id(); 05678 if (space_dim < var_id + 1) 05679 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)", 05680 var.id()+1); 05681 05682 // The dimension of `lb_expr' and `ub_expr' should not be 05683 // greater than the dimension of `*this'. 05684 const dimension_type lb_space_dim = lb_expr.space_dimension(); 05685 if (space_dim < lb_space_dim) 05686 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)", 05687 "lb", lb_expr); 05688 const dimension_type ub_space_dim = ub_expr.space_dimension(); 05689 if (space_dim < ub_space_dim) 05690 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)", 05691 "ub", ub_expr); 05692 05693 strong_closure_assign(); 05694 // The image of an empty octagon is empty too. 05695 if (marked_empty()) 05696 return; 05697 05698 if (ub_expr.coefficient(var) == 0) { 05699 refine(var, LESS_OR_EQUAL, ub_expr, denominator); 05700 generalized_affine_preimage(var, GREATER_OR_EQUAL, 05701 lb_expr, denominator); 05702 return; 05703 } 05704 if (lb_expr.coefficient(var) == 0) { 05705 refine(var, GREATER_OR_EQUAL, lb_expr, denominator); 05706 generalized_affine_preimage(var, LESS_OR_EQUAL, 05707 ub_expr, denominator); 05708 return; 05709 } 05710 05711 const Coefficient& expr_v = lb_expr.coefficient(var); 05712 // Here `var' occurs in `lb_expr' and `ub_expr'. 05713 // To ease the computation, we add an additional dimension. 05714 const Variable new_var = Variable(space_dim); 05715 add_space_dimensions_and_embed(1); 05716 const Linear_Expression lb_inverse 05717 = lb_expr - (expr_v + denominator)*var; 05718 TEMP_INTEGER(inverse_den); 05719 neg_assign(inverse_den, expr_v); 05720 affine_image(new_var, lb_inverse, inverse_den); 05721 strong_closure_assign(); 05722 assert(!marked_empty()); 05723 generalized_affine_preimage(var, LESS_OR_EQUAL, 05724 ub_expr, denominator); 05725 if (sgn(denominator) == sgn(inverse_den)) 05726 refine_no_check(var >= new_var) ; 05727 else 05728 refine_no_check(var <= new_var); 05729 // Remove the temporarily added dimension. 05730 remove_higher_space_dimensions(space_dim-1); 05731 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::time_elapse_assign | ( | const Octagonal_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 569 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::swap(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Polyhedron::time_elapse_assign().
00569 { 00570 // Dimension-compatibility check. 00571 if (space_dimension() != y.space_dimension()) 00572 throw_dimension_incompatible("time_elapse_assign(y)", y); 00573 // See the polyhedra documentation. 00574 C_Polyhedron px(constraints()); 00575 C_Polyhedron py(y.constraints()); 00576 px.time_elapse_assign(py); 00577 Octagonal_Shape<T> x(px); 00578 swap(x); 00579 assert(OK()); 00580 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::topological_closure_assign | ( | ) | [inline] |
Assigns to *this its topological closure.
Definition at line 305 of file Octagonal_Shape.inlines.hh.
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign | ( | const Octagonal_Shape< T > & | y, | |
| unsigned * | tp = 0 | |||
| ) | [inline] |
Assigns to *this the result of computing the CC76-extrapolation between *this and y.
| y | An OS 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 551 of file Octagonal_Shape.inlines.hh.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_CC76_extrapolation_assign().
00552 { 00553 static N stop_points[] = { 00554 N(-2, ROUND_UP), 00555 N(-1, ROUND_UP), 00556 N( 0, ROUND_UP), 00557 N( 1, ROUND_UP), 00558 N( 2, ROUND_UP) 00559 }; 00560 CC76_extrapolation_assign(y, 00561 stop_points, 00562 stop_points 00563 + sizeof(stop_points)/sizeof(stop_points[0]), 00564 tp); 00565 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign | ( | const Octagonal_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 | An OS that must be contained in *this. | |
| first | An iterator that points to the first stop_point. | |
| last | An iterator that points to 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 2698 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), PLUS_INFINITY, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
02700 { 02701 // Dimension-compatibility check. 02702 if (space_dim != y.space_dim) 02703 throw_dimension_incompatible("CC76_extrapolation_assign(y)", y); 02704 02705 #ifndef NDEBUG 02706 { 02707 // We assume that `y' is contained in or equal to `*this'. 02708 const Octagonal_Shape x_copy = *this; 02709 const Octagonal_Shape y_copy = y; 02710 assert(x_copy.contains(y_copy)); 02711 } 02712 #endif 02713 02714 // If both octagons are zero-dimensional, 02715 // since `*this' contains `y', we simply return `*this'. 02716 if (space_dim == 0) 02717 return; 02718 02719 strong_closure_assign(); 02720 // If `*this' is empty, since `*this' contains `y', `y' is empty too. 02721 if (marked_empty()) 02722 return; 02723 y.strong_closure_assign(); 02724 // If `y' is empty, we return. 02725 if (y.marked_empty()) 02726 return; 02727 02728 // If there are tokens available, work on a temporary copy. 02729 if (tp != 0 && *tp > 0) { 02730 Octagonal_Shape x_tmp(*this); 02731 x_tmp.CC76_extrapolation_assign(y, first, last, 0); 02732 // If the widening was not precise, use one of the available tokens. 02733 if (!contains(x_tmp)) 02734 --(*tp); 02735 return; 02736 } 02737 02738 // Compare each constraint in `y' to the corresponding one in `*this'. 02739 // The constraint in `*this' is kept as is if it is stronger than or 02740 // equal to the constraint in `y'; otherwise, the inhomogeneous term 02741 // of the constraint in `*this' is further compared with elements taken 02742 // from a sorted container (the stop-points, provided by the user), and 02743 // is replaced by the first entry, if any, which is greater than or equal 02744 // to the inhomogeneous term. If no such entry exists, the constraint 02745 // is removed altogether. 02746 typename OR_Matrix<N>::const_element_iterator j = y.matrix.element_begin(); 02747 for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(), 02748 matrix_element_end = matrix.element_end(); 02749 i != matrix_element_end; 02750 ++i, ++j) { 02751 const N& y_elem = *j; 02752 N& elem = *i; 02753 if (y_elem < elem) { 02754 Iterator k = std::lower_bound(first, last, elem); 02755 if (k != last) { 02756 if (elem < *k) 02757 assign_r(elem, *k, ROUND_UP); 02758 } 02759 else 02760 assign_r(elem, PLUS_INFINITY, ROUND_NOT_NEEDED); 02761 } 02762 } 02763 02764 reset_strongly_closed(); 02765 assert(OK()); 02766 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign | ( | const Octagonal_Shape< T > & | y, | |
| unsigned * | tp = 0 | |||
| ) | [inline] |
Assigns to *this the result of computing the BHMZ05-widening between *this and y.
| y | An OS 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 2898 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_dimension(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), PLUS_INFINITY, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_BHMZ05_extrapolation_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::widening_assign().
02899 { 02900 // Dimension-compatibility check. 02901 if (space_dim != y.space_dim) 02902 throw_dimension_incompatible("BHMZ05_widening_assign(y)", y); 02903 02904 #ifndef NDEBUG 02905 { 02906 // We assume that `y' is contained in or equal to `*this'. 02907 const Octagonal_Shape x_copy = *this; 02908 const Octagonal_Shape y_copy = y; 02909 assert(x_copy.contains(y_copy)); 02910 } 02911 #endif 02912 02913 // Compute the affine dimension of `y'. 02914 const dimension_type y_affine_dim = y.affine_dimension(); 02915 // If the affine dimension of `y' is zero, then either `y' is 02916 // zero-dimensional, or it is empty, or it is a singleton. 02917 // In all cases, due to the inclusion hypothesis, the result is `*this'. 02918 if (y_affine_dim == 0) 02919 return; 02920 02921 // If the affine dimension has changed, due to the inclusion hypothesis, 02922 // the result is `*this'. 02923 const dimension_type x_affine_dim = affine_dimension(); 02924 assert(x_affine_dim >= y_affine_dim); 02925 if (x_affine_dim != y_affine_dim) 02926 return; 02927 02928 // If there are tokens available, work on a temporary copy. 02929 if (tp != 0 && *tp > 0) { 02930 Octagonal_Shape x_tmp(*this); 02931 x_tmp.BHMZ05_widening_assign(y, 0); 02932 // If the widening was not precise, use one of the available tokens. 02933 if (!contains(x_tmp)) 02934 --(*tp); 02935 return; 02936 } 02937 02938 // Here no token is available. 02939 assert(marked_strongly_closed() && y.marked_strongly_closed()); 02940 // Minimize `y'. 02941 y.strong_reduction_assign(); 02942 02943 // Extrapolate unstable bounds. 02944 typename OR_Matrix<N>::const_element_iterator j = y.matrix.element_begin(); 02945 for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(), 02946 matrix_element_end = matrix.element_end(); 02947 i != matrix_element_end; 02948 ++i, ++j) { 02949 N& elem = *i; 02950 // Note: in the following line the use of `!=' (as opposed to 02951 // the use of `<' that would seem -but is not- equivalent) is 02952 // intentional. 02953 if (*j != elem) 02954 assign_r(elem, PLUS_INFINITY, ROUND_NOT_NEEDED); 02955 } 02956 reset_strongly_closed(); 02957 assert(OK()); 02958 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::widening_assign | ( | const Octagonal_Shape< T > & | y, | |
| unsigned * | tp = 0 | |||
| ) | [inline] |
Same as BHMZ05_widening_assign(y, tp).
Definition at line 545 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign().
00545 { 00546 BHMZ05_widening_assign(y, tp); 00547 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_BHMZ05_extrapolation_assign | ( | const Octagonal_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 | An OS that must be contained in *this. | |
| cs | The system of constraints used to improve the widened OS. | |
| 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 there is in cs a strict inequality. |
Definition at line 2963 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::get_limiting_octagon(), Parma_Polyhedra_Library::Constraint_System::has_strict_inequalities(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_constraint_incompatible(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::UNIVERSE.
02965 { 02966 02967 // Dimension-compatibility check. 02968 if (space_dim != y.space_dim) 02969 throw_dimension_incompatible("limited_BHMZ05_extrapolation_assign(y, cs)", 02970 y); 02971 // `cs' must be dimension-compatible with the two octagons. 02972 const dimension_type cs_space_dim = cs.space_dimension(); 02973 if (space_dim < cs_space_dim) 02974 throw_constraint_incompatible("limited_CH78_extrapolation_assign(y, cs)"); 02975 02976 // Strict inequalities not allowed. 02977 if (cs.has_strict_inequalities()) 02978 throw_constraint_incompatible("limited_CH78_extrapolation_assign(y, cs)"); 02979 02980 // The limited BHMZ05-extrapolation between two octagons in a 02981 // zero-dimensional space is a octagon in a zero-dimensional 02982 // space, too. 02983 if (space_dim == 0) 02984 return; 02985 02986 #ifndef NDEBUG 02987 { 02988 // We assume that `y' is contained in or equal to `*this'. 02989 const Octagonal_Shape x_copy = *this; 02990 const Octagonal_Shape y_copy = y; 02991 assert(x_copy.contains(y_copy)); 02992 } 02993 #endif 02994 02995 // If `*this' is empty, since `*this' contains `y', `y' is empty too. 02996 if (marked_empty()) 02997 return; 02998 // If `y' is empty, we return. 02999 if (y.marked_empty()) 03000 return; 03001 03002 Octagonal_Shape limiting_octagon(space_dim, UNIVERSE); 03003 get_limiting_octagon(cs, limiting_octagon); 03004 BHMZ05_widening_assign(y, tp); 03005 intersection_assign(limiting_octagon); 03006 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign | ( | const Octagonal_Shape< T > & | y | ) | [inline] |
Restores from y the constraints of *this, lost by CC76-extrapolation applications.
| y | An OS that must contain *this. |
| std::invalid_argument | Thrown if *this and y are dimension-incompatible. |
Definition at line 3010 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
03010 { 03011 // Dimension-compatibility check. 03012 if (space_dim != y.space_dim) 03013 throw_dimension_incompatible("CC76_narrowing_assign(y)", y); 03014 03015 #ifndef NDEBUG 03016 { 03017 // We assume that `*this' is contained in or equal to `y'. 03018 const Octagonal_Shape x_copy = *this; 03019 const Octagonal_Shape y_copy = y; 03020 assert(y_copy.contains(x_copy)); 03021 } 03022 #endif 03023 03024 // If both octagons are zero-dimensional, since `*this' contains `y', 03025 // we simply return '*this'. 03026 if (space_dim == 0) 03027 return; 03028 03029 y.strong_closure_assign(); 03030 // If `y' is empty, since `y' contains `*this', `*this' is empty too. 03031 if (y.marked_empty()) 03032 return; 03033 strong_closure_assign(); 03034 // If `*this' is empty, we return. 03035 if (marked_empty()) 03036 return; 03037 03038 // We consider a constraint of `*this', if its value is `plus_infinity', 03039 // we take the value of the corresponding constraint of `y'. 03040 bool is_oct_changed = false; 03041 typename OR_Matrix<N>::const_element_iterator j = y.matrix.element_begin(); 03042 for (typename OR_Matrix<N>::element_iterator i = matrix.element_begin(), 03043 matrix_element_end = matrix.element_end(); 03044 i != matrix_element_end; 03045 ++i, ++j) { 03046 if (!is_plus_infinity(*i) 03047 && !is_plus_infinity(*j) 03048 && *i != *j) { 03049 *i = *j; 03050 is_oct_changed = true; 03051 } 03052 } 03053 03054 if (is_oct_changed && marked_strongly_closed()) 03055 reset_strongly_closed(); 03056 assert(OK()); 03057 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_CC76_extrapolation_assign | ( | const Octagonal_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 | An OS that must be contained in *this. | |
| cs | The system of constraints used to improve the widened OS. | |
| 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 2851 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::get_limiting_octagon(), Parma_Polyhedra_Library::Constraint_System::has_strict_inequalities(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_constraint_incompatible(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::UNIVERSE.
02853 { 02854 02855 // Dimension-compatibility check. 02856 if (space_dim != y.space_dim) 02857 throw_dimension_incompatible("limited_CC76_extrapolation_assign(y, cs)", 02858 y); 02859 // `cs' must be dimension-compatible with the two octagons. 02860 const dimension_type cs_space_dim = cs.space_dimension(); 02861 if (space_dim < cs_space_dim) 02862 throw_constraint_incompatible("limited_CC76_extrapolation_assign(y, cs)"); 02863 02864 // Strict inequalities not allowed. 02865 if (cs.has_strict_inequalities()) 02866 throw_constraint_incompatible("limited_CC76_extrapolation_assign(y, cs)"); 02867 02868 // The limited CC76-extrapolation between two octagons in a 02869 // zero-dimensional space is a octagon in a zero-dimensional 02870 // space, too. 02871 if (space_dim == 0) 02872 return; 02873 02874 #ifndef NDEBUG 02875 { 02876 // We assume that `y' is contained in or equal to `*this'. 02877 const Octagonal_Shape x_copy = *this; 02878 const Octagonal_Shape y_copy = y; 02879 assert(x_copy.contains(y_copy)); 02880 } 02881 #endif 02882 02883 // If `*this' is empty, since `*this' contains `y', `y' is empty too. 02884 if (marked_empty()) 02885 return; 02886 // If `y' is empty, we return. 02887 if (y.marked_empty()) 02888 return; 02889 02890 Octagonal_Shape limiting_octagon(space_dim, UNIVERSE); 02891 get_limiting_octagon(cs, limiting_octagon); 02892 CC76_extrapolation_assign(y, tp); 02893 intersection_assign(limiting_octagon); 02894 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed | ( | dimension_type | m | ) | [inline] |
Adds m new dimensions and embeds the old OS into the new space.
| m | The number of dimensions to add. |
and adding a third dimension, the result will be the OS
Definition at line 2442 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage().
02442 { 02443 // Adding no dimensions is a no-op. 02444 if (m == 0) 02445 return; 02446 02447 const dimension_type new_dim = space_dim + m; 02448 const bool was_zero_dim_univ = !marked_empty() && space_dim == 0; 02449 02450 // To embed an n-dimension space octagon in a (n+m)-dimension space, 02451 // we just add `m' variables in the matrix of constraints. 02452 matrix.grow(new_dim); 02453 space_dim = new_dim; 02454 // If `*this' was the zero-dim space universe octagon, 02455 // then we can set the strongly closure flag. 02456 if (was_zero_dim_univ) 02457 set_strongly_closed(); 02458 02459 assert(OK()); 02460 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_project | ( | dimension_type | m | ) | [inline] |
Adds m new dimensions to the OS and does not embed it in the new space.
| m | The number of dimensions to add. |
and adding a third dimension, the result will be the OS
Definition at line 2464 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed().
02464 { 02465 // Adding no dimensions is a no-op. 02466 if (m == 0) 02467 return; 02468 02469 const dimension_type n = matrix.num_rows(); 02470 02471 // To project an n-dimension space OS in a (space_dim+m)-dimension space, 02472 // we just add `m' columns and rows in the matrix of constraints. 02473 add_space_dimensions_and_embed(m); 02474 // We insert 0 where it needs. 02475 // Attention: now num_rows of matrix is update! 02476 for (typename OR_Matrix<N>::row_iterator i = matrix.row_begin() + n, 02477 matrix_row_end = matrix.row_end(); i != matrix_row_end; i += 2) { 02478 typename OR_Matrix<N>::row_reference_type x_i = *i; 02479 typename OR_Matrix<N>::row_reference_type x_ci = *(i+1); 02480 const dimension_type ind = i.index(); 02481 assign_r(x_i[ind+1], 0, ROUND_NOT_NEEDED); 02482 assign_r(x_ci[ind], 0, ROUND_NOT_NEEDED); 02483 } 02484 02485 if (marked_strongly_closed()) 02486 reset_strongly_closed(); 02487 assert(OK()); 02488 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::concatenate_assign | ( | const Octagonal_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 665 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim.
00665 { 00666 // If `y' is an empty 0-dim space octagon, let `*this' become empty. 00667 // If `y' is an universal 0-dim space octagon, we simply return. 00668 if (y.space_dim == 0) { 00669 if (y.marked_empty()) 00670 set_empty(); 00671 return; 00672 } 00673 00674 // If `*this' is an empty 0-dim space octagon, then it is sufficient 00675 // to adjust the dimension of the vector space. 00676 if (space_dim == 0 && marked_empty()) { 00677 add_space_dimensions_and_embed(y.space_dim); 00678 return; 00679 } 00680 00681 // This is the old number of rows in the matrix. It is equal to 00682 // the first index of columns to change. 00683 dimension_type old_num_rows = matrix.num_rows(); 00684 // First we increase the space dimension of `*this' by adding 00685 // `y.space_dimension()' new dimensions. 00686 // The matrix for the new octagon is obtained 00687 // by leaving the old system of constraints in the upper left-hand side 00688 // (where they are at the present) and placing the constraints of `y' in the 00689 // lower right-hand side. 00690 add_space_dimensions_and_embed(y.space_dim); 00691 typename OR_Matrix<N>::const_element_iterator 00692 y_it = y.matrix.element_begin(); 00693 for(typename OR_Matrix<N>::row_iterator i = matrix.row_begin()+old_num_rows, 00694 matrix_row_end = matrix.row_end(); i != matrix_row_end; ++i) { 00695 typename OR_Matrix<N>::row_reference_type r = *i; 00696 dimension_type rs_i = i.row_size(); 00697 for (dimension_type j = old_num_rows; j < rs_i; ++j, ++y_it) 00698 r[j] = *y_it; 00699 } 00700 00701 // The concatenation doesn't preserve the closure. 00702 if (marked_strongly_closed()) 00703 reset_strongly_closed(); 00704 assert(OK()); 00705 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions | ( | const Variables_Set & | to_be_removed | ) | [inline] |
Removes all the specified dimensions.
| to_be_removed | 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 to_be_removed. |
Definition at line 2493 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_zero_dim_univ(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::fold_space_dimensions().
02493 { 02494 // The removal of no dimensions from any octagon is a no-op. 02495 // Note that this case also captures the only legal removal of 02496 // dimensions from a octagon in a 0-dim space. 02497 if (to_be_removed.empty()) { 02498 assert(OK()); 02499 return; 02500 } 02501 02502 // Dimension-compatibility check. 02503 const dimension_type min_space_dim = to_be_removed.space_dimension(); 02504 if (space_dim < min_space_dim) 02505 throw_dimension_incompatible("remove_space_dimensions(vs)", min_space_dim); 02506 02507 const dimension_type new_space_dim = space_dim - to_be_removed.size(); 02508 02509 strong_closure_assign(); 02510 // When removing _all_ dimensions from an octagon, 02511 // we obtain the zero-dimensional octagon. 02512 if (new_space_dim == 0) { 02513 matrix.shrink(0); 02514 if (!marked_empty()) 02515 // We set the zero_dim_univ flag. 02516 set_zero_dim_univ(); 02517 space_dim = 0; 02518 assert(OK()); 02519 return; 02520 } 02521 02522 // We consider every variable and we check if it is to be removed. 02523 // If it is to be removed, we pass to the successive one, elsewhere 02524 // we move its elements in the right position. 02525 Variables_Set::const_iterator tbr = to_be_removed.begin(); 02526 dimension_type ftr = *tbr; 02527 dimension_type ftr_size = 2*ftr*(ftr+1); 02528 typename OR_Matrix<N>::element_iterator 02529 iter = matrix.element_begin()+ftr_size; 02530 02531 dimension_type i = ftr + 1; 02532 while (i < space_dim) { 02533 if (to_be_removed.count(i) != 0) 02534 ++i; 02535 else { 02536 typename OR_Matrix<N>::row_iterator 02537 row_iter = matrix.row_begin()+2*i; 02538 typename OR_Matrix<N>::row_reference_type 02539 row_ref = *row_iter; 02540 typename OR_Matrix<N>::row_reference_type 02541 row_ref1 = *(++row_iter); 02542 // If variable(j) is to remove, we pass another variable, 02543 // else we shift its cells to up right. 02544 // Attention: first we shift the cells corrispondent to the first 02545 // row of variable(j), then we shift the cells corrispondent to the 02546 // second row. We recall that every variable is represented 02547 // in the `matrix' by two rows and two rows. 02548 for (dimension_type j = 0; j <= i; ++j) 02549 if (to_be_removed.count(j) == 0) { 02550 assign_or_swap(*(iter++), row_ref[2*j]); 02551 assign_or_swap(*(iter++), row_ref[2*j+1]); 02552 } 02553 for (dimension_type j = 0; j <= i; ++j) 02554 if (to_be_removed.count(j) == 0) { 02555 assign_or_swap(*(iter++), row_ref1[2*j]); 02556 assign_or_swap(*(iter++), row_ref1[2*j+1]); 02557 } 02558 ++i; 02559 } 02560 } 02561 // Update the space dimension. 02562 matrix.shrink(new_space_dim); 02563 space_dim = new_space_dim; 02564 assert(OK()); 02565 }
| void Parma_Polyhedra_Library::Octagonal_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 520 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_zero_dim_univ(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::map_space_dimensions().
00520 { 00521 // Dimension-compatibility check. 00522 if (new_dimension > space_dim) 00523 throw_dimension_incompatible("remove_higher_space_dimension(nd)", 00524 new_dimension); 00525 // The removal of no dimensions from any octagon is a no-op. 00526 // Note that this case also captures the only legal removal of 00527 // dimensions from an octagon in a 0-dim space. 00528 if (new_dimension == space_dim) { 00529 assert(OK()); 00530 return; 00531 } 00532 00533 strong_closure_assign(); 00534 matrix.shrink(new_dimension); 00535 // When we remove all dimensions from a non-empty octagon, 00536 // we obtain the zero-dimensional universe octagon. 00537 if (new_dimension == 0 && !marked_empty()) 00538 set_zero_dim_univ(); 00539 space_dim = new_dimension; 00540 assert(OK()); 00541 }
| void Parma_Polyhedra_Library::Octagonal_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. |
bool has_empty_codomain() const
true if and only if the represented partial function has an empty codomain (i.e., it is always undefined). The has_empty_codomain() method will always be called before the methods below. However, if has_empty_codomain() returns true, none of the functions below will be called. dimension_type max_in_codomain() const
bool maps(dimension_type i, dimension_type& j) const
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 2570 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::OR_Matrix< T >::row_end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::swap().
02570 { 02571 if (space_dim == 0) 02572 return; 02573 02574 if (pfunc.has_empty_codomain()) { 02575 // All dimensions vanish: the octagon becomes zero_dimensional. 02576 remove_higher_space_dimensions(0); 02577 return; 02578 } 02579 02580 const dimension_type new_space_dim = pfunc.max_in_codomain() + 1; 02581 // If we are going to actually reduce the space dimension, 02582 // then shortest-path closure is required to keep precision. 02583 if (new_space_dim < space_dim) 02584 strong_closure_assign(); 02585 02586 // If the octagon is empty, then it is sufficient to adjust 02587 // the space dimension of the octagon. 02588 if (marked_empty()) { 02589 remove_higher_space_dimensions(new_space_dim); 02590 return; 02591 } 02592 02593 // We create a new matrix with the new space dimension. 02594 OR_Matrix<N> x(new_space_dim); 02595 02596 typedef typename OR_Matrix<N>::row_iterator Row_Iterator; 02597 typedef typename OR_Matrix<N>::row_reference_type Row_Reference; 02598 02599 Row_Iterator m_begin = x.row_begin(); 02600 Row_Iterator m_end = x.row_end(); 02601 02602 for (Row_Iterator i_iter = matrix.row_begin(), i_end = matrix.row_end(); 02603 i_iter != i_end; i_iter += 2) { 02604 dimension_type new_i; 02605 dimension_type i = i_iter.index()/2; 02606 // We copy and place in the position into `x' the only cells of 02607 // the `matrix' that refer to both mapped variables, 02608 // the variable `i' and `j'. 02609 if (pfunc.maps(i, new_i)) { 02610 Row_Reference r_i = *i_iter; 02611 Row_Reference r_ii = *(i_iter + 1); 02612 dimension_type double_new_i = 2*new_i; 02613 Row_Iterator x_iter = m_begin + double_new_i; 02614 Row_Reference x_i = *x_iter; 02615 Row_Reference x_ii = *(x_iter + 1); 02616 for (dimension_type j = 0; j <= i; ++j) { 02617 dimension_type new_j; 02618 // If also the second variable is mapped, we work. 02619 if (pfunc.maps(j, new_j)) { 02620 dimension_type dj = 2*j; 02621 dimension_type double_new_j = 2*new_j; 02622 // Mapped the constraints, exchanging the indexes. 02623 // Attention: our matrix is pseudo-triangular. 02624 // If new_j > new_i, we must consider, as rows, the rows of 02625 // the variable new_j, and not of new_i ones. 02626 if (new_i >= new_j) { 02627 assign_or_swap(x_i[double_new_j], r_i[dj]); 02628 assign_or_swap(x_ii[double_new_j], r_ii[dj]); 02629 assign_or_swap(x_ii[double_new_j+1], r_ii[dj + 1]); 02630 assign_or_swap(x_i[double_new_j+1], r_i[dj + 1]); 02631 } 02632 else { 02633 Row_Iterator xj_iter = m_begin + double_new_j; 02634 Row_Reference x_j = *xj_iter; 02635 Row_Reference x_jj = *(xj_iter + 1); 02636 assign_or_swap(x_jj[double_new_i+1], r_i[dj]); 02637 assign_or_swap(x_jj[double_new_i], r_ii[dj]); 02638 assign_or_swap(x_j[double_new_i+1], r_i[dj+1]); 02639 assign_or_swap(x_j[double_new_i], r_ii[dj+1]); 02640 } 02641 02642 } 02643 } 02644 } 02645 } 02646 02647 std::swap(matrix, x); 02648 space_dim = new_space_dim; 02649 assert(OK()); 02650 }
| void Parma_Polyhedra_Library::Octagonal_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(). |
*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 5841 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::max_space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().
05841 { 05842 // `var' should be one of the dimensions of the vector space. 05843 const dimension_type var_id = var.id(); 05844 if (var_id+1 > space_dim) 05845 throw_dimension_incompatible("expand_space_dimension(v, m)", var_id+1); 05846 05847 // The space dimension of the resulting octagon should not 05848 // overflow the maximum allowed space dimension. 05849 if (m > max_space_dimension() - space_dim) 05850 throw_generic("expand_dimension(v, m)", 05851 "adding m new space dimensions exceeds " 05852 "the maximum allowed space dimension"); 05853 05854 // Nothing to do, if no dimensions must be added. 05855 if (m == 0) 05856 return; 05857 05858 // Keep track of the dimension before adding the new ones. 05859 const dimension_type old_num_rows = matrix.num_rows(); 05860 05861 // Add the required new dimensions. 05862 add_space_dimensions_and_embed(m); 05863 05864 // For each constraints involving variable `var', we add a 05865 // similar constraint with the new variable substituted for 05866 // variable `var'. 05867 typedef typename OR_Matrix<N>::row_iterator Row_Iterator; 05868 typedef typename OR_Matrix<N>::row_reference_type Row_Reference; 05869 typedef typename OR_Matrix<N>::const_row_iterator Row_iterator; 05870 typedef typename OR_Matrix<N>::const_row_reference_type Row_reference; 05871 05872 const Row_Iterator m_begin = matrix.row_begin(); 05873 const Row_Iterator m_end = matrix.row_end(); 05874 const dimension_type n_var = 2*var_id; 05875 Row_iterator v_iter = m_begin + n_var; 05876 Row_reference m_v = *v_iter; 05877 Row_reference m_cv = *(v_iter+1); 05878 05879 for (Row_Iterator i_iter = m_begin + old_num_rows; i_iter != m_end; 05880 i_iter += 2) { 05881 Row_Reference m_i = *i_iter; 05882 Row_Reference m_ci = *(i_iter+1); 05883 const dimension_type i = i_iter.index(); 05884 const dimension_type ci = i+1; 05885 m_i[ci] = m_v[n_var+1]; 05886 m_ci[i] = m_cv[n_var]; 05887 for (dimension_type j = 0; j < n_var; ++j) { 05888 m_i[j] = m_v[j]; 05889 m_ci[j] = m_cv[j]; 05890 } 05891 for (dimension_type j = n_var+2; j < old_num_rows; ++j) { 05892 Row_Iterator j_iter = m_begin + j; 05893 Row_Reference m_j = *j_iter; 05894 Row_Reference m_cj = (j%2) ? *(j_iter-1) : *(j_iter+1); 05895 m_i[j] = m_cj[n_var+1]; 05896 m_ci[j] = m_cj[n_var]; 05897 } 05898 } 05899 // In general, adding a constraint does not preserve the strong closure 05900 // of the octagon. 05901 if (marked_strongly_closed()) 05902 reset_strongly_closed(); 05903 assert(OK()); 05904 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::fold_space_dimensions | ( | const Variables_Set & | to_be_folded, | |
| Variable | var | |||
| ) | [inline] |
Folds the space dimensions in to_be_folded into var.
| to_be_folded | The set of Variable objects corresponding to the space dimensions to be folded; | |
| var | 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 var or with one of the Variable objects contained in to_be_folded. Also thrown if var is contained in to_be_folded. |
*this has space dimension
, with
, var has space dimension
, to_be_folded is a set of variables whose maximum space dimension is also less than or equal to
, and var is not a member of to_be_folded, then the space dimensions corresponding to variables in to_be_folded are folded into the
-th space dimension.
Definition at line 5908 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::max_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic().
05909 { 05910 // `var' should be one of the dimensions of the octagon. 05911 if (var.space_dimension() > space_dim) 05912 throw_dimension_incompatible("fold_space_dimensions(tbf, v)", "v", var); 05913 05914 // The folding of no dimensions is a no-op. 05915 if (to_be_folded.empty()) 05916 return; 05917 05918 // All variables in `to_be_folded' should be dimensions of the octagon. 05919 if (to_be_folded.space_dimension() > space_dim) 05920 throw_dimension_incompatible("fold_space_dimensions(tbf, ...)", 05921 to_be_folded.space_dimension()); 05922 05923 // Moreover, `var.id()' should not occur in `to_be_folded'. 05924 if (to_be_folded.find(var.id()) != to_be_folded.end()) 05925 throw_generic("fold_space_dimensions(tbf, v)", 05926 "v should not occur in tbf"); 05927 05928 // Recompute the elements of the row and the column corresponding 05929 // to variable `var' by taking the join of their value with the 05930 // value of the corresponding elements in the row and column of the 05931 // variable `to_be_folded'. 05932 typedef typename OR_Matrix<N>::row_iterator Row_Iterator; 05933 typedef typename OR_Matrix<N>::row_reference_type Row_Reference; 05934 05935 const Row_Iterator m_begin = matrix.row_begin(); 05936 const Row_Iterator m_end = matrix.row_end(); 05937 05938 strong_closure_assign(); 05939 const dimension_type n_rows = matrix.num_rows(); 05940 const dimension_type n_var = 2*var.id(); 05941 Row_Iterator v_iter = m_begin + n_var; 05942 Row_Reference m_v = *v_iter; 05943 Row_Reference m_cv = *(v_iter+1); 05944 for (Variables_Set::const_iterator i = to_be_folded.begin(), 05945 tbf_end = to_be_folded.end(); i != tbf_end; ++i) { 05946 const dimension_type tbf_id = *i; 05947 const dimension_type tbf_var = 2*tbf_id; 05948 Row_Iterator tbf_iter = m_begin + tbf_var; 05949 Row_Reference m_tbf = *tbf_iter; 05950 Row_Reference m_ctbf = *(tbf_iter+1); 05951 max_assign(m_v[n_var+1], m_tbf[tbf_var+1]); 05952 max_assign(m_cv[n_var], m_ctbf[tbf_var]); 05953 05954 const dimension_type min_id = std::min(n_var, tbf_var); 05955 const dimension_type max_id = std::max(n_var, tbf_var); 05956 05957 for (dimension_type j = 0; j < min_id; ++j) { 05958 const dimension_type cj = coherent_index(j); 05959 max_assign(m_v[j], m_tbf[j]); 05960 max_assign(m_cv[j], m_ctbf[j]); 05961 max_assign(m_cv[cj], m_ctbf[cj]); 05962 max_assign(m_v[cj], m_tbf[cj]); 05963 } 05964 for (dimension_type j = min_id+2; j < max_id; ++j) { 05965 const dimension_type cj = coherent_index(j); 05966 Row_Iterator j_iter = m_begin + j; 05967 Row_Reference m_j = *j_iter; 05968 Row_Reference m_cj = (j%2) ? *(j_iter-1) : *(j_iter+1); 05969 if (n_var == min_id) { 05970 max_assign(m_cj[n_var+1], m_tbf[j]); 05971 max_assign(m_cj[n_var], m_ctbf[j]); 05972 max_assign(m_j[n_var], m_ctbf[cj]); 05973 max_assign(m_j[n_var+1], m_tbf[cj]); 05974 } 05975 else { 05976 max_assign(m_v[j], m_cj[tbf_var+1]); 05977 max_assign(m_cv[j], m_cj[tbf_var]); 05978 max_assign(m_cv[cj], m_j[tbf_var]); 05979 max_assign(m_v[cj], m_j[tbf_var+1]); 05980 } 05981 } 05982 for (dimension_type j = max_id+2; j < n_rows; ++j) { 05983 Row_Iterator j_iter = m_begin + j; 05984 Row_Reference m_j = *j_iter; 05985 Row_Reference m_cj = (j%2) ? *(j_iter-1) : *(j_iter+1); 05986 max_assign(m_cj[n_var+1], m_cj[tbf_var+1]); 05987 max_assign(m_cj[n_var], m_cj[tbf_var]); 05988 max_assign(m_j[n_var], m_j[tbf_var]); 05989 max_assign(m_j[n_var+1], m_j[tbf_var+1]); 05990 } 05991 } 05992 remove_space_dimensions(to_be_folded); 05993 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::ascii_dump | ( | ) | const |
Writes to std::cerr an ASCII representation of *this.
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::ascii_dump | ( | std::ostream & | s | ) | const [inline] |
Writes to s an ASCII representation of *this.
Definition at line 6169 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::Status::ascii_dump(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::status.
06169 { 06170 s << "space_dim " 06171 << space_dim 06172 << "\n"; 06173 status.ascii_dump(s); 06174 s << "\n"; 06175 matrix.ascii_dump(s); 06176 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::print | ( | ) | const |
Prints *this to std::cerr using operator<<.
| bool Parma_Polyhedra_Library::Octagonal_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 6182 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::Status::ascii_load(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::status.
06182 { 06183 std::string str; 06184 06185 if (!(s >> str) || str != "space_dim") 06186 return false; 06187 06188 if (!(s >> space_dim)) 06189 return false; 06190 06191 if (!status.ascii_load(s)) 06192 return false; 06193 06194 if (!matrix.ascii_load(s)) 06195 return false; 06196 06197 assert(OK()); 06198 return true; 06199 }
| memory_size_type Parma_Polyhedra_Library::Octagonal_Shape< T >::total_memory_in_bytes | ( | ) | const [inline] |
Returns the total size in bytes of the memory occupied by *this.
Definition at line 794 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::external_memory_in_bytes().
00794 { 00795 return sizeof(*this) + external_memory_in_bytes(); 00796 }
| memory_size_type Parma_Polyhedra_Library::Octagonal_Shape< T >::external_memory_in_bytes | ( | ) | const [inline] |
Returns the size in bytes of the memory managed by *this.
Definition at line 6203 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::total_memory_in_bytes().
06203 { 06204 return matrix.external_memory_in_bytes(); 06205 }
| int32_t Parma_Polyhedra_Library::Octagonal_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 800 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension().
00800 { 00801 return space_dimension() & 0x7fffffff; 00802 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_zero_dim_univ | ( | ) | const [inline, private] |
Returns true if the OS is the zero-dimensional universe.
Definition at line 54 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::status, and Parma_Polyhedra_Library::Octagonal_Shape< T >::Status::test_zero_dim_univ().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape().
00054 { 00055 return status.test_zero_dim_univ(); 00056 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty | ( | ) | const [inline, private] |
Returns true if the OS is known to be empty.
The return value false does not necessarily implies that *this is non-empty.
Definition at line 66 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::status, and Parma_Polyhedra_Library::Octagonal_Shape< T >::Status::test_empty().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_leaders(), Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_successors(), Parma_Polyhedra_Library::Octagonal_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constrains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::euclidean_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_bounded(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_strongly_reduced(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_universe(), Parma_Polyhedra_Library::Octagonal_Shape< T >::l_infinity_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_BHMZ05_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::rectilinear_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruence(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::unconstrain(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign().
00066 { 00067 return status.test_empty(); 00068 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed | ( | ) | const [inline, private] |
Returns true if this->matrix is known to be strongly closed.
The return value false does not necessarily implies that this->matrix is not strongly closed.
Definition at line 60 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::status, and Parma_Polyhedra_Library::Octagonal_Shape< T >::Status::test_strongly_closed().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_leaders(), Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_successors(), Parma_Polyhedra_Library::Octagonal_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::get_limiting_octagon(), Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_coherence_would_make_empty().
00060 { 00061 return status.test_strongly_closed(); 00062 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::set_zero_dim_univ | ( | ) | [inline, private] |
Turns *this into a zero-dimensional universe OS.
Definition at line 72 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::Status::set_zero_dim_univ(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::status.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_higher_space_dimensions(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions().
00072 { 00073 status.set_zero_dim_univ(); 00074 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty | ( | ) | [inline, private] |
Turns *this into an empty OS.
Definition at line 78 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::Status::set_empty(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::status.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruence(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed | ( | ) | [inline, private] |
Marks *this as strongly closed.
Definition at line 84 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::Status::set_strongly_closed(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::status.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().
00084 { 00085 status.set_strongly_closed(); 00086 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed | ( | ) | [inline, private] |
Marks *this as possibly not strongly closed.
Definition at line 90 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::Status::reset_strongly_closed(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::status.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::get_limiting_octagon(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign().
00090 { 00091 status.reset_strongly_closed(); 00092 }
| Octagonal_Shape< T >::coefficient_type & Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix_at | ( | dimension_type | i, | |
| dimension_type | j | |||
| ) | [inline, private] |
Definition at line 357 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix.
00358 { 00359 assert(i < matrix.num_rows() && j < matrix.num_rows()); 00360 return (j < matrix.row_size(i)) 00361 ? matrix[i][j] 00362 : matrix[coherent_index(j)][coherent_index(i)]; 00363 }
| const Octagonal_Shape< T >::coefficient_type & Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix_at | ( | dimension_type | i, | |
| dimension_type | j | |||
| ) | const [inline, private] |
Definition at line 347 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix.
00348 { 00349 assert(i < matrix.num_rows() && j < matrix.num_rows()); 00350 return (j < matrix.row_size(i)) 00351 ? matrix[i][j] 00352 : matrix[coherent_index(j)][coherent_index(i)]; 00353 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check | ( | const Constraint & | c | ) | [inline, private] |
Uses the constraint c to refine *this.
| c | The constraint to be added. Non-octagonal constraints are ignored. |
c and *this are dimension-incompatible, the behavior is undefined. Definition at line 478 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::Octagonal_Shape< T >::extract_octagonal_difference(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), and TEMP_INTEGER.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruence(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraint(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraints().
00478 { 00479 assert(!marked_empty()); 00480 const dimension_type c_space_dim = c.space_dimension(); 00481 assert(c_space_dim <= space_dim); 00482 00483 dimension_type num_vars = 0; 00484 dimension_type i = 0; 00485 dimension_type j = 0; 00486 TEMP_INTEGER(coeff); 00487 TEMP_INTEGER(term); 00488 // Constraints that are not octagonal differences are ignored. 00489 if (!extract_octagonal_difference(c, c_space_dim, num_vars, 00490 i, j, coeff, term)) 00491 return; 00492 00493 if (num_vars == 0) { 00494 const Coefficient& c_inhomo = c.inhomogeneous_term(); 00495 // Dealing with a trivial constraint (maybe a strict inequality). 00496 if (c_inhomo < 0 00497 || (c_inhomo != 0 && c.is_equality()) 00498 || (c_inhomo == 0 && c.is_strict_inequality())) 00499 set_empty(); 00500 return; 00501 } 00502 00503 // Select the cell to be modified for the "<=" part of constraint. 00504 typename OR_Matrix<N>::row_iterator i_iter = matrix.row_begin() + i; 00505 typename OR_Matrix<N>::row_reference_type m_i = *i_iter; 00506 N& m_i_j = m_i[j]; 00507 // Set `coeff' to the absolute value of itself. 00508 if (coeff < 0) 00509 neg_assign(coeff); 00510 00511 bool is_oct_changed = false; 00512 // Compute the bound for `m_i_j', rounding towards plus infinity. 00513 DIRTY_TEMP(N, d); 00514 div_round_up(d, term, coeff); 00515 if (m_i_j > d) { 00516 m_i_j = d; 00517 is_oct_changed = true; 00518 } 00519 00520 if (c.is_equality()) { 00521 // Select the cell to be modified for the ">=" part of constraint. 00522 if (i%2 == 0) 00523 ++i_iter; 00524 else 00525 --i_iter; 00526 00527 typename OR_Matrix<N>::row_reference_type m_ci = *i_iter; 00528 dimension_type cj = coherent_index(j); 00529 N& m_ci_cj = m_ci[cj]; 00530 // Also compute the bound for `m_ci_cj', rounding towards plus infinity. 00531 neg_assign(term); 00532 div_round_up(d, term, coeff); 00533 if (m_ci_cj > d) { 00534 m_ci_cj = d; 00535 is_oct_changed = true; 00536 } 00537 } 00538 00539 // This method does not preserve closure. 00540 if (is_oct_changed && marked_strongly_closed()) 00541 reset_strongly_closed(); 00542 assert(OK()); 00543 }
| void Parma_Polyhedra_Library::Octagonal_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-octagonal equalities are ignored. |
cg and *this are dimension-incompatible, the behavior is undefined. Definition at line 489 of file Octagonal_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::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::Congruence::space_dimension().
00489 { 00490 assert(!marked_empty()); 00491 assert(cg.space_dimension() <= space_dimension()); 00492 00493 if (cg.is_proper_congruence()) { 00494 if (cg.is_inconsistent()) 00495 set_empty(); 00496 // Other proper congruences are just ignored. 00497 return; 00498 } 00499 00500 assert(cg.is_equality()); 00501 Constraint c(cg); 00502 refine_no_check(c); 00503 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint | ( | dimension_type | i, | |
| dimension_type | j, | |||
| const N & | k | |||
| ) | [inline, private] |
Adds the constraint matrix[i][j] <= k.
Definition at line 374 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::OR_Matrix< T >::row_size(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::refine().
00376 { 00377 // Private method: the caller has to ensure the following. 00378 #ifndef NDEBUG 00379 assert(i < 2*space_dim && j < 2*space_dim && i != j); 00380 typename OR_Matrix<N>::row_iterator m_i = matrix.row_begin() + i; 00381 assert(j < m_i.row_size()); 00382 #endif 00383 N& r_i_j = matrix[i][j]; 00384 if (r_i_j > k) { 00385 r_i_j = k; 00386 if (marked_strongly_closed()) 00387 reset_strongly_closed(); 00388 } 00389 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint | ( | dimension_type | i, | |
| dimension_type | j, | |||
| Coefficient_traits::const_reference | num, | |||
| Coefficient_traits::const_reference | den | |||
| ) | [inline, private] |
Adds the constraint matrix[i][j] <= num/den.
Definition at line 394 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::OR_Matrix< T >::row_size(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim.
00397 { 00398 #ifndef NDEBUG 00399 // Private method: the caller has to ensure the following. 00400 assert(i < 2*space_dim && j < 2*space_dim && i != j); 00401 typename OR_Matrix<N>::row_iterator m_i = matrix.row_begin() + i; 00402 assert(j < m_i.row_size()); 00403 assert(den != 0); 00404 #endif 00405 DIRTY_TEMP(N, k); 00406 div_round_up(k, num, den); 00407 add_octagonal_constraint(i, j, k); 00408 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::refine | ( | Variable | var, | |
| Relation_Symbol | relsym, | |||
| const Linear_Expression & | expr, | |||
| Coefficient_traits::const_reference | denominator = Coefficient_one() | |||
| ) | [inline, private] |
Adds to the Octagonal_Shape the constraint
.
Note that the coefficient of var in expr is null.
Definition at line 3388 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Octagonal_Shape< T >::deduce_minus_v_pm_u_bounds(), Parma_Polyhedra_Library::Octagonal_Shape< T >::deduce_v_pm_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::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and TEMP_INTEGER.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage().
03391 { 03392 assert(denominator != 0); 03393 const dimension_type expr_space_dim = expr.space_dimension(); 03394 assert(space_dim >= expr_space_dim); 03395 const dimension_type var_id = var.id(); 03396 assert(var_id <= space_dim); 03397 assert(expr.coefficient(var) == 0); 03398 assert(relsym != LESS_THAN && relsym != GREATER_THAN); 03399 03400 const Coefficient& b = expr.inhomogeneous_term(); 03401 // Number of non-zero coefficients in `expr': will be set to 03402 // 0, 1, or 2, the latter value meaning any value greater than 1. 03403 dimension_type t = 0; 03404 03405 // Variable index of the last non-zero coefficient in `expr', if any. 03406 dimension_type w_id = 0; 03407 03408 // Get information about the number of non-zero coefficients in `expr'. 03409 for (dimension_type i = expr_space_dim; i-- > 0; ) 03410 if (expr.coefficient(Variable(i)) != 0) { 03411 if (t++ == 1) 03412 break; 03413 else 03414 w_id = i; 03415 } 03416 03417 // Now we know the form of `expr': 03418 // - If t == 0, then expr == b, with `b' a constant; 03419 // - If t == 1, then expr == a*j + b, where `j != v'; 03420 // - If t == 2, the `expr' is of the general form. 03421 typedef typename OR_Matrix<N>::row_iterator Row_Iterator; 03422 typedef typename OR_Matrix<N>::row_reference_type Row_Reference; 03423 typedef typename OR_Matrix<N>::const_row_iterator Row_iterator; 03424 typedef typename OR_Matrix<N>::const_row_reference_type Row_reference; 03425 03426 const Row_Iterator m_begin = matrix.row_begin(); 03427 const dimension_type n_var = 2*var_id; 03428 TEMP_INTEGER(minus_den); 03429 neg_assign(minus_den, denominator); 03430 03431 // Since we are only able to record octagonal differences, we can 03432 // precisely deal with the case of a single variable only if its 03433 // coefficient (taking into account the denominator) is 1. 03434 // If this is not the case, we fall back to the general case 03435 // so as to over-approximate the constraint. 03436 if (t == 1 && expr.coefficient(Variable(w_id)) != denominator 03437 && expr.coefficient(Variable(w_id)) != minus_den) 03438 t = 2; 03439 03440 if (t == 0) { 03441 // Case 1: expr == b. 03442 TEMP_INTEGER(two_b); 03443 two_b = 2*b; 03444 switch (relsym) { 03445 case EQUAL: 03446 // Add the constraint `var == b/denominator'. 03447 add_octagonal_constraint(n_var+1, n_var, two_b, denominator); 03448 add_octagonal_constraint(n_var, n_var+1, two_b, minus_den); 03449 break; 03450 case LESS_OR_EQUAL: 03451 // Add the constraint `var <= b/denominator'. 03452 add_octagonal_constraint(n_var+1, n_var, two_b, denominator); 03453 break; 03454 case GREATER_OR_EQUAL: 03455 // Add the constraint `var >= b/denominator', 03456 // i.e., `-var <= -b/denominator', 03457 add_octagonal_constraint(n_var, n_var+1, two_b, minus_den); 03458 break; 03459 default: 03460 // We already dealt with the other cases. 03461 throw std::runtime_error("PPL internal error"); 03462 } 03463 } 03464 else if (t == 1) { 03465 // Value of the one and only non-zero coefficient in `expr'. 03466 const Coefficient& w_coeff = expr.coefficient(Variable(w_id)); 03467 const dimension_type n_w = 2*w_id; 03468 switch (relsym) { 03469 case EQUAL: 03470 if (w_coeff == denominator) 03471 // Add the new constraint `var - w = b/denominator'. 03472 if (var_id < w_id) { 03473 add_octagonal_constraint(n_w, n_var, b, denominator); 03474 add_octagonal_constraint(n_w+1, n_var+1, b, minus_den); 03475 } 03476 else { 03477 add_octagonal_constraint(n_var+1, n_w+1, b, denominator); 03478 add_octagonal_constraint(n_var, n_w, b, minus_den); 03479 } 03480 else 03481 // Add the new constraint `var + w = b/denominator'. 03482 if (var_id < w_id) { 03483 add_octagonal_constraint(n_w+1, n_var, b, denominator); 03484 add_octagonal_constraint(n_w, n_var+1, b, minus_den); 03485 } 03486 else { 03487 add_octagonal_constraint(n_var+1, n_w, b, denominator); 03488 add_octagonal_constraint(n_var, n_w+1, b, minus_den); 03489 } 03490 break; 03491 case LESS_OR_EQUAL: 03492 { 03493 DIRTY_TEMP(N, d); 03494 div_round_up(d, b, denominator); 03495 // Note that: `w_id != v', so that `expr' is of the form 03496 // w_coeff * w + b, with `w_id != v'. 03497 if (w_coeff == denominator) { 03498 // Add the new constraints `v - w <= b/denominator'. 03499 if (var_id < w_id) 03500 add_octagonal_constraint(n_w, n_var, d); 03501 else 03502 add_octagonal_constraint(n_var+1, n_w+1, d); 03503 } 03504 else if (w_coeff == minus_den) { 03505 // Add the new constraints `v + w <= b/denominator'. 03506 if (var_id < w_id) 03507 add_octagonal_constraint(n_w+1, n_var, d); 03508 else 03509 add_octagonal_constraint(n_var+1, n_w, d); 03510 } 03511 break; 03512 } 03513 03514 case GREATER_OR_EQUAL: 03515 { 03516 DIRTY_TEMP(N, d); 03517 div_round_up(d, b, minus_den); 03518 // Note that: `w_id != v', so that `expr' is of the form 03519 // w_coeff * w + b, with `w_id != v'. 03520 if (w_coeff == denominator) { 03521 // Add the new constraint `v - w >= b/denominator', 03522 // i.e., `-v + w <= -b/denominator'. 03523 if (var_id < w_id) 03524 add_octagonal_constraint(n_w+1, n_var+1, d); 03525 else 03526 add_octagonal_constraint(n_var, n_w, d); 03527 } 03528 else if (w_coeff == minus_den) { 03529 // Add the new constraints `v + w >= b/denominator', 03530 // i.e., `-v - w <= -b/denominator'. 03531 if (var_id < w_id) 03532 add_octagonal_constraint(n_w, n_var+1, d); 03533 else 03534 add_octagonal_constraint(n_var, n_w+1, d); 03535 } 03536 break; 03537 } 03538 03539 default: 03540 // We already dealt with the other cases. 03541 throw std::runtime_error("PPL internal error"); 03542 } 03543 } 03544 else { 03545 // Here t == 2, so that 03546 // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2. 03547 const bool is_sc = (denominator > 0); 03548 TEMP_INTEGER(minus_b); 03549 neg_assign(minus_b, b); 03550 const Coefficient& sc_b = is_sc ? b : minus_b; 03551 const Coefficient& minus_sc_b = is_sc ? minus_b : b; 03552 const Coefficient& sc_den = is_sc ? denominator : minus_den; 03553 const Coefficient& minus_sc_den = is_sc ? minus_den : denominator; 03554 // NOTE: here, for optimization purposes, `minus_expr' is only assigned 03555 // when `denominator' is negative. Do not use it unless you are sure 03556 // it has been correctly assigned. 03557 Linear_Expression minus_expr; 03558 if (!is_sc) 03559 minus_expr = -expr; 03560 const Linear_Expression& sc_expr = is_sc ? expr : minus_expr; 03561 03562 DIRTY_TEMP(N, sum); 03563 // Index of variable that is unbounded in `this'. 03564 PPL_UNINITIALIZED(dimension_type, pinf_index); 03565 // Number of unbounded variables found. 03566 dimension_type pinf_count = 0; 03567 03568 switch (relsym) { 03569 case EQUAL: 03570 { 03571 DIRTY_TEMP(N, neg_sum); 03572 // Index of variable that is unbounded in `this'. 03573 PPL_UNINITIALIZED(dimension_type, neg_pinf_index); 03574 // Number of unbounded variables found. 03575 dimension_type neg_pinf_count = 0; 03576 03577 // Approximate the inhomogeneous term. 03578 assign_r(sum, sc_b, ROUND_UP); 03579 assign_r(neg_sum, minus_sc_b, ROUND_UP); 03580 03581 // Approximate the homogeneous part of `sc_expr'. 03582 DIRTY_TEMP(N, coeff_i); 03583 DIRTY_TEMP(N, half); 03584 TEMP_INTEGER(minus_sc_i); 03585 DIRTY_TEMP(N, minus_coeff_i); 03586 // Note: indices above `w' can be disregarded, as they all have 03587 // a zero coefficient in `sc_expr'. 03588 for (Row_iterator m_iter = m_begin, m_iter_end = m_iter + (2*w_id) + 2; 03589 m_iter != m_iter_end; ) { 03590 const dimension_type n_i = m_iter.index(); 03591 const dimension_type id = n_i/2; 03592 Row_reference m_i = *m_iter; 03593 ++m_iter; 03594 Row_reference m_ci = *m_iter; 03595 ++m_iter; 03596 const Coefficient& sc_i = sc_expr.coefficient(Variable(id)); 03597 const int sign_i = sgn(sc_i); 03598 if (sign_i > 0) { 03599 assign_r(coeff_i, sc_i, ROUND_UP); 03600 // Approximating `sc_expr'. 03601 if (pinf_count <= 1) { 03602 const N& double_approx_i = m_ci[n_i]; 03603 if (!is_plus_infinity(double_approx_i)) { 03604 // Let half = double_approx_i / 2. 03605 div2exp_assign_r(half, double_approx_i, 1, ROUND_UP); 03606 add_mul_assign_r(sum, coeff_i, half, ROUND_UP); 03607 } 03608 else { 03609 ++pinf_count; 03610 pinf_index = id; 03611 } 03612 } 03613 // Approximating `-sc_expr'. 03614 if (neg_pinf_count <= 1) { 03615 const N& double_approx_minus_i = m_i[n_i+1]; 03616 if (!is_plus_infinity(double_approx_minus_i)) { 03617 // Let half = double_approx_minus_i / 2. 03618 div2exp_assign_r(half, double_approx_minus_i, 1, ROUND_UP); 03619 add_mul_assign_r(neg_sum, coeff_i, half, ROUND_UP); 03620 } 03621 else { 03622 ++neg_pinf_count; 03623 neg_pinf_index = id; 03624 } 03625 } 03626 } 03627 else if (sign_i < 0) { 03628 neg_assign_r(minus_sc_i, sc_i, ROUND_NOT_NEEDED); 03629 assign_r(minus_coeff_i, minus_sc_i, ROUND_UP); 03630 // Approximating `sc_expr'. 03631 if (pinf_count <= 1) { 03632 const N& double_approx_minus_i = m_i[n_i+1]; 03633 if (!is_plus_infinity(double_approx_minus_i)) { 03634 // Let half = double_approx_minus_i / 2. 03635 div2exp_assign_r(half, double_approx_minus_i, 1, ROUND_UP); 03636 add_mul_assign_r(sum, minus_coeff_i, half, ROUND_UP); 03637 } 03638 else { 03639 ++pinf_count; 03640 pinf_index = id; 03641 } 03642 } 03643 // Approximating `-sc_expr'. 03644 if (neg_pinf_count <= 1) { 03645 const N& double_approx_i = m_ci[n_i]; 03646 if (!is_plus_infinity(double_approx_i)) { 03647 // Let half = double_approx_i / 2. 03648 div2exp_assign_r(half, double_approx_i, 1, ROUND_UP); 03649 add_mul_assign_r(neg_sum, minus_coeff_i, half, ROUND_UP); 03650 } 03651 else { 03652 ++neg_pinf_count; 03653 neg_pinf_index = id; 03654 } 03655 } 03656 } 03657 } 03658 // Return immediately if no approximation could be computed. 03659 if (pinf_count > 1 && neg_pinf_count > 1) { 03660 assert(OK()); 03661 return; 03662 } 03663 03664 // In the following, strong closure will be definitely lost. 03665 reset_strongly_closed(); 03666 03667 // Exploit the upper approximation, if possible. 03668 if (pinf_count <= 1) { 03669 // Compute quotient (if needed). 03670 if (sc_den != 1) { 03671 // Before computing quotients, the denominator should be 03672 // approximated towards zero. Since `sc_den' is known to be 03673 // positive, this amounts to rounding downwards, which is 03674 // achieved as usual by rounding upwards `minus_sc_den' 03675 // and negating again the result. 03676 DIRTY_TEMP(N, down_sc_den); 03677 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 03678 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 03679 div_assign_r(sum, sum, down_sc_den, ROUND_UP); 03680 } 03681 // Add the upper bound constraint, if meaningful. 03682 if (pinf_count == 0) { 03683 // Add the constraint `v <= sum'. 03684 DIRTY_TEMP(N, double_sum); 03685 mul2exp_assign_r(double_sum, sum, 1, ROUND_IGNORE); 03686 matrix[n_var+1][n_var] = double_sum; 03687 // Deduce constraints of the form `v +/- u', where `u != v'. 03688 deduce_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, sum); 03689 } 03690 else 03691 // Here `pinf_count == 1'. 03692 if (pinf_index != var_id) { 03693 const Coefficient& ppi = 03694 sc_expr.coefficient(Variable(pinf_index)); 03695 if (ppi == sc_den) 03696 // Add the constraint `v - pinf_index <= sum'. 03697 if (var_id < pinf_index) 03698 matrix[2*pinf_index][n_var] = sum; 03699 else 03700 matrix[n_var+1][2*pinf_index+1] = sum; 03701 else 03702 if (ppi == minus_sc_den) { 03703 // Add the constraint `v + pinf_index <= sum'. 03704 if (var_id < pinf_index) 03705 matrix[2*pinf_index+1][n_var] = sum; 03706 else 03707 matrix[n_var+1][2*pinf_index] = sum; 03708 } 03709 } 03710 } 03711 03712 // Exploit the lower approximation, if possible. 03713 if (neg_pinf_count <= 1) { 03714 // Compute quotient (if needed). 03715 if (sc_den != 1) { 03716 // Before computing quotients, the denominator should be 03717 // approximated towards zero. Since `sc_den' is known to be 03718 // positive, this amounts to rounding downwards, which is 03719 // achieved as usual by rounding upwards `minus_sc_den' 03720 // and negating again the result. 03721 DIRTY_TEMP(N, down_sc_den); 03722 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 03723 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 03724 div_assign_r(neg_sum, neg_sum, down_sc_den, ROUND_UP); 03725 } 03726 // Add the lower bound constraint, if meaningful. 03727 if (neg_pinf_count == 0) { 03728 // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'. 03729 DIRTY_TEMP(N, double_neg_sum); 03730 mul2exp_assign_r(double_neg_sum, neg_sum, 1, ROUND_IGNORE); 03731 matrix[n_var][n_var+1] = double_neg_sum; 03732 // Deduce constraints of the form `-v +/- u', where `u != v'. 03733 deduce_minus_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, neg_sum); 03734 } 03735 else 03736 // Here `neg_pinf_count == 1'. 03737 if (neg_pinf_index != var_id) { 03738 const Coefficient& npi = 03739 sc_expr.coefficient(Variable(neg_pinf_index)); 03740 if (npi == sc_den) 03741 // Add the constraint `v - neg_pinf_index >= -neg_sum', 03742 // i.e., `neg_pinf_index - v <= neg_sum'. 03743 if (neg_pinf_index < var_id) 03744 matrix[n_var][2*neg_pinf_index] = neg_sum; 03745 else 03746 matrix[2*neg_pinf_index+1][n_var+1] = neg_sum; 03747 else 03748 if (npi == minus_sc_den) { 03749 // Add the constraint `v + neg_pinf_index >= -neg_sum', 03750 // i.e., `-neg_pinf_index - v <= neg_sum'. 03751 if (neg_pinf_index < var_id) 03752 matrix[n_var][2*neg_pinf_index+1] = neg_sum; 03753 else 03754 matrix[2*neg_pinf_index][n_var+1] = neg_sum; 03755 } 03756 } 03757 } 03758 break; 03759 } 03760 03761 case LESS_OR_EQUAL: 03762 { 03763 // Compute an upper approximation for `expr' into `sum', 03764 // taking into account the sign of `denominator'. 03765 03766 // Approximate the inhomogeneous term. 03767 assign_r(sum, sc_b, ROUND_UP); 03768 03769 // Approximate the homogeneous part of `sc_expr'. 03770 DIRTY_TEMP(N, coeff_i); 03771 DIRTY_TEMP(N, approx_i); 03772 TEMP_INTEGER(minus_sc_i); 03773 // Note: indices above `w_id' can be disregarded, as they all have 03774 // a zero coefficient in `expr'. 03775 for (Row_Iterator m_iter = m_begin, m_end = m_iter + (2*w_id) + 2; 03776 m_iter != m_end; ) { 03777 const dimension_type n_i = m_iter.index(); 03778 const dimension_type id = n_i/2; 03779 Row_Reference m_i = *m_iter; 03780 ++m_iter; 03781 Row_Reference m_ci = *m_iter; 03782 ++m_iter; 03783 const Coefficient& sc_i = sc_expr.coefficient(Variable(id)); 03784 const int sign_i = sgn(sc_i); 03785 if (sign_i == 0) 03786 continue; 03787 // Choose carefully: we are approximating `sc_expr'. 03788 const N& double_approx_i = (sign_i > 0) ? m_ci[n_i] : m_i[n_i+1]; 03789 if (is_plus_infinity(double_approx_i)) { 03790 if (++pinf_count > 1) 03791 break; 03792 pinf_index = id; 03793 continue; 03794 } 03795 if (sign_i > 0) 03796 assign_r(coeff_i, sc_i, ROUND_UP); 03797 else { 03798 neg_assign(minus_sc_i, sc_i); 03799 assign_r(coeff_i, minus_sc_i, ROUND_UP); 03800 } 03801 div2exp_assign_r(approx_i, double_approx_i, 1, ROUND_UP); 03802 add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP); 03803 } 03804 // Divide by the (sign corrected) denominator (if needed). 03805 if (sc_den != 1) { 03806 // Before computing the quotient, the denominator should be 03807 // approximated towards zero. Since `sc_den' is known to be 03808 // positive, this amounts to rounding downwards, which is achieved 03809 // by rounding upwards `minus_sc-den' and negating again the result. 03810 DIRTY_TEMP(N, down_sc_den); 03811 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 03812 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 03813 div_assign_r(sum, sum, down_sc_den, ROUND_UP); 03814 } 03815 03816 if (pinf_count == 0) { 03817 // Add the constraint `v <= sum'. 03818 DIRTY_TEMP(N, double_sum); 03819 mul2exp_assign_r(double_sum, sum, 1, ROUND_IGNORE); 03820 add_octagonal_constraint(n_var+1, n_var, double_sum); 03821 // Deduce constraints of the form `v +/- u', where `u != v'. 03822 deduce_v_pm_u_bounds(var_id, w_id, sc_expr, sc_den, sum); 03823 } 03824 else if (pinf_count == 1) { 03825 dimension_type pinf_ind = 2*pinf_index; 03826 if (expr.coefficient(Variable(pinf_index)) == denominator ) { 03827 // Add the constraint `v - pinf_index <= sum'. 03828 if (var_id < pinf_index) 03829 add_octagonal_constraint(pinf_ind, n_var, sum); 03830 else 03831 add_octagonal_constraint(n_var+1, pinf_ind+1, sum); 03832 } 03833 else { 03834 if (expr.coefficient(Variable(pinf_index)) == minus_den) { 03835 // Add the constraint `v + pinf_index <= sum'. 03836 if (var_id < pinf_index) 03837 add_octagonal_constraint(pinf_ind+1, n_var, sum); 03838 else 03839 add_octagonal_constraint(n_var+1, pinf_ind, sum); 03840 } 03841 } 03842 } 03843 break; 03844 } 03845 03846 case GREATER_OR_EQUAL: 03847 { 03848 // Compute an upper approximation for `-sc_expr' into `sum'. 03849 // Note: approximating `-sc_expr' from above and then negating the 03850 // result is the same as approximating `sc_expr' from below. 03851 03852 // Approximate the inhomogeneous term. 03853 assign_r(sum, minus_sc_b, ROUND_UP); 03854 03855 // Approximate the homogeneous part of `-sc_expr'. 03856 DIRTY_TEMP(N, coeff_i); 03857 DIRTY_TEMP(N, approx_i); 03858 TEMP_INTEGER(minus_sc_i); 03859 for (Row_Iterator m_iter = m_begin, m_end = m_iter + (2*w_id) + 2; 03860 m_iter != m_end; ) { 03861 const dimension_type n_i = m_iter.index(); 03862 const dimension_type id = n_i/2; 03863 Row_Reference m_i = *m_iter; 03864 ++m_iter; 03865 Row_Reference m_ci = *m_iter; 03866 ++m_iter; 03867 const Coefficient& sc_i = sc_expr.coefficient(Variable(id)); 03868 const int sign_i = sgn(sc_i); 03869 if (sign_i == 0) 03870 continue; 03871 // Choose carefully: we are approximating `-sc_expr'. 03872 const N& double_approx_i = (sign_i > 0) ? m_i[n_i+1] : m_ci[n_i]; 03873 if (is_plus_infinity(double_approx_i)) { 03874 if (++pinf_count > 1) 03875 break; 03876 pinf_index = id; 03877 continue; 03878 } 03879 if (sign_i > 0) 03880 assign_r(coeff_i, sc_i, ROUND_UP); 03881 else { 03882 neg_assign(minus_sc_i, sc_i); 03883 assign_r(coeff_i, minus_sc_i, ROUND_UP); 03884 } 03885 div2exp_assign_r(approx_i, double_approx_i, 1, ROUND_UP); 03886 add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP); 03887 } 03888 03889 // Divide by the (sign corrected) denominator (if needed). 03890 if (sc_den != 1) { 03891 // Before computing the quotient, the denominator should be 03892 // approximated towards zero. Since `sc_den' is known to be positive, 03893 // this amounts to rounding downwards, which is achieved by rounding 03894 // upwards `minus_sc_den' and negating again the result. 03895 DIRTY_TEMP(N, down_sc_den); 03896 assign_r(down_sc_den, minus_sc_den, ROUND_UP); 03897 neg_assign_r(down_sc_den, down_sc_den, ROUND_UP); 03898 div_assign_r(sum, sum, down_sc_den, ROUND_UP); 03899 } 03900 03901 if (pinf_count == 0) { 03902 // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'. 03903 DIRTY_TEMP(N, double_sum); 03904 mul2exp_assign_r(double_sum, sum, 1, ROUND_IGNORE); 03905 add_octagonal_constraint(n_var, n_var+1, double_sum); 03906 // Deduce constraints of the form `-v +/- u', where `u != v'. 03907 deduce_minus_v_pm_u_bounds(var_id, pinf_index, sc_expr, sc_den, sum); 03908 } 03909 else if (pinf_count == 1) { 03910 dimension_type pinf_ind = 2*pinf_index; 03911 if (expr.coefficient(Variable(pinf_index)) == denominator) { 03912 // Add the constraint `v - pinf_index >= -sum', 03913 // i.e., `pinf_index - v <= sum'. 03914 if (pinf_index < var_id) 03915 add_octagonal_constraint(n_var, pinf_ind, sum); 03916 else 03917 add_octagonal_constraint(pinf_ind+1, n_var, sum); 03918 } 03919 else { 03920 if (expr.coefficient(Variable(pinf_index)) == minus_den) { 03921 // Add the constraint `v + pinf_index >= -sum', 03922 // i.e., `-pinf_index - v <= sum'. 03923 if (pinf_index < var_id) 03924 add_octagonal_constraint(n_var, pinf_ind+1, sum); 03925 else 03926 add_octagonal_constraint(pinf_ind, n_var+1, sum); 03927 } 03928 } 03929 } 03930 break; 03931 } 03932 03933 default: 03934 // We already dealt with the other cases. 03935 throw std::runtime_error("PPL internal error"); 03936 } 03937 } 03938 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_all_octagonal_constraints | ( | dimension_type | v_id | ) | [inline, private] |
Removes all the constraints on variable v_id.
Definition at line 3298 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, PLUS_INFINITY, Parma_Polyhedra_Library::OR_Matrix< T >::row_size(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::unconstrain().
03298 { 03299 assert(v_id < space_dim); 03300 const dimension_type n_v = 2*v_id; 03301 typename OR_Matrix<N>::row_iterator m_iter = matrix.row_begin() + n_v; 03302 typename OR_Matrix<N>::row_reference_type r_v = *m_iter; 03303 typename OR_Matrix<N>::row_reference_type r_cv = *(++m_iter); 03304 for (dimension_type h = m_iter.row_size(); h-- > 0; ) { 03305 assign_r(r_v[h], PLUS_INFINITY, ROUND_NOT_NEEDED); 03306 assign_r(r_cv[h], PLUS_INFINITY, ROUND_NOT_NEEDED); 03307 } 03308 ++m_iter; 03309 for (typename OR_Matrix<N>::row_iterator m_end = matrix.row_end(); 03310 m_iter != m_end; ++m_iter) { 03311 typename OR_Matrix<N>::row_reference_type r = *m_iter; 03312 assign_r(r[n_v], PLUS_INFINITY, ROUND_NOT_NEEDED); 03313 assign_r(r[n_v+1], PLUS_INFINITY, ROUND_NOT_NEEDED); 03314 } 03315 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_binary_octagonal_constraints | ( | dimension_type | v_id | ) | [inline, private] |
Removes all binary constraints on variable v_id.
Definition at line 3320 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, PLUS_INFINITY, and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image().
03320 { 03321 assert(v_id < space_dim); 03322 const dimension_type n_v = 2*v_id; 03323 typename OR_Matrix<N>::row_iterator m_iter = matrix.row_begin() + n_v; 03324 typename OR_Matrix<N>::row_reference_type r_v = *m_iter; 03325 typename OR_Matrix<N>::row_reference_type r_cv = *(++m_iter); 03326 for (dimension_type k = n_v; k-- > 0; ) { 03327 assign_r(r_v[k], PLUS_INFINITY, ROUND_NOT_NEEDED); 03328 assign_r(r_cv[k], PLUS_INFINITY, ROUND_NOT_NEEDED); 03329 } 03330 ++m_iter; 03331 for (typename OR_Matrix<N>::row_iterator m_end = matrix.row_end(); 03332 m_iter != m_end; ++m_iter) { 03333 typename OR_Matrix<N>::row_reference_type r = *m_iter; 03334 assign_r(r[n_v], PLUS_INFINITY, ROUND_NOT_NEEDED); 03335 assign_r(r[n_v+1], PLUS_INFINITY, ROUND_NOT_NEEDED); 03336 } 03337 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::deduce_v_pm_u_bounds | ( | dimension_type | v_id, | |
| dimension_type | last_id, | |||
| 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 variable index u_id (less than or equal to last_id and different from v_id), deduce constraints of the form v - u <= k and v + u <= k, starting from ub_v, which is an upper bound for v computed according to sc_expr and sc_den.
Strong-closure will be able to deduce the constraints v - u <= ub_v - lb_u and v + u <= ub_v + ub_u. We can be more precise if variable u played an active role in the computation of the upper bound for v.
Namely, if the corresponding coefficient q == sc_expr[u]/sc_den of u in sc_expr is greater than zero, we can improve the bound for v - u. 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).
Conversely, if q is less than zero, we can improve the bound for v + u. In particular:
q <= -1, then v + u <= ub_v + lb_u;-1 < q < 0, then v + u <= ub_v + ((-q)*lb_u + (1+q)*ub_u). Definition at line 3062 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::neg_assign(), and TEMP_INTEGER.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::refine().
03066 { 03067 // Private method: the caller has to ensure the following. 03068 assert(sc_den > 0); 03069 assert(!is_plus_infinity(ub_v)); 03070 03071 DIRTY_TEMP0(mpq_class, mpq_sc_den); 03072 assign_r(mpq_sc_den, sc_den, ROUND_NOT_NEEDED); 03073 03074 // No need to consider indices greater than `last_id'. 03075 const dimension_type n_v = 2*v_id; 03076 typename OR_Matrix<N>::row_reference_type m_cv = matrix[n_v+1]; 03077 03078 // Speculatively allocate temporaries out of the loop. 03079 DIRTY_TEMP(N, half); 03080 DIRTY_TEMP0(mpq_class, minus_lb_u); 03081 DIRTY_TEMP0(mpq_class, q); 03082 DIRTY_TEMP0(mpq_class, minus_q); 03083 DIRTY_TEMP0(mpq_class, ub_u); 03084 DIRTY_TEMP0(mpq_class, lb_u); 03085 DIRTY_TEMP(N, up_approx); 03086 TEMP_INTEGER(minus_expr_u); 03087 03088 for (dimension_type u_id = last_id+1; u_id-- > 0; ) { 03089 // Skip the case when `u_id == v_id'. 03090 if (u_id == v_id) 03091 continue; 03092 const Coefficient& expr_u = sc_expr.coefficient(Variable(u_id)); 03093 // Skip the case when `expr_u == 0'. 03094 if (expr_u == 0) 03095 continue; 03096 03097 const dimension_type n_u = u_id*2; 03098 // If `expr_u' is positive, we can improve `v - u'. 03099 if (expr_u > 0) { 03100 if (expr_u >= sc_den) { 03101 // Here q >= 1: deducing `v - u <= ub_v - ub_u'. 03102 // We avoid to check if `ub_u' is plus infinity, because 03103 // it is used for the computation of `ub_v'. 03104 // Let half = m_cu_u / 2. 03105 div2exp_assign_r(half, matrix[n_u+1][n_u], 1, ROUND_UP); 03106 N& m_v_minus_u = (n_v < n_u) ? matrix[n_u][n_v] : m_cv[n_u+1]; 03107 sub_assign_r(m_v_minus_u, ub_v, half, ROUND_UP); 03108 } 03109 else { 03110 // Here 0 < q < 1. 03111 typename OR_Matrix<N>::row_reference_type m_u = matrix[n_u]; 03112 const N& m_u_cu = m_u[n_u+1]; 03113 if (!is_plus_infinity(m_u_cu)) { 03114 // Let `ub_u' and `lb_u' be the known upper and lower bound 03115 // for `u', respectively. The upper bound for `v - u' is 03116 // computed as `ub_v - (q * ub_u + (1-q) * lb_u)', 03117 // i.e., `ub_v + (-lb_u) - q * (ub_u + (-lb_u))'. 03118 assign_r(minus_lb_u, m_u_cu, ROUND_NOT_NEEDED); 03119 div2exp_assign_r(minus_lb_u, minus_lb_u, 1, ROUND_NOT_NEEDED); 03120 assign_r(q, expr_u, ROUND_NOT_NEEDED); 03121 div_assign_r(q, q, mpq_sc_den, ROUND_NOT_NEEDED); 03122 assign_r(ub_u, matrix[n_u+1][n_u], ROUND_NOT_NEEDED); 03123 div2exp_assign_r(ub_u, ub_u, 1, ROUND_NOT_NEEDED); 03124 // Compute `ub_u - lb_u'. 03125 add_assign_r(ub_u, ub_u, minus_lb_u, ROUND_NOT_NEEDED); 03126 // Compute `(-lb_u) - q * (ub_u - lb_u)'. 03127 sub_mul_assign_r(minus_lb_u, q, ub_u, ROUND_NOT_NEEDED); 03128 assign_r(up_approx, minus_lb_u, ROUND_UP); 03129 // Deducing `v - u <= ub_v - (q * ub_u + (1-q) * lb_u)'. 03130 N& m_v_minus_u = (n_v < n_u) ? m_u[n_v] : m_cv[n_u+1]; 03131 add_assign_r(m_v_minus_u, ub_v, up_approx, ROUND_UP); 03132 } 03133 } 03134 } 03135 else { 03136 assert(expr_u < 0); 03137 // If `expr_u' is negative, we can improve `v + u'. 03138 neg_assign(minus_expr_u, expr_u); 03139 if (minus_expr_u >= sc_den) { 03140 // Here q <= -1: Deducing `v + u <= ub_v + lb_u'. 03141 // We avoid to check if `lb_u' is plus infinity, because 03142 // it is used for the computation of `ub_v'. 03143 // Let half = m_u_cu / 2. 03144 div2exp_assign_r(half, matrix[n_u][n_u+1], 1, ROUND_UP); 03145 N& m_v_plus_u = (n_v < n_u) ? matrix[n_u+1][n_v] : m_cv[n_u]; 03146 sub_assign_r(m_v_plus_u, ub_v, half, ROUND_UP); 03147 } 03148 else { 03149 // Here -1 < q < 0. 03150 typename OR_Matrix<N>::row_reference_type m_cu = matrix[n_u+1]; 03151 const N& m_cu_u = m_cu[n_u]; 03152 if (!is_plus_infinity(m_cu_u)) { 03153 // Let `ub_u' and `lb_u' be the known upper and lower bound 03154 // for `u', respectively. The upper bound for `v + u' is 03155 // computed as `ub_v + ((-q) * lb_u + (1+q) * ub_u)', 03156 // i.e., `ub_v + ub_u + (-q) * (lb_u - ub_u)'. 03157 assign_r(ub_u, m_cu[n_u], ROUND_NOT_NEEDED); 03158 div2exp_assign_r(ub_u, ub_u, 1, ROUND_NOT_NEEDED); 03159 assign_r(minus_q, minus_expr_u, ROUND_NOT_NEEDED); 03160 div_assign_r(minus_q, minus_q, mpq_sc_den, ROUND_NOT_NEEDED); 03161 assign_r(lb_u, matrix[n_u][n_u+1], ROUND_NOT_NEEDED); 03162 div2exp_assign_r(lb_u, lb_u, 1, ROUND_NOT_NEEDED); 03163 neg_assign_r(lb_u, lb_u, ROUND_NOT_NEEDED); 03164 // Compute `lb_u - ub_u'. 03165 sub_assign_r(lb_u, lb_u, ub_u, ROUND_NOT_NEEDED); 03166 // Compute `ub_u + (-q) * (lb_u - ub_u)'. 03167 add_mul_assign_r(ub_u, minus_q, lb_u, ROUND_NOT_NEEDED); 03168 assign_r(up_approx, ub_u, ROUND_UP); 03169 // Deducing `v + u <= ub_v + ((-q) * lb_u + (1+q) * ub_u)'. 03170 N& m_v_plus_u = (n_v < n_u) ? m_cu[n_v] : m_cv[n_u]; 03171 add_assign_r(m_v_plus_u, ub_v, up_approx, ROUND_UP); 03172 } 03173 } 03174 } 03175 } 03176 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::deduce_minus_v_pm_u_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 variable index u_id (less than or equal to last_id and different from v_id), deduce constraints of the form -v + u <= k and -v - u <= k, starting from minus_lb_v, which is the negation of a lower bound for v computed according to sc_expr and sc_den.
Strong-closure will be able to deduce the constraints -v - u <= -lb_v - lb_u and -v + u <= -lb_v + ub_u. We can be more precise if variable u played an active role in the computation of (the negation of) the lower bound for v.
Namely, if the corresponding coefficient q == sc_expr[u]/sc_den of u in sc_expr is greater than zero, we can improve the bound for -v + u. In particular:
q >= 1, then -v + u <= -lb_v + lb_u;0 < q < 1, then -v + u <= -lb_v + (q*lb_u + (1-q)*ub_u).
Conversely, if q is less than zero, we can improve the bound for -v - u. In particular:
q <= -1, then -v - u <= -lb_v - ub_u;-1 < q < 0, then -v - u <= -lb_v - ((-q)*ub_u + (1+q)*lb_u). Definition at line 3181 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::neg_assign(), and TEMP_INTEGER.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::refine().
03185 { 03186 // Private method: the caller has to ensure the following. 03187 assert(sc_den > 0); 03188 assert(!is_plus_infinity(minus_lb_v)); 03189 03190 DIRTY_TEMP0(mpq_class, mpq_sc_den); 03191 assign_r(mpq_sc_den, sc_den, ROUND_NOT_NEEDED); 03192 03193 // No need to consider indices greater than `last_id'. 03194 const dimension_type n_v = 2*v_id; 03195 typename OR_Matrix<N>::row_reference_type m_v = matrix[n_v]; 03196 03197 // Speculatively allocate temporaries out of the loop. 03198 DIRTY_TEMP(N, half); 03199 DIRTY_TEMP0(mpq_class, ub_u); 03200 DIRTY_TEMP0(mpq_class, q); 03201 DIRTY_TEMP0(mpq_class, minus_lb_u); 03202 DIRTY_TEMP(N, up_approx); 03203 TEMP_INTEGER(minus_expr_u); 03204 03205 for (dimension_type u_id = last_id+1; u_id-- > 0; ) { 03206 // Skip the case when `u_id == v_id'. 03207 if (u_id == v_id) 03208 continue; 03209 const Coefficient& expr_u = sc_expr.coefficient(Variable(u_id)); 03210 // Skip the case when `expr_u == 0'. 03211 if (expr_u == 0) 03212 continue; 03213 03214 const dimension_type n_u = u_id*2; 03215 // If `expr_u' is positive, we can improve `-v + u'. 03216 if (expr_u > 0) { 03217 if (expr_u >= sc_den) { 03218 // Here q >= 1: deducing `-v + u <= lb_u - lb_v', 03219 // i.e., `u - v <= (-lb_v) - (-lb_u)'. 03220 // We avoid to check if `lb_u' is plus infinity, because 03221 // it is used for the computation of `lb_v'. 03222 // Let half = m_u_cu / 2. 03223 div2exp_assign_r(half, matrix[n_u][n_u+1], 1, ROUND_UP); 03224 N& m_u_minus_v = (n_v < n_u) ? matrix[n_u+1][n_v+1] : m_v[n_u]; 03225 sub_assign_r(m_u_minus_v, minus_lb_v, half, ROUND_UP); 03226 } 03227 else { 03228 // Here 0 < q < 1. 03229 typename OR_Matrix<N>::row_reference_type m_cu = matrix[n_u+1]; 03230 const N& m_cu_u = m_cu[n_u]; 03231 if (!is_plus_infinity(m_cu_u)) { 03232 // Let `ub_u' and `lb_u' be the known upper and lower bound 03233 // for `u', respectively. The upper bound for `u - v' is 03234 // computed as `(q * lb_u + (1-q) * ub_u) - lb_v', 03235 // i.e., `ub_u - q * (ub_u + (-lb_u)) + minus_lb_v'. 03236 assign_r(ub_u, m_cu[n_u], ROUND_NOT_NEEDED); 03237 div2exp_assign_r(ub_u, ub_u, 1, ROUND_NOT_NEEDED); 03238 assign_r(q, expr_u, ROUND_NOT_NEEDED); 03239 div_assign_r(q, q, mpq_sc_den, ROUND_NOT_NEEDED); 03240 assign_r(minus_lb_u, matrix[n_u][n_u+1], ROUND_NOT_NEEDED); 03241 div2exp_assign_r(minus_lb_u, minus_lb_u, 1, ROUND_NOT_NEEDED); 03242 // Compute `ub_u - lb_u'. 03243 add_assign_r(minus_lb_u, ub_u, minus_lb_u, ROUND_NOT_NEEDED); 03244 // Compute `ub_u - q * (ub_u - lb_u)'. 03245 sub_mul_assign_r(ub_u, q, minus_lb_u, ROUND_NOT_NEEDED); 03246 assign_r(up_approx, ub_u, ROUND_UP); 03247 // Deducing `u - v <= -lb_v - (q * lb_u + (1-q) * ub_u)'. 03248 N& m_u_minus_v = (n_v < n_u) ? m_cu[n_v+1] : m_v[n_u]; 03249 add_assign_r(m_u_minus_v, minus_lb_v, up_approx, ROUND_UP); 03250 } 03251 } 03252 } 03253 else { 03254 assert(expr_u < 0); 03255 // If `expr_u' is negative, we can improve `-v - u'. 03256 neg_assign(minus_expr_u, expr_u); 03257 if (minus_expr_u >= sc_den) { 03258 // Here q <= -1: Deducing `-v - u <= -lb_v - ub_u'. 03259 // We avoid to check if `ub_u' is plus infinity, because 03260 // it is used for the computation of `lb_v'. 03261 // Let half = m_cu_u / 2. 03262 div2exp_assign_r(half, matrix[n_u+1][n_u], 1, ROUND_UP); 03263 N& m_minus_v_minus_u = (n_v < n_u) ? matrix[n_u][n_v+1] : m_v[n_u+1]; 03264 sub_assign_r(m_minus_v_minus_u, minus_lb_v, half, ROUND_UP); 03265 } 03266 else { 03267 // Here -1 < q < 0. 03268 typename OR_Matrix<N>::row_reference_type m_u = matrix[n_u]; 03269 const N& m_u_cu = m_u[n_u+1]; 03270 if (!is_plus_infinity(m_u_cu)) { 03271 // Let `ub_u' and `lb_u' be the known upper and lower bound 03272 // for `u', respectively. The upper bound for `-v - u' is 03273 // computed as `-lb_v - ((-q)*ub_u + (1+q)*lb_u)', 03274 // i.e., `minus_lb_v - lb_u + q*(ub_u - lb_u)'. 03275 assign_r(ub_u, matrix[n_u+1][n_u], ROUND_NOT_NEEDED); 03276 div2exp_assign_r(ub_u, ub_u, 1, ROUND_NOT_NEEDED); 03277 assign_r(q, expr_u, ROUND_NOT_NEEDED); 03278 div_assign_r(q, q, mpq_sc_den, ROUND_NOT_NEEDED); 03279 assign_r(minus_lb_u, m_u[n_u+1], ROUND_NOT_NEEDED); 03280 div2exp_assign_r(minus_lb_u, minus_lb_u, 1, ROUND_NOT_NEEDED); 03281 // Compute `ub_u - lb_u'. 03282 add_assign_r(ub_u, ub_u, minus_lb_u, ROUND_NOT_NEEDED); 03283 // Compute `-lb_u + q*(ub_u - lb_u)'. 03284 add_mul_assign_r(minus_lb_u, q, ub_u, ROUND_NOT_NEEDED); 03285 assign_r(up_approx, minus_lb_u, ROUND_UP); 03286 // Deducing `-v - u <= -lb_v - ((-q) * ub_u + (1+q) * lb_u)'. 03287 N& m_minus_v_minus_u = (n_v < n_u) ? m_u[n_v+1] : m_v[n_u+1]; 03288 add_assign_r(m_minus_v_minus_u, minus_lb_v, up_approx, ROUND_UP); 03289 } 03290 } 03291 } 03292 } 03293 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::get_limiting_octagon | ( | const Constraint_System & | cs, | |
| Octagonal_Shape< T > & | limiting_octagon | |||
| ) | const [inline, private] |
Adds to limiting_octagon the octagonal differences in cs that are satisfied by *this.
Definition at line 2771 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Octagonal_Shape< T >::extract_octagonal_difference(), Parma_Polyhedra_Library::Constraint::is_inequality(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::OR_Matrix< T >::row_begin(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and TEMP_INTEGER.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_BHMZ05_extrapolation_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_CC76_extrapolation_assign().
02772 { 02773 const dimension_type cs_space_dim = cs.space_dimension(); 02774 // Private method: the caller has to ensure the following. 02775 assert(cs_space_dim <= space_dim); 02776 02777 strong_closure_assign(); 02778 bool is_oct_changed = false; 02779 02780 // Allocate temporaries outside of the loop. 02781 TEMP_INTEGER(coeff); 02782 TEMP_INTEGER(term); 02783 DIRTY_TEMP(N, d); 02784 02785 for (Constraint_System::const_iterator cs_i = cs.begin(), 02786 cs_end = cs.end(); cs_i != cs_end; ++cs_i) { 02787 const Constraint& c = *cs_i; 02788 dimension_type num_vars = 0; 02789 dimension_type i = 0; 02790 dimension_type j = 0; 02791 // Constraints that are not octagonal differences are ignored. 02792 if (!extract_octagonal_difference(c, cs_space_dim, num_vars, i, j, 02793 coeff, term)) 02794 continue; 02795 02796 typedef typename OR_Matrix<N>::const_row_iterator Row_iterator; 02797 typedef typename OR_Matrix<N>::const_row_reference_type Row_reference; 02798 typedef typename OR_Matrix<N>::row_iterator Row_Iterator; 02799 typedef typename OR_Matrix<N>::row_reference_type Row_Reference; 02800 Row_iterator m_begin = matrix.row_begin(); 02801 // Select the cell to be modified for the "<=" part of the constraint. 02802 Row_iterator i_iter = m_begin + i; 02803 Row_reference m_i = *i_iter; 02804 OR_Matrix<N>& lo_mat = limiting_octagon.matrix; 02805 Row_Iterator lo_iter = lo_mat.row_begin() + i; 02806 Row_Reference lo_m_i = *lo_iter; 02807 N& lo_m_i_j = lo_m_i[j]; 02808 if (coeff < 0) 02809 neg_assign(coeff); 02810 // Compute the bound for `m_i_j', rounding towards plus infinity. 02811 div_round_up(d, term, coeff); 02812 if (m_i[j] <= d) 02813 if (c.is_inequality()) { 02814 if (lo_m_i_j > d) { 02815 lo_m_i_j = d; 02816 is_oct_changed = true; 02817 } 02818 else { 02819 // Select the right row of the cell. 02820 if (i%2 == 0) { 02821 ++i_iter; 02822 ++lo_iter; 02823 } 02824 else { 02825 --i_iter; 02826 --lo_iter; 02827 } 02828 Row_reference m_ci = *i_iter; 02829 Row_Reference lo_m_ci = *lo_iter; 02830 // Select the right column of the cell. 02831 dimension_type cj = coherent_index(j); 02832 N& lo_m_ci_cj = lo_m_ci[cj]; 02833 neg_assign(term); 02834 div_round_up(d, term, coeff); 02835 if (m_ci[cj] <= d && lo_m_ci_cj > d) { 02836 lo_m_ci_cj = d; 02837 is_oct_changed = true; 02838 } 02839 } 02840 } 02841 } 02842 // In general, adding a constraint does not preserve the strongly 02843 // closure of the octagon. 02844 if (is_oct_changed && limiting_octagon.marked_strongly_closed()) 02845 limiting_octagon.reset_strongly_closed(); 02846 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_successors | ( | std::vector< dimension_type > & | successor | ) | const [inline, private] |
Compute the (zero-equivalence classes) successor relation.
It is assumed that the octagon is not empty and strongly closed.
Definition at line 2100 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign().
02100 { 02101 assert(!marked_empty() && marked_strongly_closed()); 02102 assert(successor.size() == 0); 02103 // Variables are ordered according to their index. 02104 // The vector `successor' is used to indicate which variable 02105 // immediately follows a given one in the corresponding equivalence class. 02106 const dimension_type successor_size = matrix.num_rows(); 02107 // Initially, each variable is successor of its own zero-equivalence class. 02108 successor.reserve(successor_size); 02109 for (dimension_type i = 0; i < successor_size; ++i) 02110 successor.push_back(i); 02111 // Now compute actual successors. 02112 for (dimension_type i = successor_size; i-- > 0; ) { 02113 typename OR_Matrix<N>::const_row_iterator i_iter = matrix.row_begin()+i; 02114 typename OR_Matrix<N>::const_row_reference_type m_i = *i_iter; 02115 typename OR_Matrix<N>::const_row_reference_type m_ci = (i%2) ? 02116 *(i_iter-1) : *(i_iter+1); 02117 for (dimension_type j = 0; j < i; ++j) { 02118 //for (dimension_type j = i; j-- > 0; ) { 02119 dimension_type cj = coherent_index(j); 02120 if (is_additive_inverse(m_ci[cj], m_i[j])) 02121 // Choose as successor the variable having the greatest index. 02122 successor[j] = i; 02123 } 02124 } 02125 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_leaders | ( | std::vector< dimension_type > & | successor, | |
| std::vector< dimension_type > & | no_sing_leaders, | |||
| bool & | exist_sing_class, | |||
| dimension_type & | sing_leader | |||
| ) | const [inline, private] |
Compute the leaders of zero-equivalence classes.
It is assumed that the OS is not empty and strongly closed.
Definition at line 2161 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_congruences(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign().
02164 { 02165 assert(!marked_empty() && marked_strongly_closed()); 02166 assert(no_sing_leaders.size() == 0); 02167 dimension_type successor_size = successor.size(); 02168 std::deque<bool> dealt_with(successor_size, false); 02169 for (dimension_type i = 0; i < successor_size; ++i) { 02170 dimension_type next_i = successor[i]; 02171 if (!dealt_with[i]) { 02172 // The index is a leader. 02173 // Now check if it is a leader of a singular class or not. 02174 if (next_i == coherent_index(i)) { 02175 exist_sing_class = true; 02176 sing_leader = i; 02177 } 02178 else 02179 no_sing_leaders.push_back(i); 02180 } 02181 // The following index isn't a leader. 02182 dealt_with[next_i] = true; 02183 } 02184 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_leaders | ( | std::vector< dimension_type > & | leaders | ) | const [inline, private] |
Compute the leaders of zero-equivalence classes.
It is assumed that the OS is not empty and strongly closed.
Definition at line 2130 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix.
02130 { 02131 assert(!marked_empty() && marked_strongly_closed()); 02132 assert(leaders.size() == 0); 02133 // Variables are ordered according to their index. 02134 // The vector `leaders' is used to indicate the smallest variable 02135 // that belongs to the corresponding equivalence class. 02136 const dimension_type leader_size = matrix.num_rows(); 02137 // Initially, each variable is leader of its own zero-equivalence class. 02138 leaders.reserve(leader_size); 02139 for (dimension_type i = 0; i < leader_size; ++i) 02140 leaders.push_back(i); 02141 // Now compute actual leaders. 02142 for (typename OR_Matrix<N>::const_row_iterator i_iter = matrix.row_begin(), 02143 matrix_row_end = matrix.row_end(); 02144 i_iter != matrix_row_end; ++i_iter) { 02145 typename OR_Matrix<N>::const_row_reference_type m_i = *i_iter; 02146 dimension_type i = i_iter.index(); 02147 typename OR_Matrix<N>::const_row_reference_type m_ci = 02148 (i%2) ? *(i_iter-1) : *(i_iter+1); 02149 for (dimension_type j = 0; j < i; ++j) { 02150 dimension_type cj = coherent_index(j); 02151 if (is_additive_inverse(m_ci[cj], m_i[j])) 02152 // Choose as leader the variable having the smaller index. 02153 leaders[i] = leaders[j]; 02154 } 02155 } 02156 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign | ( | ) | const [inline, private] |
Removes the redundant constraints from this->matrix.
Definition at line 2188 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_leaders(), Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_successors(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_strongly_reduced(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::swap().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_constraints().
02188 { 02189 // Zero-dimensional Octagonal shapes are necessarily reduced. 02190 if (space_dim == 0) 02191 return; 02192 02193 // First find the tightest constraints for this octagon. 02194 strong_closure_assign(); 02195 02196 // If `*this' is empty, then there is nothing to reduce. 02197 if (marked_empty()) 02198 return; 02199 02200 // Step 1: compute zero-equivalence classes. 02201 // Variables corresponding to indices `i' and `j' are zero-equivalent 02202 // if they lie on a zero-weight loop; since the matrix is strongly 02203 // closed, this happens if and only if matrix[i][j] == -matrix[ci][cj]. 02204 std::vector<dimension_type> no_sing_leaders; 02205 dimension_type sing_leader = 0; 02206 bool exist_sing_class = false; 02207 std::vector<dimension_type> successor; 02208 compute_successors(successor); 02209 compute_leaders(successor, no_sing_leaders, exist_sing_class, sing_leader); 02210 const dimension_type num_no_sing_leaders = no_sing_leaders.size(); 02211 02212 Octagonal_Shape aux(space_dim); 02213 // Step 2: add to auxiliary octagon only non-redundant 02214 // constraints and construct a 0-cycle using only 02215 // the leaders of the non-singular classes. 02216 for (dimension_type li = 0; li < num_no_sing_leaders; ++li) { 02217 const dimension_type i = no_sing_leaders[li]; 02218 const dimension_type ci = coherent_index(i); 02219 typename OR_Matrix<N>::const_row_reference_type m_i = 02220 *(matrix.row_begin()+i); 02221 typename OR_Matrix<N>::row_reference_type aux_i = 02222 *(aux.matrix.row_begin()+i); 02223 if (i%2 == 0) { 02224 // Each positive equivalence class must have a single 0-cycle 02225 // connecting all equivalent variables in increasing order. 02226 // Note: by coherence assumption, the variables in the 02227 // corresponding negative equivalence class are 02228 // automatically connected. 02229 if (i != successor[i]) { 02230 dimension_type j = i; 02231 dimension_type next_j = successor[j]; 02232 while (j != next_j) { 02233 aux.matrix[next_j][j] = matrix[next_j][j]; 02234 j = next_j; 02235 next_j = successor[j]; 02236 } 02237 const dimension_type cj = coherent_index(j); 02238 aux.matrix[cj][ci] = matrix[cj][ci]; 02239 } 02240 } 02241 02242 dimension_type rs_li = (li%2) ? li :li+1; 02243 // Check if the constraint is redundant. 02244 DIRTY_TEMP(N, tmp); 02245 for (dimension_type lj = 0 ; lj <= rs_li; ++lj) { 02246 const dimension_type j = no_sing_leaders[lj]; 02247 const dimension_type cj = coherent_index(j); 02248 const N& m_i_j = m_i[j]; 02249 const N& m_i_ci = m_i[ci]; 02250 bool to_add = true; 02251 // Control if the constraint is redundant by strong-coherence, 02252 // that is: 02253 // m_i_j >= (m_i_ci + m_cj_j)/2, where j != ci. 02254 if (j != ci) { 02255 add_assign_r(tmp, m_i_ci, matrix[cj][j], ROUND_UP); 02256 div2exp_assign_r(tmp, tmp, 1, ROUND_UP); 02257 if (m_i_j >= tmp) { 02258 to_add = false; 02259 continue; 02260 } 02261 } 02262 // Control if the constraint is redundant by strong closure, that is 02263 // if there is a path from i to j (i = i_0, ... , i_n = j), such that 02264 // m_i_j = sum_{k=0}^{n-1} m_{i_k}_{i_(k+1)}. 02265 // Since the octagon is already strongly closed, the above relation 02266 // is reduced to three case, in accordance with k, i, j inter-depend: 02267 // exit k such that 02268 // 1.) m_i_j >= m_i_k + m_cj_ck, if k < j < i; or 02269 // 2.) m_i_j >= m_i_k + m_k,_j, if j < k < i; or 02270 // 3.) m_i_j >= m_ck_ci + m_k_j, if j < i < k. 02271 // Note: `i > j'. 02272 for (dimension_type lk = 0; lk < num_no_sing_leaders; ++lk) { 02273 const dimension_type k = no_sing_leaders[lk]; 02274 if (k != i && k != j) { 02275 dimension_type ck = coherent_index(k); 02276 if (k < j) 02277 // Case 1. 02278 add_assign_r(tmp, m_i[k], matrix[cj][ck], ROUND_UP); 02279 else if (k < i) 02280 // Case 2. 02281 add_assign_r(tmp, m_i[k], matrix[k][j], ROUND_UP); 02282 else 02283 // Case 3. 02284 add_assign_r(tmp, matrix[ck][ci], matrix[k][j], ROUND_UP); 02285 02286 // Checks if the constraint is redundant. 02287 if (m_i_j >= tmp) { 02288 to_add = false; 02289 break; 02290 } 02291 } 02292 } 02293 02294 // The constraint is not redundant. 02295 if (to_add) 02296 aux_i[j] = m_i_j; 02297 } 02298 } 02299 02300 // If there exist a singular equivalence class, then it must have a 02301 // single 0-cycle connecting all the positive and negative equivalent 02302 // variables. 02303 // Note: the singular class is not connected with the other classes. 02304 if (exist_sing_class) { 02305 aux.matrix[sing_leader][sing_leader+1] 02306 = matrix[sing_leader][sing_leader+1]; 02307 if (successor[sing_leader+1] != sing_leader+1) { 02308 dimension_type j = sing_leader; 02309 dimension_type next_jj = successor[j+1]; 02310 while (next_jj != j+1) { 02311 aux.matrix[next_jj][j] = matrix[next_jj][j]; 02312 j = next_jj; 02313 next_jj = successor[j+1]; 02314 } 02315 aux.matrix[j+1][j] = matrix[j+1][j]; 02316 } 02317 else 02318 aux.matrix[sing_leader+1][sing_leader] 02319 = matrix[sing_leader+1][sing_leader]; 02320 } 02321 02322 Octagonal_Shape<T>& x = const_cast<Octagonal_Shape<T>&>(*this); 02323 aux.reset_strongly_closed(); 02324 02325 #ifndef NDEBUG 02326 { 02327 // We assume that `aux' is equal to `*this'. 02328 const Octagonal_Shape x_copy = *this; 02329 const Octagonal_Shape y_copy = aux; 02330 assert(x_copy == y_copy); 02331 } 02332 #endif 02333 02334 std::swap(x, aux); 02335 assert(is_strongly_reduced()); 02336 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::is_strongly_reduced | ( | ) | const [inline, private] |
Returns true if and only if this->matrix is strongly reduced.
Definition at line 968 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, and PLUS_INFINITY.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign().
00968 { 00969 // This method is only used in assertions: efficiency is not a must. 00970 00971 // An empty octagon is already transitively reduced. 00972 if (marked_empty()) 00973 return true; 00974 00975 Octagonal_Shape x = *this; 00976 // The matrix representing an OS is strongly reduced if, by removing 00977 // any constraint, the resulting matrix describes a different OS. 00978 for (typename OR_Matrix<N>::const_row_iterator iter = matrix.row_begin(), 00979 matrix_row_end = matrix.row_end(); iter != matrix_row_end; ++iter) { 00980 typename OR_Matrix<N>::const_row_reference_type m_i = *iter; 00981 const dimension_type i = iter.index(); 00982 for (dimension_type j = iter.row_size(); j-- > 0; ) { 00983 if (!is_plus_infinity(m_i[j])) { 00984 Octagonal_Shape x_copy = *this; 00985 assign_r(x_copy.matrix[i][j], PLUS_INFINITY, ROUND_NOT_NEEDED); 00986 if (x == x_copy) 00987 return false; 00988 } 00989 } 00990 } 00991 // The octagon is just reduced. 00992 return true; 00993 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::is_strong_coherent | ( | ) | const [inline, private] |
Returns true if in the octagon taken two at a time unary constraints, there is also the constraint that represent their sum.
Definition at line 932 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::is_plus_infinity(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::OK().
00932 { 00933 // This method is only used by method OK() so as to check if a 00934 // strongly closed matrix is also strong-coherent, as it must be. 00935 const dimension_type num_rows = matrix.num_rows(); 00936 00937 // Allocated here once and for all. 00938 DIRTY_TEMP(N, semi_sum); 00939 // The strong-coherence is: for every indexes i and j (and i != j) 00940 // matrix[i][j] <= (matrix[i][ci] + matrix[cj][j])/2 00941 // where ci = i + 1, if i is even number or 00942 // ci = i - 1, if i is odd. 00943 // Ditto for cj. 00944 for (dimension_type i = num_rows; i-- > 0; ) { 00945 typename OR_Matrix<N>::const_row_iterator iter = matrix.row_begin() + i; 00946 typename OR_Matrix<N>::const_row_reference_type m_i = *iter; 00947 const N& m_i_ci = m_i[coherent_index(i)]; 00948 for (dimension_type j = matrix.row_size(i); j-- > 0; ) 00949 // Note: on the main diagonal only PLUS_INFINITY can occur. 00950 if (i != j) { 00951 const N& m_cj_j = matrix[coherent_index(j)][j]; 00952 if (!is_plus_infinity(m_i_ci) 00953 && !is_plus_infinity(m_cj_j)) { 00954 // Compute (m_i_ci + m_cj_j)/2 into `semi_sum', 00955 // rounding the result towards plus infinity. 00956 add_assign_r(semi_sum, m_i_ci, m_cj_j, ROUND_UP); 00957 div2exp_assign_r(semi_sum, semi_sum, 1, ROUND_UP); 00958 if (m_i[j] > semi_sum) 00959 return false; 00960 } 00961 } 00962 } 00963 return true; 00964 }
| bool Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_coherence_would_make_empty | ( | ) | const [inline, private] |
Definition at line 1935 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::is_even(), Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point().
01935 { 01936 assert(std::numeric_limits<N>::is_integer); 01937 assert(marked_strongly_closed()); 01938 const dimension_type space_dim = space_dimension(); 01939 for (dimension_type i = 0; i < 2*space_dim; i += 2) { 01940 const dimension_type ci = i+1; 01941 const N& mat_i_ci = matrix[i][ci]; 01942 if (!is_plus_infinity(mat_i_ci) 01943 // Check for oddness of `mat_i_ci'. 01944 && !is_even(mat_i_ci) 01945 // Check for zero-equivalence of `i' and `ci'. 01946 && is_additive_inverse(mat_i_ci, matrix[ci][i])) 01947 return true; 01948 } 01949 return false; 01950 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign | ( | ) | const [inline, private] |
Assigns to this->matrix its strong closure.
Strong closure is a necessary condition for the precision and/or the correctness of many methods. It explicitly records into matrix those constraints that are implicitly obtainable by the other ones, therefore obtaining a canonical representation for the OS.
Definition at line 1767 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::min_assign(), PLUS_INFINITY, Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_coherence_assign().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::euclidean_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::get_limiting_octagon(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_bounded(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::l_infinity_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::rectilinear_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::unconstrain(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign().
01767 { 01768 // Do something only if necessary (zero-dim implies strong closure). 01769 if (marked_empty() || marked_strongly_closed() || space_dim == 0) 01770 return; 01771 01772 // Even though the octagon will not change, its internal representation 01773 // is going to be modified by the closure algorithm. 01774 Octagonal_Shape& x = const_cast<Octagonal_Shape<T>&>(*this); 01775 01776 typedef typename OR_Matrix<N>::row_iterator Row_Iterator; 01777 typedef typename OR_Matrix<N>::row_reference_type Row_Reference; 01778 01779 const dimension_type n_rows = x.matrix.num_rows(); 01780 const Row_Iterator m_begin = x.matrix.row_begin(); 01781 const Row_Iterator m_end = x.matrix.row_end(); 01782 01783 // Fill the main diagonal with zeros. 01784 for (Row_Iterator i = m_begin; i != m_end; ++i) { 01785 assert(is_plus_infinity((*i)[i.index()])); 01786 assign_r((*i)[i.index()], 0, ROUND_NOT_NEEDED); 01787 } 01788 01789 // This algorithm is given by two steps: the first one is a simple 01790 // adaptation of the `shortest-path closure' using the Floyd-Warshall 01791 // algorithm; the second one is the `strong-coherence' algorithm. 01792 // It is important to note that after the strong-coherence, 01793 // the octagon is still shortest-path closed and hence, strongly closed. 01794 01795 // Recall that, given an index `h', we indicate with `ch' the coherent 01796 // index, i.e., the index such that: 01797 // ch = h + 1, if h is an even number; 01798 // ch = h - 1, if h is an odd number. 01799 01800 typename OR_Matrix<N>::element_iterator iter_ij; 01801 std::vector<N> vec_k(n_rows); 01802 std::vector<N> vec_ck(n_rows); 01803 DIRTY_TEMP(N, sum1); 01804 DIRTY_TEMP(N, sum2); 01805 Row_Reference x_k; 01806 Row_Reference x_ck; 01807 Row_Reference x_i; 01808 Row_Reference x_ci; 01809 01810 // Since the index `j' of the inner loop will go from 0 up to `i', 01811 // the three nested loops have to be executed twice. 01812 for (int twice = 0; twice < 2; ++twice) { 01813 01814 Row_Iterator x_k_iter = m_begin; 01815 Row_Iterator x_i_iter = m_begin; 01816 for (dimension_type k = 0; k < n_rows; k += 2) { 01817 const dimension_type ck = k+1; 01818 // Re-initialize the element iterator. 01819 iter_ij = x.matrix.element_begin(); 01820 // Compute the row references `x_k' and `x_ck'. 01821 x_k = *x_k_iter; 01822 ++x_k_iter; 01823 x_ck = *x_k_iter; 01824 ++x_k_iter; 01825 01826 for (dimension_type i = 0; i <= k; i += 2) { 01827 const dimension_type ci = i+1; 01828 // Storing x_k_i == x_ci_ck. 01829 vec_k[i] = x_k[i]; 01830 // Storing x_k_ci == x_i_ck. 01831 vec_k[ci] = x_k[ci]; 01832 // Storing x_ck_i == x_ci_k. 01833 vec_ck[i] = x_ck[i]; 01834 // Storing x_ck_ci == x_i_k. 01835 vec_ck[ci] = x_ck[ci]; 01836 } 01837 x_i_iter = x_k_iter; 01838 for (dimension_type i = k+2; i < n_rows; i += 2) { 01839 const dimension_type ci = i+1; 01840 x_i = *x_i_iter; 01841 ++x_i_iter; 01842 x_ci = *x_i_iter; 01843 ++x_i_iter; 01844 // Storing x_k_i == x_ci_ck. 01845 vec_k[i] = x_ci[ck]; 01846 // Storing x_k_ci == x_i_ck. 01847 vec_k[ci] = x_i[ck]; 01848 // Storing x_ck_i == x_ci_k. 01849 vec_ck[i] = x_ci[k]; 01850 // Storing x_ck_ci == x_i_k. 01851 vec_ck[ci] = x_i[k]; 01852 } 01853 01854 for (dimension_type i = 0; i < n_rows; ++i) { 01855 const dimension_type ci = coherent_index(i); 01856 const N& vec_k_ci = vec_k[ci]; 01857 const N& vec_ck_ci = vec_ck[ci]; 01858 // Unfolding two iterations on `j': this ensures that 01859 // the loop exit condition `j <= i' is OK. 01860 for (dimension_type j = 0; j <= i; ) { 01861 // First iteration: 01862 // sum1 = x_i_k + x_k_j == x_ck_ci + x_k_j; 01863 // sum2 = x_i_ck + x_ck_j == x_k_ci + x_ck_j. 01864 add_assign_r(sum1, vec_ck_ci, vec_k[j], ROUND_UP); 01865 add_assign_r(sum2, vec_k_ci, vec_ck[j], ROUND_UP); 01866 min_assign(sum1, sum2); 01867 min_assign(*iter_ij, sum1); 01868 // Exiting the first iteration: loop index control. 01869 ++j; 01870 ++iter_ij; 01871 // Second iteration: ditto. 01872 add_assign_r(sum1, vec_ck_ci, vec_k[j], ROUND_UP); 01873 add_assign_r(sum2, vec_k_ci, vec_ck[j], ROUND_UP); 01874 min_assign(sum1, sum2); 01875 min_assign(*iter_ij, sum1); 01876 // Exiting the second iteration: loop index control. 01877 ++j; 01878 ++iter_ij; 01879 } 01880 } 01881 } 01882 } 01883 01884 // Check for emptiness: the octagon is empty if and only if there is a 01885 // negative value in the main diagonal. 01886 for (Row_Iterator i = m_begin; i != m_end; ++i) { 01887 N& x_i_i = (*i)[i.index()]; 01888 if (sgn(x_i_i) < 0) { 01889 x.set_empty(); 01890 return; 01891 } 01892 else { 01893 assert(sgn(x_i_i) == 0); 01894 // Restore PLUS_INFINITY on the main diagonal. 01895 assign_r(x_i_i, PLUS_INFINITY, ROUND_NOT_NEEDED); 01896 } 01897 } 01898 01899 // Step 2: we enforce the strong coherence. 01900 x.strong_coherence_assign(); 01901 // The octagon is not empty and it is now strongly closed. 01902 x.set_strongly_closed(); 01903 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_coherence_assign | ( | ) | [inline, private] |
Applies the strong-coherence step to this->matrix.
Definition at line 1907 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, and Parma_Polyhedra_Library::min_assign().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().
01907 { 01908 // The strong-coherence is: for every indexes i and j 01909 // m_i_j <= (m_i_ci + m_cj_j)/2 01910 // where ci = i + 1, if i is even number or 01911 // ci = i - 1, if i is odd. 01912 // Ditto for cj. 01913 DIRTY_TEMP(N, semi_sum); 01914 for (typename OR_Matrix<N>::row_iterator i_iter = matrix.row_begin(), 01915 i_end = matrix.row_end(); i_iter != i_end; ++i_iter) { 01916 typename OR_Matrix<N>::row_reference_type x_i = *i_iter; 01917 const dimension_type i = i_iter.index(); 01918 const N& x_i_ci = x_i[coherent_index(i)]; 01919 // Avoid to do unnecessary sums. 01920 if (!is_plus_infinity(x_i_ci)) 01921 for (dimension_type j = 0, rs_i = i_iter.row_size(); j < rs_i; ++j) 01922 if (i != j) { 01923 const N& x_cj_j = matrix[coherent_index(j)][j]; 01924 if (!is_plus_infinity(x_cj_j)) { 01925 add_assign_r(semi_sum, x_i_ci, x_cj_j, ROUND_UP); 01926 div2exp_assign_r(semi_sum, semi_sum, 1, ROUND_UP); 01927 min_assign(x_i[j], semi_sum); 01928 } 01929 } 01930 } 01931 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign | ( | Variable | var | ) | const [inline, private] |
Puts in *this all implicit constraints and computes the tighter ones.
| var | The variable of the altered constraints. |
.
Definition at line 1955 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::coherent_index(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::min_assign(), PLUS_INFINITY, Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_coherence_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image().
01955 { 01956 // `var' should be one of the dimensions of the octagon. 01957 if (var.id() >= space_dim) 01958 throw_dimension_incompatible("incremental_strong_closure_assign(v)", 01959 var.id()); 01960 01961 // Do something only if necessary. 01962 if (marked_empty() || marked_strongly_closed()) 01963 return; 01964 01965 // Zero-dimensional octagons are necessarily strongly closed. 01966 if (space_dim == 0) 01967 return; 01968 01969 Octagonal_Shape& x = const_cast<Octagonal_Shape<T>&>(*this); 01970 01971 typedef typename OR_Matrix<N>::row_iterator Row_Iterator; 01972 typedef typename OR_Matrix<N>::row_reference_type Row_Reference; 01973 01974 const Row_Iterator m_begin = x.matrix.row_begin(); 01975 const Row_Iterator m_end = x.matrix.row_end(); 01976 01977 // Fill the main diagonal with zeros. 01978 for (Row_Iterator i = m_begin; i != m_end; ++i) { 01979 assert(is_plus_infinity((*i)[i.index()])); 01980 assign_r((*i)[i.index()], 0, ROUND_NOT_NEEDED); 01981 } 01982 01983 // Using the incremental Floyd-Warshall algorithm. 01984 // Step 1: Improve all constraints on variable `var'. 01985 const dimension_type v = 2*var.id(); 01986 const dimension_type cv = v+1; 01987 Row_Iterator v_iter = m_begin + v; 01988 Row_Iterator cv_iter = v_iter + 1; 01989 Row_Reference x_v = *v_iter; 01990 Row_Reference x_cv = *cv_iter; 01991 const dimension_type rs_v = v_iter.row_size(); 01992 const dimension_type n_rows = x.matrix.num_rows(); 01993 DIRTY_TEMP(N, sum); 01994 for (Row_Iterator k_iter = m_begin; k_iter != m_end; ++k_iter) { 01995 const dimension_type k = k_iter.index(); 01996 const dimension_type ck = coherent_index(k); 01997 const dimension_type rs_k = k_iter.row_size(); 01998 Row_Reference x_k = *k_iter; 01999 Row_Reference x_ck = (k%2) ? *(k_iter-1) : *(k_iter+1); 02000 02001 for (Row_Iterator i_iter = m_begin; i_iter != m_end; ++i_iter) { 02002 const dimension_type i = i_iter.index(); 02003 const dimension_type ci = coherent_index(i); 02004 const dimension_type rs_i = i_iter.row_size(); 02005 Row_Reference x_i = *i_iter; 02006 Row_Reference x_ci = (i%2) ? *(i_iter-1) : *(i_iter+1); 02007 02008 const N& x_i_k = (k < rs_i) ? x_i[k] : x_ck[ci]; 02009 if (!is_plus_infinity(x_i_k)) { 02010 const N& x_k_v = (v < rs_k) ? x_k[v] : x_cv[ck]; 02011 if (!is_plus_infinity(x_k_v)) { 02012 add_assign_r(sum, x_i_k, x_k_v, ROUND_UP); 02013 N& x_i_v = (v < rs_i) ? x_i[v] : x_cv[ci]; 02014 min_assign(x_i_v, sum); 02015 } 02016 const N& x_k_cv = (cv < rs_k) ? x_k[cv] : x_v[ck]; 02017 if (!is_plus_infinity(x_k_cv)) { 02018 add_assign_r(sum, x_i_k, x_k_cv, ROUND_UP); 02019 N& x_i_cv = (cv < rs_i) ? x_i[cv] : x_v[ci]; 02020 min_assign(x_i_cv, sum); 02021 } 02022 } 02023 const N& x_k_i = (i < rs_k) ? x_k[i] : x_ci[ck]; 02024 if (!is_plus_infinity(x_k_i)) { 02025 const N& x_v_k = (k < rs_v) ? x_v[k] : x_ck[cv]; 02026 if (!is_plus_infinity(x_v_k)) { 02027 N& x_v_i = (i < rs_v) ? x_v[i] : x_ci[cv]; 02028 add_assign_r(sum, x_v_k, x_k_i, ROUND_UP); 02029 min_assign(x_v_i, sum); 02030 } 02031 const N& x_cv_k = (k < rs_v) ? x_cv[k] : x_ck[v]; 02032 if (!is_plus_infinity(x_cv_k)) { 02033 N& x_cv_i = (i < rs_v) ? x_cv[i] : x_ci[v]; 02034 add_assign_r(sum, x_cv_k, x_k_i, ROUND_UP); 02035 min_assign(x_cv_i, sum); 02036 } 02037 } 02038 02039 } 02040 } 02041 02042 // Step 2: improve the other bounds by using the precise bounds 02043 // for the constraints on `var'. 02044 for (Row_Iterator i_iter = m_begin; i_iter != m_end; ++i_iter) { 02045 const dimension_type i = i_iter.index(); 02046 const dimension_type ci = coherent_index(i); 02047 const dimension_type rs_i = i_iter.row_size(); 02048 Row_Reference x_i = *i_iter; 02049 Row_Reference x_ci = (i%2) ? *(i_iter-1) : *(i_iter+1); 02050 const N& x_i_v = (v < rs_i) ? x_i[v] : x_cv[ci]; 02051 // TODO: see if it is possible to optimize this inner loop 02052 // by splitting it into several parts, so as to avoid 02053 // conditional expressions. 02054 for (dimension_type j = 0; j < n_rows; ++j) { 02055 const dimension_type cj = coherent_index(j); 02056 Row_Reference x_cj = *(m_begin+cj); 02057 N& x_i_j = (j < rs_i) ? x_i[j] : x_cj[ci]; 02058 if (!is_plus_infinity(x_i_v)) { 02059 const N& x_v_j = (j < rs_v) ? x_v[j] : x_cj[cv]; 02060 if (!is_plus_infinity(x_v_j)) { 02061 add_assign_r(sum, x_i_v, x_v_j, ROUND_UP); 02062 min_assign(x_i_j, sum); 02063 } 02064 } 02065 const N& x_i_cv = (cv < rs_i) ? x_i[cv] : x_v[ci]; 02066 if (!is_plus_infinity(x_i_cv)) { 02067 const N& x_cv_j = (j < rs_v) ? x_cv[j] : x_cj[v]; 02068 if (!is_plus_infinity(x_cv_j)) { 02069 add_assign_r(sum, x_i_cv, x_cv_j, ROUND_UP); 02070 min_assign(x_i_j, sum); 02071 } 02072 } 02073 } 02074 } 02075 02076 // Check for emptiness: the octagon is empty if and only if there is a 02077 // negative value on the main diagonal. 02078 for (Row_Iterator i = m_begin; i != m_end; ++i) { 02079 N& x_i_i = (*i)[i.index()]; 02080 if (sgn(x_i_i) < 0) { 02081 x.set_empty(); 02082 return; 02083 } 02084 else { 02085 // Restore PLUS_INFINITY on the main diagonal. 02086 assert(sgn(x_i_i) == 0); 02087 assign_r(x_i_i, PLUS_INFINITY, ROUND_NOT_NEEDED); 02088 } 02089 } 02090 02091 // Step 3: we enforce the strong coherence. 02092 x.strong_coherence_assign(); 02093 // The octagon is not empty and it is now strongly closed. 02094 x.set_strongly_closed(); 02095 }
| bool Parma_Polyhedra_Library::Octagonal_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 997 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::extract_octagonal_difference(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::MINIMIZATION, Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, Parma_Polyhedra_Library::MIP_Problem::solve(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), TEMP_INTEGER, and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds_from_above(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds_from_below().
00998 { 00999 // The dimension of `expr' should not be greater than the dimension 01000 // of `*this'. 01001 const dimension_type expr_space_dim = expr.space_dimension(); 01002 if (space_dim < expr_space_dim) 01003 throw_dimension_incompatible((from_above 01004 ? "bounds_from_above(e)" 01005 : "bounds_from_below(e)"), "e", expr); 01006 strong_closure_assign(); 01007 01008 // A zero-dimensional or empty octagon bounds everything. 01009 if (space_dim == 0 || marked_empty()) 01010 return true; 01011 01012 // The constraint `c' is used to check if `expr' is an octagonal difference 01013 // and, in this case, to select the cell. 01014 const Constraint& c = (from_above) ? expr <= 0 : expr >= 0; 01015 dimension_type num_vars = 0; 01016 dimension_type i = 0; 01017 dimension_type j = 0; 01018 TEMP_INTEGER(coeff); 01019 TEMP_INTEGER(term); 01020 if (extract_octagonal_difference(c, c.space_dimension(), num_vars, 01021 i, j, coeff, term)) { 01022 if (num_vars == 0) 01023 return true; 01024 // Select the cell to be checked. 01025 typename OR_Matrix<N>::const_row_iterator i_iter = matrix.row_begin() + i; 01026 typename OR_Matrix<N>::const_row_reference_type m_i = *i_iter; 01027 return !is_plus_infinity(m_i[j]); 01028 } 01029 else { 01030 // `c' is not an octagonal constraint: use the MIP solver. 01031 Optimization_Mode mode_bounds = 01032 from_above ? MAXIMIZATION : MINIMIZATION; 01033 MIP_Problem mip(space_dim, constraints(), expr, mode_bounds); 01034 return (mip.solve() == OPTIMIZED_MIP_PROBLEM); 01035 } 01036 }
| bool Parma_Polyhedra_Library::Octagonal_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. |
*this is empty or expr is not bounded in the appropriate direction, false is returned and ext_n, ext_d and included are left untouched.
Definition at line 1040 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::extract_octagonal_difference(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, 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, Parma_Polyhedra_Library::MIP_Problem::solve(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), TEMP_INTEGER, and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::Octagonal_Shape< T >::maximize(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::minimize().
01043 { 01044 // The dimension of `expr' should not be greater than the dimension 01045 // of `*this'. 01046 const dimension_type expr_space_dim = expr.space_dimension(); 01047 if (space_dim < expr_space_dim) 01048 throw_dimension_incompatible((maximize 01049 ? "maximize(e, ...)" 01050 : "minimize(e, ...)"), "e", expr); 01051 // Deal with zero-dim octagons first. 01052 if (space_dim == 0) { 01053 if (marked_empty()) 01054 return false; 01055 else { 01056 ext_n = expr.inhomogeneous_term(); 01057 ext_d = 1; 01058 included = true; 01059 return true; 01060 } 01061 } 01062 01063 strong_closure_assign(); 01064 // For an empty OS we simply return false. 01065 if (marked_empty()) 01066 return false; 01067 01068 // The constraint `c' is used to check if `expr' is an octagonal difference 01069 // and, in this case, to select the cell. 01070 const Constraint& c = (maximize) ? expr <= 0 : expr >= 0; 01071 dimension_type num_vars = 0; 01072 dimension_type i = 0; 01073 dimension_type j = 0; 01074 TEMP_INTEGER(coeff); 01075 TEMP_INTEGER(term); 01076 if (!extract_octagonal_difference(c, c.space_dimension(), num_vars, 01077 i, j, coeff, term)) { 01078 // `c' is not an octagonal constraint: use the MIP solver. 01079 Optimization_Mode max_min = (maximize) ? MAXIMIZATION : MINIMIZATION; 01080 MIP_Problem mip(space_dim, constraints(), expr, max_min); 01081 if (mip.solve() == OPTIMIZED_MIP_PROBLEM) { 01082 mip.optimal_value(ext_n, ext_d); 01083 included = true; 01084 return true; 01085 } 01086 else 01087 // Here`expr' is unbounded in `*this'. 01088 return false; 01089 } 01090 else { 01091 // `c' is an octagonal constraint. 01092 if (num_vars == 0) { 01093 ext_n = expr.inhomogeneous_term(); 01094 ext_d = 1; 01095 included = true; 01096 return true; 01097 } 01098 01099 // Select the cell to be checked. 01100 typename OR_Matrix<N>::const_row_iterator i_iter = matrix.row_begin() + i; 01101 typename OR_Matrix<N>::const_row_reference_type m_i = *i_iter; 01102 DIRTY_TEMP(N, d); 01103 if (!is_plus_infinity(m_i[j])) { 01104 const Coefficient& b = expr.inhomogeneous_term(); 01105 TEMP_INTEGER(minus_b); 01106 neg_assign(minus_b, b); 01107 const Coefficient& sc_b = maximize ? b : minus_b; 01108 assign_r(d, sc_b, ROUND_UP); 01109 // Set `coeff_expr' to the absolute value of coefficient of a variable 01110 // of `expr'. 01111 DIRTY_TEMP(N, coeff_expr); 01112 const Coefficient& coeff_i = expr.coefficient(Variable(i/2)); 01113 const int sign_i = sgn(coeff_i); 01114 if (sign_i > 0) 01115 assign_r(coeff_expr, coeff_i, ROUND_UP); 01116 else { 01117 TEMP_INTEGER(minus_coeff_i); 01118 neg_assign(minus_coeff_i, expr.coefficient(Variable(i/2))); 01119 assign_r(coeff_expr, minus_coeff_i, ROUND_UP); 01120 } 01121 // Approximating the maximum/minimum of `expr'. 01122 if (num_vars == 1) { 01123 DIRTY_TEMP(N, m_i_j); 01124 div2exp_assign_r(m_i_j, m_i[j], 1, ROUND_UP); 01125 add_mul_assign_r(d, coeff_expr, m_i_j, ROUND_UP); 01126 } 01127 else 01128 add_mul_assign_r(d, coeff_expr, m_i[j], ROUND_UP); 01129 numer_denom(d, ext_n, ext_d); 01130 if (!maximize) 01131 neg_assign(ext_n); 01132 included = true; 01133 return true; 01134 } 01135 01136 // The `expr' is unbounded. 01137 return false; 01138 } 01139 }
| bool Parma_Polyhedra_Library::Octagonal_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. |
*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 1143 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::MIP_Problem::evaluate_objective_function(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_universe(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::MINIMIZATION, Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, Parma_Polyhedra_Library::MIP_Problem::optimizing_point(), Parma_Polyhedra_Library::MIP_Problem::solve(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible().
01146 { 01147 // The dimension of `expr' should not be greater than the dimension 01148 // of `*this'. 01149 const dimension_type expr_space_dim = expr.space_dimension(); 01150 if (space_dim < expr_space_dim) 01151 throw_dimension_incompatible((maximize 01152 ? "maximize(e, ...)" 01153 : "minimize(e, ...)"), "e", expr); 01154 // Deal with zero-dim octagons first. 01155 if (space_dim == 0) { 01156 if (marked_empty()) 01157 return false; 01158 else { 01159 ext_n = expr.inhomogeneous_term(); 01160 ext_d = 1; 01161 included = true; 01162 g = point(); 01163 return true; 01164 } 01165 } 01166 01167 strong_closure_assign(); 01168 // For an empty OS we simply return false. 01169 if (marked_empty()) 01170 return false; 01171 if (!is_universe()) { 01172 // We use MIP_Problems to handle constraints that are not 01173 // octagonal difference. 01174 Optimization_Mode max_min = (maximize) ? MAXIMIZATION : MINIMIZATION; 01175 MIP_Problem mip(space_dim, constraints(), expr, max_min); 01176 if (mip.solve() == OPTIMIZED_MIP_PROBLEM) { 01177 g = mip.optimizing_point(); 01178 mip.evaluate_objective_function(g, ext_n, ext_d); 01179 included = true; 01180 return true; 01181 } 01182 } 01183 // The `expr' is unbounded. 01184 return false; 01185 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible | ( | const char * | method, | |
| const Octagonal_Shape< T > & | x | |||
| ) | const [inline, private] |
Definition at line 6296 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruence(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constrains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_BHMZ05_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruence(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::time_elapse_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::unconstrain(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign().
06297 { 06298 std::ostringstream s; 06299 s << "PPL::Octagonal_Shape::" << method << ":\n" 06300 << "this->space_dimension() == " << space_dimension() 06301 << ", y->space_dimension() == " << y.space_dimension() << "."; 06302 throw std::invalid_argument(s.str()); 06303 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible | ( | const char * | method, | |
| dimension_type | required_dim | |||
| ) | const [inline, private] |
Definition at line 6308 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension().
06309 { 06310 std::ostringstream s; 06311 s << "PPL::Octagonal_Shape::" << method << ":\n" 06312 << "this->space_dimension() == " << space_dimension() 06313 << ", required dimension == " << required_dim << "."; 06314 throw std::invalid_argument(s.str()); 06315 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible | ( | const char * | method, | |
| const Constraint & | c | |||
| ) | const [inline, private] |
Definition at line 6319 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Constraint::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension().
06320 { 06321 std::ostringstream s; 06322 s << "PPL::Octagonal_Shape::" << method << ":\n" 06323 << "this->space_dimension() == " << space_dimension() 06324 << ", c->space_dimension == " << c.space_dimension() << "."; 06325 throw std::invalid_argument(s.str()); 06326 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible | ( | const char * | method, | |
| const Congruence & | cg | |||
| ) | const [inline, private] |
Definition at line 6330 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Congruence::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension().
06331 { 06332 std::ostringstream s; 06333 s << "PPL::Octagonal_Shape::" << method << ":\n" 06334 << "this->space_dimension() == " << space_dimension() 06335 << ", cg->space_dimension == " << cg.space_dimension() << "."; 06336 throw std::invalid_argument(s.str()); 06337 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible | ( | const char * | method, | |
| const Generator & | g | |||
| ) | const [inline, private] |
Definition at line 6341 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Generator::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension().
06342 { 06343 std::ostringstream s; 06344 s << "PPL::Octagonal_Shape::" << method << ":\n" 06345 << "this->space_dimension() == " << space_dimension() 06346 << ", g->space_dimension == " << g.space_dimension() << "."; 06347 throw std::invalid_argument(s.str()); 06348 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_dimension_incompatible | ( | const char * | method, | |
| const char * | name_row, | |||
| const Linear_Expression & | y | |||
| ) | const [inline, private] |
Definition at line 6374 of file Octagonal_Shape.templates.hh.
References Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension().
06376 { 06377 std::ostringstream s; 06378 s << "PPL::Octagonal_Shape::" << method << ":\n" 06379 << "this->space_dimension() == " << space_dimension() 06380 << ", " << name_row << "->space_dimension() == " 06381 << y.space_dimension() << "."; 06382 throw std::invalid_argument(s.str()); 06383 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_constraint_incompatible | ( | const char * | method | ) | const [inline, private] |
Definition at line 6352 of file Octagonal_Shape.templates.hh.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_BHMZ05_extrapolation_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_CC76_extrapolation_assign().
06352 { 06353 std::ostringstream s; 06354 s << "PPL::Octagonal_Shape::" << method << ":\n" 06355 << "the constraint is incompatible."; 06356 throw std::invalid_argument(s.str()); 06357 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_expression_too_complex | ( | const char * | method, | |
| const Linear_Expression & | e | |||
| ) | const [inline, private] |
Definition at line 6362 of file Octagonal_Shape.templates.hh.
06363 { 06364 using namespace IO_Operators; 06365 std::ostringstream s; 06366 s << "PPL::Octagonal_Shape::" << method << ":\n" 06367 << e << " is too complex."; 06368 throw std::invalid_argument(s.str()); 06369 }
| void Parma_Polyhedra_Library::Octagonal_Shape< T >::throw_generic | ( | const char * | method, | |
| const char * | reason | |||
| ) | const [inline, private] |
Definition at line 6388 of file Octagonal_Shape.templates.hh.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_congruence(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_congruences(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_with_constraints().
06389 { 06390 std::ostringstream s; 06391 s << "PPL::Octagonal_Shape::" << method << ":\n" 06392 << reason << "."; 06393 throw std::invalid_argument(s.str()); 06394 }
friend class Parma_Polyhedra_Library::Octagonal_Shape [friend] |
Definition at line 1616 of file Octagonal_Shape.defs.hh.
friend class Parma_Polyhedra_Library::Box [friend] |
Definition at line 1617 of file Octagonal_Shape.defs.hh.
| bool operator== | ( | const Octagonal_Shape< T > & | x, | |
| const Octagonal_Shape< T > & | y | |||
| ) | [friend] |
Returns true if and only if x and y are the same octagon.
Note that x and y may be dimension-incompatible shapes: in this case, the value false is returned.
Definition at line 313 of file Octagonal_Shape.inlines.hh.
00313 { 00314 if (x.space_dim != y.space_dim) 00315 // Dimension-incompatible OSs are different. 00316 return false; 00317 00318 // Zero-dim OSs are equal if and only if they are both empty or universe. 00319 if (x.space_dim == 0) { 00320 if (x.marked_empty()) 00321 return y.marked_empty(); 00322 else 00323 return !y.marked_empty(); 00324 } 00325 00326 x.strong_closure_assign(); 00327 y.strong_closure_assign(); 00328 // If one of two octagons is empty, then they are equal if and only if 00329 // the other octagon is empty too. 00330 if (x.marked_empty()) 00331 return y.marked_empty(); 00332 if (y.marked_empty()) 00333 return false; 00334 // Strong closure is a canonical form. 00335 return x.matrix == y.matrix; 00336 }
| bool rectilinear_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const Octagonal_Shape< U > & | x, | |||
| const Octagonal_Shape< U > & | y, | |||
| const Rounding_Dir | dir, | |||
| Temp & | tmp0, | |||
| Temp & | tmp1, | |||
| Temp & | tmp2 | |||
| ) | [friend] |
| bool euclidean_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const Octagonal_Shape< U > & | x, | |||
| const Octagonal_Shape< U > & | y, | |||
| const Rounding_Dir | dir, | |||
| Temp & | tmp0, | |||
| Temp & | tmp1, | |||
| Temp & | tmp2 | |||
| ) | [friend] |
| bool l_infinity_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const Octagonal_Shape< U > & | x, | |||
| const Octagonal_Shape< U > & | y, | |||
| const Rounding_Dir | dir, | |||
| Temp & | tmp0, | |||
| Temp & | tmp1, | |||
| Temp & | tmp2 | |||
| ) | [friend] |
| std::ostream & operator<< | ( | std::ostream & | s, | |
| const Octagonal_Shape< T > & | x | |||
| ) | [friend] |
Output operator.
Writes a textual representation of oct on s: false is written if oct is an empty polyhedron; true is written if oct is a universe polyhedron; a system of constraints defining oct is written otherwise, all constraints separated by ", ".
Definition at line 5998 of file Octagonal_Shape.templates.hh.
05998 { 05999 // Handle special cases first. 06000 if (x.marked_empty()) { 06001 s << "false"; 06002 return s; 06003 } 06004 if (x.is_universe()) { 06005 s << "true"; 06006 return s; 06007 } 06008 06009 typedef typename Octagonal_Shape<T>::coefficient_type N; 06010 typedef typename OR_Matrix<N>::const_row_iterator Row_Iterator; 06011 typedef typename OR_Matrix<N>::const_row_reference_type Row_Reference; 06012 06013 // Records whether or not we still have to print the first constraint. 06014 bool first = true; 06015 06016 Row_Iterator m_begin = x.matrix.row_begin(); 06017 Row_Iterator m_end = x.matrix.row_end(); 06018 06019 // Temporaries. 06020 DIRTY_TEMP(N, negation); 06021 DIRTY_TEMP(N, half); 06022 // Go through all the unary constraints. 06023 // (Note: loop iterator is incremented in the loop body.) 06024 for (Row_Iterator i_iter = m_begin; i_iter != m_end; ) { 06025 const dimension_type i = i_iter.index(); 06026 const Variable v_i = Variable(i/2); 06027 const N& x_i_ii = (*i_iter)[i+1]; 06028 ++i_iter; 06029 const N& x_ii_i = (*i_iter)[i]; 06030 ++i_iter; 06031 // Check whether or not it is an equality constraint. 06032 if (is_additive_inverse(x_i_ii, x_ii_i)) { 06033 // It is an equality. 06034 assert(!is_plus_infinity(x_i_ii) && !is_plus_infinity(x_ii_i)); 06035 if (first) 06036 first = false; 06037 else 06038 s << ", "; 06039 // If the value bound can NOT be divided by 2 exactly, 06040 // then we output the constraint `2*v_i == bound'. 06041 if (div2exp_assign_r(half, x_ii_i, 1, ROUND_UP) == V_EQ) 06042 s << v_i << " == " << half; 06043 else 06044 s << "2*" << v_i << " == " << x_ii_i; 06045 } 06046 else { 06047 // We will print unary non-strict inequalities, if any. 06048 if (!is_plus_infinity(x_i_ii)) { 06049 if (first) 06050 first = false; 06051 else 06052 s << ", "; 06053 neg_assign_r(negation, x_i_ii, ROUND_NOT_NEEDED); 06054 // If the value bound can NOT be divided by 2 exactly, 06055 // then we output the constraint `2*v_i >= negation'. 06056 if (div2exp_assign_r(half, negation, 1, ROUND_UP) == V_EQ) 06057 s << v_i << " >= " << half; 06058 else 06059 s << "2*" << v_i << " >= " << negation; 06060 } 06061 if (!is_plus_infinity(x_ii_i)) { 06062 if (first) 06063 first = false; 06064 else 06065 s << ", "; 06066 // If the value bound can NOT be divided by 2 exactly, 06067 // then we output the constraint `2*v_i <= bound'. 06068 if (div2exp_assign_r(half, x_ii_i, 1, ROUND_UP) == V_EQ) 06069 s << v_i << " <= " << half; 06070 else 06071 s << "2*" << v_i << " <= " << x_ii_i; 06072 } 06073 } 06074 } 06075 06076 // Go through all the binary constraints. 06077 // (Note: loop iterator is incremented in the loop body.) 06078 for (Row_Iterator i_iter = m_begin; i_iter != m_end; ) { 06079 const dimension_type i = i_iter.index(); 06080 const Variable v_i = Variable(i/2); 06081 Row_Reference r_i = *i_iter; 06082 ++i_iter; 06083 Row_Reference r_ii = *i_iter; 06084 ++i_iter; 06085 06086 for (dimension_type j = 0; j < i; j += 2) { 06087 const Variable v_j = Variable(j/2); 06088 // Print binary differences. 06089 const N& x_ii_jj = r_ii[j+1]; 06090 const N& x_i_j = r_i[j]; 06091 // Check whether or not it is an equality constraint. 06092 if (is_additive_inverse(x_ii_jj, x_i_j)) { 06093 // It is an equality. 06094 assert(!is_plus_infinity(x_i_j) && !is_plus_infinity(x_ii_jj)); 06095 if (first) 06096 first = false; 06097 else 06098 s << ", "; 06099 if (sgn(x_i_j) >= 0) 06100 s << v_j << " - " << v_i << " == " << x_i_j; 06101 else 06102 s << v_i << " - " << v_j << " == " << x_ii_jj; 06103 } 06104 else { 06105 // We will print non-strict inequalities, if any. 06106 if (!is_plus_infinity(x_i_j)) { 06107 if (first) 06108 first = false; 06109 else 06110 s << ", "; 06111 if (sgn(x_i_j) >= 0) 06112 s << v_j << " - " << v_i << " <= " << x_i_j; 06113 else { 06114 neg_assign_r(negation, x_i_j, ROUND_DOWN); 06115 s << v_i << " - " << v_j << " >= " << negation; 06116 } 06117 } 06118 if (!is_plus_infinity(x_ii_jj)) { 06119 if (first) 06120 first = false; 06121 else 06122 s << ", "; 06123 if (sgn(x_ii_jj) >= 0) 06124 s << v_i << " - " << v_j << " <= " << x_ii_jj; 06125 else { 06126 neg_assign_r(negation, x_ii_jj, ROUND_DOWN); 06127 s << v_j << " - " << v_i << " >= " << negation; 06128 } 06129 } 06130 } 06131 // Print binary sums. 06132 const N& x_i_jj = r_i[j+1]; 06133 const N& x_ii_j = r_ii[j]; 06134 // Check whether or not it is an equality constraint. 06135 if (is_additive_inverse(x_i_jj, x_ii_j)) { 06136 // It is an equality. 06137 assert(!is_plus_infinity(x_i_jj) && !is_plus_infinity(x_ii_j)); 06138 if (first) 06139 first = false; 06140 else 06141 s << ", "; 06142 s << v_j << " + " << v_i << " == " << x_ii_j; 06143 } 06144 else { 06145 // We will print non-strict inequalities, if any. 06146 if (!is_plus_infinity(x_i_jj)) { 06147 if (first) 06148 first = false; 06149 else 06150 s << ", "; 06151 neg_assign_r(negation, x_i_jj, ROUND_DOWN); 06152 s << v_j << " + " << v_i << " >= " << negation; 06153 } 06154 if (!is_plus_infinity(x_ii_j)) { 06155 if (first) 06156 first = false; 06157 else 06158 s << ", "; 06159 s << v_j << " + " << v_i << " <= " << x_ii_j; 06160 } 06161 } 06162 } 06163 } 06164 return s; 06165 }
| bool operator!= | ( | const Octagonal_Shape< T > & | x, | |
| const Octagonal_Shape< T > & | y | |||
| ) | [related] |
Returns true if and only if x and y are different shapes.
Note that x and y may be dimension-incompatible shapes: in this case, the value true is returned.
Definition at line 341 of file Octagonal_Shape.inlines.hh.
| bool rectilinear_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const Octagonal_Shape< T > & | x, | |||
| const Octagonal_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 641 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::rectilinear_distance_assign.
00644 { 00645 typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp; 00646 DIRTY_TEMP(Checked_Temp, tmp0); 00647 DIRTY_TEMP(Checked_Temp, tmp1); 00648 DIRTY_TEMP(Checked_Temp, tmp2); 00649 return rectilinear_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2); 00650 }
| bool rectilinear_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const Octagonal_Shape< T > & | x, | |||
| const Octagonal_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 600 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, PLUS_INFINITY, Parma_Polyhedra_Library::Octagonal_Shape< T >::rectilinear_distance_assign, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().
00606 { 00607 // Dimension-compatibility check. 00608 if (x.space_dim != y.space_dim) 00609 return false; 00610 00611 // Zero-dim OSs are equal if and only if they are both empty or universe. 00612 if (x.space_dim == 0) { 00613 if (x.marked_empty() == y.marked_empty()) 00614 assign_r(r, 0, ROUND_NOT_NEEDED); 00615 else 00616 assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED); 00617 return true; 00618 } 00619 00620 // The distance computation requires strong closure. 00621 x.strong_closure_assign(); 00622 y.strong_closure_assign(); 00623 00624 // If one of two OSs is empty, then they are equal if and only if 00625 // the other OS is empty too. 00626 if (x.marked_empty() || y.marked_empty()) { 00627 if (x.marked_empty() == y.marked_empty()) 00628 assign_r(r, 0, ROUND_NOT_NEEDED); 00629 else 00630 assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED); 00631 return true; 00632 } 00633 00634 return rectilinear_distance_assign(r, x.matrix, y.matrix, dir, 00635 tmp0, tmp1, tmp2); 00636 }
| bool euclidean_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const Octagonal_Shape< T > & | x, | |||
| const Octagonal_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 706 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::euclidean_distance_assign.
00709 { 00710 typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp; 00711 DIRTY_TEMP(Checked_Temp, tmp0); 00712 DIRTY_TEMP(Checked_Temp, tmp1); 00713 DIRTY_TEMP(Checked_Temp, tmp2); 00714 return euclidean_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2); 00715 }
| bool euclidean_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const Octagonal_Shape< T > & | x, | |||
| const Octagonal_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 665 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::euclidean_distance_assign, Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, PLUS_INFINITY, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().
00671 { 00672 // Dimension-compatibility check. 00673 if (x.space_dim != y.space_dim) 00674 return false; 00675 00676 // Zero-dim OSs are equal if and only if they are both empty or universe. 00677 if (x.space_dim == 0) { 00678 if (x.marked_empty() == y.marked_empty()) 00679 assign_r(r, 0, ROUND_NOT_NEEDED); 00680 else 00681 assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED); 00682 return true; 00683 } 00684 00685 // The distance computation requires strong closure. 00686 x.strong_closure_assign(); 00687 y.strong_closure_assign(); 00688 00689 // If one of two OSs is empty, then they are equal if and only if 00690 // the other OS is empty too. 00691 if (x.marked_empty() || y.marked_empty()) { 00692 if (x.marked_empty() == y.marked_empty()) 00693 assign_r(r, 0, ROUND_NOT_NEEDED); 00694 else 00695 assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED); 00696 return true; 00697 } 00698 00699 return euclidean_distance_assign(r, x.matrix, y.matrix, dir, 00700 tmp0, tmp1, tmp2); 00701 }
| bool l_infinity_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const Octagonal_Shape< T > & | x, | |||
| const Octagonal_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 771 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::l_infinity_distance_assign.
00774 { 00775 typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp; 00776 DIRTY_TEMP(Checked_Temp, tmp0); 00777 DIRTY_TEMP(Checked_Temp, tmp1); 00778 DIRTY_TEMP(Checked_Temp, tmp2); 00779 return l_infinity_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2); 00780 }
| bool l_infinity_distance_assign | ( | Checked_Number< To, Extended_Number_Policy > & | r, | |
| const Octagonal_Shape< T > & | x, | |||
| const Octagonal_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 730 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Octagonal_Shape< T >::l_infinity_distance_assign, Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix, PLUS_INFINITY, Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim, and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign().
00736 { 00737 // Dimension-compatibility check. 00738 if (x.space_dim != y.space_dim) 00739 return false; 00740 00741 // Zero-dim OSs are equal if and only if they are both empty or universe. 00742 if (x.space_dim == 0) { 00743 if (x.marked_empty() == y.marked_empty()) 00744 assign_r(r, 0, ROUND_NOT_NEEDED); 00745 else 00746 assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED); 00747 return true; 00748 } 00749 00750 // The distance computation requires strong closure. 00751 x.strong_closure_assign(); 00752 y.strong_closure_assign(); 00753 00754 // If one of two OSs is empty, then they are equal if and only if 00755 // the other OS is empty too. 00756 if (x.marked_empty() || y.marked_empty()) { 00757 if (x.marked_empty() == y.marked_empty()) 00758 assign_r(r, 0, ROUND_NOT_NEEDED); 00759 else 00760 assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED); 00761 return true; 00762 } 00763 00764 return l_infinity_distance_assign(r, x.matrix, y.matrix, dir, 00765 tmp0, tmp1, tmp2); 00766 }
| bool extract_octagonal_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, | |||
| Coefficient & | c_term | |||
| ) | [related] |
Decodes the constraint c as an octagonal difference.
true if the constraint c is an octagonal 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. | |
| c_term | If true is returned and if c_num_vars is not set to 0, then it will be set to the right value of the inhomogeneous term of c. |
Definition at line 33 of file Octagonal_Shape.cc.
References Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), and Parma_Polyhedra_Library::Constraint::space_dimension().
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds(), Parma_Polyhedra_Library::Octagonal_Shape< T >::get_limiting_octagon(), Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with().
00039 { 00040 // Check for preconditions. 00041 assert(c.space_dimension() == c_space_dim); 00042 assert(c_num_vars == 0 && c_first_var == 0 && c_second_var == 0); 00043 // Store the indices of the non-zero components of `c', 00044 dimension_type non_zero_index[2] = { 0, 0 }; 00045 // Collect the non-zero components of `c'. 00046 for (dimension_type i = c_space_dim; i-- > 0; ) 00047 if (c.coefficient(Variable(i)) != 0) { 00048 if (c_num_vars <= 1) 00049 non_zero_index[c_num_vars++] = i; 00050 else 00051 // Constraint `c' is not an octagonal difference. 00052 return false; 00053 } 00054 00055 // Make sure that `c' is indeed an octagonal difference, 00056 // i.e., it has one of the following forms: 00057 // 0 <=/= b, if c_num_vars == 0; 00058 // (+/-) a*x <=/= b, if c_num_vars == 1; 00059 // (+/-) a*x (+/-) a*y <=/= b, if c_num_vars == 2. 00060 c_term = c.inhomogeneous_term(); 00061 switch (c_num_vars) { 00062 case 2: 00063 { 00064 const Coefficient& c0 = c.coefficient(Variable(non_zero_index[0])); 00065 const Coefficient& c1 = c.coefficient(Variable(non_zero_index[1])); 00066 if (c0 != c1 && c0 != -c1) 00067 // Constraint `c' is not an octagonal difference. 00068 return false; 00069 c_first_var = non_zero_index[0]; 00070 c_second_var = non_zero_index[1]; 00071 c_first_var *= 2; 00072 if (sgn(c0) < 0) 00073 ++c_first_var; 00074 c_second_var *= 2; 00075 if (sgn(c1) > 0) 00076 ++c_second_var; 00077 c_coeff = c0; 00078 } 00079 break; 00080 case 1: 00081 { 00082 c_term *= 2; 00083 c_first_var = non_zero_index[0]; 00084 c_first_var *= 2; 00085 if (sgn(c.coefficient(Variable(non_zero_index[0]))) < 0) { 00086 c_second_var = c_first_var; 00087 ++c_first_var; 00088 } 00089 else 00090 c_second_var = c_first_var + 1; 00091 c_coeff = c.coefficient(Variable(non_zero_index[0])); 00092 } 00093 break; 00094 default: 00095 assert(c_num_vars == 0); 00096 break; 00097 } 00098 return true; 00099 }
| dimension_type coherent_index | ( | dimension_type | i | ) | [related] |
Returns the index coherent to i.
Definition at line 42 of file Octagonal_Shape.inlines.hh.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_leaders(), Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_successors(), Parma_Polyhedra_Library::Octagonal_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::get_limiting_octagon(), Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_strong_coherent(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix_at(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_coherence_assign(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign().
| void swap | ( | Parma_Polyhedra_Library::Octagonal_Shape< T > & | x, | |
| Parma_Polyhedra_Library::Octagonal_Shape< T > & | y | |||
| ) | [related] |
Specializes std::swap.
Definition at line 811 of file Octagonal_Shape.inlines.hh.
References Parma_Polyhedra_Library::Octagonal_Shape< T >::swap().
00812 { 00813 x.swap(y); 00814 }
OR_Matrix<N> Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix [private] |
The matrix that represents the octagonal shape.
Definition at line 1620 of file Octagonal_Shape.defs.hh.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::ascii_dump(), Parma_Polyhedra_Library::Octagonal_Shape< T >::ascii_load(), Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_leaders(), Parma_Polyhedra_Library::Octagonal_Shape< T >::compute_successors(), Parma_Polyhedra_Library::Octagonal_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constrains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::Octagonal_Shape< T >::deduce_minus_v_pm_u_bounds(), Parma_Polyhedra_Library::Octagonal_Shape< T >::deduce_v_pm_u_bounds(), Parma_Polyhedra_Library::Octagonal_Shape< T >::euclidean_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::external_memory_in_bytes(), Parma_Polyhedra_Library::Octagonal_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_all_octagonal_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_binary_octagonal_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::get_limiting_octagon(), Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_bounded(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_strong_coherent(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_strongly_reduced(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_universe(), Parma_Polyhedra_Library::Octagonal_Shape< T >::l_infinity_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::matrix_at(), Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::operator=(), Parma_Polyhedra_Library::Octagonal_Shape< T >::rectilinear_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_coherence_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::swap(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_coherence_would_make_empty(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign().
dimension_type Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dim [private] |
Dimension of the space of the octagonal shape.
Definition at line 1623 of file Octagonal_Shape.defs.hh.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_octagonal_constraint(), Parma_Polyhedra_Library::Octagonal_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::ascii_dump(), Parma_Polyhedra_Library::Octagonal_Shape< T >::ascii_load(), Parma_Polyhedra_Library::Octagonal_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounded_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::bounds(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains(), Parma_Polyhedra_Library::Octagonal_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::Octagonal_Shape< T >::difference_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::euclidean_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_all_octagonal_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::forget_binary_octagonal_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::Octagonal_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::Octagonal_Shape< T >::get_limiting_octagon(), Parma_Polyhedra_Library::Octagonal_Shape< T >::incremental_strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_bounded(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_universe(), Parma_Polyhedra_Library::Octagonal_Shape< T >::l_infinity_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_BHMZ05_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::max_min(), Parma_Polyhedra_Library::Octagonal_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::operator=(), Parma_Polyhedra_Library::Octagonal_Shape< T >::rectilinear_distance_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine(), Parma_Polyhedra_Library::Octagonal_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::Octagonal_Shape< T >::relation_with(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_closure_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::strong_reduction_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::swap(), Parma_Polyhedra_Library::Octagonal_Shape< T >::tight_coherence_would_make_empty(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::upper_bound_assign().
Status Parma_Polyhedra_Library::Octagonal_Shape< T >::status [private] |
The status flags to keep track of the internal state.
Definition at line 1745 of file Octagonal_Shape.defs.hh.
Referenced by Parma_Polyhedra_Library::Octagonal_Shape< T >::ascii_dump(), Parma_Polyhedra_Library::Octagonal_Shape< T >::ascii_load(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::marked_zero_dim_univ(), Parma_Polyhedra_Library::Octagonal_Shape< T >::OK(), Parma_Polyhedra_Library::Octagonal_Shape< T >::operator=(), Parma_Polyhedra_Library::Octagonal_Shape< T >::reset_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_empty(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_strongly_closed(), Parma_Polyhedra_Library::Octagonal_Shape< T >::set_zero_dim_univ(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::swap().
T Parma_Polyhedra_Library::Octagonal_Shape< T >::default_stop_points[] [static, private] |
Definition at line 2089 of file Octagonal_Shape.defs.hh.
1.5.6