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.

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)

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 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.
bool add_constraint_and_minimize (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 (without minimizing the result).
bool add_congruence_and_minimize (const Congruence &cg)
 Adds a copy of congruence cg to the system of congruences of *this, minimizing the result.
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 (without minimizing the result).
bool add_constraints_and_minimize (const Constraint_System &cs)
 Adds the constraints in cs to the system of bounded differences defining *this.
bool add_recycled_constraints_and_minimize (Constraint_System &cs)
 Adds the constraints in cs to the system of constraints of *this, minimizing the result.
void add_congruences (const Congruence_System &cgs)
 Adds to *this constraints equivalent to the congruences in cgs (without minimizing the result).
bool add_congruences_and_minimize (const Congruence_System &cs)
 Adds a copy of the congruences in cs to the system of congruences of *this, minimizing the result.
void add_recycled_congruences (Congruence_System &cgs)
 Adds the congruences in cs to the system of congruences of *this (without minimizing the result).
bool add_recycled_congruences_and_minimize (Congruence_System &cgs)
 Adds the congruences in cs to the system of congruences of *this, minimizing the result.
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 &to_be_unconstrained)
 Computes the cylindrification of *this with respect to the set of space dimensions to_be_unconstrained, assigning the result to *this.
void intersection_assign (const BD_Shape &y)
 Assigns to *this the intersection of *this and y.
bool intersection_assign_and_minimize (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_and_minimize (const BD_Shape &y)
 Assigns to *this the smallest BDS containing the convex 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.
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 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 &to_be_removed)
 Removes all the specified dimensions.
void remove_higher_space_dimensions (dimension_type new_dimension)
 Removes the higher dimensions so that the resulting space will have dimension new_dimension.
template<typename Partial_Function>
void map_space_dimensions (const Partial_Function &pfunc)
 Remaps the dimensions of the vector space according to a partial function.
void expand_space_dimension (Variable var, dimension_type m)
 Creates m copies of the space dimension corresponding to var.
void fold_space_dimensions (const Variables_Set &to_be_folded, Variable var)
 Folds the space dimensions in to_be_folded into var.

Static Public Member Functions

static dimension_type max_space_dimension ()
 Returns the maximum space dimension that 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,
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.
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.
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.

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 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 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 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 & operator<< (std::ostream &s, const BD_Shape< T > &c)
 Output operator.

Related Functions

(Note that these are not member functions.)

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.

Classes

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


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. At the interface level, bounded differences are specified using objects of type Constraint: such a constraint is a bounded difference if it is of 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 Constraint object will be mapped into a correct approximation that, depending on the expressive power of the chosen template argument T, may loose some precision. In particular, constraint objects that do not encode a bounded difference will be simply (and safely) ignored.

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

On the other hand, a Constraint object encoding $3x - y \leq 1$ will be safely ignored in all of the above cases.

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

    Variable x(0);
    Variable y(1);
    Variable z(2);

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 considered, the following code will build the same BDS as above (i.e., the constraints 7, 8, and 9 are ignored):
    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 392 of file BD_Shape.defs.hh.


Member Typedef Documentation

template<typename T>
typedef Checked_Number<T, 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 398 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 402 of file BD_Shape.defs.hh.

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 408 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 112 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().

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

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

00128   : dbm(y.dbm), status(y.status), redundancy_dbm() {
00129   if (y.marked_shortest_path_reduced())
00130     redundancy_dbm = y.redundancy_dbm;
00131 }

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 136 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().

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

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 constraints: constraints that are not bounded differences are ignored (even though they may have contributed to the space dimension).
Exceptions:
std::invalid_argument Thrown if the system of constraints cs contains strict inequalities.

Definition at line 309 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().

00310   : dbm(cs.space_dimension() + 1), status(), redundancy_dbm() {
00311   if (cs.space_dimension() > 0)
00312     // A (non zero-dim) universe BDS is shortest-path closed.
00313     set_shortest_path_closed();
00314   add_constraints(cs);
00315 }

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: some elements may be safely ignored.

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

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

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

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 55 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(), 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().

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

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 173 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, 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(), TEMP_INTEGER, and Parma_Polyhedra_Library::UNIVERSE.

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

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 320 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().

00322   : dbm(box.space_dimension() + 1), status(), redundancy_dbm() {
00323   // Check for emptyness for maximum precision.
00324   if (box.is_empty())
00325     set_empty();
00326   else if (box.space_dimension() > 0) {
00327     // A (non zero-dim) universe BDS is shortest-path closed.
00328     set_shortest_path_closed();
00329     refine_with_constraints(box.constraints());
00330   }
00331 }

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 335 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().

00337   : dbm(grid.space_dimension() + 1), status(), redundancy_dbm() {
00338   if (grid.space_dimension() > 0)
00339     // A (non zero-dim) universe BDS is shortest-path closed.
00340     set_shortest_path_closed();
00341   // Taking minimized congruences ensures maximum precision.
00342   refine_with_congruences(grid.minimized_congruences());
00343 }

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 348 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().

00350   : dbm(os.space_dimension() + 1), status(), redundancy_dbm() {
00351   // Check for emptyness for maximum precision.
00352   if (os.is_empty())
00353     set_empty();
00354   else if (os.space_dimension() > 0) {
00355     // A (non zero-dim) universe BDS is shortest-path closed.
00356     set_shortest_path_closed();
00357     refine_with_constraints(os.constraints());
00358     // After refining, shortest-path closure is possibly lost
00359     // (even when `os' was strongly closed: recall that U
00360     // is possibly different from T).
00361   }
00362 }

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

Destructor.

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

00376                        {
00377 }


Member Function Documentation

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

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

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

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

00296                                             {
00297   return false;
00298 }

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

00303                                             {
00304   return false;
00305 }

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

00366                                         {
00367   dbm = y.dbm;
00368   status = y.status;
00369   if (y.marked_shortest_path_reduced())
00370     redundancy_dbm = y.redundancy_dbm;
00371   return *this;
00372 }

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

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

References Parma_Polyhedra_Library::BD_Shape< T >::dbm.

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 >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::bounded_affine_preimage(), 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 >::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 >::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 >::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 >::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_and_minimize().

00389                                    {
00390   return dbm.num_rows() - 1;
00391 }

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 291 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().

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

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

Returns a system of constraints defining *this.

Definition at line 4675 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(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), TEMP_INTEGER, 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().

04675                                {
04676   Constraint_System cs;
04677   const dimension_type space_dim = space_dimension();
04678   if (space_dim == 0) {
04679     if (marked_empty())
04680       cs = Constraint_System::zero_dim_empty();
04681   }
04682   else if (marked_empty())
04683     cs.insert(0*Variable(space_dim-1) <= -1);
04684   else if (marked_shortest_path_reduced())
04685     // Disregard redundant constraints.
04686     cs = minimized_constraints();
04687   else {
04688     // KLUDGE: in the future `cs' will be constructed of the right dimension.
04689     // For the time being, we force the dimension with the following line.
04690     cs.insert(0*Variable(space_dim-1) <= 0);
04691 
04692     TEMP_INTEGER(a);
04693     TEMP_INTEGER(b);
04694     // Go through all the unary constraints in `dbm'.
04695     const DB_Row<N>& dbm_0 = dbm[0];
04696     for (dimension_type j = 1; j <= space_dim; ++j) {
04697       const Variable x(j-1);
04698       const N& dbm_0j = dbm_0[j];
04699       const N& dbm_j0 = dbm[j][0];
04700       if (is_additive_inverse(dbm_j0, dbm_0j)) {
04701         // We have a unary equality constraint.
04702         numer_denom(dbm_0j, b, a);
04703         cs.insert(a*x == b);
04704       }
04705       else {
04706         // We have 0, 1 or 2 unary inequality constraints.
04707         if (!is_plus_infinity(dbm_0j)) {
04708           numer_denom(dbm_0j, b, a);
04709           cs.insert(a*x <= b);
04710         }
04711         if (!is_plus_infinity(dbm_j0)) {
04712           numer_denom(dbm_j0, b, a);
04713           cs.insert(-a*x <= b);
04714         }
04715       }
04716     }
04717 
04718     // Go through all the binary constraints in `dbm'.
04719     for (dimension_type i = 1; i <= space_dim; ++i) {
04720       const Variable y(i-1);
04721       const DB_Row<N>& dbm_i = dbm[i];
04722       for (dimension_type j = i + 1; j <= space_dim; ++j) {
04723         const Variable x(j-1);
04724         const N& dbm_ij = dbm_i[j];
04725         const N& dbm_ji = dbm[j][i];
04726         if (is_additive_inverse(dbm_ji, dbm_ij)) {
04727           // We have a binary equality constraint.
04728           numer_denom(dbm_ij, b, a);
04729           cs.insert(a*x - a*y == b);
04730         }
04731         else {
04732           // We have 0, 1 or 2 binary inequality constraints.
04733           if (!is_plus_infinity(dbm_ij)) {
04734             numer_denom(dbm_ij, b, a);
04735             cs.insert(a*x - a*y <= b);
04736           }
04737           if (!is_plus_infinity(dbm_ji)) {
04738             numer_denom(dbm_ji, b, a);
04739             cs.insert(a*y - a*x <= b);
04740           }
04741         }
04742       }
04743     }
04744   }
04745   return cs;
04746 }

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 4750 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(), 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(), TEMP_INTEGER, and Parma_Polyhedra_Library::Constraint_System::zero_dim_empty().

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

04750                                          {
04751   shortest_path_reduction_assign();
04752   Constraint_System cs;
04753   const dimension_type space_dim = space_dimension();
04754   if (space_dim == 0) {
04755     if (marked_empty())
04756       cs = Constraint_System::zero_dim_empty();
04757   }
04758   else if (marked_empty())
04759     cs.insert(0*Variable(space_dim-1) <= -1);
04760   else {
04761     // KLUDGE: in the future `cs' will be constructed of the right dimension.
04762     // For the time being, we force the dimension with the following line.
04763     cs.insert(0*Variable(space_dim-1) <= 0);
04764 
04765     TEMP_INTEGER(num);
04766     TEMP_INTEGER(den);
04767 
04768     // Compute leader information.
04769     std::vector<dimension_type> leaders;
04770     compute_leaders(leaders);
04771     std::vector<dimension_type> leader_indices;
04772     compute_leader_indices(leaders, leader_indices);
04773     const dimension_type num_leaders = leader_indices.size();
04774 
04775     // Go through the non-leaders to generate equality constraints.
04776     const DB_Row<N>& dbm_0 = dbm[0];
04777     for (dimension_type i = 1; i <= space_dim; ++i) {
04778       const dimension_type leader = leaders[i];
04779       if (i != leader) {
04780         // Generate the constraint relating `i' and its leader.
04781         if (leader == 0) {
04782           // A unary equality has to be generated.
04783           assert(!is_plus_infinity(dbm_0[i]));
04784           numer_denom(dbm_0[i], num, den);
04785           cs.insert(den*Variable(i-1) == num);
04786         }
04787         else {
04788           // A binary equality has to be generated.
04789           assert(!is_plus_infinity(dbm[i][leader]));
04790           numer_denom(dbm[i][leader], num, den);
04791           cs.insert(den*Variable(leader-1) - den*Variable(i-1) == num);
04792         }
04793       }
04794     }
04795 
04796     // Go through the leaders to generate inequality constraints.
04797     // First generate all the unary inequalities.
04798     const Bit_Row& red_0 = redundancy_dbm[0];
04799     for (dimension_type l_i = 1; l_i < num_leaders; ++l_i) {
04800       const dimension_type i = leader_indices[l_i];
04801       if (!red_0[i]) {
04802         numer_denom(dbm_0[i], num, den);
04803         cs.insert(den*Variable(i-1) <= num);
04804       }
04805       if (!redundancy_dbm[i][0]) {
04806         numer_denom(dbm[i][0], num, den);
04807         cs.insert(-den*Variable(i-1) <= num);
04808       }
04809     }
04810     // Then generate all the binary inequalities.
04811     for (dimension_type l_i = 1; l_i < num_leaders; ++l_i) {
04812       const dimension_type i = leader_indices[l_i];
04813       const DB_Row<N>& dbm_i = dbm[i];
04814       const Bit_Row& red_i = redundancy_dbm[i];
04815       for (dimension_type l_j = l_i + 1; l_j < num_leaders; ++l_j) {
04816         const dimension_type j = leader_indices[l_j];
04817         if (!red_i[j]) {
04818           numer_denom(dbm_i[j], num, den);
04819           cs.insert(den*Variable(j-1) - den*Variable(i-1) <= num);
04820         }
04821         if (!redundancy_dbm[j][i]) {
04822           numer_denom(dbm[j][i], num, den);
04823           cs.insert(den*Variable(i-1) - den*Variable(j-1) <= num);
04824         }
04825       }
04826     }
04827   }
04828   return cs;
04829 }

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

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

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

00151                                {
00152   return minimized_congruences();
00153 }

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 322 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(), Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), TEMP_INTEGER, and Parma_Polyhedra_Library::Congruence_System::zero_dim_empty().

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

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

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

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

00402                                                                   {
00403   return bounds(expr, true);
00404 }

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

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

00408                                                                   {
00409   return bounds(expr, false);
00410 }

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 414 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().

00416                                            {
00417   return max_min(expr, true, sup_n, sup_d, maximum);
00418 }

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

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

00424                                           {
00425   return max_min(expr, true, sup_n, sup_d, maximum, g);
00426 }

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 430 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().

00432                                            {
00433   return max_min(expr, false, inf_n, inf_d, minimum);
00434 }

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

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

00440                                           {
00441   return max_min(expr, false, inf_n, inf_d, minimum, g);
00442 }

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 577 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(), and Parma_Polyhedra_Library::BD_Shape< T >::strictly_contains().

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

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

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

00743                                                       {
00744   const BD_Shape<T>& x = *this;
00745   return x.contains(y) && !y.contains(x);
00746 }

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 636 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().

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

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 1272 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(), 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(), TEMP_INTEGER, 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().

01272                                                     {
01273   const dimension_type c_space_dim = c.space_dimension();
01274   const dimension_type space_dim = space_dimension();
01275 
01276   // Dimension-compatibility check.
01277   if (c_space_dim > space_dim)
01278     throw_dimension_incompatible("relation_with(c)", c);
01279 
01280   shortest_path_closure_assign();
01281 
01282   if (marked_empty())
01283     return Poly_Con_Relation::saturates()
01284       && Poly_Con_Relation::is_included()
01285       && Poly_Con_Relation::is_disjoint();
01286 
01287   if (space_dim == 0) {
01288     if ((c.is_equality() && c.inhomogeneous_term() != 0)
01289         || (c.is_inequality() && c.inhomogeneous_term() < 0))
01290       return Poly_Con_Relation::is_disjoint();
01291     else if (c.is_strict_inequality() && c.inhomogeneous_term() == 0)
01292       // The constraint 0 > 0 implicitly defines the hyperplane 0 = 0;
01293       // thus, the zero-dimensional point also saturates it.
01294       return Poly_Con_Relation::saturates()
01295         && Poly_Con_Relation::is_disjoint();
01296     else if (c.is_equality() || c.inhomogeneous_term() == 0)
01297       return Poly_Con_Relation::saturates()
01298         && Poly_Con_Relation::is_included();
01299     else
01300       // The zero-dimensional point saturates
01301       // neither the positivity constraint 1 >= 0,
01302       // nor the strict positivity constraint 1 > 0.
01303       return Poly_Con_Relation::is_included();
01304   }
01305 
01306   dimension_type num_vars = 0;
01307   dimension_type i = 0;
01308   dimension_type j = 0;
01309   TEMP_INTEGER(coeff);
01310   if (!extract_bounded_difference(c, c_space_dim, num_vars, i, j, coeff)) {
01311     // Constraints that are not bounded differences.
01312     // Use maximize() and minimize() to do much of the work.
01313 
01314     // Find the linear expression for the constraint and use that to
01315     // find if the expression is bounded from above or below and if it
01316     // is, find the maximum and minimum values.
01317     Linear_Expression le;
01318     for (dimension_type k = c_space_dim; k-- > 0; ) {
01319       Variable vk(k);
01320       le += c.coefficient(vk) * vk;
01321     }
01322     DIRTY_TEMP(Coefficient, max_num);
01323     DIRTY_TEMP(Coefficient, max_den);
01324     bool max_included;
01325     DIRTY_TEMP(Coefficient, min_num);
01326     DIRTY_TEMP(Coefficient, min_den);
01327     bool min_included;
01328     bool bounded_above = maximize(le, max_num, max_den, max_included);
01329     bool bounded_below = minimize(le, min_num, min_den, min_included);
01330     if (!bounded_above) {
01331       if (!bounded_below)
01332         return Poly_Con_Relation::strictly_intersects();
01333       min_num += c.inhomogeneous_term() * min_den;
01334       switch (sgn(min_num)) {
01335       case 1:
01336         if (c.is_equality())
01337           return  Poly_Con_Relation::is_disjoint();
01338         return  Poly_Con_Relation::is_included();
01339       case 0:
01340         if (c.is_strict_inequality() || c.is_equality())
01341           return  Poly_Con_Relation::strictly_intersects();
01342         return  Poly_Con_Relation::is_included();
01343       case -1:
01344         return  Poly_Con_Relation::strictly_intersects();
01345       }
01346     }
01347     if (!bounded_below) {
01348       max_num += c.inhomogeneous_term() * max_den;
01349       switch (sgn(max_num)) {
01350       case 1:
01351         return  Poly_Con_Relation::strictly_intersects();
01352       case 0:
01353         if (c.is_strict_inequality())
01354           return  Poly_Con_Relation::is_disjoint();
01355         return  Poly_Con_Relation::strictly_intersects();
01356       case -1:
01357         return  Poly_Con_Relation::is_disjoint();
01358       }
01359     }
01360     else {
01361       max_num += c.inhomogeneous_term() * max_den;
01362       min_num += c.inhomogeneous_term() * min_den;
01363       switch (sgn(max_num)) {
01364       case 1:
01365         switch (sgn(min_num)) {
01366         case 1:
01367           if (c.is_equality())
01368             return  Poly_Con_Relation::is_disjoint();
01369           return  Poly_Con_Relation::is_included();
01370         case 0:
01371           if (c.is_equality())
01372             return  Poly_Con_Relation::strictly_intersects();
01373           if (c.is_strict_inequality())
01374             return  Poly_Con_Relation::strictly_intersects();
01375           return  Poly_Con_Relation::is_included();
01376         case -1:
01377           return  Poly_Con_Relation::strictly_intersects();
01378         }
01379      case 0:
01380         if (min_num == 0) {
01381           if (c.is_strict_inequality())
01382             return  Poly_Con_Relation::is_disjoint()
01383               && Poly_Con_Relation::saturates();
01384           return  Poly_Con_Relation::is_included()
01385             && Poly_Con_Relation::saturates();
01386         }
01387         if (c.is_strict_inequality())
01388           return  Poly_Con_Relation::is_disjoint();
01389         return  Poly_Con_Relation::strictly_intersects();
01390       case -1:
01391         return  Poly_Con_Relation::is_disjoint();
01392       }
01393     }
01394   }
01395 
01396   // Constraints that are bounded differences.
01397   if (num_vars == 0) {
01398     // Dealing with a trivial constraint.
01399     switch (sgn(c.inhomogeneous_term())) {
01400     case -1:
01401       return Poly_Con_Relation::is_disjoint();
01402     case 0:
01403       if (c.is_strict_inequality())
01404         return Poly_Con_Relation::saturates()
01405           && Poly_Con_Relation::is_disjoint();
01406       else
01407         return Poly_Con_Relation::saturates()
01408           && Poly_Con_Relation::is_included();
01409     case 1:
01410       if (c.is_equality())
01411         return Poly_Con_Relation::is_disjoint();
01412       else
01413         return Poly_Con_Relation::is_included();
01414     }
01415   }
01416 
01417   // Select the cell to be checked for the "<=" part of the constraint,
01418   // and set `coeff' to the absolute value of itself.
01419   const bool negative = (coeff < 0);
01420   const N& x = negative ? dbm[i][j] : dbm[j][i];
01421   const N& y = negative ? dbm[j][i] : dbm[i][j];
01422   if (negative)
01423     neg_assign(coeff);
01424   // Deduce the relation/s of the constraint `c' of the form
01425   // `coeff*v - coeff*u </<=/== c.inhomogeneous_term()'
01426   // with the respectively constraints in `*this'
01427   // `-y <= v - u <= x'.
01428   // Let `d == c.inhomogeneous_term()/coeff'
01429   // and `d1 == -c.inhomogeneous_term()/coeff'.
01430   // The following variables of mpq_class type are used to be precise
01431   // when the bds is defined by integer constraints.
01432   DIRTY_TEMP0(mpq_class, q_x);
01433   DIRTY_TEMP0(mpq_class, q_y);
01434   DIRTY_TEMP0(mpq_class, d);
01435   DIRTY_TEMP0(mpq_class, d1);
01436   DIRTY_TEMP0(mpq_class, c_den);
01437   DIRTY_TEMP0(mpq_class, q_den);
01438   assign_r(c_den, coeff, ROUND_NOT_NEEDED);
01439   assign_r(d, c.inhomogeneous_term(), ROUND_NOT_NEEDED);
01440   neg_assign_r(d1, d, ROUND_NOT_NEEDED);
01441   div_assign_r(d, d, c_den, ROUND_NOT_NEEDED);
01442   div_assign_r(d1, d1, c_den, ROUND_NOT_NEEDED);
01443 
01444   if (is_plus_infinity(x)) {
01445     if (!is_plus_infinity(y)) {
01446       // `*this' is in the following form:
01447       // `-y <= v - u'.
01448       // In this case `*this' is disjoint from `c' if
01449       // `-y > d' (`-y >= d' if c is a strict equality), i.e. if
01450       // `y < d1' (`y <= d1' if c is a strict equality).
01451       TEMP_INTEGER(numer);
01452       TEMP_INTEGER(denom);
01453       numer_denom(y, numer, denom);
01454       assign_r(q_den, denom, ROUND_NOT_NEEDED);
01455       assign_r(q_y, numer, ROUND_NOT_NEEDED);
01456       div_assign_r(q_y, q_y, q_den, ROUND_NOT_NEEDED);
01457       if (q_y < d1)
01458         return Poly_Con_Relation::is_disjoint();
01459       if (q_y == d1 && c.is_strict_inequality())
01460         return Poly_Con_Relation::is_disjoint();
01461     }
01462 
01463     // In all other cases `*this' intersects `c'.
01464     return Poly_Con_Relation::strictly_intersects();
01465   }
01466 
01467   // Here `x' is not plus-infinity.
01468   TEMP_INTEGER(numer);
01469   TEMP_INTEGER(denom);
01470   numer_denom(x, numer, denom);
01471   assign_r(q_den, denom, ROUND_NOT_NEEDED);
01472   assign_r(q_x, numer, ROUND_NOT_NEEDED);
01473   div_assign_r(q_x, q_x, q_den, ROUND_NOT_NEEDED);
01474 
01475   if (!is_plus_infinity(y)) {
01476     numer_denom(y, numer, denom);
01477     assign_r(q_den, denom, ROUND_NOT_NEEDED);
01478     assign_r(q_y, numer, ROUND_NOT_NEEDED);
01479     div_assign_r(q_y, q_y, q_den, ROUND_NOT_NEEDED);
01480     if (q_x == d && q_y == d1) {
01481       if (c.is_strict_inequality())
01482         return Poly_Con_Relation::saturates()
01483           && Poly_Con_Relation::is_disjoint();
01484       else
01485         return Poly_Con_Relation::saturates()
01486           && Poly_Con_Relation::is_included();
01487     }
01488     // `*this' is disjoint from `c' when
01489     // `-y > d' (`-y >= d' if c is a strict equality), i.e. if
01490     // `y < d1' (`y <= d1' if c is a strict equality).
01491     if (q_y < d1)
01492       return Poly_Con_Relation::is_disjoint();
01493     if (q_y == d1 && c.is_strict_inequality())
01494       return Poly_Con_Relation::is_disjoint();
01495   }
01496 
01497   // Here `y' can be also plus-infinity.
01498   // If `c' is an equality, `*this' is disjoint from `c' if
01499   // `x < d'.
01500   if (d > q_x) {
01501     if (c.is_equality())
01502       return Poly_Con_Relation::is_disjoint();
01503     else
01504       return Poly_Con_Relation::is_included();
01505   }
01506 
01507   if (d == q_x && c.is_nonstrict_inequality())
01508     return Poly_Con_Relation::is_included();
01509 
01510   // In all other cases `*this' intersects `c'.
01511   return Poly_Con_Relation::strictly_intersects();
01512 }

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

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Congruence::coefficient(), Parma_Polyhedra_Library::BD_Shape< T >::extract_bounded_difference(), Parma_Polyhedra_Library::Congruence::inhomogeneous_term(), Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), Parma_Polyhedra_Library::Checked::le(), Parma_Polyhedra_Library::lower(), Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::BD_Shape< T >::minimize(), Parma_Polyhedra_Library::Congruence::modulus(), Parma_Polyhedra_Library::neg_assign(), 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::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Congruence::space_dimension(), Parma_Polyhedra_Library::Poly_Con_Relation::strictly_intersects(), TEMP_INTEGER, and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

01205                                                      {
01206   const dimension_type cg_space_dim = cg.space_dimension();
01207   const dimension_type space_dim = space_dimension();
01208 
01209   // Dimension-compatibility check.
01210   if (cg_space_dim > space_dim)
01211     throw_dimension_incompatible("relation_with(cg)", cg);
01212 
01213   // If the congruence is a bounded difference equality,
01214   // find the relation with the equivalent equality constraint.
01215   if (cg.is_equality()) {
01216     Constraint c(cg);
01217     dimension_type num_vars = 0;
01218     dimension_type i = 0;
01219     dimension_type j = 0;
01220     TEMP_INTEGER(coeff);
01221     if (extract_bounded_difference(c, cg_space_dim, num_vars,
01222                                     i, j, coeff))
01223       return relation_with(c);
01224   }
01225 
01226   shortest_path_closure_assign();
01227 
01228   if (marked_empty())
01229     return Poly_Con_Relation::saturates()
01230       && Poly_Con_Relation::is_included()
01231       && Poly_Con_Relation::is_disjoint();
01232 
01233   if (space_dim == 0) {
01234     if (cg.is_inconsistent())
01235       return Poly_Con_Relation::is_disjoint();
01236     else if (cg.inhomogeneous_term() % cg.modulus() == 0)
01237       return Poly_Con_Relation::saturates()
01238         && Poly_Con_Relation::is_included();
01239   }
01240 
01241   DIRTY_TEMP(Coefficient, min_num);
01242   DIRTY_TEMP(Coefficient, min_den);
01243   bool min_included;
01244   TEMP_INTEGER(mod);
01245   mod = cg.modulus();
01246   Linear_Expression le;
01247   for (dimension_type i = cg_space_dim; i-- > 0; )
01248     le += cg.coefficient(Variable(i)) * Variable(i);
01249   bool bounded_below = minimize(le, min_num, min_den, min_included);
01250 
01251   if (!bounded_below)
01252     return Poly_Con_Relation::strictly_intersects();
01253 
01254   TEMP_INTEGER(v);
01255   TEMP_INTEGER(lower_num);
01256   TEMP_INTEGER(lower_den);
01257   TEMP_INTEGER(lower);
01258   assign_r(lower_num, min_num, ROUND_NOT_NEEDED);
01259   assign_r(lower_den, min_den, ROUND_NOT_NEEDED);
01260   neg_assign(v, cg.inhomogeneous_term());
01261   lower = lower_num / lower_den;
01262   v += ((lower / mod) * mod);
01263   if (v * lower_den < lower_num)
01264     v += mod;
01265   const Constraint& c(le == v);
01266   return relation_with(c);
01267 }

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

References Parma_Polyhedra_Library::add_mul_assign(), Parma_Polyhedra_Library::Generator::coefficient(), 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(), 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(), TEMP_INTEGER, and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

01516                                                    {
01517   const dimension_type space_dim = space_dimension();
01518   const dimension_type g_space_dim = g.space_dimension();
01519 
01520   // Dimension-compatibility check.
01521   if (space_dim < g_space_dim)
01522     throw_dimension_incompatible("relation_with(g)", g);
01523 
01524   shortest_path_closure_assign();
01525   // The empty BDS cannot subsume a generator.
01526   if (marked_empty())
01527     return Poly_Gen_Relation::nothing();
01528 
01529   // A universe BDS in a zero-dimensional space subsumes
01530   // all the generators of a zero-dimensional space.
01531   if (space_dim == 0)
01532     return Poly_Gen_Relation::subsumes();
01533 
01534   const bool is_line = g.is_line();
01535   const bool is_line_or_ray = g.is_line_or_ray();
01536 
01537   // The relation between the BDS and the given generator is obtained
01538   // checking if the generator satisfies all the constraints in the BDS.
01539   // To check if the generator satisfies all the constraints it's enough
01540   // studying the sign of the scalar product between the generator and
01541   // all the constraints in the BDS.
01542 
01543   // Allocation of temporaries done once and for all.
01544   TEMP_INTEGER(num);
01545   TEMP_INTEGER(den);
01546   TEMP_INTEGER(product);
01547   // We find in `*this' all the constraints.
01548   for (dimension_type i = 0; i <= space_dim; ++i) {
01549     const Coefficient& g_coeff_y = (i > g_space_dim || i == 0)
01550       ? Coefficient(0) : g.coefficient(Variable(i-1));
01551     const DB_Row<N>& dbm_i = dbm[i];
01552     for (dimension_type j = i + 1; j <= space_dim; ++j) {
01553       const Coefficient& g_coeff_x = (j > g_space_dim)
01554         ? Coefficient(0) : g.coefficient(Variable(j-1));
01555       const N& dbm_ij = dbm_i[j];
01556       const N& dbm_ji = dbm[j][i];
01557       if (is_additive_inverse(dbm_ji, dbm_ij)) {
01558         // We have one equality constraint: den*x - den*y = num.
01559         // Compute the scalar product.
01560         numer_denom(dbm_ij, num, den);
01561         product = 0;
01562         add_mul_assign(product, den, g_coeff_y);
01563         add_mul_assign(product, -den, g_coeff_x);
01564         if (!is_line_or_ray)
01565           add_mul_assign(product, num, g.divisor());
01566         if (product != 0)
01567           return Poly_Gen_Relation::nothing();
01568       }
01569       else {
01570         // We have 0, 1 or 2 binary inequality constraint/s.
01571         if (!is_plus_infinity(dbm_ij)) {
01572           // We have the binary inequality constraint: den*x - den*y <= num.
01573           // Compute the scalar product.
01574           numer_denom(dbm_ij, num, den);
01575           product = 0;
01576           add_mul_assign(product, den, g_coeff_y);
01577           add_mul_assign(product, -den, g_coeff_x);
01578           if (!is_line_or_ray)
01579             add_mul_assign(product, num, g.divisor());
01580           if (is_line) {
01581             if (product != 0)
01582               // Lines must saturate all constraints.
01583               return Poly_Gen_Relation::nothing();
01584           }
01585           else
01586             // `g' is either a ray, a point or a closure point.
01587             if (product < 0)
01588               return Poly_Gen_Relation::nothing();
01589         }
01590 
01591         if (!is_plus_infinity(dbm_ji)) {
01592           // We have the binary inequality constraint: den*y - den*x <= b.
01593           // Compute the scalar product.
01594           numer_denom(dbm_ji, num, den);
01595           product = 0;
01596           add_mul_assign(product, den, g_coeff_x);
01597           add_mul_assign(product, -den, g_coeff_y);
01598           if (!is_line_or_ray)
01599             add_mul_assign(product, num, g.divisor());
01600           if (is_line) {
01601             if (product != 0)
01602               // Lines must saturate all constraints.
01603               return Poly_Gen_Relation::nothing();
01604           }
01605           else
01606             // `g' is either a ray, a point or a closure point.
01607             if (product < 0)
01608               return Poly_Gen_Relation::nothing();
01609         }
01610       }
01611     }
01612   }
01613 
01614   // The generator satisfies all the constraints.
01615   return Poly_Gen_Relation::subsumes();
01616 }

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

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

Definition at line 678 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().

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

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

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

00452                                {
00453   return affine_dimension() == 0;
00454 }

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

00446                                            {
00447   return true;
00448 }

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 701 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().

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

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 723 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().

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

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 768 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::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

00768                                                 {
00769   // `var' should be one of the dimensions of the polyhedron.
00770   const dimension_type var_space_dim = var.space_dimension();
00771   if (space_dimension() < var_space_dim)
00772     throw_dimension_incompatible("constrains(v)", "v", var);
00773 
00774   // A polyhedron known to be empty constrains all variables.
00775   // (Note: do not force emptiness check _yet_)
00776   if (marked_empty())
00777     return true;
00778 
00779   // Check whether `var' is syntactically constrained.
00780   const DB_Row<N>& dbm_v = dbm[var_space_dim];
00781   for (dimension_type i = dbm.num_rows(); i-- > 0; ) {
00782     if (!is_plus_infinity(dbm_v[i])
00783         || !is_plus_infinity(dbm[i][var_space_dim]))
00784       return true;
00785   }
00786 
00787   // `var' is not syntactically constrained:
00788   // now force an emptiness check.
00789   return is_empty();
00790 }

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 5062 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::BD_Shape< T >::Status::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 >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::bounded_affine_image(), 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 >::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().

05062                       {
05063   // Check whether the difference-bound matrix is well-formed.
05064   if (!dbm.OK())
05065     return false;
05066 
05067   // Check whether the status information is legal.
05068   if (!status.OK())
05069     return false;
05070 
05071   // An empty BDS is OK.
05072   if (marked_empty())
05073     return true;
05074 
05075   // MINUS_INFINITY cannot occur at all.
05076   for (dimension_type i = dbm.num_rows(); i-- > 0; )
05077     for (dimension_type j = dbm.num_rows(); j-- > 0; )
05078     if (is_minus_infinity(dbm[i][j])) {
05079 #ifndef NDEBUG
05080       using namespace Parma_Polyhedra_Library::IO_Operators;
05081       std::cerr << "BD_Shape::dbm[" << i << "][" << j << "] = "
05082                 << dbm[i][j] << "!"
05083                 << std::endl;
05084 #endif
05085       return false;
05086     }
05087 
05088   // On the main diagonal only PLUS_INFINITY can occur.
05089   for (dimension_type i = dbm.num_rows(); i-- > 0; )
05090     if (!is_plus_infinity(dbm[i][i])) {
05091 #ifndef NDEBUG
05092       using namespace Parma_Polyhedra_Library::IO_Operators;
05093       std::cerr << "BD_Shape::dbm[" << i << "][" << i << "] = "
05094                 << dbm[i][i] << "!  (+inf was expected.)"
05095                 << std::endl;
05096 #endif
05097       return false;
05098     }
05099 
05100   // Check whether the shortest-path closure information is legal.
05101   if (marked_shortest_path_closed()) {
05102     BD_Shape x = *this;
05103     x.reset_shortest_path_closed();
05104     x.shortest_path_closure_assign();
05105     if (x.dbm != dbm) {
05106 #ifndef NDEBUG
05107       std::cerr << "BD_Shape is marked as closed but it is not!"
05108                 << std::endl;
05109 #endif
05110       return false;
05111     }
05112   }
05113 
05114   // The following tests might result in false alarms when using floating
05115   // point coefficients: they are only meaningful if the coefficient type
05116   // base is exact (since otherwise shortest-path closure is approximated).
05117   if (std::numeric_limits<coefficient_type_base>::is_exact) {
05118 
05119     // Check whether the shortest-path reduction information is legal.
05120     if (marked_shortest_path_reduced()) {
05121       // A non-redundant constraint cannot be equal to PLUS_INFINITY.
05122       for (dimension_type i = dbm.num_rows(); i-- > 0; )
05123         for (dimension_type j = dbm.num_rows(); j-- > 0; )
05124           if (!redundancy_dbm[i][j] && is_plus_infinity(dbm[i][j])) {
05125 #ifndef NDEBUG
05126             using namespace Parma_Polyhedra_Library::IO_Operators;
05127             std::cerr << "BD_Shape::dbm[" << i << "][" << j << "] = "
05128                       << dbm[i][j] << " is marked as non-redundant!"
05129                       << std::endl;
05130 #endif
05131             return false;
05132           }
05133 
05134       BD_Shape x = *this;
05135       x.reset_shortest_path_reduced();
05136       x.shortest_path_reduction_assign();
05137       if (x.redundancy_dbm != redundancy_dbm) {
05138 #ifndef NDEBUG
05139         std::cerr << "BD_Shape is marked as reduced but it is not!"
05140                   << std::endl;
05141 #endif
05142         return false;
05143       }
05144     }
05145   }
05146 
05147   // All checks passed.
05148   return true;
05149 }

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

Definition at line 373 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(), 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(), TEMP_INTEGER, 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_constraint_and_minimize(), Parma_Polyhedra_Library::BD_Shape< T >::add_constraints(), Parma_Polyhedra_Library::BD_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::bounded_affine_preimage(), and Parma_Polyhedra_Library::BD_Shape< T >::difference_assign().

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

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

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

Returns:
false if and only if the result is empty.
Parameters:
c The constraint to be added. If it is not a bounded difference, it will be simply ignored.
Exceptions:
std::invalid_argument Thrown if *this and constraint c are dimension-incompatible, or if c is a strict inequality.
Deprecated:
See A Note on the Implementation of the Operators.

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

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

00157                                                             {
00158   add_constraint(c);
00159   shortest_path_closure_assign();
00160   return !marked_empty();
00161 }

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 (without minimizing the result).

Parameters:
cg The congruence to be added. If it is not a bounded difference, it will be simply ignored.
Exceptions:
std::invalid_argument Thrown if *this and congruence cg are dimension-incompatible.

Definition at line 446 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_congruence_and_minimize(), and Parma_Polyhedra_Library::BD_Shape< T >::add_congruences().

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

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

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

Parameters:
cg The congruence to be added. If it is not a bounded difference, it will be simply ignored.
Returns:
false if and only if the result is empty.
Exceptions:
std::invalid_argument Thrown if *this and congruence c are topology-incompatible or dimension-incompatible.
Deprecated:
See A Note on the Implementation of the Operators.

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

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

00165                                                              {
00166   add_congruence(cg);
00167   shortest_path_closure_assign();
00168   return !marked_empty();
00169 }

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. Constraints that are not bounded differences will be simply ignored.
Exceptions:
std::invalid_argument Thrown if *this and cs are dimension-incompatible, or if cs contains a strict inequality.

Definition at line 173 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_constraints_and_minimize(), Parma_Polyhedra_Library::BD_Shape< T >::add_recycled_constraints(), and Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape().

00173                                                         {
00174   for (Constraint_System::const_iterator i = cs.begin(),
00175          cs_end = cs.end(); i != cs_end; ++i)
00176     add_constraint(*i);
00177 }

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 (without minimizing the result).

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 topology-incompatible or dimension-incompatible.
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 189 of file BD_Shape.inlines.hh.

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

00189                                                            {
00190   add_constraints(cs);
00191 }

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

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

Returns:
false if and only if the result is empty.
Parameters:
cs The constraints that will be added. Constraints that are not bounded differences will be simply ignored.
Exceptions:
std::invalid_argument Thrown if *this and cs are dimension-incompatible, or if cs contains a strict inequality.
Deprecated:
See A Note on the Implementation of the Operators.

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

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

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

00181                                                                      {
00182   add_constraints(cs);
00183   shortest_path_closure_assign();
00184   return !marked_empty();
00185 }

template<typename T>
bool Parma_Polyhedra_Library::BD_Shape< T >::add_recycled_constraints_and_minimize ( Constraint_System cs  )  [inline]

Adds the constraints in cs to the system of constraints of *this, minimizing the result.

Returns:
false if and only if the result is empty.
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 topology-incompatible or dimension-incompatible.
Warning:
The only assumption that can be made on cs upon successful or exceptional return is that it can be safely destroyed.
Deprecated:
See A Note on the Implementation of the Operators.

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

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

00195                                                                         {
00196   return add_constraints_and_minimize(cs);
00197 }

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 (without minimizing the result).

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 topology-incompatible or dimension-incompatible.

Definition at line 201 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_congruences_and_minimize(), Parma_Polyhedra_Library::BD_Shape< T >::add_recycled_congruences(), and Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape().

00201                                                          {
00202   for (Congruence_System::const_iterator i = cgs.begin(),
00203          cgs_end = cgs.end(); i != cgs_end; ++i)
00204     add_congruence(*i);
00205 }

template<typename T>
bool Parma_Polyhedra_Library::BD_Shape< T >::add_congruences_and_minimize ( const Congruence_System cs  )  [inline]

Adds a copy of the congruences in cs to the system of congruences of *this, minimizing the result.

Returns:
false if and only if the result is empty.
Parameters:
cs Contains the congruences that will be added to the system of congruences of *this.
Exceptions:
std::invalid_argument Thrown if *this and cs are dimension-incompatible.
Deprecated:
See A Note on the Implementation of the Operators.

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

References Parma_Polyhedra_Library::BD_Shape< T >::add_congruences(), and Parma_Polyhedra_Library::BD_Shape< T >::is_empty().

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

00209                                                                       {
00210   add_congruences(cgs);
00211   return !is_empty();
00212 }

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

Adds the congruences in cs to the system of congruences of *this (without minimizing the result).

Parameters:
cgs The congruence system to be added to *this. The congruences in cgs may be recycled.
Exceptions:
std::invalid_argument Thrown if *this and cs are dimension-incompatible.
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 216 of file BD_Shape.inlines.hh.

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

00216                                                             {
00217   add_congruences(cgs);
00218 }

template<typename T>
bool Parma_Polyhedra_Library::BD_Shape< T >::add_recycled_congruences_and_minimize ( Congruence_System cgs  )  [inline]

Adds the congruences in cs to the system of congruences of *this, minimizing the result.

Returns:
false if and only if the result is empty.
Parameters:
cgs The congruence system to be added to *this. The congruences in cgs may be recycled.
Exceptions:
std::invalid_argument Thrown if *this and cs are dimension-incompatible.
Warning:
The only assumption that can be made on cs upon successful or exceptional return is that it can be safely destroyed.
Deprecated:
See A Note on the Implementation of the Operators.

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

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

00222                                                                          {
00223   return add_congruences_and_minimize(cgs);
00224 }

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 228 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().

00228                                                        {
00229   const dimension_type c_space_dim = c.space_dimension();
00230   // Dimension-compatibility check.
00231   if (c_space_dim > space_dimension())
00232     throw_dimension_incompatible("refine_with_constraint(c)", c);
00233 
00234   if (!marked_empty())
00235     refine_no_check(c);
00236 }

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 253 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().

00253                                                         {
00254   const dimension_type cg_space_dim = cg.space_dimension();
00255   // Dimension-compatibility check.
00256   if (cg_space_dim > space_dimension())
00257     throw_dimension_incompatible("refine_with_congruence(cg)", cg);
00258 
00259   if (!marked_empty())
00260     refine_no_check(cg);
00261 }

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 240 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().

00240                                                                 {
00241   // Dimension-compatibility check.
00242   if (cs.space_dimension() > space_dimension())
00243     throw_generic("refine_with_constraints(cs)",
00244                   "cs and *this are space-dimension incompatible");
00245 
00246   for (Constraint_System::const_iterator i = cs.begin(),
00247          cs_end = cs.end(); !marked_empty() && i != cs_end; ++i)
00248     refine_no_check(*i);
00249 }

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 265 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().

00265                                                                  {
00266   // Dimension-compatibility check.
00267   if (cgs.space_dimension() > space_dimension())
00268     throw_generic("refine_with_congruences(cgs)",
00269                   "cgs and *this are space-dimension incompatible");
00270 
00271   for (Congruence_System::const_iterator i = cgs.begin(),
00272          cgs_end = cgs.end(); !marked_empty() && i != cgs_end; ++i)
00273     refine_no_check(*i);
00274 }

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

References Parma_Polyhedra_Library::BD_Shape< T >::forget_all_dbm_constraints(), Parma_Polyhedra_Library::Variable::id(), 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(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

02672                                            {
02673   // Dimension-compatibility check.
02674   const dimension_type dim = var.id();
02675   if (space_dimension() < dim)
02676     throw_dimension_incompatible("unconstrain(var)", dim);
02677 
02678   // Shortest-path closure is necessary to detect emptiness
02679   // and all (possibly implicit) constraints.
02680   shortest_path_closure_assign();
02681 
02682   // If the shape is empty, this is a no-op.
02683   if (marked_empty())
02684     return;
02685 
02686   forget_all_dbm_constraints(dim+1);
02687   // Shortest-path closure is preserved, but not reduction.
02688   reset_shortest_path_reduced();
02689   assert(OK());
02690 }

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

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

Parameters:
to_be_unconstrained 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 to_be_removed.

Definition at line 2694 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(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

02694                                                                  {
02695   // The cylindrification wrt no dimensions is a no-op.
02696   // This case captures the only legal cylindrification in a 0-dim space.
02697   if (to_be_unconstrained.empty())
02698     return;
02699 
02700   // Dimension-compatibility check.
02701   const dimension_type min_space_dim = to_be_unconstrained.space_dimension();
02702   if (space_dimension() < min_space_dim)
02703     throw_dimension_incompatible("unconstrain(vs)", min_space_dim);
02704 
02705   // Shortest-path closure is necessary to detect emptiness
02706   // and all (possibly implicit) constraints.
02707   shortest_path_closure_assign();
02708 
02709   // If the shape is empty, this is a no-op.
02710   if (marked_empty())
02711     return;
02712 
02713   for (Variables_Set::const_iterator tbu = to_be_unconstrained.begin(),
02714          tbu_end = to_be_unconstrained.end(); tbu != tbu_end; ++tbu)
02715     forget_all_dbm_constraints(*tbu + 1);
02716   // Shortest-path closure is preserved, but not reduction.
02717   reset_shortest_path_reduced();
02718   assert(OK());
02719 }

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 2121 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 >::intersection_assign_and_minimize(), Parma_Polyhedra_Library::BD_Shape< T >::limited_BHMZ05_extrapolation_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::limited_CC76_extrapolation_assign().

02121                                                   {
02122   const dimension_type space_dim = space_dimension();
02123 
02124   // Dimension-compatibility check.
02125   if (space_dim != y.space_dimension())
02126     throw_dimension_incompatible("intersection_assign(y)", y);
02127 
02128   // If one of the two bounded difference shapes is empty,
02129   // the intersection is empty.
02130   if (marked_empty())
02131     return;
02132   if (y.marked_empty()) {
02133     set_empty();
02134     return;
02135   }
02136 
02137   // If both bounded difference shapes are zero-dimensional,
02138   // then at this point they are necessarily non-empty,
02139   // so that their intersection is non-empty too.
02140   if (space_dim == 0)
02141     return;
02142 
02143   // To intersect two bounded difference shapes we compare
02144   // the constraints and we choose the less values.
02145   bool changed = false;
02146   for (dimension_type i = space_dim + 1; i-- > 0; ) {
02147     DB_Row<N>& dbm_i = dbm[i];
02148     const DB_Row<N>& y_dbm_i = y.dbm[i];
02149     for (dimension_type j = space_dim + 1; j-- > 0; ) {
02150       N& dbm_ij = dbm_i[j];
02151       const N& y_dbm_ij = y_dbm_i[j];
02152       if (dbm_ij > y_dbm_ij) {
02153         dbm_ij = y_dbm_ij;
02154         changed = true;
02155       }
02156     }
02157   }
02158 
02159   if (changed && marked_shortest_path_closed())
02160     reset_shortest_path_closed();
02161   assert(OK());
02162 }

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

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

Returns:
false if and only if the result is empty.
Exceptions:
std::invalid_argument Thrown if *this and y are dimension-incompatible.
Deprecated:
See A Note on the Implementation of the Operators.

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

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

00800                                                                {
00801   intersection_assign(y);
00802   shortest_path_closure_assign();
00803   return !marked_empty();
00804 }

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 1776 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 >::difference_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign_and_minimize().

01776                                                  {
01777   const dimension_type space_dim = space_dimension();
01778 
01779   // Dimension-compatibility check.
01780   if (space_dim != y.space_dimension())
01781     throw_dimension_incompatible("upper_bound_assign(y)", y);
01782 
01783   // The poly-hull of a polyhedron `bd' with an empty polyhedron is `bd'.
01784   y.shortest_path_closure_assign();
01785   if (y.marked_empty())
01786     return;
01787   shortest_path_closure_assign();
01788   if (marked_empty()) {
01789     *this = y;
01790     return;
01791   }
01792 
01793   // The bds-hull consists in constructing `*this' with the maximum
01794   // elements selected from `*this' and `y'.
01795   assert(space_dim == 0 || marked_shortest_path_closed());
01796   for (dimension_type i = space_dim + 1; i-- > 0; ) {
01797     DB_Row<N>& dbm_i = dbm[i];
01798     const DB_Row<N>& y_dbm_i = y.dbm[i];
01799     for (dimension_type j = space_dim + 1; j-- > 0; ) {
01800       N& dbm_ij = dbm_i[j];
01801       const N& y_dbm_ij = y_dbm_i[j];
01802       if (dbm_ij < y_dbm_ij)
01803         dbm_ij = y_dbm_ij;
01804     }
01805   }
01806   // Shortest-path closure is maintained (if it was holding).
01807   // TODO: see whether reduction can be (efficiently!) maintained too.
01808   if (marked_shortest_path_reduced())
01809     reset_shortest_path_reduced();
01810   assert(OK());
01811 }

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

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

Returns:
false if and only if the result is empty.
Exceptions:
std::invalid_argument Thrown if *this and y are dimension-incompatible.
Deprecated:
See A Note on the Implementation of the Operators.

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

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

00750                                                               {
00751   upper_bound_assign(y);
00752   assert(marked_empty()
00753          || space_dimension() == 0 || marked_shortest_path_closed());
00754   return !marked_empty();
00755 }

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

00759                                                           {
00760   // TODO: this must be properly implemented.
00761   used(y);
00762   return false;
00763 }

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 1815 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().

01815                                                 {
01816   const dimension_type space_dim = space_dimension();
01817 
01818   // Dimension-compatibility check.
01819   if (space_dim != y.space_dimension())
01820     throw_dimension_incompatible("difference_assign(y)", y);
01821 
01822   BD_Shape new_bd_shape(space_dim, EMPTY);
01823 
01824   BD_Shape& x = *this;
01825 
01826   x.shortest_path_closure_assign();
01827   // The difference of an empty bounded difference shape
01828   // and of a bounded difference shape `p' is empty.
01829   if (x.marked_empty())
01830     return;
01831   y.shortest_path_closure_assign();
01832   // The difference of a bounded difference shape `p'
01833   // and an empty bounded difference shape is `p'.
01834   if (y.marked_empty())
01835     return;
01836 
01837   // If both bounded difference shapes are zero-dimensional,
01838   // then at this point they are necessarily universe system of
01839   // bounded differences, so that their difference is empty.
01840   if (space_dim == 0) {
01841     x.set_empty();
01842     return;
01843   }
01844 
01845   // TODO: This is just an executable specification.
01846   //       Have to find a more efficient method.
01847   if (y.contains(x)) {
01848     x.set_empty();
01849     return;
01850   }
01851 
01852   // We take a constraint of the system y at the time and we
01853   // consider its complementary. Then we intersect the union
01854   // of these complementaries with the system x.
01855   const Constraint_System& y_cs = y.constraints();
01856   for (Constraint_System::const_iterator i = y_cs.begin(),
01857          y_cs_end = y_cs.end(); i != y_cs_end; ++i) {
01858     const Constraint& c = *i;
01859     // If the bounded difference shape `x' is included
01860     // in the bounded difference shape defined by `c',
01861     // then `c' _must_ be skipped, as adding its complement to `x'
01862     // would result in the empty bounded difference shape,
01863     // and as we would obtain a result that is less precise
01864     // than the bds-difference.
01865     if (x.relation_with(c).implies(Poly_Con_Relation::is_included()))
01866       continue;
01867     BD_Shape z = x;
01868     const Linear_Expression e = Linear_Expression(c);
01869     z.add_constraint(e <= 0);
01870     if (!z.is_empty())
01871       new_bd_shape.upper_bound_assign(z);
01872     if (c.is_equality()) {
01873       z = x;
01874       z.add_constraint(e >= 0);
01875       if (!z.is_empty())
01876         new_bd_shape.upper_bound_assign(z);
01877     }
01878   }
01879   *this = new_bd_shape;
01880   assert(OK());
01881 }

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

01885                                                             {
01886   // FIXME: provide a real implementation.
01887   used(y);
01888   return true;
01889 }

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 3108 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(), 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::swap(), TEMP_INTEGER, 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 >::bounded_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::bounded_affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage().

03110                                                                          {
03111   // The denominator cannot be zero.
03112   if (denominator == 0)
03113     throw_generic("affine_image(v, e, d)", "d == 0");
03114 
03115   // Dimension-compatibility checks.
03116   // The dimension of `expr' should not be greater than the dimension
03117   // of `*this'.
03118   const dimension_type space_dim = space_dimension();
03119   const dimension_type expr_space_dim = expr.space_dimension();
03120   if (space_dim < expr_space_dim)
03121     throw_dimension_incompatible("affine_image(v, e, d)", "e", expr);
03122 
03123   // `var' should be one of the dimensions of the shape.
03124   const dimension_type v = var.id() + 1;
03125   if (v > space_dim)
03126     throw_dimension_incompatible("affine_image(v, e, d)", var.id());
03127 
03128   // The image of an empty BDS is empty too.
03129   shortest_path_closure_assign();
03130   if (marked_empty())
03131     return;
03132 
03133   const Coefficient& b = expr.inhomogeneous_term();
03134   // Number of non-zero coefficients in `expr': will be set to
03135   // 0, 1, or 2, the latter value meaning any value greater than 1.
03136   dimension_type t = 0;
03137   // Index of the last non-zero coefficient in `expr', if any.
03138   dimension_type w = 0;
03139   // Get information about the number of non-zero coefficients in `expr'.
03140   for (dimension_type i = expr_space_dim; i-- > 0; )
03141     if (expr.coefficient(Variable(i)) != 0) {
03142       if (t++ == 1)
03143         break;
03144       else
03145         w = i+1;
03146     }
03147 
03148   // Now we know the form of `expr':
03149   // - If t == 0, then expr == b, with `b' a constant;
03150   // - If t == 1, then expr == a*w + b, where `w' can be `v' or another
03151   //   variable; in this second case we have to check whether `a' is
03152   //   equal to `denominator' or `-denominator', since otherwise we have
03153   //   to fall back on the general form;
03154   // - If t == 2, the `expr' is of the general form.
03155   TEMP_INTEGER(minus_den);
03156   neg_assign(minus_den, denominator);
03157 
03158   if (t == 0) {
03159     // Case 1: expr == b.
03160     // Remove all constraints on `var'.
03161     forget_all_dbm_constraints(v);
03162     // Shortest-path closure is preserved, but not reduction.
03163     if (marked_shortest_path_reduced())
03164       reset_shortest_path_reduced();
03165     // Add the constraint `var == b/denominator'.
03166     add_dbm_constraint(0, v, b, denominator);
03167     add_dbm_constraint(v, 0, b, minus_den);
03168     assert(OK());
03169     return;
03170   }
03171 
03172   if (t == 1) {
03173     // Value of the one and only non-zero coefficient in `expr'.
03174     const Coefficient& a = expr.coefficient(Variable(w-1));
03175     if (a == denominator || a == minus_den) {
03176       // Case 2: expr == a*w + b, with a == +/- denominator.
03177       if (w == v) {
03178         // `expr' is of the form: a*v + b.
03179         if (a == denominator) {
03180           if (b == 0)
03181             // The transformation is the identity function.
03182             return;
03183           else {
03184             // Translate all the constraints on `var',
03185             // adding or subtracting the value `b/denominator'.
03186             DIRTY_TEMP(N, d);
03187             div_round_up(d, b, denominator);
03188             DIRTY_TEMP(N, c);
03189             div_round_up(c, b, minus_den);
03190             DB_Row<N>& dbm_v = dbm[v];
03191             for (dimension_type i = space_dim + 1; i-- > 0; ) {
03192               N& dbm_vi = dbm_v[i];
03193               add_assign_r(dbm_vi, dbm_vi, c, ROUND_UP);
03194               N& dbm_iv = dbm[i][v];
03195               add_assign_r(dbm_iv, dbm_iv, d, ROUND_UP);
03196             }
03197             // Both shortest-path closure and reduction are preserved.
03198           }
03199         }
03200         else {
03201           // Here `a == -denominator'.
03202           // Remove the binary constraints on `var'.
03203           forget_binary_dbm_constraints(v);
03204           // Swap the unary constraints on `var'.
03205           std::swap(dbm[v][0], dbm[0][v]);
03206           // Shortest-path closure is not preserved.
03207           reset_shortest_path_closed();
03208           if (b != 0) {
03209             // Translate the unary constraints on `var',
03210             // adding or subtracting the value `b/denominator'.
03211             DIRTY_TEMP(N, c);
03212             div_round_up(c, b, minus_den);
03213             N& dbm_v0 = dbm[v][0];
03214             add_assign_r(dbm_v0, dbm_v0, c, ROUND_UP);
03215             DIRTY_TEMP(N, d);
03216             div_round_up(d, b, denominator);
03217             N& dbm_0v = dbm[0][v];
03218             add_assign_r(dbm_0v, dbm_0v, d, ROUND_UP);
03219           }
03220         }
03221       }
03222       else {
03223         // Here `w != v', so that `expr' is of the form
03224         // +/-denominator * w + b.
03225         // Remove all constraints on `var'.
03226         forget_all_dbm_constraints(v);
03227         // Shortest-path closure is preserved, but not reduction.
03228         if (marked_shortest_path_reduced())
03229           reset_shortest_path_reduced();
03230         if (a == denominator) {
03231           // Add the new constraint `v - w == b/denominator'.
03232           add_dbm_constraint(w, v, b, denominator);
03233           add_dbm_constraint(v, w, b, minus_den);
03234         }
03235         else {
03236           // Here a == -denominator, so that we should be adding
03237           // the constraint `v + w == b/denominator'.
03238           // Approximate it by computing lower and upper bounds for `w'.
03239           const N& dbm_w0 = dbm[w][0];
03240           if (!is_plus_infinity(dbm_w0)) {
03241             // Add the constraint `v <= b/denominator - lower_w'.
03242             DIRTY_TEMP(N, d);
03243             div_round_up(d, b, denominator);
03244             add_assign_r(dbm[0][v], d, dbm_w0, ROUND_UP);
03245             reset_shortest_path_closed();
03246           }
03247           const N& dbm_0w = dbm[0][w];
03248           if (!is_plus_infinity(dbm_0w)) {
03249             // Add the constraint `v >= b/denominator - upper_w'.
03250             DIRTY_TEMP(N, c);
03251             div_round_up(c, b, minus_den);
03252             add_assign_r(dbm[v][0], dbm_0w, c, ROUND_UP);
03253             reset_shortest_path_closed();
03254           }
03255         }
03256       }
03257       assert(OK());
03258       return;
03259     }
03260   }
03261 
03262   // General case.
03263   // Either t == 2, so that
03264   // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
03265   // or t == 1, expr == a*w + b, but a <> +/- denominator.
03266   // We will remove all the constraints on `var' and add back
03267   // constraints providing upper and lower bounds for `var'.
03268 
03269   // Compute upper approximations for `expr' and `-expr'
03270   // into `pos_sum' and `neg_sum', respectively, taking into account
03271   // the sign of `denominator'.
03272   // Note: approximating `-expr' from above and then negating the
03273   // result is the same as approximating `expr' from below.
03274   const bool is_sc = (denominator > 0);
03275   TEMP_INTEGER(minus_b);
03276   neg_assign(minus_b, b);
03277   const Coefficient& sc_b = is_sc ? b : minus_b;
03278   const Coefficient& minus_sc_b = is_sc ? minus_b : b;
03279   const Coefficient& sc_den = is_sc ? denominator : minus_den;
03280   const Coefficient& minus_sc_den = is_sc ? minus_den : denominator;
03281   // NOTE: here, for optimization purposes, `minus_expr' is only assigned
03282   // when `denominator' is negative. Do not use it unless you are sure
03283   // it has been correctly assigned.
03284   Linear_Expression minus_expr;
03285   if (!is_sc)
03286     minus_expr = -expr;
03287   const Linear_Expression& sc_expr = is_sc ? expr : minus_expr;
03288 
03289   DIRTY_TEMP(N, pos_sum);
03290   DIRTY_TEMP(N, neg_sum);
03291   // Indices of the variables that are unbounded in `this->dbm'.
03292   PPL_UNINITIALIZED(dimension_type, pos_pinf_index);
03293   PPL_UNINITIALIZED(dimension_type, neg_pinf_index);
03294   // Number of unbounded variables found.
03295   dimension_type pos_pinf_count = 0;
03296   dimension_type neg_pinf_count = 0;
03297 
03298   // Approximate the inhomogeneous term.
03299   assign_r(pos_sum, sc_b, ROUND_UP);
03300   assign_r(neg_sum, minus_sc_b, ROUND_UP);
03301 
03302   // Approximate the homogeneous part of `sc_expr'.
03303   const DB_Row<N>& dbm_0 = dbm[0];
03304   // Speculative allocation of temporaries to be used in the following loop.
03305   DIRTY_TEMP(N, coeff_i);
03306   TEMP_INTEGER(minus_sc_i);
03307   // Note: indices above `w' can be disregarded, as they all have
03308   // a zero coefficient in `sc_expr'.
03309   for (dimension_type i = w; i > 0; --i) {
03310     const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1));
03311     const int sign_i = sgn(sc_i);
03312     if (sign_i > 0) {
03313       assign_r(coeff_i, sc_i, ROUND_UP);
03314       // Approximating `sc_expr'.
03315       if (pos_pinf_count <= 1) {
03316         const N& up_approx_i = dbm_0[i];
03317         if (!is_plus_infinity(up_approx_i))
03318           add_mul_assign_r(pos_sum, coeff_i, up_approx_i, ROUND_UP);
03319         else {
03320           ++pos_pinf_count;
03321           pos_pinf_index = i;
03322         }
03323       }
03324       // Approximating `-sc_expr'.
03325       if (neg_pinf_count <= 1) {
03326         const N& up_approx_minus_i = dbm[i][0];
03327         if (!is_plus_infinity(up_approx_minus_i))
03328           add_mul_assign_r(neg_sum, coeff_i, up_approx_minus_i, ROUND_UP);
03329         else {
03330           ++neg_pinf_count;
03331           neg_pinf_index = i;
03332         }
03333       }
03334     }
03335     else if (sign_i < 0) {
03336       neg_assign(minus_sc_i, sc_i);
03337       // Note: using temporary named `coeff_i' to store -coeff_i.
03338       assign_r(coeff_i, minus_sc_i, ROUND_UP);
03339       // Approximating `sc_expr'.
03340       if (pos_pinf_count <= 1) {
03341         const N& up_approx_minus_i = dbm[i][0];
03342         if (!is_plus_infinity(up_approx_minus_i))
03343           add_mul_assign_r(pos_sum, coeff_i, up_approx_minus_i, ROUND_UP);
03344         else {
03345           ++pos_pinf_count;
03346           pos_pinf_index = i;
03347         }
03348       }
03349       // Approximating `-sc_expr'.
03350       if (neg_pinf_count <= 1) {
03351         const N& up_approx_i = dbm_0[i];
03352         if (!is_plus_infinity(up_approx_i))
03353           add_mul_assign_r(neg_sum, coeff_i, up_approx_i, ROUND_UP);
03354         else {
03355           ++neg_pinf_count;
03356           neg_pinf_index = i;
03357         }
03358       }
03359     }
03360   }
03361 
03362   // Remove all constraints on 'v'.
03363   forget_all_dbm_constraints(v);
03364   // Shortest-path closure is maintained, but not reduction.
03365   if (marked_shortest_path_reduced())
03366     reset_shortest_path_reduced();
03367   // Return immediately if no approximation could be computed.
03368   if (pos_pinf_count > 1 && neg_pinf_count > 1) {
03369     assert(OK());
03370     return;
03371   }
03372 
03373   // In the following, shortest-path closure will be definitely lost.
03374   reset_shortest_path_closed();
03375 
03376   // Exploit the upper approximation, if possible.
03377   if (pos_pinf_count <= 1) {
03378     // Compute quotient (if needed).
03379     if (sc_den != 1) {
03380       // Before computing quotients, the denominator should be approximated
03381       // towards zero. Since `sc_den' is known to be positive, this amounts to
03382       // rounding downwards, which is achieved as usual by rounding upwards
03383       // `minus_sc_den' and negating again the result.
03384       DIRTY_TEMP(N, down_sc_den);
03385       assign_r(down_sc_den, minus_sc_den, ROUND_UP);
03386       neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
03387       div_assign_r(pos_sum, pos_sum, down_sc_den, ROUND_UP);
03388     }
03389     // Add the upper bound constraint, if meaningful.
03390     if (pos_pinf_count == 0) {
03391       // Add the constraint `v <= pos_sum'.
03392       dbm[0][v] = pos_sum;
03393       // Deduce constraints of the form `v - u', where `u != v'.
03394       deduce_v_minus_u_bounds(v, w, sc_expr, sc_den, pos_sum);
03395     }
03396     else
03397       // Here `pos_pinf_count == 1'.
03398       if (pos_pinf_index != v
03399           && sc_expr.coefficient(Variable(pos_pinf_index-1)) == sc_den)
03400         // Add the constraint `v - pos_pinf_index <= pos_sum'.
03401         dbm[pos_pinf_index][v] = pos_sum;
03402   }
03403 
03404   // Exploit the lower approximation, if possible.
03405   if (neg_pinf_count <= 1) {
03406     // Compute quotient (if needed).
03407     if (sc_den != 1) {
03408       // Before computing quotients, the denominator should be approximated
03409       // towards zero. Since `sc_den' is known to be positive, this amounts to
03410       // rounding downwards, which is achieved as usual by rounding upwards
03411       // `minus_sc_den' and negating again the result.
03412       DIRTY_TEMP(N, down_sc_den);
03413       assign_r(down_sc_den, minus_sc_den, ROUND_UP);
03414       neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
03415       div_assign_r(neg_sum, neg_sum, down_sc_den, ROUND_UP);
03416     }
03417     // Add the lower bound constraint, if meaningful.
03418     if (neg_pinf_count == 0) {
03419       // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'.
03420       DB_Row<N>& dbm_v = dbm[v];
03421       dbm_v[0] = neg_sum;
03422       // Deduce constraints of the form `u - v', where `u != v'.
03423       deduce_u_minus_v_bounds(v, w, sc_expr, sc_den, neg_sum);
03424     }
03425     else
03426       // Here `neg_pinf_count == 1'.
03427       if (neg_pinf_index != v
03428           && sc_expr.coefficient(Variable(neg_pinf_index-1)) == sc_den)
03429         // Add the constraint `v - neg_pinf_index >= -neg_sum',
03430         // i.e., `neg_pinf_index - v <= neg_sum'.
03431         dbm[v][neg_pinf_index] = neg_sum;
03432   }
03433 
03434   assert(OK());
03435 }

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 3439 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().

03441                                                                             {
03442   // The denominator cannot be zero.
03443   if (denominator == 0)
03444     throw_generic("affine_preimage(v, e, d)", "d == 0");
03445 
03446   // Dimension-compatibility checks.
03447   // The dimension of `expr' should not be greater than the dimension
03448   // of `*this'.
03449   const dimension_type space_dim = space_dimension();
03450   const dimension_type expr_space_dim = expr.space_dimension();
03451   if (space_dim < expr_space_dim)
03452     throw_dimension_incompatible("affine_preimage(v, e, d)", "e", expr);
03453 
03454   // `var' should be one of the dimensions of
03455   // the bounded difference shapes.
03456   const dimension_type v = var.id() + 1;
03457   if (v > space_dim)
03458     throw_dimension_incompatible("affine_preimage(v, e, d)", var.id());
03459 
03460   // The image of an empty BDS is empty too.
03461   shortest_path_closure_assign();
03462   if (marked_empty())
03463     return;
03464 
03465   const Coefficient& b = expr.inhomogeneous_term();
03466   // Number of non-zero coefficients in `expr': will be set to
03467   // 0, 1, or 2, the latter value meaning any value greater than 1.
03468   dimension_type t = 0;
03469   // Index of the last non-zero coefficient in `expr', if any.
03470   dimension_type j = 0;
03471   // Get information about the number of non-zero coefficients in `expr'.
03472   for (dimension_type i = expr_space_dim; i-- > 0; )
03473     if (expr.coefficient(Variable(i)) != 0) {
03474       if (t++ == 1)
03475         break;
03476       else
03477         j = i;
03478     }
03479 
03480   // Now we know the form of `expr':
03481   // - If t == 0, then expr = b, with `b' a constant;
03482   // - If t == 1, then expr = a*w + b, where `w' can be `v' or another
03483   //   variable; in this second case we have to check whether `a' is
03484   //   equal to `denominator' or `-denominator', since otherwise we have
03485   //   to fall back on the general form;
03486   // - If t > 1, the `expr' is of the general form.
03487   if (t == 0) {
03488     // Case 1: expr = n; remove all constraints on `var'.
03489     forget_all_dbm_constraints(v);
03490     // Shortest-path closure is preserved, but not reduction.
03491     if (marked_shortest_path_reduced())
03492       reset_shortest_path_reduced();
03493     assert(OK());
03494     return;
03495   }
03496 
03497   if (t == 1) {
03498     // Value of the one and only non-zero coefficient in `expr'.
03499     const Coefficient& a = expr.coefficient(Variable(j));
03500     if (a == denominator || a == -denominator) {
03501       // Case 2: expr = a*w + b, with a = +/- denominator.
03502       if (j == var.id())
03503         // Apply affine_image() on the inverse of this transformation.
03504         affine_image(var, denominator*var - b, a);
03505       else {
03506         // `expr == a*w + b', where `w != v'.
03507         // Remove all constraints on `var'.
03508         forget_all_dbm_constraints(v);
03509         // Shortest-path closure is preserved, but not reduction.
03510         if (marked_shortest_path_reduced())
03511           reset_shortest_path_reduced();
03512         assert(OK());
03513       }
03514       return;
03515     }
03516   }
03517 
03518   // General case.
03519   // Either t == 2, so that
03520   // expr = a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
03521   // or t = 1, expr = a*w + b, but a <> +/- denominator.
03522   const Coefficient& expr_v = expr.coefficient(var);
03523   if (expr_v != 0) {
03524     // The transformation is invertible.
03525     Linear_Expression inverse((expr_v + denominator)*var);
03526     inverse -= expr;
03527     affine_image(var, inverse, expr_v);
03528   }
03529   else {
03530     // Transformation not invertible: all constraints on `var' are lost.
03531     forget_all_dbm_constraints(v);
03532     // Shortest-path closure is preserved, but not reduction.
03533     if (marked_shortest_path_reduced())
03534       reset_shortest_path_reduced();
03535   }
03536   assert(OK());
03537 }

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 3852 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(), PLUS_INFINITY, 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(), TEMP_INTEGER, 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 >::bounded_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), and Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage().

03856                                                    {
03857   // The denominator cannot be zero.
03858   if (denominator == 0)
03859     throw_generic("generalized_affine_image(v, r, e, d)", "d == 0");
03860 
03861   // Dimension-compatibility checks.
03862   // The dimension of `expr' should not be greater than the dimension
03863   // of `*this'.
03864   const dimension_type space_dim = space_dimension();
03865   const dimension_type expr_space_dim = expr.space_dimension();
03866   if (space_dim < expr_space_dim)
03867     throw_dimension_incompatible("generalized_affine_image(v, r, e, d)",
03868                                  "e", expr);
03869 
03870   // `var' should be one of the dimensions of the BDS.
03871   const dimension_type v = var.id() + 1;
03872   if (v > space_dim)
03873     throw_dimension_incompatible("generalized_affine_image(v, r, e, d)",
03874                                  var.id());
03875 
03876   // The relation symbol cannot be a strict relation symbol.
03877   if (relsym == LESS_THAN || relsym == GREATER_THAN)
03878     throw_generic("generalized_affine_image(v, r, e, d)",
03879                   "r is a strict relation symbol and "
03880                   "*this is a BD_Shape");
03881   // The relation symbol cannot be a disequality.
03882   if (relsym == NOT_EQUAL)
03883     throw_generic("generalized_affine_image(v, r, e, d)",
03884                   "r is the disequality relation symbol and "
03885                   "*this is a BD_Shape");
03886 
03887   if (relsym == EQUAL) {
03888     // The relation symbol is "==":
03889     // this is just an affine image computation.
03890     affine_image(var, expr, denominator);
03891     return;
03892   }
03893 
03894   // The image of an empty BDS is empty too.
03895   shortest_path_closure_assign();
03896   if (marked_empty())
03897     return;
03898 
03899   const Coefficient& b = expr.inhomogeneous_term();
03900   // Number of non-zero coefficients in `expr': will be set to
03901   // 0, 1, or 2, the latter value meaning any value greater than 1.
03902   dimension_type t = 0;
03903   // Index of the last non-zero coefficient in `expr', if any.
03904   dimension_type w = 0;
03905   // Get information about the number of non-zero coefficients in `expr'.
03906   for (dimension_type i = expr_space_dim; i-- > 0; )
03907     if (expr.coefficient(Variable(i)) != 0) {
03908       if (t++ == 1)
03909         break;
03910       else
03911         w = i+1;
03912     }
03913 
03914   // Now we know the form of `expr':
03915   // - If t == 0, then expr == b, with `b' a constant;
03916   // - If t == 1, then expr == a*w + b, where `w' can be `v' or another
03917   //   variable; in this second case we have to check whether `a' is
03918   //   equal to `denominator' or `-denominator', since otherwise we have
03919   //   to fall back on the general form;
03920   // - If t == 2, the `expr' is of the general form.
03921   DB_Row<N>& dbm_0 = dbm[0];
03922   DB_Row<N>& dbm_v = dbm[v];
03923   TEMP_INTEGER(minus_den);
03924   neg_assign(minus_den, denominator);
03925 
03926   if (t == 0) {
03927     // Case 1: expr == b.
03928     // Remove all constraints on `var'.
03929     forget_all_dbm_constraints(v);
03930     // Both shortest-path closure and reduction are lost.
03931     reset_shortest_path_closed();
03932     switch (relsym) {
03933     case LESS_OR_EQUAL:
03934       // Add the constraint `var <= b/denominator'.
03935       add_dbm_constraint(0, v, b, denominator);
03936       break;
03937     case GREATER_OR_EQUAL:
03938       // Add the constraint `var >= b/denominator',
03939       // i.e., `-var <= -b/denominator',
03940       add_dbm_constraint(v, 0, b, minus_den);
03941       break;
03942     default:
03943       // We already dealt with the other cases.
03944       throw std::runtime_error("PPL internal error");
03945     }
03946     assert(OK());
03947     return;
03948   }
03949 
03950   if (t == 1) {
03951     // Value of the one and only non-zero coefficient in `expr'.
03952     const Coefficient& a = expr.coefficient(Variable(w-1));
03953     if (a == denominator || a == minus_den) {
03954       // Case 2: expr == a*w + b, with a == +/- denominator.
03955       DIRTY_TEMP(N, d);
03956       switch (relsym) {
03957       case LESS_OR_EQUAL:
03958         div_round_up(d, b, denominator);
03959         if (w == v) {
03960           // `expr' is of the form: a*v + b.
03961           // Shortest-path closure and reduction are not preserved.
03962           reset_shortest_path_closed();
03963           if (a == denominator) {
03964             // Translate each constraint `v - w <= dbm_wv'
03965             // into the constraint `v - w <= dbm_wv + b/denominator';
03966             // forget each constraint `w - v <= dbm_vw'.
03967             for (dimension_type i = space_dim + 1; i-- > 0; ) {
03968               N& dbm_iv = dbm[i][v];
03969               add_assign_r(dbm_iv, dbm_iv, d, ROUND_UP);
03970               assign_r(dbm_v[i], PLUS_INFINITY, ROUND_NOT_NEEDED);
03971             }
03972           }
03973           else {
03974             // Here `a == -denominator'.
03975             // Translate the constraint `0 - v <= dbm_v0'
03976             // into the constraint `0 - v <= dbm_v0 + b/denominator'.
03977             N& dbm_v0 = dbm_v[0];
03978             add_assign_r(dbm_0[v], dbm_v0, d, ROUND_UP);
03979             // Forget all the other constraints on `v'.
03980             assign_r(dbm_v0, PLUS_INFINITY, ROUND_NOT_NEEDED);
03981             forget_binary_dbm_constraints(v);
03982           }
03983         }
03984         else {
03985           // Here `w != v', so that `expr' is of the form
03986           // +/-denominator * w + b, with `w != v'.
03987           // Remove all constraints on `v'.
03988           forget_all_dbm_constraints(v);
03989           // Shortest-path closure is preserved, but not reduction.
03990           if (marked_shortest_path_reduced())
03991             reset_shortest_path_reduced();
03992           if (a == denominator)
03993             // Add the new constraint `v - w <= b/denominator'.
03994             add_dbm_constraint(w, v, d);
03995           else {
03996             // Here a == -denominator, so that we should be adding
03997             // the constraint `v <= b/denominator - w'.
03998             // Approximate it by computing a lower bound for `w'.
03999             const N& dbm_w0 = dbm[w][0];
04000             if (!is_plus_infinity(dbm_w0)) {
04001               // Add the constraint `v <= b/denominator - lb_w'.
04002               add_assign_r(dbm_0[v], d, dbm_w0, ROUND_UP);
04003               // Shortest-path closure is not preserved.
04004               reset_shortest_path_closed();
04005             }
04006           }
04007         }
04008         break;
04009 
04010       case GREATER_OR_EQUAL:
04011         div_round_up(d, b, minus_den);
04012         if (w == v) {
04013           // `expr' is of the form: a*w + b.
04014           // Shortest-path closure and reduction are not preserved.
04015           reset_shortest_path_closed();
04016           if (a == denominator) {
04017             // Translate each constraint `w - v <= dbm_vw'
04018             // into the constraint `w - v <= dbm_vw - b/denominator';
04019             // forget each constraint `v - w <= dbm_wv'.
04020             for (dimension_type i = space_dim + 1; i-- > 0; ) {
04021               N& dbm_vi = dbm_v[i];
04022               add_assign_r(dbm_vi, dbm_vi, d, ROUND_UP);
04023               assign_r(dbm[i][v], PLUS_INFINITY, ROUND_NOT_NEEDED);
04024             }
04025           }
04026           else {
04027             // Here `a == -denominator'.
04028             // Translate the constraint `0 - v <= dbm_v0'
04029             // into the constraint `0 - v <= dbm_0v - b/denominator'.
04030             N& dbm_0v = dbm_0[v];
04031             add_assign_r(dbm_v[0], dbm_0v, d, ROUND_UP);
04032             // Forget all the other constraints on `v'.
04033             assign_r(dbm_0v, PLUS_INFINITY, ROUND_NOT_NEEDED);
04034             forget_binary_dbm_constraints(v);
04035           }
04036         }
04037         else {
04038           // Here `w != v', so that `expr' is of the form
04039           // +/-denominator * w + b, with `w != v'.
04040           // Remove all constraints on `v'.
04041           forget_all_dbm_constraints(v);
04042           // Shortest-path closure is preserved, but not reduction.
04043           if (marked_shortest_path_reduced())
04044             reset_shortest_path_reduced();
04045           if (a == denominator)
04046             // Add the new constraint `v - w >= b/denominator',
04047             // i.e., `w - v <= -b/denominator'.
04048             add_dbm_constraint(v, w, d);
04049           else {
04050             // Here a == -denominator, so that we should be adding
04051             // the constraint `v >= -w + b/denominator',
04052             // i.e., `-v <= w - b/denominator'.
04053             // Approximate it by computing an upper bound for `w'.
04054             const N& dbm_0w = dbm_0[w];
04055             if (!is_plus_infinity(dbm_0w)) {
04056               // Add the constraint `-v <= ub_w - b/denominator'.
04057               add_assign_r(dbm_v[0], dbm_0w, d, ROUND_UP);
04058               // Shortest-path closure is not preserved.
04059               reset_shortest_path_closed();
04060             }
04061           }
04062         }
04063         break;
04064 
04065       default:
04066         // We already dealt with the other cases.
04067         throw std::runtime_error("PPL internal error");
04068       }
04069       assert(OK());
04070       return;
04071     }
04072   }
04073 
04074   // General case.
04075   // Either t == 2, so that
04076   // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
04077   // or t == 1, expr == a*w + b, but a <> +/- denominator.
04078   // We will remove all the constraints on `v' and add back
04079   // a constraint providing an upper or a lower bound for `v'
04080   // (depending on `relsym').
04081   const bool is_sc = (denominator > 0);
04082   TEMP_INTEGER(minus_b);
04083   neg_assign(minus_b, b);
04084   const Coefficient& sc_b = is_sc ? b : minus_b;
04085   const Coefficient& minus_sc_b = is_sc ? minus_b : b;
04086   const Coefficient& sc_den = is_sc ? denominator : minus_den;
04087   const Coefficient& minus_sc_den = is_sc ? minus_den : denominator;
04088   // NOTE: here, for optimization purposes, `minus_expr' is only assigned
04089   // when `denominator' is negative. Do not use it unless you are sure
04090   // it has been correctly assigned.
04091   Linear_Expression minus_expr;
04092   if (!is_sc)
04093     minus_expr = -expr;
04094   const Linear_Expression& sc_expr = is_sc ? expr : minus_expr;
04095 
04096   DIRTY_TEMP(N, sum);
04097   // Index of variable that is unbounded in `this->dbm'.
04098   PPL_UNINITIALIZED(dimension_type, pinf_index);
04099   // Number of unbounded variables found.
04100   dimension_type pinf_count = 0;
04101 
04102   // Speculative allocation of temporaries to be used in the following loops.
04103   DIRTY_TEMP(N, coeff_i);
04104   TEMP_INTEGER(minus_sc_i);
04105 
04106   switch (relsym) {
04107   case LESS_OR_EQUAL:
04108     // Compute an upper approximation for `sc_expr' into `sum'.
04109 
04110     // Approximate the inhomogeneous term.
04111     assign_r(sum, sc_b, ROUND_UP);
04112     // Approximate the homogeneous part of `sc_expr'.
04113     // Note: indices above `w' can be disregarded, as they all have
04114     // a zero coefficient in `sc_expr'.
04115     for (dimension_type i = w; i > 0; --i) {
04116       const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1));
04117       const int sign_i = sgn(sc_i);
04118       if (sign_i == 0)
04119         continue;
04120       // Choose carefully: we are approximating `sc_expr'.
04121       const N& approx_i = (sign_i > 0) ? dbm_0[i] : dbm[i][0];
04122       if (is_plus_infinity(approx_i)) {
04123         if (++pinf_count > 1)
04124           break;
04125         pinf_index = i;
04126         continue;
04127       }
04128       if (sign_i > 0)
04129         assign_r(coeff_i, sc_i, ROUND_UP);
04130       else {
04131         neg_assign(minus_sc_i, sc_i);
04132         assign_r(coeff_i, minus_sc_i, ROUND_UP);
04133       }
04134       add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
04135     }
04136 
04137     // Remove all constraints on `v'.
04138     forget_all_dbm_constraints(v);
04139     // Shortest-path closure is preserved, but not reduction.
04140     if (marked_shortest_path_reduced())
04141       reset_shortest_path_reduced();
04142     // Return immediately if no approximation could be computed.
04143     if (pinf_count > 1) {
04144       assert(OK());
04145       return;
04146     }
04147 
04148     // Divide by the (sign corrected) denominator (if needed).
04149     if (sc_den != 1) {
04150       // Before computing the quotient, the denominator should be approximated
04151       // towards zero. Since `sc_den' is known to be positive, this amounts to
04152       // rounding downwards, which is achieved as usual by rounding upwards
04153       // `minus_sc_den' and negating again the result.
04154       DIRTY_TEMP(N, down_sc_den);
04155       assign_r(down_sc_den, minus_sc_den, ROUND_UP);
04156       neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
04157       div_assign_r(sum, sum, down_sc_den, ROUND_UP);
04158     }
04159 
04160     if (pinf_count == 0) {
04161       // Add the constraint `v <= sum'.
04162       add_dbm_constraint(0, v, sum);
04163       // Deduce constraints of the form `v - u', where `u != v'.
04164       deduce_v_minus_u_bounds(v, w, sc_expr, sc_den, sum);
04165     }
04166     else if (pinf_count == 1)
04167       if (pinf_index != v
04168           && expr.coefficient(Variable(pinf_index-1)) == denominator)
04169         // Add the constraint `v - pinf_index <= sum'.
04170         add_dbm_constraint(pinf_index, v, sum);
04171     break;
04172 
04173   case GREATER_OR_EQUAL:
04174     // Compute an upper approximation for `-sc_expr' into `sum'.
04175     // Note: approximating `-sc_expr' from above and then negating the
04176     // result is the same as approximating `sc_expr' from below.
04177 
04178     // Approximate the inhomogeneous term.
04179     assign_r(sum, minus_sc_b, ROUND_UP);
04180     // Approximate the homogeneous part of `-sc_expr'.
04181     for (dimension_type i = expr_space_dim + 1; i > 0; --i) {
04182       const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1));
04183       const int sign_i = sgn(sc_i);
04184       if (sign_i == 0)
04185         continue;
04186       // Choose carefully: we are approximating `-sc_expr'.
04187       const N& approx_i = (sign_i > 0) ? dbm[i][0] : dbm_0[i];
04188       if (is_plus_infinity(approx_i)) {
04189         if (++pinf_count > 1)
04190           break;
04191         pinf_index = i;
04192         continue;
04193       }
04194       if (sign_i > 0)
04195         assign_r(coeff_i, sc_i, ROUND_UP);
04196       else {
04197         neg_assign(minus_sc_i, sc_i);
04198         assign_r(coeff_i, minus_sc_i, ROUND_UP);
04199       }
04200       add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
04201     }
04202 
04203     // Remove all constraints on `var'.
04204     forget_all_dbm_constraints(v);
04205     // Shortest-path closure is preserved, but not reduction.
04206     if (marked_shortest_path_reduced())
04207       reset_shortest_path_reduced();
04208     // Return immediately if no approximation could be computed.
04209     if (pinf_count > 1) {
04210       assert(OK());
04211       return;
04212     }
04213 
04214     // Divide by the (sign corrected) denominator (if needed).
04215     if (sc_den != 1) {
04216       // Before computing the quotient, the denominator should be approximated
04217       // towards zero. Since `sc_den' is known to be positive, this amounts to
04218       // rounding downwards, which is achieved as usual by rounding upwards
04219       // `minus_sc_den' and negating again the result.
04220       DIRTY_TEMP(N, down_sc_den);
04221       assign_r(down_sc_den, minus_sc_den, ROUND_UP);
04222       neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
04223       div_assign_r(sum, sum, down_sc_den, ROUND_UP);
04224     }
04225 
04226     if (pinf_count == 0) {
04227       // Add the constraint `v >= -sum', i.e., `-v <= sum'.
04228       add_dbm_constraint(v, 0, sum);
04229       // Deduce constraints of the form `u - v', where `u != v'.
04230       deduce_u_minus_v_bounds(v, w, sc_expr, sc_den, sum);
04231     }
04232     else if (pinf_count == 1)
04233       if (pinf_index != v
04234           && expr.coefficient(Variable(pinf_index-1)) == denominator)
04235         // Add the constraint `v - pinf_index >= -sum',
04236         // i.e., `pinf_index - v <= sum'.
04237         add_dbm_constraint(v, pinf_index, sum);
04238     break;
04239 
04240   default:
04241     // We already dealt with the other cases.
04242     throw std::runtime_error("PPL internal error");
04243   }
04244   assert(OK());
04245 }

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 4249 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().

