PPL  1.2
Parma_Polyhedra_Library::BD_Shape< T > Class Template Reference

A bounded difference shape. More...

#include <BD_Shape_defs.hh>

Collaboration diagram for Parma_Polyhedra_Library::BD_Shape< T >:

Classes

class  Status
 A conjunctive assertion about a BD_Shape<T> object. More...
 

Public Types

typedef T coefficient_type_base
 The numeric base type upon which bounded differences are built. More...
 
typedef N coefficient_type
 The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS. More...
 

Public Member Functions

void ascii_dump () const
 Writes to std::cerr an ASCII representation of *this. More...
 
void ascii_dump (std::ostream &s) const
 Writes to s an ASCII representation of *this. More...
 
void print () const
 Prints *this to std::cerr using operator<<. More...
 
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. More...
 
memory_size_type total_memory_in_bytes () const
 Returns the total size in bytes of the memory occupied by *this. More...
 
memory_size_type external_memory_in_bytes () const
 Returns the size in bytes of the memory managed by *this. More...
 
int32_t hash_code () const
 Returns a 32-bit hash code for *this. More...
 
Constructors, Assignment, Swap and Destructor
 BD_Shape (dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
 Builds a universe or empty BDS of the specified space dimension. More...
 
 BD_Shape (const BD_Shape &y, Complexity_Class complexity=ANY_COMPLEXITY)
 Ordinary copy constructor. More...
 
template<typename U >
 BD_Shape (const BD_Shape< U > &y, Complexity_Class complexity=ANY_COMPLEXITY)
 Builds a conservative, upward approximation of y. More...
 
 BD_Shape (const Constraint_System &cs)
 Builds a BDS from the system of constraints cs. More...
 
 BD_Shape (const Congruence_System &cgs)
 Builds a BDS from a system of congruences. More...
 
 BD_Shape (const Generator_System &gs)
 Builds a BDS from the system of generators gs. More...
 
 BD_Shape (const Polyhedron &ph, Complexity_Class complexity=ANY_COMPLEXITY)
 Builds a BDS from the polyhedron ph. More...
 
template<typename Interval >
 BD_Shape (const Box< Interval > &box, Complexity_Class complexity=ANY_COMPLEXITY)
 Builds a BDS out of a box. More...
 
 BD_Shape (const Grid &grid, Complexity_Class complexity=ANY_COMPLEXITY)
 Builds a BDS out of a grid. More...
 
template<typename U >
 BD_Shape (const Octagonal_Shape< U > &os, Complexity_Class complexity=ANY_COMPLEXITY)
 Builds a BDS from an octagonal shape. More...
 
BD_Shapeoperator= (const BD_Shape &y)
 The assignment operator (*this and y can be dimension-incompatible). More...
 
void m_swap (BD_Shape &y)
 Swaps *this with y (*this and y can be dimension-incompatible). More...
 
 ~BD_Shape ()
 Destructor. More...
 
Member Functions that Do Not Modify the BD_Shape
dimension_type space_dimension () const
 Returns the dimension of the vector space enclosing *this. More...
 
dimension_type affine_dimension () const
 Returns $0$, if *this is empty; otherwise, returns the affine dimension of *this. More...
 
Constraint_System constraints () const
 Returns a system of constraints defining *this. More...
 
Constraint_System minimized_constraints () const
 Returns a minimized system of constraints defining *this. More...
 
Congruence_System congruences () const
 Returns a system of (equality) congruences satisfied by *this. More...
 
Congruence_System minimized_congruences () const
 Returns a minimal system of (equality) congruences satisfied by *this with the same affine dimension as *this. More...
 
bool bounds_from_above (const Linear_Expression &expr) const
 Returns true if and only if expr is bounded from above in *this. More...
 
bool bounds_from_below (const Linear_Expression &expr) const
 Returns true if and only if expr is bounded from below in *this. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
bool frequency (const Linear_Expression &expr, Coefficient &freq_n, Coefficient &freq_d, Coefficient &val_n, Coefficient &val_d) const
 Returns true if and only if there exist a unique value val such that *this saturates the equality expr = val. More...
 
bool contains (const BD_Shape &y) const
 Returns true if and only if *this contains y. More...
 
bool strictly_contains (const BD_Shape &y) const
 Returns true if and only if *this strictly contains y. More...
 
bool is_disjoint_from (const BD_Shape &y) const
 Returns true if and only if *this and y are disjoint. More...
 
Poly_Con_Relation relation_with (const Constraint &c) const
 Returns the relations holding between *this and the constraint c. More...
 
Poly_Con_Relation relation_with (const Congruence &cg) const
 Returns the relations holding between *this and the congruence cg. More...
 
Poly_Gen_Relation relation_with (const Generator &g) const
 Returns the relations holding between *this and the generator g. More...
 
bool is_empty () const
 Returns true if and only if *this is an empty BDS. More...
 
bool is_universe () const
 Returns true if and only if *this is a universe BDS. More...
 
bool is_discrete () const
 Returns true if and only if *this is discrete. More...
 
bool is_topologically_closed () const
 Returns true if and only if *this is a topologically closed subset of the vector space. More...
 
bool is_bounded () const
 Returns true if and only if *this is a bounded BDS. More...
 
bool contains_integer_point () const
 Returns true if and only if *this contains at least one integer point. More...
 
bool constrains (Variable var) const
 Returns true if and only if var is constrained in *this. More...
 
bool OK () const
 Returns true if and only if *this satisfies all its invariants. More...
 
Space-Dimension Preserving Member Functions that May Modify the BD_Shape
void add_constraint (const Constraint &c)
 Adds a copy of constraint c to the system of bounded differences defining *this. More...
 
void add_congruence (const Congruence &cg)
 Adds a copy of congruence cg to the system of congruences of *this. More...
 
void add_constraints (const Constraint_System &cs)
 Adds the constraints in cs to the system of bounded differences defining *this. More...
 
void add_recycled_constraints (Constraint_System &cs)
 Adds the constraints in cs to the system of constraints of *this. More...
 
void add_congruences (const Congruence_System &cgs)
 Adds to *this constraints equivalent to the congruences in cgs. More...
 
void add_recycled_congruences (Congruence_System &cgs)
 Adds to *this constraints equivalent to the congruences in cgs. More...
 
void refine_with_constraint (const Constraint &c)
 Uses a copy of constraint c to refine the system of bounded differences defining *this. More...
 
void refine_with_congruence (const Congruence &cg)
 Uses a copy of congruence cg to refine the system of bounded differences of *this. More...
 
void refine_with_constraints (const Constraint_System &cs)
 Uses a copy of the constraints in cs to refine the system of bounded differences defining *this. More...
 
void refine_with_congruences (const Congruence_System &cgs)
 Uses a copy of the congruences in cgs to refine the system of bounded differences defining *this. More...
 
template<typename Interval_Info >
void refine_with_linear_form_inequality (const Linear_Form< Interval< T, Interval_Info > > &left, const Linear_Form< Interval< T, Interval_Info > > &right)
 Refines the system of BD_Shape constraints defining *this using the constraint expressed by left $\leq$ right. More...
 
template<typename Interval_Info >
void generalized_refine_with_linear_form_inequality (const Linear_Form< Interval< T, Interval_Info > > &left, const Linear_Form< Interval< T, Interval_Info > > &right, Relation_Symbol relsym)
 Refines the system of BD_Shape constraints defining *this using the constraint expressed by left $\relsym$ right, where $\relsym$ is the relation symbol specified by relsym. More...
 
template<typename U >
void export_interval_constraints (U &dest) const
 Applies to dest the interval constraints embedded in *this. More...
 
void unconstrain (Variable var)
 Computes the cylindrification of *this with respect to space dimension var, assigning the result to *this. More...
 
void unconstrain (const Variables_Set &vars)
 Computes the cylindrification of *this with respect to the set of space dimensions vars, assigning the result to *this. More...
 
void intersection_assign (const BD_Shape &y)
 Assigns to *this the intersection of *this and y. More...
 
void upper_bound_assign (const BD_Shape &y)
 Assigns to *this the smallest BDS containing the union of *this and y. More...
 
bool upper_bound_assign_if_exact (const BD_Shape &y)
 If the upper bound of *this and y is exact, it is assigned to *this and true is returned, otherwise false is returned. More...
 
bool integer_upper_bound_assign_if_exact (const BD_Shape &y)
 If the integer upper bound of *this and y is exact, it is assigned to *this and true is returned; otherwise false is returned. More...
 
void difference_assign (const BD_Shape &y)
 Assigns to *this the smallest BD shape containing the set difference of *this and y. More...
 
bool simplify_using_context_assign (const BD_Shape &y)
 Assigns to *this a meet-preserving simplification of *this with respect to y. If false is returned, then the intersection is empty. More...
 
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. More...
 
template<typename Interval_Info >
void affine_form_image (Variable var, const Linear_Form< Interval< T, Interval_Info > > &lf)
 Assigns to *this the affine form image of *this under the function mapping variable var into the affine expression(s) specified by lf. More...
 
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. More...
 
void generalized_affine_image (Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the image of *this with respect to the affine relation $\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym. More...
 
void generalized_affine_image (const Linear_Expression &lhs, Relation_Symbol relsym, const Linear_Expression &rhs)
 Assigns to *this the image of *this with respect to the affine relation $\mathrm{lhs}' \relsym \mathrm{rhs}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym. More...
 
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 $\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym. More...
 
void generalized_affine_preimage (const Linear_Expression &lhs, Relation_Symbol relsym, const Linear_Expression &rhs)
 Assigns to *this the preimage of *this with respect to the affine relation $\mathrm{lhs}' \relsym \mathrm{rhs}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym. More...
 
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 $\frac{\mathrm{lb\_expr}}{\mathrm{denominator}} \leq \mathrm{var}' \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}$. More...
 
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 $\frac{\mathrm{lb\_expr}}{\mathrm{denominator}} \leq \mathrm{var}' \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}$. More...
 
void time_elapse_assign (const BD_Shape &y)
 Assigns to *this the result of computing the time-elapse between *this and y. More...
 
void wrap_assign (const Variables_Set &vars, Bounded_Integer_Type_Width w, Bounded_Integer_Type_Representation r, Bounded_Integer_Type_Overflow o, const Constraint_System *cs_p=0, unsigned complexity_threshold=16, bool wrap_individually=true)
 Wraps the specified dimensions of the vector space. More...
 
void drop_some_non_integer_points (Complexity_Class complexity=ANY_COMPLEXITY)
 Possibly tightens *this by dropping some points with non-integer coordinates. More...
 
void drop_some_non_integer_points (const Variables_Set &vars, Complexity_Class complexity=ANY_COMPLEXITY)
 Possibly tightens *this by dropping some points with non-integer coordinates for the space dimensions corresponding to vars. More...
 
void topological_closure_assign ()
 Assigns to *this its topological closure. More...
 
void CC76_extrapolation_assign (const BD_Shape &y, unsigned *tp=0)
 Assigns to *this the result of computing the CC76-extrapolation between *this and y. More...
 
template<typename Iterator >
void CC76_extrapolation_assign (const BD_Shape &y, Iterator first, Iterator last, unsigned *tp=0)
 Assigns to *this the result of computing the CC76-extrapolation between *this and y. More...
 
void BHMZ05_widening_assign (const BD_Shape &y, unsigned *tp=0)
 Assigns to *this the result of computing the BHMZ05-widening of *this and y. More...
 
void limited_BHMZ05_extrapolation_assign (const BD_Shape &y, const Constraint_System &cs, unsigned *tp=0)
 Improves the result of the BHMZ05-widening computation by also enforcing those constraints in cs that are satisfied by all the points of *this. More...
 
void CC76_narrowing_assign (const BD_Shape &y)
 Assigns to *this the result of restoring in y the constraints of *this that were lost by CC76-extrapolation applications. More...
 
void limited_CC76_extrapolation_assign (const BD_Shape &y, const Constraint_System &cs, unsigned *tp=0)
 Improves the result of the CC76-extrapolation computation by also enforcing those constraints in cs that are satisfied by all the points of *this. More...
 
void H79_widening_assign (const BD_Shape &y, unsigned *tp=0)
 Assigns to *this the result of computing the H79-widening between *this and y. More...
 
void widening_assign (const BD_Shape &y, unsigned *tp=0)
 Same as H79_widening_assign(y, tp). More...
 
void limited_H79_extrapolation_assign (const BD_Shape &y, const Constraint_System &cs, unsigned *tp=0)
 Improves the result of the H79-widening computation by also enforcing those constraints in cs that are satisfied by all the points of *this. More...
 
Member Functions that May Modify the Dimension of the Vector Space
void add_space_dimensions_and_embed (dimension_type m)
 Adds m new dimensions and embeds the old BDS into the new space. More...
 
void add_space_dimensions_and_project (dimension_type m)
 Adds m new dimensions to the BDS and does not embed it in the new vector space. More...
 
void concatenate_assign (const BD_Shape &y)
 Assigns to *this the concatenation of *this and y, taken in this order. More...
 
void remove_space_dimensions (const Variables_Set &vars)
 Removes all the specified dimensions. More...
 
void remove_higher_space_dimensions (dimension_type new_dimension)
 Removes the higher dimensions so that the resulting space will have dimension new_dimension. More...
 
template<typename Partial_Function >
void map_space_dimensions (const Partial_Function &pfunc)
 Remaps the dimensions of the vector space according to a partial function. More...
 
void expand_space_dimension (Variable var, dimension_type m)
 Creates m copies of the space dimension corresponding to var. More...
 
void fold_space_dimensions (const Variables_Set &vars, Variable dest)
 Folds the space dimensions in vars into dest. More...
 
template<typename Interval_Info >
void refine_fp_interval_abstract_store (Box< Interval< T, Interval_Info > > &store) const
 Refines store with the constraints defining *this. More...
 

Static Public Member Functions

static dimension_type max_space_dimension ()
 Returns the maximum space dimension that a BDS can handle. More...
 
static bool can_recycle_constraint_systems ()
 Returns false indicating that this domain cannot recycle constraints. More...
 
static bool can_recycle_congruence_systems ()
 Returns false indicating that this domain cannot recycle congruences. More...
 

Private Types

typedef Checked_Number< T, Debug_WRD_Extended_Number_PolicyN
 The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS. More...
 

Private Member Functions

bool marked_zero_dim_univ () const
 Returns true if the BDS is the zero-dimensional universe. More...
 
bool marked_empty () const
 Returns true if the BDS is known to be empty. More...
 
bool marked_shortest_path_closed () const
 Returns true if the system of bounded differences is known to be shortest-path closed. More...
 
bool marked_shortest_path_reduced () const
 Returns true if the system of bounded differences is known to be shortest-path reduced. More...
 
void set_empty ()
 Turns *this into an empty BDS. More...
 
void set_zero_dim_univ ()
 Turns *this into an zero-dimensional universe BDS. More...
 
void set_shortest_path_closed ()
 Marks *this as shortest-path closed. More...
 
void set_shortest_path_reduced ()
 Marks *this as shortest-path closed. More...
 
void reset_shortest_path_closed ()
 Marks *this as possibly not shortest-path closed. More...
 
void reset_shortest_path_reduced ()
 Marks *this as possibly not shortest-path reduced. More...
 
void shortest_path_closure_assign () const
 Assigns to this->dbm its shortest-path closure. More...
 
void shortest_path_reduction_assign () const
 Assigns to this->dbm its shortest-path closure and records into this->redundancy_dbm which of the entries in this->dbm are redundant. More...
 
bool is_shortest_path_reduced () const
 Returns true if and only if this->dbm is shortest-path closed and this->redundancy_dbm correctly flags the redundant entries in this->dbm. More...
 
void incremental_shortest_path_closure_assign (Variable var) const
 Incrementally computes shortest-path closure, assuming that only constraints affecting variable var need to be considered. More...
 
bool bounds (const Linear_Expression &expr, bool from_above) const
 Checks if and how expr is bounded in *this. More...
 
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. More...
 
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. More...
 
bool BFT00_upper_bound_assign_if_exact (const BD_Shape &y)
 If the upper bound of *this and y is exact it is assigned to *this and true is returned, otherwise false is returned. More...
 
template<bool integer_upper_bound>
bool BHZ09_upper_bound_assign_if_exact (const BD_Shape &y)
 If the upper bound of *this and y is exact it is assigned to *this and true is returned, otherwise false is returned. More...
 
void refine_no_check (const Constraint &c)
 Uses the constraint c to refine *this. More...
 
void refine_no_check (const Congruence &cg)
 Uses the congruence cg to refine *this. More...
 
void add_dbm_constraint (dimension_type i, dimension_type j, const N &k)
 Adds the constraint dbm[i][j] <= k. More...
 
void add_dbm_constraint (dimension_type i, dimension_type j, Coefficient_traits::const_reference numer, Coefficient_traits::const_reference denom)
 Adds the constraint dbm[i][j] <= numer/denom. More...
 
void refine (Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Adds to the BDS the constraint $\mathrm{var} \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}$. More...
 
void forget_all_dbm_constraints (dimension_type v)
 Removes all the constraints on row/column v. More...
 
void forget_binary_dbm_constraints (dimension_type v)
 Removes all binary constraints on row/column v. More...
 
void deduce_v_minus_u_bounds (dimension_type v, dimension_type last_v, const Linear_Expression &sc_expr, Coefficient_traits::const_reference sc_denom, const N &ub_v)
 An helper function for the computation of affine relations. More...
 
template<typename Interval_Info >
void inhomogeneous_affine_form_image (const dimension_type &var_id, const Interval< T, Interval_Info > &b)
 Auxiliary function for affine form image that handle the general case: $l = c$. More...
 
template<typename Interval_Info >
void one_variable_affine_form_image (const dimension_type &var_id, const Interval< T, Interval_Info > &b, const Interval< T, Interval_Info > &w_coeff, const dimension_type &w_id, const dimension_type &space_dim)
 Auxiliary function for affine formimage" that handle the general case: $l = ax + c$. More...
 
template<typename Interval_Info >
void two_variables_affine_form_image (const dimension_type &var_id, const Linear_Form< Interval< T, Interval_Info > > &lf, const dimension_type &space_dim)
 Auxiliary function for affine form image that handle the general case: $l = ax + by + c$. More...
 
template<typename Interval_Info >
void left_inhomogeneous_refine (const dimension_type &right_t, const dimension_type &right_w_id, const Linear_Form< Interval< T, Interval_Info > > &left, const Linear_Form< Interval< T, Interval_Info > > &right)
 Auxiliary function for refine with linear form that handle the general case: $l = ax + c$. More...
 
template<typename Interval_Info >
void left_one_var_refine (const dimension_type &left_w_id, const dimension_type &right_t, const dimension_type &right_w_id, const Linear_Form< Interval< T, Interval_Info > > &left, const Linear_Form< Interval< T, Interval_Info > > &right)
 Auxiliary function for refine with linear form that handle the general case: $ax + b = cy + d$. More...
 
template<typename Interval_Info >
void general_refine (const dimension_type &left_w_id, const dimension_type &right_w_id, const Linear_Form< Interval< T, Interval_Info > > &left, const Linear_Form< Interval< T, Interval_Info > > &right)
 Auxiliary function for refine with linear form that handle the general case. More...
 
template<typename Interval_Info >
void linear_form_upper_bound (const Linear_Form< Interval< T, Interval_Info > > &lf, N &result) const
 
void deduce_u_minus_v_bounds (dimension_type v, dimension_type last_v, const Linear_Expression &sc_expr, Coefficient_traits::const_reference sc_denom, const N &minus_lb_v)
 An helper function for the computation of affine relations. More...
 
void get_limiting_shape (const Constraint_System &cs, BD_Shape &limiting_shape) const
 Adds to limiting_shape the bounded differences in cs that are satisfied by *this. More...
 
void compute_predecessors (std::vector< dimension_type > &predecessor) const
 Compute the (zero-equivalence classes) predecessor relation. More...
 
void compute_leaders (std::vector< dimension_type > &leaders) const
 Compute the leaders of zero-equivalence classes. More...
 
void drop_some_non_integer_points_helper (N &elem)
 

Private Attributes

DB_Matrix< Ndbm
 The matrix representing the system of bounded differences. More...
 
Status status
 The status flags to keep track of the internal state. More...
 
Bit_Matrix redundancy_dbm
 A matrix indicating which constraints are redundant. More...
 

Friends

template<typename U >
class Parma_Polyhedra_Library::BD_Shape
 
template<typename Interval >
class Parma_Polyhedra_Library::Box
 
bool operator== (const BD_Shape< T > &x, const BD_Shape< T > &y)
 
template<typename Temp , typename To , typename U >
bool Parma_Polyhedra_Library::rectilinear_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< U > &x, const BD_Shape< U > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
 
template<typename Temp , typename To , typename U >
bool Parma_Polyhedra_Library::euclidean_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< U > &x, const BD_Shape< U > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
 
template<typename Temp , typename To , typename U >
bool Parma_Polyhedra_Library::l_infinity_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< U > &x, const BD_Shape< U > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
 
std::ostream & Parma_Polyhedra_Library::IO_Operators::operator<< (std::ostream &s, const BD_Shape< T > &c)
 

Related Functions

(Note that these are not member functions.)

bool extract_bounded_difference (const Constraint &c, dimension_type &c_num_vars, dimension_type &c_first_var, dimension_type &c_second_var, Coefficient &c_coeff)
 
void compute_leader_indices (const std::vector< dimension_type > &predecessor, std::vector< dimension_type > &indices)
 
template<typename T >
std::ostream & operator<< (std::ostream &s, const BD_Shape< T > &bds)
 Output operator. More...
 
template<typename T >
void swap (BD_Shape< T > &x, BD_Shape< T > &y)
 Swaps x with y. More...
 
template<typename T >
bool operator== (const BD_Shape< T > &x, const BD_Shape< T > &y)
 Returns true if and only if x and y are the same BDS. More...
 
template<typename T >
bool operator!= (const BD_Shape< T > &x, const BD_Shape< T > &y)
 Returns true if and only if x and y are not the same BDS. More...
 
template<typename To , typename T >
bool rectilinear_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, Rounding_Dir dir)
 Computes the rectilinear (or Manhattan) distance between x and y. More...
 
template<typename Temp , typename To , typename T >
bool rectilinear_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, Rounding_Dir dir)
 Computes the rectilinear (or Manhattan) distance between x and y. More...
 
template<typename Temp , typename To , typename T >
bool rectilinear_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
 Computes the rectilinear (or Manhattan) distance between x and y. More...
 
template<typename To , typename T >
bool euclidean_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, Rounding_Dir dir)
 Computes the euclidean distance between x and y. More...
 
template<typename Temp , typename To , typename T >
bool euclidean_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, Rounding_Dir dir)
 Computes the euclidean distance between x and y. More...
 
template<typename Temp , typename To , typename T >
bool euclidean_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
 Computes the euclidean distance between x and y. More...
 
template<typename To , typename T >
bool l_infinity_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, Rounding_Dir dir)
 Computes the $L_\infty$ distance between x and y. More...
 
template<typename Temp , typename To , typename T >
bool l_infinity_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, Rounding_Dir dir)
 Computes the $L_\infty$ distance between x and y. More...
 
template<typename Temp , typename To , typename T >
bool l_infinity_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
 Computes the $L_\infty$ distance between x and y. More...
 
void compute_leader_indices (const std::vector< dimension_type > &predecessor, std::vector< dimension_type > &indices)
 Extracts leader indices from the predecessor relation. More...
 
template<typename T >
bool operator== (const BD_Shape< T > &x, const BD_Shape< T > &y)
 
template<typename T >
bool operator!= (const BD_Shape< T > &x, const BD_Shape< T > &y)
 
template<typename Temp , typename To , typename T >
bool rectilinear_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
 
template<typename Temp , typename To , typename T >
bool rectilinear_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, const Rounding_Dir dir)
 
template<typename To , typename T >
bool rectilinear_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, const Rounding_Dir dir)
 
template<typename Temp , typename To , typename T >
bool euclidean_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
 
template<typename Temp , typename To , typename T >
bool euclidean_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, const Rounding_Dir dir)
 
template<typename To , typename T >
bool euclidean_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, const Rounding_Dir dir)
 
template<typename Temp , typename To , typename T >
bool l_infinity_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
 
template<typename Temp , typename To , typename T >
bool l_infinity_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, const Rounding_Dir dir)
 
template<typename To , typename T >
bool l_infinity_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, const Rounding_Dir dir)
 
template<typename T >
void swap (BD_Shape< T > &x, BD_Shape< T > &y)
 
template<typename T >
std::ostream & operator<< (std::ostream &s, const BD_Shape< T > &bds)
 

Exception Throwers

void throw_dimension_incompatible (const char *method, const BD_Shape &y) 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 *le_name, const Linear_Expression &le) const
 
template<typename Interval_Info >
void throw_dimension_incompatible (const char *method, const char *lf_name, const Linear_Form< Interval< T, Interval_Info > > &lf) const
 
static void throw_expression_too_complex (const char *method, const Linear_Expression &le)
 
static void throw_invalid_argument (const char *method, const char *reason)
 

Detailed Description

template<typename T>
class Parma_Polyhedra_Library::BD_Shape< T >

A bounded difference shape.

The class template BD_Shape<T> allows for the efficient representation of a restricted kind of topologically closed convex polyhedra called bounded difference shapes (BDSs, for short). The name comes from the fact that the closed affine half-spaces that characterize the polyhedron can be expressed by constraints of the form $\pm x_i \leq k$ or $x_i - x_j \leq k$, where the inhomogeneous term $k$ is a rational number.

Based on the class template type parameter T, a family of extended numbers is built and used to approximate the inhomogeneous term of bounded differences. These extended numbers provide a representation for the value $+\infty$, as well as rounding-aware implementations for several arithmetic functions. The value of the type parameter T may be one of the following:

  • a bounded precision integer type (e.g., int32_t or int64_t);
  • a bounded precision floating point type (e.g., float or double);
  • an unbounded integer or rational type, as provided by GMP (i.e., mpz_class or mpq_class).

The user interface for BDSs is meant to be as similar as possible to the one developed for the polyhedron class C_Polyhedron.

The domain of BD shapes optimally supports:

  • tautological and inconsistent constraints and congruences;
  • bounded difference constraints;
  • non-proper congruences (i.e., equalities) that are expressible as bounded-difference constraints.

Depending on the method, using a constraint or congruence that is not optimally supported by the domain will either raise an exception or result in a (possibly non-optimal) upward approximation.

A constraint is a bounded difference if it has the form

\[ a_i x_i - a_j x_j \relsym b \]

where $\mathord{\relsym} \in \{ \leq, =, \geq \}$ and $a_i$, $a_j$, $b$ are integer coefficients such that $a_i = 0$, or $a_j = 0$, or $a_i = a_j$. The user is warned that the above bounded difference Constraint object will be mapped into a correct and optimal approximation that, depending on the expressive power of the chosen template argument T, may loose some precision. Also note that strict constraints are not bounded differences.

For instance, a Constraint object encoding $3x - 3y \leq 1$ will be approximated by:

  • $x - y \leq 1$, if T is a (bounded or unbounded) integer type;
  • $x - y \leq \frac{1}{3}$, if T is the unbounded rational type mpq_class;
  • $x - y \leq k$, where $k > \frac{1}{3}$, if T is a floating point type (having no exact representation for $\frac{1}{3}$).

On the other hand, depending from the context, a Constraint object encoding $3x - y \leq 1$ will be either upward approximated (e.g., by safely ignoring it) or it will cause an exception.

In the following examples it is assumed that the type argument T is one of the possible instances listed above and that variables x, y and z are defined (where they are used) as follows:

Variable x(0);
Variable y(1);
Variable z(2);
Example 1
The following code builds a BDS corresponding to a cube in $\Rset^3$, given as a system of constraints:
Constraint_System cs;
cs.insert(x >= 0);
cs.insert(x <= 1);
cs.insert(y >= 0);
cs.insert(y <= 1);
cs.insert(z >= 0);
cs.insert(z <= 1);
BD_Shape<T> bd(cs);
Since only those constraints having the syntactic form of a bounded difference are optimally supported, the following code will throw an exception (caused by constraints 7, 8 and 9):
Constraint_System cs;
cs.insert(x >= 0);
cs.insert(x <= 1);
cs.insert(y >= 0);
cs.insert(y <= 1);
cs.insert(z >= 0);
cs.insert(z <= 1);
cs.insert(x + y <= 0); // 7
cs.insert(x - z + x >= 0); // 8
cs.insert(3*z - y <= 1); // 9
BD_Shape<T> bd(cs);

Definition at line 412 of file BD_Shape_defs.hh.

Member Typedef Documentation

template<typename T>
typedef N Parma_Polyhedra_Library::BD_Shape< T >::coefficient_type

The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS.

Definition at line 432 of file BD_Shape_defs.hh.

template<typename T>
typedef T Parma_Polyhedra_Library::BD_Shape< T >::coefficient_type_base

The numeric base type upon which bounded differences are built.

Definition at line 426 of file BD_Shape_defs.hh.

The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS.

Definition at line 419 of file BD_Shape_defs.hh.

Constructor & Destructor Documentation

template<typename T >
Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape ( dimension_type  num_dimensions = 0,
Degenerate_Element  kind = UNIVERSE 
)
inlineexplicit

Builds a universe or empty BDS of the specified space dimension.

Parameters
num_dimensionsThe number of dimensions of the vector space enclosing the BDS;
kindSpecifies whether the universe or the empty BDS has to be built.

Definition at line 115 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), and Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed().

117  : dbm(num_dimensions + 1), status(), redundancy_dbm() {
118  if (kind == EMPTY) {
119  set_empty();
120  }
121  else {
122  if (num_dimensions > 0) {
123  // A (non zero-dim) universe BDS is closed.
125  }
126  }
127  PPL_ASSERT(OK());
128 }
The empty element, i.e., the empty set.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
void set_shortest_path_closed()
Marks *this as shortest-path closed.
Bit_Matrix redundancy_dbm
A matrix indicating which constraints are redundant.
Status status
The status flags to keep track of the internal state.
void set_empty()
Turns *this into an empty BDS.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape ( const BD_Shape< T > &  y,
Complexity_Class  complexity = ANY_COMPLEXITY 
)
inline

Ordinary copy constructor.

The complexity argument is ignored.

Definition at line 132 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), and Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm.

133  : dbm(y.dbm), status(y.status), redundancy_dbm() {
134  if (y.marked_shortest_path_reduced()) {
135  redundancy_dbm = y.redundancy_dbm;
136  }
137 }
Bit_Matrix redundancy_dbm
A matrix indicating which constraints are redundant.
Status status
The status flags to keep track of the internal state.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
template<typename U >
Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape ( const BD_Shape< U > &  y,
Complexity_Class  complexity = ANY_COMPLEXITY 
)
inlineexplicit

Builds a conservative, upward approximation of y.

The complexity argument is ignored.

Definition at line 142 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_zero_dim_univ(), Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), and Parma_Polyhedra_Library::BD_Shape< T >::set_zero_dim_univ().

145  : dbm((y.shortest_path_closure_assign(), y.dbm)),
146  status(),
147  redundancy_dbm() {
148  // TODO: handle flags properly, possibly taking special cases into account.
149  if (y.marked_empty()) {
150  set_empty();
151  }
152  else if (y.marked_zero_dim_univ()) {
154  }
155 }
void set_zero_dim_univ()
Turns *this into an zero-dimensional universe BDS.
Bit_Matrix redundancy_dbm
A matrix indicating which constraints are redundant.
Status status
The status flags to keep track of the internal state.
void set_empty()
Turns *this into an empty BDS.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape ( const Constraint_System cs)
inlineexplicit

Builds a BDS from the system of constraints cs.

The BDS inherits the space dimension of cs.

Parameters
csA system of BD constraints.
Exceptions
std::invalid_argumentThrown if cs contains a constraint which is not optimally supported by the BD shape domain.

Definition at line 285 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::add_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed(), and Parma_Polyhedra_Library::Constraint_System::space_dimension().

286  : dbm(cs.space_dimension() + 1), status(), redundancy_dbm() {
287  if (cs.space_dimension() > 0) {
288  // A (non zero-dim) universe BDS is shortest-path closed.
290  }
291  add_constraints(cs);
292 }
void set_shortest_path_closed()
Marks *this as shortest-path closed.
void add_constraints(const Constraint_System &cs)
Adds the constraints in cs to the system of bounded differences defining *this.
Bit_Matrix redundancy_dbm
A matrix indicating which constraints are redundant.
Status status
The status flags to keep track of the internal state.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape ( const Congruence_System cgs)
explicit

Builds a BDS from a system of congruences.

The BDS inherits the space dimension of cgs

Parameters
cgsA system of congruences.
Exceptions
std::invalid_argumentThrown if cgs contains congruences which are not optimally supported by the BD shape domain.

Definition at line 50 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::add_congruences().

51  : dbm(cgs.space_dimension() + 1),
52  status(),
53  redundancy_dbm() {
54  add_congruences(cgs);
55 }
Bit_Matrix redundancy_dbm
A matrix indicating which constraints are redundant.
Status status
The status flags to keep track of the internal state.
void add_congruences(const Congruence_System &cgs)
Adds to *this constraints equivalent to the congruences in cgs.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape ( const Generator_System gs)
explicit

Builds a BDS from the system of generators gs.

Builds the smallest BDS containing the polyhedron defined by gs. The BDS inherits the space dimension of gs.

Exceptions
std::invalid_argumentThrown if the system of generators is not empty but has no points.

Definition at line 58 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Expression_Adapter< T >::begin(), Parma_Polyhedra_Library::Generator_System::begin(), Parma_Polyhedra_Library::Generator::CLOSURE_POINT, Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::Generator::divisor(), Parma_Polyhedra_Library::Expression_Hide_Last< T >::end(), Parma_Polyhedra_Library::Generator_System::end(), Parma_Polyhedra_Library::Generator::expression(), Parma_Polyhedra_Library::Expression_Hide_Last< T >::get(), Parma_Polyhedra_Library::Generator::LINE, Parma_Polyhedra_Library::max_assign(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::Generator::POINT, PPL_DIRTY_TEMP, Parma_Polyhedra_Library::Generator::RAY, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_invalid_argument(), and Parma_Polyhedra_Library::Generator::type().

59  : dbm(gs.space_dimension() + 1), status(), redundancy_dbm() {
60  const Generator_System::const_iterator gs_begin = gs.begin();
61  const Generator_System::const_iterator gs_end = gs.end();
62  if (gs_begin == gs_end) {
63  // An empty generator system defines the empty BD shape.
64  set_empty();
65  return;
66  }
67 
68  const dimension_type space_dim = space_dimension();
69  DB_Row<N>& dbm_0 = dbm[0];
70  PPL_DIRTY_TEMP(N, tmp);
71 
72  bool dbm_initialized = false;
73  bool point_seen = false;
74  // Going through all the points and closure points.
75  for (Generator_System::const_iterator gs_i = gs_begin;
76  gs_i != gs_end; ++gs_i) {
77  const Generator& g = *gs_i;
78  switch (g.type()) {
79  case Generator::POINT:
80  point_seen = true;
81  // Intentionally fall through.
83  if (!dbm_initialized) {
84  // When handling the first (closure) point, we initialize the DBM.
85  dbm_initialized = true;
86  const Coefficient& d = g.divisor();
87  // TODO: Check if the following loop can be optimized used
88  // Generator::expr_type::const_iterator.
89  for (dimension_type i = space_dim; i > 0; --i) {
90  const Coefficient& g_i = g.expression().get(Variable(i - 1));
91  DB_Row<N>& dbm_i = dbm[i];
92  for (dimension_type j = space_dim; j > 0; --j) {
93  if (i != j) {
94  const Coefficient& g_j = g.expression().get(Variable(j - 1));
95  div_round_up(dbm_i[j], g_j - g_i, d);
96  }
97  }
98  div_round_up(dbm_i[0], -g_i, d);
99  }
100  for (dimension_type j = space_dim; j > 0; --j) {
101  const Coefficient& g_j = g.expression().get(Variable(j - 1));
102  div_round_up(dbm_0[j], g_j, d);
103  }
104  // Note: no need to initialize the first element of the main diagonal.
105  }
106  else {
107  // This is not the first point: the DBM already contains
108  // valid values and we must compute maxima.
109  const Coefficient& d = g.divisor();
110  // TODO: Check if the following loop can be optimized used
111  // Generator::expr_type::const_iterator.
112  for (dimension_type i = space_dim; i > 0; --i) {
113  const Coefficient& g_i = g.expression().get(Variable(i - 1));
114  DB_Row<N>& dbm_i = dbm[i];
115  // The loop correctly handles the case when i == j.
116  for (dimension_type j = space_dim; j > 0; --j) {
117  const Coefficient& g_j = g.expression().get(Variable(j - 1));
118  div_round_up(tmp, g_j - g_i, d);
119  max_assign(dbm_i[j], tmp);
120  }
121  div_round_up(tmp, -g_i, d);
122  max_assign(dbm_i[0], tmp);
123  }
124  for (dimension_type j = space_dim; j > 0; --j) {
125  const Coefficient& g_j = g.expression().get(Variable(j - 1));
126  div_round_up(tmp, g_j, d);
127  max_assign(dbm_0[j], tmp);
128  }
129  }
130  break;
131  default:
132  // Lines and rays temporarily ignored.
133  break;
134  }
135  }
136 
137  if (!point_seen) {
138  // The generator system is not empty, but contains no points.
139  throw_invalid_argument("BD_Shape(gs)",
140  "the non-empty generator system gs "
141  "contains no points.");
142  }
143 
144  // Going through all the lines and rays.
145  for (Generator_System::const_iterator gs_i = gs_begin;
146  gs_i != gs_end; ++gs_i) {
147  const Generator& g = *gs_i;
148  switch (g.type()) {
149  case Generator::LINE:
150  // TODO: Check if the following loop can be optimized used
151  // Generator::expr_type::const_iterator.
152  for (dimension_type i = space_dim; i > 0; --i) {
153  const Coefficient& g_i = g.expression().get(Variable(i - 1));
154  DB_Row<N>& dbm_i = dbm[i];
155  // The loop correctly handles the case when i == j.
156  for (dimension_type j = space_dim; j > 0; --j) {
157  if (g_i != g.expression().get(Variable(j - 1))) {
159  }
160  }
161  if (g_i != 0) {
163  }
164  }
165  for (Generator::expr_type::const_iterator i = g.expression().begin(),
166  i_end = g.expression().end(); i != i_end; ++i) {
167  assign_r(dbm_0[i.variable().space_dimension()],
169  }
170  break;
171  case Generator::RAY:
172  // TODO: Check if the following loop can be optimized used
173  // Generator::expr_type::const_iterator.
174  for (dimension_type i = space_dim; i > 0; --i) {
175  const Coefficient& g_i = g.expression().get(Variable(i - 1));
176  DB_Row<N>& dbm_i = dbm[i];
177  // The loop correctly handles the case when i == j.
178  for (dimension_type j = space_dim; j > 0; --j) {
179  if (g_i < g.expression().get(Variable(j - 1))) {
181  }
182  }
183  if (g_i < 0) {
185  }
186  }
187  for (Generator::expr_type::const_iterator i = g.expression().begin(),
188  i_end = g.expression().end(); i != i_end; ++i) {
189  if (*i > 0) {
190  assign_r(dbm_0[i.variable().space_dimension()],
192  }
193  }
194  break;
195  default:
196  // Points and closure points already dealt with.
197  break;
198  }
199  }
201  PPL_ASSERT(OK());
202 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
size_t dimension_type
An unsigned integral type for representing space dimensions.
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
void max_assign(N &x, const N &y)
Assigns to x the maximum between x and y.
Enable_If< Is_Native_Or_Checked< T >::value, void >::type div_round_up(T &to, Coefficient_traits::const_reference x, Coefficient_traits::const_reference y)
Divides x by y into to, rounding the result towards plus infinity.
static void throw_invalid_argument(const char *method, const char *reason)
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
#define PPL_DIRTY_TEMP(T, id)
bool OK() const
Returns true if and only if *this satisfies all its invariants.
void set_shortest_path_closed()
Marks *this as shortest-path closed.
Plus_Infinity PLUS_INFINITY
Definition: checked.cc:31
Generator_System_const_iterator const_iterator
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
base_type::const_iterator const_iterator
The type of const iterators on coefficients.
Bit_Matrix redundancy_dbm
A matrix indicating which constraints are redundant.
Status status
The status flags to keep track of the internal state.
void set_empty()
Turns *this into an empty BDS.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape ( const Polyhedron ph,
Complexity_Class  complexity = ANY_COMPLEXITY 
)
explicit

Builds a BDS from the polyhedron ph.

Builds a BDS containing ph using algorithms whose complexity does not exceed the one specified by complexity. If complexity is ANY_COMPLEXITY, then the BDS built is the smallest one containing ph.

Definition at line 205 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::MIP_Problem::add_constraint(), Parma_Polyhedra_Library::MIP_Problem::add_constraints(), Parma_Polyhedra_Library::ANY_COMPLEXITY, Parma_Polyhedra_Library::Constraint_System::begin(), c, Parma_Polyhedra_Library::Polyhedron::con_sys, Parma_Polyhedra_Library::Polyhedron::constraints(), Parma_Polyhedra_Library::Polyhedron::constraints_are_minimized(), Parma_Polyhedra_Library::Polyhedron::constraints_are_up_to_date(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::MIP_Problem::evaluate_objective_function(), Parma_Polyhedra_Library::Constraint::expression(), Parma_Polyhedra_Library::Polyhedron::generators(), Parma_Polyhedra_Library::Polyhedron::generators_are_up_to_date(), Parma_Polyhedra_Library::Polyhedron::has_pending_constraints(), Parma_Polyhedra_Library::Polyhedron::has_something_pending(), Parma_Polyhedra_Library::Constraint_System::has_strict_inequalities(), Parma_Polyhedra_Library::MIP_Problem::is_satisfiable(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Polyhedron::is_universe(), Parma_Polyhedra_Library::Polyhedron::marked_empty(), Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, Parma_Polyhedra_Library::MIP_Problem::optimizing_point(), Parma_Polyhedra_Library::POLYNOMIAL_COMPLEXITY, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::refine_with_constraints(), Parma_Polyhedra_Library::MIP_Problem::set_objective_function(), Parma_Polyhedra_Library::MIP_Problem::set_optimization_mode(), Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed(), Parma_Polyhedra_Library::SIMPLEX_COMPLEXITY, Parma_Polyhedra_Library::MIP_Problem::solve(), Parma_Polyhedra_Library::Polyhedron::space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.

206  : dbm(), status(), redundancy_dbm() {
207  const dimension_type num_dimensions = ph.space_dimension();
208 
209  if (ph.marked_empty()) {
210  *this = BD_Shape<T>(num_dimensions, EMPTY);
211  return;
212  }
213 
214  if (num_dimensions == 0) {
215  *this = BD_Shape<T>(num_dimensions, UNIVERSE);
216  return;
217  }
218 
219  // Build from generators when we do not care about complexity
220  // or when the process has polynomial complexity.
221  if (complexity == ANY_COMPLEXITY
222  || (!ph.has_pending_constraints() && ph.generators_are_up_to_date())) {
223  *this = BD_Shape<T>(ph.generators());
224  return;
225  }
226 
227  // We cannot afford exponential complexity, we do not have a complete set
228  // of generators for the polyhedron, and the polyhedron is not trivially
229  // empty or zero-dimensional. Constraints, however, are up to date.
230  PPL_ASSERT(ph.constraints_are_up_to_date());
231 
232  if (!ph.has_something_pending() && ph.constraints_are_minimized()) {
233  // If the constraint system of the polyhedron is minimized,
234  // the test `is_universe()' has polynomial complexity.
235  if (ph.is_universe()) {
236  *this = BD_Shape<T>(num_dimensions, UNIVERSE);
237  return;
238  }
239  }
240 
241  // See if there is at least one inconsistent constraint in `ph.con_sys'.
242  for (Constraint_System::const_iterator i = ph.con_sys.begin(),
243  cs_end = ph.con_sys.end(); i != cs_end; ++i) {
244  if (i->is_inconsistent()) {
245  *this = BD_Shape<T>(num_dimensions, EMPTY);
246  return;
247  }
248  }
249 
250  // If `complexity' allows it, use simplex to derive the exact (modulo
251  // the fact that our BDSs are topologically closed) variable bounds.
252  if (complexity == SIMPLEX_COMPLEXITY) {
253  MIP_Problem lp(num_dimensions);
254  lp.set_optimization_mode(MAXIMIZATION);
255 
256  const Constraint_System& ph_cs = ph.constraints();
257  if (!ph_cs.has_strict_inequalities()) {
258  lp.add_constraints(ph_cs);
259  }
260  else {
261  // Adding to `lp' a topologically closed version of `ph_cs'.
262  for (Constraint_System::const_iterator i = ph_cs.begin(),
263  ph_cs_end = ph_cs.end(); i != ph_cs_end; ++i) {
264  const Constraint& c = *i;
265  if (c.is_strict_inequality()) {
266  Linear_Expression expr(c.expression());
267  lp.add_constraint(expr >= 0);
268  }
269  else {
270  lp.add_constraint(c);
271  }
272  }
273  }
274 
275  // Check for unsatisfiability.
276  if (!lp.is_satisfiable()) {
277  *this = BD_Shape<T>(num_dimensions, EMPTY);
278  return;
279  }
280 
281  // Start with a universe BDS that will be refined by the simplex.
282  *this = BD_Shape<T>(num_dimensions, UNIVERSE);
283  // Get all the upper bounds.
284  Generator g(point());
287  for (dimension_type i = 1; i <= num_dimensions; ++i) {
288  Variable x(i-1);
289  // Evaluate optimal upper bound for `x <= ub'.
290  lp.set_objective_function(x);
291  if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
292  g = lp.optimizing_point();
293  lp.evaluate_objective_function(g, numer, denom);
294  div_round_up(dbm[0][i], numer, denom);
295  }
296  // Evaluate optimal upper bound for `x - y <= ub'.
297  for (dimension_type j = 1; j <= num_dimensions; ++j) {
298  if (i == j) {
299  continue;
300  }
301  Variable y(j-1);
302  lp.set_objective_function(x - y);
303  if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
304  g = lp.optimizing_point();
305  lp.evaluate_objective_function(g, numer, denom);
306  div_round_up(dbm[j][i], numer, denom);
307  }
308  }
309  // Evaluate optimal upper bound for `-x <= ub'.
310  lp.set_objective_function(-x);
311  if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
312  g = lp.optimizing_point();
313  lp.evaluate_objective_function(g, numer, denom);
314  div_round_up(dbm[i][0], numer, denom);
315  }
316  }
318  PPL_ASSERT(OK());
319  return;
320  }
321 
322  // Extract easy-to-find bounds from constraints.
323  PPL_ASSERT(complexity == POLYNOMIAL_COMPLEXITY);
324  *this = BD_Shape<T>(num_dimensions, UNIVERSE);
325  refine_with_constraints(ph.constraints());
326 }
The empty element, i.e., the empty set.
size_t dimension_type
An unsigned integral type for representing space dimensions.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
void refine_with_constraints(const Constraint_System &cs)
Uses a copy of the constraints in cs to refine the system of bounded differences defining *this...
Worst-case polynomial complexity.
Enable_If< Is_Native_Or_Checked< T >::value, void >::type div_round_up(T &to, Coefficient_traits::const_reference x, Coefficient_traits::const_reference y)
Divides x by y into to, rounding the result towards plus infinity.
Worst-case exponential complexity but typically polynomial behavior.
The universe element, i.e., the whole vector space.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
void set_shortest_path_closed()
Marks *this as shortest-path closed.
Maximization is requested.
Bit_Matrix redundancy_dbm
A matrix indicating which constraints are redundant.
Coefficient c
Definition: PIP_Tree.cc:64
Status status
The status flags to keep track of the internal state.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
The problem has an optimal solution.
Constraint_System_const_iterator const_iterator
template<typename T >
template<typename Interval >
Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape ( const Box< Interval > &  box,
Complexity_Class  complexity = ANY_COMPLEXITY 
)
inlineexplicit

Builds a BDS out of a box.

The BDS inherits the space dimension of the box. The built BDS is the most precise BDS that includes the box.

Parameters
boxThe box representing the BDS to be built.
complexityThis argument is ignored as the algorithm used has polynomial complexity.
Exceptions
std::length_errorThrown if the space dimension of box exceeds the maximum allowed space dimension.

Definition at line 297 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::Box< ITV >::constraints(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed(), and Parma_Polyhedra_Library::Box< ITV >::space_dimension().

299  : dbm(box.space_dimension() + 1), status(), redundancy_dbm() {
300  // Check emptiness for maximum precision.
301  if (box.is_empty()) {
302  set_empty();
303  }
304  else if (box.space_dimension() > 0) {
305  // A (non zero-dim) universe BDS is shortest-path closed.
307  refine_with_constraints(box.constraints());
308  }
309 }
void refine_with_constraints(const Constraint_System &cs)
Uses a copy of the constraints in cs to refine the system of bounded differences defining *this...
void set_shortest_path_closed()
Marks *this as shortest-path closed.
Bit_Matrix redundancy_dbm
A matrix indicating which constraints are redundant.
Status status
The status flags to keep track of the internal state.
void set_empty()
Turns *this into an empty BDS.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape ( const Grid grid,
Complexity_Class  complexity = ANY_COMPLEXITY 
)
inlineexplicit

Builds a BDS out of a grid.

The BDS inherits the space dimension of the grid. The built BDS is the most precise BDS that includes the grid.

Parameters
gridThe grid used to build the BDS.
complexityThis argument is ignored as the algorithm used has polynomial complexity.
Exceptions
std::length_errorThrown if the space dimension of grid exceeds the maximum allowed space dimension.

Definition at line 313 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::Grid::minimized_congruences(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_congruences(), Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed(), and Parma_Polyhedra_Library::Grid::space_dimension().

315  : dbm(grid.space_dimension() + 1), status(), redundancy_dbm() {
316  if (grid.space_dimension() > 0) {
317  // A (non zero-dim) universe BDS is shortest-path closed.
319  }
320  // Taking minimized congruences ensures maximum precision.
321  refine_with_congruences(grid.minimized_congruences());
322 }
void set_shortest_path_closed()
Marks *this as shortest-path closed.
void refine_with_congruences(const Congruence_System &cgs)
Uses a copy of the congruences in cgs to refine the system of bounded differences defining *this...
Bit_Matrix redundancy_dbm
A matrix indicating which constraints are redundant.
Status status
The status flags to keep track of the internal state.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
template<typename U >
Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape ( const Octagonal_Shape< U > &  os,
Complexity_Class  complexity = ANY_COMPLEXITY 
)
inlineexplicit

Builds a BDS from an octagonal shape.

The BDS inherits the space dimension of the octagonal shape. The built BDS is the most precise BDS that includes the octagonal shape.

Parameters
osThe octagonal shape used to build the BDS.
complexityThis argument is ignored as the algorithm used has polynomial complexity.
Exceptions
std::length_errorThrown if the space dimension of os exceeds the maximum allowed space dimension.

Definition at line 327 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::Octagonal_Shape< T >::constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::is_empty(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::space_dimension().

329  : dbm(os.space_dimension() + 1), status(), redundancy_dbm() {
330  // Check for emptiness for maximum precision.
331  if (os.is_empty()) {
332  set_empty();
333  }
334  else if (os.space_dimension() > 0) {
335  // A (non zero-dim) universe BDS is shortest-path closed.
337  refine_with_constraints(os.constraints());
338  // After refining, shortest-path closure is possibly lost
339  // (even when `os' was strongly closed: recall that U
340  // is possibly different from T).
341  }
342 }
void refine_with_constraints(const Constraint_System &cs)
Uses a copy of the constraints in cs to refine the system of bounded differences defining *this...
void set_shortest_path_closed()
Marks *this as shortest-path closed.
Bit_Matrix redundancy_dbm
A matrix indicating which constraints are redundant.
Status status
The status flags to keep track of the internal state.
void set_empty()
Turns *this into an empty BDS.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
Parma_Polyhedra_Library::BD_Shape< T >::~BD_Shape ( )
inline

Destructor.

Definition at line 357 of file BD_Shape_inlines.hh.

357  {
358 }

Member Function Documentation

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::add_congruence ( const Congruence cg)

Adds a copy of congruence cg to the system of congruences of *this.

Parameters
cgThe congruence to be added.
Exceptions
std::invalid_argumentThrown if *this and congruence cg are dimension-incompatible, or cg is not optimally supported by the BD shape domain.

Definition at line 490 of file BD_Shape_templates.hh.

References c, 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(), and Parma_Polyhedra_Library::Congruence::space_dimension().

490  {
491  const dimension_type cg_space_dim = cg.space_dimension();
492  // Dimension-compatibility check:
493  // the dimension of `cg' can not be greater than space_dim.
494  if (space_dimension() < cg_space_dim) {
495  throw_dimension_incompatible("add_congruence(cg)", cg);
496  }
497  // Handle the case of proper congruences first.
498  if (cg.is_proper_congruence()) {
499  if (cg.is_tautological()) {
500  return;
501  }
502  if (cg.is_inconsistent()) {
503  set_empty();
504  return;
505  }
506  // Non-trivial and proper congruences are not allowed.
507  throw_invalid_argument("add_congruence(cg)",
508  "cg is a non-trivial, proper congruence");
509  }
510 
511  PPL_ASSERT(cg.is_equality());
512  Constraint c(cg);
513  add_constraint(c);
514 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
void add_constraint(const Constraint &c)
Adds a copy of constraint c to the system of bounded differences defining *this.
static void throw_invalid_argument(const char *method, const char *reason)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Coefficient c
Definition: PIP_Tree.cc:64
void set_empty()
Turns *this into an empty BDS.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::add_congruences ( const Congruence_System cgs)
inline

Adds to *this constraints equivalent to the congruences in cgs.

Parameters
cgsContains the congruences that will be added to the system of constraints of *this.
Exceptions
std::invalid_argumentThrown if *this and cgs are dimension-incompatible, or cgs contains a congruence which is not optimally supported by the BD shape domain.

Definition at line 180 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::Congruence_System::begin(), and Parma_Polyhedra_Library::Congruence_System::end().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape().

180  {
181  for (Congruence_System::const_iterator i = cgs.begin(),
182  cgs_end = cgs.end(); i != cgs_end; ++i) {
183  add_congruence(*i);
184  }
185 }
void add_congruence(const Congruence &cg)
Adds a copy of congruence cg to the system of congruences of *this.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::add_constraint ( const Constraint c)

Adds a copy of constraint c to the system of bounded differences defining *this.

Parameters
cThe constraint to be added.
Exceptions
std::invalid_argumentThrown if *this and constraint c are dimension-incompatible, or c is not optimally supported by the BD shape domain.

Definition at line 414 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::BD_Shape_Helpers::extract_bounded_difference(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Constraint::is_inconsistent(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Constraint::is_tautological(), Parma_Polyhedra_Library::neg_assign(), PPL_DIRTY_TEMP, PPL_DIRTY_TEMP_COEFFICIENT, and Parma_Polyhedra_Library::Constraint::space_dimension().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::difference_assign().

414  {
415  // Dimension-compatibility check.
416  if (c.space_dimension() > space_dimension()) {
417  throw_dimension_incompatible("add_constraint(c)", c);
418  }
419  // Get rid of strict inequalities.
420  if (c.is_strict_inequality()) {
421  if (c.is_inconsistent()) {
422  set_empty();
423  return;
424  }
425  if (c.is_tautological()) {
426  return;
427  }
428  // Nontrivial strict inequalities are not allowed.
429  throw_invalid_argument("add_constraint(c)",
430  "strict inequalities are not allowed");
431  }
432 
433  dimension_type num_vars = 0;
434  dimension_type i = 0;
435  dimension_type j = 0;
437  // Constraints that are not bounded differences are not allowed.
438  if (!BD_Shape_Helpers::extract_bounded_difference(c, num_vars, i, j, coeff)) {
439  throw_invalid_argument("add_constraint(c)",
440  "c is not a bounded difference constraint");
441  }
442  const Coefficient& inhomo = c.inhomogeneous_term();
443  if (num_vars == 0) {
444  // Dealing with a trivial constraint (not a strict inequality).
445  if (inhomo < 0
446  || (inhomo != 0 && c.is_equality())) {
447  set_empty();
448  }
449  return;
450  }
451 
452  // Select the cell to be modified for the "<=" part of the constraint,
453  // and set `coeff' to the absolute value of itself.
454  const bool negative = (coeff < 0);
455  if (negative) {
456  neg_assign(coeff);
457  }
458  bool changed = false;
459  N& x = negative ? dbm[i][j] : dbm[j][i];
460  // Compute the bound for `x', rounding towards plus infinity.
461  PPL_DIRTY_TEMP(N, d);
462  div_round_up(d, inhomo, coeff);
463  if (x > d) {
464  x = d;
465  changed = true;
466  }
467 
468  if (c.is_equality()) {
469  N& y = negative ? dbm[j][i] : dbm[i][j];
470  // Also compute the bound for `y', rounding towards plus infinity.
471  PPL_DIRTY_TEMP_COEFFICIENT(minus_c_term);
472  neg_assign(minus_c_term, inhomo);
473  div_round_up(d, minus_c_term, coeff);
474  if (y > d) {
475  y = d;
476  changed = true;
477  }
478  }
479 
480  // In general, adding a constraint does not preserve the shortest-path
481  // closure or reduction of the bounded difference shape.
482  if (changed && marked_shortest_path_closed()) {
484  }
485  PPL_ASSERT(OK());
486 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
bool marked_shortest_path_closed() const
Returns true if the system of bounded differences is known to be shortest-path closed.
Enable_If< Is_Native_Or_Checked< T >::value, void >::type div_round_up(T &to, Coefficient_traits::const_reference x, Coefficient_traits::const_reference y)
Divides x by y into to, rounding the result towards plus infinity.
void reset_shortest_path_closed()
Marks *this as possibly not shortest-path closed.
static void throw_invalid_argument(const char *method, const char *reason)
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
#define PPL_DIRTY_TEMP(T, id)
bool OK() const
Returns true if and only if *this satisfies all its invariants.
void neg_assign(GMP_Integer &x)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
static bool extract_bounded_difference(const Constraint &c, dimension_type &c_num_vars, dimension_type &c_first_var, dimension_type &c_second_var, Coefficient &c_coeff)
Decodes the constraint c as a bounded difference.
Coefficient c
Definition: PIP_Tree.cc:64
void set_empty()
Turns *this into an empty BDS.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::add_constraints ( const Constraint_System cs)
inline

Adds the constraints in cs to the system of bounded differences defining *this.

Parameters
csThe constraints that will be added.
Exceptions
std::invalid_argumentThrown if *this and cs are dimension-incompatible, or cs contains a constraint which is not optimally supported by the BD shape domain.

Definition at line 165 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::Constraint_System::begin(), and Parma_Polyhedra_Library::Constraint_System::end().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape().

165  {
166  for (Constraint_System::const_iterator i = cs.begin(),
167  cs_end = cs.end(); i != cs_end; ++i) {
168  add_constraint(*i);
169  }
170 }
void add_constraint(const Constraint &c)
Adds a copy of constraint c to the system of bounded differences defining *this.
Constraint_System_const_iterator const_iterator
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::add_dbm_constraint ( dimension_type  i,
dimension_type  j,
const N k 
)
inlineprivate

Adds the constraint dbm[i][j] <= k.

Definition at line 698 of file BD_Shape_inlines.hh.

700  {
701  // Private method: the caller has to ensure the following.
702  PPL_ASSERT(i <= space_dimension() && j <= space_dimension() && i != j);
703  N& dbm_ij = dbm[i][j];
704  if (dbm_ij > k) {
705  dbm_ij = k;
708  }
709  }
710 }
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
bool marked_shortest_path_closed() const
Returns true if the system of bounded differences is known to be shortest-path closed.
void reset_shortest_path_closed()
Marks *this as possibly not shortest-path closed.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::add_dbm_constraint ( dimension_type  i,
dimension_type  j,
Coefficient_traits::const_reference  numer,
Coefficient_traits::const_reference  denom 
)
inlineprivate

Adds the constraint dbm[i][j] <= numer/denom.

Definition at line 714 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::div_round_up(), and PPL_DIRTY_TEMP.

717  {
718  // Private method: the caller has to ensure the following.
719  PPL_ASSERT(i <= space_dimension() && j <= space_dimension() && i != j);
720  PPL_ASSERT(denom != 0);
721  PPL_DIRTY_TEMP(N, k);
722  div_round_up(k, numer, denom);
723  add_dbm_constraint(i, j, k);
724 }
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
Enable_If< Is_Native_Or_Checked< T >::value, void >::type div_round_up(T &to, Coefficient_traits::const_reference x, Coefficient_traits::const_reference y)
Divides x by y into to, rounding the result towards plus infinity.
void add_dbm_constraint(dimension_type i, dimension_type j, const N &k)
Adds the constraint dbm[i][j] <= k.
#define PPL_DIRTY_TEMP(T, id)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::add_recycled_congruences ( Congruence_System cgs)
inline

Adds to *this constraints equivalent to the congruences in cgs.

Parameters
cgsContains the congruences that will be added to the system of constraints of *this. Its elements may be recycled.
Exceptions
std::invalid_argumentThrown if *this and cgs are dimension-incompatible, or cgs contains a congruence which is not optimally supported by the BD shape domain.
Warning
The only assumption that can be made on cgs upon successful or exceptional return is that it can be safely destroyed.

Definition at line 189 of file BD_Shape_inlines.hh.

189  {
190  add_congruences(cgs);
191 }
void add_congruences(const Congruence_System &cgs)
Adds to *this constraints equivalent to the congruences in cgs.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::add_recycled_constraints ( Constraint_System cs)
inline

Adds the constraints in cs to the system of constraints of *this.

Parameters
csThe constraint system to be added to *this. The constraints in cs may be recycled.
Exceptions
std::invalid_argumentThrown if *this and cs are dimension-incompatible, or cs contains a constraint which is not optimally supported by the BD shape domain.
Warning
The only assumption that can be made on cs upon successful or exceptional return is that it can be safely destroyed.

Definition at line 174 of file BD_Shape_inlines.hh.

174  {
175  add_constraints(cs);
176 }
void add_constraints(const Constraint_System &cs)
Adds the constraints in cs to the system of bounded differences defining *this.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_embed ( dimension_type  m)

Adds m new dimensions and embeds the old BDS into the new space.

Parameters
mThe number of dimensions to add.

The new dimensions will be those having the highest indexes in the new BDS, which is defined by a system of bounded differences in which the variables running through the new dimensions are unconstrained. For instance, when starting from the BDS $\cB \sseq \Rset^2$ and adding a third dimension, the result will be the BDS

\[ \bigl\{\, (x, y, z)^\transpose \in \Rset^3 \bigm| (x, y)^\transpose \in \cB \,\bigr\}. \]

Definition at line 2779 of file BD_Shape_templates.hh.

2779  {
2780  // Adding no dimensions is a no-op.
2781  if (m == 0) {
2782  return;
2783  }
2784  const dimension_type space_dim = space_dimension();
2785  const dimension_type new_space_dim = space_dim + m;
2786  const bool was_zero_dim_univ = (!marked_empty() && space_dim == 0);
2787 
2788  // To embed an n-dimension space BDS in a (n+m)-dimension space,
2789  // we just add `m' rows and columns in the bounded difference shape,
2790  // initialized to PLUS_INFINITY.
2791  dbm.grow(new_space_dim + 1);
2792 
2793  // Shortest-path closure is maintained (if it was holding).
2794  // TODO: see whether reduction can be (efficiently!) maintained too.
2797  }
2798  // If `*this' was the zero-dim space universe BDS,
2799  // the we can set the shortest-path closure flag.
2800  if (was_zero_dim_univ) {
2802  }
2803  PPL_ASSERT(OK());
2804 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool marked_shortest_path_reduced() const
Returns true if the system of bounded differences is known to be shortest-path reduced.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
void set_shortest_path_closed()
Marks *this as shortest-path closed.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void reset_shortest_path_reduced()
Marks *this as possibly not shortest-path reduced.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_project ( dimension_type  m)

Adds m new dimensions to the BDS and does not embed it in the new vector space.

Parameters
mThe number of dimensions to add.

The new dimensions will be those having the highest indexes in the new BDS, which is defined by a system of bounded differences in which the variables running through the new dimensions are all constrained to be equal to 0. For instance, when starting from the BDS $\cB \sseq \Rset^2$ and adding a third dimension, the result will be the BDS

\[ \bigl\{\, (x, y, 0)^\transpose \in \Rset^3 \bigm| (x, y)^\transpose \in \cB \,\bigr\}. \]

Definition at line 2808 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::assign_r(), and Parma_Polyhedra_Library::ROUND_NOT_NEEDED.

2808  {
2809  // Adding no dimensions is a no-op.
2810  if (m == 0) {
2811  return;
2812  }
2813  const dimension_type space_dim = space_dimension();
2814 
2815  // If `*this' was zero-dimensional, then we add `m' rows and columns.
2816  // If it also was non-empty, then we zero all the added elements
2817  // and set the flag for shortest-path closure.
2818  if (space_dim == 0) {
2819  dbm.grow(m + 1);
2820  if (!marked_empty()) {
2821  for (dimension_type i = m + 1; i-- > 0; ) {
2822  DB_Row<N>& dbm_i = dbm[i];
2823  for (dimension_type j = m + 1; j-- > 0; ) {
2824  if (i != j) {
2825  assign_r(dbm_i[j], 0, ROUND_NOT_NEEDED);
2826  }
2827  }
2828  }
2830  }
2831  PPL_ASSERT(OK());
2832  return;
2833  }
2834 
2835  // To project an n-dimension space bounded difference shape
2836  // in a (n+m)-dimension space, we add `m' rows and columns.
2837  // In the first row and column of the matrix we add `zero' from
2838  // the (n+1)-th position to the end.
2839  const dimension_type new_space_dim = space_dim + m;
2840  dbm.grow(new_space_dim + 1);
2841 
2842  // Bottom of the matrix and first row.
2843  DB_Row<N>& dbm_0 = dbm[0];
2844  for (dimension_type i = space_dim + 1; i <= new_space_dim; ++i) {
2845  assign_r(dbm[i][0], 0, ROUND_NOT_NEEDED);
2846  assign_r(dbm_0[i], 0, ROUND_NOT_NEEDED);
2847  }
2848 
2851  }
2852  PPL_ASSERT(OK());
2853 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool marked_shortest_path_closed() const
Returns true if the system of bounded differences is known to be shortest-path closed.
void reset_shortest_path_closed()
Marks *this as possibly not shortest-path closed.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
void set_shortest_path_closed()
Marks *this as shortest-path closed.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
dimension_type Parma_Polyhedra_Library::BD_Shape< T >::affine_dimension ( ) const

Returns $0$, if *this is empty; otherwise, returns the affine dimension of *this.

Definition at line 330 of file BD_Shape_templates.hh.

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign().

330  {
331  const dimension_type space_dim = space_dimension();
332  // A zero-space-dim shape always has affine dimension zero.
333  if (space_dim == 0) {
334  return 0;
335  }
336  // Shortest-path closure is necessary to detect emptiness
337  // and all (possibly implicit) equalities.
339  if (marked_empty()) {
340  return 0;
341  }
342  // The vector `predecessor' is used to represent equivalence classes:
343  // `predecessor[i] == i' if and only if `i' is the leader of its
344  // equivalence class (i.e., the minimum index in the class).
345  std::vector<dimension_type> predecessor;
346  compute_predecessors(predecessor);
347 
348  // Due to the fictitious variable `0', the affine dimension is one
349  // less the number of equivalence classes.
350  dimension_type affine_dim = 0;
351  // Note: disregard the first equivalence class.
352  for (dimension_type i = 1; i <= space_dim; ++i) {
353  if (predecessor[i] == i) {
354  ++affine_dim;
355  }
356  }
357  return affine_dim;
358 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
void compute_predecessors(std::vector< dimension_type > &predecessor) const
Compute the (zero-equivalence classes) predecessor relation.
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
template<typename T >
template<typename Interval_Info >
void Parma_Polyhedra_Library::BD_Shape< T >::affine_form_image ( Variable  var,
const Linear_Form< Interval< T, Interval_Info > > &  lf 
)

Assigns to *this the affine form image of *this under the function mapping variable var into the affine expression(s) specified by lf.

Parameters
varThe variable to which the affine expression is assigned.
lfThe linear form on intervals with floating point coefficients that defines the affine expression. ALL of its coefficients MUST be bounded.
Exceptions
std::invalid_argumentThrown if lf and *this are dimension-incompatible or if var is not a dimension of *this.

Definition at line 4369 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::Variable::id(), and PPL_COMPILE_TIME_CHECK.

4370  {
4371 
4372  // Check that T is a floating point type.
4373  PPL_COMPILE_TIME_CHECK(!std::numeric_limits<T>::is_exact,
4374  "BD_Shape<T>::affine_form_image(Variable, Linear_Form):"
4375  " T not a floating point type.");
4376 
4377  // Dimension-compatibility checks.
4378  // The dimension of `lf' should not be greater than the dimension
4379  // of `*this'.
4380  const dimension_type space_dim = space_dimension();
4381  const dimension_type lf_space_dim = lf.space_dimension();
4382  if (space_dim < lf_space_dim) {
4383  throw_dimension_incompatible("affine_form_image(var_id, l)", "l", lf);
4384  }
4385  // `var' should be one of the dimensions of the shape.
4386  const dimension_type var_id = var.id() + 1;
4387  if (space_dim < var_id) {
4388  throw_dimension_incompatible("affine_form_image(var_id, l)", var.id());
4389  }
4390  // The image of an empty BDS is empty too.
4392  if (marked_empty()) {
4393  return;
4394  }
4395  // Number of non-zero coefficients in `lf': will be set to
4396  // 0, 1, or 2, the latter value meaning any value greater than 1.
4397  dimension_type t = 0;
4398  // Index of the last non-zero coefficient in `lf', if any.
4399  dimension_type w_id = 0;
4400  // Get information about the number of non-zero coefficients in `lf'.
4401  for (dimension_type i = lf_space_dim; i-- > 0; ) {
4402  if (lf.coefficient(Variable(i)) != 0) {
4403  if (t++ == 1) {
4404  break;
4405  }
4406  else {
4407  w_id = i + 1;
4408  }
4409  }
4410  }
4411  typedef Interval<T, Interval_Info> FP_Interval_Type;
4412 
4413  const FP_Interval_Type& b = lf.inhomogeneous_term();
4414 
4415  // Now we know the form of `lf':
4416  // - If t == 0, then lf == b, with `b' a constant;
4417  // - If t == 1, then lf == a*w + b, where `w' can be `v' or another
4418  // variable;
4419  // - If t == 2, the linear form 'lf' is of the general form.
4420 
4421  if (t == 0) {
4423  PPL_ASSERT(OK());
4424  return;
4425  }
4426  else if (t == 1) {
4427  const FP_Interval_Type& w_coeff = lf.coefficient(Variable(w_id - 1));
4428  if (w_coeff == 1 || w_coeff == -1) {
4429  one_variable_affine_form_image(var_id, b, w_coeff, w_id, space_dim);
4430  PPL_ASSERT(OK());
4431  return;
4432  }
4433  }
4434  two_variables_affine_form_image(var_id, lf, space_dim);
4435  PPL_ASSERT(OK());
4436 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
void inhomogeneous_affine_form_image(const dimension_type &var_id, const Interval< T, Interval_Info > &b)
Auxiliary function for affine form image that handle the general case: .
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
#define PPL_COMPILE_TIME_CHECK(e, msg)
Produces a compilation error if the compile-time constant e does not evaluate to true ...
void two_variables_affine_form_image(const dimension_type &var_id, const Linear_Form< Interval< T, Interval_Info > > &lf, const dimension_type &space_dim)
Auxiliary function for affine form image that handle the general case: .
bool OK() const
Returns true if and only if *this satisfies all its invariants.
void one_variable_affine_form_image(const dimension_type &var_id, const Interval< T, Interval_Info > &b, const Interval< T, Interval_Info > &w_coeff, const dimension_type &w_id, const dimension_type &space_dim)
Auxiliary function for affine formimage" that handle the general case: .
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::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.

Parameters
varThe variable to which the affine expression is assigned.
exprThe numerator of the affine expression.
denominatorThe denominator of the affine expression.
Exceptions
std::invalid_argumentThrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a dimension of *this.

Definition at line 4025 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::Linear_Expression::all_zeroes(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::begin(), c, Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::Linear_Expression::get(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Linear_Expression::last_nonzero(), Parma_Polyhedra_Library::Linear_Expression::lower_bound(), Parma_Polyhedra_Library::neg_assign(), PPL_DIRTY_TEMP, PPL_DIRTY_TEMP_COEFFICIENT, PPL_UNINITIALIZED, Parma_Polyhedra_Library::ROUND_UP, Parma_Polyhedra_Library::Boundary_NS::sgn(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and Parma_Polyhedra_Library::swap().

4027  {
4028  // The denominator cannot be zero.
4029  if (denominator == 0) {
4030  throw_invalid_argument("affine_image(v, e, d)", "d == 0");
4031  }
4032  // Dimension-compatibility checks.
4033  // The dimension of `expr' should not be greater than the dimension
4034  // of `*this'.
4035  const dimension_type space_dim = space_dimension();
4036  const dimension_type expr_space_dim = expr.space_dimension();
4037  if (space_dim < expr_space_dim) {
4038  throw_dimension_incompatible("affine_image(v, e, d)", "e", expr);
4039  }
4040  // `var' should be one of the dimensions of the shape.
4041  const dimension_type v = var.id() + 1;
4042  if (v > space_dim) {
4043  throw_dimension_incompatible("affine_image(v, e, d)", var.id());
4044  }
4045  // The image of an empty BDS is empty too.
4047  if (marked_empty()) {
4048  return;
4049  }
4050  const Coefficient& b = expr.inhomogeneous_term();
4051  // Number of non-zero coefficients in `expr': will be set to
4052  // 0, 1, or 2, the latter value meaning any value greater than 1.
4053  dimension_type t = 0;
4054  // Index of the last non-zero coefficient in `expr', if any.
4055  dimension_type w = expr.last_nonzero();
4056 
4057  if (w != 0) {
4058  ++t;
4059  if (!expr.all_zeroes(1, w)) {
4060  ++t;
4061  }
4062  }
4063 
4064  // Now we know the form of `expr':
4065  // - If t == 0, then expr == b, with `b' a constant;
4066  // - If t == 1, then expr == a*w + b, where `w' can be `v' or another
4067  // variable; in this second case we have to check whether `a' is
4068  // equal to `denominator' or `-denominator', since otherwise we have
4069  // to fall back on the general form;
4070  // - If t == 2, the `expr' is of the general form.
4071  PPL_DIRTY_TEMP_COEFFICIENT(minus_denom);
4072  neg_assign(minus_denom, denominator);
4073 
4074  if (t == 0) {
4075  // Case 1: expr == b.
4076  // Remove all constraints on `var'.
4078  // Shortest-path closure is preserved, but not reduction.
4081  }
4082  // Add the constraint `var == b/denominator'.
4083  add_dbm_constraint(0, v, b, denominator);
4084  add_dbm_constraint(v, 0, b, minus_denom);
4085  PPL_ASSERT(OK());
4086  return;
4087  }
4088 
4089  if (t == 1) {
4090  // Value of the one and only non-zero coefficient in `expr'.
4091  const Coefficient& a = expr.get(Variable(w - 1));
4092  if (a == denominator || a == minus_denom) {
4093  // Case 2: expr == a*w + b, with a == +/- denominator.
4094  if (w == v) {
4095  // `expr' is of the form: a*v + b.
4096  if (a == denominator) {
4097  if (b == 0) {
4098  // The transformation is the identity function.
4099  return;
4100  }
4101  else {
4102  // Translate all the constraints on `var',
4103  // adding or subtracting the value `b/denominator'.
4104  PPL_DIRTY_TEMP(N, d);
4105  div_round_up(d, b, denominator);
4106  PPL_DIRTY_TEMP(N, c);
4107  div_round_up(c, b, minus_denom);
4108  DB_Row<N>& dbm_v = dbm[v];
4109  for (dimension_type i = space_dim + 1; i-- > 0; ) {
4110  N& dbm_vi = dbm_v[i];
4111  add_assign_r(dbm_vi, dbm_vi, c, ROUND_UP);
4112  N& dbm_iv = dbm[i][v];
4113  add_assign_r(dbm_iv, dbm_iv, d, ROUND_UP);
4114  }
4115  // Both shortest-path closure and reduction are preserved.
4116  }
4117  }
4118  else {
4119  // Here `a == -denominator'.
4120  // Remove the binary constraints on `var'.
4122  // Swap the unary constraints on `var'.
4123  using std::swap;
4124  swap(dbm[v][0], dbm[0][v]);
4125  // Shortest-path closure is not preserved.
4127  if (b != 0) {
4128  // Translate the unary constraints on `var',
4129  // adding or subtracting the value `b/denominator'.
4130  PPL_DIRTY_TEMP(N, c);
4131  div_round_up(c, b, minus_denom);
4132  N& dbm_v0 = dbm[v][0];
4133  add_assign_r(dbm_v0, dbm_v0, c, ROUND_UP);
4134  PPL_DIRTY_TEMP(N, d);
4135  div_round_up(d, b, denominator);
4136  N& dbm_0v = dbm[0][v];
4137  add_assign_r(dbm_0v, dbm_0v, d, ROUND_UP);
4138  }
4139  }
4140  }
4141  else {
4142  // Here `w != v', so that `expr' is of the form
4143  // +/-denominator * w + b.
4144  // Remove all constraints on `var'.
4146  // Shortest-path closure is preserved, but not reduction.
4149  }
4150  if (a == denominator) {
4151  // Add the new constraint `v - w == b/denominator'.
4152  add_dbm_constraint(w, v, b, denominator);
4153  add_dbm_constraint(v, w, b, minus_denom);
4154  }
4155  else {
4156  // Here a == -denominator, so that we should be adding
4157  // the constraint `v + w == b/denominator'.
4158  // Approximate it by computing lower and upper bounds for `w'.
4159  const N& dbm_w0 = dbm[w][0];
4160  if (!is_plus_infinity(dbm_w0)) {
4161  // Add the constraint `v <= b/denominator - lower_w'.
4162  PPL_DIRTY_TEMP(N, d);
4163  div_round_up(d, b, denominator);
4164  add_assign_r(dbm[0][v], d, dbm_w0, ROUND_UP);
4166  }
4167  const N& dbm_0w = dbm[0][w];
4168  if (!is_plus_infinity(dbm_0w)) {
4169  // Add the constraint `v >= b/denominator - upper_w'.
4170  PPL_DIRTY_TEMP(N, c);
4171  div_round_up(c, b, minus_denom);
4172  add_assign_r(dbm[v][0], dbm_0w, c, ROUND_UP);
4174  }
4175  }
4176  }
4177  PPL_ASSERT(OK());
4178  return;
4179  }
4180  }
4181 
4182  // General case.
4183  // Either t == 2, so that
4184  // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
4185  // or t == 1, expr == a*w + b, but a <> +/- denominator.
4186  // We will remove all the constraints on `var' and add back
4187  // constraints providing upper and lower bounds for `var'.
4188 
4189  // Compute upper approximations for `expr' and `-expr'
4190  // into `pos_sum' and `neg_sum', respectively, taking into account
4191  // the sign of `denominator'.
4192  // Note: approximating `-expr' from above and then negating the
4193  // result is the same as approximating `expr' from below.
4194  const bool is_sc = (denominator > 0);
4195  PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
4196  neg_assign(minus_b, b);
4197  const Coefficient& sc_b = is_sc ? b : minus_b;
4198  const Coefficient& minus_sc_b = is_sc ? minus_b : b;
4199  const Coefficient& sc_denom = is_sc ? denominator : minus_denom;
4200  const Coefficient& minus_sc_denom = is_sc ? minus_denom : denominator;
4201  // NOTE: here, for optimization purposes, `minus_expr' is only assigned
4202  // when `denominator' is negative. Do not use it unless you are sure
4203  // it has been correctly assigned.
4204  Linear_Expression minus_expr;
4205  if (!is_sc) {
4206  minus_expr = -expr;
4207  }
4208  const Linear_Expression& sc_expr = is_sc ? expr : minus_expr;
4209 
4210  PPL_DIRTY_TEMP(N, pos_sum);
4211  PPL_DIRTY_TEMP(N, neg_sum);
4212  // Indices of the variables that are unbounded in `this->dbm'.
4213  PPL_UNINITIALIZED(dimension_type, pos_pinf_index);
4214  PPL_UNINITIALIZED(dimension_type, neg_pinf_index);
4215  // Number of unbounded variables found.
4216  dimension_type pos_pinf_count = 0;
4217  dimension_type neg_pinf_count = 0;
4218 
4219  // Approximate the inhomogeneous term.
4220  assign_r(pos_sum, sc_b, ROUND_UP);
4221  assign_r(neg_sum, minus_sc_b, ROUND_UP);
4222 
4223  // Approximate the homogeneous part of `sc_expr'.
4224  const DB_Row<N>& dbm_0 = dbm[0];
4225  // Speculative allocation of temporaries to be used in the following loop.
4226  PPL_DIRTY_TEMP(N, coeff_i);
4227  PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
4228 
4229  // Note: indices above `w' can be disregarded, as they all have
4230  // a zero coefficient in `sc_expr'.
4231  for (Linear_Expression::const_iterator i = sc_expr.begin(),
4232  i_end = sc_expr.lower_bound(Variable(w)); i != i_end; ++i) {
4233  const Coefficient& sc_i = *i;
4234  const dimension_type i_dim = i.variable().space_dimension();
4235  const int sign_i = sgn(sc_i);
4236  if (sign_i > 0) {
4237  assign_r(coeff_i, sc_i, ROUND_UP);
4238  // Approximating `sc_expr'.
4239  if (pos_pinf_count <= 1) {
4240  const N& up_approx_i = dbm_0[i_dim];
4241  if (!is_plus_infinity(up_approx_i)) {
4242  add_mul_assign_r(pos_sum, coeff_i, up_approx_i, ROUND_UP);
4243  }
4244  else {
4245  ++pos_pinf_count;
4246  pos_pinf_index = i_dim;
4247  }
4248  }
4249  // Approximating `-sc_expr'.
4250  if (neg_pinf_count <= 1) {
4251  const N& up_approx_minus_i = dbm[i_dim][0];
4252  if (!is_plus_infinity(up_approx_minus_i)) {
4253  add_mul_assign_r(neg_sum, coeff_i, up_approx_minus_i, ROUND_UP);
4254  }
4255  else {
4256  ++neg_pinf_count;
4257  neg_pinf_index = i_dim;
4258  }
4259  }
4260  }
4261  else {
4262  PPL_ASSERT(sign_i < 0);
4263  neg_assign(minus_sc_i, sc_i);
4264  // Note: using temporary named `coeff_i' to store -coeff_i.
4265  assign_r(coeff_i, minus_sc_i, ROUND_UP);
4266  // Approximating `sc_expr'.
4267  if (pos_pinf_count <= 1) {
4268  const N& up_approx_minus_i = dbm[i_dim][0];
4269  if (!is_plus_infinity(up_approx_minus_i)) {
4270  add_mul_assign_r(pos_sum, coeff_i, up_approx_minus_i, ROUND_UP);
4271  }
4272  else {
4273  ++pos_pinf_count;
4274  pos_pinf_index = i_dim;
4275  }
4276  }
4277  // Approximating `-sc_expr'.
4278  if (neg_pinf_count <= 1) {
4279  const N& up_approx_i = dbm_0[i_dim];
4280  if (!is_plus_infinity(up_approx_i)) {
4281  add_mul_assign_r(neg_sum, coeff_i, up_approx_i, ROUND_UP);
4282  }
4283  else {
4284  ++neg_pinf_count;
4285  neg_pinf_index = i_dim;
4286  }
4287  }
4288  }
4289  }
4290 
4291  // Remove all constraints on 'v'.
4293  // Shortest-path closure is maintained, but not reduction.
4296  }
4297  // Return immediately if no approximation could be computed.
4298  if (pos_pinf_count > 1 && neg_pinf_count > 1) {
4299  PPL_ASSERT(OK());
4300  return;
4301  }
4302 
4303  // In the following, shortest-path closure will be definitely lost.
4305 
4306  // Exploit the upper approximation, if possible.
4307  if (pos_pinf_count <= 1) {
4308  // Compute quotient (if needed).
4309  if (sc_denom != 1) {
4310  // Before computing quotients, the denominator should be approximated
4311  // towards zero. Since `sc_denom' is known to be positive, this amounts to
4312  // rounding downwards, which is achieved as usual by rounding upwards
4313  // `minus_sc_denom' and negating again the result.
4314  PPL_DIRTY_TEMP(N, down_sc_denom);
4315  assign_r(down_sc_denom, minus_sc_denom, ROUND_UP);
4316  neg_assign_r(down_sc_denom, down_sc_denom, ROUND_UP);
4317  div_assign_r(pos_sum, pos_sum, down_sc_denom, ROUND_UP);
4318  }
4319  // Add the upper bound constraint, if meaningful.
4320  if (pos_pinf_count == 0) {
4321  // Add the constraint `v <= pos_sum'.
4322  dbm[0][v] = pos_sum;
4323  // Deduce constraints of the form `v - u', where `u != v'.
4324  deduce_v_minus_u_bounds(v, w, sc_expr, sc_denom, pos_sum);
4325  } // Here `pos_pinf_count == 1'.
4326  else if (pos_pinf_index != v
4327  && sc_expr.get(Variable(pos_pinf_index - 1)) == sc_denom) {
4328  // Add the constraint `v - pos_pinf_index <= pos_sum'.
4329  dbm[pos_pinf_index][v] = pos_sum;
4330  }
4331  }
4332 
4333  // Exploit the lower approximation, if possible.
4334  if (neg_pinf_count <= 1) {
4335  // Compute quotient (if needed).
4336  if (sc_denom != 1) {
4337  // Before computing quotients, the denominator should be approximated
4338  // towards zero. Since `sc_denom' is known to be positive, this amounts to
4339  // rounding downwards, which is achieved as usual by rounding upwards
4340  // `minus_sc_denom' and negating again the result.
4341  PPL_DIRTY_TEMP(N, down_sc_denom);
4342  assign_r(down_sc_denom, minus_sc_denom, ROUND_UP);
4343  neg_assign_r(down_sc_denom, down_sc_denom, ROUND_UP);
4344  div_assign_r(neg_sum, neg_sum, down_sc_denom, ROUND_UP);
4345  }
4346  // Add the lower bound constraint, if meaningful.
4347  if (neg_pinf_count == 0) {
4348  // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'.
4349  DB_Row<N>& dbm_v = dbm[v];
4350  dbm_v[0] = neg_sum;
4351  // Deduce constraints of the form `u - v', where `u != v'.
4352  deduce_u_minus_v_bounds(v, w, sc_expr, sc_denom, neg_sum);
4353  }
4354  // Here `neg_pinf_count == 1'.
4355  else if (neg_pinf_index != v
4356  && sc_expr.get(Variable(neg_pinf_index - 1)) == sc_denom) {
4357  // Add the constraint `v - neg_pinf_index >= -neg_sum',
4358  // i.e., `neg_pinf_index - v <= neg_sum'.
4359  dbm[v][neg_pinf_index] = neg_sum;
4360  }
4361  }
4362 
4363  PPL_ASSERT(OK());
4364 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
void deduce_u_minus_v_bounds(dimension_type v, dimension_type last_v, const Linear_Expression &sc_expr, Coefficient_traits::const_reference sc_denom, const N &minus_lb_v)
An helper function for the computation of affine relations.
void swap(CO_Tree &x, CO_Tree &y)
size_t dimension_type
An unsigned integral type for representing space dimensions.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
bool marked_shortest_path_reduced() const
Returns true if the system of bounded differences is known to be shortest-path reduced.
Enable_If< Is_Native_Or_Checked< T >::value, void >::type div_round_up(T &to, Coefficient_traits::const_reference x, Coefficient_traits::const_reference y)
Divides x by y into to, rounding the result towards plus infinity.
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
void reset_shortest_path_closed()
Marks *this as possibly not shortest-path closed.
void add_dbm_constraint(dimension_type i, dimension_type j, const N &k)
Adds the constraint dbm[i][j] <= k.
void swap(BD_Shape< T > &x, BD_Shape< T > &y)
Swaps x with y.
static void throw_invalid_argument(const char *method, const char *reason)
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
void deduce_v_minus_u_bounds(dimension_type v, dimension_type last_v, const Linear_Expression &sc_expr, Coefficient_traits::const_reference sc_denom, const N &ub_v)
An helper function for the computation of affine relations.
#define PPL_DIRTY_TEMP(T, id)
bool OK() const
Returns true if and only if *this satisfies all its invariants.
void forget_binary_dbm_constraints(dimension_type v)
Removes all binary constraints on row/column v.
void neg_assign(GMP_Integer &x)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
int sgn(Boundary_Type type, const T &x, const Info &info)
void forget_all_dbm_constraints(dimension_type v)
Removes all the constraints on row/column v.
Coefficient c
Definition: PIP_Tree.cc:64
void reset_shortest_path_reduced()
Marks *this as possibly not shortest-path reduced.
#define PPL_UNINITIALIZED(type, name)
Definition: compiler.hh:72
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::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.

Parameters
varThe variable to which the affine expression is substituted.
exprThe numerator of the affine expression.
denominatorThe denominator of the affine expression.
Exceptions
std::invalid_argumentThrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a dimension of *this.

Definition at line 5132 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::Linear_Expression::all_zeroes(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Linear_Expression::get(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::inverse(), Parma_Polyhedra_Library::Linear_Expression::last_nonzero(), Parma_Polyhedra_Library::Variable::space_dimension(), and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

5134  {
5135  // The denominator cannot be zero.
5136  if (denominator == 0) {
5137  throw_invalid_argument("affine_preimage(v, e, d)", "d == 0");
5138  }
5139  // Dimension-compatibility checks.
5140  // The dimension of `expr' should not be greater than the dimension
5141  // of `*this'.
5142  const dimension_type space_dim = space_dimension();
5143  const dimension_type expr_space_dim = expr.space_dimension();
5144  if (space_dim < expr_space_dim) {
5145  throw_dimension_incompatible("affine_preimage(v, e, d)", "e", expr);
5146  }
5147  // `var' should be one of the dimensions of
5148  // the bounded difference shapes.
5149  const dimension_type v = var.id() + 1;
5150  if (v > space_dim) {
5151  throw_dimension_incompatible("affine_preimage(v, e, d)", var.id());
5152  }
5153  // The image of an empty BDS is empty too.
5155  if (marked_empty()) {
5156  return;
5157  }
5158  const Coefficient& b = expr.inhomogeneous_term();
5159  // Number of non-zero coefficients in `expr': will be set to
5160  // 0, 1, or 2, the latter value meaning any value greater than 1.
5161  dimension_type t = 0;
5162  // Index of the last non-zero coefficient in `expr', if any.
5163  dimension_type j = expr.last_nonzero();
5164 
5165  if (j != 0) {
5166  ++t;
5167  if (!expr.all_zeroes(1, j)) {
5168  ++t;
5169  }
5170  }
5171 
5172  // Now we know the form of `expr':
5173  // - If t == 0, then expr = b, with `b' a constant;
5174  // - If t == 1, then expr = a*w + b, where `w' can be `v' or another
5175  // variable; in this second case we have to check whether `a' is
5176  // equal to `denominator' or `-denominator', since otherwise we have
5177  // to fall back on the general form;
5178  // - If t > 1, the `expr' is of the general form.
5179  if (t == 0) {
5180  // Case 1: expr = n; remove all constraints on `var'.
5182  // Shortest-path closure is preserved, but not reduction.
5185  }
5186  PPL_ASSERT(OK());
5187  return;
5188  }
5189 
5190  if (t == 1) {
5191  // Value of the one and only non-zero coefficient in `expr'.
5192  const Coefficient& a = expr.get(Variable(j - 1));
5193  if (a == denominator || a == -denominator) {
5194  // Case 2: expr = a*w + b, with a = +/- denominator.
5195  if (j == var.space_dimension()) {
5196  // Apply affine_image() on the inverse of this transformation.
5197  affine_image(var, denominator*var - b, a);
5198  }
5199  else {
5200  // `expr == a*w + b', where `w != v'.
5201  // Remove all constraints on `var'.
5203  // Shortest-path closure is preserved, but not reduction.
5206  }
5207  PPL_ASSERT(OK());
5208  }
5209  return;
5210  }
5211  }
5212 
5213  // General case.
5214  // Either t == 2, so that
5215  // expr = a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
5216  // or t = 1, expr = a*w + b, but a <> +/- denominator.
5217  const Coefficient& expr_v = expr.coefficient(var);
5218  if (expr_v != 0) {
5219  // The transformation is invertible.
5220  Linear_Expression inverse((expr_v + denominator)*var);
5221  inverse -= expr;
5222  affine_image(var, inverse, expr_v);
5223  }
5224  else {
5225  // Transformation not invertible: all constraints on `var' are lost.
5227  // Shortest-path closure is preserved, but not reduction.
5230  }
5231  }
5232  PPL_ASSERT(OK());
5233 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
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 ex...
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
bool marked_shortest_path_reduced() const
Returns true if the system of bounded differences is known to be shortest-path reduced.
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
Rounding_Dir inverse(Rounding_Dir dir)
static void throw_invalid_argument(const char *method, const char *reason)
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void forget_all_dbm_constraints(dimension_type v)
Removes all the constraints on row/column v.
void reset_shortest_path_reduced()
Marks *this as possibly not shortest-path reduced.
template<typename T>
void Parma_Polyhedra_Library::BD_Shape< T >::ascii_dump ( ) const

Writes to std::cerr an ASCII representation of *this.

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::ascii_dump ( std::ostream &  s) const

Writes to s an ASCII representation of *this.

Definition at line 6848 of file BD_Shape_templates.hh.

6848  {
6849  status.ascii_dump(s);
6850  s << "\n";
6851  dbm.ascii_dump(s);
6852  s << "\n";
6854 }
void ascii_dump() const
Writes to std::cerr an ASCII representation of *this.
Bit_Matrix redundancy_dbm
A matrix indicating which constraints are redundant.
Status status
The status flags to keep track of the internal state.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
void ascii_dump() const
Writes to std::cerr an ASCII representation of *this.
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::ascii_load ( std::istream &  s)

Loads from s an ASCII representation (as produced by ascii_dump(std::ostream&) const) and sets *this accordingly. Returns true if successful, false otherwise.

Definition at line 6860 of file BD_Shape_templates.hh.

6860  {
6861  if (!status.ascii_load(s)) {
6862  return false;
6863  }
6864  if (!dbm.ascii_load(s)) {
6865  return false;
6866  }
6867  if (!redundancy_dbm.ascii_load(s)) {
6868  return false;
6869  }
6870  return true;
6871 }
bool ascii_load(std::istream &s)
Loads from s an ASCII representation (as produced by ascii_dump(std::ostream&) const) and sets *this ...
Definition: Bit_Matrix.cc:189
bool ascii_load(std::istream &s)
Loads from s an ASCII representation (as produced by ascii_dump(std::ostream&) const) and sets *this ...
Bit_Matrix redundancy_dbm
A matrix indicating which constraints are redundant.
Status status
The status flags to keep track of the internal state.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::BFT00_upper_bound_assign_if_exact ( const BD_Shape< T > &  y)
private

If the upper bound of *this and y is exact it is assigned to *this and true is returned, otherwise false is returned.

Current implementation is based on a variant of Algorithm 4.1 in A. Bemporad, K. Fukuda, and F. D. Torrisi Convexity Recognition of the Union of Polyhedra Technical Report AUT00-13, ETH Zurich, 2000 tailored to the special case of BD shapes.

Note
It is assumed that *this and y are dimension-compatible; if the assumption does not hold, the behavior is undefined.

Definition at line 2194 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::MIP_Problem::add_constraint(), Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::Constraint_System::empty(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::numer_denom(), Parma_Polyhedra_Library::MIP_Problem::optimal_value(), Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm, Parma_Polyhedra_Library::Linear_Expression::set_space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign(), Parma_Polyhedra_Library::MIP_Problem::solve(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::UNBOUNDED_MIP_PROBLEM, Parma_Polyhedra_Library::UNFEASIBLE_MIP_PROBLEM, and Parma_Polyhedra_Library::upper_bound_assign().

2194  {
2195  // Declare a const reference to *this (to avoid accidental modifications).
2196  const BD_Shape& x = *this;
2197  const dimension_type x_space_dim = x.space_dimension();
2198 
2199  // Private method: the caller must ensure the following.
2200  PPL_ASSERT(x_space_dim == y.space_dimension());
2201 
2202  // The zero-dim case is trivial.
2203  if (x_space_dim == 0) {
2204  upper_bound_assign(y);
2205  return true;
2206  }
2207  // If `x' or `y' is (known to be) empty, the upper bound is exact.
2208  if (x.marked_empty()) {
2209  *this = y;
2210  return true;
2211  }
2212  else if (y.is_empty()) {
2213  return true;
2214  }
2215  else if (x.is_empty()) {
2216  *this = y;
2217  return true;
2218  }
2219 
2220  // Here both `x' and `y' are known to be non-empty.
2221  // Implementation based on Algorithm 4.1 (page 6) in [BemporadFT00TR],
2222  // tailored to the special case of BD shapes.
2223 
2224  Variable epsilon(x_space_dim);
2225  Linear_Expression zero_expr;
2226  zero_expr.set_space_dimension(x_space_dim + 1);
2227  Linear_Expression db_expr;
2230 
2231  // Step 1: compute the constraint system for the envelope env(x,y)
2232  // and put into x_cs_removed and y_cs_removed those non-redundant
2233  // constraints that are not in the constraint system for env(x,y).
2234  // While at it, also add the additional space dimension (epsilon).
2235  Constraint_System env_cs;
2236  Constraint_System x_cs_removed;
2237  Constraint_System y_cs_removed;
2238  x.shortest_path_reduction_assign();
2239  y.shortest_path_reduction_assign();
2240  for (dimension_type i = x_space_dim + 1; i-- > 0; ) {
2241  const Bit_Row& x_red_i = x.redundancy_dbm[i];
2242  const Bit_Row& y_red_i = y.redundancy_dbm[i];
2243  const DB_Row<N>& x_dbm_i = x.dbm[i];
2244  const DB_Row<N>& y_dbm_i = y.dbm[i];
2245  for (dimension_type j = x_space_dim + 1; j-- > 0; ) {
2246  if (x_red_i[j] && y_red_i[j]) {
2247  continue;
2248  }
2249  if (!x_red_i[j]) {
2250  const N& x_dbm_ij = x_dbm_i[j];
2251  PPL_ASSERT(!is_plus_infinity(x_dbm_ij));
2252  numer_denom(x_dbm_ij, numer, denom);
2253  // Build skeleton DB constraint (having the right space dimension).
2254  db_expr = zero_expr;
2255  if (i > 0) {
2256  db_expr += Variable(i-1);
2257  }
2258  if (j > 0) {
2259  db_expr -= Variable(j-1);
2260  }
2261  if (denom != 1) {
2262  db_expr *= denom;
2263  }
2264  db_expr += numer;
2265  if (x_dbm_ij >= y_dbm_i[j]) {
2266  env_cs.insert(db_expr >= 0);
2267  }
2268  else {
2269  db_expr += epsilon;
2270  x_cs_removed.insert(db_expr == 0);
2271  }
2272  }
2273  if (!y_red_i[j]) {
2274  const N& y_dbm_ij = y_dbm_i[j];
2275  const N& x_dbm_ij = x_dbm_i[j];
2276  PPL_ASSERT(!is_plus_infinity(y_dbm_ij));
2277  numer_denom(y_dbm_ij, numer, denom);
2278  // Build skeleton DB constraint (having the right space dimension).
2279  db_expr = zero_expr;
2280  if (i > 0) {
2281  db_expr += Variable(i-1);
2282  }
2283  if (j > 0) {
2284  db_expr -= Variable(j-1);
2285  }
2286  if (denom != 1) {
2287  db_expr *= denom;
2288  }
2289  db_expr += numer;
2290  if (y_dbm_ij >= x_dbm_ij) {
2291  // Check if same constraint was added when considering x_dbm_ij.
2292  if (!x_red_i[j] && x_dbm_ij == y_dbm_ij) {
2293  continue;
2294  }
2295  env_cs.insert(db_expr >= 0);
2296  }
2297  else {
2298  db_expr += epsilon;
2299  y_cs_removed.insert(db_expr == 0);
2300  }
2301  }
2302  }
2303  }
2304 
2305  if (x_cs_removed.empty()) {
2306  // No constraint of x was removed: y is included in x.
2307  return true;
2308  }
2309  if (y_cs_removed.empty()) {
2310  // No constraint of y was removed: x is included in y.
2311  *this = y;
2312  return true;
2313  }
2314 
2315  // In preparation to Step 4: build the common part of LP problems,
2316  // i.e., the constraints corresponding to env(x,y),
2317  // where the additional space dimension (epsilon) has to be maximized.
2318  MIP_Problem env_lp(x_space_dim + 1, env_cs, epsilon, MAXIMIZATION);
2319  // Pre-solve `env_lp' to later exploit incrementality.
2320  env_lp.solve();
2321  PPL_ASSERT(env_lp.solve() != UNFEASIBLE_MIP_PROBLEM);
2322 
2323  // Implementing loop in Steps 3-6.
2324  for (Constraint_System::const_iterator i = x_cs_removed.begin(),
2325  i_end = x_cs_removed.end(); i != i_end; ++i) {
2326  MIP_Problem lp_i(env_lp);
2327  lp_i.add_constraint(*i);
2328  // Pre-solve to exploit incrementality.
2329  if (lp_i.solve() == UNFEASIBLE_MIP_PROBLEM) {
2330  continue;
2331  }
2332  for (Constraint_System::const_iterator j = y_cs_removed.begin(),
2333  j_end = y_cs_removed.end(); j != j_end; ++j) {
2334  MIP_Problem lp_ij(lp_i);
2335  lp_ij.add_constraint(*j);
2336  // Solve and check for a positive optimal value.
2337  switch (lp_ij.solve()) {
2339  // CHECKME: is the following actually impossible?
2340  PPL_UNREACHABLE;
2341  return false;
2342  case UNBOUNDED_MIP_PROBLEM:
2343  return false;
2344  case OPTIMIZED_MIP_PROBLEM:
2345  lp_ij.optimal_value(numer, denom);
2346  if (numer > 0) {
2347  return false;
2348  }
2349  break;
2350  }
2351  }
2352  }
2353 
2354  // The upper bound of x and y is indeed exact.
2355  upper_bound_assign(y);
2356  PPL_ASSERT(OK());
2357  return true;
2358 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
Enable_If< Is_Native_Or_Checked< T >::value, void >::type numer_denom(const T &from, Coefficient &numer, Coefficient &denom)
Extract the numerator and denominator components of from.
void upper_bound_assign(const BD_Shape &y)
Assigns to *this the smallest BDS containing the union of *this and y.
BD_Shape(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty BDS of the specified space dimension.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
bool OK() const
Returns true if and only if *this satisfies all its invariants.
Maximization is requested.
The problem has an optimal solution.
Constraint_System_const_iterator const_iterator
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign ( const BD_Shape< T > &  y,
unsigned *  tp = 0 
)

Assigns to *this the result of computing the BHMZ05-widening of *this and y.

Parameters
yA BDS that must be contained in *this.
tpAn optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique).
Exceptions
std::invalid_argumentThrown if *this and y are dimension-incompatible.

Definition at line 3245 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::affine_dimension(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign().

3245  {
3246  const dimension_type space_dim = space_dimension();
3247 
3248  // Dimension-compatibility check.
3249  if (space_dim != y.space_dimension()) {
3250  throw_dimension_incompatible("BHMZ05_widening_assign(y)", y);
3251  }
3252  // We assume that `y' is contained in or equal to `*this'.
3253  PPL_EXPECT_HEAVY(copy_contains(*this, y));
3254 
3255  // Compute the affine dimension of `y'.
3256  const dimension_type y_affine_dim = y.affine_dimension();
3257  // If the affine dimension of `y' is zero, then either `y' is
3258  // zero-dimensional, or it is empty, or it is a singleton.
3259  // In all cases, due to the inclusion hypothesis, the result is `*this'.
3260  if (y_affine_dim == 0) {
3261  return;
3262  }
3263  // If the affine dimension has changed, due to the inclusion hypothesis,
3264  // the result is `*this'.
3265  const dimension_type x_affine_dim = affine_dimension();
3266  PPL_ASSERT(x_affine_dim >= y_affine_dim);
3267  if (x_affine_dim != y_affine_dim) {
3268  return;
3269  }
3270  // If there are tokens available, work on a temporary copy.
3271  if (tp != 0 && *tp > 0) {
3272  BD_Shape<T> x_tmp(*this);
3273  x_tmp.BHMZ05_widening_assign(y, 0);
3274  // If the widening was not precise, use one of the available tokens.
3275  if (!contains(x_tmp)) {
3276  --(*tp);
3277  }
3278  return;
3279  }
3280 
3281  // Here no token is available.
3282  PPL_ASSERT(marked_shortest_path_closed() && y.marked_shortest_path_closed());
3283  // Minimize `y'.
3284  y.shortest_path_reduction_assign();
3285 
3286  // Extrapolate unstable bounds, taking into account redundancy in `y'.
3287  for (dimension_type i = space_dim + 1; i-- > 0; ) {
3288  DB_Row<N>& dbm_i = dbm[i];
3289  const DB_Row<N>& y_dbm_i = y.dbm[i];
3290  const Bit_Row& y_redundancy_i = y.redundancy_dbm[i];
3291  for (dimension_type j = space_dim + 1; j-- > 0; ) {
3292  N& dbm_ij = dbm_i[j];
3293  // Note: in the following line the use of `!=' (as opposed to
3294  // the use of `<' that would seem -but is not- equivalent) is
3295  // intentional.
3296  if (y_redundancy_i[j] || y_dbm_i[j] != dbm_ij) {
3298  }
3299  }
3300  }
3301  // NOTE: this will also reset the shortest-path reduction flag,
3302  // even though the dbm is still in reduced form. However, the
3303  // current implementation invariant requires that any reduced dbm
3304  // is closed too.
3306  PPL_ASSERT(OK());
3307 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
size_t dimension_type
An unsigned integral type for representing space dimensions.
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
bool marked_shortest_path_closed() const
Returns true if the system of bounded differences is known to be shortest-path closed.
void reset_shortest_path_closed()
Marks *this as possibly not shortest-path closed.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
Plus_Infinity PLUS_INFINITY
Definition: checked.cc:31
bool contains(const BD_Shape &y) const
Returns true if and only if *this contains y.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
dimension_type affine_dimension() const
Returns , if *this is empty; otherwise, returns the affine dimension of *this.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
template<bool integer_upper_bound>
bool Parma_Polyhedra_Library::BD_Shape< T >::BHZ09_upper_bound_assign_if_exact ( const BD_Shape< T > &  y)
private

If the upper bound of *this and y is exact it is assigned to *this and true is returned, otherwise false is returned.

Implementation for the rational (resp., integer) case is based on Theorem 5.2 (resp. Theorem 5.3) of [BHZ09b]. The Boolean template parameter integer_upper_bound allows for choosing between the rational and integer upper bound algorithms.

Note
It is assumed that *this and y are dimension-compatible; if the assumption does not hold, the behavior is undefined.
The integer case is only enabled if T is an integer data type.

Definition at line 2363 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), PPL_COMPILE_TIME_CHECK, PPL_DIRTY_TEMP, Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::ROUND_UP, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::upper_bound_assign().

2363  {
2364  PPL_COMPILE_TIME_CHECK(!integer_upper_bound
2366  "BD_Shape<T>::BHZ09_upper_bound_assign_if_exact(y):"
2367  " instantiating for integer upper bound,"
2368  " but T in not an integer datatype.");
2369 
2370  // FIXME, CHECKME: what about inexact computations?
2371  // Declare a const reference to *this (to avoid accidental modifications).
2372  const BD_Shape& x = *this;
2373  const dimension_type x_space_dim = x.space_dimension();
2374 
2375  // Private method: the caller must ensure the following.
2376  PPL_ASSERT(x_space_dim == y.space_dimension());
2377 
2378  // The zero-dim case is trivial.
2379  if (x_space_dim == 0) {
2380  upper_bound_assign(y);
2381  return true;
2382  }
2383  // If `x' or `y' is (known to be) empty, the upper bound is exact.
2384  if (x.marked_empty()) {
2385  *this = y;
2386  return true;
2387  }
2388  else if (y.is_empty()) {
2389  return true;
2390  }
2391  else if (x.is_empty()) {
2392  *this = y;
2393  return true;
2394  }
2395 
2396  // Here both `x' and `y' are known to be non-empty.
2397  x.shortest_path_reduction_assign();
2398  y.shortest_path_reduction_assign();
2399  PPL_ASSERT(x.marked_shortest_path_closed());
2400  PPL_ASSERT(y.marked_shortest_path_closed());
2401  // Pre-compute the upper bound of `x' and `y'.
2402  BD_Shape<T> ub(x);
2403  ub.upper_bound_assign(y);
2404 
2405  PPL_DIRTY_TEMP(N, lhs);
2406  PPL_DIRTY_TEMP(N, rhs);
2407  PPL_DIRTY_TEMP(N, temp_zero);
2408  assign_r(temp_zero, 0, ROUND_NOT_NEEDED);
2409  PPL_DIRTY_TEMP(N, temp_one);
2410  if (integer_upper_bound) {
2411  assign_r(temp_one, 1, ROUND_NOT_NEEDED);
2412  }
2413  for (dimension_type i = x_space_dim + 1; i-- > 0; ) {
2414  const DB_Row<N>& x_i = x.dbm[i];
2415  const Bit_Row& x_red_i = x.redundancy_dbm[i];
2416  const DB_Row<N>& y_i = y.dbm[i];
2417  const DB_Row<N>& ub_i = ub.dbm[i];
2418  for (dimension_type j = x_space_dim + 1; j-- > 0; ) {
2419  // Check redundancy of x_i_j.
2420  if (x_red_i[j]) {
2421  continue;
2422  }
2423  // By non-redundancy, we know that i != j.
2424  PPL_ASSERT(i != j);
2425  const N& x_i_j = x_i[j];
2426  if (x_i_j < y_i[j]) {
2427  for (dimension_type k = x_space_dim + 1; k-- > 0; ) {
2428  const DB_Row<N>& x_k = x.dbm[k];
2429  const DB_Row<N>& y_k = y.dbm[k];
2430  const Bit_Row& y_red_k = y.redundancy_dbm[k];
2431  const DB_Row<N>& ub_k = ub.dbm[k];
2432  const N& ub_k_j = (k == j) ? temp_zero : ub_k[j];
2433  for (dimension_type ell = x_space_dim + 1; ell-- > 0; ) {
2434  // Check redundancy of y_k_ell.
2435  if (y_red_k[ell]) {
2436  continue;
2437  }
2438  // By non-redundancy, we know that k != ell.
2439  PPL_ASSERT(k != ell);
2440  const N& y_k_ell = y_k[ell];
2441  if (y_k_ell < x_k[ell]) {
2442  // The first condition in BHZ09 theorem holds;
2443  // now check for the second condition.
2444  add_assign_r(lhs, x_i_j, y_k_ell, ROUND_UP);
2445  const N& ub_i_ell = (i == ell) ? temp_zero : ub_i[ell];
2446  add_assign_r(rhs, ub_i_ell, ub_k_j, ROUND_UP);
2447  if (integer_upper_bound) {
2448  // Note: adding 1 rather than 2 (as in Theorem 5.3)
2449  // so as to later test for < rather than <=.
2450  add_assign_r(lhs, lhs, temp_one, ROUND_NOT_NEEDED);
2451  }
2452  // Testing for < in both the rational and integer case.
2453  if (lhs < rhs) {
2454  return false;
2455  }
2456  }
2457  }
2458  }
2459  }
2460  }
2461  }
2462  // The upper bound of x and y is indeed exact.
2463  m_swap(ub);
2464  PPL_ASSERT(OK());
2465  return true;
2466 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
size_t dimension_type
An unsigned integral type for representing space dimensions.
void upper_bound_assign(const BD_Shape &y)
Assigns to *this the smallest BDS containing the union of *this and y.
BD_Shape(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty BDS of the specified space dimension.
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
void m_swap(BD_Shape &y)
Swaps *this with y (*this and y can be dimension-incompatible).
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_integer(const T &x)
#define PPL_COMPILE_TIME_CHECK(e, msg)
Produces a compilation error if the compile-time constant e does not evaluate to true ...
#define PPL_DIRTY_TEMP(T, id)
bool OK() const
Returns true if and only if *this satisfies all its invariants.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::bounded_affine_image ( Variable  var,
const Linear_Expression lb_expr,
const Linear_Expression ub_expr,
Coefficient_traits::const_reference  denominator = Coefficient_one() 
)

Assigns to *this the image of *this with respect to the bounded affine relation $\frac{\mathrm{lb\_expr}}{\mathrm{denominator}} \leq \mathrm{var}' \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}$.

Parameters
varThe variable updated by the affine relation;
lb_exprThe numerator of the lower bounding affine expression;
ub_exprThe numerator of the upper bounding affine expression;
denominatorThe (common) denominator for the lower and upper bounding affine expressions (optional argument with default value 1).
Exceptions
std::invalid_argumentThrown 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 5238 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::Linear_Expression::all_zeroes(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::begin(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::Linear_Expression::get(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Linear_Expression::last_nonzero(), Parma_Polyhedra_Library::Linear_Expression::lower_bound(), Parma_Polyhedra_Library::neg_assign(), PPL_DIRTY_TEMP, PPL_DIRTY_TEMP_COEFFICIENT, PPL_UNINITIALIZED, Parma_Polyhedra_Library::ROUND_UP, Parma_Polyhedra_Library::Boundary_NS::sgn(), and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

5241  {
5242  // The denominator cannot be zero.
5243  if (denominator == 0) {
5244  throw_invalid_argument("bounded_affine_image(v, lb, ub, d)", "d == 0");
5245  }
5246  // Dimension-compatibility checks.
5247  // `var' should be one of the dimensions of the BD_Shape.
5248  const dimension_type bds_space_dim = space_dimension();
5249  const dimension_type v = var.id() + 1;
5250  if (v > bds_space_dim) {
5251  throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)",
5252  "v", var);
5253  }
5254  // The dimension of `lb_expr' and `ub_expr' should not be
5255  // greater than the dimension of `*this'.
5256  const dimension_type lb_space_dim = lb_expr.space_dimension();
5257  if (bds_space_dim < lb_space_dim) {
5258  throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)",
5259  "lb", lb_expr);
5260  }
5261  const dimension_type ub_space_dim = ub_expr.space_dimension();
5262  if (bds_space_dim < ub_space_dim) {
5263  throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)",
5264  "ub", ub_expr);
5265  }
5266  // Any image of an empty BDS is empty.
5268  if (marked_empty()) {
5269  return;
5270  }
5271  const Coefficient& b = ub_expr.inhomogeneous_term();
5272  // Number of non-zero coefficients in `ub_expr': will be set to
5273  // 0, 1, or 2, the latter value meaning any value greater than 1.
5274  dimension_type t = 0;
5275  // Index of the last non-zero coefficient in `ub_expr', if any.
5276  dimension_type w = ub_expr.last_nonzero();
5277 
5278  if (w != 0) {
5279  ++t;
5280  if (!ub_expr.all_zeroes(1, w)) {
5281  ++t;
5282  }
5283  }
5284 
5285  // Now we know the form of `ub_expr':
5286  // - If t == 0, then ub_expr == b, with `b' a constant;
5287  // - If t == 1, then ub_expr == a*w + b, where `w' can be `v' or another
5288  // variable; in this second case we have to check whether `a' is
5289  // equal to `denominator' or `-denominator', since otherwise we have
5290  // to fall back on the general form;
5291  // - If t == 2, the `ub_expr' is of the general form.
5292  PPL_DIRTY_TEMP_COEFFICIENT(minus_denom);
5293  neg_assign(minus_denom, denominator);
5294 
5295  if (t == 0) {
5296  // Case 1: ub_expr == b.
5299  lb_expr,
5300  denominator);
5301  // Add the constraint `var <= b/denominator'.
5302  add_dbm_constraint(0, v, b, denominator);
5303  PPL_ASSERT(OK());
5304  return;
5305  }
5306 
5307  if (t == 1) {
5308  // Value of the one and only non-zero coefficient in `ub_expr'.
5309  const Coefficient& a = ub_expr.get(Variable(w - 1));
5310  if (a == denominator || a == minus_denom) {
5311  // Case 2: expr == a*w + b, with a == +/- denominator.
5312  if (w == v) {
5313  // Here `var' occurs in `ub_expr'.
5314  // To ease the computation, we add an additional dimension.
5315  const Variable new_var(bds_space_dim);
5317  // Constrain the new dimension to be equal to `ub_expr'.
5318  affine_image(new_var, ub_expr, denominator);
5319  // NOTE: enforce shortest-path closure for precision.
5321  PPL_ASSERT(!marked_empty());
5322  // Apply the affine lower bound.
5325  lb_expr,
5326  denominator);
5327  // Now apply the affine upper bound, as recorded in `new_var'.
5328  add_constraint(var <= new_var);
5329  // Remove the temporarily added dimension.
5330  remove_higher_space_dimensions(bds_space_dim);
5331  return;
5332  }
5333  else {
5334  // Here `w != v', so that `expr' is of the form
5335  // +/-denominator * w + b.
5336  // Apply the affine lower bound.
5339  lb_expr,
5340  denominator);
5341  if (a == denominator) {
5342  // Add the new constraint `v - w == b/denominator'.
5343  add_dbm_constraint(w, v, b, denominator);
5344  }
5345  else {
5346  // Here a == -denominator, so that we should be adding
5347  // the constraint `v + w == b/denominator'.
5348  // Approximate it by computing lower and upper bounds for `w'.
5349  const N& dbm_w0 = dbm[w][0];
5350  if (!is_plus_infinity(dbm_w0)) {
5351  // Add the constraint `v <= b/denominator - lower_w'.
5352  PPL_DIRTY_TEMP(N, d);
5353  div_round_up(d, b, denominator);
5354  add_assign_r(dbm[0][v], d, dbm_w0, ROUND_UP);
5356  }
5357  }
5358  PPL_ASSERT(OK());
5359  return;
5360  }
5361  }
5362  }
5363 
5364  // General case.
5365  // Either t == 2, so that
5366  // ub_expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
5367  // or t == 1, ub_expr == a*w + b, but a <> +/- denominator.
5368  // We will remove all the constraints on `var' and add back
5369  // constraints providing upper and lower bounds for `var'.
5370 
5371  // Compute upper approximations for `ub_expr' into `pos_sum'
5372  // taking into account the sign of `denominator'.
5373  const bool is_sc = (denominator > 0);
5374  PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
5375  neg_assign(minus_b, b);
5376  const Coefficient& sc_b = is_sc ? b : minus_b;
5377  const Coefficient& sc_denom = is_sc ? denominator : minus_denom;
5378  const Coefficient& minus_sc_denom = is_sc ? minus_denom : denominator;
5379  // NOTE: here, for optimization purposes, `minus_expr' is only assigned
5380  // when `denominator' is negative. Do not use it unless you are sure
5381  // it has been correctly assigned.
5382  Linear_Expression minus_expr;
5383  if (!is_sc) {
5384  minus_expr = -ub_expr;
5385  }
5386  const Linear_Expression& sc_expr = is_sc ? ub_expr : minus_expr;
5387 
5388  PPL_DIRTY_TEMP(N, pos_sum);
5389  // Index of the variable that are unbounded in `this->dbm'.
5390  PPL_UNINITIALIZED(dimension_type, pos_pinf_index);
5391  // Number of unbounded variables found.
5392  dimension_type pos_pinf_count = 0;
5393 
5394  // Approximate the inhomogeneous term.
5395  assign_r(pos_sum, sc_b, ROUND_UP);
5396 
5397  // Approximate the homogeneous part of `sc_expr'.
5398  const DB_Row<N>& dbm_0 = dbm[0];
5399  // Speculative allocation of temporaries to be used in the following loop.
5400  PPL_DIRTY_TEMP(N, coeff_i);
5401  PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
5402  // Note: indices above `w' can be disregarded, as they all have
5403  // a zero coefficient in `sc_expr'.
5404  for (Linear_Expression::const_iterator i = sc_expr.begin(),
5405  i_end = sc_expr.lower_bound(Variable(w)); i != i_end; ++i) {
5406  const Coefficient& sc_i = *i;
5407  const dimension_type i_dim = i.variable().space_dimension();
5408  const int sign_i = sgn(sc_i);
5409  if (sign_i > 0) {
5410  assign_r(coeff_i, sc_i, ROUND_UP);
5411  // Approximating `sc_expr'.
5412  if (pos_pinf_count <= 1) {
5413  const N& up_approx_i = dbm_0[i_dim];
5414  if (!is_plus_infinity(up_approx_i)) {
5415  add_mul_assign_r(pos_sum, coeff_i, up_approx_i, ROUND_UP);
5416  }
5417  else {
5418  ++pos_pinf_count;
5419  pos_pinf_index = i_dim;
5420  }
5421  }
5422  }
5423  else {
5424  PPL_ASSERT(sign_i < 0);
5425  neg_assign(minus_sc_i, sc_i);
5426  // Note: using temporary named `coeff_i' to store -coeff_i.
5427  assign_r(coeff_i, minus_sc_i, ROUND_UP);
5428  // Approximating `sc_expr'.
5429  if (pos_pinf_count <= 1) {
5430  const N& up_approx_minus_i = dbm[i_dim][0];
5431  if (!is_plus_infinity(up_approx_minus_i)) {
5432  add_mul_assign_r(pos_sum, coeff_i, up_approx_minus_i, ROUND_UP);
5433  }
5434  else {
5435  ++pos_pinf_count;
5436  pos_pinf_index = i_dim;
5437  }
5438  }
5439  }
5440  }
5441  // Apply the affine lower bound.
5444  lb_expr,
5445  denominator);
5446  // Return immediately if no approximation could be computed.
5447  if (pos_pinf_count > 1) {
5448  return;
5449  }
5450 
5451  // In the following, shortest-path closure will be definitely lost.
5453 
5454  // Exploit the upper approximation, if possible.
5455  if (pos_pinf_count <= 1) {
5456  // Compute quotient (if needed).
5457  if (sc_denom != 1) {
5458  // Before computing quotients, the denominator should be approximated
5459  // towards zero. Since `sc_denom' is known to be positive, this amounts to
5460  // rounding downwards, which is achieved as usual by rounding upwards
5461  // `minus_sc_denom' and negating again the result.
5462  PPL_DIRTY_TEMP(N, down_sc_denom);
5463  assign_r(down_sc_denom, minus_sc_denom, ROUND_UP);
5464  neg_assign_r(down_sc_denom, down_sc_denom, ROUND_UP);
5465  div_assign_r(pos_sum, pos_sum, down_sc_denom, ROUND_UP);
5466  }
5467  // Add the upper bound constraint, if meaningful.
5468  if (pos_pinf_count == 0) {
5469  // Add the constraint `v <= pos_sum'.
5470  dbm[0][v] = pos_sum;
5471  // Deduce constraints of the form `v - u', where `u != v'.
5472  deduce_v_minus_u_bounds(v, w, sc_expr, sc_denom, pos_sum);
5473  }
5474  // Here `pos_pinf_count == 1'.
5475  else if (pos_pinf_index != v
5476  && sc_expr.get(Variable(pos_pinf_index - 1)) == sc_denom) {
5477  // Add the constraint `v - pos_pinf_index <= pos_sum'.
5478  dbm[pos_pinf_index][v] = pos_sum;
5479  }
5480  }
5481  PPL_ASSERT(OK());
5482 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
size_t dimension_type
An unsigned integral type for representing space dimensions.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
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 ex...
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
void add_constraint(const Constraint &c)
Adds a copy of constraint c to the system of bounded differences defining *this.
void generalized_affine_image(Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
Assigns to *this the image of *this with respect to the affine relation , where is the relation symb...
Enable_If< Is_Native_Or_Checked< T >::value, void >::type div_round_up(T &to, Coefficient_traits::const_reference x, Coefficient_traits::const_reference y)
Divides x by y into to, rounding the result towards plus infinity.
void add_space_dimensions_and_embed(dimension_type m)
Adds m new dimensions and embeds the old BDS into the new space.
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
void reset_shortest_path_closed()
Marks *this as possibly not shortest-path closed.
void add_dbm_constraint(dimension_type i, dimension_type j, const N &k)
Adds the constraint dbm[i][j] <= k.
static void throw_invalid_argument(const char *method, const char *reason)
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
void deduce_v_minus_u_bounds(dimension_type v, dimension_type last_v, const Linear_Expression &sc_expr, Coefficient_traits::const_reference sc_denom, const N &ub_v)
An helper function for the computation of affine relations.
#define PPL_DIRTY_TEMP(T, id)
bool OK() const
Returns true if and only if *this satisfies all its invariants.
void neg_assign(GMP_Integer &x)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
int sgn(Boundary_Type type, const T &x, const Info &info)
void remove_higher_space_dimensions(dimension_type new_dimension)
Removes the higher dimensions so that the resulting space will have dimension new_dimension.
#define PPL_UNINITIALIZED(type, name)
Definition: compiler.hh:72
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::bounded_affine_preimage ( Variable  var,
const Linear_Expression lb_expr,
const Linear_Expression ub_expr,
Coefficient_traits::const_reference  denominator = Coefficient_one() 
)

Assigns to *this the preimage of *this with respect to the bounded affine relation $\frac{\mathrm{lb\_expr}}{\mathrm{denominator}} \leq \mathrm{var}' \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}$.

Parameters
varThe variable updated by the affine relation;
lb_exprThe numerator of the lower bounding affine expression;
ub_exprThe numerator of the upper bounding affine expression;
denominatorThe (common) denominator for the lower and upper bounding affine expressions (optional argument with default value 1).
Exceptions
std::invalid_argumentThrown 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 5487 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::neg_assign(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Boundary_NS::sgn(), and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

5490  {
5491  // The denominator cannot be zero.
5492  if (denominator == 0) {
5493  throw_invalid_argument("bounded_affine_preimage(v, lb, ub, d)", "d == 0");
5494  }
5495  // Dimension-compatibility checks.
5496  // `var' should be one of the dimensions of the BD_Shape.
5497  const dimension_type space_dim = space_dimension();
5498  const dimension_type v = var.id() + 1;
5499  if (v > space_dim) {
5500  throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
5501  "v", var);
5502  }
5503  // The dimension of `lb_expr' and `ub_expr' should not be
5504  // greater than the dimension of `*this'.
5505  const dimension_type lb_space_dim = lb_expr.space_dimension();
5506  if (space_dim < lb_space_dim) {
5507  throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
5508  "lb", lb_expr);
5509  }
5510  const dimension_type ub_space_dim = ub_expr.space_dimension();
5511  if (space_dim < ub_space_dim) {
5512  throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
5513  "ub", ub_expr);
5514  }
5515  // Any preimage of an empty BDS is empty.
5517  if (marked_empty()) {
5518  return;
5519  }
5520  if (ub_expr.coefficient(var) == 0) {
5521  refine(var, LESS_OR_EQUAL, ub_expr, denominator);
5523  lb_expr, denominator);
5524  return;
5525  }
5526  if (lb_expr.coefficient(var) == 0) {
5527  refine(var, GREATER_OR_EQUAL, lb_expr, denominator);
5529  ub_expr, denominator);
5530  return;
5531  }
5532 
5533  const Coefficient& lb_expr_v = lb_expr.coefficient(var);
5534  // Here `var' occurs in `lb_expr' and `ub_expr'.
5535  // To ease the computation, we add an additional dimension.
5536  const Variable new_var(space_dim);
5538  const Linear_Expression lb_inverse
5539  = lb_expr - (lb_expr_v + denominator)*var;
5540  PPL_DIRTY_TEMP_COEFFICIENT(lb_inverse_denom);
5541  neg_assign(lb_inverse_denom, lb_expr_v);
5542  affine_image(new_var, lb_inverse, lb_inverse_denom);
5544  PPL_ASSERT(!marked_empty());
5546  ub_expr, denominator);
5547  if (sgn(denominator) == sgn(lb_inverse_denom)) {
5548  add_constraint(var >= new_var);
5549  }
5550  else {
5551  add_constraint(var <= new_var);
5552  }
5553  // Remove the temporarily added dimension.
5554  remove_higher_space_dimensions(space_dim);
5555 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
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 ex...
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
void add_constraint(const Constraint &c)
Adds a copy of constraint c to the system of bounded differences defining *this.
void add_space_dimensions_and_embed(dimension_type m)
Adds m new dimensions and embeds the old BDS into the new space.
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
static void throw_invalid_argument(const char *method, const char *reason)
void generalized_affine_preimage(Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
Assigns to *this the preimage of *this with respect to the affine relation , where is the relation s...
void refine(Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
Adds to the BDS the constraint .
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
void neg_assign(GMP_Integer &x)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
int sgn(Boundary_Type type, const T &x, const Info &info)
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 T >
bool Parma_Polyhedra_Library::BD_Shape< T >::bounds ( const Linear_Expression expr,
bool  from_above 
) const
private

Checks if and how expr is bounded in *this.

Returns true if and only if from_above is true and expr is bounded from above in *this, or from_above is false and expr is bounded from below in *this.

Parameters
exprThe linear expression to test;
from_abovetrue if and only if the boundedness of interest is "from above".
Exceptions
std::invalid_argumentThrown if expr and *this are dimension-incompatible.

Definition at line 1202 of file BD_Shape_templates.hh.

References c, Parma_Polyhedra_Library::BD_Shape_Helpers::extract_bounded_difference(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::MINIMIZATION, Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::MIP_Problem::solve(), and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

1203  {
1204  // The dimension of `expr' should not be greater than the dimension
1205  // of `*this'.
1206  const dimension_type expr_space_dim = expr.space_dimension();
1207  const dimension_type space_dim = space_dimension();
1208  if (space_dim < expr_space_dim) {
1209  throw_dimension_incompatible((from_above
1210  ? "bounds_from_above(e)"
1211  : "bounds_from_below(e)"), "e", expr);
1212  }
1214  // A zero-dimensional or empty BDS bounds everything.
1215  if (space_dim == 0 || marked_empty()) {
1216  return true;
1217  }
1218  // The constraint `c' is used to check if `expr' is a difference
1219  // bounded and, in this case, to select the cell.
1220  const Constraint& c = from_above ? expr <= 0 : expr >= 0;
1221  dimension_type num_vars = 0;
1222  dimension_type i = 0;
1223  dimension_type j = 0;
1225  // Check if `c' is a BD constraint.
1226  if (BD_Shape_Helpers::extract_bounded_difference(c, num_vars, i, j, coeff)) {
1227  if (num_vars == 0) {
1228  // Dealing with a trivial constraint.
1229  return true;
1230  }
1231  // Select the cell to be checked.
1232  const N& x = (coeff < 0) ? dbm[i][j] : dbm[j][i];
1233  return !is_plus_infinity(x);
1234  }
1235  else {
1236  // Not a DB constraint: use the MIP solver.
1237  Optimization_Mode mode_bounds
1238  = from_above ? MAXIMIZATION : MINIMIZATION;
1239  MIP_Problem mip(space_dim, constraints(), expr, mode_bounds);
1240  // Problem is known to be feasible.
1241  return mip.solve() == OPTIMIZED_MIP_PROBLEM;
1242  }
1243 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
Minimization is requested.
Optimization_Mode
Possible optimization modes.
size_t dimension_type
An unsigned integral type for representing space dimensions.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
Constraint_System constraints() const
Returns a system of constraints defining *this.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
Maximization is requested.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
static bool extract_bounded_difference(const Constraint &c, dimension_type &c_num_vars, dimension_type &c_first_var, dimension_type &c_second_var, Coefficient &c_coeff)
Decodes the constraint c as a bounded difference.
Coefficient c
Definition: PIP_Tree.cc:64
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
The problem has an optimal solution.
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::bounds_from_above ( const Linear_Expression expr) const
inline

Returns true if and only if expr is bounded from above in *this.

Exceptions
std::invalid_argumentThrown if expr and *this are dimension-incompatible.

Definition at line 384 of file BD_Shape_inlines.hh.

384  {
385  return bounds(expr, true);
386 }
bool bounds(const Linear_Expression &expr, bool from_above) const
Checks if and how expr is bounded in *this.
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::bounds_from_below ( const Linear_Expression expr) const
inline

Returns true if and only if expr is bounded from below in *this.

Exceptions
std::invalid_argumentThrown if expr and *this are dimension-incompatible.

Definition at line 390 of file BD_Shape_inlines.hh.

390  {
391  return bounds(expr, false);
392 }
bool bounds(const Linear_Expression &expr, bool from_above) const
Checks if and how expr is bounded in *this.
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::can_recycle_congruence_systems ( )
inlinestatic

Returns false indicating that this domain cannot recycle congruences.

Definition at line 279 of file BD_Shape_inlines.hh.

279  {
280  return false;
281 }
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::can_recycle_constraint_systems ( )
inlinestatic

Returns false indicating that this domain cannot recycle constraints.

Definition at line 272 of file BD_Shape_inlines.hh.

272  {
273  return false;
274 }
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign ( const BD_Shape< T > &  y,
unsigned *  tp = 0 
)
inline

Assigns to *this the result of computing the CC76-extrapolation between *this and y.

Parameters
yA BDS that must be contained in *this.
tpAn optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique).
Exceptions
std::invalid_argumentThrown if *this and y are dimension-incompatible.

Definition at line 832 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::ROUND_UP.

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign().

832  {
833  static N stop_points[] = {
834  N(-2, ROUND_UP),
835  N(-1, ROUND_UP),
836  N( 0, ROUND_UP),
837  N( 1, ROUND_UP),
838  N( 2, ROUND_UP)
839  };
841  stop_points,
842  stop_points
843  + sizeof(stop_points)/sizeof(stop_points[0]),
844  tp);
845 }
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
void CC76_extrapolation_assign(const BD_Shape &y, unsigned *tp=0)
Assigns to *this the result of computing the CC76-extrapolation between *this and y...
template<typename T >
template<typename Iterator >
void Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign ( const BD_Shape< T > &  y,
Iterator  first,
Iterator  last,
unsigned *  tp = 0 
)

Assigns to *this the result of computing the CC76-extrapolation between *this and y.

Parameters
yA BDS that must be contained in *this.
firstAn iterator referencing the first stop-point.
lastAn iterator referencing one past the last stop-point.
tpAn optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique).
Exceptions
std::invalid_argumentThrown if *this and y are dimension-incompatible.

Definition at line 3062 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::ROUND_UP, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

3064  {
3065  const dimension_type space_dim = space_dimension();
3066 
3067  // Dimension-compatibility check.
3068  if (space_dim != y.space_dimension()) {
3069  throw_dimension_incompatible("CC76_extrapolation_assign(y)", y);
3070  }
3071  // We assume that `y' is contained in or equal to `*this'.
3072  PPL_EXPECT_HEAVY(copy_contains(*this, y));
3073 
3074  // If both bounded difference shapes are zero-dimensional,
3075  // since `*this' contains `y', we simply return `*this'.
3076  if (space_dim == 0) {
3077  return;
3078  }
3080  // If `*this' is empty, since `*this' contains `y', `y' is empty too.
3081  if (marked_empty()) {
3082  return;
3083  }
3084  y.shortest_path_closure_assign();
3085  // If `y' is empty, we return.
3086  if (y.marked_empty()) {
3087  return;
3088  }
3089  // If there are tokens available, work on a temporary copy.
3090  if (tp != 0 && *tp > 0) {
3091  BD_Shape<T> x_tmp(*this);
3092  x_tmp.CC76_extrapolation_assign(y, first, last, 0);
3093  // If the widening was not precise, use one of the available tokens.
3094  if (!contains(x_tmp)) {
3095  --(*tp);
3096  }
3097  return;
3098  }
3099 
3100  // Compare each constraint in `y' to the corresponding one in `*this'.
3101  // The constraint in `*this' is kept as is if it is stronger than or
3102  // equal to the constraint in `y'; otherwise, the inhomogeneous term
3103  // of the constraint in `*this' is further compared with elements taken
3104  // from a sorted container (the stop-points, provided by the user), and
3105  // is replaced by the first entry, if any, which is greater than or equal
3106  // to the inhomogeneous term. If no such entry exists, the constraint
3107  // is removed altogether.
3108  for (dimension_type i = space_dim + 1; i-- > 0; ) {
3109  DB_Row<N>& dbm_i = dbm[i];
3110  const DB_Row<N>& y_dbm_i = y.dbm[i];
3111  for (dimension_type j = space_dim + 1; j-- > 0; ) {
3112  N& dbm_ij = dbm_i[j];
3113  const N& y_dbm_ij = y_dbm_i[j];
3114  if (y_dbm_ij < dbm_ij) {
3115  Iterator k = std::lower_bound(first, last, dbm_ij);
3116  if (k != last) {
3117  if (dbm_ij < *k) {
3118  assign_r(dbm_ij, *k, ROUND_UP);
3119  }
3120  }
3121  else {
3123  }
3124  }
3125  }
3126  }
3128  PPL_ASSERT(OK());
3129 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
size_t dimension_type
An unsigned integral type for representing space dimensions.
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
void reset_shortest_path_closed()
Marks *this as possibly not shortest-path closed.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
Plus_Infinity PLUS_INFINITY
Definition: checked.cc:31
bool contains(const BD_Shape &y) const
Returns true if and only if *this contains y.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::CC76_narrowing_assign ( const BD_Shape< T > &  y)

Assigns to *this the result of restoring in y the constraints of *this that were lost by CC76-extrapolation applications.

Parameters
yA BDS that must contain *this.
Exceptions
std::invalid_argumentThrown if *this and y are dimension-incompatible.
Note
As was the case for widening operators, the argument y is meant to denote the value computed in the previous iteration step, whereas *this denotes the value computed in the current iteration step (in the decreasing iteration sequence). Hence, the call x.CC76_narrowing_assign(y) will assign to x the result of the computation $\mathtt{y} \Delta \mathtt{x}$.

Definition at line 3357 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

3357  {
3358  const dimension_type space_dim = space_dimension();
3359 
3360  // Dimension-compatibility check.
3361  if (space_dim != y.space_dimension()) {
3362  throw_dimension_incompatible("CC76_narrowing_assign(y)", y);
3363  }
3364  // We assume that `*this' is contained in or equal to `y'.
3365  PPL_EXPECT_HEAVY(copy_contains(y, *this));
3366 
3367  // If both bounded difference shapes are zero-dimensional,
3368  // since `y' contains `*this', we simply return `*this'.
3369  if (space_dim == 0) {
3370  return;
3371  }
3372  y.shortest_path_closure_assign();
3373  // If `y' is empty, since `y' contains `this', `*this' is empty too.
3374  if (y.marked_empty()) {
3375  return;
3376  }
3378  // If `*this' is empty, we return.
3379  if (marked_empty()) {
3380  return;
3381  }
3382  // Replace each constraint in `*this' by the corresponding constraint
3383  // in `y' if the corresponding inhomogeneous terms are both finite.
3384  bool changed = false;
3385  for (dimension_type i = space_dim + 1; i-- > 0; ) {
3386  DB_Row<N>& dbm_i = dbm[i];
3387  const DB_Row<N>& y_dbm_i = y.dbm[i];
3388  for (dimension_type j = space_dim + 1; j-- > 0; ) {
3389  N& dbm_ij = dbm_i[j];
3390  const N& y_dbm_ij = y_dbm_i[j];
3391  if (!is_plus_infinity(dbm_ij)
3392  && !is_plus_infinity(y_dbm_ij)
3393  && dbm_ij != y_dbm_ij) {
3394  dbm_ij = y_dbm_ij;
3395  changed = true;
3396  }
3397  }
3398  }
3399  if (changed && marked_shortest_path_closed()) {
3401  }
3402  PPL_ASSERT(OK());
3403 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
bool marked_shortest_path_closed() const
Returns true if the system of bounded differences is known to be shortest-path closed.
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
void reset_shortest_path_closed()
Marks *this as possibly not shortest-path closed.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
bool OK() const
Returns true if and only if *this satisfies all its invariants.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::compute_leaders ( std::vector< dimension_type > &  leaders) const
private

Compute the leaders of zero-equivalence classes.

It is assumed that the BDS is not empty and shortest-path closed.

Definition at line 997 of file BD_Shape_templates.hh.

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign().

997  {
998  PPL_ASSERT(!marked_empty() && marked_shortest_path_closed());
999  PPL_ASSERT(leaders.size() == 0);
1000  // Compute predecessor information.
1001  compute_predecessors(leaders);
1002  // Flatten the predecessor chains so as to obtain leaders.
1003  PPL_ASSERT(leaders[0] == 0);
1004  for (dimension_type i = 1, l_size = leaders.size(); i != l_size; ++i) {
1005  const dimension_type leaders_i = leaders[i];
1006  PPL_ASSERT(leaders_i <= i);
1007  if (leaders_i != i) {
1008  const dimension_type leaders_leaders_i = leaders[leaders_i];
1009  PPL_ASSERT(leaders_leaders_i == leaders[leaders_leaders_i]);
1010  leaders[i] = leaders_leaders_i;
1011  }
1012  }
1013 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool marked_shortest_path_closed() const
Returns true if the system of bounded differences is known to be shortest-path closed.
void compute_predecessors(std::vector< dimension_type > &predecessor) const
Compute the (zero-equivalence classes) predecessor relation.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::compute_predecessors ( std::vector< dimension_type > &  predecessor) const
private

Compute the (zero-equivalence classes) predecessor relation.

It is assumed that the BDS is not empty and shortest-path closed.

Definition at line 965 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::is_additive_inverse().

965  {
966  PPL_ASSERT(!marked_empty() && marked_shortest_path_closed());
967  PPL_ASSERT(predecessor.size() == 0);
968  // Variables are ordered according to their index.
969  // The vector `predecessor' is used to indicate which variable
970  // immediately precedes a given one in the corresponding equivalence class.
971  // The `leader' of an equivalence class is the element having minimum
972  // index: leaders are their own predecessors.
973  const dimension_type predecessor_size = dbm.num_rows();
974  // Initially, each variable is leader of its own zero-equivalence class.
975  predecessor.reserve(predecessor_size);
976  for (dimension_type i = 0; i < predecessor_size; ++i) {
977  predecessor.push_back(i);
978  }
979  // Now compute actual predecessors.
980  for (dimension_type i = predecessor_size; i-- > 1; ) {
981  if (i == predecessor[i]) {
982  const DB_Row<N>& dbm_i = dbm[i];
983  for (dimension_type j = i; j-- > 0; ) {
984  if (j == predecessor[j]
985  && is_additive_inverse(dbm[j][i], dbm_i[j])) {
986  // Choose as predecessor the variable having the smaller index.
987  predecessor[i] = j;
988  break;
989  }
990  }
991  }
992  }
993 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool marked_shortest_path_closed() const
Returns true if the system of bounded differences is known to be shortest-path closed.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_additive_inverse(const T &x, const T &y)
Returns true if and only if .
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::concatenate_assign ( const BD_Shape< T > &  y)

Assigns to *this the concatenation of *this and y, taken in this order.

Exceptions
std::length_errorThrown if the concatenation would cause the vector space to exceed dimension max_space_dimension().

Definition at line 579 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

579  {
580  BD_Shape& x = *this;
581 
582  const dimension_type x_space_dim = x.space_dimension();
583  const dimension_type y_space_dim = y.space_dimension();
584 
585  // If `y' is an empty 0-dim space bounded difference shape,
586  // let `*this' become empty.
587  if (y_space_dim == 0 && y.marked_empty()) {
588  set_empty();
589  return;
590  }
591 
592  // If `x' is an empty 0-dim space BDS, then it is sufficient to adjust
593  // the dimension of the vector space.
594  if (x_space_dim == 0 && marked_empty()) {
595  dbm.grow(y_space_dim + 1);
596  PPL_ASSERT(OK());
597  return;
598  }
599  // First we increase the space dimension of `x' by adding
600  // `y.space_dimension()' new dimensions.
601  // The matrix for the new system of constraints is obtained
602  // by leaving the old system of constraints in the upper left-hand side
603  // and placing the constraints of `y' in the lower right-hand side,
604  // except the constraints as `y(i) >= cost' or `y(i) <= cost', that are
605  // placed in the right position on the new matrix.
606  add_space_dimensions_and_embed(y_space_dim);
607  const dimension_type new_space_dim = x_space_dim + y_space_dim;
608  for (dimension_type i = x_space_dim + 1; i <= new_space_dim; ++i) {
609  DB_Row<N>& dbm_i = dbm[i];
610  dbm_i[0] = y.dbm[i - x_space_dim][0];
611  dbm[0][i] = y.dbm[0][i - x_space_dim];
612  for (dimension_type j = x_space_dim + 1; j <= new_space_dim; ++j) {
613  dbm_i[j] = y.dbm[i - x_space_dim][j - x_space_dim];
614  }
615  }
616 
619  }
620  PPL_ASSERT(OK());
621 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
BD_Shape(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty BDS of the specified space dimension.
bool marked_shortest_path_closed() const
Returns true if the system of bounded differences is known to be shortest-path closed.
void add_space_dimensions_and_embed(dimension_type m)
Adds m new dimensions and embeds the old BDS into the new space.
void reset_shortest_path_closed()
Marks *this as possibly not shortest-path closed.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
void set_empty()
Turns *this into an empty BDS.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
Congruence_System Parma_Polyhedra_Library::BD_Shape< T >::congruences ( ) const
inline

Returns a system of (equality) congruences satisfied by *this.

Definition at line 159 of file BD_Shape_inlines.hh.

Referenced by Parma_Polyhedra_Library::Grid::Grid().

159  {
160  return minimized_congruences();
161 }
Congruence_System minimized_congruences() const
Returns a minimal system of (equality) congruences satisfied by *this with the same affine dimension ...
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::constrains ( Variable  var) const

Returns true if and only if var is constrained in *this.

Exceptions
std::invalid_argumentThrown if var is not a space dimension of *this.

Definition at line 936 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::is_plus_infinity(), and Parma_Polyhedra_Library::Variable::space_dimension().

936  {
937  // `var' should be one of the dimensions of the BD shape.
938  const dimension_type var_space_dim = var.space_dimension();
939  if (space_dimension() < var_space_dim) {
940  throw_dimension_incompatible("constrains(v)", "v", var);
941  }
943  // A BD shape known to be empty constrains all variables.
944  // (Note: do not force emptiness check _yet_)
945  if (marked_empty()) {
946  return true;
947  }
948  // Check whether `var' is syntactically constrained.
949  const DB_Row<N>& dbm_v = dbm[var_space_dim];
950  for (dimension_type i = dbm.num_rows(); i-- > 0; ) {
951  if (!is_plus_infinity(dbm_v[i])
952  || !is_plus_infinity(dbm[i][var_space_dim])) {
953  return true;
954  }
955  }
956 
957  // `var' is not syntactically constrained:
958  // now force an emptiness check.
959  return is_empty();
960 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
bool is_empty() const
Returns true if and only if *this is an empty BDS.
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
Constraint_System Parma_Polyhedra_Library::BD_Shape< T >::constraints ( ) const

Returns a system of constraints defining *this.

Definition at line 6409 of file BD_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::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Constraint_System::set_space_dimension(), Parma_Polyhedra_Library::Constraint_System::zero_dim_empty(), and Parma_Polyhedra_Library::Constraint::zero_dim_false().

Referenced by Parma_Polyhedra_Library::C_Polyhedron::C_Polyhedron(), Parma_Polyhedra_Library::BD_Shape< T >::difference_assign(), Parma_Polyhedra_Library::BD_Shape< T >::H79_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::limited_H79_extrapolation_assign(), Parma_Polyhedra_Library::NNC_Polyhedron::NNC_Polyhedron(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), and Parma_Polyhedra_Library::BD_Shape< T >::time_elapse_assign().

6409  {
6410  const dimension_type space_dim = space_dimension();
6411  Constraint_System cs;
6412  cs.set_space_dimension(space_dim);
6413 
6414  if (space_dim == 0) {
6415  if (marked_empty()) {
6417  }
6418  return cs;
6419  }
6420 
6421  if (marked_empty()) {
6422  cs.insert(Constraint::zero_dim_false());
6423  return cs;
6424  }
6425 
6427  // Disregard redundant constraints.
6428  cs = minimized_constraints();
6429  return cs;
6430  }
6431 
6434  // Go through all the unary constraints in `dbm'.
6435  const DB_Row<N>& dbm_0 = dbm[0];
6436  for (dimension_type j = 1; j <= space_dim; ++j) {
6437  const Variable x(j-1);
6438  const N& dbm_0j = dbm_0[j];
6439  const N& dbm_j0 = dbm[j][0];
6440  if (is_additive_inverse(dbm_j0, dbm_0j)) {
6441  // We have a unary equality constraint.
6442  numer_denom(dbm_0j, b, a);
6443  cs.insert(a*x == b);
6444  }
6445  else {
6446  // We have 0, 1 or 2 unary inequality constraints.
6447  if (!is_plus_infinity(dbm_0j)) {
6448  numer_denom(dbm_0j, b, a);
6449  cs.insert(a*x <= b);
6450  }
6451  if (!is_plus_infinity(dbm_j0)) {
6452  numer_denom(dbm_j0, b, a);
6453  cs.insert(-a*x <= b);
6454  }
6455  }
6456  }
6457 
6458  // Go through all the binary constraints in `dbm'.
6459  for (dimension_type i = 1; i <= space_dim; ++i) {
6460  const Variable y(i-1);
6461  const DB_Row<N>& dbm_i = dbm[i];
6462  for (dimension_type j = i + 1; j <= space_dim; ++j) {
6463  const Variable x(j-1);
6464  const N& dbm_ij = dbm_i[j];
6465  const N& dbm_ji = dbm[j][i];
6466  if (is_additive_inverse(dbm_ji, dbm_ij)) {
6467  // We have a binary equality constraint.
6468  numer_denom(dbm_ij, b, a);
6469  cs.insert(a*x - a*y == b);
6470  }
6471  else {
6472  // We have 0, 1 or 2 binary inequality constraints.
6473  if (!is_plus_infinity(dbm_ij)) {
6474  numer_denom(dbm_ij, b, a);
6475  cs.insert(a*x - a*y <= b);
6476  }
6477  if (!is_plus_infinity(dbm_ji)) {
6478  numer_denom(dbm_ji, b, a);
6479  cs.insert(a*y - a*x <= b);
6480  }
6481  }
6482  }
6483  }
6484  return cs;
6485 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Enable_If< Is_Native_Or_Checked< T >::value, void >::type numer_denom(const T &from, Coefficient &numer, Coefficient &denom)
Extract the numerator and denominator components of from.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
static const Constraint_System & zero_dim_empty()
Returns the singleton system containing only Constraint::zero_dim_false().
static const Constraint & zero_dim_false()
The unsatisfiable (zero-dimension space) constraint .
bool marked_shortest_path_reduced() const
Returns true if the system of bounded differences is known to be shortest-path reduced.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_additive_inverse(const T &x, const T &y)
Returns true if and only if .
Constraint_System minimized_constraints() const
Returns a minimized system of constraints defining *this.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::contains ( const BD_Shape< T > &  y) const

Returns true if and only if *this contains y.

Exceptions
std::invalid_argumentThrown if *this and y are dimension-incompatible.

Definition at line 625 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::difference_assign(), Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::strictly_contains().

625  {
626  const BD_Shape<T>& x = *this;
627  const dimension_type x_space_dim = x.space_dimension();
628 
629  // Dimension-compatibility check.
630  if (x_space_dim != y.space_dimension()) {
631  throw_dimension_incompatible("contains(y)", y);
632  }
633  if (x_space_dim == 0) {
634  // The zero-dimensional empty shape only contains another
635  // zero-dimensional empty shape.
636  // The zero-dimensional universe shape contains any other
637  // zero-dimensional shape.
638  return marked_empty() ? y.marked_empty() : true;
639  }
640 
641  /*
642  The `y' bounded difference shape must be closed. As an example,
643  consider the case where in `*this' we have the constraints
644 
645  x1 - x2 <= 1,
646  x1 <= 3,
647  x2 <= 2,
648 
649  and in `y' the constraints are
650 
651  x1 - x2 <= 0,
652  x2 <= 1.
653 
654  Without closure the (erroneous) analysis of the inhomogeneous terms
655  would conclude containment does not hold. Closing `y' results into
656  the "discovery" of the implicit constraint
657 
658  x1 <= 1,
659 
660  at which point the inhomogeneous terms can be examined to determine
661  that containment does hold.
662  */
663  y.shortest_path_closure_assign();
664  // An empty shape is contained in any other dimension-compatible shapes.
665  if (y.marked_empty()) {
666  return true;
667  }
668  // If `x' is empty it can not contain `y' (which is not empty).
669  if (x.is_empty()) {
670  return false;
671  }
672  // `*this' contains `y' if and only if every cell of `dbm'
673  // is greater than or equal to the correspondent one of `y.dbm'.
674  for (dimension_type i = x_space_dim + 1; i-- > 0; ) {
675  const DB_Row<N>& x_dbm_i = x.dbm[i];
676  const DB_Row<N>& y_dbm_i = y.dbm[i];
677  for (dimension_type j = x_space_dim + 1; j-- > 0; ) {
678  if (x_dbm_i[j] < y_dbm_i[j]) {
679  return false;
680  }
681  }
682  }
683  return true;
684 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::contains_integer_point ( ) const

Returns true if and only if *this contains at least one integer point.

Definition at line 782 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::is_plus_infinity(), PPL_DIRTY_TEMP, Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::ROUND_NOT_NEEDED, and Parma_Polyhedra_Library::ROUND_UP.

782  {
783  // Force shortest-path closure.
784  if (is_empty()) {
785  return false;
786  }
787  const dimension_type space_dim = space_dimension();
788  if (space_dim == 0) {
789  return true;
790  }
791  // A non-empty BD_Shape defined by integer constraints
792  // necessarily contains an integer point.
794  return true;
795  }
796  // Build an integer BD_Shape z with bounds at least as tight as
797  // those in *this and then recheck for emptiness.
798  BD_Shape<mpz_class> bds_z(space_dim);
799  typedef BD_Shape<mpz_class>::N Z;
800  bds_z.reset_shortest_path_closed();
801  PPL_DIRTY_TEMP(N, tmp);
802  bool all_integers = true;
803  for (dimension_type i = space_dim + 1; i-- > 0; ) {
804  DB_Row<Z>& z_i = bds_z.dbm[i];
805  const DB_Row<N>& dbm_i = dbm[i];
806  for (dimension_type j = space_dim + 1; j-- > 0; ) {
807  const N& dbm_i_j = dbm_i[j];
808  if (is_plus_infinity(dbm_i_j)) {
809  continue;
810  }
811  if (is_integer(dbm_i_j)) {
812  assign_r(z_i[j], dbm_i_j, ROUND_NOT_NEEDED);
813  }
814  else {
815  all_integers = false;
816  Z& z_i_j = z_i[j];
817  // Copy dbm_i_j into z_i_j, but rounding downwards.
818  neg_assign_r(tmp, dbm_i_j, ROUND_NOT_NEEDED);
819  assign_r(z_i_j, tmp, ROUND_UP);
820  neg_assign_r(z_i_j, z_i_j, ROUND_NOT_NEEDED);
821  }
822  }
823  }
824  return all_integers || !bds_z.is_empty();
825 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
size_t dimension_type
An unsigned integral type for representing space dimensions.
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_integer(const T &x)
bool is_empty() const
Returns true if and only if *this is an empty BDS.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
#define PPL_DIRTY_TEMP(T, id)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::deduce_u_minus_v_bounds ( dimension_type  v,
dimension_type  last_v,
const Linear_Expression sc_expr,
Coefficient_traits::const_reference  sc_denom,
const N minus_lb_v 
)
private

An helper function for the computation of affine relations.

For each dbm index u (less than or equal to last_v and different from v), deduce constraints of the form u - v <= c, starting from minus_lb_v which is a lower bound for v.

The shortest-path closure is able to deduce the constraint u - v <= ub_u - lb_v. We can be more precise if variable u played an active role in the computation of the lower bound for v, i.e., if the corresponding coefficient q == sc_expr[u]/sc_denom is greater than zero. In particular:

  • if q >= 1, then u - v <= lb_u - lb_v;
  • if 0 < q < 1, then u - v <= (q*lb_u + (1-q)*ub_u) - lb_v.

Definition at line 3475 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::begin(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Linear_Expression::lower_bound(), PPL_DIRTY_TEMP, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::ROUND_UP, and Parma_Polyhedra_Library::Variable::space_dimension().

3479  {
3480  PPL_ASSERT(sc_denom > 0);
3481  PPL_ASSERT(!is_plus_infinity(minus_lb_v));
3482  // Deduce constraints of the form `u - v', where `u != v'.
3483  // Note: the shortest-path closure is able to deduce the constraint
3484  // `u - v <= ub_u - lb_v'. We can be more precise if variable `u'
3485  // played an active role in the computation of the lower bound for `v',
3486  // i.e., if the corresponding coefficient `q == expr_u/denom' is
3487  // greater than zero. In particular:
3488  // if `q >= 1', then `u - v <= lb_u - lb_v';
3489  // if `0 < q < 1', then `u - v <= (q*lb_u + (1-q)*ub_u) - lb_v'.
3490  PPL_DIRTY_TEMP(mpq_class, mpq_sc_denom);
3491  assign_r(mpq_sc_denom, sc_denom, ROUND_NOT_NEEDED);
3492  DB_Row<N>& dbm_0 = dbm[0];
3493  DB_Row<N>& dbm_v = dbm[v];
3494  // Speculative allocation of temporaries to be used in the following loop.
3495  PPL_DIRTY_TEMP(mpq_class, ub_u);
3496  PPL_DIRTY_TEMP(mpq_class, q);
3497  PPL_DIRTY_TEMP(mpq_class, minus_lb_u);
3498  PPL_DIRTY_TEMP(N, up_approx);
3499  // No need to consider indices greater than `last_v'.
3500  for (Linear_Expression::const_iterator u = sc_expr.begin(),
3501  u_end = sc_expr.lower_bound(Variable(last_v)); u != u_end; ++u) {
3502  const Variable u_var = u.variable();
3503  const dimension_type u_dim = u_var.space_dimension();
3504  if (u_var.space_dimension() == v) {
3505  continue;
3506  }
3507  const Coefficient& expr_u = *u;
3508  if (expr_u < 0) {
3509  continue;
3510  }
3511  PPL_ASSERT(expr_u > 0);
3512  if (expr_u >= sc_denom) {
3513  // Deducing `u - v <= lb_u - lb_v',
3514  // i.e., `u - v <= (-lb_v) - (-lb_u)'.
3515  sub_assign_r(dbm_v[u_dim], minus_lb_v, dbm[u_dim][0], ROUND_UP);
3516  }
3517  else {
3518  const N& dbm_0u = dbm_0[u_dim];
3519  if (!is_plus_infinity(dbm_0u)) {
3520  // Let `ub_u' and `lb_u' be the known upper and lower bound
3521  // for `u', respectively. Letting `q = expr_u/sc_denom' be the
3522  // rational coefficient of `u' in `sc_expr/sc_denom',
3523  // the upper bound for `u - v' is computed as
3524  // `(q * lb_u + (1-q) * ub_u) - lb_v', i.e.,
3525  // `ub_u - q * (ub_u + (-lb_u)) + minus_lb_v'.
3526  assign_r(ub_u, dbm_0u, ROUND_NOT_NEEDED);
3527  assign_r(q, expr_u, ROUND_NOT_NEEDED);
3528  div_assign_r(q, q, mpq_sc_denom, ROUND_NOT_NEEDED);
3529  assign_r(minus_lb_u, dbm[u_dim][0], ROUND_NOT_NEEDED);
3530  // Compute `ub_u - lb_u'.
3531  add_assign_r(minus_lb_u, minus_lb_u, ub_u, ROUND_NOT_NEEDED);
3532  // Compute `ub_u - q * (ub_u - lb_u)'.
3533  sub_mul_assign_r(ub_u, q, minus_lb_u, ROUND_NOT_NEEDED);
3534  assign_r(up_approx, ub_u, ROUND_UP);
3535  // Deducing `u - v <= (q*lb_u + (1-q)*ub_u) - lb_v'.
3536  add_assign_r(dbm_v[u_dim], up_approx, minus_lb_v, ROUND_UP);
3537  }
3538  }
3539  }
3540 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
size_t dimension_type
An unsigned integral type for representing space dimensions.
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
#define PPL_DIRTY_TEMP(T, id)
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::deduce_v_minus_u_bounds ( dimension_type  v,
dimension_type  last_v,
const Linear_Expression sc_expr,
Coefficient_traits::const_reference  sc_denom,
const N ub_v 
)
private

An helper function for the computation of affine relations.

For each dbm index u (less than or equal to last_v and different from v), deduce constraints of the form v - u <= c, starting from ub_v which is an upper bound for v.

The shortest-path closure is able to deduce the constraint v - u <= ub_v - lb_u. We can be more precise if variable u played an active role in the computation of the upper bound for v, i.e., if the corresponding coefficient q == sc_expr[u]/sc_denom is greater than zero. In particular:

  • if q >= 1, then v - u <= ub_v - ub_u;
  • if 0 < q < 1, then v - u <= ub_v - (q*ub_u + (1-q)*lb_u).

Definition at line 3408 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::begin(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Linear_Expression::lower_bound(), PPL_DIRTY_TEMP, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, and Parma_Polyhedra_Library::ROUND_UP.

3412  {
3413  PPL_ASSERT(sc_denom > 0);
3414  PPL_ASSERT(!is_plus_infinity(ub_v));
3415  // Deduce constraints of the form `v - u', where `u != v'.
3416  // Note: the shortest-path closure is able to deduce the constraint
3417  // `v - u <= ub_v - lb_u'. We can be more precise if variable `u'
3418  // played an active role in the computation of the upper bound for `v',
3419  // i.e., if the corresponding coefficient `q == expr_u/denom' is
3420  // greater than zero. In particular:
3421  // if `q >= 1', then `v - u <= ub_v - ub_u';
3422  // if `0 < q < 1', then `v - u <= ub_v - (q*ub_u + (1-q)*lb_u)'.
3423  PPL_DIRTY_TEMP(mpq_class, mpq_sc_denom);
3424  assign_r(mpq_sc_denom, sc_denom, ROUND_NOT_NEEDED);
3425  const DB_Row<N>& dbm_0 = dbm[0];
3426  // Speculative allocation of temporaries to be used in the following loop.
3427  PPL_DIRTY_TEMP(mpq_class, minus_lb_u);
3428  PPL_DIRTY_TEMP(mpq_class, q);
3429  PPL_DIRTY_TEMP(mpq_class, ub_u);
3430  PPL_DIRTY_TEMP(N, up_approx);
3431  for (Linear_Expression::const_iterator u = sc_expr.begin(),
3432  u_end = sc_expr.lower_bound(Variable(last_v)); u != u_end; ++u) {
3433  const dimension_type u_dim = u.variable().space_dimension();
3434  if (u_dim == v) {
3435  continue;
3436  }
3437  const Coefficient& expr_u = *u;
3438  if (expr_u < 0) {
3439  continue;
3440  }
3441  PPL_ASSERT(expr_u > 0);
3442  if (expr_u >= sc_denom) {
3443  // Deducing `v - u <= ub_v - ub_u'.
3444  sub_assign_r(dbm[u_dim][v], ub_v, dbm_0[u_dim], ROUND_UP);
3445  }
3446  else {
3447  DB_Row<N>& dbm_u = dbm[u_dim];
3448  const N& dbm_u0 = dbm_u[0];
3449  if (!is_plus_infinity(dbm_u0)) {
3450  // Let `ub_u' and `lb_u' be the known upper and lower bound
3451  // for `u', respectively. Letting `q = expr_u/sc_denom' be the
3452  // rational coefficient of `u' in `sc_expr/sc_denom',
3453  // the upper bound for `v - u' is computed as
3454  // `ub_v - (q * ub_u + (1-q) * lb_u)', i.e.,
3455  // `ub_v + (-lb_u) - q * (ub_u + (-lb_u))'.
3456  assign_r(minus_lb_u, dbm_u0, ROUND_NOT_NEEDED);
3457  assign_r(q, expr_u, ROUND_NOT_NEEDED);
3458  div_assign_r(q, q, mpq_sc_denom, ROUND_NOT_NEEDED);
3459  assign_r(ub_u, dbm_0[u_dim], ROUND_NOT_NEEDED);
3460  // Compute `ub_u - lb_u'.
3461  add_assign_r(ub_u, ub_u, minus_lb_u, ROUND_NOT_NEEDED);
3462  // Compute `(-lb_u) - q * (ub_u - lb_u)'.
3463  sub_mul_assign_r(minus_lb_u, q, ub_u, ROUND_NOT_NEEDED);
3464  assign_r(up_approx, minus_lb_u, ROUND_UP);
3465  // Deducing `v - u <= ub_v - (q * ub_u + (1-q) * lb_u)'.
3466  add_assign_r(dbm_u[v], ub_v, up_approx, ROUND_UP);
3467  }
3468  }
3469  }
3470 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
size_t dimension_type
An unsigned integral type for representing space dimensions.
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
#define PPL_DIRTY_TEMP(T, id)
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::difference_assign ( const BD_Shape< T > &  y)

Assigns to *this the smallest BD shape containing the set difference of *this and y.

Exceptions
std::invalid_argumentThrown if *this and y are dimension-incompatible.

Definition at line 2470 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Constraint_System::begin(), c, Parma_Polyhedra_Library::BD_Shape< T >::constraints(), Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Constraint::expression(), Parma_Polyhedra_Library::Poly_Con_Relation::implies(), Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::relation_with(), Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign().

2470  {
2471  const dimension_type space_dim = space_dimension();
2472 
2473  // Dimension-compatibility check.
2474  if (space_dim != y.space_dimension()) {
2475  throw_dimension_incompatible("difference_assign(y)", y);
2476  }
2477  BD_Shape new_bd_shape(space_dim, EMPTY);
2478 
2479  BD_Shape& x = *this;
2480 
2481  x.shortest_path_closure_assign();
2482  // The difference of an empty bounded difference shape
2483  // and of a bounded difference shape `p' is empty.
2484  if (x.marked_empty()) {
2485  return;
2486  }
2487  y.shortest_path_closure_assign();
2488  // The difference of a bounded difference shape `p'
2489  // and an empty bounded difference shape is `p'.
2490  if (y.marked_empty()) {
2491  return;
2492  }
2493  // If both bounded difference shapes are zero-dimensional,
2494  // then at this point they are necessarily universe system of
2495  // bounded differences, so that their difference is empty.
2496  if (space_dim == 0) {
2497  x.set_empty();
2498  return;
2499  }
2500 
2501  // TODO: This is just an executable specification.
2502  // Have to find a more efficient method.
2503  if (y.contains(x)) {
2504  x.set_empty();
2505  return;
2506  }
2507 
2508  // We take a constraint of the system y at the time and we
2509  // consider its complementary. Then we intersect the union
2510  // of these complementary constraints with the system x.
2511  const Constraint_System& y_cs = y.constraints();
2512  for (Constraint_System::const_iterator i = y_cs.begin(),
2513  y_cs_end = y_cs.end(); i != y_cs_end; ++i) {
2514  const Constraint& c = *i;
2515  // If the bounded difference shape `x' is included
2516  // in the bounded difference shape defined by `c',
2517  // then `c' _must_ be skipped, as adding its complement to `x'
2518  // would result in the empty bounded difference shape,
2519  // and as we would obtain a result that is less precise
2520  // than the bds-difference.
2521  if (x.relation_with(c).implies(Poly_Con_Relation::is_included())) {
2522  continue;
2523  }
2524  BD_Shape z = x;
2525  const Linear_Expression e(c.expression());
2526  z.add_constraint(e <= 0);
2527  if (!z.is_empty()) {
2528  new_bd_shape.upper_bound_assign(z);
2529  }
2530  if (c.is_equality()) {
2531  z = x;
2532  z.add_constraint(e >= 0);
2533  if (!z.is_empty()) {
2534  new_bd_shape.upper_bound_assign(z);
2535  }
2536  }
2537  }
2538  *this = new_bd_shape;
2539  PPL_ASSERT(OK());
2540 }
The empty element, i.e., the empty set.
size_t dimension_type
An unsigned integral type for representing space dimensions.
BD_Shape(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty BDS of the specified space dimension.
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
static Poly_Con_Relation is_included()
The polyhedron is included in the set of points satisfying the constraint.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Coefficient c
Definition: PIP_Tree.cc:64
Constraint_System_const_iterator const_iterator
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points ( Complexity_Class  complexity = ANY_COMPLEXITY)

Possibly tightens *this by dropping some points with non-integer coordinates.

Parameters
complexityThe maximal complexity of any algorithms used.
Note
Currently there is no optimality guarantee, not even if complexity is ANY_COMPLEXITY.

Definition at line 6664 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::is_integer().

6664  {
6666  return;
6667  }
6668  const dimension_type space_dim = space_dimension();
6670  if (space_dim == 0 || marked_empty()) {
6671  return;
6672  }
6673  for (dimension_type i = space_dim + 1; i-- > 0; ) {
6674  DB_Row<N>& dbm_i = dbm[i];
6675  for (dimension_type j = space_dim + 1; j-- > 0; ) {
6676  if (i != j) {
6678  }
6679  }
6680  }
6681  PPL_ASSERT(OK());
6682 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_integer(const T &x)
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points ( const Variables_Set vars,
Complexity_Class  complexity = ANY_COMPLEXITY 
)

Possibly tightens *this by dropping some points with non-integer coordinates for the space dimensions corresponding to vars.

Parameters
varsPoints with non-integer coordinates for these variables/space-dimensions can be discarded.
complexityThe maximal complexity of any algorithms used.
Note
Currently there is no optimality guarantee, not even if complexity is ANY_COMPLEXITY.

Definition at line 6686 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::is_integer(), and Parma_Polyhedra_Library::Variables_Set::space_dimension().

6687  {
6688  // Dimension-compatibility check.
6689  const dimension_type space_dim = space_dimension();
6690  const dimension_type min_space_dim = vars.space_dimension();
6691  if (space_dim < min_space_dim) {
6692  throw_dimension_incompatible("drop_some_non_integer_points(vs, cmpl)",
6693  min_space_dim);
6694  }
6695  if (std::numeric_limits<T>::is_integer || min_space_dim == 0) {
6696  return;
6697  }
6699  if (marked_empty()) {
6700  return;
6701  }
6702  const Variables_Set::const_iterator v_begin = vars.begin();
6703  const Variables_Set::const_iterator v_end = vars.end();
6704  PPL_ASSERT(v_begin != v_end);
6705  // Unary constraints on a variable occurring in `vars'.
6706  DB_Row<N>& dbm_0 = dbm[0];
6707  for (Variables_Set::const_iterator v_i = v_begin; v_i != v_end; ++v_i) {
6708  const dimension_type i = *v_i + 1;
6711  }
6712 
6713  // Binary constraints where both variables occur in `vars'.
6714  for (Variables_Set::const_iterator v_i = v_begin; v_i != v_end; ++v_i) {
6715  const dimension_type i = *v_i + 1;
6716  DB_Row<N>& dbm_i = dbm[i];
6717  for (Variables_Set::const_iterator v_j = v_begin; v_j != v_end; ++v_j) {
6718  const dimension_type j = *v_j + 1;
6719  if (i != j) {
6721  }
6722  }
6723  }
6724  PPL_ASSERT(OK());
6725 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_integer(const T &x)
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points_helper ( N elem)
inlineprivate

Definition at line 939 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::is_integer(), PPL_USED, Parma_Polyhedra_Library::ROUND_DOWN, and Parma_Polyhedra_Library::V_EQ.

939  {
940  if (!is_integer(elem)) {
941  Result r = floor_assign_r(elem, elem, ROUND_DOWN);
942  PPL_USED(r);
943  PPL_ASSERT(r == V_EQ);
945  }
946 }
The computed result is exact.
Definition: Result_defs.hh:81
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_integer(const T &x)
Result
Possible outcomes of a checked arithmetic computation.
Definition: Result_defs.hh:76
void reset_shortest_path_closed()
Marks *this as possibly not shortest-path closed.
#define PPL_USED(v)
No-op macro that allows to avoid unused variable warnings from the compiler.
Definition: compiler.hh:39
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::expand_space_dimension ( Variable  var,
dimension_type  m 
)

Creates m copies of the space dimension corresponding to var.

Parameters
varThe variable corresponding to the space dimension to be replicated;
mThe number of replicas to be created.
Exceptions
std::invalid_argumentThrown if var does not correspond to a dimension of the vector space.
std::length_errorThrown if adding m new space dimensions would cause the vector space to exceed dimension max_space_dimension().

If *this has space dimension $n$, with $n > 0$, and var has space dimension $k \leq n$, then the $k$-th space dimension is expanded to m new space dimensions $n$, $n+1$, $\dots$, $n+m-1$.

Definition at line 6574 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::max_space_dimension(), and Parma_Polyhedra_Library::Variable::space_dimension().

6574  {
6575  dimension_type old_dim = space_dimension();
6576  // `var' should be one of the dimensions of the vector space.
6577  if (var.space_dimension() > old_dim) {
6578  throw_dimension_incompatible("expand_space_dimension(v, m)", "v", var);
6579  }
6580 
6581  // The space dimension of the resulting BDS should not
6582  // overflow the maximum allowed space dimension.
6583  if (m > max_space_dimension() - space_dimension()) {
6584  throw_invalid_argument("expand_dimension(v, m)",
6585  "adding m new space dimensions exceeds "
6586  "the maximum allowed space dimension");
6587  }
6588  // Nothing to do, if no dimensions must be added.
6589  if (m == 0) {
6590  return;
6591  }
6592  // Add the required new dimensions.
6594 
6595  // For each constraints involving variable `var', we add a
6596  // similar constraint with the new variable substituted for
6597  // variable `var'.
6598  const dimension_type v_id = var.id() + 1;
6599  const DB_Row<N>& dbm_v = dbm[v_id];
6600  for (dimension_type i = old_dim + 1; i-- > 0; ) {
6601  DB_Row<N>& dbm_i = dbm[i];
6602  const N& dbm_i_v = dbm[i][v_id];
6603  const N& dbm_v_i = dbm_v[i];
6604  for (dimension_type j = old_dim+1; j < old_dim+m+1; ++j) {
6605  dbm_i[j] = dbm_i_v;
6606  dbm[j][i] = dbm_v_i;
6607  }
6608  }
6609  // In general, adding a constraint does not preserve the shortest-path
6610  // closure or reduction of the bounded difference shape.
6613  }
6614  PPL_ASSERT(OK());
6615 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
bool marked_shortest_path_closed() const
Returns true if the system of bounded differences is known to be shortest-path closed.
void add_space_dimensions_and_embed(dimension_type m)
Adds m new dimensions and embeds the old BDS into the new space.
static dimension_type max_space_dimension()
Returns the maximum space dimension that a BDS can handle.
void reset_shortest_path_closed()
Marks *this as possibly not shortest-path closed.
static void throw_invalid_argument(const char *method, const char *reason)
bool OK() const
Returns true if and only if *this satisfies all its invariants.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
template<typename U >
void Parma_Polyhedra_Library::BD_Shape< T >::export_interval_constraints ( U &  dest) const

Applies to dest the interval constraints embedded in *this.

Parameters
destThe object to which the constraints will be added.
Exceptions
std::invalid_argumentThrown if *this is dimension-incompatible with dest.

The template type parameter U must provide the following methods.

returns the space dimension of the object.

void set_empty()

sets the object to an empty object.

bool restrict_lower(dimension_type dim, const T& lb)

restricts the object by applying the lower bound lb to the space dimension dim and returns false if and only if the object becomes empty.

bool restrict_upper(dimension_type dim, const T& ub)

restricts the object by applying the upper bound ub to the space dimension dim and returns false if and only if the object becomes empty.

Definition at line 4704 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::is_plus_infinity(), PPL_DIRTY_TEMP, Parma_Polyhedra_Library::Checked_Number< T, Policy >::raw_value(), and Parma_Polyhedra_Library::ROUND_DOWN.

4704  {
4705  const dimension_type space_dim = space_dimension();
4706  if (space_dim > dest.space_dimension()) {
4707  throw std::invalid_argument(
4708  "BD_Shape<T>::export_interval_constraints");
4709  }
4710 
4711  // Expose all the interval constraints.
4713 
4714  if (marked_empty()) {
4715  dest.set_empty();
4716  PPL_ASSERT(OK());
4717  return;
4718  }
4719 
4720  PPL_DIRTY_TEMP(N, tmp);
4721  const DB_Row<N>& dbm_0 = dbm[0];
4722  for (dimension_type i = space_dim; i-- > 0; ) {
4723  // Set the upper bound.
4724  const N& u = dbm_0[i+1];
4725  if (!is_plus_infinity(u)) {
4726  if (!dest.restrict_upper(i, u.raw_value())) {
4727  return;
4728  }
4729  }
4730  // Set the lower bound.
4731  const N& negated_l = dbm[i+1][0];
4732  if (!is_plus_infinity(negated_l)) {
4733  neg_assign_r(tmp, negated_l, ROUND_DOWN);
4734  if (!dest.restrict_lower(i, tmp.raw_value())) {
4735  return;
4736  }
4737  }
4738  }
4739 
4740  PPL_ASSERT(OK());
4741 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
#define PPL_DIRTY_TEMP(T, id)
bool OK() const
Returns true if and only if *this satisfies all its invariants.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
memory_size_type Parma_Polyhedra_Library::BD_Shape< T >::external_memory_in_bytes ( ) const

Returns the size in bytes of the memory managed by *this.

Definition at line 6875 of file BD_Shape_templates.hh.

6875  {
6876  return dbm.external_memory_in_bytes()
6878 }
memory_size_type external_memory_in_bytes() const
Returns the size in bytes of the memory managed by *this.
Definition: Bit_Matrix.cc:225
Bit_Matrix redundancy_dbm
A matrix indicating which constraints are redundant.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::fold_space_dimensions ( const Variables_Set vars,
Variable  dest 
)

Folds the space dimensions in vars into dest.

Parameters
varsThe set of Variable objects corresponding to the space dimensions to be folded;
destThe variable corresponding to the space dimension that is the destination of the folding operation.
Exceptions
std::invalid_argumentThrown if *this is dimension-incompatible with dest or with one of the Variable objects contained in vars. Also thrown if dest is contained in vars.

If *this has space dimension $n$, with $n > 0$, dest has space dimension $k \leq n$, vars is a set of variables whose maximum space dimension is also less than or equal to $n$, and dest is not a member of vars, then the space dimensions corresponding to variables in vars are folded into the $k$-th space dimension.

Definition at line 6619 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::max_assign(), Parma_Polyhedra_Library::Variables_Set::space_dimension(), and Parma_Polyhedra_Library::Variable::space_dimension().

6620  {
6621  const dimension_type space_dim = space_dimension();
6622  // `dest' should be one of the dimensions of the BDS.
6623  if (dest.space_dimension() > space_dim) {
6624  throw_dimension_incompatible("fold_space_dimensions(vs, v)",
6625  "v", dest);
6626  }
6627  // The folding of no dimensions is a no-op.
6628  if (vars.empty()) {
6629  return;
6630  }
6631  // All variables in `vars' should be dimensions of the BDS.
6632  if (vars.space_dimension() > space_dim) {
6633  throw_dimension_incompatible("fold_space_dimensions(vs, v)",
6634  vars.space_dimension());
6635  }
6636  // Moreover, `dest.id()' should not occur in `vars'.
6637  if (vars.find(dest.id()) != vars.end()) {
6638  throw_invalid_argument("fold_space_dimensions(vs, v)",
6639  "v should not occur in vs");
6640  }
6642  if (!marked_empty()) {
6643  // Recompute the elements of the row and the column corresponding
6644  // to variable `dest' by taking the join of their value with the
6645  // value of the corresponding elements in the row and column of the
6646  // variable `vars'.
6647  const dimension_type v_id = dest.id() + 1;
6648  DB_Row<N>& dbm_v = dbm[v_id];
6649  for (Variables_Set::const_iterator i = vars.begin(),
6650  vs_end = vars.end(); i != vs_end; ++i) {
6651  const dimension_type to_be_folded_id = *i + 1;
6652  const DB_Row<N>& dbm_to_be_folded_id = dbm[to_be_folded_id];
6653  for (dimension_type j = space_dim + 1; j-- > 0; ) {
6654  max_assign(dbm[j][v_id], dbm[j][to_be_folded_id]);
6655  max_assign(dbm_v[j], dbm_to_be_folded_id[j]);
6656  }
6657  }
6658  }
6660 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
void max_assign(N &x, const N &y)
Assigns to x the maximum between x and y.
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
static void throw_invalid_argument(const char *method, const char *reason)
void remove_space_dimensions(const Variables_Set &vars)
Removes all the specified dimensions.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::forget_all_dbm_constraints ( dimension_type  v)
private

Removes all the constraints on row/column v.

Definition at line 3544 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::PLUS_INFINITY, and Parma_Polyhedra_Library::ROUND_NOT_NEEDED.

3544  {
3545  PPL_ASSERT(0 < v && v <= dbm.num_rows());
3546  DB_Row<N>& dbm_v = dbm[v];
3547  for (dimension_type i = dbm.num_rows(); i-- > 0; ) {
3550  }
3551 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
size_t dimension_type
An unsigned integral type for representing space dimensions.
Plus_Infinity PLUS_INFINITY
Definition: checked.cc:31
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::forget_binary_dbm_constraints ( dimension_type  v)
private

Removes all binary constraints on row/column v.

Definition at line 3555 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::PLUS_INFINITY, and Parma_Polyhedra_Library::ROUND_NOT_NEEDED.

3555  {
3556  PPL_ASSERT(0 < v && v <= dbm.num_rows());
3557  DB_Row<N>& dbm_v = dbm[v];
3558  for (dimension_type i = dbm.num_rows()-1; i > 0; --i) {
3561  }
3562 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
size_t dimension_type
An unsigned integral type for representing space dimensions.
Plus_Infinity PLUS_INFINITY
Definition: checked.cc:31
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::frequency ( const Linear_Expression expr,
Coefficient freq_n,
Coefficient freq_d,
Coefficient val_n,
Coefficient val_d 
) const

Returns true if and only if there exist a unique value val such that *this saturates the equality expr = val.

Parameters
exprThe linear expression for which the frequency is needed;
freq_nIf true is returned, the value is set to $0$; Present for interface compatibility with class Grid, where the frequency can have a non-zero value;
freq_dIf true is returned, the value is set to $1$;
val_nThe numerator of val;
val_dThe denominator of val;
Exceptions
std::invalid_argumentThrown if expr and *this are dimension-incompatible.

If false is returned, then freq_n, freq_d, val_n and val_d are left untouched.

Definition at line 829 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::add_mul_assign(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::begin(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::Boundary_NS::le(), Parma_Polyhedra_Library::Linear_Expression::lower_bound(), Parma_Polyhedra_Library::normalize2(), Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and Parma_Polyhedra_Library::sub_mul_assign().

831  {
832  dimension_type space_dim = space_dimension();
833  // The dimension of `expr' must be at most the dimension of *this.
834  if (space_dim < expr.space_dimension()) {
835  throw_dimension_incompatible("frequency(e, ...)", "e", expr);
836  }
837  // Check if `expr' has a constant value.
838  // If it is constant, set the frequency `freq_n' to 0
839  // and return true. Otherwise the values for \p expr
840  // are not discrete so return false.
841 
842  // Space dimension is 0: if empty, then return false;
843  // otherwise the frequency is 0 and the value is the inhomogeneous term.
844  if (space_dim == 0) {
845  if (is_empty()) {
846  return false;
847  }
848  freq_n = 0;
849  freq_d = 1;
850  val_n = expr.inhomogeneous_term();
851  val_d = 1;
852  return true;
853  }
854 
856  // For an empty BD shape, we simply return false.
857  if (marked_empty()) {
858  return false;
859  }
860  // The BD shape has at least 1 dimension and is not empty.
864  PPL_DIRTY_TEMP(N, tmp);
865  Linear_Expression le = expr;
866  // Boolean to keep track of a variable `v' in expression `le'.
867  // If we can replace `v' by an expression using variables other
868  // than `v' and are already in `le', then this is set to true.
869 
870  PPL_DIRTY_TEMP_COEFFICIENT(val_denom);
871  val_denom = 1;
872 
873  // TODO: This loop can be optimized more, if needed, exploiting the
874  // (possible) sparseness of le.
875  for (dimension_type i = dbm.num_rows(); i-- > 1; ) {
876  const Variable v(i-1);
877  coeff = le.coefficient(v);
878  if (coeff == 0) {
879  continue;
880  }
881  const DB_Row<N>& dbm_i = dbm[i];
882  // Check if `v' is constant in the BD shape.
883  assign_r(tmp, dbm_i[0], ROUND_NOT_NEEDED);
884  if (is_additive_inverse(dbm[0][i], tmp)) {
885  // If `v' is constant, replace it in `le' by the value.
886  numer_denom(tmp, numer, denom);
887  sub_mul_assign(le, coeff, v);
888  le *= denom;
889  le -= numer*coeff;
890  val_denom *= denom;
891  continue;
892  }
893  // Check the bounded differences with the other dimensions that
894  // have non-zero coefficient in `le'.
895  else {
896  bool constant_v = false;
897  for (Linear_Expression::const_iterator j = le.begin(),
898  j_end = le.lower_bound(Variable(i - 1)); j != j_end; ++j) {
899  const Variable vj = j.variable();
900  const dimension_type j_dim = vj.space_dimension();
901  assign_r(tmp, dbm_i[j_dim], ROUND_NOT_NEEDED);
902  if (is_additive_inverse(dbm[j_dim][i], tmp)) {
903  // The coefficient for `vj' in `le' is not 0
904  // and the difference with `v' in the BD shape is constant.
905  // So apply this equality to eliminate `v' in `le'.
906  numer_denom(tmp, numer, denom);
907  // Modifying le invalidates the iterators, but it's not a problem
908  // since we are going to exit the loop.
909  sub_mul_assign(le, coeff, v);
910  add_mul_assign(le, coeff, vj);
911  le *= denom;
912  le -= numer*coeff;
913  val_denom *= denom;
914  constant_v = true;
915  break;
916  }
917  }
918  if (!constant_v) {
919  // The expression `expr' is not constant.
920  return false;
921  }
922  }
923  }
924 
925  // The expression `expr' is constant.
926  freq_n = 0;
927  freq_d = 1;
928 
929  // Reduce `val_n' and `val_d'.
930  normalize2(le.inhomogeneous_term(), val_denom, val_n, val_d);
931  return true;
932 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
size_t dimension_type
An unsigned integral type for representing space dimensions.
Enable_If< Is_Native_Or_Checked< T >::value, void >::type numer_denom(const T &from, Coefficient &numer, Coefficient &denom)
Extract the numerator and denominator components of from.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
void add_mul_assign(GMP_Integer &x, const GMP_Integer &y, const GMP_Integer &z)
bool is_empty() const
Returns true if and only if *this is an empty BDS.
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_additive_inverse(const T &x, const T &y)
Returns true if and only if .
#define PPL_DIRTY_TEMP(T, id)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void sub_mul_assign(GMP_Integer &x, const GMP_Integer &y, const GMP_Integer &z)
void normalize2(Coefficient_traits::const_reference x, Coefficient_traits::const_reference y, Coefficient &n_x, Coefficient &n_y)
If is the GCD of x and y, the values of x and y divided by are assigned to n_x and n_y...
bool le(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
template<typename Interval_Info >
void Parma_Polyhedra_Library::BD_Shape< T >::general_refine ( const dimension_type left_w_id,
const dimension_type right_w_id,
const Linear_Form< Interval< T, Interval_Info > > &  left,
const Linear_Form< Interval< T, Interval_Info > > &  right 
)
private

Auxiliary function for refine with linear form that handle the general case.

Definition at line 4937 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::assign_r(), PPL_DIRTY_TEMP, and Parma_Polyhedra_Library::ROUND_NOT_NEEDED.

4940  {
4941 
4942  typedef Interval<T, Interval_Info> FP_Interval_Type;
4943  Linear_Form<FP_Interval_Type> right_minus_left(right);
4944  right_minus_left -= left;
4945 
4946  // Declare temporaries outside of the loop.
4947  PPL_DIRTY_TEMP(N, low_coeff);
4948  PPL_DIRTY_TEMP(N, high_coeff);
4949  PPL_DIRTY_TEMP(N, upper_bound);
4950 
4951  dimension_type max_w_id = std::max(left_w_id, right_w_id);
4952 
4953  for (dimension_type first_v = 0; first_v < max_w_id; ++first_v) {
4954  for (dimension_type second_v = first_v+1;
4955  second_v <= max_w_id; ++second_v) {
4956  const FP_Interval_Type& lfv_coefficient =
4957  left.coefficient(Variable(first_v));
4958  const FP_Interval_Type& lsv_coefficient =
4959  left.coefficient(Variable(second_v));
4960  const FP_Interval_Type& rfv_coefficient =
4961  right.coefficient(Variable(first_v));
4962  const FP_Interval_Type& rsv_coefficient =
4963  right.coefficient(Variable(second_v));
4964  // We update the constraints only when both variables appear in at
4965  // least one argument.
4966  bool do_update = false;
4967  assign_r(low_coeff, lfv_coefficient.lower(), ROUND_NOT_NEEDED);
4968  assign_r(high_coeff, lfv_coefficient.upper(), ROUND_NOT_NEEDED);
4969  if (low_coeff != 0 || high_coeff != 0) {
4970  assign_r(low_coeff, lsv_coefficient.lower(), ROUND_NOT_NEEDED);
4971  assign_r(high_coeff, lsv_coefficient.upper(), ROUND_NOT_NEEDED);
4972  if (low_coeff != 0 || high_coeff != 0) {
4973  do_update = true;
4974  }
4975  else {
4976  assign_r(low_coeff, rsv_coefficient.lower(), ROUND_NOT_NEEDED);
4977  assign_r(high_coeff, rsv_coefficient.upper(), ROUND_NOT_NEEDED);
4978  if (low_coeff != 0 || high_coeff != 0) {
4979  do_update = true;
4980  }
4981  }
4982  }
4983  else {
4984  assign_r(low_coeff, rfv_coefficient.lower(), ROUND_NOT_NEEDED);
4985  assign_r(high_coeff, rfv_coefficient.upper(), ROUND_NOT_NEEDED);
4986  if (low_coeff != 0 || high_coeff != 0) {
4987  assign_r(low_coeff, lsv_coefficient.lower(), ROUND_NOT_NEEDED);
4988  assign_r(high_coeff, lsv_coefficient.upper(), ROUND_NOT_NEEDED);
4989  if (low_coeff != 0 || high_coeff != 0) {
4990  do_update = true;
4991  }
4992  else {
4993  assign_r(low_coeff, rsv_coefficient.lower(), ROUND_NOT_NEEDED);
4994  assign_r(high_coeff, rsv_coefficient.upper(), ROUND_NOT_NEEDED);
4995  if (low_coeff != 0 || high_coeff != 0) {
4996  do_update = true;
4997  }
4998  }
4999  }
5000  }
5001 
5002  if (do_update) {
5003  Variable first(first_v);
5004  Variable second(second_v);
5005  dimension_type n_first_var = first_v +1 ;
5006  dimension_type n_second_var = second_v + 1;
5007  linear_form_upper_bound(right_minus_left - first + second,
5008  upper_bound);
5009  add_dbm_constraint(n_first_var, n_second_var, upper_bound);
5010  linear_form_upper_bound(right_minus_left + first - second,
5011  upper_bound);
5012  add_dbm_constraint(n_second_var, n_first_var, upper_bound);
5013  }
5014  }
5015  }
5016 
5017  // Finally, update the unary constraints.
5018  for (dimension_type v = 0; v < max_w_id; ++v) {
5019  const FP_Interval_Type& lv_coefficient =
5020  left.coefficient(Variable(v));
5021  const FP_Interval_Type& rv_coefficient =
5022  right.coefficient(Variable(v));
5023  // We update the constraints only if v appears in at least one of the
5024  // two arguments.
5025  bool do_update = false;
5026  assign_r(low_coeff, lv_coefficient.lower(), ROUND_NOT_NEEDED);
5027  assign_r(high_coeff, lv_coefficient.upper(), ROUND_NOT_NEEDED);
5028  if (low_coeff != 0 || high_coeff != 0) {
5029  do_update = true;
5030  }
5031  else {
5032  assign_r(low_coeff, rv_coefficient.lower(), ROUND_NOT_NEEDED);
5033  assign_r(high_coeff, rv_coefficient.upper(), ROUND_NOT_NEEDED);
5034  if (low_coeff != 0 || high_coeff != 0) {
5035  do_update = true;
5036  }
5037  }
5038 
5039  if (do_update) {
5040  Variable var(v);
5041  dimension_type n_var = v + 1;
5042  linear_form_upper_bound(right_minus_left + var, upper_bound);
5043  add_dbm_constraint(0, n_var, upper_bound);
5044  linear_form_upper_bound(right_minus_left - var, upper_bound);
5045  add_dbm_constraint(n_var, 0, upper_bound);
5046  }
5047  }
5048 
5049 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
size_t dimension_type
An unsigned integral type for representing space dimensions.
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
void linear_form_upper_bound(const Linear_Form< Interval< T, Interval_Info > > &lf, N &result) const
void add_dbm_constraint(dimension_type i, dimension_type j, const N &k)
Adds the constraint dbm[i][j] <= k.
#define PPL_DIRTY_TEMP(T, id)
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image ( Variable  var,
Relation_Symbol  relsym,
const Linear_Expression expr,
Coefficient_traits::const_reference  denominator = Coefficient_one() 
)

Assigns to *this the image of *this with respect to the affine relation $\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym.

Parameters
varThe left hand side variable of the generalized affine transfer function.
relsymThe relation symbol.
exprThe numerator of the right hand side affine expression.
denominatorThe denominator of the right hand side affine expression.
Exceptions
std::invalid_argumentThrown 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 5559 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::Linear_Expression::all_zeroes(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::begin(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::Linear_Expression::get(), 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::Linear_Expression::last_nonzero(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::Linear_Expression::lower_bound(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::NOT_EQUAL, Parma_Polyhedra_Library::PLUS_INFINITY, PPL_DIRTY_TEMP, PPL_DIRTY_TEMP_COEFFICIENT, PPL_UNINITIALIZED, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::ROUND_UP, Parma_Polyhedra_Library::Boundary_NS::sgn(), and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

5563  {
5564  // The denominator cannot be zero.
5565  if (denominator == 0) {
5566  throw_invalid_argument("generalized_affine_image(v, r, e, d)", "d == 0");
5567  }
5568  // Dimension-compatibility checks.
5569  // The dimension of `expr' should not be greater than the dimension
5570  // of `*this'.
5571  const dimension_type space_dim = space_dimension();
5572  const dimension_type expr_space_dim = expr.space_dimension();
5573  if (space_dim < expr_space_dim) {
5574  throw_dimension_incompatible("generalized_affine_image(v, r, e, d)",
5575  "e", expr);
5576  }
5577  // `var' should be one of the dimensions of the BDS.
5578  const dimension_type v = var.id() + 1;
5579  if (v > space_dim) {
5580  throw_dimension_incompatible("generalized_affine_image(v, r, e, d)",
5581  var.id());
5582  }
5583  // The relation symbol cannot be a strict relation symbol.
5584  if (relsym == LESS_THAN || relsym == GREATER_THAN) {
5585  throw_invalid_argument("generalized_affine_image(v, r, e, d)",
5586  "r is a strict relation symbol");
5587  }
5588  // The relation symbol cannot be a disequality.
5589  if (relsym == NOT_EQUAL) {
5590  throw_invalid_argument("generalized_affine_image(v, r, e, d)",
5591  "r is the disequality relation symbol");
5592  }
5593  if (relsym == EQUAL) {
5594  // The relation symbol is "=":
5595  // this is just an affine image computation.
5596  affine_image(var, expr, denominator);
5597  return;
5598  }
5599 
5600  // The image of an empty BDS is empty too.
5602  if (marked_empty()) {
5603  return;
5604  }
5605  const Coefficient& b = expr.inhomogeneous_term();
5606  // Number of non-zero coefficients in `expr': will be set to
5607  // 0, 1, or 2, the latter value meaning any value greater than 1.
5608  dimension_type t = 0;
5609  // Index of the last non-zero coefficient in `expr', if any.
5610  dimension_type w = expr.last_nonzero();
5611 
5612  if (w != 0) {
5613  ++t;
5614  if (!expr.all_zeroes(1, w)) {
5615  ++t;
5616  }
5617  }
5618 
5619  // Now we know the form of `expr':
5620  // - If t == 0, then expr == b, with `b' a constant;
5621  // - If t == 1, then expr == a*w + b, where `w' can be `v' or another
5622  // variable; in this second case we have to check whether `a' is
5623  // equal to `denominator' or `-denominator', since otherwise we have
5624  // to fall back on the general form;
5625  // - If t == 2, the `expr' is of the general form.
5626  DB_Row<N>& dbm_0 = dbm[0];
5627  DB_Row<N>& dbm_v = dbm[v];
5628  PPL_DIRTY_TEMP_COEFFICIENT(minus_denom);
5629  neg_assign(minus_denom, denominator);
5630 
5631  if (t == 0) {
5632  // Case 1: expr == b.
5633  // Remove all constraints on `var'.
5635  // Both shortest-path closure and reduction are lost.
5637  switch (relsym) {
5638  case LESS_OR_EQUAL:
5639  // Add the constraint `var <= b/denominator'.
5640  add_dbm_constraint(0, v, b, denominator);
5641  break;
5642  case GREATER_OR_EQUAL:
5643  // Add the constraint `var >= b/denominator',
5644  // i.e., `-var <= -b/denominator',
5645  add_dbm_constraint(v, 0, b, minus_denom);
5646  break;
5647  default:
5648  // We already dealt with the other cases.
5649  PPL_UNREACHABLE;
5650  break;
5651  }
5652  PPL_ASSERT(OK());
5653  return;
5654  }
5655 
5656  if (t == 1) {
5657  // Value of the one and only non-zero coefficient in `expr'.
5658  const Coefficient& a = expr.get(Variable(w - 1));
5659  if (a == denominator || a == minus_denom) {
5660  // Case 2: expr == a*w + b, with a == +/- denominator.
5661  PPL_DIRTY_TEMP(N, d);
5662  switch (relsym) {
5663  case LESS_OR_EQUAL:
5664  div_round_up(d, b, denominator);
5665  if (w == v) {
5666  // `expr' is of the form: a*v + b.
5667  // Shortest-path closure and reduction are not preserved.
5669  if (a == denominator) {
5670  // Translate each constraint `v - w <= dbm_wv'
5671  // into the constraint `v - w <= dbm_wv + b/denominator';
5672  // forget each constraint `w - v <= dbm_vw'.
5673  for (dimension_type i = space_dim + 1; i-- > 0; ) {
5674  N& dbm_iv = dbm[i][v];
5675  add_assign_r(dbm_iv, dbm_iv, d, ROUND_UP);
5677  }
5678  }
5679  else {
5680  // Here `a == -denominator'.
5681  // Translate the constraint `0 - v <= dbm_v0'
5682  // into the constraint `0 - v <= dbm_v0 + b/denominator'.
5683  N& dbm_v0 = dbm_v[0];
5684  add_assign_r(dbm_0[v], dbm_v0, d, ROUND_UP);
5685  // Forget all the other constraints on `v'.
5688  }
5689  }
5690  else {
5691  // Here `w != v', so that `expr' is of the form
5692  // +/-denominator * w + b, with `w != v'.
5693  // Remove all constraints on `v'.
5695  // Shortest-path closure is preserved, but not reduction.
5698  }
5699  if (a == denominator) {
5700  // Add the new constraint `v - w <= b/denominator'.
5701  add_dbm_constraint(w, v, d);
5702  }
5703  else {
5704  // Here a == -denominator, so that we should be adding
5705  // the constraint `v <= b/denominator - w'.
5706  // Approximate it by computing a lower bound for `w'.
5707  const N& dbm_w0 = dbm[w][0];
5708  if (!is_plus_infinity(dbm_w0)) {
5709  // Add the constraint `v <= b/denominator - lb_w'.
5710  add_assign_r(dbm_0[v], d, dbm_w0, ROUND_UP);
5711  // Shortest-path closure is not preserved.
5713  }
5714  }
5715  }
5716  break;
5717 
5718  case GREATER_OR_EQUAL:
5719  div_round_up(d, b, minus_denom);
5720  if (w == v) {
5721  // `expr' is of the form: a*w + b.
5722  // Shortest-path closure and reduction are not preserved.
5724  if (a == denominator) {
5725  // Translate each constraint `w - v <= dbm_vw'
5726  // into the constraint `w - v <= dbm_vw - b/denominator';
5727  // forget each constraint `v - w <= dbm_wv'.
5728  for (dimension_type i = space_dim + 1; i-- > 0; ) {
5729  N& dbm_vi = dbm_v[i];
5730  add_assign_r(dbm_vi, dbm_vi, d, ROUND_UP);
5732  }
5733  }
5734  else {
5735  // Here `a == -denominator'.
5736  // Translate the constraint `0 - v <= dbm_v0'
5737  // into the constraint `0 - v <= dbm_0v - b/denominator'.
5738  N& dbm_0v = dbm_0[v];
5739  add_assign_r(dbm_v[0], dbm_0v, d, ROUND_UP);
5740  // Forget all the other constraints on `v'.
5743  }
5744  }
5745  else {
5746  // Here `w != v', so that `expr' is of the form
5747  // +/-denominator * w + b, with `w != v'.
5748  // Remove all constraints on `v'.
5750  // Shortest-path closure is preserved, but not reduction.
5753  }
5754  if (a == denominator) {
5755  // Add the new constraint `v - w >= b/denominator',
5756  // i.e., `w - v <= -b/denominator'.
5757  add_dbm_constraint(v, w, d);
5758  }
5759  else {
5760  // Here a == -denominator, so that we should be adding
5761  // the constraint `v >= -w + b/denominator',
5762  // i.e., `-v <= w - b/denominator'.
5763  // Approximate it by computing an upper bound for `w'.
5764  const N& dbm_0w = dbm_0[w];
5765  if (!is_plus_infinity(dbm_0w)) {
5766  // Add the constraint `-v <= ub_w - b/denominator'.
5767  add_assign_r(dbm_v[0], dbm_0w, d, ROUND_UP);
5768  // Shortest-path closure is not preserved.
5770  }
5771  }
5772  }
5773  break;
5774 
5775  default:
5776  // We already dealt with the other cases.
5777  PPL_UNREACHABLE;
5778  break;
5779  }
5780  PPL_ASSERT(OK());
5781  return;
5782  }
5783  }
5784 
5785  // General case.
5786  // Either t == 2, so that
5787  // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
5788  // or t == 1, expr == a*w + b, but a <> +/- denominator.
5789  // We will remove all the constraints on `v' and add back
5790  // a constraint providing an upper or a lower bound for `v'
5791  // (depending on `relsym').
5792  const bool is_sc = (denominator > 0);
5793  PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
5794  neg_assign(minus_b, b);
5795  const Coefficient& sc_b = is_sc ? b : minus_b;
5796  const Coefficient& minus_sc_b = is_sc ? minus_b : b;
5797  const Coefficient& sc_denom = is_sc ? denominator : minus_denom;
5798  const Coefficient& minus_sc_denom = is_sc ? minus_denom : denominator;
5799  // NOTE: here, for optimization purposes, `minus_expr' is only assigned
5800  // when `denominator' is negative. Do not use it unless you are sure
5801  // it has been correctly assigned.
5802  Linear_Expression minus_expr;
5803  if (!is_sc) {
5804  minus_expr = -expr;
5805  }
5806  const Linear_Expression& sc_expr = is_sc ? expr : minus_expr;
5807 
5808  PPL_DIRTY_TEMP(N, sum);
5809  // Index of variable that is unbounded in `this->dbm'.
5810  PPL_UNINITIALIZED(dimension_type, pinf_index);
5811  // Number of unbounded variables found.
5812  dimension_type pinf_count = 0;
5813 
5814  // Speculative allocation of temporaries to be used in the following loops.
5815  PPL_DIRTY_TEMP(N, coeff_i);
5816  PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
5817 
5818  switch (relsym) {
5819  case LESS_OR_EQUAL:
5820  // Compute an upper approximation for `sc_expr' into `sum'.
5821 
5822  // Approximate the inhomogeneous term.
5823  assign_r(sum, sc_b, ROUND_UP);
5824  // Approximate the homogeneous part of `sc_expr'.
5825  // Note: indices above `w' can be disregarded, as they all have
5826  // a zero coefficient in `sc_expr'.
5827  PPL_ASSERT(w != 0);
5828  for (Linear_Expression::const_iterator i = sc_expr.begin(),
5829  i_end = sc_expr.lower_bound(Variable(w)); i != i_end; ++i) {
5830  const Coefficient& sc_i = *i;
5831  const dimension_type i_dim = i.variable().space_dimension();
5832  const int sign_i = sgn(sc_i);
5833  PPL_ASSERT(sign_i != 0);
5834  // Choose carefully: we are approximating `sc_expr'.
5835  const N& approx_i = (sign_i > 0) ? dbm_0[i_dim] : dbm[i_dim][0];
5836  if (is_plus_infinity(approx_i)) {
5837  if (++pinf_count > 1) {
5838  break;
5839  }
5840  pinf_index = i_dim;
5841  continue;
5842  }
5843  if (sign_i > 0) {
5844  assign_r(coeff_i, sc_i, ROUND_UP);
5845  }
5846  else {
5847  neg_assign(minus_sc_i, sc_i);
5848  assign_r(coeff_i, minus_sc_i, ROUND_UP);
5849  }
5850  add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
5851  }
5852 
5853  // Remove all constraints on `v'.
5855  // Shortest-path closure is preserved, but not reduction.
5858  }
5859  // Return immediately if no approximation could be computed.
5860  if (pinf_count > 1) {
5861  PPL_ASSERT(OK());
5862  return;
5863  }
5864 
5865  // Divide by the (sign corrected) denominator (if needed).
5866  if (sc_denom != 1) {
5867  // Before computing the quotient, the denominator should be approximated
5868  // towards zero. Since `sc_denom' is known to be positive, this amounts to
5869  // rounding downwards, which is achieved as usual by rounding upwards
5870  // `minus_sc_denom' and negating again the result.
5871  PPL_DIRTY_TEMP(N, down_sc_denom);
5872  assign_r(down_sc_denom, minus_sc_denom, ROUND_UP);
5873  neg_assign_r(down_sc_denom, down_sc_denom, ROUND_UP);
5874  div_assign_r(sum, sum, down_sc_denom, ROUND_UP);
5875  }
5876 
5877  if (pinf_count == 0) {
5878  // Add the constraint `v <= sum'.
5879  add_dbm_constraint(0, v, sum);
5880  // Deduce constraints of the form `v - u', where `u != v'.
5881  deduce_v_minus_u_bounds(v, w, sc_expr, sc_denom, sum);
5882  }
5883  else if (pinf_count == 1) {
5884  if (pinf_index != v
5885  && expr.get(Variable(pinf_index - 1)) == denominator) {
5886  // Add the constraint `v - pinf_index <= sum'.
5887  add_dbm_constraint(pinf_index, v, sum);
5888  }
5889  }
5890  break;
5891 
5892  case GREATER_OR_EQUAL:
5893  // Compute an upper approximation for `-sc_expr' into `sum'.
5894  // Note: approximating `-sc_expr' from above and then negating the
5895  // result is the same as approximating `sc_expr' from below.
5896 
5897  // Approximate the inhomogeneous term.
5898  assign_r(sum, minus_sc_b, ROUND_UP);
5899  // Approximate the homogeneous part of `-sc_expr'.
5900  for (Linear_Expression::const_iterator i = sc_expr.begin(),
5901  i_end = sc_expr.lower_bound(Variable(w)); i != i_end; ++i) {
5902  const Coefficient& sc_i = *i;
5903  const int sign_i = sgn(sc_i);
5904  PPL_ASSERT(sign_i != 0);
5905  const dimension_type i_dim = i.variable().space_dimension();
5906  // Choose carefully: we are approximating `-sc_expr'.
5907  const N& approx_i = (sign_i > 0) ? dbm[i_dim][0] : dbm_0[i_dim];
5908  if (is_plus_infinity(approx_i)) {
5909  if (++pinf_count > 1) {
5910  break;
5911  }
5912  pinf_index = i_dim;
5913  continue;
5914  }
5915  if (sign_i > 0) {
5916  assign_r(coeff_i, sc_i, ROUND_UP);
5917  }
5918  else {
5919  neg_assign(minus_sc_i, sc_i);
5920  assign_r(coeff_i, minus_sc_i, ROUND_UP);
5921  }
5922  add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
5923  }
5924 
5925  // Remove all constraints on `var'.
5927  // Shortest-path closure is preserved, but not reduction.
5930  }
5931  // Return immediately if no approximation could be computed.
5932  if (pinf_count > 1) {
5933  PPL_ASSERT(OK());
5934  return;
5935  }
5936 
5937  // Divide by the (sign corrected) denominator (if needed).
5938  if (sc_denom != 1) {
5939  // Before computing the quotient, the denominator should be approximated
5940  // towards zero. Since `sc_denom' is known to be positive, this amounts to
5941  // rounding downwards, which is achieved as usual by rounding upwards
5942  // `minus_sc_denom' and negating again the result.
5943  PPL_DIRTY_TEMP(N, down_sc_denom);
5944  assign_r(down_sc_denom, minus_sc_denom, ROUND_UP);
5945  neg_assign_r(down_sc_denom, down_sc_denom, ROUND_UP);
5946  div_assign_r(sum, sum, down_sc_denom, ROUND_UP);
5947  }
5948 
5949  if (pinf_count == 0) {
5950  // Add the constraint `v >= -sum', i.e., `-v <= sum'.
5951  add_dbm_constraint(v, 0, sum);
5952  // Deduce constraints of the form `u - v', where `u != v'.
5953  deduce_u_minus_v_bounds(v, w, sc_expr, sc_denom, sum);
5954  }
5955  else if (pinf_count == 1) {
5956  if (pinf_index != v
5957  && expr.get(Variable(pinf_index - 1)) == denominator) {
5958  // Add the constraint `v - pinf_index >= -sum',
5959  // i.e., `pinf_index - v <= sum'.
5960  add_dbm_constraint(v, pinf_index, sum);
5961  }
5962  }
5963  break;
5964 
5965  default:
5966  // We already dealt with the other cases.
5967  PPL_UNREACHABLE;
5968  break;
5969  }
5970  PPL_ASSERT(OK());
5971 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
void deduce_u_minus_v_bounds(dimension_type v, dimension_type last_v, const Linear_Expression &sc_expr, Coefficient_traits::const_reference sc_denom, const N &minus_lb_v)
An helper function for the computation of affine relations.
size_t dimension_type
An unsigned integral type for representing space dimensions.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
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 ex...
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
bool marked_shortest_path_reduced() const
Returns true if the system of bounded differences is known to be shortest-path reduced.
Enable_If< Is_Native_Or_Checked< T >::value, void >::type div_round_up(T &to, Coefficient_traits::const_reference x, Coefficient_traits::const_reference y)
Divides x by y into to, rounding the result towards plus infinity.
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
void reset_shortest_path_closed()
Marks *this as possibly not shortest-path closed.
void add_dbm_constraint(dimension_type i, dimension_type j, const N &k)
Adds the constraint dbm[i][j] <= k.
static void throw_invalid_argument(const char *method, const char *reason)
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
void deduce_v_minus_u_bounds(dimension_type v, dimension_type last_v, const Linear_Expression &sc_expr, Coefficient_traits::const_reference sc_denom, const N &ub_v)
An helper function for the computation of affine relations.
#define PPL_DIRTY_TEMP(T, id)
bool OK() const
Returns true if and only if *this satisfies all its invariants.
void forget_binary_dbm_constraints(dimension_type v)
Removes all binary constraints on row/column v.
Plus_Infinity PLUS_INFINITY
Definition: checked.cc:31
void neg_assign(GMP_Integer &x)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
int sgn(Boundary_Type type, const T &x, const Info &info)
void forget_all_dbm_constraints(dimension_type v)
Removes all the constraints on row/column v.
void reset_shortest_path_reduced()
Marks *this as possibly not shortest-path reduced.
#define PPL_UNINITIALIZED(type, name)
Definition: compiler.hh:72
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image ( const Linear_Expression lhs,
Relation_Symbol  relsym,
const Linear_Expression rhs 
)

Assigns to *this the image of *this with respect to the affine relation $\mathrm{lhs}' \relsym \mathrm{rhs}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym.

Parameters
lhsThe left hand side affine expression.
relsymThe relation symbol.
rhsThe right hand side affine expression.
Exceptions
std::invalid_argumentThrown if *this is dimension-incompatible with lhs or rhs or if relsym is a strict relation symbol.

Definition at line 5975 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::Linear_Expression::all_zeroes(), Parma_Polyhedra_Library::Linear_Expression::begin(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Linear_Expression::end(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Linear_Expression::have_a_common_variable(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Linear_Expression::last_nonzero(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::NOT_EQUAL, and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

5977  {
5978  // Dimension-compatibility checks.
5979  // The dimension of `lhs' should not be greater than the dimension
5980  // of `*this'.
5981  const dimension_type space_dim = space_dimension();
5982  const dimension_type lhs_space_dim = lhs.space_dimension();
5983  if (space_dim < lhs_space_dim) {
5984  throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
5985  "e1", lhs);
5986  }
5987  // The dimension of `rhs' should not be greater than the dimension
5988  // of `*this'.
5989  const dimension_type rhs_space_dim = rhs.space_dimension();
5990  if (space_dim < rhs_space_dim) {
5991  throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
5992  "e2", rhs);
5993  }
5994  // Strict relation symbols are not admitted for BDSs.
5995  if (relsym == LESS_THAN || relsym == GREATER_THAN) {
5996  throw_invalid_argument("generalized_affine_image(e1, r, e2)",
5997  "r is a strict relation symbol");
5998  }
5999  // The relation symbol cannot be a disequality.
6000  if (relsym == NOT_EQUAL) {
6001  throw_invalid_argument("generalized_affine_image(e1, r, e2)",
6002  "r is the disequality relation symbol");
6003  }
6004  // The image of an empty BDS is empty.
6006  if (marked_empty()) {
6007  return;
6008  }
6009  // Number of non-zero coefficients in `lhs': will be set to
6010  // 0, 1, or 2, the latter value meaning any value greater than 1.
6011  dimension_type t_lhs = 0;
6012  // Index of the last non-zero coefficient in `lhs', if any.
6013  dimension_type j_lhs = lhs.last_nonzero();
6014 
6015  if (j_lhs != 0) {
6016  ++t_lhs;
6017  if (!lhs.all_zeroes(1, j_lhs)) {
6018  ++t_lhs;
6019  }
6020  --j_lhs;
6021  }
6022 
6023  const Coefficient& b_lhs = lhs.inhomogeneous_term();
6024 
6025  if (t_lhs == 0) {
6026  // `lhs' is a constant.
6027  // In principle, it is sufficient to add the constraint `lhs relsym rhs'.
6028  // Note that this constraint is a bounded difference if `t_rhs <= 1'
6029  // or `t_rhs > 1' and `rhs == a*v - a*w + b_rhs'. If `rhs' is of a
6030  // more general form, it will be simply ignored.
6031  // TODO: if it is not a bounded difference, should we compute
6032  // approximations for this constraint?
6033  switch (relsym) {
6034  case LESS_OR_EQUAL:
6035  refine_no_check(lhs <= rhs);
6036  break;
6037  case EQUAL:
6038  refine_no_check(lhs == rhs);
6039  break;
6040  case GREATER_OR_EQUAL:
6041  refine_no_check(lhs >= rhs);
6042  break;
6043  default:
6044  // We already dealt with the other cases.
6045  PPL_UNREACHABLE;
6046  break;
6047  }
6048  }
6049  else if (t_lhs == 1) {
6050  // Here `lhs == a_lhs * v + b_lhs'.
6051  // Independently from the form of `rhs', we can exploit the
6052  // method computing generalized affine images for a single variable.
6053  Variable v(j_lhs);
6054  // Compute a sign-corrected relation symbol.
6055  const Coefficient& denom = lhs.coefficient(v);
6056  Relation_Symbol new_relsym = relsym;
6057  if (denom < 0) {
6058  if (relsym == LESS_OR_EQUAL) {
6059  new_relsym = GREATER_OR_EQUAL;
6060  }
6061  else if (relsym == GREATER_OR_EQUAL) {
6062  new_relsym = LESS_OR_EQUAL;
6063  }
6064  }
6065  Linear_Expression expr = rhs - b_lhs;
6066  generalized_affine_image(v, new_relsym, expr, denom);
6067  }
6068  else {
6069  // Here `lhs' is of the general form, having at least two variables.
6070  // Compute the set of variables occurring in `lhs'.
6071  std::vector<Variable> lhs_vars;
6072  for (Linear_Expression::const_iterator i = lhs.begin(), i_end = lhs.end();
6073  i != i_end; ++i) {
6074  lhs_vars.push_back(i.variable());
6075  }
6076  const dimension_type num_common_dims = std::min(lhs_space_dim, rhs_space_dim);
6077  if (!lhs.have_a_common_variable(rhs, Variable(0), Variable(num_common_dims))) {
6078  // `lhs' and `rhs' variables are disjoint.
6079  // Existentially quantify all variables in the lhs.
6080  for (dimension_type i = lhs_vars.size(); i-- > 0; ) {
6081  forget_all_dbm_constraints(lhs_vars[i].id() + 1);
6082  }
6083  // Constrain the left hand side expression so that it is related to
6084  // the right hand side expression as dictated by `relsym'.
6085  // TODO: if the following constraint is NOT a bounded difference,
6086  // it will be simply ignored. Should we compute approximations for it?
6087  switch (relsym) {
6088  case LESS_OR_EQUAL:
6089  refine_no_check(lhs <= rhs);
6090  break;
6091  case EQUAL:
6092  refine_no_check(lhs == rhs);
6093  break;
6094  case GREATER_OR_EQUAL:
6095  refine_no_check(lhs >= rhs);
6096  break;
6097  default:
6098  // We already dealt with the other cases.
6099  PPL_UNREACHABLE;
6100  break;
6101  }
6102  }
6103  else {
6104  // Some variables in `lhs' also occur in `rhs'.
6105 
6106 #if 1 // Simplified computation (see the TODO note below).
6107 
6108  for (dimension_type i = lhs_vars.size(); i-- > 0; ) {
6109  forget_all_dbm_constraints(lhs_vars[i].id() + 1);
6110  }
6111 #else // Currently unnecessarily complex computation.
6112 
6113  // More accurate computation that is worth doing only if
6114  // the following TODO note is accurately dealt with.
6115 
6116  // To ease the computation, we add an additional dimension.
6117  const Variable new_var(space_dim);
6119  // Constrain the new dimension to be equal to `rhs'.
6120  // NOTE: calling affine_image() instead of refine_no_check()
6121  // ensures some approximation is tried even when the constraint
6122  // is not a bounded difference.
6123  affine_image(new_var, rhs);
6124  // Existentially quantify all variables in the lhs.
6125  // NOTE: enforce shortest-path closure for precision.
6127  PPL_ASSERT(!marked_empty());
6128  for (dimension_type i = lhs_vars.size(); i-- > 0; ) {
6129  forget_all_dbm_constraints(lhs_vars[i].id() + 1);
6130  }
6131  // Constrain the new dimension so that it is related to
6132  // the left hand side as dictated by `relsym'.
6133  // TODO: each one of the following constraints is definitely NOT
6134  // a bounded differences (since it has 3 variables at least).
6135  // Thus, the method refine_no_check() will simply ignore it.
6136  // Should we compute approximations for this constraint?
6137  switch (relsym) {
6138  case LESS_OR_EQUAL:
6139  refine_no_check(lhs <= new_var);
6140  break;
6141  case EQUAL:
6142  refine_no_check(lhs == new_var);
6143  break;
6144  case GREATER_OR_EQUAL:
6145  refine_no_check(lhs >= new_var);
6146  break;
6147  default:
6148  // We already dealt with the other cases.
6149  PPL_UNREACHABLE;
6150  break;
6151  }
6152  // Remove the temporarily added dimension.
6153  remove_higher_space_dimensions(space_dim-1);
6154 #endif // Currently unnecessarily complex computation.
6155  }
6156  }
6157 
6158  PPL_ASSERT(OK());
6159 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
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 ex...
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
void generalized_affine_image(Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
Assigns to *this the image of *this with respect to the affine relation , where is the relation symb...
void add_space_dimensions_and_embed(dimension_type m)
Adds m new dimensions and embeds the old BDS into the new space.
void refine_no_check(const Constraint &c)
Uses the constraint c to refine *this.
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
Relation_Symbol
Relation symbols.
static void throw_invalid_argument(const char *method, const char *reason)
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void forget_all_dbm_constraints(dimension_type v)
Removes all the constraints on row/column v.
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 T >
void Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage ( Variable  var,
Relation_Symbol  relsym,
const Linear_Expression expr,
Coefficient_traits::const_reference  denominator = Coefficient_one() 
)

Assigns to *this the preimage of *this with respect to the affine relation $\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym.

Parameters
varThe left hand side variable of the generalized affine transfer function.
relsymThe relation symbol.
exprThe numerator of the right hand side affine expression.
denominatorThe denominator of the right hand side affine expression.
Exceptions
std::invalid_argumentThrown 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 6163 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::inverse(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::NOT_EQUAL, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Boundary_NS::sgn(), and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

6167  {
6168  // The denominator cannot be zero.
6169  if (denominator == 0) {
6170  throw_invalid_argument("generalized_affine_preimage(v, r, e, d)",
6171  "d == 0");
6172  }
6173  // Dimension-compatibility checks.
6174  // The dimension of `expr' should not be greater than the dimension
6175  // of `*this'.
6176  const dimension_type space_dim = space_dimension();
6177  const dimension_type expr_space_dim = expr.space_dimension();
6178  if (space_dim < expr_space_dim) {
6179  throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)",
6180  "e", expr);
6181  }
6182  // `var' should be one of the dimensions of the BDS.
6183  const dimension_type v = var.id() + 1;
6184  if (v > space_dim) {
6185  throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)",
6186  var.id());
6187  }
6188  // The relation symbol cannot be a strict relation symbol.
6189  if (relsym == LESS_THAN || relsym == GREATER_THAN) {
6190  throw_invalid_argument("generalized_affine_preimage(v, r, e, d)",
6191  "r is a strict relation symbol");
6192  }
6193  // The relation symbol cannot be a disequality.
6194  if (relsym == NOT_EQUAL) {
6195  throw_invalid_argument("generalized_affine_preimage(v, r, e, d)",
6196  "r is the disequality relation symbol");
6197  }
6198  if (relsym == EQUAL) {
6199  // The relation symbol is "=":
6200  // this is just an affine preimage computation.
6201  affine_preimage(var, expr, denominator);
6202  return;
6203  }
6204 
6205  // The preimage of an empty BDS is empty too.
6207  if (marked_empty()) {
6208  return;
6209  }
6210  // Check whether the preimage of this affine relation can be easily
6211  // computed as the image of its inverse relation.
6212  const Coefficient& expr_v = expr.coefficient(var);
6213  if (expr_v != 0) {
6214  const Relation_Symbol reversed_relsym = (relsym == LESS_OR_EQUAL)
6216  const Linear_Expression inverse
6217  = expr - (expr_v + denominator)*var;
6218  PPL_DIRTY_TEMP_COEFFICIENT(inverse_denom);
6219  neg_assign(inverse_denom, expr_v);
6220  const Relation_Symbol inverse_relsym
6221  = (sgn(denominator) == sgn(inverse_denom)) ? relsym : reversed_relsym;
6222  generalized_affine_image(var, inverse_relsym, inverse, inverse_denom);
6223  return;
6224  }
6225 
6226  refine(var, relsym, expr, denominator);
6227  // If the shrunk BD_Shape is empty, its preimage is empty too; ...
6228  if (is_empty()) {
6229  return;
6230  }
6231  // ... otherwise, since the relation was not invertible,
6232  // we just forget all constraints on `v'.
6234  // Shortest-path closure is preserved, but not reduction.
6237  }
6238  PPL_ASSERT(OK());
6239 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
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...
void generalized_affine_image(Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
Assigns to *this the image of *this with respect to the affine relation , where is the relation symb...
bool marked_shortest_path_reduced() const
Returns true if the system of bounded differences is known to be shortest-path reduced.
bool is_empty() const
Returns true if and only if *this is an empty BDS.
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
Rounding_Dir inverse(Rounding_Dir dir)
Relation_Symbol
Relation symbols.
static void throw_invalid_argument(const char *method, const char *reason)
void refine(Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
Adds to the BDS the constraint .
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
void neg_assign(GMP_Integer &x)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
int sgn(Boundary_Type type, const T &x, const Info &info)
void forget_all_dbm_constraints(dimension_type v)
Removes all the constraints on row/column v.
void reset_shortest_path_reduced()
Marks *this as possibly not shortest-path reduced.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage ( const Linear_Expression lhs,
Relation_Symbol  relsym,
const Linear_Expression rhs 
)

Assigns to *this the preimage of *this with respect to the affine relation $\mathrm{lhs}' \relsym \mathrm{rhs}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym.

Parameters
lhsThe left hand side affine expression.
relsymThe relation symbol.
rhsThe right hand side affine expression.
Exceptions
std::invalid_argumentThrown if *this is dimension-incompatible with lhs or rhs or if relsym is a strict relation symbol.

Definition at line 6243 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::Linear_Expression::all_zeroes(), Parma_Polyhedra_Library::Linear_Expression::begin(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Linear_Expression::end(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Linear_Expression::have_a_common_variable(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Linear_Expression::last_nonzero(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::NOT_EQUAL, and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

6245  {
6246  // Dimension-compatibility checks.
6247  // The dimension of `lhs' should not be greater than the dimension
6248  // of `*this'.
6249  const dimension_type bds_space_dim = space_dimension();
6250  const dimension_type lhs_space_dim = lhs.space_dimension();
6251  if (bds_space_dim < lhs_space_dim) {
6252  throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)",
6253  "e1", lhs);
6254  }
6255  // The dimension of `rhs' should not be greater than the dimension
6256  // of `*this'.
6257  const dimension_type rhs_space_dim = rhs.space_dimension();
6258  if (bds_space_dim < rhs_space_dim) {
6259  throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)",
6260  "e2", rhs);
6261  }
6262  // Strict relation symbols are not admitted for BDSs.
6263  if (relsym == LESS_THAN || relsym == GREATER_THAN) {
6264  throw_invalid_argument("generalized_affine_preimage(e1, r, e2)",
6265  "r is a strict relation symbol");
6266  }
6267  // The relation symbol cannot be a disequality.
6268  if (relsym == NOT_EQUAL) {
6269  throw_invalid_argument("generalized_affine_preimage(e1, r, e2)",
6270  "r is the disequality relation symbol");
6271  }
6272  // The preimage of an empty BDS is empty.
6274  if (marked_empty()) {
6275  return;
6276  }
6277  // Number of non-zero coefficients in `lhs': will be set to
6278  // 0, 1, or 2, the latter value meaning any value greater than 1.
6279  dimension_type t_lhs = 0;
6280  // Index of the last non-zero coefficient in `lhs', if any.
6281  dimension_type j_lhs = lhs.last_nonzero();
6282 
6283  if (j_lhs != 0) {
6284  ++t_lhs;
6285  if (!lhs.all_zeroes(1, j_lhs)) {
6286  ++t_lhs;
6287  }
6288  --j_lhs;
6289  }
6290 
6291  const Coefficient& b_lhs = lhs.inhomogeneous_term();
6292 
6293  if (t_lhs == 0) {
6294  // `lhs' is a constant.
6295  // In this case, preimage and image happen to be the same.
6296  generalized_affine_image(lhs, relsym, rhs);
6297  return;
6298  }
6299  else if (t_lhs == 1) {
6300  // Here `lhs == a_lhs * v + b_lhs'.
6301  // Independently from the form of `rhs', we can exploit the
6302  // method computing generalized affine preimages for a single variable.
6303  Variable v(j_lhs);
6304  // Compute a sign-corrected relation symbol.
6305  const Coefficient& denom = lhs.coefficient(v);
6306  Relation_Symbol new_relsym = relsym;
6307  if (denom < 0) {
6308  if (relsym == LESS_OR_EQUAL) {
6309  new_relsym = GREATER_OR_EQUAL;
6310  }
6311  else if (relsym == GREATER_OR_EQUAL) {
6312  new_relsym = LESS_OR_EQUAL;
6313  }
6314  }
6315  Linear_Expression expr = rhs - b_lhs;
6316  generalized_affine_preimage(v, new_relsym, expr, denom);
6317  }
6318  else {
6319  // Here `lhs' is of the general form, having at least two variables.
6320  // Compute the set of variables occurring in `lhs'.
6321  std::vector<Variable> lhs_vars;
6322  for (Linear_Expression::const_iterator i = lhs.begin(), i_end = lhs.end();
6323  i != i_end; ++i) {
6324  lhs_vars.push_back(i.variable());
6325  }
6326  const dimension_type num_common_dims = std::min(lhs_space_dim, rhs_space_dim);
6327  if (!lhs.have_a_common_variable(rhs, Variable(0), Variable(num_common_dims))) {
6328  // `lhs' and `rhs' variables are disjoint.
6329 
6330  // Constrain the left hand side expression so that it is related to
6331  // the right hand side expression as dictated by `relsym'.
6332  // TODO: if the following constraint is NOT a bounded difference,
6333  // it will be simply ignored. Should we compute approximations for it?
6334  switch (relsym) {
6335  case LESS_OR_EQUAL:
6336  refine_no_check(lhs <= rhs);
6337  break;
6338  case EQUAL:
6339  refine_no_check(lhs == rhs);
6340  break;
6341  case GREATER_OR_EQUAL:
6342  refine_no_check(lhs >= rhs);
6343  break;
6344  default:
6345  // We already dealt with the other cases.
6346  PPL_UNREACHABLE;
6347  break;
6348  }
6349 
6350  // If the shrunk BD_Shape is empty, its preimage is empty too; ...
6351  if (is_empty()) {
6352  return;
6353  }
6354  // Existentially quantify all variables in the lhs.
6355  for (dimension_type i = lhs_vars.size(); i-- > 0; ) {
6356  forget_all_dbm_constraints(lhs_vars[i].id() + 1);
6357  }
6358  }
6359  else {
6360 
6361  // Some variables in `lhs' also occur in `rhs'.
6362  // To ease the computation, we add an additional dimension.
6363  const Variable new_var(bds_space_dim);
6365  // Constrain the new dimension to be equal to `lhs'.
6366  // NOTE: calling affine_image() instead of refine_no_check()
6367  // ensures some approximation is tried even when the constraint
6368  // is not a bounded difference.
6369  affine_image(new_var, lhs);
6370  // Existentiallly quantify all variables in the lhs.
6371  // NOTE: enforce shortest-path closure for precision.
6373  PPL_ASSERT(!marked_empty());
6374  for (dimension_type i = lhs_vars.size(); i-- > 0; ) {
6375  forget_all_dbm_constraints(lhs_vars[i].id() + 1);
6376  }
6377  // Constrain the new dimension so that it is related to
6378  // the left hand side as dictated by `relsym'.
6379  // Note: if `rhs == a_rhs*v + b_rhs' where `a_rhs' is in {0, 1},
6380  // then one of the following constraints will be added,
6381  // since it is a bounded difference. Else the method
6382  // refine_no_check() will ignore it, because the
6383  // constraint is NOT a bounded difference.
6384  switch (relsym) {
6385  case LESS_OR_EQUAL:
6386  refine_no_check(new_var <= rhs);
6387  break;
6388  case EQUAL:
6389  refine_no_check(new_var == rhs);
6390  break;
6391  case GREATER_OR_EQUAL:
6392  refine_no_check(new_var >= rhs);
6393  break;
6394  default:
6395  // We already dealt with the other cases.
6396  PPL_UNREACHABLE;
6397  break;
6398  }
6399  // Remove the temporarily added dimension.
6400  remove_higher_space_dimensions(bds_space_dim);
6401  }
6402  }
6403 
6404  PPL_ASSERT(OK());
6405 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
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 ex...
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
void generalized_affine_image(Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
Assigns to *this the image of *this with respect to the affine relation , where is the relation symb...
void add_space_dimensions_and_embed(dimension_type m)
Adds m new dimensions and embeds the old BDS into the new space.
bool is_empty() const
Returns true if and only if *this is an empty BDS.
void refine_no_check(const Constraint &c)
Uses the constraint c to refine *this.
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
Relation_Symbol
Relation symbols.
static void throw_invalid_argument(const char *method, const char *reason)
void generalized_affine_preimage(Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
Assigns to *this the preimage of *this with respect to the affine relation , where is the relation s...
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void forget_all_dbm_constraints(dimension_type v)
Removes all the constraints on row/column v.
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 T >
template<typename Interval_Info >
void Parma_Polyhedra_Library::BD_Shape< T >::generalized_refine_with_linear_form_inequality ( const Linear_Form< Interval< T, Interval_Info > > &  left,
const Linear_Form< Interval< T, Interval_Info > > &  right,
Relation_Symbol  relsym 
)
inline

Refines the system of BD_Shape constraints defining *this using the constraint expressed by left $\relsym$ right, where $\relsym$ is the relation symbol specified by relsym.

Parameters
leftThe linear form on intervals with floating point boundaries that is at the left of the comparison operator. All of its coefficients MUST be bounded.
rightThe linear form on intervals with floating point boundaries that is at the right of the comparison operator. All of its coefficients MUST be bounded.
relsymThe relation symbol.
Exceptions
std::invalid_argumentThrown if left (or right) is dimension-incompatible with *this.
std::runtime_errorThrown if relsym is not a valid relation symbol.

This function is used in abstract interpretation to model a filter that is generated by a comparison of two expressions that are correctly approximated by left and right respectively.

Definition at line 896 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, and Parma_Polyhedra_Library::NOT_EQUAL.

899  {
900  switch (relsym) {
901  case EQUAL:
902  // TODO: see if we can handle this case more efficiently.
905  break;
906  case LESS_THAN:
907  case LESS_OR_EQUAL:
909  break;
910  case GREATER_THAN:
911  case GREATER_OR_EQUAL:
913  break;
914  case NOT_EQUAL:
915  break;
916  default:
917  PPL_UNREACHABLE;
918  }
919 }
void refine_with_linear_form_inequality(const Linear_Form< Interval< T, Interval_Info > > &left, const Linear_Form< Interval< T, Interval_Info > > &right)
Refines the system of BD_Shape constraints defining *this using the constraint expressed by left rig...
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::get_limiting_shape ( const Constraint_System cs,
BD_Shape< T > &  limiting_shape 
) const
private

Adds to limiting_shape the bounded differences in cs that are satisfied by *this.

Definition at line 3133 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::Constraint_System::begin(), c, Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::BD_Shape_Helpers::extract_bounded_difference(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Constraint::is_inequality(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::neg_assign(), PPL_DIRTY_TEMP, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), and Parma_Polyhedra_Library::Constraint_System::space_dimension().

3134  {
3135  // Private method: the caller has to ensure the following.
3136  PPL_ASSERT(cs.space_dimension() <= space_dimension());
3137 
3139  bool changed = false;
3141  PPL_DIRTY_TEMP_COEFFICIENT(minus_c_term);
3142  PPL_DIRTY_TEMP(N, d);
3143  PPL_DIRTY_TEMP(N, d1);
3144  for (Constraint_System::const_iterator cs_i = cs.begin(),
3145  cs_end = cs.end(); cs_i != cs_end; ++cs_i) {
3146  const Constraint& c = *cs_i;
3147  dimension_type num_vars = 0;
3148  dimension_type i = 0;
3149  dimension_type j = 0;
3150  // Constraints that are not bounded differences are ignored.
3151  if (BD_Shape_Helpers::extract_bounded_difference(c, num_vars, i, j, coeff)) {
3152  // Select the cell to be modified for the "<=" part of the constraint,
3153  // and set `coeff' to the absolute value of itself.
3154  const bool negative = (coeff < 0);
3155  const N& x = negative ? dbm[i][j] : dbm[j][i];
3156  const N& y = negative ? dbm[j][i] : dbm[i][j];
3157  DB_Matrix<N>& ls_dbm = limiting_shape.dbm;
3158  if (negative) {
3159  neg_assign(coeff);
3160  }
3161  // Compute the bound for `x', rounding towards plus infinity.
3162  div_round_up(d, c.inhomogeneous_term(), coeff);
3163  if (x <= d) {
3164  if (c.is_inequality()) {
3165  N& ls_x = negative ? ls_dbm[i][j] : ls_dbm[j][i];
3166  if (ls_x > d) {
3167  ls_x = d;
3168  changed = true;
3169  }
3170  }
3171  else {
3172  // Compute the bound for `y', rounding towards plus infinity.
3173  neg_assign(minus_c_term, c.inhomogeneous_term());
3174  div_round_up(d1, minus_c_term, coeff);
3175  if (y <= d1) {
3176  N& ls_x = negative ? ls_dbm[i][j] : ls_dbm[j][i];
3177  N& ls_y = negative ? ls_dbm[j][i] : ls_dbm[i][j];
3178  if ((ls_x >= d && ls_y > d1) || (ls_x > d && ls_y >= d1)) {
3179  ls_x = d;
3180  ls_y = d1;
3181  changed = true;
3182  }
3183  }
3184  }
3185  }
3186  }
3187  }
3188 
3189  // In general, adding a constraint does not preserve the shortest-path
3190  // closure of the bounded difference shape.
3191  if (changed && limiting_shape.marked_shortest_path_closed()) {
3192  limiting_shape.reset_shortest_path_closed();
3193  }
3194 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
Enable_If< Is_Native_Or_Checked< T >::value, void >::type div_round_up(T &to, Coefficient_traits::const_reference x, Coefficient_traits::const_reference y)
Divides x by y into to, rounding the result towards plus infinity.
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
#define PPL_DIRTY_TEMP(T, id)
void neg_assign(GMP_Integer &x)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
static bool extract_bounded_difference(const Constraint &c, dimension_type &c_num_vars, dimension_type &c_first_var, dimension_type &c_second_var, Coefficient &c_coeff)
Decodes the constraint c as a bounded difference.
Coefficient c
Definition: PIP_Tree.cc:64
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
Constraint_System_const_iterator const_iterator
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::H79_widening_assign ( const BD_Shape< T > &  y,
unsigned *  tp = 0 
)
inline

Assigns to *this the result of computing the H79-widening between *this and y.

Parameters
yA BDS that must be contained in *this.
tpAn optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique).
Exceptions
std::invalid_argumentThrown if *this and y are dimension-incompatible.

Definition at line 849 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::constraints(), and Parma_Polyhedra_Library::Polyhedron::H79_widening_assign().

849  {
850  // Compute the H79 widening on polyhedra.
851  // TODO: provide a direct implementation.
852  C_Polyhedron ph_x(constraints());
853  C_Polyhedron ph_y(y.constraints());
854  ph_x.H79_widening_assign(ph_y, tp);
855  BD_Shape x(ph_x);
856  m_swap(x);
857  PPL_ASSERT(OK());
858 }
BD_Shape(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty BDS of the specified space dimension.
void m_swap(BD_Shape &y)
Swaps *this with y (*this and y can be dimension-incompatible).
Constraint_System constraints() const
Returns a system of constraints defining *this.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
template<typename T >
int32_t Parma_Polyhedra_Library::BD_Shape< T >::hash_code ( ) const
inline

Returns a 32-bit hash code for *this.

If x and y are such that x == y, then x.hash_code() == y.hash_code().

Definition at line 889 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::hash_code_from_dimension().

889  {
891 }
int32_t hash_code_from_dimension(dimension_type dim)
Returns the hash code for space dimension dim.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::incremental_shortest_path_closure_assign ( Variable  var) const
private

Incrementally computes shortest-path closure, assuming that only constraints affecting variable var need to be considered.

Note
It is assumed that *this, which was shortest-path closed, has only been modified by adding constraints affecting variable var. If this assumption is not satisfied, i.e., if a non-redundant constraint not affecting variable var has been added, the behavior is undefined.

Definition at line 1940 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::min_assign(), Parma_Polyhedra_Library::PLUS_INFINITY, PPL_DIRTY_TEMP, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::ROUND_UP, and Parma_Polyhedra_Library::Boundary_NS::sgn().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign().

1940  {
1941  // Do something only if necessary.
1943  return;
1944  }
1945  const dimension_type num_dimensions = space_dimension();
1946  PPL_ASSERT(var.id() < num_dimensions);
1947 
1948  // Even though the BDS will not change, its internal representation
1949  // is going to be modified by the incremental Floyd-Warshall algorithm.
1950  BD_Shape& x = const_cast<BD_Shape&>(*this);
1951 
1952  // Fill the main diagonal with zeros.
1953  for (dimension_type h = num_dimensions + 1; h-- > 0; ) {
1954  PPL_ASSERT(is_plus_infinity(x.dbm[h][h]));
1955  assign_r(x.dbm[h][h], 0, ROUND_NOT_NEEDED);
1956  }
1957 
1958  // Using the incremental Floyd-Warshall algorithm.
1959  PPL_DIRTY_TEMP(N, sum);
1960  const dimension_type v = var.id() + 1;
1961  DB_Row<N>& x_v = x.dbm[v];
1962  // Step 1: Improve all constraints on variable `var'.
1963  for (dimension_type k = num_dimensions + 1; k-- > 0; ) {
1964  DB_Row<N>& x_k = x.dbm[k];
1965  const N& x_v_k = x_v[k];
1966  const N& x_k_v = x_k[v];
1967  const bool x_v_k_finite = !is_plus_infinity(x_v_k);
1968  const bool x_k_v_finite = !is_plus_infinity(x_k_v);
1969  // Specialize inner loop based on finiteness info.
1970  if (x_v_k_finite) {
1971  if (x_k_v_finite) {
1972  // Here both x_v_k and x_k_v are finite.
1973  for (dimension_type i = num_dimensions + 1; i-- > 0; ) {
1974  DB_Row<N>& x_i = x.dbm[i];
1975  const N& x_i_k = x_i[k];
1976  if (!is_plus_infinity(x_i_k)) {
1977  add_assign_r(sum, x_i_k, x_k_v, ROUND_UP);
1978  min_assign(x_i[v], sum);
1979  }
1980  const N& x_k_i = x_k[i];
1981  if (!is_plus_infinity(x_k_i)) {
1982  add_assign_r(sum, x_v_k, x_k_i, ROUND_UP);
1983  min_assign(x_v[i], sum);
1984  }
1985  }
1986  }
1987  else {
1988  // Here x_v_k is finite, but x_k_v is not.
1989  for (dimension_type i = num_dimensions + 1; i-- > 0; ) {
1990  const N& x_k_i = x_k[i];
1991  if (!is_plus_infinity(x_k_i)) {
1992  add_assign_r(sum, x_v_k, x_k_i, ROUND_UP);
1993  min_assign(x_v[i], sum);
1994  }
1995  }
1996  }
1997  }
1998  else if (x_k_v_finite) {
1999  // Here x_v_k is infinite, but x_k_v is finite.
2000  for (dimension_type i = num_dimensions + 1; i-- > 0; ) {
2001  DB_Row<N>& x_i = x.dbm[i];
2002  const N& x_i_k = x_i[k];
2003  if (!is_plus_infinity(x_i_k)) {
2004  add_assign_r(sum, x_i_k, x_k_v, ROUND_UP);
2005  min_assign(x_i[v], sum);
2006  }
2007  }
2008  }
2009  else {
2010  // Here both x_v_k and x_k_v are infinite.
2011  continue;
2012  }
2013  }
2014 
2015  // Step 2: improve the other bounds by using the precise bounds
2016  // for the constraints on `var'.
2017  for (dimension_type i = num_dimensions + 1; i-- > 0; ) {
2018  DB_Row<N>& x_i = x.dbm[i];
2019  const N& x_i_v = x_i[v];
2020  if (!is_plus_infinity(x_i_v)) {
2021  for (dimension_type j = num_dimensions + 1; j-- > 0; ) {
2022  const N& x_v_j = x_v[j];
2023  if (!is_plus_infinity(x_v_j)) {
2024  add_assign_r(sum, x_i_v, x_v_j, ROUND_UP);
2025  min_assign(x_i[j], sum);
2026  }
2027  }
2028  }
2029  }
2030 
2031  // Check for emptiness: the BDS is empty if and only if there is a
2032  // negative value on the main diagonal of `dbm'.
2033  for (dimension_type h = num_dimensions + 1; h-- > 0; ) {
2034  N& x_dbm_hh = x.dbm[h][h];
2035  if (sgn(x_dbm_hh) < 0) {
2036  x.set_empty();
2037  return;
2038  }
2039  else {
2040  PPL_ASSERT(sgn(x_dbm_hh) == 0);
2041  // Restore PLUS_INFINITY on the main diagonal.
2043  }
2044  }
2045 
2046  // The BDS is not empty and it is now shortest-path closed.
2047  x.set_shortest_path_closed();
2048 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
size_t dimension_type
An unsigned integral type for representing space dimensions.
BD_Shape(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty BDS of the specified space dimension.
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
bool marked_shortest_path_closed() const
Returns true if the system of bounded differences is known to be shortest-path closed.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
#define PPL_DIRTY_TEMP(T, id)
Plus_Infinity PLUS_INFINITY
Definition: checked.cc:31
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
int sgn(Boundary_Type type, const T &x, const Info &info)
void min_assign(N &x, const N &y)
Assigns to x the minimum between x and y.
template<typename T >
template<typename Interval_Info >
void Parma_Polyhedra_Library::BD_Shape< T >::inhomogeneous_affine_form_image ( const dimension_type var_id,
const Interval< T, Interval_Info > &  b 
)
private

Auxiliary function for affine form image that handle the general case: $l = c$.

Definition at line 4443 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Interval< Boundary, Info >::lower(), PPL_DIRTY_TEMP, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, and Parma_Polyhedra_Library::Interval< Boundary, Info >::upper().

4444  {
4445  PPL_DIRTY_TEMP(N, b_ub);
4446  assign_r(b_ub, b.upper(), ROUND_NOT_NEEDED);
4447  PPL_DIRTY_TEMP(N, b_mlb);
4448  neg_assign_r(b_mlb, b.lower(), ROUND_NOT_NEEDED);
4449 
4450  // Remove all constraints on `var'.
4452  // Shortest-path closure is preserved, but not reduction.
4455  }
4456  // Add the constraint `var >= lb && var <= ub'.
4457  add_dbm_constraint(0, var_id, b_ub);
4458  add_dbm_constraint(var_id, 0, b_mlb);
4459  return;
4460 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
bool marked_shortest_path_reduced() const
Returns true if the system of bounded differences is known to be shortest-path reduced.
void add_dbm_constraint(dimension_type i, dimension_type j, const N &k)
Adds the constraint dbm[i][j] <= k.
#define PPL_DIRTY_TEMP(T, id)
void forget_all_dbm_constraints(dimension_type v)
Removes all the constraints on row/column v.
void reset_shortest_path_reduced()
Marks *this as possibly not shortest-path reduced.
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::integer_upper_bound_assign_if_exact ( const BD_Shape< T > &  y)
inline

If the integer upper bound of *this and y is exact, it is assigned to *this and true is returned; otherwise false is returned.

Exceptions
std::invalid_argumentThrown if *this and y are dimension-incompatible.
Note
The integer upper bound of two rational BDS is the smallest rational BDS containing all the integral points of the two arguments. This method requires that the coefficient type parameter T is an integral type.

Definition at line 766 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::is_integer(), PPL_COMPILE_TIME_CHECK, and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

766  {
768  "BD_Shape<T>::integer_upper_bound_assign_if_exact(y):"
769  " T in not an integer datatype.");
770  if (space_dimension() != y.space_dimension()) {
771  throw_dimension_incompatible("integer_upper_bound_assign_if_exact(y)", y);
772  }
773  const bool integer_upper_bound = true;
774  return BHZ09_upper_bound_assign_if_exact<integer_upper_bound>(y);
775 }
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_integer(const T &x)
#define PPL_COMPILE_TIME_CHECK(e, msg)
Produces a compilation error if the compile-time constant e does not evaluate to true ...
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign ( const BD_Shape< T > &  y)

Assigns to *this the intersection of *this and y.

Exceptions
std::invalid_argumentThrown if *this and y are dimension-incompatible.

Definition at line 3014 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign().

3014  {
3015  const dimension_type space_dim = space_dimension();
3016 
3017  // Dimension-compatibility check.
3018  if (space_dim != y.space_dimension()) {
3019  throw_dimension_incompatible("intersection_assign(y)", y);
3020  }
3021  // If one of the two bounded difference shapes is empty,
3022  // the intersection is empty.
3023  if (marked_empty()) {
3024  return;
3025  }
3026  if (y.marked_empty()) {
3027  set_empty();
3028  return;
3029  }
3030 
3031  // If both bounded difference shapes are zero-dimensional,
3032  // then at this point they are necessarily non-empty,
3033  // so that their intersection is non-empty too.
3034  if (space_dim == 0) {
3035  return;
3036  }
3037  // To intersect two bounded difference shapes we compare
3038  // the constraints and we choose the less values.
3039  bool changed = false;
3040  for (dimension_type i = space_dim + 1; i-- > 0; ) {
3041  DB_Row<N>& dbm_i = dbm[i];
3042  const DB_Row<N>& y_dbm_i = y.dbm[i];
3043  for (dimension_type j = space_dim + 1; j-- > 0; ) {
3044  N& dbm_ij = dbm_i[j];
3045  const N& y_dbm_ij = y_dbm_i[j];
3046  if (dbm_ij > y_dbm_ij) {
3047  dbm_ij = y_dbm_ij;
3048  changed = true;
3049  }
3050  }
3051  }
3052 
3053  if (changed && marked_shortest_path_closed()) {
3055  }
3056  PPL_ASSERT(OK());
3057 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
bool marked_shortest_path_closed() const
Returns true if the system of bounded differences is known to be shortest-path closed.
void reset_shortest_path_closed()
Marks *this as possibly not shortest-path closed.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void set_empty()
Turns *this into an empty BDS.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::is_bounded ( ) const

Returns true if and only if *this is a bounded BDS.

Definition at line 757 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::is_plus_infinity().

757  {
759  const dimension_type space_dim = space_dimension();
760  // A zero-dimensional or empty BDS is bounded.
761  if (marked_empty() || space_dim == 0) {
762  return true;
763  }
764  // A bounded difference shape defining the bounded BDS never can
765  // contain trivial constraints.
766  for (dimension_type i = space_dim + 1; i-- > 0; ) {
767  const DB_Row<N>& dbm_i = dbm[i];
768  for (dimension_type j = space_dim + 1; j-- > 0; ) {
769  if (i != j) {
770  if (is_plus_infinity(dbm_i[j])) {
771  return false;
772  }
773  }
774  }
775  }
776 
777  return true;
778 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::is_discrete ( ) const
inline

Returns true if and only if *this is discrete.

Definition at line 434 of file BD_Shape_inlines.hh.

434  {
435  return affine_dimension() == 0;
436 }
dimension_type affine_dimension() const
Returns , if *this is empty; otherwise, returns the affine dimension of *this.
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::is_disjoint_from ( const BD_Shape< T > &  y) const

Returns true if and only if *this and y are disjoint.

Exceptions
std::invalid_argumentThrown if x and y are topology-incompatible or dimension-incompatible.

Definition at line 688 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), PPL_DIRTY_TEMP, Parma_Polyhedra_Library::ROUND_UP, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

688  {
689  const dimension_type space_dim = space_dimension();
690  // Dimension-compatibility check.
691  if (space_dim != y.space_dimension()) {
692  throw_dimension_incompatible("is_disjoint_from(y)", y);
693  }
694  // If one of the two bounded difference shape is empty,
695  // then the two bounded difference shape are disjoint.
697  if (marked_empty()) {
698  return true;
699  }
700  y.shortest_path_closure_assign();
701  if (y.marked_empty()) {
702  return true;
703  }
704  // Two BDSs are disjoint when their intersection is empty.
705  // That is if and only if there exists at least a bounded difference
706  // such that the upper bound of the bounded difference in the first
707  // BD_Shape is strictly less than the lower bound of
708  // the corresponding bounded difference in the second BD_Shape
709  // or vice versa.
710  // For example: let be
711  // in `*this': -a_j_i <= v_j - v_i <= a_i_j;
712  // and in `y': -b_j_i <= v_j - v_i <= b_i_j;
713  // `*this' and `y' are disjoint if
714  // 1.) a_i_j < -b_j_i or
715  // 2.) b_i_j < -a_j_i.
716  PPL_DIRTY_TEMP(N, tmp);
717  for (dimension_type i = space_dim+1; i-- > 0; ) {
718  const DB_Row<N>& x_i = dbm[i];
719  for (dimension_type j = space_dim+1; j-- > 0; ) {
720  neg_assign_r(tmp, y.dbm[j][i], ROUND_UP);
721  if (x_i[j] < tmp) {
722  return true;
723  }
724  }
725  }
726 
727  return false;
728 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
#define PPL_DIRTY_TEMP(T, id)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::is_shortest_path_reduced ( ) const
private

Returns true if and only if this->dbm is shortest-path closed and this->redundancy_dbm correctly flags the redundant entries in this->dbm.

Definition at line 1017 of file BD_Shape_templates.hh.

References c, Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), PPL_DIRTY_TEMP, Parma_Polyhedra_Library::ROUND_UP, and Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign().

1017  {
1018  // If the BDS is empty, it is also reduced.
1019  if (marked_empty()) {
1020  return true;
1021  }
1022  const dimension_type space_dim = space_dimension();
1023  // Zero-dimensional BDSs are necessarily reduced.
1024  if (space_dim == 0) {
1025  return true;
1026  }
1027  // A shortest-path reduced dbm is just a dbm with an indication of
1028  // those constraints that are redundant. If there is no indication
1029  // of the redundant constraints, then it cannot be reduced.
1031  return false;
1032  }
1033 
1034  const BD_Shape x_copy = *this;
1035  x_copy.shortest_path_closure_assign();
1036  // If we just discovered emptiness, it cannot be reduced.
1037  if (x_copy.marked_empty()) {
1038  return false;
1039  }
1040  // The vector `leader' is used to indicate which variables are equivalent.
1041  std::vector<dimension_type> leader(space_dim + 1);
1042 
1043  // We store the leader.
1044  for (dimension_type i = space_dim + 1; i-- > 0; ) {
1045  leader[i] = i;
1046  }
1047  // Step 1: we store really the leader with the corrected value.
1048  // We search for the equivalent or zero-equivalent variables.
1049  // The variable(i-1) and variable(j-1) are equivalent if and only if
1050  // m_i_j == -(m_j_i).
1051  for (dimension_type i = 0; i < space_dim; ++i) {
1052  const DB_Row<N>& x_copy_dbm_i = x_copy.dbm[i];
1053  for (dimension_type j = i + 1; j <= space_dim; ++j) {
1054  if (is_additive_inverse(x_copy.dbm[j][i], x_copy_dbm_i[j])) {
1055  // Two equivalent variables have got the same leader
1056  // (the smaller variable).
1057  leader[j] = leader[i];
1058  }
1059  }
1060  }
1061 
1062  // Step 2: we check if there are redundant constraints in the zero_cycle
1063  // free bounded difference shape, considering only the leaders.
1064  // A constraint `c' is redundant, when there are two constraints such that
1065  // their sum is the same constraint with the inhomogeneous term
1066  // less than or equal to the `c' one.
1067  PPL_DIRTY_TEMP(N, c);
1068  for (dimension_type k = 0; k <= space_dim; ++k) {
1069  if (leader[k] == k) {
1070  const DB_Row<N>& x_k = x_copy.dbm[k];
1071  for (dimension_type i = 0; i <= space_dim; ++i) {
1072  if (leader[i] == i) {
1073  const DB_Row<N>& x_i = x_copy.dbm[i];
1074  const Bit_Row& redundancy_i = redundancy_dbm[i];
1075  const N& x_i_k = x_i[k];
1076  for (dimension_type j = 0; j <= space_dim; ++j) {
1077  if (leader[j] == j) {
1078  const N& x_i_j = x_i[j];
1079  if (!is_plus_infinity(x_i_j)) {
1080  add_assign_r(c, x_i_k, x_k[j], ROUND_UP);
1081  if (x_i_j >= c && !redundancy_i[j]) {
1082  return false;
1083  }
1084  }
1085  }
1086  }
1087  }
1088  }
1089  }
1090  }
1091 
1092  // The vector `var_conn' is used to check if there is a single cycle
1093  // that connected all zero-equivalent variables between them.
1094  // The value `space_dim + 1' is used to indicate that the equivalence
1095  // class contains a single variable.
1096  std::vector<dimension_type> var_conn(space_dim + 1);
1097  for (dimension_type i = space_dim + 1; i-- > 0; ) {
1098  var_conn[i] = space_dim + 1;
1099  }
1100  // Step 3: we store really the `var_conn' with the right value, putting
1101  // the variable with the selected variable is connected:
1102  // we check the row of each variable:
1103  // a- each leader could be connected with only zero-equivalent one,
1104  // b- each non-leader with only another zero-equivalent one.
1105  for (dimension_type i = 0; i <= space_dim; ++i) {
1106  // It count with how many variables the selected variable is
1107  // connected.
1108  dimension_type t = 0;
1109  dimension_type leader_i = leader[i];
1110  // Case a: leader.
1111  if (leader_i == i) {
1112  for (dimension_type j = 0; j <= space_dim; ++j) {
1113  dimension_type leader_j = leader[j];
1114  // Only the connectedness with equivalent variables
1115  // is considered.
1116  if (j != leader_j) {
1117  if (!redundancy_dbm[i][j]) {
1118  if (t == 1) {
1119  // Two non-leaders cannot be connected with the same leader.
1120  return false;
1121  }
1122  else {
1123  if (leader_j != i) {
1124  // The variables are not in the same equivalence class.
1125  return false;
1126  }
1127  else {
1128  ++t;
1129  var_conn[i] = j;
1130  }
1131  }
1132  }
1133  }
1134  }
1135  }
1136  // Case b: non-leader.
1137  else {
1138  for (dimension_type j = 0; j <= space_dim; ++j) {
1139  if (!redundancy_dbm[i][j]) {
1140  dimension_type leader_j = leader[j];
1141  if (leader_i != leader_j) {
1142  // The variables are not in the same equivalence class.
1143  return false;
1144  }
1145  else {
1146  if (t == 1) {
1147  // The variables cannot be connected with the same leader.
1148  return false;
1149  }
1150  else {
1151  ++t;
1152  var_conn[i] = j;
1153  }
1154  }
1155  // A non-leader must be connected with
1156  // another variable.
1157  if (t == 0) {
1158  return false;
1159  }
1160  }
1161  }
1162  }
1163  }
1164 
1165  // The vector `just_checked' is used to check if
1166  // a variable is already checked.
1167  std::vector<bool> just_checked(space_dim + 1);
1168  for (dimension_type i = space_dim + 1; i-- > 0; ) {
1169  just_checked[i] = false;
1170  }
1171  // Step 4: we check if there are single cycles that
1172  // connected all the zero-equivalent variables between them.
1173  for (dimension_type i = 0; i <= space_dim; ++i) {
1174  // We do not re-check the already considered single cycles.
1175  if (!just_checked[i]) {
1176  dimension_type v_con = var_conn[i];
1177  // We consider only the equivalence classes with
1178  // 2 or plus variables.
1179  if (v_con != space_dim + 1) {
1180  // There is a single cycle if taken a variable,
1181  // we return to this same variable.
1182  while (v_con != i) {
1183  just_checked[v_con] = true;
1184  v_con = var_conn[v_con];
1185  // If we re-pass to an already considered variable,
1186  // then we haven't a single cycle.
1187  if (just_checked[v_con]) {
1188  return false;
1189  }
1190  }
1191  }
1192  }
1193  just_checked[i] = true;
1194  }
1195 
1196  // The system bounded differences is just reduced.
1197  return true;
1198 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
BD_Shape(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty BDS of the specified space dimension.
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
bool marked_shortest_path_reduced() const
Returns true if the system of bounded differences is known to be shortest-path reduced.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_additive_inverse(const T &x, const T &y)
Returns true if and only if .
#define PPL_DIRTY_TEMP(T, id)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Bit_Matrix redundancy_dbm
A matrix indicating which constraints are redundant.
Coefficient c
Definition: PIP_Tree.cc:64
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::is_topologically_closed ( ) const
inline

Returns true if and only if *this is a topologically closed subset of the vector space.

Definition at line 428 of file BD_Shape_inlines.hh.

428  {
429  return true;
430 }
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::is_universe ( ) const

Returns true if and only if *this is a universe BDS.

Definition at line 732 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::is_plus_infinity().

732  {
733  if (marked_empty()) {
734  return false;
735  }
736  const dimension_type space_dim = space_dimension();
737  // If the BDS is non-empty and zero-dimensional,
738  // then it is necessarily the universe BDS.
739  if (space_dim == 0) {
740  return true;
741  }
742  // A bounded difference shape defining the universe BDS can only
743  // contain trivial constraints.
744  for (dimension_type i = space_dim + 1; i-- > 0; ) {
745  const DB_Row<N>& dbm_i = dbm[i];
746  for (dimension_type j = space_dim + 1; j-- > 0; ) {
747  if (!is_plus_infinity(dbm_i[j])) {
748  return false;
749  }
750  }
751  }
752  return true;
753 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
template<typename Interval_Info >
void Parma_Polyhedra_Library::BD_Shape< T >::left_inhomogeneous_refine ( const dimension_type right_t,
const dimension_type right_w_id,
const Linear_Form< Interval< T, Interval_Info > > &  left,
const Linear_Form< Interval< T, Interval_Info > > &  right 
)
private

Auxiliary function for refine with linear form that handle the general case: $l = ax + c$.

Definition at line 4746 of file BD_Shape_templates.hh.

References PPL_DIRTY_TEMP, and Parma_Polyhedra_Library::ROUND_UP.

4749  {
4750 
4751  typedef Interval<T, Interval_Info> FP_Interval_Type;
4752 
4753  if (right_t == 1) {
4754  // The constraint has the form [a-, a+] <= [b-, b+] + [c-, c+] * x.
4755  // Reduce it to the constraint +/-x <= b+ - a- if [c-, c+] = +/-[1, 1].
4756  const FP_Interval_Type& right_w_coeff =
4757  right.coefficient(Variable(right_w_id));
4758  if (right_w_coeff == 1) {
4759  PPL_DIRTY_TEMP(N, b_plus_minus_a_minus);
4760  const FP_Interval_Type& left_a = left.inhomogeneous_term();
4761  const FP_Interval_Type& right_b = right.inhomogeneous_term();
4762  sub_assign_r(b_plus_minus_a_minus, right_b.upper(), left_a.lower(),
4763  ROUND_UP);
4764  add_dbm_constraint(right_w_id+1, 0, b_plus_minus_a_minus);
4765  return;
4766  }
4767 
4768  if (right_w_coeff == -1) {
4769  PPL_DIRTY_TEMP(N, b_plus_minus_a_minus);
4770  const FP_Interval_Type& left_a = left.inhomogeneous_term();
4771  const FP_Interval_Type& right_b = right.inhomogeneous_term();
4772  sub_assign_r(b_plus_minus_a_minus, right_b.upper(), left_a.lower(),
4773  ROUND_UP);
4774  add_dbm_constraint(0, right_w_id+1, b_plus_minus_a_minus);
4775  return;
4776  }
4777  }
4778 } // end of left_inhomogeneous_refine
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
void add_dbm_constraint(dimension_type i, dimension_type j, const N &k)
Adds the constraint dbm[i][j] <= k.
#define PPL_DIRTY_TEMP(T, id)
template<typename T >
template<typename Interval_Info >
void Parma_Polyhedra_Library::BD_Shape< T >::left_one_var_refine ( const dimension_type left_w_id,
const dimension_type right_t,
const dimension_type right_w_id,
const Linear_Form< Interval< T, Interval_Info > > &  left,
const Linear_Form< Interval< T, Interval_Info > > &  right 
)
private

Auxiliary function for refine with linear form that handle the general case: $ax + b = cy + d$.

Definition at line 4785 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::is_plus_infinity(), PPL_DIRTY_TEMP, and Parma_Polyhedra_Library::ROUND_UP.

4789  {
4790 
4791  typedef Interval<T, Interval_Info> FP_Interval_Type;
4792 
4793  if (right_t == 0) {
4794  // The constraint has the form [b-, b+] + [c-, c+] * x <= [a-, a+]
4795  // Reduce it to the constraint +/-x <= a+ - b- if [c-, c+] = +/-[1, 1].
4796  const FP_Interval_Type& left_w_coeff =
4797  left.coefficient(Variable(left_w_id));
4798 
4799  if (left_w_coeff == 1) {
4800  PPL_DIRTY_TEMP(N, a_plus_minus_b_minus);
4801  const FP_Interval_Type& left_b = left.inhomogeneous_term();
4802  const FP_Interval_Type& right_a = right.inhomogeneous_term();
4803  sub_assign_r(a_plus_minus_b_minus, right_a.upper(), left_b.lower(),
4804  ROUND_UP);
4805  add_dbm_constraint(0, left_w_id+1, a_plus_minus_b_minus);
4806  return;
4807  }
4808 
4809  if (left_w_coeff == -1) {
4810  PPL_DIRTY_TEMP(N, a_plus_minus_b_minus);
4811  const FP_Interval_Type& left_b = left.inhomogeneous_term();
4812  const FP_Interval_Type& right_a = right.inhomogeneous_term();
4813  sub_assign_r(a_plus_minus_b_minus, right_a.upper(), left_b.lower(),
4814  ROUND_UP);
4815  add_dbm_constraint(left_w_id+1, 0, a_plus_minus_b_minus);
4816  return;
4817  }
4818  }
4819  else if (right_t == 1) {
4820  // The constraint has the form
4821  // [a-, a+] + [b-, b+] * x <= [c-, c+] + [d-, d+] * y.
4822  // Reduce it to the constraint +/-x +/-y <= c+ - a-
4823  // if [b-, b+] = +/-[1, 1] and [d-, d+] = +/-[1, 1].
4824  const FP_Interval_Type& left_w_coeff =
4825  left.coefficient(Variable(left_w_id));
4826 
4827  const FP_Interval_Type& right_w_coeff =
4828  right.coefficient(Variable(right_w_id));
4829 
4830  bool is_left_coeff_one = (left_w_coeff == 1);
4831  bool is_left_coeff_minus_one = (left_w_coeff == -1);
4832  bool is_right_coeff_one = (right_w_coeff == 1);
4833  bool is_right_coeff_minus_one = (right_w_coeff == -1);
4834  if (left_w_id == right_w_id) {
4835  if ((is_left_coeff_one && is_right_coeff_one)
4836  ||
4837  (is_left_coeff_minus_one && is_right_coeff_minus_one)) {
4838  // Here we have an identity or a constants-only constraint.
4839  return;
4840  }
4841  if (is_left_coeff_one && is_right_coeff_minus_one) {
4842  // We fall back to a previous case.
4843  PPL_DIRTY_TEMP(N, a_plus_minus_b_minus);
4844  const FP_Interval_Type& left_b = left.inhomogeneous_term();
4845  const FP_Interval_Type& right_a = right.inhomogeneous_term();
4846  sub_assign_r(a_plus_minus_b_minus, right_a.upper(), left_b.lower(),
4847  ROUND_UP);
4848  div_2exp_assign_r(a_plus_minus_b_minus, a_plus_minus_b_minus, 1,
4849  ROUND_UP);
4850  add_dbm_constraint(0, left_w_id + 1, a_plus_minus_b_minus);
4851  return;
4852  }
4853  if (is_left_coeff_minus_one && is_right_coeff_one) {
4854  // We fall back to a previous case.
4855  PPL_DIRTY_TEMP(N, a_plus_minus_b_minus);
4856  const FP_Interval_Type& left_b = left.inhomogeneous_term();
4857  const FP_Interval_Type& right_a = right.inhomogeneous_term();
4858  sub_assign_r(a_plus_minus_b_minus, right_a.upper(), left_b.lower(),
4859  ROUND_UP);
4860  div_2exp_assign_r(a_plus_minus_b_minus, a_plus_minus_b_minus, 1,
4861  ROUND_UP);
4862  add_dbm_constraint(right_w_id + 1, 0, a_plus_minus_b_minus);
4863  return;
4864  }
4865  }
4866  else if (is_left_coeff_minus_one && is_right_coeff_one) {
4867  // over-approximate (if is it possible) the inequality
4868  // -B + [b1, b2] <= A + [a1, a2] by adding the constraints
4869  // -B <= upper_bound(A) + (a2 - b1) and
4870  // -A <= upper_bound(B) + (a2 - b1)
4871  PPL_DIRTY_TEMP(N, a_plus_minus_b_minus);
4872  const FP_Interval_Type& left_b = left.inhomogeneous_term();
4873  const FP_Interval_Type& right_a = right.inhomogeneous_term();
4874  sub_assign_r(a_plus_minus_b_minus, right_a.upper(), left_b.lower(),
4875  ROUND_UP);
4876  PPL_DIRTY_TEMP(N, ub);
4877  ub = dbm[0][right_w_id + 1];
4878  if (!is_plus_infinity(ub)) {
4879  add_assign_r(ub, ub, a_plus_minus_b_minus, ROUND_UP);
4880  add_dbm_constraint(left_w_id + 1, 0, ub);
4881  }
4882  ub = dbm[0][left_w_id + 1];
4883  if (!is_plus_infinity(ub)) {
4884  add_assign_r(ub, ub, a_plus_minus_b_minus, ROUND_UP);
4885  add_dbm_constraint(right_w_id + 1, 0, ub);
4886  }
4887  return;
4888  }
4889  if (is_left_coeff_one && is_right_coeff_minus_one) {
4890  // over-approximate (if is it possible) the inequality
4891  // B + [b1, b2] <= -A + [a1, a2] by adding the constraints
4892  // B <= upper_bound(-A) + (a2 - b1) and
4893  // A <= upper_bound(-B) + (a2 - b1)
4894  PPL_DIRTY_TEMP(N, a_plus_minus_b_minus);
4895  const FP_Interval_Type& left_b = left.inhomogeneous_term();
4896  const FP_Interval_Type& right_a = right.inhomogeneous_term();
4897  sub_assign_r(a_plus_minus_b_minus, right_a.upper(), left_b.lower(),
4898  ROUND_UP);
4899  PPL_DIRTY_TEMP(N, ub);
4900  ub = dbm[right_w_id + 1][0];
4901  if (!is_plus_infinity(ub)) {
4902  add_assign_r(ub, ub, a_plus_minus_b_minus, ROUND_UP);
4903  add_dbm_constraint(0, left_w_id + 1, ub);
4904  }
4905  ub = dbm[left_w_id + 1][0];
4906  if (!is_plus_infinity(ub)) {
4907  add_assign_r(ub, ub, a_plus_minus_b_minus, ROUND_UP);
4908  add_dbm_constraint(0, right_w_id + 1, ub);
4909  }
4910  return;
4911  }
4912  if (is_left_coeff_one && is_right_coeff_one) {
4913  PPL_DIRTY_TEMP(N, c_plus_minus_a_minus);
4914  const FP_Interval_Type& left_a = left.inhomogeneous_term();
4915  const FP_Interval_Type& right_c = right.inhomogeneous_term();
4916  sub_assign_r(c_plus_minus_a_minus, right_c.upper(), left_a.lower(),
4917  ROUND_UP);
4918  add_dbm_constraint(right_w_id+1, left_w_id+1, c_plus_minus_a_minus);
4919  return;
4920  }
4921  if (is_left_coeff_minus_one && is_right_coeff_minus_one) {
4922  PPL_DIRTY_TEMP(N, c_plus_minus_a_minus);
4923  const FP_Interval_Type& left_a = left.inhomogeneous_term();
4924  const FP_Interval_Type& right_c = right.inhomogeneous_term();
4925  sub_assign_r(c_plus_minus_a_minus, right_c.upper(), left_a.lower(),
4926  ROUND_UP);
4927  add_dbm_constraint(left_w_id+1, right_w_id+1, c_plus_minus_a_minus);
4928  return;
4929  }
4930  }
4931 }
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
void add_dbm_constraint(dimension_type i, dimension_type j, const N &k)
Adds the constraint dbm[i][j] <= k.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
#define PPL_DIRTY_TEMP(T, id)
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::limited_BHMZ05_extrapolation_assign ( const BD_Shape< T > &  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.

Parameters
yA BDS that must be contained in *this.
csThe system of constraints used to improve the widened BDS.
tpAn optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique).
Exceptions
std::invalid_argumentThrown if *this, y and cs are dimension-incompatible or if cs contains a strict inequality.

Definition at line 3311 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::Constraint_System::has_strict_inequalities(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.

3313  {
3314  // Dimension-compatibility check.
3315  const dimension_type space_dim = space_dimension();
3316  if (space_dim != y.space_dimension()) {
3317  throw_dimension_incompatible("limited_BHMZ05_extrapolation_assign(y, cs)",
3318  y);
3319  }
3320  // `cs' must be dimension-compatible with the two systems
3321  // of bounded differences.
3322  const dimension_type cs_space_dim = cs.space_dimension();
3323  if (space_dim < cs_space_dim) {
3324  throw_invalid_argument("limited_BHMZ05_extrapolation_assign(y, cs)",
3325  "cs is space-dimension incompatible");
3326  }
3327  // Strict inequalities are not allowed.
3328  if (cs.has_strict_inequalities()) {
3329  throw_invalid_argument("limited_BHMZ05_extrapolation_assign(y, cs)",
3330  "cs has strict inequalities");
3331  }
3332  // The limited BHMZ05-extrapolation between two systems of bounded
3333  // differences in a zero-dimensional space is a system of bounded
3334  // differences in a zero-dimensional space, too.
3335  if (space_dim == 0) {
3336  return;
3337  }
3338  // We assume that `y' is contained in or equal to `*this'.
3339  PPL_EXPECT_HEAVY(copy_contains(*this, y));
3340 
3341  // If `*this' is empty, since `*this' contains `y', `y' is empty too.
3342  if (marked_empty()) {
3343  return;
3344  }
3345  // If `y' is empty, we return.
3346  if (y.marked_empty()) {
3347  return;
3348  }
3349  BD_Shape<T> limiting_shape(space_dim, UNIVERSE);
3350  get_limiting_shape(cs, limiting_shape);
3351  BHMZ05_widening_assign(y, tp);
3352  intersection_assign(limiting_shape);
3353 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
void BHMZ05_widening_assign(const BD_Shape &y, unsigned *tp=0)
Assigns to *this the result of computing the BHMZ05-widening of *this and y.
size_t dimension_type
An unsigned integral type for representing space dimensions.
void get_limiting_shape(const Constraint_System &cs, BD_Shape &limiting_shape) const
Adds to limiting_shape the bounded differences in cs that are satisfied by *this. ...
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
static void throw_invalid_argument(const char *method, const char *reason)
void intersection_assign(const BD_Shape &y)
Assigns to *this the intersection of *this and y.
The universe element, i.e., the whole vector space.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::limited_CC76_extrapolation_assign ( const BD_Shape< T > &  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.

Parameters
yA BDS that must be contained in *this.
csThe system of constraints used to improve the widened BDS.
tpAn optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique).
Exceptions
std::invalid_argumentThrown if *this, y and cs are dimension-incompatible or if cs contains a strict inequality.

Definition at line 3198 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::Constraint_System::has_strict_inequalities(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.

3200  {
3201  // Dimension-compatibility check.
3202  const dimension_type space_dim = space_dimension();
3203  if (space_dim != y.space_dimension()) {
3204  throw_dimension_incompatible("limited_CC76_extrapolation_assign(y, cs)",
3205  y);
3206  }
3207  // `cs' must be dimension-compatible with the two systems
3208  // of bounded differences.
3209  const dimension_type cs_space_dim = cs.space_dimension();
3210  if (space_dim < cs_space_dim) {
3211  throw_invalid_argument("limited_CC76_extrapolation_assign(y, cs)",
3212  "cs is space_dimension incompatible");
3213  }
3214 
3215  // Strict inequalities not allowed.
3216  if (cs.has_strict_inequalities()) {
3217  throw_invalid_argument("limited_CC76_extrapolation_assign(y, cs)",
3218  "cs has strict inequalities");
3219  }
3220  // The limited CC76-extrapolation between two systems of bounded
3221  // differences in a zero-dimensional space is a system of bounded
3222  // differences in a zero-dimensional space, too.
3223  if (space_dim == 0) {
3224  return;
3225  }
3226  // We assume that `y' is contained in or equal to `*this'.
3227  PPL_EXPECT_HEAVY(copy_contains(*this, y));
3228 
3229  // If `*this' is empty, since `*this' contains `y', `y' is empty too.
3230  if (marked_empty()) {
3231  return;
3232  }
3233  // If `y' is empty, we return.
3234  if (y.marked_empty()) {
3235  return;
3236  }
3237  BD_Shape<T> limiting_shape(space_dim, UNIVERSE);
3238  get_limiting_shape(cs, limiting_shape);
3240  intersection_assign(limiting_shape);
3241 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
void get_limiting_shape(const Constraint_System &cs, BD_Shape &limiting_shape) const
Adds to limiting_shape the bounded differences in cs that are satisfied by *this. ...
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
void CC76_extrapolation_assign(const BD_Shape &y, unsigned *tp=0)
Assigns to *this the result of computing the CC76-extrapolation between *this and y...
static void throw_invalid_argument(const char *method, const char *reason)
void intersection_assign(const BD_Shape &y)
Assigns to *this the intersection of *this and y.
The universe element, i.e., the whole vector space.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::limited_H79_extrapolation_assign ( const BD_Shape< T > &  y,
const Constraint_System cs,
unsigned *  tp = 0 
)
inline

Improves the result of the H79-widening computation by also enforcing those constraints in cs that are satisfied by all the points of *this.

Parameters
yA BDS that must be contained in *this.
csThe system of constraints used to improve the widened BDS.
tpAn optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique).
Exceptions
std::invalid_argumentThrown if *this, y and cs are dimension-incompatible.

Definition at line 868 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::constraints(), and Parma_Polyhedra_Library::Polyhedron::limited_H79_extrapolation_assign().

870  {
871  // Compute the limited H79 extrapolation on polyhedra.
872  // TODO: provide a direct implementation.
873  C_Polyhedron ph_x(constraints());
874  C_Polyhedron ph_y(y.constraints());
875  ph_x.limited_H79_extrapolation_assign(ph_y, cs, tp);
876  BD_Shape x(ph_x);
877  m_swap(x);
878  PPL_ASSERT(OK());
879 }
BD_Shape(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty BDS of the specified space dimension.
void m_swap(BD_Shape &y)
Swaps *this with y (*this and y can be dimension-incompatible).
Constraint_System constraints() const
Returns a system of constraints defining *this.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
template<typename T >
template<typename Interval_Info >
void Parma_Polyhedra_Library::BD_Shape< T >::linear_form_upper_bound ( const Linear_Form< Interval< T, Interval_Info > > &  lf,
N result 
) const
private

Definition at line 5055 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::assign_r(), PPL_COMPILE_TIME_CHECK, PPL_DIRTY_TEMP, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, and Parma_Polyhedra_Library::ROUND_UP.

5056  {
5057 
5058  // Check that T is a floating point type.
5059  PPL_COMPILE_TIME_CHECK(!std::numeric_limits<T>::is_exact,
5060  "BD_Shape<T>::linear_form_upper_bound:"
5061  " T not a floating point type.");
5062 
5063  const dimension_type lf_space_dimension = lf.space_dimension();
5064  PPL_ASSERT(lf_space_dimension <= space_dimension());
5065 
5066  typedef Interval<T, Interval_Info> FP_Interval_Type;
5067 
5068  PPL_DIRTY_TEMP(N, curr_lb);
5069  PPL_DIRTY_TEMP(N, curr_ub);
5070  PPL_DIRTY_TEMP(N, curr_var_ub);
5071  PPL_DIRTY_TEMP(N, curr_minus_var_ub);
5072 
5073  PPL_DIRTY_TEMP(N, first_comparison_term);
5074  PPL_DIRTY_TEMP(N, second_comparison_term);
5075 
5076  PPL_DIRTY_TEMP(N, negator);
5077 
5078  assign_r(result, lf.inhomogeneous_term().upper(), ROUND_NOT_NEEDED);
5079 
5080  for (dimension_type curr_var = 0, n_var = 0; curr_var < lf_space_dimension;
5081  ++curr_var) {
5082  n_var = curr_var + 1;
5083  const FP_Interval_Type&
5084  curr_coefficient = lf.coefficient(Variable(curr_var));
5085  assign_r(curr_lb, curr_coefficient.lower(), ROUND_NOT_NEEDED);
5086  assign_r(curr_ub, curr_coefficient.upper(), ROUND_NOT_NEEDED);
5087  if (curr_lb != 0 || curr_ub != 0) {
5088  assign_r(curr_var_ub, dbm[0][n_var], ROUND_NOT_NEEDED);
5089  neg_assign_r(curr_minus_var_ub, dbm[n_var][0], ROUND_NOT_NEEDED);
5090  // Optimize the most commons cases: curr = +/-[1, 1].
5091  if (curr_lb == 1 && curr_ub == 1) {
5092  add_assign_r(result, result, std::max(curr_var_ub, curr_minus_var_ub),
5093  ROUND_UP);
5094  }
5095  else if (curr_lb == -1 && curr_ub == -1) {
5096  neg_assign_r(negator, std::min(curr_var_ub, curr_minus_var_ub),
5098  add_assign_r(result, result, negator, ROUND_UP);
5099  }
5100  else {
5101  // Next addend will be the maximum of four quantities.
5102  assign_r(first_comparison_term, 0, ROUND_NOT_NEEDED);
5103  assign_r(second_comparison_term, 0, ROUND_NOT_NEEDED);
5104  add_mul_assign_r(first_comparison_term, curr_var_ub, curr_ub,
5105  ROUND_UP);
5106  add_mul_assign_r(second_comparison_term, curr_var_ub, curr_lb,
5107  ROUND_UP);
5108  assign_r(first_comparison_term, std::max(first_comparison_term,
5109  second_comparison_term),
5111  assign_r(second_comparison_term, 0, ROUND_NOT_NEEDED);
5112  add_mul_assign_r(second_comparison_term, curr_minus_var_ub, curr_ub,
5113  ROUND_UP);
5114  assign_r(first_comparison_term, std::max(first_comparison_term,
5115  second_comparison_term),
5117  assign_r(second_comparison_term, 0, ROUND_NOT_NEEDED);
5118  add_mul_assign_r(second_comparison_term, curr_minus_var_ub, curr_lb,
5119  ROUND_UP);
5120  assign_r(first_comparison_term, std::max(first_comparison_term,
5121  second_comparison_term),
5123 
5124  add_assign_r(result, result, first_comparison_term, ROUND_UP);
5125  }
5126  }
5127  }
5128 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
size_t dimension_type
An unsigned integral type for representing space dimensions.
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
#define PPL_COMPILE_TIME_CHECK(e, msg)
Produces a compilation error if the compile-time constant e does not evaluate to true ...
#define PPL_DIRTY_TEMP(T, id)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::m_swap ( BD_Shape< T > &  y)
inline

Swaps *this with y (*this and y can be dimension-incompatible).

Definition at line 362 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm, Parma_Polyhedra_Library::BD_Shape< T >::status, and Parma_Polyhedra_Library::swap().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::swap().

362  {
363  using std::swap;
364  swap(dbm, y.dbm);
365  swap(status, y.status);
366  swap(redundancy_dbm, y.redundancy_dbm);
367 }
void swap(CO_Tree &x, CO_Tree &y)
void swap(BD_Shape< T > &x, BD_Shape< T > &y)
Swaps x with y.
Bit_Matrix redundancy_dbm
A matrix indicating which constraints are redundant.
Status status
The status flags to keep track of the internal state.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
template<typename Partial_Function >
void Parma_Polyhedra_Library::BD_Shape< T >::map_space_dimensions ( const Partial_Function pfunc)

Remaps the dimensions of the vector space according to a partial function.

Parameters
pfuncThe partial function specifying the destiny of each dimension.

The template type parameter Partial_Function must provide the following methods.

bool has_empty_codomain() const

returns true if and only if the represented partial function has an empty co-domain (i.e., it is always undefined). The has_empty_codomain() method will always be called before the methods below. However, if has_empty_codomain() returns true, none of the functions below will be called.

dimension_type max_in_codomain() const

returns the maximum value that belongs to the co-domain of the partial function.

bool maps(dimension_type i, dimension_type& j) const

Let $f$ be the represented function and $k$ be the value of i. If $f$ is defined in $k$, then $f(k)$ is assigned to j and true is returned. If $f$ is undefined in $k$, then false is returned.

The result is undefined if pfunc does not encode a partial function with the properties described in the specification of the mapping operator.

Definition at line 2945 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::assign_or_swap(), Parma_Polyhedra_Library::Partial_Function::has_empty_codomain(), Parma_Polyhedra_Library::Partial_Function::maps(), Parma_Polyhedra_Library::Partial_Function::max_in_codomain(), and Parma_Polyhedra_Library::swap().

2945  {
2946  const dimension_type space_dim = space_dimension();
2947  // TODO: this implementation is just an executable specification.
2948  if (space_dim == 0) {
2949  return;
2950  }
2951  if (pfunc.has_empty_codomain()) {
2952  // All dimensions vanish: the BDS becomes zero_dimensional.
2954  return;
2955  }
2956 
2957  const dimension_type new_space_dim = pfunc.max_in_codomain() + 1;
2958  // If we are going to actually reduce the space dimension,
2959  // then shortest-path closure is required to keep precision.
2960  if (new_space_dim < space_dim) {
2962  }
2963  // If the BDS is empty, then it is sufficient to adjust the
2964  // space dimension of the bounded difference shape.
2965  if (marked_empty()) {
2966  remove_higher_space_dimensions(new_space_dim);
2967  return;
2968  }
2969 
2970  // Shortest-path closure is maintained (if it was holding).
2971  // TODO: see whether reduction can be (efficiently!) maintained too.
2974  }
2975  // We create a new matrix with the new space dimension.
2976  DB_Matrix<N> x(new_space_dim+1);
2977  // First of all we must map the unary constraints, because
2978  // there is the fictitious variable `zero', that can't be mapped
2979  // at all.
2980  DB_Row<N>& dbm_0 = dbm[0];
2981  DB_Row<N>& x_0 = x[0];
2982  for (dimension_type j = 1; j <= space_dim; ++j) {
2983  dimension_type new_j;
2984  if (pfunc.maps(j - 1, new_j)) {
2985  assign_or_swap(x_0[new_j + 1], dbm_0[j]);
2986  assign_or_swap(x[new_j + 1][0], dbm[j][0]);
2987  }
2988  }
2989  // Now we map the binary constraints, exchanging the indexes.
2990  for (dimension_type i = 1; i <= space_dim; ++i) {
2991  dimension_type new_i;
2992  if (pfunc.maps(i - 1, new_i)) {
2993  DB_Row<N>& dbm_i = dbm[i];
2994  ++new_i;
2995  DB_Row<N>& x_new_i = x[new_i];
2996  for (dimension_type j = i+1; j <= space_dim; ++j) {
2997  dimension_type new_j;
2998  if (pfunc.maps(j - 1, new_j)) {
2999  ++new_j;
3000  assign_or_swap(x_new_i[new_j], dbm_i[j]);
3001  assign_or_swap(x[new_j][new_i], dbm[j][i]);
3002  }
3003  }
3004  }
3005  }
3006 
3007  using std::swap;
3008  swap(dbm, x);
3009  PPL_ASSERT(OK());
3010 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
void swap(CO_Tree &x, CO_Tree &y)
size_t dimension_type
An unsigned integral type for representing space dimensions.
Enable_If< Has_Assign_Or_Swap< T >::value, void >::type assign_or_swap(T &to, T &from)
bool marked_shortest_path_reduced() const
Returns true if the system of bounded differences is known to be shortest-path reduced.
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
void swap(BD_Shape< T > &x, BD_Shape< T > &y)
Swaps x with y.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void remove_higher_space_dimensions(dimension_type new_dimension)
Removes the higher dimensions so that the resulting space will have dimension new_dimension.
void reset_shortest_path_reduced()
Marks *this as possibly not shortest-path reduced.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::marked_empty ( ) const
inlineprivate

Returns true if the BDS is known to be empty.

The return value false does not necessarily implies that *this is non-empty.

Definition at line 61 of file BD_Shape_inlines.hh.

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::BD_Shape< T >::BFT00_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::BHZ09_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::BD_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::difference_assign(), Parma_Polyhedra_Library::BD_Shape< T >::euclidean_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::BD_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::BD_Shape< T >::is_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::l_infinity_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::limited_BHMZ05_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::operator==(), Parma_Polyhedra_Library::BD_Shape< T >::rectilinear_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign().

61  {
62  return status.test_empty();
63 }
Status status
The status flags to keep track of the internal state.
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed ( ) const
inlineprivate

Returns true if the system of bounded differences is known to be shortest-path closed.

The return value false does not necessarily implies that this->dbm is not shortest-path closed.

Definition at line 67 of file BD_Shape_inlines.hh.

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::BHZ09_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::get_limiting_shape(), and Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign().

67  {
69 }
Status status
The status flags to keep track of the internal state.
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced ( ) const
inlineprivate

Returns true if the system of bounded differences is known to be shortest-path reduced.

The return value false does not necessarily implies that this->dbm is not shortest-path reduced.

Definition at line 73 of file BD_Shape_inlines.hh.

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), and Parma_Polyhedra_Library::BD_Shape< T >::operator=().

73  {
75 }
Status status
The status flags to keep track of the internal state.
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::marked_zero_dim_univ ( ) const
inlineprivate

Returns true if the BDS is the zero-dimensional universe.

Definition at line 55 of file BD_Shape_inlines.hh.

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape().

55  {
56  return status.test_zero_dim_univ();
57 }
Status status
The status flags to keep track of the internal state.
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::max_min ( const Linear_Expression expr,
bool  maximize,
Coefficient ext_n,
Coefficient ext_d,
bool &  included,
Generator g 
) const
private

Maximizes or minimizes expr subject to *this.

Parameters
exprThe linear expression to be maximized or minimized subject to this;
maximizetrue if maximization is what is wanted;
ext_nThe numerator of the extremum value;
ext_dThe denominator of the extremum value;
includedtrue if and only if the extremum of expr can actually be reached in * this;
gWhen maximization or minimization succeeds, will be assigned a point or closure point where expr reaches the corresponding extremum value.
Exceptions
std::invalid_argumentThrown if expr and *this are dimension-incompatible.

If *this is empty or expr is not bounded in the appropriate direction, false is returned and ext_n, ext_d, included and g are left untouched.

Definition at line 1351 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::MIP_Problem::evaluate_objective_function(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), 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(), and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

1355  {
1356  // The dimension of `expr' should not be greater than the dimension
1357  // of `*this'.
1358  const dimension_type space_dim = space_dimension();
1359  const dimension_type expr_space_dim = expr.space_dimension();
1360  if (space_dim < expr_space_dim) {
1362  ? "maximize(e, ...)"
1363  : "minimize(e, ...)"), "e", expr);
1364  }
1365  // Deal with zero-dim BDS first.
1366  if (space_dim == 0) {
1367  if (marked_empty()) {
1368  return false;
1369  }
1370  else {
1371  ext_n = expr.inhomogeneous_term();
1372  ext_d = 1;
1373  included = true;
1374  g = point();
1375  return true;
1376  }
1377  }
1378 
1380  // For an empty BDS we simply return false.
1381  if (marked_empty()) {
1382  return false;
1383  }
1384  Optimization_Mode mode_max_min
1386  MIP_Problem mip(space_dim, constraints(), expr, mode_max_min);
1387  if (mip.solve() == OPTIMIZED_MIP_PROBLEM) {
1388  g = mip.optimizing_point();
1389  mip.evaluate_objective_function(g, ext_n, ext_d);
1390  included = true;
1391  return true;
1392  }
1393  // Here `expr' is unbounded in `*this'.
1394  return false;
1395 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
Minimization is requested.
Optimization_Mode
Possible optimization modes.
size_t dimension_type
An unsigned integral type for representing space dimensions.
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
Constraint_System constraints() const
Returns a system of constraints defining *this.
Maximization is requested.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *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.
The problem has an optimal solution.
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::max_min ( const Linear_Expression expr,
bool  maximize,
Coefficient ext_n,
Coefficient ext_d,
bool &  included 
) const
private

Maximizes or minimizes expr subject to *this.

Parameters
exprThe linear expression to be maximized or minimized subject to this;
maximizetrue if maximization is what is wanted;
ext_nThe numerator of the extremum value;
ext_dThe denominator of the extremum value;
includedtrue if and only if the extremum of expr can actually be reached in * this;
Exceptions
std::invalid_argumentThrown if expr and *this are dimension-incompatible.

If *this is empty or expr is not bounded in the appropriate direction, false is returned and ext_n, ext_d, included and point are left untouched.

Definition at line 1247 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::assign_r(), c, Parma_Polyhedra_Library::BD_Shape_Helpers::extract_bounded_difference(), Parma_Polyhedra_Library::Linear_Expression::get(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::MINIMIZATION, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::numer_denom(), Parma_Polyhedra_Library::MIP_Problem::optimal_value(), Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, PPL_DIRTY_TEMP, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::ROUND_UP, Parma_Polyhedra_Library::Boundary_NS::sgn(), Parma_Polyhedra_Library::MIP_Problem::solve(), and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

1250  {
1251  // The dimension of `expr' should not be greater than the dimension
1252  // of `*this'.
1253  const dimension_type space_dim = space_dimension();
1254  const dimension_type expr_space_dim = expr.space_dimension();
1255  if (space_dim < expr_space_dim) {
1257  ? "maximize(e, ...)"
1258  : "minimize(e, ...)"), "e", expr);
1259  }
1260  // Deal with zero-dim BDS first.
1261  if (space_dim == 0) {
1262  if (marked_empty()) {
1263  return false;
1264  }
1265  else {
1266  ext_n = expr.inhomogeneous_term();
1267  ext_d = 1;
1268  included = true;
1269  return true;
1270  }
1271  }
1272 
1274  // For an empty BDS we simply return false.
1275  if (marked_empty()) {
1276  return false;
1277  }
1278  // The constraint `c' is used to check if `expr' is a difference
1279  // bounded and, in this case, to select the cell.
1280  const Constraint& c = maximize ? expr <= 0 : expr >= 0;
1281  dimension_type num_vars = 0;
1282  dimension_type i = 0;
1283  dimension_type j = 0;
1285  // Check if `c' is a BD constraint.
1286  if (!BD_Shape_Helpers::extract_bounded_difference(c, num_vars, i, j, coeff)) {
1287  Optimization_Mode mode_max_min
1289  MIP_Problem mip(space_dim, constraints(), expr, mode_max_min);
1290  if (mip.solve() == OPTIMIZED_MIP_PROBLEM) {
1291  mip.optimal_value(ext_n, ext_d);
1292  included = true;
1293  return true;
1294  }
1295  else {
1296  // Here`expr' is unbounded in `*this'.
1297  return false;
1298  }
1299  }
1300  else {
1301  // Here `expr' is a bounded difference.
1302  if (num_vars == 0) {
1303  // Dealing with a trivial expression.
1304  ext_n = expr.inhomogeneous_term();
1305  ext_d = 1;
1306  included = true;
1307  return true;
1308  }
1309 
1310  // Select the cell to be checked.
1311  const N& x = (coeff < 0) ? dbm[i][j] : dbm[j][i];
1312  if (!is_plus_infinity(x)) {
1313  // Compute the maximize/minimize of `expr'.
1314  PPL_DIRTY_TEMP(N, d);
1315  const Coefficient& b = expr.inhomogeneous_term();
1316  PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
1317  neg_assign(minus_b, b);
1318  const Coefficient& sc_b = maximize ? b : minus_b;
1319  assign_r(d, sc_b, ROUND_UP);
1320  // Set `coeff_expr' to the absolute value of coefficient of
1321  // a variable in `expr'.
1322  PPL_DIRTY_TEMP(N, coeff_expr);
1323  PPL_ASSERT(i != 0);
1324  const Coefficient& coeff_i = expr.get(Variable(i - 1));
1325  const int sign_i = sgn(coeff_i);
1326  if (sign_i > 0) {
1327  assign_r(coeff_expr, coeff_i, ROUND_UP);
1328  }
1329  else {
1330  PPL_DIRTY_TEMP_COEFFICIENT(minus_coeff_i);
1331  neg_assign(minus_coeff_i, coeff_i);
1332  assign_r(coeff_expr, minus_coeff_i, ROUND_UP);
1333  }
1334  // Approximating the maximum/minimum of `expr'.
1335  add_mul_assign_r(d, coeff_expr, x, ROUND_UP);
1336  numer_denom(d, ext_n, ext_d);
1337  if (!maximize) {
1338  neg_assign(ext_n);
1339  }
1340  included = true;
1341  return true;
1342  }
1343 
1344  // `expr' is unbounded.
1345  return false;
1346  }
1347 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
Minimization is requested.
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
Optimization_Mode
Possible optimization modes.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Enable_If< Is_Native_Or_Checked< T >::value, void >::type numer_denom(const T &from, Coefficient &numer, Coefficient &denom)
Extract the numerator and denominator components of from.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
Constraint_System constraints() const
Returns a system of constraints defining *this.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
#define PPL_DIRTY_TEMP(T, id)
void neg_assign(GMP_Integer &x)
Maximization is requested.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
int sgn(Boundary_Type type, const T &x, const Info &info)
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.
static bool extract_bounded_difference(const Constraint &c, dimension_type &c_num_vars, dimension_type &c_first_var, dimension_type &c_second_var, Coefficient &c_coeff)
Decodes the constraint c as a bounded difference.
Coefficient c
Definition: PIP_Tree.cc:64
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
The problem has an optimal solution.
template<typename T >
dimension_type Parma_Polyhedra_Library::BD_Shape< T >::max_space_dimension ( )
inlinestatic

Returns the maximum space dimension that a BDS can handle.

Definition at line 46 of file BD_Shape_inlines.hh.

46  {
47  // One dimension is reserved to have a value of type dimension_type
48  // that does not represent a legal dimension.
49  return std::min(DB_Matrix<N>::max_num_rows() - 1,
50  DB_Matrix<N>::max_num_columns() - 1);
51 }
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::maximize ( const Linear_Expression expr,
Coefficient sup_n,
Coefficient sup_d,
bool &  maximum 
) const
inline

Returns true if and only if *this is not empty and expr is bounded from above in *this, in which case the supremum value is computed.

Parameters
exprThe linear expression to be maximized subject to *this;
sup_nThe numerator of the supremum value;
sup_dThe denominator of the supremum value;
maximumtrue if and only if the supremum is also the maximum value.
Exceptions
std::invalid_argumentThrown if expr and *this are dimension-incompatible.

If *this is empty or expr is not bounded from above, false is returned and sup_n, sup_d and maximum are left untouched.

Definition at line 396 of file BD_Shape_inlines.hh.

398  {
399  return max_min(expr, true, sup_n, sup_d, maximum);
400 }
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.
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::maximize ( const Linear_Expression expr,
Coefficient sup_n,
Coefficient sup_d,
bool &  maximum,
Generator g 
) const
inline

Returns true if and only if *this is not empty and expr is bounded from above in *this, in which case the supremum value and a point where expr reaches it are computed.

Parameters
exprThe linear expression to be maximized subject to *this;
sup_nThe numerator of the supremum value;
sup_dThe denominator of the supremum value;
maximumtrue if and only if the supremum is also the maximum value;
gWhen maximization succeeds, will be assigned the point or closure point where expr reaches its supremum value.
Exceptions
std::invalid_argumentThrown if expr and *this are dimension-incompatible.

If *this is empty or expr is not bounded from above, false is returned and sup_n, sup_d, maximum and g are left untouched.

Definition at line 404 of file BD_Shape_inlines.hh.

406  {
407  return max_min(expr, true, sup_n, sup_d, maximum, g);
408 }
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.
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::minimize ( const Linear_Expression expr,
Coefficient inf_n,
Coefficient inf_d,
bool &  minimum 
) const
inline

Returns true if and only if *this is not empty and expr is bounded from below in *this, in which case the infimum value is computed.

Parameters
exprThe linear expression to be minimized subject to *this;
inf_nThe numerator of the infimum value;
inf_dThe denominator of the infimum value;
minimumtrue if and only if the infimum is also the minimum value.
Exceptions
std::invalid_argumentThrown if expr and *this are dimension-incompatible.

If *this is empty or expr is not bounded from below, false is returned and inf_n, inf_d and minimum are left untouched.

Definition at line 412 of file BD_Shape_inlines.hh.

414  {
415  return max_min(expr, false, inf_n, inf_d, minimum);
416 }
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.
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::minimize ( const Linear_Expression expr,
Coefficient inf_n,
Coefficient inf_d,
bool &  minimum,
Generator g 
) const
inline

Returns true if and only if *this is not empty and expr is bounded from below in *this, in which case the infimum value and a point where expr reaches it are computed.

Parameters
exprThe linear expression to be minimized subject to *this;
inf_nThe numerator of the infimum value;
inf_dThe denominator of the infimum value;
minimumtrue if and only if the infimum is also the minimum value;
gWhen minimization succeeds, will be assigned a point or closure point where expr reaches its infimum value.
Exceptions
std::invalid_argumentThrown if expr and *this are dimension-incompatible.

If *this is empty or expr is not bounded from below, false is returned and inf_n, inf_d, minimum and g are left untouched.

Definition at line 420 of file BD_Shape_inlines.hh.

422  {
423  return max_min(expr, false, inf_n, inf_d, minimum, g);
424 }
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.
template<typename T >
Congruence_System Parma_Polyhedra_Library::BD_Shape< T >::minimized_congruences ( ) const

Returns a minimal system of (equality) congruences satisfied by *this with the same affine dimension as *this.

Definition at line 362 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::Congruence_System::insert(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Congruence_System::zero_dim_empty(), and Parma_Polyhedra_Library::Congruence::zero_dim_false().

362  {
363  // Shortest-path closure is necessary to detect emptiness
364  // and all (possibly implicit) equalities.
366 
367  const dimension_type space_dim = space_dimension();
368  Congruence_System cgs(space_dim);
369 
370  if (space_dim == 0) {
371  if (marked_empty()) {
373  }
374  return cgs;
375  }
376 
377  if (marked_empty()) {
378  cgs.insert(Congruence::zero_dim_false());
379  return cgs;
380  }
381 
384 
385  // Compute leader information.
386  std::vector<dimension_type> leaders;
387  compute_leaders(leaders);
388 
389  // Go through the non-leaders to generate equality constraints.
390  const DB_Row<N>& dbm_0 = dbm[0];
391  for (dimension_type i = 1; i <= space_dim; ++i) {
392  const dimension_type leader = leaders[i];
393  if (i != leader) {
394  // Generate the constraint relating `i' and its leader.
395  if (leader == 0) {
396  // A unary equality has to be generated.
397  PPL_ASSERT(!is_plus_infinity(dbm_0[i]));
398  numer_denom(dbm_0[i], numer, denom);
399  cgs.insert(denom*Variable(i-1) == numer);
400  }
401  else {
402  // A binary equality has to be generated.
403  PPL_ASSERT(!is_plus_infinity(dbm[i][leader]));
404  numer_denom(dbm[i][leader], numer, denom);
405  cgs.insert(denom*Variable(leader-1) - denom*Variable(i-1) == numer);
406  }
407  }
408  }
409  return cgs;
410 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Enable_If< Is_Native_Or_Checked< T >::value, void >::type numer_denom(const T &from, Coefficient &numer, Coefficient &denom)
Extract the numerator and denominator components of from.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
static const Congruence_System & zero_dim_empty()
Returns the system containing only Congruence::zero_dim_false().
static const Congruence & zero_dim_false()
Returns a reference to the false (zero-dimension space) congruence .
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void compute_leaders(std::vector< dimension_type > &leaders) const
Compute the leaders of zero-equivalence classes.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
Constraint_System Parma_Polyhedra_Library::BD_Shape< T >::minimized_constraints ( ) const

Returns a minimized system of constraints defining *this.

Definition at line 6489 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Constraint_System::set_space_dimension(), Parma_Polyhedra_Library::Constraint_System::zero_dim_empty(), and Parma_Polyhedra_Library::Constraint::zero_dim_false().

6489  {
6491  const dimension_type space_dim = space_dimension();
6492  Constraint_System cs;
6493  cs.set_space_dimension(space_dim);
6494 
6495  if (space_dim == 0) {
6496  if (marked_empty()) {
6498  }
6499  return cs;
6500  }
6501 
6502  if (marked_empty()) {
6503  cs.insert(Constraint::zero_dim_false());
6504  return cs;
6505  }
6506 
6509 
6510  // Compute leader information.
6511  std::vector<dimension_type> leaders;
6512  compute_leaders(leaders);
6513  std::vector<dimension_type> leader_indices;
6514  compute_leader_indices(leaders, leader_indices);
6515  const dimension_type num_leaders = leader_indices.size();
6516 
6517  // Go through the non-leaders to generate equality constraints.
6518  const DB_Row<N>& dbm_0 = dbm[0];
6519  for (dimension_type i = 1; i <= space_dim; ++i) {
6520  const dimension_type leader = leaders[i];
6521  if (i != leader) {
6522  // Generate the constraint relating `i' and its leader.
6523  if (leader == 0) {
6524  // A unary equality has to be generated.
6525  PPL_ASSERT(!is_plus_infinity(dbm_0[i]));
6526  numer_denom(dbm_0[i], numer, denom);
6527  cs.insert(denom*Variable(i-1) == numer);
6528  }
6529  else {
6530  // A binary equality has to be generated.
6531  PPL_ASSERT(!is_plus_infinity(dbm[i][leader]));
6532  numer_denom(dbm[i][leader], numer, denom);
6533  cs.insert(denom*Variable(leader-1) - denom*Variable(i-1) == numer);
6534  }
6535  }
6536  }
6537 
6538  // Go through the leaders to generate inequality constraints.
6539  // First generate all the unary inequalities.
6540  const Bit_Row& red_0 = redundancy_dbm[0];
6541  for (dimension_type l_i = 1; l_i < num_leaders; ++l_i) {
6542  const dimension_type i = leader_indices[l_i];
6543  if (!red_0[i]) {
6544  numer_denom(dbm_0[i], numer, denom);
6545  cs.insert(denom*Variable(i-1) <= numer);
6546  }
6547  if (!redundancy_dbm[i][0]) {
6548  numer_denom(dbm[i][0], numer, denom);
6549  cs.insert(-denom*Variable(i-1) <= numer);
6550  }
6551  }
6552  // Then generate all the binary inequalities.
6553  for (dimension_type l_i = 1; l_i < num_leaders; ++l_i) {
6554  const dimension_type i = leader_indices[l_i];
6555  const DB_Row<N>& dbm_i = dbm[i];
6556  const Bit_Row& red_i = redundancy_dbm[i];
6557  for (dimension_type l_j = l_i + 1; l_j < num_leaders; ++l_j) {
6558  const dimension_type j = leader_indices[l_j];
6559  if (!red_i[j]) {
6560  numer_denom(dbm_i[j], numer, denom);
6561  cs.insert(denom*Variable(j-1) - denom*Variable(i-1) <= numer);
6562  }
6563  if (!redundancy_dbm[j][i]) {
6564  numer_denom(dbm[j][i], numer, denom);
6565  cs.insert(denom*Variable(i-1) - denom*Variable(j-1) <= numer);
6566  }
6567  }
6568  }
6569  return cs;
6570 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Enable_If< Is_Native_Or_Checked< T >::value, void >::type numer_denom(const T &from, Coefficient &numer, Coefficient &denom)
Extract the numerator and denominator components of from.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
static const Constraint_System & zero_dim_empty()
Returns the singleton system containing only Constraint::zero_dim_false().
static const Constraint & zero_dim_false()
The unsatisfiable (zero-dimension space) constraint .
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void compute_leader_indices(const std::vector< dimension_type > &predecessor, std::vector< dimension_type > &indices)
Definition: BD_Shape.cc:85
void compute_leaders(std::vector< dimension_type > &leaders) const
Compute the leaders of zero-equivalence classes.
Bit_Matrix redundancy_dbm
A matrix indicating which constraints are redundant.
void shortest_path_reduction_assign() const
Assigns to this->dbm its shortest-path closure and records into this->redundancy_dbm which of the ent...
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::OK ( ) const

Returns true if and only if *this satisfies all its invariants.

Definition at line 6882 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::is_minus_infinity(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm, Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::Status::ascii_load(), and Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape().

6882  {
6883  // Check whether the difference-bound matrix is well-formed.
6884  if (!dbm.OK()) {
6885  return false;
6886  }
6887  // Check whether the status information is legal.
6888  if (!status.OK()) {
6889  return false;
6890  }
6891  // An empty BDS is OK.
6892  if (marked_empty()) {
6893  return true;
6894  }
6895  // MINUS_INFINITY cannot occur at all.
6896  for (dimension_type i = dbm.num_rows(); i-- > 0; ) {
6897  for (dimension_type j = dbm.num_rows(); j-- > 0; ) {
6898  if (is_minus_infinity(dbm[i][j])) {
6899 #ifndef NDEBUG
6900  using namespace Parma_Polyhedra_Library::IO_Operators;
6901  std::cerr << "BD_Shape::dbm[" << i << "][" << j << "] = "
6902  << dbm[i][j] << "!"
6903  << std::endl;
6904 #endif
6905  return false;
6906  }
6907  }
6908  }
6909  // On the main diagonal only PLUS_INFINITY can occur.
6910  for (dimension_type i = dbm.num_rows(); i-- > 0; ) {
6911  if (!is_plus_infinity(dbm[i][i])) {
6912 #ifndef NDEBUG
6913  using namespace Parma_Polyhedra_Library::IO_Operators;
6914  std::cerr << "BD_Shape::dbm[" << i << "][" << i << "] = "
6915  << dbm[i][i] << "! (+inf was expected.)"
6916  << std::endl;
6917 #endif
6918  return false;
6919  }
6920  }
6921  // Check whether the shortest-path closure information is legal.
6923  BD_Shape x = *this;
6924  x.reset_shortest_path_closed();
6925  x.shortest_path_closure_assign();
6926  if (x.dbm != dbm) {
6927 #ifndef NDEBUG
6928  std::cerr << "BD_Shape is marked as closed but it is not!"
6929  << std::endl;
6930 #endif
6931  return false;
6932  }
6933  }
6934 
6935  // The following tests might result in false alarms when using floating
6936  // point coefficients: they are only meaningful if the coefficient type
6937  // base is exact (since otherwise shortest-path closure is approximated).
6938  if (std::numeric_limits<coefficient_type_base>::is_exact) {
6939 
6940  // Check whether the shortest-path reduction information is legal.
6942  // A non-redundant constraint cannot be equal to PLUS_INFINITY.
6943  for (dimension_type i = dbm.num_rows(); i-- > 0; ) {
6944  for (dimension_type j = dbm.num_rows(); j-- > 0; ) {
6945  if (!redundancy_dbm[i][j] && is_plus_infinity(dbm[i][j])) {
6946 #ifndef NDEBUG
6947  using namespace Parma_Polyhedra_Library::IO_Operators;
6948  std::cerr << "BD_Shape::dbm[" << i << "][" << j << "] = "
6949  << dbm[i][j] << " is marked as non-redundant!"
6950  << std::endl;
6951 #endif
6952  return false;
6953  }
6954  }
6955  }
6956  BD_Shape x = *this;
6957  x.reset_shortest_path_reduced();
6958  x.shortest_path_reduction_assign();
6959  if (x.redundancy_dbm != redundancy_dbm) {
6960 #ifndef NDEBUG
6961  std::cerr << "BD_Shape is marked as reduced but it is not!"
6962  << std::endl;
6963 #endif
6964  return false;
6965  }
6966  }
6967  }
6968 
6969  // All checks passed.
6970  return true;
6971 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_minus_infinity(const T &x)
size_t dimension_type
An unsigned integral type for representing space dimensions.
BD_Shape(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty BDS of the specified space dimension.
All input/output operators are confined to this namespace.
bool marked_shortest_path_closed() const
Returns true if the system of bounded differences is known to be shortest-path closed.
bool marked_shortest_path_reduced() const
Returns true if the system of bounded differences is known to be shortest-path reduced.
bool OK() const
Checks if all the invariants are satisfied.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
Bit_Matrix redundancy_dbm
A matrix indicating which constraints are redundant.
Status status
The status flags to keep track of the internal state.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
template<typename Interval_Info >
void Parma_Polyhedra_Library::BD_Shape< T >::one_variable_affine_form_image ( const dimension_type var_id,
const Interval< T, Interval_Info > &  b,
const Interval< T, Interval_Info > &  w_coeff,
const dimension_type w_id,
const dimension_type space_dim 
)
private

Auxiliary function for affine formimage" that handle the general case: $l = ax + c$.

Definition at line 4467 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Interval< Boundary, Info >::lower(), PPL_DIRTY_TEMP, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::ROUND_UP, Parma_Polyhedra_Library::swap(), and Parma_Polyhedra_Library::Interval< Boundary, Info >::upper().

4471  {
4472 
4473  PPL_DIRTY_TEMP(N, b_ub);
4474  assign_r(b_ub, b.upper(), ROUND_NOT_NEEDED);
4475  PPL_DIRTY_TEMP(N, b_mlb);
4476  neg_assign_r(b_mlb, b.lower(), ROUND_NOT_NEEDED);
4477 
4478  // True if `w_coeff' is in [1, 1].
4479  bool is_w_coeff_one = (w_coeff == 1);
4480 
4481  if (w_id == var_id) {
4482  // True if `b' is in [b_mlb, b_ub] and that is [0, 0].
4483  bool is_b_zero = (b_mlb == 0 && b_ub == 0);
4484  // Here `lf' is of the form: [+/-1, +/-1] * v + b.
4485  if (is_w_coeff_one) {
4486  if (is_b_zero) {
4487  // The transformation is the identity function.
4488  return;
4489  }
4490  else {
4491  // Translate all the constraints on `var' by adding the value
4492  // `b_ub' or subtracting the value `b_mlb'.
4493  DB_Row<N>& dbm_v = dbm[var_id];
4494  for (dimension_type i = space_dim + 1; i-- > 0; ) {
4495  N& dbm_vi = dbm_v[i];
4496  add_assign_r(dbm_vi, dbm_vi, b_mlb, ROUND_UP);
4497  N& dbm_iv = dbm[i][var_id];
4498  add_assign_r(dbm_iv, dbm_iv, b_ub, ROUND_UP);
4499  }
4500  // Both shortest-path closure and reduction are preserved.
4501  }
4502  }
4503  else {
4504  // Here `w_coeff = [-1, -1].
4505  // Remove the binary constraints on `var'.
4507  using std::swap;
4508  swap(dbm[var_id][0], dbm[0][var_id]);
4509  // Shortest-path closure is not preserved.
4511  if (!is_b_zero) {
4512  // Translate the unary constraints on `var' by adding the value
4513  // `b_ub' or subtracting the value `b_mlb'.
4514  N& dbm_v0 = dbm[var_id][0];
4515  add_assign_r(dbm_v0, dbm_v0, b_mlb, ROUND_UP);
4516  N& dbm_0v = dbm[0][var_id];
4517  add_assign_r(dbm_0v, dbm_0v, b_ub, ROUND_UP);
4518  }
4519  }
4520  }
4521  else {
4522  // Here `w != var', so that `lf' is of the form
4523  // [+/-1, +/-1] * w + b.
4524  // Remove all constraints on `var'.
4526  // Shortest-path closure is preserved, but not reduction.
4529  }
4530  if (is_w_coeff_one) {
4531  // Add the new constraints `var - w >= b_mlb'
4532  // `and var - w <= b_ub'.
4533  add_dbm_constraint(w_id, var_id, b_ub);
4534  add_dbm_constraint(var_id, w_id, b_mlb);
4535  }
4536  else {
4537  // We have to add the constraint `v + w == b', over-approximating it
4538  // by computing lower and upper bounds for `w'.
4539  const N& mlb_w = dbm[w_id][0];
4540  if (!is_plus_infinity(mlb_w)) {
4541  // Add the constraint `v <= ub - lb_w'.
4542  add_assign_r(dbm[0][var_id], b_ub, mlb_w, ROUND_UP);
4544  }
4545  const N& ub_w = dbm[0][w_id];
4546  if (!is_plus_infinity(ub_w)) {
4547  // Add the constraint `v >= lb - ub_w'.
4548  add_assign_r(dbm[var_id][0], ub_w, b_mlb, ROUND_UP);
4550  }
4551  }
4552  }
4553  return;
4554 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
void swap(CO_Tree &x, CO_Tree &y)
size_t dimension_type
An unsigned integral type for representing space dimensions.
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
bool marked_shortest_path_reduced() const
Returns true if the system of bounded differences is known to be shortest-path reduced.
void reset_shortest_path_closed()
Marks *this as possibly not shortest-path closed.
void add_dbm_constraint(dimension_type i, dimension_type j, const N &k)
Adds the constraint dbm[i][j] <= k.
void swap(BD_Shape< T > &x, BD_Shape< T > &y)
Swaps x with y.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
#define PPL_DIRTY_TEMP(T, id)
void forget_binary_dbm_constraints(dimension_type v)
Removes all binary constraints on row/column v.
void forget_all_dbm_constraints(dimension_type v)
Removes all the constraints on row/column v.
void reset_shortest_path_reduced()
Marks *this as possibly not shortest-path reduced.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
BD_Shape< T > & Parma_Polyhedra_Library::BD_Shape< T >::operator= ( const BD_Shape< T > &  y)
inline

The assignment operator (*this and y can be dimension-incompatible).

Definition at line 346 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm, and Parma_Polyhedra_Library::BD_Shape< T >::status.

346  {
347  dbm = y.dbm;
348  status = y.status;
349  if (y.marked_shortest_path_reduced()) {
350  redundancy_dbm = y.redundancy_dbm;
351  }
352  return *this;
353 }
Bit_Matrix redundancy_dbm
A matrix indicating which constraints are redundant.
Status status
The status flags to keep track of the internal state.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T>
void Parma_Polyhedra_Library::BD_Shape< T >::print ( ) const

Prints *this to std::cerr using operator<<.

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::refine ( Variable  var,
Relation_Symbol  relsym,
const Linear_Expression expr,
Coefficient_traits::const_reference  denominator = Coefficient_one() 
)
private

Adds to the BDS the constraint $\mathrm{var} \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}$.

Note that the coefficient of var in expr is null.

Definition at line 3618 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::Linear_Expression::all_zeroes(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::begin(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::Linear_Expression::get(), 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::Linear_Expression::last_nonzero(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::Linear_Expression::lower_bound(), Parma_Polyhedra_Library::neg_assign(), PPL_DIRTY_TEMP, PPL_DIRTY_TEMP_COEFFICIENT, PPL_UNINITIALIZED, Parma_Polyhedra_Library::ROUND_UP, Parma_Polyhedra_Library::Boundary_NS::sgn(), and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

3621  {
3622  PPL_ASSERT(denominator != 0);
3623  PPL_ASSERT(space_dimension() >= expr.space_dimension());
3624  const dimension_type v = var.id() + 1;
3625  PPL_ASSERT(v <= space_dimension());
3626  PPL_ASSERT(expr.coefficient(var) == 0);
3627  PPL_ASSERT(relsym != LESS_THAN && relsym != GREATER_THAN);
3628 
3629  const Coefficient& b = expr.inhomogeneous_term();
3630  // Number of non-zero coefficients in `expr': will be set to
3631  // 0, 1, or 2, the latter value meaning any value greater than 1.
3632  dimension_type t = 0;
3633  // Index of the last non-zero coefficient in `expr', if any.
3634  dimension_type w = expr.last_nonzero();
3635 
3636  if (w != 0) {
3637  ++t;
3638  if (!expr.all_zeroes(1, w)) {
3639  ++t;
3640  }
3641  }
3642 
3643  // Since we are only able to record bounded differences, we can
3644  // precisely deal with the case of a single variable only if its
3645  // coefficient (taking into account the denominator) is 1.
3646  // If this is not the case, we fall back to the general case
3647  // so as to over-approximate the constraint.
3648  if (t == 1 && expr.get(Variable(w - 1)) != denominator) {
3649  t = 2;
3650  }
3651  // Now we know the form of `expr':
3652  // - If t == 0, then expr == b, with `b' a constant;
3653  // - If t == 1, then expr == a*w + b, where `w != v' and `a == denominator';
3654  // - If t == 2, the `expr' is of the general form.
3655  const DB_Row<N>& dbm_0 = dbm[0];
3656  PPL_DIRTY_TEMP_COEFFICIENT(minus_denom);
3657  neg_assign(minus_denom, denominator);
3658 
3659  if (t == 0) {
3660  // Case 1: expr == b.
3661  switch (relsym) {
3662  case EQUAL:
3663  // Add the constraint `var == b/denominator'.
3664  add_dbm_constraint(0, v, b, denominator);
3665  add_dbm_constraint(v, 0, b, minus_denom);
3666  break;
3667  case LESS_OR_EQUAL:
3668  // Add the constraint `var <= b/denominator'.
3669  add_dbm_constraint(0, v, b, denominator);
3670  break;
3671  case GREATER_OR_EQUAL:
3672  // Add the constraint `var >= b/denominator',
3673  // i.e., `-var <= -b/denominator',
3674  add_dbm_constraint(v, 0, b, minus_denom);
3675  break;
3676  default:
3677  // We already dealt with the other cases.
3678  PPL_UNREACHABLE;
3679  break;
3680  }
3681  return;
3682  }
3683 
3684  if (t == 1) {
3685  // Case 2: expr == a*w + b, w != v, a == denominator.
3686  PPL_ASSERT(expr.get(Variable(w - 1)) == denominator);
3687  PPL_DIRTY_TEMP(N, d);
3688  switch (relsym) {
3689  case EQUAL:
3690  // Add the new constraint `v - w <= b/denominator'.
3691  div_round_up(d, b, denominator);
3692  add_dbm_constraint(w, v, d);
3693  // Add the new constraint `v - w >= b/denominator',
3694  // i.e., `w - v <= -b/denominator'.
3695  div_round_up(d, b, minus_denom);
3696  add_dbm_constraint(v, w, d);
3697  break;
3698  case LESS_OR_EQUAL:
3699  // Add the new constraint `v - w <= b/denominator'.
3700  div_round_up(d, b, denominator);
3701  add_dbm_constraint(w, v, d);
3702  break;
3703  case GREATER_OR_EQUAL:
3704  // Add the new constraint `v - w >= b/denominator',
3705  // i.e., `w - v <= -b/denominator'.
3706  div_round_up(d, b, minus_denom);
3707  add_dbm_constraint(v, w, d);
3708  break;
3709  default:
3710  // We already dealt with the other cases.
3711  PPL_UNREACHABLE;
3712  break;
3713  }
3714  return;
3715  }
3716 
3717  // Here t == 2, so that either
3718  // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2, or
3719  // expr == a*w + b, w != v and a != denominator.
3720  const bool is_sc = (denominator > 0);
3721  PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
3722  neg_assign(minus_b, b);
3723  const Coefficient& sc_b = is_sc ? b : minus_b;
3724  const Coefficient& minus_sc_b = is_sc ? minus_b : b;
3725  const Coefficient& sc_denom = is_sc ? denominator : minus_denom;
3726  const Coefficient& minus_sc_denom = is_sc ? minus_denom : denominator;
3727  // NOTE: here, for optimization purposes, `minus_expr' is only assigned
3728  // when `denominator' is negative. Do not use it unless you are sure
3729  // it has been correctly assigned.
3730  Linear_Expression minus_expr;
3731  if (!is_sc) {
3732  minus_expr = -expr;
3733  }
3734  const Linear_Expression& sc_expr = is_sc ? expr : minus_expr;
3735 
3736  PPL_DIRTY_TEMP(N, sum);
3737  // Indices of the variables that are unbounded in `this->dbm'.
3738  PPL_UNINITIALIZED(dimension_type, pinf_index);
3739  // Number of unbounded variables found.
3740  dimension_type pinf_count = 0;
3741 
3742  // Speculative allocation of temporaries that are used in most
3743  // of the computational traces starting from this point (also loops).
3744  PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
3745  PPL_DIRTY_TEMP(N, coeff_i);
3746 
3747  switch (relsym) {
3748  case EQUAL:
3749  {
3750  PPL_DIRTY_TEMP(N, neg_sum);
3751  // Indices of the variables that are unbounded in `this->dbm'.
3752  PPL_UNINITIALIZED(dimension_type, neg_pinf_index);
3753  // Number of unbounded variables found.
3754  dimension_type neg_pinf_count = 0;
3755 
3756  // Compute an upper approximation for `expr' into `sum',
3757  // taking into account the sign of `denominator'.
3758 
3759  // Approximate the inhomogeneous term.
3760  assign_r(sum, sc_b, ROUND_UP);
3761  assign_r(neg_sum, minus_sc_b, ROUND_UP);
3762 
3763  // Approximate the homogeneous part of `sc_expr'.
3764  // Note: indices above `w' can be disregarded, as they all have
3765  // a zero coefficient in `expr'.
3766  for (Linear_Expression::const_iterator i = sc_expr.begin(),
3767  i_end = sc_expr.lower_bound(Variable(w)); i != i_end; ++i) {
3768  const dimension_type i_dim = i.variable().space_dimension();
3769  const Coefficient& sc_i = *i;
3770  const int sign_i = sgn(sc_i);
3771  PPL_ASSERT(sign_i != 0);
3772  if (sign_i > 0) {
3773  assign_r(coeff_i, sc_i, ROUND_UP);
3774  // Approximating `sc_expr'.
3775  if (pinf_count <= 1) {
3776  const N& approx_i = dbm_0[i_dim];
3777  if (!is_plus_infinity(approx_i)) {
3778  add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
3779  }
3780  else {
3781  ++pinf_count;
3782  pinf_index = i_dim;
3783  }
3784  }
3785  // Approximating `-sc_expr'.
3786  if (neg_pinf_count <= 1) {
3787  const N& approx_minus_i = dbm[i_dim][0];
3788  if (!is_plus_infinity(approx_minus_i)) {
3789  add_mul_assign_r(neg_sum, coeff_i, approx_minus_i, ROUND_UP);
3790  }
3791  else {
3792  ++neg_pinf_count;
3793  neg_pinf_index = i_dim;
3794  }
3795  }
3796  }
3797  else {
3798  PPL_ASSERT(sign_i < 0);
3799  neg_assign(minus_sc_i, sc_i);
3800  // Note: using temporary named `coeff_i' to store -coeff_i.
3801  assign_r(coeff_i, minus_sc_i, ROUND_UP);
3802  // Approximating `sc_expr'.
3803  if (pinf_count <= 1) {
3804  const N& approx_minus_i = dbm[i_dim][0];
3805  if (!is_plus_infinity(approx_minus_i)) {
3806  add_mul_assign_r(sum, coeff_i, approx_minus_i, ROUND_UP);
3807  }
3808  else {
3809  ++pinf_count;
3810  pinf_index = i_dim;
3811  }
3812  }
3813  // Approximating `-sc_expr'.
3814  if (neg_pinf_count <= 1) {
3815  const N& approx_i = dbm_0[i_dim];
3816  if (!is_plus_infinity(approx_i)) {
3817  add_mul_assign_r(neg_sum, coeff_i, approx_i, ROUND_UP);
3818  }
3819  else {
3820  ++neg_pinf_count;
3821  neg_pinf_index = i_dim;
3822  }
3823  }
3824  }
3825  }
3826  // Return immediately if no approximation could be computed.
3827  if (pinf_count > 1 && neg_pinf_count > 1) {
3828  PPL_ASSERT(OK());
3829  return;
3830  }
3831 
3832  // In the following, shortest-path closure will be definitely lost.
3834 
3835  // Before computing quotients, the denominator should be approximated
3836  // towards zero. Since `sc_denom' is known to be positive, this amounts to
3837  // rounding downwards, which is achieved as usual by rounding upwards
3838  // `minus_sc_denom' and negating again the result.
3839  PPL_DIRTY_TEMP(N, down_sc_denom);
3840  assign_r(down_sc_denom, minus_sc_denom, ROUND_UP);
3841  neg_assign_r(down_sc_denom, down_sc_denom, ROUND_UP);
3842 
3843  // Exploit the upper approximation, if possible.
3844  if (pinf_count <= 1) {
3845  // Compute quotient (if needed).
3846  if (down_sc_denom != 1) {
3847  div_assign_r(sum, sum, down_sc_denom, ROUND_UP);
3848  }
3849  // Add the upper bound constraint, if meaningful.
3850  if (pinf_count == 0) {
3851  // Add the constraint `v <= sum'.
3852  dbm[0][v] = sum;
3853  // Deduce constraints of the form `v - u', where `u != v'.
3854  deduce_v_minus_u_bounds(v, w, sc_expr, sc_denom, sum);
3855  }
3856  else {
3857  // Here `pinf_count == 1'.
3858  if (pinf_index != v
3859  && sc_expr.get(Variable(pinf_index - 1)) == sc_denom) {
3860  // Add the constraint `v - pinf_index <= sum'.
3861  dbm[pinf_index][v] = sum;
3862  }
3863  }
3864  }
3865 
3866  // Exploit the lower approximation, if possible.
3867  if (neg_pinf_count <= 1) {
3868  // Compute quotient (if needed).
3869  if (down_sc_denom != 1) {
3870  div_assign_r(neg_sum, neg_sum, down_sc_denom, ROUND_UP);
3871  }
3872  // Add the lower bound constraint, if meaningful.
3873  if (neg_pinf_count == 0) {
3874  // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'.
3875  DB_Row<N>& dbm_v = dbm[v];
3876  dbm_v[0] = neg_sum;
3877  // Deduce constraints of the form `u - v', where `u != v'.
3878  deduce_u_minus_v_bounds(v, w, sc_expr, sc_denom, neg_sum);
3879  }
3880  // Here `neg_pinf_count == 1'.
3881  else if (neg_pinf_index != v
3882  && sc_expr.get(Variable(neg_pinf_index - 1)) == sc_denom) {
3883  // Add the constraint `v - neg_pinf_index >= -neg_sum',
3884  // i.e., `neg_pinf_index - v <= neg_sum'.
3885  dbm[v][neg_pinf_index] = neg_sum;
3886  }
3887  }
3888  }
3889  break;
3890 
3891  case LESS_OR_EQUAL:
3892  // Compute an upper approximation for `expr' into `sum',
3893  // taking into account the sign of `denominator'.
3894 
3895  // Approximate the inhomogeneous term.
3896  assign_r(sum, sc_b, ROUND_UP);
3897 
3898  // Approximate the homogeneous part of `sc_expr'.
3899  // Note: indices above `w' can be disregarded, as they all have
3900  // a zero coefficient in `expr'.
3901  for (Linear_Expression::const_iterator i = sc_expr.begin(),
3902  i_end = sc_expr.lower_bound(Variable(w)); i != i_end; ++i) {
3903  const Coefficient& sc_i = *i;
3904  const dimension_type i_dim = i.variable().space_dimension();
3905  const int sign_i = sgn(sc_i);
3906  PPL_ASSERT(sign_i != 0);
3907  // Choose carefully: we are approximating `sc_expr'.
3908  const N& approx_i = (sign_i > 0) ? dbm_0[i_dim] : dbm[i_dim][0];
3909  if (is_plus_infinity(approx_i)) {
3910  if (++pinf_count > 1) {
3911  break;
3912  }
3913  pinf_index = i_dim;
3914  continue;
3915  }
3916  if (sign_i > 0) {
3917  assign_r(coeff_i, sc_i, ROUND_UP);
3918  }
3919  else {
3920  neg_assign(minus_sc_i, sc_i);
3921  assign_r(coeff_i, minus_sc_i, ROUND_UP);
3922  }
3923  add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
3924  }
3925 
3926  // Divide by the (sign corrected) denominator (if needed).
3927  if (sc_denom != 1) {
3928  // Before computing the quotient, the denominator should be
3929  // approximated towards zero. Since `sc_denom' is known to be
3930  // positive, this amounts to rounding downwards, which is achieved
3931  // by rounding upwards `minus_sc - denom' and negating again the result.
3932  PPL_DIRTY_TEMP(N, down_sc_denom);
3933  assign_r(down_sc_denom, minus_sc_denom, ROUND_UP);
3934  neg_assign_r(down_sc_denom, down_sc_denom, ROUND_UP);
3935  div_assign_r(sum, sum, down_sc_denom, ROUND_UP);
3936  }
3937 
3938  if (pinf_count == 0) {
3939  // Add the constraint `v <= sum'.
3940  add_dbm_constraint(0, v, sum);
3941  // Deduce constraints of the form `v - u', where `u != v'.
3942  deduce_v_minus_u_bounds(v, w, sc_expr, sc_denom, sum);
3943  }
3944  else if (pinf_count == 1) {
3945  if (expr.get(Variable(pinf_index - 1)) == denominator) {
3946  // Add the constraint `v - pinf_index <= sum'.
3947  add_dbm_constraint(pinf_index, v, sum);
3948  }
3949  }
3950  break;
3951 
3952  case GREATER_OR_EQUAL:
3953  // Compute an upper approximation for `-sc_expr' into `sum'.
3954  // Note: approximating `-sc_expr' from above and then negating the
3955  // result is the same as approximating `sc_expr' from below.
3956 
3957  // Approximate the inhomogeneous term.
3958  assign_r(sum, minus_sc_b, ROUND_UP);
3959 
3960  // Approximate the homogeneous part of `-sc_expr'.
3961  for (Linear_Expression::const_iterator i = sc_expr.begin(),
3962  i_end = sc_expr.lower_bound(Variable(w)); i != i_end; ++i) {
3963  const Coefficient& sc_i = *i;
3964  const dimension_type i_dim = i.variable().space_dimension();
3965  const int sign_i = sgn(sc_i);
3966  PPL_ASSERT(sign_i != 0);
3967  // Choose carefully: we are approximating `-sc_expr'.
3968  const N& approx_i = (sign_i > 0) ? dbm[i_dim][0] : dbm_0[i_dim];
3969  if (is_plus_infinity(approx_i)) {
3970  if (++pinf_count > 1) {
3971  break;
3972  }
3973  pinf_index = i_dim;
3974  continue;
3975  }
3976  if (sign_i > 0) {
3977  assign_r(coeff_i, sc_i, ROUND_UP);
3978  }
3979  else {
3980  neg_assign(minus_sc_i, sc_i);
3981  assign_r(coeff_i, minus_sc_i, ROUND_UP);
3982  }
3983  add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
3984  }
3985 
3986  // Divide by the (sign corrected) denominator (if needed).
3987  if (sc_denom != 1) {
3988  // Before computing the quotient, the denominator should be
3989  // approximated towards zero. Since `sc_denom' is known to be positive,
3990  // this amounts to rounding downwards, which is achieved by rounding
3991  // upwards `minus_sc_denom' and negating again the result.
3992  PPL_DIRTY_TEMP(N, down_sc_denom);
3993  assign_r(down_sc_denom, minus_sc_denom, ROUND_UP);
3994  neg_assign_r(down_sc_denom, down_sc_denom, ROUND_UP);
3995  div_assign_r(sum, sum, down_sc_denom, ROUND_UP);
3996  }
3997 
3998  if (pinf_count == 0) {
3999  // Add the constraint `v >= -sum', i.e., `-v <= sum'.
4000  add_dbm_constraint(v, 0, sum);
4001  // Deduce constraints of the form `u - v', where `u != v'.
4002  deduce_u_minus_v_bounds(v, w, sc_expr, sc_denom, sum);
4003  }
4004  else if (pinf_count == 1) {
4005  if (pinf_index != v
4006  && expr.get(Variable(pinf_index - 1)) == denominator) {
4007  // Add the constraint `v - pinf_index >= -sum',
4008  // i.e., `pinf_index - v <= sum'.
4009  add_dbm_constraint(v, pinf_index, sum);
4010  }
4011  }
4012  break;
4013 
4014  default:
4015  // We already dealt with the other cases.
4016  PPL_UNREACHABLE;
4017  break;
4018  }
4019 
4020  PPL_ASSERT(OK());
4021 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
void deduce_u_minus_v_bounds(dimension_type v, dimension_type last_v, const Linear_Expression &sc_expr, Coefficient_traits::const_reference sc_denom, const N &minus_lb_v)
An helper function for the computation of affine relations.
size_t dimension_type
An unsigned integral type for representing space dimensions.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
Enable_If< Is_Native_Or_Checked< T >::value, void >::type div_round_up(T &to, Coefficient_traits::const_reference x, Coefficient_traits::const_reference y)
Divides x by y into to, rounding the result towards plus infinity.
void reset_shortest_path_closed()
Marks *this as possibly not shortest-path closed.
void add_dbm_constraint(dimension_type i, dimension_type j, const N &k)
Adds the constraint dbm[i][j] <= k.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
void deduce_v_minus_u_bounds(dimension_type v, dimension_type last_v, const Linear_Expression &sc_expr, Coefficient_traits::const_reference sc_denom, const N &ub_v)
An helper function for the computation of affine relations.
#define PPL_DIRTY_TEMP(T, id)
bool OK() const
Returns true if and only if *this satisfies all its invariants.
void neg_assign(GMP_Integer &x)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
int sgn(Boundary_Type type, const T &x, const Info &info)
#define PPL_UNINITIALIZED(type, name)
Definition: compiler.hh:72
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
template<typename Interval_Info >
void Parma_Polyhedra_Library::BD_Shape< T >::refine_fp_interval_abstract_store ( Box< Interval< T, Interval_Info > > &  store) const
inline

Refines store with the constraints defining *this.

Parameters
storeThe interval floating point abstract store to refine.

Definition at line 925 of file BD_Shape_inlines.hh.

References PPL_COMPILE_TIME_CHECK.

926  {
927 
928  // Check that T is a floating point type.
929  PPL_COMPILE_TIME_CHECK(!std::numeric_limits<T>::is_exact,
930  "BD_Shape<T>::refine_fp_interval_abstract_store:"
931  " T not a floating point type.");
932 
933  typedef Interval<T, Interval_Info> FP_Interval_Type;
934  store.intersection_assign(Box<FP_Interval_Type>(*this));
935 }
#define PPL_COMPILE_TIME_CHECK(e, msg)
Produces a compilation error if the compile-time constant e does not evaluate to true ...
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check ( const Constraint c)
private

Uses the constraint c to refine *this.

Parameters
cThe constraint to be added. Non BD constraints are ignored.
Warning
If c and *this are dimension-incompatible, the behavior is undefined.

Definition at line 518 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::BD_Shape_Helpers::extract_bounded_difference(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::neg_assign(), PPL_DIRTY_TEMP, PPL_DIRTY_TEMP_COEFFICIENT, and Parma_Polyhedra_Library::Constraint::space_dimension().

518  {
519  PPL_ASSERT(!marked_empty());
520  PPL_ASSERT(c.space_dimension() <= space_dimension());
521 
522  dimension_type num_vars = 0;
523  dimension_type i = 0;
524  dimension_type j = 0;
526  // Constraints that are not bounded differences are ignored.
527  if (!BD_Shape_Helpers::extract_bounded_difference(c, num_vars, i, j, coeff)) {
528  return;
529  }
530  const Coefficient& inhomo = c.inhomogeneous_term();
531  if (num_vars == 0) {
532  // Dealing with a trivial constraint (might be a strict inequality).
533  if (inhomo < 0
534  || (c.is_equality() && inhomo != 0)
535  || (c.is_strict_inequality() && inhomo == 0)) {
536  set_empty();
537  }
538  return;
539  }
540 
541  // Select the cell to be modified for the "<=" part of the constraint,
542  // and set `coeff' to the absolute value of itself.
543  const bool negative = (coeff < 0);
544  N& x = negative ? dbm[i][j] : dbm[j][i];
545  N& y = negative ? dbm[j][i] : dbm[i][j];
546  if (negative) {
547  neg_assign(coeff);
548  }
549  bool changed = false;
550  // Compute the bound for `x', rounding towards plus infinity.
551  PPL_DIRTY_TEMP(N, d);
552  div_round_up(d, inhomo, coeff);
553  if (x > d) {
554  x = d;
555  changed = true;
556  }
557 
558  if (c.is_equality()) {
559  // Also compute the bound for `y', rounding towards plus infinity.
560  PPL_DIRTY_TEMP_COEFFICIENT(minus_c_term);
561  neg_assign(minus_c_term, inhomo);
562  div_round_up(d, minus_c_term, coeff);
563  if (y > d) {
564  y = d;
565  changed = true;
566  }
567  }
568 
569  // In general, adding a constraint does not preserve the shortest-path
570  // closure or reduction of the bounded difference shape.
571  if (changed && marked_shortest_path_closed()) {
573  }
574  PPL_ASSERT(OK());
575 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
bool marked_shortest_path_closed() const
Returns true if the system of bounded differences is known to be shortest-path closed.
Enable_If< Is_Native_Or_Checked< T >::value, void >::type div_round_up(T &to, Coefficient_traits::const_reference x, Coefficient_traits::const_reference y)
Divides x by y into to, rounding the result towards plus infinity.
void reset_shortest_path_closed()
Marks *this as possibly not shortest-path closed.
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
#define PPL_DIRTY_TEMP(T, id)
bool OK() const
Returns true if and only if *this satisfies all its invariants.
void neg_assign(GMP_Integer &x)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
static bool extract_bounded_difference(const Constraint &c, dimension_type &c_num_vars, dimension_type &c_first_var, dimension_type &c_second_var, Coefficient &c_coeff)
Decodes the constraint c as a bounded difference.
Coefficient c
Definition: PIP_Tree.cc:64
void set_empty()
Turns *this into an empty BDS.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check ( const Congruence cg)
inlineprivate

Uses the congruence cg to refine *this.

Parameters
cgThe congruence to be added. Nontrivial proper congruences are ignored. Non BD equalities are ignored.
Warning
If cg and *this are dimension-incompatible, the behavior is undefined.

Definition at line 253 of file BD_Shape_inlines.hh.

References c, Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), Parma_Polyhedra_Library::Congruence::is_proper_congruence(), and Parma_Polyhedra_Library::Congruence::space_dimension().

253  {
254  PPL_ASSERT(!marked_empty());
255  PPL_ASSERT(cg.space_dimension() <= space_dimension());
256 
257  if (cg.is_proper_congruence()) {
258  if (cg.is_inconsistent()) {
259  set_empty();
260  }
261  // Other proper congruences are just ignored.
262  return;
263  }
264 
265  PPL_ASSERT(cg.is_equality());
266  Constraint c(cg);
268 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
void refine_no_check(const Constraint &c)
Uses the constraint c to refine *this.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Coefficient c
Definition: PIP_Tree.cc:64
void set_empty()
Turns *this into an empty BDS.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::refine_with_congruence ( const Congruence cg)
inline

Uses a copy of congruence cg to refine the system of bounded differences of *this.

Parameters
cgThe congruence. If it is not a bounded difference equality, it will be ignored.
Exceptions
std::invalid_argumentThrown if *this and congruence cg are dimension-incompatible.

Definition at line 224 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::Congruence::space_dimension().

224  {
225  const dimension_type cg_space_dim = cg.space_dimension();
226  // Dimension-compatibility check.
227  if (cg_space_dim > space_dimension()) {
228  throw_dimension_incompatible("refine_with_congruence(cg)", cg);
229  }
230 
231  if (!marked_empty()) {
232  refine_no_check(cg);
233  }
234 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
void refine_no_check(const Constraint &c)
Uses the constraint c to refine *this.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::refine_with_congruences ( const Congruence_System cgs)

Uses a copy of the congruences in cgs to refine the system of bounded differences defining *this.

Parameters
cgsThe congruence system to be used. Congruences that are not bounded difference equalities are ignored.
Exceptions
std::invalid_argumentThrown if *this and cgs are dimension-incompatible.

Definition at line 238 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::Congruence_System::begin(), Parma_Polyhedra_Library::Congruence_System::end(), and Parma_Polyhedra_Library::Congruence_System::space_dimension().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape().

238  {
239  // Dimension-compatibility check.
240  if (cgs.space_dimension() > space_dimension()) {
241  throw_invalid_argument("refine_with_congruences(cgs)",
242  "cgs and *this are space-dimension incompatible");
243  }
244 
245  for (Congruence_System::const_iterator i = cgs.begin(),
246  cgs_end = cgs.end(); !marked_empty() && i != cgs_end; ++i) {
247  refine_no_check(*i);
248  }
249 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
void refine_no_check(const Constraint &c)
Uses the constraint c to refine *this.
static void throw_invalid_argument(const char *method, const char *reason)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::refine_with_constraint ( const Constraint c)
inline

Uses a copy of constraint c to refine the system of bounded differences defining *this.

Parameters
cThe constraint. If it is not a bounded difference, it will be ignored.
Exceptions
std::invalid_argumentThrown if *this and constraint c are dimension-incompatible.

Definition at line 195 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::Constraint::space_dimension().

195  {
196  const dimension_type c_space_dim = c.space_dimension();
197  // Dimension-compatibility check.
198  if (c_space_dim > space_dimension()) {
199  throw_dimension_incompatible("refine_with_constraint(c)", c);
200  }
201 
202  if (!marked_empty()) {
204  }
205 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
void refine_no_check(const Constraint &c)
Uses the constraint c to refine *this.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Coefficient c
Definition: PIP_Tree.cc:64
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::refine_with_constraints ( const Constraint_System cs)
inline

Uses a copy of the constraints in cs to refine the system of bounded differences defining *this.

Parameters
csThe constraint system to be used. Constraints that are not bounded differences are ignored.
Exceptions
std::invalid_argumentThrown if *this and cs are dimension-incompatible.

Definition at line 209 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Constraint_System::end(), and Parma_Polyhedra_Library::Constraint_System::space_dimension().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape().

209  {
210  // Dimension-compatibility check.
211  if (cs.space_dimension() > space_dimension()) {
212  throw_invalid_argument("refine_with_constraints(cs)",
213  "cs and *this are space-dimension incompatible");
214  }
215 
216  for (Constraint_System::const_iterator i = cs.begin(),
217  cs_end = cs.end(); !marked_empty() && i != cs_end; ++i) {
218  refine_no_check(*i);
219  }
220 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
void refine_no_check(const Constraint &c)
Uses the constraint c to refine *this.
static void throw_invalid_argument(const char *method, const char *reason)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Constraint_System_const_iterator const_iterator
template<typename T >
template<typename Interval_Info >
void Parma_Polyhedra_Library::BD_Shape< T >::refine_with_linear_form_inequality ( const Linear_Form< Interval< T, Interval_Info > > &  left,
const Linear_Form< Interval< T, Interval_Info > > &  right 
)

Refines the system of BD_Shape constraints defining *this using the constraint expressed by left $\leq$ right.

Parameters
leftThe linear form on intervals with floating point boundaries that is at the left of the comparison operator. All of its coefficients MUST be bounded.
rightThe linear form on intervals with floating point boundaries that is at the right of the comparison operator. All of its coefficients MUST be bounded.
Exceptions
std::invalid_argumentThrown if left (or right) is dimension-incompatible with *this.

This function is used in abstract interpretation to model a filter that is generated by a comparison of two expressions that are correctly approximated by left and right respectively.

Definition at line 4605 of file BD_Shape_templates.hh.

References PPL_COMPILE_TIME_CHECK.

4607  {
4608  // Check that T is a floating point type.
4609  PPL_COMPILE_TIME_CHECK(!std::numeric_limits<T>::is_exact,
4610  "Octagonal_Shape<T>::refine_with_linear_form_inequality:"
4611  " T not a floating point type.");
4612 
4613  //We assume that the analyzer will not try to apply an unreachable filter.
4614  PPL_ASSERT(!marked_empty());
4615 
4616  // Dimension-compatibility checks.
4617  // The dimensions of `left' and `right' should not be greater than the
4618  // dimension of `*this'.
4619  const dimension_type left_space_dim = left.space_dimension();
4620  const dimension_type space_dim = space_dimension();
4621  if (space_dim < left_space_dim) {
4623  "refine_with_linear_form_inequality(left, right)", "left", left);
4624  }
4625  const dimension_type right_space_dim = right.space_dimension();
4626  if (space_dim < right_space_dim) {
4628  "refine_with_linear_form_inequality(left, right)", "right", right);
4629  }
4630  // Number of non-zero coefficients in `left': will be set to
4631  // 0, 1, or 2, the latter value meaning any value greater than 1.
4632  dimension_type left_t = 0;
4633  // Variable-index of the last non-zero coefficient in `left', if any.
4634  dimension_type left_w_id = 0;
4635  // Number of non-zero coefficients in `right': will be set to
4636  // 0, 1, or 2, the latter value meaning any value greater than 1.
4637  dimension_type right_t = 0;
4638  // Variable-index of the last non-zero coefficient in `right', if any.
4639  dimension_type right_w_id = 0;
4640 
4641  typedef Interval<T, Interval_Info> FP_Interval_Type;
4642 
4643  // Get information about the number of non-zero coefficients in `left'.
4644  for (dimension_type i = left_space_dim; i-- > 0; ) {
4645  if (left.coefficient(Variable(i)) != 0) {
4646  if (left_t++ == 1) {
4647  break;
4648  }
4649  else {
4650  left_w_id = i;
4651  }
4652  }
4653  }
4654 
4655  // Get information about the number of non-zero coefficients in `right'.
4656  for (dimension_type i = right_space_dim; i-- > 0; ) {
4657  if (right.coefficient(Variable(i)) != 0) {
4658  if (right_t++ == 1) {
4659  break;
4660  }
4661  else {
4662  right_w_id = i;
4663  }
4664  }
4665  }
4666 
4667  const FP_Interval_Type& left_w_coeff =
4668  left.coefficient(Variable(left_w_id));
4669  const FP_Interval_Type& right_w_coeff =
4670  right.coefficient(Variable(right_w_id));
4671 
4672  if (left_t == 0) {
4673  if (right_t == 0) {
4674  // The constraint involves constants only. Ignore it: it is up to
4675  // the analyzer to handle it.
4676  PPL_ASSERT(OK());
4677  return;
4678  }
4679  else if (right_w_coeff == 1 || right_w_coeff == -1) {
4680  left_inhomogeneous_refine(right_t, right_w_id, left, right);
4681  PPL_ASSERT(OK());
4682  return;
4683  }
4684  }
4685  else if (left_t == 1) {
4686  if (left_w_coeff == 1 || left_w_coeff == -1) {
4687  if (right_t == 0 || (right_w_coeff == 1 || right_w_coeff == -1)) {
4688  left_one_var_refine(left_w_id, right_t, right_w_id, left, right);
4689  PPL_ASSERT(OK());
4690  return;
4691  }
4692  }
4693  }
4694 
4695  // General case.
4696  general_refine(left_w_id, right_w_id, left, right);
4697  PPL_ASSERT(OK());
4698 } // end of refine_with_linear_form_inequality
bool marked_empty() const
Returns true if the BDS is known to be empty.
void left_inhomogeneous_refine(const dimension_type &right_t, const dimension_type &right_w_id, const Linear_Form< Interval< T, Interval_Info > > &left, const Linear_Form< Interval< T, Interval_Info > > &right)
Auxiliary function for refine with linear form that handle the general case: .
size_t dimension_type
An unsigned integral type for representing space dimensions.
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
void left_one_var_refine(const dimension_type &left_w_id, const dimension_type &right_t, const dimension_type &right_w_id, const Linear_Form< Interval< T, Interval_Info > > &left, const Linear_Form< Interval< T, Interval_Info > > &right)
Auxiliary function for refine with linear form that handle the general case: .
#define PPL_COMPILE_TIME_CHECK(e, msg)
Produces a compilation error if the compile-time constant e does not evaluate to true ...
bool OK() const
Returns true if and only if *this satisfies all its invariants.
void general_refine(const dimension_type &left_w_id, const dimension_type &right_w_id, const Linear_Form< Interval< T, Interval_Info > > &left, const Linear_Form< Interval< T, Interval_Info > > &right)
Auxiliary function for refine with linear form that handle the general case.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
template<typename T >
Poly_Con_Relation Parma_Polyhedra_Library::BD_Shape< T >::relation_with ( const Constraint c) const

Returns the relations holding between *this and the constraint c.

Exceptions
std::invalid_argumentThrown if *this and constraint c are dimension-incompatible.

Definition at line 1494 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Coefficient_zero(), Parma_Polyhedra_Library::Constraint::expression(), Parma_Polyhedra_Library::BD_Shape_Helpers::extract_bounded_difference(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Constraint::is_inequality(), Parma_Polyhedra_Library::Constraint::is_nonstrict_inequality(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Boundary_NS::le(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), Parma_Polyhedra_Library::Boundary_NS::sgn(), Parma_Polyhedra_Library::Constraint::space_dimension(), and Parma_Polyhedra_Library::Poly_Con_Relation::strictly_intersects().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::difference_assign().

1494  {
1495  const dimension_type c_space_dim = c.space_dimension();
1496  const dimension_type space_dim = space_dimension();
1497 
1498  // Dimension-compatibility check.
1499  if (c_space_dim > space_dim) {
1500  throw_dimension_incompatible("relation_with(c)", c);
1501  }
1503 
1504  if (marked_empty()) {
1508  }
1509  if (space_dim == 0) {
1510  if ((c.is_equality() && c.inhomogeneous_term() != 0)
1511  || (c.is_inequality() && c.inhomogeneous_term() < 0)) {
1513  }
1514  else if (c.is_strict_inequality() && c.inhomogeneous_term() == 0) {
1515  // The constraint 0 > 0 implicitly defines the hyperplane 0 = 0;
1516  // thus, the zero-dimensional point also saturates it.
1519  }
1520  else if (c.is_equality() || c.inhomogeneous_term() == 0) {
1523  }
1524  else {
1525  // The zero-dimensional point saturates
1526  // neither the positivity constraint 1 >= 0,
1527  // nor the strict positivity constraint 1 > 0.
1529  }
1530  }
1531 
1532  dimension_type num_vars = 0;
1533  dimension_type i = 0;
1534  dimension_type j = 0;
1536  if (!BD_Shape_Helpers::extract_bounded_difference(c, num_vars, i, j, coeff)) {
1537  // Constraints that are not bounded differences.
1538  // Use maximize() and minimize() to do much of the work.
1539 
1540  // Find the linear expression for the constraint and use that to
1541  // find if the expression is bounded from above or below and if it
1542  // is, find the maximum and minimum values.
1543  Linear_Expression le(c.expression());
1544  le.set_inhomogeneous_term(Coefficient_zero());
1545 
1546  PPL_DIRTY_TEMP_COEFFICIENT(max_numer);
1547  PPL_DIRTY_TEMP_COEFFICIENT(max_denom);
1548  bool max_included;
1549  PPL_DIRTY_TEMP_COEFFICIENT(min_numer);
1550  PPL_DIRTY_TEMP_COEFFICIENT(min_denom);
1551  bool min_included;
1552  bool bounded_above = maximize(le, max_numer, max_denom, max_included);
1553  bool bounded_below = minimize(le, min_numer, min_denom, min_included);
1554  if (!bounded_above) {
1555  if (!bounded_below) {
1557  }
1558  min_numer += c.inhomogeneous_term() * min_denom;
1559  switch (sgn(min_numer)) {
1560  case 1:
1561  if (c.is_equality()) {
1563  }
1565  case 0:
1566  if (c.is_strict_inequality() || c.is_equality()) {
1568  }
1570  case -1:
1572  }
1573  }
1574  if (!bounded_below) {
1575  max_numer += c.inhomogeneous_term() * max_denom;
1576  switch (sgn(max_numer)) {
1577  case 1:
1579  case 0:
1580  if (c.is_strict_inequality()) {
1582  }
1584  case -1:
1586  }
1587  }
1588  else {
1589  max_numer += c.inhomogeneous_term() * max_denom;
1590  min_numer += c.inhomogeneous_term() * min_denom;
1591  switch (sgn(max_numer)) {
1592  case 1:
1593  switch (sgn(min_numer)) {
1594  case 1:
1595  if (c.is_equality()) {
1597  }
1599  case 0:
1600  if (c.is_equality()) {
1602  }
1603  if (c.is_strict_inequality()) {
1605  }
1607  case -1:
1609  }
1610  PPL_UNREACHABLE;
1611  break;
1612  case 0:
1613  if (min_numer == 0) {
1614  if (c.is_strict_inequality()) {
1617  }
1620  }
1621  if (c.is_strict_inequality()) {
1623  }
1625  case -1:
1627  }
1628  }
1629  }
1630 
1631  // Constraints that are bounded differences.
1632  if (num_vars == 0) {
1633  // Dealing with a trivial constraint.
1634  switch (sgn(c.inhomogeneous_term())) {
1635  case -1:
1637  case 0:
1638  if (c.is_strict_inequality()) {
1641  }
1642  else {
1645  }
1646  case 1:
1647  if (c.is_equality()) {
1649  }
1650  else {
1652  }
1653  }
1654  }
1655 
1656  // Select the cell to be checked for the "<=" part of the constraint,
1657  // and set `coeff' to the absolute value of itself.
1658  const bool negative = (coeff < 0);
1659  const N& x = negative ? dbm[i][j] : dbm[j][i];
1660  const N& y = negative ? dbm[j][i] : dbm[i][j];
1661  if (negative) {
1662  neg_assign(coeff);
1663  }
1664  // Deduce the relation/s of the constraint `c' of the form
1665  // `coeff*v - coeff*u </<=/== c.inhomogeneous_term()'
1666  // with the respectively constraints in `*this'
1667  // `-y <= v - u <= x'.
1668  // Let `d == c.inhomogeneous_term()/coeff'
1669  // and `d1 == -c.inhomogeneous_term()/coeff'.
1670  // The following variables of mpq_class type are used to be precise
1671  // when the bds is defined by integer constraints.
1672  PPL_DIRTY_TEMP(mpq_class, q_x);
1673  PPL_DIRTY_TEMP(mpq_class, q_y);
1674  PPL_DIRTY_TEMP(mpq_class, d);
1675  PPL_DIRTY_TEMP(mpq_class, d1);
1676  PPL_DIRTY_TEMP(mpq_class, c_denom);
1677  PPL_DIRTY_TEMP(mpq_class, q_denom);
1678  assign_r(c_denom, coeff, ROUND_NOT_NEEDED);
1679  assign_r(d, c.inhomogeneous_term(), ROUND_NOT_NEEDED);
1680  neg_assign_r(d1, d, ROUND_NOT_NEEDED);
1681  div_assign_r(d, d, c_denom, ROUND_NOT_NEEDED);
1682  div_assign_r(d1, d1, c_denom, ROUND_NOT_NEEDED);
1683 
1684  if (is_plus_infinity(x)) {
1685  if (!is_plus_infinity(y)) {
1686  // `*this' is in the following form:
1687  // `-y <= v - u'.
1688  // In this case `*this' is disjoint from `c' if
1689  // `-y > d' (`-y >= d' if c is a strict equality), i.e. if
1690  // `y < d1' (`y <= d1' if c is a strict equality).
1693  numer_denom(y, numer, denom);
1694  assign_r(q_denom, denom, ROUND_NOT_NEEDED);
1695  assign_r(q_y, numer, ROUND_NOT_NEEDED);
1696  div_assign_r(q_y, q_y, q_denom, ROUND_NOT_NEEDED);
1697  if (q_y < d1) {
1699  }
1700  if (q_y == d1 && c.is_strict_inequality()) {
1702  }
1703  }
1704 
1705  // In all other cases `*this' intersects `c'.
1707  }
1708 
1709  // Here `x' is not plus-infinity.
1712  numer_denom(x, numer, denom);
1713  assign_r(q_denom, denom, ROUND_NOT_NEEDED);
1714  assign_r(q_x, numer, ROUND_NOT_NEEDED);
1715  div_assign_r(q_x, q_x, q_denom, ROUND_NOT_NEEDED);
1716 
1717  if (!is_plus_infinity(y)) {
1718  numer_denom(y, numer, denom);
1719  assign_r(q_denom, denom, ROUND_NOT_NEEDED);
1720  assign_r(q_y, numer, ROUND_NOT_NEEDED);
1721  div_assign_r(q_y, q_y, q_denom, ROUND_NOT_NEEDED);
1722  if (q_x == d && q_y == d1) {
1723  if (c.is_strict_inequality()) {
1726  }
1727  else {
1730  }
1731  }
1732  // `*this' is disjoint from `c' when
1733  // `-y > d' (`-y >= d' if c is a strict equality), i.e. if
1734  // `y < d1' (`y <= d1' if c is a strict equality).
1735  if (q_y < d1) {
1737  }
1738  if (q_y == d1 && c.is_strict_inequality()) {
1740  }
1741  }
1742 
1743  // Here `y' can be also plus-infinity.
1744  // If `c' is an equality, `*this' is disjoint from `c' if
1745  // `x < d'.
1746  if (d > q_x) {
1747  if (c.is_equality()) {
1749  }
1750  else {
1752  }
1753  }
1754 
1755  if (d == q_x && c.is_nonstrict_inequality()) {
1757  }
1758  // In all other cases `*this' intersects `c'.
1760 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
static Poly_Con_Relation is_disjoint()
The polyhedron and the set of points satisfying the constraint are disjoint.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Enable_If< Is_Native_Or_Checked< T >::value, void >::type numer_denom(const T &from, Coefficient &numer, Coefficient &denom)
Extract the numerator and denominator components of from.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
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.
static Poly_Con_Relation is_included()
The polyhedron is included in the set of points satisfying the constraint.
static Poly_Con_Relation saturates()
The polyhedron is included in the set of points saturating the constraint.
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
#define PPL_DIRTY_TEMP(T, id)
void neg_assign(GMP_Integer &x)
Coefficient_traits::const_reference Coefficient_zero()
Returns a const reference to a Coefficient with value 0.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
int sgn(Boundary_Type type, const T &x, const Info &info)
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.
static bool extract_bounded_difference(const Constraint &c, dimension_type &c_num_vars, dimension_type &c_first_var, dimension_type &c_second_var, Coefficient &c_coeff)
Decodes the constraint c as a bounded difference.
Coefficient c
Definition: PIP_Tree.cc:64
static Poly_Con_Relation strictly_intersects()
The polyhedron intersects the set of points satisfying the constraint, but it is not included in it...
bool le(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
Poly_Con_Relation Parma_Polyhedra_Library::BD_Shape< T >::relation_with ( const Congruence cg) const

Returns the relations holding between *this and the congruence cg.

Exceptions
std::invalid_argumentThrown if *this and congruence cg are dimension-incompatible.

Definition at line 1399 of file BD_Shape_templates.hh.

References c, Parma_Polyhedra_Library::Congruence::expression(), 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::Boundary_NS::le(), Parma_Polyhedra_Library::Congruence::modulus(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), Parma_Polyhedra_Library::Congruence::space_dimension(), and Parma_Polyhedra_Library::Poly_Con_Relation::strictly_intersects().

1399  {
1400  const dimension_type space_dim = space_dimension();
1401 
1402  // Dimension-compatibility check.
1403  if (cg.space_dimension() > space_dim) {
1404  throw_dimension_incompatible("relation_with(cg)", cg);
1405  }
1406  // If the congruence is an equality, find the relation with
1407  // the equivalent equality constraint.
1408  if (cg.is_equality()) {
1409  Constraint c(cg);
1410  return relation_with(c);
1411  }
1412 
1414 
1415  if (marked_empty()) {
1419  }
1420  if (space_dim == 0) {
1421  if (cg.is_inconsistent()) {
1423  }
1424  else {
1427  }
1428  }
1429 
1430  // Find the lower bound for a hyperplane with direction
1431  // defined by the congruence.
1432  Linear_Expression le = Linear_Expression(cg.expression());
1433  PPL_DIRTY_TEMP_COEFFICIENT(min_numer);
1434  PPL_DIRTY_TEMP_COEFFICIENT(min_denom);
1435  bool min_included;
1436  bool bounded_below = minimize(le, min_numer, min_denom, min_included);
1437 
1438  // If there is no lower bound, then some of the hyperplanes defined by
1439  // the congruence will strictly intersect the shape.
1440  if (!bounded_below) {
1442  }
1443  // TODO: Consider adding a max_and_min() method, performing both
1444  // maximization and minimization so as to possibly exploit
1445  // incrementality of the MIP solver.
1446 
1447  // Find the upper bound for a hyperplane with direction
1448  // defined by the congruence.
1449  PPL_DIRTY_TEMP_COEFFICIENT(max_numer);
1450  PPL_DIRTY_TEMP_COEFFICIENT(max_denom);
1451  bool max_included;
1452  bool bounded_above = maximize(le, max_numer, max_denom, max_included);
1453 
1454  // If there is no upper bound, then some of the hyperplanes defined by
1455  // the congruence will strictly intersect the shape.
1456  if (!bounded_above) {
1458  }
1459  PPL_DIRTY_TEMP_COEFFICIENT(signed_distance);
1460 
1461  // Find the position value for the hyperplane that satisfies the congruence
1462  // and is above the lower bound for the shape.
1463  PPL_DIRTY_TEMP_COEFFICIENT(min_value);
1464  min_value = min_numer / min_denom;
1465  const Coefficient& modulus = cg.modulus();
1466  signed_distance = min_value % modulus;
1467  min_value -= signed_distance;
1468  if (min_value * min_denom < min_numer) {
1469  min_value += modulus;
1470  }
1471  // Find the position value for the hyperplane that satisfies the congruence
1472  // and is below the upper bound for the shape.
1473  PPL_DIRTY_TEMP_COEFFICIENT(max_value);
1474  max_value = max_numer / max_denom;
1475  signed_distance = max_value % modulus;
1476  max_value += signed_distance;
1477  if (max_value * max_denom > max_numer) {
1478  max_value -= modulus;
1479  }
1480  // If the upper bound value is less than the lower bound value,
1481  // then there is an empty intersection with the congruence;
1482  // otherwise it will strictly intersect.
1483  if (max_value < min_value) {
1485  }
1486  else {
1488  }
1489 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
static Poly_Con_Relation is_disjoint()
The polyhedron and the set of points satisfying the constraint are disjoint.
size_t dimension_type
An unsigned integral type for representing space dimensions.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
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.
static Poly_Con_Relation is_included()
The polyhedron is included in the set of points satisfying the constraint.
static Poly_Con_Relation saturates()
The polyhedron is included in the set of points saturating the constraint.
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
Poly_Con_Relation relation_with(const Constraint &c) const
Returns the relations holding between *this and the constraint c.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *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.
Coefficient c
Definition: PIP_Tree.cc:64
static Poly_Con_Relation strictly_intersects()
The polyhedron intersects the set of points satisfying the constraint, but it is not included in it...
bool le(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
template<typename T >
Poly_Gen_Relation Parma_Polyhedra_Library::BD_Shape< T >::relation_with ( const Generator g) const

Returns the relations holding between *this and the generator g.

Exceptions
std::invalid_argumentThrown if *this and generator g are dimension-incompatible.

Definition at line 1764 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::add_mul_assign(), Parma_Polyhedra_Library::Generator::coefficient(), Parma_Polyhedra_Library::Coefficient_zero(), Parma_Polyhedra_Library::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::Poly_Gen_Relation::nothing(), Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Generator::space_dimension(), and Parma_Polyhedra_Library::Poly_Gen_Relation::subsumes().

1764  {
1765  const dimension_type space_dim = space_dimension();
1766  const dimension_type g_space_dim = g.space_dimension();
1767 
1768  // Dimension-compatibility check.
1769  if (space_dim < g_space_dim) {
1770  throw_dimension_incompatible("relation_with(g)", g);
1771  }
1773  // The empty BDS cannot subsume a generator.
1774  if (marked_empty()) {
1775  return Poly_Gen_Relation::nothing();
1776  }
1777  // A universe BDS in a zero-dimensional space subsumes
1778  // all the generators of a zero-dimensional space.
1779  if (space_dim == 0) {
1780  return Poly_Gen_Relation::subsumes();
1781  }
1782  const bool is_line = g.is_line();
1783  const bool is_line_or_ray = g.is_line_or_ray();
1784 
1785  // The relation between the BDS and the given generator is obtained
1786  // checking if the generator satisfies all the constraints in the BDS.
1787  // To check if the generator satisfies all the constraints it's enough
1788  // studying the sign of the scalar product between the generator and
1789  // all the constraints in the BDS.
1790 
1791  // Allocation of temporaries done once and for all.
1794  PPL_DIRTY_TEMP_COEFFICIENT(product);
1795  // We find in `*this' all the constraints.
1796  // TODO: This loop can be optimized more, if needed.
1797  for (dimension_type i = 0; i <= space_dim; ++i) {
1798  const Coefficient& g_coeff_y = (i > g_space_dim || i == 0)
1799  ? Coefficient_zero() : g.coefficient(Variable(i-1));
1800  const DB_Row<N>& dbm_i = dbm[i];
1801  for (dimension_type j = i + 1; j <= space_dim; ++j) {
1802  const Coefficient& g_coeff_x = (j > g_space_dim)
1803  ? Coefficient_zero() : g.coefficient(Variable(j-1));
1804  const N& dbm_ij = dbm_i[j];
1805  const N& dbm_ji = dbm[j][i];
1806  if (is_additive_inverse(dbm_ji, dbm_ij)) {
1807  // We have one equality constraint: denom*x - denom*y = numer.
1808  // Compute the scalar product.
1809  numer_denom(dbm_ij, numer, denom);
1810  product = g_coeff_y;
1811  product -= g_coeff_x;
1812  product *= denom;
1813  if (!is_line_or_ray) {
1814  add_mul_assign(product, numer, g.divisor());
1815  }
1816  if (product != 0) {
1817  return Poly_Gen_Relation::nothing();
1818  }
1819  }
1820  else {
1821  // We have 0, 1 or 2 binary inequality constraint/s.
1822  if (!is_plus_infinity(dbm_ij)) {
1823  // We have the binary inequality constraint:
1824  // denom*x - denom*y <= numer.
1825  // Compute the scalar product.
1826  numer_denom(dbm_ij, numer, denom);
1827  product = g_coeff_y;
1828  product -= g_coeff_x;
1829  product *= denom;
1830  if (!is_line_or_ray) {
1831  add_mul_assign(product, numer, g.divisor());
1832  }
1833  if (is_line) {
1834  if (product != 0) {
1835  // Lines must saturate all constraints.
1836  return Poly_Gen_Relation::nothing();
1837  }
1838  }
1839  else {
1840  // `g' is either a ray, a point or a closure point.
1841  if (product < 0) {
1842  return Poly_Gen_Relation::nothing();
1843  }
1844  }
1845  }
1846 
1847  if (!is_plus_infinity(dbm_ji)) {
1848  // We have the binary inequality constraint: denom*y - denom*x <= b.
1849  // Compute the scalar product.
1850  numer_denom(dbm_ji, numer, denom);
1851  product = 0;
1852  add_mul_assign(product, denom, g_coeff_x);
1853  add_mul_assign(product, -denom, g_coeff_y);
1854  if (!is_line_or_ray) {
1855  add_mul_assign(product, numer, g.divisor());
1856  }
1857  if (is_line) {
1858  if (product != 0) {
1859  // Lines must saturate all constraints.
1860  return Poly_Gen_Relation::nothing();
1861  }
1862  }
1863  else {
1864  // `g' is either a ray, a point or a closure point.
1865  if (product < 0) {
1866  return Poly_Gen_Relation::nothing();
1867  }
1868  }
1869  }
1870  }
1871  }
1872  }
1873 
1874  // The generator satisfies all the constraints.
1875  return Poly_Gen_Relation::subsumes();
1876 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
static Poly_Gen_Relation subsumes()
Adding the generator would not change the polyhedron.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Enable_If< Is_Native_Or_Checked< T >::value, void >::type numer_denom(const T &from, Coefficient &numer, Coefficient &denom)
Extract the numerator and denominator components of from.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
void add_mul_assign(GMP_Integer &x, const GMP_Integer &y, const GMP_Integer &z)
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_additive_inverse(const T &x, const T &y)
Returns true if and only if .
Coefficient_traits::const_reference Coefficient_zero()
Returns a const reference to a Coefficient with value 0.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
static Poly_Gen_Relation nothing()
The assertion that says nothing.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::remove_higher_space_dimensions ( dimension_type  new_dimension)
inline

Removes the higher dimensions so that the resulting space will have dimension new_dimension.

Exceptions
std::invalid_argumentThrown if new_dimension is greater than the space dimension of *this.

Definition at line 780 of file BD_Shape_inlines.hh.

780  {
781  // Dimension-compatibility check: the variable having
782  // maximum index is the one occurring last in the set.
783  const dimension_type space_dim = space_dimension();
784  if (new_dimension > space_dim) {
785  throw_dimension_incompatible("remove_higher_space_dimensions(nd)",
786  new_dimension);
787  }
788 
789  // The removal of no dimensions from any BDS is a no-op.
790  // Note that this case also captures the only legal removal of
791  // dimensions from a zero-dim space BDS.
792  if (new_dimension == space_dim) {
793  PPL_ASSERT(OK());
794  return;
795  }
796 
797  // Shortest-path closure is necessary as in remove_space_dimensions().
799  dbm.resize_no_copy(new_dimension + 1);
800 
801  // Shortest-path closure is maintained.
802  // TODO: see whether or not reduction can be (efficiently!) maintained too.
805  }
806 
807  // If we removed _all_ dimensions from a non-empty BDS,
808  // the zero-dim universe BDS has been obtained.
809  if (new_dimension == 0 && !marked_empty()) {
811  }
812  PPL_ASSERT(OK());
813 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
void set_zero_dim_univ()
Turns *this into an zero-dimensional universe BDS.
bool marked_shortest_path_reduced() const
Returns true if the system of bounded differences is known to be shortest-path reduced.
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void reset_shortest_path_reduced()
Marks *this as possibly not shortest-path reduced.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::remove_space_dimensions ( const Variables_Set vars)

Removes all the specified dimensions.

Parameters
varsThe set of Variable objects corresponding to the dimensions to be removed.
Exceptions
std::invalid_argumentThrown if *this is dimension-incompatible with one of the Variable objects contained in vars.

Definition at line 2857 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::assign_or_swap(), Parma_Polyhedra_Library::Variables_Set::space_dimension(), and Parma_Polyhedra_Library::swap().

2857  {
2858  // The removal of no dimensions from any BDS is a no-op.
2859  // Note that this case also captures the only legal removal of
2860  // space dimensions from a BDS in a 0-dim space.
2861  if (vars.empty()) {
2862  PPL_ASSERT(OK());
2863  return;
2864  }
2865 
2866  const dimension_type old_space_dim = space_dimension();
2867 
2868  // Dimension-compatibility check.
2869  const dimension_type min_space_dim = vars.space_dimension();
2870  if (old_space_dim < min_space_dim) {
2871  throw_dimension_incompatible("remove_space_dimensions(vs)", min_space_dim);
2872  }
2873  // Shortest-path closure is necessary to keep precision.
2875 
2876  // When removing _all_ dimensions from a BDS, we obtain the
2877  // zero-dimensional BDS.
2878  const dimension_type new_space_dim = old_space_dim - vars.size();
2879  if (new_space_dim == 0) {
2880  dbm.resize_no_copy(1);
2881  if (!marked_empty()) {
2882  // We set the zero_dim_univ flag.
2884  }
2885  PPL_ASSERT(OK());
2886  return;
2887  }
2888 
2889  // Handle the case of an empty BD_Shape.
2890  if (marked_empty()) {
2891  dbm.resize_no_copy(new_space_dim + 1);
2892  PPL_ASSERT(OK());
2893  return;
2894  }
2895 
2896  // Shortest-path closure is maintained.
2897  // TODO: see whether reduction can be (efficiently!) maintained too.
2900  }
2901  // For each variable to remove, we fill the corresponding column and
2902  // row by shifting respectively left and above those
2903  // columns and rows, that will not be removed.
2904  Variables_Set::const_iterator vsi = vars.begin();
2905  Variables_Set::const_iterator vsi_end = vars.end();
2906  dimension_type dst = *vsi + 1;
2907  dimension_type src = dst + 1;
2908  for (++vsi; vsi != vsi_end; ++vsi) {
2909  const dimension_type vsi_next = *vsi + 1;
2910  // All other columns and rows are moved respectively to the left
2911  // and above.
2912  while (src < vsi_next) {
2913  using std::swap;
2914  swap(dbm[dst], dbm[src]);
2915  for (dimension_type i = old_space_dim + 1; i-- > 0; ) {
2916  DB_Row<N>& dbm_i = dbm[i];
2917  assign_or_swap(dbm_i[dst], dbm_i[src]);
2918  }
2919  ++dst;
2920  ++src;
2921  }
2922  ++src;
2923  }
2924 
2925  // Moving the remaining rows and columns.
2926  while (src <= old_space_dim) {
2927  using std::swap;
2928  swap(dbm[dst], dbm[src]);
2929  for (dimension_type i = old_space_dim + 1; i-- > 0; ) {
2930  DB_Row<N>& dbm_i = dbm[i];
2931  assign_or_swap(dbm_i[dst], dbm_i[src]);
2932  }
2933  ++src;
2934  ++dst;
2935  }
2936 
2937  // Update the space dimension.
2938  dbm.resize_no_copy(new_space_dim + 1);
2939  PPL_ASSERT(OK());
2940 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
void swap(CO_Tree &x, CO_Tree &y)
size_t dimension_type
An unsigned integral type for representing space dimensions.
Enable_If< Has_Assign_Or_Swap< T >::value, void >::type assign_or_swap(T &to, T &from)
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
void set_zero_dim_univ()
Turns *this into an zero-dimensional universe BDS.
bool marked_shortest_path_reduced() const
Returns true if the system of bounded differences is known to be shortest-path reduced.
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
void swap(BD_Shape< T > &x, BD_Shape< T > &y)
Swaps x with y.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void reset_shortest_path_reduced()
Marks *this as possibly not shortest-path reduced.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced ( )
inlineprivate

Marks *this as possibly not shortest-path reduced.

Definition at line 109 of file BD_Shape_inlines.hh.

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::Status::ascii_load(), and Parma_Polyhedra_Library::BD_Shape< T >::OK().

109  {
111 }
Status status
The status flags to keep track of the internal state.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed ( )
inlineprivate
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_reduced ( )
inlineprivate

Marks *this as shortest-path closed.

Definition at line 97 of file BD_Shape_inlines.hh.

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::Status::ascii_load(), and Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign().

97  {
99 }
Status status
The status flags to keep track of the internal state.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::set_zero_dim_univ ( )
inlineprivate
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign ( ) const
private

Assigns to this->dbm its shortest-path closure.

Definition at line 1880 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::min_assign(), Parma_Polyhedra_Library::PLUS_INFINITY, PPL_DIRTY_TEMP, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::ROUND_UP, Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed(), and Parma_Polyhedra_Library::Boundary_NS::sgn().

Referenced by Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::difference_assign(), Parma_Polyhedra_Library::BD_Shape< T >::euclidean_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::BD_Shape< T >::is_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::l_infinity_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::operator==(), Parma_Polyhedra_Library::BD_Shape< T >::rectilinear_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign().

1880  {
1881  // Do something only if necessary.
1883  return;
1884  }
1885  const dimension_type num_dimensions = space_dimension();
1886  // Zero-dimensional BDSs are necessarily shortest-path closed.
1887  if (num_dimensions == 0) {
1888  return;
1889  }
1890  // Even though the BDS will not change, its internal representation
1891  // is going to be modified by the Floyd-Warshall algorithm.
1892  BD_Shape& x = const_cast<BD_Shape<T>&>(*this);
1893 
1894  // Fill the main diagonal with zeros.
1895  for (dimension_type h = num_dimensions + 1; h-- > 0; ) {
1896  PPL_ASSERT(is_plus_infinity(x.dbm[h][h]));
1897  assign_r(x.dbm[h][h], 0, ROUND_NOT_NEEDED);
1898  }
1899 
1900  PPL_DIRTY_TEMP(N, sum);
1901  for (dimension_type k = num_dimensions + 1; k-- > 0; ) {
1902  const DB_Row<N>& x_dbm_k = x.dbm[k];
1903  for (dimension_type i = num_dimensions + 1; i-- > 0; ) {
1904  DB_Row<N>& x_dbm_i = x.dbm[i];
1905  const N& x_dbm_i_k = x_dbm_i[k];
1906  if (!is_plus_infinity(x_dbm_i_k)) {
1907  for (dimension_type j = num_dimensions + 1; j-- > 0; ) {
1908  const N& x_dbm_k_j = x_dbm_k[j];
1909  if (!is_plus_infinity(x_dbm_k_j)) {
1910  // Rounding upward for correctness.
1911  add_assign_r(sum, x_dbm_i_k, x_dbm_k_j, ROUND_UP);
1912  min_assign(x_dbm_i[j], sum);
1913  }
1914  }
1915  }
1916  }
1917  }
1918 
1919  // Check for emptiness: the BDS is empty if and only if there is a
1920  // negative value on the main diagonal of `dbm'.
1921  for (dimension_type h = num_dimensions + 1; h-- > 0; ) {
1922  N& x_dbm_hh = x.dbm[h][h];
1923  if (sgn(x_dbm_hh) < 0) {
1924  x.set_empty();
1925  return;
1926  }
1927  else {
1928  PPL_ASSERT(sgn(x_dbm_hh) == 0);
1929  // Restore PLUS_INFINITY on the main diagonal.
1931  }
1932  }
1933 
1934  // The BDS is not empty and it is now shortest-path closed.
1935  x.set_shortest_path_closed();
1936 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
size_t dimension_type
An unsigned integral type for representing space dimensions.
BD_Shape(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty BDS of the specified space dimension.
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
bool marked_shortest_path_closed() const
Returns true if the system of bounded differences is known to be shortest-path closed.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
#define PPL_DIRTY_TEMP(T, id)
Plus_Infinity PLUS_INFINITY
Definition: checked.cc:31
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
int sgn(Boundary_Type type, const T &x, const Info &info)
void min_assign(N &x, const N &y)
Assigns to x the minimum between x and y.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign ( ) const
private

Assigns to this->dbm its shortest-path closure and records into this->redundancy_dbm which of the entries in this->dbm are redundant.

Definition at line 2052 of file BD_Shape_templates.hh.

References c, Parma_Polyhedra_Library::Bit_Matrix::clear(), Parma_Polyhedra_Library::Bit_Row::clear(), PPL_DIRTY_TEMP, Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm, Parma_Polyhedra_Library::ROUND_UP, Parma_Polyhedra_Library::Bit_Row::set(), Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_reduced(), and Parma_Polyhedra_Library::swap().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BFT00_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::BHZ09_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), and Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign().

2052  {
2053  // Do something only if necessary.
2055  return;
2056  }
2057  const dimension_type space_dim = space_dimension();
2058  // Zero-dimensional BDSs are necessarily reduced.
2059  if (space_dim == 0) {
2060  return;
2061  }
2062  // First find the tightest constraints for this BDS.
2064 
2065  // If `*this' is empty, then there is nothing to reduce.
2066  if (marked_empty()) {
2067  return;
2068  }
2069  // Step 1: compute zero-equivalence classes.
2070  // Variables corresponding to indices `i' and `j' are zero-equivalent
2071  // if they lie on a zero-weight loop; since the matrix is shortest-path
2072  // closed, this happens if and only if dbm[i][j] == -dbm[j][i].
2073  std::vector<dimension_type> predecessor;
2074  compute_predecessors(predecessor);
2075  std::vector<dimension_type> leaders;
2076  compute_leader_indices(predecessor, leaders);
2077  const dimension_type num_leaders = leaders.size();
2078 
2079  Bit_Matrix redundancy(space_dim + 1, space_dim + 1);
2080  // Init all constraints to be redundant.
2081  // TODO: provide an appropriate method to set multiple bits.
2082  Bit_Row& red_0 = redundancy[0];
2083  for (dimension_type j = space_dim + 1; j-- > 0; ) {
2084  red_0.set(j);
2085  }
2086  for (dimension_type i = space_dim + 1; i-- > 0; ) {
2087  redundancy[i] = red_0;
2088  }
2089  // Step 2: flag non-redundant constraints in the (zero-cycle-free)
2090  // subsystem of bounded differences having only leaders as variables.
2091  PPL_DIRTY_TEMP(N, c);
2092  for (dimension_type l_i = 0; l_i < num_leaders; ++l_i) {
2093  const dimension_type i = leaders[l_i];
2094  const DB_Row<N>& dbm_i = dbm[i];
2095  Bit_Row& redundancy_i = redundancy[i];
2096  for (dimension_type l_j = 0; l_j < num_leaders; ++l_j) {
2097  const dimension_type j = leaders[l_j];
2098  if (redundancy_i[j]) {
2099  const N& dbm_i_j = dbm_i[j];
2100  redundancy_i.clear(j);
2101  for (dimension_type l_k = 0; l_k < num_leaders; ++l_k) {
2102  const dimension_type k = leaders[l_k];
2103  add_assign_r(c, dbm_i[k], dbm[k][j], ROUND_UP);
2104  if (dbm_i_j >= c) {
2105  redundancy_i.set(j);
2106  break;
2107  }
2108  }
2109  }
2110  }
2111  }
2112 
2113  // Step 3: flag non-redundant constraints in zero-equivalence classes.
2114  // Each equivalence class must have a single 0-cycle connecting
2115  // all the equivalent variables in increasing order.
2116  std::deque<bool> dealt_with(space_dim + 1, false);
2117  for (dimension_type i = space_dim + 1; i-- > 0; ) {
2118  // We only need to deal with non-singleton zero-equivalence classes
2119  // that haven't already been dealt with.
2120  if (i != predecessor[i] && !dealt_with[i]) {
2121  dimension_type j = i;
2122  while (true) {
2123  const dimension_type predecessor_j = predecessor[j];
2124  if (j == predecessor_j) {
2125  // We finally found the leader of `i'.
2126  PPL_ASSERT(redundancy[i][j]);
2127  redundancy[i].clear(j);
2128  // Here we dealt with `j' (i.e., `predecessor_j'), but it is useless
2129  // to update `dealt_with' because `j' is a leader.
2130  break;
2131  }
2132  // We haven't found the leader of `i' yet.
2133  PPL_ASSERT(redundancy[predecessor_j][j]);
2134  redundancy[predecessor_j].clear(j);
2135  dealt_with[predecessor_j] = true;
2136  j = predecessor_j;
2137  }
2138  }
2139  }
2140  // Even though shortest-path reduction is not going to change the BDS,
2141  // it might change its internal representation.
2142  BD_Shape<T>& x = const_cast<BD_Shape<T>&>(*this);
2143  using std::swap;
2144  swap(x.redundancy_dbm, redundancy);
2145  x.set_shortest_path_reduced();
2146 
2147  PPL_ASSERT(is_shortest_path_reduced());
2148 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
void swap(CO_Tree &x, CO_Tree &y)
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool is_shortest_path_reduced() const
Returns true if and only if this->dbm is shortest-path closed and this->redundancy_dbm correctly flag...
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
bool marked_shortest_path_reduced() const
Returns true if the system of bounded differences is known to be shortest-path reduced.
void compute_predecessors(std::vector< dimension_type > &predecessor) const
Compute the (zero-equivalence classes) predecessor relation.
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
void swap(BD_Shape< T > &x, BD_Shape< T > &y)
Swaps x with y.
#define PPL_DIRTY_TEMP(T, id)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void compute_leader_indices(const std::vector< dimension_type > &predecessor, std::vector< dimension_type > &indices)
Definition: BD_Shape.cc:85
Coefficient c
Definition: PIP_Tree.cc:64
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign ( const BD_Shape< T > &  y)

Assigns to *this a meet-preserving simplification of *this with respect to y. If false is returned, then the intersection is empty.

Exceptions
std::invalid_argumentThrown if *this and y are topology-incompatible or dimension-incompatible.

Definition at line 2544 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::BD_Shape< T >::compute_leaders(), Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::incremental_shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::m_swap(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), PPL_DIRTY_TEMP, Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm, Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::ROUND_DOWN, Parma_Polyhedra_Library::ROUND_UP, Parma_Polyhedra_Library::BD_Shape< T >::set_zero_dim_univ(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::UNIVERSE.

2544  {
2545  BD_Shape& x = *this;
2546  const dimension_type dim = x.space_dimension();
2547  // Dimension-compatibility check.
2548  if (dim != y.space_dimension()) {
2549  throw_dimension_incompatible("simplify_using_context_assign(y)", y);
2550  }
2551  // Filter away the zero-dimensional case.
2552  if (dim == 0) {
2553  if (y.marked_empty()) {
2554  x.set_zero_dim_univ();
2555  return false;
2556  }
2557  else {
2558  return !x.marked_empty();
2559  }
2560  }
2561 
2562  // Filter away the case where `x' contains `y'
2563  // (this subsumes the case when `y' is empty).
2564  y.shortest_path_closure_assign();
2565  if (x.contains(y)) {
2566  BD_Shape<T> res(dim, UNIVERSE);
2567  x.m_swap(res);
2568  return false;
2569  }
2570 
2571  // Filter away the case where `x' is empty.
2572  x.shortest_path_closure_assign();
2573  if (x.marked_empty()) {
2574  // Search for a constraint of `y' that is not a tautology.
2575  dimension_type i;
2576  dimension_type j;
2577  // Prefer unary constraints.
2578  i = 0;
2579  const DB_Row<N>& y_dbm_0 = y.dbm[0];
2580  for (j = 1; j <= dim; ++j) {
2581  if (!is_plus_infinity(y_dbm_0[j])) {
2582  // FIXME: if N is a float or bounded integer type, then
2583  // we also need to check that we are actually able to construct
2584  // a constraint inconsistent with respect to this one.
2585  goto found;
2586  }
2587  }
2588  j = 0;
2589  for (i = 1; i <= dim; ++i) {
2590  if (!is_plus_infinity(y.dbm[i][0])) {
2591  // FIXME: if N is a float or bounded integer type, then
2592  // we also need to check that we are actually able to construct
2593  // a constraint inconsistent with respect to this one.
2594  goto found;
2595  }
2596  }
2597  // Then search binary constraints.
2598  for (i = 1; i <= dim; ++i) {
2599  const DB_Row<N>& y_dbm_i = y.dbm[i];
2600  for (j = 1; j <= dim; ++j) {
2601  if (!is_plus_infinity(y_dbm_i[j])) {
2602  // FIXME: if N is a float or bounded integer type, then
2603  // we also need to check that we are actually able to construct
2604  // a constraint inconsistent with respect to this one.
2605  goto found;
2606  }
2607  }
2608  }
2609  // Not found: we were not able to build a constraint contradicting
2610  // one of the constraints in `y': `x' cannot be enlarged.
2611  return false;
2612 
2613  found:
2614  // Found: build a new BDS contradicting the constraint found.
2615  PPL_ASSERT(i <= dim && j <= dim && (i > 0 || j > 0));
2616  BD_Shape<T> res(dim, UNIVERSE);
2617  PPL_DIRTY_TEMP(N, tmp);
2618  assign_r(tmp, 1, ROUND_UP);
2619  add_assign_r(tmp, tmp, y.dbm[i][j], ROUND_UP);
2620  PPL_ASSERT(!is_plus_infinity(tmp));
2621  // CHECKME: round down is really meant.
2622  neg_assign_r(res.dbm[j][i], tmp, ROUND_DOWN);
2623  x.m_swap(res);
2624  return false;
2625  }
2626 
2627  // Here `x' and `y' are not empty and shortest-path closed;
2628  // also, `x' does not contain `y'.
2629  // Let `target' be the intersection of `x' and `y'.
2630  BD_Shape<T> target = x;
2631  target.intersection_assign(y);
2632  const bool bool_result = !target.is_empty();
2633 
2634  // Compute a reduced dbm for `x' and ...
2635  x.shortest_path_reduction_assign();
2636  // ... count the non-redundant constraints.
2637  dimension_type x_num_non_redundant = (dim+1)*(dim+1);
2638  for (dimension_type i = dim + 1; i-- > 0; ) {
2639  x_num_non_redundant -= x.redundancy_dbm[i].count_ones();
2640  }
2641  PPL_ASSERT(x_num_non_redundant > 0);
2642 
2643  // Let `yy' be a copy of `y': we will keep adding to `yy'
2644  // the non-redundant constraints of `x',
2645  // stopping as soon as `yy' becomes equal to `target'.
2646  BD_Shape<T> yy = y;
2647 
2648  // The constraints added to `yy' will be recorded in `res' ...
2649  BD_Shape<T> res(dim, UNIVERSE);
2650  // ... and we will count them too.
2651  dimension_type res_num_non_redundant = 0;
2652 
2653  // Compute leader information for `x'.
2654  std::vector<dimension_type> x_leaders;
2655  x.compute_leaders(x_leaders);
2656 
2657  // First go through the unary equality constraints.
2658  const DB_Row<N>& x_dbm_0 = x.dbm[0];
2659  DB_Row<N>& yy_dbm_0 = yy.dbm[0];
2660  DB_Row<N>& res_dbm_0 = res.dbm[0];
2661  for (dimension_type j = 1; j <= dim; ++j) {
2662  // Unary equality constraints are encoded in entries dbm_0j and dbm_j0
2663  // provided index j has special variable index 0 as its leader.
2664  if (x_leaders[j] != 0) {
2665  continue;
2666  }
2667  PPL_ASSERT(!is_plus_infinity(x_dbm_0[j]));
2668  if (x_dbm_0[j] < yy_dbm_0[j]) {
2669  res_dbm_0[j] = x_dbm_0[j];
2670  ++res_num_non_redundant;
2671  // Tighten context `yy' using the newly added constraint.
2672  yy_dbm_0[j] = x_dbm_0[j];
2673  yy.reset_shortest_path_closed();
2674  }
2675  PPL_ASSERT(!is_plus_infinity(x.dbm[j][0]));
2676  if (x.dbm[j][0] < yy.dbm[j][0]) {
2677  res.dbm[j][0] = x.dbm[j][0];
2678  ++res_num_non_redundant;
2679  // Tighten context `yy' using the newly added constraint.
2680  yy.dbm[j][0] = x.dbm[j][0];
2681  yy.reset_shortest_path_closed();
2682  }
2683  // Restore shortest-path closure, if it was lost.
2684  if (!yy.marked_shortest_path_closed()) {
2685  Variable var_j(j-1);
2686  yy.incremental_shortest_path_closure_assign(var_j);
2687  if (target.contains(yy)) {
2688  // Target reached: swap `x' and `res' if needed.
2689  if (res_num_non_redundant < x_num_non_redundant) {
2690  res.reset_shortest_path_closed();
2691  x.m_swap(res);
2692  }
2693  return bool_result;
2694  }
2695  }
2696  }
2697 
2698  // Go through the binary equality constraints.
2699  // Note: no need to consider the case i == 1.
2700  for (dimension_type i = 2; i <= dim; ++i) {
2701  const dimension_type j = x_leaders[i];
2702  if (j == i || j == 0) {
2703  continue;
2704  }
2705  PPL_ASSERT(!is_plus_infinity(x.dbm[i][j]));
2706  if (x.dbm[i][j] < yy.dbm[i][j]) {
2707  res.dbm[i][j] = x.dbm[i][j];
2708  ++res_num_non_redundant;
2709  // Tighten context `yy' using the newly added constraint.
2710  yy.dbm[i][j] = x.dbm[i][j];
2711  yy.reset_shortest_path_closed();
2712  }
2713  PPL_ASSERT(!is_plus_infinity(x.dbm[j][i]));
2714  if (x.dbm[j][i] < yy.dbm[j][i]) {
2715  res.dbm[j][i] = x.dbm[j][i];
2716  ++res_num_non_redundant;
2717  // Tighten context `yy' using the newly added constraint.
2718  yy.dbm[j][i] = x.dbm[j][i];
2719  yy.reset_shortest_path_closed();
2720  }
2721  // Restore shortest-path closure, if it was lost.
2722  if (!yy.marked_shortest_path_closed()) {
2723  Variable var_j(j-1);
2724  yy.incremental_shortest_path_closure_assign(var_j);
2725  if (target.contains(yy)) {
2726  // Target reached: swap `x' and `res' if needed.
2727  if (res_num_non_redundant < x_num_non_redundant) {
2728  res.reset_shortest_path_closed();
2729  x.m_swap(res);
2730  }
2731  return bool_result;
2732  }
2733  }
2734  }
2735 
2736  // Finally go through the (proper) inequality constraints:
2737  // both indices i and j should be leaders.
2738  for (dimension_type i = 0; i <= dim; ++i) {
2739  if (i != x_leaders[i]) {
2740  continue;
2741  }
2742  const DB_Row<N>& x_dbm_i = x.dbm[i];
2743  const Bit_Row& x_redundancy_dbm_i = x.redundancy_dbm[i];
2744  DB_Row<N>& yy_dbm_i = yy.dbm[i];
2745  DB_Row<N>& res_dbm_i = res.dbm[i];
2746  for (dimension_type j = 0; j <= dim; ++j) {
2747  if (j != x_leaders[j] || x_redundancy_dbm_i[j]) {
2748  continue;
2749  }
2750  N& yy_dbm_ij = yy_dbm_i[j];
2751  const N& x_dbm_ij = x_dbm_i[j];
2752  if (x_dbm_ij < yy_dbm_ij) {
2753  res_dbm_i[j] = x_dbm_ij;
2754  ++res_num_non_redundant;
2755  // Tighten context `yy' using the newly added constraint.
2756  yy_dbm_ij = x_dbm_ij;
2757  yy.reset_shortest_path_closed();
2758  PPL_ASSERT(i > 0 || j > 0);
2759  Variable var(((i > 0) ? i : j) - 1);
2760  yy.incremental_shortest_path_closure_assign(var);
2761  if (target.contains(yy)) {
2762  // Target reached: swap `x' and `res' if needed.
2763  if (res_num_non_redundant < x_num_non_redundant) {
2764  res.reset_shortest_path_closed();
2765  x.m_swap(res);
2766  }
2767  return bool_result;
2768  }
2769  }
2770  }
2771  }
2772  // This point should be unreachable.
2773  PPL_UNREACHABLE;
2774  return false;
2775 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
size_t dimension_type
An unsigned integral type for representing space dimensions.
BD_Shape(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty BDS of the specified space dimension.
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
#define PPL_DIRTY_TEMP(T, id)
The universe element, i.e., the whole vector space.
template<typename T >
dimension_type Parma_Polyhedra_Library::BD_Shape< T >::space_dimension ( ) const
inline

Returns the dimension of the vector space enclosing *this.

Definition at line 371 of file BD_Shape_inlines.hh.

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::BD_Shape< T >::BFT00_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::BHZ09_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::BD_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::difference_assign(), Parma_Polyhedra_Library::BD_Shape< T >::euclidean_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::integer_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::BD_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::BD_Shape< T >::l_infinity_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::limited_BHMZ05_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::BD_Shape< T >::operator==(), Parma_Polyhedra_Library::BD_Shape< T >::rectilinear_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), Parma_Polyhedra_Library::BD_Shape< T >::time_elapse_assign(), Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign_if_exact().

371  {
372  return dbm.num_rows() - 1;
373 }
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::strictly_contains ( const BD_Shape< T > &  y) const
inline

Returns true if and only if *this strictly contains y.

Exceptions
std::invalid_argumentThrown if *this and y are dimension-incompatible.

Definition at line 745 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::contains().

745  {
746  const BD_Shape<T>& x = *this;
747  return x.contains(y) && !y.contains(x);
748 }
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible ( const char *  method,
const BD_Shape< T > &  y 
) const
private

Definition at line 6975 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

6976  {
6977  std::ostringstream s;
6978  s << "PPL::BD_Shape::" << method << ":" << std::endl
6979  << "this->space_dimension() == " << space_dimension()
6980  << ", y->space_dimension() == " << y.space_dimension() << ".";
6981  throw std::invalid_argument(s.str());
6982 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible ( const char *  method,
dimension_type  required_dim 
) const
private

Definition at line 6986 of file BD_Shape_templates.hh.

6987  {
6988  std::ostringstream s;
6989  s << "PPL::BD_Shape::" << method << ":" << std::endl
6990  << "this->space_dimension() == " << space_dimension()
6991  << ", required dimension == " << required_dim << ".";
6992  throw std::invalid_argument(s.str());
6993 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible ( const char *  method,
const Constraint c 
) const
private

Definition at line 6997 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::Constraint::space_dimension().

6998  {
6999  std::ostringstream s;
7000  s << "PPL::BD_Shape::" << method << ":" << std::endl
7001  << "this->space_dimension() == " << space_dimension()
7002  << ", c->space_dimension == " << c.space_dimension() << ".";
7003  throw std::invalid_argument(s.str());
7004 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Coefficient c
Definition: PIP_Tree.cc:64
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible ( const char *  method,
const Congruence cg 
) const
private

Definition at line 7008 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::Congruence::space_dimension().

7009  {
7010  std::ostringstream s;
7011  s << "PPL::BD_Shape::" << method << ":" << std::endl
7012  << "this->space_dimension() == " << space_dimension()
7013  << ", cg->space_dimension == " << cg.space_dimension() << ".";
7014  throw std::invalid_argument(s.str());
7015 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible ( const char *  method,
const Generator g 
) const
private

Definition at line 7019 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::Generator::space_dimension().

7020  {
7021  std::ostringstream s;
7022  s << "PPL::BD_Shape::" << method << ":" << std::endl
7023  << "this->space_dimension() == " << space_dimension()
7024  << ", g->space_dimension == " << g.space_dimension() << ".";
7025  throw std::invalid_argument(s.str());
7026 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible ( const char *  method,
const char *  le_name,
const Linear_Expression le 
) const
private

Definition at line 7042 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::Linear_Expression::space_dimension().

7044  {
7045  std::ostringstream s;
7046  s << "PPL::BD_Shape::" << method << ":" << std::endl
7047  << "this->space_dimension() == " << space_dimension()
7048  << ", " << le_name << "->space_dimension() == "
7049  << le.space_dimension() << ".";
7050  throw std::invalid_argument(s.str());
7051 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
bool le(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
template<typename T >
template<typename Interval_Info >
void Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible ( const char *  method,
const char *  lf_name,
const Linear_Form< Interval< T, Interval_Info > > &  lf 
) const
private

Definition at line 7056 of file BD_Shape_templates.hh.

7059  {
7060  std::ostringstream s;
7061  s << "PPL::BD_Shape::" << method << ":" << std::endl
7062  << "this->space_dimension() == " << space_dimension()
7063  << ", " << lf_name << "->space_dimension() == "
7064  << lf.space_dimension() << ".";
7065  throw std::invalid_argument(s.str());
7066 }
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::throw_expression_too_complex ( const char *  method,
const Linear_Expression le 
)
staticprivate

Definition at line 7030 of file BD_Shape_templates.hh.

7031  {
7032  using namespace IO_Operators;
7033  std::ostringstream s;
7034  s << "PPL::BD_Shape::" << method << ":" << std::endl
7035  << le << " is too complex.";
7036  throw std::invalid_argument(s.str());
7037 }
bool le(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::throw_invalid_argument ( const char *  method,
const char *  reason 
)
staticprivate

Definition at line 7070 of file BD_Shape_templates.hh.

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape().

7070  {
7071  std::ostringstream s;
7072  s << "PPL::BD_Shape::" << method << ":" << std::endl
7073  << reason << ".";
7074  throw std::invalid_argument(s.str());
7075 }
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::time_elapse_assign ( const BD_Shape< T > &  y)
inline

Assigns to *this the result of computing the time-elapse between *this and y.

Exceptions
std::invalid_argumentThrown if *this and y are dimension-incompatible.

Definition at line 728 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::constraints(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::Polyhedron::time_elapse_assign().

728  {
729  // Dimension-compatibility check.
730  if (space_dimension() != y.space_dimension()) {
731  throw_dimension_incompatible("time_elapse_assign(y)", y);
732  }
733  // Compute time-elapse on polyhedra.
734  // TODO: provide a direct implementation.
735  C_Polyhedron ph_x(constraints());
736  C_Polyhedron ph_y(y.constraints());
737  ph_x.time_elapse_assign(ph_y);
738  BD_Shape<T> x(ph_x);
739  m_swap(x);
740  PPL_ASSERT(OK());
741 }
void m_swap(BD_Shape &y)
Swaps *this with y (*this and y can be dimension-incompatible).
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
Constraint_System constraints() const
Returns a system of constraints defining *this.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::topological_closure_assign ( )
inline

Assigns to *this its topological closure.

Definition at line 440 of file BD_Shape_inlines.hh.

440  {
441 }
template<typename T >
memory_size_type Parma_Polyhedra_Library::BD_Shape< T >::total_memory_in_bytes ( ) const
inline

Returns the total size in bytes of the memory occupied by *this.

Definition at line 883 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::external_memory_in_bytes().

883  {
884  return sizeof(*this) + external_memory_in_bytes();
885 }
memory_size_type external_memory_in_bytes() const
Returns the size in bytes of the memory managed by *this.
template<typename T >
template<typename Interval_Info >
void Parma_Polyhedra_Library::BD_Shape< T >::two_variables_affine_form_image ( const dimension_type var_id,
const Linear_Form< Interval< T, Interval_Info > > &  lf,
const dimension_type space_dim 
)
private

Auxiliary function for affine form image that handle the general case: $l = ax + by + c$.

Definition at line 4563 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Form< C >::negate(), PPL_DIRTY_TEMP, and Parma_Polyhedra_Library::ROUND_NOT_NEEDED.

4565  {
4566  // Shortest-path closure is maintained, but not reduction.
4569  }
4571 
4572  Linear_Form< Interval<T, Interval_Info> > minus_lf(lf);
4573  minus_lf.negate();
4574 
4575  // Declare temporaries outside the loop.
4576  PPL_DIRTY_TEMP(N, upper_bound);
4577 
4578  // Update binary constraints on var FIRST.
4579  for (dimension_type curr_var = 1; curr_var < var_id; ++curr_var) {
4580  Variable current(curr_var - 1);
4581  linear_form_upper_bound(lf - current, upper_bound);
4582  assign_r(dbm[curr_var][var_id], upper_bound, ROUND_NOT_NEEDED);
4583  linear_form_upper_bound(minus_lf + current, upper_bound);
4584  assign_r(dbm[var_id][curr_var], upper_bound, ROUND_NOT_NEEDED);
4585  }
4586  for (dimension_type curr_var = var_id + 1; curr_var <= space_dim;
4587  ++curr_var) {
4588  Variable current(curr_var - 1);
4589  linear_form_upper_bound(lf - current, upper_bound);
4590  assign_r(dbm[curr_var][var_id], upper_bound, ROUND_NOT_NEEDED);
4591  linear_form_upper_bound(minus_lf + current, upper_bound);
4592  assign_r(dbm[var_id][curr_var], upper_bound, ROUND_NOT_NEEDED);
4593  }
4594  // Finally, update unary constraints on var.
4595  PPL_DIRTY_TEMP(N, lf_ub);
4596  linear_form_upper_bound(lf, lf_ub);
4597  PPL_DIRTY_TEMP(N, minus_lf_ub);
4598  linear_form_upper_bound(minus_lf, minus_lf_ub);
4599  assign_r(dbm[0][var_id], lf_ub, ROUND_NOT_NEEDED);
4600  assign_r(dbm[var_id][0], minus_lf_ub, ROUND_NOT_NEEDED);
4601 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
size_t dimension_type
An unsigned integral type for representing space dimensions.
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
bool marked_shortest_path_reduced() const
Returns true if the system of bounded differences is known to be shortest-path reduced.
void linear_form_upper_bound(const Linear_Form< Interval< T, Interval_Info > > &lf, N &result) const
void reset_shortest_path_closed()
Marks *this as possibly not shortest-path closed.
#define PPL_DIRTY_TEMP(T, id)
void reset_shortest_path_reduced()
Marks *this as possibly not shortest-path reduced.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::unconstrain ( Variable  var)

Computes the cylindrification of *this with respect to space dimension var, assigning the result to *this.

Parameters
varThe space dimension that will be unconstrained.
Exceptions
std::invalid_argumentThrown if var is not a space dimension of *this.

Definition at line 3566 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::Variable::space_dimension().

3566  {
3567  // Dimension-compatibility check.
3568  const dimension_type var_space_dim = var.space_dimension();
3569  if (space_dimension() < var_space_dim) {
3570  throw_dimension_incompatible("unconstrain(var)", var_space_dim);
3571  }
3572  // Shortest-path closure is necessary to detect emptiness
3573  // and all (possibly implicit) constraints.
3575 
3576  // If the shape is empty, this is a no-op.
3577  if (marked_empty()) {
3578  return;
3579  }
3580  forget_all_dbm_constraints(var_space_dim);
3581  // Shortest-path closure is preserved, but not reduction.
3583  PPL_ASSERT(OK());
3584 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void forget_all_dbm_constraints(dimension_type v)
Removes all the constraints on row/column v.
void reset_shortest_path_reduced()
Marks *this as possibly not shortest-path reduced.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::unconstrain ( const Variables_Set vars)

Computes the cylindrification of *this with respect to the set of space dimensions vars, assigning the result to *this.

Parameters
varsThe set of space dimension that will be unconstrained.
Exceptions
std::invalid_argumentThrown if *this is dimension-incompatible with one of the Variable objects contained in vars.

Definition at line 3588 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::Variables_Set::space_dimension().

3588  {
3589  // The cylindrification with respect to no dimensions is a no-op.
3590  // This case captures the only legal cylindrification in a 0-dim space.
3591  if (vars.empty()) {
3592  return;
3593  }
3594  // Dimension-compatibility check.
3595  const dimension_type min_space_dim = vars.space_dimension();
3596  if (space_dimension() < min_space_dim) {
3597  throw_dimension_incompatible("unconstrain(vs)", min_space_dim);
3598  }
3599  // Shortest-path closure is necessary to detect emptiness
3600  // and all (possibly implicit) constraints.
3602 
3603  // If the shape is empty, this is a no-op.
3604  if (marked_empty()) {
3605  return;
3606  }
3607  for (Variables_Set::const_iterator vsi = vars.begin(),
3608  vsi_end = vars.end(); vsi != vsi_end; ++vsi) {
3609  forget_all_dbm_constraints(*vsi + 1);
3610  }
3611  // Shortest-path closure is preserved, but not reduction.
3613  PPL_ASSERT(OK());
3614 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void forget_all_dbm_constraints(dimension_type v)
Removes all the constraints on row/column v.
void reset_shortest_path_reduced()
Marks *this as possibly not shortest-path reduced.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign ( const BD_Shape< T > &  y)

Assigns to *this the smallest BDS containing the union of *this and y.

Exceptions
std::invalid_argumentThrown if *this and y are dimension-incompatible.

Definition at line 2152 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::difference_assign().

2152  {
2153  const dimension_type space_dim = space_dimension();
2154 
2155  // Dimension-compatibility check.
2156  if (space_dim != y.space_dimension()) {
2157  throw_dimension_incompatible("upper_bound_assign(y)", y);
2158  }
2159  // The upper bound of a BD shape `bd' with an empty shape is `bd'.
2160  y.shortest_path_closure_assign();
2161  if (y.marked_empty()) {
2162  return;
2163  }
2165  if (marked_empty()) {
2166  *this = y;
2167  return;
2168  }
2169 
2170  // The bds-hull consists in constructing `*this' with the maximum
2171  // elements selected from `*this' and `y'.
2172  PPL_ASSERT(space_dim == 0 || marked_shortest_path_closed());
2173  for (dimension_type i = space_dim + 1; i-- > 0; ) {
2174  DB_Row<N>& dbm_i = dbm[i];
2175  const DB_Row<N>& y_dbm_i = y.dbm[i];
2176  for (dimension_type j = space_dim + 1; j-- > 0; ) {
2177  N& dbm_ij = dbm_i[j];
2178  const N& y_dbm_ij = y_dbm_i[j];
2179  if (dbm_ij < y_dbm_ij) {
2180  dbm_ij = y_dbm_ij;
2181  }
2182  }
2183  }
2184  // Shortest-path closure is maintained (if it was holding).
2185  // TODO: see whether reduction can be (efficiently!) maintained too.
2188  }
2189  PPL_ASSERT(OK());
2190 }
bool marked_empty() const
Returns true if the BDS is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
bool marked_shortest_path_closed() const
Returns true if the system of bounded differences is known to be shortest-path closed.
bool marked_shortest_path_reduced() const
Returns true if the system of bounded differences is known to be shortest-path reduced.
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void reset_shortest_path_reduced()
Marks *this as possibly not shortest-path reduced.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign_if_exact ( const BD_Shape< T > &  y)
inline

If the upper bound of *this and y is exact, it is assigned to *this and true is returned, otherwise false is returned.

Exceptions
std::invalid_argumentThrown if *this and y are dimension-incompatible.

Definition at line 752 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

752  {
753  if (space_dimension() != y.space_dimension()) {
754  throw_dimension_incompatible("upper_bound_assign_if_exact(y)", y);
755  }
756 #if 0
758 #else
759  const bool integer_upper_bound = false;
760  return BHZ09_upper_bound_assign_if_exact<integer_upper_bound>(y);
761 #endif
762 }
void throw_dimension_incompatible(const char *method, const BD_Shape &y) const
bool BFT00_upper_bound_assign_if_exact(const BD_Shape &y)
If the upper bound of *this and y is exact it is assigned to *this and true is returned, otherwise false is returned.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::widening_assign ( const BD_Shape< T > &  y,
unsigned *  tp = 0 
)
inline

Same as H79_widening_assign(y, tp).

Definition at line 862 of file BD_Shape_inlines.hh.

862  {
863  H79_widening_assign(y, tp);
864 }
void H79_widening_assign(const BD_Shape &y, unsigned *tp=0)
Assigns to *this the result of computing the H79-widening between *this and y.
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::wrap_assign ( const Variables_Set vars,
Bounded_Integer_Type_Width  w,
Bounded_Integer_Type_Representation  r,
Bounded_Integer_Type_Overflow  o,
const Constraint_System cs_p = 0,
unsigned  complexity_threshold = 16,
bool  wrap_individually = true 
)

Wraps the specified dimensions of the vector space.

Parameters
varsThe set of Variable objects corresponding to the space dimensions to be wrapped.
wThe width of the bounded integer type corresponding to all the dimensions to be wrapped.
rThe representation of the bounded integer type corresponding to all the dimensions to be wrapped.
oThe overflow behavior of the bounded integer type corresponding to all the dimensions to be wrapped.
cs_pPossibly null pointer to a constraint system whose variables are contained in vars. If *cs_p depends on variables not in vars, the behavior is undefined. When non-null, the pointed-to constraint system is assumed to represent the conditional or looping construct guard with respect to which wrapping is performed. Since wrapping requires the computation of upper bounds and due to non-distributivity of constraint refinement over upper bounds, passing a constraint system in this way can be more precise than refining the result of the wrapping operation with the constraints in *cs_p.
complexity_thresholdA precision parameter of the wrapping operator: higher values result in possibly improved precision.
wrap_individuallytrue if the dimensions should be wrapped individually (something that results in much greater efficiency to the detriment of precision).
Exceptions
std::invalid_argumentThrown if *cs_p is dimension-incompatible with vars, or if *this is dimension-incompatible vars or with *cs_p.

Definition at line 817 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::Implementation::wrap_assign().

823  {
825  vars, w, r, o, cs_p,
826  complexity_threshold, wrap_individually,
827  "BD_Shape");
828 }
void wrap_assign(PSET &pointset, const Variables_Set &vars, const Bounded_Integer_Type_Width w, const Bounded_Integer_Type_Representation r, const Bounded_Integer_Type_Overflow o, const Constraint_System *cs_p, const unsigned complexity_threshold, const bool wrap_individually, const char *class_name)
Definition: wrap_assign.hh:152

Friends And Related Function Documentation

template<typename T>
void compute_leader_indices ( const std::vector< dimension_type > &  predecessor,
std::vector< dimension_type > &  indices 
)
related

Definition at line 85 of file BD_Shape.cc.

86  {
87  // The vector `indices' contains one entry for each equivalence
88  // class, storing the index of the corresponding leader in
89  // increasing order: it is used to avoid repeated tests for leadership.
90  PPL_ASSERT(indices.size() == 0);
91  PPL_ASSERT(0 == predecessor[0]);
92  indices.push_back(0);
93  for (dimension_type i = 1, p_size = predecessor.size(); i != p_size; ++i) {
94  if (i == predecessor[i]) {
95  indices.push_back(i);
96  }
97  }
98 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
template<typename T>
void compute_leader_indices ( const std::vector< dimension_type > &  predecessor,
std::vector< dimension_type > &  indices 
)
related

Extracts leader indices from the predecessor relation.

template<typename To , typename T >
bool euclidean_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const BD_Shape< T > &  x,
const BD_Shape< T > &  y,
Rounding_Dir  dir 
)
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>.

template<typename Temp , typename To , typename T >
bool euclidean_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const BD_Shape< T > &  x,
const BD_Shape< T > &  y,
Rounding_Dir  dir 
)
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<Temp, Extended_Number_Policy>.

template<typename Temp , typename To , typename T >
bool euclidean_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const BD_Shape< T > &  x,
const BD_Shape< T > &  y,
Rounding_Dir  dir,
Temp &  tmp0,
Temp &  tmp1,
Temp &  tmp2 
)
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.

template<typename Temp , typename To , typename T >
bool euclidean_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const BD_Shape< T > &  x,
const BD_Shape< T > &  y,
const Rounding_Dir  dir,
Temp &  tmp0,
Temp &  tmp1,
Temp &  tmp2 
)
related

Definition at line 560 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

566  {
567  const dimension_type x_space_dim = x.space_dimension();
568  // Dimension-compatibility check.
569  if (x_space_dim != y.space_dimension()) {
570  return false;
571  }
572 
573  // Zero-dim BDSs are equal if and only if they are both empty or universe.
574  if (x_space_dim == 0) {
575  if (x.marked_empty() == y.marked_empty()) {
576  assign_r(r, 0, ROUND_NOT_NEEDED);
577  }
578  else {
580  }
581  return true;
582  }
583 
584  // The distance computation requires shortest-path closure.
585  x.shortest_path_closure_assign();
586  y.shortest_path_closure_assign();
587 
588  // If one of two BDSs is empty, then they are equal if and only if
589  // the other BDS is empty too.
590  if (x.marked_empty() || y.marked_empty()) {
591  if (x.marked_empty() == y.marked_empty()) {
592  assign_r(r, 0, ROUND_NOT_NEEDED);
593  }
594  else {
596  }
597  return true;
598  }
599 
600  return euclidean_distance_assign(r, x.dbm, y.dbm, dir, tmp0, tmp1, tmp2);
601 }
bool euclidean_distance_assign(Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, Rounding_Dir dir)
Computes the euclidean distance between x and y.
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
size_t dimension_type
An unsigned integral type for representing space dimensions.
Plus_Infinity PLUS_INFINITY
Definition: checked.cc:31
template<typename Temp , typename To , typename T >
bool euclidean_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const BD_Shape< T > &  x,
const BD_Shape< T > &  y,
const Rounding_Dir  dir 
)
related

Definition at line 606 of file BD_Shape_inlines.hh.

References PPL_DIRTY_TEMP.

609  {
610  typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
611  PPL_DIRTY_TEMP(Checked_Temp, tmp0);
612  PPL_DIRTY_TEMP(Checked_Temp, tmp1);
613  PPL_DIRTY_TEMP(Checked_Temp, tmp2);
614  return euclidean_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
615 }
bool euclidean_distance_assign(Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, Rounding_Dir dir)
Computes the euclidean distance between x and y.
#define PPL_DIRTY_TEMP(T, id)
template<typename To , typename T >
bool euclidean_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const BD_Shape< T > &  x,
const BD_Shape< T > &  y,
const Rounding_Dir  dir 
)
related

Definition at line 620 of file BD_Shape_inlines.hh.

623  {
624  return euclidean_distance_assign<To, To, T>(r, x, y, dir);
625 }
template<typename T>
bool extract_bounded_difference ( const Constraint c,
dimension_type c_num_vars,
dimension_type c_first_var,
dimension_type c_second_var,
Coefficient c_coeff 
)
related

Definition at line 33 of file BD_Shape.cc.

References Parma_Polyhedra_Library::Expression_Hide_Last< T >::all_zeroes(), Parma_Polyhedra_Library::Constraint::expression(), Parma_Polyhedra_Library::Expression_Hide_Last< T >::first_nonzero(), Parma_Polyhedra_Library::Expression_Hide_Last< T >::get(), Parma_Polyhedra_Library::Boundary_NS::sgn(), and Parma_Polyhedra_Library::Constraint::space_dimension().

37  {
38  // Check for preconditions.
39  const dimension_type space_dim = c.space_dimension();
40  PPL_ASSERT(c_num_vars == 0 && c_first_var == 0 && c_second_var == 0);
41 
42  c_first_var = c.expression().first_nonzero(1, space_dim + 1);
43  if (c_first_var == space_dim + 1) {
44  // All the inhomogeneous coefficients are zero.
45  return true;
46  }
47 
48  ++c_num_vars;
49 
50  c_second_var = c.expression().first_nonzero(c_first_var + 1, space_dim + 1);
51  if (c_second_var == space_dim + 1) {
52  // c_first_var is the only inhomogeneous coefficient different from zero.
53  c_coeff = -c.expression().get(Variable(c_first_var - 1));
54 
55  c_second_var = 0;
56  return true;
57  }
58 
59  ++c_num_vars;
60 
61  if (!c.expression().all_zeroes(c_second_var + 1, space_dim + 1)) {
62  // The constraint `c' is not a bounded difference.
63  return false;
64  }
65 
66  // Make sure that `c' is indeed a bounded difference, i.e., it is of the
67  // form:
68  // a*x - a*y <=/= b.
69  Coefficient_traits::const_reference c0 = c.expression().get(Variable(c_first_var - 1));
70  Coefficient_traits::const_reference c1 = c.expression().get(Variable(c_second_var - 1));
71  if (sgn(c0) == sgn(c1) || c0 != -c1) {
72  // Constraint `c' is not a bounded difference.
73  return false;
74  }
75 
76  c_coeff = c1;
77 
78  return true;
79 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
int sgn(Boundary_Type type, const T &x, const Info &info)
Coefficient c
Definition: PIP_Tree.cc:64
template<typename To , typename T >
bool l_infinity_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const BD_Shape< T > &  x,
const BD_Shape< T > &  y,
Rounding_Dir  dir 
)
related

Computes the $L_\infty$ distance between x and y.

If the $L_\infty$ 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>.

template<typename Temp , typename To , typename T >
bool l_infinity_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const BD_Shape< T > &  x,
const BD_Shape< T > &  y,
Rounding_Dir  dir 
)
related

Computes the $L_\infty$ distance between x and y.

If the $L_\infty$ 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>.

template<typename Temp , typename To , typename T >
bool l_infinity_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const BD_Shape< T > &  x,
const BD_Shape< T > &  y,
Rounding_Dir  dir,
Temp &  tmp0,
Temp &  tmp1,
Temp &  tmp2 
)
related

Computes the $L_\infty$ distance between x and y.

If the $L_\infty$ 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.

template<typename Temp , typename To , typename T >
bool l_infinity_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const BD_Shape< T > &  x,
const BD_Shape< T > &  y,
const Rounding_Dir  dir,
Temp &  tmp0,
Temp &  tmp1,
Temp &  tmp2 
)
related

Definition at line 630 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

636  {
637  const dimension_type x_space_dim = x.space_dimension();
638  // Dimension-compatibility check.
639  if (x_space_dim != y.space_dimension()) {
640  return false;
641  }
642  // Zero-dim BDSs are equal if and only if they are both empty or universe.
643  if (x_space_dim == 0) {
644  if (x.marked_empty() == y.marked_empty()) {
645  assign_r(r, 0, ROUND_NOT_NEEDED);
646  }
647  else {
649  }
650  return true;
651  }
652 
653  // The distance computation requires shortest-path closure.
654  x.shortest_path_closure_assign();
655  y.shortest_path_closure_assign();
656 
657  // If one of two BDSs is empty, then they are equal if and only if
658  // the other BDS is empty too.
659  if (x.marked_empty() || y.marked_empty()) {
660  if (x.marked_empty() == y.marked_empty()) {
661  assign_r(r, 0, ROUND_NOT_NEEDED);
662  }
663  else {
665  }
666  return true;
667  }
668 
669  return l_infinity_distance_assign(r, x.dbm, y.dbm, dir, tmp0, tmp1, tmp2);
670 }
bool l_infinity_distance_assign(Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, Rounding_Dir dir)
Computes the distance between x and y.
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
size_t dimension_type
An unsigned integral type for representing space dimensions.
Plus_Infinity PLUS_INFINITY
Definition: checked.cc:31
template<typename Temp , typename To , typename T >
bool l_infinity_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const BD_Shape< T > &  x,
const BD_Shape< T > &  y,
const Rounding_Dir  dir 
)
related

Definition at line 675 of file BD_Shape_inlines.hh.

References PPL_DIRTY_TEMP.

678  {
679  typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
680  PPL_DIRTY_TEMP(Checked_Temp, tmp0);
681  PPL_DIRTY_TEMP(Checked_Temp, tmp1);
682  PPL_DIRTY_TEMP(Checked_Temp, tmp2);
683  return l_infinity_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
684 }
bool l_infinity_distance_assign(Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, Rounding_Dir dir)
Computes the distance between x and y.
#define PPL_DIRTY_TEMP(T, id)
template<typename To , typename T >
bool l_infinity_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const BD_Shape< T > &  x,
const BD_Shape< T > &  y,
const Rounding_Dir  dir 
)
related

Definition at line 689 of file BD_Shape_inlines.hh.

692  {
693  return l_infinity_distance_assign<To, To, T>(r, x, y, dir);
694 }
template<typename T >
bool operator!= ( const BD_Shape< T > &  x,
const BD_Shape< T > &  y 
)
related

Returns true if and only if x and y are not the same BDS.

Note that x and y may be dimension-incompatible shapes: in this case, the value true is returned.

template<typename T >
bool operator!= ( const BD_Shape< T > &  x,
const BD_Shape< T > &  y 
)
related

Definition at line 483 of file BD_Shape_inlines.hh.

483  {
484  return !(x == y);
485 }
template<typename T >
std::ostream & operator<< ( std::ostream &  s,
const BD_Shape< T > &  bds 
)
related

Output operator.

Writes a textual representation of bds on s: false is written if bds is an empty polyhedron; true is written if bds is the universe polyhedron; a system of constraints defining bds is written otherwise, all constraints separated by ", ".

template<typename T >
std::ostream & operator<< ( std::ostream &  s,
const BD_Shape< T > &  bds 
)
related

Definition at line 6730 of file BD_Shape_templates.hh.

References Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::is_plus_infinity(), PPL_DIRTY_TEMP, Parma_Polyhedra_Library::ROUND_DOWN, and Parma_Polyhedra_Library::Boundary_NS::sgn().

6730  {
6731  typedef typename BD_Shape<T>::coefficient_type N;
6732  if (bds.is_universe()) {
6733  s << "true";
6734  }
6735  else {
6736  // We control empty bounded difference shape.
6737  dimension_type n = bds.space_dimension();
6738  if (bds.marked_empty()) {
6739  s << "false";
6740  }
6741  else {
6742  PPL_DIRTY_TEMP(N, v);
6743  bool first = true;
6744  for (dimension_type i = 0; i <= n; ++i) {
6745  for (dimension_type j = i + 1; j <= n; ++j) {
6746  const N& c_i_j = bds.dbm[i][j];
6747  const N& c_j_i = bds.dbm[j][i];
6748  if (is_additive_inverse(c_j_i, c_i_j)) {
6749  // We will print an equality.
6750  if (first) {
6751  first = false;
6752  }
6753  else {
6754  s << ", ";
6755  }
6756  if (i == 0) {
6757  // We have got a equality constraint with one variable.
6758  s << Variable(j - 1);
6759  s << " = " << c_i_j;
6760  }
6761  else {
6762  // We have got a equality constraint with two variables.
6763  if (sgn(c_i_j) >= 0) {
6764  s << Variable(j - 1);
6765  s << " - ";
6766  s << Variable(i - 1);
6767  s << " = " << c_i_j;
6768  }
6769  else {
6770  s << Variable(i - 1);
6771  s << " - ";
6772  s << Variable(j - 1);
6773  s << " = " << c_j_i;
6774  }
6775  }
6776  }
6777  else {
6778  // We will print a non-strict inequality.
6779  if (!is_plus_infinity(c_j_i)) {
6780  if (first) {
6781  first = false;
6782  }
6783  else {
6784  s << ", ";
6785  }
6786  if (i == 0) {
6787  // We have got a constraint with only one variable.
6788  s << Variable(j - 1);
6789  neg_assign_r(v, c_j_i, ROUND_DOWN);
6790  s << " >= " << v;
6791  }
6792  else {
6793  // We have got a constraint with two variables.
6794  if (sgn(c_j_i) >= 0) {
6795  s << Variable(i - 1);
6796  s << " - ";
6797  s << Variable(j - 1);
6798  s << " <= " << c_j_i;
6799  }
6800  else {
6801  s << Variable(j - 1);
6802  s << " - ";
6803  s << Variable(i - 1);
6804  neg_assign_r(v, c_j_i, ROUND_DOWN);
6805  s << " >= " << v;
6806  }
6807  }
6808  }
6809  if (!is_plus_infinity(c_i_j)) {
6810  if (first) {
6811  first = false;
6812  }
6813  else {
6814  s << ", ";
6815  }
6816  if (i == 0) {
6817  // We have got a constraint with only one variable.
6818  s << Variable(j - 1);
6819  s << " <= " << c_i_j;
6820  }
6821  else {
6822  // We have got a constraint with two variables.
6823  if (sgn(c_i_j) >= 0) {
6824  s << Variable(j - 1);
6825  s << " - ";
6826  s << Variable(i - 1);
6827  s << " <= " << c_i_j;
6828  }
6829  else {
6830  s << Variable(i - 1);
6831  s << " - ";
6832  s << Variable(j - 1);
6833  neg_assign_r(v, c_i_j, ROUND_DOWN);
6834  s << " >= " << v;
6835  }
6836  }
6837  }
6838  }
6839  }
6840  }
6841  }
6842  }
6843  return s;
6844 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
Checked_Number< T, Debug_WRD_Extended_Number_Policy > N
The (extended) numeric type of the inhomogeneous term of the inequalities defining a BDS...
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_additive_inverse(const T &x, const T &y)
Returns true if and only if .
#define PPL_DIRTY_TEMP(T, id)
int sgn(Boundary_Type type, const T &x, const Info &info)
template<typename T >
bool operator== ( const BD_Shape< T > &  x,
const BD_Shape< T > &  y 
)
related

Returns true if and only if x and y are the same BDS.

Note that x and y may be dimension-incompatible shapes: in this case, the value false is returned.

template<typename T >
bool operator== ( const BD_Shape< T > &  x,
const BD_Shape< T > &  y 
)
related

Definition at line 446 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

446  {
447  const dimension_type x_space_dim = x.space_dimension();
448  // Dimension-compatibility check.
449  if (x_space_dim != y.space_dimension()) {
450  return false;
451  }
452 
453  // Zero-dim BDSs are equal if and only if they are both empty or universe.
454  if (x_space_dim == 0) {
455  if (x.marked_empty()) {
456  return y.marked_empty();
457  }
458  else {
459  return !y.marked_empty();
460  }
461  }
462 
463  // The exact equivalence test requires shortest-path closure.
464  x.shortest_path_closure_assign();
465  y.shortest_path_closure_assign();
466 
467  // If one of two BDSs is empty, then they are equal
468  // if and only if the other BDS is empty too.
469  if (x.marked_empty()) {
470  return y.marked_empty();
471  }
472  if (y.marked_empty()) {
473  return false;
474  }
475  // Check for syntactic equivalence of the two (shortest-path closed)
476  // systems of bounded differences.
477  return x.dbm == y.dbm;
478 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
template<typename T>
bool operator== ( const BD_Shape< T > &  x,
const BD_Shape< T > &  y 
)
friend
template<typename T>
template<typename U >
friend class Parma_Polyhedra_Library::BD_Shape
friend

Definition at line 1936 of file BD_Shape_defs.hh.

template<typename T>
template<typename Interval >
friend class Parma_Polyhedra_Library::Box
friend

Definition at line 1937 of file BD_Shape_defs.hh.

template<typename T>
template<typename Temp , typename To , typename U >
bool Parma_Polyhedra_Library::euclidean_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const BD_Shape< U > &  x,
const BD_Shape< U > &  y,
const Rounding_Dir  dir,
Temp &  tmp0,
Temp &  tmp1,
Temp &  tmp2 
)
friend
template<typename T>
std::ostream& Parma_Polyhedra_Library::IO_Operators::operator<< ( std::ostream &  s,
const BD_Shape< T > &  c 
)
friend
template<typename T>
template<typename Temp , typename To , typename U >
bool Parma_Polyhedra_Library::l_infinity_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const BD_Shape< U > &  x,
const BD_Shape< U > &  y,
const Rounding_Dir  dir,
Temp &  tmp0,
Temp &  tmp1,
Temp &  tmp2 
)
friend
template<typename T>
template<typename Temp , typename To , typename U >
bool Parma_Polyhedra_Library::rectilinear_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const BD_Shape< U > &  x,
const BD_Shape< U > &  y,
const Rounding_Dir  dir,
Temp &  tmp0,
Temp &  tmp1,
Temp &  tmp2 
)
friend
template<typename To , typename T >
bool rectilinear_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const BD_Shape< T > &  x,
const BD_Shape< T > &  y,
Rounding_Dir  dir 
)
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>.

template<typename Temp , typename To , typename T >
bool rectilinear_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const BD_Shape< T > &  x,
const BD_Shape< T > &  y,
Rounding_Dir  dir 
)
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<Temp, Extended_Number_Policy>.

template<typename Temp , typename To , typename T >
bool rectilinear_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const BD_Shape< T > &  x,
const BD_Shape< T > &  y,
Rounding_Dir  dir,
Temp &  tmp0,
Temp &  tmp1,
Temp &  tmp2 
)
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.

template<typename Temp , typename To , typename T >
bool rectilinear_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const BD_Shape< T > &  x,
const BD_Shape< T > &  y,
const Rounding_Dir  dir,
Temp &  tmp0,
Temp &  tmp1,
Temp &  tmp2 
)
related

Definition at line 490 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

496  {
497  const dimension_type x_space_dim = x.space_dimension();
498  // Dimension-compatibility check.
499  if (x_space_dim != y.space_dimension()) {
500  return false;
501  }
502 
503  // Zero-dim BDSs are equal if and only if they are both empty or universe.
504  if (x_space_dim == 0) {
505  if (x.marked_empty() == y.marked_empty()) {
506  assign_r(r, 0, ROUND_NOT_NEEDED);
507  }
508  else {
510  }
511  return true;
512  }
513 
514  // The distance computation requires shortest-path closure.
515  x.shortest_path_closure_assign();
516  y.shortest_path_closure_assign();
517 
518  // If one of two BDSs is empty, then they are equal if and only if
519  // the other BDS is empty too.
520  if (x.marked_empty() || y.marked_empty()) {
521  if (x.marked_empty() == y.marked_empty()) {
522  assign_r(r, 0, ROUND_NOT_NEEDED);
523  }
524  else {
526  }
527  return true;
528  }
529 
530  return rectilinear_distance_assign(r, x.dbm, y.dbm, dir, tmp0, tmp1, tmp2);
531 }
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool rectilinear_distance_assign(Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, Rounding_Dir dir)
Computes the rectilinear (or Manhattan) distance between x and y.
Plus_Infinity PLUS_INFINITY
Definition: checked.cc:31
template<typename Temp , typename To , typename T >
bool rectilinear_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const BD_Shape< T > &  x,
const BD_Shape< T > &  y,
const Rounding_Dir  dir 
)
related

Definition at line 536 of file BD_Shape_inlines.hh.

References PPL_DIRTY_TEMP.

539  {
540  typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
541  PPL_DIRTY_TEMP(Checked_Temp, tmp0);
542  PPL_DIRTY_TEMP(Checked_Temp, tmp1);
543  PPL_DIRTY_TEMP(Checked_Temp, tmp2);
544  return rectilinear_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
545 }
bool rectilinear_distance_assign(Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< T > &x, const BD_Shape< T > &y, Rounding_Dir dir)
Computes the rectilinear (or Manhattan) distance between x and y.
#define PPL_DIRTY_TEMP(T, id)
template<typename To , typename T >
bool rectilinear_distance_assign ( Checked_Number< To, Extended_Number_Policy > &  r,
const BD_Shape< T > &  x,
const BD_Shape< T > &  y,
const Rounding_Dir  dir 
)
related

Definition at line 550 of file BD_Shape_inlines.hh.

553  {
554  return rectilinear_distance_assign<To, To, T>(r, x, y, dir);
555 }
template<typename T >
void swap ( BD_Shape< T > &  x,
BD_Shape< T > &  y 
)
related

Swaps x with y.

template<typename T >
void swap ( BD_Shape< T > &  x,
BD_Shape< T > &  y 
)
related

Definition at line 951 of file BD_Shape_inlines.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::m_swap().

951  {
952  x.m_swap(y);
953 }

Member Data Documentation

template<typename T>
DB_Matrix<N> Parma_Polyhedra_Library::BD_Shape< T >::dbm
private

The matrix representing the system of bounded differences.

Definition at line 1940 of file BD_Shape_defs.hh.

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::BD_Shape< T >::BFT00_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::BHZ09_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::BD_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::BD_Shape< T >::euclidean_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::get_limiting_shape(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::BD_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::BD_Shape< T >::is_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::l_infinity_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::m_swap(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::operator=(), Parma_Polyhedra_Library::BD_Shape< T >::operator==(), Parma_Polyhedra_Library::BD_Shape< T >::rectilinear_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign().

template<typename T>
Status Parma_Polyhedra_Library::BD_Shape< T >::status
private

The status flags to keep track of the internal state.

Definition at line 1947 of file BD_Shape_defs.hh.

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::m_swap(), and Parma_Polyhedra_Library::BD_Shape< T >::operator=().


The documentation for this class was generated from the following files: