Parma_Polyhedra_Library::BD_Shape< T > Class Template Reference
[C++ Language Interface]

A bounded difference shape. More...

#include <BD_Shape.defs.hh>

Collaboration diagram for Parma_Polyhedra_Library::BD_Shape< T >:
Collaboration graph
[legend]

List of all members.

Classes

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

Public Types

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

Public Member Functions

void ascii_dump () const
 Writes to std::cerr an ASCII representation of *this.
void ascii_dump (std::ostream &s) const
 Writes to s an ASCII representation of *this.
void print () const
 Prints *this to std::cerr using operator<<.
bool ascii_load (std::istream &s)
 Loads from s an ASCII representation (as produced by ascii_dump(std::ostream&) const) and sets *this accordingly. Returns true if successful, false otherwise.
memory_size_type total_memory_in_bytes () const
 Returns the total size in bytes of the memory occupied by *this.
memory_size_type external_memory_in_bytes () const
 Returns the size in bytes of the memory managed by *this.
int32_t hash_code () const
 Returns a 32-bit hash code for *this.
Constructors, Assignment, Swap and Destructor

 BD_Shape (dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
 Builds a universe or empty BDS of the specified space dimension.
 BD_Shape (const BD_Shape &y, Complexity_Class complexity=ANY_COMPLEXITY)
 Ordinary copy constructor.
template<typename U >
 BD_Shape (const BD_Shape< U > &y, Complexity_Class complexity=ANY_COMPLEXITY)
 Builds a conservative, upward approximation of y.
 BD_Shape (const Constraint_System &cs)
 Builds a BDS from the system of constraints cs.
 BD_Shape (const Congruence_System &cgs)
 Builds a BDS from a system of congruences.
 BD_Shape (const Generator_System &gs)
 Builds a BDS from the system of generators gs.
 BD_Shape (const Polyhedron &ph, Complexity_Class complexity=ANY_COMPLEXITY)
 Builds a BDS from the polyhedron ph.
template<typename Interval >
 BD_Shape (const Box< Interval > &box, Complexity_Class complexity=ANY_COMPLEXITY)
 Builds a BDS out of a box.
 BD_Shape (const Grid &grid, Complexity_Class complexity=ANY_COMPLEXITY)
 Builds a BDS out of a grid.
template<typename U >
 BD_Shape (const Octagonal_Shape< U > &os, Complexity_Class complexity=ANY_COMPLEXITY)
 Builds a BDS from an octagonal shape.
BD_Shapeoperator= (const BD_Shape &y)
 The assignment operator (*this and y can be dimension-incompatible).
void swap (BD_Shape &y)
 Swaps *this with y (*this and y can be dimension-incompatible).
 ~BD_Shape ()
 Destructor.
Member Functions that Do Not Modify the BD_Shape

dimension_type space_dimension () const
 Returns the dimension of the vector space enclosing *this.
dimension_type affine_dimension () const
 Returns $0$, if *this is empty; otherwise, returns the affine dimension of *this.
Constraint_System constraints () const
 Returns a system of constraints defining *this.
Constraint_System minimized_constraints () const
 Returns a minimized system of constraints defining *this.
Congruence_System congruences () const
 Returns a system of (equality) congruences satisfied by *this.
Congruence_System minimized_congruences () const
 Returns a minimal system of (equality) congruences satisfied by *this with the same affine dimension as *this.
bool bounds_from_above (const Linear_Expression &expr) const
 Returns true if and only if expr is bounded from above in *this.
bool bounds_from_below (const Linear_Expression &expr) const
 Returns true if and only if expr is bounded from below in *this.
bool maximize (const Linear_Expression &expr, Coefficient &sup_n, Coefficient &sup_d, bool &maximum) const
 Returns true if and only if *this is not empty and expr is bounded from above in *this, in which case the supremum value is computed.
bool maximize (const Linear_Expression &expr, Coefficient &sup_n, Coefficient &sup_d, bool &maximum, Generator &g) const
 Returns true if and only if *this is not empty and expr is bounded from above in *this, in which case the supremum value and a point where expr reaches it are computed.
bool minimize (const Linear_Expression &expr, Coefficient &inf_n, Coefficient &inf_d, bool &minimum) const
 Returns true if and only if *this is not empty and expr is bounded from below in *this, in which case the infimum value is computed.
bool minimize (const Linear_Expression &expr, Coefficient &inf_n, Coefficient &inf_d, bool &minimum, Generator &g) const
 Returns true if and only if *this is not empty and expr is bounded from below in *this, in which case the infimum value and a point where expr reaches it are computed.
bool frequency (const Linear_Expression &expr, Coefficient &freq_n, Coefficient &freq_d, Coefficient &val_n, Coefficient &val_d) const
 Returns true if and only if there exist a unique value val such that *this saturates the equality expr = val.
bool contains (const BD_Shape &y) const
 Returns true if and only if *this contains y.
bool strictly_contains (const BD_Shape &y) const
 Returns true if and only if *this strictly contains y.
bool is_disjoint_from (const BD_Shape &y) const
 Returns true if and only if *this and y are disjoint.
Poly_Con_Relation relation_with (const Constraint &c) const
 Returns the relations holding between *this and the constraint c.
Poly_Con_Relation relation_with (const Congruence &cg) const
 Returns the relations holding between *this and the congruence cg.
Poly_Gen_Relation relation_with (const Generator &g) const
 Returns the relations holding between *this and the generator g.
bool is_empty () const
 Returns true if and only if *this is an empty BDS.
bool is_universe () const
 Returns true if and only if *this is a universe BDS.
bool is_discrete () const
 Returns true if and only if *this is discrete.
bool is_topologically_closed () const
 Returns true if and only if *this is a topologically closed subset of the vector space.
bool is_bounded () const
 Returns true if and only if *this is a bounded BDS.
bool contains_integer_point () const
 Returns true if and only if *this contains at least one integer point.
bool constrains (Variable var) const
 Returns true if and only if var is constrained in *this.
bool OK () const
 Returns true if and only if *this satisfies all its invariants.
Space-Dimension Preserving Member Functions that May Modify the BD_Shape

void add_constraint (const Constraint &c)
 Adds a copy of constraint c to the system of bounded differences defining *this.
void add_congruence (const Congruence &cg)
 Adds a copy of congruence cg to the system of congruences of *this.
void add_constraints (const Constraint_System &cs)
 Adds the constraints in cs to the system of bounded differences defining *this.
void add_recycled_constraints (Constraint_System &cs)
 Adds the constraints in cs to the system of constraints of *this.
void add_congruences (const Congruence_System &cgs)
 Adds to *this constraints equivalent to the congruences in cgs.
void add_recycled_congruences (Congruence_System &cgs)
 Adds to *this constraints equivalent to the congruences in cgs.
void refine_with_constraint (const Constraint &c)
 Uses a copy of constraint c to refine the system of bounded differences defining *this.
void refine_with_congruence (const Congruence &cg)
 Uses a copy of congruence cg to refine the system of bounded differences of *this.
void refine_with_constraints (const Constraint_System &cs)
 Uses a copy of the constraints in cs to refine the system of bounded differences defining *this.
void refine_with_congruences (const Congruence_System &cgs)
 Uses a copy of the congruences in cgs to refine the system of bounded differences defining *this.
void unconstrain (Variable var)
 Computes the cylindrification of *this with respect to space dimension var, assigning the result to *this.
void unconstrain (const Variables_Set &vars)
 Computes the cylindrification of *this with respect to the set of space dimensions vars, assigning the result to *this.
void intersection_assign (const BD_Shape &y)
 Assigns to *this the intersection of *this and y.
void upper_bound_assign (const BD_Shape &y)
 Assigns to *this the smallest BDS containing the union of *this and y.
bool upper_bound_assign_if_exact (const BD_Shape &y)
 If the upper bound of *this and y is exact, it is assigned to *this and true is returned, otherwise false is returned.
bool integer_upper_bound_assign_if_exact (const BD_Shape &y)
 If the integer upper bound of *this and y is exact, it is assigned to *this and true is returned; otherwise false is returned.
void difference_assign (const BD_Shape &y)
 Assigns to *this the smallest BD shape containing the set difference of *this and y.
bool simplify_using_context_assign (const BD_Shape &y)
 Assigns to *this a meet-preserving simplification of *this with respect to y. If false is returned, then the intersection is empty.
void affine_image (Variable var, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the affine image of *this under the function mapping variable var into the affine expression specified by expr and denominator.
void affine_preimage (Variable var, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the affine preimage of *this under the function mapping variable var into the affine expression specified by expr and denominator.
void generalized_affine_image (Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the image of *this with respect to the affine relation $\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym.
void generalized_affine_image (const Linear_Expression &lhs, Relation_Symbol relsym, const Linear_Expression &rhs)
 Assigns to *this the image of *this with respect to the affine relation $\mathrm{lhs}' \relsym \mathrm{rhs}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym.
void generalized_affine_preimage (Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the preimage of *this with respect to the affine relation $\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym.
void generalized_affine_preimage (const Linear_Expression &lhs, Relation_Symbol relsym, const Linear_Expression &rhs)
 Assigns to *this the preimage of *this with respect to the affine relation $\mathrm{lhs}' \relsym \mathrm{rhs}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym.
void bounded_affine_image (Variable var, const Linear_Expression &lb_expr, const Linear_Expression &ub_expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the image of *this with respect to the bounded affine relation $\frac{\mathrm{lb\_expr}}{\mathrm{denominator}} \leq \mathrm{var}' \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}$.
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}}$.
void time_elapse_assign (const BD_Shape &y)
 Assigns to *this the result of computing the time-elapse between *this and y.
void wrap_assign (const Variables_Set &vars, Bounded_Integer_Type_Width w, Bounded_Integer_Type_Representation r, Bounded_Integer_Type_Overflow o, const Constraint_System *pcs=0, unsigned complexity_threshold=16, bool wrap_individually=true)
 Wraps the specified dimensions of the vector space.
void drop_some_non_integer_points (Complexity_Class complexity=ANY_COMPLEXITY)
 Possibly tightens *this by dropping some points with non-integer coordinates.
void drop_some_non_integer_points (const Variables_Set &vars, Complexity_Class complexity=ANY_COMPLEXITY)
 Possibly tightens *this by dropping some points with non-integer coordinates for the space dimensions corresponding to vars.
void topological_closure_assign ()
 Assigns to *this its topological closure.
void CC76_extrapolation_assign (const BD_Shape &y, unsigned *tp=0)
 Assigns to *this the result of computing the CC76-extrapolation between *this and y.
template<typename Iterator >
void CC76_extrapolation_assign (const BD_Shape &y, Iterator first, Iterator last, unsigned *tp=0)
 Assigns to *this the result of computing the CC76-extrapolation between *this and y.
void BHMZ05_widening_assign (const BD_Shape &y, unsigned *tp=0)
 Assigns to *this the result of computing the BHMZ05-widening of *this and y.
void limited_BHMZ05_extrapolation_assign (const BD_Shape &y, const Constraint_System &cs, unsigned *tp=0)
 Improves the result of the BHMZ05-widening computation by also enforcing those constraints in cs that are satisfied by all the points of *this.
void CC76_narrowing_assign (const BD_Shape &y)
 Assigns to *this the result of restoring in y the constraints of *this that were lost by CC76-extrapolation applications.
void limited_CC76_extrapolation_assign (const BD_Shape &y, const Constraint_System &cs, unsigned *tp=0)
 Improves the result of the CC76-extrapolation computation by also enforcing those constraints in cs that are satisfied by all the points of *this.
void H79_widening_assign (const BD_Shape &y, unsigned *tp=0)
 Assigns to *this the result of computing the H79-widening between *this and y.
void widening_assign (const BD_Shape &y, unsigned *tp=0)
 Same as H79_widening_assign(y, tp).
void limited_H79_extrapolation_assign (const BD_Shape &y, const Constraint_System &cs, unsigned *tp=0)
 Improves the result of the H79-widening computation by also enforcing those constraints in cs that are satisfied by all the points of *this.
Member Functions that May Modify the Dimension of the Vector Space

void add_space_dimensions_and_embed (dimension_type m)
 Adds m new dimensions and embeds the old BDS into the new space.
void add_space_dimensions_and_project (dimension_type m)
 Adds m new dimensions to the BDS and does not embed it in the new vector space.
void concatenate_assign (const BD_Shape &y)
 Assigns to *this the concatenation of *this and y, taken in this order.
void remove_space_dimensions (const Variables_Set &vars)
 Removes all the specified dimensions.
void remove_higher_space_dimensions (dimension_type new_dimension)
 Removes the higher dimensions so that the resulting space will have dimension new_dimension.
template<typename Partial_Function >
void map_space_dimensions (const Partial_Function &pfunc)
 Remaps the dimensions of the vector space according to a partial function.
void expand_space_dimension (Variable var, dimension_type m)
 Creates m copies of the space dimension corresponding to var.
void fold_space_dimensions (const Variables_Set &vars, Variable dest)
 Folds the space dimensions in vars into dest.

Static Public Member Functions

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

Private Types

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

Private Member Functions

bool marked_zero_dim_univ () const
 Returns true if the BDS is the zero-dimensional universe.
bool marked_empty () const
 Returns true if the BDS is known to be empty.
bool marked_shortest_path_closed () const
 Returns true if the system of bounded differences is known to be shortest-path closed.
bool marked_shortest_path_reduced () const
 Returns true if the system of bounded differences is known to be shortest-path reduced.
void set_empty ()
 Turns *this into an empty BDS.
void set_zero_dim_univ ()
 Turns *this into an zero-dimensional universe BDS.
void set_shortest_path_closed ()
 Marks *this as shortest-path closed.
void set_shortest_path_reduced ()
 Marks *this as shortest-path closed.
void reset_shortest_path_closed ()
 Marks *this as possibly not shortest-path closed.
void reset_shortest_path_reduced ()
 Marks *this as possibly not shortest-path reduced.
void shortest_path_closure_assign () const
 Assigns to this->dbm its shortest-path closure.
void shortest_path_reduction_assign () const
 Assigns to this->dbm its shortest-path closure and records into this->redundancy_dbm which of the entries in this->dbm are redundant.
bool is_shortest_path_reduced () const
 Returns true if and only if this->dbm is shortest-path closed and this->redundancy_dbm correctly flags the redundant entries in this->dbm.
void incremental_shortest_path_closure_assign (Variable var) const
 Incrementally computes shortest-path closure, assuming that only constraints affecting variable var need to be considered.
bool bounds (const Linear_Expression &expr, bool from_above) const
 Checks if and how expr is bounded in *this.
bool max_min (const Linear_Expression &expr, bool maximize, Coefficient &ext_n, Coefficient &ext_d, bool &included, Generator &g) const
 Maximizes or minimizes expr subject to *this.
bool max_min (const Linear_Expression &expr, bool maximize, Coefficient &ext_n, Coefficient &ext_d, bool &included) const
 Maximizes or minimizes expr subject to *this.
bool BFT00_upper_bound_assign_if_exact (const BD_Shape &y)
 If the upper bound of *this and y is exact it is assigned to *this and true is returned, otherwise false is returned.
template<bool integer_upper_bound>
bool BHZ09_upper_bound_assign_if_exact (const BD_Shape &y)
 If the upper bound of *this and y is exact it is assigned to *this and true is returned, otherwise false is returned.
void refine_no_check (const Constraint &c)
 Uses the constraint c to refine *this.
void refine_no_check (const Congruence &cg)
 Uses the congruence cg to refine *this.
void add_dbm_constraint (dimension_type i, dimension_type j, const N &k)
 Adds the constraint dbm[i][j] <= k.
void add_dbm_constraint (dimension_type i, dimension_type j, Coefficient_traits::const_reference num, Coefficient_traits::const_reference den)
 Adds the constraint dbm[i][j] <= num/den.
void refine (Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Adds to the BDS the constraint $\mathrm{var} \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}$.
void forget_all_dbm_constraints (dimension_type v)
 Removes all the constraints on row/column v.
void forget_binary_dbm_constraints (dimension_type v)
 Removes all binary constraints on row/column v.
void deduce_v_minus_u_bounds (dimension_type v, dimension_type last_v, const Linear_Expression &sc_expr, Coefficient_traits::const_reference sc_den, const N &ub_v)
 An helper function for the computation of affine relations.
void deduce_u_minus_v_bounds (dimension_type v, dimension_type last_v, const Linear_Expression &sc_expr, Coefficient_traits::const_reference sc_den, const N &minus_lb_v)
 An helper function for the computation of affine relations.
void get_limiting_shape (const Constraint_System &cs, BD_Shape &limiting_shape) const
 Adds to limiting_shape the bounded differences in cs that are satisfied by *this.
void compute_predecessors (std::vector< dimension_type > &predecessor) const
 Compute the (zero-equivalence classes) predecessor relation.
void compute_leaders (std::vector< dimension_type > &leaders) const
 Compute the leaders of zero-equivalence classes.
void drop_some_non_integer_points_helper (N &elem)

Private Attributes

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

Friends

class Parma_Polyhedra_Library::BD_Shape
class Parma_Polyhedra_Library::Box
bool operator== (const BD_Shape< T > &x, const BD_Shape< T > &y)
 Returns true if and only if x and y are the same BDS.
template<typename Temp , typename To , typename U >
bool Parma_Polyhedra_Library::rectilinear_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< U > &x, const BD_Shape< U > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
template<typename Temp , typename To , typename U >
bool Parma_Polyhedra_Library::euclidean_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< U > &x, const BD_Shape< U > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
template<typename Temp , typename To , typename U >
bool Parma_Polyhedra_Library::l_infinity_distance_assign (Checked_Number< To, Extended_Number_Policy > &r, const BD_Shape< U > &x, const BD_Shape< U > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
std::ostream & Parma_Polyhedra_Library::IO_Operators::operator<< (std::ostream &s, const BD_Shape< T > &c)

Related Functions

(Note that these are not member functions.)



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

Exception Throwers



void throw_dimension_incompatible (const char *method, const BD_Shape &x) const
void throw_dimension_incompatible (const char *method, dimension_type required_dim) const
void throw_dimension_incompatible (const char *method, const Constraint &c) const
void throw_dimension_incompatible (const char *method, const Congruence &cg) const
void throw_dimension_incompatible (const char *method, const Generator &g) const
void throw_dimension_incompatible (const char *method, const char *name_row, const Linear_Expression &y) const
static void throw_expression_too_complex (const char *method, const Linear_Expression &e)
static void throw_generic (const char *method, const char *reason)

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:

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

The domain of BD shapes optimally supports:

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

A constraint is a bounded difference if it has the form

\[ 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:

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 403 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 423 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 417 of file BD_Shape.defs.hh.

template<typename T>
typedef Checked_Number<T, Debug_WRD_Extended_Number_Policy> Parma_Polyhedra_Library::BD_Shape< T >::N [private]

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

Definition at line 410 of file BD_Shape.defs.hh.


Constructor & Destructor Documentation

template<typename T >
Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape ( dimension_type  num_dimensions = 0,
Degenerate_Element  kind = UNIVERSE 
) [inline, explicit]

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

Parameters:
num_dimensions The number of dimensions of the vector space enclosing the BDS;
kind Specifies whether the universe or the empty BDS has to be built.

Definition at line 115 of file BD_Shape.inlines.hh.

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

00117   : dbm(num_dimensions + 1), status(), redundancy_dbm() {
00118   if (kind == EMPTY)
00119     set_empty();
00120   else {
00121     if (num_dimensions > 0)
00122       // A (non zero-dim) universe BDS is closed.
00123       set_shortest_path_closed();
00124   }
00125   PPL_ASSERT(OK());
00126 }

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 130 of file BD_Shape.inlines.hh.

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

00131   : dbm(y.dbm), status(y.status), redundancy_dbm() {
00132   if (y.marked_shortest_path_reduced())
00133     redundancy_dbm = y.redundancy_dbm;
00134 }

template<typename T >
template<typename U >
Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape ( const BD_Shape< U > &  y,
Complexity_Class  complexity = ANY_COMPLEXITY 
) [inline, explicit]

Builds a conservative, upward approximation of y.

The complexity argument is ignored.

Definition at line 139 of file BD_Shape.inlines.hh.

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

00142   : dbm((y.shortest_path_closure_assign(), y.dbm)),
00143     status(),
00144     redundancy_dbm() {
00145   // TODO: handle flags properly, possibly taking special cases into account.
00146   if (y.marked_empty())
00147     set_empty();
00148   else if (y.marked_zero_dim_univ())
00149     set_zero_dim_univ();
00150 }

template<typename T >
Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape ( const Constraint_System cs  )  [inline, explicit]

Builds a BDS from the system of constraints cs.

The BDS inherits the space dimension of cs.

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

Definition at line 269 of file BD_Shape.inlines.hh.

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

00270   : dbm(cs.space_dimension() + 1), status(), redundancy_dbm() {
00271   if (cs.space_dimension() > 0)
00272     // A (non zero-dim) universe BDS is shortest-path closed.
00273     set_shortest_path_closed();
00274   add_constraints(cs);
00275 }

template<typename T >
Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape ( const Congruence_System cgs  )  [inline, explicit]

Builds a BDS from a system of congruences.

The BDS inherits the space dimension of cgs

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

Definition at line 48 of file BD_Shape.templates.hh.

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

00049   : dbm(cgs.space_dimension() + 1),
00050     status(),
00051     redundancy_dbm() {
00052   add_congruences(cgs);
00053 }

template<typename T >
Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape ( const Generator_System gs  )  [inline, explicit]

Builds a BDS from the system of generators gs.

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

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

Definition at line 56 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Generator_System::begin(), Parma_Polyhedra_Library::Generator::CLOSURE_POINT, Parma_Polyhedra_Library::Generator::coefficient(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::Generator::divisor(), Parma_Polyhedra_Library::Generator_System::end(), Parma_Polyhedra_Library::Generator::LINE, Parma_Polyhedra_Library::max_assign(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::Generator::POINT, Parma_Polyhedra_Library::Generator::RAY, Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_generic(), and Parma_Polyhedra_Library::Generator::type().

00057   : dbm(gs.space_dimension() + 1), status(), redundancy_dbm() {
00058   const Generator_System::const_iterator gs_begin = gs.begin();
00059   const Generator_System::const_iterator gs_end = gs.end();
00060   if (gs_begin == gs_end) {
00061     // An empty generator system defines the empty BD shape.
00062     set_empty();
00063     return;
00064   }
00065 
00066   const dimension_type space_dim = space_dimension();
00067   DB_Row<N>& dbm_0 = dbm[0];
00068   PPL_DIRTY_TEMP(N, tmp);
00069 
00070   bool dbm_initialized = false;
00071   bool point_seen = false;
00072   // Going through all the points and closure points.
00073   for (Generator_System::const_iterator gs_i = gs_begin;
00074        gs_i != gs_end; ++gs_i) {
00075     const Generator& g = *gs_i;
00076     switch (g.type()) {
00077     case Generator::POINT:
00078       point_seen = true;
00079       // Intentionally fall through.
00080     case Generator::CLOSURE_POINT:
00081       if (!dbm_initialized) {
00082         // When handling the first (closure) point, we initialize the DBM.
00083         dbm_initialized = true;
00084         const Coefficient& d = g.divisor();
00085         for (dimension_type i = space_dim; i > 0; --i) {
00086           const Coefficient& g_i = g.coefficient(Variable(i-1));
00087           DB_Row<N>& dbm_i = dbm[i];
00088           for (dimension_type j = space_dim; j > 0; --j)
00089             if (i != j)
00090               div_round_up(dbm_i[j], g.coefficient(Variable(j-1)) - g_i, d);
00091           div_round_up(dbm_i[0], -g_i, d);
00092         }
00093         for (dimension_type j = space_dim; j > 0; --j)
00094           div_round_up(dbm_0[j], g.coefficient(Variable(j-1)), d);
00095         // Note: no need to initialize the first element of the main diagonal.
00096       }
00097       else {
00098         // This is not the first point: the DBM already contains
00099         // valid values and we must compute maxima.
00100         const Coefficient& d = g.divisor();
00101         for (dimension_type i = space_dim; i > 0; --i) {
00102           const Coefficient& g_i = g.coefficient(Variable(i-1));
00103           DB_Row<N>& dbm_i = dbm[i];
00104           // The loop correctly handles the case when i == j.
00105           for (dimension_type j = space_dim; j > 0; --j) {
00106             div_round_up(tmp, g.coefficient(Variable(j-1)) - g_i, d);
00107             max_assign(dbm_i[j], tmp);
00108           }
00109           div_round_up(tmp, -g_i, d);
00110           max_assign(dbm_i[0], tmp);
00111         }
00112         for (dimension_type j = space_dim; j > 0; --j) {
00113           div_round_up(tmp, g.coefficient(Variable(j-1)), d);
00114           max_assign(dbm_0[j], tmp);
00115         }
00116       }
00117       break;
00118     default:
00119       // Lines and rays temporarily ignored.
00120       break;
00121     }
00122   }
00123 
00124   if (!point_seen)
00125     // The generator system is not empty, but contains no points.
00126     throw_generic("BD_Shape(gs)",
00127                   "the non-empty generator system gs contains no points.");
00128 
00129   // Going through all the lines and rays.
00130   for (Generator_System::const_iterator gs_i = gs_begin;
00131        gs_i != gs_end; ++gs_i) {
00132     const Generator& g = *gs_i;
00133     switch (g.type()) {
00134     case Generator::LINE:
00135       for (dimension_type i = space_dim; i > 0; --i) {
00136         const Coefficient& g_i = g.coefficient(Variable(i-1));
00137         DB_Row<N>& dbm_i = dbm[i];
00138         // The loop correctly handles the case when i == j.
00139         for (dimension_type j = space_dim; j > 0; --j)
00140           if (g_i != g.coefficient(Variable(j-1)))
00141             assign_r(dbm_i[j], PLUS_INFINITY, ROUND_NOT_NEEDED);
00142         if (g_i != 0)
00143           assign_r(dbm_i[0], PLUS_INFINITY, ROUND_NOT_NEEDED);
00144       }
00145       for (dimension_type j = space_dim; j > 0; --j)
00146         if (g.coefficient(Variable(j-1)) != 0)
00147           assign_r(dbm_0[j], PLUS_INFINITY, ROUND_NOT_NEEDED);
00148       break;
00149     case Generator::RAY:
00150       for (dimension_type i = space_dim; i > 0; --i) {
00151         const Coefficient& g_i = g.coefficient(Variable(i-1));
00152         DB_Row<N>& dbm_i = dbm[i];
00153         // The loop correctly handles the case when i == j.
00154         for (dimension_type j = space_dim; j > 0; --j)
00155           if (g_i < g.coefficient(Variable(j-1)))
00156             assign_r(dbm_i[j], PLUS_INFINITY, ROUND_NOT_NEEDED);
00157         if (g_i < 0)
00158           assign_r(dbm_i[0], PLUS_INFINITY, ROUND_NOT_NEEDED);
00159       }
00160       for (dimension_type j = space_dim; j > 0; --j)
00161         if (g.coefficient(Variable(j-1)) > 0)
00162           assign_r(dbm_0[j], PLUS_INFINITY, ROUND_NOT_NEEDED);
00163       break;
00164     default:
00165       // Points and closure points already dealt with.
00166       break;
00167     }
00168   }
00169   set_shortest_path_closed();
00170   PPL_ASSERT(OK());
00171 }

template<typename T >
Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape ( const Polyhedron ph,
Complexity_Class  complexity = ANY_COMPLEXITY 
) [inline, explicit]

Builds a BDS from the polyhedron ph.

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

Definition at line 174 of file BD_Shape.templates.hh.

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

00175   : dbm(), status(), redundancy_dbm() {
00176   const dimension_type num_dimensions = ph.space_dimension();
00177 
00178   if (ph.marked_empty()) {
00179     *this = BD_Shape<T>(num_dimensions, EMPTY);
00180     return;
00181   }
00182 
00183   if (num_dimensions == 0) {
00184     *this = BD_Shape<T>(num_dimensions, UNIVERSE);
00185     return;
00186   }
00187 
00188   // Build from generators when we do not care about complexity
00189   // or when the process has polynomial complexity.
00190   if (complexity == ANY_COMPLEXITY
00191       || (!ph.has_pending_constraints() && ph.generators_are_up_to_date())) {
00192     *this = BD_Shape<T>(ph.generators());
00193     return;
00194   }
00195 
00196   // We cannot afford exponential complexity, we do not have a complete set
00197   // of generators for the polyhedron, and the polyhedron is not trivially
00198   // empty or zero-dimensional.  Constraints, however, are up to date.
00199   PPL_ASSERT(ph.constraints_are_up_to_date());
00200 
00201   if (!ph.has_something_pending() && ph.constraints_are_minimized()) {
00202     // If the constraint system of the polyhedron is minimized,
00203     // the test `is_universe()' has polynomial complexity.
00204     if (ph.is_universe()) {
00205       *this = BD_Shape<T>(num_dimensions, UNIVERSE);
00206       return;
00207     }
00208   }
00209 
00210   // See if there is at least one inconsistent constraint in `ph.con_sys'.
00211   for (Constraint_System::const_iterator i = ph.con_sys.begin(),
00212          cs_end = ph.con_sys.end(); i != cs_end; ++i)
00213     if (i->is_inconsistent()) {
00214       *this = BD_Shape<T>(num_dimensions, EMPTY);
00215       return;
00216     }
00217 
00218   // If `complexity' allows it, use simplex to derive the exact (modulo
00219   // the fact that our BDSs are topologically closed) variable bounds.
00220   if (complexity == SIMPLEX_COMPLEXITY) {
00221     MIP_Problem lp(num_dimensions);
00222     lp.set_optimization_mode(MAXIMIZATION);
00223 
00224     const Constraint_System& ph_cs = ph.constraints();
00225     if (!ph_cs.has_strict_inequalities())
00226       lp.add_constraints(ph_cs);
00227     else
00228       // Adding to `lp' a topologically closed version of `ph_cs'.
00229       for (Constraint_System::const_iterator i = ph_cs.begin(),
00230              ph_cs_end = ph_cs.end(); i != ph_cs_end; ++i) {
00231         const Constraint& c = *i;
00232         if (c.is_strict_inequality())
00233           lp.add_constraint(Linear_Expression(c) >= 0);
00234         else
00235           lp.add_constraint(c);
00236       }
00237 
00238     // Check for unsatisfiability.
00239     if (!lp.is_satisfiable()) {
00240       *this = BD_Shape<T>(num_dimensions, EMPTY);
00241       return;
00242     }
00243 
00244     // Start with a universe BDS that will be refined by the simplex.
00245     *this = BD_Shape<T>(num_dimensions, UNIVERSE);
00246     // Get all the upper bounds.
00247     Generator g(point());
00248     PPL_DIRTY_TEMP_COEFFICIENT(num);
00249     PPL_DIRTY_TEMP_COEFFICIENT(den);
00250     for (dimension_type i = 1; i <= num_dimensions; ++i) {
00251       Variable x(i-1);
00252       // Evaluate optimal upper bound for `x <= ub'.
00253       lp.set_objective_function(x);
00254       if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
00255         g = lp.optimizing_point();
00256         lp.evaluate_objective_function(g, num, den);
00257         div_round_up(dbm[0][i], num, den);
00258       }
00259       // Evaluate optimal upper bound for `x - y <= ub'.
00260       for (dimension_type j = 1; j <= num_dimensions; ++j) {
00261         if (i == j)
00262           continue;
00263         Variable y(j-1);
00264         lp.set_objective_function(x - y);
00265         if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
00266           g = lp.optimizing_point();
00267           lp.evaluate_objective_function(g, num, den);
00268           div_round_up(dbm[j][i], num, den);
00269         }
00270       }
00271       // Evaluate optimal upper bound for `-x <= ub'.
00272       lp.set_objective_function(-x);
00273       if (lp.solve() == OPTIMIZED_MIP_PROBLEM) {
00274         g = lp.optimizing_point();
00275         lp.evaluate_objective_function(g, num, den);
00276         div_round_up(dbm[i][0], num, den);
00277       }
00278     }
00279     set_shortest_path_closed();
00280     PPL_ASSERT(OK());
00281     return;
00282   }
00283 
00284   // Extract easy-to-find bounds from constraints.
00285   PPL_ASSERT(complexity == POLYNOMIAL_COMPLEXITY);
00286   *this = BD_Shape<T>(num_dimensions, UNIVERSE);
00287   refine_with_constraints(ph.constraints());
00288 }

template<typename T >
template<typename Interval >
Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape ( const Box< Interval > &  box,
Complexity_Class  complexity = ANY_COMPLEXITY 
) [inline, explicit]

Builds a BDS out of a box.

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

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

Definition at line 280 of file BD_Shape.inlines.hh.

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

00282   : dbm(box.space_dimension() + 1), status(), redundancy_dbm() {
00283   // Check for emptyness for maximum precision.
00284   if (box.is_empty())
00285     set_empty();
00286   else if (box.space_dimension() > 0) {
00287     // A (non zero-dim) universe BDS is shortest-path closed.
00288     set_shortest_path_closed();
00289     refine_with_constraints(box.constraints());
00290   }
00291 }

template<typename T >
Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape ( const Grid grid,
Complexity_Class  complexity = ANY_COMPLEXITY 
) [inline, explicit]

Builds a BDS out of a grid.

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

Parameters:
grid The grid used to build the BDS.
complexity This argument is ignored as the algorithm used has polynomial complexity.
Exceptions:
std::length_error Thrown if the space dimension of grid exceeds the maximum allowed space dimension.

Definition at line 295 of file BD_Shape.inlines.hh.

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

00297   : dbm(grid.space_dimension() + 1), status(), redundancy_dbm() {
00298   if (grid.space_dimension() > 0)
00299     // A (non zero-dim) universe BDS is shortest-path closed.
00300     set_shortest_path_closed();
00301   // Taking minimized congruences ensures maximum precision.
00302   refine_with_congruences(grid.minimized_congruences());
00303 }

template<typename T >
template<typename U >
Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape ( const Octagonal_Shape< U > &  os,
Complexity_Class  complexity = ANY_COMPLEXITY 
) [inline, explicit]

Builds a BDS from an octagonal shape.

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

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

Definition at line 308 of file BD_Shape.inlines.hh.

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

00310   : dbm(os.space_dimension() + 1), status(), redundancy_dbm() {
00311   // Check for emptyness for maximum precision.
00312   if (os.is_empty())
00313     set_empty();
00314   else if (os.space_dimension() > 0) {
00315     // A (non zero-dim) universe BDS is shortest-path closed.
00316     set_shortest_path_closed();
00317     refine_with_constraints(os.constraints());
00318     // After refining, shortest-path closure is possibly lost
00319     // (even when `os' was strongly closed: recall that U
00320     // is possibly different from T).
00321   }
00322 }

template<typename T >
Parma_Polyhedra_Library::BD_Shape< T >::~BD_Shape (  )  [inline]

Destructor.

Definition at line 336 of file BD_Shape.inlines.hh.

00336                        {
00337 }


Member Function Documentation

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

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

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

Definition at line 447 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), Parma_Polyhedra_Library::Congruence::is_proper_congruence(), Parma_Polyhedra_Library::Congruence::is_tautological(), Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Congruence::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().

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

00447                                                 {
00448   const dimension_type cg_space_dim = cg.space_dimension();
00449   // Dimension-compatibility check:
00450   // the dimension of `cg' can not be greater than space_dim.
00451   if (space_dimension() < cg_space_dim)
00452     throw_dimension_incompatible("add_congruence(cg)", cg);
00453 
00454   // Handle the case of proper congruences first.
00455   if (cg.is_proper_congruence()) {
00456     if (cg.is_tautological())
00457       return;
00458     if (cg.is_inconsistent()) {
00459       set_empty();
00460       return;
00461     }
00462     // Non-trivial and proper congruences are not allowed.
00463     throw_generic("add_congruence(cg)",
00464                   "cg is a non-trivial, proper congruence");
00465   }
00466 
00467   PPL_ASSERT(cg.is_equality());
00468   Constraint c(cg);
00469   add_constraint(c);
00470 }

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:
cgs Contains the congruences that will be added to the system of constraints of *this.
Exceptions:
std::invalid_argument Thrown if *this and cgs are dimension-incompatible, or cgs contains a congruence which is not optimally supported by the BD shape domain.

Definition at line 174 of file BD_Shape.inlines.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::add_congruence(), Parma_Polyhedra_Library::Congruence_System::begin(), and Parma_Polyhedra_Library::Congruence_System::end().

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

00174                                                          {
00175   for (Congruence_System::const_iterator i = cgs.begin(),
00176          cgs_end = cgs.end(); i != cgs_end; ++i)
00177     add_congruence(*i);
00178 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::add_constraint ( const Constraint c  )  [inline]

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

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

Definition at line 374 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::BD_Shape< T >::extract_bounded_difference(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Constraint::is_inconsistent(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Constraint::is_tautological(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_congruence(), Parma_Polyhedra_Library::BD_Shape< T >::add_constraints(), and Parma_Polyhedra_Library::BD_Shape< T >::difference_assign().

00374                                                {
00375   const dimension_type c_space_dim = c.space_dimension();
00376   // Dimension-compatibility check.
00377   if (c_space_dim > space_dimension())
00378     throw_dimension_incompatible("add_constraint(c)", c);
00379 
00380   // Get rid of strict inequalities.
00381   if (c.is_strict_inequality()) {
00382     if (c.is_inconsistent()) {
00383       set_empty();
00384       return;
00385     }
00386     if (c.is_tautological())
00387       return;
00388     // Nontrivial strict inequalities are not allowed.
00389     throw_generic("add_constraint(c)", "strict inequalities are not allowed");
00390   }
00391 
00392   dimension_type num_vars = 0;
00393   dimension_type i = 0;
00394   dimension_type j = 0;
00395   PPL_DIRTY_TEMP_COEFFICIENT(coeff);
00396   // Constraints that are not bounded differences are not allowed.
00397   if (!extract_bounded_difference(c, c_space_dim, num_vars, i, j, coeff))
00398     throw_generic("add_constraint(c)",
00399                   "c is not a bounded difference constraint");
00400 
00401   const Coefficient& inhomo = c.inhomogeneous_term();
00402   if (num_vars == 0) {
00403     // Dealing with a trivial constraint (not a strict inequality).
00404     if (inhomo < 0
00405         || (inhomo != 0 && c.is_equality()))
00406       set_empty();
00407     return;
00408   }
00409 
00410   // Select the cell to be modified for the "<=" part of the constraint,
00411   // and set `coeff' to the absolute value of itself.
00412   const bool negative = (coeff < 0);
00413   N& x = negative ? dbm[i][j] : dbm[j][i];
00414   N& y = negative ? dbm[j][i] : dbm[i][j];
00415   if (negative)
00416     neg_assign(coeff);
00417 
00418   bool changed = false;
00419   // Compute the bound for `x', rounding towards plus infinity.
00420   PPL_DIRTY_TEMP(N, d);
00421   div_round_up(d, inhomo, coeff);
00422   if (x > d) {
00423     x = d;
00424     changed = true;
00425   }
00426 
00427   if (c.is_equality()) {
00428     // Also compute the bound for `y', rounding towards plus infinity.
00429     PPL_DIRTY_TEMP_COEFFICIENT(minus_c_term);
00430     neg_assign(minus_c_term, inhomo);
00431     div_round_up(d, minus_c_term, coeff);
00432     if (y > d) {
00433       y = d;
00434       changed = true;
00435     }
00436   }
00437 
00438   // In general, adding a constraint does not preserve the shortest-path
00439   // closure or reduction of the bounded difference shape.
00440   if (changed && marked_shortest_path_closed())
00441     reset_shortest_path_closed();
00442   PPL_ASSERT(OK());
00443 }

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:
cs The constraints that will be added.
Exceptions:
std::invalid_argument Thrown if *this and cs are dimension-incompatible, or cs contains a constraint which is not optimally supported by the BD shape domain.

Definition at line 160 of file BD_Shape.inlines.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::add_constraint(), Parma_Polyhedra_Library::Constraint_System::begin(), and Parma_Polyhedra_Library::Constraint_System::end().

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

00160                                                         {
00161   for (Constraint_System::const_iterator i = cs.begin(),
00162          cs_end = cs.end(); i != cs_end; ++i)
00163     add_constraint(*i);
00164 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::add_dbm_constraint ( dimension_type  i,
dimension_type  j,
Coefficient_traits::const_reference  num,
Coefficient_traits::const_reference  den 
) [inline, private]

Adds the constraint dbm[i][j] <= num/den.

Definition at line 672 of file BD_Shape.inlines.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::add_dbm_constraint(), Parma_Polyhedra_Library::div_round_up(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

00675                                                                        {
00676   // Private method: the caller has to ensure the following.
00677   PPL_ASSERT(i <= space_dimension() && j <= space_dimension() && i != j);
00678   PPL_ASSERT(den != 0);
00679   PPL_DIRTY_TEMP(N, k);
00680   div_round_up(k, num, den);
00681   add_dbm_constraint(i, j, k);
00682 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::add_dbm_constraint ( dimension_type  i,
dimension_type  j,
const N k 
) [inline, private]
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:
cgs Contains the congruences that will be added to the system of constraints of *this. Its elements may be recycled.
Exceptions:
std::invalid_argument Thrown if *this and cgs are dimension-incompatible, or cgs contains a congruence which is not optimally supported by the BD shape domain.
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 182 of file BD_Shape.inlines.hh.

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

00182                                                             {
00183   add_congruences(cgs);
00184 }

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:
cs The constraint system to be added to *this. The constraints in cs may be recycled.
Exceptions:
std::invalid_argument Thrown if *this and cs are dimension-incompatible, or cs contains a constraint which is not optimally supported by the BD shape domain.
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 168 of file BD_Shape.inlines.hh.

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

00168                                                            {
00169   add_constraints(cs);
00170 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_embed ( dimension_type  m  )  [inline]

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

Parameters:
m The number of dimensions to add.

The new dimensions will be those having the highest indexes in the new BDS, which is defined by a system of bounded differences in which the variables running through the new dimensions are unconstrained. For instance, when starting from the BDS $\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 2611 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::DB_Matrix< T >::grow(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::BD_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage().

02611                                                                   {
02612   // Adding no dimensions is a no-op.
02613   if (m == 0)
02614     return;
02615 
02616   const dimension_type space_dim = space_dimension();
02617   const dimension_type new_space_dim = space_dim + m;
02618   const bool was_zero_dim_univ = (!marked_empty() && space_dim == 0);
02619 
02620   // To embed an n-dimension space BDS in a (n+m)-dimension space,
02621   // we just add `m' rows and columns in the bounded difference shape,
02622   // initialized to PLUS_INFINITY.
02623   dbm.grow(new_space_dim + 1);
02624 
02625   // Shortest-path closure is maintained (if it was holding).
02626   // TODO: see whether reduction can be (efficiently!) maintained too.
02627   if (marked_shortest_path_reduced())
02628     reset_shortest_path_reduced();
02629 
02630   // If `*this' was the zero-dim space universe BDS,
02631   // the we can set the shortest-path closure flag.
02632   if (was_zero_dim_univ)
02633     set_shortest_path_closed();
02634 
02635   PPL_ASSERT(OK());
02636 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_project ( dimension_type  m  )  [inline]

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

Parameters:
m The number of dimensions to add.

The new dimensions will be those having the highest indexes in the new BDS, which is defined by a system of bounded differences in which the variables running through the new dimensions are all constrained to be equal to 0. For instance, when starting from the BDS $\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 2640 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::DB_Matrix< T >::grow(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

02640                                                                     {
02641   // Adding no dimensions is a no-op.
02642   if (m == 0)
02643     return;
02644 
02645   const dimension_type space_dim = space_dimension();
02646 
02647   // If `*this' was zero-dimensional, then we add `m' rows and columns.
02648   // If it also was non-empty, then we zero all the added elements
02649   // and set the flag for shortest-path closure.
02650   if (space_dim == 0) {
02651     dbm.grow(m + 1);
02652     if (!marked_empty()) {
02653       for (dimension_type i = m + 1; i-- > 0; ) {
02654         DB_Row<N>& dbm_i = dbm[i];
02655         for (dimension_type j = m + 1; j-- > 0; )
02656           if (i != j)
02657             assign_r(dbm_i[j], 0, ROUND_NOT_NEEDED);
02658       }
02659       set_shortest_path_closed();
02660     }
02661     PPL_ASSERT(OK());
02662     return;
02663   }
02664 
02665   // To project an n-dimension space bounded difference shape
02666   // in a (n+m)-dimension space, we add `m' rows and columns.
02667   // In the first row and column of the matrix we add `zero' from
02668   // the (n+1)-th position to the end.
02669   const dimension_type new_space_dim = space_dim + m;
02670   dbm.grow(new_space_dim + 1);
02671 
02672   // Bottom of the matrix and first row.
02673   DB_Row<N>& dbm_0 = dbm[0];
02674   for (dimension_type i = space_dim + 1; i <= new_space_dim; ++i) {
02675     assign_r(dbm[i][0], 0, ROUND_NOT_NEEDED);
02676     assign_r(dbm_0[i], 0, ROUND_NOT_NEEDED);
02677   }
02678 
02679   if (marked_shortest_path_closed())
02680     reset_shortest_path_closed();
02681   PPL_ASSERT(OK());
02682 }

template<typename T >
dimension_type Parma_Polyhedra_Library::BD_Shape< T >::affine_dimension (  )  const [inline]

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

Definition at line 292 of file BD_Shape.templates.hh.

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

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

00292                                     {
00293   const dimension_type space_dim = space_dimension();
00294   // A zero-space-dim shape always has affine dimension zero.
00295   if (space_dim == 0)
00296     return 0;
00297 
00298   // Shortest-path closure is necessary to detect emptiness
00299   // and all (possibly implicit) equalities.
00300   shortest_path_closure_assign();
00301   if (marked_empty())
00302     return 0;
00303 
00304   // The vector `predecessor' is used to represent equivalence classes:
00305   // `predecessor[i] == i' if and only if `i' is the leader of its
00306   // equivalence class (i.e., the minimum index in the class);
00307   std::vector<dimension_type> predecessor;
00308   compute_predecessors(predecessor);
00309 
00310   // Due to the fictitious variable `0', the affine dimension is one
00311   // less the number of equivalence classes.
00312   dimension_type affine_dim = 0;
00313   // Note: disregard the first equivalence class.
00314   for (dimension_type i = 1; i <= space_dim; ++i)
00315     if (predecessor[i] == i)
00316       ++affine_dim;
00317 
00318   return affine_dim;
00319 }

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() 
) [inline]

Assigns to *this the affine image of *this under the function mapping variable var into the affine expression specified by expr and denominator.

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

Definition at line 3826 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::add_dbm_constraint(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::deduce_u_minus_v_bounds(), Parma_Polyhedra_Library::BD_Shape< T >::deduce_v_minus_u_bounds(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::BD_Shape< T >::forget_all_dbm_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::forget_binary_dbm_constraints(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::swap(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage().

03828                                                                          {
03829   // The denominator cannot be zero.
03830   if (denominator == 0)
03831     throw_generic("affine_image(v, e, d)", "d == 0");
03832 
03833   // Dimension-compatibility checks.
03834   // The dimension of `expr' should not be greater than the dimension
03835   // of `*this'.
03836   const dimension_type space_dim = space_dimension();
03837   const dimension_type expr_space_dim = expr.space_dimension();
03838   if (space_dim < expr_space_dim)
03839     throw_dimension_incompatible("affine_image(v, e, d)", "e", expr);
03840 
03841   // `var' should be one of the dimensions of the shape.
03842   const dimension_type v = var.id() + 1;
03843   if (v > space_dim)
03844     throw_dimension_incompatible("affine_image(v, e, d)", var.id());
03845 
03846   // The image of an empty BDS is empty too.
03847   shortest_path_closure_assign();
03848   if (marked_empty())
03849     return;
03850 
03851   const Coefficient& b = expr.inhomogeneous_term();
03852   // Number of non-zero coefficients in `expr': will be set to
03853   // 0, 1, or 2, the latter value meaning any value greater than 1.
03854   dimension_type t = 0;
03855   // Index of the last non-zero coefficient in `expr', if any.
03856   dimension_type w = 0;
03857   // Get information about the number of non-zero coefficients in `expr'.
03858   for (dimension_type i = expr_space_dim; i-- > 0; )
03859     if (expr.coefficient(Variable(i)) != 0) {
03860       if (t++ == 1)
03861         break;
03862       else
03863         w = i+1;
03864     }
03865 
03866   // Now we know the form of `expr':
03867   // - If t == 0, then expr == b, with `b' a constant;
03868   // - If t == 1, then expr == a*w + b, where `w' can be `v' or another
03869   //   variable; in this second case we have to check whether `a' is
03870   //   equal to `denominator' or `-denominator', since otherwise we have
03871   //   to fall back on the general form;
03872   // - If t == 2, the `expr' is of the general form.
03873   PPL_DIRTY_TEMP_COEFFICIENT(minus_den);
03874   neg_assign(minus_den, denominator);
03875 
03876   if (t == 0) {
03877     // Case 1: expr == b.
03878     // Remove all constraints on `var'.
03879     forget_all_dbm_constraints(v);
03880     // Shortest-path closure is preserved, but not reduction.
03881     if (marked_shortest_path_reduced())
03882       reset_shortest_path_reduced();
03883     // Add the constraint `var == b/denominator'.
03884     add_dbm_constraint(0, v, b, denominator);
03885     add_dbm_constraint(v, 0, b, minus_den);
03886     PPL_ASSERT(OK());
03887     return;
03888   }
03889 
03890   if (t == 1) {
03891     // Value of the one and only non-zero coefficient in `expr'.
03892     const Coefficient& a = expr.coefficient(Variable(w-1));
03893     if (a == denominator || a == minus_den) {
03894       // Case 2: expr == a*w + b, with a == +/- denominator.
03895       if (w == v) {
03896         // `expr' is of the form: a*v + b.
03897         if (a == denominator) {
03898           if (b == 0)
03899             // The transformation is the identity function.
03900             return;
03901           else {
03902             // Translate all the constraints on `var',
03903             // adding or subtracting the value `b/denominator'.
03904             PPL_DIRTY_TEMP(N, d);
03905             div_round_up(d, b, denominator);
03906             PPL_DIRTY_TEMP(N, c);
03907             div_round_up(c, b, minus_den);
03908             DB_Row<N>& dbm_v = dbm[v];
03909             for (dimension_type i = space_dim + 1; i-- > 0; ) {
03910               N& dbm_vi = dbm_v[i];
03911               add_assign_r(dbm_vi, dbm_vi, c, ROUND_UP);
03912               N& dbm_iv = dbm[i][v];
03913               add_assign_r(dbm_iv, dbm_iv, d, ROUND_UP);
03914             }
03915             // Both shortest-path closure and reduction are preserved.
03916           }
03917         }
03918         else {
03919           // Here `a == -denominator'.
03920           // Remove the binary constraints on `var'.
03921           forget_binary_dbm_constraints(v);
03922           // Swap the unary constraints on `var'.
03923           std::swap(dbm[v][0], dbm[0][v]);
03924           // Shortest-path closure is not preserved.
03925           reset_shortest_path_closed();
03926           if (b != 0) {
03927             // Translate the unary constraints on `var',
03928             // adding or subtracting the value `b/denominator'.
03929             PPL_DIRTY_TEMP(N, c);
03930             div_round_up(c, b, minus_den);
03931             N& dbm_v0 = dbm[v][0];
03932             add_assign_r(dbm_v0, dbm_v0, c, ROUND_UP);
03933             PPL_DIRTY_TEMP(N, d);
03934             div_round_up(d, b, denominator);
03935             N& dbm_0v = dbm[0][v];
03936             add_assign_r(dbm_0v, dbm_0v, d, ROUND_UP);
03937           }
03938         }
03939       }
03940       else {
03941         // Here `w != v', so that `expr' is of the form
03942         // +/-denominator * w + b.
03943         // Remove all constraints on `var'.
03944         forget_all_dbm_constraints(v);
03945         // Shortest-path closure is preserved, but not reduction.
03946         if (marked_shortest_path_reduced())
03947           reset_shortest_path_reduced();
03948         if (a == denominator) {
03949           // Add the new constraint `v - w == b/denominator'.
03950           add_dbm_constraint(w, v, b, denominator);
03951           add_dbm_constraint(v, w, b, minus_den);
03952         }
03953         else {
03954           // Here a == -denominator, so that we should be adding
03955           // the constraint `v + w == b/denominator'.
03956           // Approximate it by computing lower and upper bounds for `w'.
03957           const N& dbm_w0 = dbm[w][0];
03958           if (!is_plus_infinity(dbm_w0)) {
03959             // Add the constraint `v <= b/denominator - lower_w'.
03960             PPL_DIRTY_TEMP(N, d);
03961             div_round_up(d, b, denominator);
03962             add_assign_r(dbm[0][v], d, dbm_w0, ROUND_UP);
03963             reset_shortest_path_closed();
03964           }
03965           const N& dbm_0w = dbm[0][w];
03966           if (!is_plus_infinity(dbm_0w)) {
03967             // Add the constraint `v >= b/denominator - upper_w'.
03968             PPL_DIRTY_TEMP(N, c);
03969             div_round_up(c, b, minus_den);
03970             add_assign_r(dbm[v][0], dbm_0w, c, ROUND_UP);
03971             reset_shortest_path_closed();
03972           }
03973         }
03974       }
03975       PPL_ASSERT(OK());
03976       return;
03977     }
03978   }
03979 
03980   // General case.
03981   // Either t == 2, so that
03982   // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
03983   // or t == 1, expr == a*w + b, but a <> +/- denominator.
03984   // We will remove all the constraints on `var' and add back
03985   // constraints providing upper and lower bounds for `var'.
03986 
03987   // Compute upper approximations for `expr' and `-expr'
03988   // into `pos_sum' and `neg_sum', respectively, taking into account
03989   // the sign of `denominator'.
03990   // Note: approximating `-expr' from above and then negating the
03991   // result is the same as approximating `expr' from below.
03992   const bool is_sc = (denominator > 0);
03993   PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
03994   neg_assign(minus_b, b);
03995   const Coefficient& sc_b = is_sc ? b : minus_b;
03996   const Coefficient& minus_sc_b = is_sc ? minus_b : b;
03997   const Coefficient& sc_den = is_sc ? denominator : minus_den;
03998   const Coefficient& minus_sc_den = is_sc ? minus_den : denominator;
03999   // NOTE: here, for optimization purposes, `minus_expr' is only assigned
04000   // when `denominator' is negative. Do not use it unless you are sure
04001   // it has been correctly assigned.
04002   Linear_Expression minus_expr;
04003   if (!is_sc)
04004     minus_expr = -expr;
04005   const Linear_Expression& sc_expr = is_sc ? expr : minus_expr;
04006 
04007   PPL_DIRTY_TEMP(N, pos_sum);
04008   PPL_DIRTY_TEMP(N, neg_sum);
04009   // Indices of the variables that are unbounded in `this->dbm'.
04010   PPL_UNINITIALIZED(dimension_type, pos_pinf_index);
04011   PPL_UNINITIALIZED(dimension_type, neg_pinf_index);
04012   // Number of unbounded variables found.
04013   dimension_type pos_pinf_count = 0;
04014   dimension_type neg_pinf_count = 0;
04015 
04016   // Approximate the inhomogeneous term.
04017   assign_r(pos_sum, sc_b, ROUND_UP);
04018   assign_r(neg_sum, minus_sc_b, ROUND_UP);
04019 
04020   // Approximate the homogeneous part of `sc_expr'.
04021   const DB_Row<N>& dbm_0 = dbm[0];
04022   // Speculative allocation of temporaries to be used in the following loop.
04023   PPL_DIRTY_TEMP(N, coeff_i);
04024   PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
04025   // Note: indices above `w' can be disregarded, as they all have
04026   // a zero coefficient in `sc_expr'.
04027   for (dimension_type i = w; i > 0; --i) {
04028     const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1));
04029     const int sign_i = sgn(sc_i);
04030     if (sign_i > 0) {
04031       assign_r(coeff_i, sc_i, ROUND_UP);
04032       // Approximating `sc_expr'.
04033       if (pos_pinf_count <= 1) {
04034         const N& up_approx_i = dbm_0[i];
04035         if (!is_plus_infinity(up_approx_i))
04036           add_mul_assign_r(pos_sum, coeff_i, up_approx_i, ROUND_UP);
04037         else {
04038           ++pos_pinf_count;
04039           pos_pinf_index = i;
04040         }
04041       }
04042       // Approximating `-sc_expr'.
04043       if (neg_pinf_count <= 1) {
04044         const N& up_approx_minus_i = dbm[i][0];
04045         if (!is_plus_infinity(up_approx_minus_i))
04046           add_mul_assign_r(neg_sum, coeff_i, up_approx_minus_i, ROUND_UP);
04047         else {
04048           ++neg_pinf_count;
04049           neg_pinf_index = i;
04050         }
04051       }
04052     }
04053     else if (sign_i < 0) {
04054       neg_assign(minus_sc_i, sc_i);
04055       // Note: using temporary named `coeff_i' to store -coeff_i.
04056       assign_r(coeff_i, minus_sc_i, ROUND_UP);
04057       // Approximating `sc_expr'.
04058       if (pos_pinf_count <= 1) {
04059         const N& up_approx_minus_i = dbm[i][0];
04060         if (!is_plus_infinity(up_approx_minus_i))
04061           add_mul_assign_r(pos_sum, coeff_i, up_approx_minus_i, ROUND_UP);
04062         else {
04063           ++pos_pinf_count;
04064           pos_pinf_index = i;
04065         }
04066       }
04067       // Approximating `-sc_expr'.
04068       if (neg_pinf_count <= 1) {
04069         const N& up_approx_i = dbm_0[i];
04070         if (!is_plus_infinity(up_approx_i))
04071           add_mul_assign_r(neg_sum, coeff_i, up_approx_i, ROUND_UP);
04072         else {
04073           ++neg_pinf_count;
04074           neg_pinf_index = i;
04075         }
04076       }
04077     }
04078   }
04079 
04080   // Remove all constraints on 'v'.
04081   forget_all_dbm_constraints(v);
04082   // Shortest-path closure is maintained, but not reduction.
04083   if (marked_shortest_path_reduced())
04084     reset_shortest_path_reduced();
04085   // Return immediately if no approximation could be computed.
04086   if (pos_pinf_count > 1 && neg_pinf_count > 1) {
04087     PPL_ASSERT(OK());
04088     return;
04089   }
04090 
04091   // In the following, shortest-path closure will be definitely lost.
04092   reset_shortest_path_closed();
04093 
04094   // Exploit the upper approximation, if possible.
04095   if (pos_pinf_count <= 1) {
04096     // Compute quotient (if needed).
04097     if (sc_den != 1) {
04098       // Before computing quotients, the denominator should be approximated
04099       // towards zero. Since `sc_den' is known to be positive, this amounts to
04100       // rounding downwards, which is achieved as usual by rounding upwards
04101       // `minus_sc_den' and negating again the result.
04102       PPL_DIRTY_TEMP(N, down_sc_den);
04103       assign_r(down_sc_den, minus_sc_den, ROUND_UP);
04104       neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
04105       div_assign_r(pos_sum, pos_sum, down_sc_den, ROUND_UP);
04106     }
04107     // Add the upper bound constraint, if meaningful.
04108     if (pos_pinf_count == 0) {
04109       // Add the constraint `v <= pos_sum'.
04110       dbm[0][v] = pos_sum;
04111       // Deduce constraints of the form `v - u', where `u != v'.
04112       deduce_v_minus_u_bounds(v, w, sc_expr, sc_den, pos_sum);
04113     }
04114     else
04115       // Here `pos_pinf_count == 1'.
04116       if (pos_pinf_index != v
04117           && sc_expr.coefficient(Variable(pos_pinf_index-1)) == sc_den)
04118         // Add the constraint `v - pos_pinf_index <= pos_sum'.
04119         dbm[pos_pinf_index][v] = pos_sum;
04120   }
04121 
04122   // Exploit the lower approximation, if possible.
04123   if (neg_pinf_count <= 1) {
04124     // Compute quotient (if needed).
04125     if (sc_den != 1) {
04126       // Before computing quotients, the denominator should be approximated
04127       // towards zero. Since `sc_den' is known to be positive, this amounts to
04128       // rounding downwards, which is achieved as usual by rounding upwards
04129       // `minus_sc_den' and negating again the result.
04130       PPL_DIRTY_TEMP(N, down_sc_den);
04131       assign_r(down_sc_den, minus_sc_den, ROUND_UP);
04132       neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
04133       div_assign_r(neg_sum, neg_sum, down_sc_den, ROUND_UP);
04134     }
04135     // Add the lower bound constraint, if meaningful.
04136     if (neg_pinf_count == 0) {
04137       // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'.
04138       DB_Row<N>& dbm_v = dbm[v];
04139       dbm_v[0] = neg_sum;
04140       // Deduce constraints of the form `u - v', where `u != v'.
04141       deduce_u_minus_v_bounds(v, w, sc_expr, sc_den, neg_sum);
04142     }
04143     else
04144       // Here `neg_pinf_count == 1'.
04145       if (neg_pinf_index != v
04146           && sc_expr.coefficient(Variable(neg_pinf_index-1)) == sc_den)
04147         // Add the constraint `v - neg_pinf_index >= -neg_sum',
04148         // i.e., `neg_pinf_index - v <= neg_sum'.
04149         dbm[v][neg_pinf_index] = neg_sum;
04150   }
04151 
04152   PPL_ASSERT(OK());
04153 }

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() 
) [inline]

Assigns to *this the affine preimage of *this under the function mapping variable var into the affine expression specified by expr and denominator.

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

Definition at line 4157 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::BD_Shape< T >::forget_all_dbm_constraints(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().

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

04159                                                                             {
04160   // The denominator cannot be zero.
04161   if (denominator == 0)
04162     throw_generic("affine_preimage(v, e, d)", "d == 0");
04163 
04164   // Dimension-compatibility checks.
04165   // The dimension of `expr' should not be greater than the dimension
04166   // of `*this'.
04167   const dimension_type space_dim = space_dimension();
04168   const dimension_type expr_space_dim = expr.space_dimension();
04169   if (space_dim < expr_space_dim)
04170     throw_dimension_incompatible("affine_preimage(v, e, d)", "e", expr);
04171 
04172   // `var' should be one of the dimensions of
04173   // the bounded difference shapes.
04174   const dimension_type v = var.id() + 1;
04175   if (v > space_dim)
04176     throw_dimension_incompatible("affine_preimage(v, e, d)", var.id());
04177 
04178   // The image of an empty BDS is empty too.
04179   shortest_path_closure_assign();
04180   if (marked_empty())
04181     return;
04182 
04183   const Coefficient& b = expr.inhomogeneous_term();
04184   // Number of non-zero coefficients in `expr': will be set to
04185   // 0, 1, or 2, the latter value meaning any value greater than 1.
04186   dimension_type t = 0;
04187   // Index of the last non-zero coefficient in `expr', if any.
04188   dimension_type j = 0;
04189   // Get information about the number of non-zero coefficients in `expr'.
04190   for (dimension_type i = expr_space_dim; i-- > 0; )
04191     if (expr.coefficient(Variable(i)) != 0) {
04192       if (t++ == 1)
04193         break;
04194       else
04195         j = i;
04196     }
04197 
04198   // Now we know the form of `expr':
04199   // - If t == 0, then expr = b, with `b' a constant;
04200   // - If t == 1, then expr = a*w + b, where `w' can be `v' or another
04201   //   variable; in this second case we have to check whether `a' is
04202   //   equal to `denominator' or `-denominator', since otherwise we have
04203   //   to fall back on the general form;
04204   // - If t > 1, the `expr' is of the general form.
04205   if (t == 0) {
04206     // Case 1: expr = n; remove all constraints on `var'.
04207     forget_all_dbm_constraints(v);
04208     // Shortest-path closure is preserved, but not reduction.
04209     if (marked_shortest_path_reduced())
04210       reset_shortest_path_reduced();
04211     PPL_ASSERT(OK());
04212     return;
04213   }
04214 
04215   if (t == 1) {
04216     // Value of the one and only non-zero coefficient in `expr'.
04217     const Coefficient& a = expr.coefficient(Variable(j));
04218     if (a == denominator || a == -denominator) {
04219       // Case 2: expr = a*w + b, with a = +/- denominator.
04220       if (j == var.id())
04221         // Apply affine_image() on the inverse of this transformation.
04222         affine_image(var, denominator*var - b, a);
04223       else {
04224         // `expr == a*w + b', where `w != v'.
04225         // Remove all constraints on `var'.
04226         forget_all_dbm_constraints(v);
04227         // Shortest-path closure is preserved, but not reduction.
04228         if (marked_shortest_path_reduced())
04229           reset_shortest_path_reduced();
04230         PPL_ASSERT(OK());
04231       }
04232       return;
04233     }
04234   }
04235 
04236   // General case.
04237   // Either t == 2, so that
04238   // expr = a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
04239   // or t = 1, expr = a*w + b, but a <> +/- denominator.
04240   const Coefficient& expr_v = expr.coefficient(var);
04241   if (expr_v != 0) {
04242     // The transformation is invertible.
04243     Linear_Expression inverse((expr_v + denominator)*var);
04244     inverse -= expr;
04245     affine_image(var, inverse, expr_v);
04246   }
04247   else {
04248     // Transformation not invertible: all constraints on `var' are lost.
04249     forget_all_dbm_constraints(v);
04250     // Shortest-path closure is preserved, but not reduction.
04251     if (marked_shortest_path_reduced())
04252       reset_shortest_path_reduced();
04253   }
04254   PPL_ASSERT(OK());
04255 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::ascii_dump ( std::ostream &  s  )  const [inline]
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 >
bool Parma_Polyhedra_Library::BD_Shape< T >::ascii_load ( std::istream &  s  )  [inline]

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

Definition at line 5823 of file BD_Shape.templates.hh.

05823                                      {
05824   if (!status.ascii_load(s))
05825     return false;
05826   if (!dbm.ascii_load(s))
05827     return false;
05828   if (!redundancy_dbm.ascii_load(s))
05829     return false;
05830   return true;
05831 }

template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::BFT00_upper_bound_assign_if_exact ( const BD_Shape< T > &  y  )  [inline, private]

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

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

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

Definition at line 2060 of file BD_Shape.templates.hh.

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

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

02060                                                                 {
02061   // Declare a const reference to *this (to avoid accidental modifications).
02062   const BD_Shape& x = *this;
02063   const dimension_type x_space_dim = x.space_dimension();
02064 
02065   // Private method: the caller must ensure the following.
02066   PPL_ASSERT(x_space_dim == y.space_dimension());
02067 
02068   // The zero-dim case is trivial.
02069   if (x_space_dim == 0) {
02070     upper_bound_assign(y);
02071     return true;
02072   }
02073   // If `x' or `y' is (known to be) empty, the upper bound is exact.
02074   if (x.marked_empty()) {
02075     *this = y;
02076     return true;
02077   }
02078   else if (y.is_empty())
02079     return true;
02080   else if (x.is_empty()) {
02081     *this = y;
02082     return true;
02083   }
02084 
02085   // Here both `x' and `y' are known to be non-empty.
02086   // Implementation based on Algorithm 4.1 (page 6) in [BemporadFT00TR],
02087   // tailored to the special case of BD shapes.
02088 
02089   Variable eps(x_space_dim);
02090   Linear_Expression zero_expr = 0*eps;
02091   Linear_Expression db_expr;
02092   PPL_DIRTY_TEMP_COEFFICIENT(num);
02093   PPL_DIRTY_TEMP_COEFFICIENT(den);
02094 
02095   // Step 1: compute the constraint system for the envelope env(x,y)
02096   // and put into x_cs_removed and y_cs_removed those non-redundant
02097   // constraints that are not in the constraint system for env(x,y).
02098   // While at it, also add the additional space dimension (eps).
02099   Constraint_System env_cs;
02100   Constraint_System x_cs_removed;
02101   Constraint_System y_cs_removed;
02102   x.shortest_path_reduction_assign();
02103   y.shortest_path_reduction_assign();
02104   for (dimension_type i = x_space_dim + 1; i-- > 0; ) {
02105     const Bit_Row& x_red_i = x.redundancy_dbm[i];
02106     const Bit_Row& y_red_i = y.redundancy_dbm[i];
02107     const DB_Row<N>& x_dbm_i = x.dbm[i];
02108     const DB_Row<N>& y_dbm_i = y.dbm[i];
02109     for (dimension_type j = x_space_dim + 1; j-- > 0; ) {
02110       if (x_red_i[j] && y_red_i[j])
02111         continue;
02112       if (!x_red_i[j]) {
02113         const N& x_dbm_ij = x_dbm_i[j];
02114         PPL_ASSERT(!is_plus_infinity(x_dbm_ij));
02115         numer_denom(x_dbm_ij, num, den);
02116         // Build skeleton DB constraint (having the right space dimension).
02117         db_expr = zero_expr;
02118         if (i > 0)
02119           db_expr += Variable(i-1);
02120         if (j > 0)
02121           db_expr -= Variable(j-1);
02122         if (den != 1)
02123           db_expr *= den;
02124         db_expr += num;
02125         if (x_dbm_ij >= y_dbm_i[j])
02126           env_cs.insert(db_expr >= 0);
02127         else {
02128           db_expr += eps;
02129           x_cs_removed.insert(db_expr == 0);
02130         }
02131       }
02132       if (!y_red_i[j]) {
02133         const N& y_dbm_ij = y_dbm_i[j];
02134         const N& x_dbm_ij = x_dbm_i[j];
02135         PPL_ASSERT(!is_plus_infinity(y_dbm_ij));
02136         numer_denom(y_dbm_ij, num, den);
02137         // Build skeleton DB constraint (having the right space dimension).
02138         db_expr = zero_expr;
02139         if (i > 0)
02140           db_expr += Variable(i-1);
02141         if (j > 0)
02142           db_expr -= Variable(j-1);
02143         if (den != 1)
02144           db_expr *= den;
02145         db_expr += num;
02146         if (y_dbm_ij >= x_dbm_ij) {
02147           // Check if same constraint was added when considering x_dbm_ij.
02148           if (!x_red_i[j] && x_dbm_ij == y_dbm_ij)
02149             continue;
02150           env_cs.insert(db_expr >= 0);
02151         }
02152         else {
02153           db_expr += eps;
02154           y_cs_removed.insert(db_expr == 0);
02155         }
02156       }
02157     }
02158   }
02159 
02160   if (x_cs_removed.empty())
02161     // No constraint of x was removed: y is included in x.
02162     return true;
02163   if (y_cs_removed.empty()) {
02164     // No constraint of y was removed: x is included in y.
02165     *this = y;
02166     return true;
02167   }
02168 
02169   // In preparation to Step 4: build the common part of LP problems,
02170   // i.e., the constraints corresponding to env(x,y),
02171   // where the additional space dimension (eps) has to be maximised.
02172   MIP_Problem env_lp(x_space_dim + 1, env_cs, eps, MAXIMIZATION);
02173   // Pre-solve `env_lp' to later exploit incrementality.
02174   env_lp.solve();
02175   PPL_ASSERT(env_lp.solve() != UNFEASIBLE_MIP_PROBLEM);
02176 
02177   // Implementing loop in Steps 3-6.
02178   for (Constraint_System::const_iterator i = x_cs_removed.begin(),
02179          i_end = x_cs_removed.end(); i != i_end; ++i) {
02180     MIP_Problem lp_i(env_lp);
02181     lp_i.add_constraint(*i);
02182     // Pre-solve to exploit incrementality.
02183     if (lp_i.solve() == UNFEASIBLE_MIP_PROBLEM)
02184       continue;
02185     for (Constraint_System::const_iterator j = y_cs_removed.begin(),
02186            j_end = y_cs_removed.end(); j != j_end; ++j) {
02187       MIP_Problem lp_ij(lp_i);
02188       lp_ij.add_constraint(*j);
02189       // Solve and check for a positive optimal value.
02190       switch (lp_ij.solve()) {
02191       case UNFEASIBLE_MIP_PROBLEM:
02192         // CHECKME: is the following actually impossible?
02193         throw std::runtime_error("PPL internal error");
02194       case UNBOUNDED_MIP_PROBLEM:
02195         return false;
02196       case OPTIMIZED_MIP_PROBLEM:
02197         lp_ij.optimal_value(num, den);
02198         if (num > 0)
02199           return false;
02200         break;
02201       }
02202     }
02203   }
02204 
02205   // The upper bound of x and y is indeed exact.
02206   upper_bound_assign(y);
02207   PPL_ASSERT(OK());
02208   return true;
02209 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign ( const BD_Shape< T > &  y,
unsigned *  tp = 0 
) [inline]

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

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

Definition at line 3071 of file BD_Shape.templates.hh.

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

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

03071                                                                    {
03072   const dimension_type space_dim = space_dimension();
03073 
03074   // Dimension-compatibility check.
03075   if (space_dim != y.space_dimension())
03076     throw_dimension_incompatible("BHMZ05_widening_assign(y)", y);
03077 
03078 #ifndef NDEBUG
03079   {
03080     // We assume that `y' is contained in or equal to `*this'.
03081     const BD_Shape x_copy = *this;
03082     const BD_Shape y_copy = y;
03083     PPL_ASSERT(x_copy.contains(y_copy));
03084   }
03085 #endif
03086 
03087   // Compute the affine dimension of `y'.
03088   const dimension_type y_affine_dim = y.affine_dimension();
03089   // If the affine dimension of `y' is zero, then either `y' is
03090   // zero-dimensional, or it is empty, or it is a singleton.
03091   // In all cases, due to the inclusion hypothesis, the result is `*this'.
03092   if (y_affine_dim == 0)
03093     return;
03094 
03095   // If the affine dimension has changed, due to the inclusion hypothesis,
03096   // the result is `*this'.
03097   const dimension_type x_affine_dim = affine_dimension();
03098   PPL_ASSERT(x_affine_dim >= y_affine_dim);
03099   if (x_affine_dim != y_affine_dim)
03100     return;
03101 
03102   // If there are tokens available, work on a temporary copy.
03103   if (tp != 0 && *tp > 0) {
03104     BD_Shape<T> x_tmp(*this);
03105     x_tmp.BHMZ05_widening_assign(y, 0);
03106     // If the widening was not precise, use one of the available tokens.
03107     if (!contains(x_tmp))
03108       --(*tp);
03109     return;
03110   }
03111 
03112   // Here no token is available.
03113   PPL_ASSERT(marked_shortest_path_closed() && y.marked_shortest_path_closed());
03114   // Minimize `y'.
03115   y.shortest_path_reduction_assign();
03116 
03117   // Extrapolate unstable bounds, taking into account redundancy in `y'.
03118   for (dimension_type i = space_dim + 1; i-- > 0; ) {
03119     DB_Row<N>& dbm_i = dbm[i];
03120     const DB_Row<N>& y_dbm_i = y.dbm[i];
03121     const Bit_Row& y_redundancy_i = y.redundancy_dbm[i];
03122     for (dimension_type j = space_dim + 1; j-- > 0; ) {
03123       N& dbm_ij = dbm_i[j];
03124       // Note: in the following line the use of `!=' (as opposed to
03125       // the use of `<' that would seem -but is not- equivalent) is
03126       // intentional.
03127       if (y_redundancy_i[j] || y_dbm_i[j] != dbm_ij)
03128         assign_r(dbm_ij, PLUS_INFINITY, ROUND_NOT_NEEDED);
03129     }
03130   }
03131   // NOTE: this will also reset the shortest-path reduction flag,
03132   // even though the dbm is still in reduced form. However, the
03133   // current implementation invariant requires that any reduced dbm
03134   // is closed too.
03135   reset_shortest_path_closed();
03136   PPL_ASSERT(OK());
03137 }

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  )  [inline, private]

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

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

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 datatype.

Definition at line 2214 of file BD_Shape.templates.hh.

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

02214                                                                 {
02215   PPL_COMPILE_TIME_CHECK(!integer_upper_bound
02216                          || std::numeric_limits<T>::is_integer,
02217                          "BD_Shape<T>::BHZ09_upper_bound_assign_if_exact(y):"
02218                          " instantiating for integer upper bound,"
02219                          " but T in not an integer datatype.");
02220 
02221   // FIXME, CHECKME: what about inexact computations?
02222   // Declare a const reference to *this (to avoid accidental modifications).
02223   const BD_Shape& x = *this;
02224   const dimension_type x_space_dim = x.space_dimension();
02225 
02226   // Private method: the caller must ensure the following.
02227   PPL_ASSERT(x_space_dim == y.space_dimension());
02228 
02229   // The zero-dim case is trivial.
02230   if (x_space_dim == 0) {
02231     upper_bound_assign(y);
02232     return true;
02233   }
02234   // If `x' or `y' is (known to be) empty, the upper bound is exact.
02235   if (x.marked_empty()) {
02236     *this = y;
02237     return true;
02238   }
02239   else if (y.is_empty())
02240     return true;
02241   else if (x.is_empty()) {
02242     *this = y;
02243     return true;
02244   }
02245 
02246   // Here both `x' and `y' are known to be non-empty.
02247   x.shortest_path_reduction_assign();
02248   y.shortest_path_reduction_assign();
02249   PPL_ASSERT(x.marked_shortest_path_closed());
02250   PPL_ASSERT(y.marked_shortest_path_closed());
02251   // Pre-compute the upper bound of `x' and `y'.
02252   BD_Shape<T> ub(x);
02253   ub.upper_bound_assign(y);
02254 
02255   PPL_DIRTY_TEMP(N, lhs);
02256   PPL_DIRTY_TEMP(N, rhs);
02257   PPL_DIRTY_TEMP(N, temp_zero);
02258   assign_r(temp_zero, 0, ROUND_NOT_NEEDED);
02259   PPL_DIRTY_TEMP(N, temp_one);
02260   if (integer_upper_bound)
02261     assign_r(temp_one, 1, ROUND_NOT_NEEDED);
02262 
02263   for (dimension_type i = x_space_dim + 1; i-- > 0; ) {
02264     const DB_Row<N>& x_i = x.dbm[i];
02265     const Bit_Row& x_red_i = x.redundancy_dbm[i];
02266     const DB_Row<N>& y_i = y.dbm[i];
02267     const DB_Row<N>& ub_i = ub.dbm[i];
02268     for (dimension_type j = x_space_dim + 1; j-- > 0; ) {
02269       // Check redundancy of x_i_j.
02270       if (x_red_i[j])
02271         continue;
02272       // By non-redundancy, we know that i != j.
02273       PPL_ASSERT(i != j);
02274       const N& x_i_j = x_i[j];
02275       if (x_i_j < y_i[j]) {
02276         for (dimension_type k = x_space_dim + 1; k-- > 0; ) {
02277           const DB_Row<N>& x_k = x.dbm[k];
02278           const DB_Row<N>& y_k = y.dbm[k];
02279           const Bit_Row& y_red_k = y.redundancy_dbm[k];
02280           const DB_Row<N>& ub_k = ub.dbm[k];
02281           const N& ub_k_j = (k == j) ? temp_zero : ub_k[j];
02282           for (dimension_type ell = x_space_dim + 1; ell-- > 0; ) {
02283             // Check redundancy of y_k_ell.
02284             if (y_red_k[ell])
02285               continue;
02286             // By non-redundancy, we know that k != ell.
02287             PPL_ASSERT(k != ell);
02288             const N& y_k_ell = y_k[ell];
02289             if (y_k_ell < x_k[ell]) {
02290               // The first condition in BHZ09 theorem holds;
02291               // now check for the second condition.
02292               add_assign_r(lhs, x_i_j, y_k_ell, ROUND_UP);
02293               const N& ub_i_ell = (i == ell) ? temp_zero : ub_i[ell];
02294               add_assign_r(rhs, ub_i_ell, ub_k_j, ROUND_UP);
02295               if (integer_upper_bound) {
02296                 // Note: adding 1 rather than 2 (as in Theorem 5.3)
02297                 // so as to later test for < rather than <=.
02298                 add_assign_r(lhs, lhs, temp_one, ROUND_NOT_NEEDED);
02299               }
02300               // Testing for < in both the rational and integer case.
02301               if (lhs < rhs)
02302                 return false;
02303             }
02304           }
02305         }
02306       }
02307     }
02308   }
02309   // The upper bound of x and y is indeed exact.
02310   swap(ub);
02311   PPL_ASSERT(OK());
02312   return true;
02313 }

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() 
) [inline]

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:
var The variable updated by the affine relation;
lb_expr The numerator of the lower bounding affine expression;
ub_expr The numerator of the upper bounding affine expression;
denominator The (common) denominator for the lower and upper bounding affine expressions (optional argument with default value 1).
Exceptions:
std::invalid_argument Thrown if denominator is zero or if lb_expr (resp., ub_expr) and *this are dimension-incompatible or if var is not a space dimension of *this.

Definition at line 4260 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::neg_assign(), PPL_DIRTY_TEMP_COEFFICIENT, and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

04263                                                                       {
04264   // The denominator cannot be zero.
04265   if (denominator == 0)
04266     throw_generic("bounded_affine_image(v, lb, ub, d)", "d == 0");
04267 
04268   // Dimension-compatibility checks.
04269   // `var' should be one of the dimensions of the BD_Shape.
04270   const dimension_type bds_space_dim = space_dimension();
04271   const dimension_type v = var.id() + 1;
04272   if (v > bds_space_dim)
04273     throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)",
04274                                  "v", var);
04275   // The dimension of `lb_expr' and `ub_expr' should not be
04276   // greater than the dimension of `*this'.
04277   const dimension_type lb_space_dim = lb_expr.space_dimension();
04278   if (bds_space_dim < lb_space_dim)
04279     throw_dimension_incompatible("bounded_affine_image(v, lb, ub)",
04280                                  "lb", lb_expr);
04281   const dimension_type ub_space_dim = ub_expr.space_dimension();
04282   if (bds_space_dim < ub_space_dim)
04283     throw_dimension_incompatible("bounded_affine_image(v, lb, ub)",
04284                                  "ub", ub_expr);
04285 
04286   // Any image of an empty BDS is empty.
04287   shortest_path_closure_assign();
04288   if (marked_empty())
04289     return;
04290 
04291   const Coefficient& b = ub_expr.inhomogeneous_term();
04292   // Number of non-zero coefficients in `ub_expr': will be set to
04293   // 0, 1, or 2, the latter value meaning any value greater than 1.
04294   dimension_type t = 0;
04295   // Index of the last non-zero coefficient in `ub_expr', if any.
04296   dimension_type w = 0;
04297   // Get information about the number of non-zero coefficients in `expr'.
04298   for (dimension_type i = ub_space_dim; i-- > 0; )
04299     if (ub_expr.coefficient(Variable(i)) != 0) {
04300       if (t++ == 1)
04301         break;
04302       else
04303         w = i+1;
04304     }
04305 
04306   // Now we know the form of `ub_expr':
04307   // - If t == 0, then ub_expr == b, with `b' a constant;
04308   // - If t == 1, then ub_expr == a*w + b, where `w' can be `v' or another
04309   //   variable; in this second case we have to check whether `a' is
04310   //   equal to `denominator' or `-denominator', since otherwise we have
04311   //   to fall back on the general form;
04312   // - If t == 2, the `ub_expr' is of the general form.
04313   PPL_DIRTY_TEMP_COEFFICIENT(minus_den);
04314   neg_assign(minus_den, denominator);
04315 
04316   if (t == 0) {
04317     // Case 1: ub_expr == b.
04318     generalized_affine_image(var,
04319                              GREATER_OR_EQUAL,
04320                              lb_expr,
04321                              denominator);
04322     // Add the constraint `var <= b/denominator'.
04323     add_dbm_constraint(0, v, b, denominator);
04324     PPL_ASSERT(OK());
04325     return;
04326   }
04327 
04328   if (t == 1) {
04329     // Value of the one and only non-zero coefficient in `ub_expr'.
04330     const Coefficient& a = ub_expr.coefficient(Variable(w-1));
04331     if (a == denominator || a == minus_den) {
04332       // Case 2: expr == a*w + b, with a == +/- denominator.
04333       if (w == v) {
04334         // Here `var' occurs in `ub_expr'.
04335         // To ease the computation, we add an additional dimension.
04336         const Variable new_var = Variable(bds_space_dim);
04337         add_space_dimensions_and_embed(1);
04338         // Constrain the new dimension to be equal to `ub_expr'.
04339         affine_image(new_var, ub_expr, denominator);
04340         // NOTE: enforce shortest-path closure for precision.
04341         shortest_path_closure_assign();
04342         PPL_ASSERT(!marked_empty());
04343         // Apply the affine lower bound.
04344         generalized_affine_image(var,
04345                                  GREATER_OR_EQUAL,
04346                                  lb_expr,
04347                                  denominator);
04348         // Now apply the affine upper bound, as recorded in `new_var'.
04349         add_constraint(var <= new_var);
04350         // Remove the temporarily added dimension.
04351         remove_higher_space_dimensions(bds_space_dim);
04352         return;
04353       }
04354       else {
04355         // Here `w != v', so that `expr' is of the form
04356         // +/-denominator * w + b.
04357         // Apply the affine lower bound.
04358         generalized_affine_image(var,
04359                                  GREATER_OR_EQUAL,
04360                                  lb_expr,
04361                                  denominator);
04362         if (a == denominator) {
04363           // Add the new constraint `v - w == b/denominator'.
04364           add_dbm_constraint(w, v, b, denominator);
04365         }
04366         else {
04367           // Here a == -denominator, so that we should be adding
04368           // the constraint `v + w == b/denominator'.
04369           // Approximate it by computing lower and upper bounds for `w'.
04370           const N& dbm_w0 = dbm[w][0];
04371           if (!is_plus_infinity(dbm_w0)) {
04372             // Add the constraint `v <= b/denominator - lower_w'.
04373             PPL_DIRTY_TEMP(N, d);
04374             div_round_up(d, b, denominator);
04375             add_assign_r(dbm[0][v], d, dbm_w0, ROUND_UP);
04376             reset_shortest_path_closed();
04377           }
04378         }
04379         PPL_ASSERT(OK());
04380         return;
04381       }
04382     }
04383   }
04384 
04385   // General case.
04386   // Either t == 2, so that
04387   // ub_expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
04388   // or t == 1, ub_expr == a*w + b, but a <> +/- denominator.
04389   // We will remove all the constraints on `var' and add back
04390   // constraints providing upper and lower bounds for `var'.
04391 
04392   // Compute upper approximations for `ub_expr' into `pos_sum'
04393   // taking into account the sign of `denominator'.
04394   const bool is_sc = (denominator > 0);
04395   PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
04396   neg_assign(minus_b, b);
04397   const Coefficient& sc_b = is_sc ? b : minus_b;
04398   const Coefficient& sc_den = is_sc ? denominator : minus_den;
04399   const Coefficient& minus_sc_den = is_sc ? minus_den : denominator;
04400   // NOTE: here, for optimization purposes, `minus_expr' is only assigned
04401   // when `denominator' is negative. Do not use it unless you are sure
04402   // it has been correctly assigned.
04403   Linear_Expression minus_expr;
04404   if (!is_sc)
04405     minus_expr = -ub_expr;
04406   const Linear_Expression& sc_expr = is_sc ? ub_expr : minus_expr;
04407 
04408   PPL_DIRTY_TEMP(N, pos_sum);
04409   // Index of the variable that are unbounded in `this->dbm'.
04410   PPL_UNINITIALIZED(dimension_type, pos_pinf_index);
04411   // Number of unbounded variables found.
04412   dimension_type pos_pinf_count = 0;
04413 
04414   // Approximate the inhomogeneous term.
04415   assign_r(pos_sum, sc_b, ROUND_UP);
04416 
04417   // Approximate the homogeneous part of `sc_expr'.
04418   const DB_Row<N>& dbm_0 = dbm[0];
04419   // Speculative allocation of temporaries to be used in the following loop.
04420   PPL_DIRTY_TEMP(N, coeff_i);
04421   PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
04422   // Note: indices above `w' can be disregarded, as they all have
04423   // a zero coefficient in `sc_expr'.
04424   for (dimension_type i = w; i > 0; --i) {
04425     const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1));
04426     const int sign_i = sgn(sc_i);
04427     if (sign_i > 0) {
04428       assign_r(coeff_i, sc_i, ROUND_UP);
04429       // Approximating `sc_expr'.
04430       if (pos_pinf_count <= 1) {
04431         const N& up_approx_i = dbm_0[i];
04432         if (!is_plus_infinity(up_approx_i))
04433           add_mul_assign_r(pos_sum, coeff_i, up_approx_i, ROUND_UP);
04434         else {
04435           ++pos_pinf_count;
04436           pos_pinf_index = i;
04437         }
04438       }
04439     }
04440     else if (sign_i < 0) {
04441       neg_assign(minus_sc_i, sc_i);
04442       // Note: using temporary named `coeff_i' to store -coeff_i.
04443       assign_r(coeff_i, minus_sc_i, ROUND_UP);
04444       // Approximating `sc_expr'.
04445       if (pos_pinf_count <= 1) {
04446         const N& up_approx_minus_i = dbm[i][0];
04447         if (!is_plus_infinity(up_approx_minus_i))
04448           add_mul_assign_r(pos_sum, coeff_i, up_approx_minus_i, ROUND_UP);
04449         else {
04450           ++pos_pinf_count;
04451           pos_pinf_index = i;
04452         }
04453       }
04454     }
04455   }
04456   // Apply the affine lower bound.
04457   generalized_affine_image(var,
04458                            GREATER_OR_EQUAL,
04459                            lb_expr,
04460                            denominator);
04461   // Return immediately if no approximation could be computed.
04462   if (pos_pinf_count > 1) {
04463     return;
04464   }
04465 
04466   // In the following, shortest-path closure will be definitely lost.
04467   reset_shortest_path_closed();
04468 
04469   // Exploit the upper approximation, if possible.
04470   if (pos_pinf_count <= 1) {
04471     // Compute quotient (if needed).
04472     if (sc_den != 1) {
04473       // Before computing quotients, the denominator should be approximated
04474       // towards zero. Since `sc_den' is known to be positive, this amounts to
04475       // rounding downwards, which is achieved as usual by rounding upwards
04476       // `minus_sc_den' and negating again the result.
04477       PPL_DIRTY_TEMP(N, down_sc_den);
04478       assign_r(down_sc_den, minus_sc_den, ROUND_UP);
04479       neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
04480       div_assign_r(pos_sum, pos_sum, down_sc_den, ROUND_UP);
04481     }
04482     // Add the upper bound constraint, if meaningful.
04483     if (pos_pinf_count == 0) {
04484       // Add the constraint `v <= pos_sum'.
04485       dbm[0][v] = pos_sum;
04486       // Deduce constraints of the form `v - u', where `u != v'.
04487       deduce_v_minus_u_bounds(v, w, sc_expr, sc_den, pos_sum);
04488     }
04489     else
04490       // Here `pos_pinf_count == 1'.
04491       if (pos_pinf_index != v
04492           && sc_expr.coefficient(Variable(pos_pinf_index-1)) == sc_den)
04493         // Add the constraint `v - pos_pinf_index <= pos_sum'.
04494         dbm[pos_pinf_index][v] = pos_sum;
04495   }
04496   PPL_ASSERT(OK());
04497 }

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() 
) [inline]

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:
var The variable updated by the affine relation;
lb_expr The numerator of the lower bounding affine expression;
ub_expr The numerator of the upper bounding affine expression;
denominator The (common) denominator for the lower and upper bounding affine expressions (optional argument with default value 1).
Exceptions:
std::invalid_argument Thrown if denominator is zero or if lb_expr (resp., ub_expr) and *this are dimension-incompatible or if var is not a space dimension of *this.

Definition at line 4502 of file BD_Shape.templates.hh.

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

04505                                                                          {
04506   // The denominator cannot be zero.
04507   if (denominator == 0)
04508     throw_generic("bounded_affine_preimage(v, lb, ub, d)", "d == 0");
04509 
04510   // Dimension-compatibility checks.
04511   // `var' should be one of the dimensions of the BD_Shape.
04512   const dimension_type space_dim = space_dimension();
04513   const dimension_type v = var.id() + 1;
04514   if (v > space_dim)
04515     throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
04516                                  "v", var);
04517   // The dimension of `lb_expr' and `ub_expr' should not be
04518   // greater than the dimension of `*this'.
04519   const dimension_type lb_space_dim = lb_expr.space_dimension();
04520   if (space_dim < lb_space_dim)
04521     throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)",
04522                                  "lb", lb_expr);
04523   const dimension_type ub_space_dim = ub_expr.space_dimension();
04524   if (space_dim < ub_space_dim)
04525     throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)",
04526                                  "ub", ub_expr);
04527 
04528   // Any preimage of an empty BDS is empty.
04529   shortest_path_closure_assign();
04530   if (marked_empty())
04531     return;
04532 
04533   if (ub_expr.coefficient(var) == 0) {
04534     refine(var, LESS_OR_EQUAL, ub_expr, denominator);
04535     generalized_affine_preimage(var, GREATER_OR_EQUAL,
04536                                 lb_expr, denominator);
04537     return;
04538   }
04539   if (lb_expr.coefficient(var) == 0) {
04540     refine(var, GREATER_OR_EQUAL, lb_expr, denominator);
04541     generalized_affine_preimage(var, LESS_OR_EQUAL,
04542                                 ub_expr, denominator);
04543     return;
04544   }
04545 
04546   const Coefficient& lb_expr_v = lb_expr.coefficient(var);
04547   // Here `var' occurs in `lb_expr' and `ub_expr'.
04548   // To ease the computation, we add an additional dimension.
04549   const Variable new_var = Variable(space_dim);
04550   add_space_dimensions_and_embed(1);
04551   const Linear_Expression lb_inverse
04552     = lb_expr - (lb_expr_v + denominator)*var;
04553   PPL_DIRTY_TEMP_COEFFICIENT(lb_inverse_den);
04554   neg_assign(lb_inverse_den, lb_expr_v);
04555   affine_image(new_var, lb_inverse, lb_inverse_den);
04556   shortest_path_closure_assign();
04557   PPL_ASSERT(!marked_empty());
04558   generalized_affine_preimage(var, LESS_OR_EQUAL,
04559                               ub_expr, denominator);
04560   if (sgn(denominator) == sgn(lb_inverse_den))
04561     add_constraint(var >= new_var);
04562   else
04563     add_constraint(var <= new_var);
04564   // Remove the temporarily added dimension.
04565   remove_higher_space_dimensions(space_dim);
04566 }

template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::bounds ( const Linear_Expression expr,
bool  from_above 
) const [inline, private]

Checks if and how expr is bounded in *this.

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

Parameters:
expr The linear expression to test;
from_above true if and only if the boundedness of interest is "from above".
Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

Definition at line 1126 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::constraints(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::extract_bounded_difference(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::MINIMIZATION, Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::MIP_Problem::solve(), Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::bounds_from_above(), and Parma_Polyhedra_Library::BD_Shape< T >::bounds_from_below().

01127                                                  {
01128   // The dimension of `expr' should not be greater than the dimension
01129   // of `*this'.
01130   const dimension_type expr_space_dim = expr.space_dimension();
01131   const dimension_type space_dim = space_dimension();
01132   if (space_dim < expr_space_dim)
01133     throw_dimension_incompatible((from_above
01134                                   ? "bounds_from_above(e)"
01135                                   : "bounds_from_below(e)"), "e", expr);
01136 
01137   shortest_path_closure_assign();
01138   // A zero-dimensional or empty BDS bounds everything.
01139   if (space_dim == 0 || marked_empty())
01140     return true;
01141 
01142   // The constraint `c' is used to check if `expr' is a difference
01143   // bounded and, in this case, to select the cell.
01144   const Constraint& c = from_above ? expr <= 0 : expr >= 0;
01145   const dimension_type c_space_dim = c.space_dimension();
01146   dimension_type num_vars = 0;
01147   dimension_type i = 0;
01148   dimension_type j = 0;
01149   PPL_DIRTY_TEMP_COEFFICIENT(coeff);
01150   // Check if `c' is a BD constraint.
01151   if (extract_bounded_difference(c, c_space_dim, num_vars, i, j, coeff)) {
01152     if (num_vars == 0)
01153       // Dealing with a trivial constraint.
01154       return true;
01155     // Select the cell to be checked.
01156     const N& x = (coeff < 0) ? dbm[i][j] : dbm[j][i];
01157     return !is_plus_infinity(x);
01158   }
01159   else {
01160     // Not a DB constraint: use the MIP solver.
01161     Optimization_Mode mode_bounds
01162       = from_above ? MAXIMIZATION : MINIMIZATION;
01163     MIP_Problem mip(space_dim, constraints(), expr, mode_bounds);
01164     // Problem is known to be feasible.
01165     return mip.solve() == OPTIMIZED_MIP_PROBLEM;
01166   }
01167 }

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_argument Thrown if expr and *this are dimension-incompatible.

Definition at line 362 of file BD_Shape.inlines.hh.

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

00362                                                                   {
00363   return bounds(expr, true);
00364 }

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_argument Thrown if expr and *this are dimension-incompatible.

Definition at line 368 of file BD_Shape.inlines.hh.

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

00368                                                                   {
00369   return bounds(expr, false);
00370 }

template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::can_recycle_congruence_systems (  )  [inline, static]

Returns false indicating that this domain cannot recycle congruences.

Definition at line 263 of file BD_Shape.inlines.hh.

00263                                             {
00264   return false;
00265 }

template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::can_recycle_constraint_systems (  )  [inline, static]

Returns false indicating that this domain cannot recycle constraints.

Definition at line 256 of file BD_Shape.inlines.hh.

00256                                             {
00257   return false;
00258 }

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 
) [inline]

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

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

Definition at line 2885 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

02887                                                      {
02888   const dimension_type space_dim = space_dimension();
02889 
02890   // Dimension-compatibility check.
02891   if (space_dim != y.space_dimension())
02892     throw_dimension_incompatible("CC76_extrapolation_assign(y)", y);
02893 
02894 #ifndef NDEBUG
02895   {
02896     // We assume that `y' is contained in or equal to `*this'.
02897     const BD_Shape x_copy = *this;
02898     const BD_Shape y_copy = y;
02899     PPL_ASSERT(x_copy.contains(y_copy));
02900   }
02901 #endif
02902 
02903   // If both bounded difference shapes are zero-dimensional,
02904   // since `*this' contains `y', we simply return `*this'.
02905   if (space_dim == 0)
02906     return;
02907 
02908   shortest_path_closure_assign();
02909   // If `*this' is empty, since `*this' contains `y', `y' is empty too.
02910   if (marked_empty())
02911     return;
02912   y.shortest_path_closure_assign();
02913   // If `y' is empty, we return.
02914   if (y.marked_empty())
02915     return;
02916 
02917   // If there are tokens available, work on a temporary copy.
02918   if (tp != 0 && *tp > 0) {
02919     BD_Shape<T> x_tmp(*this);
02920     x_tmp.CC76_extrapolation_assign(y, first, last, 0);
02921     // If the widening was not precise, use one of the available tokens.
02922     if (!contains(x_tmp))
02923       --(*tp);
02924     return;
02925   }
02926 
02927   // Compare each constraint in `y' to the corresponding one in `*this'.
02928   // The constraint in `*this' is kept as is if it is stronger than or
02929   // equal to the constraint in `y'; otherwise, the inhomogeneous term
02930   // of the constraint in `*this' is further compared with elements taken
02931   // from a sorted container (the stop-points, provided by the user), and
02932   // is replaced by the first entry, if any, which is greater than or equal
02933   // to the inhomogeneous term. If no such entry exists, the constraint
02934   // is removed altogether.
02935   for (dimension_type i = space_dim + 1; i-- > 0; ) {
02936     DB_Row<N>& dbm_i = dbm[i];
02937     const DB_Row<N>& y_dbm_i = y.dbm[i];
02938     for (dimension_type j = space_dim + 1; j-- > 0; ) {
02939       N& dbm_ij = dbm_i[j];
02940       const N& y_dbm_ij = y_dbm_i[j];
02941       if (y_dbm_ij < dbm_ij) {
02942         Iterator k = std::lower_bound(first, last, dbm_ij);
02943         if (k != last) {
02944           if (dbm_ij < *k)
02945             assign_r(dbm_ij, *k, ROUND_UP);
02946         }
02947         else
02948           assign_r(dbm_ij, PLUS_INFINITY, ROUND_NOT_NEEDED);
02949       }
02950     }
02951   }
02952   reset_shortest_path_closed();
02953   PPL_ASSERT(OK());
02954 }

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:
y A BDS that must be contained in *this.
tp An optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique).
Exceptions:
std::invalid_argument Thrown if *this and y are dimension-incompatible.

Definition at line 781 of file BD_Shape.inlines.hh.

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

00781                                                                       {
00782   static N stop_points[] = {
00783     N(-2, ROUND_UP),
00784     N(-1, ROUND_UP),
00785     N( 0, ROUND_UP),
00786     N( 1, ROUND_UP),
00787     N( 2, ROUND_UP)
00788   };
00789   CC76_extrapolation_assign(y,
00790                             stop_points,
00791                             stop_points
00792                             + sizeof(stop_points)/sizeof(stop_points[0]),
00793                             tp);
00794 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::CC76_narrowing_assign ( const BD_Shape< T > &  y  )  [inline]

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

Parameters:
y A BDS that must contain *this.
Exceptions:
std::invalid_argument Thrown 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 3191 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

03191                                                     {
03192   const dimension_type space_dim = space_dimension();
03193 
03194   // Dimension-compatibility check.
03195   if (space_dim != y.space_dimension())
03196     throw_dimension_incompatible("CC76_narrowing_assign(y)", y);
03197 
03198 #ifndef NDEBUG
03199   {
03200     // We assume that `*this' is contained in or equal to `y'.
03201     const BD_Shape x_copy = *this;
03202     const BD_Shape y_copy = y;
03203     PPL_ASSERT(y_copy.contains(x_copy));
03204   }
03205 #endif
03206 
03207   // If both bounded difference shapes are zero-dimensional,
03208   // since `y' contains `*this', we simply return `*this'.
03209   if (space_dim == 0)
03210     return;
03211 
03212   y.shortest_path_closure_assign();
03213   // If `y' is empty, since `y' contains `this', `*this' is empty too.
03214   if (y.marked_empty())
03215     return;
03216   shortest_path_closure_assign();
03217   // If `*this' is empty, we return.
03218   if (marked_empty())
03219     return;
03220 
03221   // Replace each constraint in `*this' by the corresponding constraint
03222   // in `y' if the corresponding inhomogeneous terms are both finite.
03223   bool changed = false;
03224   for (dimension_type i = space_dim + 1; i-- > 0; ) {
03225     DB_Row<N>& dbm_i = dbm[i];
03226     const DB_Row<N>& y_dbm_i = y.dbm[i];
03227     for (dimension_type j = space_dim + 1; j-- > 0; ) {
03228       N& dbm_ij = dbm_i[j];
03229       const N& y_dbm_ij = y_dbm_i[j];
03230       if (!is_plus_infinity(dbm_ij)
03231           && !is_plus_infinity(y_dbm_ij)
03232           && dbm_ij != y_dbm_ij) {
03233         dbm_ij = y_dbm_ij;
03234         changed = true;
03235       }
03236     }
03237   }
03238   if (changed && marked_shortest_path_closed())
03239     reset_shortest_path_closed();
03240   PPL_ASSERT(OK());
03241 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::compute_leaders ( std::vector< dimension_type > &  leaders  )  const [inline, private]

Compute the leaders of zero-equivalence classes.

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

Definition at line 935 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::compute_predecessors(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), and Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed().

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

00935                                                                      {
00936   PPL_ASSERT(!marked_empty() && marked_shortest_path_closed());
00937   PPL_ASSERT(leaders.size() == 0);
00938   // Compute predecessor information.
00939   compute_predecessors(leaders);
00940   // Flatten the predecessor chains so as to obtain leaders.
00941   PPL_ASSERT(leaders[0] == 0);
00942   for (dimension_type i = 1, l_size = leaders.size(); i != l_size; ++i) {
00943     const dimension_type l_i = leaders[i];
00944     PPL_ASSERT(l_i <= i);
00945     if (l_i != i) {
00946       const dimension_type ll_i = leaders[l_i];
00947       PPL_ASSERT(ll_i == leaders[ll_i]);
00948       leaders[i] = ll_i;
00949     }
00950   }
00951 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::compute_predecessors ( std::vector< dimension_type > &  predecessor  )  const [inline, private]

Compute the (zero-equivalence classes) predecessor relation.

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

Definition at line 906 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::is_additive_inverse().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::affine_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::compute_leaders(), and Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign().

00906                                                                    {
00907   PPL_ASSERT(!marked_empty() && marked_shortest_path_closed());
00908   PPL_ASSERT(predecessor.size() == 0);
00909   // Variables are ordered according to their index.
00910   // The vector `predecessor' is used to indicate which variable
00911   // immediately precedes a given one in the corresponding equivalence class.
00912   // The `leader' of an equivalence class is the element having minimum
00913   // index: leaders are their own predecessors.
00914   const dimension_type pred_size = dbm.num_rows();
00915   // Initially, each variable is leader of its own zero-equivalence class.
00916   predecessor.reserve(pred_size);
00917   for (dimension_type i = 0; i < pred_size; ++i)
00918     predecessor.push_back(i);
00919   // Now compute actual predecessors.
00920   for (dimension_type i = pred_size; i-- > 1; )
00921     if (i == predecessor[i]) {
00922       const DB_Row<N>& dbm_i = dbm[i];
00923       for (dimension_type j = i; j-- > 0; )
00924         if (j == predecessor[j]
00925             && is_additive_inverse(dbm[j][i], dbm_i[j])) {
00926           // Choose as predecessor the variable having the smaller index.
00927           predecessor[i] = j;
00928           break;
00929         }
00930     }
00931 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::concatenate_assign ( const BD_Shape< T > &  y  )  [inline]

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

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

Definition at line 534 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::DB_Matrix< T >::grow(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

00534                                                  {
00535   BD_Shape& x = *this;
00536 
00537   const dimension_type x_space_dim = x.space_dimension();
00538   const dimension_type y_space_dim = y.space_dimension();
00539 
00540   // If `y' is an empty 0-dim space bounded difference shape,
00541   // let `*this' become empty.
00542   if (y_space_dim == 0 && y.marked_empty()) {
00543     set_empty();
00544     return;
00545   }
00546 
00547   // If `x' is an empty 0-dim space BDS, then it is sufficient to adjust
00548   // the dimension of the vector space.
00549   if (x_space_dim == 0 && marked_empty()) {
00550     dbm.grow(y_space_dim + 1);
00551     PPL_ASSERT(OK());
00552     return;
00553   }
00554   // First we increase the space dimension of `x' by adding
00555   // `y.space_dimension()' new dimensions.
00556   // The matrix for the new system of constraints is obtained
00557   // by leaving the old system of constraints in the upper left-hand side
00558   // and placing the constraints of `y' in the lower right-hand side,
00559   // except the constraints as `y(i) >= cost' or `y(i) <= cost', that are
00560   // placed in the right position on the new matrix.
00561   add_space_dimensions_and_embed(y_space_dim);
00562   const dimension_type new_space_dim = x_space_dim + y_space_dim;
00563   for (dimension_type i = x_space_dim + 1; i <= new_space_dim; ++i) {
00564     DB_Row<N>& dbm_i = dbm[i];
00565     dbm_i[0] = y.dbm[i - x_space_dim][0];
00566     dbm[0][i] = y.dbm[0][i - x_space_dim];
00567     for (dimension_type j = x_space_dim + 1; j <= new_space_dim; ++j)
00568       dbm_i[j] = y.dbm[i - x_space_dim][j - x_space_dim];
00569   }
00570 
00571   if (marked_shortest_path_closed())
00572     reset_shortest_path_closed();
00573   PPL_ASSERT(OK());
00574 }

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 154 of file BD_Shape.inlines.hh.

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

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

00154                                {
00155   return minimized_congruences();
00156 }

template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::constrains ( Variable  var  )  const [inline]

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

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

Definition at line 878 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::DB_Matrix< T >::num_rows(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

00878                                                 {
00879   // `var' should be one of the dimensions of the BD shape.
00880   const dimension_type var_space_dim = var.space_dimension();
00881   if (space_dimension() < var_space_dim)
00882     throw_dimension_incompatible("constrains(v)", "v", var);
00883 
00884   shortest_path_closure_assign();
00885   // A BD shape known to be empty constrains all variables.
00886   // (Note: do not force emptiness check _yet_)
00887   if (marked_empty())
00888     return true;
00889 
00890   // Check whether `var' is syntactically constrained.
00891   const DB_Row<N>& dbm_v = dbm[var_space_dim];
00892   for (dimension_type i = dbm.num_rows(); i-- > 0; ) {
00893     if (!is_plus_infinity(dbm_v[i])
00894         || !is_plus_infinity(dbm[i][var_space_dim]))
00895       return true;
00896   }
00897 
00898   // `var' is not syntactically constrained:
00899   // now force an emptiness check.
00900   return is_empty();
00901 }

template<typename T >
Constraint_System Parma_Polyhedra_Library::BD_Shape< T >::constraints (  )  const [inline]

Returns a system of constraints defining *this.

Definition at line 5393 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::minimized_constraints(), Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::Constraint_System::zero_dim_empty().

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

05393                                {
05394   Constraint_System cs;
05395   const dimension_type space_dim = space_dimension();
05396   if (space_dim == 0) {
05397     if (marked_empty())
05398       cs = Constraint_System::zero_dim_empty();
05399   }
05400   else if (marked_empty())
05401     cs.insert(0*Variable(space_dim-1) <= -1);
05402   else if (marked_shortest_path_reduced())
05403     // Disregard redundant constraints.
05404     cs = minimized_constraints();
05405   else {
05406     // KLUDGE: in the future `cs' will be constructed of the right dimension.
05407     // For the time being, we force the dimension with the following line.
05408     cs.insert(0*Variable(space_dim-1) <= 0);
05409 
05410     PPL_DIRTY_TEMP_COEFFICIENT(a);
05411     PPL_DIRTY_TEMP_COEFFICIENT(b);
05412     // Go through all the unary constraints in `dbm'.
05413     const DB_Row<N>& dbm_0 = dbm[0];
05414     for (dimension_type j = 1; j <= space_dim; ++j) {
05415       const Variable x(j-1);
05416       const N& dbm_0j = dbm_0[j];
05417       const N& dbm_j0 = dbm[j][0];
05418       if (is_additive_inverse(dbm_j0, dbm_0j)) {
05419         // We have a unary equality constraint.
05420         numer_denom(dbm_0j, b, a);
05421         cs.insert(a*x == b);
05422       }
05423       else {
05424         // We have 0, 1 or 2 unary inequality constraints.
05425         if (!is_plus_infinity(dbm_0j)) {
05426           numer_denom(dbm_0j, b, a);
05427           cs.insert(a*x <= b);
05428         }
05429         if (!is_plus_infinity(dbm_j0)) {
05430           numer_denom(dbm_j0, b, a);
05431           cs.insert(-a*x <= b);
05432         }
05433       }
05434     }
05435 
05436     // Go through all the binary constraints in `dbm'.
05437     for (dimension_type i = 1; i <= space_dim; ++i) {
05438       const Variable y(i-1);
05439       const DB_Row<N>& dbm_i = dbm[i];
05440       for (dimension_type j = i + 1; j <= space_dim; ++j) {
05441         const Variable x(j-1);
05442         const N& dbm_ij = dbm_i[j];
05443         const N& dbm_ji = dbm[j][i];
05444         if (is_additive_inverse(dbm_ji, dbm_ij)) {
05445           // We have a binary equality constraint.
05446           numer_denom(dbm_ij, b, a);
05447           cs.insert(a*x - a*y == b);
05448         }
05449         else {
05450           // We have 0, 1 or 2 binary inequality constraints.
05451           if (!is_plus_infinity(dbm_ij)) {
05452             numer_denom(dbm_ij, b, a);
05453             cs.insert(a*x - a*y <= b);
05454           }
05455           if (!is_plus_infinity(dbm_ji)) {
05456             numer_denom(dbm_ji, b, a);
05457             cs.insert(a*y - a*x <= b);
05458           }
05459         }
05460       }
05461     }
05462   }
05463   return cs;
05464 }

template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::contains ( const BD_Shape< T > &  y  )  const [inline]

Returns true if and only if *this contains y.

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

Definition at line 578 of file BD_Shape.templates.hh.

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

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::BD_Shape< T >::difference_assign(), Parma_Polyhedra_Library::BD_Shape< T >::limited_BHMZ05_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::strictly_contains().

00578                                              {
00579   const BD_Shape<T>& x = *this;
00580   const dimension_type x_space_dim = x.space_dimension();
00581 
00582   // Dimension-compatibility check.
00583   if (x_space_dim != y.space_dimension())
00584     throw_dimension_incompatible("contains(y)", y);
00585 
00586   // The zero-dimensional universe shape contains any other
00587   // dimension-compatible shape.
00588   // The zero-dimensional empty shape only contains another
00589   // zero-dimensional empty shape.
00590   if (x_space_dim == 0) {
00591     if (!marked_empty())
00592       return true;
00593     else
00594       return y.marked_empty();
00595   }
00596 
00597   /*
00598     The `y' bounded difference shape need be closed.
00599     In fact if, for example, in `*this' we have the constraints:
00600 
00601     x1 - x2 <= 1;
00602     x1      <= 3;
00603     x2      <= 2;
00604 
00605     in `y' the constraints are:
00606 
00607     x1 - x2 <= 0;
00608     x2      <= 1;
00609 
00610     without closure it returns "false", instead if we close `y' we have
00611     the implicit constraint
00612 
00613     x1      <= 1;
00614 
00615     and so we obtain the right result "true".
00616   */
00617   y.shortest_path_closure_assign();
00618 
00619   // An empty shape is contained in any other dimension-compatible shapes.
00620   if (y.marked_empty())
00621     return true;
00622 
00623   // `*this' contains `y' if and only if every cell of `dbm'
00624   // is greater than or equal to the correspondent one of `y.dbm'.
00625   for (dimension_type i = x_space_dim + 1; i-- > 0; ) {
00626     const DB_Row<N>& x_dbm_i = x.dbm[i];
00627     const DB_Row<N>& y_dbm_i = y.dbm[i];
00628     for (dimension_type j = x_space_dim + 1; j-- > 0; )
00629       if (x_dbm_i[j] < y_dbm_i[j])
00630         return false;
00631   }
00632   return true;
00633 }

template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::contains_integer_point (  )  const [inline]

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

Definition at line 724 of file BD_Shape.templates.hh.

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

00724                                           {
00725   // Force shortest-path closure.
00726   if (is_empty())
00727     return false;
00728 
00729   const dimension_type space_dim = space_dimension();
00730   if (space_dim == 0)
00731     return true;
00732 
00733   // A non-empty BD_Shape defined by integer constraints
00734   // necessarily contains an integer point.
00735   if (std::numeric_limits<T>::is_integer)
00736     return true;
00737 
00738   // Build an integer BD_Shape z with bounds at least as tight as
00739   // those in *this and then recheck for emptiness.
00740   BD_Shape<mpz_class> bds_z(space_dim);
00741   typedef BD_Shape<mpz_class>::N Z;
00742   bds_z.reset_shortest_path_closed();
00743   PPL_DIRTY_TEMP(N, tmp);
00744   bool all_integers = true;
00745   for (dimension_type i = space_dim + 1; i-- > 0; ) {
00746     DB_Row<Z>& z_i = bds_z.dbm[i];
00747     const DB_Row<N>& dbm_i = dbm[i];
00748     for (dimension_type j = space_dim + 1; j-- > 0; ) {
00749       const N& dbm_i_j = dbm_i[j];
00750       if (is_plus_infinity(dbm_i_j))
00751         continue;
00752       if (is_integer(dbm_i_j))
00753         assign_r(z_i[j], dbm_i_j, ROUND_NOT_NEEDED);
00754       else {
00755         all_integers = false;
00756         Z& z_i_j = z_i[j];
00757         // Copy dbm_i_j into z_i_j, but rounding downwards.
00758         neg_assign_r(tmp, dbm_i_j, ROUND_NOT_NEEDED);
00759         assign_r(z_i_j, tmp, ROUND_UP);
00760         neg_assign_r(z_i_j, z_i_j, ROUND_NOT_NEEDED);
00761       }
00762     }
00763   }
00764   return all_integers || !bds_z.is_empty();
00765 }

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_den,
const N minus_lb_v 
) [inline, private]

An helper function for the computation of affine relations.

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

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

  • 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 3307 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), and Parma_Polyhedra_Library::is_plus_infinity().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::BD_Shape< T >::refine().

03311                                                {
03312   PPL_ASSERT(sc_den > 0);
03313   PPL_ASSERT(!is_plus_infinity(minus_lb_v));
03314   // Deduce constraints of the form `u - v', where `u != v'.
03315   // Note: the shortest-path closure is able to deduce the constraint
03316   // `u - v <= ub_u - lb_v'. We can be more precise if variable `u'
03317   // played an active role in the computation of the lower bound for `v',
03318   // i.e., if the corresponding coefficient `q == expr_u/den' is
03319   // greater than zero. In particular:
03320   // if `q >= 1',    then `u - v <= lb_u - lb_v';
03321   // if `0 < q < 1', then `u - v <= (q*lb_u + (1-q)*ub_u) - lb_v'.
03322   PPL_DIRTY_TEMP0(mpq_class, mpq_sc_den);
03323   assign_r(mpq_sc_den, sc_den, ROUND_NOT_NEEDED);
03324   DB_Row<N>& dbm_0 = dbm[0];
03325   DB_Row<N>& dbm_v = dbm[v];
03326   // Speculative allocation of temporaries to be used in the following loop.
03327   PPL_DIRTY_TEMP0(mpq_class, ub_u);
03328   PPL_DIRTY_TEMP0(mpq_class, q);
03329   PPL_DIRTY_TEMP0(mpq_class, minus_lb_u);
03330   PPL_DIRTY_TEMP(N, up_approx);
03331   // No need to consider indices greater than `last_v'.
03332   for (dimension_type u = last_v; u > 0; --u)
03333     if (u != v) {
03334       const Coefficient& expr_u = sc_expr.coefficient(Variable(u-1));
03335       if (expr_u > 0) {
03336         if (expr_u >= sc_den)
03337           // Deducing `u - v <= lb_u - lb_v',
03338           // i.e., `u - v <= (-lb_v) - (-lb_u)'.
03339           sub_assign_r(dbm_v[u], minus_lb_v, dbm[u][0], ROUND_UP);
03340         else {
03341           const N& dbm_0u = dbm_0[u];
03342           if (!is_plus_infinity(dbm_0u)) {
03343             // Let `ub_u' and `lb_u' be the known upper and lower bound
03344             // for `u', respectively. Letting `q = expr_u/sc_den' be the
03345             // rational coefficient of `u' in `sc_expr/sc_den',
03346             // the upper bound for `u - v' is computed as
03347             // `(q * lb_u + (1-q) * ub_u) - lb_v', i.e.,
03348             // `ub_u - q * (ub_u + (-lb_u)) + minus_lb_v'.
03349             assign_r(ub_u, dbm_0u, ROUND_NOT_NEEDED);
03350             assign_r(q, expr_u, ROUND_NOT_NEEDED);
03351             div_assign_r(q, q, mpq_sc_den, ROUND_NOT_NEEDED);
03352             assign_r(minus_lb_u, dbm[u][0], ROUND_NOT_NEEDED);
03353             // Compute `ub_u - lb_u'.
03354             add_assign_r(minus_lb_u, minus_lb_u, ub_u, ROUND_NOT_NEEDED);
03355             // Compute `ub_u - q * (ub_u - lb_u)'.
03356             sub_mul_assign_r(ub_u, q, minus_lb_u, ROUND_NOT_NEEDED);
03357             assign_r(up_approx, ub_u, ROUND_UP);
03358             // Deducing `u - v <= (q*lb_u + (1-q)*ub_u) - lb_v'.
03359             add_assign_r(dbm_v[u], up_approx, minus_lb_v, ROUND_UP);
03360           }
03361         }
03362       }
03363     }
03364 }

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_den,
const N ub_v 
) [inline, private]

An helper function for the computation of affine relations.

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

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

  • 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 3246 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), and Parma_Polyhedra_Library::is_plus_infinity().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::BD_Shape< T >::refine().

03250                                          {
03251   PPL_ASSERT(sc_den > 0);
03252   PPL_ASSERT(!is_plus_infinity(ub_v));
03253   // Deduce constraints of the form `v - u', where `u != v'.
03254   // Note: the shortest-path closure is able to deduce the constraint
03255   // `v - u <= ub_v - lb_u'. We can be more precise if variable `u'
03256   // played an active role in the computation of the upper bound for `v',
03257   // i.e., if the corresponding coefficient `q == expr_u/den' is
03258   // greater than zero. In particular:
03259   // if `q >= 1',    then `v - u <= ub_v - ub_u';
03260   // if `0 < q < 1', then `v - u <= ub_v - (q*ub_u + (1-q)*lb_u)'.
03261   PPL_DIRTY_TEMP0(mpq_class, mpq_sc_den);
03262   assign_r(mpq_sc_den, sc_den, ROUND_NOT_NEEDED);
03263   const DB_Row<N>& dbm_0 = dbm[0];
03264   // Speculative allocation of temporaries to be used in the following loop.
03265   PPL_DIRTY_TEMP0(mpq_class, minus_lb_u);
03266   PPL_DIRTY_TEMP0(mpq_class, q);
03267   PPL_DIRTY_TEMP0(mpq_class, ub_u);
03268   PPL_DIRTY_TEMP(N, up_approx);
03269   // No need to consider indices greater than `last_v'.
03270   for (dimension_type u = last_v; u > 0; --u)
03271     if (u != v) {
03272       const Coefficient& expr_u = sc_expr.coefficient(Variable(u-1));
03273       if (expr_u > 0) {
03274         if (expr_u >= sc_den)
03275           // Deducing `v - u <= ub_v - ub_u'.
03276           sub_assign_r(dbm[u][v], ub_v, dbm_0[u], ROUND_UP);
03277         else {
03278           DB_Row<N>& dbm_u = dbm[u];
03279           const N& dbm_u0 = dbm_u[0];
03280           if (!is_plus_infinity(dbm_u0)) {
03281             // Let `ub_u' and `lb_u' be the known upper and lower bound
03282             // for `u', respectively. Letting `q = expr_u/sc_den' be the
03283             // rational coefficient of `u' in `sc_expr/sc_den',
03284             // the upper bound for `v - u' is computed as
03285             // `ub_v - (q * ub_u + (1-q) * lb_u)', i.e.,
03286             // `ub_v + (-lb_u) - q * (ub_u + (-lb_u))'.
03287             assign_r(minus_lb_u, dbm_u0, ROUND_NOT_NEEDED);
03288             assign_r(q, expr_u, ROUND_NOT_NEEDED);
03289             div_assign_r(q, q, mpq_sc_den, ROUND_NOT_NEEDED);
03290             assign_r(ub_u, dbm_0[u], ROUND_NOT_NEEDED);
03291             // Compute `ub_u - lb_u'.
03292             add_assign_r(ub_u, ub_u, minus_lb_u, ROUND_NOT_NEEDED);
03293             // Compute `(-lb_u) - q * (ub_u - lb_u)'.
03294             sub_mul_assign_r(minus_lb_u, q, ub_u, ROUND_NOT_NEEDED);
03295             assign_r(up_approx, minus_lb_u, ROUND_UP);
03296             // Deducing `v - u <= ub_v - (q * ub_u + (1-q) * lb_u)'.
03297             add_assign_r(dbm_u[v], ub_v, up_approx, ROUND_UP);
03298           }
03299         }
03300       }
03301     }
03302 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::difference_assign ( const BD_Shape< T > &  y  )  [inline]

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

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

Definition at line 2317 of file BD_Shape.templates.hh.

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

02317                                                 {
02318   const dimension_type space_dim = space_dimension();
02319 
02320   // Dimension-compatibility check.
02321   if (space_dim != y.space_dimension())
02322     throw_dimension_incompatible("difference_assign(y)", y);
02323 
02324   BD_Shape new_bd_shape(space_dim, EMPTY);
02325 
02326   BD_Shape& x = *this;
02327 
02328   x.shortest_path_closure_assign();
02329   // The difference of an empty bounded difference shape
02330   // and of a bounded difference shape `p' is empty.
02331   if (x.marked_empty())
02332     return;
02333   y.shortest_path_closure_assign();
02334   // The difference of a bounded difference shape `p'
02335   // and an empty bounded difference shape is `p'.
02336   if (y.marked_empty())
02337     return;
02338 
02339   // If both bounded difference shapes are zero-dimensional,
02340   // then at this point they are necessarily universe system of
02341   // bounded differences, so that their difference is empty.
02342   if (space_dim == 0) {
02343     x.set_empty();
02344     return;
02345   }
02346 
02347   // TODO: This is just an executable specification.
02348   //       Have to find a more efficient method.
02349   if (y.contains(x)) {
02350     x.set_empty();
02351     return;
02352   }
02353 
02354   // We take a constraint of the system y at the time and we
02355   // consider its complementary. Then we intersect the union
02356   // of these complementaries with the system x.
02357   const Constraint_System& y_cs = y.constraints();
02358   for (Constraint_System::const_iterator i = y_cs.begin(),
02359          y_cs_end = y_cs.end(); i != y_cs_end; ++i) {
02360     const Constraint& c = *i;
02361     // If the bounded difference shape `x' is included
02362     // in the bounded difference shape defined by `c',
02363     // then `c' _must_ be skipped, as adding its complement to `x'
02364     // would result in the empty bounded difference shape,
02365     // and as we would obtain a result that is less precise
02366     // than the bds-difference.
02367     if (x.relation_with(c).implies(Poly_Con_Relation::is_included()))
02368       continue;
02369     BD_Shape z = x;
02370     const Linear_Expression e = Linear_Expression(c);
02371     z.add_constraint(e <= 0);
02372     if (!z.is_empty())
02373       new_bd_shape.upper_bound_assign(z);
02374     if (c.is_equality()) {
02375       z = x;
02376       z.add_constraint(e >= 0);
02377       if (!z.is_empty())
02378         new_bd_shape.upper_bound_assign(z);
02379     }
02380   }
02381   *this = new_bd_shape;
02382   PPL_ASSERT(OK());
02383 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points ( const Variables_Set vars,
Complexity_Class  complexity = ANY_COMPLEXITY 
) [inline]

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

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

Definition at line 5659 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points_helper(), Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::Variables_Set::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

05660                                                             {
05661   // Dimension-compatibility check.
05662   const dimension_type space_dim = space_dimension();
05663   const dimension_type min_space_dim = vars.space_dimension();
05664   if (space_dim < min_space_dim)
05665     throw_dimension_incompatible("drop_some_non_integer_points(vs, cmpl)",
05666                                  min_space_dim);
05667 
05668   if (std::numeric_limits<T>::is_integer || min_space_dim == 0)
05669     return;
05670 
05671   shortest_path_closure_assign();
05672   if (marked_empty())
05673     return;
05674 
05675   const Variables_Set::const_iterator v_begin = vars.begin();
05676   const Variables_Set::const_iterator v_end = vars.end();
05677   PPL_ASSERT(v_begin != v_end);
05678   // Unary constraints on a variable occurring in `vars'.
05679   DB_Row<N>& dbm_0 = dbm[0];
05680   for (Variables_Set::const_iterator v_i = v_begin; v_i != v_end; ++v_i) {
05681     const dimension_type i = *v_i + 1;
05682     drop_some_non_integer_points_helper(dbm_0[i]);
05683     drop_some_non_integer_points_helper(dbm[i][0]);
05684   }
05685 
05686   // Binary constraints where both variables occur in `vars'.
05687   for (Variables_Set::const_iterator v_i = v_begin; v_i != v_end; ++v_i) {
05688     const dimension_type i = *v_i + 1;
05689     DB_Row<N>& dbm_i = dbm[i];
05690     for (Variables_Set::const_iterator v_j = v_begin; v_j != v_end; ++v_j) {
05691       const dimension_type j = *v_j + 1;
05692       if (i != j)
05693         drop_some_non_integer_points_helper(dbm_i[j]);
05694     }
05695   }
05696   PPL_ASSERT(OK());
05697 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points ( Complexity_Class  complexity = ANY_COMPLEXITY  )  [inline]

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

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

Definition at line 5639 of file BD_Shape.templates.hh.

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

05639                                                           {
05640   if (std::numeric_limits<T>::is_integer)
05641     return;
05642 
05643   const dimension_type space_dim = space_dimension();
05644   shortest_path_closure_assign();
05645   if (space_dim == 0 || marked_empty())
05646     return;
05647 
05648   for (dimension_type i = space_dim + 1; i-- > 0; ) {
05649     DB_Row<N>& dbm_i = dbm[i];
05650     for (dimension_type j = space_dim + 1; j-- > 0; )
05651       if (i != j)
05652         drop_some_non_integer_points_helper(dbm_i[j]);
05653   }
05654   PPL_ASSERT(OK());
05655 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points_helper ( N elem  )  [inline, private]

Definition at line 842 of file BD_Shape.inlines.hh.

References Parma_Polyhedra_Library::is_integer(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), and Parma_Polyhedra_Library::Checked::Result.

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

00842                                                         {
00843   if (!is_integer(elem)) {
00844     Result r = floor_assign_r(elem, elem, ROUND_DOWN);
00845     used(r);
00846     PPL_ASSERT(r == V_EQ);
00847     reset_shortest_path_closed();
00848   }
00849 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::expand_space_dimension ( Variable  var,
dimension_type  m 
) [inline]

Creates m copies of the space dimension corresponding to var.

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

If *this has space dimension $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 5551 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::max_space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().

05551                                                                   {
05552   dimension_type old_dim = space_dimension();
05553   // `var' should be one of the dimensions of the vector space.
05554   if (var.space_dimension() > old_dim)
05555     throw_dimension_incompatible("expand_space_dimension(v, m)", "v", var);
05556 
05557   // The space dimension of the resulting BDS should not
05558   // overflow the maximum allowed space dimension.
05559   if (m > max_space_dimension() - space_dimension())
05560     throw_generic("expand_dimension(v, m)",
05561                   "adding m new space dimensions exceeds "
05562                   "the maximum allowed space dimension");
05563 
05564   // Nothing to do, if no dimensions must be added.
05565   if (m == 0)
05566     return;
05567 
05568   // Add the required new dimensions.
05569   add_space_dimensions_and_embed(m);
05570 
05571   // For each constraints involving variable `var', we add a
05572   // similar constraint with the new variable substituted for
05573   // variable `var'.
05574   const dimension_type v_id = var.id() + 1;
05575   const DB_Row<N>& dbm_v = dbm[v_id];
05576   for (dimension_type i = old_dim + 1; i-- > 0; ) {
05577     DB_Row<N>& dbm_i = dbm[i];
05578     const N& dbm_i_v = dbm[i][v_id];
05579     const N& dbm_v_i = dbm_v[i];
05580     for (dimension_type j = old_dim+1; j < old_dim+m+1; ++j) {
05581       dbm_i[j] = dbm_i_v;
05582       dbm[j][i] = dbm_v_i;
05583     }
05584   }
05585   // In general, adding a constraint does not preserve the shortest-path
05586   // closure or reduction of the bounded difference shape.
05587   if (marked_shortest_path_closed())
05588     reset_shortest_path_closed();
05589   PPL_ASSERT(OK());
05590 }

template<typename T >
memory_size_type Parma_Polyhedra_Library::BD_Shape< T >::external_memory_in_bytes (  )  const [inline]

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

Definition at line 5835 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::Bit_Matrix::external_memory_in_bytes(), Parma_Polyhedra_Library::DB_Matrix< T >::external_memory_in_bytes(), and Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm.

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

05835                                             {
05836   return dbm.external_memory_in_bytes()
05837     + redundancy_dbm.external_memory_in_bytes();
05838 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::fold_space_dimensions ( const Variables_Set vars,
Variable  dest 
) [inline]

Folds the space dimensions in vars into dest.

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

If *this has space dimension $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 5594 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::max_assign(), Parma_Polyhedra_Library::BD_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::Variables_Set::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().

05595                                                   {
05596   const dimension_type space_dim = space_dimension();
05597   // `dest' should be one of the dimensions of the BDS.
05598   if (dest.space_dimension() > space_dim)
05599     throw_dimension_incompatible("fold_space_dimensions(vs, v)",
05600                                  "v", dest);
05601 
05602   // The folding of no dimensions is a no-op.
05603   if (vars.empty())
05604     return;
05605 
05606   // All variables in `vars' should be dimensions of the BDS.
05607   if (vars.space_dimension() > space_dim)
05608     throw_dimension_incompatible("fold_space_dimensions(vs, v)",
05609                                  vars.space_dimension());
05610 
05611   // Moreover, `dest.id()' should not occur in `vars'.
05612   if (vars.find(dest.id()) != vars.end())
05613     throw_generic("fold_space_dimensions(vs, v)",
05614                   "v should not occur in vs");
05615 
05616   shortest_path_closure_assign();
05617   if (!marked_empty()) {
05618     // Recompute the elements of the row and the column corresponding
05619     // to variable `dest' by taking the join of their value with the
05620     // value of the corresponding elements in the row and column of the
05621     // variable `vars'.
05622     const dimension_type v_id = dest.id() + 1;
05623     DB_Row<N>& dbm_v = dbm[v_id];
05624     for (Variables_Set::const_iterator i = vars.begin(),
05625            vs_end = vars.end(); i != vs_end; ++i) {
05626       const dimension_type tbf_id = *i + 1;
05627       const DB_Row<N>& dbm_tbf = dbm[tbf_id];
05628       for (dimension_type j = space_dim + 1; j-- > 0; ) {
05629         max_assign(dbm[j][v_id], dbm[j][tbf_id]);
05630         max_assign(dbm_v[j], dbm_tbf[j]);
05631       }
05632     }
05633   }
05634   remove_space_dimensions(vars);
05635 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::forget_all_dbm_constraints ( dimension_type  v  )  [inline, private]
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::forget_binary_dbm_constraints ( dimension_type  v  )  [inline, private]

Removes all binary constraints on row/column v.

Definition at line 3379 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::DB_Matrix< T >::num_rows(), and Parma_Polyhedra_Library::PLUS_INFINITY.

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), and Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image().

03379                                                                  {
03380   PPL_ASSERT(0 < v && v <= dbm.num_rows());
03381   DB_Row<N>& dbm_v = dbm[v];
03382   for (dimension_type i = dbm.num_rows()-1; i > 0; --i) {
03383     assign_r(dbm_v[i], PLUS_INFINITY, ROUND_NOT_NEEDED);
03384     assign_r(dbm[i][v], PLUS_INFINITY, ROUND_NOT_NEEDED);
03385   }
03386 }

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 [inline]

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

Parameters:
expr The linear expression for which the frequency is needed;
freq_n If 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_d If true is returned, the value is set to $1$;
val_n The numerator of val;
val_d The denominator of val;
Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

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

Definition at line 769 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::Checked::le, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::normalize2(), Parma_Polyhedra_Library::DB_Matrix< T >::num_rows(), Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

00771                                                                      {
00772   dimension_type space_dim = space_dimension();
00773   // The dimension of `expr' must be at most the dimension of *this.
00774   if (space_dim < expr.space_dimension())
00775     throw_dimension_incompatible("frequency(e, ...)", "e", expr);
00776 
00777   // Check if `expr' has a constant value.
00778   // If it is constant, set the frequency `freq_n' to 0
00779   // and return true. Otherwise the values for \p expr
00780   // are not discrete so return false.
00781 
00782   // Space dimension = 0: if empty, then return false;
00783   // otherwise the frequency is 0 and the value is the inhomogeneous term.
00784   if (space_dim == 0) {
00785     if (is_empty())
00786       return false;
00787     freq_n = 0;
00788     freq_d = 1;
00789     val_n = expr.inhomogeneous_term();
00790     val_d = 1;
00791     return true;
00792   }
00793 
00794   shortest_path_closure_assign();
00795   // For an empty BD shape, we simply return false.
00796   if (marked_empty())
00797     return false;
00798 
00799   // The BD shape has at least 1 dimension and is not empty.
00800   PPL_DIRTY_TEMP_COEFFICIENT(coeff);
00801   PPL_DIRTY_TEMP_COEFFICIENT(num);
00802   PPL_DIRTY_TEMP_COEFFICIENT(den);
00803   PPL_DIRTY_TEMP(N, tmp);
00804   Linear_Expression le = expr;
00805   // Boolean to keep track of a variable `v' in expression `le'.
00806   // If we can replace `v' by an expression using variables other
00807   // than `v' and are already in `le', then this is set to true.
00808   bool constant_v = false;
00809 
00810   PPL_DIRTY_TEMP_COEFFICIENT(val_den);
00811   val_den = 1;
00812 
00813   for (dimension_type i = dbm.num_rows(); i-- > 1; ) {
00814     constant_v = false;
00815     const Variable v(i-1);
00816     coeff = le.coefficient(v);
00817     if (coeff == 0) {
00818       constant_v = true;
00819       continue;
00820     }
00821 
00822     const DB_Row<N>& dbm_i = dbm[i];
00823     // Check if `v' is constant in the BD shape.
00824     assign_r(tmp, dbm_i[0], ROUND_NOT_NEEDED);
00825     if (is_additive_inverse(dbm[0][i], tmp)) {
00826       // If `v' is constant, replace it in `le' by the value.
00827       numer_denom(tmp, num, den);
00828       le -= coeff*v;
00829       le *= den;
00830       le -= num*coeff;
00831       val_den *= den;
00832       constant_v = true;
00833       continue;
00834     }
00835     // Check the bounded differences with the other dimensions that
00836     // have non-zero coefficient in `le'.
00837     else {
00838       PPL_ASSERT(!constant_v);
00839       for (dimension_type j = i; j-- > 1; ) {
00840         const Variable vj(j-1);
00841         if (le.coefficient(vj) == 0)
00842           // The coefficient in `le' is 0, so do nothing.
00843           continue;
00844         assign_r(tmp, dbm_i[j], ROUND_NOT_NEEDED);
00845         if (is_additive_inverse(dbm[j][i], tmp)) {
00846           // The coefficient for `vj' in `le' is not 0
00847           // and the difference with `v' in the BD shape is constant.
00848           // So apply this equality to eliminate `v' in `le'.
00849           numer_denom(tmp, num, den);
00850           le -= coeff*v - coeff*vj;
00851           le *= den;
00852           le -= num*coeff;
00853           val_den *= den;
00854           constant_v = true;
00855           break;
00856         }
00857       }
00858       if (!constant_v)
00859         // The expression `expr' is not constant.
00860         return false;
00861     }
00862   }
00863   if (!constant_v)
00864     // The expression `expr' is not constant.
00865     return false;
00866 
00867   // The expression `expr' is constant.
00868   freq_n = 0;
00869   freq_d = 1;
00870 
00871   // Reduce `val_n' and `val_d'.
00872   normalize2(le.inhomogeneous_term(), val_den, val_n, val_d);
00873   return true;
00874 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image ( const Linear_Expression lhs,
Relation_Symbol  relsym,
const Linear_Expression rhs 
) [inline]

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

Parameters:
lhs The left hand side affine expression.
relsym The relation symbol.
rhs The right hand side affine expression.
Exceptions:
std::invalid_argument Thrown if *this is dimension-incompatible with lhs or rhs or if relsym is a strict relation symbol.

Definition at line 4967 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::BD_Shape< T >::forget_all_dbm_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::NOT_EQUAL, Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().

04969                                                                     {
04970   // Dimension-compatibility checks.
04971   // The dimension of `lhs' should not be greater than the dimension
04972   // of `*this'.
04973   const dimension_type space_dim = space_dimension();
04974   const dimension_type lhs_space_dim = lhs.space_dimension();
04975   if (space_dim < lhs_space_dim)
04976     throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
04977                                  "e1", lhs);
04978 
04979   // The dimension of `rhs' should not be greater than the dimension
04980   // of `*this'.
04981   const dimension_type rhs_space_dim = rhs.space_dimension();
04982   if (space_dim < rhs_space_dim)
04983     throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
04984                                  "e2", rhs);
04985 
04986   // Strict relation symbols are not admitted for BDSs.
04987   if (relsym == LESS_THAN || relsym == GREATER_THAN)
04988     throw_generic("generalized_affine_image(e1, r, e2)",
04989                   "r is a strict relation symbol and "
04990                   "*this is a BD_Shape");
04991   // The relation symbol cannot be a disequality.
04992   if (relsym == NOT_EQUAL)
04993     throw_generic("generalized_affine_image(e1, r, e2)",
04994                   "r is the disequality relation symbol and "
04995                   "*this is a BD_Shape");
04996 
04997   // The image of an empty BDS is empty.
04998   shortest_path_closure_assign();
04999   if (marked_empty())
05000     return;
05001 
05002   // Number of non-zero coefficients in `lhs': will be set to
05003   // 0, 1, or 2, the latter value meaning any value greater than 1.
05004   dimension_type t_lhs = 0;
05005   // Index of the last non-zero coefficient in `lhs', if any.
05006   dimension_type j_lhs = 0;
05007   // Compute the number of the non-zero components of `lhs'.
05008   for (dimension_type i = lhs_space_dim; i-- > 0; )
05009     if (lhs.coefficient(Variable(i)) != 0) {
05010       if (t_lhs++ == 1)
05011         break;
05012       else
05013         j_lhs = i;
05014     }
05015 
05016   const Coefficient& b_lhs = lhs.inhomogeneous_term();
05017 
05018   if (t_lhs == 0) {
05019     // `lhs' is a constant.
05020     // In principle, it is sufficient to add the constraint `lhs relsym rhs'.
05021     // Note that this constraint is a bounded difference if `t_rhs <= 1'
05022     // or `t_rhs > 1' and `rhs == a*v - a*w + b_rhs'. If `rhs' is of a
05023     // more general form, it will be simply ignored.
05024     // TODO: if it is not a bounded difference, should we compute
05025     // approximations for this constraint?
05026     switch (relsym) {
05027     case LESS_OR_EQUAL:
05028       refine_no_check(lhs <= rhs);
05029       break;
05030     case EQUAL:
05031       refine_no_check(lhs == rhs);
05032       break;
05033     case GREATER_OR_EQUAL:
05034       refine_no_check(lhs >= rhs);
05035       break;
05036     default:
05037       // We already dealt with the other cases.
05038       throw std::runtime_error("PPL internal error");
05039     }
05040   }
05041   else if (t_lhs == 1) {
05042     // Here `lhs == a_lhs * v + b_lhs'.
05043     // Independently from the form of `rhs', we can exploit the
05044     // method computing generalized affine images for a single variable.
05045     Variable v(j_lhs);
05046     // Compute a sign-corrected relation symbol.
05047     const Coefficient& den = lhs.coefficient(v);
05048     Relation_Symbol new_relsym = relsym;
05049     if (den < 0) {
05050       if (relsym == LESS_OR_EQUAL)
05051         new_relsym = GREATER_OR_EQUAL;
05052       else if (relsym == GREATER_OR_EQUAL)
05053         new_relsym = LESS_OR_EQUAL;
05054     }
05055     Linear_Expression expr = rhs - b_lhs;
05056     generalized_affine_image(v, new_relsym, expr, den);
05057   }
05058   else {
05059     // Here `lhs' is of the general form, having at least two variables.
05060     // Compute the set of variables occurring in `lhs'.
05061     bool lhs_vars_intersects_rhs_vars = false;
05062     std::vector<Variable> lhs_vars;
05063     for (dimension_type i = lhs_space_dim; i-- > 0; )
05064       if (lhs.coefficient(Variable(i)) != 0) {
05065         lhs_vars.push_back(Variable(i));
05066         if (rhs.coefficient(Variable(i)) != 0)
05067           lhs_vars_intersects_rhs_vars = true;
05068       }
05069 
05070     if (!lhs_vars_intersects_rhs_vars) {
05071       // `lhs' and `rhs' variables are disjoint.
05072       // Existentially quantify all variables in the lhs.
05073       for (dimension_type i = lhs_vars.size(); i-- > 0; )
05074         forget_all_dbm_constraints(lhs_vars[i].id() + 1);
05075       // Constrain the left hand side expression so that it is related to
05076       // the right hand side expression as dictated by `relsym'.
05077       // TODO: if the following constraint is NOT a bounded difference,
05078       // it will be simply ignored. Should we compute approximations for it?
05079       switch (relsym) {
05080       case LESS_OR_EQUAL:
05081         refine_no_check(lhs <= rhs);
05082         break;
05083       case EQUAL:
05084         refine_no_check(lhs == rhs);
05085         break;
05086       case GREATER_OR_EQUAL:
05087         refine_no_check(lhs >= rhs);
05088         break;
05089       default:
05090         // We already dealt with the other cases.
05091         throw std::runtime_error("PPL internal error");
05092       }
05093     }
05094     else {
05095       // Some variables in `lhs' also occur in `rhs'.
05096 
05097 #if 1 // Simplified computation (see the TODO note below).
05098 
05099       for (dimension_type i = lhs_vars.size(); i-- > 0; )
05100         forget_all_dbm_constraints(lhs_vars[i].id() + 1);
05101 
05102 #else // Currently unnecessarily complex computation.
05103 
05104       // More accurate computation that is worth doing only if
05105       // the following TODO note is accurately dealt with.
05106 
05107       // To ease the computation, we add an additional dimension.
05108       const Variable new_var = Variable(space_dim);
05109       add_space_dimensions_and_embed(1);
05110       // Constrain the new dimension to be equal to `rhs'.
05111       // NOTE: calling affine_image() instead of refine_no_check()
05112       // ensures some approximation is tried even when the constraint
05113       // is not a bounded difference.
05114       affine_image(new_var, rhs);
05115       // Existentially quantify all variables in the lhs.
05116       // NOTE: enforce shortest-path closure for precision.
05117       shortest_path_closure_assign();
05118       PPL_ASSERT(!marked_empty());
05119       for (dimension_type i = lhs_vars.size(); i-- > 0; )
05120         forget_all_dbm_constraints(lhs_vars[i].id() + 1);
05121       // Constrain the new dimension so that it is related to
05122       // the left hand side as dictated by `relsym'.
05123       // TODO: each one of the following constraints is definitely NOT
05124       // a bounded differences (since it has 3 variables at least).
05125       // Thus, the method refine_no_check() will simply ignore it.
05126       // Should we compute approximations for this constraint?
05127       switch (relsym) {
05128       case LESS_OR_EQUAL:
05129         refine_no_check(lhs <= new_var);
05130         break;
05131       case EQUAL:
05132         refine_no_check(lhs == new_var);
05133         break;
05134       case GREATER_OR_EQUAL:
05135         refine_no_check(lhs >= new_var);
05136         break;
05137       default:
05138         // We already dealt with the other cases.
05139         throw std::runtime_error("PPL internal error");
05140       }
05141       // Remove the temporarily added dimension.
05142       remove_higher_space_dimensions(space_dim-1);
05143 #endif // Currently unnecessarily complex computation.
05144     }
05145   }
05146 
05147   PPL_ASSERT(OK());
05148 }

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() 
) [inline]

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:
var The left hand side variable of the generalized affine transfer function.
relsym The relation symbol.
expr The numerator of the right hand side affine expression.
denominator The denominator of the right hand side affine expression.
Exceptions:
std::invalid_argument Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a dimension of *this or if relsym is a strict relation symbol.

Definition at line 4570 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::add_dbm_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::deduce_u_minus_v_bounds(), Parma_Polyhedra_Library::BD_Shape< T >::deduce_v_minus_u_bounds(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::BD_Shape< T >::forget_all_dbm_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::forget_binary_dbm_constraints(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::NOT_EQUAL, Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::PLUS_INFINITY, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage().

04574                                                    {
04575   // The denominator cannot be zero.
04576   if (denominator == 0)
04577     throw_generic("generalized_affine_image(v, r, e, d)", "d == 0");
04578 
04579   // Dimension-compatibility checks.
04580   // The dimension of `expr' should not be greater than the dimension
04581   // of `*this'.
04582   const dimension_type space_dim = space_dimension();
04583   const dimension_type expr_space_dim = expr.space_dimension();
04584   if (space_dim < expr_space_dim)
04585     throw_dimension_incompatible("generalized_affine_image(v, r, e, d)",
04586                                  "e", expr);
04587 
04588   // `var' should be one of the dimensions of the BDS.
04589   const dimension_type v = var.id() + 1;
04590   if (v > space_dim)
04591     throw_dimension_incompatible("generalized_affine_image(v, r, e, d)",
04592                                  var.id());
04593 
04594   // The relation symbol cannot be a strict relation symbol.
04595   if (relsym == LESS_THAN || relsym == GREATER_THAN)
04596     throw_generic("generalized_affine_image(v, r, e, d)",
04597                   "r is a strict relation symbol and "
04598                   "*this is a BD_Shape");
04599   // The relation symbol cannot be a disequality.
04600   if (relsym == NOT_EQUAL)
04601     throw_generic("generalized_affine_image(v, r, e, d)",
04602                   "r is the disequality relation symbol and "
04603                   "*this is a BD_Shape");
04604 
04605   if (relsym == EQUAL) {
04606     // The relation symbol is "=":
04607     // this is just an affine image computation.
04608     affine_image(var, expr, denominator);
04609     return;
04610   }
04611 
04612   // The image of an empty BDS is empty too.
04613   shortest_path_closure_assign();
04614   if (marked_empty())
04615     return;
04616 
04617   const Coefficient& b = expr.inhomogeneous_term();
04618   // Number of non-zero coefficients in `expr': will be set to
04619   // 0, 1, or 2, the latter value meaning any value greater than 1.
04620   dimension_type t = 0;
04621   // Index of the last non-zero coefficient in `expr', if any.
04622   dimension_type w = 0;
04623   // Get information about the number of non-zero coefficients in `expr'.
04624   for (dimension_type i = expr_space_dim; i-- > 0; )
04625     if (expr.coefficient(Variable(i)) != 0) {
04626       if (t++ == 1)
04627         break;
04628       else
04629         w = i+1;
04630     }
04631 
04632   // Now we know the form of `expr':
04633   // - If t == 0, then expr == b, with `b' a constant;
04634   // - If t == 1, then expr == a*w + b, where `w' can be `v' or another
04635   //   variable; in this second case we have to check whether `a' is
04636   //   equal to `denominator' or `-denominator', since otherwise we have
04637   //   to fall back on the general form;
04638   // - If t == 2, the `expr' is of the general form.
04639   DB_Row<N>& dbm_0 = dbm[0];
04640   DB_Row<N>& dbm_v = dbm[v];
04641   PPL_DIRTY_TEMP_COEFFICIENT(minus_den);
04642   neg_assign(minus_den, denominator);
04643 
04644   if (t == 0) {
04645     // Case 1: expr == b.
04646     // Remove all constraints on `var'.
04647     forget_all_dbm_constraints(v);
04648     // Both shortest-path closure and reduction are lost.
04649     reset_shortest_path_closed();
04650     switch (relsym) {
04651     case LESS_OR_EQUAL:
04652       // Add the constraint `var <= b/denominator'.
04653       add_dbm_constraint(0, v, b, denominator);
04654       break;
04655     case GREATER_OR_EQUAL:
04656       // Add the constraint `var >= b/denominator',
04657       // i.e., `-var <= -b/denominator',
04658       add_dbm_constraint(v, 0, b, minus_den);
04659       break;
04660     default:
04661       // We already dealt with the other cases.
04662       throw std::runtime_error("PPL internal error");
04663     }
04664     PPL_ASSERT(OK());
04665     return;
04666   }
04667 
04668   if (t == 1) {
04669     // Value of the one and only non-zero coefficient in `expr'.
04670     const Coefficient& a = expr.coefficient(Variable(w-1));
04671     if (a == denominator || a == minus_den) {
04672       // Case 2: expr == a*w + b, with a == +/- denominator.
04673       PPL_DIRTY_TEMP(N, d);
04674       switch (relsym) {
04675       case LESS_OR_EQUAL:
04676         div_round_up(d, b, denominator);
04677         if (w == v) {
04678           // `expr' is of the form: a*v + b.
04679           // Shortest-path closure and reduction are not preserved.
04680           reset_shortest_path_closed();
04681           if (a == denominator) {
04682             // Translate each constraint `v - w <= dbm_wv'
04683             // into the constraint `v - w <= dbm_wv + b/denominator';
04684             // forget each constraint `w - v <= dbm_vw'.
04685             for (dimension_type i = space_dim + 1; i-- > 0; ) {
04686               N& dbm_iv = dbm[i][v];
04687               add_assign_r(dbm_iv, dbm_iv, d, ROUND_UP);
04688               assign_r(dbm_v[i], PLUS_INFINITY, ROUND_NOT_NEEDED);
04689             }
04690           }
04691           else {
04692             // Here `a == -denominator'.
04693             // Translate the constraint `0 - v <= dbm_v0'
04694             // into the constraint `0 - v <= dbm_v0 + b/denominator'.
04695             N& dbm_v0 = dbm_v[0];
04696             add_assign_r(dbm_0[v], dbm_v0, d, ROUND_UP);
04697             // Forget all the other constraints on `v'.
04698             assign_r(dbm_v0, PLUS_INFINITY, ROUND_NOT_NEEDED);
04699             forget_binary_dbm_constraints(v);
04700           }
04701         }
04702         else {
04703           // Here `w != v', so that `expr' is of the form
04704           // +/-denominator * w + b, with `w != v'.
04705           // Remove all constraints on `v'.
04706           forget_all_dbm_constraints(v);
04707           // Shortest-path closure is preserved, but not reduction.
04708           if (marked_shortest_path_reduced())
04709             reset_shortest_path_reduced();
04710           if (a == denominator)
04711             // Add the new constraint `v - w <= b/denominator'.
04712             add_dbm_constraint(w, v, d);
04713           else {
04714             // Here a == -denominator, so that we should be adding
04715             // the constraint `v <= b/denominator - w'.
04716             // Approximate it by computing a lower bound for `w'.
04717             const N& dbm_w0 = dbm[w][0];
04718             if (!is_plus_infinity(dbm_w0)) {
04719               // Add the constraint `v <= b/denominator - lb_w'.
04720               add_assign_r(dbm_0[v], d, dbm_w0, ROUND_UP);
04721               // Shortest-path closure is not preserved.
04722               reset_shortest_path_closed();
04723             }
04724           }
04725         }
04726         break;
04727 
04728       case GREATER_OR_EQUAL:
04729         div_round_up(d, b, minus_den);
04730         if (w == v) {
04731           // `expr' is of the form: a*w + b.
04732           // Shortest-path closure and reduction are not preserved.
04733           reset_shortest_path_closed();
04734           if (a == denominator) {
04735             // Translate each constraint `w - v <= dbm_vw'
04736             // into the constraint `w - v <= dbm_vw - b/denominator';
04737             // forget each constraint `v - w <= dbm_wv'.
04738             for (dimension_type i = space_dim + 1; i-- > 0; ) {
04739               N& dbm_vi = dbm_v[i];
04740               add_assign_r(dbm_vi, dbm_vi, d, ROUND_UP);
04741               assign_r(dbm[i][v], PLUS_INFINITY, ROUND_NOT_NEEDED);
04742             }
04743           }
04744           else {
04745             // Here `a == -denominator'.
04746             // Translate the constraint `0 - v <= dbm_v0'
04747             // into the constraint `0 - v <= dbm_0v - b/denominator'.
04748             N& dbm_0v = dbm_0[v];
04749             add_assign_r(dbm_v[0], dbm_0v, d, ROUND_UP);
04750             // Forget all the other constraints on `v'.
04751             assign_r(dbm_0v, PLUS_INFINITY, ROUND_NOT_NEEDED);
04752             forget_binary_dbm_constraints(v);
04753           }
04754         }
04755         else {
04756           // Here `w != v', so that `expr' is of the form
04757           // +/-denominator * w + b, with `w != v'.
04758           // Remove all constraints on `v'.
04759           forget_all_dbm_constraints(v);
04760           // Shortest-path closure is preserved, but not reduction.
04761           if (marked_shortest_path_reduced())
04762             reset_shortest_path_reduced();
04763           if (a == denominator)
04764             // Add the new constraint `v - w >= b/denominator',
04765             // i.e., `w - v <= -b/denominator'.
04766             add_dbm_constraint(v, w, d);
04767           else {
04768             // Here a == -denominator, so that we should be adding
04769             // the constraint `v >= -w + b/denominator',
04770             // i.e., `-v <= w - b/denominator'.
04771             // Approximate it by computing an upper bound for `w'.
04772             const N& dbm_0w = dbm_0[w];
04773             if (!is_plus_infinity(dbm_0w)) {
04774               // Add the constraint `-v <= ub_w - b/denominator'.
04775               add_assign_r(dbm_v[0], dbm_0w, d, ROUND_UP);
04776               // Shortest-path closure is not preserved.
04777               reset_shortest_path_closed();
04778             }
04779           }
04780         }
04781         break;
04782 
04783       default:
04784         // We already dealt with the other cases.
04785         throw std::runtime_error("PPL internal error");
04786       }
04787       PPL_ASSERT(OK());
04788       return;
04789     }
04790   }
04791 
04792   // General case.
04793   // Either t == 2, so that
04794   // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
04795   // or t == 1, expr == a*w + b, but a <> +/- denominator.
04796   // We will remove all the constraints on `v' and add back
04797   // a constraint providing an upper or a lower bound for `v'
04798   // (depending on `relsym').
04799   const bool is_sc = (denominator > 0);
04800   PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
04801   neg_assign(minus_b, b);
04802   const Coefficient& sc_b = is_sc ? b : minus_b;
04803   const Coefficient& minus_sc_b = is_sc ? minus_b : b;
04804   const Coefficient& sc_den = is_sc ? denominator : minus_den;
04805   const Coefficient& minus_sc_den = is_sc ? minus_den : denominator;
04806   // NOTE: here, for optimization purposes, `minus_expr' is only assigned
04807   // when `denominator' is negative. Do not use it unless you are sure
04808   // it has been correctly assigned.
04809   Linear_Expression minus_expr;
04810   if (!is_sc)
04811     minus_expr = -expr;
04812   const Linear_Expression& sc_expr = is_sc ? expr : minus_expr;
04813 
04814   PPL_DIRTY_TEMP(N, sum);
04815   // Index of variable that is unbounded in `this->dbm'.
04816   PPL_UNINITIALIZED(dimension_type, pinf_index);
04817   // Number of unbounded variables found.
04818   dimension_type pinf_count = 0;
04819 
04820   // Speculative allocation of temporaries to be used in the following loops.
04821   PPL_DIRTY_TEMP(N, coeff_i);
04822   PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
04823 
04824   switch (relsym) {
04825   case LESS_OR_EQUAL:
04826     // Compute an upper approximation for `sc_expr' into `sum'.
04827 
04828     // Approximate the inhomogeneous term.
04829     assign_r(sum, sc_b, ROUND_UP);
04830     // Approximate the homogeneous part of `sc_expr'.
04831     // Note: indices above `w' can be disregarded, as they all have
04832     // a zero coefficient in `sc_expr'.
04833     for (dimension_type i = w; i > 0; --i) {
04834       const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1));
04835       const int sign_i = sgn(sc_i);
04836       if (sign_i == 0)
04837         continue;
04838       // Choose carefully: we are approximating `sc_expr'.
04839       const N& approx_i = (sign_i > 0) ? dbm_0[i] : dbm[i][0];
04840       if (is_plus_infinity(approx_i)) {
04841         if (++pinf_count > 1)
04842           break;
04843         pinf_index = i;
04844         continue;
04845       }
04846       if (sign_i > 0)
04847         assign_r(coeff_i, sc_i, ROUND_UP);
04848       else {
04849         neg_assign(minus_sc_i, sc_i);
04850         assign_r(coeff_i, minus_sc_i, ROUND_UP);
04851       }
04852       add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
04853     }
04854 
04855     // Remove all constraints on `v'.
04856     forget_all_dbm_constraints(v);
04857     // Shortest-path closure is preserved, but not reduction.
04858     if (marked_shortest_path_reduced())
04859       reset_shortest_path_reduced();
04860     // Return immediately if no approximation could be computed.
04861     if (pinf_count > 1) {
04862       PPL_ASSERT(OK());
04863       return;
04864     }
04865 
04866     // Divide by the (sign corrected) denominator (if needed).
04867     if (sc_den != 1) {
04868       // Before computing the quotient, the denominator should be approximated
04869       // towards zero. Since `sc_den' is known to be positive, this amounts to
04870       // rounding downwards, which is achieved as usual by rounding upwards
04871       // `minus_sc_den' and negating again the result.
04872       PPL_DIRTY_TEMP(N, down_sc_den);
04873       assign_r(down_sc_den, minus_sc_den, ROUND_UP);
04874       neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
04875       div_assign_r(sum, sum, down_sc_den, ROUND_UP);
04876     }
04877 
04878     if (pinf_count == 0) {
04879       // Add the constraint `v <= sum'.
04880       add_dbm_constraint(0, v, sum);
04881       // Deduce constraints of the form `v - u', where `u != v'.
04882       deduce_v_minus_u_bounds(v, w, sc_expr, sc_den, sum);
04883     }
04884     else if (pinf_count == 1)
04885       if (pinf_index != v
04886           && expr.coefficient(Variable(pinf_index-1)) == denominator)
04887         // Add the constraint `v - pinf_index <= sum'.
04888         add_dbm_constraint(pinf_index, v, sum);
04889     break;
04890 
04891   case GREATER_OR_EQUAL:
04892     // Compute an upper approximation for `-sc_expr' into `sum'.
04893     // Note: approximating `-sc_expr' from above and then negating the
04894     // result is the same as approximating `sc_expr' from below.
04895 
04896     // Approximate the inhomogeneous term.
04897     assign_r(sum, minus_sc_b, ROUND_UP);
04898     // Approximate the homogeneous part of `-sc_expr'.
04899     for (dimension_type i = expr_space_dim + 1; i > 0; --i) {
04900       const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1));
04901       const int sign_i = sgn(sc_i);
04902       if (sign_i == 0)
04903         continue;
04904       // Choose carefully: we are approximating `-sc_expr'.
04905       const N& approx_i = (sign_i > 0) ? dbm[i][0] : dbm_0[i];
04906       if (is_plus_infinity(approx_i)) {
04907         if (++pinf_count > 1)
04908           break;
04909         pinf_index = i;
04910         continue;
04911       }
04912       if (sign_i > 0)
04913         assign_r(coeff_i, sc_i, ROUND_UP);
04914       else {
04915         neg_assign(minus_sc_i, sc_i);
04916         assign_r(coeff_i, minus_sc_i, ROUND_UP);
04917       }
04918       add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
04919     }
04920 
04921     // Remove all constraints on `var'.
04922     forget_all_dbm_constraints(v);
04923     // Shortest-path closure is preserved, but not reduction.
04924     if (marked_shortest_path_reduced())
04925       reset_shortest_path_reduced();
04926     // Return immediately if no approximation could be computed.
04927     if (pinf_count > 1) {
04928       PPL_ASSERT(OK());
04929       return;
04930     }
04931 
04932     // Divide by the (sign corrected) denominator (if needed).
04933     if (sc_den != 1) {
04934       // Before computing the quotient, the denominator should be approximated
04935       // towards zero. Since `sc_den' is known to be positive, this amounts to
04936       // rounding downwards, which is achieved as usual by rounding upwards
04937       // `minus_sc_den' and negating again the result.
04938       PPL_DIRTY_TEMP(N, down_sc_den);
04939       assign_r(down_sc_den, minus_sc_den, ROUND_UP);
04940       neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
04941       div_assign_r(sum, sum, down_sc_den, ROUND_UP);
04942     }
04943 
04944     if (pinf_count == 0) {
04945       // Add the constraint `v >= -sum', i.e., `-v <= sum'.
04946       add_dbm_constraint(v, 0, sum);
04947       // Deduce constraints of the form `u - v', where `u != v'.
04948       deduce_u_minus_v_bounds(v, w, sc_expr, sc_den, sum);
04949     }
04950     else if (pinf_count == 1)
04951       if (pinf_index != v
04952           && expr.coefficient(Variable(pinf_index-1)) == denominator)
04953         // Add the constraint `v - pinf_index >= -sum',
04954         // i.e., `pinf_index - v <= sum'.
04955         add_dbm_constraint(v, pinf_index, sum);
04956     break;
04957 
04958   default:
04959     // We already dealt with the other cases.
04960     throw std::runtime_error("PPL internal error");
04961   }
04962   PPL_ASSERT(OK());
04963 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage ( const Linear_Expression lhs,
Relation_Symbol  relsym,
const Linear_Expression rhs 
) [inline]

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

Parameters:
lhs The left hand side affine expression.
relsym The relation symbol.
rhs The right hand side affine expression.
Exceptions:
std::invalid_argument Thrown if *this is dimension-incompatible with lhs or rhs or if relsym is a strict relation symbol.

Definition at line 5230 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::BD_Shape< T >::forget_all_dbm_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::NOT_EQUAL, Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().

05232                                                                        {
05233   // Dimension-compatibility checks.
05234   // The dimension of `lhs' should not be greater than the dimension
05235   // of `*this'.
05236   const dimension_type bds_space_dim = space_dimension();
05237   const dimension_type lhs_space_dim = lhs.space_dimension();
05238   if (bds_space_dim < lhs_space_dim)
05239     throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)",
05240                                  "e1", lhs);
05241 
05242   // The dimension of `rhs' should not be greater than the dimension
05243   // of `*this'.
05244   const dimension_type rhs_space_dim = rhs.space_dimension();
05245   if (bds_space_dim < rhs_space_dim)
05246     throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)",
05247                                  "e2", rhs);
05248 
05249   // Strict relation symbols are not admitted for BDSs.
05250   if (relsym == LESS_THAN || relsym == GREATER_THAN)
05251     throw_generic("generalized_affine_preimage(e1, r, e2)",
05252                   "r is a strict relation symbol and "
05253                   "*this is a BD_Shape");
05254   // The relation symbol cannot be a disequality.
05255   if (relsym == NOT_EQUAL)
05256     throw_generic("generalized_affine_preimage(e1, r, e2)",
05257                   "r is the disequality relation symbol and "
05258                   "*this is a BD_Shape");
05259 
05260   // The preimage of an empty BDS is empty.
05261   shortest_path_closure_assign();
05262   if (marked_empty())
05263     return;
05264 
05265   // Number of non-zero coefficients in `lhs': will be set to
05266   // 0, 1, or 2, the latter value meaning any value greater than 1.
05267   dimension_type t_lhs = 0;
05268   // Index of the last non-zero coefficient in `lhs', if any.
05269   dimension_type j_lhs = 0;
05270   // Compute the number of the non-zero components of `lhs'.
05271   for (dimension_type i = lhs_space_dim; i-- > 0; )
05272     if (lhs.coefficient(Variable(i)) != 0) {
05273       if (t_lhs++ == 1)
05274         break;
05275       else
05276         j_lhs = i;
05277     }
05278 
05279   const Coefficient& b_lhs = lhs.inhomogeneous_term();
05280 
05281   if (t_lhs == 0) {
05282     // `lhs' is a constant.
05283     // In this case, preimage and image happen to be the same.
05284     generalized_affine_image(lhs, relsym, rhs);
05285     return;
05286   }
05287   else if (t_lhs == 1) {
05288     // Here `lhs == a_lhs * v + b_lhs'.
05289     // Independently from the form of `rhs', we can exploit the
05290     // method computing generalized affine preimages for a single variable.
05291     Variable v(j_lhs);
05292     // Compute a sign-corrected relation symbol.
05293     const Coefficient& den = lhs.coefficient(v);
05294     Relation_Symbol new_relsym = relsym;
05295     if (den < 0) {
05296       if (relsym == LESS_OR_EQUAL)
05297         new_relsym = GREATER_OR_EQUAL;
05298       else if (relsym == GREATER_OR_EQUAL)
05299         new_relsym = LESS_OR_EQUAL;
05300     }
05301     Linear_Expression expr = rhs - b_lhs;
05302     generalized_affine_preimage(v, new_relsym, expr, den);
05303   }
05304   else {
05305     // Here `lhs' is of the general form, having at least two variables.
05306     // Compute the set of variables occurring in `lhs'.
05307     bool lhs_vars_intersects_rhs_vars = false;
05308     std::vector<Variable> lhs_vars;
05309     for (dimension_type i = lhs_space_dim; i-- > 0; )
05310       if (lhs.coefficient(Variable(i)) != 0) {
05311         lhs_vars.push_back(Variable(i));
05312         if (rhs.coefficient(Variable(i)) != 0)
05313           lhs_vars_intersects_rhs_vars = true;
05314       }
05315 
05316     if (!lhs_vars_intersects_rhs_vars) {
05317       // `lhs' and `rhs' variables are disjoint.
05318 
05319       // Constrain the left hand side expression so that it is related to
05320       // the right hand side expression as dictated by `relsym'.
05321       // TODO: if the following constraint is NOT a bounded difference,
05322       // it will be simply ignored. Should we compute approximations for it?
05323       switch (relsym) {
05324       case LESS_OR_EQUAL:
05325         refine_no_check(lhs <= rhs);
05326         break;
05327       case EQUAL:
05328         refine_no_check(lhs == rhs);
05329         break;
05330       case GREATER_OR_EQUAL:
05331         refine_no_check(lhs >= rhs);
05332         break;
05333       default:
05334         // We already dealt with the other cases.
05335         throw std::runtime_error("PPL internal error");
05336       }
05337 
05338       // If the shrunk BD_Shape is empty, its preimage is empty too; ...
05339       if (is_empty())
05340         return;
05341       // Existentially quantify all variables in the lhs.
05342       for (dimension_type i = lhs_vars.size(); i-- > 0; )
05343         forget_all_dbm_constraints(lhs_vars[i].id() + 1);
05344     }
05345     else {
05346 
05347       // Some variables in `lhs' also occur in `rhs'.
05348       // To ease the computation, we add an additional dimension.
05349       const Variable new_var = Variable(bds_space_dim);
05350       add_space_dimensions_and_embed(1);
05351       // Constrain the new dimension to be equal to `lhs'.
05352       // NOTE: calling affine_image() instead of refine_no_check()
05353       // ensures some approximation is tried even when the constraint
05354       // is not a bounded difference.
05355       affine_image(new_var, lhs);
05356       // Existentiallly quantify all variables in the lhs.
05357       // NOTE: enforce shortest-path closure for precision.
05358       shortest_path_closure_assign();
05359       PPL_ASSERT(!marked_empty());
05360       for (dimension_type i = lhs_vars.size(); i-- > 0; )
05361         forget_all_dbm_constraints(lhs_vars[i].id() + 1);
05362       // Constrain the new dimension so that it is related to
05363       // the left hand side as dictated by `relsym'.
05364       // Note: if `rhs == a_rhs*v + b_rhs' where `a_rhs' is in {0, 1},
05365       // then one of the following constraints will be added,
05366       // since it is a bounded difference. Else the method
05367       // refine_no_check() will ignore it, because the
05368       // constraint is NOT a bounded difference.
05369       switch (relsym) {
05370       case LESS_OR_EQUAL:
05371         refine_no_check(new_var <= rhs);
05372         break;
05373       case EQUAL:
05374         refine_no_check(new_var == rhs);
05375         break;
05376       case GREATER_OR_EQUAL:
05377         refine_no_check(new_var >= rhs);
05378         break;
05379       default:
05380         // We already dealt with the other cases.
05381         throw std::runtime_error("PPL internal error");
05382       }
05383       // Remove the temporarily added dimension.
05384       remove_higher_space_dimensions(bds_space_dim);
05385     }
05386   }
05387 
05388   PPL_ASSERT(OK());
05389 }

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() 
) [inline]

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:
var The left hand side variable of the generalized affine transfer function.
relsym The relation symbol.
expr The numerator of the right hand side affine expression.
denominator The denominator of the right hand side affine expression.
Exceptions:
std::invalid_argument Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a dimension of *this or if relsym is a strict relation symbol.

Definition at line 5152 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::BD_Shape< T >::forget_all_dbm_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::NOT_EQUAL, Parma_Polyhedra_Library::BD_Shape< T >::OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::refine(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().

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

05156                                                       {
05157   // The denominator cannot be zero.
05158   if (denominator == 0)
05159     throw_generic("generalized_affine_preimage(v, r, e, d)", "d == 0");
05160 
05161   // Dimension-compatibility checks.
05162   // The dimension of `expr' should not be greater than the dimension
05163   // of `*this'.
05164   const dimension_type space_dim = space_dimension();
05165   const dimension_type expr_space_dim = expr.space_dimension();
05166   if (space_dim < expr_space_dim)
05167     throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)",
05168                                  "e", expr);
05169 
05170   // `var' should be one of the dimensions of the BDS.
05171   const dimension_type v = var.id() + 1;
05172   if (v > space_dim)
05173     throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)",
05174                                  var.id());
05175 
05176   // The relation symbol cannot be a strict relation symbol.
05177   if (relsym == LESS_THAN || relsym == GREATER_THAN)
05178     throw_generic("generalized_affine_preimage(v, r, e, d)",
05179                   "r is a strict relation symbol and "
05180                   "*this is a BD_Shape");
05181   // The relation symbol cannot be a disequality.
05182   if (relsym == NOT_EQUAL)
05183     throw_generic("generalized_affine_preimage(v, r, e, d)",
05184                   "r is the disequality relation symbol and "
05185                   "*this is a BD_Shape");
05186 
05187   if (relsym == EQUAL) {
05188     // The relation symbol is "=":
05189     // this is just an affine preimage computation.
05190     affine_preimage(var, expr, denominator);
05191     return;
05192   }
05193 
05194   // The preimage of an empty BDS is empty too.
05195   shortest_path_closure_assign();
05196   if (marked_empty())
05197     return;
05198 
05199   // Check whether the preimage of this affine relation can be easily
05200   // computed as the image of its inverse relation.
05201   const Coefficient& expr_v = expr.coefficient(var);
05202   if (expr_v != 0) {
05203     const Relation_Symbol reversed_relsym = (relsym == LESS_OR_EQUAL)
05204       ? GREATER_OR_EQUAL : LESS_OR_EQUAL;
05205     const Linear_Expression inverse
05206       = expr - (expr_v + denominator)*var;
05207     PPL_DIRTY_TEMP_COEFFICIENT(inverse_den);
05208     neg_assign(inverse_den, expr_v);
05209     const Relation_Symbol inverse_relsym
05210       = (sgn(denominator) == sgn(inverse_den)) ? relsym : reversed_relsym;
05211     generalized_affine_image(var, inverse_relsym, inverse, inverse_den);
05212     return;
05213   }
05214 
05215   refine(var, relsym, expr, denominator);
05216   // If the shrunk BD_Shape is empty, its preimage is empty too; ...
05217   if (is_empty())
05218     return;
05219   // ...  otherwise, since the relation was not invertible,
05220   // we just forget all constraints on `v'.
05221   forget_all_dbm_constraints(v);
05222   // Shortest-path closure is preserved, but not reduction.
05223   if (marked_shortest_path_reduced())
05224     reset_shortest_path_reduced();
05225   PPL_ASSERT(OK());
05226 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::get_limiting_shape ( const Constraint_System cs,
BD_Shape< T > &  limiting_shape 
) const [inline, private]

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

Definition at line 2958 of file BD_Shape.templates.hh.

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

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::limited_BHMZ05_extrapolation_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::limited_CC76_extrapolation_assign().

02959                                                                 {
02960   const dimension_type cs_space_dim = cs.space_dimension();
02961   // Private method: the caller has to ensure the following.
02962   PPL_ASSERT(cs_space_dim <= space_dimension());
02963 
02964   shortest_path_closure_assign();
02965   bool changed = false;
02966   PPL_DIRTY_TEMP_COEFFICIENT(coeff);
02967   PPL_DIRTY_TEMP_COEFFICIENT(minus_c_term);
02968   PPL_DIRTY_TEMP(N, d);
02969   PPL_DIRTY_TEMP(N, d1);
02970   for (Constraint_System::const_iterator cs_i = cs.begin(),
02971          cs_end = cs.end(); cs_i != cs_end; ++cs_i) {
02972     const Constraint& c = *cs_i;
02973     dimension_type num_vars = 0;
02974     dimension_type i = 0;
02975     dimension_type j = 0;
02976     // Constraints that are not bounded differences are ignored.
02977     if (extract_bounded_difference(c, cs_space_dim, num_vars, i, j, coeff)) {
02978       // Select the cell to be modified for the "<=" part of the constraint,
02979       // and set `coeff' to the absolute value of itself.
02980       const bool negative = (coeff < 0);
02981       const N& x = negative ? dbm[i][j] : dbm[j][i];
02982       const N& y = negative ? dbm[j][i] : dbm[i][j];
02983       DB_Matrix<N>& ls_dbm = limiting_shape.dbm;
02984       N& ls_x = negative ? ls_dbm[i][j] : ls_dbm[j][i];
02985       N& ls_y = negative ? ls_dbm[j][i] : ls_dbm[i][j];
02986       if (negative)
02987         neg_assign(coeff);
02988       // Compute the bound for `x', rounding towards plus infinity.
02989       div_round_up(d, c.inhomogeneous_term(), coeff);
02990       if (x <= d) {
02991         if (c.is_inequality()) {
02992           if (ls_x > d) {
02993             ls_x = d;
02994             changed = true;
02995           }
02996         }
02997         else {
02998           // Compute the bound for `y', rounding towards plus infinity.
02999           neg_assign(minus_c_term, c.inhomogeneous_term());
03000           div_round_up(d1, minus_c_term, coeff);
03001           if (y <= d1)
03002             if ((ls_x >= d && ls_y > d1) || (ls_x > d && ls_y >= d1)) {
03003               ls_x = d;
03004               ls_y = d1;
03005               changed = true;
03006           }
03007         }
03008       }
03009     }
03010   }
03011 
03012   // In general, adding a constraint does not preserve the shortest-path
03013   // closure of the bounded difference shape.
03014   if (changed && limiting_shape.marked_shortest_path_closed())
03015     limiting_shape.reset_shortest_path_closed();
03016 }

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:
y A BDS that must be contained in *this.
tp An optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique).
Exceptions:
std::invalid_argument Thrown if *this and y are dimension-incompatible.

Definition at line 798 of file BD_Shape.inlines.hh.

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

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

00798                                                                 {
00799   // See the documentation for polyhedra.
00800   C_Polyhedron px(constraints());
00801   C_Polyhedron py(y.constraints());
00802   px.H79_widening_assign(py, tp);
00803   BD_Shape x(px);
00804   swap(x);
00805   PPL_ASSERT(OK());
00806 }

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 836 of file BD_Shape.inlines.hh.

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

00836                              {
00837   return space_dimension() & 0x7fffffff;
00838 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::incremental_shortest_path_closure_assign ( Variable  var  )  const [inline, private]

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

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 1813 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::min_assign(), Parma_Polyhedra_Library::PLUS_INFINITY, and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

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

01813                                                                         {
01814   // Do something only if necessary.
01815   if (marked_empty() || marked_shortest_path_closed())
01816     return;
01817   const dimension_type num_dimensions = space_dimension();
01818   PPL_ASSERT(var.id() < num_dimensions);
01819 
01820   // Even though the BDS will not change, its internal representation
01821   // is going to be modified by the incremental Floyd-Warshall algorithm.
01822   BD_Shape& x = const_cast<BD_Shape&>(*this);
01823 
01824   // Fill the main diagonal with zeros.
01825   for (dimension_type h = num_dimensions + 1; h-- > 0; ) {
01826     PPL_ASSERT(is_plus_infinity(x.dbm[h][h]));
01827     assign_r(x.dbm[h][h], 0, ROUND_NOT_NEEDED);
01828   }
01829 
01830   // Using the incremental Floyd-Warshall algorithm.
01831   PPL_DIRTY_TEMP(N, sum);
01832   const dimension_type v = var.id() + 1;
01833   DB_Row<N>& x_v = x.dbm[v];
01834   // Step 1: Improve all constraints on variable `var'.
01835   for (dimension_type k = num_dimensions + 1; k-- > 0; ) {
01836     DB_Row<N>& x_k = x.dbm[k];
01837     const N& x_v_k = x_v[k];
01838     const N& x_k_v = x_k[v];
01839     const bool x_v_k_finite = !is_plus_infinity(x_v_k);
01840     const bool x_k_v_finite = !is_plus_infinity(x_k_v);
01841     // Specialize inner loop based on finiteness info.
01842     if (x_v_k_finite) {
01843       if (x_k_v_finite) {
01844         // Here both x_v_k and x_k_v are finite.
01845         for (dimension_type i = num_dimensions + 1; i-- > 0; ) {
01846           DB_Row<N>& x_i = x.dbm[i];
01847           const N& x_i_k = x_i[k];
01848           if (!is_plus_infinity(x_i_k)) {
01849             add_assign_r(sum, x_i_k, x_k_v, ROUND_UP);
01850             min_assign(x_i[v], sum);
01851           }
01852           const N& x_k_i = x_k[i];
01853           if (!is_plus_infinity(x_k_i)) {
01854             add_assign_r(sum, x_v_k, x_k_i, ROUND_UP);
01855             min_assign(x_v[i], sum);
01856           }
01857         }
01858       }
01859       else {
01860         // Here x_v_k is finite, but x_k_v is not.
01861         for (dimension_type i = num_dimensions + 1; i-- > 0; ) {
01862           const N& x_k_i = x_k[i];
01863           if (!is_plus_infinity(x_k_i)) {
01864             add_assign_r(sum, x_v_k, x_k_i, ROUND_UP);
01865             min_assign(x_v[i], sum);
01866           }
01867         }
01868       }
01869     }
01870     else if (x_k_v_finite) {
01871       // Here x_v_k is infinite, but x_k_v is finite.
01872       for (dimension_type i = num_dimensions + 1; i-- > 0; ) {
01873         DB_Row<N>& x_i = x.dbm[i];
01874         const N& x_i_k = x_i[k];
01875         if (!is_plus_infinity(x_i_k)) {
01876           add_assign_r(sum, x_i_k, x_k_v, ROUND_UP);
01877           min_assign(x_i[v], sum);
01878         }
01879       }
01880     }
01881     else
01882       // Here both x_v_k and x_k_v are infinite.
01883       continue;
01884   }
01885 
01886   // Step 2: improve the other bounds by using the precise bounds
01887   // for the constraints on `var'.
01888   for (dimension_type i = num_dimensions + 1; i-- > 0; ) {
01889     DB_Row<N>& x_i = x.dbm[i];
01890     const N& x_i_v = x_i[v];
01891     if (!is_plus_infinity(x_i_v)) {
01892       for (dimension_type j = num_dimensions + 1; j-- > 0; ) {
01893         const N& x_v_j = x_v[j];
01894         if (!is_plus_infinity(x_v_j)) {
01895           add_assign_r(sum, x_i_v, x_v_j, ROUND_UP);
01896           min_assign(x_i[j], sum);
01897         }
01898       }
01899     }
01900   }
01901 
01902   // Check for emptiness: the BDS is empty if and only if there is a
01903   // negative value on the main diagonal of `dbm'.
01904   for (dimension_type h = num_dimensions + 1; h-- > 0; ) {
01905     N& x_dbm_hh = x.dbm[h][h];
01906     if (sgn(x_dbm_hh) < 0) {
01907       x.set_empty();
01908       return;
01909     }
01910     else {
01911       PPL_ASSERT(sgn(x_dbm_hh) == 0);
01912       // Restore PLUS_INFINITY on the main diagonal.
01913       assign_r(x_dbm_hh, PLUS_INFINITY, ROUND_NOT_NEEDED);
01914     }
01915   }
01916 
01917   // The BDS is not empty and it is now shortest-path closed.
01918   x.set_shortest_path_closed();
01919 }

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_argument Thrown 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 721 of file BD_Shape.inlines.hh.

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

00721                                                                   {
00722   PPL_COMPILE_TIME_CHECK(std::numeric_limits<T>::is_integer,
00723                          "BD_Shape<T>::integer_upper_bound_assign_if_exact(y):"
00724                          " T in not an integer datatype.");
00725   if (space_dimension() != y.space_dimension())
00726     throw_dimension_incompatible("integer_upper_bound_assign_if_exact(y)", y);
00727   const bool integer_upper_bound = true;
00728   return BHZ09_upper_bound_assign_if_exact<integer_upper_bound>(y);
00729 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign ( const BD_Shape< T > &  y  )  [inline]

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

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

Definition at line 2839 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

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

02839                                                   {
02840   const dimension_type space_dim = space_dimension();
02841 
02842   // Dimension-compatibility check.
02843   if (space_dim != y.space_dimension())
02844     throw_dimension_incompatible("intersection_assign(y)", y);
02845 
02846   // If one of the two bounded difference shapes is empty,
02847   // the intersection is empty.
02848   if (marked_empty())
02849     return;
02850   if (y.marked_empty()) {
02851     set_empty();
02852     return;
02853   }
02854 
02855   // If both bounded difference shapes are zero-dimensional,
02856   // then at this point they are necessarily non-empty,
02857   // so that their intersection is non-empty too.
02858   if (space_dim == 0)
02859     return;
02860 
02861   // To intersect two bounded difference shapes we compare
02862   // the constraints and we choose the less values.
02863   bool changed = false;
02864   for (dimension_type i = space_dim + 1; i-- > 0; ) {
02865     DB_Row<N>& dbm_i = dbm[i];
02866     const DB_Row<N>& y_dbm_i = y.dbm[i];
02867     for (dimension_type j = space_dim + 1; j-- > 0; ) {
02868       N& dbm_ij = dbm_i[j];
02869       const N& y_dbm_ij = y_dbm_i[j];
02870       if (dbm_ij > y_dbm_ij) {
02871         dbm_ij = y_dbm_ij;
02872         changed = true;
02873       }
02874     }
02875   }
02876 
02877   if (changed && marked_shortest_path_closed())
02878     reset_shortest_path_closed();
02879   PPL_ASSERT(OK());
02880 }

template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::is_bounded (  )  const [inline]

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

Definition at line 702 of file BD_Shape.templates.hh.

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

00702                               {
00703   shortest_path_closure_assign();
00704   const dimension_type space_dim = space_dimension();
00705   // A zero-dimensional or empty BDS is bounded.
00706   if (marked_empty() || space_dim == 0)
00707     return true;
00708 
00709   // A bounded difference shape defining the bounded BDS never can
00710   // contain trivial constraints.
00711   for (dimension_type i = space_dim + 1; i-- > 0; ) {
00712     const DB_Row<N>& dbm_i = dbm[i];
00713     for (dimension_type j = space_dim + 1; j-- > 0; )
00714       if (i != j)
00715         if (is_plus_infinity(dbm_i[j]))
00716           return false;
00717   }
00718 
00719   return true;
00720 }

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 412 of file BD_Shape.inlines.hh.

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

00412                                {
00413   return affine_dimension() == 0;
00414 }

template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::is_disjoint_from ( const BD_Shape< T > &  y  )  const [inline]

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

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

Definition at line 637 of file BD_Shape.templates.hh.

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

00637                                                      {
00638   const dimension_type space_dim = space_dimension();
00639   // Dimension-compatibility check.
00640   if (space_dim != y.space_dimension())
00641     throw_dimension_incompatible("is_disjoint_from(y)", y);
00642 
00643   // If one of the two bounded difference shape is empty,
00644   // then the two bounded difference shape are disjoint.
00645   shortest_path_closure_assign();
00646   if (marked_empty())
00647     return true;
00648   y.shortest_path_closure_assign();
00649   if (y.marked_empty())
00650     return true;
00651 
00652   // Two BDSs are disjoint when their intersection is empty.
00653   // That is if and only if there exists at least a bounded difference
00654   // such that the upper bound of the bounded difference in the first
00655   // BD_Shape is strictly less than the lower bound of
00656   // the corresponding bounded difference in the second BD_Shape
00657   // or vice versa.
00658   // For example: let be
00659   // in `*this':    -a_j_i <= v_j - v_i <= a_i_j;
00660   // and in `y':    -b_j_i <= v_j - v_i <= b_i_j;
00661   // `*this' and `y' are disjoint if
00662   // 1.) a_i_j < -b_j_i or
00663   // 2.) b_i_j < -a_j_i.
00664   PPL_DIRTY_TEMP(N, tmp);
00665   for (dimension_type i = space_dim+1; i-- > 0; ) {
00666     const DB_Row<N>& x_i = dbm[i];
00667     for (dimension_type j = space_dim+1; j-- > 0; ) {
00668       neg_assign_r(tmp, y.dbm[j][i], ROUND_UP);
00669       if (x_i[j] < tmp)
00670         return true;
00671     }
00672   }
00673 
00674   return false;
00675 }

template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::is_empty (  )  const [inline]
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::is_shortest_path_reduced (  )  const [inline, private]

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

Definition at line 955 of file BD_Shape.templates.hh.

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

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

00955                                             {
00956   // If the BDS is empty, it is also reduced.
00957   if (marked_empty())
00958     return true;
00959 
00960   const dimension_type space_dim = space_dimension();
00961   // Zero-dimensional BDSs are necessarily reduced.
00962   if (space_dim == 0)
00963     return true;
00964 
00965   // A shortest-path reduced dbm is just a dbm with an indication of
00966   // those constraints that are redundant. If there is no indication
00967   // of the redundant constraints, then it cannot be reduced.
00968   if (!marked_shortest_path_reduced())
00969     return false;
00970 
00971   const BD_Shape x_copy = *this;
00972   x_copy.shortest_path_closure_assign();
00973   // If we just discovered emptiness, it cannot be reduced.
00974   if (x_copy.marked_empty())
00975     return false;
00976 
00977   // The vector `leader' is used to indicate which variables are equivalent.
00978   std::vector<dimension_type> leader(space_dim + 1);
00979 
00980   // We store the leader.
00981   for (dimension_type i = space_dim + 1; i-- > 0; )
00982     leader[i] = i;
00983 
00984   // Step 1: we store really the leader with the corrected value.
00985   // We search for the equivalent or zero-equivalent variables.
00986   // The variable(i-1) and variable(j-1) are equivalent if and only if
00987   // m_i_j == -(m_j_i).
00988   for (dimension_type i = 0; i < space_dim; ++i) {
00989     const DB_Row<N>& x_copy_dbm_i = x_copy.dbm[i];
00990     for (dimension_type j = i + 1; j <= space_dim; ++j)
00991       if (is_additive_inverse(x_copy.dbm[j][i], x_copy_dbm_i[j]))
00992         // Two equivalent variables have got the same leader
00993         // (the smaller variable).
00994         leader[j] = leader[i];
00995   }
00996 
00997   // Step 2: we check if there are redundant constraints in the zero_cycle
00998   // free bounded difference shape, considering only the leaders.
00999   // A constraint `c' is redundant, when there are two constraints such that
01000   // their sum is the same constraint with the inhomogeneous term
01001   // less than or equal to the `c' one.
01002   PPL_DIRTY_TEMP(N, c);
01003   for (dimension_type k = 0; k <= space_dim; ++k)
01004     if (leader[k] == k) {
01005       const DB_Row<N>& x_k = x_copy.dbm[k];
01006       for (dimension_type i = 0; i <= space_dim; ++i)
01007         if (leader[i] == i) {
01008           const DB_Row<N>& x_i = x_copy.dbm[i];
01009           const Bit_Row& redundancy_i = redundancy_dbm[i];
01010           const N& x_i_k = x_i[k];
01011           for (dimension_type j = 0; j <= space_dim; ++j)
01012             if (leader[j] == j) {
01013               const N& x_i_j = x_i[j];
01014               if (!is_plus_infinity(x_i_j)) {
01015                 add_assign_r(c, x_i_k, x_k[j], ROUND_UP);
01016                 if (x_i_j >= c && !redundancy_i[j])
01017                   return false;
01018               }
01019             }
01020         }
01021     }
01022 
01023   // The vector `var_conn' is used to check if there is a single cycle
01024   // that connected all zero-equivalent variables between them.
01025   // The value `space_dim + 1' is used to indicate that the equivalence
01026   // class contains a single variable.
01027   std::vector<dimension_type> var_conn(space_dim + 1);
01028   for (dimension_type i = space_dim + 1; i-- > 0; )
01029     var_conn[i] = space_dim + 1;
01030 
01031   // Step 3: we store really the `var_conn' with the right value, putting
01032   // the variable with the selected variable is connected:
01033   // we check the row of each variable:
01034   // a- each leader could be connected with only zero-equivalent one,
01035   // b- each no-leader with only another zero-equivalent one.
01036   for (dimension_type i = 0; i <= space_dim; ++i) {
01037     // It count with how many variables the selected variable is
01038     // connected.
01039     dimension_type t = 0;
01040     dimension_type ld_i = leader[i];
01041     // Case a: leader.
01042     if (ld_i == i) {
01043       for (dimension_type j = 0; j <= space_dim; ++j) {
01044         dimension_type ld_j = leader[j];
01045         // Only the connectedness with equivalent variables
01046         // is considered.
01047         if (j != ld_j)
01048           if (!redundancy_dbm[i][j]) {
01049             if (t == 1)
01050               // Two no-leaders couldn't connected with the same leader.
01051               return false;
01052             else
01053               if (ld_j != i)
01054                 // The variables isn't in the same equivalence class.
01055                 return false;
01056               else {
01057                 ++t;
01058                 var_conn[i] = j;
01059               }
01060           }
01061       }
01062     }
01063     // Case b: no-leader.
01064     else {
01065       for (dimension_type j = 0; j <= space_dim; ++j) {
01066         if (!redundancy_dbm[i][j]) {
01067           dimension_type ld_j = leader[j];
01068           if (ld_i != ld_j)
01069             // The variables isn't in the same equivalence class.
01070             return false;
01071           else {
01072             if (t == 1)
01073               // Two variables couldn't connected with the same leader.
01074               return false;
01075             else {
01076               ++t;
01077               var_conn[i] = j;
01078             }
01079           }
01080           // A no-leader must be connected with
01081           // another variable.
01082           if (t == 0)
01083             return false;
01084         }
01085       }
01086     }
01087   }
01088 
01089   // The vector `just_checked' is used to check if
01090   // a variable is already checked.
01091   std::vector<bool> just_checked(space_dim + 1);
01092   for (dimension_type i = space_dim + 1; i-- > 0; )
01093     just_checked[i] = false;
01094 
01095   // Step 4: we check if there are single cycles that
01096   // connected all the zero-equivalent variables between them.
01097   for (dimension_type i = 0; i <= space_dim; ++i) {
01098     bool jc_i = just_checked[i];
01099     // We do not re-check the already considered single cycles.
01100     if (!jc_i) {
01101       dimension_type v_con = var_conn[i];
01102       // We consider only the equivalence classes with
01103       // 2 or plus variables.
01104       if (v_con != space_dim + 1) {
01105         // There is a single cycle if taken a variable,
01106         // we return to this same variable.
01107         while (v_con != i) {
01108           just_checked[v_con] = true;
01109           v_con = var_conn[v_con];
01110           // If we re-pass to an already considered variable,
01111           // then we haven't a single cycle.
01112           if (just_checked[v_con])
01113             return false;
01114         }
01115       }
01116     }
01117     just_checked[i] = true;
01118   }
01119 
01120   // The system bounded differences is just reduced.
01121   return true;
01122 }

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 406 of file BD_Shape.inlines.hh.

00406                                            {
00407   return true;
00408 }

template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::is_universe (  )  const [inline]

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

Definition at line 679 of file BD_Shape.templates.hh.

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

00679                                {
00680   if (marked_empty())
00681     return false;
00682 
00683   const dimension_type space_dim = space_dimension();
00684   // If the BDS is non-empty and zero-dimensional,
00685   // then it is necessarily the universe BDS.
00686   if (space_dim == 0)
00687     return true;
00688 
00689   // A bounded difference shape defining the universe BDS can only
00690   // contain trivial constraints.
00691   for (dimension_type i = space_dim + 1; i-- > 0; ) {
00692     const DB_Row<N>& dbm_i = dbm[i];
00693     for (dimension_type j = space_dim + 1; j-- > 0; )
00694       if (!is_plus_infinity(dbm_i[j]))
00695         return false;
00696   }
00697   return true;
00698 }

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 
) [inline]

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

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

Definition at line 3141 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::get_limiting_shape(), Parma_Polyhedra_Library::Constraint_System::has_strict_inequalities(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), Parma_Polyhedra_Library::BD_Shape< T >::throw_generic(), and Parma_Polyhedra_Library::UNIVERSE.

03143                                                                {
03144   // Dimension-compatibility check.
03145   const dimension_type space_dim = space_dimension();
03146   if (space_dim != y.space_dimension())
03147     throw_dimension_incompatible("limited_BHMZ05_extrapolation_assign(y, cs)",
03148                                  y);
03149   // `cs' must be dimension-compatible with the two systems
03150   // of bounded differences.
03151   const dimension_type cs_space_dim = cs.space_dimension();
03152   if (space_dim < cs_space_dim)
03153     throw_generic("limited_BHMZ05_extrapolation_assign(y, cs)",
03154                   "cs is space-dimension incompatible");
03155 
03156   // Strict inequalities are not allowed.
03157   if (cs.has_strict_inequalities())
03158     throw_generic("limited_BHMZ05_extrapolation_assign(y, cs)",
03159                   "cs has strict inequalities");
03160 
03161   // The limited BHMZ05-extrapolation between two systems of bounded
03162   // differences in a zero-dimensional space is a system of bounded
03163   // differences in a zero-dimensional space, too.
03164   if (space_dim == 0)
03165     return;
03166 
03167 #ifndef NDEBUG
03168   {
03169     // We assume that `y' is contained in or equal to `*this'.
03170     const BD_Shape x_copy = *this;
03171     const BD_Shape y_copy = y;
03172     PPL_ASSERT(x_copy.contains(y_copy));
03173   }
03174 #endif
03175 
03176   // If `*this' is empty, since `*this' contains `y', `y' is empty too.
03177   if (marked_empty())
03178     return;
03179   // If `y' is empty, we return.
03180   if (y.marked_empty())
03181     return;
03182 
03183   BD_Shape<T> limiting_shape(space_dim, UNIVERSE);
03184   get_limiting_shape(cs, limiting_shape);
03185   BHMZ05_widening_assign(y, tp);
03186   intersection_assign(limiting_shape);
03187 }

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 
) [inline]

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

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

Definition at line 3020 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::get_limiting_shape(), Parma_Polyhedra_Library::Constraint_System::has_strict_inequalities(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), Parma_Polyhedra_Library::BD_Shape< T >::throw_generic(), and Parma_Polyhedra_Library::UNIVERSE.

03022                                                              {
03023   // Dimension-compatibility check.
03024   const dimension_type space_dim = space_dimension();
03025   if (space_dim != y.space_dimension())
03026     throw_dimension_incompatible("limited_CC76_extrapolation_assign(y, cs)",
03027                                  y);
03028 
03029   // `cs' must be dimension-compatible with the two systems
03030   // of bounded differences.
03031   const dimension_type cs_space_dim = cs.space_dimension();
03032   if (space_dim < cs_space_dim)
03033     throw_generic("limited_CC76_extrapolation_assign(y, cs)",
03034                   "cs is space_dimension incompatible");
03035 
03036   // Strict inequalities not allowed.
03037   if (cs.has_strict_inequalities())
03038     throw_generic("limited_CC76_extrapolation_assign(y, cs)",
03039                   "cs has strict inequalities");
03040 
03041   // The limited CC76-extrapolation between two systems of bounded
03042   // differences in a zero-dimensional space is a system of bounded
03043   // differences in a zero-dimensional space, too.
03044   if (space_dim == 0)
03045     return;
03046 
03047 #ifndef NDEBUG
03048   {
03049     // We assume that `y' is contained in or equal to `*this'.
03050     const BD_Shape x_copy = *this;
03051     const BD_Shape y_copy = y;
03052     PPL_ASSERT(x_copy.contains(y_copy));
03053   }
03054 #endif
03055 
03056   // If `*this' is empty, since `*this' contains `y', `y' is empty too.
03057   if (marked_empty())
03058     return;
03059   // If `y' is empty, we return.
03060   if (y.marked_empty())
03061     return;
03062 
03063   BD_Shape<T> limiting_shape(space_dim, UNIVERSE);
03064   get_limiting_shape(cs, limiting_shape);
03065   CC76_extrapolation_assign(y, tp);
03066   intersection_assign(limiting_shape);
03067 }

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:
y A BDS that must be contained in *this.
cs The system of constraints used to improve the widened BDS.
tp An optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique).
Exceptions:
std::invalid_argument Thrown if *this, y and cs are dimension-incompatible.

Definition at line 816 of file BD_Shape.inlines.hh.

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

00818                                                             {
00819   // See the documentation for polyhedra.
00820   C_Polyhedron px(constraints());
00821   C_Polyhedron py(y.constraints());
00822   px.limited_H79_extrapolation_assign(py, cs, tp);
00823   BD_Shape x(px);
00824   swap(x);
00825   PPL_ASSERT(OK());
00826 }

template<typename T >
template<typename Partial_Function >
void Parma_Polyhedra_Library::BD_Shape< T >::map_space_dimensions ( const Partial_Function &  pfunc  )  [inline]

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

Parameters:
pfunc The partial function specifying the destiny of each dimension.

The template type parameter Partial_Function must provide the following methods.

      bool has_empty_codomain() const

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

      dimension_type max_in_codomain() const

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

      bool maps(dimension_type i, dimension_type& j) const

Let $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 2771 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::swap().

02771                                                                {
02772   const dimension_type space_dim = space_dimension();
02773   // TODO: this implementation is just an executable specification.
02774   if (space_dim == 0)
02775     return;
02776 
02777   if (pfunc.has_empty_codomain()) {
02778     // All dimensions vanish: the BDS becomes zero_dimensional.
02779     remove_higher_space_dimensions(0);
02780     return;
02781   }
02782 
02783   const dimension_type new_space_dim = pfunc.max_in_codomain() + 1;
02784   // If we are going to actually reduce the space dimension,
02785   // then shortest-path closure is required to keep precision.
02786   if (new_space_dim < space_dim)
02787     shortest_path_closure_assign();
02788 
02789   // If the BDS is empty, then it is sufficient to adjust the
02790   // space dimension of the bounded difference shape.
02791   if (marked_empty()) {
02792     remove_higher_space_dimensions(new_space_dim);
02793     return;
02794   }
02795 
02796   // Shortest-path closure is maintained (if it was holding).
02797   // TODO: see whether reduction can be (efficiently!) maintained too.
02798   if (marked_shortest_path_reduced())
02799     reset_shortest_path_reduced();
02800 
02801   // We create a new matrix with the new space dimension.
02802   DB_Matrix<N> x(new_space_dim+1);
02803   // First of all we must map the unary constraints, because
02804   // there is the fictitious variable `zero', that can't be mapped
02805   // at all.
02806   DB_Row<N>& dbm_0 = dbm[0];
02807   DB_Row<N>& x_0 = x[0];
02808   for (dimension_type j = 1; j <= space_dim; ++j) {
02809     dimension_type new_j;
02810     if (pfunc.maps(j - 1, new_j)) {
02811       assign_or_swap(x_0[new_j + 1], dbm_0[j]);
02812       assign_or_swap(x[new_j + 1][0], dbm[j][0]);
02813     }
02814   }
02815   // Now we map the binary constraints, exchanging the indexes.
02816   for (dimension_type i = 1; i <= space_dim; ++i) {
02817     dimension_type new_i;
02818     if (pfunc.maps(i - 1, new_i)) {
02819       DB_Row<N>& dbm_i = dbm[i];
02820       ++new_i;
02821       DB_Row<N>& x_new_i = x[new_i];
02822       for (dimension_type j = i+1; j <= space_dim; ++j) {
02823         dimension_type new_j;
02824         if (pfunc.maps(j - 1, new_j)) {
02825           ++new_j;
02826           assign_or_swap(x_new_i[new_j], dbm_i[j]);
02827           assign_or_swap(x[new_j][new_i], dbm[j][i]);
02828         }
02829       }
02830     }
02831   }
02832 
02833   std::swap(dbm, x);
02834   PPL_ASSERT(OK());
02835 }

template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::marked_empty (  )  const [inline, private]

Returns true if the BDS is known to be empty.

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

Definition at line 61 of file BD_Shape.inlines.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::status, and Parma_Polyhedra_Library::BD_Shape< T >::Status::test_empty().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::BD_Shape< T >::affine_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::BD_Shape< T >::BFT00_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::BHZ09_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::BD_Shape< T >::compute_leaders(), Parma_Polyhedra_Library::BD_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::BD_Shape< T >::constrains(), Parma_Polyhedra_Library::BD_Shape< T >::constraints(), Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::difference_assign(), Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::BD_Shape< T >::euclidean_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::frequency(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::incremental_shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::BD_Shape< T >::is_bounded(), Parma_Polyhedra_Library::BD_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::BD_Shape< T >::is_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::is_universe(), Parma_Polyhedra_Library::BD_Shape< T >::l_infinity_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::limited_BHMZ05_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::max_min(), Parma_Polyhedra_Library::BD_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::BD_Shape< T >::minimized_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::rectilinear_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_congruence(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_congruences(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::relation_with(), Parma_Polyhedra_Library::BD_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign(), Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign(), Parma_Polyhedra_Library::BD_Shape< T >::unconstrain(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign().

00061                                 {
00062   return status.test_empty();
00063 }

template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed (  )  const [inline, private]

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

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

Definition at line 67 of file BD_Shape.inlines.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::status, and Parma_Polyhedra_Library::BD_Shape< T >::Status::test_shortest_path_closed().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::add_dbm_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::BHZ09_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::BD_Shape< T >::compute_leaders(), Parma_Polyhedra_Library::BD_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::BD_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::get_limiting_shape(), Parma_Polyhedra_Library::BD_Shape< T >::incremental_shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign().

00067                                                {
00068   return status.test_shortest_path_closed();
00069 }

template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced (  )  const [inline, private]
template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::marked_zero_dim_univ (  )  const [inline, private]

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

Definition at line 55 of file BD_Shape.inlines.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::status, and Parma_Polyhedra_Library::BD_Shape< T >::Status::test_zero_dim_univ().

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

00055                                         {
00056   return status.test_zero_dim_univ();
00057 }

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 [inline, private]

Maximizes or minimizes expr subject to *this.

Parameters:
expr The linear expression to be maximized or minimized subject to this;
maximize true if maximization is what is wanted;
ext_n The numerator of the extremum value;
ext_d The denominator of the extremum value;
included true if and only if the extremum of expr can actually be reached in * this;
Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

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

Definition at line 1171 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::BD_Shape< T >::constraints(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::extract_bounded_difference(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::MINIMIZATION, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::numer_denom(), Parma_Polyhedra_Library::MIP_Problem::optimal_value(), Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::MIP_Problem::solve(), Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

01174                                            {
01175   // The dimension of `expr' should not be greater than the dimension
01176   // of `*this'.
01177   const dimension_type space_dim = space_dimension();
01178   const dimension_type expr_space_dim = expr.space_dimension();
01179   if (space_dim < expr_space_dim)
01180     throw_dimension_incompatible((maximize
01181                                   ? "maximize(e, ...)"
01182                                   : "minimize(e, ...)"), "e", expr);
01183   // Deal with zero-dim BDS first.
01184   if (space_dim == 0) {
01185     if (marked_empty())
01186       return false;
01187     else {
01188       ext_n = expr.inhomogeneous_term();
01189       ext_d = 1;
01190       included = true;
01191       return true;
01192     }
01193   }
01194 
01195   shortest_path_closure_assign();
01196   // For an empty BDS we simply return false.
01197   if (marked_empty())
01198     return false;
01199 
01200   // The constraint `c' is used to check if `expr' is a difference
01201   // bounded and, in this case, to select the cell.
01202   const Constraint& c = maximize ? expr <= 0 : expr >= 0;
01203   const dimension_type c_space_dim = c.space_dimension();
01204   dimension_type num_vars = 0;
01205   dimension_type i = 0;
01206   dimension_type j = 0;
01207   PPL_DIRTY_TEMP_COEFFICIENT(coeff);
01208   // Check if `c' is a BD constraint.
01209   if (!extract_bounded_difference(c, c_space_dim, num_vars, i, j, coeff)) {
01210     Optimization_Mode mode_max_min
01211       = maximize ? MAXIMIZATION : MINIMIZATION;
01212     MIP_Problem mip(space_dim, constraints(), expr, mode_max_min);
01213     if (mip.solve() == OPTIMIZED_MIP_PROBLEM) {
01214       mip.optimal_value(ext_n, ext_d);
01215       included = true;
01216       return true;
01217     }
01218     else
01219       // Here`expr' is unbounded in `*this'.
01220       return false;
01221   }
01222   else {
01223     // Here `expr' is a bounded difference.
01224     if (num_vars == 0) {
01225       // Dealing with a trivial expression.
01226       ext_n = expr.inhomogeneous_term();
01227       ext_d = 1;
01228       included = true;
01229       return true;
01230     }
01231 
01232     // Select the cell to be checked.
01233     const N& x = (coeff < 0) ? dbm[i][j] : dbm[j][i];
01234     if (!is_plus_infinity(x)) {
01235       // Compute the maximize/minimize of `expr'.
01236       PPL_DIRTY_TEMP(N, d);
01237       const Coefficient& b = expr.inhomogeneous_term();
01238       PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
01239       neg_assign(minus_b, b);
01240       const Coefficient& sc_b = maximize ? b : minus_b;
01241       assign_r(d, sc_b, ROUND_UP);
01242       // Set `coeff_expr' to the absolute value of coefficient of
01243       // a variable in `expr'.
01244       PPL_DIRTY_TEMP(N, coeff_expr);
01245       const Coefficient& coeff_i = expr.coefficient(Variable(i-1));
01246       const int sign_i = sgn(coeff_i);
01247       if (sign_i > 0)
01248         assign_r(coeff_expr, coeff_i, ROUND_UP);
01249       else {
01250         PPL_DIRTY_TEMP_COEFFICIENT(minus_coeff_i);
01251         neg_assign(minus_coeff_i, coeff_i);
01252         assign_r(coeff_expr, minus_coeff_i, ROUND_UP);
01253       }
01254       // Approximating the maximum/minimum of `expr'.
01255       add_mul_assign_r(d, coeff_expr, x, ROUND_UP);
01256       numer_denom(d, ext_n, ext_d);
01257       if (!maximize)
01258         neg_assign(ext_n);
01259       included = true;
01260       return true;
01261     }
01262 
01263     // `expr' is unbounded.
01264     return false;
01265   }
01266 }

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 [inline, private]

Maximizes or minimizes expr subject to *this.

Parameters:
expr The linear expression to be maximized or minimized subject to this;
maximize true if maximization is what is wanted;
ext_n The numerator of the extremum value;
ext_d The denominator of the extremum value;
included true if and only if the extremum of expr can actually be reached in * this;
g When maximization or minimization succeeds, will be assigned a point or closure point where expr reaches the corresponding extremum value.
Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

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

Definition at line 1270 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::constraints(), Parma_Polyhedra_Library::MIP_Problem::evaluate_objective_function(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::MINIMIZATION, Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, Parma_Polyhedra_Library::MIP_Problem::optimizing_point(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::MIP_Problem::solve(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::maximize(), and Parma_Polyhedra_Library::BD_Shape< T >::minimize().

01274                                          {
01275   // The dimension of `expr' should not be greater than the dimension
01276   // of `*this'.
01277   const dimension_type space_dim = space_dimension();
01278   const dimension_type expr_space_dim = expr.space_dimension();
01279   if (space_dim < expr_space_dim)
01280     throw_dimension_incompatible((maximize
01281                                   ? "maximize(e, ...)"
01282                                   : "minimize(e, ...)"), "e", expr);
01283   // Deal with zero-dim BDS first.
01284   if (space_dim == 0) {
01285     if (marked_empty())
01286       return false;
01287     else {
01288       ext_n = expr.inhomogeneous_term();
01289       ext_d = 1;
01290       included = true;
01291       g = point();
01292       return true;
01293     }
01294   }
01295 
01296   shortest_path_closure_assign();
01297   // For an empty BDS we simply return false.
01298   if (marked_empty())
01299     return false;
01300 
01301   Optimization_Mode mode_max_min
01302     = maximize ? MAXIMIZATION : MINIMIZATION;
01303   MIP_Problem mip(space_dim, constraints(), expr, mode_max_min);
01304   if (mip.solve() == OPTIMIZED_MIP_PROBLEM) {
01305     g = mip.optimizing_point();
01306     mip.evaluate_objective_function(g, ext_n, ext_d);
01307     included = true;
01308     return true;
01309   }
01310   // Here `expr' is unbounded in `*this'.
01311   return false;
01312 }

template<typename T >
dimension_type Parma_Polyhedra_Library::BD_Shape< T >::max_space_dimension (  )  [inline, static]

Returns the maximum space dimension that a BDS can handle.

Definition at line 46 of file BD_Shape.inlines.hh.

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

00046                                  {
00047   // One dimension is reserved to have a value of type dimension_type
00048   // that does not represent a legal dimension.
00049   return std::min(DB_Matrix<N>::max_num_rows() - 1,
00050                   DB_Matrix<N>::max_num_columns() - 1);
00051 }

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:
expr The linear expression to be maximized subject to *this;
sup_n The numerator of the supremum value;
sup_d The denominator of the supremum value;
maximum true if and only if the supremum is also the maximum value;
g When maximization succeeds, will be assigned the point or closure point where expr reaches its supremum value.
Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

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

Definition at line 382 of file BD_Shape.inlines.hh.

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

00384                                           {
00385   return max_min(expr, true, sup_n, sup_d, maximum, g);
00386 }

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:
expr The linear expression to be maximized subject to *this;
sup_n The numerator of the supremum value;
sup_d The denominator of the supremum value;
maximum true if and only if the supremum is also the maximum value.
Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

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

Definition at line 374 of file BD_Shape.inlines.hh.

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

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

00376                                            {
00377   return max_min(expr, true, sup_n, sup_d, maximum);
00378 }

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:
expr The linear expression to be minimized subject to *this;
inf_n The numerator of the infimum value;
inf_d The denominator of the infimum value;
minimum true if and only if the infimum is also the minimum value;
g When minimization succeeds, will be assigned a point or closure point where expr reaches its infimum value.
Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

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

Definition at line 398 of file BD_Shape.inlines.hh.

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

00400                                           {
00401   return max_min(expr, false, inf_n, inf_d, minimum, g);
00402 }

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:
expr The linear expression to be minimized subject to *this;
inf_n The numerator of the infimum value;
inf_d The denominator of the infimum value;
minimum true if and only if the infimum is also the minimum value.
Exceptions:
std::invalid_argument Thrown if expr and *this are dimension-incompatible.

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

Definition at line 390 of file BD_Shape.inlines.hh.

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

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

00392                                            {
00393   return max_min(expr, false, inf_n, inf_d, minimum);
00394 }

template<typename T >
Congruence_System Parma_Polyhedra_Library::BD_Shape< T >::minimized_congruences (  )  const [inline]

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

Definition at line 323 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::compute_leaders(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::Congruence_System::insert(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::Congruence_System::zero_dim_empty().

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

00323                                          {
00324   // Shortest-path closure is necessary to detect emptiness
00325   // and all (possibly implicit) equalities.
00326   shortest_path_closure_assign();
00327 
00328   const dimension_type space_dim = space_dimension();
00329   Congruence_System cgs;
00330   if (space_dim == 0) {
00331     if (marked_empty())
00332       cgs = Congruence_System::zero_dim_empty();
00333   }
00334   else if (marked_empty())
00335     cgs.insert((0*Variable(space_dim-1) %= 1) / 0);
00336   else {
00337     // KLUDGE: in the future `cgs' will be constructed of the right dimension.
00338     // For the time being, we force the dimension with the following line.
00339     cgs.insert(0*Variable(space_dim-1) == 0);
00340 
00341     PPL_DIRTY_TEMP_COEFFICIENT(num);
00342     PPL_DIRTY_TEMP_COEFFICIENT(den);
00343 
00344     // Compute leader information.
00345     std::vector<dimension_type> leaders;
00346     compute_leaders(leaders);
00347 
00348     // Go through the non-leaders to generate equality constraints.
00349     const DB_Row<N>& dbm_0 = dbm[0];
00350     for (dimension_type i = 1; i <= space_dim; ++i) {
00351       const dimension_type leader = leaders[i];
00352       if (i != leader) {
00353         // Generate the constraint relating `i' and its leader.
00354         if (leader == 0) {
00355           // A unary equality has to be generated.
00356           PPL_ASSERT(!is_plus_infinity(dbm_0[i]));
00357           numer_denom(dbm_0[i], num, den);
00358           cgs.insert(den*Variable(i-1) == num);
00359         }
00360         else {
00361           // A binary equality has to be generated.
00362           PPL_ASSERT(!is_plus_infinity(dbm[i][leader]));
00363           numer_denom(dbm[i][leader], num, den);
00364           cgs.insert(den*Variable(leader-1) - den*Variable(i-1) == num);
00365         }
00366       }
00367     }
00368   }
00369   return cgs;
00370 }

template<typename T >
Constraint_System Parma_Polyhedra_Library::BD_Shape< T >::minimized_constraints (  )  const [inline]

Returns a minimized system of constraints defining *this.

Definition at line 5468 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::compute_leader_indices(), Parma_Polyhedra_Library::BD_Shape< T >::compute_leaders(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::Constraint_System::zero_dim_empty().

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

05468                                          {
05469   shortest_path_reduction_assign();
05470   Constraint_System cs;
05471   const dimension_type space_dim = space_dimension();
05472   if (space_dim == 0) {
05473     if (marked_empty())
05474       cs = Constraint_System::zero_dim_empty();
05475   }
05476   else if (marked_empty())
05477     cs.insert(0*Variable(space_dim-1) <= -1);
05478   else {
05479     // KLUDGE: in the future `cs' will be constructed of the right dimension.
05480     // For the time being, we force the dimension with the following line.
05481     cs.insert(0*Variable(space_dim-1) <= 0);
05482 
05483     PPL_DIRTY_TEMP_COEFFICIENT(num);
05484     PPL_DIRTY_TEMP_COEFFICIENT(den);
05485 
05486     // Compute leader information.
05487     std::vector<dimension_type> leaders;
05488     compute_leaders(leaders);
05489     std::vector<dimension_type> leader_indices;
05490     compute_leader_indices(leaders, leader_indices);
05491     const dimension_type num_leaders = leader_indices.size();
05492 
05493     // Go through the non-leaders to generate equality constraints.
05494     const DB_Row<N>& dbm_0 = dbm[0];
05495     for (dimension_type i = 1; i <= space_dim; ++i) {
05496       const dimension_type leader = leaders[i];
05497       if (i != leader) {
05498         // Generate the constraint relating `i' and its leader.
05499         if (leader == 0) {
05500           // A unary equality has to be generated.
05501           PPL_ASSERT(!is_plus_infinity(dbm_0[i]));
05502           numer_denom(dbm_0[i], num, den);
05503           cs.insert(den*Variable(i-1) == num);
05504         }
05505         else {
05506           // A binary equality has to be generated.
05507           PPL_ASSERT(!is_plus_infinity(dbm[i][leader]));
05508           numer_denom(dbm[i][leader], num, den);
05509           cs.insert(den*Variable(leader-1) - den*Variable(i-1) == num);
05510         }
05511       }
05512     }
05513 
05514     // Go through the leaders to generate inequality constraints.
05515     // First generate all the unary inequalities.
05516     const Bit_Row& red_0 = redundancy_dbm[0];
05517     for (dimension_type l_i = 1; l_i < num_leaders; ++l_i) {
05518       const dimension_type i = leader_indices[l_i];
05519       if (!red_0[i]) {
05520         numer_denom(dbm_0[i], num, den);
05521         cs.insert(den*Variable(i-1) <= num);
05522       }
05523       if (!redundancy_dbm[i][0]) {
05524         numer_denom(dbm[i][0], num, den);
05525         cs.insert(-den*Variable(i-1) <= num);
05526       }
05527     }
05528     // Then generate all the binary inequalities.
05529     for (dimension_type l_i = 1; l_i < num_leaders; ++l_i) {
05530       const dimension_type i = leader_indices[l_i];
05531       const DB_Row<N>& dbm_i = dbm[i];
05532       const Bit_Row& red_i = redundancy_dbm[i];
05533       for (dimension_type l_j = l_i + 1; l_j < num_leaders; ++l_j) {
05534         const dimension_type j = leader_indices[l_j];
05535         if (!red_i[j]) {
05536           numer_denom(dbm_i[j], num, den);
05537           cs.insert(den*Variable(j-1) - den*Variable(i-1) <= num);
05538         }
05539         if (!redundancy_dbm[j][i]) {
05540           numer_denom(dbm[j][i], num, den);
05541           cs.insert(den*Variable(i-1) - den*Variable(j-1) <= num);
05542         }
05543       }
05544     }
05545   }
05546   return cs;
05547 }

template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::OK (  )  const [inline]

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

Definition at line 5842 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::is_minus_infinity(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::DB_Matrix< T >::num_rows(), Parma_Polyhedra_Library::BD_Shape< T >::Status::OK(), Parma_Polyhedra_Library::DB_Matrix< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm, Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::status.

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::BD_Shape< T >::BFT00_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::BHZ09_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::BD_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::BD_Shape< T >::difference_assign(), Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::BD_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::H79_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::BD_Shape< T >::limited_H79_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::refine(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::time_elapse_assign(), Parma_Polyhedra_Library::BD_Shape< T >::unconstrain(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign().

05842                       {
05843   // Check whether the difference-bound matrix is well-formed.
05844   if (!dbm.OK())
05845     return false;
05846 
05847   // Check whether the status information is legal.
05848   if (!status.OK())
05849     return false;
05850 
05851   // An empty BDS is OK.
05852   if (marked_empty())
05853     return true;
05854 
05855   // MINUS_INFINITY cannot occur at all.
05856   for (dimension_type i = dbm.num_rows(); i-- > 0; )
05857     for (dimension_type j = dbm.num_rows(); j-- > 0; )
05858       if (is_minus_infinity(dbm[i][j])) {
05859 #ifndef NDEBUG
05860         using namespace Parma_Polyhedra_Library::IO_Operators;
05861         std::cerr << "BD_Shape::dbm[" << i << "][" << j << "] = "
05862                   << dbm[i][j] << "!"
05863                   << std::endl;
05864 #endif
05865         return false;
05866       }
05867 
05868   // On the main diagonal only PLUS_INFINITY can occur.
05869   for (dimension_type i = dbm.num_rows(); i-- > 0; )
05870     if (!is_plus_infinity(dbm[i][i])) {
05871 #ifndef NDEBUG
05872       using namespace Parma_Polyhedra_Library::IO_Operators;
05873       std::cerr << "BD_Shape::dbm[" << i << "][" << i << "] = "
05874                 << dbm[i][i] << "!  (+inf was expected.)"
05875                 << std::endl;
05876 #endif
05877       return false;
05878     }
05879 
05880   // Check whether the shortest-path closure information is legal.
05881   if (marked_shortest_path_closed()) {
05882     BD_Shape x = *this;
05883     x.reset_shortest_path_closed();
05884     x.shortest_path_closure_assign();
05885     if (x.dbm != dbm) {
05886 #ifndef NDEBUG
05887       std::cerr << "BD_Shape is marked as closed but it is not!"
05888                 << std::endl;
05889 #endif
05890       return false;
05891     }
05892   }
05893 
05894   // The following tests might result in false alarms when using floating
05895   // point coefficients: they are only meaningful if the coefficient type
05896   // base is exact (since otherwise shortest-path closure is approximated).
05897   if (std::numeric_limits<coefficient_type_base>::is_exact) {
05898 
05899     // Check whether the shortest-path reduction information is legal.
05900     if (marked_shortest_path_reduced()) {
05901       // A non-redundant constraint cannot be equal to PLUS_INFINITY.
05902       for (dimension_type i = dbm.num_rows(); i-- > 0; )
05903         for (dimension_type j = dbm.num_rows(); j-- > 0; )
05904           if (!redundancy_dbm[i][j] && is_plus_infinity(dbm[i][j])) {
05905 #ifndef NDEBUG
05906             using namespace Parma_Polyhedra_Library::IO_Operators;
05907             std::cerr << "BD_Shape::dbm[" << i << "][" << j << "] = "
05908                       << dbm[i][j] << " is marked as non-redundant!"
05909                       << std::endl;
05910 #endif
05911             return false;
05912           }
05913 
05914       BD_Shape x = *this;
05915       x.reset_shortest_path_reduced();
05916       x.shortest_path_reduction_assign();
05917       if (x.redundancy_dbm != redundancy_dbm) {
05918 #ifndef NDEBUG
05919         std::cerr << "BD_Shape is marked as reduced but it is not!"
05920                   << std::endl;
05921 #endif
05922         return false;
05923       }
05924     }
05925   }
05926 
05927   // All checks passed.
05928   return true;
05929 }

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 326 of file BD_Shape.inlines.hh.

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

00326                                         {
00327   dbm = y.dbm;
00328   status = y.status;
00329   if (y.marked_shortest_path_reduced())
00330     redundancy_dbm = y.redundancy_dbm;
00331   return *this;
00332 }

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() 
) [inline, 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 3441 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::add_dbm_constraint(), Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::deduce_u_minus_v_bounds(), Parma_Polyhedra_Library::BD_Shape< T >::deduce_v_minus_u_bounds(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

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

03444                                                                    {
03445   PPL_ASSERT(denominator != 0);
03446   const dimension_type expr_space_dim = expr.space_dimension();
03447   PPL_ASSERT(space_dimension() >= expr_space_dim);
03448   const dimension_type v = var.id() + 1;
03449   PPL_ASSERT(v <= space_dimension());
03450   PPL_ASSERT(expr.coefficient(var) == 0);
03451   PPL_ASSERT(relsym != LESS_THAN && relsym != GREATER_THAN);
03452 
03453   const Coefficient& b = expr.inhomogeneous_term();
03454   // Number of non-zero coefficients in `expr': will be set to
03455   // 0, 1, or 2, the latter value meaning any value greater than 1.
03456   dimension_type t = 0;
03457   // Index of the last non-zero coefficient in `expr', if any.
03458   dimension_type w = 0;
03459   // Get information about the number of non-zero coefficients in `expr'.
03460   for (dimension_type i = expr_space_dim; i-- > 0; )
03461     if (expr.coefficient(Variable(i)) != 0) {
03462       if (t++ == 1)
03463         break;
03464       else
03465         w = i+1;
03466     }
03467 
03468   // Since we are only able to record bounded differences, we can
03469   // precisely deal with the case of a single variable only if its
03470   // coefficient (taking into account the denominator) is 1.
03471   // If this is not the case, we fall back to the general case
03472   // so as to over-approximate the constraint.
03473   if (t == 1 && expr.coefficient(Variable(w-1)) != denominator)
03474     t = 2;
03475 
03476   // Now we know the form of `expr':
03477   // - If t == 0, then expr == b, with `b' a constant;
03478   // - If t == 1, then expr == a*w + b, where `w != v' and `a == denominator';
03479   // - If t == 2, the `expr' is of the general form.
03480   const DB_Row<N>& dbm_0 = dbm[0];
03481   PPL_DIRTY_TEMP_COEFFICIENT(minus_den);
03482   neg_assign(minus_den, denominator);
03483 
03484   if (t == 0) {
03485     // Case 1: expr == b.
03486     switch (relsym) {
03487     case EQUAL:
03488       // Add the constraint `var == b/denominator'.
03489       add_dbm_constraint(0, v, b, denominator);
03490       add_dbm_constraint(v, 0, b, minus_den);
03491       break;
03492     case LESS_OR_EQUAL:
03493       // Add the constraint `var <= b/denominator'.
03494       add_dbm_constraint(0, v, b, denominator);
03495       break;
03496     case GREATER_OR_EQUAL:
03497       // Add the constraint `var >= b/denominator',
03498       // i.e., `-var <= -b/denominator',
03499       add_dbm_constraint(v, 0, b, minus_den);
03500       break;
03501     default:
03502       // We already dealt with the other cases.
03503       throw std::runtime_error("PPL internal error");
03504     }
03505     return;
03506   }
03507 
03508   if (t == 1) {
03509     // Case 2: expr == a*w + b, w != v, a == denominator.
03510     PPL_ASSERT(expr.coefficient(Variable(w-1)) == denominator);
03511     PPL_DIRTY_TEMP(N, d);
03512     switch (relsym) {
03513     case EQUAL:
03514       // Add the new constraint `v - w <= b/denominator'.
03515       div_round_up(d, b, denominator);
03516       add_dbm_constraint(w, v, d);
03517       // Add the new constraint `v - w >= b/denominator',
03518       // i.e., `w - v <= -b/denominator'.
03519       div_round_up(d, b, minus_den);
03520       add_dbm_constraint(v, w, d);
03521       break;
03522     case LESS_OR_EQUAL:
03523       // Add the new constraint `v - w <= b/denominator'.
03524       div_round_up(d, b, denominator);
03525       add_dbm_constraint(w, v, d);
03526       break;
03527     case GREATER_OR_EQUAL:
03528       // Add the new constraint `v - w >= b/denominator',
03529       // i.e., `w - v <= -b/denominator'.
03530       div_round_up(d, b, minus_den);
03531       add_dbm_constraint(v, w, d);
03532       break;
03533     default:
03534       // We already dealt with the other cases.
03535       throw std::runtime_error("PPL internal error");
03536     }
03537     return;
03538   }
03539 
03540   // Here t == 2, so that either
03541   // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2, or
03542   // expr == a*w + b, w != v and a != denominator.
03543   const bool is_sc = (denominator > 0);
03544   PPL_DIRTY_TEMP_COEFFICIENT(minus_b);
03545   neg_assign(minus_b, b);
03546   const Coefficient& sc_b = is_sc ? b : minus_b;
03547   const Coefficient& minus_sc_b = is_sc ? minus_b : b;
03548   const Coefficient& sc_den = is_sc ? denominator : minus_den;
03549   const Coefficient& minus_sc_den = is_sc ? minus_den : denominator;
03550   // NOTE: here, for optimization purposes, `minus_expr' is only assigned
03551   // when `denominator' is negative. Do not use it unless you are sure
03552   // it has been correctly assigned.
03553   Linear_Expression minus_expr;
03554   if (!is_sc)
03555     minus_expr = -expr;
03556   const Linear_Expression& sc_expr = is_sc ? expr : minus_expr;
03557 
03558   PPL_DIRTY_TEMP(N, sum);
03559   // Indices of the variables that are unbounded in `this->dbm'.
03560   PPL_UNINITIALIZED(dimension_type, pinf_index);
03561   // Number of unbounded variables found.
03562   dimension_type pinf_count = 0;
03563 
03564   // Speculative allocation of temporaries that are used in most
03565   // of the computational traces starting from this point (also loops).
03566   PPL_DIRTY_TEMP_COEFFICIENT(minus_sc_i);
03567   PPL_DIRTY_TEMP(N, coeff_i);
03568 
03569   switch (relsym) {
03570   case EQUAL:
03571     {
03572       PPL_DIRTY_TEMP(N, neg_sum);
03573       // Indices of the variables that are unbounded in `this->dbm'.
03574       PPL_UNINITIALIZED(dimension_type, neg_pinf_index);
03575       // Number of unbounded variables found.
03576       dimension_type neg_pinf_count = 0;
03577 
03578       // Compute an upper approximation for `expr' into `sum',
03579       // taking into account the sign of `denominator'.
03580 
03581       // Approximate the inhomogeneous term.
03582       assign_r(sum, sc_b, ROUND_UP);
03583       assign_r(neg_sum, minus_sc_b, ROUND_UP);
03584 
03585       // Approximate the homogeneous part of `sc_expr'.
03586       // Note: indices above `w' can be disregarded, as they all have
03587       // a zero coefficient in `expr'.
03588       for (dimension_type i = w; i > 0; --i) {
03589         const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1));
03590         const int sign_i = sgn(sc_i);
03591         if (sign_i == 0)
03592           continue;
03593         if (sign_i > 0) {
03594           assign_r(coeff_i, sc_i, ROUND_UP);
03595           // Approximating `sc_expr'.
03596           if (pinf_count <= 1) {
03597             const N& approx_i = dbm_0[i];
03598             if (!is_plus_infinity(approx_i))
03599               add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
03600             else {
03601               ++pinf_count;
03602               pinf_index = i;
03603             }
03604           }
03605           // Approximating `-sc_expr'.
03606           if (neg_pinf_count <= 1) {
03607             const N& approx_minus_i = dbm[i][0];
03608             if (!is_plus_infinity(approx_minus_i))
03609               add_mul_assign_r(neg_sum, coeff_i, approx_minus_i, ROUND_UP);
03610             else {
03611               ++neg_pinf_count;
03612               neg_pinf_index = i;
03613             }
03614           }
03615         }
03616         else if (sign_i < 0) {
03617           neg_assign(minus_sc_i, sc_i);
03618           // Note: using temporary named `coeff_i' to store -coeff_i.
03619           assign_r(coeff_i, minus_sc_i, ROUND_UP);
03620           // Approximating `sc_expr'.
03621           if (pinf_count <= 1) {
03622             const N& approx_minus_i = dbm[i][0];
03623             if (!is_plus_infinity(approx_minus_i))
03624               add_mul_assign_r(sum, coeff_i, approx_minus_i, ROUND_UP);
03625             else {
03626               ++pinf_count;
03627               pinf_index = i;
03628             }
03629           }
03630           // Approximating `-sc_expr'.
03631           if (neg_pinf_count <= 1) {
03632             const N& approx_i = dbm_0[i];
03633             if (!is_plus_infinity(approx_i))
03634               add_mul_assign_r(neg_sum, coeff_i, approx_i, ROUND_UP);
03635             else {
03636               ++neg_pinf_count;
03637               neg_pinf_index = i;
03638             }
03639           }
03640         }
03641       }
03642       // Return immediately if no approximation could be computed.
03643       if (pinf_count > 1 && neg_pinf_count > 1) {
03644         PPL_ASSERT(OK());
03645         return;
03646       }
03647 
03648       // In the following, shortest-path closure will be definitely lost.
03649       reset_shortest_path_closed();
03650 
03651       // Before computing quotients, the denominator should be approximated
03652       // towards zero. Since `sc_den' is known to be positive, this amounts to
03653       // rounding downwards, which is achieved as usual by rounding upwards
03654       // `minus_sc_den' and negating again the result.
03655       PPL_DIRTY_TEMP(N, down_sc_den);
03656       assign_r(down_sc_den, minus_sc_den, ROUND_UP);
03657       neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
03658 
03659       // Exploit the upper approximation, if possible.
03660       if (pinf_count <= 1) {
03661         // Compute quotient (if needed).
03662         if (down_sc_den != 1)
03663           div_assign_r(sum, sum, down_sc_den, ROUND_UP);
03664         // Add the upper bound constraint, if meaningful.
03665         if (pinf_count == 0) {
03666           // Add the constraint `v <= sum'.
03667           dbm[0][v] = sum;
03668           // Deduce constraints of the form `v - u', where `u != v'.
03669           deduce_v_minus_u_bounds(v, w, sc_expr, sc_den, sum);
03670         }
03671         else
03672           // Here `pinf_count == 1'.
03673           if (pinf_index != v
03674               && sc_expr.coefficient(Variable(pinf_index-1)) == sc_den)
03675             // Add the constraint `v - pinf_index <= sum'.
03676             dbm[pinf_index][v] = sum;
03677       }
03678 
03679       // Exploit the lower approximation, if possible.
03680       if (neg_pinf_count <= 1) {
03681         // Compute quotient (if needed).
03682         if (down_sc_den != 1)
03683           div_assign_r(neg_sum, neg_sum, down_sc_den, ROUND_UP);
03684         // Add the lower bound constraint, if meaningful.
03685         if (neg_pinf_count == 0) {
03686           // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'.
03687           DB_Row<N>& dbm_v = dbm[v];
03688           dbm_v[0] = neg_sum;
03689           // Deduce constraints of the form `u - v', where `u != v'.
03690           deduce_u_minus_v_bounds(v, w, sc_expr, sc_den, neg_sum);
03691         }
03692         else
03693           // Here `neg_pinf_count == 1'.
03694           if (neg_pinf_index != v
03695               && sc_expr.coefficient(Variable(neg_pinf_index-1)) == sc_den)
03696             // Add the constraint `v - neg_pinf_index >= -neg_sum',
03697             // i.e., `neg_pinf_index - v <= neg_sum'.
03698             dbm[v][neg_pinf_index] = neg_sum;
03699       }
03700     }
03701     break;
03702 
03703   case LESS_OR_EQUAL:
03704     // Compute an upper approximation for `expr' into `sum',
03705     // taking into account the sign of `denominator'.
03706 
03707     // Approximate the inhomogeneous term.
03708     assign_r(sum, sc_b, ROUND_UP);
03709 
03710     // Approximate the homogeneous part of `sc_expr'.
03711     // Note: indices above `w' can be disregarded, as they all have
03712     // a zero coefficient in `expr'.
03713     for (dimension_type i = w; i > 0; --i) {
03714       const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1));
03715       const int sign_i = sgn(sc_i);
03716       if (sign_i == 0)
03717         continue;
03718       // Choose carefully: we are approximating `sc_expr'.
03719       const N& approx_i = (sign_i > 0) ? dbm_0[i] : dbm[i][0];
03720       if (is_plus_infinity(approx_i)) {
03721         if (++pinf_count > 1)
03722           break;
03723         pinf_index = i;
03724         continue;
03725       }
03726       if (sign_i > 0)
03727         assign_r(coeff_i, sc_i, ROUND_UP);
03728       else {
03729         neg_assign(minus_sc_i, sc_i);
03730         assign_r(coeff_i, minus_sc_i, ROUND_UP);
03731       }
03732       add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
03733     }
03734 
03735     // Divide by the (sign corrected) denominator (if needed).
03736     if (sc_den != 1) {
03737       // Before computing the quotient, the denominator should be
03738       // approximated towards zero. Since `sc_den' is known to be
03739       // positive, this amounts to rounding downwards, which is achieved
03740       // by rounding upwards `minus_sc-den' and negating again the result.
03741       PPL_DIRTY_TEMP(N, down_sc_den);
03742       assign_r(down_sc_den, minus_sc_den, ROUND_UP);
03743       neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
03744       div_assign_r(sum, sum, down_sc_den, ROUND_UP);
03745     }
03746 
03747     if (pinf_count == 0) {
03748       // Add the constraint `v <= sum'.
03749       add_dbm_constraint(0, v, sum);
03750       // Deduce constraints of the form `v - u', where `u != v'.
03751       deduce_v_minus_u_bounds(v, w, sc_expr, sc_den, sum);
03752     }
03753     else if (pinf_count == 1)
03754       if (expr.coefficient(Variable(pinf_index-1)) == denominator)
03755         // Add the constraint `v - pinf_index <= sum'.
03756         add_dbm_constraint(pinf_index, v, sum);
03757       break;
03758 
03759   case GREATER_OR_EQUAL:
03760     // Compute an upper approximation for `-sc_expr' into `sum'.
03761     // Note: approximating `-sc_expr' from above and then negating the
03762     // result is the same as approximating `sc_expr' from below.
03763 
03764     // Approximate the inhomogeneous term.
03765     assign_r(sum, minus_sc_b, ROUND_UP);
03766 
03767     // Approximate the homogeneous part of `-sc_expr'.
03768     for (dimension_type i = w; i > 0; --i) {
03769       const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1));
03770       const int sign_i = sgn(sc_i);
03771       if (sign_i == 0)
03772         continue;
03773       // Choose carefully: we are approximating `-sc_expr'.
03774       const N& approx_i = (sign_i > 0) ? dbm[i][0] : dbm_0[i];
03775       if (is_plus_infinity(approx_i)) {
03776         if (++pinf_count > 1)
03777           break;
03778         pinf_index = i;
03779         continue;
03780       }
03781       if (sign_i > 0)
03782         assign_r(coeff_i, sc_i, ROUND_UP);
03783       else {
03784         neg_assign(minus_sc_i, sc_i);
03785         assign_r(coeff_i, minus_sc_i, ROUND_UP);
03786       }
03787       add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
03788     }
03789 
03790     // Divide by the (sign corrected) denominator (if needed).
03791     if (sc_den != 1) {
03792       // Before computing the quotient, the denominator should be
03793       // approximated towards zero. Since `sc_den' is known to be positive,
03794       // this amounts to rounding downwards, which is achieved by rounding
03795       // upwards `minus_sc_den' and negating again the result.
03796       PPL_DIRTY_TEMP(N, down_sc_den);
03797       assign_r(down_sc_den, minus_sc_den, ROUND_UP);
03798       neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
03799       div_assign_r(sum, sum, down_sc_den, ROUND_UP);
03800     }
03801 
03802     if (pinf_count == 0) {
03803       // Add the constraint `v >= -sum', i.e., `-v <= sum'.
03804       add_dbm_constraint(v, 0, sum);
03805       // Deduce constraints of the form `u - v', where `u != v'.
03806       deduce_u_minus_v_bounds(v, w, sc_expr, sc_den, sum);
03807     }
03808     else if (pinf_count == 1)
03809       if (pinf_index != v
03810           && expr.coefficient(Variable(pinf_index-1)) == denominator)
03811         // Add the constraint `v - pinf_index >= -sum',
03812         // i.e., `pinf_index - v <= sum'.
03813         add_dbm_constraint(v, pinf_index, sum);
03814     break;
03815 
03816   default:
03817     // We already dealt with the other cases.
03818     throw std::runtime_error("PPL internal error");
03819   }
03820 
03821   PPL_ASSERT(OK());
03822 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check ( const Congruence cg  )  [inline, private]

Uses the congruence cg to refine *this.

Parameters:
cg The 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 238 of file BD_Shape.inlines.hh.

References Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), Parma_Polyhedra_Library::Congruence::is_proper_congruence(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::Congruence::space_dimension().

00238                                                  {
00239   PPL_ASSERT(!marked_empty());
00240   PPL_ASSERT(cg.space_dimension() <= space_dimension());
00241 
00242   if (cg.is_proper_congruence()) {
00243     if (cg.is_inconsistent())
00244       set_empty();
00245     // Other proper congruences are just ignored.
00246     return;
00247   }
00248 
00249   PPL_ASSERT(cg.is_equality());
00250   Constraint c(cg);
00251   refine_no_check(c);
00252 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check ( const Constraint c  )  [inline, private]

Uses the constraint c to refine *this.

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

Definition at line 474 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::BD_Shape< T >::extract_bounded_difference(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::Constraint::space_dimension().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_congruence(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_congruences(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_constraint(), and Parma_Polyhedra_Library::BD_Shape< T >::refine_with_constraints().

00474                                                 {
00475   PPL_ASSERT(!marked_empty());
00476   const dimension_type c_space_dim = c.space_dimension();
00477   PPL_ASSERT(c_space_dim <= space_dimension());
00478 
00479   dimension_type num_vars = 0;
00480   dimension_type i = 0;
00481   dimension_type j = 0;
00482   PPL_DIRTY_TEMP_COEFFICIENT(coeff);
00483   // Constraints that are not bounded differences are ignored.
00484   if (!extract_bounded_difference(c, c_space_dim, num_vars, i, j, coeff))
00485     return;
00486 
00487   const Coefficient& inhomo = c.inhomogeneous_term();
00488   if (num_vars == 0) {
00489     // Dealing with a trivial constraint (might be a strict inequality).
00490     if (inhomo < 0
00491         || (c.is_equality() && inhomo != 0)
00492         || (c.is_strict_inequality() && inhomo == 0))
00493       set_empty();
00494     return;
00495   }
00496 
00497   // Select the cell to be modified for the "<=" part of the constraint,
00498   // and set `coeff' to the absolute value of itself.
00499   const bool negative = (coeff < 0);
00500   N& x = negative ? dbm[i][j] : dbm[j][i];
00501   N& y = negative ? dbm[j][i] : dbm[i][j];
00502   if (negative)
00503     neg_assign(coeff);
00504 
00505   bool changed = false;
00506   // Compute the bound for `x', rounding towards plus infinity.
00507   PPL_DIRTY_TEMP(N, d);
00508   div_round_up(d, inhomo, coeff);
00509   if (x > d) {
00510     x = d;
00511     changed = true;
00512   }
00513 
00514   if (c.is_equality()) {
00515     // Also compute the bound for `y', rounding towards plus infinity.
00516     PPL_DIRTY_TEMP_COEFFICIENT(minus_c_term);
00517     neg_assign(minus_c_term, inhomo);
00518     div_round_up(d, minus_c_term, coeff);
00519     if (y > d) {
00520       y = d;
00521       changed = true;
00522     }
00523   }
00524 
00525   // In general, adding a constraint does not preserve the shortest-path
00526   // closure or reduction of the bounded difference shape.
00527   if (changed && marked_shortest_path_closed())
00528     reset_shortest_path_closed();
00529   PPL_ASSERT(OK());
00530 }

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:
cg The congruence. If it is not a bounded difference equality, it will be ignored.
Exceptions:
std::invalid_argument Thrown if *this and congruence cg are dimension-incompatible.

Definition at line 213 of file BD_Shape.inlines.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Congruence::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

00213                                                         {
00214   const dimension_type cg_space_dim = cg.space_dimension();
00215   // Dimension-compatibility check.
00216   if (cg_space_dim > space_dimension())
00217     throw_dimension_incompatible("refine_with_congruence(cg)", cg);
00218 
00219   if (!marked_empty())
00220     refine_no_check(cg);
00221 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::refine_with_congruences ( const Congruence_System cgs  )  [inline]

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

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

Definition at line 225 of file BD_Shape.inlines.hh.

References Parma_Polyhedra_Library::Congruence_System::begin(), Parma_Polyhedra_Library::Congruence_System::end(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Congruence_System::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().

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

00225                                                                  {
00226   // Dimension-compatibility check.
00227   if (cgs.space_dimension() > space_dimension())
00228     throw_generic("refine_with_congruences(cgs)",
00229                   "cgs and *this are space-dimension incompatible");
00230 
00231   for (Congruence_System::const_iterator i = cgs.begin(),
00232          cgs_end = cgs.end(); !marked_empty() && i != cgs_end; ++i)
00233     refine_no_check(*i);
00234 }

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:
c The constraint. If it is not a bounded difference, it will be ignored.
Exceptions:
std::invalid_argument Thrown if *this and constraint c are dimension-incompatible.

Definition at line 188 of file BD_Shape.inlines.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Constraint::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

00188                                                        {
00189   const dimension_type c_space_dim = c.space_dimension();
00190   // Dimension-compatibility check.
00191   if (c_space_dim > space_dimension())
00192     throw_dimension_incompatible("refine_with_constraint(c)", c);
00193 
00194   if (!marked_empty())
00195     refine_no_check(c);
00196 }

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:
cs The constraint system to be used. Constraints that are not bounded differences are ignored.
Exceptions:
std::invalid_argument Thrown if *this and cs are dimension-incompatible.

Definition at line 200 of file BD_Shape.inlines.hh.

References Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().

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

00200                                                                 {
00201   // Dimension-compatibility check.
00202   if (cs.space_dimension() > space_dimension())
00203     throw_generic("refine_with_constraints(cs)",
00204                   "cs and *this are space-dimension incompatible");
00205 
00206   for (Constraint_System::const_iterator i = cs.begin(),
00207          cs_end = cs.end(); !marked_empty() && i != cs_end; ++i)
00208     refine_no_check(*i);
00209 }

template<typename T >
Poly_Gen_Relation Parma_Polyhedra_Library::BD_Shape< T >::relation_with ( const Generator g  )  const [inline]

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

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

Definition at line 1651 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::add_mul_assign(), Parma_Polyhedra_Library::Generator::coefficient(), Parma_Polyhedra_Library::Coefficient_zero(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::Generator::divisor(), Parma_Polyhedra_Library::is_additive_inverse(), Parma_Polyhedra_Library::Generator::is_line(), Parma_Polyhedra_Library::Generator::is_line_or_ray(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::Poly_Gen_Relation::nothing(), Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::Generator::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Poly_Gen_Relation::subsumes(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

01651                                                    {
01652   const dimension_type space_dim = space_dimension();
01653   const dimension_type g_space_dim = g.space_dimension();
01654 
01655   // Dimension-compatibility check.
01656   if (space_dim < g_space_dim)
01657     throw_dimension_incompatible("relation_with(g)", g);
01658 
01659   shortest_path_closure_assign();
01660   // The empty BDS cannot subsume a generator.
01661   if (marked_empty())
01662     return Poly_Gen_Relation::nothing();
01663 
01664   // A universe BDS in a zero-dimensional space subsumes
01665   // all the generators of a zero-dimensional space.
01666   if (space_dim == 0)
01667     return Poly_Gen_Relation::subsumes();
01668 
01669   const bool is_line = g.is_line();
01670   const bool is_line_or_ray = g.is_line_or_ray();
01671 
01672   // The relation between the BDS and the given generator is obtained
01673   // checking if the generator satisfies all the constraints in the BDS.
01674   // To check if the generator satisfies all the constraints it's enough
01675   // studying the sign of the scalar product between the generator and
01676   // all the constraints in the BDS.
01677 
01678   // Allocation of temporaries done once and for all.
01679   PPL_DIRTY_TEMP_COEFFICIENT(num);
01680   PPL_DIRTY_TEMP_COEFFICIENT(den);
01681   PPL_DIRTY_TEMP_COEFFICIENT(product);
01682   // We find in `*this' all the constraints.
01683   for (dimension_type i = 0; i <= space_dim; ++i) {
01684     const Coefficient& g_coeff_y = (i > g_space_dim || i == 0)
01685       ? Coefficient_zero() : g.coefficient(Variable(i-1));
01686     const DB_Row<N>& dbm_i = dbm[i];
01687     for (dimension_type j = i + 1; j <= space_dim; ++j) {
01688       const Coefficient& g_coeff_x = (j > g_space_dim)
01689         ? Coefficient_zero() : g.coefficient(Variable(j-1));
01690       const N& dbm_ij = dbm_i[j];
01691       const N& dbm_ji = dbm[j][i];
01692       if (is_additive_inverse(dbm_ji, dbm_ij)) {
01693         // We have one equality constraint: den*x - den*y = num.
01694         // Compute the scalar product.
01695         numer_denom(dbm_ij, num, den);
01696         product = 0;
01697         add_mul_assign(product, den, g_coeff_y);
01698         add_mul_assign(product, -den, g_coeff_x);
01699         if (!is_line_or_ray)
01700           add_mul_assign(product, num, g.divisor());
01701         if (product != 0)
01702           return Poly_Gen_Relation::nothing();
01703       }
01704       else {
01705         // We have 0, 1 or 2 binary inequality constraint/s.
01706         if (!is_plus_infinity(dbm_ij)) {
01707           // We have the binary inequality constraint: den*x - den*y <= num.
01708           // Compute the scalar product.
01709           numer_denom(dbm_ij, num, den);
01710           product = 0;
01711           add_mul_assign(product, den, g_coeff_y);
01712           add_mul_assign(product, -den, g_coeff_x);
01713           if (!is_line_or_ray)
01714             add_mul_assign(product, num, g.divisor());
01715           if (is_line) {
01716             if (product != 0)
01717               // Lines must saturate all constraints.
01718               return Poly_Gen_Relation::nothing();
01719           }
01720           else
01721             // `g' is either a ray, a point or a closure point.
01722             if (product < 0)
01723               return Poly_Gen_Relation::nothing();
01724         }
01725 
01726         if (!is_plus_infinity(dbm_ji)) {
01727           // We have the binary inequality constraint: den*y - den*x <= b.
01728           // Compute the scalar product.
01729           numer_denom(dbm_ji, num, den);
01730           product = 0;
01731           add_mul_assign(product, den, g_coeff_x);
01732           add_mul_assign(product, -den, g_coeff_y);
01733           if (!is_line_or_ray)
01734             add_mul_assign(product, num, g.divisor());
01735           if (is_line) {
01736             if (product != 0)
01737               // Lines must saturate all constraints.
01738               return Poly_Gen_Relation::nothing();
01739           }
01740           else
01741             // `g' is either a ray, a point or a closure point.
01742             if (product < 0)
01743               return Poly_Gen_Relation::nothing();
01744         }
01745       }
01746     }
01747   }
01748 
01749   // The generator satisfies all the constraints.
01750   return Poly_Gen_Relation::subsumes();
01751 }

template<typename T >
Poly_Con_Relation Parma_Polyhedra_Library::BD_Shape< T >::relation_with ( const Congruence cg  )  const [inline]

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

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

Definition at line 1316 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), Parma_Polyhedra_Library::Checked::le, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::maximize(), Parma_Polyhedra_Library::BD_Shape< T >::minimize(), Parma_Polyhedra_Library::Congruence::modulus(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::BD_Shape< T >::relation_with(), Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::Congruence::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Poly_Con_Relation::strictly_intersects(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

01316                                                      {
01317   const dimension_type space_dim = space_dimension();
01318 
01319   // Dimension-compatibility check.
01320   if (cg.space_dimension() > space_dim)
01321     throw_dimension_incompatible("relation_with(cg)", cg);
01322 
01323   // If the congruence is an equality, find the relation with
01324   // the equivalent equality constraint.
01325   if (cg.is_equality()) {
01326     Constraint c(cg);
01327     return relation_with(c);
01328   }
01329 
01330   shortest_path_closure_assign();
01331 
01332   if (marked_empty())
01333     return Poly_Con_Relation::saturates()
01334       && Poly_Con_Relation::is_included()
01335       && Poly_Con_Relation::is_disjoint();
01336 
01337   if (space_dim == 0) {
01338     if (cg.is_inconsistent())
01339       return Poly_Con_Relation::is_disjoint();
01340     else
01341       return Poly_Con_Relation::saturates()
01342         && Poly_Con_Relation::is_included();
01343   }
01344 
01345   // Find the lower bound for a hyperplane with direction
01346   // defined by the congruence.
01347   Linear_Expression le = Linear_Expression(cg);
01348   PPL_DIRTY_TEMP_COEFFICIENT(min_num);
01349   PPL_DIRTY_TEMP_COEFFICIENT(min_den);
01350   bool min_included;
01351   bool bounded_below = minimize(le, min_num, min_den, min_included);
01352 
01353   // If there is no lower bound, then some of the hyperplanes defined by
01354   // the congruence will strictly intersect the shape.
01355   if (!bounded_below)
01356     return Poly_Con_Relation::strictly_intersects();
01357 
01358   // TODO: Consider adding a max_and_min() method, performing both
01359   // maximization and minimization so as to possibly exploit
01360   // incrementality of the MIP solver.
01361 
01362   // Find the upper bound for a hyperplane with direction
01363   // defined by the congruence.
01364   PPL_DIRTY_TEMP_COEFFICIENT(max_num);
01365   PPL_DIRTY_TEMP_COEFFICIENT(max_den);
01366   bool max_included;
01367   bool bounded_above = maximize(le, max_num, max_den, max_included);
01368 
01369   // If there is no upper bound, then some of the hyperplanes defined by
01370   // the congruence will strictly intersect the shape.
01371   if (!bounded_above)
01372     return Poly_Con_Relation::strictly_intersects();
01373 
01374   PPL_DIRTY_TEMP_COEFFICIENT(signed_distance);
01375 
01376   // Find the position value for the hyperplane that satisfies the congruence
01377   // and is above the lower bound for the shape.
01378   PPL_DIRTY_TEMP_COEFFICIENT(min_value);
01379   min_value = min_num / min_den;
01380   const Coefficient& modulus = cg.modulus();
01381   signed_distance = min_value % modulus;
01382   min_value -= signed_distance;
01383   if (min_value * min_den < min_num)
01384     min_value += modulus;
01385 
01386   // Find the position value for the hyperplane that satisfies the congruence
01387   // and is below the upper bound for the shape.
01388   PPL_DIRTY_TEMP_COEFFICIENT(max_value);
01389   max_value = max_num / max_den;
01390   signed_distance = max_value % modulus;
01391   max_value += signed_distance;
01392   if (max_value * max_den > max_num)
01393     max_value -= modulus;
01394 
01395   // If the upper bound value is less than the lower bound value,
01396   // then there is an empty intersection with the congruence;
01397   // otherwise it will strictly intersect.
01398   if (max_value < min_value)
01399     return Poly_Con_Relation::is_disjoint();
01400   else
01401     return Poly_Con_Relation::strictly_intersects();
01402 }

template<typename T >
Poly_Con_Relation Parma_Polyhedra_Library::BD_Shape< T >::relation_with ( const Constraint c  )  const [inline]

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

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

Definition at line 1407 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::extract_bounded_difference(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Constraint::is_inequality(), Parma_Polyhedra_Library::Constraint::is_nonstrict_inequality(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Checked::le, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::maximize(), Parma_Polyhedra_Library::BD_Shape< T >::minimize(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::numer_denom(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Constraint::space_dimension(), Parma_Polyhedra_Library::Poly_Con_Relation::strictly_intersects(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

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

01407                                                     {
01408   const dimension_type c_space_dim = c.space_dimension();
01409   const dimension_type space_dim = space_dimension();
01410 
01411   // Dimension-compatibility check.
01412   if (c_space_dim > space_dim)
01413     throw_dimension_incompatible("relation_with(c)", c);
01414 
01415   shortest_path_closure_assign();
01416 
01417   if (marked_empty())
01418     return Poly_Con_Relation::saturates()
01419       && Poly_Con_Relation::is_included()
01420       && Poly_Con_Relation::is_disjoint();
01421 
01422   if (space_dim == 0) {
01423     if ((c.is_equality() && c.inhomogeneous_term() != 0)
01424         || (c.is_inequality() && c.inhomogeneous_term() < 0))
01425       return Poly_Con_Relation::is_disjoint();
01426     else if (c.is_strict_inequality() && c.inhomogeneous_term() == 0)
01427       // The constraint 0 > 0 implicitly defines the hyperplane 0 = 0;
01428       // thus, the zero-dimensional point also saturates it.
01429       return Poly_Con_Relation::saturates()
01430         && Poly_Con_Relation::is_disjoint();
01431     else if (c.is_equality() || c.inhomogeneous_term() == 0)
01432       return Poly_Con_Relation::saturates()
01433         && Poly_Con_Relation::is_included();
01434     else
01435       // The zero-dimensional point saturates
01436       // neither the positivity constraint 1 >= 0,
01437       // nor the strict positivity constraint 1 > 0.
01438       return Poly_Con_Relation::is_included();
01439   }
01440 
01441   dimension_type num_vars = 0;
01442   dimension_type i = 0;
01443   dimension_type j = 0;
01444   PPL_DIRTY_TEMP_COEFFICIENT(coeff);
01445   if (!extract_bounded_difference(c, c_space_dim, num_vars, i, j, coeff)) {
01446     // Constraints that are not bounded differences.
01447     // Use maximize() and minimize() to do much of the work.
01448 
01449     // Find the linear expression for the constraint and use that to
01450     // find if the expression is bounded from above or below and if it
01451     // is, find the maximum and minimum values.
01452     Linear_Expression le;
01453     for (dimension_type k = c_space_dim; k-- > 0; ) {
01454       Variable vk(k);
01455       le += c.coefficient(vk) * vk;
01456     }
01457     PPL_DIRTY_TEMP(Coefficient, max_num);
01458     PPL_DIRTY_TEMP(Coefficient, max_den);
01459     bool max_included;
01460     PPL_DIRTY_TEMP(Coefficient, min_num);
01461     PPL_DIRTY_TEMP(Coefficient, min_den);
01462     bool min_included;
01463     bool bounded_above = maximize(le, max_num, max_den, max_included);
01464     bool bounded_below = minimize(le, min_num, min_den, min_included);
01465     if (!bounded_above) {
01466       if (!bounded_below)
01467         return Poly_Con_Relation::strictly_intersects();
01468       min_num += c.inhomogeneous_term() * min_den;
01469       switch (sgn(min_num)) {
01470       case 1:
01471         if (c.is_equality())
01472           return  Poly_Con_Relation::is_disjoint();
01473         return  Poly_Con_Relation::is_included();
01474       case 0:
01475         if (c.is_strict_inequality() || c.is_equality())
01476           return  Poly_Con_Relation::strictly_intersects();
01477         return  Poly_Con_Relation::is_included();
01478       case -1:
01479         return  Poly_Con_Relation::strictly_intersects();
01480       }
01481     }
01482     if (!bounded_below) {
01483       max_num += c.inhomogeneous_term() * max_den;
01484       switch (sgn(max_num)) {
01485       case 1:
01486         return  Poly_Con_Relation::strictly_intersects();
01487       case 0:
01488         if (c.is_strict_inequality())
01489           return  Poly_Con_Relation::is_disjoint();
01490         return  Poly_Con_Relation::strictly_intersects();
01491       case -1:
01492         return  Poly_Con_Relation::is_disjoint();
01493       }
01494     }
01495     else {
01496       max_num += c.inhomogeneous_term() * max_den;
01497       min_num += c.inhomogeneous_term() * min_den;
01498       switch (sgn(max_num)) {
01499       case 1:
01500         switch (sgn(min_num)) {
01501         case 1:
01502           if (c.is_equality())
01503             return  Poly_Con_Relation::is_disjoint();
01504           return  Poly_Con_Relation::is_included();
01505         case 0:
01506           if (c.is_equality())
01507             return  Poly_Con_Relation::strictly_intersects();
01508           if (c.is_strict_inequality())
01509             return  Poly_Con_Relation::strictly_intersects();
01510           return  Poly_Con_Relation::is_included();
01511         case -1:
01512           return  Poly_Con_Relation::strictly_intersects();
01513         }
01514      case 0:
01515         if (min_num == 0) {
01516           if (c.is_strict_inequality())
01517             return  Poly_Con_Relation::is_disjoint()
01518               && Poly_Con_Relation::saturates();
01519           return  Poly_Con_Relation::is_included()
01520             && Poly_Con_Relation::saturates();
01521         }
01522         if (c.is_strict_inequality())
01523           return  Poly_Con_Relation::is_disjoint();
01524         return  Poly_Con_Relation::strictly_intersects();
01525       case -1:
01526         return  Poly_Con_Relation::is_disjoint();
01527       }
01528     }
01529   }
01530 
01531   // Constraints that are bounded differences.
01532   if (num_vars == 0) {
01533     // Dealing with a trivial constraint.
01534     switch (sgn(c.inhomogeneous_term())) {
01535     case -1:
01536       return Poly_Con_Relation::is_disjoint();
01537     case 0:
01538       if (c.is_strict_inequality())
01539         return Poly_Con_Relation::saturates()
01540           && Poly_Con_Relation::is_disjoint();
01541       else
01542         return Poly_Con_Relation::saturates()
01543           && Poly_Con_Relation::is_included();
01544     case 1:
01545       if (c.is_equality())
01546         return Poly_Con_Relation::is_disjoint();
01547       else
01548         return Poly_Con_Relation::is_included();
01549     }
01550   }
01551 
01552   // Select the cell to be checked for the "<=" part of the constraint,
01553   // and set `coeff' to the absolute value of itself.
01554   const bool negative = (coeff < 0);
01555   const N& x = negative ? dbm[i][j] : dbm[j][i];
01556   const N& y = negative ? dbm[j][i] : dbm[i][j];
01557   if (negative)
01558     neg_assign(coeff);
01559   // Deduce the relation/s of the constraint `c' of the form
01560   // `coeff*v - coeff*u </<=/== c.inhomogeneous_term()'
01561   // with the respectively constraints in `*this'
01562   // `-y <= v - u <= x'.
01563   // Let `d == c.inhomogeneous_term()/coeff'
01564   // and `d1 == -c.inhomogeneous_term()/coeff'.
01565   // The following variables of mpq_class type are used to be precise
01566   // when the bds is defined by integer constraints.
01567   PPL_DIRTY_TEMP0(mpq_class, q_x);
01568   PPL_DIRTY_TEMP0(mpq_class, q_y);
01569   PPL_DIRTY_TEMP0(mpq_class, d);
01570   PPL_DIRTY_TEMP0(mpq_class, d1);
01571   PPL_DIRTY_TEMP0(mpq_class, c_den);
01572   PPL_DIRTY_TEMP0(mpq_class, q_den);
01573   assign_r(c_den, coeff, ROUND_NOT_NEEDED);
01574   assign_r(d, c.inhomogeneous_term(), ROUND_NOT_NEEDED);
01575   neg_assign_r(d1, d, ROUND_NOT_NEEDED);
01576   div_assign_r(d, d, c_den, ROUND_NOT_NEEDED);
01577   div_assign_r(d1, d1, c_den, ROUND_NOT_NEEDED);
01578 
01579   if (is_plus_infinity(x)) {
01580     if (!is_plus_infinity(y)) {
01581       // `*this' is in the following form:
01582       // `-y <= v - u'.
01583       // In this case `*this' is disjoint from `c' if
01584       // `-y > d' (`-y >= d' if c is a strict equality), i.e. if
01585       // `y < d1' (`y <= d1' if c is a strict equality).
01586       PPL_DIRTY_TEMP_COEFFICIENT(numer);
01587       PPL_DIRTY_TEMP_COEFFICIENT(denom);
01588       numer_denom(y, numer, denom);
01589       assign_r(q_den, denom, ROUND_NOT_NEEDED);
01590       assign_r(q_y, numer, ROUND_NOT_NEEDED);
01591       div_assign_r(q_y, q_y, q_den, ROUND_NOT_NEEDED);
01592       if (q_y < d1)
01593         return Poly_Con_Relation::is_disjoint();
01594       if (q_y == d1 && c.is_strict_inequality())
01595         return Poly_Con_Relation::is_disjoint();
01596     }
01597 
01598     // In all other cases `*this' intersects `c'.
01599     return Poly_Con_Relation::strictly_intersects();
01600   }
01601 
01602   // Here `x' is not plus-infinity.
01603   PPL_DIRTY_TEMP_COEFFICIENT(numer);
01604   PPL_DIRTY_TEMP_COEFFICIENT(denom);
01605   numer_denom(x, numer, denom);
01606   assign_r(q_den, denom, ROUND_NOT_NEEDED);
01607   assign_r(q_x, numer, ROUND_NOT_NEEDED);
01608   div_assign_r(q_x, q_x, q_den, ROUND_NOT_NEEDED);
01609 
01610   if (!is_plus_infinity(y)) {
01611     numer_denom(y, numer, denom);
01612     assign_r(q_den, denom, ROUND_NOT_NEEDED);
01613     assign_r(q_y, numer, ROUND_NOT_NEEDED);
01614     div_assign_r(q_y, q_y, q_den, ROUND_NOT_NEEDED);
01615     if (q_x == d && q_y == d1) {
01616       if (c.is_strict_inequality())
01617         return Poly_Con_Relation::saturates()
01618           && Poly_Con_Relation::is_disjoint();
01619       else
01620         return Poly_Con_Relation::saturates()
01621           && Poly_Con_Relation::is_included();
01622     }
01623     // `*this' is disjoint from `c' when
01624     // `-y > d' (`-y >= d' if c is a strict equality), i.e. if
01625     // `y < d1' (`y <= d1' if c is a strict equality).
01626     if (q_y < d1)
01627       return Poly_Con_Relation::is_disjoint();
01628     if (q_y == d1 && c.is_strict_inequality())
01629       return Poly_Con_Relation::is_disjoint();
01630   }
01631 
01632   // Here `y' can be also plus-infinity.
01633   // If `c' is an equality, `*this' is disjoint from `c' if
01634   // `x < d'.
01635   if (d > q_x) {
01636     if (c.is_equality())
01637       return Poly_Con_Relation::is_disjoint();
01638     else
01639       return Poly_Con_Relation::is_included();
01640   }
01641 
01642   if (d == q_x && c.is_nonstrict_inequality())
01643     return Poly_Con_Relation::is_included();
01644 
01645   // In all other cases `*this' intersects `c'.
01646   return Poly_Con_Relation::strictly_intersects();
01647 }

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_argument Thrown if new_dimension is greater than the space dimension of *this.

Definition at line 733 of file BD_Shape.inlines.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::DB_Matrix< T >::resize_no_copy(), Parma_Polyhedra_Library::BD_Shape< T >::set_zero_dim_univ(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), and Parma_Polyhedra_Library::BD_Shape< T >::map_space_dimensions().

00733                                                                         {
00734   // Dimension-compatibility check: the variable having
00735   // maximum index is the one occurring last in the set.
00736   if (new_dim > space_dimension())
00737     throw_dimension_incompatible("remove_higher_space_dimensions(nd)",
00738                                  new_dim);
00739 
00740   // The removal of no dimensions from any BDS is a no-op.
00741   // Note that this case also captures the only legal removal of
00742   // dimensions from a zero-dim space BDS.
00743   if (new_dim == space_dimension()) {
00744     PPL_ASSERT(OK());
00745     return;
00746   }
00747 
00748   // Shortest-path closure is necessary as in remove_space_dimensions().
00749   shortest_path_closure_assign();
00750   dbm.resize_no_copy(new_dim + 1);
00751 
00752   // Shortest-path closure is maintained.
00753   // TODO: see whether or not reduction can be (efficiently!) maintained too.
00754   if (marked_shortest_path_reduced())
00755     reset_shortest_path_reduced();
00756 
00757   // If we removed _all_ dimensions from a non-empty BDS,
00758   // the zero-dim universe BDS has been obtained.
00759   if (new_dim == 0 && !marked_empty())
00760     set_zero_dim_univ();
00761   PPL_ASSERT(OK());
00762 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::remove_space_dimensions ( const Variables_Set vars  )  [inline]

Removes all the specified dimensions.

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

Definition at line 2686 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::DB_Matrix< T >::resize_no_copy(), Parma_Polyhedra_Library::BD_Shape< T >::set_zero_dim_univ(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::Variables_Set::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::swap(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

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

02686                                                               {
02687   // The removal of no dimensions from any BDS is a no-op.
02688   // Note that this case also captures the only legal removal of
02689   // space dimensions from a BDS in a 0-dim space.
02690   if (vars.empty()) {
02691     PPL_ASSERT(OK());
02692     return;
02693   }
02694 
02695   const dimension_type old_space_dim = space_dimension();
02696 
02697   // Dimension-compatibility check.
02698   const dimension_type min_space_dim = vars.space_dimension();
02699   if (old_space_dim < min_space_dim)
02700     throw_dimension_incompatible("remove_space_dimensions(vs)", min_space_dim);
02701 
02702   // Shortest-path closure is necessary to keep precision.
02703   shortest_path_closure_assign();
02704 
02705   // When removing _all_ dimensions from a BDS, we obtain the
02706   // zero-dimensional BDS.
02707   const dimension_type new_space_dim = old_space_dim - vars.size();
02708   if (new_space_dim == 0) {
02709     dbm.resize_no_copy(1);
02710     if (!marked_empty())
02711       // We set the zero_dim_univ flag.
02712       set_zero_dim_univ();
02713     PPL_ASSERT(OK());
02714     return;
02715   }
02716 
02717   // Handle the case of an empty BD_Shape.
02718   if (marked_empty()) {
02719     dbm.resize_no_copy(new_space_dim + 1);
02720     PPL_ASSERT(OK());
02721     return;
02722   }
02723 
02724   // Shortest-path closure is maintained.
02725   // TODO: see whether reduction can be (efficiently!) maintained too.
02726   if (marked_shortest_path_reduced())
02727     reset_shortest_path_reduced();
02728 
02729   // For each variable to remove, we fill the corresponding column and
02730   // row by shifting respectively left and above those
02731   // columns and rows, that will not be removed.
02732   Variables_Set::const_iterator vsi = vars.begin();
02733   Variables_Set::const_iterator vsi_end = vars.end();
02734   dimension_type dst = *vsi + 1;
02735   dimension_type src = dst + 1;
02736   for (++vsi; vsi != vsi_end; ++vsi) {
02737     const dimension_type vsi_next = *vsi + 1;
02738     // All other columns and rows are moved respectively to the left
02739     // and above.
02740     while (src < vsi_next) {
02741       std::swap(dbm[dst], dbm[src]);
02742       for (dimension_type i = old_space_dim + 1; i-- > 0; ) {
02743         DB_Row<N>& dbm_i = dbm[i];
02744         assign_or_swap(dbm_i[dst], dbm_i[src]);
02745       }
02746       ++dst;
02747       ++src;
02748     }
02749     ++src;
02750   }
02751 
02752   // Moving the remaining rows and columns.
02753   while (src <= old_space_dim) {
02754     std::swap(dbm[dst], dbm[src]);
02755     for (dimension_type i = old_space_dim + 1; i-- > 0; ) {
02756       DB_Row<N>& dbm_i = dbm[i];
02757       assign_or_swap(dbm_i[dst], dbm_i[src]);
02758     }
02759     ++src;
02760     ++dst;
02761   }
02762 
02763   // Update the space dimension.
02764   dbm.resize_no_copy(new_space_dim + 1);
02765   PPL_ASSERT(OK());
02766 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed (  )  [inline, private]
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced (  )  [inline, private]
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::set_empty (  )  [inline, private]
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed (  )  [inline, private]
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_reduced (  )  [inline, private]
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::set_zero_dim_univ (  )  [inline, private]
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign (  )  const [inline, private]

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

Definition at line 1755 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::min_assign(), Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::BD_Shape< T >::set_empty(), Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_closed(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::affine_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::BD_Shape< T >::constrains(), Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::difference_assign(), Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::BD_Shape< T >::euclidean_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::frequency(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::get_limiting_shape(), Parma_Polyhedra_Library::BD_Shape< T >::is_bounded(), Parma_Polyhedra_Library::BD_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::BD_Shape< T >::is_empty(), Parma_Polyhedra_Library::BD_Shape< T >::is_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::l_infinity_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::max_min(), Parma_Polyhedra_Library::BD_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::rectilinear_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::relation_with(), Parma_Polyhedra_Library::BD_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign(), Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign(), Parma_Polyhedra_Library::BD_Shape< T >::unconstrain(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign().

01755                                                 {
01756   // Do something only if necessary.
01757   if (marked_empty() || marked_shortest_path_closed())
01758     return;
01759   const dimension_type num_dimensions = space_dimension();
01760   // Zero-dimensional BDSs are necessarily shortest-path closed.
01761   if (num_dimensions == 0)
01762     return;
01763 
01764   // Even though the BDS will not change, its internal representation
01765   // is going to be modified by the Floyd-Warshall algorithm.
01766   BD_Shape& x = const_cast<BD_Shape<T>&>(*this);
01767 
01768   // Fill the main diagonal with zeros.
01769   for (dimension_type h = num_dimensions + 1; h-- > 0; ) {
01770     PPL_ASSERT(is_plus_infinity(x.dbm[h][h]));
01771     assign_r(x.dbm[h][h], 0, ROUND_NOT_NEEDED);
01772   }
01773 
01774   PPL_DIRTY_TEMP(N, sum);
01775   for (dimension_type k = num_dimensions + 1; k-- > 0; ) {
01776     const DB_Row<N>& x_dbm_k = x.dbm[k];
01777     for (dimension_type i = num_dimensions + 1; i-- > 0; ) {
01778       DB_Row<N>& x_dbm_i = x.dbm[i];
01779       const N& x_dbm_i_k = x_dbm_i[k];
01780       if (!is_plus_infinity(x_dbm_i_k))
01781         for (dimension_type j = num_dimensions + 1; j-- > 0; ) {
01782           const N& x_dbm_k_j = x_dbm_k[j];
01783           if (!is_plus_infinity(x_dbm_k_j)) {
01784             // Rounding upward for correctness.
01785             add_assign_r(sum, x_dbm_i_k, x_dbm_k_j, ROUND_UP);
01786             min_assign(x_dbm_i[j], sum);
01787           }
01788         }
01789     }
01790   }
01791 
01792   // Check for emptiness: the BDS is empty if and only if there is a
01793   // negative value on the main diagonal of `dbm'.
01794   for (dimension_type h = num_dimensions + 1; h-- > 0; ) {
01795     N& x_dbm_hh = x.dbm[h][h];
01796     if (sgn(x_dbm_hh) < 0) {
01797       x.set_empty();
01798       return;
01799     }
01800     else {
01801       PPL_ASSERT(sgn(x_dbm_hh) == 0);
01802       // Restore PLUS_INFINITY on the main diagonal.
01803       assign_r(x_dbm_hh, PLUS_INFINITY, ROUND_NOT_NEEDED);
01804     }
01805   }
01806 
01807   // The BDS is not empty and it is now shortest-path closed.
01808   x.set_shortest_path_closed();
01809 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign (  )  const [inline, private]

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

Definition at line 1923 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::Bit_Matrix::clear(), Parma_Polyhedra_Library::Bit_Row::clear(), Parma_Polyhedra_Library::BD_Shape< T >::compute_leader_indices(), Parma_Polyhedra_Library::BD_Shape< T >::compute_predecessors(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::is_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm, Parma_Polyhedra_Library::Bit_Row::set(), Parma_Polyhedra_Library::BD_Shape< T >::set_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::swap().

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

01923                                                   {
01924   // Do something only if necessary.
01925   if (marked_shortest_path_reduced())
01926     return;
01927 
01928   const dimension_type space_dim = space_dimension();
01929   // Zero-dimensional BDSs are necessarily reduced.
01930   if (space_dim == 0)
01931     return;
01932 
01933   // First find the tightest constraints for this BDS.
01934   shortest_path_closure_assign();
01935 
01936   // If `*this' is empty, then there is nothing to reduce.
01937   if (marked_empty())
01938     return;
01939 
01940   // Step 1: compute zero-equivalence classes.
01941   // Variables corresponding to indices `i' and `j' are zero-equivalent
01942   // if they lie on a zero-weight loop; since the matrix is shortest-path
01943   // closed, this happens if and only if dbm[i][j] == -dbm[j][i].
01944   std::vector<dimension_type> predecessor;
01945   compute_predecessors(predecessor);
01946   std::vector<dimension_type> leaders;
01947   compute_leader_indices(predecessor, leaders);
01948   const dimension_type num_leaders = leaders.size();
01949 
01950   Bit_Matrix redundancy(space_dim + 1, space_dim + 1);
01951   // Init all constraints to be redundant.
01952   // TODO: provide an appropriate method to set multiple bits.
01953   Bit_Row& red_0 = redundancy[0];
01954   for (dimension_type j = space_dim + 1; j-- > 0; )
01955     red_0.set(j);
01956   for (dimension_type i = space_dim + 1; i-- > 0; )
01957     redundancy[i] = red_0;
01958 
01959   // Step 2: flag non-redundant constraints in the (zero-cycle-free)
01960   // subsystem of bounded differences having only leaders as variables.
01961   PPL_DIRTY_TEMP(N, c);
01962   for (dimension_type l_i = 0; l_i < num_leaders; ++l_i) {
01963     const dimension_type i = leaders[l_i];
01964     const DB_Row<N>& dbm_i = dbm[i];
01965     Bit_Row& redundancy_i = redundancy[i];
01966     for (dimension_type l_j = 0; l_j < num_leaders; ++l_j) {
01967       const dimension_type j = leaders[l_j];
01968       if (redundancy_i[j]) {
01969         const N& dbm_i_j = dbm_i[j];
01970         redundancy_i.clear(j);
01971         for (dimension_type l_k = 0; l_k < num_leaders; ++l_k) {
01972           const dimension_type k = leaders[l_k];
01973           add_assign_r(c, dbm_i[k], dbm[k][j], ROUND_UP);
01974           if (dbm_i_j >= c) {
01975             redundancy_i.set(j);
01976             break;
01977           }
01978         }
01979       }
01980     }
01981   }
01982 
01983   // Step 3: flag non-redundant constraints in zero-equivalence classes.
01984   // Each equivalence class must have a single 0-cycle connecting
01985   // all the equivalent variables in increasing order.
01986   std::deque<bool> dealt_with(space_dim + 1, false);
01987   for (dimension_type i = space_dim + 1; i-- > 0; )
01988     // We only need to deal with non-singleton zero-equivalence classes
01989     // that haven't already been dealt with.
01990     if (i != predecessor[i] && !dealt_with[i]) {
01991       dimension_type j = i;
01992       while (true) {
01993         const dimension_type pred_j = predecessor[j];
01994         if (j == pred_j) {
01995           // We finally found the leader of `i'.
01996           PPL_ASSERT(redundancy[i][j]);
01997           redundancy[i].clear(j);
01998           // Here we dealt with `j' (i.e., `pred_j'), but it is useless
01999           // to update `dealt_with' because `j' is a leader.
02000           break;
02001         }
02002         // We haven't found the leader of `i' yet.
02003         PPL_ASSERT(redundancy[pred_j][j]);
02004         redundancy[pred_j].clear(j);
02005         dealt_with[pred_j] = true;
02006         j = pred_j;
02007       }
02008     }
02009 
02010   // Even though shortest-path reduction is not going to change the BDS,
02011   // it might change its internal representation.
02012   BD_Shape<T>& x = const_cast<BD_Shape<T>&>(*this);
02013   std::swap(x.redundancy_dbm, redundancy);
02014   x.set_shortest_path_reduced();
02015 
02016   PPL_ASSERT(is_shortest_path_reduced());
02017 }

template<typename T >
bool Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign ( const BD_Shape< T > &  y  )  [inline]

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

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

Definition at line 2387 of file BD_Shape.templates.hh.

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

02387                                                             {
02388   BD_Shape& x = *this;
02389   const dimension_type dim = x.space_dimension();
02390   // Dimension-compatibility check.
02391   if (dim != y.space_dimension())
02392     throw_dimension_incompatible("simplify_using_context_assign(y)", y);
02393 
02394   // Filter away the zero-dimensional case.
02395   if (dim == 0) {
02396     if (y.marked_empty()) {
02397       x.set_zero_dim_univ();
02398       return false;
02399     }
02400     else
02401       return !x.marked_empty();
02402   }
02403 
02404   // Filter away the case where `x' contains `y'
02405   // (this subsumes the case when `y' is empty).
02406   y.shortest_path_closure_assign();
02407   if (x.contains(y)) {
02408     BD_Shape<T> res(dim, UNIVERSE);
02409     x.swap(res);
02410     return false;
02411   }
02412 
02413   // Filter away the case where `x' is empty.
02414   x.shortest_path_closure_assign();
02415   if (x.marked_empty()) {
02416     // Search for a constraint of `y' that is not a tautology.
02417     dimension_type i;
02418     dimension_type j;
02419     // Prefer unary constraints.
02420     i = 0;
02421     const DB_Row<N>& y_dbm_0 = y.dbm[0];
02422     for (j = 1; j <= dim; ++j) {
02423       if (!is_plus_infinity(y_dbm_0[j]))
02424         // FIXME: if N is a float or bounded integer type, then
02425         // we also need to check that we are actually able to construct
02426         // a constraint inconsistent wrt this one.
02427         goto found;
02428     }
02429     j = 0;
02430     for (i = 1; i <= dim; ++i) {
02431       if (!is_plus_infinity(y.dbm[i][0]))
02432         // FIXME: if N is a float or bounded intefer type, then
02433         // we also need to check that we are actually able to construct
02434         // a constraint inconsistent wrt this one.
02435         goto found;
02436     }
02437     // Then search binary constraints.
02438     for (i = 1; i <= dim; ++i) {
02439       const DB_Row<N>& y_dbm_i = y.dbm[i];
02440       for (j = 1; j <= dim; ++j)
02441         if (!is_plus_infinity(y_dbm_i[j]))
02442           // FIXME: if N is a float or bounded intefer type, then
02443           // we also need to check that we are actually able to construct
02444           // a constraint inconsistent wrt this one.
02445           goto found;
02446     }
02447     // Not found: we were not able to build a constraint contradicting
02448     // one of the constraints in `y': `x' cannot be enlarged.
02449     return false;
02450 
02451   found:
02452     // Found: build a new BDS contradicting the constraint found.
02453     PPL_ASSERT(i <= dim && j <= dim && (i > 0 || j > 0));
02454     BD_Shape<T> res(dim, UNIVERSE);
02455     PPL_DIRTY_TEMP(N, tmp);
02456     assign_r(tmp, 1, ROUND_UP);
02457     add_assign_r(tmp, tmp, y.dbm[i][j], ROUND_UP);
02458     PPL_ASSERT(!is_plus_infinity(tmp));
02459     // CHECKME: round down is really meant.
02460     neg_assign_r(res.dbm[j][i], tmp, ROUND_DOWN);
02461     x.swap(res);
02462     return false;
02463   }
02464 
02465   // Here `x' and `y' are not empty and shortest-path closed;
02466   // also, `x' does not contain `y'.
02467   // Let `target' be the intersection of `x' and `y'.
02468   BD_Shape<T> target = x;
02469   target.intersection_assign(y);
02470   const bool bool_result = !target.is_empty();
02471 
02472   // Compute a reduced dbm for `x' and ...
02473   x.shortest_path_reduction_assign();
02474   // ... count the non-redundant constraints.
02475   dimension_type x_num_nonredundant = (dim+1)*(dim+1);
02476   for (dimension_type i = dim + 1; i-- > 0; )
02477     x_num_nonredundant -= x.redundancy_dbm[i].count_ones();
02478   PPL_ASSERT(x_num_nonredundant > 0);
02479 
02480   // Let `yy' be a copy of `y': we will keep adding to `yy'
02481   // the non-redundant constraints of `x',
02482   // stopping as soon as `yy' becomes equal to `target'.
02483   BD_Shape<T> yy = y;
02484 
02485   // The constraints added to `yy' will be recorded in `res' ...
02486   BD_Shape<T> res(dim, UNIVERSE);
02487   // ... and we will count them too.
02488   dimension_type res_num_nonredundant = 0;
02489 
02490   // Compute leader information for `x'.
02491   std::vector<dimension_type> x_leaders;
02492   x.compute_leaders(x_leaders);
02493 
02494   // First go through the unary equality constraints.
02495   const DB_Row<N>& x_dbm_0 = x.dbm[0];
02496   DB_Row<N>& yy_dbm_0 = yy.dbm[0];
02497   DB_Row<N>& res_dbm_0 = res.dbm[0];
02498   for (dimension_type j = 1; j <= dim; ++j) {
02499     // Unary equality constraints are encoded in entries dbm_0j and dbm_j0
02500     // provided index j has special variable index 0 as its leader.
02501     if (x_leaders[j] != 0)
02502       continue;
02503     PPL_ASSERT(!is_plus_infinity(x_dbm_0[j]));
02504     if (x_dbm_0[j] < yy_dbm_0[j]) {
02505       res_dbm_0[j] = x_dbm_0[j];
02506       ++res_num_nonredundant;
02507       // Tighten context `yy' using the newly added constraint.
02508       yy_dbm_0[j] = x_dbm_0[j];
02509       yy.reset_shortest_path_closed();
02510     }
02511     PPL_ASSERT(!is_plus_infinity(x.dbm[j][0]));
02512     if (x.dbm[j][0] < yy.dbm[j][0]) {
02513       res.dbm[j][0] = x.dbm[j][0];
02514       ++res_num_nonredundant;
02515       // Tighten context `yy' using the newly added constraint.
02516       yy.dbm[j][0] = x.dbm[j][0];
02517       yy.reset_shortest_path_closed();
02518     }
02519     // Restore shortest-path closure, if it was lost.
02520     if (!yy.marked_shortest_path_closed()) {
02521       Variable var_j(j-1);
02522       yy.incremental_shortest_path_closure_assign(var_j);
02523       if (target.contains(yy)) {
02524         // Target reached: swap `x' and `res' if needed.
02525         if (res_num_nonredundant < x_num_nonredundant) {
02526           res.reset_shortest_path_closed();
02527           x.swap(res);
02528         }
02529         return bool_result;
02530       }
02531     }
02532   }
02533 
02534   // Go through the binary equality constraints.
02535   // Note: no need to consider the case i == 1.
02536   for (dimension_type i = 2; i <= dim; ++i) {
02537     const dimension_type j = x_leaders[i];
02538     if (j == i || j == 0)
02539       continue;
02540     PPL_ASSERT(!is_plus_infinity(x.dbm[i][j]));
02541     if (x.dbm[i][j] < yy.dbm[i][j]) {
02542       res.dbm[i][j] = x.dbm[i][j];
02543       ++res_num_nonredundant;
02544       // Tighten context `yy' using the newly added constraint.
02545       yy.dbm[i][j] = x.dbm[i][j];
02546       yy.reset_shortest_path_closed();
02547     }
02548     PPL_ASSERT(!is_plus_infinity(x.dbm[j][i]));
02549     if (x.dbm[j][i] < yy.dbm[j][i]) {
02550       res.dbm[j][i] = x.dbm[j][i];
02551       ++res_num_nonredundant;
02552       // Tighten context `yy' using the newly added constraint.
02553       yy.dbm[j][i] = x.dbm[j][i];
02554       yy.reset_shortest_path_closed();
02555     }
02556     // Restore shortest-path closure, if it was lost.
02557     if (!yy.marked_shortest_path_closed()) {
02558       Variable var_j(j-1);
02559       yy.incremental_shortest_path_closure_assign(var_j);
02560       if (target.contains(yy)) {
02561         // Target reached: swap `x' and `res' if needed.
02562         if (res_num_nonredundant < x_num_nonredundant) {
02563           res.reset_shortest_path_closed();
02564           x.swap(res);
02565         }
02566         return bool_result;
02567       }
02568     }
02569   }
02570 
02571   // Finally go through the (proper) inequality constraints:
02572   // both indices i and j should be leaders.
02573   for (dimension_type i = 0; i <= dim; ++i) {
02574     if (i != x_leaders[i])
02575       continue;
02576     const DB_Row<N>& x_dbm_i = x.dbm[i];
02577     const Bit_Row& x_redundancy_dbm_i = x.redundancy_dbm[i];
02578     DB_Row<N>& yy_dbm_i = yy.dbm[i];
02579     DB_Row<N>& res_dbm_i = res.dbm[i];
02580     for (dimension_type j = 0; j <= dim; ++j) {
02581       if (j != x_leaders[j] || x_redundancy_dbm_i[j])
02582         continue;
02583       N& yy_dbm_ij = yy_dbm_i[j];
02584       const N& x_dbm_ij = x_dbm_i[j];
02585       if (x_dbm_ij < yy_dbm_ij) {
02586         res_dbm_i[j] = x_dbm_ij;
02587         ++res_num_nonredundant;
02588         // Tighten context `yy' using the newly added constraint.
02589         yy_dbm_ij = x_dbm_ij;
02590         yy.reset_shortest_path_closed();
02591         PPL_ASSERT(i > 0 || j > 0);
02592         Variable var((i > 0 ? i : j) - 1);
02593         yy.incremental_shortest_path_closure_assign(var);
02594         if (target.contains(yy)) {
02595           // Target reached: swap `x' and `res' if needed.
02596           if (res_num_nonredundant < x_num_nonredundant) {
02597             res.reset_shortest_path_closed();
02598             x.swap(res);
02599           }
02600           return bool_result;
02601         }
02602       }
02603     }
02604   }
02605   // This point should be unreachable.
02606   throw std::runtime_error("PPL internal error");
02607 }

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 349 of file BD_Shape.inlines.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, and Parma_Polyhedra_Library::DB_Matrix< T >::num_rows().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_congruence(), Parma_Polyhedra_Library::BD_Shape< T >::add_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::add_dbm_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::BD_Shape< T >::affine_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::BD_Shape< T >::BFT00_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::BHZ09_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::bounds(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::BD_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::BD_Shape< T >::constrains(), Parma_Polyhedra_Library::BD_Shape< T >::constraints(), Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::BD_Shape< T >::difference_assign(), Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::BD_Shape< T >::euclidean_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::frequency(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::get_limiting_shape(), Parma_Polyhedra_Library::BD_Shape< T >::hash_code(), Parma_Polyhedra_Library::BD_Shape< T >::incremental_shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::integer_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::BD_Shape< T >::is_bounded(), Parma_Polyhedra_Library::BD_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::BD_Shape< T >::is_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::is_universe(), Parma_Polyhedra_Library::BD_Shape< T >::l_infinity_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::limited_BHMZ05_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::max_min(), Parma_Polyhedra_Library::BD_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::BD_Shape< T >::minimized_constraints(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), Parma_Polyhedra_Library::BD_Shape< T >::rectilinear_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::refine(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_congruence(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_congruences(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::relation_with(), Parma_Polyhedra_Library::BD_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign(), Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign(), Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), Parma_Polyhedra_Library::BD_Shape< T >::time_elapse_assign(), Parma_Polyhedra_Library::BD_Shape< T >::unconstrain(), Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign_if_exact().

00349                                    {
00350   return dbm.num_rows() - 1;
00351 }

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_argument Thrown if *this and y are dimension-incompatible.

Definition at line 701 of file BD_Shape.inlines.hh.

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

00701                                                       {
00702   const BD_Shape<T>& x = *this;
00703   return x.contains(y) && !y.contains(x);
00704 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::swap ( BD_Shape< T > &  y  )  [inline]
template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible ( const char *  method,
const char *  name_row,
const Linear_Expression y 
) const [inline, private]

Definition at line 6000 of file BD_Shape.templates.hh.

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

06002                                                                             {
06003   std::ostringstream s;
06004   s << "PPL::BD_Shape::" << method << ":" << std::endl
06005     << "this->space_dimension() == " << space_dimension()
06006     << ", " << name_row << "->space_dimension() == "
06007     << y.space_dimension() << ".";
06008   throw std::invalid_argument(s.str());
06009 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible ( const char *  method,
const Generator g 
) const [inline, private]

Definition at line 5977 of file BD_Shape.templates.hh.

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

05978                                                                     {
05979   std::ostringstream s;
05980   s << "PPL::BD_Shape::" << method << ":" << std::endl
05981     << "this->space_dimension() == " << space_dimension()
05982     << ", g->space_dimension == " << g.space_dimension() << ".";
05983   throw std::invalid_argument(s.str());
05984 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible ( const char *  method,
const Congruence cg 
) const [inline, private]

Definition at line 5966 of file BD_Shape.templates.hh.

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

05967                                                                       {
05968   std::ostringstream s;
05969   s << "PPL::BD_Shape::" << method << ":" << std::endl
05970     << "this->space_dimension() == " << space_dimension()
05971     << ", cg->space_dimension == " << cg.space_dimension() << ".";
05972   throw std::invalid_argument(s.str());
05973 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible ( const char *  method,
const Constraint c 
) const [inline, private]

Definition at line 5955 of file BD_Shape.templates.hh.

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

05956                                                                      {
05957   std::ostringstream s;
05958   s << "PPL::BD_Shape::" << method << ":" << std::endl
05959     << "this->space_dimension() == " << space_dimension()
05960     << ", c->space_dimension == " << c.space_dimension() << ".";
05961   throw std::invalid_argument(s.str());
05962 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible ( const char *  method,
dimension_type  required_dim 
) const [inline, private]

Definition at line 5944 of file BD_Shape.templates.hh.

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

05945                                                                              {
05946   std::ostringstream s;
05947   s << "PPL::BD_Shape::" << method << ":" << std::endl
05948     << "this->space_dimension() == " << space_dimension()
05949     << ", required dimension == " << required_dim << ".";
05950   throw std::invalid_argument(s.str());
05951 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible ( const char *  method,
const BD_Shape< T > &  x 
) const [inline, private]

Definition at line 5933 of file BD_Shape.templates.hh.

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

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_congruence(), Parma_Polyhedra_Library::BD_Shape< T >::add_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::bounds(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::BD_Shape< T >::constrains(), Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::difference_assign(), Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::BD_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::frequency(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::integer_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::BD_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::BD_Shape< T >::limited_BHMZ05_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::limited_CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::max_min(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_congruence(), Parma_Polyhedra_Library::BD_Shape< T >::refine_with_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::relation_with(), Parma_Polyhedra_Library::BD_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign(), Parma_Polyhedra_Library::BD_Shape< T >::time_elapse_assign(), Parma_Polyhedra_Library::BD_Shape< T >::unconstrain(), Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign_if_exact().

05934                                                                    {
05935   std::ostringstream s;
05936   s << "PPL::BD_Shape::" << method << ":" << std::endl
05937     << "this->space_dimension() == " << space_dimension()
05938     << ", y->space_dimension() == " << y.space_dimension() << ".";
05939   throw std::invalid_argument(s.str());
05940 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::throw_expression_too_complex ( const char *  method,
const Linear_Expression e 
) [inline, static, private]

Definition at line 5988 of file BD_Shape.templates.hh.

05989                                                                       {
05990   using namespace IO_Operators;
05991   std::ostringstream s;
05992   s << "PPL::BD_Shape::" << method << ":" << std::endl
05993     << e << " is too complex.";
05994   throw std::invalid_argument(s.str());
05995 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::throw_generic ( const char *  method,
const char *  reason 
) [inline, static, private]
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_argument Thrown if *this and y are dimension-incompatible.

Definition at line 686 of file BD_Shape.inlines.hh.

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

00686                                                  {
00687   // Dimension-compatibility check.
00688   if (space_dimension() != y.space_dimension())
00689     throw_dimension_incompatible("time_elapse_assign(y)", y);
00690   // See the polyhedra documentation.
00691   C_Polyhedron px(constraints());
00692   C_Polyhedron py(y.constraints());
00693   px.time_elapse_assign(py);
00694   BD_Shape<T> x(px);
00695   swap(x);
00696   PPL_ASSERT(OK());
00697 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::topological_closure_assign (  )  [inline]

Assigns to *this its topological closure.

Definition at line 418 of file BD_Shape.inlines.hh.

00418                                         {
00419 }

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 830 of file BD_Shape.inlines.hh.

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

00830                                          {
00831   return sizeof(*this) + external_memory_in_bytes();
00832 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::unconstrain ( const Variables_Set vars  )  [inline]

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

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

Definition at line 3412 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::forget_all_dbm_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Variables_Set::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

03412                                                   {
03413   // The cylindrification wrt no dimensions is a no-op.
03414   // This case captures the only legal cylindrification in a 0-dim space.
03415   if (vars.empty())
03416     return;
03417 
03418   // Dimension-compatibility check.
03419   const dimension_type min_space_dim = vars.space_dimension();
03420   if (space_dimension() < min_space_dim)
03421     throw_dimension_incompatible("unconstrain(vs)", min_space_dim);
03422 
03423   // Shortest-path closure is necessary to detect emptiness
03424   // and all (possibly implicit) constraints.
03425   shortest_path_closure_assign();
03426 
03427   // If the shape is empty, this is a no-op.
03428   if (marked_empty())
03429     return;
03430 
03431   for (Variables_Set::const_iterator vsi = vars.begin(),
03432          vsi_end = vars.end(); vsi != vsi_end; ++vsi)
03433     forget_all_dbm_constraints(*vsi + 1);
03434   // Shortest-path closure is preserved, but not reduction.
03435   reset_shortest_path_reduced();
03436   PPL_ASSERT(OK());
03437 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::unconstrain ( Variable  var  )  [inline]

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

Parameters:
var The space dimension that will be unconstrained.
Exceptions:
std::invalid_argument Thrown if var is not a space dimension of *this.

Definition at line 3390 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::forget_all_dbm_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

03390                                            {
03391   // Dimension-compatibility check.
03392   const dimension_type var_space_dim = var.space_dimension();
03393   if (space_dimension() < var_space_dim)
03394     throw_dimension_incompatible("unconstrain(var)", var_space_dim);
03395 
03396   // Shortest-path closure is necessary to detect emptiness
03397   // and all (possibly implicit) constraints.
03398   shortest_path_closure_assign();
03399 
03400   // If the shape is empty, this is a no-op.
03401   if (marked_empty())
03402     return;
03403 
03404   forget_all_dbm_constraints(var_space_dim);
03405   // Shortest-path closure is preserved, but not reduction.
03406   reset_shortest_path_reduced();
03407   PPL_ASSERT(OK());
03408 }

template<typename T >
void Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign ( const BD_Shape< T > &  y  )  [inline]

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

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

Definition at line 2021 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BFT00_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::BHZ09_upper_bound_assign_if_exact(), and Parma_Polyhedra_Library::BD_Shape< T >::difference_assign().

02021                                                  {
02022   const dimension_type space_dim = space_dimension();
02023 
02024   // Dimension-compatibility check.
02025   if (space_dim != y.space_dimension())
02026     throw_dimension_incompatible("upper_bound_assign(y)", y);
02027 
02028   // The upper bound of a BD shape `bd' with an empty shape is `bd'.
02029   y.shortest_path_closure_assign();
02030   if (y.marked_empty())
02031     return;
02032   shortest_path_closure_assign();
02033   if (marked_empty()) {
02034     *this = y;
02035     return;
02036   }
02037 
02038   // The bds-hull consists in constructing `*this' with the maximum
02039   // elements selected from `*this' and `y'.
02040   PPL_ASSERT(space_dim == 0 || marked_shortest_path_closed());
02041   for (dimension_type i = space_dim + 1; i-- > 0; ) {
02042     DB_Row<N>& dbm_i = dbm[i];
02043     const DB_Row<N>& y_dbm_i = y.dbm[i];
02044     for (dimension_type j = space_dim + 1; j-- > 0; ) {
02045       N& dbm_ij = dbm_i[j];
02046       const N& y_dbm_ij = y_dbm_i[j];
02047       if (dbm_ij < y_dbm_ij)
02048         dbm_ij = y_dbm_ij;
02049     }
02050   }
02051   // Shortest-path closure is maintained (if it was holding).
02052   // TODO: see whether reduction can be (efficiently!) maintained too.
02053   if (marked_shortest_path_reduced())
02054     reset_shortest_path_reduced();
02055   PPL_ASSERT(OK());
02056 }

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_argument Thrown if *this and y are dimension-incompatible.

Definition at line 708 of file BD_Shape.inlines.hh.

References Parma_Polyhedra_Library::BD_Shape< T >::BFT00_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

00708                                                           {
00709   if (space_dimension() != y.space_dimension())
00710     throw_dimension_incompatible("upper_bound_assign_if_exact(y)", y);
00711 #if 0
00712   return BFT00_upper_bound_assign_if_exact(y);
00713 #else
00714   const bool integer_upper_bound = false;
00715   return BHZ09_upper_bound_assign_if_exact<integer_upper_bound>(y);
00716 #endif
00717 }

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 810 of file BD_Shape.inlines.hh.

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

00810                                                             {
00811   H79_widening_assign(y, tp);
00812 }

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 pcs = 0,
unsigned  complexity_threshold = 16,
bool  wrap_individually = true 
) [inline]

Wraps the specified dimensions of the vector space.

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

Definition at line 766 of file BD_Shape.inlines.hh.

00772                                                  {
00773   Implementation::wrap_assign(*this,
00774                               vars, w, r, o, pcs,
00775                               complexity_threshold, wrap_individually,
00776                               "BD_Shape");
00777 }


Friends And Related Function Documentation

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.

Definition at line 87 of file BD_Shape.cc.

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

00088                                                                 {
00089   // The vector `indices' contains one entry for each equivalence
00090   // class, storing the index of the corresponding leader in
00091   // increasing order: it is used to avoid repeated tests for leadership.
00092   PPL_ASSERT(indices.size() == 0);
00093   PPL_ASSERT(0 == predecessor[0]);
00094   indices.push_back(0);
00095   for (dimension_type i = 1, p_size = predecessor.size(); i != p_size; ++i)
00096     if (i == predecessor[i])
00097       indices.push_back(i);
00098 }

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.

Definition at line 528 of file BD_Shape.inlines.hh.

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

00534                                       {
00535   const dimension_type x_space_dim = x.space_dimension();
00536   // Dimension-compatibility check.
00537   if (x_space_dim != y.space_dimension())
00538     return false;
00539 
00540   // Zero-dim BDSs are equal if and only if they are both empty or universe.
00541   if (x_space_dim == 0) {
00542     if (x.marked_empty() == y.marked_empty())
00543       assign_r(r, 0, ROUND_NOT_NEEDED);
00544     else
00545       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
00546     return true;
00547   }
00548 
00549   // The distance computation requires shortest-path closure.
00550   x.shortest_path_closure_assign();
00551   y.shortest_path_closure_assign();
00552 
00553   // If one of two BDSs is empty, then they are equal if and only if
00554   // the other BDS is empty too.
00555   if (x.marked_empty() ||  y.marked_empty()) {
00556    if (x.marked_empty() == y.marked_empty())
00557       assign_r(r, 0, ROUND_NOT_NEEDED);
00558     else
00559       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
00560    return true;
00561   }
00562 
00563   return euclidean_distance_assign(r, x.dbm, y.dbm, dir, tmp0, tmp1, tmp2);
00564 }

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>.

If the euclidean distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.

The direction of the approximation is specified by dir.

All computations are performed using variables of type Checked_Number<Temp, Extended_Number_Policy>.

Definition at line 569 of file BD_Shape.inlines.hh.

00572                                                   {
00573   typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
00574   PPL_DIRTY_TEMP(Checked_Temp, tmp0);
00575   PPL_DIRTY_TEMP(Checked_Temp, tmp1);
00576   PPL_DIRTY_TEMP(Checked_Temp, tmp2);
00577   return euclidean_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
00578 }

template<typename T>
bool extract_bounded_difference ( const Constraint c,
dimension_type  c_space_dim,
dimension_type c_num_vars,
dimension_type c_first_var,
dimension_type c_second_var,
Coefficient c_coeff 
) [related]

Decodes the constraint c as a bounded difference.

Returns:
true if the constraint c is a bounded difference; false otherwise.
Parameters:
c The constraint to be decoded.
c_space_dim The space dimension of the constraint c (it is assumed to match the actual space dimension of c).
c_num_vars If true is returned, then it will be set to the number of variables having a non-zero coefficient. The only legal values will therefore be 0, 1 and 2.
c_first_var If true is returned and if c_num_vars is not set to 0, then it will be set to the index of the first variable having a non-zero coefficient in c.
c_second_var If true is returned and if c_num_vars is set to 2, then it will be set to the index of the second variable having a non-zero coefficient in c.
c_coeff If true is returned and if c_num_vars is not set to 0, then it will be set to the value of the first non-zero coefficient in c.

Definition at line 33 of file BD_Shape.cc.

References Parma_Polyhedra_Library::Constraint::coefficient(), and Parma_Polyhedra_Library::Constraint::space_dimension().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::bounds(), Parma_Polyhedra_Library::BD_Shape< T >::get_limiting_shape(), Parma_Polyhedra_Library::BD_Shape< T >::max_min(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), and Parma_Polyhedra_Library::BD_Shape< T >::relation_with().

00038                                                       {
00039   // Check for preconditions.
00040   PPL_ASSERT(c.space_dimension() == c_space_dim);
00041   PPL_ASSERT(c_num_vars == 0 && c_first_var == 0 && c_second_var == 0);
00042   // Store the indices of the non-zero components of `c',
00043   dimension_type non_zero_index[2] = { 0, 0 };
00044   // Collect the non-zero components of `c'.
00045   for (dimension_type i = c_space_dim; i-- > 0; )
00046     if (c.coefficient(Variable(i)) != 0) {
00047       if (c_num_vars <= 1)
00048         non_zero_index[c_num_vars++] = i + 1;
00049       else
00050         // Constraint `c' is not a bounded difference.
00051         return false;
00052     }
00053 
00054   // Make sure that `c' is indeed a bounded difference,
00055   // i.e., it has one of the following forms:
00056   //           0 <=/= b, if c_num_vars == 0;
00057   //   a*x       <=/= b, if c_num_vars == 1;
00058   //   a*x - a*y <=/= b, if c_num_vars == 2.
00059   switch (c_num_vars) {
00060   case 2:
00061     {
00062       const Coefficient& c0 = c.coefficient(Variable(non_zero_index[0]-1));
00063       const Coefficient& c1 = c.coefficient(Variable(non_zero_index[1]-1));
00064       if (sgn(c0) == sgn(c1) || c0 != -c1)
00065         // Constraint `c' is not a bounded difference.
00066         return false;
00067       c_coeff = c1;
00068     }
00069     c_first_var = non_zero_index[0];
00070     c_second_var = non_zero_index[1];
00071     break;
00072   case 1:
00073     c_coeff = -c.coefficient(Variable(non_zero_index[0]-1));
00074     c_first_var = non_zero_index[0];
00075     break;
00076   default:
00077     PPL_ASSERT(c_num_vars == 0);
00078     break;
00079   }
00080   return true;
00081 }

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.

Definition at line 593 of file BD_Shape.inlines.hh.

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

00599                                        {
00600   const dimension_type x_space_dim = x.space_dimension();
00601   // Dimension-compatibility check.
00602   if (x_space_dim != y.space_dimension())
00603     return false;
00604 
00605   // Zero-dim BDSs are equal if and only if they are both empty or universe.
00606   if (x_space_dim == 0) {
00607     if (x.marked_empty() == y.marked_empty())
00608       assign_r(r, 0, ROUND_NOT_NEEDED);
00609     else
00610       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
00611     return true;
00612   }
00613 
00614   // The distance computation requires shortest-path closure.
00615   x.shortest_path_closure_assign();
00616   y.shortest_path_closure_assign();
00617 
00618   // If one of two BDSs is empty, then they are equal if and only if
00619   // the other BDS is empty too.
00620   if (x.marked_empty() ||  y.marked_empty()) {
00621    if (x.marked_empty() == y.marked_empty())
00622       assign_r(r, 0, ROUND_NOT_NEEDED);
00623     else
00624       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
00625    return true;
00626   }
00627 
00628   return l_infinity_distance_assign(r, x.dbm, y.dbm, dir, tmp0, tmp1, tmp2);
00629 }

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>.

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>.

Definition at line 634 of file BD_Shape.inlines.hh.

00637                                                    {
00638   typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
00639   PPL_DIRTY_TEMP(Checked_Temp, tmp0);
00640   PPL_DIRTY_TEMP(Checked_Temp, tmp1);
00641   PPL_DIRTY_TEMP(Checked_Temp, tmp2);
00642   return l_infinity_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
00643 }

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 aren't the same BDS.

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

Definition at line 456 of file BD_Shape.inlines.hh.

00456                                                        {
00457   return !(x == y);
00458 }

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

Output operator.

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

Definition at line 5702 of file BD_Shape.templates.hh.

References Parma_Polyhedra_Library::is_additive_inverse(), and Parma_Polyhedra_Library::is_plus_infinity().

05702                                                             {
05703   typedef typename BD_Shape<T>::coefficient_type N;
05704   if (c.is_universe())
05705     s << "true";
05706   else {
05707     // We control empty bounded difference shape.
05708     dimension_type n = c.space_dimension();
05709     if (c.marked_empty())
05710       s << "false";
05711     else {
05712       PPL_DIRTY_TEMP(N, v);
05713       bool first = true;
05714       for (dimension_type i = 0; i <= n; ++i)
05715         for (dimension_type j = i + 1; j <= n; ++j) {
05716           const N& c_i_j = c.dbm[i][j];
05717           const N& c_j_i = c.dbm[j][i];
05718           if (is_additive_inverse(c_j_i, c_i_j)) {
05719             // We will print an equality.
05720             if (first)
05721               first = false;
05722             else
05723               s << ", ";
05724             if (i == 0) {
05725               // We have got a equality constraint with one variable.
05726               s << Variable(j - 1);
05727               s << " = " << c_i_j;
05728             }
05729             else {
05730               // We have got a equality constraint with two variables.
05731               if (sgn(c_i_j) >= 0) {
05732                 s << Variable(j - 1);
05733                 s << " - ";
05734                 s << Variable(i - 1);
05735                 s << " = " << c_i_j;
05736               }
05737               else {
05738                 s << Variable(i - 1);
05739                 s << " - ";
05740                 s << Variable(j - 1);
05741                 s << " = " << c_j_i;
05742               }
05743             }
05744           }
05745           else {
05746             // We will print a non-strict inequality.
05747             if (!is_plus_infinity(c_j_i)) {
05748               if (first)
05749                 first = false;
05750               else
05751                 s << ", ";
05752               if (i == 0) {
05753                 // We have got a constraint with only one variable.
05754                 s << Variable(j - 1);
05755                 neg_assign_r(v, c_j_i, ROUND_DOWN);
05756                 s << " >= " << v;
05757               }
05758               else {
05759                 // We have got a constraint with two variables.
05760                 if (sgn(c_j_i) >= 0) {
05761                   s << Variable(i - 1);
05762                   s << " - ";
05763                   s << Variable(j - 1);
05764                   s << " <= " << c_j_i;
05765                 }
05766                 else {
05767                   s << Variable(j - 1);
05768                   s << " - ";
05769                   s << Variable(i - 1);
05770                   neg_assign_r(v, c_j_i, ROUND_DOWN);
05771                   s << " >= " << v;
05772                 }
05773               }
05774             }
05775             if (!is_plus_infinity(c_i_j)) {
05776               if (first)
05777                 first = false;
05778               else
05779                 s << ", ";
05780               if (i == 0) {
05781                 // We have got a constraint with only one variable.
05782                 s << Variable(j - 1);
05783                 s << " <= " << c_i_j;
05784               }
05785               else {
05786                 // We have got a constraint with two variables.
05787                 if (sgn(c_i_j) >= 0) {
05788                   s << Variable(j - 1);
05789                   s << " - ";
05790                   s << Variable(i - 1);
05791                   s << " <= " << c_i_j;
05792                 }
05793                 else {
05794                   s << Variable(i - 1);
05795                   s << " - ";
05796                   s << Variable(j - 1);
05797                   neg_assign_r(v, c_i_j, ROUND_DOWN);
05798                   s << " >= " << v;
05799                 }
05800               }
05801             }
05802           }
05803         }
05804     }
05805   }
05806   return s;
05807 }

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

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

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

Definition at line 424 of file BD_Shape.inlines.hh.

00424                                                        {
00425   const dimension_type x_space_dim = x.space_dimension();
00426   // Dimension-compatibility check.
00427   if (x_space_dim != y.space_dimension())
00428     return false;
00429 
00430   // Zero-dim BDSs are equal if and only if they are both empty or universe.
00431   if (x_space_dim == 0) {
00432     if (x.marked_empty())
00433       return y.marked_empty();
00434     else
00435       return !y.marked_empty();
00436   }
00437 
00438   // The exact equivalence test requires shortest-path closure.
00439   x.shortest_path_closure_assign();
00440   y.shortest_path_closure_assign();
00441 
00442   // If one of two BDSs is empty, then they are equal
00443   // if and only if the other BDS is empty too.
00444   if (x.marked_empty())
00445     return y.marked_empty();
00446   if (y.marked_empty())
00447     return false;
00448   // Check for syntactic equivalence of the two (shortest-path closed)
00449   // systems of bounded differences.
00450   return x.dbm == y.dbm;
00451 }

template<typename T>
friend class Parma_Polyhedra_Library::BD_Shape [friend]

Definition at line 1800 of file BD_Shape.defs.hh.

template<typename T>
friend class Parma_Polyhedra_Library::Box [friend]

Definition at line 1801 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 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.

Definition at line 463 of file BD_Shape.inlines.hh.

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

00469                                         {
00470   const dimension_type x_space_dim = x.space_dimension();
00471   // Dimension-compatibility check.
00472   if (x_space_dim != y.space_dimension())
00473     return false;
00474 
00475   // Zero-dim BDSs are equal if and only if they are both empty or universe.
00476   if (x_space_dim == 0) {
00477     if (x.marked_empty() == y.marked_empty())
00478       assign_r(r, 0, ROUND_NOT_NEEDED);
00479     else
00480       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
00481     return true;
00482   }
00483 
00484   // The distance computation requires shortest-path closure.
00485   x.shortest_path_closure_assign();
00486   y.shortest_path_closure_assign();
00487 
00488   // If one of two BDSs is empty, then they are equal if and only if
00489   // the other BDS is empty too.
00490   if (x.marked_empty() ||  y.marked_empty()) {
00491    if (x.marked_empty() == y.marked_empty())
00492       assign_r(r, 0, ROUND_NOT_NEEDED);
00493     else
00494       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
00495    return true;
00496   }
00497 
00498   return rectilinear_distance_assign(r, x.dbm, y.dbm, dir, tmp0, tmp1, tmp2);
00499 }

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>.

If the rectilinear distance between x and y is defined, stores an approximation of it into r and returns true; returns false otherwise.

The direction of the approximation is specified by dir.

All computations are performed using variables of type Checked_Number<Temp, Extended_Number_Policy>.

Definition at line 504 of file BD_Shape.inlines.hh.

00507                                                     {
00508   typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
00509   PPL_DIRTY_TEMP(Checked_Temp, tmp0);
00510   PPL_DIRTY_TEMP(Checked_Temp, tmp1);
00511   PPL_DIRTY_TEMP(Checked_Temp, tmp2);
00512   return rectilinear_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
00513 }

template<typename T >
void swap ( Parma_Polyhedra_Library::BD_Shape< T > &  x,
Parma_Polyhedra_Library::BD_Shape< T > &  y 
) [related]

Specializes std::swap.

Definition at line 858 of file BD_Shape.inlines.hh.

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

00859                                             {
00860   x.swap(y);
00861 }


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 1804 of file BD_Shape.defs.hh.

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::add_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::add_dbm_constraint(), Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::BD_Shape< T >::add_space_dimensions_and_project(), Parma_Polyhedra_Library::BD_Shape< T >::affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::ascii_dump(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::BD_Shape< T >::BFT00_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::BHZ09_upper_bound_assign_if_exact(), Parma_Polyhedra_Library::BD_Shape< T >::bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_extrapolation_assign(), Parma_Polyhedra_Library::BD_Shape< T >::CC76_narrowing_assign(), Parma_Polyhedra_Library::BD_Shape< T >::concatenate_assign(), Parma_Polyhedra_Library::BD_Shape< T >::constrains(), Parma_Polyhedra_Library::BD_Shape< T >::constraints(), Parma_Polyhedra_Library::BD_Shape< T >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::contains_integer_point(), Parma_Polyhedra_Library::BD_Shape< T >::drop_some_non_integer_points(), Parma_Polyhedra_Library::BD_Shape< T >::euclidean_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::expand_space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::external_memory_in_bytes(), Parma_Polyhedra_Library::BD_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::forget_all_dbm_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::forget_binary_dbm_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::frequency(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::get_limiting_shape(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::BD_Shape< T >::is_bounded(), Parma_Polyhedra_Library::BD_Shape< T >::is_disjoint_from(), Parma_Polyhedra_Library::BD_Shape< T >::is_shortest_path_reduced(), Parma_Polyhedra_Library::BD_Shape< T >::is_universe(), Parma_Polyhedra_Library::BD_Shape< T >::l_infinity_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::map_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::max_min(), Parma_Polyhedra_Library::BD_Shape< T >::minimized_congruences(), Parma_Polyhedra_Library::BD_Shape< T >::minimized_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::OK(), Parma_Polyhedra_Library::BD_Shape< T >::operator=(), Parma_Polyhedra_Library::BD_Shape< T >::rectilinear_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::refine(), Parma_Polyhedra_Library::BD_Shape< T >::refine_no_check(), Parma_Polyhedra_Library::BD_Shape< T >::relation_with(), Parma_Polyhedra_Library::BD_Shape< T >::remove_higher_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::remove_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign(), Parma_Polyhedra_Library::BD_Shape< T >::simplify_using_context_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::swap(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign().

template<typename T>
Bit_Matrix Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm [private]
template<typename T>
Status Parma_Polyhedra_Library::BD_Shape< T >::status [private]

The documentation for this class was generated from the following files:
Generated on Sun Feb 27 16:20:31 2011 for PPL by  doxygen 1.6.3