04251                                                                     {
04252   // Dimension-compatibility checks.
04253   // The dimension of `lhs' should not be greater than the dimension
04254   // of `*this'.
04255   const dimension_type space_dim = space_dimension();
04256   const dimension_type lhs_space_dim = lhs.space_dimension();
04257   if (space_dim < lhs_space_dim)
04258     throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
04259                                  "e1", lhs);
04260 
04261   // The dimension of `rhs' should not be greater than the dimension
04262   // of `*this'.
04263   const dimension_type rhs_space_dim = rhs.space_dimension();
04264   if (space_dim < rhs_space_dim)
04265     throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
04266                                  "e2", rhs);
04267 
04268   // Strict relation symbols are not admitted for BDSs.
04269   if (relsym == LESS_THAN || relsym == GREATER_THAN)
04270     throw_generic("generalized_affine_image(e1, r, e2)",
04271                   "r is a strict relation symbol and "
04272                   "*this is a BD_Shape");
04273   // The relation symbol cannot be a disequality.
04274   if (relsym == NOT_EQUAL)
04275     throw_generic("generalized_affine_image(e1, r, e2)",
04276                   "r is the disequality relation symbol and "
04277                   "*this is a BD_Shape");
04278 
04279   // The image of an empty BDS is empty.
04280   shortest_path_closure_assign();
04281   if (marked_empty())
04282     return;
04283 
04284   // Number of non-zero coefficients in `lhs': will be set to
04285   // 0, 1, or 2, the latter value meaning any value greater than 1.
04286   dimension_type t_lhs = 0;
04287   // Index of the last non-zero coefficient in `lhs', if any.
04288   dimension_type j_lhs = 0;
04289   // Compute the number of the non-zero components of `lhs'.
04290   for (dimension_type i = lhs_space_dim; i-- > 0; )
04291     if (lhs.coefficient(Variable(i)) != 0) {
04292       if (t_lhs++ == 1)
04293         break;
04294       else
04295         j_lhs = i;
04296     }
04297 
04298   const Coefficient& b_lhs = lhs.inhomogeneous_term();
04299 
04300   if (t_lhs == 0) {
04301     // `lhs' is a constant.
04302     // In principle, it is sufficient to add the constraint `lhs relsym rhs'.
04303     // Note that this constraint is a bounded difference if `t_rhs <= 1'
04304     // or `t_rhs > 1' and `rhs == a*v - a*w + b_rhs'. If `rhs' is of a
04305     // more general form, it will be simply ignored.
04306     // TODO: if it is not a bounded difference, should we compute
04307     // approximations for this constraint?
04308     switch (relsym) {
04309     case LESS_OR_EQUAL:
04310       refine_no_check(lhs <= rhs);
04311       break;
04312     case EQUAL:
04313       refine_no_check(lhs == rhs);
04314       break;
04315     case GREATER_OR_EQUAL:
04316       refine_no_check(lhs >= rhs);
04317       break;
04318     default:
04319       // We already dealt with the other cases.
04320       throw std::runtime_error("PPL internal error");
04321     }
04322   }
04323   else if (t_lhs == 1) {
04324     // Here `lhs == a_lhs * v + b_lhs'.
04325     // Independently from the form of `rhs', we can exploit the
04326     // method computing generalized affine images for a single variable.
04327     Variable v(j_lhs);
04328     // Compute a sign-corrected relation symbol.
04329     const Coefficient& den = lhs.coefficient(v);
04330     Relation_Symbol new_relsym = relsym;
04331     if (den < 0) {
04332       if (relsym == LESS_OR_EQUAL)
04333         new_relsym = GREATER_OR_EQUAL;
04334       else if (relsym == GREATER_OR_EQUAL)
04335         new_relsym = LESS_OR_EQUAL;
04336     }
04337     Linear_Expression expr = rhs - b_lhs;
04338     generalized_affine_image(v, new_relsym, expr, den);
04339   }
04340   else {
04341     // Here `lhs' is of the general form, having at least two variables.
04342     // Compute the set of variables occurring in `lhs'.
04343     bool lhs_vars_intersects_rhs_vars = false;
04344     std::vector<Variable> lhs_vars;
04345     for (dimension_type i = lhs_space_dim; i-- > 0; )
04346       if (lhs.coefficient(Variable(i)) != 0) {
04347         lhs_vars.push_back(Variable(i));
04348         if (rhs.coefficient(Variable(i)) != 0)
04349           lhs_vars_intersects_rhs_vars = true;
04350       }
04351 
04352     if (!lhs_vars_intersects_rhs_vars) {
04353       // `lhs' and `rhs' variables are disjoint.
04354       // Existentially quantify all variables in the lhs.
04355       for (dimension_type i = lhs_vars.size(); i-- > 0; )
04356         forget_all_dbm_constraints(lhs_vars[i].id() + 1);
04357       // Constrain the left hand side expression so that it is related to
04358       // the right hand side expression as dictated by `relsym'.
04359       // TODO: if the following constraint is NOT a bounded difference,
04360       // it will be simply ignored. Should we compute approximations for it?
04361       switch (relsym) {
04362       case LESS_OR_EQUAL:
04363         refine_no_check(lhs <= rhs);
04364         break;
04365       case EQUAL:
04366         refine_no_check(lhs == rhs);
04367         break;
04368       case GREATER_OR_EQUAL:
04369         refine_no_check(lhs >= rhs);
04370         break;
04371       default:
04372         // We already dealt with the other cases.
04373         throw std::runtime_error("PPL internal error");
04374       }
04375     }
04376     else {
04377       // Some variables in `lhs' also occur in `rhs'.
04378 
04379 #if 1 // Simplified computation (see the TODO note below).
04380 
04381       for (dimension_type i = lhs_vars.size(); i-- > 0; )
04382         forget_all_dbm_constraints(lhs_vars[i].id() + 1);
04383 
04384 #else // Currently unnecessarily complex computation.
04385 
04386       // More accurate computation that is worth doing only if
04387       // the following TODO note is accurately dealt with.
04388 
04389       // To ease the computation, we add an additional dimension.
04390       const Variable new_var = Variable(space_dim);
04391       add_space_dimensions_and_embed(1);
04392       // Constrain the new dimension to be equal to `rhs'.
04393       // NOTE: calling affine_image() instead of refine_no_check()
04394       // ensures some approximation is tried even when the constraint
04395       // is not a bounded difference.
04396       affine_image(new_var, rhs);
04397       // Existentially quantify all variables in the lhs.
04398       // NOTE: enforce shortest-path closure for precision.
04399       shortest_path_closure_assign();
04400       assert(!marked_empty());
04401       for (dimension_type i = lhs_vars.size(); i-- > 0; )
04402         forget_all_dbm_constraints(lhs_vars[i].id() + 1);
04403       // Constrain the new dimension so that it is related to
04404       // the left hand side as dictated by `relsym'.
04405       // TODO: each one of the following constraints is definitely NOT
04406       // a bounded differences (since it has 3 variables at least).
04407       // Thus, the method refine_no_check() will simply ignore it.
04408       // Should we compute approximations for this constraint?
04409       switch (relsym) {
04410       case LESS_OR_EQUAL:
04411         refine_no_check(lhs <= new_var);
04412         break;
04413       case EQUAL:
04414         refine_no_check(lhs == new_var);
04415         break;
04416       case GREATER_OR_EQUAL:
04417         refine_no_check(lhs >= new_var);
04418         break;
04419       default:
04420         // We already dealt with the other cases.
04421         throw std::runtime_error("PPL internal error");
04422       }
04423       // Remove the temporarily added dimension.
04424       remove_higher_space_dimensions(space_dim-1);
04425 #endif // Currently unnecessarily complex computation.
04426     }
04427   }
04428 
04429   assert(OK());
04430 }

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 4434 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(), 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(), TEMP_INTEGER, 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 >::bounded_affine_preimage(), and Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage().

04438                                                       {
04439   // The denominator cannot be zero.
04440   if (denominator == 0)
04441     throw_generic("generalized_affine_preimage(v, r, e, d)", "d == 0");
04442 
04443   // Dimension-compatibility checks.
04444   // The dimension of `expr' should not be greater than the dimension
04445   // of `*this'.
04446   const dimension_type space_dim = space_dimension();
04447   const dimension_type expr_space_dim = expr.space_dimension();
04448   if (space_dim < expr_space_dim)
04449     throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)",
04450                                  "e", expr);
04451 
04452   // `var' should be one of the dimensions of the BDS.
04453   const dimension_type v = var.id() + 1;
04454   if (v > space_dim)
04455     throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)",
04456                                  var.id());
04457 
04458   // The relation symbol cannot be a strict relation symbol.
04459   if (relsym == LESS_THAN || relsym == GREATER_THAN)
04460     throw_generic("generalized_affine_preimage(v, r, e, d)",
04461                   "r is a strict relation symbol and "
04462                   "*this is a BD_Shape");
04463   // The relation symbol cannot be a disequality.
04464   if (relsym == NOT_EQUAL)
04465     throw_generic("generalized_affine_preimage(v, r, e, d)",
04466                   "r is the disequality relation symbol and "
04467                   "*this is a BD_Shape");
04468 
04469   if (relsym == EQUAL) {
04470     // The relation symbol is "==":
04471     // this is just an affine preimage computation.
04472     affine_preimage(var, expr, denominator);
04473     return;
04474   }
04475 
04476   // The preimage of an empty BDS is empty too.
04477   shortest_path_closure_assign();
04478   if (marked_empty())
04479     return;
04480 
04481   // Check whether the preimage of this affine relation can be easily
04482   // computed as the image of its inverse relation.
04483   const Coefficient& expr_v = expr.coefficient(var);
04484   if (expr_v != 0) {
04485     const Relation_Symbol reversed_relsym = (relsym == LESS_OR_EQUAL)
04486       ? GREATER_OR_EQUAL : LESS_OR_EQUAL;
04487     const Linear_Expression inverse
04488       = expr - (expr_v + denominator)*var;
04489     TEMP_INTEGER(inverse_den);
04490     neg_assign(inverse_den, expr_v);
04491     const Relation_Symbol inverse_relsym
04492       = (sgn(denominator) == sgn(inverse_den)) ? relsym : reversed_relsym;
04493     generalized_affine_image(var, inverse_relsym, inverse, inverse_den);
04494     return;
04495   }
04496 
04497   refine(var, relsym, expr, denominator);
04498   // If the shrunk BD_Shape is empty, its preimage is empty too; ...
04499   if (is_empty())
04500     return;
04501   // ...  otherwise, since the relation was not invertible,
04502   // we just forget all constraints on `v'.
04503   forget_all_dbm_constraints(v);
04504   // Shortest-path closure is preserved, but not reduction.
04505   if (marked_shortest_path_reduced())
04506     reset_shortest_path_reduced();
04507   assert(OK());
04508 }

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 4512 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().

04514                                                                        {
04515   // Dimension-compatibility checks.
04516   // The dimension of `lhs' should not be greater than the dimension
04517   // of `*this'.
04518   const dimension_type bds_space_dim = space_dimension();
04519   const dimension_type lhs_space_dim = lhs.space_dimension();
04520   if (bds_space_dim < lhs_space_dim)
04521     throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)",
04522                                  "e1", lhs);
04523 
04524   // The dimension of `rhs' should not be greater than the dimension
04525   // of `*this'.
04526   const dimension_type rhs_space_dim = rhs.space_dimension();
04527   if (bds_space_dim < rhs_space_dim)
04528     throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)",
04529                                  "e2", rhs);
04530 
04531   // Strict relation symbols are not admitted for BDSs.
04532   if (relsym == LESS_THAN || relsym == GREATER_THAN)
04533     throw_generic("generalized_affine_preimage(e1, r, e2)",
04534                   "r is a strict relation symbol and "
04535                   "*this is a BD_Shape");
04536   // The relation symbol cannot be a disequality.
04537   if (relsym == NOT_EQUAL)
04538     throw_generic("generalized_affine_preimage(e1, r, e2)",
04539                   "r is the disequality relation symbol and "
04540                   "*this is a BD_Shape");
04541 
04542   // The preimage of an empty BDS is empty.
04543   shortest_path_closure_assign();
04544   if (marked_empty())
04545     return;
04546 
04547   // Number of non-zero coefficients in `lhs': will be set to
04548   // 0, 1, or 2, the latter value meaning any value greater than 1.
04549   dimension_type t_lhs = 0;
04550   // Index of the last non-zero coefficient in `lhs', if any.
04551   dimension_type j_lhs = 0;
04552   // Compute the number of the non-zero components of `lhs'.
04553   for (dimension_type i = lhs_space_dim; i-- > 0; )
04554     if (lhs.coefficient(Variable(i)) != 0) {
04555       if (t_lhs++ == 1)
04556         break;
04557       else
04558         j_lhs = i;
04559     }
04560 
04561   const Coefficient& b_lhs = lhs.inhomogeneous_term();
04562 
04563   if (t_lhs == 0) {
04564     // `lhs' is a constant.
04565     // In this case, preimage and image happen to be the same.
04566     generalized_affine_image(lhs, relsym, rhs);
04567     return;
04568   }
04569   else if (t_lhs == 1) {
04570     // Here `lhs == a_lhs * v + b_lhs'.
04571     // Independently from the form of `rhs', we can exploit the
04572     // method computing generalized affine preimages for a single variable.
04573     Variable v(j_lhs);
04574     // Compute a sign-corrected relation symbol.
04575     const Coefficient& den = lhs.coefficient(v);
04576     Relation_Symbol new_relsym = relsym;
04577     if (den < 0) {
04578       if (relsym == LESS_OR_EQUAL)
04579         new_relsym = GREATER_OR_EQUAL;
04580       else if (relsym == GREATER_OR_EQUAL)
04581         new_relsym = LESS_OR_EQUAL;
04582     }
04583     Linear_Expression expr = rhs - b_lhs;
04584     generalized_affine_preimage(v, new_relsym, expr, den);
04585   }
04586   else {
04587     // Here `lhs' is of the general form, having at least two variables.
04588     // Compute the set of variables occurring in `lhs'.
04589     bool lhs_vars_intersects_rhs_vars = false;
04590     std::vector<Variable> lhs_vars;
04591     for (dimension_type i = lhs_space_dim; i-- > 0; )
04592       if (lhs.coefficient(Variable(i)) != 0) {
04593         lhs_vars.push_back(Variable(i));
04594         if (rhs.coefficient(Variable(i)) != 0)
04595           lhs_vars_intersects_rhs_vars = true;
04596       }
04597 
04598     if (!lhs_vars_intersects_rhs_vars) {
04599       // `lhs' and `rhs' variables are disjoint.
04600 
04601       // Constrain the left hand side expression so that it is related to
04602       // the right hand side expression as dictated by `relsym'.
04603       // TODO: if the following constraint is NOT a bounded difference,
04604       // it will be simply ignored. Should we compute approximations for it?
04605       switch (relsym) {
04606       case LESS_OR_EQUAL:
04607         refine_no_check(lhs <= rhs);
04608         break;
04609       case EQUAL:
04610         refine_no_check(lhs == rhs);
04611         break;
04612       case GREATER_OR_EQUAL:
04613         refine_no_check(lhs >= rhs);
04614         break;
04615       default:
04616         // We already dealt with the other cases.
04617         throw std::runtime_error("PPL internal error");
04618       }
04619 
04620       // If the shrunk BD_Shape is empty, its preimage is empty too; ...
04621       if (is_empty())
04622         return;
04623       // Existentially quantify all variables in the lhs.
04624       for (dimension_type i = lhs_vars.size(); i-- > 0; )
04625         forget_all_dbm_constraints(lhs_vars[i].id() + 1);
04626     }
04627     else {
04628 
04629       // Some variables in `lhs' also occur in `rhs'.
04630       // To ease the computation, we add an additional dimension.
04631       const Variable new_var = Variable(bds_space_dim);
04632       add_space_dimensions_and_embed(1);
04633       // Constrain the new dimension to be equal to `lhs'.
04634       // NOTE: calling affine_image() instead of refine_no_check()
04635       // ensures some approximation is tried even when the constraint
04636       // is not a bounded difference.
04637       affine_image(new_var, lhs);
04638       // Existentiallly quantify all variables in the lhs.
04639       // NOTE: enforce shortest-path closure for precision.
04640       shortest_path_closure_assign();
04641       assert(!marked_empty());
04642       for (dimension_type i = lhs_vars.size(); i-- > 0; )
04643         forget_all_dbm_constraints(lhs_vars[i].id() + 1);
04644       // Constrain the new dimension so that it is related to
04645       // the left hand side as dictated by `relsym'.
04646       // Note: if `rhs == a_rhs*v + b_rhs' where `a_rhs' is in {0, 1},
04647       // then one of the following constraints will be added,
04648       // since it is a bounded difference. Else the method
04649       // refine_no_check() will ignore it, because the
04650       // constraint is NOT a bounded difference.
04651       switch (relsym) {
04652       case LESS_OR_EQUAL:
04653         refine_no_check(new_var <= rhs);
04654         break;
04655       case EQUAL:
04656         refine_no_check(new_var == rhs);
04657         break;
04658       case GREATER_OR_EQUAL:
04659         refine_no_check(new_var >= rhs);
04660         break;
04661       default:
04662         // We already dealt with the other cases.
04663         throw std::runtime_error("PPL internal error");
04664       }
04665       // Remove the temporarily added dimension.
04666       remove_higher_space_dimensions(bds_space_dim);
04667     }
04668   }
04669 
04670   assert(OK());
04671 }

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

References 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 >::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_v_minus_u_bounds(), Parma_Polyhedra_Library::div_round_up(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), 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::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::neg_assign(), 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_closed(), 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(), TEMP_INTEGER, Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().

