#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 ![]() *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 ![]() ![]() 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 ![]() ![]() 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 ![]() ![]() 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 ![]() ![]() 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 ![]() 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 ![]() 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:
T
is a (bounded or unbounded) integer type;T
is the unbounded rational type mpq_class
;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);
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. |
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. |
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
i
. If j
and true
is returned. If 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 var
has space dimension 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 var
has space dimension to_be_folded
is a set of variables whose maximum space dimension is also less than or equal to var
is not a member of to_be_folded
, then the space dimensions corresponding to variables in to_be_folded
are folded into the 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.