03545                                                                       {
03546   // The denominator cannot be zero.
03547   if (denominator == 0)
03548     throw_generic("bounded_affine_image(v, lb, ub, d)", "d == 0");
03549 
03550   // Dimension-compatibility checks.
03551   // `var' should be one of the dimensions of the BD_Shape.
03552   const dimension_type bds_space_dim = space_dimension();
03553   const dimension_type v = var.id() + 1;
03554   if (v > bds_space_dim)
03555     throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)",
03556                                  "v", var);
03557   // The dimension of `lb_expr' and `ub_expr' should not be
03558   // greater than the dimension of `*this'.
03559   const dimension_type lb_space_dim = lb_expr.space_dimension();
03560   if (bds_space_dim < lb_space_dim)
03561     throw_dimension_incompatible("bounded_affine_image(v, lb, ub)",
03562                                  "lb", lb_expr);
03563   const dimension_type ub_space_dim = ub_expr.space_dimension();
03564   if (bds_space_dim < ub_space_dim)
03565     throw_dimension_incompatible("bounded_affine_image(v, lb, ub)",
03566                                  "ub", ub_expr);
03567 
03568   // Any image of an empty BDS is empty.
03569   shortest_path_closure_assign();
03570   if (marked_empty())
03571     return;
03572 
03573   const Coefficient& b = ub_expr.inhomogeneous_term();
03574   // Number of non-zero coefficients in `ub_expr': will be set to
03575   // 0, 1, or 2, the latter value meaning any value greater than 1.
03576   dimension_type t = 0;
03577   // Index of the last non-zero coefficient in `ub_expr', if any.
03578   dimension_type w = 0;
03579   // Get information about the number of non-zero coefficients in `expr'.
03580   for (dimension_type i = ub_space_dim; i-- > 0; )
03581     if (ub_expr.coefficient(Variable(i)) != 0) {
03582       if (t++ == 1)
03583         break;
03584       else
03585         w = i+1;
03586     }
03587 
03588   // Now we know the form of `ub_expr':
03589   // - If t == 0, then ub_expr == b, with `b' a constant;
03590   // - If t == 1, then ub_expr == a*w + b, where `w' can be `v' or another
03591   //   variable; in this second case we have to check whether `a' is
03592   //   equal to `denominator' or `-denominator', since otherwise we have
03593   //   to fall back on the general form;
03594   // - If t == 2, the `ub_expr' is of the general form.
03595   TEMP_INTEGER(minus_den);
03596   neg_assign(minus_den, denominator);
03597 
03598   if (t == 0) {
03599     // Case 1: ub_expr == b.
03600     generalized_affine_image(var,
03601                              GREATER_OR_EQUAL,
03602                              lb_expr,
03603                              denominator);
03604     // Add the constraint `var <= b/denominator'.
03605     add_dbm_constraint(0, v, b, denominator);
03606     assert(OK());
03607     return;
03608   }
03609 
03610   if (t == 1) {
03611     // Value of the one and only non-zero coefficient in `ub_expr'.
03612     const Coefficient& a = ub_expr.coefficient(Variable(w-1));
03613     if (a == denominator || a == minus_den) {
03614       // Case 2: expr == a*w + b, with a == +/- denominator.
03615       if (w == v) {
03616         // Here `var' occurs in `ub_expr'.
03617         // To ease the computation, we add an additional dimension.
03618         const Variable new_var = Variable(bds_space_dim);
03619         add_space_dimensions_and_embed(1);
03620         // Constrain the new dimension to be equal to `ub_expr'.
03621         affine_image(new_var, ub_expr, denominator);
03622         // NOTE: enforce shortest-path closure for precision.
03623         shortest_path_closure_assign();
03624         assert(!marked_empty());
03625         // Apply the affine lower bound.
03626         generalized_affine_image(var,
03627                                  GREATER_OR_EQUAL,
03628                                  lb_expr,
03629                                  denominator);
03630         // Now apply the affine upper bound, as recorded in `new_var'.
03631         add_constraint(var <= new_var);
03632         // Remove the temporarily added dimension.
03633         remove_higher_space_dimensions(bds_space_dim);
03634         return;
03635       }
03636       else {
03637         // Here `w != v', so that `expr' is of the form
03638         // +/-denominator * w + b.
03639         // Apply the affine lower bound.
03640         generalized_affine_image(var,
03641                                  GREATER_OR_EQUAL,
03642                                  lb_expr,
03643                                  denominator);
03644         if (a == denominator) {
03645           // Add the new constraint `v - w == b/denominator'.
03646           add_dbm_constraint(w, v, b, denominator);
03647         }
03648         else {
03649           // Here a == -denominator, so that we should be adding
03650           // the constraint `v + w == b/denominator'.
03651           // Approximate it by computing lower and upper bounds for `w'.
03652           const N& dbm_w0 = dbm[w][0];
03653           if (!is_plus_infinity(dbm_w0)) {
03654             // Add the constraint `v <= b/denominator - lower_w'.
03655             DIRTY_TEMP(N, d);
03656             div_round_up(d, b, denominator);
03657             add_assign_r(dbm[0][v], d, dbm_w0, ROUND_UP);
03658             reset_shortest_path_closed();
03659           }
03660         }
03661         assert(OK());
03662         return;
03663       }
03664     }
03665   }
03666 
03667   // General case.
03668   // Either t == 2, so that
03669   // ub_expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2,
03670   // or t == 1, ub_expr == a*w + b, but a <> +/- denominator.
03671   // We will remove all the constraints on `var' and add back
03672   // constraints providing upper and lower bounds for `var'.
03673 
03674   // Compute upper approximations for `ub_expr' into `pos_sum'
03675   // taking into account the sign of `denominator'.
03676   const bool is_sc = (denominator > 0);
03677   TEMP_INTEGER(minus_b);
03678   neg_assign(minus_b, b);
03679   const Coefficient& sc_b = is_sc ? b : minus_b;
03680   const Coefficient& sc_den = is_sc ? denominator : minus_den;
03681   const Coefficient& minus_sc_den = is_sc ? minus_den : denominator;
03682   // NOTE: here, for optimization purposes, `minus_expr' is only assigned
03683   // when `denominator' is negative. Do not use it unless you are sure
03684   // it has been correctly assigned.
03685   Linear_Expression minus_expr;
03686   if (!is_sc)
03687     minus_expr = -ub_expr;
03688   const Linear_Expression& sc_expr = is_sc ? ub_expr : minus_expr;
03689 
03690   DIRTY_TEMP(N, pos_sum);
03691   // Index of the variable that are unbounded in `this->dbm'.
03692   PPL_UNINITIALIZED(dimension_type, pos_pinf_index);
03693   // Number of unbounded variables found.
03694   dimension_type pos_pinf_count = 0;
03695 
03696   // Approximate the inhomogeneous term.
03697   assign_r(pos_sum, sc_b, ROUND_UP);
03698 
03699   // Approximate the homogeneous part of `sc_expr'.
03700   const DB_Row<N>& dbm_0 = dbm[0];
03701   // Speculative allocation of temporaries to be used in the following loop.
03702   DIRTY_TEMP(N, coeff_i);
03703   TEMP_INTEGER(minus_sc_i);
03704   // Note: indices above `w' can be disregarded, as they all have
03705   // a zero coefficient in `sc_expr'.
03706   for (dimension_type i = w; i > 0; --i) {
03707     const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1));
03708     const int sign_i = sgn(sc_i);
03709     if (sign_i > 0) {
03710       assign_r(coeff_i, sc_i, ROUND_UP);
03711       // Approximating `sc_expr'.
03712       if (pos_pinf_count <= 1) {
03713         const N& up_approx_i = dbm_0[i];
03714         if (!is_plus_infinity(up_approx_i))
03715           add_mul_assign_r(pos_sum, coeff_i, up_approx_i, ROUND_UP);
03716         else {
03717           ++pos_pinf_count;
03718           pos_pinf_index = i;
03719         }
03720       }
03721     }
03722     else if (sign_i < 0) {
03723       neg_assign(minus_sc_i, sc_i);
03724       // Note: using temporary named `coeff_i' to store -coeff_i.
03725       assign_r(coeff_i, minus_sc_i, ROUND_UP);
03726       // Approximating `sc_expr'.
03727       if (pos_pinf_count <= 1) {
03728         const N& up_approx_minus_i = dbm[i][0];
03729         if (!is_plus_infinity(up_approx_minus_i))
03730           add_mul_assign_r(pos_sum, coeff_i, up_approx_minus_i, ROUND_UP);
03731         else {
03732           ++pos_pinf_count;
03733           pos_pinf_index = i;
03734         }
03735       }
03736     }
03737   }
03738   // Apply the affine lower bound.
03739   generalized_affine_image(var,
03740                            GREATER_OR_EQUAL,
03741                            lb_expr,
03742                            denominator);
03743   // Return immediately if no approximation could be computed.
03744   if (pos_pinf_count > 1) {
03745     return;
03746   }
03747 
03748   // In the following, shortest-path closure will be definitely lost.
03749   reset_shortest_path_closed();
03750 
03751   // Exploit the upper approximation, if possible.
03752   if (pos_pinf_count <= 1) {
03753     // Compute quotient (if needed).
03754     if (sc_den != 1) {
03755       // Before computing quotients, the denominator should be approximated
03756       // towards zero. Since `sc_den' is known to be positive, this amounts to
03757       // rounding downwards, which is achieved as usual by rounding upwards
03758       // `minus_sc_den' and negating again the result.
03759       DIRTY_TEMP(N, down_sc_den);
03760       assign_r(down_sc_den, minus_sc_den, ROUND_UP);
03761       neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
03762       div_assign_r(pos_sum, pos_sum, down_sc_den, ROUND_UP);
03763     }
03764     // Add the upper bound constraint, if meaningful.
03765     if (pos_pinf_count == 0) {
03766       // Add the constraint `v <= pos_sum'.
03767       dbm[0][v] = pos_sum;
03768       // Deduce constraints of the form `v - u', where `u != v'.
03769       deduce_v_minus_u_bounds(v, w, sc_expr, sc_den, pos_sum);
03770     }
03771     else
03772       // Here `pos_pinf_count == 1'.
03773       if (pos_pinf_index != v
03774           && sc_expr.coefficient(Variable(pos_pinf_index-1)) == sc_den)
03775         // Add the constraint `v - pos_pinf_index <= pos_sum'.
03776         dbm[pos_pinf_index][v] = pos_sum;
03777   }
03778   assert(OK());
03779 }

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

References 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 >::affine_image(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::BD_Shape< T >::refine(), 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(), TEMP_INTEGER, Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_generic().

03787                                                                          {
03788   // The denominator cannot be zero.
03789   if (denominator == 0)
03790     throw_generic("bounded_affine_preimage(v, lb, ub, d)", "d == 0");
03791 
03792   // Dimension-compatibility checks.
03793   // `var' should be one of the dimensions of the BD_Shape.
03794   const dimension_type space_dim = space_dimension();
03795   const dimension_type v = var.id() + 1;
03796   if (v > space_dim)
03797     throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
03798                                  "v", var);
03799   // The dimension of `lb_expr' and `ub_expr' should not be
03800   // greater than the dimension of `*this'.
03801   const dimension_type lb_space_dim = lb_expr.space_dimension();
03802   if (space_dim < lb_space_dim)
03803     throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)",
03804                                  "lb", lb_expr);
03805   const dimension_type ub_space_dim = ub_expr.space_dimension();
03806   if (space_dim < ub_space_dim)
03807     throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)",
03808                                  "ub", ub_expr);
03809 
03810   // Any preimage of an empty BDS is empty.
03811   shortest_path_closure_assign();
03812   if (marked_empty())
03813     return;
03814 
03815   if (ub_expr.coefficient(var) == 0) {
03816     refine(var, LESS_OR_EQUAL, ub_expr, denominator);
03817     generalized_affine_preimage(var, GREATER_OR_EQUAL,
03818                                 lb_expr, denominator);
03819     return;
03820   }
03821   if (lb_expr.coefficient(var) == 0) {
03822     refine(var, GREATER_OR_EQUAL, lb_expr, denominator);
03823     generalized_affine_preimage(var, LESS_OR_EQUAL,
03824                                 ub_expr, denominator);
03825     return;
03826   }
03827 
03828   const Coefficient& lb_expr_v = lb_expr.coefficient(var);
03829   // Here `var' occurs in `lb_expr' and `ub_expr'.
03830   // To ease the computation, we add an additional dimension.
03831   const Variable new_var = Variable(space_dim);
03832   add_space_dimensions_and_embed(1);
03833   const Linear_Expression lb_inverse
03834     = lb_expr - (lb_expr_v + denominator)*var;
03835   TEMP_INTEGER(lb_inverse_den);
03836   neg_assign(lb_inverse_den, lb_expr_v);
03837   affine_image(new_var, lb_inverse, lb_inverse_den);
03838   shortest_path_closure_assign();
03839   assert(!marked_empty());
03840   generalized_affine_preimage(var, LESS_OR_EQUAL,
03841                               ub_expr, denominator);
03842   if (sgn(denominator) == sgn(lb_inverse_den))
03843     add_constraint(var >= new_var);
03844   else
03845     add_constraint(var <= new_var);
03846   // Remove the temporarily added dimension.
03847   remove_higher_space_dimensions(space_dim);
03848 }

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 728 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().

00728                                                  {
00729   // Dimension-compatibility check.
00730   if (space_dimension() != y.space_dimension())
00731     throw_dimension_incompatible("time_elapse_assign(y)", y);
00732   // See the polyhedra documentation.
00733   C_Polyhedron px(constraints());
00734   C_Polyhedron py(y.constraints());
00735   px.time_elapse_assign(py);
00736   BD_Shape<T> x(px);
00737   swap(x);
00738   assert(OK());
00739 }

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

Assigns to *this its topological closure.

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

00458                                         {
00459   // Nothing to be done.
00460   return;
00461 }

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 808 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().

00808                                                                       {
00809   static N stop_points[] = {
00810     N(-2, ROUND_UP),
00811     N(-1, ROUND_UP),
00812     N( 0, ROUND_UP),
00813     N( 1, ROUND_UP),
00814     N( 2, ROUND_UP)
00815   };
00816   CC76_extrapolation_assign(y,
00817                             stop_points,
00818                             stop_points
00819                             + sizeof(stop_points)/sizeof(stop_points[0]),
00820                             tp);
00821 }

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 2167 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(), 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().

02169                                                      {
02170   const dimension_type space_dim = space_dimension();
02171 
02172   // Dimension-compatibility check.
02173   if (space_dim != y.space_dimension())
02174     throw_dimension_incompatible("CC76_extrapolation_assign(y)", y);
02175 
02176 #ifndef NDEBUG
02177   {
02178     // We assume that `y' is contained in or equal to `*this'.
02179     const BD_Shape x_copy = *this;
02180     const BD_Shape y_copy = y;
02181     assert(x_copy.contains(y_copy));
02182   }
02183 #endif
02184 
02185   // If both bounded difference shapes are zero-dimensional,
02186   // since `*this' contains `y', we simply return `*this'.
02187   if (space_dim == 0)
02188     return;
02189 
02190   shortest_path_closure_assign();
02191   // If `*this' is empty, since `*this' contains `y', `y' is empty too.
02192   if (marked_empty())
02193     return;
02194   y.shortest_path_closure_assign();
02195   // If `y' is empty, we return.
02196   if (y.marked_empty())
02197     return;
02198 
02199   // If there are tokens available, work on a temporary copy.
02200   if (tp != 0 && *tp > 0) {
02201     BD_Shape<T> x_tmp(*this);
02202     x_tmp.CC76_extrapolation_assign(y, first, last, 0);
02203     // If the widening was not precise, use one of the available tokens.
02204     if (!contains(x_tmp))
02205       --(*tp);
02206     return;
02207   }
02208 
02209   // Compare each constraint in `y' to the corresponding one in `*this'.
02210   // The constraint in `*this' is kept as is if it is stronger than or
02211   // equal to the constraint in `y'; otherwise, the inhomogeneous term
02212   // of the constraint in `*this' is further compared with elements taken
02213   // from a sorted container (the stop-points, provided by the user), and
02214   // is replaced by the first entry, if any, which is greater than or equal
02215   // to the inhomogeneous term. If no such entry exists, the constraint
02216   // is removed altogether.
02217   for (dimension_type i = space_dim + 1; i-- > 0; ) {
02218     DB_Row<N>& dbm_i = dbm[i];
02219     const DB_Row<N>& y_dbm_i = y.dbm[i];
02220     for (dimension_type j = space_dim + 1; j-- > 0; ) {
02221       N& dbm_ij = dbm_i[j];
02222       const N& y_dbm_ij = y_dbm_i[j];
02223       if (y_dbm_ij < dbm_ij) {
02224         Iterator k = std::lower_bound(first, last, dbm_ij);
02225         if (k != last) {
02226           if (dbm_ij < *k)
02227             assign_r(dbm_ij, *k, ROUND_UP);
02228         }
02229         else
02230           assign_r(dbm_ij, PLUS_INFINITY, ROUND_NOT_NEEDED);
02231       }
02232     }
02233   }
02234   reset_shortest_path_closed();
02235   assert(OK());
02236 }

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 2353 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(), 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().

02353                                                                    {
02354   const dimension_type space_dim = space_dimension();
02355 
02356   // Dimension-compatibility check.
02357   if (space_dim != y.space_dimension())
02358     throw_dimension_incompatible("BHMZ05_widening_assign(y)", y);
02359 
02360 #ifndef NDEBUG
02361   {
02362     // We assume that `y' is contained in or equal to `*this'.
02363     const BD_Shape x_copy = *this;
02364     const BD_Shape y_copy = y;
02365     assert(x_copy.contains(y_copy));
02366   }
02367 #endif
02368 
02369   // Compute the affine dimension of `y'.
02370   const dimension_type y_affine_dim = y.affine_dimension();
02371   // If the affine dimension of `y' is zero, then either `y' is
02372   // zero-dimensional, or it is empty, or it is a singleton.
02373   // In all cases, due to the inclusion hypothesis, the result is `*this'.
02374   if (y_affine_dim == 0)
02375     return;
02376 
02377   // If the affine dimension has changed, due to the inclusion hypothesis,
02378   // the result is `*this'.
02379   const dimension_type x_affine_dim = affine_dimension();
02380   assert(x_affine_dim >= y_affine_dim);
02381   if (x_affine_dim != y_affine_dim)
02382     return;
02383 
02384   // If there are tokens available, work on a temporary copy.
02385   if (tp != 0 && *tp > 0) {
02386     BD_Shape<T> x_tmp(*this);
02387     x_tmp.BHMZ05_widening_assign(y, 0);
02388     // If the widening was not precise, use one of the available tokens.
02389     if (!contains(x_tmp))
02390       --(*tp);
02391     return;
02392   }
02393 
02394   // Here no token is available.
02395   assert(marked_shortest_path_closed() && y.marked_shortest_path_closed());
02396   // Minimize `y'.
02397   y.shortest_path_reduction_assign();
02398 
02399   // Extrapolate unstable bounds, taking into account redundancy in `y'.
02400   for (dimension_type i = space_dim + 1; i-- > 0; ) {
02401     DB_Row<N>& dbm_i = dbm[i];
02402     const DB_Row<N>& y_dbm_i = y.dbm[i];
02403     const Bit_Row& y_redundancy_i = y.redundancy_dbm[i];
02404     for (dimension_type j = space_dim + 1; j-- > 0; ) {
02405       N& dbm_ij = dbm_i[j];
02406       // Note: in the following line the use of `!=' (as opposed to
02407       // the use of `<' that would seem -but is not- equivalent) is
02408       // intentional.
02409       if (y_redundancy_i[j] || y_dbm_i[j] != dbm_ij)
02410         assign_r(dbm_ij, PLUS_INFINITY, ROUND_NOT_NEEDED);
02411     }
02412   }
02413   // NOTE: this will also reset the shortest-path reduction flag,
02414   // even though the dbm is still in reduced form. However, the
02415   // current implementation invariant requires that any reduced dbm
02416   // is closed too.
02417   reset_shortest_path_closed();
02418   assert(OK());
02419 }

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

02425                                                                {
02426   // Dimension-compatibility check.
02427   const dimension_type space_dim = space_dimension();
02428   if (space_dim != y.space_dimension())
02429     throw_dimension_incompatible("limited_BHMZ05_extrapolation_assign(y, cs)",
02430                                  y);
02431   // `cs' must be dimension-compatible with the two systems
02432   // of bounded differences.
02433   const dimension_type cs_space_dim = cs.space_dimension();
02434   if (space_dim < cs_space_dim)
02435     throw_generic("limited_BHMZ05_extrapolation_assign(y, cs)",
02436                   "cs is space-dimension incompatible");
02437 
02438   // Strict inequalities are not allowed.
02439   if (cs.has_strict_inequalities())
02440     throw_generic("limited_BHMZ05_extrapolation_assign(y, cs)",
02441                   "cs has strict inequalities");
02442 
02443   // The limited BHMZ05-extrapolation between two systems of bounded
02444   // differences in a zero-dimensional space is a system of bounded
02445   // differences in a zero-dimensional space, too.
02446   if (space_dim == 0)
02447     return;
02448 
02449 #ifndef NDEBUG
02450   {
02451     // We assume that `y' is contained in or equal to `*this'.
02452     const BD_Shape x_copy = *this;
02453     const BD_Shape y_copy = y;
02454     assert(x_copy.contains(y_copy));
02455   }
02456 #endif
02457 
02458   // If `*this' is empty, since `*this' contains `y', `y' is empty too.
02459   if (marked_empty())
02460     return;
02461   // If `y' is empty, we return.
02462   if (y.marked_empty())
02463     return;
02464 
02465   BD_Shape<T> limiting_shape(space_dim, UNIVERSE);
02466   get_limiting_shape(cs, limiting_shape);
02467   BHMZ05_widening_assign(y, tp);
02468   intersection_assign(limiting_shape);
02469 }

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 2473 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().

02473                                                     {
02474   const dimension_type space_dim = space_dimension();
02475 
02476   // Dimension-compatibility check.
02477   if (space_dim != y.space_dimension())
02478     throw_dimension_incompatible("CC76_narrowing_assign(y)", y);
02479 
02480 #ifndef NDEBUG
02481   {
02482     // We assume that `*this' is contained in or equal to `y'.
02483     const BD_Shape x_copy = *this;
02484     const BD_Shape y_copy = y;
02485     assert(y_copy.contains(x_copy));
02486   }
02487 #endif
02488 
02489   // If both bounded difference shapes are zero-dimensional,
02490   // since `y' contains `*this', we simply return `*this'.
02491   if (space_dim == 0)
02492     return;
02493 
02494   y.shortest_path_closure_assign();
02495   // If `y' is empty, since `y' contains `this', `*this' is empty too.
02496   if (y.marked_empty())
02497     return;
02498   shortest_path_closure_assign();
02499   // If `*this' is empty, we return.
02500   if (marked_empty())
02501     return;
02502 
02503   // Replace each constraint in `*this' by the corresponding constraint
02504   // in `y' if the corresponding inhomogeneous terms are both finite.
02505   bool changed = false;
02506   for (dimension_type i = space_dim + 1; i-- > 0; ) {
02507     DB_Row<N>& dbm_i = dbm[i];
02508     const DB_Row<N>& y_dbm_i = y.dbm[i];
02509     for (dimension_type j = space_dim + 1; j-- > 0; ) {
02510       N& dbm_ij = dbm_i[j];
02511       const N& y_dbm_ij = y_dbm_i[j];
02512       if (!is_plus_infinity(dbm_ij)
02513           && !is_plus_infinity(y_dbm_ij)
02514           && dbm_ij != y_dbm_ij) {
02515         dbm_ij = y_dbm_ij;
02516         changed = true;
02517       }
02518     }
02519   }
02520   if (changed && marked_shortest_path_closed())
02521     reset_shortest_path_closed();
02522   assert(OK());
02523 }

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

02304                                                              {
02305   // Dimension-compatibility check.
02306   const dimension_type space_dim = space_dimension();
02307   if (space_dim != y.space_dimension())
02308     throw_dimension_incompatible("limited_CC76_extrapolation_assign(y, cs)",
02309                                  y);
02310 
02311   // `cs' must be dimension-compatible with the two systems
02312   // of bounded differences.
02313   const dimension_type cs_space_dim = cs.space_dimension();
02314   if (space_dim < cs_space_dim)
02315     throw_generic("limited_CC76_extrapolation_assign(y, cs)",
02316                   "cs is space_dimension incompatible");
02317 
02318   // Strict inequalities not allowed.
02319   if (cs.has_strict_inequalities())
02320     throw_generic("limited_CC76_extrapolation_assign(y, cs)",
02321                   "cs has strict inequalities");
02322 
02323   // The limited CC76-extrapolation between two systems of bounded
02324   // differences in a zero-dimensional space is a system of bounded
02325   // differences in a zero-dimensional space, too.
02326   if (space_dim == 0)
02327     return;
02328 
02329 #ifndef NDEBUG
02330   {
02331     // We assume that `y' is contained in or equal to `*this'.
02332     const BD_Shape x_copy = *this;
02333     const BD_Shape y_copy = y;
02334     assert(x_copy.contains(y_copy));
02335   }
02336 #endif
02337 
02338   // If `*this' is empty, since `*this' contains `y', `y' is empty too.
02339   if (marked_empty())
02340     return;
02341   // If `y' is empty, we return.
02342   if (y.marked_empty())
02343     return;
02344 
02345   BD_Shape<T> limiting_shape(space_dim, UNIVERSE);
02346   get_limiting_shape(cs, limiting_shape);
02347   CC76_extrapolation_assign(y, tp);
02348   intersection_assign(limiting_shape);
02349 }

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 825 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().

00825                                                                 {
00826   // See the documentation for polyhedra.
00827   C_Polyhedron px(constraints());
00828   C_Polyhedron py(y.constraints());
00829   px.H79_widening_assign(py, tp);
00830   BD_Shape x(px);
00831   swap(x);
00832   assert(OK());
00833 }

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

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

00837                                                             {
00838   H79_widening_assign(y, tp);
00839 }

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 843 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().

00845                                                             {
00846   // See the documentation for polyhedra.
00847   C_Polyhedron px(constraints());
00848   C_Polyhedron py(y.constraints());
00849   px.limited_H79_extrapolation_assign(py, cs, tp);
00850   BD_Shape x(px);
00851   swap(x);
00852   assert(OK());
00853 }

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 1893 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::BD_Shape< T >::set_shortest_path_closed(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::bounded_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::bounded_affine_preimage(), 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().

01893                                                                   {
01894   // Adding no dimensions is a no-op.
01895   if (m == 0)
01896     return;
01897 
01898   const dimension_type space_dim = space_dimension();
01899   const dimension_type new_space_dim = space_dim + m;
01900   const bool was_zero_dim_univ = (!marked_empty() && space_dim == 0);
01901 
01902   // To embed an n-dimension space BDS in a (n+m)-dimension space,
01903   // we just add `m' rows and columns in the bounded difference shape,
01904   // initialized to PLUS_INFINITY.
01905   dbm.grow(new_space_dim + 1);
01906 
01907   // Shortest-path closure is maintained (if it was holding).
01908   // TODO: see whether reduction can be (efficiently!) maintained too.
01909   if (marked_shortest_path_reduced())
01910     reset_shortest_path_reduced();
01911 
01912   // If `*this' was the zero-dim space universe BDS,
01913   // the we can set the shortest-path closure flag.
01914   if (was_zero_dim_univ)
01915     set_shortest_path_closed();
01916 
01917   assert(OK());
01918 }

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 1922 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 >::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().

01922                                                                     {
01923   // Adding no dimensions is a no-op.
01924   if (m == 0)
01925     return;
01926 
01927   const dimension_type space_dim = space_dimension();
01928 
01929   // If `*this' was zero-dimensional, then we add `m' rows and columns.
01930   // If it also was non-empty, then we zero all the added elements
01931   // and set the flag for shortest-path closure.
01932   if (space_dim == 0) {
01933     dbm.grow(m + 1);
01934     if (!marked_empty()) {
01935       for (dimension_type i = m + 1; i-- > 0; ) {
01936         DB_Row<N>& dbm_i = dbm[i];
01937         for (dimension_type j = m + 1; j-- > 0; )
01938           if (i != j)
01939             assign_r(dbm_i[j], 0, ROUND_NOT_NEEDED);
01940       }
01941       set_shortest_path_closed();
01942     }
01943     assert(OK());
01944     return;
01945   }
01946 
01947   // To project an n-dimension space bounded difference shape
01948   // in a (n+m)-dimension space, we add `m' rows and columns.
01949   // In the first row and column of the matrix we add `zero' from
01950   // the (n+1)-th position to the end.
01951   const dimension_type new_space_dim = space_dim + m;
01952   dbm.grow(new_space_dim + 1);
01953 
01954   // Bottom of the matrix and first row.
01955   DB_Row<N>& dbm_0 = dbm[0];
01956   for (dimension_type i = space_dim + 1; i <= new_space_dim; ++i) {
01957     assign_r(dbm[i][0], 0, ROUND_NOT_NEEDED);
01958     assign_r(dbm_0[i], 0, ROUND_NOT_NEEDED);
01959   }
01960 
01961   if (marked_shortest_path_closed())
01962     reset_shortest_path_closed();
01963   assert(OK());
01964 }

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 533 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::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().

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

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

Removes all the specified dimensions.

Parameters:
to_be_removed 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 to_be_removed.

Definition at line 1968 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::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(), Parma_Polyhedra_Library::swap(), and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

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

01968                                                                        {
01969   // The removal of no dimensions from any BDS is a no-op.
01970   // Note that this case also captures the only legal removal of
01971   // space dimensions from a BDS in a 0-dim space.
01972   if (to_be_removed.empty()) {
01973     assert(OK());
01974     return;
01975   }
01976 
01977   const dimension_type old_space_dim = space_dimension();
01978 
01979   // Dimension-compatibility check.
01980   const dimension_type min_space_dim = to_be_removed.space_dimension();
01981   if (old_space_dim < min_space_dim)
01982     throw_dimension_incompatible("remove_space_dimensions(vs)", min_space_dim);
01983 
01984   // Shortest-path closure is necessary to keep precision.
01985   shortest_path_closure_assign();
01986 
01987   // When removing _all_ dimensions from a BDS, we obtain the
01988   // zero-dimensional BDS.
01989   const dimension_type new_space_dim = old_space_dim - to_be_removed.size();
01990   if (new_space_dim == 0) {
01991     dbm.resize_no_copy(1);
01992     if (!marked_empty())
01993       // We set the zero_dim_univ flag.
01994       set_zero_dim_univ();
01995     assert(OK());
01996     return;
01997   }
01998 
01999   // Handle the case of an empty BD_Shape.
02000   if (marked_empty()) {
02001     dbm.resize_no_copy(new_space_dim + 1);
02002     assert(OK());
02003     return;
02004   }
02005 
02006   // Shortest-path closure is maintained.
02007   // TODO: see whether reduction can be (efficiently!) maintained too.
02008   if (marked_shortest_path_reduced())
02009     reset_shortest_path_reduced();
02010 
02011   // For each variable to remove, we fill the corresponding column and
02012   // row by shifting respectively left and above those
02013   // columns and rows, that will not be removed.
02014   Variables_Set::const_iterator tbr = to_be_removed.begin();
02015   Variables_Set::const_iterator tbr_end = to_be_removed.end();
02016   dimension_type dst = *tbr + 1;
02017   dimension_type src = dst + 1;
02018   for (++tbr; tbr != tbr_end; ++tbr) {
02019     const dimension_type tbr_next = *tbr + 1;
02020     // All other columns and rows are moved respectively to the left
02021     // and above.
02022     while (src < tbr_next) {
02023       std::swap(dbm[dst], dbm[src]);
02024       for (dimension_type i = old_space_dim + 1; i-- > 0; ) {
02025         DB_Row<N>& dbm_i = dbm[i];
02026         assign_or_swap(dbm_i[dst], dbm_i[src]);
02027       }
02028       ++dst;
02029       ++src;
02030     }
02031     ++src;
02032   }
02033 
02034   // Moving the remaining rows and columns.
02035   while (src <= old_space_dim) {
02036     std::swap(dbm[dst], dbm[src]);
02037     for (dimension_type i = old_space_dim + 1; i-- > 0; ) {
02038       DB_Row<N>& dbm_i = dbm[i];
02039       assign_or_swap(dbm_i[dst], dbm_i[src]);
02040     }
02041     ++src;
02042     ++dst;
02043   }
02044 
02045   // Update the space dimension.
02046   dbm.resize_no_copy(new_space_dim + 1);
02047   assert(OK());
02048 }

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 767 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::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 >::bounded_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::bounded_affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), and Parma_Polyhedra_Library::BD_Shape< T >::map_space_dimensions().

00767                                                                         {
00768   // Dimension-compatibility check: the variable having
00769   // maximum index is the one occurring last in the set.
00770   if (new_dim > space_dimension())
00771     throw_dimension_incompatible("remove_higher_space_dimensions(nd)",
00772                                  new_dim);
00773 
00774   // The removal of no dimensions from any BDS is a no-op.
00775   // Note that this case also captures the only legal removal of
00776   // dimensions from a zero-dim space BDS.
00777   if (new_dim == space_dimension()) {
00778     assert(OK());
00779     return;
00780   }
00781 
00782   // Shortest-path closure is necessary as in remove_space_dimensions().
00783   shortest_path_closure_assign();
00784   dbm.resize_no_copy(new_dim + 1);
00785 
00786   // Shortest-path closure is maintained.
00787   // TODO: see whether or not reduction can be (efficiently!) maintained too.
00788   if (marked_shortest_path_reduced())
00789     reset_shortest_path_reduced();
00790 
00791   // If we removed _all_ dimensions from a non-empty BDS,
00792   // the zero-dim universe BDS has been obtained.
00793   if (new_dim == 0 && !marked_empty())
00794     set_zero_dim_univ();
00795   assert(OK());
00796 }

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 class 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 2053 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::swap().

02053                                                                {
02054   const dimension_type space_dim = space_dimension();
02055   // TODO: this implementation is just an executable specification.
02056   if (space_dim == 0)
02057     return;
02058 
02059   if (pfunc.has_empty_codomain()) {
02060     // All dimensions vanish: the BDS becomes zero_dimensional.
02061     remove_higher_space_dimensions(0);
02062     return;
02063   }
02064 
02065   const dimension_type new_space_dim = pfunc.max_in_codomain() + 1;
02066   // If we are going to actually reduce the space dimension,
02067   // then shortest-path closure is required to keep precision.
02068   if (new_space_dim < space_dim)
02069     shortest_path_closure_assign();
02070 
02071   // If the BDS is empty, then it is sufficient to adjust the
02072   // space dimension of the bounded difference shape.
02073   if (marked_empty()) {
02074     remove_higher_space_dimensions(new_space_dim);
02075     return;
02076   }
02077 
02078   // Shortest-path closure is maintained (if it was holding).
02079   // TODO: see whether reduction can be (efficiently!) maintained too.
02080   if (marked_shortest_path_reduced())
02081     reset_shortest_path_reduced();
02082 
02083   // We create a new matrix with the new space dimension.
02084   DB_Matrix<N> x(new_space_dim+1);
02085   // First of all we must map the unary constraints, because
02086   // there is the fictitious variable `zero', that can't be mapped
02087   // at all.
02088   DB_Row<N>& dbm_0 = dbm[0];
02089   DB_Row<N>& x_0 = x[0];
02090   for (dimension_type j = 1; j <= space_dim; ++j) {
02091     dimension_type new_j;
02092     if (pfunc.maps(j - 1, new_j)) {
02093       assign_or_swap(x_0[new_j + 1], dbm_0[j]);
02094       assign_or_swap(x[new_j + 1][0], dbm[j][0]);
02095     }
02096   }
02097   // Now we map the binary constraints, exchanging the indexes.
02098   for (dimension_type i = 1; i <= space_dim; ++i) {
02099     dimension_type new_i;
02100     if (pfunc.maps(i - 1, new_i)) {
02101       DB_Row<N>& dbm_i = dbm[i];
02102       ++new_i;
02103       DB_Row<N>& x_new_i = x[new_i];
02104       for (dimension_type j = i+1; j <= space_dim; ++j) {
02105         dimension_type new_j;
02106         if (pfunc.maps(j - 1, new_j)) {
02107           ++new_j;
02108           assign_or_swap(x_new_i[new_j], dbm_i[j]);
02109           assign_or_swap(x[new_j][new_i], dbm[j][i]);
02110         }
02111       }
02112     }
02113   }
02114 
02115   std::swap(dbm, x);
02116   assert(OK());
02117 }

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 4833 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().

04833                                                                   {
04834   dimension_type old_dim = space_dimension();
04835   // `var' should be one of the dimensions of the vector space.
04836   if (var.space_dimension() > old_dim)
04837     throw_dimension_incompatible("expand_space_dimension(v, m)", "v", var);
04838 
04839   // The space dimension of the resulting BDS should not
04840   // overflow the maximum allowed space dimension.
04841   if (m > max_space_dimension() - space_dimension())
04842     throw_generic("expand_dimension(v, m)",
04843                   "adding m new space dimensions exceeds "
04844                   "the maximum allowed space dimension");
04845 
04846   // Nothing to do, if no dimensions must be added.
04847   if (m == 0)
04848     return;
04849 
04850   // Add the required new dimensions.
04851   add_space_dimensions_and_embed(m);
04852 
04853   // For each constraints involving variable `var', we add a
04854   // similar constraint with the new variable substituted for
04855   // variable `var'.
04856   const dimension_type v_id = var.id() + 1;
04857   const DB_Row<N>& dbm_v = dbm[v_id];
04858   for (dimension_type i = old_dim + 1; i-- > 0; ) {
04859     DB_Row<N>& dbm_i = dbm[i];
04860     const N& dbm_i_v = dbm[i][v_id];
04861     const N& dbm_v_i = dbm_v[i];
04862     for (dimension_type j = old_dim+1; j < old_dim+m+1; ++j) {
04863       dbm_i[j] = dbm_i_v;
04864       dbm[j][i] = dbm_v_i;
04865     }
04866   }
04867   // In general, adding a constraint does not preserve the shortest-path
04868   // closure or reduction of the bounded difference shape.
04869   if (marked_shortest_path_closed())
04870     reset_shortest_path_closed();
04871   assert(OK());
04872 }

template<typename T>
void Parma_Polyhedra_Library::BD_Shape< T >::fold_space_dimensions ( const Variables_Set &  to_be_folded,
Variable  var 
) [inline]

Folds the space dimensions in to_be_folded into var.

Parameters:
to_be_folded The set of Variable objects corresponding to the space dimensions to be folded;
var The variable corresponding to the space dimension that is the destination of the folding operation.
Exceptions:
std::invalid_argument Thrown if *this is dimension-incompatible with var or with one of the Variable objects contained in to_be_folded. Also thrown if var is contained in to_be_folded.
If *this has space dimension $n$, with $n > 0$, var has space dimension $k \leq n$, to_be_folded is a set of variables whose maximum space dimension is also less than or equal to $n$, and var is not a member of to_be_folded, then the space dimensions corresponding to variables in to_be_folded are folded into the $k$-th space dimension.

Definition at line 4876 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::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().

04877                                                  {
04878   const dimension_type space_dim = space_dimension();
04879   // `var' should be one of the dimensions of the BDS.
04880   if (var.space_dimension() > space_dim)
04881     throw_dimension_incompatible("fold_space_dimensions(tbf, v)",
04882                                  "v", var);
04883 
04884   // The folding of no dimensions is a no-op.
04885   if (to_be_folded.empty())
04886     return;
04887 
04888   // All variables in `to_be_folded' should be dimensions of the BDS.
04889   if (to_be_folded.space_dimension() > space_dim)
04890     throw_dimension_incompatible("fold_space_dimensions(tbf, ...)",
04891                                  to_be_folded.space_dimension());
04892 
04893   // Moreover, `var.id()' should not occur in `to_be_folded'.
04894   if (to_be_folded.find(var.id()) != to_be_folded.end())
04895     throw_generic("fold_space_dimensions(tbf, v)",
04896                   "v should not occur in tbf");
04897 
04898   shortest_path_closure_assign();
04899   if (!marked_empty()) {
04900     // Recompute the elements of the row and the column corresponding
04901     // to variable `var' by taking the join of their value with the
04902     // value of the corresponding elements in the row and column of the
04903     // variable `to_be_folded'.
04904     const dimension_type v_id = var.id() + 1;
04905     DB_Row<N>& dbm_v = dbm[v_id];
04906     for (Variables_Set::const_iterator i = to_be_folded.begin(),
04907            tbf_end = to_be_folded.end(); i != tbf_end; ++i) {
04908       const dimension_type tbf_id = *i + 1;
04909       const DB_Row<N>& dbm_tbf = dbm[tbf_id];
04910       for (dimension_type j = space_dim + 1; j-- > 0; ) {
04911         max_assign(dbm[j][v_id], dbm[j][tbf_id]);
04912         max_assign(dbm_v[j], dbm_tbf[j]);
04913       }
04914     }
04915   }
04916   remove_space_dimensions(to_be_folded);
04917 }

template<typename T>
void Parma_Polyhedra_Library::BD_Shape< T >::ascii_dump (  )  const

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

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

Writes to s an ASCII representation of *this.

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

References Parma_Polyhedra_Library::Bit_Matrix::ascii_dump(), Parma_Polyhedra_Library::BD_Shape< T >::Status::ascii_dump(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm, and Parma_Polyhedra_Library::BD_Shape< T >::status.

05031                                            {
05032   status.ascii_dump(s);
05033   s << "\n";
05034   dbm.ascii_dump(s);
05035   s << "\n";
05036   redundancy_dbm.ascii_dump(s);
05037 }

template<typename T>
void Parma_Polyhedra_Library::BD_Shape< T >::print (  )  const

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

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

References Parma_Polyhedra_Library::Bit_Matrix::ascii_load(), Parma_Polyhedra_Library::BD_Shape< T >::Status::ascii_load(), Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::BD_Shape< T >::redundancy_dbm, and Parma_Polyhedra_Library::BD_Shape< T >::status.

05043                                      {
05044   if (!status.ascii_load(s))
05045     return false;
05046   if (!dbm.ascii_load(s))
05047     return false;
05048   if (!redundancy_dbm.ascii_load(s))
05049     return false;
05050   return true;
05051 }

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

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

00857                                          {
00858   return sizeof(*this) + external_memory_in_bytes();
00859 }

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

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::Bit_Matrix::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().

05055                                             {
05056   return dbm.external_memory_in_bytes()
05057     + redundancy_dbm.external_memory_in_bytes();
05058 }

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

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

00863                              {
00864   return space_dimension() & 0x7fffffff;
00865 }

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 52 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().

00052                                         {
00053   return status.test_zero_dim_univ();
00054 }

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 58 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_congruence_and_minimize(), Parma_Polyhedra_Library::BD_Shape< T >::add_constraint_and_minimize(), Parma_Polyhedra_Library::BD_Shape< T >::add_constraints_and_minimize(), 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 >::bounded_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::bounded_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 >::compute_leaders(), Parma_Polyhedra_Library::BD_Shape< T >::compute_predecessors(), 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 >::euclidean_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign_and_minimize(), 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 >::unconstrain(), Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign_and_minimize().

00058                                 {
00059   return status.test_empty();
00060 }

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

template<typename T>
bool Parma_Polyhedra_Library::BD_Shape< T >::marked_shortest_path_reduced (  )  const [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_zero_dim_univ (  )  [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 >::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 >::shortest_path_closure_assign (  )  const [inline, private]

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

Definition at line 1620 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(), 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 >::add_congruence_and_minimize(), Parma_Polyhedra_Library::BD_Shape< T >::add_constraint_and_minimize(), Parma_Polyhedra_Library::BD_Shape< T >::add_constraints_and_minimize(), 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 >::bounded_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::bounded_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 >::contains(), Parma_Polyhedra_Library::BD_Shape< T >::difference_assign(), Parma_Polyhedra_Library::BD_Shape< T >::euclidean_distance_assign(), Parma_Polyhedra_Library::BD_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::get_limiting_shape(), Parma_Polyhedra_Library::BD_Shape< T >::intersection_assign_and_minimize(), 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 >::unconstrain(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign().

01620                                                 {
01621   // Do something only if necessary.
01622   if (marked_empty() || marked_shortest_path_closed())
01623     return;
01624   const dimension_type num_dimensions = space_dimension();
01625   // Zero-dimensional BDSs are necessarily shortest-path closed.
01626   if (num_dimensions == 0)
01627     return;
01628 
01629   // Even though the BDS will not change, its internal representation
01630   // is going to be modified by the Floyd-Warshall algorithm.
01631   BD_Shape& x = const_cast<BD_Shape<T>&>(*this);
01632 
01633   // Fill the main diagonal with zeros.
01634   for (dimension_type h = num_dimensions + 1; h-- > 0; ) {
01635     assert(is_plus_infinity(x.dbm[h][h]));
01636     assign_r(x.dbm[h][h], 0, ROUND_NOT_NEEDED);
01637   }
01638 
01639   DIRTY_TEMP(N, sum);
01640   for (dimension_type k = num_dimensions + 1; k-- > 0; ) {
01641     const DB_Row<N>& x_dbm_k = x.dbm[k];
01642     for (dimension_type i = num_dimensions + 1; i-- > 0; ) {
01643       DB_Row<N>& x_dbm_i = x.dbm[i];
01644       const N& x_dbm_i_k = x_dbm_i[k];
01645       if (!is_plus_infinity(x_dbm_i_k))
01646         for (dimension_type j = num_dimensions + 1; j-- > 0; ) {
01647           const N& x_dbm_k_j = x_dbm_k[j];
01648           if (!is_plus_infinity(x_dbm_k_j)) {
01649             // Rounding upward for correctness.
01650             add_assign_r(sum, x_dbm_i_k, x_dbm_k_j, ROUND_UP);
01651             min_assign(x_dbm_i[j], sum);
01652           }
01653         }
01654     }
01655   }
01656 
01657   // Check for emptiness: the BDS is empty if and only if there is a
01658   // negative value on the main diagonal of `dbm'.
01659   for (dimension_type h = num_dimensions + 1; h-- > 0; ) {
01660     N& x_dbm_hh = x.dbm[h][h];
01661     if (sgn(x_dbm_hh) < 0) {
01662       x.set_empty();
01663       return;
01664     }
01665     else {
01666       assert(sgn(x_dbm_hh) == 0);
01667       // Restore PLUS_INFINITY on the main diagonal.
01668       assign_r(x_dbm_hh, PLUS_INFINITY, ROUND_NOT_NEEDED);
01669     }
01670   }
01671 
01672   // The BDS is not empty and it is now shortest-path closed.
01673   x.set_shortest_path_closed();
01674 }

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 1678 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::swap().

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

01678                                                   {
01679   // Do something only if necessary.
01680   if (marked_shortest_path_reduced())
01681     return;
01682 
01683   const dimension_type space_dim = space_dimension();
01684   // Zero-dimensional BDSs are necessarily reduced.
01685   if (space_dim == 0)
01686     return;
01687 
01688   // First find the tightest constraints for this BDS.
01689   shortest_path_closure_assign();
01690 
01691   // If `*this' is empty, then there is nothing to reduce.
01692   if (marked_empty())
01693     return;
01694 
01695   // Step 1: compute zero-equivalence classes.
01696   // Variables corresponding to indices `i' and `j' are zero-equivalent
01697   // if they lie on a zero-weight loop; since the matrix is shortest-path
01698   // closed, this happens if and only if dbm[i][j] == -dbm[j][i].
01699   std::vector<dimension_type> predecessor;
01700   compute_predecessors(predecessor);
01701   std::vector<dimension_type> leaders;
01702   compute_leader_indices(predecessor, leaders);
01703   const dimension_type num_leaders = leaders.size();
01704 
01705   Bit_Matrix redundancy(space_dim + 1, space_dim + 1);
01706   // Init all constraints to be redundant.
01707   // TODO: provide an appropriate method to set multiple bits.
01708   Bit_Row& red_0 = redundancy[0];
01709   for (dimension_type j = space_dim + 1; j-- > 0; )
01710     red_0.set(j);
01711   for (dimension_type i = space_dim + 1; i-- > 0; )
01712     redundancy[i] = red_0;
01713 
01714   // Step 2: flag non-redundant constraints in the (zero-cycle-free)
01715   // subsystem of bounded differences having only leaders as variables.
01716   DIRTY_TEMP(N, c);
01717   for (dimension_type l_i = 0; l_i < num_leaders; ++l_i) {
01718     const dimension_type i = leaders[l_i];
01719     const DB_Row<N>& dbm_i = dbm[i];
01720     Bit_Row& redundancy_i = redundancy[i];
01721     for (dimension_type l_j = 0; l_j < num_leaders; ++l_j) {
01722       const dimension_type j = leaders[l_j];
01723       if (redundancy_i[j]) {
01724         const N& dbm_i_j = dbm_i[j];
01725         redundancy_i.clear(j);
01726         for (dimension_type l_k = 0; l_k < num_leaders; ++l_k) {
01727           const dimension_type k = leaders[l_k];
01728           add_assign_r(c, dbm_i[k], dbm[k][j], ROUND_UP);
01729           if (dbm_i_j >= c) {
01730             redundancy_i.set(j);
01731             break;
01732           }
01733         }
01734       }
01735     }
01736   }
01737 
01738   // Step 3: flag non-redundant constraints in zero-equivalence classes.
01739   // Each equivalence class must have a single 0-cycle connecting
01740   // all the equivalent variables in increasing order.
01741   std::deque<bool> dealt_with(space_dim + 1, false);
01742   for (dimension_type i = space_dim + 1; i-- > 0; )
01743     // We only need to deal with non-singleton zero-equivalence classes
01744     // that haven't already been dealt with.
01745     if (i != predecessor[i] && !dealt_with[i]) {
01746       dimension_type j = i;
01747       while (true) {
01748         const dimension_type pred_j = predecessor[j];
01749         if (j == pred_j) {
01750           // We finally found the leader of `i'.
01751           assert(redundancy[i][j]);
01752           redundancy[i].clear(j);
01753           // Here we dealt with `j' (i.e., `pred_j'), but it is useless
01754           // to update `dealt_with' because `j' is a leader.
01755           break;
01756         }
01757         // We haven't found the leader of `i' yet.
01758         assert(redundancy[pred_j][j]);
01759         redundancy[pred_j].clear(j);
01760         dealt_with[pred_j] = true;
01761         j = pred_j;
01762       }
01763     }
01764 
01765   // Even though shortest-path reduction is not going to change the BDS,
01766   // it might change its internal representation.
01767   BD_Shape<T>& x = const_cast<BD_Shape<T>&>(*this);
01768   std::swap(x.redundancy_dbm, redundancy);
01769   x.set_shortest_path_reduced();
01770 
01771   assert(is_shortest_path_reduced());
01772 }

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 844 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().

00844                                             {
00845   // If the BDS is empty, it is also reduced.
00846   if (marked_empty())
00847     return true;
00848 
00849   const dimension_type space_dim = space_dimension();
00850   // Zero-dimensional BDSs are necessarily reduced.
00851   if (space_dim == 0)
00852     return true;
00853 
00854   // A shortest-path reduced dbm is just a dbm with an indication of
00855   // those constraints that are redundant. If there is no indication
00856   // of the redundant constraints, then it cannot be reduced.
00857   if (!marked_shortest_path_reduced())
00858     return false;
00859 
00860   const BD_Shape x_copy = *this;
00861   x_copy.shortest_path_closure_assign();
00862   // If we just discovered emptiness, it cannot be reduced.
00863   if (x_copy.marked_empty())
00864     return false;
00865 
00866   // The vector `leader' is used to indicate which variables are equivalent.
00867   std::vector<dimension_type> leader(space_dim + 1);
00868 
00869   // We store the leader.
00870   for (dimension_type i = space_dim + 1; i-- > 0; )
00871     leader[i] = i;
00872 
00873   // Step 1: we store really the leader with the corrected value.
00874   // We search for the equivalent or zero-equivalent variables.
00875   // The variable(i-1) and variable(j-1) are equivalent if and only if
00876   // m_i_j == -(m_j_i).
00877   for (dimension_type i = 0; i < space_dim; ++i) {
00878     const DB_Row<N>& x_copy_dbm_i = x_copy.dbm[i];
00879     for (dimension_type j = i + 1; j <= space_dim; ++j)
00880       if (is_additive_inverse(x_copy.dbm[j][i], x_copy_dbm_i[j]))
00881         // Two equivalent variables have got the same leader
00882         // (the smaller variable).
00883         leader[j] = leader[i];
00884   }
00885 
00886   // Step 2: we check if there are redundant constraints in the zero_cycle
00887   // free bounded difference shape, considering only the leaders.
00888   // A constraint `c' is redundant, when there are two constraints such that
00889   // their sum is the same constraint with the inhomogeneous term
00890   // less than or equal to the `c' one.
00891   DIRTY_TEMP(N, c);
00892   for (dimension_type k = 0; k <= space_dim; ++k)
00893     if (leader[k] == k) {
00894       const DB_Row<N>& x_k = x_copy.dbm[k];
00895       for (dimension_type i = 0; i <= space_dim; ++i)
00896         if (leader[i] == i) {
00897           const DB_Row<N>& x_i = x_copy.dbm[i];
00898           const Bit_Row& redundancy_i = redundancy_dbm[i];
00899           const N& x_i_k = x_i[k];
00900           for (dimension_type j = 0; j <= space_dim; ++j)
00901             if (leader[j] == j) {
00902               const N& x_i_j = x_i[j];
00903               if (!is_plus_infinity(x_i_j)) {
00904                 add_assign_r(c, x_i_k, x_k[j], ROUND_UP);
00905                 if (x_i_j >= c && !redundancy_i[j])
00906                   return false;
00907               }
00908             }
00909         }
00910     }
00911 
00912   // The vector `var_conn' is used to check if there is a single cycle
00913   // that connected all zero-equivalent variables between them.
00914   // The value `space_dim + 1' is used to indicate that the equivalence
00915   // class contains a single variable.
00916   std::vector<dimension_type> var_conn(space_dim + 1);
00917   for (dimension_type i = space_dim + 1; i-- > 0; )
00918     var_conn[i] = space_dim + 1;
00919 
00920   // Step 3: we store really the `var_conn' with the right value, putting
00921   // the variable with the selected variable is connected:
00922   // we check the row of each variable:
00923   // a- each leader could be connected with only zero-equivalent one,
00924   // b- each no-leader with only another zero-equivalent one.
00925   for (dimension_type i = 0; i <= space_dim; ++i) {
00926     // It count with how many variables the selected variable is
00927     // connected.
00928     dimension_type t = 0;
00929     dimension_type ld_i = leader[i];
00930     // Case a: leader.
00931     if (ld_i == i) {
00932       for (dimension_type j = 0; j <= space_dim; ++j) {
00933         dimension_type ld_j = leader[j];
00934         // Only the connectedness with equivalent variables
00935         // is considered.
00936         if (j != ld_j)
00937           if (!redundancy_dbm[i][j]) {
00938             if (t == 1)
00939               // Two no-leaders couldn't connected with the same leader.
00940               return false;
00941             else
00942               if (ld_j != i)
00943                 // The variables isn't in the same equivalence class.
00944                 return false;
00945               else {
00946                 ++t;
00947                 var_conn[i] = j;
00948               }
00949           }
00950       }
00951     }
00952     // Case b: no-leader.
00953     else {
00954       for (dimension_type j = 0; j <= space_dim; ++j) {
00955         if (!redundancy_dbm[i][j]) {
00956           dimension_type ld_j = leader[j];
00957           if (ld_i != ld_j)
00958             // The variables isn't in the same equivalence class.
00959             return false;
00960           else {
00961             if (t == 1)
00962               // Two variables couldn't connected with the same leader.
00963               return false;
00964             else {
00965               ++t;
00966               var_conn[i] = j;
00967             }
00968           }
00969           // A no-leader must be connected with
00970           // another variable.
00971           if (t == 0)
00972             return false;
00973         }
00974       }
00975     }
00976   }
00977 
00978   // The vector `just_checked' is used to check if
00979   // a variable is already checked.
00980   std::vector<bool> just_checked(space_dim + 1);
00981   for (dimension_type i = space_dim + 1; i-- > 0; )
00982     just_checked[i] = false;
00983 
00984   // Step 4: we check if there are single cycles that
00985   // connected all the zero-equivalent variables between them.
00986   for (dimension_type i = 0; i <= space_dim; ++i) {
00987     bool jc_i = just_checked[i];
00988     // We do not re-check the already considered single cycles.
00989     if (!jc_i) {
00990       dimension_type v_con = var_conn[i];
00991       // We consider only the equivalence classes with
00992       // 2 or plus variables.
00993       if (v_con != space_dim + 1) {
00994         // There is a single cycle if taken a variable,
00995         // we return to this same variable.
00996         while (v_con != i) {
00997           just_checked[v_con] = true;
00998           v_con = var_conn[v_con];
00999           // If we re-pass to an already considered variable,
01000           // then we haven't a single cycle.
01001           if (just_checked[v_con])
01002             return false;
01003         }
01004       }
01005     }
01006     just_checked[i] = true;
01007   }
01008 
01009   // The system bounded differences is just reduced.
01010   return true;
01011 }

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 1015 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, 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(), TEMP_INTEGER, 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().

01016                                                  {
01017   // The dimension of `expr' should not be greater than the dimension
01018   // of `*this'.
01019   const dimension_type expr_space_dim = expr.space_dimension();
01020   const dimension_type space_dim = space_dimension();
01021   if (space_dim < expr_space_dim)
01022     throw_dimension_incompatible((from_above
01023                                   ? "bounds_from_above(e)"
01024                                   : "bounds_from_below(e)"), "e", expr);
01025 
01026   shortest_path_closure_assign();
01027   // A zero-dimensional or empty BDS bounds everything.
01028   if (space_dim == 0 || marked_empty())
01029     return true;
01030 
01031   // The constraint `c' is used to check if `expr' is a difference
01032   // bounded and, in this case, to select the cell.
01033   const Constraint& c = from_above ? expr <= 0 : expr >= 0;
01034   const dimension_type c_space_dim = c.space_dimension();
01035   dimension_type num_vars = 0;
01036   dimension_type i = 0;
01037   dimension_type j = 0;
01038   TEMP_INTEGER(coeff);
01039   // Check if `c' is a BD constraint.
01040   if (extract_bounded_difference(c, c_space_dim, num_vars, i, j, coeff)) {
01041     if (num_vars == 0)
01042       // Dealing with a trivial constraint.
01043       return true;
01044     // Select the cell to be checked.
01045     const N& x = (coeff < 0) ? dbm[i][j] : dbm[j][i];
01046     return !is_plus_infinity(x);
01047   }
01048   else {
01049     // Not a DB constraint: use the MIP solver.
01050     Optimization_Mode mode_bounds
01051       = from_above ? MAXIMIZATION : MINIMIZATION;
01052     MIP_Problem mip(space_dim, constraints(), expr, mode_bounds);
01053     // Problem is known to be feasible.
01054     return (mip.solve() == OPTIMIZED_MIP_PROBLEM);
01055   }
01056 }

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 1159 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().

01163                                          {
01164   // The dimension of `expr' should not be greater than the dimension
01165   // of `*this'.
01166   const dimension_type space_dim = space_dimension();
01167   const dimension_type expr_space_dim = expr.space_dimension();
01168   if (space_dim < expr_space_dim)
01169     throw_dimension_incompatible((maximize
01170                                   ? "maximize(e, ...)"
01171                                   : "minimize(e, ...)"), "e", expr);
01172   // Deal with zero-dim BDS first.
01173   if (space_dim == 0) {
01174     if (marked_empty())
01175       return false;
01176     else {
01177       ext_n = expr.inhomogeneous_term();
01178       ext_d = 1;
01179       included = true;
01180       g = point();
01181       return true;
01182     }
01183   }
01184 
01185   shortest_path_closure_assign();
01186   // For an empty BDS we simply return false.
01187   if (marked_empty())
01188     return false;
01189 
01190   Optimization_Mode mode_max_min
01191     = maximize ? MAXIMIZATION : MINIMIZATION;
01192   MIP_Problem mip(space_dim, constraints(), expr, mode_max_min);
01193   if (mip.solve() == OPTIMIZED_MIP_PROBLEM) {
01194     g = mip.optimizing_point();
01195     mip.evaluate_objective_function(g, ext_n, ext_d);
01196     included = true;
01197     return true;
01198   }
01199   // Here `expr' is unbounded in `*this'.
01200   return false;
01201 }

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 1060 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, 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(), TEMP_INTEGER, and Parma_Polyhedra_Library::BD_Shape< T >::throw_dimension_incompatible().

01063                                            {
01064   // The dimension of `expr' should not be greater than the dimension
01065   // of `*this'.
01066   const dimension_type space_dim = space_dimension();
01067   const dimension_type expr_space_dim = expr.space_dimension();
01068   if (space_dim < expr_space_dim)
01069     throw_dimension_incompatible((maximize
01070                                   ? "maximize(e, ...)"
01071                                   : "minimize(e, ...)"), "e", expr);
01072   // Deal with zero-dim BDS first.
01073   if (space_dim == 0) {
01074     if (marked_empty())
01075       return false;
01076     else {
01077       ext_n = expr.inhomogeneous_term();
01078       ext_d = 1;
01079       included = true;
01080       return true;
01081     }
01082   }
01083 
01084   shortest_path_closure_assign();
01085   // For an empty BDS we simply return false.
01086   if (marked_empty())
01087     return false;
01088 
01089   // The constraint `c' is used to check if `expr' is a difference
01090   // bounded and, in this case, to select the cell.
01091   const Constraint& c = maximize ? expr <= 0 : expr >= 0;
01092   const dimension_type c_space_dim = c.space_dimension();
01093   dimension_type num_vars = 0;
01094   dimension_type i = 0;
01095   dimension_type j = 0;
01096   TEMP_INTEGER(coeff);
01097   // Check if `c' is a BD constraint.
01098   if (!extract_bounded_difference(c, c_space_dim, num_vars, i, j, coeff)) {
01099     Optimization_Mode mode_max_min
01100       = maximize ? MAXIMIZATION : MINIMIZATION;
01101     MIP_Problem mip(space_dim, constraints(), expr, mode_max_min);
01102     if (mip.solve() == OPTIMIZED_MIP_PROBLEM) {
01103       mip.optimal_value(ext_n, ext_d);
01104       included = true;
01105       return true;
01106     }
01107     else
01108       // Here`expr' is unbounded in `*this'.
01109       return false;
01110   }
01111   else {
01112     // Here `expr' is a bounded difference.
01113     if (num_vars == 0) {
01114       // Dealing with a trivial expression.
01115       ext_n = expr.inhomogeneous_term();
01116       ext_d = 1;
01117       included = true;
01118       return true;
01119     }
01120 
01121     // Select the cell to be checked.
01122     const N& x = (coeff < 0) ? dbm[i][j] : dbm[j][i];
01123     if (!is_plus_infinity(x)) {
01124       // Compute the maximize/minimize of `expr'.
01125       DIRTY_TEMP(N, d);
01126       const Coefficient& b = expr.inhomogeneous_term();
01127       TEMP_INTEGER(minus_b);
01128       neg_assign(minus_b, b);
01129       const Coefficient& sc_b = maximize ? b : minus_b;
01130       assign_r(d, sc_b, ROUND_UP);
01131       // Set `coeff_expr' to the absolute value of coefficient of
01132       // a variable in `expr'.
01133       DIRTY_TEMP(N, coeff_expr);
01134       const Coefficient& coeff_i = expr.coefficient(Variable(i-1));
01135       const int sign_i = sgn(coeff_i);
01136       if (sign_i > 0)
01137         assign_r(coeff_expr, coeff_i, ROUND_UP);
01138       else {
01139         TEMP_INTEGER(minus_coeff_i);
01140         neg_assign(minus_coeff_i, coeff_i);
01141         assign_r(coeff_expr, minus_coeff_i, ROUND_UP);
01142       }
01143       // Approximating the maximum/minimum of `expr'.
01144       add_mul_assign_r(d, coeff_expr, x, ROUND_UP);
01145       numer_denom(d, ext_n, ext_d);
01146       if (!maximize)
01147         neg_assign(ext_n);
01148       included = true;
01149       return true;
01150     }
01151 
01152     // `expr' is unbounded.
01153     return false;
01154   }
01155 }

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 473 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(), 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(), and TEMP_INTEGER.

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

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

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 278 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().

00278                                                  {
00279   assert(!marked_empty());
00280   assert(cg.space_dimension() <= space_dimension());
00281 
00282   if (cg.is_proper_congruence()) {
00283     if (cg.is_inconsistent())
00284       set_empty();
00285     // Other proper congruences are just ignored.
00286     return;
00287   }
00288 
00289   assert(cg.is_equality());
00290   Constraint c(cg);
00291   refine_no_check(c);
00292 }

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_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 714 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().

00717                                                                        {
00718   // Private method: the caller has to ensure the following.
00719   assert(i <= space_dimension() && j <= space_dimension() && i != j);
00720   assert(den != 0);
00721   DIRTY_TEMP(N, k);
00722   div_round_up(k, num, den);
00723   add_dbm_constraint(i, j, k);
00724 }

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 2723 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(), Parma_Polyhedra_Library::BD_Shape< T >::reset_shortest_path_closed(), Parma_Polyhedra_Library::BD_Shape< T >::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and TEMP_INTEGER.

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

02726                                                                    {
02727   assert(denominator != 0);
02728   const dimension_type expr_space_dim = expr.space_dimension();
02729   assert(space_dimension() >= expr_space_dim);
02730   const dimension_type v = var.id() + 1;
02731   assert(v <= space_dimension());
02732   assert(expr.coefficient(var) == 0);
02733   assert(relsym != LESS_THAN && relsym != GREATER_THAN);
02734 
02735   const Coefficient& b = expr.inhomogeneous_term();
02736   // Number of non-zero coefficients in `expr': will be set to
02737   // 0, 1, or 2, the latter value meaning any value greater than 1.
02738   dimension_type t = 0;
02739   // Index of the last non-zero coefficient in `expr', if any.
02740   dimension_type w = 0;
02741   // Get information about the number of non-zero coefficients in `expr'.
02742   for (dimension_type i = expr_space_dim; i-- > 0; )
02743     if (expr.coefficient(Variable(i)) != 0) {
02744       if (t++ == 1)
02745         break;
02746       else
02747         w = i+1;
02748     }
02749 
02750   // Since we are only able to record bounded differences, we can
02751   // precisely deal with the case of a single variable only if its
02752   // coefficient (taking into account the denominator) is 1.
02753   // If this is not the case, we fall back to the general case
02754   // so as to over-approximate the constraint.
02755   if (t == 1 && expr.coefficient(Variable(w-1)) != denominator)
02756     t = 2;
02757 
02758   // Now we know the form of `expr':
02759   // - If t == 0, then expr == b, with `b' a constant;
02760   // - If t == 1, then expr == a*w + b, where `w != v' and `a == denominator';
02761   // - If t == 2, the `expr' is of the general form.
02762   const DB_Row<N>& dbm_0 = dbm[0];
02763   TEMP_INTEGER(minus_den);
02764   neg_assign(minus_den, denominator);
02765 
02766   if (t == 0) {
02767     // Case 1: expr == b.
02768     switch (relsym) {
02769     case EQUAL:
02770       // Add the constraint `var == b/denominator'.
02771       add_dbm_constraint(0, v, b, denominator);
02772       add_dbm_constraint(v, 0, b, minus_den);
02773       break;
02774     case LESS_OR_EQUAL:
02775       // Add the constraint `var <= b/denominator'.
02776       add_dbm_constraint(0, v, b, denominator);
02777       break;
02778     case GREATER_OR_EQUAL:
02779       // Add the constraint `var >= b/denominator',
02780       // i.e., `-var <= -b/denominator',
02781       add_dbm_constraint(v, 0, b, minus_den);
02782       break;
02783     default:
02784       // We already dealt with the other cases.
02785       throw std::runtime_error("PPL internal error");
02786     }
02787     return;
02788   }
02789 
02790   if (t == 1) {
02791     // Case 2: expr == a*w + b, w != v, a == denominator.
02792     assert(expr.coefficient(Variable(w-1)) == denominator);
02793     DIRTY_TEMP(N, d);
02794     switch (relsym) {
02795     case EQUAL:
02796       // Add the new constraint `v - w <= b/denominator'.
02797       div_round_up(d, b, denominator);
02798       add_dbm_constraint(w, v, d);
02799       // Add the new constraint `v - w >= b/denominator',
02800       // i.e., `w - v <= -b/denominator'.
02801       div_round_up(d, b, minus_den);
02802       add_dbm_constraint(v, w, d);
02803       break;
02804     case LESS_OR_EQUAL:
02805       // Add the new constraint `v - w <= b/denominator'.
02806       div_round_up(d, b, denominator);
02807       add_dbm_constraint(w, v, d);
02808       break;
02809     case GREATER_OR_EQUAL:
02810       // Add the new constraint `v - w >= b/denominator',
02811       // i.e., `w - v <= -b/denominator'.
02812       div_round_up(d, b, minus_den);
02813       add_dbm_constraint(v, w, d);
02814       break;
02815     default:
02816       // We already dealt with the other cases.
02817       throw std::runtime_error("PPL internal error");
02818     }
02819     return;
02820   }
02821 
02822   // Here t == 2, so that either
02823   // expr == a_1*x_1 + a_2*x_2 + ... + a_n*x_n + b, where n >= 2, or
02824   // expr == a*w + b, w != v and a != denominator.
02825   const bool is_sc = (denominator > 0);
02826   TEMP_INTEGER(minus_b);
02827   neg_assign(minus_b, b);
02828   const Coefficient& sc_b = is_sc ? b : minus_b;
02829   const Coefficient& minus_sc_b = is_sc ? minus_b : b;
02830   const Coefficient& sc_den = is_sc ? denominator : minus_den;
02831   const Coefficient& minus_sc_den = is_sc ? minus_den : denominator;
02832   // NOTE: here, for optimization purposes, `minus_expr' is only assigned
02833   // when `denominator' is negative. Do not use it unless you are sure
02834   // it has been correctly assigned.
02835   Linear_Expression minus_expr;
02836   if (!is_sc)
02837     minus_expr = -expr;
02838   const Linear_Expression& sc_expr = is_sc ? expr : minus_expr;
02839 
02840   DIRTY_TEMP(N, sum);
02841   // Indices of the variables that are unbounded in `this->dbm'.
02842   PPL_UNINITIALIZED(dimension_type, pinf_index);
02843   // Number of unbounded variables found.
02844   dimension_type pinf_count = 0;
02845 
02846   // Speculative allocation of temporaries that are used in most
02847   // of the computational traces starting from this point (also loops).
02848   TEMP_INTEGER(minus_sc_i);
02849   DIRTY_TEMP(N, coeff_i);
02850 
02851   switch (relsym) {
02852   case EQUAL:
02853     {
02854       DIRTY_TEMP(N, neg_sum);
02855       // Indices of the variables that are unbounded in `this->dbm'.
02856       PPL_UNINITIALIZED(dimension_type, neg_pinf_index);
02857       // Number of unbounded variables found.
02858       dimension_type neg_pinf_count = 0;
02859 
02860       // Compute an upper approximation for `expr' into `sum',
02861       // taking into account the sign of `denominator'.
02862 
02863       // Approximate the inhomogeneous term.
02864       assign_r(sum, sc_b, ROUND_UP);
02865       assign_r(neg_sum, minus_sc_b, ROUND_UP);
02866 
02867       // Approximate the homogeneous part of `sc_expr'.
02868       // Note: indices above `w' can be disregarded, as they all have
02869       // a zero coefficient in `expr'.
02870       for (dimension_type i = w; i > 0; --i) {
02871         const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1));
02872         const int sign_i = sgn(sc_i);
02873         if (sign_i == 0)
02874           continue;
02875         if (sign_i > 0) {
02876           assign_r(coeff_i, sc_i, ROUND_UP);
02877           // Approximating `sc_expr'.
02878           if (pinf_count <= 1) {
02879             const N& approx_i = dbm_0[i];
02880             if (!is_plus_infinity(approx_i))
02881               add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
02882             else {
02883               ++pinf_count;
02884               pinf_index = i;
02885             }
02886           }
02887           // Approximating `-sc_expr'.
02888           if (neg_pinf_count <= 1) {
02889             const N& approx_minus_i = dbm[i][0];
02890             if (!is_plus_infinity(approx_minus_i))
02891               add_mul_assign_r(neg_sum, coeff_i, approx_minus_i, ROUND_UP);
02892             else {
02893               ++neg_pinf_count;
02894               neg_pinf_index = i;
02895             }
02896           }
02897         }
02898         else if (sign_i < 0) {
02899           neg_assign(minus_sc_i, sc_i);
02900           // Note: using temporary named `coeff_i' to store -coeff_i.
02901           assign_r(coeff_i, minus_sc_i, ROUND_UP);
02902           // Approximating `sc_expr'.
02903           if (pinf_count <= 1) {
02904             const N& approx_minus_i = dbm[i][0];
02905             if (!is_plus_infinity(approx_minus_i))
02906               add_mul_assign_r(sum, coeff_i, approx_minus_i, ROUND_UP);
02907             else {
02908               ++pinf_count;
02909               pinf_index = i;
02910             }
02911           }
02912           // Approximating `-sc_expr'.
02913           if (neg_pinf_count <= 1) {
02914             const N& approx_i = dbm_0[i];
02915             if (!is_plus_infinity(approx_i))
02916               add_mul_assign_r(neg_sum, coeff_i, approx_i, ROUND_UP);
02917             else {
02918               ++neg_pinf_count;
02919               neg_pinf_index = i;
02920             }
02921           }
02922         }
02923       }
02924       // Return immediately if no approximation could be computed.
02925       if (pinf_count > 1 && neg_pinf_count > 1) {
02926         assert(OK());
02927         return;
02928       }
02929 
02930       // In the following, shortest-path closure will be definitely lost.
02931       reset_shortest_path_closed();
02932 
02933       // Before computing quotients, the denominator should be approximated
02934       // towards zero. Since `sc_den' is known to be positive, this amounts to
02935       // rounding downwards, which is achieved as usual by rounding upwards
02936       // `minus_sc_den' and negating again the result.
02937       DIRTY_TEMP(N, down_sc_den);
02938       assign_r(down_sc_den, minus_sc_den, ROUND_UP);
02939       neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
02940 
02941       // Exploit the upper approximation, if possible.
02942       if (pinf_count <= 1) {
02943         // Compute quotient (if needed).
02944         if (down_sc_den != 1)
02945           div_assign_r(sum, sum, down_sc_den, ROUND_UP);
02946         // Add the upper bound constraint, if meaningful.
02947         if (pinf_count == 0) {
02948           // Add the constraint `v <= sum'.
02949           dbm[0][v] = sum;
02950           // Deduce constraints of the form `v - u', where `u != v'.
02951           deduce_v_minus_u_bounds(v, w, sc_expr, sc_den, sum);
02952         }
02953         else
02954           // Here `pinf_count == 1'.
02955           if (pinf_index != v
02956               && sc_expr.coefficient(Variable(pinf_index-1)) == sc_den)
02957             // Add the constraint `v - pinf_index <= sum'.
02958             dbm[pinf_index][v] = sum;
02959       }
02960 
02961       // Exploit the lower approximation, if possible.
02962       if (neg_pinf_count <= 1) {
02963         // Compute quotient (if needed).
02964         if (down_sc_den != 1)
02965           div_assign_r(neg_sum, neg_sum, down_sc_den, ROUND_UP);
02966         // Add the lower bound constraint, if meaningful.
02967         if (neg_pinf_count == 0) {
02968           // Add the constraint `v >= -neg_sum', i.e., `-v <= neg_sum'.
02969           DB_Row<N>& dbm_v = dbm[v];
02970           dbm_v[0] = neg_sum;
02971           // Deduce constraints of the form `u - v', where `u != v'.
02972           deduce_u_minus_v_bounds(v, w, sc_expr, sc_den, neg_sum);
02973         }
02974         else
02975           // Here `neg_pinf_count == 1'.
02976           if (neg_pinf_index != v
02977               && sc_expr.coefficient(Variable(neg_pinf_index-1)) == sc_den)
02978             // Add the constraint `v - neg_pinf_index >= -neg_sum',
02979             // i.e., `neg_pinf_index - v <= neg_sum'.
02980             dbm[v][neg_pinf_index] = neg_sum;
02981       }
02982     }
02983     break;
02984 
02985   case LESS_OR_EQUAL:
02986     // Compute an upper approximation for `expr' into `sum',
02987     // taking into account the sign of `denominator'.
02988 
02989     // Approximate the inhomogeneous term.
02990     assign_r(sum, sc_b, ROUND_UP);
02991 
02992     // Approximate the homogeneous part of `sc_expr'.
02993     // Note: indices above `w' can be disregarded, as they all have
02994     // a zero coefficient in `expr'.
02995     for (dimension_type i = w; i > 0; --i) {
02996       const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1));
02997       const int sign_i = sgn(sc_i);
02998       if (sign_i == 0)
02999         continue;
03000       // Choose carefully: we are approximating `sc_expr'.
03001       const N& approx_i = (sign_i > 0) ? dbm_0[i] : dbm[i][0];
03002       if (is_plus_infinity(approx_i)) {
03003         if (++pinf_count > 1)
03004           break;
03005         pinf_index = i;
03006         continue;
03007       }
03008       if (sign_i > 0)
03009         assign_r(coeff_i, sc_i, ROUND_UP);
03010       else {
03011         neg_assign(minus_sc_i, sc_i);
03012         assign_r(coeff_i, minus_sc_i, ROUND_UP);
03013       }
03014       add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
03015     }
03016 
03017     // Divide by the (sign corrected) denominator (if needed).
03018     if (sc_den != 1) {
03019       // Before computing the quotient, the denominator should be
03020       // approximated towards zero. Since `sc_den' is known to be
03021       // positive, this amounts to rounding downwards, which is achieved
03022       // by rounding upwards `minus_sc-den' and negating again the result.
03023       DIRTY_TEMP(N, down_sc_den);
03024       assign_r(down_sc_den, minus_sc_den, ROUND_UP);
03025       neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
03026       div_assign_r(sum, sum, down_sc_den, ROUND_UP);
03027     }
03028 
03029     if (pinf_count == 0) {
03030       // Add the constraint `v <= sum'.
03031       add_dbm_constraint(0, v, sum);
03032       // Deduce constraints of the form `v - u', where `u != v'.
03033       deduce_v_minus_u_bounds(v, w, sc_expr, sc_den, sum);
03034     }
03035     else if (pinf_count == 1)
03036       if (expr.coefficient(Variable(pinf_index-1)) == denominator)
03037         // Add the constraint `v - pinf_index <= sum'.
03038         add_dbm_constraint(pinf_index, v, sum);
03039       break;
03040 
03041   case GREATER_OR_EQUAL:
03042     // Compute an upper approximation for `-sc_expr' into `sum'.
03043     // Note: approximating `-sc_expr' from above and then negating the
03044     // result is the same as approximating `sc_expr' from below.
03045 
03046     // Approximate the inhomogeneous term.
03047     assign_r(sum, minus_sc_b, ROUND_UP);
03048 
03049     // Approximate the homogeneous part of `-sc_expr'.
03050     for (dimension_type i = w; i > 0; --i) {
03051       const Coefficient& sc_i = sc_expr.coefficient(Variable(i-1));
03052       const int sign_i = sgn(sc_i);
03053       if (sign_i == 0)
03054         continue;
03055       // Choose carefully: we are approximating `-sc_expr'.
03056       const N& approx_i = (sign_i > 0) ? dbm[i][0] : dbm_0[i];
03057       if (is_plus_infinity(approx_i)) {
03058         if (++pinf_count > 1)
03059           break;
03060         pinf_index = i;
03061         continue;
03062       }
03063       if (sign_i > 0)
03064         assign_r(coeff_i, sc_i, ROUND_UP);
03065       else {
03066         neg_assign(minus_sc_i, sc_i);
03067         assign_r(coeff_i, minus_sc_i, ROUND_UP);
03068       }
03069       add_mul_assign_r(sum, coeff_i, approx_i, ROUND_UP);
03070     }
03071 
03072     // Divide by the (sign corrected) denominator (if needed).
03073     if (sc_den != 1) {
03074       // Before computing the quotient, the denominator should be
03075       // approximated towards zero. Since `sc_den' is known to be positive,
03076       // this amounts to rounding downwards, which is achieved by rounding
03077       // upwards `minus_sc_den' and negating again the result.
03078       DIRTY_TEMP(N, down_sc_den);
03079       assign_r(down_sc_den, minus_sc_den, ROUND_UP);
03080       neg_assign_r(down_sc_den, down_sc_den, ROUND_UP);
03081       div_assign_r(sum, sum, down_sc_den, ROUND_UP);
03082     }
03083 
03084     if (pinf_count == 0) {
03085       // Add the constraint `v >= -sum', i.e., `-v <= sum'.
03086       add_dbm_constraint(v, 0, sum);
03087       // Deduce constraints of the form `u - v', where `u != v'.
03088       deduce_u_minus_v_bounds(v, w, sc_expr, sc_den, sum);
03089     }
03090     else if (pinf_count == 1)
03091       if (pinf_index != v
03092           && expr.coefficient(Variable(pinf_index-1)) == denominator)
03093         // Add the constraint `v - pinf_index >= -sum',
03094         // i.e., `pinf_index - v <= sum'.
03095         add_dbm_constraint(v, pinf_index, sum);
03096     break;
03097 
03098   default:
03099     // We already dealt with the other cases.
03100     throw std::runtime_error("PPL internal error");
03101   }
03102 
03103   assert(OK());
03104 }

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

Removes all the constraints on row/column v.

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

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

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

02650                                                               {
02651   assert(0 < v && v <= dbm.num_rows());
02652   DB_Row<N>& dbm_v = dbm[v];
02653   for (dimension_type i = dbm.num_rows(); i-- > 0; ) {
02654     assign_r(dbm_v[i], PLUS_INFINITY, ROUND_NOT_NEEDED);
02655     assign_r(dbm[i][v], PLUS_INFINITY, ROUND_NOT_NEEDED);
02656   }
02657 }

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

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

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

02661                                                                  {
02662   assert(0 < v && v <= dbm.num_rows());
02663   DB_Row<N>& dbm_v = dbm[v];
02664   for (dimension_type i = dbm.num_rows()-1; i > 0; --i) {
02665     assign_r(dbm_v[i], PLUS_INFINITY, ROUND_NOT_NEEDED);
02666     assign_r(dbm[i][v], PLUS_INFINITY, ROUND_NOT_NEEDED);
02667   }
02668 }

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 2528 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, and Parma_Polyhedra_Library::is_plus_infinity().

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

02532                                          {
02533   assert(sc_den > 0);
02534   assert(!is_plus_infinity(ub_v));
02535   // Deduce constraints of the form `v - u', where `u != v'.
02536   // Note: the shortest-path closure is able to deduce the constraint
02537   // `v - u <= ub_v - lb_u'. We can be more precise if variable `u'
02538   // played an active role in the computation of the upper bound for `v',
02539   // i.e., if the corresponding coefficient `q == expr_u/den' is
02540   // greater than zero. In particular:
02541   // if `q >= 1',    then `v - u <= ub_v - ub_u';
02542   // if `0 < q < 1', then `v - u <= ub_v - (q*ub_u + (1-q)*lb_u)'.
02543   DIRTY_TEMP0(mpq_class, mpq_sc_den);
02544   assign_r(mpq_sc_den, sc_den, ROUND_NOT_NEEDED);
02545   const DB_Row<N>& dbm_0 = dbm[0];
02546   // Speculative allocation of temporaries to be used in the following loop.
02547   DIRTY_TEMP0(mpq_class, minus_lb_u);
02548   DIRTY_TEMP0(mpq_class, q);
02549   DIRTY_TEMP0(mpq_class, ub_u);
02550   DIRTY_TEMP(N, up_approx);
02551   // No need to consider indices greater than `last_v'.
02552   for (dimension_type u = last_v; u > 0; --u)
02553     if (u != v) {
02554       const Coefficient& expr_u = sc_expr.coefficient(Variable(u-1));
02555       if (expr_u > 0) {
02556         if (expr_u >= sc_den)
02557           // Deducing `v - u <= ub_v - ub_u'.
02558           sub_assign_r(dbm[u][v], ub_v, dbm_0[u], ROUND_UP);
02559         else {
02560           DB_Row<N>& dbm_u = dbm[u];
02561           const N& dbm_u0 = dbm_u[0];
02562           if (!is_plus_infinity(dbm_u0)) {
02563             // Let `ub_u' and `lb_u' be the known upper and lower bound
02564             // for `u', respectively. Letting `q = expr_u/sc_den' be the
02565             // rational coefficient of `u' in `sc_expr/sc_den',
02566             // the upper bound for `v - u' is computed as
02567             // `ub_v - (q * ub_u + (1-q) * lb_u)', i.e.,
02568             // `ub_v + (-lb_u) - q * (ub_u + (-lb_u))'.
02569             assign_r(minus_lb_u, dbm_u0, ROUND_NOT_NEEDED);
02570             assign_r(q, expr_u, ROUND_NOT_NEEDED);
02571             div_assign_r(q, q, mpq_sc_den, ROUND_NOT_NEEDED);
02572             assign_r(ub_u, dbm_0[u], ROUND_NOT_NEEDED);
02573             // Compute `ub_u - lb_u'.
02574             add_assign_r(ub_u, ub_u, minus_lb_u, ROUND_NOT_NEEDED);
02575             // Compute `(-lb_u) - q * (ub_u - lb_u)'.
02576             sub_mul_assign_r(minus_lb_u, q, ub_u, ROUND_NOT_NEEDED);
02577             assign_r(up_approx, minus_lb_u, ROUND_UP);
02578             // Deducing `v - u <= ub_v - (q * ub_u + (1-q) * lb_u)'.
02579             add_assign_r(dbm_u[v], ub_v, up_approx, ROUND_UP);
02580           }
02581         }
02582       }
02583     }
02584 }

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 2589 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, 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().

02593                                                {
02594   assert(sc_den > 0);
02595   assert(!is_plus_infinity(minus_lb_v));
02596   // Deduce constraints of the form `u - v', where `u != v'.
02597   // Note: the shortest-path closure is able to deduce the constraint
02598   // `u - v <= ub_u - lb_v'. We can be more precise if variable `u'
02599   // played an active role in the computation of the lower bound for `v',
02600   // i.e., if the corresponding coefficient `q == expr_u/den' is
02601   // greater than zero. In particular:
02602   // if `q >= 1',    then `u - v <= lb_u - lb_v';
02603   // if `0 < q < 1', then `u - v <= (q*lb_u + (1-q)*ub_u) - lb_v'.
02604   DIRTY_TEMP0(mpq_class, mpq_sc_den);
02605   assign_r(mpq_sc_den, sc_den, ROUND_NOT_NEEDED);
02606   DB_Row<N>& dbm_0 = dbm[0];
02607   DB_Row<N>& dbm_v = dbm[v];
02608   // Speculative allocation of temporaries to be used in the following loop.
02609   DIRTY_TEMP0(mpq_class, ub_u);
02610   DIRTY_TEMP0(mpq_class, q);
02611   DIRTY_TEMP0(mpq_class, minus_lb_u);
02612   DIRTY_TEMP(N, up_approx);
02613   // No need to consider indices greater than `last_v'.
02614   for (dimension_type u = last_v; u > 0; --u)
02615     if (u != v) {
02616       const Coefficient& expr_u = sc_expr.coefficient(Variable(u-1));
02617       if (expr_u > 0) {
02618         if (expr_u >= sc_den)
02619           // Deducing `u - v <= lb_u - lb_v',
02620           // i.e., `u - v <= (-lb_v) - (-lb_u)'.
02621           sub_assign_r(dbm_v[u], minus_lb_v, dbm[u][0], ROUND_UP);
02622         else {
02623           const N& dbm_0u = dbm_0[u];
02624           if (!is_plus_infinity(dbm_0u)) {
02625             // Let `ub_u' and `lb_u' be the known upper and lower bound
02626             // for `u', respectively. Letting `q = expr_u/sc_den' be the
02627             // rational coefficient of `u' in `sc_expr/sc_den',
02628             // the upper bound for `u - v' is computed as
02629             // `(q * lb_u + (1-q) * ub_u) - lb_v', i.e.,
02630             // `ub_u - q * (ub_u + (-lb_u)) + minus_lb_v'.
02631             assign_r(ub_u, dbm_0u, ROUND_NOT_NEEDED);
02632             assign_r(q, expr_u, ROUND_NOT_NEEDED);
02633             div_assign_r(q, q, mpq_sc_den, ROUND_NOT_NEEDED);
02634             assign_r(minus_lb_u, dbm[u][0], ROUND_NOT_NEEDED);
02635             // Compute `ub_u - lb_u'.
02636             add_assign_r(minus_lb_u, minus_lb_u, ub_u, ROUND_NOT_NEEDED);
02637             // Compute `ub_u - q * (ub_u - lb_u)'.
02638             sub_mul_assign_r(ub_u, q, minus_lb_u, ROUND_NOT_NEEDED);
02639             assign_r(up_approx, ub_u, ROUND_UP);
02640             // Deducing `u - v <= (q*lb_u + (1-q)*ub_u) - lb_v'.
02641             add_assign_r(dbm_v[u], up_approx, minus_lb_v, ROUND_UP);
02642           }
02643         }
02644       }
02645     }
02646 }

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 2240 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(), 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(), Parma_Polyhedra_Library::Constraint_System::space_dimension(), and TEMP_INTEGER.

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

02241                                                                 {
02242   const dimension_type cs_space_dim = cs.space_dimension();
02243   // Private method: the caller has to ensure the following.
02244   assert(cs_space_dim <= space_dimension());
02245 
02246   shortest_path_closure_assign();
02247   bool changed = false;
02248   TEMP_INTEGER(coeff);
02249   TEMP_INTEGER(minus_c_term);
02250   DIRTY_TEMP(N, d);
02251   DIRTY_TEMP(N, d1);
02252   for (Constraint_System::const_iterator cs_i = cs.begin(),
02253          cs_end = cs.end(); cs_i != cs_end; ++cs_i) {
02254     const Constraint& c = *cs_i;
02255     dimension_type num_vars = 0;
02256     dimension_type i = 0;
02257     dimension_type j = 0;
02258     // Constraints that are not bounded differences are ignored.
02259     if (extract_bounded_difference(c, cs_space_dim, num_vars, i, j, coeff)) {
02260       // Select the cell to be modified for the "<=" part of the constraint,
02261       // and set `coeff' to the absolute value of itself.
02262       const bool negative = (coeff < 0);
02263       const N& x = negative ? dbm[i][j] : dbm[j][i];
02264       const N& y = negative ? dbm[j][i] : dbm[i][j];
02265       DB_Matrix<N>& ls_dbm = limiting_shape.dbm;
02266       N& ls_x = negative ? ls_dbm[i][j] : ls_dbm[j][i];
02267       N& ls_y = negative ? ls_dbm[j][i] : ls_dbm[i][j];
02268       if (negative)
02269         neg_assign(coeff);
02270       // Compute the bound for `x', rounding towards plus infinity.
02271       div_round_up(d, c.inhomogeneous_term(), coeff);
02272       if (x <= d) {
02273         if (c.is_inequality()) {
02274           if (ls_x > d) {
02275             ls_x = d;
02276             changed = true;
02277           }
02278         }
02279         else {
02280           // Compute the bound for `y', rounding towards plus infinity.
02281           neg_assign(minus_c_term, c.inhomogeneous_term());
02282           div_round_up(d1, minus_c_term, coeff);
02283           if (y <= d1)
02284             if((ls_x >= d && ls_y > d1) || (ls_x > d && ls_y >= d1)) {
02285               ls_x = d;
02286               ls_y = d1;
02287               changed = true;
02288           }
02289         }
02290       }
02291     }
02292   }
02293 
02294   // In general, adding a constraint does not preserve the shortest-path
02295   // closure of the bounded difference shape.
02296   if (changed && limiting_shape.marked_shortest_path_closed())
02297     limiting_shape.reset_shortest_path_closed();
02298 }

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

References Parma_Polyhedra_Library::BD_Shape< T >::dbm, Parma_Polyhedra_Library::is_additive_inverse(), 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 >::affine_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::compute_leaders(), and Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_reduction_assign().

00795                                                                    {
00796   assert(!marked_empty() && marked_shortest_path_closed());
00797   assert(predecessor.size() == 0);
00798   // Variables are ordered according to their index.
00799   // The vector `predecessor' is used to indicate which variable
00800   // immediately precedes a given one in the corresponding equivalence class.
00801   // The `leader' of an equivalence class is the element having minimum
00802   // index: leaders are their own predecessors.
00803   const dimension_type pred_size = dbm.num_rows();
00804   // Initially, each variable is leader of its own zero-equivalence class.
00805   predecessor.reserve(pred_size);
00806   for (dimension_type i = 0; i < pred_size; ++i)
00807     predecessor.push_back(i);
00808   // Now compute actual predecessors.
00809   for (dimension_type i = pred_size; i-- > 1; )
00810     if (i == predecessor[i]) {
00811       const DB_Row<N>& dbm_i = dbm[i];
00812       for (dimension_type j = i; j-- > 0; )
00813         if (j == predecessor[j]
00814             && is_additive_inverse(dbm[j][i], dbm_i[j])) {
00815           // Choose as predecessor the variable having the smaller index.
00816           predecessor[i] = j;
00817           break;
00818         }
00819     }
00820 }

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 824 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(), and Parma_Polyhedra_Library::BD_Shape< T >::minimized_constraints().

00824                                                                      {
00825   assert(!marked_empty() && marked_shortest_path_closed());
00826   assert(leaders.size() == 0);
00827   // Compute predecessor information.
00828   compute_predecessors(leaders);
00829   // Flatten the predecessor chains so as to obtain leaders.
00830   assert(leaders[0] == 0);
00831   for (dimension_type i = 1, l_size = leaders.size(); i != l_size; ++i) {
00832     const dimension_type l_i = leaders[i];
00833     assert(l_i <= i);
00834     if (l_i != i) {
00835       const dimension_type ll_i = leaders[l_i];
00836       assert(ll_i == leaders[ll_i]);
00837       leaders[i] = ll_i;
00838     }
00839   }
00840 }

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 5153 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 >::bounded_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::bounded_affine_preimage(), 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 >::expand_space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::fold_space_dimensions(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_image(), Parma_Polyhedra_Library::BD_Shape< T >::generalized_affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::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 >::time_elapse_assign(), Parma_Polyhedra_Library::BD_Shape< T >::unconstrain(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign().

05154                                                                    {
05155   std::ostringstream s;
05156   s << "PPL::BD_Shape::" << method << ":" << std::endl
05157     << "this->space_dimension() == " << space_dimension()
05158     << ", y->space_dimension() == " << y.space_dimension() << ".";
05159   throw std::invalid_argument(s.str());
05160 }

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

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

05165                                                                              {
05166   std::ostringstream s;
05167   s << "PPL::BD_Shape::" << method << ":" << std::endl
05168     << "this->space_dimension() == " << space_dimension()
05169     << ", required dimension == " << required_dim << ".";
05170   throw std::invalid_argument(s.str());
05171 }

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

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

05176                                                                      {
05177   std::ostringstream s;
05178   s << "PPL::BD_Shape::" << method << ":" << std::endl
05179     << "this->space_dimension() == " << space_dimension()
05180     << ", c->space_dimension == " << c.space_dimension() << ".";
05181   throw std::invalid_argument(s.str());
05182 }

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

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

05187                                                                       {
05188   std::ostringstream s;
05189   s << "PPL::BD_Shape::" << method << ":" << std::endl
05190     << "this->space_dimension() == " << space_dimension()
05191     << ", cg->space_dimension == " << cg.space_dimension() << ".";
05192   throw std::invalid_argument(s.str());
05193 }

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

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

05198                                                                     {
05199   std::ostringstream s;
05200   s << "PPL::BD_Shape::" << method << ":" << std::endl
05201     << "this->space_dimension() == " << space_dimension()
05202     << ", g->space_dimension == " << g.space_dimension() << ".";
05203   throw std::invalid_argument(s.str());
05204 }

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

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

05222                                                                             {
05223   std::ostringstream s;
05224   s << "PPL::BD_Shape::" << method << ":" << std::endl
05225     << "this->space_dimension() == " << space_dimension()
05226     << ", " << name_row << "->space_dimension() == "
05227     << y.space_dimension() << ".";
05228   throw std::invalid_argument(s.str());
05229 }

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

05209                                                                       {
05210   using namespace IO_Operators;
05211   std::ostringstream s;
05212   s << "PPL::BD_Shape::" << method << ":" << std::endl
05213     << e << " is too complex.";
05214   throw std::invalid_argument(s.str());
05215 }

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


Friends And Related Function Documentation

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

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

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

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

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

00466                                                        {
00467   const dimension_type x_space_dim = x.space_dimension();
00468   // Dimension-compatibility check.
00469   if (x_space_dim != y.space_dimension())
00470     return false;
00471 
00472   // Zero-dim BDSs are equal if and only if they are both empty or universe.
00473   if (x_space_dim == 0) {
00474     if (x.marked_empty())
00475       return y.marked_empty();
00476     else
00477       return !y.marked_empty();
00478   }
00479 
00480   // The exact equivalence test requires shortest-path closure.
00481   x.shortest_path_closure_assign();
00482   y.shortest_path_closure_assign();
00483 
00484   // If one of two BDSs is empty, then they are equal
00485   // if and only if the other BDS is empty too.
00486   if (x.marked_empty())
00487     return y.marked_empty();
00488   if (y.marked_empty())
00489     return false;
00490   // Check for syntactic equivalence of the two (shortest-path closed)
00491   // systems of bounded differences.
00492   return x.dbm == y.dbm;
00493 }

template<typename T>
template<typename Temp, typename To, typename U>
bool 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 T>
template<typename Temp, typename To, typename U>
bool 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>
template<typename Temp, typename To, typename U>
bool 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>
std::ostream & operator<< ( std::ostream &  s,
const BD_Shape< T > &  c 
) [friend]

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

04922                                                             {
04923   typedef typename BD_Shape<T>::coefficient_type N;
04924   if (c.is_universe())
04925     s << "true";
04926   else {
04927     // We control empty bounded difference shape.
04928     dimension_type n = c.space_dimension();
04929     if (c.marked_empty())
04930       s << "false";
04931     else {
04932       DIRTY_TEMP(N, v);
04933       bool first = true;
04934       for (dimension_type i = 0; i <= n; ++i)
04935         for (dimension_type j = i + 1; j <= n; ++j) {
04936           const N& c_i_j = c.dbm[i][j];
04937           const N& c_j_i = c.dbm[j][i];
04938           if (is_additive_inverse(c_j_i, c_i_j)) {
04939             // We will print an equality.
04940             if (first)
04941               first = false;
04942             else
04943               s << ", ";
04944             if (i == 0) {
04945               // We have got a equality constraint with one Variable.
04946               s << Variable(j - 1);
04947               s << " == " << c_i_j;
04948             }
04949             else {
04950               // We have got a equality constraint with two Variables.
04951               if (sgn(c_i_j) >= 0) {
04952                 s << Variable(j - 1);
04953                 s << " - ";
04954                 s << Variable(i - 1);
04955                 s << " == " << c_i_j;
04956               }
04957               else {
04958                 s << Variable(i - 1);
04959                 s << " - ";
04960                 s << Variable(j - 1);
04961                 s << " == " << c_j_i;
04962               }
04963             }
04964           }
04965           else {
04966             // We will print a non-strict inequality.
04967             if (!is_plus_infinity(c_j_i)) {
04968               if (first)
04969                 first = false;
04970               else
04971                 s << ", ";
04972               if (i == 0) {
04973                 // We have got a constraint with an only Variable.
04974                 s << Variable(j - 1);
04975                 neg_assign_r(v, c_j_i, ROUND_DOWN);
04976                 s << " >= " << v;
04977               }
04978               else {
04979                 // We have got a constraint with two Variables.
04980                 if (sgn(c_j_i) >= 0) {
04981                   s << Variable(i - 1);
04982                   s << " - ";
04983                   s << Variable(j - 1);
04984                   s << " <= " << c_j_i;
04985                 }
04986                 else {
04987                   s << Variable(j - 1);
04988                   s << " - ";
04989                   s << Variable(i - 1);
04990                   neg_assign_r(v, c_j_i, ROUND_DOWN);
04991                   s << " >= " << v;
04992                 }
04993               }
04994             }
04995             if (!is_plus_infinity(c_i_j)) {
04996               if (first)
04997                 first = false;
04998               else
04999                 s << ", ";
05000               if (i == 0) {
05001                 // We have got a constraint with an only Variable.
05002                 s << Variable(j - 1);
05003                 s << " <= " << c_i_j;
05004               }
05005               else {
05006                 // We have got a constraint with two Variables.
05007                 if (sgn(c_i_j) >= 0) {
05008                   s << Variable(j - 1);
05009                   s << " - ";
05010                   s << Variable(i - 1);
05011                   s << " <= " << c_i_j;
05012                 }
05013                 else {
05014                   s << Variable(i - 1);
05015                   s << " - ";
05016                   s << Variable(j - 1);
05017                   neg_assign_r(v, c_i_j, ROUND_DOWN);
05018                   s << " >= " << v;
05019                 }
05020               }
05021             }
05022           }
05023         }
05024     }
05025   }
05026   return s;
05027 }

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

00498                                                        {
00499   return !(x == y);
00500 }

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

References Parma_Polyhedra_Library::BD_Shape< T >::rectilinear_distance_assign.

00549                                                     {
00550   typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
00551   DIRTY_TEMP(Checked_Temp, tmp0);
00552   DIRTY_TEMP(Checked_Temp, tmp1);
00553   DIRTY_TEMP(Checked_Temp, tmp2);
00554   return rectilinear_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
00555 }

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 505 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(), PLUS_INFINITY, Parma_Polyhedra_Library::BD_Shape< T >::rectilinear_distance_assign, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

00511                                         {
00512   const dimension_type x_space_dim = x.space_dimension();
00513   // Dimension-compatibility check.
00514   if (x_space_dim != y.space_dimension())
00515     return false;
00516 
00517   // Zero-dim BDSs are equal if and only if they are both empty or universe.
00518   if (x_space_dim == 0) {
00519     if (x.marked_empty() == y.marked_empty())
00520       assign_r(r, 0, ROUND_NOT_NEEDED);
00521     else
00522       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
00523     return true;
00524   }
00525 
00526   // The distance computation requires shortest-path closure.
00527   x.shortest_path_closure_assign();
00528   y.shortest_path_closure_assign();
00529 
00530   // If one of two BDSs is empty, then they are equal if and only if
00531   // the other BDS is empty too.
00532   if (x.marked_empty() ||  y.marked_empty()) {
00533    if (x.marked_empty() == y.marked_empty())
00534       assign_r(r, 0, ROUND_NOT_NEEDED);
00535     else
00536       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
00537    return true;
00538   }
00539 
00540   return rectilinear_distance_assign(r, x.dbm, y.dbm, dir, tmp0, tmp1, tmp2);
00541 }

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

References Parma_Polyhedra_Library::BD_Shape< T >::euclidean_distance_assign.

00614                                                   {
00615   typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
00616   DIRTY_TEMP(Checked_Temp, tmp0);
00617   DIRTY_TEMP(Checked_Temp, tmp1);
00618   DIRTY_TEMP(Checked_Temp, tmp2);
00619   return euclidean_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
00620 }

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 570 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 >::euclidean_distance_assign, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), PLUS_INFINITY, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

00576                                       {
00577   const dimension_type x_space_dim = x.space_dimension();
00578   // Dimension-compatibility check.
00579   if (x_space_dim != y.space_dimension())
00580     return false;
00581 
00582   // Zero-dim BDSs are equal if and only if they are both empty or universe.
00583   if (x_space_dim == 0) {
00584     if (x.marked_empty() == y.marked_empty())
00585       assign_r(r, 0, ROUND_NOT_NEEDED);
00586     else
00587       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
00588     return true;
00589   }
00590 
00591   // The distance computation requires shortest-path closure.
00592   x.shortest_path_closure_assign();
00593   y.shortest_path_closure_assign();
00594 
00595   // If one of two BDSs is empty, then they are equal if and only if
00596   // the other BDS is empty too.
00597   if (x.marked_empty() ||  y.marked_empty()) {
00598    if (x.marked_empty() == y.marked_empty())
00599       assign_r(r, 0, ROUND_NOT_NEEDED);
00600     else
00601       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
00602    return true;
00603   }
00604 
00605   return euclidean_distance_assign(r, x.dbm, y.dbm, dir, tmp0, tmp1, tmp2);
00606 }

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

References Parma_Polyhedra_Library::BD_Shape< T >::l_infinity_distance_assign.

00679                                                    {
00680   typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
00681   DIRTY_TEMP(Checked_Temp, tmp0);
00682   DIRTY_TEMP(Checked_Temp, tmp1);
00683   DIRTY_TEMP(Checked_Temp, tmp2);
00684   return l_infinity_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
00685 }

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 635 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 >::l_infinity_distance_assign, Parma_Polyhedra_Library::BD_Shape< T >::marked_empty(), PLUS_INFINITY, Parma_Polyhedra_Library::BD_Shape< T >::shortest_path_closure_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::space_dimension().

00641                                        {
00642   const dimension_type x_space_dim = x.space_dimension();
00643   // Dimension-compatibility check.
00644   if (x_space_dim != y.space_dimension())
00645     return false;
00646 
00647   // Zero-dim BDSs are equal if and only if they are both empty or universe.
00648   if (x_space_dim == 0) {
00649     if (x.marked_empty() == y.marked_empty())
00650       assign_r(r, 0, ROUND_NOT_NEEDED);
00651     else
00652       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
00653     return true;
00654   }
00655 
00656   // The distance computation requires shortest-path closure.
00657   x.shortest_path_closure_assign();
00658   y.shortest_path_closure_assign();
00659 
00660   // If one of two BDSs is empty, then they are equal if and only if
00661   // the other BDS is empty too.
00662   if (x.marked_empty() ||  y.marked_empty()) {
00663    if (x.marked_empty() == y.marked_empty())
00664       assign_r(r, 0, ROUND_NOT_NEEDED);
00665     else
00666       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
00667    return true;
00668   }
00669 
00670   return l_infinity_distance_assign(r, x.dbm, y.dbm, dir, tmp0, tmp1, tmp2);
00671 }

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 32 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().

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

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 86 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().

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

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

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

00875                                             {
00876   x.swap(y);
00877 }


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 1810 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 >::ascii_load(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::BD_Shape< T >::BHMZ05_widening_assign(), Parma_Polyhedra_Library::BD_Shape< T >::bounded_affine_image(), 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_predecessors(), 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 >::deduce_u_minus_v_bounds(), Parma_Polyhedra_Library::BD_Shape< T >::deduce_v_minus_u_bounds(), 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 >::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 >::space_dimension(), Parma_Polyhedra_Library::BD_Shape< T >::swap(), and Parma_Polyhedra_Library::BD_Shape< T >::upper_bound_assign().

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

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


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

Generated on Sat Oct 11 10:41:17 2008 for PPL by  doxygen 1.5.6