PPL  1.2
Parma_Polyhedra_Library::Polyhedron Class Reference

The base class for convex polyhedra. More...

#include <Polyhedron_defs.hh>

Inheritance diagram for Parma_Polyhedra_Library::Polyhedron:
Collaboration diagram for Parma_Polyhedra_Library::Polyhedron:

Classes

class  Status
 A conjunctive assertion about a polyhedron. More...
 

Public Types

typedef Coefficient coefficient_type
 The numeric type of coefficients. More...
 

Public Member Functions

template<typename Input >
Input & check_obj_space_dimension_overflow (Input &input, const Topology topol, const char *method, const char *reason)
 
Member Functions that Do Not Modify the Polyhedron
dimension_type space_dimension () const
 Returns the dimension of the vector space enclosing *this. More...
 
dimension_type affine_dimension () const
 Returns $0$, if *this is empty; otherwise, returns the affine dimension of *this. More...
 
const Constraint_Systemconstraints () const
 Returns the system of constraints. More...
 
const Constraint_Systemminimized_constraints () const
 Returns the system of constraints, with no redundant constraint. More...
 
const Generator_Systemgenerators () const
 Returns the system of generators. More...
 
const Generator_Systemminimized_generators () const
 Returns the system of generators, with no redundant generator. More...
 
Congruence_System congruences () const
 Returns a system of (equality) congruences satisfied by *this. More...
 
Congruence_System minimized_congruences () const
 Returns a system of (equality) congruences satisfied by *this, with no redundant congruences and having the same affine dimension as *this. More...
 
Poly_Con_Relation relation_with (const Constraint &c) const
 Returns the relations holding between the polyhedron *this and the constraint c. More...
 
Poly_Gen_Relation relation_with (const Generator &g) const
 Returns the relations holding between the polyhedron *this and the generator g. More...
 
Poly_Con_Relation relation_with (const Congruence &cg) const
 Returns the relations holding between the polyhedron *this and the congruence c. More...
 
bool is_empty () const
 Returns true if and only if *this is an empty polyhedron. More...
 
bool is_universe () const
 Returns true if and only if *this is a universe polyhedron. More...
 
bool is_topologically_closed () const
 Returns true if and only if *this is a topologically closed subset of the vector space. More...
 
bool is_disjoint_from (const Polyhedron &y) const
 Returns true if and only if *this and y are disjoint. More...
 
bool is_discrete () const
 Returns true if and only if *this is discrete. More...
 
bool is_bounded () const
 Returns true if and only if *this is a bounded polyhedron. More...
 
bool contains_integer_point () const
 Returns true if and only if *this contains at least one integer point. More...
 
bool constrains (Variable var) const
 Returns true if and only if var is constrained in *this. More...
 
bool bounds_from_above (const Linear_Expression &expr) const
 Returns true if and only if expr is bounded from above in *this. More...
 
bool bounds_from_below (const Linear_Expression &expr) const
 Returns true if and only if expr is bounded from below in *this. More...
 
bool maximize (const Linear_Expression &expr, Coefficient &sup_n, Coefficient &sup_d, bool &maximum) const
 Returns true if and only if *this is not empty and expr is bounded from above in *this, in which case the supremum value is computed. More...
 
bool maximize (const Linear_Expression &expr, Coefficient &sup_n, Coefficient &sup_d, bool &maximum, Generator &g) const
 Returns true if and only if *this is not empty and expr is bounded from above in *this, in which case the supremum value and a point where expr reaches it are computed. More...
 
bool minimize (const Linear_Expression &expr, Coefficient &inf_n, Coefficient &inf_d, bool &minimum) const
 Returns true if and only if *this is not empty and expr is bounded from below in *this, in which case the infimum value is computed. More...
 
bool minimize (const Linear_Expression &expr, Coefficient &inf_n, Coefficient &inf_d, bool &minimum, Generator &g) const
 Returns true if and only if *this is not empty and expr is bounded from below in *this, in which case the infimum value and a point where expr reaches it are computed. More...
 
bool frequency (const Linear_Expression &expr, Coefficient &freq_n, Coefficient &freq_d, Coefficient &val_n, Coefficient &val_d) const
 Returns true if and only if there exist a unique value val such that *this saturates the equality expr = val. More...
 
bool contains (const Polyhedron &y) const
 Returns true if and only if *this contains y. More...
 
bool strictly_contains (const Polyhedron &y) const
 Returns true if and only if *this strictly contains y. More...
 
bool OK (bool check_not_empty=false) const
 Checks if all the invariants are satisfied. More...
 
Space Dimension Preserving Member Functions that May Modify the Polyhedron
void add_constraint (const Constraint &c)
 Adds a copy of constraint c to the system of constraints of *this (without minimizing the result). More...
 
void add_generator (const Generator &g)
 Adds a copy of generator g to the system of generators of *this (without minimizing the result). More...
 
void add_congruence (const Congruence &cg)
 Adds a copy of congruence cg to *this, if cg can be exactly represented by a polyhedron. More...
 
void add_constraints (const Constraint_System &cs)
 Adds a copy of the constraints in cs to the system of constraints of *this (without minimizing the result). More...
 
void add_recycled_constraints (Constraint_System &cs)
 Adds the constraints in cs to the system of constraints of *this (without minimizing the result). More...
 
void add_generators (const Generator_System &gs)
 Adds a copy of the generators in gs to the system of generators of *this (without minimizing the result). More...
 
void add_recycled_generators (Generator_System &gs)
 Adds the generators in gs to the system of generators of *this (without minimizing the result). More...
 
void add_congruences (const Congruence_System &cgs)
 Adds a copy of the congruences in cgs to *this, if all the congruences can be exactly represented by a polyhedron. More...
 
void add_recycled_congruences (Congruence_System &cgs)
 Adds the congruences in cgs to *this, if all the congruences can be exactly represented by a polyhedron. More...
 
void refine_with_constraint (const Constraint &c)
 Uses a copy of constraint c to refine *this. More...
 
void refine_with_congruence (const Congruence &cg)
 Uses a copy of congruence cg to refine *this. More...
 
void refine_with_constraints (const Constraint_System &cs)
 Uses a copy of the constraints in cs to refine *this. More...
 
void refine_with_congruences (const Congruence_System &cgs)
 Uses a copy of the congruences in cgs to refine *this. More...
 
template<typename FP_Format , typename Interval_Info >
void refine_with_linear_form_inequality (const Linear_Form< Interval< FP_Format, Interval_Info > > &left, const Linear_Form< Interval< FP_Format, Interval_Info > > &right, bool is_strict=false)
 Refines *this with the constraint expressed by left $<$ right if is_strict is set, with the constraint left $\leq$ right otherwise. More...
 
template<typename FP_Format , typename Interval_Info >
void generalized_refine_with_linear_form_inequality (const Linear_Form< Interval< FP_Format, Interval_Info > > &left, const Linear_Form< Interval< FP_Format, Interval_Info > > &right, Relation_Symbol relsym)
 Refines *this with the constraint expressed by left $\relsym$ right, where $\relsym$ is the relation symbol specified by relsym.. More...
 
template<typename FP_Format , typename Interval_Info >
void refine_fp_interval_abstract_store (Box< Interval< FP_Format, Interval_Info > > &store) const
 Refines store with the constraints defining *this. More...
 
void unconstrain (Variable var)
 Computes the cylindrification of *this with respect to space dimension var, assigning the result to *this. More...
 
void unconstrain (const Variables_Set &vars)
 Computes the cylindrification of *this with respect to the set of space dimensions vars, assigning the result to *this. More...
 
void intersection_assign (const Polyhedron &y)
 Assigns to *this the intersection of *this and y. More...
 
void poly_hull_assign (const Polyhedron &y)
 Assigns to *this the poly-hull of *this and y. More...
 
void upper_bound_assign (const Polyhedron &y)
 Same as poly_hull_assign(y). More...
 
void poly_difference_assign (const Polyhedron &y)
 Assigns to *this the poly-difference of *this and y. More...
 
void difference_assign (const Polyhedron &y)
 Same as poly_difference_assign(y). More...
 
bool simplify_using_context_assign (const Polyhedron &y)
 Assigns to *this a meet-preserving simplification of *this with respect to y. If false is returned, then the intersection is empty. More...
 
void affine_image (Variable var, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the affine image of *this under the function mapping variable var to the affine expression specified by expr and denominator. More...
 
template<typename FP_Format , typename Interval_Info >
void affine_form_image (Variable var, const Linear_Form< Interval< FP_Format, Interval_Info > > &lf)
 
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 to the affine expression specified by expr and denominator. More...
 
void generalized_affine_image (Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the image of *this with respect to the generalized affine relation $\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym. More...
 
void generalized_affine_preimage (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 generalized affine relation $\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym. More...
 
void generalized_affine_image (const Linear_Expression &lhs, Relation_Symbol relsym, const Linear_Expression &rhs)
 Assigns to *this the image of *this with respect to the generalized affine relation $\mathrm{lhs}' \relsym \mathrm{rhs}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym. More...
 
void generalized_affine_preimage (const Linear_Expression &lhs, Relation_Symbol relsym, const Linear_Expression &rhs)
 Assigns to *this the preimage of *this with respect to the generalized affine relation $\mathrm{lhs}' \relsym \mathrm{rhs}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym. More...
 
void bounded_affine_image (Variable var, const Linear_Expression &lb_expr, const Linear_Expression &ub_expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the image of *this with respect to the bounded affine relation $\frac{\mathrm{lb\_expr}}{\mathrm{denominator}} \leq \mathrm{var}' \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}$. More...
 
void bounded_affine_preimage (Variable var, const Linear_Expression &lb_expr, const Linear_Expression &ub_expr, Coefficient_traits::const_reference denominator=Coefficient_one())
 Assigns to *this the preimage of *this with respect to the bounded affine relation $\frac{\mathrm{lb\_expr}}{\mathrm{denominator}} \leq \mathrm{var}' \leq \frac{\mathrm{ub\_expr}}{\mathrm{denominator}}$. More...
 
void time_elapse_assign (const Polyhedron &y)
 Assigns to *this the result of computing the time-elapse between *this and y. More...
 
void positive_time_elapse_assign (const Polyhedron &y)
 Assigns to *this (the best approximation of) the result of computing the positive time-elapse between *this and y. More...
 
void wrap_assign (const Variables_Set &vars, Bounded_Integer_Type_Width w, Bounded_Integer_Type_Representation r, Bounded_Integer_Type_Overflow o, const Constraint_System *cs_p=0, unsigned complexity_threshold=16, bool wrap_individually=true)
 Wraps the specified dimensions of the vector space. More...
 
void drop_some_non_integer_points (Complexity_Class complexity=ANY_COMPLEXITY)
 Possibly tightens *this by dropping some points with non-integer coordinates. More...
 
void drop_some_non_integer_points (const Variables_Set &vars, Complexity_Class complexity=ANY_COMPLEXITY)
 Possibly tightens *this by dropping some points with non-integer coordinates for the space dimensions corresponding to vars. More...
 
void topological_closure_assign ()
 Assigns to *this its topological closure. More...
 
void BHRZ03_widening_assign (const Polyhedron &y, unsigned *tp=0)
 Assigns to *this the result of computing the BHRZ03-widening between *this and y. More...
 
void limited_BHRZ03_extrapolation_assign (const Polyhedron &y, const Constraint_System &cs, unsigned *tp=0)
 Assigns to *this the result of computing the limited extrapolation between *this and y using the BHRZ03-widening operator. More...
 
void bounded_BHRZ03_extrapolation_assign (const Polyhedron &y, const Constraint_System &cs, unsigned *tp=0)
 Assigns to *this the result of computing the bounded extrapolation between *this and y using the BHRZ03-widening operator. More...
 
void H79_widening_assign (const Polyhedron &y, unsigned *tp=0)
 Assigns to *this the result of computing the H79_widening between *this and y. More...
 
void widening_assign (const Polyhedron &y, unsigned *tp=0)
 Same as H79_widening_assign(y, tp). More...
 
void limited_H79_extrapolation_assign (const Polyhedron &y, const Constraint_System &cs, unsigned *tp=0)
 Assigns to *this the result of computing the limited extrapolation between *this and y using the H79-widening operator. More...
 
void bounded_H79_extrapolation_assign (const Polyhedron &y, const Constraint_System &cs, unsigned *tp=0)
 Assigns to *this the result of computing the bounded extrapolation between *this and y using the H79-widening operator. More...
 
Member Functions that May Modify the Dimension of the Vector Space
void add_space_dimensions_and_embed (dimension_type m)
 Adds m new space dimensions and embeds the old polyhedron in the new vector space. More...
 
void add_space_dimensions_and_project (dimension_type m)
 Adds m new space dimensions to the polyhedron and does not embed it in the new vector space. More...
 
void concatenate_assign (const Polyhedron &y)
 Assigns to *this the concatenation of *this and y, taken in this order. More...
 
void remove_space_dimensions (const Variables_Set &vars)
 Removes all the specified dimensions from the vector space. More...
 
void remove_higher_space_dimensions (dimension_type new_dimension)
 Removes the higher dimensions of the vector space so that the resulting space will have dimension new_dimension. More...
 
template<typename Partial_Function >
void map_space_dimensions (const Partial_Function &pfunc)
 Remaps the dimensions of the vector space according to a partial function. More...
 
void expand_space_dimension (Variable var, dimension_type m)
 Creates m copies of the space dimension corresponding to var. More...
 
void fold_space_dimensions (const Variables_Set &vars, Variable dest)
 Folds the space dimensions in vars into dest. More...
 
Miscellaneous Member Functions
 ~Polyhedron ()
 Destructor. More...
 
void m_swap (Polyhedron &y)
 Swaps *this with polyhedron y. (*this and y can be dimension-incompatible.) More...
 
void ascii_dump () const
 Writes to std::cerr an ASCII representation of *this. More...
 
void ascii_dump (std::ostream &s) const
 Writes to s an ASCII representation of *this. More...
 
void print () const
 Prints *this to std::cerr using operator<<. More...
 
bool ascii_load (std::istream &s)
 Loads from s an ASCII representation (as produced by ascii_dump(std::ostream&) const) and sets *this accordingly. Returns true if successful, false otherwise. More...
 
memory_size_type total_memory_in_bytes () const
 Returns the total size in bytes of the memory occupied by *this. More...
 
memory_size_type external_memory_in_bytes () const
 Returns the size in bytes of the memory managed by *this. More...
 
int32_t hash_code () const
 Returns a 32-bit hash code for *this. More...
 

Static Public Member Functions

static dimension_type max_space_dimension ()
 Returns the maximum space dimension all kinds of Polyhedron can handle. More...
 
static bool can_recycle_constraint_systems ()
 Returns true indicating that this domain has methods that can recycle constraints. More...
 
static void initialize ()
 Initializes the class. More...
 
static void finalize ()
 Finalizes the class. More...
 
static bool can_recycle_congruence_systems ()
 Returns false indicating that this domain cannot recycle congruences. More...
 

Protected Member Functions

 Polyhedron (Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
 Builds a polyhedron having the specified properties. More...
 
 Polyhedron (const Polyhedron &y, Complexity_Class complexity=ANY_COMPLEXITY)
 Ordinary copy constructor. More...
 
 Polyhedron (Topology topol, const Constraint_System &cs)
 Builds a polyhedron from a system of constraints. More...
 
 Polyhedron (Topology topol, Constraint_System &cs, Recycle_Input dummy)
 Builds a polyhedron recycling a system of constraints. More...
 
 Polyhedron (Topology topol, const Generator_System &gs)
 Builds a polyhedron from a system of generators. More...
 
 Polyhedron (Topology topol, Generator_System &gs, Recycle_Input dummy)
 Builds a polyhedron recycling a system of generators. More...
 
template<typename Interval >
 Polyhedron (Topology topol, const Box< Interval > &box, Complexity_Class complexity=ANY_COMPLEXITY)
 Builds a polyhedron from a box. More...
 
Polyhedronoperator= (const Polyhedron &y)
 The assignment operator. (*this and y can be dimension-incompatible.) More...
 
bool BFT00_poly_hull_assign_if_exact (const Polyhedron &y)
 If the poly-hull of *this and y is exact it is assigned to *this and true is returned, otherwise false is returned. More...
 
bool BHZ09_poly_hull_assign_if_exact (const Polyhedron &y)
 
bool BHZ09_C_poly_hull_assign_if_exact (const Polyhedron &y)
 
bool BHZ09_NNC_poly_hull_assign_if_exact (const Polyhedron &y)
 
void drop_some_non_integer_points (const Variables_Set *vars_p, Complexity_Class complexity)
 Possibly tightens *this by dropping some points with non-integer coordinates for the space dimensions corresponding to *vars_p. More...
 
template<typename FP_Format , typename Interval_Info >
void overapproximate_linear_form (const Linear_Form< Interval< FP_Format, Interval_Info > > &lf, const dimension_type lf_dimension, Linear_Form< Interval< FP_Format, Interval_Info > > &result)
 Helper function that overapproximates an interval linear form. More...
 
void positive_time_elapse_assign_impl (const Polyhedron &y)
 Assuming *this is NNC, assigns to *this the result of the "positive time-elapse" between *this and y. More...
 

Static Protected Member Functions

template<typename FP_Format , typename Interval_Info >
static void convert_to_integer_expression (const Linear_Form< Interval< FP_Format, Interval_Info > > &lf, const dimension_type lf_dimension, Linear_Expression &result)
 Helper function that makes result become a Linear_Expression obtained by normalizing the denominators in lf. More...
 
template<typename FP_Format , typename Interval_Info >
static void convert_to_integer_expressions (const Linear_Form< Interval< FP_Format, Interval_Info > > &lf, const dimension_type lf_dimension, Linear_Expression &res, Coefficient &res_low_coeff, Coefficient &res_hi_coeff, Coefficient &denominator)
 Normalization helper function. More...
 
template<typename Linear_System1 , typename Row2 >
static bool add_to_system_and_check_independence (Linear_System1 &eq_sys, const Row2 &eq)
 

Private Types

enum  Three_Valued_Boolean { TVB_TRUE, TVB_FALSE, TVB_DONT_KNOW }
 

Private Member Functions

Topology topology () const
 Returns the topological kind of the polyhedron. More...
 
bool is_necessarily_closed () const
 Returns true if and only if the polyhedron is necessarily closed. More...
 
void refine_no_check (const Constraint &c)
 Uses a copy of constraint c to refine the system of constraints of *this. More...
 
Three_Valued_Boolean quick_equivalence_test (const Polyhedron &y) const
 Polynomial but incomplete equivalence test between polyhedra. More...
 
bool is_included_in (const Polyhedron &y) const
 Returns true if and only if *this is included in y. More...
 
bool bounds (const Linear_Expression &expr, bool from_above) const
 Checks if and how expr is bounded in *this. More...
 
bool max_min (const Linear_Expression &expr, bool maximize, Coefficient &ext_n, Coefficient &ext_d, bool &included, Generator &g) const
 Maximizes or minimizes expr subject to *this. More...
 
Private Verifiers: Verify if Individual Flags are Set
bool marked_empty () const
 Returns true if the polyhedron is known to be empty. More...
 
bool constraints_are_up_to_date () const
 Returns true if the system of constraints is up-to-date. More...
 
bool generators_are_up_to_date () const
 Returns true if the system of generators is up-to-date. More...
 
bool constraints_are_minimized () const
 Returns true if the system of constraints is minimized. More...
 
bool generators_are_minimized () const
 Returns true if the system of generators is minimized. More...
 
bool has_pending_constraints () const
 Returns true if there are pending constraints. More...
 
bool has_pending_generators () const
 Returns true if there are pending generators. More...
 
bool has_something_pending () const
 Returns true if there are either pending constraints or pending generators. More...
 
bool can_have_something_pending () const
 Returns true if the polyhedron can have something pending. More...
 
bool sat_c_is_up_to_date () const
 Returns true if the saturation matrix sat_c is up-to-date. More...
 
bool sat_g_is_up_to_date () const
 Returns true if the saturation matrix sat_g is up-to-date. More...
 
State Flag Setters: Set Only the Specified Flags
void set_zero_dim_univ ()
 Sets status to express that the polyhedron is the universe 0-dimension vector space, clearing all corresponding matrices. More...
 
void set_empty ()
 Sets status to express that the polyhedron is empty, clearing all corresponding matrices. More...
 
void set_constraints_up_to_date ()
 Sets status to express that constraints are up-to-date. More...
 
void set_generators_up_to_date ()
 Sets status to express that generators are up-to-date. More...
 
void set_constraints_minimized ()
 Sets status to express that constraints are minimized. More...
 
void set_generators_minimized ()
 Sets status to express that generators are minimized. More...
 
void set_constraints_pending ()
 Sets status to express that constraints are pending. More...
 
void set_generators_pending ()
 Sets status to express that generators are pending. More...
 
void set_sat_c_up_to_date ()
 Sets status to express that sat_c is up-to-date. More...
 
void set_sat_g_up_to_date ()
 Sets status to express that sat_g is up-to-date. More...
 
State Flag Cleaners: Clear Only the Specified Flag
void clear_empty ()
 Clears the status flag indicating that the polyhedron is empty. More...
 
void clear_constraints_up_to_date ()
 Sets status to express that constraints are no longer up-to-date. More...
 
void clear_generators_up_to_date ()
 Sets status to express that generators are no longer up-to-date. More...
 
void clear_constraints_minimized ()
 Sets status to express that constraints are no longer minimized. More...
 
void clear_generators_minimized ()
 Sets status to express that generators are no longer minimized. More...
 
void clear_pending_constraints ()
 Sets status to express that there are no longer pending constraints. More...
 
void clear_pending_generators ()
 Sets status to express that there are no longer pending generators. More...
 
void clear_sat_c_up_to_date ()
 Sets status to express that sat_c is no longer up-to-date. More...
 
void clear_sat_g_up_to_date ()
 Sets status to express that sat_g is no longer up-to-date. More...
 
The Handling of Pending Rows
bool process_pending () const
 Processes the pending rows of either description of the polyhedron and obtains a minimized polyhedron. More...
 
bool process_pending_constraints () const
 Processes the pending constraints and obtains a minimized polyhedron. More...
 
void process_pending_generators () const
 Processes the pending generators and obtains a minimized polyhedron. More...
 
void remove_pending_to_obtain_constraints () const
 Lazily integrates the pending descriptions of the polyhedron to obtain a constraint system without pending rows. More...
 
bool remove_pending_to_obtain_generators () const
 Lazily integrates the pending descriptions of the polyhedron to obtain a generator system without pending rows. More...
 
Updating and Sorting Matrices
void update_constraints () const
 Updates constraints starting from generators and minimizes them. More...
 
bool update_generators () const
 Updates generators starting from constraints and minimizes them. More...
 
void update_sat_c () const
 Updates sat_c using the updated constraints and generators. More...
 
void update_sat_g () const
 Updates sat_g using the updated constraints and generators. More...
 
void obtain_sorted_constraints () const
 Sorts the matrix of constraints keeping status consistency. More...
 
void obtain_sorted_generators () const
 Sorts the matrix of generators keeping status consistency. More...
 
void obtain_sorted_constraints_with_sat_c () const
 Sorts the matrix of constraints and updates sat_c. More...
 
void obtain_sorted_generators_with_sat_g () const
 Sorts the matrix of generators and updates sat_g. More...
 
Weak and Strong Minimization of Descriptions
bool minimize () const
 Applies (weak) minimization to both the constraints and generators. More...
 
bool strongly_minimize_constraints () const
 Applies strong minimization to the constraints of an NNC polyhedron. More...
 
bool strongly_minimize_generators () const
 Applies strong minimization to the generators of an NNC polyhedron. More...
 
Constraint_System simplified_constraints () const
 If constraints are up-to-date, obtain a simplified copy of them. More...
 

Static Private Member Functions

template<typename Linear_System1 , typename Linear_System2 >
static void add_space_dimensions (Linear_System1 &sys1, Linear_System2 &sys2, Bit_Matrix &sat1, Bit_Matrix &sat2, dimension_type add_dim)
 Adds new space dimensions to the given linear systems. More...
 
Minimization-Related Static Member Functions
template<typename Source_Linear_System , typename Dest_Linear_System >
static bool minimize (bool con_to_gen, Source_Linear_System &source, Dest_Linear_System &dest, Bit_Matrix &sat)
 Builds and simplifies constraints from generators (or vice versa). More...
 
template<typename Source_Linear_System1 , typename Source_Linear_System2 , typename Dest_Linear_System >
static bool add_and_minimize (bool con_to_gen, Source_Linear_System1 &source1, Dest_Linear_System &dest, Bit_Matrix &sat, const Source_Linear_System2 &source2)
 Adds given constraints and builds minimized corresponding generators or vice versa. More...
 
template<typename Source_Linear_System , typename Dest_Linear_System >
static bool add_and_minimize (bool con_to_gen, Source_Linear_System &source, Dest_Linear_System &dest, Bit_Matrix &sat)
 Adds given constraints and builds minimized corresponding generators or vice versa. The given constraints are in source. More...
 
template<typename Source_Linear_System , typename Dest_Linear_System >
static dimension_type conversion (Source_Linear_System &source, dimension_type start, Dest_Linear_System &dest, Bit_Matrix &sat, dimension_type num_lines_or_equalities)
 Performs the conversion from constraints to generators and vice versa. More...
 
template<typename Linear_System1 >
static dimension_type simplify (Linear_System1 &sys, Bit_Matrix &sat)
 Uses Gauss' elimination method to simplify the result of conversion(). More...
 

Private Attributes

Constraint_System con_sys
 The system of constraints. More...
 
Generator_System gen_sys
 The system of generators. More...
 
Bit_Matrix sat_c
 The saturation matrix having constraints on its columns. More...
 
Bit_Matrix sat_g
 The saturation matrix having generators on its columns. More...
 
Status status
 The status flags to keep track of the polyhedron's internal state. More...
 
dimension_type space_dim
 The number of dimensions of the enclosing vector space. More...
 

Static Private Attributes

static const Representation default_con_sys_repr = DENSE
 
static const Representation default_gen_sys_repr = DENSE
 
static dimension_typesimplify_num_saturators_p = 0
 Pointer to an array used by simplify(). More...
 
static size_t simplify_num_saturators_size = 0
 Dimension of an array used by simplify(). More...
 

Friends

template<typename Interval >
class Parma_Polyhedra_Library::Box
 
template<typename T >
class Parma_Polyhedra_Library::BD_Shape
 
template<typename T >
class Parma_Polyhedra_Library::Octagonal_Shape
 
class Parma_Polyhedra_Library::Grid
 
class Parma_Polyhedra_Library::BHRZ03_Certificate
 
class Parma_Polyhedra_Library::H79_Certificate
 
bool operator== (const Polyhedron &x, const Polyhedron &y)
 
bool Parma_Polyhedra_Library::Interfaces::is_necessarily_closed_for_interfaces (const Polyhedron &)
 

Related Functions

(Note that these are not member functions.)

template<typename PH >
bool poly_hull_assign_if_exact (PH &p, const PH &q)
 If the poly-hull of p and q is exact it is assigned to p and true is returned, otherwise false is returned. More...
 
template<typename PH >
bool poly_hull_assign_if_exact (PH &p, const PH &q)
 
std::ostream & operator<< (std::ostream &s, const Polyhedron &ph)
 Output operator. More...
 
void swap (Polyhedron &x, Polyhedron &y)
 Swaps x with y. More...
 
bool operator== (const Polyhedron &x, const Polyhedron &y)
 Returns true if and only if x and y are the same polyhedron. More...
 
bool operator!= (const Polyhedron &x, const Polyhedron &y)
 Returns true if and only if x and y are different polyhedra. More...
 
void swap (Polyhedron &x, Polyhedron &y)
 
bool operator!= (const Polyhedron &x, const Polyhedron &y)
 
bool operator== (const Polyhedron &x, const Polyhedron &y)
 
std::ostream & operator<< (std::ostream &s, const Polyhedron &ph)
 

Widening- and Extrapolation-Related Functions

void select_CH78_constraints (const Polyhedron &y, Constraint_System &cs_selection) const
 Copies to cs_selection the constraints of y corresponding to the definition of the CH78-widening of *this and y. More...
 
void select_H79_constraints (const Polyhedron &y, Constraint_System &cs_selected, Constraint_System &cs_not_selected) const
 Splits the constraints of `x' into two subsets, depending on whether or not they are selected to compute the H79-widening of *this and y. More...
 
bool BHRZ03_combining_constraints (const Polyhedron &y, const BHRZ03_Certificate &y_cert, const Polyhedron &H79, const Constraint_System &x_minus_H79_cs)
 
bool BHRZ03_evolving_points (const Polyhedron &y, const BHRZ03_Certificate &y_cert, const Polyhedron &H79)
 
bool BHRZ03_evolving_rays (const Polyhedron &y, const BHRZ03_Certificate &y_cert, const Polyhedron &H79)
 
static void modify_according_to_evolution (Linear_Expression &ray, const Linear_Expression &x, const Linear_Expression &y)
 

Exception Throwers

void throw_invalid_argument (const char *method, const char *reason) const
 
void throw_topology_incompatible (const char *method, const char *ph_name, const Polyhedron &ph) const
 
void throw_topology_incompatible (const char *method, const char *c_name, const Constraint &c) const
 
void throw_topology_incompatible (const char *method, const char *g_name, const Generator &g) const
 
void throw_topology_incompatible (const char *method, const char *cs_name, const Constraint_System &cs) const
 
void throw_topology_incompatible (const char *method, const char *gs_name, const Generator_System &gs) const
 
void throw_dimension_incompatible (const char *method, const char *other_name, dimension_type other_dim) const
 
void throw_dimension_incompatible (const char *method, const char *ph_name, const Polyhedron &ph) const
 
void throw_dimension_incompatible (const char *method, const char *le_name, const Linear_Expression &le) const
 
void throw_dimension_incompatible (const char *method, const char *c_name, const Constraint &c) const
 
void throw_dimension_incompatible (const char *method, const char *g_name, const Generator &g) const
 
void throw_dimension_incompatible (const char *method, const char *cg_name, const Congruence &cg) const
 
void throw_dimension_incompatible (const char *method, const char *cs_name, const Constraint_System &cs) const
 
void throw_dimension_incompatible (const char *method, const char *gs_name, const Generator_System &gs) const
 
void throw_dimension_incompatible (const char *method, const char *cgs_name, const Congruence_System &cgs) const
 
template<typename C >
void throw_dimension_incompatible (const char *method, const char *lf_name, const Linear_Form< C > &lf) const
 
void throw_dimension_incompatible (const char *method, const char *var_name, Variable var) const
 
void throw_dimension_incompatible (const char *method, dimension_type required_space_dim) const
 
void throw_invalid_generator (const char *method, const char *g_name) const
 
void throw_invalid_generators (const char *method, const char *gs_name) const
 
static dimension_type check_space_dimension_overflow (dimension_type dim, dimension_type max, const Topology topol, const char *method, const char *reason)
 
static dimension_type check_space_dimension_overflow (dimension_type dim, const Topology topol, const char *method, const char *reason)
 
template<typename Object >
static Object & check_obj_space_dimension_overflow (Object &input, Topology topol, const char *method, const char *reason)
 

Detailed Description

The base class for convex polyhedra.

An object of the class Polyhedron represents a convex polyhedron in the vector space $\Rset^n$.

A polyhedron can be specified as either a finite system of constraints or a finite system of generators (see Section Representations of Convex Polyhedra) and it is always possible to obtain either representation. That is, if we know the system of constraints, we can obtain from this the system of generators that define the same polyhedron and vice versa. These systems can contain redundant members: in this case we say that they are not in the minimal form.

Two key attributes of any polyhedron are its topological kind (recording whether it is a C_Polyhedron or an NNC_Polyhedron object) and its space dimension (the dimension $n \in \Nset$ of the enclosing vector space):

  • all polyhedra, the empty ones included, are endowed with a specific topology and space dimension;
  • most operations working on a polyhedron and another object (i.e., another polyhedron, a constraint or generator, a set of variables, etc.) will throw an exception if the polyhedron and the object are not both topology-compatible and dimension-compatible (see Section Representations of Convex Polyhedra);
  • the topology of a polyhedron cannot be changed; rather, there are constructors for each of the two derived classes that will build a new polyhedron with the topology of that class from another polyhedron from either class and any topology;
  • the only ways in which the space dimension of a polyhedron can be changed are:
    • explicit calls to operators provided for that purpose;
    • standard copy, assignment and swap operators.

Note that four different polyhedra can be defined on the zero-dimension space: the empty polyhedron, either closed or NNC, and the universe polyhedron $R^0$, again either closed or NNC.

In all the examples it is assumed that variables x and y are defined (where they are used) as follows:
Variable x(0);
Variable y(1);
Example 1
The following code builds a polyhedron corresponding to a square in $\Rset^2$, given as a system of constraints:
Constraint_System cs;
cs.insert(x >= 0);
cs.insert(x <= 3);
cs.insert(y >= 0);
cs.insert(y <= 3);
C_Polyhedron ph(cs);
The following code builds the same polyhedron as above, but starting from a system of generators specifying the four vertices of the square:
Generator_System gs;
gs.insert(point(0*x + 0*y));
gs.insert(point(0*x + 3*y));
gs.insert(point(3*x + 0*y));
gs.insert(point(3*x + 3*y));
C_Polyhedron ph(gs);
Example 2
The following code builds an unbounded polyhedron corresponding to a half-strip in $\Rset^2$, given as a system of constraints:
Constraint_System cs;
cs.insert(x >= 0);
cs.insert(x - y <= 0);
cs.insert(x - y + 1 >= 0);
C_Polyhedron ph(cs);
The following code builds the same polyhedron as above, but starting from the system of generators specifying the two vertices of the polyhedron and one ray:
Generator_System gs;
gs.insert(point(0*x + 0*y));
gs.insert(point(0*x + y));
gs.insert(ray(x - y));
C_Polyhedron ph(gs);
Example 3
The following code builds the polyhedron corresponding to a half-plane by adding a single constraint to the universe polyhedron in $\Rset^2$:
C_Polyhedron ph(2);
ph.add_constraint(y >= 0);
The following code builds the same polyhedron as above, but starting from the empty polyhedron in the space $\Rset^2$ and inserting the appropriate generators (a point, a ray and a line).
C_Polyhedron ph(2, EMPTY);
ph.add_generator(point(0*x + 0*y));
ph.add_generator(ray(y));
ph.add_generator(line(x));
Note that, although the above polyhedron has no vertices, we must add one point, because otherwise the result of the Minkowski's sum would be an empty polyhedron. To avoid subtle errors related to the minimization process, it is required that the first generator inserted in an empty polyhedron is a point (otherwise, an exception is thrown).
Example 4
The following code shows the use of the function add_space_dimensions_and_embed:
C_Polyhedron ph(1);
ph.add_constraint(x == 2);
ph.add_space_dimensions_and_embed(1);
We build the universe polyhedron in the 1-dimension space $\Rset$. Then we add a single equality constraint, thus obtaining the polyhedron corresponding to the singleton set $\{ 2 \} \sseq \Rset$. After the last line of code, the resulting polyhedron is

\[ \bigl\{\, (2, y)^\transpose \in \Rset^2 \bigm| y \in \Rset \,\bigr\}. \]

Example 5
The following code shows the use of the function add_space_dimensions_and_project:
C_Polyhedron ph(1);
ph.add_constraint(x == 2);
ph.add_space_dimensions_and_project(1);
The first two lines of code are the same as in Example 4 for add_space_dimensions_and_embed. After the last line of code, the resulting polyhedron is the singleton set $\bigl\{ (2, 0)^\transpose \bigr\} \sseq \Rset^2$.
Example 6
The following code shows the use of the function affine_image:
C_Polyhedron ph(2, EMPTY);
ph.add_generator(point(0*x + 0*y));
ph.add_generator(point(0*x + 3*y));
ph.add_generator(point(3*x + 0*y));
ph.add_generator(point(3*x + 3*y));
Linear_Expression expr = x + 4;
ph.affine_image(x, expr);
In this example the starting polyhedron is a square in $\Rset^2$, the considered variable is $x$ and the affine expression is $x+4$. The resulting polyhedron is the same square translated to the right. Moreover, if the affine transformation for the same variable x is $x+y$:
Linear_Expression expr = x + y;
the resulting polyhedron is a parallelogram with the height equal to the side of the square and the oblique sides parallel to the line $x-y$. Instead, if we do not use an invertible transformation for the same variable; for example, the affine expression $y$:
Linear_Expression expr = y;
the resulting polyhedron is a diagonal of the square.
Example 7
The following code shows the use of the function affine_preimage:
C_Polyhedron ph(2);
ph.add_constraint(x >= 0);
ph.add_constraint(x <= 3);
ph.add_constraint(y >= 0);
ph.add_constraint(y <= 3);
Linear_Expression expr = x + 4;
ph.affine_preimage(x, expr);
In this example the starting polyhedron, var and the affine expression and the denominator are the same as in Example 6, while the resulting polyhedron is again the same square, but translated to the left. Moreover, if the affine transformation for x is $x+y$
Linear_Expression expr = x + y;
the resulting polyhedron is a parallelogram with the height equal to the side of the square and the oblique sides parallel to the line $x+y$. Instead, if we do not use an invertible transformation for the same variable x, for example, the affine expression $y$:
Linear_Expression expr = y;
the resulting polyhedron is a line that corresponds to the $y$ axis.
Example 8
For this example we use also the variables:
Variable z(2);
Variable w(3);
The following code shows the use of the function remove_space_dimensions:
Generator_System gs;
gs.insert(point(3*x + y + 0*z + 2*w));
C_Polyhedron ph(gs);
Variables_Set vars;
vars.insert(y);
vars.insert(z);
ph.remove_space_dimensions(vars);
The starting polyhedron is the singleton set $\bigl\{ (3, 1, 0, 2)^\transpose \bigr\} \sseq \Rset^4$, while the resulting polyhedron is $\bigl\{ (3, 2)^\transpose \bigr\} \sseq \Rset^2$. Be careful when removing space dimensions incrementally: since dimensions are automatically renamed after each application of the remove_space_dimensions operator, unexpected results can be obtained. For instance, by using the following code we would obtain a different result:
set<Variable> vars1;
vars1.insert(y);
ph.remove_space_dimensions(vars1);
set<Variable> vars2;
vars2.insert(z);
ph.remove_space_dimensions(vars2);
In this case, the result is the polyhedron $\bigl\{(3, 0)^\transpose \bigr\} \sseq \Rset^2$: when removing the set of dimensions vars2 we are actually removing variable $w$ of the original polyhedron. For the same reason, the operator remove_space_dimensions is not idempotent: removing twice the same non-empty set of dimensions is never the same as removing them just once.

Definition at line 369 of file Polyhedron_defs.hh.

Member Typedef Documentation

The numeric type of coefficients.

Definition at line 372 of file Polyhedron_defs.hh.

Constructor & Destructor Documentation

Parma_Polyhedra_Library::Polyhedron::Polyhedron ( Topology  topol,
dimension_type  num_dimensions,
Degenerate_Element  kind 
)
protected

Builds a polyhedron having the specified properties.

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

Definition at line 52 of file Polyhedron_nonpublic.cc.

References Parma_Polyhedra_Library::Constraint_System::add_low_level_constraints(), Parma_Polyhedra_Library::Constraint_System::adjust_topology_and_space_dimension(), con_sys, Parma_Polyhedra_Library::EMPTY, max_space_dimension(), OK(), set_constraints_minimized(), Parma_Polyhedra_Library::Polyhedron::Status::set_empty(), space_dim, and status.

Referenced by affine_form_image().

55  : con_sys(topol, default_con_sys_repr),
57  sat_c(),
58  sat_g() {
59  // Protecting against space dimension overflow is up to the caller.
60  PPL_ASSERT(num_dimensions <= max_space_dimension());
61 
62  if (kind == EMPTY) {
63  status.set_empty();
64  }
65  else if (num_dimensions > 0) {
67  con_sys.adjust_topology_and_space_dimension(topol, num_dimensions);
69  }
70  space_dim = num_dimensions;
71  PPL_ASSERT_HEAVY(OK());
72 }
The empty element, i.e., the empty set.
Generator_System gen_sys
The system of generators.
Constraint_System con_sys
The system of constraints.
Bit_Matrix sat_g
The saturation matrix having generators on its columns.
static dimension_type max_space_dimension()
Returns the maximum space dimension all kinds of Polyhedron can handle.
Status status
The status flags to keep track of the polyhedron's internal state.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
static const Representation default_con_sys_repr
void add_low_level_constraints()
Adds low-level constraints to the constraint system.
Bit_Matrix sat_c
The saturation matrix having constraints on its columns.
static const Representation default_gen_sys_repr
void set_constraints_minimized()
Sets status to express that constraints are minimized.
bool adjust_topology_and_space_dimension(Topology new_topology, dimension_type new_space_dim)
Adjusts *this so that it matches new_topology and new_space_dim (adding or removing columns if needed...
Parma_Polyhedra_Library::Polyhedron::Polyhedron ( const Polyhedron y,
Complexity_Class  complexity = ANY_COMPLEXITY 
)
protected

Ordinary copy constructor.

The complexity argument is ignored.

Definition at line 74 of file Polyhedron_nonpublic.cc.

References Parma_Polyhedra_Library::Generator_System::assign_with_pending(), Parma_Polyhedra_Library::Constraint_System::assign_with_pending(), con_sys, constraints_are_up_to_date(), gen_sys, generators_are_up_to_date(), sat_c, sat_c_is_up_to_date(), sat_g, sat_g_is_up_to_date(), and topology().

75  : con_sys(y.topology(), default_con_sys_repr),
76  gen_sys(y.topology(), default_gen_sys_repr),
77  status(y.status),
78  space_dim(y.space_dim) {
79  // Being a protected method, we simply assert that topologies do match.
80  PPL_ASSERT(topology() == y.topology());
81  if (y.constraints_are_up_to_date()) {
82  con_sys.assign_with_pending(y.con_sys);
83  }
84  if (y.generators_are_up_to_date()) {
85  gen_sys.assign_with_pending(y.gen_sys);
86  }
87  if (y.sat_c_is_up_to_date()) {
88  sat_c = y.sat_c;
89  }
90  if (y.sat_g_is_up_to_date()) {
91  sat_g = y.sat_g;
92  }
93 }
Generator_System gen_sys
The system of generators.
void assign_with_pending(const Constraint_System &y)
Full assignment operator: pending rows are copied as pending.
void assign_with_pending(const Generator_System &y)
Full assignment operator: pending rows are copied as pending.
Topology topology() const
Returns the topological kind of the polyhedron.
Constraint_System con_sys
The system of constraints.
Bit_Matrix sat_g
The saturation matrix having generators on its columns.
Status status
The status flags to keep track of the polyhedron's internal state.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
static const Representation default_con_sys_repr
Bit_Matrix sat_c
The saturation matrix having constraints on its columns.
static const Representation default_gen_sys_repr
Parma_Polyhedra_Library::Polyhedron::Polyhedron ( Topology  topol,
const Constraint_System cs 
)
protected

Builds a polyhedron from a system of constraints.

The polyhedron inherits the space dimension of the constraint system.

Parameters
topolThe topology of the polyhedron;
csThe system of constraints defining the polyhedron.
Exceptions
std::invalid_argumentThrown if the topology of cs is incompatible with topol.

Definition at line 95 of file Polyhedron_nonpublic.cc.

References Parma_Polyhedra_Library::Constraint_System::add_low_level_constraints(), con_sys, max_space_dimension(), Parma_Polyhedra_Library::NECESSARILY_CLOSED, Parma_Polyhedra_Library::Constraint_System::num_pending_rows(), OK(), set_constraints_up_to_date(), set_empty(), Parma_Polyhedra_Library::Constraint_System::set_sorted(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), swap(), Parma_Polyhedra_Library::swap(), throw_topology_incompatible(), and Parma_Polyhedra_Library::Constraint_System::unset_pending_rows().

96  : con_sys(topol, default_con_sys_repr),
98  sat_c(),
99  sat_g() {
100  // Protecting against space dimension overflow is up to the caller.
101  PPL_ASSERT(cs.space_dimension() <= max_space_dimension());
102 
103  // TODO: this implementation is just an executable specification.
104  Constraint_System cs_copy = cs;
105 
106  // Try to adapt `cs_copy' to the required topology.
107  const dimension_type cs_copy_space_dim = cs_copy.space_dimension();
108  if (!cs_copy.adjust_topology_and_space_dimension(topol, cs_copy_space_dim)) {
110  ? "C_Polyhedron(cs)"
111  : "NNC_Polyhedron(cs)", "cs", cs_copy);
112  }
113  // Set the space dimension.
114  space_dim = cs_copy_space_dim;
115 
116  if (space_dim > 0) {
117  // Stealing the rows from `cs_copy'.
118  using std::swap;
119  swap(con_sys, cs_copy);
120  if (con_sys.num_pending_rows() > 0) {
121  // Even though `cs_copy' has pending constraints, since the
122  // generators of the polyhedron are not up-to-date, the
123  // polyhedron cannot have pending constraints. By integrating
124  // the pending part of `con_sys' we may loose sortedness.
125  con_sys.set_sorted(false);
127  }
130  }
131  else {
132  // Here `space_dim == 0'.
133  // See if an inconsistent constraint has been passed.
134  for (dimension_type i = cs_copy.num_rows(); i-- > 0; ) {
135  if (cs_copy[i].is_inconsistent()) {
136  // Inconsistent constraint found: the polyhedron is empty.
137  set_empty();
138  break;
139  }
140  }
141  }
142  PPL_ASSERT_HEAVY(OK());
143 }
void swap(CO_Tree &x, CO_Tree &y)
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
dimension_type num_pending_rows() const
Returns the number of rows that are in the pending part of the system.
void set_constraints_up_to_date()
Sets status to express that constraints are up-to-date.
void swap(Polyhedron &x, Polyhedron &y)
Swaps x with y.
Constraint_System con_sys
The system of constraints.
void throw_topology_incompatible(const char *method, const char *ph_name, const Polyhedron &ph) const
Bit_Matrix sat_g
The saturation matrix having generators on its columns.
static dimension_type max_space_dimension()
Returns the maximum space dimension all kinds of Polyhedron can handle.
void set_empty()
Sets status to express that the polyhedron is empty, clearing all corresponding matrices.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
void unset_pending_rows()
Sets the index to indicate that the system has no pending rows.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
static const Representation default_con_sys_repr
void add_low_level_constraints()
Adds low-level constraints to the constraint system.
void set_sorted(bool b)
Sets the sortedness flag of the system to b.
Bit_Matrix sat_c
The saturation matrix having constraints on its columns.
static const Representation default_gen_sys_repr
Parma_Polyhedra_Library::Polyhedron::Polyhedron ( Topology  topol,
Constraint_System cs,
Recycle_Input  dummy 
)
protected

Builds a polyhedron recycling a system of constraints.

The polyhedron inherits the space dimension of the constraint system.

Parameters
topolThe topology of the polyhedron;
csThe system of constraints defining the polyhedron. It is not declared const because its data-structures may be recycled to build the polyhedron.
dummyA dummy tag to syntactically differentiate this one from the other constructors.
Exceptions
std::invalid_argumentThrown if the topology of cs is incompatible with topol.

Definition at line 145 of file Polyhedron_nonpublic.cc.

References Parma_Polyhedra_Library::Constraint_System::add_low_level_constraints(), Parma_Polyhedra_Library::Constraint_System::adjust_topology_and_space_dimension(), con_sys, max_space_dimension(), Parma_Polyhedra_Library::NECESSARILY_CLOSED, Parma_Polyhedra_Library::Constraint_System::num_pending_rows(), Parma_Polyhedra_Library::Constraint_System::num_rows(), OK(), set_constraints_up_to_date(), set_empty(), Parma_Polyhedra_Library::Constraint_System::set_sorted(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), swap(), throw_topology_incompatible(), and Parma_Polyhedra_Library::Constraint_System::unset_pending_rows().

148  : con_sys(topol, default_con_sys_repr),
150  sat_c(),
151  sat_g() {
152  // Protecting against space dimension overflow is up to the caller.
153  PPL_ASSERT(cs.space_dimension() <= max_space_dimension());
154 
155  // Try to adapt `cs' to the required topology.
156  const dimension_type cs_space_dim = cs.space_dimension();
157  if (!cs.adjust_topology_and_space_dimension(topol, cs_space_dim)) {
159  ? "C_Polyhedron(cs, recycle)"
160  : "NNC_Polyhedron(cs, recycle)", "cs", cs);
161  }
162 
163  // Set the space dimension.
164  space_dim = cs_space_dim;
165 
166  if (space_dim > 0) {
167  // Stealing the rows from `cs'.
168  swap(con_sys, cs);
169  if (con_sys.num_pending_rows() > 0) {
170  // Even though `cs' has pending constraints, since the generators
171  // of the polyhedron are not up-to-date, the polyhedron cannot
172  // have pending constraints. By integrating the pending part
173  // of `con_sys' we may loose sortedness.
175  con_sys.set_sorted(false);
176  }
179  }
180  else {
181  // Here `space_dim == 0'.
182 
183  // See if an inconsistent constraint has been passed.
184  for (dimension_type i = cs.num_rows(); i-- > 0; ) {
185  if (cs[i].is_inconsistent()) {
186  // Inconsistent constraint found: the polyhedron is empty.
187  set_empty();
188  break;
189  }
190  }
191  }
192  PPL_ASSERT_HEAVY(OK());
193 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
dimension_type num_pending_rows() const
Returns the number of rows that are in the pending part of the system.
void set_constraints_up_to_date()
Sets status to express that constraints are up-to-date.
void swap(Polyhedron &x, Polyhedron &y)
Swaps x with y.
Constraint_System con_sys
The system of constraints.
void throw_topology_incompatible(const char *method, const char *ph_name, const Polyhedron &ph) const
Bit_Matrix sat_g
The saturation matrix having generators on its columns.
static dimension_type max_space_dimension()
Returns the maximum space dimension all kinds of Polyhedron can handle.
void set_empty()
Sets status to express that the polyhedron is empty, clearing all corresponding matrices.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
void unset_pending_rows()
Sets the index to indicate that the system has no pending rows.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
static const Representation default_con_sys_repr
void add_low_level_constraints()
Adds low-level constraints to the constraint system.
void set_sorted(bool b)
Sets the sortedness flag of the system to b.
Bit_Matrix sat_c
The saturation matrix having constraints on its columns.
static const Representation default_gen_sys_repr
Parma_Polyhedra_Library::Polyhedron::Polyhedron ( Topology  topol,
const Generator_System gs 
)
protected

Builds a polyhedron from a system of generators.

The polyhedron inherits the space dimension of the generator system.

Parameters
topolThe topology of the polyhedron;
gsThe system of generators defining the polyhedron.
Exceptions
std::invalid_argumentThrown if the topology of gs is incompatible with topol, or if the system of generators is not empty but has no points.

Definition at line 195 of file Polyhedron_nonpublic.cc.

References Parma_Polyhedra_Library::Generator_System::add_corresponding_closure_points(), Parma_Polyhedra_Library::Generator_System::adjust_topology_and_space_dimension(), gen_sys, Parma_Polyhedra_Library::Generator_System::has_no_rows(), Parma_Polyhedra_Library::Generator_System::has_points(), max_space_dimension(), Parma_Polyhedra_Library::NECESSARILY_CLOSED, Parma_Polyhedra_Library::NOT_NECESSARILY_CLOSED, Parma_Polyhedra_Library::Generator_System::num_pending_rows(), OK(), Parma_Polyhedra_Library::Polyhedron::Status::set_empty(), set_generators_up_to_date(), Parma_Polyhedra_Library::Generator_System::set_sorted(), space_dim, Parma_Polyhedra_Library::Generator_System::space_dimension(), status, swap(), Parma_Polyhedra_Library::swap(), throw_invalid_generators(), throw_topology_incompatible(), and Parma_Polyhedra_Library::Generator_System::unset_pending_rows().

196  : con_sys(topol, default_con_sys_repr),
198  sat_c(),
199  sat_g() {
200  // Protecting against space dimension overflow is up to the caller.
201  PPL_ASSERT(gs.space_dimension() <= max_space_dimension());
202 
203  // An empty set of generators defines the empty polyhedron.
204  if (gs.has_no_rows()) {
205  space_dim = gs.space_dimension();
206  status.set_empty();
207  PPL_ASSERT_HEAVY(OK());
208  return;
209  }
210 
211  // Non-empty valid generator systems have a supporting point, at least.
212  if (!gs.has_points()) {
214  ? "C_Polyhedron(gs)"
215  : "NNC_Polyhedron(gs)", "gs");
216  }
217  // TODO: this implementation is just an executable specification.
218  Generator_System gs_copy = gs;
219 
220  const dimension_type gs_copy_space_dim = gs_copy.space_dimension();
221  // Try to adapt `gs_copy' to the required topology.
222  if (!gs_copy.adjust_topology_and_space_dimension(topol, gs_copy_space_dim)) {
224  ? "C_Polyhedron(gs)"
225  : "NNC_Polyhedron(gs)", "gs", gs_copy);
226  }
227 
228  if (gs_copy_space_dim > 0) {
229  // Stealing the rows from `gs_copy'.
230  using std::swap;
231  swap(gen_sys, gs_copy);
232  // In a generator system describing a NNC polyhedron,
233  // for each point we must also have the corresponding closure point.
234  if (topol == NOT_NECESSARILY_CLOSED) {
236  }
237  if (gen_sys.num_pending_rows() > 0) {
238  // Even though `gs_copy' has pending generators, since the
239  // constraints of the polyhedron are not up-to-date, the
240  // polyhedron cannot have pending generators. By integrating the
241  // pending part of `gen_sys' we may lose sortedness.
242  gen_sys.set_sorted(false);
244  }
245  // Generators are now up-to-date.
247 
248  // Set the space dimension.
249  space_dim = gs_copy_space_dim;
250  PPL_ASSERT_HEAVY(OK());
251  return;
252  }
253 
254  // Here `gs_copy.num_rows > 0' and `gs_copy_space_dim == 0':
255  // we already checked for both the topology-compatibility
256  // and the supporting point.
257  space_dim = 0;
258  PPL_ASSERT_HEAVY(OK());
259 }
void swap(CO_Tree &x, CO_Tree &y)
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
void set_generators_up_to_date()
Sets status to express that generators are up-to-date.
void swap(Polyhedron &x, Polyhedron &y)
Swaps x with y.
void throw_invalid_generators(const char *method, const char *gs_name) const
Constraint_System con_sys
The system of constraints.
void throw_topology_incompatible(const char *method, const char *ph_name, const Polyhedron &ph) const
Bit_Matrix sat_g
The saturation matrix having generators on its columns.
static dimension_type max_space_dimension()
Returns the maximum space dimension all kinds of Polyhedron can handle.
Status status
The status flags to keep track of the polyhedron's internal state.
void add_corresponding_closure_points()
For each unmatched point in *this, adds the corresponding closure point.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
void set_sorted(bool b)
Sets the sortedness flag of the system to b.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
static const Representation default_con_sys_repr
dimension_type num_pending_rows() const
Returns the number of rows that are in the pending part of the system.
Bit_Matrix sat_c
The saturation matrix having constraints on its columns.
static const Representation default_gen_sys_repr
void unset_pending_rows()
Sets the index to indicate that the system has no pending rows.
Parma_Polyhedra_Library::Polyhedron::Polyhedron ( Topology  topol,
Generator_System gs,
Recycle_Input  dummy 
)
protected

Builds a polyhedron recycling a system of generators.

The polyhedron inherits the space dimension of the generator system.

Parameters
topolThe topology of the polyhedron;
gsThe system of generators defining the polyhedron. It is not declared const because its data-structures may be recycled to build the polyhedron.
dummyA dummy tag to syntactically differentiate this one from the other constructors.
Exceptions
std::invalid_argumentThrown if the topology of gs is incompatible with topol, or if the system of generators is not empty but has no points.

Definition at line 261 of file Polyhedron_nonpublic.cc.

References Parma_Polyhedra_Library::Generator_System::add_corresponding_closure_points(), Parma_Polyhedra_Library::Generator_System::adjust_topology_and_space_dimension(), gen_sys, Parma_Polyhedra_Library::Generator_System::has_no_rows(), Parma_Polyhedra_Library::Generator_System::has_points(), max_space_dimension(), Parma_Polyhedra_Library::NECESSARILY_CLOSED, Parma_Polyhedra_Library::NOT_NECESSARILY_CLOSED, Parma_Polyhedra_Library::Generator_System::num_pending_rows(), OK(), Parma_Polyhedra_Library::Polyhedron::Status::set_empty(), set_generators_up_to_date(), Parma_Polyhedra_Library::Generator_System::set_sorted(), space_dim, Parma_Polyhedra_Library::Generator_System::space_dimension(), status, swap(), throw_invalid_generators(), throw_topology_incompatible(), and Parma_Polyhedra_Library::Generator_System::unset_pending_rows().

264  : con_sys(topol, default_con_sys_repr),
266  sat_c(),
267  sat_g() {
268  // Protecting against space dimension overflow is up to the caller.
269  PPL_ASSERT(gs.space_dimension() <= max_space_dimension());
270 
271  // An empty set of generators defines the empty polyhedron.
272  if (gs.has_no_rows()) {
273  space_dim = gs.space_dimension();
274  status.set_empty();
275  PPL_ASSERT_HEAVY(OK());
276  return;
277  }
278 
279  // Non-empty valid generator systems have a supporting point, at least.
280  if (!gs.has_points()) {
282  ? "C_Polyhedron(gs, recycle)"
283  : "NNC_Polyhedron(gs, recycle)", "gs");
284  }
285 
286  const dimension_type gs_space_dim = gs.space_dimension();
287  // Try to adapt `gs' to the required topology.
288  if (!gs.adjust_topology_and_space_dimension(topol, gs_space_dim)) {
290  ? "C_Polyhedron(gs, recycle)"
291  : "NNC_Polyhedron(gs, recycle)", "gs", gs);
292  }
293 
294  if (gs_space_dim > 0) {
295  // Stealing the rows from `gs'.
296  swap(gen_sys, gs);
297  // In a generator system describing a NNC polyhedron,
298  // for each point we must also have the corresponding closure point.
299  if (topol == NOT_NECESSARILY_CLOSED) {
301  }
302  if (gen_sys.num_pending_rows() > 0) {
303  // Even though `gs' has pending generators, since the constraints
304  // of the polyhedron are not up-to-date, the polyhedron cannot
305  // have pending generators. By integrating the pending part
306  // of `gen_sys' we may loose sortedness.
307  gen_sys.set_sorted(false);
309  }
310  // Generators are now up-to-date.
312 
313  // Set the space dimension.
314  space_dim = gs_space_dim;
315  PPL_ASSERT_HEAVY(OK());
316  return;
317  }
318 
319  // Here `gs.num_rows > 0' and `gs_space_dim == 0':
320  // we already checked for both the topology-compatibility
321  // and the supporting point.
322  space_dim = 0;
323  PPL_ASSERT_HEAVY(OK());
324 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
void set_generators_up_to_date()
Sets status to express that generators are up-to-date.
void swap(Polyhedron &x, Polyhedron &y)
Swaps x with y.
void throw_invalid_generators(const char *method, const char *gs_name) const
Constraint_System con_sys
The system of constraints.
void throw_topology_incompatible(const char *method, const char *ph_name, const Polyhedron &ph) const
Bit_Matrix sat_g
The saturation matrix having generators on its columns.
static dimension_type max_space_dimension()
Returns the maximum space dimension all kinds of Polyhedron can handle.
Status status
The status flags to keep track of the polyhedron's internal state.
void add_corresponding_closure_points()
For each unmatched point in *this, adds the corresponding closure point.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
void set_sorted(bool b)
Sets the sortedness flag of the system to b.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
static const Representation default_con_sys_repr
dimension_type num_pending_rows() const
Returns the number of rows that are in the pending part of the system.
Bit_Matrix sat_c
The saturation matrix having constraints on its columns.
static const Representation default_gen_sys_repr
void unset_pending_rows()
Sets the index to indicate that the system has no pending rows.
template<typename Interval >
Parma_Polyhedra_Library::Polyhedron::Polyhedron ( Topology  topol,
const Box< Interval > &  box,
Complexity_Class  complexity = ANY_COMPLEXITY 
)
protected

Builds a polyhedron from a box.

This will use an algorithm whose complexity is polynomial and build the smallest polyhedron with topology topol containing box.

Parameters
topolThe topology of the polyhedron;
boxThe box representing the polyhedron to be built;
complexityThis argument is ignored.

Definition at line 39 of file Polyhedron_templates.hh.

References Parma_Polyhedra_Library::Constraint_System::add_low_level_constraints(), con_sys, Parma_Polyhedra_Library::Box< ITV >::has_lower_bound(), Parma_Polyhedra_Library::Box< ITV >::has_upper_bound(), Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::NECESSARILY_CLOSED, OK(), PPL_DIRTY_TEMP_COEFFICIENT, set_constraints_up_to_date(), set_empty(), Parma_Polyhedra_Library::Constraint_System::set_space_dimension(), set_zero_dim_univ(), space_dim, and Parma_Polyhedra_Library::Box< ITV >::space_dimension().

42  : con_sys(topol, default_con_sys_repr),
44  sat_c(),
45  sat_g() {
46  // Initialize the space dimension as indicated by the box.
47  space_dim = box.space_dimension();
48 
49  // Check for emptiness.
50  if (box.is_empty()) {
51  set_empty();
52  return;
53  }
54 
55  // Zero-dim universe polyhedron.
56  if (space_dim == 0) {
58  return;
59  }
60 
61  // Properly set the space dimension of `con_sys'.
63 
68 
69  if (topol == NECESSARILY_CLOSED) {
70  for (dimension_type k = space_dim; k-- > 0; ) {
71  const Variable v_k = Variable(k);
72  // See if we have a valid lower bound.
73  bool l_closed = false;
74  bool l_bounded = box.has_lower_bound(v_k, l_n, l_d, l_closed);
75  // See if we have a valid upper bound.
76  bool u_closed = false;
77  bool u_bounded = box.has_upper_bound(v_k, u_n, u_d, u_closed);
78 
79  // See if we have an implicit equality constraint.
80  if (l_bounded && u_bounded
81  && l_closed && u_closed
82  && l_n == u_n && l_d == u_d) {
83  // Add the constraint `l_d*v_k == l_n'.
84  con_sys.insert(l_d * v_k == l_n);
85  }
86  else {
87  if (l_bounded) {
88  // Add the constraint `l_d*v_k >= l_n'.
89  con_sys.insert(l_d * v_k >= l_n);
90  }
91  if (u_bounded) {
92  // Add the constraint `u_d*v_k <= u_n'.
93  con_sys.insert(u_d * v_k <= u_n);
94  }
95  }
96  }
97  }
98  else {
99  // topol == NOT_NECESSARILY_CLOSED
100  for (dimension_type k = space_dim; k-- > 0; ) {
101  const Variable v_k = Variable(k);
102  // See if we have a valid lower bound.
103  bool l_closed = false;
104  bool l_bounded = box.has_lower_bound(v_k, l_n, l_d, l_closed);
105  // See if we have a valid upper bound.
106  bool u_closed = false;
107  bool u_bounded = box.has_upper_bound(v_k, u_n, u_d, u_closed);
108 
109  // See if we have an implicit equality constraint.
110  if (l_bounded && u_bounded
111  && l_closed && u_closed
112  && l_n == u_n && l_d == u_d) {
113  // Add the constraint `l_d*v_k == l_n'.
114  con_sys.insert(l_d * v_k == l_n);
115  }
116  else {
117  // Check if a lower bound constraint is required.
118  if (l_bounded) {
119  if (l_closed) {
120  // Add the constraint `l_d*v_k >= l_n'.
121  con_sys.insert(l_d * v_k >= l_n);
122  }
123  else {
124  // Add the constraint `l_d*v_k > l_n'.
125  con_sys.insert(l_d * v_k > l_n);
126  }
127  }
128  // Check if an upper bound constraint is required.
129  if (u_bounded) {
130  if (u_closed) {
131  // Add the constraint `u_d*v_k <= u_n'.
132  con_sys.insert(u_d * v_k <= u_n);
133  }
134  else {
135  // Add the constraint `u_d*v_k < u_n'.
136  con_sys.insert(u_d * v_k < u_n);
137  }
138  }
139  }
140  }
141  }
142 
143  // Adding the low-level constraints.
145 
146  // Constraints are up-to-date.
148  PPL_ASSERT_HEAVY(OK());
149 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
void set_space_dimension(dimension_type space_dim)
Sets the space dimension of the rows in the system to space_dim .
Generator_System gen_sys
The system of generators.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
void insert(const Constraint &c)
Inserts in *this a copy of the constraint c, increasing the number of space dimensions if needed...
void set_constraints_up_to_date()
Sets status to express that constraints are up-to-date.
Constraint_System con_sys
The system of constraints.
Bit_Matrix sat_g
The saturation matrix having generators on its columns.
void set_empty()
Sets status to express that the polyhedron is empty, clearing all corresponding matrices.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
static const Representation default_con_sys_repr
void add_low_level_constraints()
Adds low-level constraints to the constraint system.
Bit_Matrix sat_c
The saturation matrix having constraints on its columns.
static const Representation default_gen_sys_repr
void set_zero_dim_univ()
Sets status to express that the polyhedron is the universe 0-dimension vector space, clearing all corresponding matrices.
Parma_Polyhedra_Library::Polyhedron::~Polyhedron ( )
inline

Destructor.

Definition at line 96 of file Polyhedron_inlines.hh.

96  {
97 }

Member Function Documentation

template<typename Source_Linear_System1 , typename Source_Linear_System2 , typename Dest_Linear_System >
bool Parma_Polyhedra_Library::Polyhedron::add_and_minimize ( bool  con_to_gen,
Source_Linear_System1 &  source1,
Dest_Linear_System &  dest,
Bit_Matrix sat,
const Source_Linear_System2 &  source2 
)
staticprivate

Adds given constraints and builds minimized corresponding generators or vice versa.

Returns
true if the obtained polyhedron is empty, false otherwise.
Parameters
con_to_gentrue if source1 and source2 are system of constraints, false otherwise;
source1The first element of the given DD pair;
destThe second element of the given DD pair;
satThe saturation matrix that bind source1 to dest;
source2The new system of generators or constraints.

It is assumed that source1 and source2 are sorted and have no pending rows. It is also assumed that dest has no pending rows. On entry, the rows of sat are indexed by the rows of dest and its columns are indexed by the rows of source1. On exit, the rows of sat are indexed by the rows of dest and its columns are indexed by the rows of the system obtained by merging source1 and source2.

Let us suppose we want to add some constraints to a given system of constraints source1. This method, given a minimized double description pair (source1, dest) and a system of new constraints source2, modifies source1 by adding to it the constraints of source2 that are not in source1. Then, by invoking add_and_minimize(bool, Linear_System_Class&, Linear_System_Class&, Bit_Matrix&), processes the added constraints obtaining a new DD pair.

This method treats also the dual case, i.e., adding new generators to a previous system of generators. In this case source1 contains the old generators, source2 the new ones and dest is the system of constraints in the given minimized DD pair.

Since source2 contains the constraints (or the generators) that will be added to source1, it is constant: it will not be modified.

Definition at line 267 of file Polyhedron_minimize_templates.hh.

References Parma_Polyhedra_Library::cmp(), and Parma_Polyhedra_Library::compare().

271  {
272  // `source1' and `source2' cannot be empty.
273  PPL_ASSERT(!source1.has_no_rows() && !source2.has_no_rows());
274  // `source1' and `source2' must have the same number of columns
275  // to be merged.
276  PPL_ASSERT(source1.num_columns() == source2.num_columns());
277  // `source1' and `source2' are fully sorted.
278  PPL_ASSERT(source1.is_sorted() && source1.num_pending_rows() == 0);
279  PPL_ASSERT(source2.is_sorted() && source2.num_pending_rows() == 0);
280  PPL_ASSERT(dest.num_pending_rows() == 0);
281 
282  const dimension_type old_source1_num_rows = source1.num_rows();
283  // `k1' and `k2' run through the rows of `source1' and `source2', resp.
284  dimension_type k1 = 0;
285  dimension_type k2 = 0;
286  dimension_type source2_num_rows = source2.num_rows();
287  while (k1 < old_source1_num_rows && k2 < source2_num_rows) {
288  // Add to `source1' the constraints from `source2', as pending rows.
289  // We exploit the property that initially both `source1' and `source2'
290  // are sorted and index `k1' only scans the non-pending rows of `source1',
291  // so that it is not influenced by the pending rows appended to it.
292  // This way no duplicate (i.e., trivially redundant) constraint
293  // is introduced in `source1'.
294  const int cmp = compare(source1[k1], source2[k2]);
295  if (cmp == 0) {
296  // We found the same row: there is no need to add `source2[k2]'.
297  ++k2;
298  // By sortedness, since `k1 < old_source1_num_rows',
299  // we can increment index `k1' too.
300  ++k1;
301  }
302  else if (cmp < 0) {
303  // By sortedness, we can increment `k1'.
304  ++k1;
305  }
306  else {
307  // Here `cmp > 0'.
308  // By sortedness, `source2[k2]' cannot be in `source1'.
309  // We add it as a pending row of `source1' (sortedness unaffected).
310  source1.add_pending_row(source2[k2]);
311  // We can increment `k2'.
312  ++k2;
313  }
314  }
315  // Have we scanned all the rows in `source2'?
316  if (k2 < source2_num_rows) {
317  // By sortedness, all the rows in `source2' having indexes
318  // greater than or equal to `k2' were not in `source1'.
319  // We add them as pending rows of 'source1' (sortedness not affected).
320  for ( ; k2 < source2_num_rows; ++k2) {
321  source1.add_pending_row(source2[k2]);
322  }
323  }
324 
325  if (source1.num_pending_rows() == 0) {
326  // No row was appended to `source1', because all the constraints
327  // in `source2' were already in `source1'.
328  // There is nothing left to do ...
329  return false;
330  }
331  return add_and_minimize(con_to_gen, source1, dest, sat);
332 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
int compare(const Linear_Expression &x, const Linear_Expression &y)
int cmp(const GMP_Integer &x, const GMP_Integer &y)
static bool add_and_minimize(bool con_to_gen, Source_Linear_System1 &source1, Dest_Linear_System &dest, Bit_Matrix &sat, const Source_Linear_System2 &source2)
Adds given constraints and builds minimized corresponding generators or vice versa.
template<typename Source_Linear_System , typename Dest_Linear_System >
bool Parma_Polyhedra_Library::Polyhedron::add_and_minimize ( bool  con_to_gen,
Source_Linear_System &  source,
Dest_Linear_System &  dest,
Bit_Matrix sat 
)
staticprivate

Adds given constraints and builds minimized corresponding generators or vice versa. The given constraints are in source.

Returns
true if the obtained polyhedron is empty, false otherwise.
Parameters
con_to_gentrue if source is a system of constraints, false otherwise;
sourceThe first element of the given DD pair. It also contains the pending rows to be processed;
destThe second element of the given DD pair. It cannot have pending rows;
satThe saturation matrix that bind the upper part of source to dest.

On entry, the rows of sat are indexed by the rows of dest and its columns are indexed by the non-pending rows of source. On exit, the rows of sat are indexed by the rows of dest and its columns are indexed by the rows of source.

Let us suppose that source is a system of constraints. This method assumes that the non-pending part of source and system dest form a double description pair in minimal form and will build a new DD pair in minimal form by processing the pending constraints in source. To this end, it will call conversion()) and simplify.

This method treats also the dual case, i.e., processing pending generators. In this case source contains generators and dest is the system of constraints corresponding to the non-pending part of source.

Definition at line 372 of file Polyhedron_minimize_templates.hh.

References conversion(), Parma_Polyhedra_Library::Bit_Matrix::resize(), and simplify().

375  {
376  PPL_ASSERT(source.num_pending_rows() > 0);
377  PPL_ASSERT(source.space_dimension() == dest.space_dimension());
378  PPL_ASSERT(source.is_sorted());
379 
380  // First, pad the saturation matrix with new columns (of zeroes)
381  // to accommodate for the pending rows of `source'.
382  sat.resize(dest.num_rows(), source.num_rows());
383 
384  // Incrementally compute the new system of generators.
385  // Parameter `start' is set to the index of the first pending constraint.
386  const dimension_type num_lines_or_equalities
387  = conversion(source, source.first_pending_row(),
388  dest, sat,
389  dest.num_lines_or_equalities());
390 
391  // conversion() may have modified the number of rows in `dest'.
392  const dimension_type dest_num_rows = dest.num_rows();
393 
394  // Checking if the generators in `dest' represent an empty polyhedron:
395  // the polyhedron is empty if there are no points
396  // (because rays, lines and closure points need a supporting point).
397  // Points can be detected by looking at:
398  // - the divisor, for necessarily closed polyhedra;
399  // - the epsilon coordinate, for NNC polyhedra.
400  dimension_type first_point;
401  if (dest.is_necessarily_closed()) {
402  for (first_point = num_lines_or_equalities;
403  first_point < dest_num_rows;
404  ++first_point) {
405  if (dest[first_point].expr.inhomogeneous_term() > 0) {
406  break;
407  }
408  }
409  }
410  else {
411  for (first_point = num_lines_or_equalities;
412  first_point < dest_num_rows;
413  ++first_point) {
414  if (dest[first_point].expr.get(Variable(dest.space_dimension())) > 0) {
415  break;
416  }
417  }
418  }
419 
420  if (first_point == dest_num_rows) {
421  if (con_to_gen) {
422  // No point has been found: the polyhedron is empty.
423  return true;
424  }
425  else {
426  // Here `con_to_gen' is false: `dest' is a system of constraints.
427  // In this case the condition `first_point == dest_num_rows'
428  // actually means that all the constraints in `dest' have their
429  // inhomogeneous term equal to 0.
430  // This is an ILLEGAL situation, because it implies that
431  // the constraint system `dest' lacks the positivity constraint
432  // and no linear combination of the constraints in `dest'
433  // can reintroduce the positivity constraint.
434  PPL_UNREACHABLE;
435  return false;
436  }
437  }
438  else {
439  // A point has been found: the polyhedron is not empty.
440  // Now invoking `simplify()' to remove all the redundant constraints
441  // from the system `source'.
442  // Since the saturation matrix `sat' returned by `conversion()'
443  // has rows indexed by generators (the rows of `dest') and columns
444  // indexed by constraints (the rows of `source'), we have to
445  // transpose it to obtain the saturation matrix needed by `simplify()'.
446  sat.transpose();
447  simplify(source, sat);
448  // Transposing back.
449  sat.transpose();
450  return false;
451  }
452 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
static dimension_type simplify(Linear_System1 &sys, Bit_Matrix &sat)
Uses Gauss' elimination method to simplify the result of conversion().
static dimension_type conversion(Source_Linear_System &source, dimension_type start, Dest_Linear_System &dest, Bit_Matrix &sat, dimension_type num_lines_or_equalities)
Performs the conversion from constraints to generators and vice versa.
void Parma_Polyhedra_Library::Polyhedron::add_congruence ( const Congruence cg)

Adds a copy of congruence cg to *this, if cg can be exactly represented by a polyhedron.

Exceptions
std::invalid_argumentThrown if *this and congruence cg are dimension-incompatible, of if cg is a proper congruence which is neither a tautology, nor a contradiction.

Definition at line 1329 of file Polyhedron_public.cc.

References c, Parma_Polyhedra_Library::Constraint::EQUALITY, Parma_Polyhedra_Library::Congruence::expression(), 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::Boundary_NS::le(), Parma_Polyhedra_Library::NECESSARILY_CLOSED, and Parma_Polyhedra_Library::Congruence::space_dimension().

1329  {
1330  // Dimension-compatibility check:
1331  // the dimension of `cg' can not be greater than space_dim.
1332  if (space_dim < cg.space_dimension()) {
1333  throw_dimension_incompatible("add_congruence(cg)", "cg", cg);
1334  }
1335 
1336  // Handle the case of proper congruences first.
1337  if (cg.is_proper_congruence()) {
1338  if (cg.is_tautological()) {
1339  return;
1340  }
1341  if (cg.is_inconsistent()) {
1342  set_empty();
1343  return;
1344  }
1345  // Non-trivial and proper congruences are not allowed.
1346  throw_invalid_argument("add_congruence(cg)",
1347  "cg is a non-trivial, proper congruence");
1348  }
1349 
1350  PPL_ASSERT(cg.is_equality());
1351  // Handle empty and 0-dim cases first.
1352  if (marked_empty()) {
1353  return;
1354  }
1355  if (space_dim == 0) {
1356  if (cg.is_inconsistent()) {
1357  set_empty();
1358  }
1359  return;
1360  }
1361 
1362  // Add the equality.
1365  refine_no_check(c);
1366 }
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
A linear equality or inequality.
bool is_inconsistent() const
Returns true if and only if *this is inconsistent (i.e., an always false congruence).
Definition: Congruence.cc:218
expr_type expression() const
Partial read access to the (adapted) internal expression.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
bool is_proper_congruence() const
Returns true if the modulus is greater than zero.
void throw_invalid_argument(const char *method, const char *reason) const
bool is_equality() const
Returns true if *this is an equality.
void refine_no_check(const Constraint &c)
Uses a copy of constraint c to refine the system of constraints of *this.
bool is_tautological() const
Returns true if and only if *this is a tautology (i.e., an always true congruence).
Definition: Congruence.cc:210
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void set_empty()
Sets status to express that the polyhedron is empty, clearing all corresponding matrices.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
Coefficient c
Definition: PIP_Tree.cc:64
bool le(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
void Parma_Polyhedra_Library::Polyhedron::add_congruences ( const Congruence_System cgs)

Adds a copy of the congruences in cgs to *this, if all the congruences can be exactly represented by a polyhedron.

Parameters
cgsThe congruences to be added.
Exceptions
std::invalid_argumentThrown if *this and cgs are dimension-incompatible, of if there exists in cgs a proper congruence which is neither a tautology, nor a contradiction.

Definition at line 1707 of file Polyhedron_public.cc.

References Parma_Polyhedra_Library::Congruence_System::begin(), c, Parma_Polyhedra_Library::Congruence_System::end(), Parma_Polyhedra_Library::Constraint::EQUALITY, Parma_Polyhedra_Library::Congruence::expression(), Parma_Polyhedra_Library::Constraint_System::insert(), 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::Boundary_NS::le(), Parma_Polyhedra_Library::NECESSARILY_CLOSED, and Parma_Polyhedra_Library::Congruence_System::space_dimension().

Referenced by add_recycled_congruences(), Parma_Polyhedra_Library::C_Polyhedron::C_Polyhedron(), and Parma_Polyhedra_Library::NNC_Polyhedron::NNC_Polyhedron().

1707  {
1708  // Dimension-compatibility check.
1709  if (space_dim < cgs.space_dimension()) {
1710  throw_dimension_incompatible("add_congruences(cgs)", "cgs", cgs);
1711  }
1712 
1713  Constraint_System cs;
1714  bool inserted = false;
1716  cgs_end = cgs.end(); i != cgs_end; ++i) {
1717  const Congruence& cg = *i;
1718  if (cg.is_equality()) {
1721 
1722  // TODO: Consider stealing the row in c when adding it to cs.
1723  cs.insert(c);
1724  inserted = true;
1725  }
1726  else {
1727  PPL_ASSERT(cg.is_proper_congruence());
1728  if (cg.is_inconsistent()) {
1729  set_empty();
1730  return;
1731  }
1732  if (!cg.is_tautological()) {
1733  throw_invalid_argument("add_congruences(cgs)",
1734  "cgs has a non-trivial, proper congruence");
1735  }
1736  }
1737  }
1738  // Only add cs if it contains something.
1739  if (inserted) {
1741  }
1742 }
A linear equality or inequality.
bool is_inconsistent() const
Returns true if and only if *this is inconsistent (i.e., an always false congruence).
Definition: Congruence.cc:218
void insert(const Constraint &c)
Inserts in *this a copy of the constraint c, increasing the number of space dimensions if needed...
const_iterator end() const
Returns the past-the-end const_iterator.
expr_type expression() const
Partial read access to the (adapted) internal expression.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
void add_recycled_constraints(Constraint_System &cs)
Adds the constraints in cs to the system of constraints of *this (without minimizing the result)...
bool is_proper_congruence() const
Returns true if the modulus is greater than zero.
void throw_invalid_argument(const char *method, const char *reason) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
bool is_equality() const
Returns true if *this is an equality.
const_iterator begin() const
Returns the const_iterator pointing to the first congruence, if this is not empty; otherwise...
bool is_tautological() const
Returns true if and only if *this is a tautology (i.e., an always true congruence).
Definition: Congruence.cc:210
void set_empty()
Sets status to express that the polyhedron is empty, clearing all corresponding matrices.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
Coefficient c
Definition: PIP_Tree.cc:64
bool le(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
void Parma_Polyhedra_Library::Polyhedron::add_constraint ( const Constraint c)

Adds a copy of constraint c to the system of constraints of *this (without minimizing the result).

Parameters
cThe constraint that will be added to the system of constraints of *this.
Exceptions
std::invalid_argumentThrown if *this and constraint c are topology-incompatible or dimension-incompatible.

Definition at line 1301 of file Polyhedron_public.cc.

References Parma_Polyhedra_Library::Constraint::is_inconsistent(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Constraint::is_tautological(), and Parma_Polyhedra_Library::Constraint::space_dimension().

Referenced by Parma_Polyhedra_Library::Pointset_Powerset< PSET >::affine_dimension(), Parma_Polyhedra_Library::Termination_Helpers::all_affine_ranking_functions_PR(), Parma_Polyhedra_Library::Termination_Helpers::all_affine_ranking_functions_PR_original(), BHZ09_NNC_poly_hull_assign_if_exact(), Parma_Polyhedra_Library::C_Polyhedron::C_Polyhedron(), and Parma_Polyhedra_Library::Pointset_Powerset< PSET >::linear_partition_aux().

1301  {
1302  // Topology-compatibility check.
1304  // Trivially true/false strict inequalities are legal.
1305  if (c.is_tautological()) {
1306  return;
1307  }
1308  if (c.is_inconsistent()) {
1309  set_empty();
1310  return;
1311  }
1312  // Here c is a non-trivial strict inequality.
1313  throw_topology_incompatible("add_constraint(c)", "c", c);
1314  }
1315 
1316  // Dimension-compatibility check:
1317  // the dimension of `c' can not be greater than space_dim.
1318  if (space_dim < c.space_dimension()) {
1319  throw_dimension_incompatible("add_constraint(c)", "c", c);
1320  }
1321 
1322  if (!marked_empty()) {
1323  refine_no_check(c);
1324  }
1325 
1326 }
bool is_tautological() const
Returns true if and only if *this is a tautology (i.e., an always true constraint).
Definition: Constraint.cc:105
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
bool is_strict_inequality() const
Returns true if and only if *this is a strict inequality constraint.
void refine_no_check(const Constraint &c)
Uses a copy of constraint c to refine the system of constraints of *this.
void throw_topology_incompatible(const char *method, const char *ph_name, const Polyhedron &ph) const
bool is_inconsistent() const
Returns true if and only if *this is inconsistent (i.e., an always false constraint).
Definition: Constraint.cc:148
void set_empty()
Sets status to express that the polyhedron is empty, clearing all corresponding matrices.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
void Parma_Polyhedra_Library::Polyhedron::add_constraints ( const Constraint_System cs)

Adds a copy of the constraints in cs to the system of constraints of *this (without minimizing the result).

Parameters
csContains the constraints that will be added to the system of constraints of *this.
Exceptions
std::invalid_argumentThrown if *this and cs are topology-incompatible or dimension-incompatible.

Definition at line 1602 of file Polyhedron_public.cc.

Referenced by Parma_Polyhedra_Library::C_Polyhedron::C_Polyhedron(), Parma_Polyhedra_Library::NNC_Polyhedron::NNC_Polyhedron(), and simplify_using_context_assign().

1602  {
1603  // TODO: this is just an executable specification.
1604  Constraint_System cs_copy = cs;
1605  add_recycled_constraints(cs_copy);
1606 }
void add_recycled_constraints(Constraint_System &cs)
Adds the constraints in cs to the system of constraints of *this (without minimizing the result)...
void Parma_Polyhedra_Library::Polyhedron::add_generator ( const Generator g)

Adds a copy of generator g to the system of generators of *this (without minimizing the result).

Exceptions
std::invalid_argumentThrown if *this and generator g are topology-incompatible or dimension-incompatible, or if *this is an empty polyhedron and g is not a point.

Definition at line 1369 of file Polyhedron_public.cc.

References Parma_Polyhedra_Library::Generator::CLOSURE_POINT, Parma_Polyhedra_Library::Generator::divisor(), Parma_Polyhedra_Library::Generator::expression(), Parma_Polyhedra_Library::Generator::is_closure_point(), Parma_Polyhedra_Library::Generator::is_necessarily_closed(), Parma_Polyhedra_Library::Generator::is_point(), Parma_Polyhedra_Library::Generator::line(), Parma_Polyhedra_Library::Generator::LINE, Parma_Polyhedra_Library::Generator::point(), Parma_Polyhedra_Library::Generator::POINT, Parma_Polyhedra_Library::Generator::ray(), Parma_Polyhedra_Library::Generator::RAY, Parma_Polyhedra_Library::Generator::space_dimension(), and Parma_Polyhedra_Library::Generator::type().

Referenced by BHZ09_NNC_poly_hull_assign_if_exact().

1369  {
1370  // Topology-compatibility check.
1371  if (g.is_closure_point() && is_necessarily_closed()) {
1372  throw_topology_incompatible("add_generator(g)", "g", g);
1373  }
1374  // Dimension-compatibility check:
1375  // the dimension of `g' can not be greater than space_dim.
1376  const dimension_type g_space_dim = g.space_dimension();
1377  if (space_dim < g_space_dim) {
1378  throw_dimension_incompatible("add_generator(g)", "g", g);
1379  }
1380  // Dealing with a zero-dimensional space polyhedron first.
1381  if (space_dim == 0) {
1382  // It is not possible to create 0-dim rays or lines.
1383  PPL_ASSERT(g.is_point() || g.is_closure_point());
1384  // Closure points can only be inserted in non-empty polyhedra.
1385  if (marked_empty()) {
1386  if (g.type() != Generator::POINT) {
1387  throw_invalid_generator("add_generator(g)", "g");
1388  }
1389  else {
1391  }
1392  }
1393  PPL_ASSERT_HEAVY(OK());
1394  return;
1395  }
1396 
1397  if (marked_empty()
1400  // Here the polyhedron is empty:
1401  // the specification says we can only insert a point.
1402  if (!g.is_point()) {
1403  throw_invalid_generator("add_generator(g)", "g");
1404  }
1406  gen_sys.insert(g);
1407  // Since `gen_sys' was empty, after inserting `g' we have to resize
1408  // the system of generators to have the right dimension.
1410  if (!is_necessarily_closed()) {
1411  // In the NNC topology, each point has to be matched by
1412  // a corresponding closure point:
1413  // turn the just inserted point into the corresponding
1414  // (normalized) closure point.
1415  gen_sys.sys.rows.back().set_epsilon_coefficient(0);
1416  gen_sys.sys.rows.back().expr.normalize();
1417  PPL_ASSERT(gen_sys.sys.rows.back().OK());
1418  PPL_ASSERT(gen_sys.sys.OK());
1419  // Re-insert the point (which is already normalized).
1420  gen_sys.insert(g);
1421  }
1422  }
1423  else {
1424  // Note: here we have a _legal_ topology mismatch,
1425  // because `g' is NOT a closure point (it is a point!)
1426  // However, by barely invoking `gen_sys.insert(g)' we would
1427  // cause a change in the topology of `gen_sys', which is wrong.
1428  // Thus, we insert a "topology corrected" copy of `g'.
1429  const Linear_Expression nc_expr(g.expression());
1430  gen_sys.insert(Generator::point(nc_expr, g.divisor()));
1431  // Since `gen_sys' was empty, after inserting `g' we have to resize
1432  // the system of generators to have the right dimension.
1434  }
1435  // No longer empty, generators up-to-date and minimized.
1436  clear_empty();
1438  }
1439  else {
1440  PPL_ASSERT(generators_are_up_to_date());
1441  const bool has_pending = can_have_something_pending();
1443  // Since `gen_sys' is not empty, the topology and space dimension
1444  // of the inserted generator are automatically adjusted.
1445  if (has_pending) {
1447  }
1448  else {
1449  gen_sys.insert(g);
1450  }
1451  if (!is_necessarily_closed() && g.is_point()) {
1452  // In the NNC topology, each point has to be matched by
1453  // a corresponding closure point:
1454  // turn the just inserted point into the corresponding
1455  // (normalized) closure point.
1456  gen_sys.sys.rows.back().set_epsilon_coefficient(0);
1457  gen_sys.sys.rows.back().expr.normalize();
1458  PPL_ASSERT(gen_sys.sys.rows.back().OK());
1459  PPL_ASSERT(gen_sys.sys.OK());
1460  // Re-insert the point (which is already normalized).
1461  if (has_pending) {
1463  }
1464  else {
1465  gen_sys.insert(g);
1466  }
1467  }
1468  }
1469  else {
1470  PPL_ASSERT(!g.is_closure_point());
1471  // Note: here we have a _legal_ topology mismatch, because
1472  // `g' is NOT a closure point.
1473  // However, by barely invoking `gen_sys.insert(g)' we would
1474  // cause a change in the topology of `gen_sys', which is wrong.
1475  // Thus, we insert a "topology corrected" copy of `g'.
1476  const Linear_Expression nc_expr(g.expression());
1477  switch (g.type()) {
1478  case Generator::LINE:
1479  if (has_pending) {
1481  }
1482  else {
1483  gen_sys.insert(Generator::line(nc_expr));
1484  }
1485  break;
1486  case Generator::RAY:
1487  if (has_pending) {
1489  }
1490  else {
1491  gen_sys.insert(Generator::ray(nc_expr));
1492  }
1493  break;
1494  case Generator::POINT:
1495  if (has_pending) {
1497  }
1498  else {
1499  gen_sys.insert(Generator::point(nc_expr, g.divisor()));
1500  }
1501  break;
1503  PPL_UNREACHABLE;
1504  break;
1505  }
1506  }
1507 
1508  if (has_pending) {
1510  }
1511  else {
1512  // After adding the new generator,
1513  // constraints are no longer up-to-date.
1516  }
1517  }
1518  PPL_ASSERT_HEAVY(OK());
1519 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
void clear_constraints_up_to_date()
Sets status to express that constraints are no longer up-to-date.
bool adjust_topology_and_space_dimension(Topology new_topology, dimension_type new_space_dim)
Adjusts *this so that it matches the new_topology and new_space_dim (adding or removing columns if ne...
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
static Generator ray(const Linear_Expression &e, Representation r=default_representation)
Returns the ray of direction e.
Definition: Generator.cc:128
bool update_generators() const
Updates generators starting from constraints and minimizes them.
expr_type expression() const
Partial read access to the (adapted) internal expression.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
static Generator line(const Linear_Expression &e, Representation r=default_representation)
Returns the line of direction e.
Definition: Generator.cc:143
bool can_have_something_pending() const
Returns true if the polyhedron can have something pending.
Topology topology() const
Returns the topological kind of the polyhedron.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
Type type() const
Returns the generator type of *this.
void throw_topology_incompatible(const char *method, const char *ph_name, const Polyhedron &ph) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void set_generators_minimized()
Sets status to express that generators are minimized.
void insert_pending(const Generator_System &r)
Adds a copy of the rows of `y' to the pending part of `*this'.
bool is_point() const
Returns true if and only if *this is a point.
void clear_empty()
Clears the status flag indicating that the polyhedron is empty.
static Generator point(const Linear_Expression &e=Linear_Expression::zero(), Coefficient_traits::const_reference d=Coefficient_one(), Representation r=default_representation)
Returns the point at e / d.
Definition: Generator.cc:57
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
bool process_pending_constraints() const
Processes the pending constraints and obtains a minimized polyhedron.
bool is_necessarily_closed() const
Returns true if and only if the topology of *this row is necessarily closed.
Coefficient_traits::const_reference divisor() const
If *this is either a point or a closure point, returns its divisor.
void throw_invalid_generator(const char *method, const char *g_name) const
void set_generators_pending()
Sets status to express that generators are pending.
void insert(const Generator &g)
Inserts in *this a copy of the generator g, increasing the number of space dimensions if needed...
void set_zero_dim_univ()
Sets status to express that the polyhedron is the universe 0-dimension vector space, clearing all corresponding matrices.
void clear_generators_minimized()
Sets status to express that generators are no longer minimized.
bool is_closure_point() const
Returns true if and only if *this is a closure point.
void Parma_Polyhedra_Library::Polyhedron::add_generators ( const Generator_System gs)

Adds a copy of the generators in gs to the system of generators of *this (without minimizing the result).

Parameters
gsContains the generators that will be added to the system of generators of *this.
Exceptions
std::invalid_argumentThrown if *this and gs are topology-incompatible or dimension-incompatible, or if *this is empty and the system of generators gs is not empty, but has no points.

Definition at line 1700 of file Polyhedron_public.cc.

1700  {
1701  // TODO: this is just an executable specification.
1702  Generator_System gs_copy = gs;
1703  add_recycled_generators(gs_copy);
1704 }
void add_recycled_generators(Generator_System &gs)
Adds the generators in gs to the system of generators of *this (without minimizing the result)...
void Parma_Polyhedra_Library::Polyhedron::add_recycled_congruences ( Congruence_System cgs)
inline

Adds the congruences in cgs to *this, if all the congruences can be exactly represented by a polyhedron.

Parameters
cgsThe congruences to be added. Its elements may be recycled.
Exceptions
std::invalid_argumentThrown if *this and cgs are dimension-incompatible, of if there exists in cgs a proper congruence which is neither a tautology, nor a contradiction
Warning
The only assumption that can be made on cgs upon successful or exceptional return is that it can be safely destroyed.

Definition at line 377 of file Polyhedron_inlines.hh.

References add_congruences().

377  {
378  add_congruences(cgs);
379 }
void add_congruences(const Congruence_System &cgs)
Adds a copy of the congruences in cgs to *this, if all the congruences can be exactly represented by ...
void Parma_Polyhedra_Library::Polyhedron::add_recycled_constraints ( Constraint_System cs)

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

Parameters
csThe constraint system to be added to *this. The constraints in cs may be recycled.
Exceptions
std::invalid_argumentThrown if *this and cs are 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 1522 of file Polyhedron_public.cc.

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

Referenced by BHRZ03_combining_constraints(), H79_widening_assign(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), and simplify_using_context_assign().

1522  {
1523  // Topology compatibility check.
1525  // We check if _all_ strict inequalities in cs are trivially false.
1526  // (The iterators already filter away trivially true constraints.)
1528  i_end = cs.end(); i != i_end; ++i) {
1529  if (i->is_strict_inequality()
1530  && !i->is_inconsistent()) {
1531  throw_topology_incompatible("add_recycled_constraints(cs)",
1532  "cs", cs);
1533  }
1534  }
1535  // If we reach this point, all strict inequalities were inconsistent.
1536  set_empty();
1537  return;
1538  }
1539 
1540  // Dimension-compatibility check:
1541  // the dimension of `cs' can not be greater than space_dim.
1542  const dimension_type cs_space_dim = cs.space_dimension();
1543  if (space_dim < cs_space_dim) {
1544  throw_dimension_incompatible("add_recycled_constraints(cs)", "cs", cs);
1545  }
1546  // Adding no constraints is a no-op.
1547  if (cs.has_no_rows()) {
1548  return;
1549  }
1550 
1551  if (space_dim == 0) {
1552  // In a 0-dimensional space the constraints are
1553  // tautologies (e.g., 0 == 0 or 1 >= 0 or 1 > 0) or
1554  // inconsistent (e.g., 1 == 0 or -1 >= 0 or 0 > 0).
1555  // In a system of constraints `begin()' and `end()' are equal
1556  // if and only if the system only contains tautologies.
1557  if (cs.begin() != cs.end()) {
1558  // There is a constraint, it must be inconsistent,
1559  // the polyhedron is empty.
1560  status.set_empty();
1561  }
1562  return;
1563  }
1564 
1565  if (marked_empty()) {
1566  return;
1567  }
1568 
1569  // The constraints (possibly with pending rows) are required.
1570  if (has_pending_generators()) {
1572  }
1573  else if (!constraints_are_up_to_date()) {
1575  }
1576 
1577  // Adjust `cs' to the right topology and space dimension.
1578  // NOTE: we already checked for topology compatibility.
1580 
1581  const bool adding_pending = can_have_something_pending();
1582 
1583  // Here we do not require `con_sys' to be sorted.
1584  // also, we _recycle_ (instead of copying) the coefficients of `cs'.
1585  if (adding_pending) {
1588  }
1589  else {
1590  con_sys.insert(cs, Recycle_Input());
1591  // Constraints are not minimized and generators are not up-to-date.
1594  }
1595 
1596  // Note: the constraint system may have become unsatisfiable, thus
1597  // we do not check for satisfiability.
1598  PPL_ASSERT_HEAVY(OK());
1599 }
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
void insert_pending(const Constraint &c)
Inserts in *this a copy of the constraint c, increasing the number of space dimensions if needed...
size_t dimension_type
An unsigned integral type for representing space dimensions.
void update_constraints() const
Updates constraints starting from generators and minimizes them.
void set_constraints_pending()
Sets status to express that constraints are pending.
void insert(const Constraint &c)
Inserts in *this a copy of the constraint c, increasing the number of space dimensions if needed...
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
const_iterator begin() const
Returns the const_iterator pointing to the first constraint, if *this is not empty; otherwise...
bool can_have_something_pending() const
Returns true if the polyhedron can have something pending.
Topology topology() const
Returns the topological kind of the polyhedron.
Constraint_System con_sys
The system of constraints.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
void throw_topology_incompatible(const char *method, const char *ph_name, const Polyhedron &ph) const
const_iterator end() const
Returns the past-the-end const_iterator.
void process_pending_generators() const
Processes the pending generators and obtains a minimized polyhedron.
Status status
The status flags to keep track of the polyhedron's internal state.
void set_empty()
Sets status to express that the polyhedron is empty, clearing all corresponding matrices.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
void clear_constraints_minimized()
Sets status to express that constraints are no longer minimized.
bool has_pending_generators() const
Returns true if there are pending generators.
bool adjust_topology_and_space_dimension(Topology new_topology, dimension_type new_space_dim)
Adjusts *this so that it matches new_topology and new_space_dim (adding or removing columns if needed...
void clear_generators_up_to_date()
Sets status to express that generators are no longer up-to-date.
bool has_strict_inequalities() const
Returns true if and only if *this contains one or more strict inequality constraints.
void Parma_Polyhedra_Library::Polyhedron::add_recycled_generators ( Generator_System gs)

Adds the generators in gs to the system of generators of *this (without minimizing the result).

Parameters
gsThe generator system to be added to *this. The generators in gs may be recycled.
Exceptions
std::invalid_argumentThrown if *this and gs are topology-incompatible or dimension-incompatible, or if *this is empty and the system of generators gs is not empty, but has no points.
Warning
The only assumption that can be made on gs upon successful or exceptional return is that it can be safely destroyed.

Definition at line 1609 of file Polyhedron_public.cc.

References Parma_Polyhedra_Library::Generator_System::add_corresponding_closure_points(), Parma_Polyhedra_Library::Generator_System::adjust_topology_and_space_dimension(), Parma_Polyhedra_Library::Generator_System::clear(), Parma_Polyhedra_Library::Generator_System::has_closure_points(), Parma_Polyhedra_Library::Generator_System::has_no_rows(), Parma_Polyhedra_Library::Generator_System::has_points(), Parma_Polyhedra_Library::Generator_System::num_rows(), Parma_Polyhedra_Library::Generator_System::space_dimension(), Parma_Polyhedra_Library::swap(), and Parma_Polyhedra_Library::Generator_System::sys.

Referenced by BHRZ03_evolving_points(), and BHRZ03_evolving_rays().

1609  {
1610  // Topology compatibility check.
1611  if (is_necessarily_closed() && gs.has_closure_points()) {
1612  throw_topology_incompatible("add_recycled_generators(gs)", "gs", gs);
1613  }
1614  // Dimension-compatibility check:
1615  // the dimension of `gs' can not be greater than space_dim.
1616  const dimension_type gs_space_dim = gs.space_dimension();
1617  if (space_dim < gs_space_dim) {
1618  throw_dimension_incompatible("add_recycled_generators(gs)", "gs", gs);
1619  }
1620 
1621  // Adding no generators is a no-op.
1622  if (gs.has_no_rows()) {
1623  return;
1624  }
1625 
1626  // Adding valid generators to a zero-dimensional polyhedron
1627  // transform it in the zero-dimensional universe polyhedron.
1628  if (space_dim == 0) {
1629  if (marked_empty() && !gs.has_points()) {
1630  throw_invalid_generators("add_recycled_generators(gs)", "gs");
1631  }
1633  PPL_ASSERT_HEAVY(OK(true));
1634  return;
1635  }
1636 
1637  // Adjust `gs' to the right topology and dimensions.
1638  // NOTE: we already checked for topology compatibility.
1640  // For NNC polyhedra, each point must be matched by
1641  // the corresponding closure point.
1642  if (!is_necessarily_closed()) {
1644  }
1645 
1646  // The generators (possibly with pending rows) are required.
1648  || (!generators_are_up_to_date() && !minimize())) {
1649  // We have just discovered that `*this' is empty.
1650  // So `gs' must contain at least one point.
1651  if (!gs.has_points()) {
1652  throw_invalid_generators("add_recycled_generators(gs)", "gs");
1653  }
1654  // The polyhedron is no longer empty and generators are up-to-date.
1655  swap(gen_sys, gs);
1656  if (gen_sys.num_pending_rows() > 0) {
1657  // Even though `gs' has pending generators, since the constraints
1658  // of the polyhedron are not up-to-date, the polyhedron cannot
1659  // have pending generators. By integrating the pending part
1660  // of `gen_sys' we may loose sortedness.
1661  gen_sys.sys.index_first_pending = gen_sys.num_rows();
1662  gen_sys.set_sorted(false);
1663  }
1665  clear_empty();
1666  PPL_ASSERT_HEAVY(OK());
1667  return;
1668  }
1669 
1671  // Here we do not require `gen_sys' to be sorted.
1672  // also, we _remove_ (instead of copying) the rows of `gs'
1673  // (which is not a const).
1674  for (dimension_type i = 0; i < gs.num_rows(); ++i) {
1675  gs.sys.rows[i].set_topology(topology());
1676  gen_sys.insert_pending(gs.sys.rows[i], Recycle_Input());
1677  }
1678  gs.clear();
1679 
1681  }
1682  else {
1683  // Here we do not require `gen_sys' to be sorted.
1684  // also, we _remove_ (instead of copying) the coefficients of `gs'
1685  // (which is not a const).
1686  for (dimension_type i = 0; i < gs.num_rows(); ++i) {
1687  gs.sys.rows[i].set_topology(topology());
1688  gen_sys.insert(gs.sys.rows[i], Recycle_Input());
1689  }
1690  gs.clear();
1691 
1692  // Constraints are not up-to-date and generators are not minimized.
1695  }
1696  PPL_ASSERT_HEAVY(OK(true));
1697 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
bool minimize() const
Applies (weak) minimization to both the constraints and generators.
void clear_constraints_up_to_date()
Sets status to express that constraints are no longer up-to-date.
bool adjust_topology_and_space_dimension(Topology new_topology, dimension_type new_space_dim)
Adjusts *this so that it matches the new_topology and new_space_dim (adding or removing columns if ne...
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
void set_generators_up_to_date()
Sets status to express that generators are up-to-date.
void swap(Polyhedron &x, Polyhedron &y)
Swaps x with y.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
bool has_points() const
Returns true if and only if *this contains one or more points.
bool can_have_something_pending() const
Returns true if the polyhedron can have something pending.
void throw_invalid_generators(const char *method, const char *gs_name) const
Topology topology() const
Returns the topological kind of the polyhedron.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
void clear()
Removes all the generators from the generator system and sets its space dimension to 0...
void throw_topology_incompatible(const char *method, const char *ph_name, const Polyhedron &ph) const
void insert_pending(const Generator_System &r)
Adds a copy of the rows of `y' to the pending part of `*this'.
void clear_empty()
Clears the status flag indicating that the polyhedron is empty.
void add_corresponding_closure_points()
For each unmatched point in *this, adds the corresponding closure point.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
void set_sorted(bool b)
Sets the sortedness flag of the system to b.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
bool process_pending_constraints() const
Processes the pending constraints and obtains a minimized polyhedron.
dimension_type num_pending_rows() const
Returns the number of rows that are in the pending part of the system.
void set_generators_pending()
Sets status to express that generators are pending.
void insert(const Generator &g)
Inserts in *this a copy of the generator g, increasing the number of space dimensions if needed...
bool has_closure_points() const
Returns true if and only if *this contains one or more closure points.
void set_zero_dim_univ()
Sets status to express that the polyhedron is the universe 0-dimension vector space, clearing all corresponding matrices.
void clear_generators_minimized()
Sets status to express that generators are no longer minimized.
template<typename Linear_System1 , typename Linear_System2 >
void Parma_Polyhedra_Library::Polyhedron::add_space_dimensions ( Linear_System1 &  sys1,
Linear_System2 &  sys2,
Bit_Matrix sat1,
Bit_Matrix sat2,
dimension_type  add_dim 
)
staticprivate

Adds new space dimensions to the given linear systems.

Parameters
sys1The linear system to which columns are added;
sys2The linear system to which rows and columns are added;
sat1The saturation matrix whose columns are indexed by the rows of sys1. On entry it is up-to-date;
sat2The saturation matrix whose columns are indexed by the rows of sys2;
add_dimThe number of space dimensions to add.

Adds new space dimensions to the vector space modifying the linear systems and saturation matrices. This function is invoked only by add_space_dimensions_and_embed() and add_space_dimensions_and_project(), passing the linear system of constraints and that of generators (and the corresponding saturation matrices) in different order (see those methods for details).

Definition at line 32 of file Polyhedron_chdims_templates.hh.

References Parma_Polyhedra_Library::Bit_Matrix::num_columns(), Parma_Polyhedra_Library::Bit_Matrix::num_rows(), Parma_Polyhedra_Library::Bit_Matrix::resize(), swap(), and Parma_Polyhedra_Library::Bit_Matrix::transpose_assign().

Referenced by add_space_dimensions_and_embed().

36  {
37  PPL_ASSERT(sys1.topology() == sys2.topology());
38  PPL_ASSERT(sys1.space_dimension() == sys2.space_dimension());
39  PPL_ASSERT(add_dim != 0);
40 
41  sys1.set_space_dimension(sys1.space_dimension() + add_dim);
42  sys2.add_universe_rows_and_space_dimensions(add_dim);
43 
44  // The resulting saturation matrix will be as follows:
45  // from row 0 to add_dim-1 : only zeroes
46  // add_dim add_dim+num_rows-1 : old saturation matrix
47 
48  // In fact all the old generators saturate all the new constraints
49  // because the polyhedron has not been embedded in the new space.
50  sat1.resize(sat1.num_rows() + add_dim, sat1.num_columns());
51  // The old matrix is moved to the end of the new matrix.
52  for (dimension_type i = sat1.num_rows() - add_dim; i-- > 0; ) {
53  swap(sat1[i], sat1[i+add_dim]);
54  }
55  // Computes the "sat_c", too.
56  sat2.transpose_assign(sat1);
57 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
void swap(Polyhedron &x, Polyhedron &y)
Swaps x with y.
void Parma_Polyhedra_Library::Polyhedron::add_space_dimensions_and_embed ( dimension_type  m)

Adds m new space dimensions and embeds the old polyhedron in the new vector space.

Parameters
mThe number of dimensions to add.
Exceptions
std::length_errorThrown if adding m new space dimensions would cause the vector space to exceed dimension max_space_dimension().

The new space dimensions will be those having the highest indexes in the new polyhedron, which is characterized by a system of constraints in which the variables running through the new dimensions are not constrained. For instance, when starting from the polyhedron $\cP \sseq \Rset^2$ and adding a third space dimension, the result will be the polyhedron

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

Definition at line 35 of file Polyhedron_chdims.cc.

References add_space_dimensions(), Parma_Polyhedra_Library::Generator_System::add_universe_rows_and_space_dimensions(), check_space_dimension_overflow(), Parma_Polyhedra_Library::Constraint_System::clear(), con_sys, constraints_are_up_to_date(), gen_sys, generators_are_up_to_date(), m_swap(), marked_empty(), max_space_dimension(), OK(), sat_c, sat_c_is_up_to_date(), sat_g, Parma_Polyhedra_Library::Constraint_System::set_space_dimension(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), space_dimension(), status, Parma_Polyhedra_Library::Polyhedron::Status::test_zero_dim_univ(), topology(), Parma_Polyhedra_Library::UNIVERSE, and update_sat_c().

Referenced by Parma_Polyhedra_Library::Implementation::Termination::all_affine_quasi_ranking_functions_MS(), Parma_Polyhedra_Library::Implementation::Termination::all_affine_ranking_functions_MS(), Parma_Polyhedra_Library::Termination_Helpers::all_affine_ranking_functions_PR(), and Parma_Polyhedra_Library::Termination_Helpers::all_affine_ranking_functions_PR_original().

35  {
36  // The space dimension of the resulting polyhedron should not
37  // overflow the maximum allowed space dimension.
39  topology(),
40  "add_space_dimensions_and_embed(m)",
41  "adding m new space dimensions exceeds "
42  "the maximum allowed space dimension");
43 
44  // Adding no dimensions to any polyhedron is a no-op.
45  if (m == 0) {
46  return;
47  }
48 
49  // Adding dimensions to an empty polyhedron is obtained by adjusting
50  // `space_dim' and clearing `con_sys' (since it can contain the
51  // unsatisfiable constraint system of the wrong dimension).
52  if (marked_empty()) {
53  space_dim += m;
54  con_sys.clear();
55  return;
56  }
57 
58  // The case of a zero-dimensional space polyhedron.
59  if (space_dim == 0) {
60  // Since it is not empty, it has to be the universe polyhedron.
61  PPL_ASSERT(status.test_zero_dim_univ());
62  // We swap `*this' with a newly created
63  // universe polyhedron of dimension `m'.
64  Polyhedron ph(topology(), m, UNIVERSE);
65  m_swap(ph);
66  return;
67  }
68 
69  // To embed an n-dimension space polyhedron in a (n+m)-dimension space,
70  // we just add `m' zero-columns to the rows in the system of constraints;
71  // in contrast, the system of generators needs additional rows,
72  // corresponding to the vectors of the canonical basis
73  // for the added dimensions. That is, for each new dimension `x[k]'
74  // we add the line having that direction. This is done by invoking
75  // the function add_space_dimensions() giving the system of generators
76  // as the second argument.
79  // `sat_c' must be up to date for add_space_dimensions().
80  if (!sat_c_is_up_to_date()) {
81  update_sat_c();
82  }
83  // Adds rows and/or columns to both matrices.
84  // `add_space_dimensions' correctly handles pending constraints
85  // or generators.
87  }
88  else {
89  // Only constraints are up-to-date: no need to modify the generators.
91  }
92  }
93  else {
94  // Only generators are up-to-date: no need to modify the constraints.
95  PPL_ASSERT(generators_are_up_to_date());
97  }
98  // Update the space dimension.
99  space_dim += m;
100 
101  // Note: we do not check for satisfiability, because the system of
102  // constraints may be unsatisfiable.
103  PPL_ASSERT_HEAVY(OK());
104 }
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
void set_space_dimension(dimension_type space_dim)
Sets the space dimension of the rows in the system to space_dim .
Generator_System gen_sys
The system of generators.
void add_universe_rows_and_space_dimensions(dimension_type n)
Adds n rows and space dimensions to the system.
bool sat_c_is_up_to_date() const
Returns true if the saturation matrix sat_c is up-to-date.
void clear()
Removes all the constraints from the constraint system and sets its space dimension to 0...
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
Topology topology() const
Returns the topological kind of the polyhedron.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
Constraint_System con_sys
The system of constraints.
static dimension_type check_space_dimension_overflow(dimension_type dim, dimension_type max, const Topology topol, const char *method, const char *reason)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
Bit_Matrix sat_g
The saturation matrix having generators on its columns.
static dimension_type max_space_dimension()
Returns the maximum space dimension all kinds of Polyhedron can handle.
Status status
The status flags to keep track of the polyhedron's internal state.
The universe element, i.e., the whole vector space.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
void update_sat_c() const
Updates sat_c using the updated constraints and generators.
Bit_Matrix sat_c
The saturation matrix having constraints on its columns.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
static void add_space_dimensions(Linear_System1 &sys1, Linear_System2 &sys2, Bit_Matrix &sat1, Bit_Matrix &sat2, dimension_type add_dim)
Adds new space dimensions to the given linear systems.
void m_swap(Polyhedron &y)
Swaps *this with polyhedron y. (*this and y can be dimension-incompatible.)
void Parma_Polyhedra_Library::Polyhedron::add_space_dimensions_and_project ( dimension_type  m)

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

Parameters
mThe number of space dimensions to add.
Exceptions
std::length_errorThrown if adding m new space dimensions would cause the vector space to exceed dimension max_space_dimension().

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

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

Definition at line 107 of file Polyhedron_chdims.cc.

References Parma_Polyhedra_Library::check_space_dimension_overflow(), Parma_Polyhedra_Library::max_space_dimension(), Parma_Polyhedra_Library::Generator::zero_dim_closure_point(), and Parma_Polyhedra_Library::Generator::zero_dim_point().

107  {
108  // The space dimension of the resulting polyhedron should not
109  // overflow the maximum allowed space dimension.
111  topology(),
112  "add_space_dimensions_and_project(m)",
113  "adding m new space dimensions exceeds "
114  "the maximum allowed space dimension");
115 
116  // Adding no dimensions to any polyhedron is a no-op.
117  if (m == 0) {
118  return;
119  }
120 
121  // Adding dimensions to an empty polyhedron is obtained
122  // by merely adjusting `space_dim'.
123  if (marked_empty()) {
124  space_dim += m;
125  con_sys.clear();
126  return;
127  }
128 
129  if (space_dim == 0) {
130  PPL_ASSERT(status.test_zero_dim_univ() && gen_sys.has_no_rows());
131  // The system of generators for this polyhedron has only
132  // the origin as a point.
133  // In an NNC polyhedron, all points have to be accompanied
134  // by the corresponding closure points
135  // (this time, dimensions are automatically adjusted).
136  if (!is_necessarily_closed()) {
138  }
142  space_dim = m;
143  PPL_ASSERT_HEAVY(OK());
144  return;
145  }
146 
147  // To project an n-dimension space polyhedron in a (n+m)-dimension space,
148  // we just add to the system of generators `m' zero-columns;
149  // In contrast, in the system of constraints, new rows are needed
150  // in order to avoid embedding the old polyhedron in the new space.
151  // Thus, for each new dimensions `x[k]', we add the constraint
152  // x[k] = 0: this is done by invoking the function add_space_dimensions()
153  // giving the system of constraints as the second argument.
156  // `sat_g' must be up to date for add_space_dimensions().
157  if (!sat_g_is_up_to_date()) {
158  update_sat_g();
159  }
160  // Adds rows and/or columns to both matrices.
161  // `add_space_dimensions()' correctly handles pending constraints
162  // or generators.
164  }
165  else {
166  // Only constraints are up-to-date: no need to modify the generators.
168  }
169  }
170  else {
171  // Only generators are up-to-date: no need to modify the constraints.
172  PPL_ASSERT(generators_are_up_to_date());
174  }
175  // Now we update the space dimension.
176  space_dim += m;
177 
178  // Note: we do not check for satisfiability, because the system of
179  // constraints may be unsatisfiable.
180  PPL_ASSERT_HEAVY(OK());
181 }
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
bool adjust_topology_and_space_dimension(Topology new_topology, dimension_type new_space_dim)
Adjusts *this so that it matches the new_topology and new_space_dim (adding or removing columns if ne...
Generator_System gen_sys
The system of generators.
static const Generator & zero_dim_point()
Returns the origin of the zero-dimensional space .
void add_universe_rows_and_space_dimensions(dimension_type n)
Adds n rows and space dimensions to the system.
bool sat_g_is_up_to_date() const
Returns true if the saturation matrix sat_g is up-to-date.
void clear()
Removes all the constraints from the constraint system and sets its space dimension to 0...
void update_sat_g() const
Updates sat_g using the updated constraints and generators.
Topology topology() const
Returns the topological kind of the polyhedron.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
Constraint_System con_sys
The system of constraints.
static dimension_type check_space_dimension_overflow(dimension_type dim, dimension_type max, const Topology topol, const char *method, const char *reason)
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
Bit_Matrix sat_g
The saturation matrix having generators on its columns.
void set_generators_minimized()
Sets status to express that generators are minimized.
static dimension_type max_space_dimension()
Returns the maximum space dimension all kinds of Polyhedron can handle.
Status status
The status flags to keep track of the polyhedron's internal state.
static const Generator & zero_dim_closure_point()
Returns, as a closure point, the origin of the zero-dimensional space .
dimension_type space_dim
The number of dimensions of the enclosing vector space.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
void set_space_dimension(dimension_type space_dim)
Sets the space dimension of the rows in the system to space_dim .
Bit_Matrix sat_c
The saturation matrix having constraints on its columns.
void insert(const Generator &g)
Inserts in *this a copy of the generator g, increasing the number of space dimensions if needed...
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
static void add_space_dimensions(Linear_System1 &sys1, Linear_System2 &sys2, Bit_Matrix &sat1, Bit_Matrix &sat2, dimension_type add_dim)
Adds new space dimensions to the given linear systems.
template<typename Linear_System1 , typename Row2 >
bool Parma_Polyhedra_Library::Polyhedron::add_to_system_and_check_independence ( Linear_System1 &  eq_sys,
const Row2 &  eq 
)
staticprotected

Definition at line 2135 of file Polyhedron_public.cc.

2136  {
2137  // Check if eq is linearly independent from eq_sys.
2138  PPL_ASSERT(eq.is_line_or_equality());
2139  eq_sys.insert(eq);
2140  const PPL::dimension_type eq_sys_num_rows = eq_sys.num_rows();
2141  const PPL::dimension_type rank = eq_sys.gauss(eq_sys_num_rows);
2142  if (rank == eq_sys_num_rows) {
2143  // eq is linearly independent from eq_sys.
2144  return true;
2145  }
2146  else {
2147  // eq is not linearly independent from eq_sys.
2148  PPL_ASSERT(rank == eq_sys_num_rows - 1);
2149  eq_sys.remove_trailing_rows(1);
2150  return false;
2151  }
2152 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool eq(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
PPL::dimension_type Parma_Polyhedra_Library::Polyhedron::affine_dimension ( ) const

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

Definition at line 61 of file Polyhedron_public.cc.

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

Referenced by Parma_Polyhedra_Library::Pointset_Powerset< PSET >::affine_dimension(), BHZ09_C_poly_hull_assign_if_exact(), and is_discrete().

61  {
62  if (is_empty()) {
63  return 0;
64  }
65 
69  cs_end = cs.end(); i != cs_end; ++i) {
70  if (i->is_equality()) {
71  --d;
72  }
73  }
74  return d;
75 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool is_empty() const
Returns true if and only if *this is an empty polyhedron.
const_iterator begin() const
Returns the const_iterator pointing to the first constraint, if *this is not empty; otherwise...
const_iterator end() const
Returns the past-the-end const_iterator.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
const Constraint_System & minimized_constraints() const
Returns the system of constraints, with no redundant constraint.
template<typename FP_Format , typename Interval_Info >
void Parma_Polyhedra_Library::Polyhedron::affine_form_image ( Variable  var,
const Linear_Form< Interval< FP_Format, Interval_Info > > &  lf 
)

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

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

This function is used in abstract interpretation to model an assignment of a value that is correctly overapproximated by lf to the floating point variable represented by var.

Definition at line 372 of file Polyhedron_templates.hh.

References bounded_affine_image(), convert_to_integer_expressions(), Parma_Polyhedra_Library::Variable::id(), marked_empty(), overapproximate_linear_form(), Polyhedron(), PPL_COMPILE_TIME_CHECK, PPL_DIRTY_TEMP_COEFFICIENT, space_dim, throw_dimension_incompatible(), topology(), and Parma_Polyhedra_Library::UNIVERSE.

373  {
374 
375  // Check that FP_Format is indeed a floating point type.
376  PPL_COMPILE_TIME_CHECK(!std::numeric_limits<FP_Format>::is_exact,
377  "Polyhedron::affine_form_image:"
378  " FP_Format not a floating point type.");
379 
380  // Dimension compatibility checks.
381  // The dimension of lf should not be greater than the dimension of *this.
382  const dimension_type lf_space_dim = lf.space_dimension();
383  if (space_dim < lf_space_dim) {
384  throw_dimension_incompatible("affine_form_image(v, l, s)", "l", lf);
385  }
386 
387  // `var' should be one of the dimensions of the polyhedron.
388  const dimension_type var_id = var.id();
389  if (space_dim < var_id + 1) {
390  throw_dimension_incompatible("affine_form_image(v, l, s)", "v", var);
391  }
392 
393  // We assume that the analyzer will not perform an unreachable assignment.
394  PPL_ASSERT(!marked_empty());
395 
396  typedef Interval<FP_Format, Interval_Info> FP_Interval_Type;
397  typedef Linear_Form<FP_Interval_Type> FP_Linear_Form;
398 
399  if (Floating_Point_Expression<FP_Interval_Type, float_ieee754_single>::
400  overflows(lf)) {
401  *this = Polyhedron(topology(), space_dim, UNIVERSE);
402  return;
403  }
404 
405  // Overapproximate lf.
406  FP_Linear_Form lf_approx;
407  overapproximate_linear_form(lf, lf_space_dim, lf_approx);
408 
409  if (Floating_Point_Expression<FP_Interval_Type, float_ieee754_single>::
410  overflows(lf_approx)) {
411  *this = Polyhedron(topology(), space_dim, UNIVERSE);
412  return;
413  }
414 
415  // Normalize lf.
416  Linear_Expression lf_approx_le;
417  PPL_DIRTY_TEMP_COEFFICIENT(lo_coeff);
418  PPL_DIRTY_TEMP_COEFFICIENT(hi_coeff);
419  PPL_DIRTY_TEMP_COEFFICIENT(denominator);
420  convert_to_integer_expressions(lf_approx, lf_space_dim, lf_approx_le,
421  lo_coeff, hi_coeff, denominator);
422 
423  // Finally, do the assignment.
424  bounded_affine_image(var, lf_approx_le + lo_coeff, lf_approx_le + hi_coeff,
425  denominator);
426 }
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
void bounded_affine_image(Variable var, const Linear_Expression &lb_expr, const Linear_Expression &ub_expr, Coefficient_traits::const_reference denominator=Coefficient_one())
Assigns to *this the image of *this with respect to the bounded affine relation . ...
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
Topology topology() const
Returns the topological kind of the polyhedron.
static void convert_to_integer_expressions(const Linear_Form< Interval< FP_Format, Interval_Info > > &lf, const dimension_type lf_dimension, Linear_Expression &res, Coefficient &res_low_coeff, Coefficient &res_hi_coeff, Coefficient &denominator)
Normalization helper function.
#define PPL_COMPILE_TIME_CHECK(e, msg)
Produces a compilation error if the compile-time constant e does not evaluate to true ...
The universe element, i.e., the whole vector space.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
void overapproximate_linear_form(const Linear_Form< Interval< FP_Format, Interval_Info > > &lf, const dimension_type lf_dimension, Linear_Form< Interval< FP_Format, Interval_Info > > &result)
Helper function that overapproximates an interval linear form.
void Parma_Polyhedra_Library::Polyhedron::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 to the affine expression specified by expr and denominator.

Parameters
varThe variable to which the affine expression is assigned;
exprThe numerator of the affine expression;
denominatorThe denominator of the affine expression (optional argument with default value 1).
Exceptions
std::invalid_argumentThrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a space dimension of *this.

When considering the generators of a polyhedron, the affine transformation

\[ \frac{\sum_{i=0}^{n-1} a_i x_i + b}{\mathrm{denominator}} \]

is assigned to var where expr is $\sum_{i=0}^{n-1} a_i x_i + b$ ( $b$ is the inhomogeneous term).

If constraints are up-to-date, it uses the specialized function affine_preimage() (for the system of constraints) and inverse transformation to reach the same result. To obtain the inverse transformation we use the following observation.

Observation:

  1. The affine transformation is invertible if the coefficient of var in this transformation (i.e., $a_\mathrm{var}$) is different from zero.
  2. If the transformation is invertible, then we can write

    \[ \mathrm{denominator} * {x'}_\mathrm{var} = \sum_{i = 0}^{n - 1} a_i x_i + b = a_\mathrm{var} x_\mathrm{var} + \sum_{i \neq var} a_i x_i + b, \]

    so that the inverse transformation is

    \[ a_\mathrm{var} x_\mathrm{var} = \mathrm{denominator} * {x'}_\mathrm{var} - \sum_{i \neq j} a_i x_i - b. \]

Then, if the transformation is invertible, all the entities that were up-to-date remain up-to-date. Otherwise only generators remain up-to-date.

In other words, if $R$ is a $m_1 \times n$ matrix representing the rays of the polyhedron, $V$ is a $m_2 \times n$ matrix representing the points of the polyhedron and

\[ P = \bigl\{\, \vect{x} = (x_0, \ldots, x_{n-1})^\mathrm{T} \bigm| \vect{x} = \vect{\lambda} R + \vect{\mu} V, \vect{\lambda} \in \Rset^{m_1}_+, \vect{\mu} \in \Rset^{m_2}_+, \sum_{i = 0}^{m_2 - 1} \mu_i = 1 \,\bigr\} \]

and $T$ is the affine transformation to apply to $P$, then the resulting polyhedron is

\[ P' = \bigl\{\, (x_0, \ldots, T(x_0, \ldots, x_{n-1}), \ldots, x_{n-1})^\mathrm{T} \bigm| (x_0, \ldots, x_{n-1})^\mathrm{T} \in P \,\bigr\}. \]

Affine transformations are, for example:

  • translations
  • rotations
  • symmetries.

Definition at line 2745 of file Polyhedron_public.cc.

References c, Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::inverse(), Parma_Polyhedra_Library::Linear_Expression::set_coefficient(), Parma_Polyhedra_Library::Variable::space_dimension(), and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

Referenced by fold_space_dimensions().

2747  {
2748  // The denominator cannot be zero.
2749  if (denominator == 0) {
2750  throw_invalid_argument("affine_image(v, e, d)", "d == 0");
2751  }
2752  // Dimension-compatibility checks.
2753  // The dimension of `expr' should not be greater than the dimension
2754  // of `*this'.
2755  if (space_dim < expr.space_dimension()) {
2756  throw_dimension_incompatible("affine_image(v, e, d)", "e", expr);
2757  // `var' should be one of the dimensions of the polyhedron.
2758  }
2759  const dimension_type var_space_dim = var.space_dimension();
2760  if (space_dim < var_space_dim) {
2761  throw_dimension_incompatible("affine_image(v, e, d)", "v", var);
2762  }
2763  if (marked_empty()) {
2764  return;
2765  }
2766 
2767  if (expr.coefficient(var) != 0) {
2768  // The transformation is invertible:
2769  // minimality and saturators are preserved, so that
2770  // pending rows, if present, are correctly handled.
2771  if (generators_are_up_to_date()) {
2772  // Generator_System::affine_image() requires the third argument
2773  // to be a positive Coefficient.
2774  if (denominator > 0) {
2775  gen_sys.affine_image(var, expr, denominator);
2776  }
2777  else {
2778  gen_sys.affine_image(var, -expr, -denominator);
2779  }
2780  }
2782  // To build the inverse transformation,
2783  // after copying and negating `expr',
2784  // we exchange the roles of `expr[var_space_dim]' and `denominator'.
2786  Coefficient_traits::const_reference c = expr.coefficient(var);
2787  if (c > 0) {
2788  inverse = -expr;
2789  inverse.set_coefficient(var, denominator);
2790  con_sys.affine_preimage(var, inverse, c);
2791  }
2792  else {
2793  // The new denominator is negative: we negate everything once
2794  // more, as Constraint_System::affine_preimage() requires the
2795  // third argument to be positive.
2796  inverse = expr;
2797  inverse.set_coefficient(var, -denominator);
2798  con_sys.affine_preimage(var, inverse, -c);
2799  }
2800  }
2801  }
2802  else {
2803  // The transformation is not invertible.
2804  // We need an up-to-date system of generators.
2805  if (has_something_pending()) {
2807  }
2808  else if (!generators_are_up_to_date()) {
2809  minimize();
2810  }
2811  if (!marked_empty()) {
2812  // Generator_System::affine_image() requires the third argument
2813  // to be a positive Coefficient.
2814  if (denominator > 0) {
2815  gen_sys.affine_image(var, expr, denominator);
2816  }
2817  else {
2818  gen_sys.affine_image(var, -expr, -denominator);
2819  }
2820 
2825  }
2826  }
2827  PPL_ASSERT_HEAVY(OK());
2828 }
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
bool minimize() const
Applies (weak) minimization to both the constraints and generators.
void clear_constraints_up_to_date()
Sets status to express that constraints are no longer up-to-date.
bool remove_pending_to_obtain_generators() const
Lazily integrates the pending descriptions of the polyhedron to obtain a generator system without pen...
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void set_coefficient(Variable v, Coefficient_traits::const_reference n)
Sets the coefficient of v in *this to n.
Coefficient_traits::const_reference coefficient(Variable v) const
Returns the coefficient of v in *this.
Rounding_Dir inverse(Rounding_Dir dir)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
void throw_invalid_argument(const char *method, const char *reason) const
Constraint_System con_sys
The system of constraints.
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
void clear_sat_g_up_to_date()
Sets status to express that sat_g is no longer up-to-date.
void affine_preimage(Variable v, const Linear_Expression &expr, Coefficient_traits::const_reference denominator)
Substitutes a given column of coefficients by a given affine expression.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
void clear_sat_c_up_to_date()
Sets status to express that sat_c is no longer up-to-date.
Coefficient c
Definition: PIP_Tree.cc:64
void clear_generators_minimized()
Sets status to express that generators are no longer minimized.
void affine_image(Variable v, const Linear_Expression &expr, Coefficient_traits::const_reference denominator)
Assigns to a given variable an affine expression.
bool has_something_pending() const
Returns true if there are either pending constraints or pending generators.
void Parma_Polyhedra_Library::Polyhedron::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 to the affine expression specified by expr and denominator.

Parameters
varThe variable to which the affine expression is substituted;
exprThe numerator of the affine expression;
denominatorThe denominator of the affine expression (optional argument with default value 1).
Exceptions
std::invalid_argumentThrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a space dimension of *this.

When considering constraints of a polyhedron, the affine transformation

\[ \frac{\sum_{i=0}^{n-1} a_i x_i + b}{denominator}, \]

is assigned to var where expr is $\sum_{i=0}^{n-1} a_i x_i + b$ ( $b$ is the inhomogeneous term).

If generators are up-to-date, then the specialized function affine_image() is used (for the system of generators) and inverse transformation to reach the same result. To obtain the inverse transformation, we use the following observation.

Observation:

  1. The affine transformation is invertible if the coefficient of var in this transformation (i.e. $a_\mathrm{var}$) is different from zero.
  2. If the transformation is invertible, then we can write

    \[ \mathrm{denominator} * {x'}_\mathrm{var} = \sum_{i = 0}^{n - 1} a_i x_i + b = a_\mathrm{var} x_\mathrm{var} + \sum_{i \neq \mathrm{var}} a_i x_i + b, \]

    , the inverse transformation is

    \[ a_\mathrm{var} x_\mathrm{var} = \mathrm{denominator} * {x'}_\mathrm{var} - \sum_{i \neq j} a_i x_i - b. \]

    .

Then, if the transformation is invertible, all the entities that were up-to-date remain up-to-date. Otherwise only constraints remain up-to-date.

In other words, if $A$ is a $m \times n$ matrix representing the constraints of the polyhedron, $T$ is the affine transformation to apply to $P$ and

\[ P = \bigl\{\, \vect{x} = (x_0, \ldots, x_{n-1})^\mathrm{T} \bigm| A\vect{x} \geq \vect{0} \,\bigr\}. \]

The resulting polyhedron is

\[ P' = \bigl\{\, \vect{x} = (x_0, \ldots, x_{n-1}))^\mathrm{T} \bigm| A'\vect{x} \geq \vect{0} \,\bigr\}, \]

where $A'$ is defined as follows:

\[ {a'}_{ij} = \begin{cases} a_{ij} * \mathrm{denominator} + a_{i\mathrm{var}}*\mathrm{expr}[j] \quad \mathrm{for } j \neq \mathrm{var}; \\ \mathrm{expr}[\mathrm{var}] * a_{i\mathrm{var}}, \quad \text{for } j = \mathrm{var}. \end{cases} \]

Definition at line 2833 of file Polyhedron_public.cc.

References c, Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::inverse(), Parma_Polyhedra_Library::Linear_Expression::set_coefficient(), Parma_Polyhedra_Library::Variable::space_dimension(), and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

2835  {
2836  // The denominator cannot be zero.
2837  if (denominator == 0) {
2838  throw_invalid_argument("affine_preimage(v, e, d)", "d == 0");
2839  }
2840 
2841  // Dimension-compatibility checks.
2842  // The dimension of `expr' should not be greater than the dimension
2843  // of `*this'.
2844  if (space_dim < expr.space_dimension()) {
2845  throw_dimension_incompatible("affine_preimage(v, e, d)", "e", expr);
2846  // `var' should be one of the dimensions of the polyhedron.
2847  }
2848  const dimension_type var_space_dim = var.space_dimension();
2849  if (space_dim < var_space_dim) {
2850  throw_dimension_incompatible("affine_preimage(v, e, d)", "v", var);
2851  }
2852 
2853  if (marked_empty()) {
2854  return;
2855  }
2856 
2857  if (expr.coefficient(var) != 0) {
2858  // The transformation is invertible:
2859  // minimality and saturators are preserved.
2861  // Constraint_System::affine_preimage() requires the third argument
2862  // to be a positive Coefficient.
2863  if (denominator > 0) {
2864  con_sys.affine_preimage(var, expr, denominator);
2865  }
2866  else {
2867  con_sys.affine_preimage(var, -expr, -denominator);
2868  }
2869  }
2870  if (generators_are_up_to_date()) {
2871  // To build the inverse transformation,
2872  // after copying and negating `expr',
2873  // we exchange the roles of `expr[var_space_dim]' and `denominator'.
2875  Coefficient_traits::const_reference c = expr.coefficient(var);
2876  if (c > 0) {
2877  inverse = -expr;
2878  inverse.set_coefficient(var, denominator);
2879  gen_sys.affine_image(var, inverse, c);
2880  }
2881  else {
2882  // The new denominator is negative:
2883  // we negate everything once more, as Generator_System::affine_image()
2884  // requires the third argument to be positive.
2885  inverse = expr;
2886  inverse.set_coefficient(var, -denominator);
2887  gen_sys.affine_image(var, inverse, -c);
2888  }
2889  }
2890  }
2891  else {
2892  // The transformation is not invertible.
2893  // We need an up-to-date system of constraints.
2894  if (has_something_pending()) {
2896  }
2897  else if (!constraints_are_up_to_date()) {
2898  minimize();
2899  }
2900  // Constraint_System::affine_preimage() requires the third argument
2901  // to be a positive Coefficient.
2902  if (denominator > 0) {
2903  con_sys.affine_preimage(var, expr, denominator);
2904  }
2905  else {
2906  con_sys.affine_preimage(var, -expr, -denominator);
2907  }
2908  // Generators, minimality and saturators are no longer valid.
2913  }
2914  PPL_ASSERT_HEAVY(OK());
2915 }
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
bool minimize() const
Applies (weak) minimization to both the constraints and generators.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void set_coefficient(Variable v, Coefficient_traits::const_reference n)
Sets the coefficient of v in *this to n.
Coefficient_traits::const_reference coefficient(Variable v) const
Returns the coefficient of v in *this.
Rounding_Dir inverse(Rounding_Dir dir)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
void throw_invalid_argument(const char *method, const char *reason) const
Constraint_System con_sys
The system of constraints.
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
void remove_pending_to_obtain_constraints() const
Lazily integrates the pending descriptions of the polyhedron to obtain a constraint system without pe...
dimension_type space_dim
The number of dimensions of the enclosing vector space.
void clear_sat_g_up_to_date()
Sets status to express that sat_g is no longer up-to-date.
void affine_preimage(Variable v, const Linear_Expression &expr, Coefficient_traits::const_reference denominator)
Substitutes a given column of coefficients by a given affine expression.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
void clear_constraints_minimized()
Sets status to express that constraints are no longer minimized.
void clear_sat_c_up_to_date()
Sets status to express that sat_c is no longer up-to-date.
Coefficient c
Definition: PIP_Tree.cc:64
void clear_generators_up_to_date()
Sets status to express that generators are no longer up-to-date.
void affine_image(Variable v, const Linear_Expression &expr, Coefficient_traits::const_reference denominator)
Assigns to a given variable an affine expression.
bool has_something_pending() const
Returns true if there are either pending constraints or pending generators.
void Parma_Polyhedra_Library::Polyhedron::ascii_dump ( ) const

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

void Parma_Polyhedra_Library::Polyhedron::ascii_dump ( std::ostream &  s) const

Writes to s an ASCII representation of *this.

Definition at line 3965 of file Polyhedron_public.cc.

3965  {
3966  s << "space_dim " << space_dim << "\n";
3967  status.ascii_dump(s);
3968  s << "\ncon_sys ("
3969  << (constraints_are_up_to_date() ? "" : "not_")
3970  << "up-to-date)"
3971  << "\n";
3972  con_sys.ascii_dump(s);
3973  s << "\ngen_sys ("
3974  << (generators_are_up_to_date() ? "" : "not_")
3975  << "up-to-date)"
3976  << "\n";
3977  gen_sys.ascii_dump(s);
3978  s << "\nsat_c\n";
3979  sat_c.ascii_dump(s);
3980  s << "\nsat_g\n";
3981  sat_g.ascii_dump(s);
3982  s << "\n";
3983 }
Generator_System gen_sys
The system of generators.
void ascii_dump() const
Writes to std::cerr an ASCII representation of *this.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
Constraint_System con_sys
The system of constraints.
void ascii_dump() const
Writes to std::cerr an ASCII representation of *this.
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
Bit_Matrix sat_g
The saturation matrix having generators on its columns.
Status status
The status flags to keep track of the polyhedron's internal state.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
Bit_Matrix sat_c
The saturation matrix having constraints on its columns.
void ascii_dump() const
Writes to std::cerr an ASCII representation of *this.
void ascii_dump() const
Writes to std::cerr an ASCII representation of *this.
bool Parma_Polyhedra_Library::Polyhedron::ascii_load ( std::istream &  s)

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

Definition at line 3988 of file Polyhedron_public.cc.

3988  {
3989  std::string str;
3990 
3991  if (!(s >> str) || str != "space_dim") {
3992  return false;
3993  }
3994 
3995  if (!(s >> space_dim)) {
3996  return false;
3997  }
3998 
3999  if (!status.ascii_load(s)) {
4000  return false;
4001  }
4002 
4003  if (!(s >> str) || str != "con_sys") {
4004  return false;
4005  }
4006 
4007  if (!(s >> str) || (str != "(not_up-to-date)" && str != "(up-to-date)")) {
4008  return false;
4009  }
4010 
4011  if (!con_sys.ascii_load(s)) {
4012  return false;
4013  }
4014 
4015  if (!(s >> str) || str != "gen_sys") {
4016  return false;
4017  }
4018 
4019  if (!(s >> str) || (str != "(not_up-to-date)" && str != "(up-to-date)")) {
4020  return false;
4021  }
4022 
4023  if (!gen_sys.ascii_load(s)) {
4024  return false;
4025  }
4026 
4027  if (!(s >> str) || str != "sat_c") {
4028  return false;
4029  }
4030 
4031  if (!sat_c.ascii_load(s)) {
4032  return false;
4033  }
4034 
4035  if (!(s >> str) || str != "sat_g") {
4036  return false;
4037  }
4038 
4039  if (!sat_g.ascii_load(s)) {
4040  return false;
4041  }
4042 
4043  // Check invariants.
4044  PPL_ASSERT_HEAVY(OK());
4045  return true;
4046 }
bool ascii_load(std::istream &s)
Loads from s an ASCII representation (as produced by ascii_dump(std::ostream&) const) and sets *this ...
Definition: Bit_Matrix.cc:189
Generator_System gen_sys
The system of generators.
Constraint_System con_sys
The system of constraints.
bool ascii_load(std::istream &s)
Loads from s an ASCII representation (as produced by ascii_dump(std::ostream&) const) and sets *this ...
bool ascii_load(std::istream &s)
Loads from s an ASCII representation (as produced by ascii_dump(std::ostream&) const) and sets *this ...
Definition: Ph_Status.cc:88
Bit_Matrix sat_g
The saturation matrix having generators on its columns.
Status status
The status flags to keep track of the polyhedron's internal state.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
bool ascii_load(std::istream &s)
Loads from s an ASCII representation (as produced by ascii_dump(std::ostream&) const) and sets *this ...
Bit_Matrix sat_c
The saturation matrix having constraints on its columns.
bool Parma_Polyhedra_Library::Polyhedron::BFT00_poly_hull_assign_if_exact ( const Polyhedron y)
protected

If the poly-hull of *this and y is exact it is assigned to *this and true is returned, otherwise false is returned.

Current implementation is based on (a variant of) Algorithm 8.1 in A. Bemporad, K. Fukuda, and F. D. Torrisi Convexity Recognition of the Union of Polyhedra Technical Report AUT00-13, ETH Zurich, 2000

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

Definition at line 2024 of file Polyhedron_nonpublic.cc.

References Parma_Polyhedra_Library::Linear_Expression::all_homogeneous_terms_are_zero(), con_sys, Parma_Polyhedra_Library::Generator::expr, gen_sys, Parma_Polyhedra_Library::Poly_Con_Relation::implies(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), is_empty(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Generator::is_line_or_equality(), is_necessarily_closed(), marked_empty(), minimize(), Parma_Polyhedra_Library::Linear_Expression::normalize(), Parma_Polyhedra_Library::Poly_Gen_Relation::nothing(), Parma_Polyhedra_Library::Generator_System::num_rows(), Parma_Polyhedra_Library::Constraint_System::num_rows(), Parma_Polyhedra_Library::Generator::OK(), relation_with(), Parma_Polyhedra_Library::Generator::set_is_ray_or_point_or_inequality(), Parma_Polyhedra_Library::Generator::sign_normalize(), space_dim, Parma_Polyhedra_Library::Poly_Gen_Relation::subsumes(), topology(), and Parma_Polyhedra_Library::upper_bound_assign().

2024  {
2025  // Declare a const reference to *this (to avoid accidental modifications).
2026  const Polyhedron& x = *this;
2027  // Private method: the caller must ensure the following.
2028  PPL_ASSERT(x.is_necessarily_closed());
2029  PPL_ASSERT(x.topology() == y.topology());
2030  PPL_ASSERT(x.space_dim == y.space_dim);
2031 
2032  // The zero-dim case is trivial.
2033  if (x.space_dim == 0) {
2034  upper_bound_assign(y);
2035  return true;
2036  }
2037  // If `x' or `y' is (known to be) empty, the convex union is exact.
2038  if (x.marked_empty()) {
2039  *this = y;
2040  return true;
2041  }
2042  else if (y.is_empty()) {
2043  return true;
2044  }
2045  else if (x.is_empty()) {
2046  *this = y;
2047  return true;
2048  }
2049 
2050  // Here both `x' and `y' are known to be non-empty.
2051 
2052  // Implementation based on Algorithm 8.1 (page 15) in [BemporadFT00TR],
2053  // generalized so as to also allow for unbounded polyhedra.
2054  // The extension to unbounded polyhedra is obtained by mimicking
2055  // what done in Algorithm 8.2 (page 19) with respect to
2056  // Algorithm 6.2 (page 13).
2057  // We also apply a couple of improvements (see steps 2.1, 3.1, 6.1, 7.1)
2058  // so as to quickly handle special cases and avoid the splitting
2059  // of equalities/lines into pairs of inequalities/rays.
2060 
2061  (void) x.minimize();
2062  (void) y.minimize();
2063  const Constraint_System& x_cs = x.con_sys;
2064  const Constraint_System& y_cs = y.con_sys;
2065  const Generator_System& x_gs = x.gen_sys;
2066  const Generator_System& y_gs = y.gen_sys;
2067  const dimension_type x_gs_num_rows = x_gs.num_rows();
2068  const dimension_type y_gs_num_rows = y_gs.num_rows();
2069 
2070  // Step 1: generators of `x' that are redundant in `y', and vice versa.
2071  std::vector<bool> x_gs_red_in_y(x_gs_num_rows, false);
2072  dimension_type num_x_gs_red_in_y = 0;
2073  for (dimension_type i = x_gs_num_rows; i-- > 0; ) {
2074  if (y.relation_with(x_gs[i]).implies(Poly_Gen_Relation::subsumes())) {
2075  x_gs_red_in_y[i] = true;
2076  ++num_x_gs_red_in_y;
2077  }
2078  }
2079  std::vector<bool> y_gs_red_in_x(y_gs_num_rows, false);
2080  dimension_type num_y_gs_red_in_x = 0;
2081  for (dimension_type i = y_gs_num_rows; i-- > 0; ) {
2082  if (x.relation_with(y_gs[i]).implies(Poly_Gen_Relation::subsumes())) {
2083  y_gs_red_in_x[i] = true;
2084  ++num_y_gs_red_in_x;
2085  }
2086  }
2087 
2088  // Step 2: if no redundant generator has been identified,
2089  // then the union is not convex. CHECKME: why?
2090  if (num_x_gs_red_in_y == 0 && num_y_gs_red_in_x == 0) {
2091  return false;
2092  }
2093 
2094  // Step 2.1: while at it, also perform quick inclusion tests.
2095  if (num_y_gs_red_in_x == y_gs_num_rows) {
2096  // `y' is included into `x': union is convex.
2097  return true;
2098  }
2099  if (num_x_gs_red_in_y == x_gs_num_rows) {
2100  // `x' is included into `y': union is convex.
2101  *this = y;
2102  return true;
2103  }
2104 
2105  // Here we know that `x' is not included in `y', and vice versa.
2106 
2107  // Step 3: constraints of `x' that are satisfied by `y', and vice versa.
2108  const dimension_type x_cs_num_rows = x_cs.num_rows();
2109  std::vector<bool> x_cs_red_in_y(x_cs_num_rows, false);
2110  for (dimension_type i = x_cs_num_rows; i-- > 0; ) {
2111  const Constraint& x_cs_i = x_cs[i];
2112  if (y.relation_with(x_cs_i).implies(Poly_Con_Relation::is_included())) {
2113  x_cs_red_in_y[i] = true;
2114  }
2115  else if (x_cs_i.is_equality()) {
2116  // Step 3.1: `x' has an equality not satisfied by `y':
2117  // union is not convex (recall that `y' does not contain `x').
2118  // NOTE: this would be false for NNC polyhedra.
2119  // Example: x = { A == 0 }, y = { 0 < A <= 1 }.
2120  return false;
2121  }
2122  }
2123  const dimension_type y_cs_num_rows = y_cs.num_rows();
2124  std::vector<bool> y_cs_red_in_x(y_cs_num_rows, false);
2125  for (dimension_type i = y_cs_num_rows; i-- > 0; ) {
2126  const Constraint& y_cs_i = y_cs[i];
2127  if (x.relation_with(y_cs_i).implies(Poly_Con_Relation::is_included())) {
2128  y_cs_red_in_x[i] = true;
2129  }
2130  else if (y_cs_i.is_equality()) {
2131  // Step 3.1: `y' has an equality not satisfied by `x':
2132  // union is not convex (see explanation above).
2133  return false;
2134  }
2135  }
2136 
2137  // Loop in steps 5-9: for each pair of non-redundant generators,
2138  // compute their "mid-point" and check if it is both in `x' and `y'.
2139 
2140  // Note: reasoning at the polyhedral cone level.
2141  Generator mid_g;
2142 
2143  for (dimension_type i = x_gs_num_rows; i-- > 0; ) {
2144  if (x_gs_red_in_y[i]) {
2145  continue;
2146  }
2147  const Generator& x_g = x_gs[i];
2148  const bool x_g_is_line = x_g.is_line_or_equality();
2149  for (dimension_type j = y_gs_num_rows; j-- > 0; ) {
2150  if (y_gs_red_in_x[j]) {
2151  continue;
2152  }
2153  const Generator& y_g = y_gs[j];
2154  const bool y_g_is_line = y_g.is_line_or_equality();
2155 
2156  // Step 6: compute mid_g = x_g + y_g.
2157  // NOTE: no need to actually compute the "mid-point",
2158  // since any strictly positive combination would do.
2159  mid_g = x_g;
2160  mid_g.expr += y_g.expr;
2161  // A zero ray is not a well formed generator.
2162  const bool illegal_ray
2163  = (mid_g.expr.inhomogeneous_term() == 0 && mid_g.expr.all_homogeneous_terms_are_zero());
2164  // A zero ray cannot be generated from a line: this holds
2165  // because x_row (resp., y_row) is not subsumed by y (resp., x).
2166  PPL_ASSERT(!(illegal_ray && (x_g_is_line || y_g_is_line)));
2167  if (illegal_ray) {
2168  continue;
2169  }
2170  mid_g.expr.normalize();
2171  if (x_g_is_line) {
2172  if (y_g_is_line) {
2173  // mid_row is a line too: sign normalization is needed.
2174  mid_g.sign_normalize();
2175  }
2176  else {
2177  // mid_row is a ray/point.
2178  mid_g.set_is_ray_or_point_or_inequality();
2179  }
2180  }
2181  PPL_ASSERT(mid_g.OK());
2182 
2183  // Step 7: check if mid_g is in the union of x and y.
2184  if (x.relation_with(mid_g) == Poly_Gen_Relation::nothing()
2185  && y.relation_with(mid_g) == Poly_Gen_Relation::nothing()) {
2186  return false;
2187  }
2188  // If either x_g or y_g is a line, we should use its
2189  // negation to produce another generator to be tested too.
2190  // NOTE: exclusive-or is meant.
2191  if (!x_g_is_line && y_g_is_line) {
2192  // Step 6.1: (re-)compute mid_row = x_g - y_g.
2193  mid_g = x_g;
2194  mid_g.expr -= y_g.expr;
2195  mid_g.expr.normalize();
2196  PPL_ASSERT(mid_g.OK());
2197  // Step 7.1: check if mid_g is in the union of x and y.
2198  if (x.relation_with(mid_g) == Poly_Gen_Relation::nothing()
2199  && y.relation_with(mid_g) == Poly_Gen_Relation::nothing()) {
2200  return false;
2201  }
2202  }
2203  else if (x_g_is_line && !y_g_is_line) {
2204  // Step 6.1: (re-)compute mid_row = - x_row + y_row.
2205  mid_g = y_g;
2206  mid_g.expr -= x_g.expr;
2207  mid_g.expr.normalize();
2208  PPL_ASSERT(mid_g.OK());
2209  // Step 7.1: check if mid_g is in the union of x and y.
2210  if (x.relation_with(mid_g) == Poly_Gen_Relation::nothing()
2211  && y.relation_with(mid_g) == Poly_Gen_Relation::nothing()) {
2212  return false;
2213  }
2214  }
2215  }
2216  }
2217 
2218  // Here we know that the union of x and y is convex.
2219  // TODO: exploit knowledge on the cardinality of non-redundant
2220  // constraints/generators to improve the convex-hull computation.
2221  // Using generators allows for exploiting incrementality.
2222  for (dimension_type j = 0; j < y_gs_num_rows; ++j) {
2223  if (!y_gs_red_in_x[j]) {
2224  add_generator(y_gs[j]);
2225  }
2226  }
2227  PPL_ASSERT_HEAVY(OK());
2228  return true;
2229 }
static Poly_Gen_Relation subsumes()
Adding the generator would not change the polyhedron.
size_t dimension_type
An unsigned integral type for representing space dimensions.
static Poly_Con_Relation is_included()
The polyhedron is included in the set of points satisfying the constraint.
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
void add_generator(const Generator &g)
Adds a copy of generator g to the system of generators of *this (without minimizing the result)...
void upper_bound_assign(const Polyhedron &y)
Same as poly_hull_assign(y).
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
static Poly_Gen_Relation nothing()
The assertion that says nothing.
bool Parma_Polyhedra_Library::Polyhedron::BHRZ03_combining_constraints ( const Polyhedron y,
const BHRZ03_Certificate y_cert,
const Polyhedron H79,
const Constraint_System x_minus_H79_cs 
)
private

Definition at line 399 of file Polyhedron_widenings.cc.

References add_recycled_constraints(), Parma_Polyhedra_Library::Linear_Expression::all_homogeneous_terms_are_zero(), c, Parma_Polyhedra_Library::Constraint_System::clear(), con_sys, constraints_are_minimized(), contains(), gen_sys, generators_are_minimized(), has_something_pending(), Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::Generator::is_closure_point(), Parma_Polyhedra_Library::Constraint::is_inequality(), is_necessarily_closed(), Parma_Polyhedra_Library::Generator::is_point(), Parma_Polyhedra_Library::BHRZ03_Certificate::is_stabilizing(), m_swap(), marked_empty(), minimize(), Parma_Polyhedra_Library::Generator_System::num_rows(), Parma_Polyhedra_Library::Constraint_System::num_rows(), OK(), relation_with(), Parma_Polyhedra_Library::Scalar_Products::sign(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), Parma_Polyhedra_Library::Poly_Con_Relation::strictly_intersects(), Parma_Polyhedra_Library::Constraint_System::topology(), and topology().

Referenced by BHRZ03_widening_assign().

402  {
403  Polyhedron& x = *this;
404  // It is assumed that `y <= x <= H79'.
405  PPL_ASSERT(x.topology() == y.topology()
406  && x.topology() == H79.topology()
407  && x.topology() == x_minus_H79_cs.topology());
408  PPL_ASSERT(x.space_dim == y.space_dim
409  && x.space_dim == H79.space_dim
410  && x.space_dim == x_minus_H79_cs.space_dimension());
411  PPL_ASSERT(!x.marked_empty() && !x.has_something_pending()
412  && x.constraints_are_minimized() && x.generators_are_minimized());
413  PPL_ASSERT(!y.marked_empty() && !y.has_something_pending()
414  && y.constraints_are_minimized() && y.generators_are_minimized());
415  PPL_ASSERT(!H79.marked_empty() && !H79.has_something_pending()
416  && H79.constraints_are_minimized() && H79.generators_are_minimized());
417 
418  // We will choose from `x_minus_H79_cs' many subsets of constraints,
419  // that will be collected (one at a time) in `combining_cs'.
420  // For each group collected, we compute an average constraint,
421  // that will be stored in `new_cs'.
422 
423  // There is no point in applying this technique when `x_minus_H79_cs'
424  // has one constraint at most (no ``new'' constraint can be computed).
425  const dimension_type x_minus_H79_cs_num_rows = x_minus_H79_cs.num_rows();
426  if (x_minus_H79_cs_num_rows <= 1) {
427  return false;
428  }
429 
430  const Topology topol = x.topology();
431  Constraint_System combining_cs(topol);
432  Constraint_System new_cs(topol);
433 
434  // Consider the points that belong to both `x.gen_sys' and `y.gen_sys'.
435  // For NNC polyhedra, the role of points is played by closure points.
436  const bool closed = x.is_necessarily_closed();
437  for (dimension_type i = y.gen_sys.num_rows(); i-- > 0; ) {
438  const Generator& g = y.gen_sys[i];
439  if ((g.is_point() && closed) || (g.is_closure_point() && !closed)) {
440  // If in `H79.con_sys' there is already an inequality constraint
441  // saturating this point, then there is no need to produce another
442  // constraint.
443  bool lies_on_the_boundary_of_H79 = false;
444  const Constraint_System& H79_cs = H79.con_sys;
445  for (dimension_type j = H79_cs.num_rows(); j-- > 0; ) {
446  const Constraint& c = H79_cs[j];
447  if (c.is_inequality() && Scalar_Products::sign(c, g) == 0) {
448  lies_on_the_boundary_of_H79 = true;
449  break;
450  }
451  }
452  if (lies_on_the_boundary_of_H79) {
453  continue;
454  }
455 
456  // Consider all the constraints in `x_minus_H79_cs'
457  // that are saturated by the point `g'.
458  combining_cs.clear();
459  for (dimension_type j = x_minus_H79_cs_num_rows; j-- > 0; ) {
460  const Constraint& c = x_minus_H79_cs[j];
461  if (Scalar_Products::sign(c, g) == 0) {
462  combining_cs.insert(c);
463  }
464  }
465  // Build a new constraint by combining all the chosen constraints.
466  const dimension_type combining_cs_num_rows = combining_cs.num_rows();
467  if (combining_cs_num_rows > 0) {
468  if (combining_cs_num_rows == 1) {
469  // No combination is needed.
470  new_cs.insert(combining_cs[0]);
471  }
472  else {
473  Linear_Expression e(0);
474  bool strict_inequality = false;
475  for (dimension_type h = combining_cs_num_rows; h-- > 0; ) {
476  if (combining_cs[h].is_strict_inequality()) {
477  strict_inequality = true;
478  }
479  e += Linear_Expression(combining_cs[h].expression());
480  }
481 
482  if (!e.all_homogeneous_terms_are_zero()) {
483  if (strict_inequality) {
484  new_cs.insert(e > 0);
485  }
486  else {
487  new_cs.insert(e >= 0);
488  }
489  }
490  }
491  }
492  }
493  }
494 
495  // If none of the collected constraints strictly intersects `H79',
496  // then the technique was unsuccessful.
497  bool improves_upon_H79 = false;
498  const Poly_Con_Relation si = Poly_Con_Relation::strictly_intersects();
499  for (dimension_type i = new_cs.num_rows(); i-- > 0; ) {
500  if (H79.relation_with(new_cs[i]) == si) {
501  improves_upon_H79 = true;
502  break;
503  }
504  }
505  if (!improves_upon_H79) {
506  return false;
507  }
508 
509  // The resulting polyhedron is obtained by adding the constraints
510  // in `new_cs' to polyhedron `H79'.
511  Polyhedron result = H79;
512  result.add_recycled_constraints(new_cs);
513  // Force minimization.
514  result.minimize();
515 
516  // Check for stabilization with respect to `y_cert' and improvement
517  // over `H79'.
518  if (y_cert.is_stabilizing(result) && !result.contains(H79)) {
519  // The technique was successful.
520  x.m_swap(result);
521  PPL_ASSERT_HEAVY(x.OK(true));
522  return true;
523  }
524  else {
525  // The technique was unsuccessful.
526  return false;
527  }
528 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
static int sign(const Linear_Expression &x, const Linear_Expression &y)
Returns the sign of the scalar product between x and y.
Coefficient c
Definition: PIP_Tree.cc:64
static Poly_Con_Relation strictly_intersects()
The polyhedron intersects the set of points satisfying the constraint, but it is not included in it...
Topology
Kinds of polyhedra domains.
bool Parma_Polyhedra_Library::Polyhedron::BHRZ03_evolving_points ( const Polyhedron y,
const BHRZ03_Certificate y_cert,
const Polyhedron H79 
)
private

Definition at line 531 of file Polyhedron_widenings.cc.

References add_recycled_generators(), Parma_Polyhedra_Library::compare(), constraints_are_minimized(), contains(), gen_sys, generators_are_minimized(), has_something_pending(), intersection_assign(), Parma_Polyhedra_Library::Generator::is_closure_point(), is_necessarily_closed(), Parma_Polyhedra_Library::Generator::is_point(), Parma_Polyhedra_Library::BHRZ03_Certificate::is_stabilizing(), Parma_Polyhedra_Library::Generator::linear_combine(), m_swap(), marked_empty(), minimize(), Parma_Polyhedra_Library::Poly_Gen_Relation::nothing(), Parma_Polyhedra_Library::Generator_System::num_rows(), OK(), relation_with(), space_dim, and topology().

Referenced by BHRZ03_widening_assign().

533  {
534  Polyhedron& x = *this;
535  // It is assumed that `y <= x <= H79'.
536  PPL_ASSERT(x.topology() == y.topology()
537  && x.topology() == H79.topology());
538  PPL_ASSERT(x.space_dim == y.space_dim
539  && x.space_dim == H79.space_dim);
540  PPL_ASSERT(!x.marked_empty() && !x.has_something_pending()
541  && x.constraints_are_minimized() && x.generators_are_minimized());
542  PPL_ASSERT(!y.marked_empty() && !y.has_something_pending()
543  && y.constraints_are_minimized() && y.generators_are_minimized());
544  PPL_ASSERT(!H79.marked_empty() && !H79.has_something_pending()
545  && H79.constraints_are_minimized() && H79.generators_are_minimized());
546 
547  // For each point in `x.gen_sys' that is not in `y',
548  // this technique tries to identify a set of rays that:
549  // - are included in polyhedron `H79';
550  // - when added to `y' will subsume the point.
551  Generator_System candidate_rays;
552 
553  const dimension_type x_gen_sys_num_rows = x.gen_sys.num_rows();
554  const dimension_type y_gen_sys_num_rows = y.gen_sys.num_rows();
555  const bool closed = x.is_necessarily_closed();
556  for (dimension_type i = x_gen_sys_num_rows; i-- > 0; ) {
557  const Generator& g1 = x.gen_sys[i];
558  // For C polyhedra, we choose a point of `x.gen_sys'
559  // that is not included in `y'.
560  // In the case of NNC polyhedra, we can restrict attention to
561  // closure points (considering also points will only add redundancy).
562  if (((g1.is_point() && closed) || (g1.is_closure_point() && !closed))
563  && y.relation_with(g1) == Poly_Gen_Relation::nothing()) {
564  // For each point (resp., closure point) `g2' in `y.gen_sys',
565  // where `g1' and `g2' are different,
566  // build the candidate ray `g1 - g2'.
567  for (dimension_type j = y_gen_sys_num_rows; j-- > 0; ) {
568  const Generator& g2 = y.gen_sys[j];
569  if ((g2.is_point() && closed)
570  || (g2.is_closure_point() && !closed)) {
571  PPL_ASSERT(compare(g1, g2) != 0);
572  Generator ray_from_g2_to_g1 = g1;
573  ray_from_g2_to_g1.linear_combine(g2, 0);
574  candidate_rays.insert(ray_from_g2_to_g1);
575  }
576  }
577  }
578  }
579 
580  // Be non-intrusive.
581  Polyhedron result = x;
582  result.add_recycled_generators(candidate_rays);
583  result.intersection_assign(H79);
584  // Force minimization.
585  result.minimize();
586 
587  // Check for stabilization with respect to `y_cert' and improvement
588  // over `H79'.
589  if (y_cert.is_stabilizing(result) && !result.contains(H79)) {
590  // The technique was successful.
591  x.m_swap(result);
592  PPL_ASSERT_HEAVY(x.OK(true));
593  return true;
594  }
595  else {
596  // The technique was unsuccessful.
597  return false;
598  }
599 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
int compare(const Linear_Expression &x, const Linear_Expression &y)
static Poly_Gen_Relation nothing()
The assertion that says nothing.
bool Parma_Polyhedra_Library::Polyhedron::BHRZ03_evolving_rays ( const Polyhedron y,
const BHRZ03_Certificate y_cert,
const Polyhedron H79 
)
private

Definition at line 679 of file Polyhedron_widenings.cc.

References add_recycled_generators(), constraints_are_minimized(), contains(), Parma_Polyhedra_Library::Generator::expr, gen_sys, generators_are_minimized(), Parma_Polyhedra_Library::Generator_System::has_no_rows(), has_something_pending(), Parma_Polyhedra_Library::Generator_System::insert(), intersection_assign(), Parma_Polyhedra_Library::Generator::is_ray(), Parma_Polyhedra_Library::BHRZ03_Certificate::is_stabilizing(), m_swap(), marked_empty(), minimize(), Parma_Polyhedra_Library::Poly_Gen_Relation::nothing(), Parma_Polyhedra_Library::Generator_System::num_rows(), Parma_Polyhedra_Library::Generator::OK(), OK(), relation_with(), space_dim, and topology().

Referenced by BHRZ03_widening_assign().

681  {
682  Polyhedron& x = *this;
683  // It is assumed that `y <= x <= H79'.
684  PPL_ASSERT(x.topology() == y.topology()
685  && x.topology() == H79.topology());
686  PPL_ASSERT(x.space_dim == y.space_dim
687  && x.space_dim == H79.space_dim);
688  PPL_ASSERT(!x.marked_empty() && !x.has_something_pending()
689  && x.constraints_are_minimized() && x.generators_are_minimized());
690  PPL_ASSERT(!y.marked_empty() && !y.has_something_pending()
691  && y.constraints_are_minimized() && y.generators_are_minimized());
692  PPL_ASSERT(!H79.marked_empty() && !H79.has_something_pending()
693  && H79.constraints_are_minimized() && H79.generators_are_minimized());
694 
695  const dimension_type x_gen_sys_num_rows = x.gen_sys.num_rows();
696  const dimension_type y_gen_sys_num_rows = y.gen_sys.num_rows();
697 
698  // Candidate rays are kept in a temporary generator system.
699  Generator_System candidate_rays;
700  for (dimension_type i = x_gen_sys_num_rows; i-- > 0; ) {
701  const Generator& x_g = x.gen_sys[i];
702  // We choose a ray of `x' that does not belong to `y'.
703  if (x_g.is_ray() && y.relation_with(x_g) == Poly_Gen_Relation::nothing()) {
704  for (dimension_type j = y_gen_sys_num_rows; j-- > 0; ) {
705  const Generator& y_g = y.gen_sys[j];
706  if (y_g.is_ray()) {
707  Generator new_ray(x_g);
708  // Modify `new_ray' according to the evolution of `x_g' with
709  // respect to `y_g'.
710  modify_according_to_evolution(new_ray.expr, x_g.expr, y_g.expr);
711  PPL_ASSERT(new_ray.OK());
712  candidate_rays.insert(new_ray);
713  }
714  }
715  }
716  }
717 
718  // If there are no candidate rays, we cannot obtain stabilization.
719  if (candidate_rays.has_no_rows()) {
720  return false;
721  }
722 
723  // Be non-intrusive.
724  Polyhedron result = x;
725  result.add_recycled_generators(candidate_rays);
726  result.intersection_assign(H79);
727  // Force minimization.
728  result.minimize();
729 
730  // Check for stabilization with respect to `y' and improvement over `H79'.
731  if (y_cert.is_stabilizing(result) && !result.contains(H79)) {
732  // The technique was successful.
733  x.m_swap(result);
734  PPL_ASSERT_HEAVY(x.OK(true));
735  return true;
736  }
737  else {
738  // The technique was unsuccessful.
739  return false;
740  }
741 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
static void modify_according_to_evolution(Linear_Expression &ray, const Linear_Expression &x, const Linear_Expression &y)
static Poly_Gen_Relation nothing()
The assertion that says nothing.
void Parma_Polyhedra_Library::Polyhedron::BHRZ03_widening_assign ( const Polyhedron y,
unsigned *  tp = 0 
)

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

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

Definition at line 744 of file Polyhedron_widenings.cc.

References BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), contains(), Parma_Polyhedra_Library::Constraint_System::has_no_rows(), Parma_Polyhedra_Library::BHRZ03_Certificate::is_stabilizing(), m_swap(), marked_empty(), minimize(), OK(), select_H79_constraints(), space_dim, topology(), and Parma_Polyhedra_Library::UNIVERSE.

Referenced by limited_BHRZ03_extrapolation_assign().

744  {
745  Polyhedron& x = *this;
746  // Topology compatibility check.
747  if (x.topology() != y.topology()) {
748  throw_topology_incompatible("BHRZ03_widening_assign(y)", "y", y);
749  }
750  // Dimension-compatibility check.
751  if (x.space_dim != y.space_dim) {
752  throw_dimension_incompatible("BHRZ03_widening_assign(y)", "y", y);
753  }
754 
755  // Assume `y' is contained in or equal to `x'.
756  PPL_EXPECT_HEAVY(copy_contains(x, y));
757 
758  // If any argument is zero-dimensional or empty,
759  // the BHRZ03-widening behaves as the identity function.
760  if (x.space_dim == 0 || x.marked_empty() || y.marked_empty()) {
761  return;
762  }
763 
764  // `y.con_sys' and `y.gen_sys' should be in minimal form.
765  if (!y.minimize()) {
766  // `y' is empty: the result is `x'.
767  return;
768  }
769  // `x.con_sys' and `x.gen_sys' should be in minimal form.
770  x.minimize();
771 
772  // Compute certificate info for polyhedron `y'.
773  const BHRZ03_Certificate y_cert(y);
774 
775  // If the iteration is stabilizing, the resulting polyhedron is `x'.
776  // At this point, also check if the two polyhedra are the same
777  // (exploiting the knowledge that `y <= x').
778  if (y_cert.is_stabilizing(x) || y.contains(x)) {
779  PPL_ASSERT_HEAVY(OK());
780  return;
781  }
782 
783  // Here the iteration is not immediately stabilizing.
784  // If we are using the widening-with-tokens technique and
785  // there are tokens available, use one of them and return `x'.
786  if (tp != 0 && *tp > 0) {
787  --(*tp);
788  PPL_ASSERT_HEAVY(OK());
789  return;
790  }
791 
792  // Copy into `H79_cs' the constraints that are common to `x' and `y',
793  // according to the definition of the H79 widening.
794  // The other ones are copied into `x_minus_H79_cs'.
795  const Topology topol = x.topology();
796  Constraint_System H79_cs(topol);
797  Constraint_System x_minus_H79_cs(topol);
798  x.select_H79_constraints(y, H79_cs, x_minus_H79_cs);
799 
800  // We cannot have selected all of the rows, since otherwise
801  // the iteration should have been immediately stabilizing.
802  PPL_ASSERT(!x_minus_H79_cs.has_no_rows());
803  // Be careful to obtain the right space dimension
804  // (because `H79_cs' may be empty).
805  Polyhedron H79(topol, x.space_dim, UNIVERSE);
806  H79.add_recycled_constraints(H79_cs);
807  // Force minimization.
808  H79.minimize();
809 
810  // NOTE: none of the following widening heuristics is intrusive:
811  // they will modify `x' only when returning successfully.
812  if (x.BHRZ03_combining_constraints(y, y_cert, H79, x_minus_H79_cs)) {
813  return;
814  }
815 
816  PPL_ASSERT_HEAVY(H79.OK() && x.OK() && y.OK());
817 
818  if (x.BHRZ03_evolving_points(y, y_cert, H79)) {
819  return;
820  }
821 
822  PPL_ASSERT_HEAVY(H79.OK() && x.OK() && y.OK());
823 
824  if (x.BHRZ03_evolving_rays(y, y_cert, H79)) {
825  return;
826  }
827 
828  PPL_ASSERT_HEAVY(H79.OK() && x.OK() && y.OK());
829 
830  // No previous technique was successful: fall back to the H79 widening.
831  x.m_swap(H79);
832  PPL_ASSERT_HEAVY(x.OK(true));
833 
834  // The H79 widening is always stabilizing.
835  PPL_ASSERT(y_cert.is_stabilizing(x));
836 }
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
void throw_topology_incompatible(const char *method, const char *ph_name, const Polyhedron &ph) const
The universe element, i.e., the whole vector space.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
Topology
Kinds of polyhedra domains.
bool Parma_Polyhedra_Library::Polyhedron::BHZ09_C_poly_hull_assign_if_exact ( const Polyhedron y)
protected

Definition at line 1540 of file Polyhedron_nonpublic.cc.

References affine_dimension(), con_sys, gen_sys, Parma_Polyhedra_Library::Poly_Con_Relation::implies(), is_empty(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), is_included_in(), is_necessarily_closed(), minimize(), Parma_Polyhedra_Library::Generator_System::num_rows(), Parma_Polyhedra_Library::Constraint_System::num_rows(), relation_with(), sat_g, sat_g_is_up_to_date(), Parma_Polyhedra_Library::Bit_Row::set(), Parma_Polyhedra_Library::Bit_Row::set_until(), space_dim, Parma_Polyhedra_Library::Poly_Gen_Relation::subsumes(), Parma_Polyhedra_Library::Bit_Row::union_assign(), and update_sat_g().

Referenced by BHZ09_poly_hull_assign_if_exact().

1540  {
1541  Polyhedron& x = *this;
1542  // Private method: the caller must ensure the following.
1543  PPL_ASSERT(x.is_necessarily_closed() && y.is_necessarily_closed());
1544  PPL_ASSERT(x.space_dim > 0 && x.space_dim == y.space_dim);
1545  PPL_ASSERT(!x.is_empty() && !y.is_empty());
1546 
1547  // Minimization is not really required, but it is probably the best
1548  // way of getting constraints, generators and saturation matrices
1549  // up-to-date. Minimization it also removes redundant
1550  // constraints/generators.
1551  (void) x.minimize();
1552  (void) y.minimize();
1553 
1554  // Handle a special case: for topologically closed polyhedra P and Q,
1555  // if the affine dimension of P is greater than that of Q, then
1556  // their upper bound is exact if and only if P includes Q.
1557  const dimension_type x_affine_dim = x.affine_dimension();
1558  const dimension_type y_affine_dim = y.affine_dimension();
1559  if (x_affine_dim > y_affine_dim) {
1560  return y.is_included_in(x);
1561  }
1562  else if (x_affine_dim < y_affine_dim) {
1563  if (x.is_included_in(y)) {
1564  x = y;
1565  return true;
1566  }
1567  else {
1568  return false;
1569  }
1570  }
1571 
1572  const Constraint_System& x_cs = x.con_sys;
1573  const Generator_System& x_gs = x.gen_sys;
1574  const Generator_System& y_gs = y.gen_sys;
1575  const dimension_type x_gs_num_rows = x_gs.num_rows();
1576  const dimension_type y_gs_num_rows = y_gs.num_rows();
1577 
1578  // Step 1: generators of `x' that are redundant in `y', and vice versa.
1579  Bit_Row x_gs_red_in_y;
1580  dimension_type num_x_gs_red_in_y = 0;
1581  for (dimension_type i = x_gs_num_rows; i-- > 0; ) {
1582  if (y.relation_with(x_gs[i]).implies(Poly_Gen_Relation::subsumes())) {
1583  x_gs_red_in_y.set(i);
1584  ++num_x_gs_red_in_y;
1585  }
1586  }
1587 
1588  Bit_Row y_gs_red_in_x;
1589  dimension_type num_y_gs_red_in_x = 0;
1590  for (dimension_type i = y_gs_num_rows; i-- > 0; ) {
1591  if (x.relation_with(y_gs[i]).implies(Poly_Gen_Relation::subsumes())) {
1592  y_gs_red_in_x.set(i);
1593  ++num_y_gs_red_in_x;
1594  }
1595  }
1596  // Step 2: filter away special cases.
1597 
1598  // Step 2.1: inclusion tests.
1599  if (num_y_gs_red_in_x == y_gs_num_rows) {
1600  // `y' is included into `x': upper bound `x' is exact.
1601  return true;
1602  }
1603  if (num_x_gs_red_in_y == x_gs_num_rows) {
1604  // `x' is included into `y': upper bound `y' is exact.
1605  x = y;
1606  return true;
1607  }
1608 
1609  // Step 2.2: if no generator of `x' is redundant for `y', then
1610  // (as by 2.1 there exists a constraint of `x' non-redundant for `y')
1611  // the upper bound is not exact; the same if exchanging `x' and `y'.
1612  if (num_x_gs_red_in_y == 0 || num_y_gs_red_in_x == 0) {
1613  return false;
1614  }
1615 
1616  // Step 3: see if `x' has a non-redundant constraint `c_x' that is not
1617  // satisfied by `y' and a non-redundant generator in `y' (see Step 1)
1618  // saturating `c_x'. If so, the upper bound is not exact.
1619 
1620  // Make sure the saturation matrix for `x' is up to date.
1621  // Any sat matrix would do: we choose `sat_g' because it matches
1622  // the two nested loops (constraints on rows and generators on columns).
1623  if (!x.sat_g_is_up_to_date()) {
1624  x.update_sat_g();
1625  }
1626  const Bit_Matrix& x_sat = x.sat_g;
1627 
1628  Bit_Row all_ones;
1629  all_ones.set_until(x_gs_num_rows);
1630  Bit_Row row_union;
1631  for (dimension_type i = x_cs.num_rows(); i-- > 0; ) {
1632  const bool included
1633  = y.relation_with(x_cs[i]).implies(Poly_Con_Relation::is_included());
1634  if (!included) {
1635  row_union.union_assign(x_gs_red_in_y, x_sat[i]);
1636  if (row_union != all_ones) {
1637  return false;
1638  }
1639  }
1640  }
1641 
1642  // Here we know that the upper bound is exact: compute it.
1643  for (dimension_type j = y_gs_num_rows; j-- > 0; ) {
1644  if (!y_gs_red_in_x[j]) {
1645  add_generator(y_gs[j]);
1646  }
1647  }
1648 
1649  PPL_ASSERT_HEAVY(OK());
1650  return true;
1651 }
static Poly_Gen_Relation subsumes()
Adding the generator would not change the polyhedron.
size_t dimension_type
An unsigned integral type for representing space dimensions.
static Poly_Con_Relation is_included()
The polyhedron is included in the set of points satisfying the constraint.
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
void add_generator(const Generator &g)
Adds a copy of generator g to the system of generators of *this (without minimizing the result)...
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
bool Parma_Polyhedra_Library::Polyhedron::BHZ09_NNC_poly_hull_assign_if_exact ( const Polyhedron y)
protected

Definition at line 1654 of file Polyhedron_nonpublic.cc.

References add_constraint(), add_generator(), Parma_Polyhedra_Library::Bit_Row::clear(), con_sys, constraints(), contains(), Parma_Polyhedra_Library::Bit_Row::difference_assign(), Parma_Polyhedra_Library::Bit_Row::empty(), Parma_Polyhedra_Library::Constraint::expression(), Parma_Polyhedra_Library::Bit_Row::first(), gen_sys, Parma_Polyhedra_Library::Poly_Con_Relation::implies(), Parma_Polyhedra_Library::Bit_Row::intersection_assign(), Parma_Polyhedra_Library::Generator::is_closure_point(), Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), is_empty(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), is_necessarily_closed(), Parma_Polyhedra_Library::Generator::is_point(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), minimize(), Parma_Polyhedra_Library::Bit_Row::next(), Parma_Polyhedra_Library::Generator_System::num_rows(), Parma_Polyhedra_Library::Constraint_System::num_rows(), Parma_Polyhedra_Library::Scalar_Products::reduced_sign(), relation_with(), sat_g, sat_g_is_up_to_date(), Parma_Polyhedra_Library::Bit_Row::set(), Parma_Polyhedra_Library::Bit_Row::set_until(), space_dim, Parma_Polyhedra_Library::Poly_Gen_Relation::subsumes(), Parma_Polyhedra_Library::Bit_Row::union_assign(), and update_sat_g().

Referenced by BHZ09_poly_hull_assign_if_exact().

1654  {
1655  const Polyhedron& x = *this;
1656  // Private method: the caller must ensure the following.
1657  PPL_ASSERT(!x.is_necessarily_closed() && !y.is_necessarily_closed());
1658  PPL_ASSERT(x.space_dim > 0 && x.space_dim == y.space_dim);
1659  PPL_ASSERT(!x.is_empty() && !y.is_empty());
1660 
1661  // Minimization is not really required, but it is probably the best
1662  // way of getting constraints, generators and saturation matrices
1663  // up-to-date. Minimization also removes redundant
1664  // constraints/generators.
1665  (void) x.minimize();
1666  (void) y.minimize();
1667 
1668  const Generator_System& x_gs = x.gen_sys;
1669  const Generator_System& y_gs = y.gen_sys;
1670  const dimension_type x_gs_num_rows = x_gs.num_rows();
1671  const dimension_type y_gs_num_rows = y_gs.num_rows();
1672 
1673  // Compute generators of `x' that are non-redundant in `y' ...
1674  Bit_Row x_gs_non_redundant_in_y;
1675  Bit_Row x_points_non_redundant_in_y;
1676  Bit_Row x_closure_points;
1677  dimension_type num_x_gs_non_redundant_in_y = 0;
1678  for (dimension_type i = x_gs_num_rows; i-- > 0; ) {
1679  const Generator& x_gs_i = x_gs[i];
1680  if (x_gs_i.is_closure_point()) {
1681  x_closure_points.set(i);
1682  }
1683  if (y.relation_with(x_gs[i]).implies(Poly_Gen_Relation::subsumes())) {
1684  continue;
1685  }
1686  x_gs_non_redundant_in_y.set(i);
1687  ++num_x_gs_non_redundant_in_y;
1688  if (x_gs_i.is_point()) {
1689  x_points_non_redundant_in_y.set(i);
1690  }
1691  }
1692 
1693  // If `x' is included into `y', the upper bound `y' is exact.
1694  if (num_x_gs_non_redundant_in_y == 0) {
1695  *this = y;
1696  return true;
1697  }
1698 
1699  // ... and vice versa, generators of `y' that are non-redundant in `x'.
1700  Bit_Row y_gs_non_redundant_in_x;
1701  Bit_Row y_points_non_redundant_in_x;
1702  Bit_Row y_closure_points;
1703  dimension_type num_y_gs_non_redundant_in_x = 0;
1704  for (dimension_type i = y_gs_num_rows; i-- > 0; ) {
1705  const Generator& y_gs_i = y_gs[i];
1706  if (y_gs_i.is_closure_point()) {
1707  y_closure_points.set(i);
1708  }
1709  if (x.relation_with(y_gs_i).implies(Poly_Gen_Relation::subsumes())) {
1710  continue;
1711  }
1712  y_gs_non_redundant_in_x.set(i);
1713  ++num_y_gs_non_redundant_in_x;
1714  if (y_gs_i.is_point()) {
1715  y_points_non_redundant_in_x.set(i);
1716  }
1717  }
1718 
1719  // If `y' is included into `x', the upper bound `x' is exact.
1720  if (num_y_gs_non_redundant_in_x == 0) {
1721  return true;
1722  }
1723 
1724  Bit_Row x_non_points_non_redundant_in_y;
1725  x_non_points_non_redundant_in_y
1726  .difference_assign(x_gs_non_redundant_in_y,
1727  x_points_non_redundant_in_y);
1728 
1729  const Constraint_System& x_cs = x.con_sys;
1730  const Constraint_System& y_cs = y.con_sys;
1731  const dimension_type x_cs_num_rows = x_cs.num_rows();
1732  const dimension_type y_cs_num_rows = y_cs.num_rows();
1733 
1734  // Filter away the points of `x_gs' that would be redundant
1735  // in the topological closure of `y'.
1736  Bit_Row x_points_non_redundant_in_y_closure;
1737  for (dimension_type i = x_points_non_redundant_in_y.first();
1739  i = x_points_non_redundant_in_y.next(i)) {
1740  const Generator& x_p = x_gs[i];
1741  PPL_ASSERT(x_p.is_point());
1742  // NOTE: we cannot use Constraint_System::relation_with()
1743  // as we need to treat strict inequalities as if they were nonstrict.
1744  for (dimension_type j = y_cs_num_rows; j-- > 0; ) {
1745  const Constraint& y_c = y_cs[j];
1746  const int sp_sign = Scalar_Products::reduced_sign(y_c, x_p);
1747  if (sp_sign < 0 || (y_c.is_equality() && sp_sign > 0)) {
1748  x_points_non_redundant_in_y_closure.set(i);
1749  break;
1750  }
1751  }
1752  }
1753 
1754  // Make sure the saturation matrix for `x' is up to date.
1755  // Any sat matrix would do: we choose `sat_g' because it matches
1756  // the two nested loops (constraints on rows and generators on columns).
1757  if (!x.sat_g_is_up_to_date()) {
1758  x.update_sat_g();
1759  }
1760  const Bit_Matrix& x_sat = x.sat_g;
1761 
1762  Bit_Row x_cs_condition_3;
1763  Bit_Row x_gs_condition_3;
1764  Bit_Row all_ones;
1765  all_ones.set_until(x_gs_num_rows);
1766  Bit_Row saturators;
1767  Bit_Row tmp_set;
1768  for (dimension_type i = x_cs_num_rows; i-- > 0; ) {
1769  const Constraint& x_c = x_cs[i];
1770  // Skip constraint if it is not violated by `y'.
1771  if (y.relation_with(x_c).implies(Poly_Con_Relation::is_included())) {
1772  continue;
1773  }
1774  saturators.difference_assign(all_ones, x_sat[i]);
1775  // Check condition 1.
1776  tmp_set.intersection_assign(x_non_points_non_redundant_in_y, saturators);
1777  if (!tmp_set.empty()) {
1778  return false;
1779  }
1780  if (x_c.is_strict_inequality()) {
1781  // Postpone check for condition 3.
1782  x_cs_condition_3.set(i);
1783  tmp_set.intersection_assign(x_closure_points, saturators);
1784  x_gs_condition_3.union_assign(x_gs_condition_3, tmp_set);
1785  }
1786  else {
1787  // Check condition 2.
1788  tmp_set.intersection_assign(x_points_non_redundant_in_y_closure,
1789  saturators);
1790  if (!tmp_set.empty()) {
1791  return false;
1792  }
1793  }
1794  }
1795 
1796  // Now exchange the roles of `x' and `y'
1797  // (the statement of the NNC theorem in BHZ09 is symmetric).
1798 
1799  Bit_Row y_non_points_non_redundant_in_x;
1800  y_non_points_non_redundant_in_x
1801  .difference_assign(y_gs_non_redundant_in_x,
1802  y_points_non_redundant_in_x);
1803 
1804  // Filter away the points of `y_gs' that would be redundant
1805  // in the topological closure of `x'.
1806  Bit_Row y_points_non_redundant_in_x_closure;
1807  for (dimension_type i = y_points_non_redundant_in_x.first();
1809  i = y_points_non_redundant_in_x.next(i)) {
1810  const Generator& y_p = y_gs[i];
1811  PPL_ASSERT(y_p.is_point());
1812  // NOTE: we cannot use Constraint_System::relation_with()
1813  // as we need to treat strict inequalities as if they were nonstrict.
1814  for (dimension_type j = x_cs_num_rows; j-- > 0; ) {
1815  const Constraint& x_c = x_cs[j];
1816  const int sp_sign = Scalar_Products::reduced_sign(x_c, y_p);
1817  if (sp_sign < 0 || (x_c.is_equality() && sp_sign > 0)) {
1818  y_points_non_redundant_in_x_closure.set(i);
1819  break;
1820  }
1821  }
1822  }
1823 
1824  // Make sure the saturation matrix `sat_g' for `y' is up to date.
1825  if (!y.sat_g_is_up_to_date()) {
1826  y.update_sat_g();
1827  }
1828  const Bit_Matrix& y_sat = y.sat_g;
1829 
1830  Bit_Row y_cs_condition_3;
1831  Bit_Row y_gs_condition_3;
1832  all_ones.clear();
1833  all_ones.set_until(y_gs_num_rows);
1834  for (dimension_type i = y_cs_num_rows; i-- > 0; ) {
1835  const Constraint& y_c = y_cs[i];
1836  // Skip constraint if it is not violated by `x'.
1837  if (x.relation_with(y_c).implies(Poly_Con_Relation::is_included())) {
1838  continue;
1839  }
1840  saturators.difference_assign(all_ones, y_sat[i]);
1841  // Check condition 1.
1842  tmp_set.intersection_assign(y_non_points_non_redundant_in_x, saturators);
1843  if (!tmp_set.empty()) {
1844  return false;
1845  }
1846  if (y_c.is_strict_inequality()) {
1847  // Postpone check for condition 3.
1848  y_cs_condition_3.set(i);
1849  tmp_set.intersection_assign(y_closure_points, saturators);
1850  y_gs_condition_3.union_assign(y_gs_condition_3, tmp_set);
1851  }
1852  else {
1853  // Check condition 2.
1854  tmp_set.intersection_assign(y_points_non_redundant_in_x_closure,
1855  saturators);
1856  if (!tmp_set.empty()) {
1857  return false;
1858  }
1859  }
1860  }
1861 
1862  // Now considering condition 3.
1863 
1864  if (x_cs_condition_3.empty() && y_cs_condition_3.empty()) {
1865  // No test for condition 3 is needed.
1866  // The hull is exact: compute it.
1867  for (dimension_type j = y_gs_num_rows; j-- > 0; ) {
1868  if (y_gs_non_redundant_in_x[j]) {
1869  add_generator(y_gs[j]);
1870  }
1871  }
1872  return true;
1873  }
1874 
1875  // We have anyway to compute the upper bound and its constraints too.
1876  Polyhedron ub(x);
1877  for (dimension_type j = y_gs_num_rows; j-- > 0; ) {
1878  if (y_gs_non_redundant_in_x[j]) {
1879  ub.add_generator(y_gs[j]);
1880  }
1881  }
1882  (void) ub.minimize();
1883  PPL_ASSERT(!ub.is_empty());
1884 
1885  // NOTE: the following computation of x_gs_condition_3_not_in_y
1886  // (resp., y_gs_condition_3_not_in_x) is not required for correctness.
1887  // It is done so as to later apply a speculative test
1888  // (i.e., a non-conclusive but computationally lighter test).
1889 
1890  // Filter away from `x_gs_condition_3' those closure points
1891  // that, when considered as points, would belong to `y',
1892  // i.e., those that violate no strict constraint in `y_cs'.
1893  Bit_Row x_gs_condition_3_not_in_y;
1894  for (dimension_type i = y_cs_num_rows; i-- > 0; ) {
1895  const Constraint& y_c = y_cs[i];
1896  if (y_c.is_strict_inequality()) {
1897  for (dimension_type j = x_gs_condition_3.first();
1898  j != C_Integer<unsigned long>::max; j = x_gs_condition_3.next(j)) {
1899  const Generator& x_cp = x_gs[j];
1900  PPL_ASSERT(x_cp.is_closure_point());
1901  const int sp_sign = Scalar_Products::reduced_sign(y_c, x_cp);
1902  PPL_ASSERT(sp_sign >= 0);
1903  if (sp_sign == 0) {
1904  x_gs_condition_3.clear(j);
1905  x_gs_condition_3_not_in_y.set(j);
1906  }
1907  }
1908  if (x_gs_condition_3.empty()) {
1909  break;
1910  }
1911  }
1912  }
1913  // Symmetrically, filter away from `y_gs_condition_3' those
1914  // closure points that, when considered as points, would belong to `x',
1915  // i.e., those that violate no strict constraint in `x_cs'.
1916  Bit_Row y_gs_condition_3_not_in_x;
1917  for (dimension_type i = x_cs_num_rows; i-- > 0; ) {
1918  if (x_cs[i].is_strict_inequality()) {
1919  const Constraint& x_c = x_cs[i];
1920  for (dimension_type j = y_gs_condition_3.first();
1921  j != C_Integer<unsigned long>::max; j = y_gs_condition_3.next(j)) {
1922  const Generator& y_cp = y_gs[j];
1923  PPL_ASSERT(y_cp.is_closure_point());
1924  const int sp_sign = Scalar_Products::reduced_sign(x_c, y_cp);
1925  PPL_ASSERT(sp_sign >= 0);
1926  if (sp_sign == 0) {
1927  y_gs_condition_3.clear(j);
1928  y_gs_condition_3_not_in_x.set(j);
1929  }
1930  }
1931  if (y_gs_condition_3.empty()) {
1932  break;
1933  }
1934  }
1935  }
1936 
1937  // NOTE: here we apply the speculative test.
1938  // Check if there exists a closure point in `x_gs_condition_3_not_in_y'
1939  // or `y_gs_condition_3_not_in_x' that belongs (as point) to the hull.
1940  // If so, the hull is not exact.
1941  const Constraint_System& ub_cs = ub.constraints();
1942  for (dimension_type i = ub_cs.num_rows(); i-- > 0; ) {
1943  if (ub_cs[i].is_strict_inequality()) {
1944  const Constraint& ub_c = ub_cs[i];
1945  for (dimension_type j = x_gs_condition_3_not_in_y.first();
1947  j = x_gs_condition_3_not_in_y.next(j)) {
1948  const Generator& x_cp = x_gs[j];
1949  PPL_ASSERT(x_cp.is_closure_point());
1950  const int sp_sign = Scalar_Products::reduced_sign(ub_c, x_cp);
1951  PPL_ASSERT(sp_sign >= 0);
1952  if (sp_sign == 0) {
1953  x_gs_condition_3_not_in_y.clear(j);
1954  }
1955  }
1956  for (dimension_type j = y_gs_condition_3_not_in_x.first();
1958  j = y_gs_condition_3_not_in_x.next(j)) {
1959  const Generator& y_cp = y_gs[j];
1960  PPL_ASSERT(y_cp.is_closure_point());
1961  const int sp_sign = Scalar_Products::reduced_sign(ub_c, y_cp);
1962  PPL_ASSERT(sp_sign >= 0);
1963  if (sp_sign == 0) {
1964  y_gs_condition_3_not_in_x.clear(j);
1965  }
1966  }
1967  }
1968  }
1969 
1970  if (!(x_gs_condition_3_not_in_y.empty()
1971  && y_gs_condition_3_not_in_x.empty())) {
1972  // There exist a closure point satisfying condition 3,
1973  // hence the hull is not exact.
1974  return false;
1975  }
1976  // The speculative test was not successful:
1977  // apply the expensive (but conclusive) test for condition 3.
1978 
1979  // Consider strict inequalities in `x' violated by `y'.
1980  for (dimension_type i = x_cs_condition_3.first();
1981  i != C_Integer<unsigned long>::max; i = x_cs_condition_3.next(i)) {
1982  const Constraint& x_cs_i = x_cs[i];
1983  PPL_ASSERT(x_cs_i.is_strict_inequality());
1984  // Build the equality constraint induced by x_cs_i.
1985  const Linear_Expression expr(x_cs_i.expression());
1986  const Constraint eq_i(expr == 0);
1987  PPL_ASSERT(!(ub.relation_with(eq_i)
1988  .implies(Poly_Con_Relation::is_disjoint())));
1989  Polyhedron ub_inters_hyperplane(ub);
1990  ub_inters_hyperplane.add_constraint(eq_i);
1991  Polyhedron y_inters_hyperplane(y);
1992  y_inters_hyperplane.add_constraint(eq_i);
1993  if (!y_inters_hyperplane.contains(ub_inters_hyperplane)) {
1994  // The hull is not exact.
1995  return false;
1996  }
1997  }
1998 
1999  // Consider strict inequalities in `y' violated by `x'.
2000  for (dimension_type i = y_cs_condition_3.first();
2001  i != C_Integer<unsigned long>::max; i = y_cs_condition_3.next(i)) {
2002  const Constraint& y_cs_i = y_cs[i];
2003  PPL_ASSERT(y_cs_i.is_strict_inequality());
2004  // Build the equality constraint induced by y_cs_i.
2005  const Constraint eq_i(Linear_Expression(y_cs_i.expression()) == 0);
2006  PPL_ASSERT(!(ub.relation_with(eq_i)
2007  .implies(Poly_Con_Relation::is_disjoint())));
2008  Polyhedron ub_inters_hyperplane(ub);
2009  ub_inters_hyperplane.add_constraint(eq_i);
2010  Polyhedron x_inters_hyperplane(x);
2011  x_inters_hyperplane.add_constraint(eq_i);
2012  if (!x_inters_hyperplane.contains(ub_inters_hyperplane)) {
2013  // The hull is not exact.
2014  return false;
2015  }
2016  }
2017 
2018  // The hull is exact.
2019  m_swap(ub);
2020  return true;
2021 }
static Poly_Con_Relation is_disjoint()
The polyhedron and the set of points satisfying the constraint are disjoint.
static Poly_Gen_Relation subsumes()
Adding the generator would not change the polyhedron.
size_t dimension_type
An unsigned integral type for representing space dimensions.
static Poly_Con_Relation is_included()
The polyhedron is included in the set of points satisfying the constraint.
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
static int reduced_sign(const Linear_Expression &x, const Linear_Expression &y)
Returns the sign of the reduced scalar product of x and y, where the coefficient of x is ignored...
void add_generator(const Generator &g)
Adds a copy of generator g to the system of generators of *this (without minimizing the result)...
void m_swap(Polyhedron &y)
Swaps *this with polyhedron y. (*this and y can be dimension-incompatible.)
bool Parma_Polyhedra_Library::Polyhedron::BHZ09_poly_hull_assign_if_exact ( const Polyhedron y)
protected

Definition at line 1505 of file Polyhedron_nonpublic.cc.

References BHZ09_C_poly_hull_assign_if_exact(), BHZ09_NNC_poly_hull_assign_if_exact(), is_empty(), is_necessarily_closed(), marked_empty(), space_dim, topology(), and upper_bound_assign().

1505  {
1506  Polyhedron& x = *this;
1507 
1508  // Private method: the caller must ensure the following.
1509  PPL_ASSERT(x.topology() == y.topology());
1510  PPL_ASSERT(x.space_dim == y.space_dim);
1511 
1512  // The zero-dim case is trivial.
1513  if (x.space_dim == 0) {
1514  x.upper_bound_assign(y);
1515  return true;
1516  }
1517 
1518  // If `x' or `y' are (known to be) empty, the upper bound is exact.
1519  if (x.marked_empty()) {
1520  x = y;
1521  return true;
1522  }
1523  else if (y.is_empty()) {
1524  return true;
1525  }
1526  else if (x.is_empty()) {
1527  x = y;
1528  return true;
1529  }
1530 
1531  if (x.is_necessarily_closed()) {
1532  return x.BHZ09_C_poly_hull_assign_if_exact(y);
1533  }
1534  else {
1535  return x.BHZ09_NNC_poly_hull_assign_if_exact(y);
1536  }
1537 }
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
void Parma_Polyhedra_Library::Polyhedron::bounded_affine_image ( Variable  var,
const Linear_Expression lb_expr,
const Linear_Expression ub_expr,
Coefficient_traits::const_reference  denominator = Coefficient_one() 
)

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

Parameters
varThe variable updated by the affine relation;
lb_exprThe numerator of the lower bounding affine expression;
ub_exprThe numerator of the upper bounding affine expression;
denominatorThe (common) denominator for the lower and upper bounding affine expressions (optional argument with default value 1).
Exceptions
std::invalid_argumentThrown if denominator is zero or if lb_expr (resp., ub_expr) and *this are dimension-incompatible or if var is not a space dimension of *this.

Definition at line 2919 of file Polyhedron_public.cc.

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

Referenced by affine_form_image().

2922  {
2923  // The denominator cannot be zero.
2924  if (denominator == 0) {
2925  throw_invalid_argument("bounded_affine_image(v, lb, ub, d)", "d == 0");
2926  }
2927 
2928  // Dimension-compatibility checks.
2929  // `var' should be one of the dimensions of the polyhedron.
2930  const dimension_type var_space_dim = var.space_dimension();
2931  if (space_dim < var_space_dim) {
2932  throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)",
2933  "v", var);
2934  }
2935  // The dimension of `lb_expr' and `ub_expr' should not be
2936  // greater than the dimension of `*this'.
2937  const dimension_type lb_space_dim = lb_expr.space_dimension();
2938  if (space_dim < lb_space_dim) {
2939  throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)",
2940  "lb", lb_expr);
2941  }
2942  const dimension_type ub_space_dim = ub_expr.space_dimension();
2943  if (space_dim < ub_space_dim) {
2944  throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)",
2945  "ub", ub_expr);
2946  }
2947 
2948  // Any image of an empty polyhedron is empty.
2949  if (marked_empty()) {
2950  return;
2951  }
2952 
2953  // Check whether `var' occurs in `lb_expr' and/or `ub_expr'.
2954  if (lb_expr.coefficient(var) == 0) {
2955  // Here `var' may only occur in `ub_expr'.
2957  LESS_OR_EQUAL,
2958  ub_expr,
2959  denominator);
2960  if (denominator > 0) {
2961  refine_no_check(lb_expr <= denominator*var);
2962  }
2963  else {
2964  refine_no_check(denominator*var <= lb_expr);
2965  }
2966  }
2967  else if (ub_expr.coefficient(var) == 0) {
2968  // Here `var' only occurs in `lb_expr'.
2971  lb_expr,
2972  denominator);
2973  if (denominator > 0) {
2974  refine_no_check(denominator*var <= ub_expr);
2975  }
2976  else {
2977  refine_no_check(ub_expr <= denominator*var);
2978  }
2979  }
2980  else {
2981  // Here `var' occurs in both `lb_expr' and `ub_expr'.
2982  // To ease the computation, we add an additional dimension.
2983  const Variable new_var(space_dim);
2985  // Constrain the new dimension to be equal to `ub_expr'.
2986  refine_no_check(denominator*new_var == ub_expr);
2987  // Apply the affine lower bound.
2990  lb_expr,
2991  denominator);
2992  if (!marked_empty()) {
2993  // Now apply the affine upper bound, as recorded in `new_var'.
2994  refine_no_check(new_var >= var);
2995  }
2996  // Remove the temporarily added dimension.
2998  }
2999  PPL_ASSERT_HEAVY(OK());
3000 }
void add_space_dimensions_and_embed(dimension_type m)
Adds m new space dimensions and embeds the old polyhedron in the new vector space.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Coefficient_traits::const_reference coefficient(Variable v) const
Returns the coefficient of v in *this.
A dimension of the vector space.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void throw_invalid_argument(const char *method, const char *reason) const
void remove_higher_space_dimensions(dimension_type new_dimension)
Removes the higher dimensions of the vector space so that the resulting space will have dimension new...
void refine_no_check(const Constraint &c)
Uses a copy of constraint c to refine the system of constraints of *this.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
void generalized_affine_image(Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
Assigns to *this the image of *this with respect to the generalized affine relation ...
void Parma_Polyhedra_Library::Polyhedron::bounded_affine_preimage ( Variable  var,
const Linear_Expression lb_expr,
const Linear_Expression ub_expr,
Coefficient_traits::const_reference  denominator = Coefficient_one() 
)

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

Parameters
varThe variable updated by the affine relation;
lb_exprThe numerator of the lower bounding affine expression;
ub_exprThe numerator of the upper bounding affine expression;
denominatorThe (common) denominator for the lower and upper bounding affine expressions (optional argument with default value 1).
Exceptions
std::invalid_argumentThrown if denominator is zero or if lb_expr (resp., ub_expr) and *this are dimension-incompatible or if var is not a space dimension of *this.

Definition at line 3004 of file Polyhedron_public.cc.

References Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::Variable::space_dimension(), and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

3007  {
3008  // The denominator cannot be zero.
3009  if (denominator == 0) {
3010  throw_invalid_argument("bounded_affine_preimage(v, lb, ub, d)", "d == 0");
3011  }
3012 
3013  // Dimension-compatibility checks.
3014  // `var' should be one of the dimensions of the polyhedron.
3015  const dimension_type var_space_dim = var.space_dimension();
3016  if (space_dim < var_space_dim) {
3017  throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
3018  "v", var);
3019  }
3020  // The dimension of `lb_expr' and `ub_expr' should not be
3021  // greater than the dimension of `*this'.
3022  const dimension_type lb_space_dim = lb_expr.space_dimension();
3023  if (space_dim < lb_space_dim) {
3024  throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
3025  "lb", lb_expr);
3026  }
3027  const dimension_type ub_space_dim = ub_expr.space_dimension();
3028  if (space_dim < ub_space_dim) {
3029  throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)",
3030  "ub", ub_expr);
3031  }
3032 
3033  // Any preimage of an empty polyhedron is empty.
3034  if (marked_empty()) {
3035  return;
3036  }
3037 
3038  // Check whether `var' occurs in neither `lb_expr' nor `ub_expr'.
3039  if (lb_expr.coefficient(var) == 0 && ub_expr.coefficient(var) == 0) {
3040  if (denominator > 0) {
3041  refine_no_check(lb_expr <= denominator*var);
3042  refine_no_check(denominator*var <= ub_expr);
3043  }
3044  else {
3045  refine_no_check(ub_expr <= denominator*var);
3046  refine_no_check(denominator*var <= lb_expr);
3047  }
3048  unconstrain(var);
3049  }
3050  else {
3051  // Here `var' occurs in `lb_expr' or `ub_expr'.
3052  // To ease the computation, add an additional dimension.
3053  const Variable new_var(space_dim);
3055 
3056  // Swap dimensions `var' and `new_var'.
3058  con_sys.swap_space_dimensions(var, new_var);
3059  }
3060  if (generators_are_up_to_date()) {
3061  gen_sys.swap_space_dimensions(var, new_var);
3062  }
3063 
3064  // Constrain the new dimension as dictated by `lb_expr' and `ub_expr'.
3065  // (we force minimization because we will need the generators).
3066  if (denominator > 0) {
3067  refine_no_check(lb_expr <= denominator*new_var);
3068  refine_no_check(denominator*new_var <= ub_expr);
3069  }
3070  else {
3071  refine_no_check(ub_expr <= denominator*new_var);
3072  refine_no_check(denominator*new_var <= lb_expr);
3073  }
3074  // Remove the temporarily added dimension.
3076  }
3077  PPL_ASSERT_HEAVY(OK());
3078 }
void add_space_dimensions_and_embed(dimension_type m)
Adds m new space dimensions and embeds the old polyhedron in the new vector space.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Coefficient_traits::const_reference coefficient(Variable v) const
Returns the coefficient of v in *this.
A dimension of the vector space.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
void throw_invalid_argument(const char *method, const char *reason) const
Constraint_System con_sys
The system of constraints.
void remove_higher_space_dimensions(dimension_type new_dimension)
Removes the higher dimensions of the vector space so that the resulting space will have dimension new...
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
void refine_no_check(const Constraint &c)
Uses a copy of constraint c to refine the system of constraints of *this.
void swap_space_dimensions(Variable v1, Variable v2)
Swaps the coefficients of the variables v1 and v2 .
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
void unconstrain(Variable var)
Computes the cylindrification of *this with respect to space dimension var, assigning the result to *...
void swap_space_dimensions(Variable v1, Variable v2)
Swaps the coefficients of the variables v1 and v2 .
void Parma_Polyhedra_Library::Polyhedron::bounded_BHRZ03_extrapolation_assign ( const Polyhedron y,
const Constraint_System cs,
unsigned *  tp = 0 
)

Assigns to *this the result of computing the bounded extrapolation between *this and y using the BHRZ03-widening operator.

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

Definition at line 928 of file Polyhedron_widenings.cc.

References Parma_Polyhedra_Library::ANY_COMPLEXITY, Parma_Polyhedra_Library::Box< ITV >::CC76_widening_assign(), and Parma_Polyhedra_Library::Box< ITV >::constraints().

930  {
931  Rational_Box x_box(*this, ANY_COMPLEXITY);
932  const Rational_Box y_box(y, ANY_COMPLEXITY);
933  x_box.CC76_widening_assign(y_box);
935  Constraint_System x_box_cs = x_box.constraints();
936  add_recycled_constraints(x_box_cs);
937 }
void limited_BHRZ03_extrapolation_assign(const Polyhedron &y, const Constraint_System &cs, unsigned *tp=0)
Assigns to *this the result of computing the limited extrapolation between *this and y using the BHRZ...
void add_recycled_constraints(Constraint_System &cs)
Adds the constraints in cs to the system of constraints of *this (without minimizing the result)...
Box< Rational_Interval > Rational_Box
A box with rational, possibly open boundaries.
Definition: Rational_Box.hh:35
void Parma_Polyhedra_Library::Polyhedron::bounded_H79_extrapolation_assign ( const Polyhedron y,
const Constraint_System cs,
unsigned *  tp = 0 
)

Assigns to *this the result of computing the bounded extrapolation between *this and y using the H79-widening operator.

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

Definition at line 386 of file Polyhedron_widenings.cc.

References Parma_Polyhedra_Library::ANY_COMPLEXITY, Parma_Polyhedra_Library::Box< ITV >::CC76_widening_assign(), and Parma_Polyhedra_Library::Box< ITV >::constraints().

388  {
389  Rational_Box x_box(*this, ANY_COMPLEXITY);
390  const Rational_Box y_box(y, ANY_COMPLEXITY);
391  x_box.CC76_widening_assign(y_box);
393  Constraint_System x_box_cs = x_box.constraints();
394  add_recycled_constraints(x_box_cs);
395 }
void add_recycled_constraints(Constraint_System &cs)
Adds the constraints in cs to the system of constraints of *this (without minimizing the result)...
void limited_H79_extrapolation_assign(const Polyhedron &y, const Constraint_System &cs, unsigned *tp=0)
Assigns to *this the result of computing the limited extrapolation between *this and y using the H79-...
Box< Rational_Interval > Rational_Box
A box with rational, possibly open boundaries.
Definition: Rational_Box.hh:35
bool Parma_Polyhedra_Library::Polyhedron::bounds ( const Linear_Expression expr,
bool  from_above 
) const
private

Checks if and how expr is bounded in *this.

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

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

Definition at line 569 of file Polyhedron_nonpublic.cc.

References Parma_Polyhedra_Library::Scalar_Products::homogeneous_sign(), Parma_Polyhedra_Library::Generator::is_line(), Parma_Polyhedra_Library::Generator::is_line_or_ray(), and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

Referenced by bounds_from_above(), and bounds_from_below().

570  {
571  // The dimension of `expr' should not be greater than the dimension
572  // of `*this'.
573  const dimension_type expr_space_dim = expr.space_dimension();
574  if (space_dim < expr_space_dim) {
575  throw_dimension_incompatible((from_above
576  ? "bounds_from_above(e)"
577  : "bounds_from_below(e)"), "e", expr);
578  }
579 
580  // A zero-dimensional or empty polyhedron bounds everything.
581  if (space_dim == 0
582  || marked_empty()
585  return true;
586  }
587  // The polyhedron has updated, possibly pending generators.
588  for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) {
589  const Generator& g = gen_sys[i];
590  // Only lines and rays in `*this' can cause `expr' to be unbounded.
591  if (g.is_line_or_ray()) {
592  const int sp_sign = Scalar_Products::homogeneous_sign(expr, g);
593  if (sp_sign != 0
594  && (g.is_line()
595  || (from_above && sp_sign > 0)
596  || (!from_above && sp_sign < 0))) {
597  // `*this' does not bound `expr'.
598  return false;
599  }
600  }
601  }
602  // No sources of unboundedness have been found for `expr'
603  // in the given direction.
604  return true;
605 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
static int homogeneous_sign(const Linear_Expression &x, const Linear_Expression &y)
Returns the sign of the homogeneous scalar product of x and y, where the inhomogeneous terms are igno...
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
bool update_generators() const
Updates generators starting from constraints and minimizes them.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool process_pending_constraints() const
Processes the pending constraints and obtains a minimized polyhedron.
bool Parma_Polyhedra_Library::Polyhedron::bounds_from_above ( const Linear_Expression expr) const
inline

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

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

Definition at line 314 of file Polyhedron_inlines.hh.

References bounds().

314  {
315  return bounds(expr, true);
316 }
bool bounds(const Linear_Expression &expr, bool from_above) const
Checks if and how expr is bounded in *this.
bool Parma_Polyhedra_Library::Polyhedron::bounds_from_below ( const Linear_Expression expr) const
inline

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

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

Definition at line 319 of file Polyhedron_inlines.hh.

References bounds().

319  {
320  return bounds(expr, false);
321 }
bool bounds(const Linear_Expression &expr, bool from_above) const
Checks if and how expr is bounded in *this.
bool Parma_Polyhedra_Library::Polyhedron::can_have_something_pending ( ) const
inlineprivate

Returns true if the polyhedron can have something pending.

Definition at line 180 of file Polyhedron_inlines.hh.

References constraints_are_minimized(), generators_are_minimized(), sat_c_is_up_to_date(), and sat_g_is_up_to_date().

Referenced by intersection_assign(), poly_hull_assign(), and time_elapse_assign().

180  {
184 }
bool constraints_are_minimized() const
Returns true if the system of constraints is minimized.
bool generators_are_minimized() const
Returns true if the system of generators is minimized.
bool sat_c_is_up_to_date() const
Returns true if the saturation matrix sat_c is up-to-date.
bool sat_g_is_up_to_date() const
Returns true if the saturation matrix sat_g is up-to-date.
bool Parma_Polyhedra_Library::Polyhedron::can_recycle_congruence_systems ( )
inlinestatic

Returns false indicating that this domain cannot recycle congruences.

Definition at line 125 of file Polyhedron_inlines.hh.

125  {
126  return false;
127 }
bool Parma_Polyhedra_Library::Polyhedron::can_recycle_constraint_systems ( )
inlinestatic

Returns true indicating that this domain has methods that can recycle constraints.

Definition at line 120 of file Polyhedron_inlines.hh.

120  {
121  return true;
122 }
template<typename Input >
Input& Parma_Polyhedra_Library::Polyhedron::check_obj_space_dimension_overflow ( Input &  input,
const Topology  topol,
const char *  method,
const char *  reason 
)

Definition at line 599 of file Polyhedron_templates.hh.

References check_space_dimension_overflow(), and max_space_dimension().

602  {
603  check_space_dimension_overflow(input.space_dimension(),
605  topol, method, reason);
606  return input;
607 }
static dimension_type check_space_dimension_overflow(dimension_type dim, dimension_type max, const Topology topol, const char *method, const char *reason)
static dimension_type max_space_dimension()
Returns the maximum space dimension all kinds of Polyhedron can handle.
template<typename Object >
static Object& Parma_Polyhedra_Library::Polyhedron::check_obj_space_dimension_overflow ( Object &  input,
Topology  topol,
const char *  method,
const char *  reason 
)
staticprotected
PPL::dimension_type Parma_Polyhedra_Library::Polyhedron::check_space_dimension_overflow ( dimension_type  dim,
dimension_type  max,
const Topology  topol,
const char *  method,
const char *  reason 
)
staticprotected

Definition at line 2717 of file Polyhedron_nonpublic.cc.

References Parma_Polyhedra_Library::check_space_dimension_overflow(), and Parma_Polyhedra_Library::NECESSARILY_CLOSED.

Referenced by add_space_dimensions_and_embed(), and check_obj_space_dimension_overflow().

2721  {
2722  const char* const domain = (topol == NECESSARILY_CLOSED)
2723  ? "PPL::C_Polyhedron::" : "PPL::NNC_Polyhedron::";
2724  return PPL::check_space_dimension_overflow(dim, max, domain, method, reason);
2725 }
dimension_type check_space_dimension_overflow(const dimension_type dim, const dimension_type max, const char *domain, const char *method, const char *reason)
Definition: globals.cc:48
PPL::dimension_type Parma_Polyhedra_Library::Polyhedron::check_space_dimension_overflow ( dimension_type  dim,
const Topology  topol,
const char *  method,
const char *  reason 
)
staticprotected

Definition at line 2728 of file Polyhedron_nonpublic.cc.

References Parma_Polyhedra_Library::check_space_dimension_overflow(), and max_space_dimension().

2731  {
2733  topol, method, reason);
2734 }
static dimension_type check_space_dimension_overflow(dimension_type dim, dimension_type max, const Topology topol, const char *method, const char *reason)
static dimension_type max_space_dimension()
Returns the maximum space dimension all kinds of Polyhedron can handle.
void Parma_Polyhedra_Library::Polyhedron::clear_constraints_minimized ( )
inlineprivate

Sets status to express that constraints are no longer minimized.

Definition at line 248 of file Polyhedron_inlines.hh.

References Parma_Polyhedra_Library::Polyhedron::Status::reset_c_minimized(), and status.

Referenced by clear_constraints_up_to_date(), intersection_assign(), and remove_pending_to_obtain_constraints().

248  {
250 }
Status status
The status flags to keep track of the polyhedron's internal state.
void Parma_Polyhedra_Library::Polyhedron::clear_constraints_up_to_date ( )
inlineprivate

Sets status to express that constraints are no longer up-to-date.

This also implies that they are neither minimized and both saturation matrices are no longer meaningful.

Definition at line 280 of file Polyhedron_inlines.hh.

References clear_constraints_minimized(), clear_pending_constraints(), clear_sat_c_up_to_date(), clear_sat_g_up_to_date(), Parma_Polyhedra_Library::Polyhedron::Status::reset_c_up_to_date(), and status.

Referenced by poly_hull_assign(), remove_pending_to_obtain_generators(), strongly_minimize_generators(), and time_elapse_assign().

280  {
286  // Can get rid of con_sys here.
287 }
void clear_pending_constraints()
Sets status to express that there are no longer pending constraints.
Status status
The status flags to keep track of the polyhedron's internal state.
void clear_sat_g_up_to_date()
Sets status to express that sat_g is no longer up-to-date.
void clear_constraints_minimized()
Sets status to express that constraints are no longer minimized.
void clear_sat_c_up_to_date()
Sets status to express that sat_c is no longer up-to-date.
void Parma_Polyhedra_Library::Polyhedron::clear_empty ( )
inlineprivate

Clears the status flag indicating that the polyhedron is empty.

Definition at line 243 of file Polyhedron_inlines.hh.

References Parma_Polyhedra_Library::Polyhedron::Status::reset_empty(), and status.

243  {
245 }
Status status
The status flags to keep track of the polyhedron's internal state.
void Parma_Polyhedra_Library::Polyhedron::clear_generators_minimized ( )
inlineprivate

Sets status to express that generators are no longer minimized.

Definition at line 253 of file Polyhedron_inlines.hh.

References Parma_Polyhedra_Library::Polyhedron::Status::reset_g_minimized(), and status.

Referenced by clear_generators_up_to_date(), poly_hull_assign(), remove_pending_to_obtain_generators(), and time_elapse_assign().

253  {
255 }
Status status
The status flags to keep track of the polyhedron's internal state.
void Parma_Polyhedra_Library::Polyhedron::clear_generators_up_to_date ( )
inlineprivate

Sets status to express that generators are no longer up-to-date.

This also implies that they are neither minimized and both saturation matrices are no longer meaningful.

Definition at line 290 of file Polyhedron_inlines.hh.

References clear_generators_minimized(), clear_pending_generators(), clear_sat_c_up_to_date(), clear_sat_g_up_to_date(), Parma_Polyhedra_Library::Polyhedron::Status::reset_g_up_to_date(), and status.

Referenced by intersection_assign(), remove_pending_to_obtain_constraints(), and strongly_minimize_constraints().

290  {
296  // Can get rid of gen_sys here.
297 }
void clear_pending_generators()
Sets status to express that there are no longer pending generators.
Status status
The status flags to keep track of the polyhedron's internal state.
void clear_sat_g_up_to_date()
Sets status to express that sat_g is no longer up-to-date.
void clear_sat_c_up_to_date()
Sets status to express that sat_c is no longer up-to-date.
void clear_generators_minimized()
Sets status to express that generators are no longer minimized.
void Parma_Polyhedra_Library::Polyhedron::clear_pending_constraints ( )
inlineprivate

Sets status to express that there are no longer pending constraints.

Definition at line 258 of file Polyhedron_inlines.hh.

References Parma_Polyhedra_Library::Polyhedron::Status::reset_c_pending(), and status.

Referenced by clear_constraints_up_to_date(), process_pending_constraints(), and remove_pending_to_obtain_constraints().

258  {
260 }
Status status
The status flags to keep track of the polyhedron's internal state.
void Parma_Polyhedra_Library::Polyhedron::clear_pending_generators ( )
inlineprivate

Sets status to express that there are no longer pending generators.

Definition at line 263 of file Polyhedron_inlines.hh.

References Parma_Polyhedra_Library::Polyhedron::Status::reset_g_pending(), and status.

Referenced by clear_generators_up_to_date(), process_pending_generators(), and remove_pending_to_obtain_generators().

263  {
265 }
Status status
The status flags to keep track of the polyhedron's internal state.
void Parma_Polyhedra_Library::Polyhedron::clear_sat_c_up_to_date ( )
inlineprivate

Sets status to express that sat_c is no longer up-to-date.

Definition at line 268 of file Polyhedron_inlines.hh.

References Parma_Polyhedra_Library::Polyhedron::Status::reset_sat_c_up_to_date(), and status.

Referenced by clear_constraints_up_to_date(), clear_generators_up_to_date(), obtain_sorted_constraints(), process_pending_generators(), and update_generators().

268  {
270  // Can get rid of sat_c here.
271 }
Status status
The status flags to keep track of the polyhedron's internal state.
void Parma_Polyhedra_Library::Polyhedron::clear_sat_g_up_to_date ( )
inlineprivate

Sets status to express that sat_g is no longer up-to-date.

Definition at line 274 of file Polyhedron_inlines.hh.

References Parma_Polyhedra_Library::Polyhedron::Status::reset_sat_g_up_to_date(), and status.

Referenced by clear_constraints_up_to_date(), clear_generators_up_to_date(), obtain_sorted_generators(), process_pending_constraints(), and update_constraints().

274  {
276  // Can get rid of sat_g here.
277 }
Status status
The status flags to keep track of the polyhedron's internal state.
void Parma_Polyhedra_Library::Polyhedron::concatenate_assign ( const Polyhedron y)

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

Exceptions
std::invalid_argumentThrown if *this and y are topology-incompatible.
std::length_errorThrown if the concatenation would cause the vector space to exceed dimension max_space_dimension().

Definition at line 184 of file Polyhedron_chdims.cc.

References Parma_Polyhedra_Library::check_space_dimension_overflow(), Parma_Polyhedra_Library::Constraint_System::clear(), constraints(), marked_empty(), Parma_Polyhedra_Library::max_space_dimension(), Parma_Polyhedra_Library::Constraint_System::num_rows(), space_dim, Parma_Polyhedra_Library::swap(), Parma_Polyhedra_Library::Constraint_System::sys, and topology().

184  {
185  if (topology() != y.topology()) {
186  throw_topology_incompatible("concatenate_assign(y)", "y", y);
187  }
188 
189  // The space dimension of the resulting polyhedron should not
190  // overflow the maximum allowed space dimension.
191  const dimension_type added_columns = y.space_dim;
192  check_space_dimension_overflow(added_columns,
194  topology(),
195  "concatenate_assign(y)",
196  "concatenation exceeds the maximum "
197  "allowed space dimension");
198 
199  // If `*this' or `y' are empty polyhedra, it is sufficient to adjust
200  // the dimension of the space.
201  if (marked_empty() || y.marked_empty()) {
202  space_dim += added_columns;
203  set_empty();
204  return;
205  }
206 
207  // If `y' is a non-empty 0-dim space polyhedron, the result is `*this'.
208  if (added_columns == 0) {
209  return;
210  }
211 
212  // If `*this' is a non-empty 0-dim space polyhedron, the result is `y'.
213  if (space_dim == 0) {
214  *this = y;
215  return;
216  }
217 
218  // TODO: this implementation is just an executable specification.
219  Constraint_System cs = y.constraints();
220 
221  // The constraints of `x' (possibly with pending rows) are required.
222  if (has_pending_generators()) {
224  }
225  else if (!constraints_are_up_to_date()) {
227  }
228 
229  // The matrix for the new system of constraints is obtained
230  // by leaving the old system of constraints in the upper left-hand side
231  // and placing the constraints of `cs' in the lower right-hand side.
232  // NOTE: here topologies agree, whereas dimensions may not agree.
233  const dimension_type added_rows = cs.num_rows();
234 
235  // We already dealt with the cases of an empty or zero-dim `y' polyhedron;
236  // also, `cs' contains the low-level constraints, at least.
237  PPL_ASSERT(added_rows > 0 && added_columns > 0);
238 
240 
242  // Steal the constraints from `cs' and put them in `con_sys'
243  // using the right displacement for coefficients.
244  for (dimension_type i = 0; i < added_rows; ++i) {
245  cs.sys.rows[i].shift_space_dimensions(Variable(0), space_dim);
246  con_sys.insert_pending(cs.sys.rows[i], Recycle_Input());
247  }
248  cs.clear();
249 
250  // If `*this' can support pending constraints, then, since we have
251  // resized the system of constraints, we must also add to the generator
252  // system those lines corresponding to the newly added dimensions,
253  // because the non-pending parts of `con_sys' and `gen_sys' must still
254  // be a DD pair in minimal form.
256  // Since we added new lines at the beginning of `x.gen_sys',
257  // we also have to adjust the saturation matrix `sat_c'.
258  // FIXME: if `sat_c' is not up-to-date, could not we directly update
259  // `sat_g' by resizing it and shifting its columns?
260  if (!sat_c_is_up_to_date()) {
263  }
265  sat_c.resize(sat_c.num_rows() + added_columns, sat_c.num_columns());
266  // The old saturation rows are copied at the end of the matrix.
267  // The newly introduced lines saturate all the non-pending constraints,
268  // thus their saturation rows are made of zeroes.
269  using std::swap;
270  for (dimension_type i = sat_c.num_rows() - added_columns;
271  i-- > 0; ) {
272  swap(sat_c[i], sat_c[i+added_columns]);
273  }
274  // Since `added_rows > 0', we now have pending constraints.
276  }
277  else {
278  // Steal the constraints from `cs' and put them in `con_sys'
279  // using the right displacement for coefficients.
280  for (dimension_type i = 0; i < added_rows; ++i) {
281  cs.sys.rows[i].shift_space_dimensions(Variable(0), space_dim);
282  con_sys.insert(cs.sys.rows[i], Recycle_Input());
283  }
284 #if !BE_LAZY
285  con_sys.sort_rows();
286 #endif
291  }
292  // Update space dimension.
293  space_dim += added_columns;
294 
295  // The system of constraints may be unsatisfiable,
296  // thus we do not check for satisfiability.
297  PPL_ASSERT_HEAVY(OK());
298 }
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
void swap(CO_Tree &x, CO_Tree &y)
void insert_pending(const Constraint &c)
Inserts in *this a copy of the constraint c, increasing the number of space dimensions if needed...
size_t dimension_type
An unsigned integral type for representing space dimensions.
void update_constraints() const
Updates constraints starting from generators and minimizes them.
void set_space_dimension(dimension_type space_dim)
Sets the space dimension of the rows in the system to space_dim .
void resize(dimension_type new_n_rows, dimension_type new_n_columns)
Resizes the matrix copying the old contents.
Definition: Bit_Matrix.cc:132
Generator_System gen_sys
The system of generators.
void add_universe_rows_and_space_dimensions(dimension_type n)
Adds n rows and space dimensions to the system.
dimension_type num_rows() const
Returns the number of rows of *this.
void set_constraints_pending()
Sets status to express that constraints are pending.
void insert(const Constraint &c)
Inserts in *this a copy of the constraint c, increasing the number of space dimensions if needed...
bool sat_c_is_up_to_date() const
Returns true if the saturation matrix sat_c is up-to-date.
void swap(Polyhedron &x, Polyhedron &y)
Swaps x with y.
bool can_have_something_pending() const
Returns true if the polyhedron can have something pending.
void set_sat_c_up_to_date()
Sets status to express that sat_c is up-to-date.
Topology topology() const
Returns the topological kind of the polyhedron.
Constraint_System con_sys
The system of constraints.
static dimension_type check_space_dimension_overflow(dimension_type dim, dimension_type max, const Topology topol, const char *method, const char *reason)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
void throw_topology_incompatible(const char *method, const char *ph_name, const Polyhedron &ph) const
Bit_Matrix sat_g
The saturation matrix having generators on its columns.
static dimension_type max_space_dimension()
Returns the maximum space dimension all kinds of Polyhedron can handle.
void process_pending_generators() const
Processes the pending generators and obtains a minimized polyhedron.
void sort_rows()
Sorts the non-pending rows (in growing order) and eliminates duplicated ones.
dimension_type num_columns() const
Returns the number of columns of *this.
void set_empty()
Sets status to express that the polyhedron is empty, clearing all corresponding matrices.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
void clear_sat_g_up_to_date()
Sets status to express that sat_g is no longer up-to-date.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
void clear_constraints_minimized()
Sets status to express that constraints are no longer minimized.
bool has_pending_generators() const
Returns true if there are pending generators.
void clear_sat_c_up_to_date()
Sets status to express that sat_c is no longer up-to-date.
Bit_Matrix sat_c
The saturation matrix having constraints on its columns.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void clear_generators_up_to_date()
Sets status to express that generators are no longer up-to-date.
void transpose_assign(const Bit_Matrix &y)
Makes *this a transposed copy of y.
Definition: Bit_Matrix.cc:117
Congruence_System Parma_Polyhedra_Library::Polyhedron::congruences ( ) const
inline

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

Definition at line 367 of file Polyhedron_inlines.hh.

References minimized_constraints().

367  {
368  return Congruence_System(minimized_constraints());
369 }
const Constraint_System & minimized_constraints() const
Returns the system of constraints, with no redundant constraint.
bool Parma_Polyhedra_Library::Polyhedron::constrains ( Variable  var) const

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

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

Definition at line 729 of file Polyhedron_public.cc.

References Parma_Polyhedra_Library::Expression_Hide_Last< T >::all_zeroes(), Parma_Polyhedra_Library::Generator::coefficient(), Parma_Polyhedra_Library::Generator::expression(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Generator::is_line(), Parma_Polyhedra_Library::Generator::is_line_or_ray(), Parma_Polyhedra_Library::Boundary_NS::sgn(), and Parma_Polyhedra_Library::Variable::space_dimension().

729  {
730  // `var' should be one of the dimensions of the polyhedron.
731  const dimension_type var_space_dim = var.space_dimension();
732  if (space_dim < var_space_dim) {
733  throw_dimension_incompatible("constrains(v)", "v", var);
734  }
735 
736  // An empty polyhedron constrains all variables.
737  if (marked_empty()) {
738  return true;
739  }
740 
742  // Since generators are up-to-date and there are no pending
743  // constraints, the generator system (since it is well formed)
744  // contains a point. Hence the polyhedron is not empty.
746  // Here a variable is constrained if and only if it is
747  // syntactically constrained.
748  goto syntactic_check;
749  }
750  if (generators_are_minimized()) {
751  // Try a quick, incomplete check for the universe polyhedron:
752  // a universe polyhedron constrains no variable.
753  // Count the number of non-pending
754  // (hence, linearly independent) lines.
755  dimension_type num_lines = 0;
756  const dimension_type first_pending = gen_sys.first_pending_row();
757  for (dimension_type i = first_pending; i-- > 0; ) {
758  if (gen_sys[i].is_line()) {
759  ++num_lines;
760  }
761  }
762 
763  if (num_lines == space_dim) {
764  return false;
765  }
766  }
767 
768  // Scan generators: perhaps we will find a generator equivalent to
769  // line(var) or a pair of generators equivalent to ray(-var) and
770  // ray(var).
771  bool have_positive_ray = false;
772  bool have_negative_ray = false;
773  const dimension_type var_id = var.id();
774  for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) {
775  const Generator& gen_sys_i = gen_sys[i];
776  if (gen_sys_i.is_line_or_ray()) {
777  const int sign = sgn(gen_sys_i.coefficient(var));
778  if (sign != 0) {
779  if (gen_sys_i.expression().all_zeroes(1, var_id)
780  && gen_sys_i.expression().all_zeroes(var_id + 1, space_dim + 1)) {
781 
782  if (gen_sys_i.is_line()) {
783  return true;
784  }
785  if (sign > 0) {
786  if (have_negative_ray) {
787  return true;
788  }
789  else {
790  have_positive_ray = true;
791  }
792  }
793  else if (have_positive_ray) {
794  return true;
795  }
796  else {
797  have_negative_ray = true;
798  }
799  }
800  }
801  }
802  }
803 
804  // We are still here: at least we know that, since generators are
805  // up-to-date and there are no pending constraints, then the
806  // generator system (since it is well formed) contains a point.
807  // Hence the polyhedron is not empty.
808  if (has_pending_generators()) {
810  }
811  else if (!constraints_are_up_to_date()) {
813  }
814  goto syntactic_check;
815  }
816 
817  // We must minimize to detect emptiness and obtain constraints.
818  if (!minimize()) {
819  return true;
820  }
821 
822  syntactic_check:
823  for (dimension_type i = con_sys.num_rows(); i-- > 0; ) {
824  if (con_sys[i].coefficient(var) != 0) {
825  return true;
826  }
827  }
828  return false;
829 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
dimension_type first_pending_row() const
Returns the index of the first pending row.
bool minimize() const
Applies (weak) minimization to both the constraints and generators.
size_t dimension_type
An unsigned integral type for representing space dimensions.
void update_constraints() const
Updates constraints starting from generators and minimizes them.
Generator_System gen_sys
The system of generators.
A line, ray, point or closure point.
bool generators_are_minimized() const
Returns true if the system of generators is minimized.
bool is_line_or_ray() const
Returns true if and only if *this is a line or a ray.
expr_type expression() const
Partial read access to the (adapted) internal expression.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
dimension_type id() const
Returns the index of the Cartesian axis associated to the variable.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
Constraint_System con_sys
The system of constraints.
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
void process_pending_generators() const
Processes the pending generators and obtains a minimized polyhedron.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
Coefficient_traits::const_reference coefficient(Variable v) const
Returns the coefficient of v in *this.
int sgn(Boundary_Type type, const T &x, const Info &info)
bool has_pending_generators() const
Returns true if there are pending generators.
bool is_line() const
Returns true if and only if *this is a line.
bool all_zeroes(const Variables_Set &vars) const
Returns true if the coefficient of each variable in vars is zero.
const PPL::Constraint_System & Parma_Polyhedra_Library::Polyhedron::constraints ( ) const

Returns the system of constraints.

Definition at line 78 of file Polyhedron_public.cc.

References Parma_Polyhedra_Library::Constraint_System::adjust_topology_and_space_dimension(), Parma_Polyhedra_Library::swap(), and Parma_Polyhedra_Library::Constraint_System::zero_dim_empty().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), BHZ09_NNC_poly_hull_assign_if_exact(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::C_Polyhedron::C_Polyhedron(), concatenate_assign(), Parma_Polyhedra_Library::Grid::Grid(), Parma_Polyhedra_Library::NNC_Polyhedron::NNC_Polyhedron(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), and poly_difference_assign().

78  {
79  if (marked_empty()) {
80  // We want `con_sys' to only contain the unsatisfiable constraint
81  // of the appropriate dimension.
82  if (con_sys.has_no_rows()) {
83  // The 0-dim unsatisfiable constraint is extended to
84  // the appropriate dimension and then stored in `con_sys'.
87  swap(const_cast<Constraint_System&>(con_sys), unsat_cs);
88  }
89  else {
90  // Checking that `con_sys' contains the right thing.
91  PPL_ASSERT(con_sys.space_dimension() == space_dim);
92  PPL_ASSERT(con_sys.num_rows() == 1);
93  PPL_ASSERT(con_sys[0].is_inconsistent());
94  }
95  return con_sys;
96  }
97 
98  if (space_dim == 0) {
99  // Zero-dimensional universe.
100  PPL_ASSERT(con_sys.num_rows() == 0 && con_sys.space_dimension() == 0);
101  return con_sys;
102  }
103 
104  // If the polyhedron has pending generators, we process them to obtain
105  // the constraints. No processing is needed if the polyhedron has
106  // pending constraints.
107  if (has_pending_generators()) {
109  }
110  else if (!constraints_are_up_to_date()) {
112  }
113 
114  // TODO: reconsider whether to really sort constraints at this stage.
115 #if ENSURE_SORTEDNESS
116  // We insist in returning a sorted system of constraints,
117  // but sorting is useless if there are pending constraints.
120 #endif
121  return con_sys;
122 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
void update_constraints() const
Updates constraints starting from generators and minimizes them.
static const Constraint_System & zero_dim_empty()
Returns the singleton system containing only Constraint::zero_dim_false().
void swap(Polyhedron &x, Polyhedron &y)
Swaps x with y.
void obtain_sorted_constraints() const
Sorts the matrix of constraints keeping status consistency.
Topology topology() const
Returns the topological kind of the polyhedron.
Constraint_System con_sys
The system of constraints.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
void process_pending_generators() const
Processes the pending generators and obtains a minimized polyhedron.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool has_pending_generators() const
Returns true if there are pending generators.
bool adjust_topology_and_space_dimension(Topology new_topology, dimension_type new_space_dim)
Adjusts *this so that it matches new_topology and new_space_dim (adding or removing columns if needed...
bool Parma_Polyhedra_Library::Polyhedron::constraints_are_minimized ( ) const
inlineprivate
bool Parma_Polyhedra_Library::Polyhedron::contains ( const Polyhedron y) const

Returns true if and only if *this contains y.

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

Definition at line 3927 of file Polyhedron_public.cc.

References is_empty(), is_included_in(), marked_empty(), quick_equivalence_test(), space_dim, topology(), and TVB_TRUE.

Referenced by BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHRZ03_widening_assign(), BHZ09_NNC_poly_hull_assign_if_exact(), Parma_Polyhedra_Library::Pointset_Powerset< PSET >::check_containment(), H79_widening_assign(), poly_difference_assign(), poly_hull_assign_if_exact(), and strictly_contains().

3927  {
3928  const Polyhedron& x = *this;
3929 
3930  // Topology compatibility check.
3931  if (x.topology() != y.topology()) {
3932  throw_topology_incompatible("contains(y)", "y", y);
3933  }
3934 
3935  // Dimension-compatibility check.
3936  if (x.space_dim != y.space_dim) {
3937  throw_dimension_incompatible("contains(y)", "y", y);
3938  }
3939 
3940  if (y.marked_empty()) {
3941  return true;
3942  }
3943  else if (x.marked_empty()) {
3944  return y.is_empty();
3945  }
3946  else if (y.space_dim == 0) {
3947  return true;
3948  }
3949  else if (x.quick_equivalence_test(y) == Polyhedron::TVB_TRUE) {
3950  return true;
3951  }
3952  else {
3953  return y.is_included_in(x);
3954  }
3955 }
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
bool is_empty() const
Returns true if and only if *this is an empty polyhedron.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
The base class for convex polyhedra.
Topology topology() const
Returns the topological kind of the polyhedron.
void throw_topology_incompatible(const char *method, const char *ph_name, const Polyhedron &ph) const
bool is_included_in(const Polyhedron &y) const
Returns true if and only if *this is included in y.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
Three_Valued_Boolean quick_equivalence_test(const Polyhedron &y) const
Polynomial but incomplete equivalence test between polyhedra.
bool Parma_Polyhedra_Library::Polyhedron::contains_integer_point ( ) const

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

Definition at line 598 of file Polyhedron_public.cc.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Constraint_System::begin(), c, Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Constraint::EQUALITY, Parma_Polyhedra_Library::Constraint::expression(), Parma_Polyhedra_Library::Expression_Hide_Last< T >::gcd(), Parma_Polyhedra_Library::gcd_assign(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::is_canonical(), Parma_Polyhedra_Library::Constraint::is_inconsistent(), Parma_Polyhedra_Library::Boundary_NS::le(), PPL_DIRTY_TEMP, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::ROUND_DOWN, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::Constraint::STRICT_INEQUALITY, and Parma_Polyhedra_Library::Constraint::type().

598  {
599  // Any empty polyhedron does not contain integer points.
600  if (marked_empty()) {
601  return false;
602  }
603  // A zero-dimensional, universe polyhedron has, by convention, an
604  // integer point.
605  if (space_dim == 0) {
606  return true;
607  }
608 
609  // CHECKME: do we really want to call conversion to check for emptiness?
611  // Empty again.
612  return false;
613  }
614 
615  // FIXME: do also exploit info regarding rays and lines, if possible.
616  // Is any integer point already available?
617  PPL_ASSERT(!has_pending_constraints());
619  for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) {
620  if (gen_sys[i].is_point() && gen_sys[i].divisor() == 1) {
621  return true;
622  }
623  }
624  }
625  const Constraint_System& cs = constraints();
626 #if 0 // TEMPORARILY DISABLED.
628  cs.begin(), cs.end(),
630 #else
631  // FIXME: temporary workaround, to be removed as soon as the MIP
632  // problem class will correctly and precisely handle
633  // ((strict) in-) equality constraints having all integer variables.
634  MIP_Problem mip(space_dim);
635  mip.add_to_integer_space_dimensions(Variables_Set(Variable(0),
636  Variable(space_dim-1)));
637  PPL_DIRTY_TEMP_COEFFICIENT(homogeneous_gcd);
639  PPL_DIRTY_TEMP(mpq_class, rational_inhomogeneous);
640  PPL_DIRTY_TEMP_COEFFICIENT(tightened_inhomogeneous);
641  for (Constraint_System::const_iterator cs_i = cs.begin(),
642  cs_end = cs.end(); cs_i != cs_end; ++cs_i) {
643  const Constraint& c = *cs_i;
644  const Constraint::Type c_type = c.type();
645  const Coefficient& inhomogeneous = c.inhomogeneous_term();
646  if (c_type == Constraint::STRICT_INEQUALITY) {
647  // CHECKME: should we change the behavior of Linear_Expression(c) ?
648  // Compute the GCD of the coefficients of c
649  // (disregarding the inhomogeneous term and the epsilon dimension).
650  homogeneous_gcd = c.expression().gcd(1, space_dim + 1);
651  if (homogeneous_gcd == 0) {
652  // NOTE: since tautological constraints are already filtered away
653  // by iterators, here we must have an inconsistent constraint.
654  PPL_ASSERT(c.is_inconsistent());
655  return false;
656  }
658  if (homogeneous_gcd != 1) {
659  le /= homogeneous_gcd;
660  }
661  // Further tighten the constraint if the inhomogeneous term
662  // was integer, i.e., if `homogeneous_gcd' divides `inhomogeneous'.
663  gcd_assign(gcd, homogeneous_gcd, inhomogeneous);
664  if (gcd == homogeneous_gcd) {
665  le -= 1;
666  }
667  mip.add_constraint(le >= 0);
668  }
669  else {
670  // Equality or non-strict inequality.
671  // If possible, avoid useless gcd computations.
672  if (inhomogeneous == 0) {
673  // The inhomogeneous term cannot be tightened.
674  mip.add_constraint(c);
675  }
676  else {
677  // Compute the GCD of the coefficients of c
678  // (disregarding the inhomogeneous term)
679  // to see whether or not the inhomogeneous term can be tightened.
680  homogeneous_gcd = c.expression().gcd(1, space_dim + 1);
681  if (homogeneous_gcd == 0) {
682  // NOTE: since tautological constraints are already filtered away
683  // by iterators, here we must have an inconsistent constraint.
684  PPL_ASSERT(c.is_inconsistent());
685  return false;
686  }
687  else if (homogeneous_gcd == 1) {
688  // The normalized inhomogeneous term is integer:
689  // add the constraint as-is.
690  mip.add_constraint(c);
691  }
692  else {
693  PPL_ASSERT(homogeneous_gcd > 1);
694  // Here the normalized inhomogeneous term is rational:
695  // the constraint has to be tightened.
696 #ifndef NDEBUG
697  // `homogeneous_gcd' does not divide `inhomogeneous'.
698  // FIXME: add a divisibility test for Coefficient.
699  gcd_assign(gcd, homogeneous_gcd, inhomogeneous);
700  PPL_ASSERT(gcd == 1);
701 #endif
702  if (c.type() == Constraint::EQUALITY) {
703  return false;
704  }
705  // Extract the homogeneous part of the constraint.
707  le -= inhomogeneous;
708  // Tighten the inhomogeneous term.
709  assign_r(rational_inhomogeneous.get_num(),
710  inhomogeneous, ROUND_NOT_NEEDED);
711  assign_r(rational_inhomogeneous.get_den(),
712  homogeneous_gcd, ROUND_NOT_NEEDED);
713  // Note: canonicalization is not needed (as gcd == 1).
714  PPL_ASSERT(is_canonical(rational_inhomogeneous));
715  assign_r(tightened_inhomogeneous,
716  rational_inhomogeneous, ROUND_DOWN);
717  tightened_inhomogeneous *= homogeneous_gcd;
718  le += tightened_inhomogeneous;
719  mip.add_constraint(le >= 0);
720  }
721  }
722  }
723  }
724 #endif // TEMPORARY WORKAROUND.
725  return mip.is_satisfiable();
726 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
A linear equality or inequality.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Type type() const
Returns the constraint type of *this.
An std::set of variables' indexes.
Generator_System gen_sys
The system of generators.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
const Constraint_System & constraints() const
Returns the system of constraints.
Coefficient gcd(dimension_type start, dimension_type end) const
Returns the gcd of the nonzero coefficients in [start,end). Returns zero if all the coefficients in t...
const_iterator begin() const
Returns the const_iterator pointing to the first constraint, if *this is not empty; otherwise...
A dimension of the vector space.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
bool is_canonical(const mpq_class &x)
Returns true if and only if x is in canonical form.
bool process_pending() const
Processes the pending rows of either description of the polyhedron and obtains a minimized polyhedron...
const_iterator end() const
Returns the past-the-end const_iterator.
A Mixed Integer (linear) Programming problem.
bool is_inconsistent() const
Returns true if and only if *this is inconsistent (i.e., an always false constraint).
Definition: Constraint.cc:148
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
#define PPL_DIRTY_TEMP(T, id)
dimension_type space_dim
The number of dimensions of the enclosing vector space.
void gcd_assign(GMP_Integer &x, const GMP_Integer &y, const GMP_Integer &z)
Coefficient c
Definition: PIP_Tree.cc:64
Coefficient_traits::const_reference inhomogeneous_term() const
Returns the inhomogeneous term of *this.
expr_type expression() const
Partial read access to the (adapted) internal expression.
bool le(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
template<typename Source_Linear_System , typename Dest_Linear_System >
dimension_type Parma_Polyhedra_Library::Polyhedron::conversion ( Source_Linear_System &  source,
dimension_type  start,
Dest_Linear_System &  dest,
Bit_Matrix sat,
dimension_type  num_lines_or_equalities 
)
staticprivate

Performs the conversion from constraints to generators and vice versa.

Returns
The number of lines of the polyhedron or the number of equality constraints in the result of conversion.
Parameters
sourceThe system to use to convert dest: it may be modified;
startThe index of source row from which conversion begin;
destThe result of the conversion;
satThe saturation matrix telling us, for each row in source, which are the rows of dest that satisfy but do not saturate it;
num_lines_or_equalitiesThe number of rows in the system dest that are either lines of the polyhedron (when dest is a system of generators) or equality constraints (when dest is a system of constraints).

For simplicity, all the following comments assume we are converting a constraint system source to a generator system dest; the comments for the symmetric case can be obtained by duality.

If some of the constraints in source are redundant, they will be removed. This is why the source is not declared to be a constant parameter.

If start is 0, then source is a sorted system; also, dest is a generator system corresponding to an empty constraint system. If otherwise start is greater than 0, then the two sub-systems of source made by the non-pending rows and the pending rows, respectively, are both sorted; also, dest is the generator system corresponding to the non-pending constraints of source.

Independently from the value of start, dest has lines from index 0 to index num_lines_or_equalities - 1 and rays/points from index num_lines_or_equalities to the last of its rows.

Note that here the rows of sat are indexed by rows of dest and its columns are indexed by rows of source.

We know that polyhedra can be represented by both a system of constraints or a system of generators (points, rays and lines) (see Section Representations of Convex Polyhedra). When we have both descriptions for a polyhedron $P$ we have what is called a double description (or DD pair) for $P$.

Here, the representation system refers to the system $C$ whose rows represent the constraints that characterize $P$ and the generating system, the system $G$ whose rows represent the generators of $P$. We say that a pair $(C, G)$ of (real) systems is a double description pair if

\[ C\vect{x} \geq \vect{0} \quad\iff\quad \exists \vect{\lambda} \geq \vect{0} \mathrel{.} \vect{x} = G\vect{\lambda}. \]

The term "double description" is quite natural in the sense that such a pair contains two different description of the same object. In fact, if we refer to the cone representation of a polyhedron $P$ and we call $C$ and $G$ the systems of constraints and rays respectively, we have

\[ P = \{\, \vect{x} \in \Rset^n \mid C\vect{x} \geq \vect{0}\, \} = \{\, \vect{x} \in \Rset^n \mid \vect{x} = G\vect{\lambda} \text{ for some } \vect{\lambda} \geq \vect{0}\, \}. \]

Because of the theorem of Minkowski (see Section Further Notation and Terminology), we can say that, given a $m \times n$ representation system $C$ such that $\mathop{\mathrm{rank}}(C) = n = \mathit{dimension of the whole space}$ for a non-empty polyhedron $P$, it is always possible to find a generating system $G$ for $P$ such that $(C, G)$ is a DD pair. Conversely, Weyl's theorem ensures that, for each generating system $G$, it is possible to find a representation system $C$ such that $(C, G)$ is a DD pair.

For efficiency reasons, our representation of polyhedra makes use of a double description. We are thus left with two problems:

  1. given $C$ find $G$ such that $(C, G)$ is a DD pair;
  2. given $G$ find $C$ such that $(C, G)$ is a DD pair.

Using Farkas' Lemma we can prove that these two problems are computationally equivalent (i.e., linear-time reducible to each other). Farkas' Lemma establishes a fundamental property of vectors in $\Rset^n$ that, in a sense, captures the essence of duality. Consider a matrix $A \in \Rset^{m \times n}$ and let $\{ \vect{a}_1, \ldots, \vect{a}_m \}$ be its set of row vectors. Consider also another vector $\vect{c} \in \Rset^n$ such that, whenever a vector $\vect{y} \in \Rset^n$ has a non-negative projection on the $\vect{a}_i$'s, it also has a non-negative projection on $\vect{c}$. The lemma states that $\vect{c}$ has this property if and only if it is in the cone generated by the $\vect{a}_i$'s. Formally, the lemma states the equivalence of the two following assertions:

  1. $ \forall \vect{y} \mathrel{:} (A\vect{y} \geq 0 \implies \langle \vect{y},\vect{c} \rangle \geq 0) $;
  2. $ \exists \vect{\lambda} \geq \vect{0} \mathrel{.} \vect{c}^\mathrm{T} = \vect{\lambda}^\mathrm{T}A $.

With this result we can prove that $(C, G)$ is a DD pair if and only if $(G^\mathrm{T}, C^\mathrm{T})$ is a DD pair.

Suppose $(C, G)$ is a DD pair. Thus, for each $x$ of the appropriate dimension, $C\vect{x} \geq \vect{0}$ if and only if $\exists \lambda \geq 0 \mathrel{.} \vect{x} = G\vect{\lambda}$, which is of course equivalent to $ \exists \vect{\lambda} \geq \vect{0} \mathrel{.} \vect{x}^\mathrm{T} = \vect{\lambda}^\mathrm{T}G^\mathrm{T} $.

First, we assume that $\vect{z}$ is such that $G^\mathrm{T}\vect{z} \geq \vect{0}$ and we will show that $\exists \vect{\mu} \geq \vect{0} \mathrel{.} \vect{z} = C^\mathrm{T}\vect{\mu}$. Let $\vect{x}$ be such that $C\vect{x} \geq \vect{0}$. Since $(C, G)$ is a DD pair, this is equivalent to $ \exists \vect{\lambda} \geq \vect{0} \mathrel{.} \vect{x}^\mathrm{T} = \vect{\lambda}^\mathrm{T}G^\mathrm{T} $, which, by Farkas' Lemma is equivalent to $ \forall \vect{y} \mathrel{:} (G^\mathrm{T}\vect{y} \geq \vect{0} \implies \langle \vect{y}, \vect{x} \rangle \geq 0) $. Taking $\vect{y} = \vect{z}$ and recalling our assumption that $G^\mathrm{T}\vect{z} \geq \vect{0}$ we can conclude that $\langle \vect{z}, \vect{x} \rangle \geq 0$, that is equivalent to $\langle \vect{x}, \vect{z} \rangle \geq 0$. We have thus established that $ \forall \vect{x} \mathrel{:} (C\vect{x} \geq \vect{0} \implies \langle \vect{x}, \vect{z} \rangle \geq 0) $. By Farkas' Lemma, this is equivalent to $\exists \vect{\mu} \geq \vect{0} \mathrel{.} \vect{z}^\mathrm{T} = \vect{\mu}^\mathrm{T} C$, which is equivalent to what we wanted to prove, that is, $\exists \vect{\mu} \geq \vect{0} \mathrel{.} \vect{z} = C^\mathrm{T}\vect{\mu}$.

In order to prove the reverse implication, the following observation turns out to be useful: when $(C, G)$ is a DD pair, $CG \geq 0$. In fact, let $\vect{e}_j$ be the vector whose components are all $0$ apart from the $j$-th one, which is $1$. Clearly $\vect{e}_j \geq \vect{0}$ and, taking $\vect{\lambda} = \vect{e}_j$ and $\vect{x} = G\vect{\lambda} = G \vect{e}_j$, we have $C\vect{x} = C(G \vect{e}_j) = (CG)\vect{e}_j \geq \vect{0}$, since $(C, G)$ is a DD pair. Thus, as $(CG)\vect{e}_j$ is the $j$-th column of $CG$ and since the choice of $j$ was arbitrary, $CG \geq \vect{0}$.

We now assume that $\vect{z}$ is such that $\exists \vect{\mu} \geq \vect{0} \mathrel{.} \vect{z} = C^\mathrm{T}\vect{\mu}$ and we will prove that $G^\mathrm{T}\vect{z} \geq \vect{0}$. By Farkas' Lemma, the assumption $\exists \vect{\mu} \geq \vect{0} \mathrel{.} \vect{z}^\mathrm{T} = \vect{\mu}^\mathrm{T}C$, is equivalent to $\forall \vect{y} \mathrel{:} (C\vect{y} \geq \vect{0} \implies \langle \vect{y}, \vect{z} \rangle \geq 0)$. If we take $\vect{y} = G\vect{e}_j$ then $C\vect{y} = CG\vect{e}_j \geq 0$, since $CG \geq \vect{0}$. So $ \langle \vect{y}, \vect{z} \rangle = (\vect{e}_j^\mathrm{T}G^\mathrm{T}) \vect{z} = \vect{e}_j^\mathrm{T}(G^\mathrm{T} \vect{z}) \geq 0 $, that is, the $j$-th component of $G^\mathrm{T}\vect{z}$ is non-negative. The arbitrary choice of $j$ allows us to conclude that $G^\mathrm{T}\vect{z} \geq \vect{0}$, as required.

In view of this result, the following exposition assumes, for clarity, that the conversion being performed is from constraints to generators. Thus, even if the roles of source and dest can be interchanged, in the sequel we assume the source system will contain the constraints that represent the polyhedron and the dest system will contain the generator that generates it.

There are some observations that are useful to understand this function:

Observation 1: Let $A$ be a system of constraints that generate the polyhedron $P$ and $\vect{c}$ a new constraint that must be added. Suppose that there is a line $\vect{z}$ that does not saturate the constraint $\vect{c}$. If we combine the old lines and rays that do not saturate $\vect{c}$ (except $\vect{z}$) with $\vect{z}$ such that the new ones saturate $\vect{c}$, the new lines and rays also saturate the constraints saturated by the old lines and rays.

In fact, if $\vect{y}_1$ is the old generator that does not saturate $\vect{c}$, $\vect{y}_2$ is the new one such that

\[ \vect{y}_2 = \lambda \vect{y}_1 + \mu \vect{z} \]

and $\vect{c}_1$ is a previous constraint that $\vect{y}_1$ and $\vect{z}$ saturates, we can see

\[ \langle \vect{c}_1, \vect{y}_2 \rangle = \langle \vect{c}_1, (\lambda \vect{y}_1 + \mu \vect{z}) \rangle = \lambda \langle \vect{c}_1, \vect{y}_1 \rangle + \mu \langle \vect{c}_1, \vect{z} \rangle = 0 + \mu \langle \vect{c}_1, \vect{z} \rangle = \mu \langle \vect{c}_1, \vect{z} \rangle \]

and

\[ \mu \langle \vect{c}_1, \vect{z} \rangle = 0. \]

Proposition 1: Let $\vect{r}_1$ and $\vect{r}_2$ be distinct rays of $P$. Then the following statements are equivalent: a) $\vect{r}_1$ and $\vect{r}_2$ are adjacent extreme rays (see Section Further Notation and Terminology); b) $\vect{r}_1$ and $\vect{r}_2$ are extreme rays and the rank of the system composed by the constraints saturated by both $\vect{r}_1$ and $\vect{r}_2$ is equal to $d - 2$, where $d$ is the rank of the system of constraints.

In fact, let $F$ be the system of generators that saturate the constraints saturated by both $\vect{r}_1$ and $\vect{r}_2$. If b) holds, the set $F$ is 2-dimensional and $\vect{r}_1$ and $\vect{r}_2$ generate this set. So, every generator $\vect{x}$ of $F$ can be built as a combination of $\vect{r}_1$ and $\vect{r}_2$, i.e.

\[ \vect{x} = \lambda \vect{r}_1 + \mu \vect{r}_2. \]

This combination is non-negative because there exists at least a constraint $c$ saturated by $\vect{r}_1$ and not $\vect{r}_2$ (or vice versa) (because they are distinct) for which

\[ \langle \vect{c}, \vect{x} \rangle \geq 0 \]

and

\[ \langle \vect{c}, \vect{x} \rangle = \lambda \langle \vect{c}, \vect{r}_1 \rangle (or = \mu \langle \vect{c}, \vect{r}_2 \rangle). \]

So, there is no other extreme ray in $F$ and a) holds. Otherwise, if b) does not hold, the rank of the system generated by the constraints saturated by both $\vect{r}_1$ and $\vect{r}_2$ is equal to $d - k$, with k >= 3, the set $F$ is k -dimensional and at least k extreme rays are necessary to generate $F$. So, $\vect{r}_1$ and $\vect{r}_2$ are not adjacent and a) does not hold.

Proposition 2: When we build the new system of generators starting from a system $A$ of constraints of $P$, if $\vect{c}$ is the constraint to add to $A$ and all lines of $P$ saturate $\vect{c}$, the new set of rays is the union of those rays that saturate, of those that satisfy and of a set $\overline Q$ of rays such that each of them

  1. lies on the hyper-plane represented by the k-th constraint,
  2. is a positive combination of two adjacent rays $\vect{r}_1$ and $\vect{r}_2$ such that the first one satisfies the constraint and the other does not satisfy it. If the adjacency property is not taken in account, the new set of rays is not irredundant, in general.

In fact, if $\vect{r}_1$ and $\vect{r}_2$ are not adjacent, the rank of the system composed by the constraints saturated by both $\vect{r}_1$ and $\vect{r}_2$ is different from $d - 2$ (see the previous proposition) or neither $\vect{r}_1$ nor $\vect{r}_2$ are extreme rays. Since the new ray $\vect{r}$ is a combination of $\vect{r}_1$ and $\vect{r}_2$, it saturates the same constraints saturated by both $\vect{r}_1$ and $\vect{r}_2$. If the rank is less than $d - 2$, the rank of the system composed by $\vect{c}$ (that is saturated by $\vect{r}$) and by the constraints of $A$ saturated by $\vect{r}$ is less than $d - 1$. It means that $r$ is redundant (see Section Further Notation and Terminology). If neither $\vect{r}_1$ nor $\vect{r}_2$ are extreme rays, they belong to a 2-dimensional face containing exactly two extreme rays of $P$. These two adjacent rays build a ray equal to $\vect{r}$ and so $\vect{r}$ is redundant.

Definition at line 369 of file Polyhedron_conversion_templates.hh.

References Parma_Polyhedra_Library::Bit_Matrix::add_recycled_row(), Parma_Polyhedra_Library::Scalar_Products::assign(), Parma_Polyhedra_Library::Coefficient_zero(), Parma_Polyhedra_Library::compare(), Parma_Polyhedra_Library::Bit_Row::count_ones(), Parma_Polyhedra_Library::maybe_abandon(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::normalize2(), Parma_Polyhedra_Library::Bit_Matrix::num_columns(), Parma_Polyhedra_Library::Bit_Matrix::num_rows(), PPL_DIRTY_TEMP, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Bit_Matrix::remove_trailing_columns(), Parma_Polyhedra_Library::Bit_Matrix::remove_trailing_rows(), Parma_Polyhedra_Library::Bit_Row::set(), Parma_Polyhedra_Library::Boundary_NS::sgn(), swap(), Parma_Polyhedra_Library::swap(), WEIGHT_ADD_MUL, and WEIGHT_BEGIN.

Referenced by add_and_minimize(), and minimize().

373  {
374  typedef typename Dest_Linear_System::row_type dest_row_type;
375  typedef typename Source_Linear_System::row_type source_row_type;
376 
377  // Constraints and generators must have the same dimension,
378  // otherwise the scalar products below will bomb.
379  PPL_ASSERT(source.space_dimension() == dest.space_dimension());
380  const dimension_type source_space_dim = source.space_dimension();
381  const dimension_type source_num_rows = source.num_rows();
382  const dimension_type source_num_columns = source_space_dim
383  + (source.is_necessarily_closed() ? 1U : 2U);
384 
385 
386  dimension_type dest_num_rows = dest.num_rows();
387  // The rows removed from `dest' will be placed in this vector, so they
388  // can be recycled if needed.
389  std::vector<dest_row_type> recyclable_dest_rows;
390 
391  using std::swap;
392 
393  // By construction, the number of columns of `sat' is the same as
394  // the number of rows of `source'; also, the number of rows of `sat'
395  // is the same as the number of rows of `dest'.
396  PPL_ASSERT(source_num_rows == sat.num_columns());
397  PPL_ASSERT(dest_num_rows == sat.num_rows());
398 
399  // If `start > 0', then we are converting the pending constraints.
400  PPL_ASSERT(start == 0 || start == source.first_pending_row());
401 
402  PPL_DIRTY_TEMP_COEFFICIENT(normalized_sp_i);
403  PPL_DIRTY_TEMP_COEFFICIENT(normalized_sp_o);
404 
405  bool dest_sorted = dest.is_sorted();
406  const dimension_type dest_first_pending_row = dest.first_pending_row();
407 
408  // This will contain the row indexes of the redundant rows of `source'.
409  std::vector<dimension_type> redundant_source_rows;
410 
411 #if PPL_QUICK_ADJ_TEST
412  // This will contain the number of ones in each row of `sat'.
413  PPL_DIRTY_TEMP(std::vector<dimension_type>, sat_num_ones);
414  sat_num_ones.resize(dest_num_rows, 0);
415  for (dimension_type i = dest_num_rows; i-- > 0; ) {
416  sat_num_ones[i] = sat[i].count_ones();
417  }
418 #endif // PPL_QUICK_ADJ_TEST
419 
420  // Converting the sub-system of `source' having rows with indexes
421  // from `start' to the last one (i.e., `source_num_rows' - 1).
422  for (dimension_type k = start; k < source_num_rows; ++k) {
423  const source_row_type& source_k = source[k];
424 
425 #ifndef NDEBUG
426 #if PPL_QUICK_ADJ_TEST
427  for (dimension_type i = dest_num_rows; i-- > 0; ) {
428  PPL_ASSERT(sat_num_ones[i] == sat[i].count_ones());
429  }
430 #endif // PPL_QUICK_ADJ_TEST
431 #endif // NDEBUG
432 
433  // `scalar_prod[i]' will contain the scalar product of the
434  // constraint `source_k' and the generator `dest_rows[i]'. This
435  // product is 0 if and only if the generator saturates the
436  // constraint.
437  PPL_DIRTY_TEMP(std::vector<Coefficient>, scalar_prod);
438  if (dest_num_rows > scalar_prod.size()) {
439  scalar_prod.insert(scalar_prod.end(),
440  dest_num_rows - scalar_prod.size(),
441  Coefficient_zero());
442  }
443  // `index_non_zero' will indicate the first generator in `dest_rows'
444  // that does not saturate the constraint `source_k'.
445  dimension_type index_non_zero = 0;
446  for ( ; index_non_zero < dest_num_rows; ++index_non_zero) {
447  WEIGHT_BEGIN();
448  Scalar_Products::assign(scalar_prod[index_non_zero],
449  source_k,
450  dest.sys.rows[index_non_zero]);
451  WEIGHT_ADD_MUL(17, source_space_dim);
452  if (scalar_prod[index_non_zero] != 0) {
453  // The generator does not saturate the constraint.
454  break;
455  }
456  // Check if the client has requested abandoning all expensive
457  // computations. If so, the exception specified by the client
458  // is thrown now.
459  maybe_abandon();
460  }
461  for (dimension_type i = index_non_zero + 1; i < dest_num_rows; ++i) {
462  WEIGHT_BEGIN();
463  Scalar_Products::assign(scalar_prod[i], source_k, dest.sys.rows[i]);
464  WEIGHT_ADD_MUL(25, source_space_dim);
465  // Check if the client has requested abandoning all expensive
466  // computations. If so, the exception specified by the client
467  // is thrown now.
468  maybe_abandon();
469  }
470 
471  // We first treat the case when `index_non_zero' is less than
472  // `num_lines_or_equalities', i.e., when the generator that
473  // does not saturate the constraint `source_k' is a line.
474  // The other case (described later) is when all the lines
475  // in `dest_rows' (i.e., all the rows having indexes less than
476  // `num_lines_or_equalities') do saturate the constraint.
477 
478  if (index_non_zero < num_lines_or_equalities) {
479  // Since the generator `dest_rows[index_non_zero]' does not saturate
480  // the constraint `source_k', it can no longer be a line
481  // (see saturation rule in Section \ref prelims).
482  // Therefore, we first transform it to a ray.
483  dest.sys.rows[index_non_zero].set_is_ray_or_point_or_inequality();
484  // Of the two possible choices, we select the ray satisfying
485  // the constraint (namely, the ray whose scalar product
486  // with the constraint gives a positive result).
487  if (scalar_prod[index_non_zero] < 0) {
488  // The ray `dest_rows[index_non_zero]' lies on the wrong half-space:
489  // we change it to have the opposite direction.
490  neg_assign(scalar_prod[index_non_zero]);
491  neg_assign(dest.sys.rows[index_non_zero].expr);
492  // The modified row may still not be OK(), so don't assert OK here.
493  // They are all checked at the end of this function.
494  }
495  // Having changed a line to a ray, we set `dest_rows' to be a
496  // non-sorted system, we decrement the number of lines of `dest_rows'
497  // and, if necessary, we move the new ray below all the remaining lines.
498  dest_sorted = false;
499  --num_lines_or_equalities;
500  if (index_non_zero != num_lines_or_equalities) {
501  swap(dest.sys.rows[index_non_zero],
502  dest.sys.rows[num_lines_or_equalities]);
503  swap(scalar_prod[index_non_zero],
504  scalar_prod[num_lines_or_equalities]);
505  }
506  const dest_row_type& dest_nle = dest.sys.rows[num_lines_or_equalities];
507 
508  // Computing the new lineality space.
509  // Since each line must lie on the hyper-plane corresponding to
510  // the constraint `source_k', the scalar product between
511  // the line and the constraint must be 0.
512  // This property already holds for the lines having indexes
513  // between 0 and `index_non_zero' - 1.
514  // We have to consider the remaining lines, having indexes
515  // between `index_non_zero' and `num_lines_or_equalities' - 1.
516  // Each line that does not saturate the constraint has to be
517  // linearly combined with generator `dest_nle' so that the
518  // resulting new line saturates the constraint.
519  // Note that, by Observation 1 above, the resulting new line
520  // will still saturate all the constraints that were saturated by
521  // the old line.
522 
523  Coefficient& scalar_prod_nle = scalar_prod[num_lines_or_equalities];
524  PPL_ASSERT(scalar_prod_nle != 0);
525  for (dimension_type
526  i = index_non_zero; i < num_lines_or_equalities; ++i) {
527  if (scalar_prod[i] != 0) {
528  // The following fragment optimizes the computation of
529  //
530  // <CODE>
531  // Coefficient scale = scalar_prod[i];
532  // scale.gcd_assign(scalar_prod_nle);
533  // Coefficient normalized_sp_i = scalar_prod[i] / scale;
534  // Coefficient normalized_sp_n = scalar_prod_nle / scale;
535  // for (dimension_type c = dest_num_columns; c-- > 0; ) {
536  // dest[i][c] *= normalized_sp_n;
537  // dest[i][c] -= normalized_sp_i * dest_nle[c];
538  // }
539  // </CODE>
540  normalize2(scalar_prod[i],
541  scalar_prod_nle,
542  normalized_sp_i,
543  normalized_sp_o);
544  dest_row_type& dest_i = dest.sys.rows[i];
545  neg_assign(normalized_sp_i);
546  dest_i.expr.linear_combine(dest_nle.expr,
547  normalized_sp_o, normalized_sp_i);
548  dest_i.strong_normalize();
549  // The modified row may still not be OK(), so don't assert OK here.
550  // They are all checked at the end of this function.
551  scalar_prod[i] = 0;
552  // dest_sorted has already been set to false.
553  }
554  }
555 
556  // Computing the new pointed cone.
557  // Similarly to what we have done during the computation of
558  // the lineality space, we consider all the remaining rays
559  // (having indexes strictly greater than `num_lines_or_equalities')
560  // that do not saturate the constraint `source_k'. These rays
561  // are positively combined with the ray `dest_nle' so that the
562  // resulting new rays saturate the constraint.
563  for (dimension_type
564  i = num_lines_or_equalities + 1; i < dest_num_rows; ++i) {
565  if (scalar_prod[i] != 0) {
566  // The following fragment optimizes the computation of
567  //
568  // <CODE>
569  // Coefficient scale = scalar_prod[i];
570  // scale.gcd_assign(scalar_prod_nle);
571  // Coefficient normalized_sp_i = scalar_prod[i] / scale;
572  // Coefficient normalized_sp_n = scalar_prod_nle / scale;
573  // for (dimension_type c = dest_num_columns; c-- > 0; ) {
574  // dest[i][c] *= normalized_sp_n;
575  // dest[i][c] -= normalized_sp_i * dest_nle[c];
576  // }
577  // </CODE>
578  normalize2(scalar_prod[i],
579  scalar_prod_nle,
580  normalized_sp_i,
581  normalized_sp_o);
582  dest_row_type& dest_i = dest.sys.rows[i];
583  WEIGHT_BEGIN();
584  neg_assign(normalized_sp_i);
585  dest_i.expr.linear_combine(dest_nle.expr,
586  normalized_sp_o, normalized_sp_i);
587  dest_i.strong_normalize();
588  // The modified row may still not be OK(), so don't assert OK here.
589  // They are all checked at the end of this function.
590  scalar_prod[i] = 0;
591  // `dest_sorted' has already been set to false.
592  WEIGHT_ADD_MUL(41, source_space_dim);
593  }
594  // Check if the client has requested abandoning all expensive
595  // computations. If so, the exception specified by the client
596  // is thrown now.
597  maybe_abandon();
598  }
599  // Since the `scalar_prod_nle' is positive (by construction), it
600  // does not saturate the constraint `source_k'. Therefore, if
601  // the constraint is an inequality, we set to 1 the
602  // corresponding element of `sat' ...
603  Bit_Row& sat_nle = sat[num_lines_or_equalities];
604  if (source_k.is_ray_or_point_or_inequality()) {
605  sat_nle.set(k - redundant_source_rows.size());
606 #if PPL_QUICK_ADJ_TEST
607  ++sat_num_ones[num_lines_or_equalities];
608 #endif // PPL_QUICK_ADJ_TEST
609  }
610  else {
611  // ... otherwise, the constraint is an equality which is
612  // violated by the generator `dest_nle': the generator has to be
613  // removed from `dest_rows'.
614  --dest_num_rows;
615  swap(dest.sys.rows[num_lines_or_equalities],
616  dest.sys.rows[dest_num_rows]);
617  recyclable_dest_rows.resize(recyclable_dest_rows.size() + 1);
618  swap(dest.sys.rows.back(), recyclable_dest_rows.back());
619  dest.sys.rows.pop_back();
620  PPL_ASSERT(dest_num_rows == dest.sys.rows.size());
621 
622  swap(scalar_prod_nle, scalar_prod[dest_num_rows]);
623  swap(sat_nle, sat[dest_num_rows]);
624 #if PPL_QUICK_ADJ_TEST
625  swap(sat_num_ones[num_lines_or_equalities],
626  sat_num_ones[dest_num_rows]);
627 #endif // PPL_QUICK_ADJ_TEST
628  // dest_sorted has already been set to false.
629  }
630  // Finished handling the line or equality case:
631  // continue with next `k'.
632  continue;
633  }
634 
635  // Here all the lines in `dest_rows' saturate the constraint `source_k'.
636  PPL_ASSERT(index_non_zero >= num_lines_or_equalities);
637  // First, we reorder the generators in `dest_rows' as follows:
638  // -# all the lines should have indexes between 0 and
639  // `num_lines_or_equalities' - 1 (this already holds);
640  // -# all the rays that saturate the constraint should have
641  // indexes between `num_lines_or_equalities' and
642  // `lines_or_equal_bound' - 1; these rays form the set Q=.
643  // -# all the rays that have a positive scalar product with the
644  // constraint should have indexes between `lines_or_equal_bound'
645  // and `sup_bound' - 1; these rays form the set Q+.
646  // -# all the rays that have a negative scalar product with the
647  // constraint should have indexes between `sup_bound' and
648  // `dest_num_rows' - 1; these rays form the set Q-.
649  dimension_type lines_or_equal_bound = num_lines_or_equalities;
650  dimension_type inf_bound = dest_num_rows;
651  // While we find saturating generators, we simply increment
652  // `lines_or_equal_bound'.
653  while (inf_bound > lines_or_equal_bound
654  && scalar_prod[lines_or_equal_bound] == 0) {
655  ++lines_or_equal_bound;
656  }
657  dimension_type sup_bound = lines_or_equal_bound;
658  while (inf_bound > sup_bound) {
659  const int sp_sign = sgn(scalar_prod[sup_bound]);
660  if (sp_sign == 0) {
661  // This generator has to be moved in Q=.
662  swap(dest.sys.rows[sup_bound], dest.sys.rows[lines_or_equal_bound]);
663  swap(scalar_prod[sup_bound], scalar_prod[lines_or_equal_bound]);
664  swap(sat[sup_bound], sat[lines_or_equal_bound]);
665 #if PPL_QUICK_ADJ_TEST
666  swap(sat_num_ones[sup_bound], sat_num_ones[lines_or_equal_bound]);
667 #endif // PPL_QUICK_ADJ_TEST
668  ++lines_or_equal_bound;
669  ++sup_bound;
670  dest_sorted = false;
671  }
672  else if (sp_sign < 0) {
673  // This generator has to be moved in Q-.
674  --inf_bound;
675  swap(dest.sys.rows[sup_bound], dest.sys.rows[inf_bound]);
676  swap(sat[sup_bound], sat[inf_bound]);
677  swap(scalar_prod[sup_bound], scalar_prod[inf_bound]);
678 #if PPL_QUICK_ADJ_TEST
679  swap(sat_num_ones[sup_bound], sat_num_ones[inf_bound]);
680 #endif // PPL_QUICK_ADJ_TEST
681  dest_sorted = false;
682  }
683  else {
684  // sp_sign > 0: this generator has to be moved in Q+.
685  ++sup_bound;
686  }
687  }
688 
689  if (sup_bound == dest_num_rows) {
690  // Here the set Q- is empty.
691  // If the constraint is an inequality, then all the generators
692  // in Q= and Q+ satisfy the constraint. The constraint is redundant
693  // and it can be safely removed from the constraint system.
694  // This is why the `source' parameter is not declared `const'.
695  if (source_k.is_ray_or_point_or_inequality()) {
696  redundant_source_rows.push_back(k);
697  }
698  else {
699  // The constraint is an equality, so that all the generators
700  // in Q+ violate it. Since the set Q- is empty, we can simply
701  // remove from `dest_rows' all the generators of Q+.
702  PPL_ASSERT(dest_num_rows >= lines_or_equal_bound);
703  while (dest_num_rows != lines_or_equal_bound) {
704  recyclable_dest_rows.resize(recyclable_dest_rows.size() + 1);
705  swap(dest.sys.rows.back(), recyclable_dest_rows.back());
706  dest.sys.rows.pop_back();
707  --dest_num_rows;
708  }
709  PPL_ASSERT(dest_num_rows == dest.sys.rows.size());
710  }
711  // Finished handling the case when Q- is empty:
712  // continue with next `k'.
713  continue;
714  }
715 
716  // The set Q- is not empty, i.e., at least one generator
717  // violates the constraint `source_k'.
718  if (sup_bound == num_lines_or_equalities) {
719  // The set Q+ is empty, so that all generators that satisfy
720  // the constraint also saturate it.
721  // We can simply remove from `dest_rows' all the generators in Q-.
722  PPL_ASSERT(dest_num_rows >= sup_bound);
723  while (dest_num_rows != sup_bound) {
724  recyclable_dest_rows.resize(recyclable_dest_rows.size() + 1);
725  swap(dest.sys.rows.back(), recyclable_dest_rows.back());
726  dest.sys.rows.pop_back();
727  --dest_num_rows;
728  }
729  PPL_ASSERT(dest_num_rows == dest.sys.rows.size());
730  // Finished handling the case when Q+ is empty:
731  // continue with next `k'.
732  continue;
733  }
734 
735  // The sets Q+ and Q- are both non-empty.
736  // The generators of the new pointed cone are all those satisfying
737  // the constraint `source_k' plus a set of new rays enjoying
738  // the following properties:
739  // -# they lie on the hyper-plane represented by the constraint
740  // -# they are obtained as a positive combination of two
741  // adjacent rays, the first taken from Q+ and the second
742  // taken from Q-.
743 
744  const dimension_type bound = dest_num_rows;
745 
746 #if PPL_QUICK_NON_ADJ_TEST
747  // For the quick non-adjacency test, we refer to the definition
748  // of a minimal proper face (see comments in Polyhedron_defs.hh):
749  // an extremal ray saturates at least `n' - `t' - 1 constraints,
750  // where `n' is the dimension of the space and `t' is the dimension
751  // of the lineality space. Since `n == source_num_columns - 1' and
752  // `t == num_lines_or_equalities', we obtain that an extremal ray
753  // saturates at least `source_num_columns - num_lines_or_equalities - 2'
754  // constraints.
755  const dimension_type min_saturators
756  = source_num_columns - num_lines_or_equalities - 2;
757  // NOTE: we are treating the `k'-th constraint.
758  const dimension_type max_saturators = k - redundant_source_rows.size();
759 #endif // PPL_QUICK_NON_ADJ_TEST
760 
761  // In the following loop,
762  // `i' runs through the generators in the set Q+ and
763  // `j' runs through the generators in the set Q-.
764  for (dimension_type i = lines_or_equal_bound; i < sup_bound; ++i) {
765  for (dimension_type j = sup_bound; j < bound; ++j) {
766  // Checking if generators `dest_rows[i]' and `dest_rows[j]' are
767  // adjacent.
768  // If there exist another generator that saturates
769  // all the constraints saturated by both `dest_rows[i]' and
770  // `dest_rows[j]', then they are NOT adjacent.
771  PPL_ASSERT(sat[i].last() == C_Integer<unsigned long>::max
772  || sat[i].last() < k);
773  PPL_ASSERT(sat[j].last() == C_Integer<unsigned long>::max
774  || sat[j].last() < k);
775 
776  // Being the union of `sat[i]' and `sat[j]',
777  // `new_satrow' corresponds to a ray that saturates all the
778  // constraints saturated by both `dest_rows[i]' and
779  // `dest_rows[j]'.
780  Bit_Row new_satrow(sat[i], sat[j]);
781 
782  // Even before actually creating the new ray as a
783  // positive combination of `dest_rows[i]' and `dest_rows[j]',
784  // we exploit saturation information to perform:
785  // - a quick non-adjacency test;
786  // - a quick adjacency test.
787 
788 #if (PPL_QUICK_NON_ADJ_TEST || PPL_QUICK_ADJ_TEST)
789  // Compute the number of common saturators.
790  dimension_type new_satrow_ones = new_satrow.count_ones();
791 #endif // (PPL_QUICK_NON_ADJ_TEST || PPL_QUICK_ADJ_TEST)
792 
793 #if PPL_QUICK_NON_ADJ_TEST
794  const dimension_type num_common_satur
795  = max_saturators - new_satrow_ones;
796  if (num_common_satur < min_saturators) {
797  // Quick non-adjacency test succeded: consider next `j'.
798  continue;
799  }
800 #endif // PPL_QUICK_NON_ADJ_TEST
801 
802 #if PPL_QUICK_ADJ_TEST
803  // If either `sat[i]' or `sat[j]' has exactly one more zeroes
804  // than `new_satrow', then `dest_rows[i]' and `dest_rows[j]'
805  // are adjacent. Equivalently, adjacency holds if `new_satrow_ones'
806  // is equal to 1 plus the maximum of `sat_num_ones[i]' and
807  // `sat_num_ones[j]'.
808  const dimension_type max_ones_i_j
809  = std::max(sat_num_ones[i], sat_num_ones[j]);
810  if (max_ones_i_j + 1 == new_satrow_ones) {
811  // Quick adjacency test succeded: skip the full test.
812  goto are_adjacent;
813  }
814 #endif // PPL_QUICK_ADJ_TEST
815 
816  // Perform the full (combinatorial) adjacency test.
817  {
818  bool redundant = false;
819  WEIGHT_BEGIN();
820  for (dimension_type l = num_lines_or_equalities; l < bound; ++l) {
821  if (l != i && l != j
822  && subset_or_equal(sat[l], new_satrow)) {
823  // Found another generator saturating all the constraints
824  // saturated by both `dest_rows[i]' and `dest_rows[j]'.
825  redundant = true;
826  break;
827  }
828  }
829  PPL_ASSERT(bound >= num_lines_or_equalities);
830  WEIGHT_ADD_MUL(15, bound - num_lines_or_equalities);
831  if (redundant) {
832  // Full non-adjacency test succeded: consider next `j'.
833  continue;
834  }
835  }
836 
837 #if PPL_QUICK_ADJ_TEST
838  are_adjacent:
839 #endif // PPL_QUICK_ADJ_TEST
840  // Adding the new ray to `dest_rows' and the corresponding
841  // saturation row to `sat'.
842  dest_row_type new_row;
843  if (recyclable_dest_rows.empty()) {
844  sat.add_recycled_row(new_satrow);
845 #if PPL_QUICK_ADJ_TEST
846  sat_num_ones.push_back(new_satrow_ones);
847 #endif // PPL_QUICK_ADJ_TEST
848  }
849  else {
850  swap(new_row, recyclable_dest_rows.back());
851  recyclable_dest_rows.pop_back();
852  new_row.set_space_dimension_no_ok(source_space_dim);
853  swap(sat[dest_num_rows], new_satrow);
854 #if PPL_QUICK_ADJ_TEST
855  swap(sat_num_ones[dest_num_rows], new_satrow_ones);
856 #endif // PPL_QUICK_ADJ_TEST
857  }
858 
859  // The following fragment optimizes the computation of
860  //
861  // <CODE>
862  // Coefficient scale = scalar_prod[i];
863  // scale.gcd_assign(scalar_prod[j]);
864  // Coefficient normalized_sp_i = scalar_prod[i] / scale;
865  // Coefficient normalized_sp_j = scalar_prod[j] / scale;
866  // for (dimension_type c = dest_num_columns; c-- > 0; ) {
867  // new_row[c] = normalized_sp_i * dest[j][c];
868  // new_row[c] -= normalized_sp_j * dest[i][c];
869  // }
870  // </CODE>
871  normalize2(scalar_prod[i],
872  scalar_prod[j],
873  normalized_sp_i,
874  normalized_sp_o);
875  WEIGHT_BEGIN();
876 
877  neg_assign(normalized_sp_o);
878  new_row = dest.sys.rows[j];
879  // TODO: Check if the following assertions hold.
880  PPL_ASSERT(normalized_sp_i != 0);
881  PPL_ASSERT(normalized_sp_o != 0);
882  new_row.expr.linear_combine(dest.sys.rows[i].expr,
883  normalized_sp_i, normalized_sp_o);
884 
885  WEIGHT_ADD_MUL(86, source_space_dim);
886  new_row.strong_normalize();
887  // Don't assert new_row.OK() here, because it may fail if
888  // the parameter `dest' contained a row that wasn't ok.
889  // Since we added a new generator to `dest_rows',
890  // we also add a new element to `scalar_prod';
891  // by construction, the new ray lies on the hyper-plane
892  // represented by the constraint `source_k'.
893  // Thus, the added scalar product is 0.
894  PPL_ASSERT(scalar_prod.size() >= dest_num_rows);
895  if (scalar_prod.size() <= dest_num_rows) {
896  scalar_prod.push_back(Coefficient_zero());
897  }
898  else {
899  scalar_prod[dest_num_rows] = Coefficient_zero();
900  }
901  dest.sys.rows.resize(dest.sys.rows.size() + 1);
902  swap(dest.sys.rows.back(), new_row);
903  // Increment the number of generators.
904  ++dest_num_rows;
905  } // End of loop on `j'.
906  // Check if the client has requested abandoning all expensive
907  // computations. If so, the exception specified by the client
908  // is thrown now.
909  maybe_abandon();
910  } // End of loop on `i'.
911  // Now we substitute the rays in Q- (i.e., the rays violating
912  // the constraint) with the newly added rays.
913  dimension_type j;
914  if (source_k.is_ray_or_point_or_inequality()) {
915  // The constraint is an inequality:
916  // the violating generators are those in Q-.
917  j = sup_bound;
918  // For all the generators in Q+, set to 1 the corresponding
919  // entry for the constraint `source_k' in the saturation matrix.
920 
921  // After the removal of redundant rows in `source', the k-th
922  // row will have index `new_k'.
923  const dimension_type new_k = k - redundant_source_rows.size();
924  for (dimension_type l = lines_or_equal_bound;
925  l < sup_bound; ++l) {
926  sat[l].set(new_k);
927 #if PPL_QUICK_ADJ_TEST
928  ++sat_num_ones[l];
929 #endif // PPL_PPL_QUICK_ADJ_TEST
930  }
931  }
932  else {
933  // The constraint is an equality:
934  // the violating generators are those in the union of Q+ and Q-.
935  j = lines_or_equal_bound;
936  }
937  // Swapping the newly added rays
938  // (index `i' running through `dest_num_rows - 1' down-to `bound')
939  // with the generators violating the constraint
940  // (index `j' running through `j' up-to `bound - 1').
941  dimension_type i = dest_num_rows;
942  while (j < bound && i > bound) {
943  --i;
944  swap(dest.sys.rows[i], dest.sys.rows[j]);
945  swap(scalar_prod[i], scalar_prod[j]);
946  swap(sat[i], sat[j]);
947 #if PPL_QUICK_ADJ_TEST
948  swap(sat_num_ones[i], sat_num_ones[j]);
949 #endif // PPL_QUICK_ADJ_TEST
950  ++j;
951  dest_sorted = false;
952  }
953  // Setting the number of generators in `dest':
954  // - if the number of generators violating the constraint
955  // is less than or equal to the number of the newly added
956  // generators, we assign `i' to `dest_num_rows' because
957  // all generators above this index are significant;
958  // - otherwise, we assign `j' to `dest_num_rows' because
959  // all generators below index `j-1' violates the constraint.
960  const dimension_type new_num_rows = (j == bound) ? i : j;
961  PPL_ASSERT(dest_num_rows >= new_num_rows);
962  while (dest_num_rows != new_num_rows) {
963  recyclable_dest_rows.resize(recyclable_dest_rows.size() + 1);
964  swap(dest.sys.rows.back(), recyclable_dest_rows.back());
965  dest.sys.rows.pop_back();
966  --dest_num_rows;
967  }
968  PPL_ASSERT(dest_num_rows == dest.sys.rows.size());
969  } // End of loop on `k'.
970 
971  // We may have identified some redundant constraints in `source',
972  // which have been swapped at the end of the system.
973  if (redundant_source_rows.size() > 0) {
974  source.remove_rows(redundant_source_rows);
975  sat.remove_trailing_columns(redundant_source_rows.size());
976  }
977 
978  // If `start == 0', then `source' was sorted and remained so.
979  // If otherwise `start > 0', then the two sub-system made by the
980  // non-pending rows and the pending rows, respectively, were both sorted.
981  // Thus, the overall system is sorted if and only if either
982  // `start == source_num_rows' (i.e., the second sub-system is empty)
983  // or the row ordering holds for the two rows at the boundary between
984  // the two sub-systems.
985  if (start > 0 && start < source.num_rows()) {
986  source.set_sorted(compare(source[start - 1], source[start]) <= 0);
987  }
988  // There are no longer pending constraints in `source'.
989  source.unset_pending_rows();
990 
991  // We may have identified some redundant rays in `dest_rows',
992  // which have been swapped into recyclable_dest_rows.
993  if (!recyclable_dest_rows.empty()) {
994  const dimension_type num_removed_rows = recyclable_dest_rows.size();
995  sat.remove_trailing_rows(num_removed_rows);
996  }
997  if (dest_sorted) {
998  // If the non-pending generators in `dest' are still declared to be
999  // sorted, then we have to also check for the sortedness of the
1000  // pending generators.
1001  for (dimension_type i = dest_first_pending_row;
1002  i < dest_num_rows; ++i) {
1003  if (compare(dest.sys.rows[i - 1], dest.sys.rows[i]) > 0) {
1004  dest_sorted = false;
1005  break;
1006  }
1007  }
1008  }
1009 #ifndef NDEBUG
1010  // The previous code can modify the rows' fields, exploiting the friendness.
1011  // Check that all rows are OK now.
1012  for (dimension_type i = dest.num_rows(); i-- > 0; ) {
1013  PPL_ASSERT(dest.sys.rows[i].OK());
1014  }
1015 #endif
1016 
1017  dest.sys.index_first_pending = dest.num_rows();
1018  dest.set_sorted(dest_sorted);
1019  PPL_ASSERT(dest.sys.OK());
1020 
1021  return num_lines_or_equalities;
1022 }
void swap(CO_Tree &x, CO_Tree &y)
size_t dimension_type
An unsigned integral type for representing space dimensions.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
void swap(Polyhedron &x, Polyhedron &y)
Swaps x with y.
#define WEIGHT_ADD_MUL(delta, factor)
Definition: globals_defs.hh:90
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
#define WEIGHT_BEGIN()
Definition: globals_defs.hh:81
int compare(const Linear_Expression &x, const Linear_Expression &y)
#define PPL_DIRTY_TEMP(T, id)
void neg_assign(GMP_Integer &x)
Coefficient_traits::const_reference Coefficient_zero()
Returns a const reference to a Coefficient with value 0.
int sgn(Boundary_Type type, const T &x, const Info &info)
void normalize2(Coefficient_traits::const_reference x, Coefficient_traits::const_reference y, Coefficient &n_x, Coefficient &n_y)
If is the GCD of x and y, the values of x and y divided by are assigned to n_x and n_y...
static void assign(Coefficient &z, const Linear_Expression &x, const Linear_Expression &y)
Computes the scalar product of x and y and assigns it to z.
template<typename FP_Format , typename Interval_Info >
void Parma_Polyhedra_Library::Polyhedron::convert_to_integer_expression ( const Linear_Form< Interval< FP_Format, Interval_Info > > &  lf,
const dimension_type  lf_dimension,
Linear_Expression result 
)
staticprotected

Helper function that makes result become a Linear_Expression obtained by normalizing the denominators in lf.

Parameters
lfThe linear form on intervals with floating point boundaries to normalize. It should be the result of an application of static method overapproximate_linear_form.
lf_dimensionMust be the space dimension of lf.
resultUsed to store the result.

This function ignores the upper bound of intervals in lf, so that in fact result can be seen as lf multiplied by a proper normalization constant.

Definition at line 476 of file Polyhedron_templates.hh.

References Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::lcm_assign(), Parma_Polyhedra_Library::numer_denom(), and PPL_DIRTY_TEMP_COEFFICIENT.

Referenced by refine_with_linear_form_inequality().

479  {
480  result = Linear_Expression();
481 
482  typedef Interval<FP_Format, Interval_Info> FP_Interval_Type;
483  std::vector<Coefficient> numerators(lf_dimension+1);
484  std::vector<Coefficient> denominators(lf_dimension+1);
485 
486  // Convert each floating point number to a pair <numerator, denominator>
487  // and compute the lcm of all denominators.
489  lcm = 1;
490  const FP_Interval_Type& b = lf.inhomogeneous_term();
491  // FIXME: are these checks numerator[i] != 0 really necessary?
492  numer_denom(b.lower(), numerators[lf_dimension],
493  denominators[lf_dimension]);
494  if (numerators[lf_dimension] != 0) {
495  lcm_assign(lcm, lcm, denominators[lf_dimension]);
496  }
497 
498  for (dimension_type i = 0; i < lf_dimension; ++i) {
499  const FP_Interval_Type& curr_int = lf.coefficient(Variable(i));
500  numer_denom(curr_int.lower(), numerators[i], denominators[i]);
501  if (numerators[i] != 0) {
502  lcm_assign(lcm, lcm, denominators[i]);
503  }
504  }
505 
506  for (dimension_type i = 0; i < lf_dimension; ++i) {
507  if (numerators[i] != 0) {
508  exact_div_assign(denominators[i], lcm, denominators[i]);
509  numerators[i] *= denominators[i];
510  result += numerators[i] * Variable(i);
511  }
512  }
513 
514  if (numerators[lf_dimension] != 0) {
515  exact_div_assign(denominators[lf_dimension],
516  lcm, denominators[lf_dimension]);
517  numerators[lf_dimension] *= denominators[lf_dimension];
518  result += numerators[lf_dimension];
519  }
520 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
Enable_If< Is_Native_Or_Checked< T >::value, void >::type numer_denom(const T &from, Coefficient &numer, Coefficient &denom)
Extract the numerator and denominator components of from.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
void lcm_assign(GMP_Integer &x, const GMP_Integer &y, const GMP_Integer &z)
void exact_div_assign(Checked_Number< T, Policy > &x, const Checked_Number< T, Policy > &y, const Checked_Number< T, Policy > &z)
template<typename FP_Format , typename Interval_Info >
void Parma_Polyhedra_Library::Polyhedron::convert_to_integer_expressions ( const Linear_Form< Interval< FP_Format, Interval_Info > > &  lf,
const dimension_type  lf_dimension,
Linear_Expression res,
Coefficient res_low_coeff,
Coefficient res_hi_coeff,
Coefficient denominator 
)
staticprotected

Normalization helper function.

Parameters
lfThe linear form on intervals with floating point boundaries to normalize. It should be the result of an application of static method overapproximate_linear_form.
lf_dimensionMust be the space dimension of lf.
resStores the normalized linear form, except its inhomogeneous term.
res_low_coeffStores the lower boundary of the inhomogeneous term of the result.
res_hi_coeffStores the higher boundary of the inhomogeneous term of the result.
denominatorBecomes the common denominator of res_low_coeff, res_hi_coeff and all coefficients in res.

Results are obtained by normalizing denominators in lf, ignoring the upper bounds of variable coefficients in lf.

Definition at line 524 of file Polyhedron_templates.hh.

References Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::lcm_assign(), and Parma_Polyhedra_Library::numer_denom().

Referenced by affine_form_image().

528  {
529  res = Linear_Expression();
530 
531  typedef Interval<FP_Format, Interval_Info> FP_Interval_Type;
532  std::vector<Coefficient> numerators(lf_dimension+2);
533  std::vector<Coefficient> denominators(lf_dimension+2);
534 
535  // Convert each floating point number to a pair <numerator, denominator>
536  // and compute the lcm of all denominators.
537  Coefficient& lcm = denominator;
538  lcm = 1;
539  const FP_Interval_Type& b = lf.inhomogeneous_term();
540  numer_denom(b.lower(), numerators[lf_dimension], denominators[lf_dimension]);
541  // FIXME: are these checks numerator[i] != 0 really necessary?
542  if (numerators[lf_dimension] != 0) {
543  lcm_assign(lcm, lcm, denominators[lf_dimension]);
544  }
545 
546  numer_denom(b.upper(), numerators[lf_dimension+1],
547  denominators[lf_dimension+1]);
548  if (numerators[lf_dimension+1] != 0) {
549  lcm_assign(lcm, lcm, denominators[lf_dimension+1]);
550  }
551 
552  for (dimension_type i = 0; i < lf_dimension; ++i) {
553  const FP_Interval_Type& curr_int = lf.coefficient(Variable(i));
554  numer_denom(curr_int.lower(), numerators[i], denominators[i]);
555  if (numerators[i] != 0) {
556  lcm_assign(lcm, lcm, denominators[i]);
557  }
558  }
559 
560  for (dimension_type i = 0; i < lf_dimension; ++i) {
561  if (numerators[i] != 0) {
562  exact_div_assign(denominators[i], lcm, denominators[i]);
563  numerators[i] *= denominators[i];
564  res += numerators[i] * Variable(i);
565  }
566  }
567 
568  if (numerators[lf_dimension] != 0) {
569  exact_div_assign(denominators[lf_dimension],
570  lcm, denominators[lf_dimension]);
571  numerators[lf_dimension] *= denominators[lf_dimension];
572  res_low_coeff = numerators[lf_dimension];
573  }
574  else {
575  res_low_coeff = 0;
576  }
577 
578  if (numerators[lf_dimension+1] != 0) {
579  exact_div_assign(denominators[lf_dimension+1],
580  lcm, denominators[lf_dimension+1]);
581  numerators[lf_dimension+1] *= denominators[lf_dimension+1];
582  res_hi_coeff = numerators[lf_dimension+1];
583  }
584  else {
585  res_hi_coeff = 0;
586  }
587 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
Enable_If< Is_Native_Or_Checked< T >::value, void >::type numer_denom(const T &from, Coefficient &numer, Coefficient &denom)
Extract the numerator and denominator components of from.
void lcm_assign(GMP_Integer &x, const GMP_Integer &y, const GMP_Integer &z)
void exact_div_assign(Checked_Number< T, Policy > &x, const Checked_Number< T, Policy > &y, const Checked_Number< T, Policy > &z)
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
void Parma_Polyhedra_Library::Polyhedron::difference_assign ( const Polyhedron y)
inline

Same as poly_difference_assign(y).

Definition at line 86 of file Polyhedron_inlines.hh.

References poly_difference_assign().

86  {
88 }
void poly_difference_assign(const Polyhedron &y)
Assigns to *this the poly-difference of *this and y.
void Parma_Polyhedra_Library::Polyhedron::drop_some_non_integer_points ( Complexity_Class  complexity = ANY_COMPLEXITY)
inline

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

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

Definition at line 442 of file Polyhedron_inlines.hh.

Referenced by drop_some_non_integer_points().

442  {
443  const Variables_Set* const p_vs = 0;
444  drop_some_non_integer_points(p_vs, complexity);
445 }
void drop_some_non_integer_points(Complexity_Class complexity=ANY_COMPLEXITY)
Possibly tightens *this by dropping some points with non-integer coordinates.
void Parma_Polyhedra_Library::Polyhedron::drop_some_non_integer_points ( const Variables_Set vars,
Complexity_Class  complexity = ANY_COMPLEXITY 
)
inline

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

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

Definition at line 448 of file Polyhedron_inlines.hh.

References drop_some_non_integer_points().

449  {
450  drop_some_non_integer_points(&vars, complexity);
451 }
void drop_some_non_integer_points(Complexity_Class complexity=ANY_COMPLEXITY)
Possibly tightens *this by dropping some points with non-integer coordinates.
void Parma_Polyhedra_Library::Polyhedron::drop_some_non_integer_points ( const Variables_Set vars_p,
Complexity_Class  complexity 
)
protected

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

Parameters
vars_pWhen nonzero, points with non-integer coordinates for the variables/space-dimensions contained in *vars_p can be discarded.
complexityThe maximal complexity of any algorithms used.
Note
Currently there is no optimality guarantee, not even if complexity is ANY_COMPLEXITY.

Definition at line 2232 of file Polyhedron_nonpublic.cc.

References Parma_Polyhedra_Library::Expression_Hide_Last< T >::all_zeroes(), Parma_Polyhedra_Library::ANY_COMPLEXITY, c, Parma_Polyhedra_Library::Constraint::epsilon_coefficient(), Parma_Polyhedra_Library::Constraint::epsilon_leq_one(), Parma_Polyhedra_Library::Linear_Expression::exact_div_assign(), Parma_Polyhedra_Library::Constraint::expr, Parma_Polyhedra_Library::Constraint::expression(), Parma_Polyhedra_Library::Expression_Hide_Last< T >::gcd(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Variables_Set::insert(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Constraint::is_tautological(), Parma_Polyhedra_Library::Linear_Expression::normalize(), Parma_Polyhedra_Library::Constraint::OK(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Constraint::set_epsilon_coefficient(), Parma_Polyhedra_Library::Linear_Expression::set_inhomogeneous_term(), Parma_Polyhedra_Library::Boundary_NS::sgn(), and Parma_Polyhedra_Library::Constraint::zero_dim_positivity().

2233  {
2234  // There is nothing to do for an empty set of variables.
2235  if (vars_p != 0 && vars_p->empty()) {
2236  return;
2237  }
2238 
2239  // Any empty polyhedron does not contain integer points.
2240  if (marked_empty()) {
2241  return;
2242  }
2243 
2244  // A zero-dimensional, universe polyhedron has, by convention, an
2245  // integer point.
2246  if (space_dim == 0) {
2247  set_empty();
2248  return;
2249  }
2250 
2251  // The constraints (possibly with pending rows) are required.
2252  if (has_pending_generators()) {
2253  // Processing of pending generators is exponential in the worst case.
2254  if (complexity != ANY_COMPLEXITY) {
2255  return;
2256  }
2257  else {
2259  }
2260  }
2261  if (!constraints_are_up_to_date()) {
2262  // Constraints update is exponential in the worst case.
2263  if (complexity != ANY_COMPLEXITY) {
2264  return;
2265  }
2266  else {
2268  }
2269  }
2270  // For NNC polyhedra we need to process any pending constraints.
2272  if (complexity != ANY_COMPLEXITY) {
2273  return;
2274  }
2275  else if (!process_pending_constraints()) {
2276  // We just discovered the polyhedron is empty.
2277  return;
2278  }
2279  }
2280 
2282  PPL_ASSERT(is_necessarily_closed() || !has_pending_constraints());
2283 
2284  bool changed = false;
2286 
2287  const bool con_sys_was_sorted = con_sys.is_sorted();
2288 
2289  Variables_Set other_vars;
2290  if (vars_p != 0) {
2291  // Compute the complement of `*vars_p'.
2292  for (dimension_type i = 0; i < space_dim; ++i) {
2293  if (vars_p->find(i) == vars_p->end()) {
2294  other_vars.insert(Variable(i));
2295  }
2296  }
2297  }
2298 
2299  for (dimension_type j = con_sys.sys.rows.size(); j-- > 0; ) {
2300  Constraint& c = con_sys.sys.rows[j];
2301  if (c.is_tautological()) {
2302  continue;
2303  }
2304  if (!other_vars.empty()) {
2305  // Skip constraints having a nonzero coefficient for a variable
2306  // that does not occurr in the input set.
2307  if (!c.expression().all_zeroes(other_vars)) {
2308  continue;
2309  }
2310  }
2311 
2312  if (!is_necessarily_closed()) {
2313  // Transform all strict inequalities into non-strict ones,
2314  // with the inhomogeneous term incremented by 1.
2315  if (c.epsilon_coefficient() < 0) {
2316  c.set_epsilon_coefficient(0);
2317  Linear_Expression& e = c.expr;
2318  e.set_inhomogeneous_term(e.inhomogeneous_term() - 1);
2319  // Enforce normalization.
2320  // FIXME: is this really necessary?
2321  e.normalize();
2322  PPL_ASSERT(c.OK());
2323  changed = true;
2324  }
2325  }
2326 
2327  // Compute the GCD of all the homogeneous terms.
2328  gcd = c.expression().gcd(1, space_dim + 1);
2329 
2330  if (gcd != 0 && gcd != 1) {
2331  PPL_ASSERT(c.expr.inhomogeneous_term() % gcd != 0);
2332 
2333  // If we have an equality, the polyhedron becomes empty.
2334  if (c.is_equality()) {
2335  set_empty();
2336  return;
2337  }
2338 
2339  // Divide the inhomogeneous coefficients by the GCD.
2340  c.expr.exact_div_assign(gcd, 1, space_dim + 1);
2341 
2343  c_0 = c.expr.inhomogeneous_term();
2344  const int c_0_sign = sgn(c_0);
2345  c_0 /= gcd;
2346  if (c_0_sign < 0) {
2347  --c_0;
2348  }
2349  c.expr.set_inhomogeneous_term(c_0);
2350  PPL_ASSERT(c.OK());
2351  changed = true;
2352  }
2353  }
2354 
2355  con_sys.set_sorted(!changed && con_sys_was_sorted);
2356  PPL_ASSERT(con_sys.sys.OK());
2357 
2358  if (changed) {
2359  if (is_necessarily_closed()) {
2361  }
2362  else {
2364  }
2365  // After changing the system of constraints, the generators
2366  // are no longer up-to-date and the constraints are no longer
2367  // minimized.
2370  }
2371  PPL_ASSERT_HEAVY(OK());
2372 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
void update_constraints() const
Updates constraints starting from generators and minimizes them.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
void insert(const Constraint &c)
Inserts in *this a copy of the constraint c, increasing the number of space dimensions if needed...
bool is_sorted() const
Returns the value of the sortedness flag.
Constraint_System con_sys
The system of constraints.
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
void process_pending_generators() const
Processes the pending generators and obtains a minimized polyhedron.
void set_empty()
Sets status to express that the polyhedron is empty, clearing all corresponding matrices.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
static const Constraint & epsilon_leq_one()
The zero-dimension space constraint (used to implement NNC polyhedra).
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
static const Constraint & zero_dim_positivity()
The true (zero-dimension space) constraint , also known as positivity constraint. ...
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
bool process_pending_constraints() const
Processes the pending constraints and obtains a minimized polyhedron.
void clear_constraints_minimized()
Sets status to express that constraints are no longer minimized.
int sgn(Boundary_Type type, const T &x, const Info &info)
bool has_pending_generators() const
Returns true if there are pending generators.
void set_sorted(bool b)
Sets the sortedness flag of the system to b.
Coefficient c
Definition: PIP_Tree.cc:64
void clear_generators_up_to_date()
Sets status to express that generators are no longer up-to-date.
void Parma_Polyhedra_Library::Polyhedron::expand_space_dimension ( Variable  var,
dimension_type  m 
)

Creates m copies of the space dimension corresponding to var.

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

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

Definition at line 401 of file Polyhedron_chdims.cc.

References Parma_Polyhedra_Library::add_mul_assign(), Parma_Polyhedra_Library::Constraint_System::begin(), c, Parma_Polyhedra_Library::check_space_dimension_overflow(), Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::Coefficient_zero(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Constraint::expr, Parma_Polyhedra_Library::max_space_dimension(), Parma_Polyhedra_Library::Constraint::OK(), Parma_Polyhedra_Library::Linear_Expression::set_coefficient(), Parma_Polyhedra_Library::Variable::space_dimension(), and Parma_Polyhedra_Library::Constraint_System::topology().

401  {
402  // `var' should be one of the dimensions of the vector space.
403  if (var.space_dimension() > space_dim) {
404  throw_dimension_incompatible("expand_space_dimension(v, m)", "v", var);
405  }
406 
407  // The space dimension of the resulting polyhedron should not
408  // overflow the maximum allowed space dimension.
410  topology(),
411  "expand_dimension(v, m)",
412  "adding m new space dimensions exceeds "
413  "the maximum allowed space dimension");
414 
415  // Nothing to do, if no dimensions must be added.
416  if (m == 0) {
417  return;
418  }
419 
420  // Keep track of the dimension before adding the new ones.
421  const dimension_type old_dim = space_dim;
422 
423  // Add the required new dimensions.
425 
426  const Constraint_System& cs = constraints();
427  Constraint_System new_constraints(cs.topology());
428  for (Constraint_System::const_iterator i = cs.begin(),
429  cs_end = cs.end(); i != cs_end; ++i) {
430  const Constraint& c = *i;
431 
432  Coefficient_traits::const_reference coeff = c.coefficient(var);
433 
434  // If `c' does not constrain `var', skip it.
435  if (coeff == 0) {
436  continue;
437  }
438 
439  Constraint c_template = c;
440  c_template.expr.set_coefficient(var, Coefficient_zero());
441 
442  // Each relevant constraint results in `m' new constraints.
443  for (dimension_type dst_d = old_dim; dst_d < old_dim+m; ++dst_d) {
444  Constraint new_c = c_template;
445  add_mul_assign(new_c.expr, coeff, Variable(dst_d));
446  PPL_ASSERT(new_c.OK());
447  new_constraints.insert(new_c, Recycle_Input());
448  }
449  }
450  add_recycled_constraints(new_constraints);
451  PPL_ASSERT_HEAVY(OK());
452 }
void add_space_dimensions_and_embed(dimension_type m)
Adds m new space dimensions and embeds the old polyhedron in the new vector space.
size_t dimension_type
An unsigned integral type for representing space dimensions.
void add_mul_assign(GMP_Integer &x, const GMP_Integer &y, const GMP_Integer &z)
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
const Constraint_System & constraints() const
Returns the system of constraints.
void add_recycled_constraints(Constraint_System &cs)
Adds the constraints in cs to the system of constraints of *this (without minimizing the result)...
Topology topology() const
Returns the topological kind of the polyhedron.
static dimension_type check_space_dimension_overflow(dimension_type dim, dimension_type max, const Topology topol, const char *method, const char *reason)
static dimension_type max_space_dimension()
Returns the maximum space dimension all kinds of Polyhedron can handle.
Coefficient_traits::const_reference Coefficient_zero()
Returns a const reference to a Coefficient with value 0.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
Coefficient c
Definition: PIP_Tree.cc:64
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Constraint_System_const_iterator const_iterator
PPL::memory_size_type Parma_Polyhedra_Library::Polyhedron::external_memory_in_bytes ( ) const

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

Definition at line 4049 of file Polyhedron_public.cc.

Referenced by total_memory_in_bytes().

4049  {
4050  return
4055 }
Generator_System gen_sys
The system of generators.
memory_size_type external_memory_in_bytes() const
Returns the size in bytes of the memory managed by *this.
Constraint_System con_sys
The system of constraints.
Bit_Matrix sat_g
The saturation matrix having generators on its columns.
memory_size_type external_memory_in_bytes() const
Returns the size in bytes of the memory managed by *this.
memory_size_type external_memory_in_bytes() const
Returns the size in bytes of the memory managed by *this.
Definition: Bit_Matrix.cc:225
Bit_Matrix sat_c
The saturation matrix having constraints on its columns.
void Parma_Polyhedra_Library::Polyhedron::finalize ( )
static

Finalizes the class.

Definition at line 54 of file Polyhedron_public.cc.

Referenced by Parma_Polyhedra_Library::Init::~Init().

54  {
55  delete [] simplify_num_saturators_p;
58 }
static dimension_type * simplify_num_saturators_p
Pointer to an array used by simplify().
static size_t simplify_num_saturators_size
Dimension of an array used by simplify().
void Parma_Polyhedra_Library::Polyhedron::fold_space_dimensions ( const Variables_Set vars,
Variable  dest 
)

Folds the space dimensions in vars into dest.

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

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

Definition at line 455 of file Polyhedron_chdims.cc.

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

456  {
457  // TODO: this implementation is _really_ an executable specification.
458 
459  // `dest' should be one of the dimensions of the polyhedron.
460  if (dest.space_dimension() > space_dim) {
461  throw_dimension_incompatible("fold_space_dimensions(vs, v)", "v", dest);
462  }
463 
464  // The folding of no dimensions is a no-op.
465  if (vars.empty()) {
466  return;
467  }
468 
469  // All variables in `vars' should be dimensions of the polyhedron.
470  if (vars.space_dimension() > space_dim) {
471  throw_dimension_incompatible("fold_space_dimensions(vs, v)",
472  "vs.space_dimension()",
473  vars.space_dimension());
474  }
475 
476  // Moreover, `dest.id()' should not occur in `vars'.
477  if (vars.find(dest.id()) != vars.end()) {
478  throw_invalid_argument("fold_space_dimensions(vs, v)",
479  "v should not occur in vs");
480  }
481 
482  // All of the affine images we are going to compute are not invertible,
483  // hence we will need to compute the generators of the polyhedron.
484  // Since we keep taking copies, make sure that a single conversion
485  // from constraints to generators is computed.
486  (void) generators();
487  // Having generators, we now know if the polyhedron is empty:
488  // in that case, folding is equivalent to just removing space dimensions.
489  if (!marked_empty()) {
490  for (Variables_Set::const_iterator i = vars.begin(),
491  vs_end = vars.end(); i != vs_end; ++i) {
492  Polyhedron copy = *this;
493  copy.affine_image(dest, Linear_Expression(Variable(*i)));
494  poly_hull_assign(copy);
495  }
496  }
498  PPL_ASSERT_HEAVY(OK());
499 }
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
void remove_space_dimensions(const Variables_Set &vars)
Removes all the specified dimensions from the vector space.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
void throw_invalid_argument(const char *method, const char *reason) const
const Generator_System & generators() const
Returns the system of generators.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
void poly_hull_assign(const Polyhedron &y)
Assigns to *this the poly-hull of *this and y.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
bool Parma_Polyhedra_Library::Polyhedron::frequency ( const Linear_Expression expr,
Coefficient freq_n,
Coefficient freq_d,
Coefficient val_n,
Coefficient val_d 
) const

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

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

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

Definition at line 3732 of file Polyhedron_public.cc.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Generator::expr, Parma_Polyhedra_Library::Scalar_Products::homogeneous_assign(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Generator::is_closure_point(), Parma_Polyhedra_Library::Generator::is_line_or_ray(), Parma_Polyhedra_Library::Generator::is_point(), PPL_DIRTY_TEMP, PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::Boundary_NS::sgn(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and value.

3734  {
3735  // The dimension of `expr' must be at most the dimension of *this.
3736  if (space_dim < expr.space_dimension()) {
3737  throw_dimension_incompatible("frequency(e, ...)", "e", expr);
3738  }
3739 
3740  // If the `expr' has a constant value, then the frequency
3741  // `freq_n' is 0. Otherwise the values for \p expr are not discrete
3742  // and we return false.
3743 
3744  // Space dimension is 0: if empty, then return false;
3745  // otherwise the frequency is 1 and the value is 0.
3746  if (space_dim == 0) {
3747  if (is_empty()) {
3748  return false;
3749  }
3750  freq_n = 0;
3751  freq_d = 1;
3752  val_n = expr.inhomogeneous_term();
3753  val_d = 1;
3754  return true;
3755  }
3756 
3757  // For an empty polyhedron, we simply return false.
3758  if (marked_empty()
3761  return false;
3762  }
3763 
3764  // The polyhedron has updated, possibly pending generators.
3765  // The following loop will iterate through the generator
3766  // to see if `expr' has a constant value.
3767  PPL_DIRTY_TEMP(mpq_class, value);
3768 
3769  // True if we have no other candidate value to compare with.
3770  bool first_candidate = true;
3771 
3773  PPL_DIRTY_TEMP(mpq_class, candidate);
3774  for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) {
3775  const Generator& gen_sys_i = gen_sys[i];
3776  Scalar_Products::homogeneous_assign(sp, expr, gen_sys_i);
3777  // Lines and rays in `*this' can cause `expr' to be non-constant.
3778  if (gen_sys_i.is_line_or_ray()) {
3779  const int sp_sign = sgn(sp);
3780  if (sp_sign != 0) {
3781  // `expr' is unbounded in `*this'.
3782  return false;
3783  }
3784  }
3785  else {
3786  // We have a point or a closure point.
3787  PPL_ASSERT(gen_sys_i.is_point() || gen_sys_i.is_closure_point());
3788  // Notice that we are ignoring the constant term in `expr' here.
3789  // We will add it to the value if there is a constant value.
3790  assign_r(candidate.get_num(), sp, ROUND_NOT_NEEDED);
3791  assign_r(candidate.get_den(), gen_sys_i.expr.inhomogeneous_term(), ROUND_NOT_NEEDED);
3792  candidate.canonicalize();
3793  if (first_candidate) {
3794  // We have a (new) candidate value.
3795  first_candidate = false;
3796  value = candidate;
3797  }
3798  else if (candidate != value) {
3799  return false;
3800  }
3801  }
3802  }
3803 
3804  // Add in the constant term in `expr'.
3805  PPL_DIRTY_TEMP(mpz_class, n);
3807  value += n;
3808  val_n = value.get_num();
3809  val_d = value.get_den();
3810 
3811  freq_n = 0;
3812  freq_d = 1;
3813  return true;
3814 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
A line, ray, point or closure point.
Linear_Expression expr
The linear expression encoding *this.
bool is_empty() const
Returns true if and only if *this is an empty polyhedron.
bool is_line_or_ray() const
Returns true if and only if *this is a line or a ray.
Coefficient_traits::const_reference inhomogeneous_term() const
Returns the inhomogeneous term of *this.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
bool update_generators() const
Updates generators starting from constraints and minimizes them.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
Coefficient value
Definition: PIP_Tree.cc:618
bool is_point() const
Returns true if and only if *this is a point.
#define PPL_DIRTY_TEMP(T, id)
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool process_pending_constraints() const
Processes the pending constraints and obtains a minimized polyhedron.
int sgn(Boundary_Type type, const T &x, const Info &info)
static void homogeneous_assign(Coefficient &z, const Linear_Expression &x, const Linear_Expression &y)
Computes the homogeneous scalar product of x and y, where the inhomogeneous terms are ignored...
bool is_closure_point() const
Returns true if and only if *this is a closure point.
void Parma_Polyhedra_Library::Polyhedron::generalized_affine_image ( Variable  var,
Relation_Symbol  relsym,
const Linear_Expression expr,
Coefficient_traits::const_reference  denominator = Coefficient_one() 
)

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

Parameters
varThe left hand side variable of the generalized affine relation;
relsymThe relation symbol;
exprThe numerator of the right hand side affine expression;
denominatorThe denominator of the right hand side affine expression (optional argument with default value 1).
Exceptions
std::invalid_argumentThrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a space dimension of *this or if *this is a C_Polyhedron and relsym is a strict relation symbol.

Definition at line 3082 of file Polyhedron_public.cc.

References Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::Generator::expr, Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Generator::is_point(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::Linear_Expression::normalize(), Parma_Polyhedra_Library::NOT_EQUAL, Parma_Polyhedra_Library::Generator::OK(), Parma_Polyhedra_Library::Generator::set_epsilon_coefficient(), Parma_Polyhedra_Library::Variable::space_dimension(), and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

3085  {
3086  // The denominator cannot be zero.
3087  if (denominator == 0) {
3088  throw_invalid_argument("generalized_affine_image(v, r, e, d)", "d == 0");
3089  }
3090 
3091  // Dimension-compatibility checks.
3092  // The dimension of `expr' should not be greater than the dimension
3093  // of `*this'.
3094  if (space_dim < expr.space_dimension()) {
3095  throw_dimension_incompatible("generalized_affine_image(v, r, e, d)",
3096  "e", expr);
3097  }
3098  // `var' should be one of the dimensions of the polyhedron.
3099  const dimension_type var_space_dim = var.space_dimension();
3100  if (space_dim < var_space_dim) {
3101  throw_dimension_incompatible("generalized_affine_image(v, r, e, d)",
3102  "v", var);
3103  }
3104 
3105  // Strict relation symbols are only admitted for NNC polyhedra.
3106  if (is_necessarily_closed()
3107  && (relsym == LESS_THAN || relsym == GREATER_THAN)) {
3108  throw_invalid_argument("generalized_affine_image(v, r, e, d)",
3109  "r is a strict relation symbol");
3110  }
3111  // The relation symbol cannot be a disequality.
3112  if (relsym == NOT_EQUAL) {
3113  throw_invalid_argument("generalized_affine_image(v, r, e, d)",
3114  "r is the disequality relation symbol");
3115  }
3116 
3117  // First compute the affine image.
3118  affine_image(var, expr, denominator);
3119 
3120  if (relsym == EQUAL) {
3121  // The affine relation is indeed an affine function.
3122  return;
3123  }
3124  // Any image of an empty polyhedron is empty.
3125  // Note: DO check for emptiness here, as we will later add a ray.
3126  if (is_empty()) {
3127  return;
3128  }
3129 
3130  switch (relsym) {
3131  case LESS_OR_EQUAL:
3132  add_generator(ray(-var));
3133  break;
3134  case GREATER_OR_EQUAL:
3135  add_generator(ray(var));
3136  break;
3137  case LESS_THAN:
3138  // Intentionally fall through.
3139  case GREATER_THAN:
3140  {
3141  // The relation symbol is strict.
3142  PPL_ASSERT(!is_necessarily_closed());
3143  // While adding the ray, we minimize the generators
3144  // in order to avoid adding too many redundant generators later.
3145  add_generator(ray((relsym == GREATER_THAN) ? var : -var));
3146  minimize();
3147 
3148  // We split each point of the generator system into two generators:
3149  // a closure point, having the same coordinates of the given point,
3150  // and another point, having the same coordinates for all but the
3151  // `var' dimension, which is displaced along the direction of the
3152  // newly introduced ray.
3153  for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) {
3154  const Generator& gen_i = gen_sys.sys.rows[i];
3155  if (gen_i.is_point()) {
3156  // Add a copy of `gen_i' at the end of the system.
3157  // Note: copying is really meant, to avoid undefined behavior.
3158  gen_sys.sys.rows.push_back(Generator(gen_i));
3159  // Note: (re-)compute references (invalidated by push_back).
3160  Generator& old_gen = gen_sys.sys.rows[i];
3161  Generator& new_gen = gen_sys.sys.rows.back();
3162  // Transform `old_gen' into a closure point.
3163  old_gen.set_epsilon_coefficient(0);
3164  old_gen.expr.normalize();
3165  PPL_ASSERT(old_gen.OK());
3166  // Displace `new_gen' by `var' (i.e., along the new ray).
3167  if (relsym == GREATER_THAN) {
3168  new_gen.expr += var;
3169  }
3170  else {
3171  new_gen.expr -= var;
3172  }
3173  new_gen.expr.normalize();
3174  PPL_ASSERT(new_gen.OK());
3175  }
3176  }
3177  // Sortedness no longer hold.
3178  gen_sys.set_sorted(false);
3180  PPL_ASSERT(gen_sys.sys.OK());
3181 
3186  }
3187  break;
3188  default:
3189  // The EQUAL and NOT_EQUAL cases have been already dealt with.
3190  PPL_UNREACHABLE;
3191  break;
3192  }
3193  PPL_ASSERT_HEAVY(OK());
3194 }
bool minimize() const
Applies (weak) minimization to both the constraints and generators.
void clear_constraints_up_to_date()
Sets status to express that constraints are no longer up-to-date.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
A line, ray, point or closure point.
Linear_Expression expr
The linear expression encoding *this.
bool is_empty() const
Returns true if and only if *this is an empty polyhedron.
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 to the affine expr...
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void throw_invalid_argument(const char *method, const char *reason) const
bool OK() const
Checks if all the invariants are satisfied.
Definition: Generator.cc:432
bool is_point() const
Returns true if and only if *this is a point.
void add_generator(const Generator &g)
Adds a copy of generator g to the system of generators of *this (without minimizing the result)...
dimension_type space_dim
The number of dimensions of the enclosing vector space.
void set_sorted(bool b)
Sets the sortedness flag of the system to b.
void set_epsilon_coefficient(Coefficient_traits::const_reference n)
Sets the epsilon coefficient to n. The generator must be NNC.
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
void clear_sat_g_up_to_date()
Sets status to express that sat_g is no longer up-to-date.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
void clear_sat_c_up_to_date()
Sets status to express that sat_c is no longer up-to-date.
void unset_pending_rows()
Sets the index to indicate that the system has no pending rows.
void clear_generators_minimized()
Sets status to express that generators are no longer minimized.
void Parma_Polyhedra_Library::Polyhedron::generalized_affine_image ( const Linear_Expression lhs,
Relation_Symbol  relsym,
const Linear_Expression rhs 
)

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

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

Definition at line 3306 of file Polyhedron_public.cc.

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

3308  {
3309  // Dimension-compatibility checks.
3310  // The dimension of `lhs' should not be greater than the dimension
3311  // of `*this'.
3312  dimension_type lhs_space_dim = lhs.space_dimension();
3313  if (space_dim < lhs_space_dim) {
3314  throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
3315  "e1", lhs);
3316  }
3317  // The dimension of `rhs' should not be greater than the dimension
3318  // of `*this'.
3319  const dimension_type rhs_space_dim = rhs.space_dimension();
3320  if (space_dim < rhs_space_dim) {
3321  throw_dimension_incompatible("generalized_affine_image(e1, r, e2)",
3322  "e2", rhs);
3323  }
3324 
3325  // Strict relation symbols are only admitted for NNC polyhedra.
3326  if (is_necessarily_closed()
3327  && (relsym == LESS_THAN || relsym == GREATER_THAN)) {
3328  throw_invalid_argument("generalized_affine_image(e1, r, e2)",
3329  "r is a strict relation symbol");
3330  }
3331  // The relation symbol cannot be a disequality.
3332  if (relsym == NOT_EQUAL) {
3333  throw_invalid_argument("generalized_affine_image(e1, r, e2)",
3334  "r is the disequality relation symbol");
3335  }
3336  // Any image of an empty polyhedron is empty.
3337  if (marked_empty()) {
3338  return;
3339  }
3340 
3341  // Compute the actual space dimension of `lhs',
3342  // i.e., the highest dimension having a non-zero coefficient in `lhs'.
3343  lhs_space_dim = lhs.last_nonzero();
3344 
3345  // If all variables have a zero coefficient, then `lhs' is a constant:
3346  // we can simply add the constraint `lhs relsym rhs'.
3347  if (lhs_space_dim == 0) {
3348  switch (relsym) {
3349  case LESS_THAN:
3350  refine_no_check(lhs < rhs);
3351  break;
3352  case LESS_OR_EQUAL:
3353  refine_no_check(lhs <= rhs);
3354  break;
3355  case EQUAL:
3356  refine_no_check(lhs == rhs);
3357  break;
3358  case GREATER_OR_EQUAL:
3359  refine_no_check(lhs >= rhs);
3360  break;
3361  case GREATER_THAN:
3362  refine_no_check(lhs > rhs);
3363  break;
3364  case NOT_EQUAL:
3365  // The NOT_EQUAL case has been already dealt with.
3366  PPL_UNREACHABLE;
3367  break;
3368  }
3369  return;
3370  }
3371 
3372  // Gather in `new_lines' the collections of all the lines having
3373  // the direction of variables occurring in `lhs'.
3374  // While at it, check whether or not there exists a variable
3375  // occurring in both `lhs' and `rhs'.
3376  Generator_System new_lines;
3378  i = lhs.begin(), i_end = lhs.end(); i != i_end; ++i) {
3379  new_lines.insert(line(i.variable()));
3380  }
3381 
3382  const dimension_type num_common_dims
3383  = std::min(lhs.space_dimension(), rhs.space_dimension());
3384  if (lhs.have_a_common_variable(rhs, Variable(0), Variable(num_common_dims))) {
3385  // Some variables in `lhs' also occur in `rhs'.
3386  // To ease the computation, we add an additional dimension.
3387  const Variable new_var(space_dim);
3389 
3390  // Constrain the new dimension to be equal to the right hand side.
3391  // (check for emptiness because we will add lines).
3392  refine_no_check(new_var == rhs);
3393  if (!is_empty()) {
3394  // Existentially quantify the variables in the left hand side.
3395  add_recycled_generators(new_lines);
3396 
3397  // Constrain the new dimension so that it is related to
3398  // the left hand side as dictated by `relsym'
3399  // (we force minimization because we will need the generators).
3400  switch (relsym) {
3401  case LESS_THAN:
3402  refine_no_check(lhs < new_var);
3403  break;
3404  case LESS_OR_EQUAL:
3405  refine_no_check(lhs <= new_var);
3406  break;
3407  case EQUAL:
3408  refine_no_check(lhs == new_var);
3409  break;
3410  case GREATER_OR_EQUAL:
3411  refine_no_check(lhs >= new_var);
3412  break;
3413  case GREATER_THAN:
3414  refine_no_check(lhs > new_var);
3415  break;
3416  case NOT_EQUAL:
3417  // The NOT_EQUAL case has been already dealt with.
3418  PPL_UNREACHABLE;
3419  break;
3420  }
3421  }
3422  // Remove the temporarily added dimension.
3424  }
3425  else {
3426  // `lhs' and `rhs' variables are disjoint:
3427  // there is no need to add a further dimension.
3428 
3429  // Any image of an empty polyhedron is empty.
3430  // Note: DO check for emptiness here, as we will add lines.
3431  if (is_empty()) {
3432  return;
3433  }
3434 
3435  // Existentially quantify the variables in the left hand side.
3436  add_recycled_generators(new_lines);
3437 
3438  // Constrain the left hand side expression so that it is related to
3439  // the right hand side expression as dictated by `relsym'.
3440  switch (relsym) {
3441  case LESS_THAN:
3442  refine_no_check(lhs < rhs);
3443  break;
3444  case LESS_OR_EQUAL:
3445  refine_no_check(lhs <= rhs);
3446  break;
3447  case EQUAL:
3448  refine_no_check(lhs == rhs);
3449  break;
3450  case GREATER_OR_EQUAL:
3451  refine_no_check(lhs >= rhs);
3452  break;
3453  case GREATER_THAN:
3454  refine_no_check(lhs > rhs);
3455  break;
3456  case NOT_EQUAL:
3457  // The NOT_EQUAL case has been already dealt with.
3458  PPL_UNREACHABLE;
3459  break;
3460  }
3461  }
3462  PPL_ASSERT_HEAVY(OK());
3463 }
void add_space_dimensions_and_embed(dimension_type m)
Adds m new space dimensions and embeds the old polyhedron in the new vector space.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool is_empty() const
Returns true if and only if *this is an empty polyhedron.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
A dimension of the vector space.
bool have_a_common_variable(const Linear_Expression &x, Variable first, Variable last) const
Returns true if there is a variable from index first (included) to index last (excluded) whose coeffi...
void add_recycled_generators(Generator_System &gs)
Adds the generators in gs to the system of generators of *this (without minimizing the result)...
void throw_invalid_argument(const char *method, const char *reason) const
void remove_higher_space_dimensions(dimension_type new_dimension)
Removes the higher dimensions of the vector space so that the resulting space will have dimension new...
void refine_no_check(const Constraint &c)
Uses a copy of constraint c to refine the system of constraints of *this.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
void insert(const Generator &g)
Inserts in *this a copy of the generator g, increasing the number of space dimensions if needed...
void Parma_Polyhedra_Library::Polyhedron::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 generalized affine relation $\mathrm{var}' \relsym \frac{\mathrm{expr}}{\mathrm{denominator}}$, where $\mathord{\relsym}$ is the relation symbol encoded by relsym.

Parameters
varThe left hand side variable of the generalized affine relation;
relsymThe relation symbol;
exprThe numerator of the right hand side affine expression;
denominatorThe denominator of the right hand side affine expression (optional argument with default value 1).
Exceptions
std::invalid_argumentThrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a space dimension of *this or if *this is a C_Polyhedron and relsym is a strict relation symbol.

Definition at line 3198 of file Polyhedron_public.cc.

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

3201  {
3202  // The denominator cannot be zero.
3203  if (denominator == 0) {
3204  throw_invalid_argument("generalized_affine_preimage(v, r, e, d)",
3205  "d == 0");
3206  }
3207 
3208  // Dimension-compatibility checks.
3209  // The dimension of `expr' should not be greater than the dimension
3210  // of `*this'.
3211  if (space_dim < expr.space_dimension()) {
3212  throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)",
3213  "e", expr);
3214  }
3215  // `var' should be one of the dimensions of the polyhedron.
3216  const dimension_type var_space_dim = var.space_dimension();
3217  if (space_dim < var_space_dim) {
3218  throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)",
3219  "v", var);
3220  }
3221 
3222  // Strict relation symbols are only admitted for NNC polyhedra.
3223  if (is_necessarily_closed()
3224  && (relsym == LESS_THAN || relsym == GREATER_THAN)) {
3225  throw_invalid_argument("generalized_affine_preimage(v, r, e, d)",
3226  "r is a strict relation symbol");
3227  }
3228  // The relation symbol cannot be a disequality.
3229  if (relsym == NOT_EQUAL) {
3230  throw_invalid_argument("generalized_affine_preimage(v, r, e, d)",
3231  "r is the disequality relation symbol");
3232  }
3233 
3234  // Check whether the affine relation is indeed an affine function.
3235  if (relsym == EQUAL) {
3236  affine_preimage(var, expr, denominator);
3237  return;
3238  }
3239 
3240  // Compute the reversed relation symbol to simplify later coding.
3241  Relation_Symbol reversed_relsym;
3242  switch (relsym) {
3243  case LESS_THAN:
3244  reversed_relsym = GREATER_THAN;
3245  break;
3246  case LESS_OR_EQUAL:
3247  reversed_relsym = GREATER_OR_EQUAL;
3248  break;
3249  case GREATER_OR_EQUAL:
3250  reversed_relsym = LESS_OR_EQUAL;
3251  break;
3252  case GREATER_THAN:
3253  reversed_relsym = LESS_THAN;
3254  break;
3255  default:
3256  // The EQUAL and NOT_EQUAL cases have been already dealt with.
3257  PPL_UNREACHABLE;
3258  return;
3259  }
3260 
3261  // Check whether the preimage of this affine relation can be easily
3262  // computed as the image of its inverse relation.
3263  const Coefficient& var_coefficient = expr.coefficient(var);
3264  if (var_coefficient != 0) {
3265  const Linear_Expression inverse_expr
3266  = expr - (denominator + var_coefficient) * var;
3267  PPL_DIRTY_TEMP_COEFFICIENT(inverse_denominator);
3268  neg_assign(inverse_denominator, var_coefficient);
3269  const Relation_Symbol inverse_relsym
3270  = (sgn(denominator) == sgn(inverse_denominator))
3271  ? relsym : reversed_relsym;
3272  generalized_affine_image(var, inverse_relsym, inverse_expr,
3273  inverse_denominator);
3274  return;
3275  }
3276 
3277  // Here `var_coefficient == 0', so that the preimage cannot
3278  // be easily computed by inverting the affine relation.
3279  // Shrink the polyhedron by adding the constraint induced
3280  // by the affine relation.
3281  const Relation_Symbol corrected_relsym
3282  = (denominator > 0) ? relsym : reversed_relsym;
3283  switch (corrected_relsym) {
3284  case LESS_THAN:
3285  refine_no_check(denominator*var < expr);
3286  break;
3287  case LESS_OR_EQUAL:
3288  refine_no_check(denominator*var <= expr);
3289  break;
3290  case GREATER_OR_EQUAL:
3291  refine_no_check(denominator*var >= expr);
3292  break;
3293  case GREATER_THAN:
3294  refine_no_check(denominator*var > expr);
3295  break;
3296  default:
3297  // The EQUAL and NOT_EQUAL cases have been already dealt with.
3298  PPL_UNREACHABLE;
3299  break;
3300  }
3301  unconstrain(var);
3302  PPL_ASSERT_HEAVY(OK());
3303 }
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 to the affine e...
size_t dimension_type
An unsigned integral type for representing space dimensions.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Coefficient_traits::const_reference coefficient(Variable v) const
Returns the coefficient of v in *this.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void throw_invalid_argument(const char *method, const char *reason) const
Relation_Symbol
Relation symbols.
void refine_no_check(const Constraint &c)
Uses a copy of constraint c to refine the system of constraints of *this.
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
void neg_assign(GMP_Integer &x)
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
int sgn(Boundary_Type type, const T &x, const Info &info)
void generalized_affine_image(Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
Assigns to *this the image of *this with respect to the generalized affine relation ...
void unconstrain(Variable var)
Computes the cylindrification of *this with respect to space dimension var, assigning the result to *...
void Parma_Polyhedra_Library::Polyhedron::generalized_affine_preimage ( const Linear_Expression lhs,
Relation_Symbol  relsym,
const Linear_Expression rhs 
)

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

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

Definition at line 3466 of file Polyhedron_public.cc.

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

3468  {
3469  // Dimension-compatibility checks.
3470  // The dimension of `lhs' should not be greater than the dimension
3471  // of `*this'.
3472  dimension_type lhs_space_dim = lhs.space_dimension();
3473  if (space_dim < lhs_space_dim) {
3474  throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)",
3475  "e1", lhs);
3476  }
3477  // The dimension of `rhs' should not be greater than the dimension
3478  // of `*this'.
3479  const dimension_type rhs_space_dim = rhs.space_dimension();
3480  if (space_dim < rhs_space_dim) {
3481  throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)",
3482  "e2", rhs);
3483  }
3484 
3485  // Strict relation symbols are only admitted for NNC polyhedra.
3486  if (is_necessarily_closed()
3487  && (relsym == LESS_THAN || relsym == GREATER_THAN)) {
3488  throw_invalid_argument("generalized_affine_preimage(e1, r, e2)",
3489  "r is a strict relation symbol");
3490  }
3491  // The relation symbol cannot be a disequality.
3492  if (relsym == NOT_EQUAL) {
3493  throw_invalid_argument("generalized_affine_preimage(e1, r, e2)",
3494  "r is the disequality relation symbol");
3495  }
3496  // Any preimage of an empty polyhedron is empty.
3497  if (marked_empty()) {
3498  return;
3499  }
3500 
3501  // Compute the actual space dimension of `lhs',
3502  // i.e., the highest dimension having a non-zero coefficient in `lhs'.
3503  lhs_space_dim = lhs.last_nonzero();
3504 
3505  // If all variables have a zero coefficient, then `lhs' is a constant:
3506  // in this case, preimage and image happen to be the same.
3507  if (lhs_space_dim == 0) {
3508  generalized_affine_image(lhs, relsym, rhs);
3509  return;
3510  }
3511 
3512  // Gather in `new_lines' the collections of all the lines having
3513  // the direction of variables occurring in `lhs'.
3514  // While at it, check whether or not there exists a variable
3515  // occurring in both `lhs' and `rhs'.
3516  Generator_System new_lines;
3518  i = lhs.begin(), i_end = lhs.end(); i != i_end; ++i) {
3519  new_lines.insert(line(i.variable()));
3520  }
3521 
3522  const dimension_type num_common_dims
3523  = std::min(lhs.space_dimension(), rhs.space_dimension());
3524  if (lhs.have_a_common_variable(rhs, Variable(0), Variable(num_common_dims))) {
3525  // Some variables in `lhs' also occur in `rhs'.
3526  // To ease the computation, we add an additional dimension.
3527  const Variable new_var(space_dim);
3529 
3530  // Constrain the new dimension to be equal to `lhs'
3531  // (also check for emptiness because we have to add lines).
3532  refine_no_check(new_var == lhs);
3533  if (!is_empty()) {
3534  // Existentially quantify the variables in the left hand side.
3535  add_recycled_generators(new_lines);
3536 
3537  // Constrain the new dimension so that it is related to
3538  // the right hand side as dictated by `relsym'.
3539  switch (relsym) {
3540  case LESS_THAN:
3541  refine_no_check(new_var < rhs);
3542  break;
3543  case LESS_OR_EQUAL:
3544  refine_no_check(new_var <= rhs);
3545  break;
3546  case EQUAL:
3547  refine_no_check(new_var == rhs);
3548  break;
3549  case GREATER_OR_EQUAL:
3550  refine_no_check(new_var >= rhs);
3551  break;
3552  case GREATER_THAN:
3553  refine_no_check(new_var > rhs);
3554  break;
3555  case NOT_EQUAL:
3556  // The NOT_EQUAL case has been already dealt with.
3557  PPL_UNREACHABLE;
3558  break;
3559  }
3560  }
3561  // Remove the temporarily added dimension.
3563  }
3564  else {
3565  // `lhs' and `rhs' variables are disjoint:
3566  // there is no need to add a further dimension.
3567 
3568  // Constrain the left hand side expression so that it is related to
3569  // the right hand side expression as dictated by `relsym'.
3570  switch (relsym) {
3571  case LESS_THAN:
3572  refine_no_check(lhs < rhs);
3573  break;
3574  case LESS_OR_EQUAL:
3575  refine_no_check(lhs <= rhs);
3576  break;
3577  case EQUAL:
3578  refine_no_check(lhs == rhs);
3579  break;
3580  case GREATER_OR_EQUAL:
3581  refine_no_check(lhs >= rhs);
3582  break;
3583  case GREATER_THAN:
3584  refine_no_check(lhs > rhs);
3585  break;
3586  case NOT_EQUAL:
3587  // The NOT_EQUAL case has been already dealt with.
3588  PPL_UNREACHABLE;
3589  break;
3590  }
3591  // Any image of an empty polyhedron is empty.
3592  // Note: DO check for emptiness here, as we will add lines.
3593  if (is_empty()) {
3594  return;
3595  }
3596  // Existentially quantify all the variables occurring in `lhs'.
3597  add_recycled_generators(new_lines);
3598  }
3599  PPL_ASSERT_HEAVY(OK());
3600 }
void add_space_dimensions_and_embed(dimension_type m)
Adds m new space dimensions and embeds the old polyhedron in the new vector space.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool is_empty() const
Returns true if and only if *this is an empty polyhedron.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
A dimension of the vector space.
bool have_a_common_variable(const Linear_Expression &x, Variable first, Variable last) const
Returns true if there is a variable from index first (included) to index last (excluded) whose coeffi...
void add_recycled_generators(Generator_System &gs)
Adds the generators in gs to the system of generators of *this (without minimizing the result)...
void throw_invalid_argument(const char *method, const char *reason) const
void remove_higher_space_dimensions(dimension_type new_dimension)
Removes the higher dimensions of the vector space so that the resulting space will have dimension new...
void refine_no_check(const Constraint &c)
Uses a copy of constraint c to refine the system of constraints of *this.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
void generalized_affine_image(Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
Assigns to *this the image of *this with respect to the generalized affine relation ...
void insert(const Generator &g)
Inserts in *this a copy of the generator g, increasing the number of space dimensions if needed...
template<typename FP_Format , typename Interval_Info >
void Parma_Polyhedra_Library::Polyhedron::generalized_refine_with_linear_form_inequality ( const Linear_Form< Interval< FP_Format, Interval_Info > > &  left,
const Linear_Form< Interval< FP_Format, Interval_Info > > &  right,
Relation_Symbol  relsym 
)
inline

Refines *this with the constraint expressed by left $\relsym$ right, where $\relsym$ is the relation symbol specified by relsym..

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

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

Definition at line 383 of file Polyhedron_inlines.hh.

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

386  {
387  switch (relsym) {
388  case EQUAL:
389  // TODO: see if we can handle this case more efficiently.
390  refine_with_linear_form_inequality(left, right, false);
391  refine_with_linear_form_inequality(right, left, false);
392  break;
393  case LESS_THAN:
394  refine_with_linear_form_inequality(left, right, true);
395  break;
396  case LESS_OR_EQUAL:
397  refine_with_linear_form_inequality(left, right, false);
398  break;
399  case GREATER_THAN:
400  refine_with_linear_form_inequality(right, left, true);
401  break;
402  case GREATER_OR_EQUAL:
403  refine_with_linear_form_inequality(right, left, false);
404  break;
405  case NOT_EQUAL:
406  break;
407  default:
408  PPL_UNREACHABLE;
409  break;
410  }
411 }
void refine_with_linear_form_inequality(const Linear_Form< Interval< FP_Format, Interval_Info > > &left, const Linear_Form< Interval< FP_Format, Interval_Info > > &right, bool is_strict=false)
Refines *this with the constraint expressed by left right if is_strict is set, with the constraint l...
const PPL::Generator_System & Parma_Polyhedra_Library::Polyhedron::generators ( ) const

Returns the system of generators.

Definition at line 138 of file Polyhedron_public.cc.

References Parma_Polyhedra_Library::Generator_System::adjust_topology_and_space_dimension(), Parma_Polyhedra_Library::swap(), and Parma_Polyhedra_Library::Generator_System::zero_dim_univ().

Referenced by Parma_Polyhedra_Library::Termination_Helpers::all_affine_ranking_functions_PR(), Parma_Polyhedra_Library::Termination_Helpers::all_affine_ranking_functions_PR_original(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::Grid::Grid(), map_space_dimensions(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape().

138  {
139  if (marked_empty()) {
140  PPL_ASSERT(gen_sys.has_no_rows());
141  // We want `gen_sys' to have the appropriate space dimension,
142  // even though it is an empty generator system.
143  if (gen_sys.space_dimension() != space_dim) {
144  Generator_System gs;
146  swap(const_cast<Generator_System&>(gen_sys), gs);
147  }
148  return gen_sys;
149  }
150 
151  if (space_dim == 0) {
152  PPL_ASSERT(gen_sys.num_rows() == 0 && gen_sys.space_dimension() == 0);
154  }
155 
156  // If the polyhedron has pending constraints, we process them to obtain
157  // the generators (we may discover that the polyhedron is empty).
158  // No processing is needed if the polyhedron has pending generators.
161  // We have just discovered that `*this' is empty.
162  PPL_ASSERT(gen_sys.has_no_rows());
163  // We want `gen_sys' to have the appropriate space dimension,
164  // even though it is an empty generator system.
165  if (gen_sys.space_dimension() != space_dim) {
166  Generator_System gs;
168  swap(const_cast<Generator_System&>(gen_sys), gs);
169  }
170  return gen_sys;
171  }
172 
173  // TODO: reconsider whether to really sort generators at this stage.
174 #if ENSURE_SORTEDNESS
175  // We insist in returning a sorted system of generators,
176  // but sorting is useless if there are pending generators.
177  if (!has_pending_generators())
179 #else
180  // In the case of an NNC polyhedron, if the generator system is fully
181  // minimized (i.e., minimized and with no pending generator), then
182  // return a sorted system of generators: this is needed so that the
183  // const_iterator could correctly filter out the matched closure points.
184  if (!is_necessarily_closed()
187  }
188 #endif
189  return gen_sys;
190 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
static const Generator_System & zero_dim_univ()
Returns the singleton system containing only Generator::zero_dim_point().
bool adjust_topology_and_space_dimension(Topology new_topology, dimension_type new_space_dim)
Adjusts *this so that it matches the new_topology and new_space_dim (adding or removing columns if ne...
Generator_System gen_sys
The system of generators.
bool generators_are_minimized() const
Returns true if the system of generators is minimized.
bool update_generators() const
Updates generators starting from constraints and minimizes them.
void swap(Polyhedron &x, Polyhedron &y)
Swaps x with y.
Topology topology() const
Returns the topological kind of the polyhedron.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
bool process_pending_constraints() const
Processes the pending constraints and obtains a minimized polyhedron.
void obtain_sorted_generators() const
Sorts the matrix of generators keeping status consistency.
bool has_pending_generators() const
Returns true if there are pending generators.
bool Parma_Polyhedra_Library::Polyhedron::generators_are_minimized ( ) const
inlineprivate

Returns true if the system of generators is minimized.

Note that only weak minimization is entailed, so that an NNC polyhedron may still have $\epsilon$-redundant generators.

Definition at line 150 of file Polyhedron_inlines.hh.

References status, and Parma_Polyhedra_Library::Polyhedron::Status::test_g_minimized().

Referenced by BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), can_have_something_pending(), quick_equivalence_test(), and simplify_using_context_assign().

150  {
151  return status.test_g_minimized();
152 }
Status status
The status flags to keep track of the polyhedron's internal state.
void Parma_Polyhedra_Library::Polyhedron::H79_widening_assign ( const Polyhedron y,
unsigned *  tp = 0 
)

Assigns to *this the result of computing the H79_widening between *this and y.

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

Definition at line 165 of file Polyhedron_widenings.cc.

References add_recycled_constraints(), con_sys, constraints_are_up_to_date(), contains(), Parma_Polyhedra_Library::Constraint_System::has_no_rows(), has_pending_generators(), intersection_assign(), is_empty(), is_necessarily_closed(), m_swap(), marked_empty(), minimize(), Parma_Polyhedra_Library::Constraint_System::num_equalities(), Parma_Polyhedra_Library::Constraint_System::num_rows(), OK(), process_pending_generators(), select_CH78_constraints(), select_H79_constraints(), space_dim, throw_dimension_incompatible(), throw_topology_incompatible(), topology(), Parma_Polyhedra_Library::UNIVERSE, and update_constraints().

Referenced by Parma_Polyhedra_Library::BD_Shape< T >::H79_widening_assign(), limited_H79_extrapolation_assign(), and widening_assign().

165  {
166  Polyhedron& x = *this;
167  // Topology compatibility check.
168  const Topology topol = x.topology();
169  if (topol != y.topology()) {
170  throw_topology_incompatible("H79_widening_assign(y)", "y", y);
171  // Dimension-compatibility check.
172  }
173  if (x.space_dim != y.space_dim) {
174  throw_dimension_incompatible("H79_widening_assign(y)", "y", y);
175  }
176  // Assume `y' is contained in or equal to `x'.
177  PPL_EXPECT_HEAVY(copy_contains(x, y));
178 
179  // If any argument is zero-dimensional or empty,
180  // the H79-widening behaves as the identity function.
181  if (x.space_dim == 0 || x.marked_empty() || y.marked_empty()) {
182  return;
183  }
184 
185  // `y.gen_sys' should be in minimal form and
186  // `y.sat_g' should be up-to-date.
187  if (y.is_necessarily_closed()) {
188  if (!y.minimize()) {
189  // `y' is empty: the result is `x'.
190  return;
191  }
192  }
193  else {
194  // Dealing with a NNC polyhedron.
195  // To obtain a correct reasoning when comparing
196  // the constraints of `x' with the generators of `y',
197  // we enforce the inclusion relation holding between
198  // the two NNC polyhedra `x' and `y' (i.e., `y <= x')
199  // to also hold for the corresponding eps-representations:
200  // this is obtained by intersecting the two eps-representations.
201  Polyhedron& yy = const_cast<Polyhedron&>(y);
202  yy.intersection_assign(x);
203  if (yy.is_empty()) {
204  // The result is `x'.
205  return;
206  }
207  }
208 
209  // If we only have the generators of `x' and the dimensions of
210  // the two polyhedra are the same, we can compute the standard
211  // widening by using the specification in [CousotH78], therefore
212  // avoiding converting from generators to constraints.
213  if (x.has_pending_generators() || !x.constraints_are_up_to_date()) {
214  Constraint_System CH78_cs(topol);
215  x.select_CH78_constraints(y, CH78_cs);
216 
217  if (CH78_cs.num_rows() == y.con_sys.num_rows()) {
218  // Having selected all the constraints, the result is `y'.
219  x = y;
220  return;
221  }
222  // Otherwise, check if `x' and `y' have the same dimension.
223  // Note that `y.con_sys' is minimized and `CH78_cs' has no redundant
224  // constraints, since it is a subset of the former.
225  else if (CH78_cs.num_equalities() == y.con_sys.num_equalities()) {
226  // Let `x' be defined by the constraints in `CH78_cs'.
227  Polyhedron CH78(topol, x.space_dim, UNIVERSE);
228  CH78.add_recycled_constraints(CH78_cs);
229 
230  // Check whether we are using the widening-with-tokens technique
231  // and there still are tokens available.
232  if (tp != 0 && *tp > 0) {
233  // There are tokens available. If `CH78' is not a subset of `x',
234  // then it is less precise and we use one of the available tokens.
235  if (!x.contains(CH78)) {
236  --(*tp);
237  }
238  }
239  else {
240  // No tokens.
241  x.m_swap(CH78);
242  }
243  PPL_ASSERT_HEAVY(x.OK(true));
244  return;
245  }
246  }
247 
248  // As the dimension of `x' is strictly greater than the dimension of `y',
249  // we have to compute the standard widening by selecting a subset of
250  // the constraints of `x'.
251  // `x.con_sys' is just required to be up-to-date, because:
252  // - if `x.con_sys' is unsatisfiable, then by assumption
253  // also `y' is empty, so that the resulting polyhedron is `x';
254  // - redundant constraints in `x.con_sys' do not affect the result
255  // of the widening, because if they are selected they will be
256  // redundant even in the result.
257  if (has_pending_generators()) {
259  }
260  else if (!x.constraints_are_up_to_date()) {
261  x.update_constraints();
262  }
263  // Copy into `H79_cs' the constraints of `x' that are common to `y',
264  // according to the definition of the H79 widening.
265  Constraint_System H79_cs(topol);
266  Constraint_System x_minus_H79_cs(topol);
267  x.select_H79_constraints(y, H79_cs, x_minus_H79_cs);
268 
269  if (x_minus_H79_cs.has_no_rows()) {
270  // We selected all of the constraints of `x',
271  // thus the result of the widening is `x'.
272  return;
273  }
274  else {
275  // We selected a strict subset of the constraints of `x'.
276  // NOTE: as `x.con_sys' was not necessarily in minimal form,
277  // this does not imply that the result strictly includes `x'.
278  // Let `H79' be defined by the constraints in `H79_cs'.
279  Polyhedron H79(topol, x.space_dim, UNIVERSE);
280  H79.add_recycled_constraints(H79_cs);
281 
282  // Check whether we are using the widening-with-tokens technique
283  // and there still are tokens available.
284  if (tp != 0 && *tp > 0) {
285  // There are tokens available. If `H79' is not a subset of `x',
286  // then it is less precise and we use one of the available tokens.
287  if (!x.contains(H79)) {
288  --(*tp);
289  }
290  }
291  else {
292  // No tokens.
293  x.m_swap(H79);
294  }
295  PPL_ASSERT_HEAVY(x.OK(true));
296  }
297 }
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
void throw_topology_incompatible(const char *method, const char *ph_name, const Polyhedron &ph) const
void process_pending_generators() const
Processes the pending generators and obtains a minimized polyhedron.
The universe element, i.e., the whole vector space.
bool has_pending_generators() const
Returns true if there are pending generators.
Topology
Kinds of polyhedra domains.
bool Parma_Polyhedra_Library::Polyhedron::has_pending_generators ( ) const
inlineprivate
int32_t Parma_Polyhedra_Library::Polyhedron::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 45 of file Polyhedron_inlines.hh.

References Parma_Polyhedra_Library::hash_code_from_dimension(), and space_dimension().

45  {
47 }
int32_t hash_code_from_dimension(dimension_type dim)
Returns the hash code for space dimension dim.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void Parma_Polyhedra_Library::Polyhedron::initialize ( )
static

Initializes the class.

Definition at line 47 of file Polyhedron_public.cc.

References simplify_num_saturators_p, and simplify_num_saturators_size.

Referenced by Parma_Polyhedra_Library::Init::Init().

47  {
48  PPL_ASSERT(simplify_num_saturators_p == 0);
49  PPL_ASSERT(simplify_num_saturators_size == 0);
51 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
static dimension_type * simplify_num_saturators_p
Pointer to an array used by simplify().
static size_t simplify_num_saturators_size
Dimension of an array used by simplify().
void Parma_Polyhedra_Library::Polyhedron::intersection_assign ( const Polyhedron y)

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

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

Definition at line 1986 of file Polyhedron_public.cc.

References can_have_something_pending(), clear_constraints_minimized(), clear_generators_up_to_date(), con_sys, constraints_are_up_to_date(), has_pending_constraints(), has_pending_generators(), Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::Constraint_System::insert_pending(), Parma_Polyhedra_Library::Constraint_System::is_sorted(), marked_empty(), Parma_Polyhedra_Library::Constraint_System::merge_rows_assign(), OK(), process_pending_generators(), set_constraints_pending(), set_empty(), space_dim, topology(), and update_constraints().

Referenced by Parma_Polyhedra_Library::Implementation::Termination::all_affine_ranking_functions_MS(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), H79_widening_assign(), and is_disjoint_from().

1986  {
1987  Polyhedron& x = *this;
1988  // Topology compatibility check.
1989  if (x.topology() != y.topology()) {
1990  throw_topology_incompatible("intersection_assign(y)", "y", y);
1991  }
1992  // Dimension-compatibility check.
1993  if (x.space_dim != y.space_dim) {
1994  throw_dimension_incompatible("intersection_assign(y)", "y", y);
1995  }
1996  // If one of the two polyhedra is empty, the intersection is empty.
1997  if (x.marked_empty()) {
1998  return;
1999  }
2000  if (y.marked_empty()) {
2001  x.set_empty();
2002  return;
2003  }
2004 
2005  // If both polyhedra are zero-dimensional,
2006  // then at this point they are necessarily non-empty,
2007  // so that their intersection is non-empty too.
2008  if (x.space_dim == 0) {
2009  return;
2010  }
2011 
2012  // Both systems of constraints have to be up-to-date,
2013  // possibly having pending constraints.
2014  if (x.has_pending_generators()) {
2016  }
2017  else if (!x.constraints_are_up_to_date()) {
2018  x.update_constraints();
2019  }
2020 
2021  if (y.has_pending_generators()) {
2023  }
2024  else if (!y.constraints_are_up_to_date()) {
2025  y.update_constraints();
2026  }
2027 
2028  // Here both systems are up-to-date and possibly have pending constraints
2029  // (but they cannot have pending generators).
2030  PPL_ASSERT(!x.has_pending_generators() && x.constraints_are_up_to_date());
2031  PPL_ASSERT(!y.has_pending_generators() && y.constraints_are_up_to_date());
2032 
2033  // If `x' can support pending constraints,
2034  // the constraints of `y' are added as pending constraints of `x'.
2035  if (x.can_have_something_pending()) {
2038  }
2039  else {
2040  // `x' cannot support pending constraints.
2041  // If both constraint systems are (fully) sorted, then we can
2042  // merge them; otherwise we simply add the second to the first.
2043  if (x.con_sys.is_sorted()
2044  && y.con_sys.is_sorted() && !y.has_pending_constraints()) {
2046  }
2047  else {
2048  x.con_sys.insert(y.con_sys);
2049  }
2050  // Generators are no longer up-to-date and constraints are no
2051  // longer minimized.
2054  }
2055  PPL_ASSERT_HEAVY(x.OK() && y.OK());
2056 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
void insert_pending(const Constraint &c)
Inserts in *this a copy of the constraint c, increasing the number of space dimensions if needed...
void update_constraints() const
Updates constraints starting from generators and minimizes them.
void set_constraints_pending()
Sets status to express that constraints are pending.
void merge_rows_assign(const Constraint_System &y)
Assigns to *this the result of merging its rows with those of y, obtaining a sorted system...
void insert(const Constraint &c)
Inserts in *this a copy of the constraint c, increasing the number of space dimensions if needed...
bool is_sorted() const
Returns the value of the sortedness flag.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
bool can_have_something_pending() const
Returns true if the polyhedron can have something pending.
The base class for convex polyhedra.
Topology topology() const
Returns the topological kind of the polyhedron.
Constraint_System con_sys
The system of constraints.
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
void throw_topology_incompatible(const char *method, const char *ph_name, const Polyhedron &ph) const
void process_pending_generators() const
Processes the pending generators and obtains a minimized polyhedron.
void set_empty()
Sets status to express that the polyhedron is empty, clearing all corresponding matrices.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
void clear_constraints_minimized()
Sets status to express that constraints are no longer minimized.
bool has_pending_generators() const
Returns true if there are pending generators.
void clear_generators_up_to_date()
Sets status to express that generators are no longer up-to-date.
bool Parma_Polyhedra_Library::Polyhedron::is_bounded ( ) const

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

Definition at line 526 of file Polyhedron_public.cc.

526  {
527  // A zero-dimensional or empty polyhedron is bounded.
528  if (space_dim == 0
529  || marked_empty()
532  return true;
533  }
534 
535  // If the system of generators contains any line or a ray,
536  // then the polyhedron is unbounded.
537  for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) {
538  if (gen_sys[i].is_line_or_ray()) {
539  return false;
540  }
541  }
542 
543  // The system of generators is composed only by
544  // points and closure points: the polyhedron is bounded.
545  return true;
546 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
bool update_generators() const
Updates generators starting from constraints and minimizes them.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool process_pending_constraints() const
Processes the pending constraints and obtains a minimized polyhedron.
bool Parma_Polyhedra_Library::Polyhedron::is_discrete ( ) const
inline

Returns true if and only if *this is discrete.

Definition at line 69 of file Polyhedron_inlines.hh.

References affine_dimension().

69  {
70  return affine_dimension() == 0;
71 }
dimension_type affine_dimension() const
Returns , if *this is empty; otherwise, returns the affine dimension of *this.
bool Parma_Polyhedra_Library::Polyhedron::is_disjoint_from ( const Polyhedron y) const

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

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

Definition at line 3958 of file Polyhedron_public.cc.

References intersection_assign(), and is_empty().

Referenced by Parma_Polyhedra_Library::Pointset_Powerset< PSET >::check_containment().

3958  {
3959  Polyhedron z = *this;
3960  z.intersection_assign(y);
3961  return z.is_empty();
3962 }
bool is_empty() const
Returns true if and only if *this is an empty polyhedron.
The base class for convex polyhedra.
void intersection_assign(const Polyhedron &y)
Assigns to *this the intersection of *this and y.
bool Parma_Polyhedra_Library::Polyhedron::is_empty ( ) const
inline

Returns true if and only if *this is an empty polyhedron.

Definition at line 187 of file Polyhedron_inlines.hh.

References generators_are_up_to_date(), has_pending_constraints(), marked_empty(), and minimize().

Referenced by BFT00_poly_hull_assign_if_exact(), BHZ09_C_poly_hull_assign_if_exact(), BHZ09_NNC_poly_hull_assign_if_exact(), BHZ09_poly_hull_assign_if_exact(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::Pointset_Powerset< PSET >::check_containment(), contains(), Parma_Polyhedra_Library::Grid::Grid(), H79_widening_assign(), is_disjoint_from(), Parma_Polyhedra_Library::Pointset_Powerset< PSET >::linear_partition_aux(), operator<<(), operator==(), Parma_Polyhedra_Library::Pointset_Powerset< PSET >::Pointset_Powerset(), and simplify_using_context_assign().

187  {
188  if (marked_empty()) {
189  return true;
190  }
191  // Try a fast-fail test: if generators are up-to-date and
192  // there are no pending constraints, then the generator system
193  // (since it is well formed) contains a point.
195  return false;
196  }
197  return !minimize();
198 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
bool minimize() const
Applies (weak) minimization to both the constraints and generators.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
bool Parma_Polyhedra_Library::Polyhedron::is_included_in ( const Polyhedron y) const
private

Returns true if and only if *this is included in y.

Definition at line 425 of file Polyhedron_nonpublic.cc.

References c, Parma_Polyhedra_Library::Generator::CLOSURE_POINT, con_sys, constraints_are_minimized(), constraints_are_up_to_date(), Parma_Polyhedra_Library::Constraint::EQUALITY, has_pending_generators(), Parma_Polyhedra_Library::Constraint::is_inequality(), Parma_Polyhedra_Library::Generator::is_line(), Parma_Polyhedra_Library::Generator::LINE, marked_empty(), minimize(), Parma_Polyhedra_Library::Constraint::NONSTRICT_INEQUALITY, Parma_Polyhedra_Library::Constraint_System::num_rows(), OK(), Parma_Polyhedra_Library::Generator::POINT, process_pending_generators(), Parma_Polyhedra_Library::Generator::RAY, Parma_Polyhedra_Library::Scalar_Products::reduced_sign(), Parma_Polyhedra_Library::Scalar_Products::sign(), space_dim, Parma_Polyhedra_Library::Constraint::STRICT_INEQUALITY, topology(), Parma_Polyhedra_Library::Constraint::type(), Parma_Polyhedra_Library::Generator::type(), and update_constraints().

Referenced by BHZ09_C_poly_hull_assign_if_exact(), contains(), and operator==().

425  {
426  // Private method: the caller must ensure the following.
427  PPL_ASSERT(topology() == y.topology());
428  PPL_ASSERT(space_dim == y.space_dim);
429  PPL_ASSERT(!marked_empty() && !y.marked_empty() && space_dim > 0);
430 
431  const Polyhedron& x = *this;
432 
433  // `x' cannot have pending constraints, because we need its generators.
434  if (x.has_pending_constraints() && !x.process_pending_constraints()) {
435  return true;
436  }
437  // `y' cannot have pending generators, because we need its constraints.
438  if (y.has_pending_generators()) {
439  y.process_pending_generators();
440  }
441 
442 #if BE_LAZY
443  if (!x.generators_are_up_to_date() && !x.update_generators()) {
444  return true;
445  }
446  if (!y.constraints_are_up_to_date()) {
447  y.update_constraints();
448  }
449 #else
450  if (!x.generators_are_minimized()) {
451  x.minimize();
452  }
453  if (!y.constraints_are_minimized()) {
454  y.minimize();
455  }
456 #endif
457 
458  PPL_ASSERT_HEAVY(x.OK());
459  PPL_ASSERT_HEAVY(y.OK());
460 
461  const Generator_System& gs = x.gen_sys;
462  const Constraint_System& cs = y.con_sys;
463 
464  if (x.is_necessarily_closed()) {
465  // When working with necessarily closed polyhedra,
466  // `x' is contained in `y' if and only if all the generators of `x'
467  // satisfy all the inequalities and saturate all the equalities of `y'.
468  // This comes from the definition of a polyhedron as the set of
469  // vectors satisfying a constraint system and the fact that all
470  // vectors in `x' can be obtained by suitably combining its generators.
471  for (dimension_type i = cs.num_rows(); i-- > 0; ) {
472  const Constraint& c = cs[i];
473  if (c.is_inequality()) {
474  for (dimension_type j = gs.num_rows(); j-- > 0; ) {
475  const Generator& g = gs[j];
476  const int sp_sign = Scalar_Products::sign(c, g);
477  if (g.is_line()) {
478  if (sp_sign != 0) {
479  return false;
480  }
481  }
482  else {
483  // `g' is a ray or a point.
484  if (sp_sign < 0) {
485  return false;
486  }
487  }
488  }
489  }
490  else {
491  // `c' is an equality.
492  for (dimension_type j = gs.num_rows(); j-- > 0; ) {
493  if (Scalar_Products::sign(c, gs[j]) != 0) {
494  return false;
495  }
496  }
497  }
498  }
499  }
500  else {
501  // Here we have an NNC polyhedron: using the reduced scalar product,
502  // which ignores the epsilon coefficient.
503  for (dimension_type i = cs.num_rows(); i-- > 0; ) {
504  const Constraint& c = cs[i];
505  switch (c.type()) {
507  for (dimension_type j = gs.num_rows(); j-- > 0; ) {
508  const Generator& g = gs[j];
509  const int sp_sign = Scalar_Products::reduced_sign(c, g);
510  if (g.is_line()) {
511  if (sp_sign != 0) {
512  return false;
513  }
514  }
515  else {
516  // `g' is a ray or a point or a closure point.
517  if (sp_sign < 0) {
518  return false;
519  }
520  }
521  }
522  break;
524  for (dimension_type j = gs.num_rows(); j-- > 0; ) {
525  if (Scalar_Products::reduced_sign(c, gs[j]) != 0) {
526  return false;
527  }
528  }
529  break;
531  for (dimension_type j = gs.num_rows(); j-- > 0; ) {
532  const Generator& g = gs[j];
533  const int sp_sign = Scalar_Products::reduced_sign(c, g);
534  switch (g.type()) {
535  case Generator::POINT:
536  // If a point violates or saturates a strict inequality
537  // (when ignoring the epsilon coefficients) then it is
538  // not included in the polyhedron.
539  if (sp_sign <= 0) {
540  return false;
541  }
542  break;
543  case Generator::LINE:
544  // Lines have to saturate all constraints.
545  if (sp_sign != 0) {
546  return false;
547  }
548  break;
549  case Generator::RAY:
550  // Intentionally fall through.
552  // The generator is a ray or closure point: usual test.
553  if (sp_sign < 0) {
554  return false;
555  }
556  break;
557  }
558  }
559  break;
560  }
561  }
562  }
563 
564  // Inclusion holds.
565  return true;
566 }
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
Topology topology() const
Returns the topological kind of the polyhedron.
static int reduced_sign(const Linear_Expression &x, const Linear_Expression &y)
Returns the sign of the reduced scalar product of x and y, where the coefficient of x is ignored...
dimension_type space_dim
The number of dimensions of the enclosing vector space.
static int sign(const Linear_Expression &x, const Linear_Expression &y)
Returns the sign of the scalar product between x and y.
Coefficient c
Definition: PIP_Tree.cc:64
bool Parma_Polyhedra_Library::Polyhedron::is_necessarily_closed ( ) const
inlineprivate

Returns true if and only if the polyhedron is necessarily closed.

Definition at line 74 of file Polyhedron_inlines.hh.

References con_sys, and Parma_Polyhedra_Library::Constraint_System::is_necessarily_closed().

Referenced by BFT00_poly_hull_assign_if_exact(), Parma_Polyhedra_Library::BHRZ03_Certificate::BHRZ03_Certificate(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHZ09_C_poly_hull_assign_if_exact(), BHZ09_NNC_poly_hull_assign_if_exact(), BHZ09_poly_hull_assign_if_exact(), Parma_Polyhedra_Library::BHRZ03_Certificate::compare(), Parma_Polyhedra_Library::H79_Certificate::compare(), Parma_Polyhedra_Library::H79_Certificate::H79_Certificate(), H79_widening_assign(), Parma_Polyhedra_Library::Interfaces::is_necessarily_closed_for_interfaces(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), positive_time_elapse_assign_impl(), refine_with_linear_form_inequality(), select_H79_constraints(), simplify_using_context_assign(), throw_topology_incompatible(), and time_elapse_assign().

74  {
75  // We can check either one of the two matrices.
76  // (`con_sys' is slightly better, since it is placed at offset 0.)
78 }
bool is_necessarily_closed() const
Returns true if and only if the system topology is NECESSARILY_CLOSED.
Constraint_System con_sys
The system of constraints.
bool Parma_Polyhedra_Library::Polyhedron::is_topologically_closed ( ) const

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

Definition at line 549 of file Polyhedron_public.cc.

References Parma_Polyhedra_Library::Generator::is_closure_point(), Parma_Polyhedra_Library::Generator::is_matching_closure_point(), and Parma_Polyhedra_Library::Generator::is_point().

549  {
550  // Necessarily closed polyhedra are trivially closed.
551  if (is_necessarily_closed()) {
552  return true;
553  }
554  // Any empty or zero-dimensional polyhedron is closed.
555  if (marked_empty()
556  || space_dim == 0
557  || (has_something_pending() && !process_pending())) {
558  return true;
559  }
560 
561  // At this point there are no pending constraints or generators.
562  PPL_ASSERT(!has_something_pending());
563 
564  if (generators_are_minimized()) {
565  // A polyhedron is closed if and only if all of its (non-redundant)
566  // closure points are matched by a corresponding point.
567  const dimension_type n_rows = gen_sys.num_rows();
568  const dimension_type n_lines = gen_sys.num_lines();
569  for (dimension_type i = n_rows; i-- > n_lines; ) {
570  const Generator& gen_sys_i = gen_sys[i];
571  if (gen_sys_i.is_closure_point()) {
572  bool gen_sys_i_has_no_matching_point = true;
573  for (dimension_type j = n_rows; j-- > n_lines; ) {
574  const Generator& gen_sys_j = gen_sys[j];
575  if (i != j
576  && gen_sys_j.is_point()
577  && gen_sys_i.is_matching_closure_point(gen_sys_j)) {
578  gen_sys_i_has_no_matching_point = false;
579  break;
580  }
581  }
582  if (gen_sys_i_has_no_matching_point) {
583  return false;
584  }
585  }
586  }
587  // All closure points are matched.
588  return true;
589  }
590 
591  // A polyhedron is closed if, after strong minimization
592  // of its constraint system, it has no strict inequalities.
595 }
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
bool strongly_minimize_constraints() const
Applies strong minimization to the constraints of an NNC polyhedron.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
A line, ray, point or closure point.
bool generators_are_minimized() const
Returns true if the system of generators is minimized.
bool is_matching_closure_point(const Generator &p) const
Returns true if and only if the closure point *this has the same coordinates of the point p...
Definition: Generator.cc:399
Constraint_System con_sys
The system of constraints.
bool process_pending() const
Processes the pending rows of either description of the polyhedron and obtains a minimized polyhedron...
bool is_point() const
Returns true if and only if *this is a point.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
dimension_type num_lines() const
Returns the number of lines of the system.
bool has_something_pending() const
Returns true if there are either pending constraints or pending generators.
bool is_closure_point() const
Returns true if and only if *this is a closure point.
bool has_strict_inequalities() const
Returns true if and only if *this contains one or more strict inequality constraints.
bool Parma_Polyhedra_Library::Polyhedron::is_universe ( ) const

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

Definition at line 388 of file Polyhedron_public.cc.

References Parma_Polyhedra_Library::Expression_Hide_Last< T >::all_homogeneous_terms_are_zero(), Parma_Polyhedra_Library::Constraint::epsilon_coefficient(), Parma_Polyhedra_Library::Constraint::expression(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Generator::LINE, and Parma_Polyhedra_Library::Generator::RAY.

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

388  {
389  if (marked_empty()) {
390  return false;
391  }
392 
393  if (space_dim == 0) {
394  return true;
395  }
397  // Search for a constraint that is not a tautology.
398  for (dimension_type i = con_sys.num_rows(); i-- > 0; ) {
399  if (!con_sys[i].is_tautological()) {
400  return false;
401  }
402  }
403  // All the constraints are tautologies.
404  return true;
405  }
406 
408 
409  // Try a fast-fail test.
410  dimension_type num_lines = 0;
411  dimension_type num_rays = 0;
412  const dimension_type first_pending = gen_sys.first_pending_row();
413  for (dimension_type i = first_pending; i-- > 0; ) {
414  switch (gen_sys[i].type()) {
415  case Generator::RAY:
416  ++num_rays;
417  break;
418  case Generator::LINE:
419  ++num_lines;
420  break;
421  default:
422  break;
423  }
424  }
425 
426  if (has_pending_generators()) {
427  // The non-pending part of `gen_sys' was minimized:
428  // a success-first test is possible in this case.
429  PPL_ASSERT(generators_are_minimized());
430  if (num_lines == space_dim) {
431  PPL_ASSERT(num_rays == 0);
432  return true;
433  }
434  PPL_ASSERT(num_lines < space_dim);
435  // Now scan the pending generators.
436  dimension_type num_pending_lines = 0;
437  dimension_type num_pending_rays = 0;
438  const dimension_type gs_num_rows = gen_sys.num_rows();
439  for (dimension_type i = first_pending; i < gs_num_rows; ++i) {
440  switch (gen_sys[i].type()) {
441  case Generator::RAY:
442  ++num_pending_rays;
443  break;
444  case Generator::LINE:
445  ++num_pending_lines;
446  break;
447  default:
448  break;
449  }
450  }
451  // If no pending rays and lines were found,
452  // then it is not the universe polyhedron.
453  if (num_pending_rays == 0 && num_pending_lines == 0) {
454  return false;
455  }
456  // Factor away the lines already seen (to be on the safe side,
457  // we assume they are all linearly independent).
458  if (num_lines + num_pending_lines < space_dim) {
459  const dimension_type num_dims_missing
460  = space_dim - (num_lines + num_pending_lines);
461  // In order to span an n dimensional space (where n = num_dims_missing),
462  // at least n+1 rays are needed.
463  if (num_rays + num_pending_rays <= num_dims_missing) {
464  return false;
465  }
466  }
467  }
468  else {
469  // There is nothing pending.
470  if (generators_are_minimized()) {
471  // The exact test is possible.
472  PPL_ASSERT(num_rays == 0 || num_lines < space_dim);
473  return num_lines == space_dim;
474  }
475  else {
476  // Only the fast-fail test can be computed: in order to span
477  // an n dimensional space (where n = space_dim - num_lines),
478  // at least n+1 rays are needed.
479  if (num_lines < space_dim && num_lines + num_rays <= space_dim) {
480  return false;
481  }
482  }
483  }
484 
485  // We need the polyhedron in minimal form.
486  if (has_pending_generators()) {
488  }
489  else if (!constraints_are_minimized()) {
490  minimize();
491  }
492  if (is_necessarily_closed()) {
493  return con_sys.num_rows() == 1
494  && con_sys[0].is_inequality()
495  && con_sys[0].is_tautological();
496  }
497  else {
498  // NNC polyhedron.
499  if (con_sys.num_rows() != 2
500  || con_sys[0].is_equality()
501  || con_sys[1].is_equality()) {
502  return false;
503  }
504  else {
505  // If the system of constraints contains two rows that
506  // are not equalities, we are sure that they are
507  // epsilon constraints: in this case we know that
508  // the polyhedron is universe.
509 #ifndef NDEBUG
511  const Constraint& eps_leq_one = con_sys[0];
512  const Constraint& eps_geq_zero = con_sys[1];
513  PPL_ASSERT(eps_leq_one.inhomogeneous_term() > 0
514  && eps_leq_one.epsilon_coefficient() < 0
515  && eps_geq_zero.inhomogeneous_term() == 0
516  && eps_geq_zero.epsilon_coefficient() > 0);
517  PPL_ASSERT(eps_leq_one.expression().all_homogeneous_terms_are_zero());
518  PPL_ASSERT(eps_geq_zero.expression().all_homogeneous_terms_are_zero());
519 #endif
520  return true;
521  }
522  }
523 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
bool constraints_are_minimized() const
Returns true if the system of constraints is minimized.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
dimension_type first_pending_row() const
Returns the index of the first pending row.
A linear equality or inequality.
bool minimize() const
Applies (weak) minimization to both the constraints and generators.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
bool generators_are_minimized() const
Returns true if the system of generators is minimized.
void obtain_sorted_constraints() const
Sorts the matrix of constraints keeping status consistency.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
Constraint_System con_sys
The system of constraints.
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
void process_pending_generators() const
Processes the pending generators and obtains a minimized polyhedron.
bool all_homogeneous_terms_are_zero() const
Returns true if and only if all the homogeneous terms of *this are zero.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
Coefficient_traits::const_reference epsilon_coefficient() const
Returns the epsilon coefficient. The constraint must be NNC.
bool has_pending_generators() const
Returns true if there are pending generators.
Coefficient_traits::const_reference inhomogeneous_term() const
Returns the inhomogeneous term of *this.
expr_type expression() const
Partial read access to the (adapted) internal expression.
void Parma_Polyhedra_Library::Polyhedron::limited_BHRZ03_extrapolation_assign ( const Polyhedron y,
const Constraint_System cs,
unsigned *  tp = 0 
)

Assigns to *this the result of computing the limited extrapolation between *this and y using the BHRZ03-widening operator.

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

Definition at line 840 of file Polyhedron_widenings.cc.

References add_recycled_constraints(), BHRZ03_widening_assign(), c, gen_sys, generators_are_up_to_date(), has_pending_constraints(), Parma_Polyhedra_Library::Constraint_System::has_strict_inequalities(), Parma_Polyhedra_Library::Constraint_System::insert(), is_necessarily_closed(), marked_empty(), minimize(), Parma_Polyhedra_Library::Constraint_System::num_rows(), process_pending_constraints(), Parma_Polyhedra_Library::Generator_System::satisfied_by_all_generators(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), and update_generators().

842  {
843  Polyhedron& x = *this;
844  const dimension_type cs_num_rows = cs.num_rows();
845  // If `cs' is empty, we fall back to ordinary, non-limited widening.
846  if (cs_num_rows == 0) {
847  x.BHRZ03_widening_assign(y, tp);
848  return;
849  }
850 
851  // Topology compatibility check.
852  if (x.is_necessarily_closed()) {
853  if (!y.is_necessarily_closed()) {
854  throw_topology_incompatible("limited_BHRZ03_extrapolation_assign(y, cs)",
855  "y", y);
856  }
857  if (cs.has_strict_inequalities()) {
858  throw_topology_incompatible("limited_BHRZ03_extrapolation_assign(y, cs)",
859  "cs", cs);
860  }
861  }
862  else if (y.is_necessarily_closed()) {
863  throw_topology_incompatible("limited_BHRZ03_extrapolation_assign(y, cs)",
864  "y", y);
865  }
866  // Dimension-compatibility check.
867  if (x.space_dim != y.space_dim) {
868  throw_dimension_incompatible("limited_BHRZ03_extrapolation_assign(y, cs)",
869  "y", y);
870  }
871  // `cs' must be dimension-compatible with the two polyhedra.
872  const dimension_type cs_space_dim = cs.space_dimension();
873  if (x.space_dim < cs_space_dim) {
874  throw_dimension_incompatible("limited_BHRZ03_extrapolation_assign(y, cs)",
875  "cs", cs);
876  }
877 
878  // Assume `y' is contained in or equal to `x'.
879  PPL_EXPECT_HEAVY(copy_contains(x, y));
880 
881  if (y.marked_empty()) {
882  return;
883  }
884  if (x.marked_empty()) {
885  return;
886  }
887 
888  // The limited BHRZ03-widening between two polyhedra in a
889  // zero-dimensional space is a polyhedron in a zero-dimensional
890  // space, too.
891  if (x.space_dim == 0) {
892  return;
893  }
894 
895  if (!y.minimize()) {
896  // We have just discovered that `y' is empty.
897  return;
898  }
899 
900  // Update the generators of `x': these are used to select,
901  // from the constraints in `cs', those that must be added
902  // to the resulting polyhedron.
903  if ((x.has_pending_constraints() && !x.process_pending_constraints())
904  || (!x.generators_are_up_to_date() && !x.update_generators())) {
905  // We have just discovered that `x' is empty.
906  return;
907  }
908 
909  Constraint_System new_cs;
910  // The constraints to be added must be satisfied by all the
911  // generators of `x'. We can disregard `y' because `y <= x'.
912  const Generator_System& x_gen_sys = x.gen_sys;
913  // Iterate upwards here so as to keep the relative ordering of constraints.
914  // Not really an issue: just aesthetics.
915  for (dimension_type i = 0; i < cs_num_rows; ++i) {
916  const Constraint& c = cs[i];
917  if (x_gen_sys.satisfied_by_all_generators(c)) {
918  new_cs.insert(c);
919  }
920  }
921  x.BHRZ03_widening_assign(y, tp);
922  x.add_recycled_constraints(new_cs);
923  PPL_ASSERT_HEAVY(OK());
924 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
void throw_topology_incompatible(const char *method, const char *ph_name, const Polyhedron &ph) const
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
Coefficient c
Definition: PIP_Tree.cc:64
void Parma_Polyhedra_Library::Polyhedron::limited_H79_extrapolation_assign ( const Polyhedron y,
const Constraint_System cs,
unsigned *  tp = 0 
)

Assigns to *this the result of computing the limited extrapolation between *this and y using the H79-widening operator.

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

Definition at line 300 of file Polyhedron_widenings.cc.

References add_recycled_constraints(), c, gen_sys, generators_are_up_to_date(), H79_widening_assign(), has_pending_constraints(), Parma_Polyhedra_Library::Constraint_System::has_strict_inequalities(), Parma_Polyhedra_Library::Constraint_System::insert(), is_necessarily_closed(), marked_empty(), minimize(), Parma_Polyhedra_Library::Constraint_System::num_rows(), process_pending_constraints(), Parma_Polyhedra_Library::Generator_System::satisfied_by_all_generators(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), and update_generators().

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

302  {
303  Polyhedron& x = *this;
304 
305  const dimension_type cs_num_rows = cs.num_rows();
306  // If `cs' is empty, we fall back to ordinary, non-limited widening.
307  if (cs_num_rows == 0) {
308  x.H79_widening_assign(y, tp);
309  return;
310  }
311 
312  // Topology compatibility check.
313  if (x.is_necessarily_closed()) {
314  if (!y.is_necessarily_closed()) {
315  throw_topology_incompatible("limited_H79_extrapolation_assign(y, cs)",
316  "y", y);
317  }
318  if (cs.has_strict_inequalities()) {
319  throw_topology_incompatible("limited_H79_extrapolation_assign(y, cs)",
320  "cs", cs);
321  }
322  }
323  else if (y.is_necessarily_closed()) {
324  throw_topology_incompatible("limited_H79_extrapolation_assign(y, cs)",
325  "y", y);
326  }
327  // Dimension-compatibility check.
328  if (x.space_dim != y.space_dim) {
329  throw_dimension_incompatible("limited_H79_extrapolation_assign(y, cs)",
330  "y", y);
331  }
332  // `cs' must be dimension-compatible with the two polyhedra.
333  const dimension_type cs_space_dim = cs.space_dimension();
334  if (x.space_dim < cs_space_dim) {
335  throw_dimension_incompatible("limited_H79_extrapolation_assign(y, cs)",
336  "cs", cs);
337  }
338  // Assume `y' is contained in or equal to `x'.
339  PPL_EXPECT_HEAVY(copy_contains(x, y));
340 
341  if (y.marked_empty()) {
342  return;
343  }
344  if (x.marked_empty()) {
345  return;
346  }
347  // The limited H79-widening between two polyhedra in a
348  // zero-dimensional space is a polyhedron in a zero-dimensional
349  // space, too.
350  if (x.space_dim == 0) {
351  return;
352  }
353 
354  if (!y.minimize()) {
355  // We have just discovered that `y' is empty.
356  return;
357  }
358 
359  // Update the generators of `x': these are used to select,
360  // from the constraints in `cs', those that must be added
361  // to the resulting polyhedron.
362  if ((x.has_pending_constraints() && !x.process_pending_constraints())
363  || (!x.generators_are_up_to_date() && !x.update_generators())) {
364  // We have just discovered that `x' is empty.
365  return;
366  }
367 
368  Constraint_System new_cs;
369  // The constraints to be added must be satisfied by all the
370  // generators of `x'. We can disregard `y' because `y <= x'.
371  const Generator_System& x_gen_sys = x.gen_sys;
372  // Iterate upwards here so as to keep the relative ordering of constraints.
373  // Not really an issue: just aesthetics.
374  for (dimension_type i = 0; i < cs_num_rows; ++i) {
375  const Constraint& c = cs[i];
376  if (x_gen_sys.satisfied_by_all_generators(c)) {
377  new_cs.insert(c);
378  }
379  }
380  x.H79_widening_assign(y, tp);
381  x.add_recycled_constraints(new_cs);
382  PPL_ASSERT_HEAVY(OK());
383 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
void throw_topology_incompatible(const char *method, const char *ph_name, const Polyhedron &ph) const
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
Coefficient c
Definition: PIP_Tree.cc:64
void Parma_Polyhedra_Library::Polyhedron::m_swap ( Polyhedron y)
inline

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

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

Definition at line 100 of file Polyhedron_inlines.hh.

References con_sys, gen_sys, sat_c, sat_g, space_dim, status, swap(), Parma_Polyhedra_Library::swap(), throw_topology_incompatible(), and topology().

Referenced by add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Implementation::Termination::all_affine_quasi_ranking_functions_MS(), Parma_Polyhedra_Library::Implementation::Termination::all_affine_ranking_functions_MS(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHRZ03_widening_assign(), H79_widening_assign(), map_space_dimensions(), Parma_Polyhedra_Library::NNC_Polyhedron::operator=(), Parma_Polyhedra_Library::C_Polyhedron::operator=(), and swap().

100  {
101  if (topology() != y.topology()) {
102  throw_topology_incompatible("swap(y)", "y", y);
103  }
104  using std::swap;
105  swap(con_sys, y.con_sys);
106  swap(gen_sys, y.gen_sys);
107  swap(sat_c, y.sat_c);
108  swap(sat_g, y.sat_g);
109  swap(status, y.status);
110  swap(space_dim, y.space_dim);
111 }
void swap(CO_Tree &x, CO_Tree &y)
Generator_System gen_sys
The system of generators.
void swap(Polyhedron &x, Polyhedron &y)
Swaps x with y.
Topology topology() const
Returns the topological kind of the polyhedron.
Constraint_System con_sys
The system of constraints.
void throw_topology_incompatible(const char *method, const char *ph_name, const Polyhedron &ph) const
Bit_Matrix sat_g
The saturation matrix having generators on its columns.
Status status
The status flags to keep track of the polyhedron's internal state.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
Bit_Matrix sat_c
The saturation matrix having constraints on its columns.
template<typename Partial_Function >
void Parma_Polyhedra_Library::Polyhedron::map_space_dimensions ( const Partial_Function pfunc)

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

Parameters
pfuncThe partial function specifying the destiny of each space dimension.

The template type parameter Partial_Function must provide the following methods.

bool has_empty_codomain() const

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

dimension_type max_in_codomain() const

returns the maximum value that belongs to the codomain of the partial function. The max_in_codomain() method is called at most once.

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. This method is called at most $n$ times, where $n$ is the dimension of the vector space enclosing the polyhedron.

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 153 of file Polyhedron_templates.hh.

References Parma_Polyhedra_Library::add_mul_assign(), Parma_Polyhedra_Library::Expression_Adapter< T >::begin(), Parma_Polyhedra_Library::Generator_System::begin(), Parma_Polyhedra_Library::Constraint_System::clear(), Parma_Polyhedra_Library::Generator::CLOSURE_POINT, con_sys, constraints_are_up_to_date(), Parma_Polyhedra_Library::Generator::divisor(), Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::Expression_Hide_Last< T >::end(), Parma_Polyhedra_Library::Generator_System::end(), Parma_Polyhedra_Library::Generator::expression(), gen_sys, generators(), generators_are_up_to_date(), Parma_Polyhedra_Library::Partial_Function::has_empty_codomain(), Parma_Polyhedra_Library::Generator_System::has_no_rows(), has_pending_constraints(), Parma_Polyhedra_Library::Generator_System::insert(), Parma_Polyhedra_Library::Generator::LINE, m_swap(), Parma_Polyhedra_Library::Partial_Function::maps(), marked_empty(), Parma_Polyhedra_Library::Partial_Function::max_in_codomain(), Parma_Polyhedra_Library::not_a_dimension(), OK(), Parma_Polyhedra_Library::Generator_System::permute_space_dimensions(), Parma_Polyhedra_Library::Constraint_System::permute_space_dimensions(), Parma_Polyhedra_Library::Generator::POINT, Parma_Polyhedra_Library::Generator::RAY, remove_pending_to_obtain_generators(), Parma_Polyhedra_Library::Linear_Expression::set_space_dimension(), set_zero_dim_univ(), space_dim, throw_invalid_argument(), topology(), Parma_Polyhedra_Library::Generator::type(), and update_generators().

153  {
154  if (space_dim == 0) {
155  return;
156  }
157  if (pfunc.has_empty_codomain()) {
158  // All dimensions vanish: the polyhedron becomes zero_dimensional.
159  if (marked_empty()
163  // Removing all dimensions from the empty polyhedron.
164  space_dim = 0;
165  con_sys.clear();
166  }
167  else {
168  // Removing all dimensions from a non-empty polyhedron.
170  }
171 
172  PPL_ASSERT_HEAVY(OK());
173  return;
174  }
175 
176  const dimension_type new_space_dimension = pfunc.max_in_codomain() + 1;
177 
178  if (new_space_dimension == space_dim) {
179  // The partial function `pfunc' is indeed total and thus specifies
180  // a permutation, that is, a renaming of the dimensions. For
181  // maximum efficiency, we will simply permute the columns of the
182  // constraint system and/or the generator system.
183 
184  std::vector<Variable> cycle;
185  cycle.reserve(space_dim);
186 
187  // Used to mark elements as soon as they are inserted in a cycle.
188  std::deque<bool> visited(space_dim);
189 
190  for (dimension_type i = space_dim; i-- > 0; ) {
191  if (visited[i]) {
192  continue;
193  }
194 
195  dimension_type j = i;
196  do {
197  visited[j] = true;
198  // The following initialization is only to make the compiler happy.
199  dimension_type k = 0;
200  if (!pfunc.maps(j, k)) {
201  throw_invalid_argument("map_space_dimensions(pfunc)",
202  " pfunc is inconsistent");
203  }
204  if (k == j) {
205  break;
206  }
207 
208  cycle.push_back(Variable(j));
209  // Go along the cycle.
210  j = k;
211  } while (!visited[j]);
212 
213  // End of cycle.
214 
215  // Permute all that is up-to-date. Notice that the contents of
216  // the saturation matrices is unaffected by the permutation of
217  // columns: they remain valid, if they were so.
220  }
221 
224  }
225 
226  cycle.clear();
227  }
228 
229  PPL_ASSERT_HEAVY(OK());
230  return;
231  }
232 
233  // If control gets here, then `pfunc' is not a permutation and some
234  // dimensions must be projected away.
235 
236  // If there are pending constraints, using `generators()' we process them.
237  const Generator_System& old_gensys = generators();
238 
239  if (old_gensys.has_no_rows()) {
240  // The polyhedron is empty.
241  Polyhedron new_polyhedron(topology(), new_space_dimension, EMPTY);
242  m_swap(new_polyhedron);
243  PPL_ASSERT_HEAVY(OK());
244  return;
245  }
246 
247  // Make a local copy of the partial function.
248  std::vector<dimension_type> pfunc_maps(space_dim, not_a_dimension());
249  for (dimension_type j = space_dim; j-- > 0; ) {
250  dimension_type pfunc_j;
251  if (pfunc.maps(j, pfunc_j)) {
252  pfunc_maps[j] = pfunc_j;
253  }
254  }
255 
256  Generator_System new_gensys;
257  for (Generator_System::const_iterator i = old_gensys.begin(),
258  old_gensys_end = old_gensys.end(); i != old_gensys_end; ++i) {
259  const Generator& old_g = *i;
260  const Generator::expr_type old_e = old_g.expression();
261  Linear_Expression expr;
262  expr.set_space_dimension(new_space_dimension);
263  bool all_zeroes = true;
264  for (Generator::expr_type::const_iterator j = old_e.begin(),
265  j_end = old_e.end(); j != j_end; ++j) {
266  const dimension_type mapped_id = pfunc_maps[j.variable().id()];
267  if (mapped_id != not_a_dimension()) {
268  add_mul_assign(expr, *j, Variable(mapped_id));
269  all_zeroes = false;
270  }
271  }
272  switch (old_g.type()) {
273  case Generator::LINE:
274  if (!all_zeroes) {
275  new_gensys.insert(line(expr));
276  }
277  break;
278  case Generator::RAY:
279  if (!all_zeroes) {
280  new_gensys.insert(ray(expr));
281  }
282  break;
283  case Generator::POINT:
284  // A point in the origin has all zero homogeneous coefficients.
285  new_gensys.insert(point(expr, old_g.divisor()));
286  break;
288  // A closure point in the origin has all zero homogeneous coefficients.
289  new_gensys.insert(closure_point(expr, old_g.divisor()));
290  break;
291  }
292  }
293  Polyhedron new_polyhedron(topology(), new_gensys);
294  m_swap(new_polyhedron);
295  PPL_ASSERT_HEAVY(OK(true));
296 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
The empty element, i.e., the empty set.
bool remove_pending_to_obtain_generators() const
Lazily integrates the pending descriptions of the polyhedron to obtain a generator system without pen...
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
dimension_type not_a_dimension()
Returns a value that does not designate a valid dimension.
void add_mul_assign(GMP_Integer &x, const GMP_Integer &y, const GMP_Integer &z)
Expression_Hide_Last< Expression_Hide_Inhomo< Linear_Expression > > expr_type
The type of the (adapted) internal expression.
bool update_generators() const
Updates generators starting from constraints and minimizes them.
void permute_space_dimensions(const std::vector< Variable > &cycle)
Permutes the space dimensions of the matrix.
void clear()
Removes all the constraints from the constraint system and sets its space dimension to 0...
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
Topology topology() const
Returns the topological kind of the polyhedron.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
void throw_invalid_argument(const char *method, const char *reason) const
Constraint_System con_sys
The system of constraints.
void permute_space_dimensions(const std::vector< Variable > &cycle)
Permutes the space dimensions of the matrix.
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
const Generator_System & generators() const
Returns the system of generators.
Generator_System_const_iterator const_iterator
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
base_type::const_iterator const_iterator
The type of const iterators on coefficients.
void m_swap(Polyhedron &y)
Swaps *this with polyhedron y. (*this and y can be dimension-incompatible.)
void set_zero_dim_univ()
Sets status to express that the polyhedron is the universe 0-dimension vector space, clearing all corresponding matrices.
bool Parma_Polyhedra_Library::Polyhedron::marked_empty ( ) const
inlineprivate

Returns true if the polyhedron is known to be empty.

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

Definition at line 130 of file Polyhedron_inlines.hh.

References status, and Parma_Polyhedra_Library::Polyhedron::Status::test_empty().

Referenced by add_space_dimensions_and_embed(), affine_form_image(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), BFT00_poly_hull_assign_if_exact(), Parma_Polyhedra_Library::BHRZ03_Certificate::BHRZ03_Certificate(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHRZ03_widening_assign(), BHZ09_poly_hull_assign_if_exact(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::BHRZ03_Certificate::compare(), Parma_Polyhedra_Library::H79_Certificate::compare(), concatenate_assign(), contains(), Parma_Polyhedra_Library::Grid::Grid(), Parma_Polyhedra_Library::H79_Certificate::H79_Certificate(), H79_widening_assign(), intersection_assign(), is_empty(), is_included_in(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), map_space_dimensions(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), operator=(), operator==(), poly_difference_assign(), poly_hull_assign(), positive_time_elapse_assign_impl(), process_pending(), quick_equivalence_test(), refine_with_linear_form_inequality(), select_CH78_constraints(), select_H79_constraints(), and time_elapse_assign().

130  {
131  return status.test_empty();
132 }
Status status
The status flags to keep track of the polyhedron's internal state.
bool Parma_Polyhedra_Library::Polyhedron::max_min ( const Linear_Expression expr,
bool  maximize,
Coefficient ext_n,
Coefficient ext_d,
bool &  included,
Generator g 
) const
private

Maximizes or minimizes expr subject to *this.

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

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

Definition at line 608 of file Polyhedron_nonpublic.cc.

References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Generator::expr, Parma_Polyhedra_Library::Scalar_Products::homogeneous_assign(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Generator::is_closure_point(), Parma_Polyhedra_Library::Generator::is_line(), Parma_Polyhedra_Library::Generator::is_line_or_ray(), Parma_Polyhedra_Library::Generator::is_point(), PPL_DIRTY_TEMP, PPL_DIRTY_TEMP_COEFFICIENT, PPL_UNINITIALIZED, Parma_Polyhedra_Library::ROUND_NOT_NEEDED, Parma_Polyhedra_Library::Boundary_NS::sgn(), and Parma_Polyhedra_Library::Linear_Expression::space_dimension().

Referenced by maximize(), and minimize().

612  {
613  // The dimension of `expr' should not be greater than the dimension
614  // of `*this'.
615  const dimension_type expr_space_dim = expr.space_dimension();
616  if (space_dim < expr_space_dim) {
618  ? "maximize(e, ...)"
619  : "minimize(e, ...)"), "e", expr);
620  }
621 
622  // Deal with zero-dim polyhedra first.
623  if (space_dim == 0) {
624  if (marked_empty()) {
625  return false;
626  }
627  else {
628  ext_n = expr.inhomogeneous_term();
629  ext_d = 1;
630  included = true;
631  g = point();
632  return true;
633  }
634  }
635 
636  // For an empty polyhedron we simply return false.
637  if (marked_empty()
640  return false;
641  }
642 
643  // The polyhedron has updated, possibly pending generators.
644  // The following loop will iterate through the generator
645  // to find the extremum.
646  PPL_DIRTY_TEMP(mpq_class, extremum);
647 
648  // True if we have no other candidate extremum to compare with.
649  bool first_candidate = true;
650 
651  // To store the position of the current candidate extremum.
652  PPL_UNINITIALIZED(dimension_type, ext_position);
653 
654  // Whether the current candidate extremum is included or not.
655  PPL_UNINITIALIZED(bool, ext_included);
656 
658  for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) {
659  const Generator& gen_sys_i = gen_sys[i];
660  Scalar_Products::homogeneous_assign(sp, expr, gen_sys_i);
661  // Lines and rays in `*this' can cause `expr' to be unbounded.
662  if (gen_sys_i.is_line_or_ray()) {
663  const int sp_sign = sgn(sp);
664  if (sp_sign != 0
665  && (gen_sys_i.is_line()
666  || (maximize && sp_sign > 0)
667  || (!maximize && sp_sign < 0))) {
668  // `expr' is unbounded in `*this'.
669  return false;
670  }
671  }
672  else {
673  // We have a point or a closure point.
674  PPL_ASSERT(gen_sys_i.is_point() || gen_sys_i.is_closure_point());
675  // Notice that we are ignoring the constant term in `expr' here.
676  // We will add it to the extremum as soon as we find it.
677  PPL_DIRTY_TEMP(mpq_class, candidate);
678  assign_r(candidate.get_num(), sp, ROUND_NOT_NEEDED);
679  assign_r(candidate.get_den(), gen_sys_i.expr.inhomogeneous_term(), ROUND_NOT_NEEDED);
680  candidate.canonicalize();
681  const bool g_is_point = gen_sys_i.is_point();
682  if (first_candidate
683  || (maximize
684  && (candidate > extremum
685  || (g_is_point
686  && !ext_included
687  && candidate == extremum)))
688  || (!maximize
689  && (candidate < extremum
690  || (g_is_point
691  && !ext_included
692  && candidate == extremum)))) {
693  // We have a (new) candidate extremum.
694  first_candidate = false;
695  extremum = candidate;
696  ext_position = i;
697  ext_included = g_is_point;
698  }
699  }
700  }
701 
702  // Add in the constant term in `expr'.
703  PPL_DIRTY_TEMP(mpz_class, n);
704  assign_r(n, expr.inhomogeneous_term(), ROUND_NOT_NEEDED);
705  extremum += n;
706 
707  // The polyhedron is bounded in the right direction and we have
708  // computed the extremum: write the result into the caller's structures.
709  PPL_ASSERT(!first_candidate);
710  ext_n = extremum.get_num();
711  ext_d = extremum.get_den();
712  included = ext_included;
713  g = gen_sys[ext_position];
714 
715  return true;
716 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
bool update_generators() const
Updates generators starting from constraints and minimizes them.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
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.
#define PPL_DIRTY_TEMP(T, id)
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool process_pending_constraints() const
Processes the pending constraints and obtains a minimized polyhedron.
int sgn(Boundary_Type type, const T &x, const Info &info)
static void homogeneous_assign(Coefficient &z, const Linear_Expression &x, const Linear_Expression &y)
Computes the homogeneous scalar product of x and y, where the inhomogeneous terms are ignored...
#define PPL_UNINITIALIZED(type, name)
Definition: compiler.hh:72
dimension_type Parma_Polyhedra_Library::Polyhedron::max_space_dimension ( )
inlinestatic

Returns the maximum space dimension all kinds of Polyhedron can handle.

Definition at line 50 of file Polyhedron_inlines.hh.

References Parma_Polyhedra_Library::Constraint_System::max_space_dimension(), and Parma_Polyhedra_Library::Generator_System::max_space_dimension().

Referenced by add_space_dimensions_and_embed(), check_obj_space_dimension_overflow(), check_space_dimension_overflow(), Parma_Polyhedra_Library::max_space_dimension(), and Polyhedron().

50  {
51  using std::min;
52  // One dimension is reserved to have a value of type dimension_type
53  // that does not represent a legal dimension.
54  return min(std::numeric_limits<dimension_type>::max() - 1,
57  )
58  );
59 }
static dimension_type max_space_dimension()
Returns the maximum space dimension a Constraint_System can handle.
static dimension_type max_space_dimension()
Returns the maximum space dimension a Generator_System can handle.
bool Parma_Polyhedra_Library::Polyhedron::maximize ( const Linear_Expression expr,
Coefficient sup_n,
Coefficient sup_d,
bool &  maximum 
) const
inline

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

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

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

Definition at line 324 of file Polyhedron_inlines.hh.

References max_min().

326  {
327  Generator g(point());
328  return max_min(expr, true, sup_n, sup_d, maximum, g);
329 }
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 Parma_Polyhedra_Library::Polyhedron::maximize ( const Linear_Expression expr,
Coefficient sup_n,
Coefficient sup_d,
bool &  maximum,
Generator g 
) const
inline

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

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

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

Definition at line 332 of file Polyhedron_inlines.hh.

References max_min().

334  {
335  return max_min(expr, true, sup_n, sup_d, maximum, g);
336 }
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 Parma_Polyhedra_Library::Polyhedron::minimize ( const Linear_Expression expr,
Coefficient inf_n,
Coefficient inf_d,
bool &  minimum 
) const
inline

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

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

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

Definition at line 339 of file Polyhedron_inlines.hh.

References max_min().

Referenced by BFT00_poly_hull_assign_if_exact(), Parma_Polyhedra_Library::BHRZ03_Certificate::BHRZ03_Certificate(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHRZ03_widening_assign(), BHZ09_C_poly_hull_assign_if_exact(), BHZ09_NNC_poly_hull_assign_if_exact(), Parma_Polyhedra_Library::BHRZ03_Certificate::compare(), Parma_Polyhedra_Library::H79_Certificate::compare(), Parma_Polyhedra_Library::Grid::Grid(), Parma_Polyhedra_Library::H79_Certificate::H79_Certificate(), H79_widening_assign(), is_included_in(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), poly_difference_assign(), and simplify_using_context_assign().

341  {
342  Generator g(point());
343  return max_min(expr, false, inf_n, inf_d, minimum, g);
344 }
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 Parma_Polyhedra_Library::Polyhedron::minimize ( const Linear_Expression expr,
Coefficient inf_n,
Coefficient inf_d,
bool &  minimum,
Generator g 
) const
inline

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

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

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

Definition at line 347 of file Polyhedron_inlines.hh.

References max_min().

349  {
350  return max_min(expr, false, inf_n, inf_d, minimum, g);
351 }
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 Parma_Polyhedra_Library::Polyhedron::minimize ( ) const
private

Applies (weak) minimization to both the constraints and generators.

Returns
false if and only if *this turns out to be an empty polyhedron.

Minimization is not attempted if the Status field already declares both systems to be minimized.

Definition at line 1105 of file Polyhedron_nonpublic.cc.

Referenced by is_empty().

1105  {
1106  // 0-dim space or empty polyhedra are already minimized.
1107  if (marked_empty()) {
1108  return false;
1109  }
1110  if (space_dim == 0) {
1111  return true;
1112  }
1113 
1114  // If the polyhedron has something pending, process it.
1115  if (has_something_pending()) {
1116  const bool not_empty = process_pending();
1117  PPL_ASSERT_HEAVY(OK());
1118  return not_empty;
1119  }
1120 
1121  // Here there are no pending constraints or generators.
1122  // Is the polyhedron already minimized?
1124  return true;
1125  }
1126 
1127  // If constraints or generators are up-to-date, invoking
1128  // update_generators() or update_constraints(), respectively,
1129  // minimizes both constraints and generators.
1130  // If both are up-to-date it does not matter whether we use
1131  // update_generators() or update_constraints():
1132  // both minimize constraints and generators.
1134  // We may discover here that `*this' is empty.
1135  const bool ret = update_generators();
1136  PPL_ASSERT_HEAVY(OK());
1137  return ret;
1138  }
1139  else {
1140  PPL_ASSERT(generators_are_up_to_date());
1142  PPL_ASSERT_HEAVY(OK());
1143  return true;
1144  }
1145 }
bool constraints_are_minimized() const
Returns true if the system of constraints is minimized.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
void update_constraints() const
Updates constraints starting from generators and minimizes them.
bool generators_are_minimized() const
Returns true if the system of generators is minimized.
bool update_generators() const
Updates generators starting from constraints and minimizes them.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
bool process_pending() const
Processes the pending rows of either description of the polyhedron and obtains a minimized polyhedron...
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
bool has_something_pending() const
Returns true if there are either pending constraints or pending generators.
template<typename Source_Linear_System , typename Dest_Linear_System >
bool Parma_Polyhedra_Library::Polyhedron::minimize ( bool  con_to_gen,
Source_Linear_System &  source,
Dest_Linear_System &  dest,
Bit_Matrix sat 
)
staticprivate

Builds and simplifies constraints from generators (or vice versa).

Returns
true if the polyhedron is empty, false otherwise.
Parameters
con_to_gentrue if source represents the constraints, false otherwise;
sourceThe given system, which is not empty;
destThe system to build and minimize;
satThe saturation matrix.

dest is not const because it will be built (and then modified) during minimize(). Also, sat and source are not const because the former will be built during dest creation and the latter will maybe be sorted and modified by conversion() and simplify().

sat has the generators on its columns and the constraints on its rows if con_to_gen is true, otherwise it has the generators on its rows and the constraints on its columns.

Given source, this function builds (by means of conversion()) dest and then simplifies (invoking simplify()) source, erasing redundant rows. For the sequel we assume that source is the system of constraints and dest is the system of generators. This will simplify the description of the function; the dual case is similar.

Definition at line 71 of file Polyhedron_minimize_templates.hh.

References conversion(), Parma_Polyhedra_Library::NECESSARILY_CLOSED, Parma_Polyhedra_Library::NOT_NECESSARILY_CLOSED, OK(), Parma_Polyhedra_Library::Linear_Expression::set_space_dimension(), simplify(), and Parma_Polyhedra_Library::Bit_Matrix::transpose_assign().

74  {
75 
76  typedef typename Dest_Linear_System::row_type dest_row_type;
77 
78  // Topologies have to agree.
79  PPL_ASSERT(source.topology() == dest.topology());
80  // `source' cannot be empty: even if it is an empty constraint system,
81  // representing the universe polyhedron, homogenization has added
82  // the positive constraint. It also cannot be an empty generator system,
83  // since this function is always called starting from a non-empty
84  // polyhedron.
85  PPL_ASSERT(!source.has_no_rows());
86 
87  // Sort the source system, if necessary.
88  if (!source.is_sorted()) {
89  source.sort_rows();
90  }
91  // Initialization of the system of generators `dest'.
92  // The algorithm works incrementally and we haven't seen any
93  // constraint yet: as a consequence, `dest' should describe
94  // the universe polyhedron of the appropriate dimension.
95  // To this end, we initialize it to the identity matrix of dimension
96  // `source.num_columns()': the rows represent the lines corresponding
97  // to the canonical basis of the vector space.
98  dimension_type dest_num_rows
99  = source.topology() == NECESSARILY_CLOSED ? source.space_dimension() + 1
100  : source.space_dimension() + 2;
101 
102  dest.clear();
103  dest.set_space_dimension(source.space_dimension());
104 
105  // Initialize `dest' to the identity matrix.
106  for (dimension_type i = 0; i < dest_num_rows; ++i) {
107  Linear_Expression expr;
108  expr.set_space_dimension(dest_num_rows - 1);
109  if (i == 0) {
110  expr += 1;
111  }
112  else {
113  expr += Variable(i - 1);
114  }
115  dest_row_type dest_i(expr, dest_row_type::LINE_OR_EQUALITY, NECESSARILY_CLOSED);
116  if (dest.topology() == NOT_NECESSARILY_CLOSED) {
117  dest_i.mark_as_not_necessarily_closed();
118  }
119  dest.sys.insert_no_ok(dest_i, Recycle_Input());
120  }
121  // The identity matrix `dest' is not sorted (see the sorting rules
122  // in Constrant.cc and Generator.cc).
123  dest.set_sorted(false);
124 
125  // NOTE: the system `dest', as it is now, is not a _legal_ system of
126  // generators, because in the first row we have a line with a
127  // non-zero divisor (which should only happen for
128  // points). However, this is NOT a problem, because `source'
129  // necessarily contains the positivity constraint (or a
130  // combination of it with another constraint) which will
131  // restore things as they should be.
132 
133 
134  // Building a saturation matrix and initializing it by setting
135  // all of its elements to zero. This matrix will be modified together
136  // with `dest' during the conversion.
137  // NOTE: since we haven't seen any constraint yet, the relevant
138  // portion of `tmp_sat' is the sub-matrix consisting of
139  // the first 0 columns: thus the relevant portion correctly
140  // characterizes the initial saturation information.
141  Bit_Matrix tmp_sat(dest_num_rows, source.num_rows());
142 
143  // By invoking the function conversion(), we populate `dest' with
144  // the generators characterizing the polyhedron described by all
145  // the constraints in `source'.
146  // The `start' parameter is zero (we haven't seen any constraint yet)
147  // and the 5th parameter (representing the number of lines in `dest'),
148  // by construction, is equal to `dest_num_rows'.
149  const dimension_type num_lines_or_equalities
150  = conversion(source, 0U, dest, tmp_sat, dest_num_rows);
151  // conversion() may have modified the number of rows in `dest'.
152  dest_num_rows = dest.num_rows();
153 
154 #ifndef NDEBUG
155  for (dimension_type i = dest.num_rows(); i-- > 0; ) {
156  PPL_ASSERT(dest[i].OK());
157  }
158 #endif
159 
160  // Checking if the generators in `dest' represent an empty polyhedron:
161  // the polyhedron is empty if there are no points
162  // (because rays, lines and closure points need a supporting point).
163  // Points can be detected by looking at:
164  // - the divisor, for necessarily closed polyhedra;
165  // - the epsilon coordinate, for NNC polyhedra.
166  dimension_type first_point;
167  if (dest.is_necessarily_closed()) {
168  for (first_point = num_lines_or_equalities;
169  first_point < dest_num_rows;
170  ++first_point) {
171  if (dest[first_point].expr.inhomogeneous_term() > 0) {
172  break;
173  }
174  }
175  }
176  else {
177  for (first_point = num_lines_or_equalities;
178  first_point < dest_num_rows;
179  ++first_point) {
180  if (dest[first_point].expr.get(Variable(dest.space_dimension())) > 0) {
181  break;
182  }
183  }
184  }
185 
186  if (first_point == dest_num_rows) {
187  if (con_to_gen) {
188  // No point has been found: the polyhedron is empty.
189  return true;
190  }
191  else {
192  // Here `con_to_gen' is false: `dest' is a system of constraints.
193  // In this case the condition `first_point == dest_num_rows'
194  // actually means that all the constraints in `dest' have their
195  // inhomogeneous term equal to 0.
196  // This is an ILLEGAL situation, because it implies that
197  // the constraint system `dest' lacks the positivity constraint
198  // and no linear combination of the constraints in `dest'
199  // can reintroduce the positivity constraint.
200  PPL_UNREACHABLE;
201  return false;
202  }
203  }
204  else {
205  // A point has been found: the polyhedron is not empty.
206  // Now invoking simplify() to remove all the redundant constraints
207  // from the system `source'.
208  // Since the saturation matrix `tmp_sat' returned by conversion()
209  // has rows indexed by generators (the rows of `dest') and columns
210  // indexed by constraints (the rows of `source'), we have to
211  // transpose it to obtain the saturation matrix needed by simplify().
212  sat.transpose_assign(tmp_sat);
213  simplify(source, sat);
214  return false;
215  }
216 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
static dimension_type simplify(Linear_System1 &sys, Bit_Matrix &sat)
Uses Gauss' elimination method to simplify the result of conversion().
static dimension_type conversion(Source_Linear_System &source, dimension_type start, Dest_Linear_System &dest, Bit_Matrix &sat, dimension_type num_lines_or_equalities)
Performs the conversion from constraints to generators and vice versa.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
Congruence_System Parma_Polyhedra_Library::Polyhedron::minimized_congruences ( ) const
inline

Returns a system of (equality) congruences satisfied by *this, with no redundant congruences and having the same affine dimension as *this.

Definition at line 372 of file Polyhedron_inlines.hh.

References minimized_constraints().

372  {
373  return Congruence_System(minimized_constraints());
374 }
const Constraint_System & minimized_constraints() const
Returns the system of constraints, with no redundant constraint.
const PPL::Constraint_System & Parma_Polyhedra_Library::Polyhedron::minimized_constraints ( ) const

Returns the system of constraints, with no redundant constraint.

Definition at line 125 of file Polyhedron_public.cc.

Referenced by Parma_Polyhedra_Library::Implementation::Termination::all_affine_quasi_ranking_functions_MS(), Parma_Polyhedra_Library::Implementation::Termination::all_affine_ranking_functions_MS(), Parma_Polyhedra_Library::Implementation::Termination::assign_all_inequalities_approximation(), Parma_Polyhedra_Library::BHRZ03_Certificate::BHRZ03_Certificate(), Parma_Polyhedra_Library::BHRZ03_Certificate::compare(), Parma_Polyhedra_Library::H79_Certificate::compare(), congruences(), Parma_Polyhedra_Library::H79_Certificate::H79_Certificate(), minimized_congruences(), Parma_Polyhedra_Library::Partially_Reduced_Product< D1, D2, R >::minimized_constraints(), and operator<<().

125  {
126  // `minimize()' or `strongly_minimize_constraints()'
127  // will process any pending constraints or generators.
128  if (is_necessarily_closed()) {
129  minimize();
130  }
131  else {
133  }
134  return constraints();
135 }
bool minimize() const
Applies (weak) minimization to both the constraints and generators.
bool strongly_minimize_constraints() const
Applies strong minimization to the constraints of an NNC polyhedron.
const Constraint_System & constraints() const
Returns the system of constraints.
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
const PPL::Generator_System & Parma_Polyhedra_Library::Polyhedron::minimized_generators ( ) const

Returns the system of generators, with no redundant generator.

Definition at line 193 of file Polyhedron_public.cc.

Referenced by Parma_Polyhedra_Library::BHRZ03_Certificate::BHRZ03_Certificate(), and Parma_Polyhedra_Library::BHRZ03_Certificate::compare().

193  {
194  // `minimize()' or `strongly_minimize_generators()'
195  // will process any pending constraints or generators.
196  if (is_necessarily_closed()) {
197  minimize();
198  }
199  else {
201  }
202  // Note: calling generators() on a strongly minimized NNC generator
203  // system will also ensure sortedness, which is required to correctly
204  // filter away the matched closure points.
205  return generators();
206 }
bool minimize() const
Applies (weak) minimization to both the constraints and generators.
bool strongly_minimize_generators() const
Applies strong minimization to the generators of an NNC polyhedron.
const Generator_System & generators() const
Returns the system of generators.
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
void Parma_Polyhedra_Library::Polyhedron::modify_according_to_evolution ( Linear_Expression ray,
const Linear_Expression x,
const Linear_Expression y 
)
staticprivate

Definition at line 602 of file Polyhedron_widenings.cc.

References Parma_Polyhedra_Library::Linear_Expression::begin(), Parma_Polyhedra_Library::Coefficient_zero(), Parma_Polyhedra_Library::Linear_Expression::end(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Linear_Expression::normalize(), PPL_DIRTY_TEMP_COEFFICIENT, Parma_Polyhedra_Library::Linear_Expression::set_coefficient(), Parma_Polyhedra_Library::Boundary_NS::sgn(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::sub_mul_assign(), and Parma_Polyhedra_Library::Linear_Expression::const_iterator::variable().

604  {
606  std::deque<bool> considered(x.space_dimension());
607  Linear_Expression::const_iterator x_end = x.end();
608  Linear_Expression::const_iterator y_end = y.end();
609  Linear_Expression::const_iterator y_k = y.begin();
610  for (Linear_Expression::const_iterator x_k = x.begin();
611  x_k != x_end; ++x_k) {
612  const Variable k_var = x_k.variable();
613  const dimension_type k = k_var.id();
614  if (considered[k]) {
615  continue;
616  }
617 
618  while (y_k != y_end && y_k.variable().id() < k) {
619  ++y_k;
620  }
621 
622  if (y_k == y_end) {
623  break;
624  }
625 
626  const Variable y_k_var = y_k.variable();
627 
628  // Note that y_k_var.id() may be greater than k.
629 
630  Linear_Expression::const_iterator y_h = y_k;
631  // Do *not* increment y_h, since it may be after k already.
632  Linear_Expression::const_iterator x_h = x_k;
633  ++x_h;
634  for ( ; x_h != x_end; ++x_h) {
635  const dimension_type h = x_h.variable().id();
636  if (considered[h]) {
637  continue;
638  }
639 
640  while (y_h != y_end && y_h.variable().id() < h) {
641  ++y_h;
642  }
643 
644  // Note that y_h may be y_end, and y_h.variable().id() may not be k.
645 
646  if (y_h != y_end && y_h.variable().id() == h) {
647  tmp = (*x_k) * (*y_h);
648  }
649  else {
650  tmp = 0;
651  }
652 
653  if (y_k_var.id() == k) {
654  // The following line optimizes the computation of
655  // <CODE> tmp -= x[h] * y[k]; </CODE>
657  }
658 
659  const int clockwise = sgn(tmp);
660  const int first_or_third_quadrant = sgn(*x_k) * sgn(*x_h);
661  switch (clockwise * first_or_third_quadrant) {
662  case -1:
663  ray.set_coefficient(k_var, Coefficient_zero());
664  considered[k] = true;
665  break;
666  case 1:
667  ray.set_coefficient(Variable(h), Coefficient_zero());
668  considered[h] = true;
669  break;
670  default:
671  break;
672  }
673  }
674  }
675  ray.normalize();
676 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
Coefficient_traits::const_reference Coefficient_zero()
Returns a const reference to a Coefficient with value 0.
int sgn(Boundary_Type type, const T &x, const Info &info)
void sub_mul_assign(GMP_Integer &x, const GMP_Integer &y, const GMP_Integer &z)
void Parma_Polyhedra_Library::Polyhedron::obtain_sorted_constraints ( ) const
private

Sorts the matrix of constraints keeping status consistency.

It is assumed that constraints are up-to-date. If at least one of the saturation matrices is up-to-date, then sat_g is kept consistent with the sorted matrix of constraints. The method is declared const because reordering the constraints does not modify the polyhedron from a logical point of view.

Definition at line 975 of file Polyhedron_nonpublic.cc.

References clear_sat_c_up_to_date(), con_sys, Parma_Polyhedra_Library::Constraint_System::is_sorted(), sat_c, sat_c_is_up_to_date(), sat_g, sat_g_is_up_to_date(), set_sat_g_up_to_date(), Parma_Polyhedra_Library::Constraint_System::sort_and_remove_with_sat(), Parma_Polyhedra_Library::Constraint_System::sort_rows(), and Parma_Polyhedra_Library::Bit_Matrix::transpose_assign().

Referenced by quick_equivalence_test().

975  {
976  PPL_ASSERT(constraints_are_up_to_date());
977  // `con_sys' will be sorted up to `index_first_pending'.
978  Polyhedron& x = const_cast<Polyhedron&>(*this);
979  if (!x.con_sys.is_sorted()) {
980  if (x.sat_g_is_up_to_date()) {
981  // Sorting constraints keeping `sat_g' consistent.
982  x.con_sys.sort_and_remove_with_sat(x.sat_g);
983  // `sat_c' is not up-to-date anymore.
984  x.clear_sat_c_up_to_date();
985  }
986  else if (x.sat_c_is_up_to_date()) {
987  // Using `sat_c' to obtain `sat_g', then it is like previous case.
988  x.sat_g.transpose_assign(x.sat_c);
989  x.con_sys.sort_and_remove_with_sat(x.sat_g);
990  x.set_sat_g_up_to_date();
991  x.clear_sat_c_up_to_date();
992  }
993  else {
994  // If neither `sat_g' nor `sat_c' are up-to-date,
995  // we just sort the constraints.
996  x.con_sys.sort_rows();
997  }
998  }
999 
1000  PPL_ASSERT(con_sys.check_sorted());
1001 }
bool check_sorted() const
Returns true if and only if *this is sorted, without checking for duplicates.
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
Constraint_System con_sys
The system of constraints.
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
void Parma_Polyhedra_Library::Polyhedron::obtain_sorted_constraints_with_sat_c ( ) const
private

Sorts the matrix of constraints and updates sat_c.

It is assumed that both constraints and generators are up-to-date and minimized. The method is declared const because reordering the constraints does not modify the polyhedron from a logical point of view.

Definition at line 1033 of file Polyhedron_nonpublic.cc.

References con_sys, Parma_Polyhedra_Library::Constraint_System::is_sorted(), sat_c, sat_c_is_up_to_date(), sat_g, sat_g_is_up_to_date(), set_sat_c_up_to_date(), set_sat_g_up_to_date(), Parma_Polyhedra_Library::Constraint_System::set_sorted(), Parma_Polyhedra_Library::Constraint_System::sort_and_remove_with_sat(), Parma_Polyhedra_Library::Bit_Matrix::transpose_assign(), and update_sat_c().

Referenced by process_pending_constraints().

1033  {
1034  PPL_ASSERT(constraints_are_up_to_date());
1035  PPL_ASSERT(constraints_are_minimized());
1036  // `con_sys' will be sorted up to `index_first_pending'.
1037  Polyhedron& x = const_cast<Polyhedron&>(*this);
1038  // At least one of the saturation matrices must be up-to-date.
1039  if (!x.sat_c_is_up_to_date() && !x.sat_g_is_up_to_date()) {
1040  x.update_sat_c();
1041  }
1042  if (x.con_sys.is_sorted()) {
1043  if (x.sat_c_is_up_to_date()) {
1044  // If constraints are already sorted and sat_c is up to
1045  // date there is nothing to do.
1046  return;
1047  }
1048  }
1049  else {
1050  if (!x.sat_g_is_up_to_date()) {
1051  // If constraints are not sorted and sat_g is not up-to-date
1052  // we obtain sat_g from sat_c (that has to be up-to-date)...
1053  x.sat_g.transpose_assign(x.sat_c);
1054  x.set_sat_g_up_to_date();
1055  }
1056  // ... and sort it together with constraints.
1057  x.con_sys.sort_and_remove_with_sat(x.sat_g);
1058  }
1059  // Obtaining sat_c from sat_g.
1060  x.sat_c.transpose_assign(x.sat_g);
1061  x.set_sat_c_up_to_date();
1062  // Constraints are sorted now.
1063  x.con_sys.set_sorted(true);
1064 
1065  PPL_ASSERT(con_sys.check_sorted());
1066 }
bool constraints_are_minimized() const
Returns true if the system of constraints is minimized.
bool check_sorted() const
Returns true if and only if *this is sorted, without checking for duplicates.
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
Constraint_System con_sys
The system of constraints.
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
void Parma_Polyhedra_Library::Polyhedron::obtain_sorted_generators ( ) const
private

Sorts the matrix of generators keeping status consistency.

It is assumed that generators are up-to-date. If at least one of the saturation matrices is up-to-date, then sat_c is kept consistent with the sorted matrix of generators. The method is declared const because reordering the generators does not modify the polyhedron from a logical point of view.

Definition at line 1004 of file Polyhedron_nonpublic.cc.

References clear_sat_g_up_to_date(), gen_sys, Parma_Polyhedra_Library::Generator_System::is_sorted(), sat_c, sat_c_is_up_to_date(), sat_g, sat_g_is_up_to_date(), set_sat_c_up_to_date(), Parma_Polyhedra_Library::Generator_System::sort_and_remove_with_sat(), Parma_Polyhedra_Library::Generator_System::sort_rows(), and Parma_Polyhedra_Library::Bit_Matrix::transpose_assign().

Referenced by quick_equivalence_test().

1004  {
1005  PPL_ASSERT(generators_are_up_to_date());
1006  // `gen_sys' will be sorted up to `index_first_pending'.
1007  Polyhedron& x = const_cast<Polyhedron&>(*this);
1008  if (!x.gen_sys.is_sorted()) {
1009  if (x.sat_c_is_up_to_date()) {
1010  // Sorting generators keeping 'sat_c' consistent.
1011  x.gen_sys.sort_and_remove_with_sat(x.sat_c);
1012  // `sat_g' is not up-to-date anymore.
1013  x.clear_sat_g_up_to_date();
1014  }
1015  else if (x.sat_g_is_up_to_date()) {
1016  // Obtaining `sat_c' from `sat_g' and proceeding like previous case.
1017  x.sat_c.transpose_assign(x.sat_g);
1018  x.gen_sys.sort_and_remove_with_sat(x.sat_c);
1019  x.set_sat_c_up_to_date();
1020  x.clear_sat_g_up_to_date();
1021  }
1022  else {
1023  // If neither `sat_g' nor `sat_c' are up-to-date, we just sort
1024  // the generators.
1025  x.gen_sys.sort_rows();
1026  }
1027  }
1028 
1029  PPL_ASSERT(gen_sys.check_sorted());
1030 }
Generator_System gen_sys
The system of generators.
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
bool check_sorted() const
Returns true if and only if *this is sorted, without checking for duplicates.
void Parma_Polyhedra_Library::Polyhedron::obtain_sorted_generators_with_sat_g ( ) const
private

Sorts the matrix of generators and updates sat_g.

It is assumed that both constraints and generators are up-to-date and minimized. The method is declared const because reordering the generators does not modify the polyhedron from a logical point of view.

Definition at line 1069 of file Polyhedron_nonpublic.cc.

References gen_sys, Parma_Polyhedra_Library::Generator_System::is_sorted(), sat_c, sat_c_is_up_to_date(), sat_g, sat_g_is_up_to_date(), set_sat_c_up_to_date(), set_sat_g_up_to_date(), Parma_Polyhedra_Library::Generator_System::set_sorted(), Parma_Polyhedra_Library::Generator_System::sort_and_remove_with_sat(), Parma_Polyhedra_Library::Bit_Matrix::transpose_assign(), and update_sat_g().

Referenced by process_pending_generators().

1069  {
1070  PPL_ASSERT(generators_are_up_to_date());
1071  // `gen_sys' will be sorted up to `index_first_pending'.
1072  Polyhedron& x = const_cast<Polyhedron&>(*this);
1073  // At least one of the saturation matrices must be up-to-date.
1074  if (!x.sat_c_is_up_to_date() && !x.sat_g_is_up_to_date()) {
1075  x.update_sat_g();
1076  }
1077 
1078  if (x.gen_sys.is_sorted()) {
1079  if (x.sat_g_is_up_to_date()) {
1080  // If generators are already sorted and sat_g is up to
1081  // date there is nothing to do.
1082  return;
1083  }
1084  }
1085  else {
1086  if (!x.sat_c_is_up_to_date()) {
1087  // If generators are not sorted and sat_c is not up-to-date
1088  // we obtain sat_c from sat_g (that has to be up-to-date)...
1089  x.sat_c.transpose_assign(x.sat_g);
1090  x.set_sat_c_up_to_date();
1091  }
1092  // ... and sort it together with generators.
1093  x.gen_sys.sort_and_remove_with_sat(x.sat_c);
1094  }
1095  // Obtaining sat_g from sat_c.
1096  x.sat_g.transpose_assign(sat_c);
1097  x.set_sat_g_up_to_date();
1098  // Generators are sorted now.
1099  x.gen_sys.set_sorted(true);
1100 
1101  PPL_ASSERT(gen_sys.check_sorted());
1102 }
Generator_System gen_sys
The system of generators.
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
bool check_sorted() const
Returns true if and only if *this is sorted, without checking for duplicates.
Bit_Matrix sat_c
The saturation matrix having constraints on its columns.
bool Parma_Polyhedra_Library::Polyhedron::OK ( bool  check_not_empty = false) const

Checks if all the invariants are satisfied.

Returns
true if and only if *this satisfies all the invariants and either check_not_empty is false or *this is not empty.
Parameters
check_not_emptytrue if and only if, in addition to checking the invariants, *this must be checked to be not empty.

The check is performed so as to intrude as little as possible. If the library has been compiled with run-time assertions enabled, error messages are written on std::cerr in case invariants are violated. This is useful for the purpose of debugging the library.

Definition at line 832 of file Polyhedron_public.cc.

References Parma_Polyhedra_Library::ascii_dump(), Parma_Polyhedra_Library::Constraint_System::ascii_dump(), Parma_Polyhedra_Library::Generator_System::ascii_dump(), Parma_Polyhedra_Library::Implementation::BD_Shapes::empty, Parma_Polyhedra_Library::Constraint_System::num_equalities(), Parma_Polyhedra_Library::Generator_System::num_lines(), Parma_Polyhedra_Library::Generator_System::num_rays(), Parma_Polyhedra_Library::Generator_System::num_rows(), Parma_Polyhedra_Library::Constraint_System::num_rows(), Parma_Polyhedra_Library::Constraint_System::remove_trailing_rows(), Parma_Polyhedra_Library::Generator_System::remove_trailing_rows(), Parma_Polyhedra_Library::Scalar_Products::sign(), Parma_Polyhedra_Library::Constraint_System::simplify(), Parma_Polyhedra_Library::Generator_System::sort_rows(), Parma_Polyhedra_Library::Constraint_System::sort_rows(), Parma_Polyhedra_Library::Constraint_System::strong_normalize(), Parma_Polyhedra_Library::Generator_System::strong_normalize(), Parma_Polyhedra_Library::Generator_System::unset_pending_rows(), and Parma_Polyhedra_Library::Constraint_System::unset_pending_rows().

Referenced by add_space_dimensions_and_embed(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHRZ03_widening_assign(), Parma_Polyhedra_Library::C_Polyhedron::C_Polyhedron(), H79_widening_assign(), intersection_assign(), is_included_in(), map_space_dimensions(), minimize(), Parma_Polyhedra_Library::NNC_Polyhedron::NNC_Polyhedron(), poly_hull_assign(), Polyhedron(), positive_time_elapse_assign_impl(), simplify_using_context_assign(), and time_elapse_assign().

832  {
833 #ifndef NDEBUG
834  using std::endl;
835  using std::cerr;
836 #endif
837 
838  // Check whether the topologies of `con_sys' and `gen_sys' agree.
839  if (con_sys.topology() != gen_sys.topology()) {
840 #ifndef NDEBUG
841  cerr << "Constraints and generators have different topologies!"
842  << endl;
843 #endif
844  goto bomb;
845  }
846 
847  // Check whether the status information is legal.
848  if (!status.OK()) {
849  goto bomb;
850  }
851 
852  if (marked_empty()) {
853  if (check_not_empty) {
854  // The caller does not want the polyhedron to be empty.
855 #ifndef NDEBUG
856  cerr << "Empty polyhedron!" << endl;
857 #endif
858  goto bomb;
859  }
860 
861  // An empty polyhedron is allowed if the system of constraints
862  // either has no rows or only contains an unsatisfiable constraint
863  // and if it has no pending constraints or generators.
864  if (has_something_pending()) {
865 #ifndef NDEBUG
866  cerr << "The polyhedron is empty, "
867  << "but it has something pending" << endl;
868 #endif
869  goto bomb;
870  }
871  if (con_sys.has_no_rows()) {
872  return true;
873  }
874  else {
875  if (con_sys.space_dimension() != space_dim) {
876 #ifndef NDEBUG
877  cerr << "The polyhedron is in a space of dimension "
878  << space_dim
879  << " while the system of constraints is in a space of dimension "
881  << endl;
882 #endif
883  goto bomb;
884  }
885  if (con_sys.num_rows() != 1) {
886 #ifndef NDEBUG
887  cerr << "The system of constraints for an empty polyhedron "
888  << "has more then one row"
889  << endl;
890 #endif
891  goto bomb;
892  }
893  if (!con_sys[0].is_inconsistent()) {
894 #ifndef NDEBUG
895  cerr << "Empty polyhedron with a satisfiable system of constraints"
896  << endl;
897 #endif
898  goto bomb;
899  }
900  // Here we have only one, inconsistent constraint.
901  return true;
902  }
903  }
904 
905  // A zero-dimensional, non-empty polyhedron is legal only if the
906  // system of constraint `con_sys' and the system of generators
907  // `gen_sys' have no rows.
908  if (space_dim == 0) {
909  if (has_something_pending()) {
910 #ifndef NDEBUG
911  cerr << "Zero-dimensional polyhedron with something pending"
912  << endl;
913 #endif
914  goto bomb;
915  }
916  if (!con_sys.has_no_rows() || !gen_sys.has_no_rows()) {
917 #ifndef NDEBUG
918  cerr << "Zero-dimensional polyhedron with a non-empty"
919  << endl
920  << "system of constraints or generators."
921  << endl;
922 #endif
923  goto bomb;
924  }
925  return true;
926  }
927 
928  // A polyhedron is defined by a system of constraints
929  // or a system of generators: at least one of them must be up to date.
931 #ifndef NDEBUG
932  cerr << "Polyhedron not empty, not zero-dimensional"
933  << endl
934  << "and with neither constraints nor generators up-to-date!"
935  << endl;
936 #endif
937  goto bomb;
938  }
939 
940  // Here we check if the size of the matrices is consistent.
941  // Let us suppose that all the matrices are up-to-date; this means:
942  // `con_sys' : number of constraints x poly_num_columns
943  // `gen_sys' : number of generators x poly_num_columns
944  // `sat_c' : number of generators x number of constraints
945  // `sat_g' : number of constraints x number of generators.
947  if (con_sys.space_dimension() != space_dim) {
948 #ifndef NDEBUG
949  cerr << "Incompatible size! (con_sys and space_dim)"
950  << endl;
951 #endif
952  goto bomb;
953  }
954  if (sat_c_is_up_to_date()) {
956 #ifndef NDEBUG
957  cerr << "Incompatible size! (con_sys and sat_c)"
958  << endl;
959 #endif
960  goto bomb;
961  }
962  }
963  if (sat_g_is_up_to_date()) {
965 #ifndef NDEBUG
966  cerr << "Incompatible size! (con_sys and sat_g)"
967  << endl;
968 #endif
969  goto bomb;
970  }
971  }
974 #ifndef NDEBUG
975  cerr << "Incompatible size! (con_sys and gen_sys)"
976  << endl;
977 #endif
978  goto bomb;
979  }
980  }
981  }
982 
984  if (gen_sys.space_dimension() != space_dim) {
985 #ifndef NDEBUG
986  cerr << "Incompatible size! (gen_sys and space_dim)"
987  << endl;
988 #endif
989  goto bomb;
990  }
991  if (sat_c_is_up_to_date()) {
993 #ifndef NDEBUG
994  cerr << "Incompatible size! (gen_sys and sat_c)"
995  << endl;
996 #endif
997  goto bomb;
998  }
999  }
1000  if (sat_g_is_up_to_date()) {
1002 #ifndef NDEBUG
1003  cerr << "Incompatible size! (gen_sys and sat_g)"
1004  << endl;
1005 #endif
1006  goto bomb;
1007  }
1008  }
1009  if (gen_sys.first_pending_row() == 0) {
1010 #ifndef NDEBUG
1011  cerr << "Up-to-date generator system with all rows pending!"
1012  << endl;
1013 #endif
1014  goto bomb;
1015  }
1016 
1017  // A non-empty system of generators describing a polyhedron
1018  // is valid if and only if it contains a point.
1019  if (!gen_sys.has_no_rows() && !gen_sys.has_points()) {
1020 #ifndef NDEBUG
1021  cerr << "Non-empty generator system declared up-to-date "
1022  << "has no points!"
1023  << endl;
1024 #endif
1025  goto bomb;
1026  }
1027 
1028 #if 0 // To be activated when Status keeps strong minimization flags.
1029  //=================================================
1030  // TODO: this test is wrong in the general case.
1031  // However, such an invariant does hold for a
1032  // strongly-minimized Generator_System.
1033  // We will activate this test as soon as the Status
1034  // flags will be able to remember if a system is
1035  // strongly minimized.
1036 
1037  // Checking that the number of closure points is always
1038  // greater than the number of points.
1039  if (!is_necessarily_closed()) {
1040  dimension_type num_points = 0;
1041  dimension_type num_closure_points = 0;
1042  dimension_type eps_index = gen_sys.space_dimension() + 1;
1043  for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) {
1044  if (!gen_sys[i].is_line_or_ray()) {
1045  if (gen_sys[i][eps_index] > 0) {
1046  ++num_points;
1047  }
1048  else {
1049  ++num_closure_points;
1050  }
1051  }
1052  }
1053  if (num_points > num_closure_points) {
1054 #ifndef NDEBUG
1055  cerr << "# POINTS > # CLOSURE_POINTS" << endl;
1056 #endif
1057  goto bomb;
1058  }
1059  }
1060  //=================================================
1061 #endif
1062 
1063  if (generators_are_minimized()) {
1064  // If the system of generators is minimized, the number of
1065  // lines, rays and points of the polyhedron must be the same as
1066  // of a temporary, minimized one. If this does not happen then
1067  // the polyhedron is not OK.
1069  Generator_System gs_without_pending = gen_sys;
1070  gs_without_pending.remove_trailing_rows(gs_without_pending.num_rows()
1072  gs_without_pending.unset_pending_rows();
1073  Generator_System copy_of_gen_sys = gs_without_pending;
1074  Bit_Matrix new_sat_c;
1075  minimize(false, copy_of_gen_sys, new_con_sys, new_sat_c);
1076  const dimension_type copy_num_lines = copy_of_gen_sys.num_lines();
1077  if (gs_without_pending.num_rows() != copy_of_gen_sys.num_rows()
1078  || gs_without_pending.num_lines() != copy_num_lines
1079  || gs_without_pending.num_rays() != copy_of_gen_sys.num_rays()) {
1080 #ifndef NDEBUG
1081  cerr << "Generators are declared minimized, but they are not!\n"
1082  << "Here is the minimized form of the generators:\n";
1083  copy_of_gen_sys.ascii_dump(cerr);
1084  cerr << endl;
1085 #endif
1086  goto bomb;
1087  }
1088 
1089  // CHECKME : the following observation is not formally true
1090  // for a NNC_Polyhedron. But it may be true for its
1091  // representation ...
1092 
1093  // If the corresponding polyhedral cone is _pointed_, then
1094  // a minimal system of generators is unique up to positive scaling.
1095  // We thus verify if the cone is pointed (i.e., there are no lines)
1096  // and, after normalizing and sorting a copy of the system `gen_sys'
1097  // of the polyhedron (we use a copy not to modify the polyhedron's
1098  // system) and the system `copy_of_gen_sys' that has been just
1099  // minimized, we check if the two matrices are identical. If
1100  // they are different it means that the generators of the
1101  // polyhedron are declared minimized, but they are not.
1102  if (copy_num_lines == 0) {
1103  copy_of_gen_sys.strong_normalize();
1104  copy_of_gen_sys.sort_rows();
1105  gs_without_pending.strong_normalize();
1106  gs_without_pending.sort_rows();
1107  if (copy_of_gen_sys != gs_without_pending) {
1108 #ifndef NDEBUG
1109  cerr << "Generators are declared minimized, but they are not!\n"
1110  << "(we are in the case:\n"
1111  << "dimension of lineality space equal to 0)\n"
1112  << "Here is the minimized form of the generators:\n";
1113  copy_of_gen_sys.ascii_dump(cerr);
1114  cerr << endl;
1115 #endif
1116  goto bomb;
1117  }
1118  }
1119  }
1120  }
1121 
1123  if (con_sys.first_pending_row() == 0) {
1124 #ifndef NDEBUG
1125  cerr << "Up-to-date constraint system with all rows pending!"
1126  << endl;
1127 #endif
1128  goto bomb;
1129  }
1130 
1131  // A non-empty system of constraints describing a polyhedron
1132  // must contain a constraint with a non-zero inhomogeneous term;
1133  // such a constraint corresponds to (a combination of other
1134  // constraints with):
1135  // -* the positivity constraint, for necessarily closed polyhedra;
1136  // -* the epsilon <= 1 constraint, for NNC polyhedra.
1137  bool no_positivity_constraint = true;
1138  for (dimension_type i = con_sys.num_rows(); i-- > 0; ) {
1139  if (con_sys[i].inhomogeneous_term() != 0) {
1140  no_positivity_constraint = false;
1141  break;
1142  }
1143  }
1144  if (no_positivity_constraint) {
1145 #ifndef NDEBUG
1146  cerr << "Non-empty constraint system has no positivity constraint"
1147  << endl;
1148 #endif
1149  goto bomb;
1150  }
1151 
1152  if (!is_necessarily_closed()) {
1153  // A non-empty system of constraints describing a NNC polyhedron
1154  // must also contain a (combination of) the constraint epsilon >= 0,
1155  // i.e., a constraint with a positive epsilon coefficient.
1156  bool no_epsilon_geq_zero = true;
1157  for (dimension_type i = con_sys.num_rows(); i-- > 0; ) {
1158  if (con_sys[i].epsilon_coefficient() > 0) {
1159  no_epsilon_geq_zero = false;
1160  break;
1161  }
1162  }
1163  if (no_epsilon_geq_zero) {
1164 #ifndef NDEBUG
1165  cerr << "Non-empty constraint system for NNC polyhedron "
1166  << "has no epsilon >= 0 constraint"
1167  << endl;
1168 #endif
1169  goto bomb;
1170  }
1171  }
1172 
1173  Constraint_System cs_without_pending = con_sys;
1174  cs_without_pending.remove_trailing_rows(cs_without_pending.num_rows()
1176  cs_without_pending.unset_pending_rows();
1177  Constraint_System copy_of_con_sys = cs_without_pending;
1178  bool empty = false;
1179  if (check_not_empty || constraints_are_minimized()) {
1181  Bit_Matrix new_sat_g;
1182  empty = minimize(true, copy_of_con_sys, new_gen_sys, new_sat_g);
1183  }
1184 
1185  if (empty && check_not_empty) {
1186 #ifndef NDEBUG
1187  cerr << "Unsatisfiable system of constraints!"
1188  << endl;
1189 #endif
1190  goto bomb;
1191  }
1192 
1193  if (constraints_are_minimized()) {
1194  // If the constraints are minimized, the number of equalities
1195  // and of inequalities of the system of the polyhedron must be
1196  // the same of the temporary minimized one.
1197  // If it does not happen, the polyhedron is not OK.
1198  if (cs_without_pending.num_rows() != copy_of_con_sys.num_rows()
1199  || cs_without_pending.num_equalities()
1200  != copy_of_con_sys.num_equalities()) {
1201 #ifndef NDEBUG
1202  cerr << "Constraints are declared minimized, but they are not!\n"
1203  << "Here is the minimized form of the constraints:\n";
1204  copy_of_con_sys.ascii_dump(cerr);
1205  cerr << endl;
1206 #endif
1207  goto bomb;
1208  }
1209  // The system `copy_of_con_sys' has the form that is obtained
1210  // after applying methods gauss() and back_substitute().
1211  // A system of constraints can be minimal even if it does not
1212  // have this form. So, to verify if the polyhedron is correct,
1213  // we copy the system `con_sys' in a temporary one and then
1214  // modify it using method simplify() (which calls both gauss()
1215  // and back_substitute()).
1216  // If the temporary system and `copy_of_con_sys' are different,
1217  // the polyhedron is not OK.
1218  copy_of_con_sys.strong_normalize();
1219  copy_of_con_sys.sort_rows();
1220  cs_without_pending.simplify();
1221  cs_without_pending.strong_normalize();
1222  cs_without_pending.sort_rows();
1223  if (cs_without_pending != copy_of_con_sys) {
1224 #ifndef NDEBUG
1225  cerr << "Constraints are declared minimized, but they are not!\n"
1226  << "Here is the minimized form of the constraints:\n";
1227  copy_of_con_sys.ascii_dump(cerr);
1228  cerr << endl;
1229 #endif
1230  goto bomb;
1231  }
1232  }
1233  }
1234 
1235  if (sat_c_is_up_to_date()) {
1236  for (dimension_type i = sat_c.num_rows(); i-- > 0; ) {
1237  const Generator tmp_gen = gen_sys[i];
1238  const Bit_Row tmp_sat = sat_c[i];
1239  for (dimension_type j = sat_c.num_columns(); j-- > 0; ) {
1240  const bool sat_j = (Scalar_Products::sign(con_sys[j], tmp_gen) == 0);
1241  if (sat_j == tmp_sat[j]) {
1242 #ifndef NDEBUG
1243  cerr << "sat_c is declared up-to-date, but it is not!"
1244  << endl;
1245 #endif
1246  goto bomb;
1247  }
1248  }
1249  }
1250  }
1251  if (sat_g_is_up_to_date()) {
1252  for (dimension_type i = sat_g.num_rows(); i-- > 0; ) {
1253  const Constraint tmp_con = con_sys[i];
1254  const Bit_Row tmp_sat = sat_g[i];
1255  for (dimension_type j = sat_g.num_columns(); j-- > 0; ) {
1256  const bool sat_j = (Scalar_Products::sign(tmp_con, gen_sys[j]) == 0);
1257  if (sat_j == tmp_sat[j]) {
1258 #ifndef NDEBUG
1259  cerr << "sat_g is declared up-to-date, but it is not!"
1260  << endl;
1261 #endif
1262  goto bomb;
1263  }
1264  }
1265  }
1266  }
1267  if (has_pending_constraints()) {
1268  if (con_sys.num_pending_rows() == 0) {
1269 #ifndef NDEBUG
1270  cerr << "The polyhedron is declared to have pending constraints, "
1271  << "but con_sys has no pending rows!"
1272  << endl;
1273 #endif
1274  goto bomb;
1275  }
1276  }
1277 
1278  if (has_pending_generators()) {
1279  if (gen_sys.num_pending_rows() == 0) {
1280 #ifndef NDEBUG
1281  cerr << "The polyhedron is declared to have pending generators, "
1282  << "but gen_sys has no pending rows!"
1283  << endl;
1284 #endif
1285  goto bomb;
1286  }
1287  }
1288 
1289  return true;
1290 
1291  bomb:
1292 #ifndef NDEBUG
1293  cerr << "Here is the guilty polyhedron:"
1294  << endl;
1295  ascii_dump(cerr);
1296 #endif
1297  return false;
1298 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
bool constraints_are_minimized() const
Returns true if the system of constraints is minimized.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
dimension_type first_pending_row() const
Returns the index of the first pending row.
A linear equality or inequality.
bool OK() const
Checks if all the invariants are satisfied.
Definition: Ph_Status.cc:191
bool minimize() const
Applies (weak) minimization to both the constraints and generators.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
A line, ray, point or closure point.
bool generators_are_minimized() const
Returns true if the system of generators is minimized.
dimension_type num_rows() const
Returns the number of rows of *this.
void simplify()
Applies Gaussian elimination and back-substitution so as to provide a partial simplification of the s...
void remove_trailing_rows(dimension_type n)
Makes the system shrink by removing its n trailing rows.
dimension_type first_pending_row() const
Returns the index of the first pending row.
bool sat_c_is_up_to_date() const
Returns true if the saturation matrix sat_c is up-to-date.
dimension_type num_pending_rows() const
Returns the number of rows that are in the pending part of the system.
bool sat_g_is_up_to_date() const
Returns true if the saturation matrix sat_g is up-to-date.
bool has_points() const
Returns true if and only if *this contains one or more points.
Topology topology() const
Returns the system topology.
void ascii_dump() const
Writes to std::cerr an ASCII representation of *this.
A row in a matrix of bits.
Topology topology() const
Returns the topological kind of the polyhedron.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
Constraint_System con_sys
The system of constraints.
void ascii_dump() const
Writes to std::cerr an ASCII representation of *this.
dimension_type num_equalities() const
Returns the number of equality constraints.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
Bit_Matrix sat_g
The saturation matrix having generators on its columns.
void sort_rows()
Sorts the non-pending rows (in growing order) and eliminates duplicated ones.
Status status
The status flags to keep track of the polyhedron's internal state.
dimension_type num_rays() const
Returns the number of rays of the system.
void sort_rows()
Sorts the non-pending rows (in growing order) and eliminates duplicated ones.
dimension_type num_columns() const
Returns the number of columns of *this.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
void remove_trailing_rows(dimension_type n)
Makes the system shrink by removing its n trailing rows.
void strong_normalize()
Strongly normalizes the system.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
void unset_pending_rows()
Sets the index to indicate that the system has no pending rows.
dimension_type num_lines() const
Returns the number of lines of the system.
static const Representation default_con_sys_repr
static int sign(const Linear_Expression &x, const Linear_Expression &y)
Returns the sign of the scalar product between x and y.
bool has_pending_generators() const
Returns true if there are pending generators.
dimension_type num_pending_rows() const
Returns the number of rows that are in the pending part of the system.
Bit_Matrix sat_c
The saturation matrix having constraints on its columns.
static const Representation default_gen_sys_repr
void ascii_dump() const
Writes to std::cerr an ASCII representation of *this.
void strong_normalize()
Strongly normalizes the system.
void unset_pending_rows()
Sets the index to indicate that the system has no pending rows.
bool has_something_pending() const
Returns true if there are either pending constraints or pending generators.
PPL::Polyhedron & Parma_Polyhedra_Library::Polyhedron::operator= ( const Polyhedron y)
protected

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

Definition at line 327 of file Polyhedron_nonpublic.cc.

References con_sys, constraints_are_up_to_date(), gen_sys, generators_are_up_to_date(), marked_empty(), sat_c, sat_c_is_up_to_date(), sat_g, sat_g_is_up_to_date(), space_dim, status, and topology().

Referenced by Parma_Polyhedra_Library::NNC_Polyhedron::operator=(), and Parma_Polyhedra_Library::C_Polyhedron::operator=().

327  {
328  // Being a protected method, we simply assert that topologies do match.
329  PPL_ASSERT(topology() == y.topology());
330  space_dim = y.space_dim;
331  if (y.marked_empty()) {
332  set_empty();
333  }
334  else if (space_dim == 0) {
336  }
337  else {
338  status = y.status;
339  if (y.constraints_are_up_to_date()) {
340  con_sys.assign_with_pending(y.con_sys);
341  }
342  if (y.generators_are_up_to_date()) {
343  gen_sys.assign_with_pending(y.gen_sys);
344  }
345  if (y.sat_c_is_up_to_date()) {
346  sat_c = y.sat_c;
347  }
348  if (y.sat_g_is_up_to_date()) {
349  sat_g = y.sat_g;
350  }
351  }
352  return *this;
353 }
Generator_System gen_sys
The system of generators.
void assign_with_pending(const Constraint_System &y)
Full assignment operator: pending rows are copied as pending.
void assign_with_pending(const Generator_System &y)
Full assignment operator: pending rows are copied as pending.
Topology topology() const
Returns the topological kind of the polyhedron.
Constraint_System con_sys
The system of constraints.
Bit_Matrix sat_g
The saturation matrix having generators on its columns.
Status status
The status flags to keep track of the polyhedron's internal state.
void set_empty()
Sets status to express that the polyhedron is empty, clearing all corresponding matrices.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
Bit_Matrix sat_c
The saturation matrix having constraints on its columns.
void set_zero_dim_univ()
Sets status to express that the polyhedron is the universe 0-dimension vector space, clearing all corresponding matrices.
template<typename FP_Format , typename Interval_Info >
void Parma_Polyhedra_Library::Polyhedron::overapproximate_linear_form ( const Linear_Form< Interval< FP_Format, Interval_Info > > &  lf,
const dimension_type  lf_dimension,
Linear_Form< Interval< FP_Format, Interval_Info > > &  result 
)
protected

Helper function that overapproximates an interval linear form.

Parameters
lfThe linear form on intervals with floating point boundaries to approximate. ALL of its coefficients MUST be bounded.
lf_dimensionMust be the space dimension of lf.
resultUsed to store the result.

This function makes result become a linear form that is a correct approximation of lf under the constraints specified by *this. The resulting linear form has the property that all of its variable coefficients have a non-significant upper bound and can thus be considered as singletons.

Definition at line 431 of file Polyhedron_templates.hh.

References Parma_Polyhedra_Library::Box< ITV >::get_interval(), and PPL_COMPILE_TIME_CHECK.

Referenced by affine_form_image(), and refine_with_linear_form_inequality().

433  {
434 
435  // Check that FP_Format is indeed a floating point type.
436  PPL_COMPILE_TIME_CHECK(!std::numeric_limits<FP_Format>::is_exact,
437  "Polyhedron::overapproximate_linear_form:"
438  " FP_Format not a floating point type.");
439 
440  typedef Interval<FP_Format, Interval_Info> FP_Interval_Type;
441  typedef Linear_Form<FP_Interval_Type> FP_Linear_Form;
442 
443  // Build a Box from the Polyhedron so that we can extract upper and
444  // lower bounds of variables easily.
445  Box<FP_Interval_Type> box(*this);
446 
447  result = FP_Linear_Form(lf.inhomogeneous_term());
448  // FIXME: this may not be policy-neutral.
449  const FP_Interval_Type aux_divisor1(static_cast<FP_Format>(0.5));
450  FP_Interval_Type aux_divisor2(aux_divisor1);
451  aux_divisor2.lower() = static_cast<FP_Format>(-0.5);
452 
453  for (dimension_type i = 0; i < lf_dimension; ++i) {
454  Variable curr_var(i);
455  const FP_Interval_Type& curr_coeff = lf.coefficient(curr_var);
456  PPL_ASSERT(curr_coeff.is_bounded());
457  FP_Format curr_lb = curr_coeff.lower();
458  FP_Format curr_ub = curr_coeff.upper();
459  if (curr_lb != 0 || curr_ub != 0) {
460  const FP_Interval_Type& curr_int = box.get_interval(curr_var);
461  FP_Interval_Type curr_addend(curr_ub - curr_lb);
462  curr_addend *= aux_divisor2;
463  curr_addend *= curr_int;
464  result += curr_addend;
465  curr_addend = FP_Interval_Type(curr_lb + curr_ub);
466  curr_addend *= aux_divisor1;
467  FP_Linear_Form curr_addend_lf(curr_var);
468  curr_addend_lf *= curr_addend;
469  result += curr_addend_lf;
470  }
471  }
472 }
size_t dimension_type
An unsigned integral type for representing space dimensions.
#define PPL_COMPILE_TIME_CHECK(e, msg)
Produces a compilation error if the compile-time constant e does not evaluate to true ...
void Parma_Polyhedra_Library::Polyhedron::poly_difference_assign ( const Polyhedron y)

Assigns to *this the poly-difference of *this and y.

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

Definition at line 2648 of file Polyhedron_public.cc.

References Parma_Polyhedra_Library::Constraint_System::begin(), c, constraints(), contains(), Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Constraint::EQUALITY, Parma_Polyhedra_Library::Constraint::expression(), Parma_Polyhedra_Library::Poly_Con_Relation::implies(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Constraint::is_inconsistent(), Parma_Polyhedra_Library::Constraint::is_tautological(), marked_empty(), minimize(), Parma_Polyhedra_Library::Constraint::NONSTRICT_INEQUALITY, poly_hull_assign(), refine_no_check(), relation_with(), set_empty(), space_dim, Parma_Polyhedra_Library::Constraint::STRICT_INEQUALITY, topology(), and Parma_Polyhedra_Library::Constraint::type().

Referenced by difference_assign().

2648  {
2649  Polyhedron& x = *this;
2650  // Topology compatibility check.
2651  if (x.topology() != y.topology()) {
2652  throw_topology_incompatible("poly_difference_assign(y)", "y", y);
2653  // Dimension-compatibility check.
2654  }
2655  if (x.space_dim != y.space_dim) {
2656  throw_dimension_incompatible("poly_difference_assign(y)", "y", y);
2657  }
2658 
2659  // The difference of a polyhedron `p' and an empty polyhedron is `p'.
2660  if (y.marked_empty()) {
2661  return;
2662  }
2663  // The difference of an empty polyhedron and of a polyhedron `p' is empty.
2664  if (x.marked_empty()) {
2665  return;
2666  }
2667 
2668  // If both polyhedra are zero-dimensional,
2669  // then at this point they are necessarily universe polyhedra,
2670  // so that their difference is empty.
2671  if (x.space_dim == 0) {
2672  x.set_empty();
2673  return;
2674  }
2675 
2676  // TODO: This is just an executable specification.
2677  // Have to find a more efficient method.
2678 
2679  if (y.contains(x)) {
2680  x.set_empty();
2681  return;
2682  }
2683 
2684  // Being lazy here is only harmful.
2685  // `minimize()' will process any pending constraints or generators.
2686  if (!y.minimize()) {
2687  return;
2688  }
2689  x.minimize();
2690 
2691  Polyhedron new_polyhedron(topology(), x.space_dim, EMPTY);
2692 
2693  const Constraint_System& y_cs = y.constraints();
2694  for (Constraint_System::const_iterator i = y_cs.begin(),
2695  y_cs_end = y_cs.end(); i != y_cs_end; ++i) {
2696  const Constraint& c = *i;
2697  PPL_ASSERT(!c.is_tautological());
2698  PPL_ASSERT(!c.is_inconsistent());
2699  // If the polyhedron `x' is included in the polyhedron defined by
2700  // `c', then `c' can be skipped, as adding its complement to `x'
2701  // would result in the empty polyhedron. Moreover, if we operate
2702  // on C-polyhedra and `c' is a non-strict inequality, c _must_ be
2703  // skipped for otherwise we would obtain a result that is less
2704  // precise than the poly-difference.
2706  continue;
2707  }
2708  Polyhedron z = x;
2709  const Linear_Expression e(c.expression());
2710  switch (c.type()) {
2712  if (is_necessarily_closed()) {
2713  z.refine_no_check(e <= 0);
2714  }
2715  else {
2716  z.refine_no_check(e < 0);
2717  }
2718  break;
2720  z.refine_no_check(e <= 0);
2721  break;
2722  case Constraint::EQUALITY:
2723  if (is_necessarily_closed()) {
2724  // We have already filtered out the case
2725  // when `x' is included in `y': the result is `x'.
2726  return;
2727  }
2728  else {
2729  Polyhedron w = x;
2730  w.refine_no_check(e < 0);
2731  new_polyhedron.poly_hull_assign(w);
2732  z.refine_no_check(e > 0);
2733  }
2734  break;
2735  }
2736  new_polyhedron.poly_hull_assign(z);
2737  }
2738  *this = new_polyhedron;
2739 
2740  PPL_ASSERT_HEAVY(OK());
2741 }
bool is_tautological() const
Returns true if and only if *this is a tautology (i.e., an always true constraint).
Definition: Constraint.cc:105
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
The empty element, i.e., the empty set.
A linear equality or inequality.
static bool implies(flags_t x, flags_t y)
True if and only if the conjunction x implies the conjunction y.
Type type() const
Returns the constraint type of *this.
static Poly_Con_Relation is_included()
The polyhedron is included in the set of points satisfying the constraint.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
const Constraint_System & constraints() const
Returns the system of constraints.
const_iterator begin() const
Returns the const_iterator pointing to the first constraint, if *this is not empty; otherwise...
The base class for convex polyhedra.
Topology topology() const
Returns the topological kind of the polyhedron.
void refine_no_check(const Constraint &c)
Uses a copy of constraint c to refine the system of constraints of *this.
void throw_topology_incompatible(const char *method, const char *ph_name, const Polyhedron &ph) const
const_iterator end() const
Returns the past-the-end const_iterator.
bool is_inconsistent() const
Returns true if and only if *this is inconsistent (i.e., an always false constraint).
Definition: Constraint.cc:148
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.
void set_empty()
Sets status to express that the polyhedron is empty, clearing all corresponding matrices.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool contains(const Polyhedron &y) const
Returns true if and only if *this contains y.
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
Coefficient c
Definition: PIP_Tree.cc:64
expr_type expression() const
Partial read access to the (adapted) internal expression.
Poly_Con_Relation relation_with(const Constraint &c) const
Returns the relations holding between the polyhedron *this and the constraint c.
void Parma_Polyhedra_Library::Polyhedron::poly_hull_assign ( const Polyhedron y)

Assigns to *this the poly-hull of *this and y.

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

Definition at line 2576 of file Polyhedron_public.cc.

References can_have_something_pending(), clear_constraints_up_to_date(), clear_generators_minimized(), gen_sys, generators_are_up_to_date(), has_pending_constraints(), has_pending_generators(), Parma_Polyhedra_Library::Generator_System::insert(), Parma_Polyhedra_Library::Generator_System::insert_pending(), Parma_Polyhedra_Library::Generator_System::is_sorted(), marked_empty(), Parma_Polyhedra_Library::Generator_System::merge_rows_assign(), OK(), process_pending_constraints(), set_generators_pending(), space_dim, topology(), and update_generators().

Referenced by Parma_Polyhedra_Library::Pointset_Powerset< PSET >::affine_dimension(), poly_difference_assign(), and upper_bound_assign().

2576  {
2577  Polyhedron& x = *this;
2578  // Topology compatibility check.
2579  if (x.topology() != y.topology()) {
2580  throw_topology_incompatible("poly_hull_assign(y)", "y", y);
2581  }
2582  // Dimension-compatibility check.
2583  if (x.space_dim != y.space_dim) {
2584  throw_dimension_incompatible("poly_hull_assign(y)", "y", y);
2585  }
2586 
2587  // The poly-hull of a polyhedron `p' with an empty polyhedron is `p'.
2588  if (y.marked_empty()) {
2589  return;
2590  }
2591  if (x.marked_empty()) {
2592  x = y;
2593  return;
2594  }
2595 
2596  // If both polyhedra are zero-dimensional,
2597  // then at this point they are necessarily universe polyhedra,
2598  // so that their poly-hull is the universe polyhedron too.
2599  if (x.space_dim == 0) {
2600  return;
2601  }
2602 
2603  // Both systems of generators have to be up-to-date,
2604  // possibly having pending generators.
2606  || (!x.generators_are_up_to_date() && !x.update_generators())) {
2607  // Discovered `x' empty when updating generators.
2608  x = y;
2609  return;
2610  }
2612  || (!y.generators_are_up_to_date() && !y.update_generators())) {
2613  // Discovered `y' empty when updating generators.
2614  return;
2615  }
2616  // Here both systems are up-to-date and possibly have pending generators
2617  // (but they cannot have pending constraints).
2618  PPL_ASSERT(!x.has_pending_constraints() && x.generators_are_up_to_date());
2619  PPL_ASSERT(!y.has_pending_constraints() && y.generators_are_up_to_date());
2620 
2621  // If `x' can support pending generators,
2622  // the generators of `y' are added as pending generators of `x'.
2623  if (x.can_have_something_pending()) {
2626  }
2627  else {
2628  // `x' cannot support pending generators.
2629  // If both generator systems are (fully) sorted, then we can merge
2630  // them; otherwise we simply add the second to the first.
2631  if (x.gen_sys.is_sorted()
2632  && y.gen_sys.is_sorted() && !y.has_pending_generators()) {
2634  }
2635  else {
2636  x.gen_sys.insert(y.gen_sys);
2637  }
2638  // Constraints are no longer up-to-date
2639  // and generators are no longer minimized.
2642  }
2643  // At this point both `x' and `y' are not empty.
2644  PPL_ASSERT_HEAVY(x.OK(true) && y.OK(true));
2645 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
void merge_rows_assign(const Generator_System &y)
Assigns to *this the result of merging its rows with those of y, obtaining a sorted system...
void clear_constraints_up_to_date()
Sets status to express that constraints are no longer up-to-date.
Generator_System gen_sys
The system of generators.
bool update_generators() const
Updates generators starting from constraints and minimizes them.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
bool is_sorted() const
Returns the value of the sortedness flag.
bool can_have_something_pending() const
Returns true if the polyhedron can have something pending.
The base class for convex polyhedra.
Topology topology() const
Returns the topological kind of the polyhedron.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
void throw_topology_incompatible(const char *method, const char *ph_name, const Polyhedron &ph) const
void insert_pending(const Generator_System &r)
Adds a copy of the rows of `y' to the pending part of `*this'.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
bool process_pending_constraints() const
Processes the pending constraints and obtains a minimized polyhedron.
bool has_pending_generators() const
Returns true if there are pending generators.
void set_generators_pending()
Sets status to express that generators are pending.
void insert(const Generator &g)
Inserts in *this a copy of the generator g, increasing the number of space dimensions if needed...
void clear_generators_minimized()
Sets status to express that generators are no longer minimized.
void Parma_Polyhedra_Library::Polyhedron::positive_time_elapse_assign ( const Polyhedron y)

Assigns to *this (the best approximation of) the result of computing the positive time-elapse between *this and y.

Exceptions
std::invalid_argumentThrown if *this and y are dimension-incompatible.
void Parma_Polyhedra_Library::Polyhedron::positive_time_elapse_assign_impl ( const Polyhedron y)
protected

Assuming *this is NNC, assigns to *this the result of the "positive time-elapse" between *this and y.

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

Definition at line 2375 of file Polyhedron_nonpublic.cc.

References Parma_Polyhedra_Library::Generator_System::add_corresponding_closure_points(), Parma_Polyhedra_Library::Linear_Expression::all_homogeneous_terms_are_zero(), Parma_Polyhedra_Library::Generator::CLOSURE_POINT, Parma_Polyhedra_Library::Generator_System::convert_into_non_necessarily_closed(), Parma_Polyhedra_Library::Generator::epsilon_coefficient(), Parma_Polyhedra_Library::Generator::expr, gen_sys, generators_are_up_to_date(), has_pending_constraints(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Generator_System::insert(), is_necessarily_closed(), Parma_Polyhedra_Library::Generator::is_point(), Parma_Polyhedra_Library::Generator::LINE, marked_empty(), Parma_Polyhedra_Library::Linear_Expression::normalize(), Parma_Polyhedra_Library::Generator_System::num_rows(), Parma_Polyhedra_Library::Generator::OK(), OK(), Parma_Polyhedra_Library::Generator::POINT, process_pending_constraints(), Parma_Polyhedra_Library::Generator::RAY, set_empty(), Parma_Polyhedra_Library::Linear_Expression::set_inhomogeneous_term(), space_dim, Parma_Polyhedra_Library::swap(), Parma_Polyhedra_Library::Generator_System::sys, Parma_Polyhedra_Library::Generator::type(), Parma_Polyhedra_Library::Generator_System::unset_pending_rows(), and update_generators().

Referenced by Parma_Polyhedra_Library::NNC_Polyhedron::positive_time_elapse_assign().

2375  {
2376  // Private method: the caller must ensure the following.
2377  PPL_ASSERT(!is_necessarily_closed());
2378 
2379  Polyhedron& x = *this;
2380  // Dimension-compatibility checks.
2381  if (x.space_dim != y.space_dim) {
2382  throw_dimension_incompatible("positive_time_elapse_assign(y)", "y", y);
2383  }
2384 
2385  // Dealing with the zero-dimensional case.
2386  if (x.space_dim == 0) {
2387  if (y.marked_empty()) {
2388  x.set_empty();
2389  }
2390  return;
2391  }
2392 
2393  // If either one of `x' or `y' is empty, the result is empty too.
2394  if (x.marked_empty() || y.marked_empty()
2395  || (x.has_pending_constraints() && !x.process_pending_constraints())
2396  || (!x.generators_are_up_to_date() && !x.update_generators())
2397  || (y.has_pending_constraints() && !y.process_pending_constraints())
2398  || (!y.generators_are_up_to_date() && !y.update_generators())) {
2399  x.set_empty();
2400  return;
2401  }
2402 
2403  // At this point both generator systems are up-to-date,
2404  // possibly containing pending generators.
2405 
2406  // The new system of generators that will replace the one of x.
2407  Generator_System new_gs(x.gen_sys);
2408  dimension_type num_rows = new_gs.num_rows();
2409 
2410  // We are going to do all sorts of funny things with new_gs, so we better
2411  // mark it unsorted.
2412  // Note: `sorted' is an attribute of Linear_System, encapsulated by
2413  // Generator_System; hence, the following is equivalent to
2414  // new_gs.set_sorted(false).
2415  new_gs.sys.set_sorted(false);
2416 
2417  // Remove all points from new_gs and put them in 'x_points_gs' for later use.
2418  // Notice that we do not remove the corresponding closure points.
2419  Generator_System x_points_gs;
2420  for (dimension_type i = num_rows; i-- > 0;) {
2421  Generator &g = new_gs.sys.rows[i];
2422  if (g.is_point()) {
2423  x_points_gs.insert(g);
2424  --num_rows;
2425  swap(g, new_gs.sys.rows[num_rows]);
2426  }
2427  }
2428  new_gs.sys.rows.resize(num_rows);
2429 
2430  // When there are no pending rows, the pending row index points at
2431  // the smallest non-valid row, i.e., it is equal to the number of rows.
2432  // Hence, each time the system is manually resized, the pending row index
2433  // must be updated.
2434  new_gs.unset_pending_rows();
2435  PPL_ASSERT(new_gs.sys.OK());
2436 
2437  // We use a pointer in order to avoid copying the generator
2438  // system when it is not necessary, i.e., when y is an NNC.
2439  const Generator_System *gs = &y.gen_sys;
2440  Generator_System y_gs;
2441 
2442  // If y is closed, promote its generator system to not necessarily closed.
2443  if (y.is_necessarily_closed()) {
2444  y_gs = y.gen_sys;
2445  y_gs.convert_into_non_necessarily_closed();
2446  y_gs.add_corresponding_closure_points();
2447  gs = &y_gs;
2448  }
2449 
2450  PPL_ASSERT(gs->OK());
2451 
2452  const dimension_type gs_num_rows = gs->num_rows();
2453 
2454  // For each generator g of y...
2455  for (dimension_type i = gs_num_rows; i-- > 0; ) {
2456  const Generator &g = gs->sys.rows[i];
2457 
2458  switch (g.type()) {
2459  case Generator::POINT:
2460  // In principle, points should be added to new_gs as rays.
2461  // However, for each point there is a corresponding closure point in "gs".
2462  // Hence, we leave this operation to closure points.
2463 
2464  // Insert into new_gs the sum of g and each point of x.
2465  // For each original point gx of x...
2466  for (dimension_type j = x_points_gs.sys.num_rows(); j-- > 0; ) {
2467  const Generator &gx = x_points_gs.sys.rows[j];
2468  PPL_ASSERT(gx.is_point());
2469  // ...insert the point obtained as the sum of g and gx.
2470  Generator new_g = g; // make a copy
2471  Coefficient new_divisor = g.expr.inhomogeneous_term() * gx.expr.inhomogeneous_term();
2472 
2473  new_g.expr.linear_combine(gx.expr, gx.expr.inhomogeneous_term(), g.expr.inhomogeneous_term());
2474  new_g.expr.set_inhomogeneous_term(new_divisor);
2475  if (new_g.is_not_necessarily_closed()) {
2476  new_g.set_epsilon_coefficient(g.epsilon_coefficient());
2477  }
2478  new_g.expr.normalize();
2479  PPL_ASSERT(new_g.OK());
2480  new_gs.insert(new_g);
2481  }
2482  break;
2484  // If g is not the origin, insert g into new_gs, as a ray.
2485  if (!g.expr.all_homogeneous_terms_are_zero()) {
2486  // Turn a copy of g into a ray.
2487  Generator g_as_a_ray = g;
2488  g_as_a_ray.expr.set_inhomogeneous_term(0);
2489  g_as_a_ray.expr.normalize();
2490  PPL_ASSERT(g_as_a_ray.OK());
2491  // Insert the ray.
2492  new_gs.insert(g_as_a_ray);
2493  }
2494  break;
2495  case Generator::RAY:
2496  case Generator::LINE:
2497  // Insert g into new_gs.
2498  new_gs.insert(g);
2499  break;
2500  }
2501  }
2502  new_gs.add_corresponding_closure_points();
2503  // Notice: add_corresponding_closure_points adds them as pending.
2504  new_gs.unset_pending_rows();
2505 
2506  //Polyhedron new_x(...,new_gs);
2507  //swap(x,new_x);
2508 
2509  PPL_ASSERT(new_gs.sys.OK());
2510 
2511  // Stealing the rows from `new_gs'.
2512  using std::swap;
2513  swap(gen_sys, new_gs);
2514 
2515  gen_sys.set_sorted(false);
2517  // Generators are now up-to-date.
2519  // Constraints are not up-to-date.
2521 
2522  PPL_ASSERT_HEAVY(x.OK(true) && y.OK(true));
2523 }
void swap(CO_Tree &x, CO_Tree &y)
void clear_constraints_up_to_date()
Sets status to express that constraints are no longer up-to-date.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
void set_generators_up_to_date()
Sets status to express that generators are up-to-date.
void swap(Polyhedron &x, Polyhedron &y)
Swaps x with y.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
void set_sorted(bool b)
Sets the sortedness flag of the system to b.
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
void clear_generators_minimized()
Sets status to express that generators are no longer minimized.
void Parma_Polyhedra_Library::Polyhedron::print ( ) const

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

bool Parma_Polyhedra_Library::Polyhedron::process_pending ( ) const
inlineprivate

Processes the pending rows of either description of the polyhedron and obtains a minimized polyhedron.

Returns
false if and only if *this turns out to be an empty polyhedron.

It is assumed that the polyhedron does have some constraints or generators pending.

Definition at line 300 of file Polyhedron_inlines.hh.

References has_pending_constraints(), has_pending_generators(), has_something_pending(), marked_empty(), process_pending_constraints(), process_pending_generators(), and space_dim.

300  {
301  PPL_ASSERT(space_dim > 0 && !marked_empty());
302  PPL_ASSERT(has_something_pending());
303 
304  if (has_pending_constraints()) {
306  }
307 
308  PPL_ASSERT(has_pending_generators());
310  return true;
311 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
void process_pending_generators() const
Processes the pending generators and obtains a minimized polyhedron.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool process_pending_constraints() const
Processes the pending constraints and obtains a minimized polyhedron.
bool has_pending_generators() const
Returns true if there are pending generators.
bool has_something_pending() const
Returns true if there are either pending constraints or pending generators.
bool Parma_Polyhedra_Library::Polyhedron::process_pending_constraints ( ) const
private

Processes the pending constraints and obtains a minimized polyhedron.

Returns
false if and only if *this turns out to be an empty polyhedron.

It is assumed that the polyhedron does have some pending constraints.

Definition at line 737 of file Polyhedron_nonpublic.cc.

References clear_pending_constraints(), clear_sat_g_up_to_date(), con_sys, Parma_Polyhedra_Library::Implementation::BD_Shapes::empty, gen_sys, Parma_Polyhedra_Library::Constraint_System::is_sorted(), Parma_Polyhedra_Library::Constraint_System::num_pending_rows(), obtain_sorted_constraints_with_sat_c(), sat_c, sat_c_is_up_to_date(), sat_g, set_empty(), set_sat_c_up_to_date(), Parma_Polyhedra_Library::Constraint_System::sort_pending_and_remove_duplicates(), and Parma_Polyhedra_Library::Bit_Matrix::transpose_assign().

Referenced by limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), poly_hull_assign(), positive_time_elapse_assign_impl(), process_pending(), remove_pending_to_obtain_generators(), and time_elapse_assign().

737  {
738  PPL_ASSERT(space_dim > 0 && !marked_empty());
740 
741  Polyhedron& x = const_cast<Polyhedron&>(*this);
742 
743  // Integrate the pending part of the system of constraints and minimize.
744  // We need `sat_c' up-to-date and `con_sys' sorted (together with `sat_c').
745  if (!x.sat_c_is_up_to_date()) {
746  x.sat_c.transpose_assign(x.sat_g);
747  }
748  if (!x.con_sys.is_sorted()) {
749  x.obtain_sorted_constraints_with_sat_c();
750  }
751  // We sort in place the pending constraints, erasing those constraints
752  // that also occur in the non-pending part of `con_sys'.
753  x.con_sys.sort_pending_and_remove_duplicates();
754  if (x.con_sys.num_pending_rows() == 0) {
755  // All pending constraints were duplicates.
756  x.clear_pending_constraints();
757  PPL_ASSERT_HEAVY(OK(true));
758  return true;
759  }
760 
761  const bool empty = add_and_minimize(true, x.con_sys, x.gen_sys, x.sat_c);
762  PPL_ASSERT(x.con_sys.num_pending_rows() == 0);
763 
764  if (empty) {
765  x.set_empty();
766  }
767  else {
768  x.clear_pending_constraints();
769  x.clear_sat_g_up_to_date();
770  x.set_sat_c_up_to_date();
771  }
772  PPL_ASSERT_HEAVY(OK(!empty));
773  return !empty;
774 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
bool has_pending_generators() const
Returns true if there are pending generators.
static bool add_and_minimize(bool con_to_gen, Source_Linear_System1 &source1, Dest_Linear_System &dest, Bit_Matrix &sat, const Source_Linear_System2 &source2)
Adds given constraints and builds minimized corresponding generators or vice versa.
void Parma_Polyhedra_Library::Polyhedron::process_pending_generators ( ) const
private

Processes the pending generators and obtains a minimized polyhedron.

It is assumed that the polyhedron does have some pending generators.

Definition at line 777 of file Polyhedron_nonpublic.cc.

References clear_pending_generators(), clear_sat_c_up_to_date(), con_sys, gen_sys, Parma_Polyhedra_Library::Generator_System::is_sorted(), Parma_Polyhedra_Library::Generator_System::num_pending_rows(), obtain_sorted_generators_with_sat_g(), sat_c, sat_g, sat_g_is_up_to_date(), set_sat_g_up_to_date(), Parma_Polyhedra_Library::Generator_System::sort_pending_and_remove_duplicates(), and Parma_Polyhedra_Library::Bit_Matrix::transpose_assign().

Referenced by H79_widening_assign(), intersection_assign(), is_included_in(), process_pending(), and remove_pending_to_obtain_constraints().

777  {
778  PPL_ASSERT(space_dim > 0 && !marked_empty());
780 
781  Polyhedron& x = const_cast<Polyhedron&>(*this);
782 
783  // Integrate the pending part of the system of generators and minimize.
784  // We need `sat_g' up-to-date and `gen_sys' sorted (together with `sat_g').
785  if (!x.sat_g_is_up_to_date()) {
786  x.sat_g.transpose_assign(x.sat_c);
787  }
788  if (!x.gen_sys.is_sorted()) {
789  x.obtain_sorted_generators_with_sat_g();
790  }
791  // We sort in place the pending generators, erasing those generators
792  // that also occur in the non-pending part of `gen_sys'.
793  x.gen_sys.sort_pending_and_remove_duplicates();
794  if (x.gen_sys.num_pending_rows() == 0) {
795  // All pending generators were duplicates.
796  x.clear_pending_generators();
797  PPL_ASSERT_HEAVY(OK(true));
798  return;
799  }
800 
801  add_and_minimize(false, x.gen_sys, x.con_sys, x.sat_g);
802  PPL_ASSERT(x.gen_sys.num_pending_rows() == 0);
803 
804  x.clear_pending_generators();
805  x.clear_sat_c_up_to_date();
806  x.set_sat_g_up_to_date();
807 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
bool has_pending_generators() const
Returns true if there are pending generators.
static bool add_and_minimize(bool con_to_gen, Source_Linear_System1 &source1, Dest_Linear_System &dest, Bit_Matrix &sat, const Source_Linear_System2 &source2)
Adds given constraints and builds minimized corresponding generators or vice versa.
PPL::Polyhedron::Three_Valued_Boolean Parma_Polyhedra_Library::Polyhedron::quick_equivalence_test ( const Polyhedron y) const
private

Polynomial but incomplete equivalence test between polyhedra.

Definition at line 356 of file Polyhedron_nonpublic.cc.

References con_sys, constraints_are_minimized(), gen_sys, generators_are_minimized(), has_something_pending(), marked_empty(), Parma_Polyhedra_Library::Constraint_System::num_equalities(), Parma_Polyhedra_Library::Generator_System::num_lines(), Parma_Polyhedra_Library::Generator_System::num_rows(), Parma_Polyhedra_Library::Constraint_System::num_rows(), obtain_sorted_constraints(), obtain_sorted_generators(), space_dim, topology(), TVB_DONT_KNOW, TVB_FALSE, and TVB_TRUE.

Referenced by contains(), and operator==().

356  {
357  // Private method: the caller must ensure the following.
358  PPL_ASSERT(topology() == y.topology());
359  PPL_ASSERT(space_dim == y.space_dim);
360  PPL_ASSERT(!marked_empty() && !y.marked_empty() && space_dim > 0);
361 
362  const Polyhedron& x = *this;
363 
364  if (x.is_necessarily_closed()) {
365  if (!x.has_something_pending() && !y.has_something_pending()) {
366  bool css_normalized = false;
367  if (x.constraints_are_minimized() && y.constraints_are_minimized()) {
368  // Equivalent minimized constraint systems have:
369  // - the same number of constraints; ...
370  if (x.con_sys.num_rows() != y.con_sys.num_rows()) {
371  return Polyhedron::TVB_FALSE;
372  }
373  // - the same number of equalities; ...
374  const dimension_type x_num_equalities = x.con_sys.num_equalities();
375  if (x_num_equalities != y.con_sys.num_equalities()) {
376  return Polyhedron::TVB_FALSE;
377  }
378  // - if there are no equalities, they have the same constraints.
379  // Delay this test: try cheaper tests on generators first.
380  css_normalized = (x_num_equalities == 0);
381  }
382 
383  if (x.generators_are_minimized() && y.generators_are_minimized()) {
384  // Equivalent minimized generator systems have:
385  // - the same number of generators; ...
386  if (x.gen_sys.num_rows() != y.gen_sys.num_rows()) {
387  return Polyhedron::TVB_FALSE;
388  }
389  // - the same number of lines; ...
390  const dimension_type x_num_lines = x.gen_sys.num_lines();
391  if (x_num_lines != y.gen_sys.num_lines()) {
392  return Polyhedron::TVB_FALSE;
393  }
394  // - if there are no lines, they have the same generators.
395  if (x_num_lines == 0) {
396  // Sort the two systems and check for syntactic identity.
397  x.obtain_sorted_generators();
398  y.obtain_sorted_generators();
399  if (x.gen_sys == y.gen_sys) {
400  return Polyhedron::TVB_TRUE;
401  }
402  else {
403  return Polyhedron::TVB_FALSE;
404  }
405  }
406  }
407 
408  if (css_normalized) {
409  // Sort the two systems and check for identity.
410  x.obtain_sorted_constraints();
411  y.obtain_sorted_constraints();
412  if (x.con_sys == y.con_sys) {
413  return Polyhedron::TVB_TRUE;
414  }
415  else {
416  return Polyhedron::TVB_FALSE;
417  }
418  }
419  }
420  }
422 }
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
Topology topology() const
Returns the topological kind of the polyhedron.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
template<typename FP_Format , typename Interval_Info >
void Parma_Polyhedra_Library::Polyhedron::refine_fp_interval_abstract_store ( Box< Interval< FP_Format, Interval_Info > > &  store) const
inline

Refines store with the constraints defining *this.

Parameters
storeThe interval floating point abstract store to refine.

Definition at line 416 of file Polyhedron_inlines.hh.

References PPL_COMPILE_TIME_CHECK.

417  {
418 
419  // Check that FP_Format is indeed a floating point type.
420  PPL_COMPILE_TIME_CHECK(!std::numeric_limits<FP_Format>::is_exact,
421  "Polyhedron::refine_fp_interval_abstract_store:"
422  " T not a floating point type.");
423 
424  typedef Interval<FP_Format, Interval_Info> FP_Interval_Type;
425  store.intersection_assign(Box<FP_Interval_Type>(*this));
426 
427 }
#define PPL_COMPILE_TIME_CHECK(e, msg)
Produces a compilation error if the compile-time constant e does not evaluate to true ...
void Parma_Polyhedra_Library::Polyhedron::refine_no_check ( const Constraint c)
private

Uses a copy of constraint c to refine the system of constraints of *this.

Parameters
cThe constraint to be added. If it is dimension-incompatible with *this, the behavior is undefined.

Definition at line 1434 of file Polyhedron_nonpublic.cc.

References Parma_Polyhedra_Library::Constraint::expression(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Constraint::is_inconsistent(), Parma_Polyhedra_Library::Constraint::is_necessarily_closed(), and Parma_Polyhedra_Library::Constraint::space_dimension().

Referenced by poly_difference_assign().

1434  {
1435  PPL_ASSERT(!marked_empty());
1436  PPL_ASSERT(space_dim >= c.space_dimension());
1437 
1438  // Dealing with a zero-dimensional space polyhedron first.
1439  if (space_dim == 0) {
1440  if (c.is_inconsistent()) {
1441  set_empty();
1442  }
1443  return;
1444  }
1445 
1446  // The constraints (possibly with pending rows) are required.
1447  if (has_pending_generators()) {
1449  }
1450  else if (!constraints_are_up_to_date()) {
1452  }
1453 
1454  const bool adding_pending = can_have_something_pending();
1455 
1456  if (c.is_necessarily_closed() || !is_necessarily_closed()) {
1457  // Since `con_sys' is not empty, the topology and space dimension
1458  // of the inserted constraint are automatically adjusted.
1459  if (adding_pending) {
1461  }
1462  else {
1463  con_sys.insert(c);
1464  }
1465  }
1466  else {
1467  // Here we know that the system of constraints has at least a row.
1468  // However, by barely invoking `con_sys.insert(c)' we would
1469  // cause a change in the topology of `con_sys', which is wrong.
1470  // Thus, we insert a "topology corrected" copy of `c'.
1471  const Linear_Expression nc_expr(c.expression());
1472  if (c.is_equality()) {
1473  if (adding_pending) {
1474  con_sys.insert_pending(nc_expr == 0);
1475  }
1476  else {
1477  con_sys.insert(nc_expr == 0);
1478  }
1479  }
1480  else {
1481  if (adding_pending) {
1482  con_sys.insert_pending(nc_expr >= 0);
1483  }
1484  else {
1485  con_sys.insert(nc_expr >= 0);
1486  }
1487  }
1488  }
1489 
1490  if (adding_pending) {
1492  }
1493  else {
1494  // Constraints are not minimized and generators are not up-to-date.
1497  }
1498 
1499  // Note: the constraint system may have become unsatisfiable, thus
1500  // we do not check for satisfiability.
1501  PPL_ASSERT_HEAVY(OK());
1502 }
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
void insert_pending(const Constraint &c)
Inserts in *this a copy of the constraint c, increasing the number of space dimensions if needed...
void update_constraints() const
Updates constraints starting from generators and minimizes them.
void set_constraints_pending()
Sets status to express that constraints are pending.
void insert(const Constraint &c)
Inserts in *this a copy of the constraint c, increasing the number of space dimensions if needed...
bool can_have_something_pending() const
Returns true if the polyhedron can have something pending.
Constraint_System con_sys
The system of constraints.
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
void process_pending_generators() const
Processes the pending generators and obtains a minimized polyhedron.
void set_empty()
Sets status to express that the polyhedron is empty, clearing all corresponding matrices.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
void clear_constraints_minimized()
Sets status to express that constraints are no longer minimized.
bool has_pending_generators() const
Returns true if there are pending generators.
Coefficient c
Definition: PIP_Tree.cc:64
void clear_generators_up_to_date()
Sets status to express that generators are no longer up-to-date.
void Parma_Polyhedra_Library::Polyhedron::refine_with_congruence ( const Congruence cg)

Uses a copy of congruence cg to refine *this.

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

Definition at line 1757 of file Polyhedron_public.cc.

References c, Parma_Polyhedra_Library::Constraint::EQUALITY, Parma_Polyhedra_Library::Congruence::expression(), Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Congruence::is_tautological(), Parma_Polyhedra_Library::Boundary_NS::le(), Parma_Polyhedra_Library::NECESSARILY_CLOSED, and Parma_Polyhedra_Library::Congruence::space_dimension().

1757  {
1758  // Dimension-compatibility check.
1759  if (space_dim < cg.space_dimension()) {
1760  throw_dimension_incompatible("refine_with_congruence(cg)", "cg", cg);
1761  }
1762 
1763  // If the polyhedron is known to be empty, do nothing.
1764  if (marked_empty()) {
1765  return;
1766  }
1767 
1768  // Dealing with a zero-dimensional space polyhedron first.
1769  if (space_dim == 0) {
1770  if (!cg.is_tautological()) {
1771  set_empty();
1772  }
1773  return;
1774  }
1775 
1776  if (cg.is_equality()) {
1779  refine_no_check(c);
1780  }
1781 }
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
A linear equality or inequality.
expr_type expression() const
Partial read access to the (adapted) internal expression.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
bool is_equality() const
Returns true if *this is an equality.
void refine_no_check(const Constraint &c)
Uses a copy of constraint c to refine the system of constraints of *this.
bool is_tautological() const
Returns true if and only if *this is a tautology (i.e., an always true congruence).
Definition: Congruence.cc:210
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void set_empty()
Sets status to express that the polyhedron is empty, clearing all corresponding matrices.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
Coefficient c
Definition: PIP_Tree.cc:64
bool le(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
void Parma_Polyhedra_Library::Polyhedron::refine_with_congruences ( const Congruence_System cgs)

Uses a copy of the congruences in cgs to refine *this.

Parameters
cgsContains the congruences used to refine the system of constraints of *this.
Exceptions
std::invalid_argumentThrown if *this and cgs are dimension-incompatible.

Definition at line 1879 of file Polyhedron_public.cc.

References Parma_Polyhedra_Library::Congruence_System::begin(), c, Parma_Polyhedra_Library::Congruence_System::end(), Parma_Polyhedra_Library::Constraint::EQUALITY, Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::Boundary_NS::le(), Parma_Polyhedra_Library::NECESSARILY_CLOSED, and Parma_Polyhedra_Library::Congruence_System::space_dimension().

1879  {
1880  // Dimension-compatibility check.
1881  if (space_dim < cgs.space_dimension()) {
1882  throw_dimension_incompatible("refine_with_congruences(cgs)", "cgs", cgs);
1883  }
1884 
1885  Constraint_System cs;
1886  bool inserted = false;
1888  cgs_end = cgs.end(); i != cgs_end; ++i) {
1889  if (i->is_equality()) {
1890  Linear_Expression le(i->expression());
1892 
1893  // TODO: Consider stealing the row in c when adding it to cs.
1894  cs.insert(c);
1895  inserted = true;
1896  }
1897  else if (i->is_inconsistent()) {
1898  set_empty();
1899  return;
1900  }
1901  }
1902  // Only add cgs if congruences were inserted into cgs, as the
1903  // dimension of cs must be at most that of the polyhedron.
1904  if (inserted) {
1906  }
1907 }
A linear equality or inequality.
void insert(const Constraint &c)
Inserts in *this a copy of the constraint c, increasing the number of space dimensions if needed...
const_iterator end() const
Returns the past-the-end const_iterator.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
void add_recycled_constraints(Constraint_System &cs)
Adds the constraints in cs to the system of constraints of *this (without minimizing the result)...
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
const_iterator begin() const
Returns the const_iterator pointing to the first congruence, if this is not empty; otherwise...
void set_empty()
Sets status to express that the polyhedron is empty, clearing all corresponding matrices.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
Coefficient c
Definition: PIP_Tree.cc:64
bool le(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
void Parma_Polyhedra_Library::Polyhedron::refine_with_constraint ( const Constraint c)

Uses a copy of constraint c to refine *this.

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

Definition at line 1745 of file Polyhedron_public.cc.

References Parma_Polyhedra_Library::Constraint::space_dimension().

Referenced by refine_with_linear_form_inequality().

1745  {
1746  // Dimension-compatibility check.
1747  if (space_dim < c.space_dimension()) {
1748  throw_dimension_incompatible("refine_with_constraint(c)", "c", c);
1749  }
1750  // If the polyhedron is known to be empty, do nothing.
1751  if (!marked_empty()) {
1752  refine_no_check(c);
1753  }
1754 }
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
void refine_no_check(const Constraint &c)
Uses a copy of constraint c to refine the system of constraints of *this.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
void Parma_Polyhedra_Library::Polyhedron::refine_with_constraints ( const Constraint_System cs)

Uses a copy of the constraints in cs to refine *this.

Parameters
csContains the constraints used to refine the system of constraints of *this.
Exceptions
std::invalid_argumentThrown if *this and cs are dimension-incompatible.

Definition at line 1784 of file Polyhedron_public.cc.

References Parma_Polyhedra_Library::Constraint_System::begin(), c, Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Constraint::expression(), Parma_Polyhedra_Library::Constraint_System::has_no_rows(), Parma_Polyhedra_Library::Constraint_System::insert_pending(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Constraint::is_necessarily_closed(), Parma_Polyhedra_Library::Constraint_System::num_rows(), and Parma_Polyhedra_Library::Constraint_System::space_dimension().

1784  {
1785  // TODO: this is just an executable specification.
1786 
1787  // Dimension-compatibility check.
1788  const dimension_type cs_space_dim = cs.space_dimension();
1789  if (space_dim < cs_space_dim) {
1790  throw_dimension_incompatible("refine_with_constraints(cs)a",
1791  "cs", cs);
1792  }
1793  // Adding no constraints is a no-op.
1794  if (cs.has_no_rows()) {
1795  return;
1796  }
1797 
1798  if (space_dim == 0) {
1799  // In a 0-dimensional space the constraints are
1800  // tautologies (e.g., 0 == 0 or 1 >= 0 or 1 > 0) or
1801  // inconsistent (e.g., 1 == 0 or -1 >= 0 or 0 > 0).
1802  // In a system of constraints `begin()' and `end()' are equal
1803  // if and only if the system only contains tautologies.
1804  if (cs.begin() != cs.end()) {
1805  // There is a constraint, it must be inconsistent,
1806  // the polyhedron is empty.
1807  status.set_empty();
1808  }
1809  return;
1810  }
1811 
1812  if (marked_empty()) {
1813  return;
1814  }
1815 
1816  // The constraints (possibly with pending rows) are required.
1817  if (has_pending_generators()) {
1819  }
1820  else if (!constraints_are_up_to_date()) {
1822  }
1823 
1824  const bool adding_pending = can_have_something_pending();
1825  for (dimension_type i = cs.num_rows(); i-- > 0; ) {
1826  const Constraint& c = cs[i];
1827 
1829  // Since `con_sys' is not empty, the topology and space dimension
1830  // of the inserted constraint are automatically adjusted.
1831  if (adding_pending) {
1833  }
1834  else {
1835  con_sys.insert(c);
1836  }
1837  }
1838  else {
1839  // Here we know that *this is necessarily closed so even if c is
1840  // topologically closed, by barely invoking `con_sys.insert(c)' we
1841  // would cause a change in the topology of `con_sys', which is
1842  // wrong. Thus, we insert a topology closed and "topology
1843  // corrected" version of `c'.
1844  const Linear_Expression nc_expr(c.expression());
1845  if (c.is_equality()) {
1846  if (adding_pending) {
1847  con_sys.insert_pending(nc_expr == 0);
1848  }
1849  else {
1850  con_sys.insert(nc_expr == 0);
1851  }
1852  }
1853  else {
1854  if (adding_pending) {
1855  con_sys.insert_pending(nc_expr >= 0);
1856  }
1857  else {
1858  con_sys.insert(nc_expr >= 0);
1859  }
1860  }
1861  }
1862  }
1863 
1864  if (adding_pending) {
1866  }
1867  else {
1868  // Constraints are not minimized and generators are not up-to-date.
1871  }
1872 
1873  // Note: the constraint system may have become unsatisfiable, thus
1874  // we do not check for satisfiability.
1875  PPL_ASSERT_HEAVY(OK());
1876 }
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
A linear equality or inequality.
bool is_equality() const
Returns true if and only if *this is an equality constraint.
void insert_pending(const Constraint &c)
Inserts in *this a copy of the constraint c, increasing the number of space dimensions if needed...
size_t dimension_type
An unsigned integral type for representing space dimensions.
void update_constraints() const
Updates constraints starting from generators and minimizes them.
bool is_necessarily_closed() const
Returns true if and only if the topology of *this row is necessarily closed.
void set_constraints_pending()
Sets status to express that constraints are pending.
void insert(const Constraint &c)
Inserts in *this a copy of the constraint c, increasing the number of space dimensions if needed...
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
const_iterator begin() const
Returns the const_iterator pointing to the first constraint, if *this is not empty; otherwise...
bool can_have_something_pending() const
Returns true if the polyhedron can have something pending.
Constraint_System con_sys
The system of constraints.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
const_iterator end() const
Returns the past-the-end const_iterator.
void process_pending_generators() const
Processes the pending generators and obtains a minimized polyhedron.
Status status
The status flags to keep track of the polyhedron's internal state.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
void clear_constraints_minimized()
Sets status to express that constraints are no longer minimized.
bool has_pending_generators() const
Returns true if there are pending generators.
Coefficient c
Definition: PIP_Tree.cc:64
expr_type expression() const
Partial read access to the (adapted) internal expression.
void clear_generators_up_to_date()
Sets status to express that generators are no longer up-to-date.
template<typename FP_Format , typename Interval_Info >
void Parma_Polyhedra_Library::Polyhedron::refine_with_linear_form_inequality ( const Linear_Form< Interval< FP_Format, Interval_Info > > &  left,
const Linear_Form< Interval< FP_Format, Interval_Info > > &  right,
bool  is_strict = false 
)

Refines *this with the constraint expressed by left $<$ right if is_strict is set, with the constraint left $\leq$ right otherwise.

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

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

Definition at line 300 of file Polyhedron_templates.hh.

References convert_to_integer_expression(), is_necessarily_closed(), marked_empty(), overapproximate_linear_form(), PPL_COMPILE_TIME_CHECK, refine_with_constraint(), space_dim, and throw_dimension_incompatible().

Referenced by generalized_refine_with_linear_form_inequality().

303  {
304 
305  // Check that FP_Format is indeed a floating point type.
306  PPL_COMPILE_TIME_CHECK(!std::numeric_limits<FP_Format>::is_exact,
307  "Polyhedron::refine_with_linear_form_inequality:"
308  " FP_Format not a floating point type.");
309 
310  // Dimension compatibility checks.
311  // The dimensions of left and right should not be greater than the
312  // dimension of *this.
313  const dimension_type left_space_dim = left.space_dimension();
314  if (space_dim < left_space_dim) {
316  "refine_with_linear_form_inequality(l1, l2, s)", "l1", left);
317  }
318 
319  const dimension_type right_space_dim = right.space_dimension();
320  if (space_dim < right_space_dim) {
322  "refine_with_linear_form_inequality(l1, l2, s)", "l2", right);
323  }
324 
325  // We assume that the analyzer will not refine an unreachable test.
326  PPL_ASSERT(!marked_empty());
327 
328  typedef Interval<FP_Format, Interval_Info> FP_Interval_Type;
329  typedef Linear_Form<FP_Interval_Type> FP_Linear_Form;
330 
331  if (Floating_Point_Expression<FP_Interval_Type, float_ieee754_single>::
332  overflows(left)) {
333  return;
334  }
335 
336  if (Floating_Point_Expression<FP_Interval_Type, float_ieee754_single>::
337  overflows(right)) {
338  return;
339  }
340 
341  // Overapproximate left - right.
342  FP_Linear_Form left_minus_right(left);
343  left_minus_right -= right;
344  if (Floating_Point_Expression<FP_Interval_Type, float_ieee754_single>::
345  overflows(left_minus_right)) {
346  return;
347  }
348 
349  dimension_type lf_space_dim = left_minus_right.space_dimension();
350  FP_Linear_Form lf_approx;
351  overapproximate_linear_form(left_minus_right, lf_space_dim, lf_approx);
352  if (Floating_Point_Expression<FP_Interval_Type, float_ieee754_single>::
353  overflows(lf_approx)) {
354  return;
355  }
356 
357  // Normalize left - right.
358  Linear_Expression lf_approx_le;
359  convert_to_integer_expression(lf_approx, lf_space_dim, lf_approx_le);
360 
361  // Finally, do the refinement.
362  if (!is_strict || is_necessarily_closed()) {
363  refine_with_constraint(lf_approx_le <= 0);
364  }
365  else {
366  refine_with_constraint(lf_approx_le < 0);
367  }
368 }
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
void refine_with_constraint(const Constraint &c)
Uses a copy of constraint c to refine *this.
#define PPL_COMPILE_TIME_CHECK(e, msg)
Produces a compilation error if the compile-time constant e does not evaluate to true ...
static void convert_to_integer_expression(const Linear_Form< Interval< FP_Format, Interval_Info > > &lf, const dimension_type lf_dimension, Linear_Expression &result)
Helper function that makes result become a Linear_Expression obtained by normalizing the denominators...
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
void overapproximate_linear_form(const Linear_Form< Interval< FP_Format, Interval_Info > > &lf, const dimension_type lf_dimension, Linear_Form< Interval< FP_Format, Interval_Info > > &result)
Helper function that overapproximates an interval linear form.
PPL::Poly_Con_Relation Parma_Polyhedra_Library::Polyhedron::relation_with ( const Constraint c) const

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

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

Definition at line 209 of file Polyhedron_public.cc.

References 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_inconsistent(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), and Parma_Polyhedra_Library::Constraint::space_dimension().

Referenced by BFT00_poly_hull_assign_if_exact(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHZ09_C_poly_hull_assign_if_exact(), BHZ09_NNC_poly_hull_assign_if_exact(), and poly_difference_assign().

209  {
210  // Dimension-compatibility check.
211  if (space_dim < c.space_dimension()) {
212  throw_dimension_incompatible("relation_with(c)", "c", c);
213  }
214 
215  if (marked_empty()) {
219  }
220  if (space_dim == 0) {
221  if (c.is_inconsistent()) {
222  if (c.is_strict_inequality() && c.inhomogeneous_term() == 0) {
223  // The constraint 0 > 0 implicitly defines the hyperplane 0 = 0;
224  // thus, the zero-dimensional point also saturates it.
227  }
228  else {
230  }
231  }
232  else if (c.is_equality() || c.inhomogeneous_term() == 0) {
235  }
236  else {
237  // The zero-dimensional point saturates
238  // neither the positivity constraint 1 >= 0,
239  // nor the strict positivity constraint 1 > 0.
241  }
242  }
243 
246  // The polyhedron is empty.
250  }
251  return gen_sys.relation_with(c);
252 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
static Poly_Con_Relation is_disjoint()
The polyhedron and the set of points satisfying the constraint are disjoint.
bool is_equality() const
Returns true if and only if *this is an equality constraint.
Generator_System gen_sys
The system of generators.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
static Poly_Con_Relation is_included()
The polyhedron is included in the set of points satisfying the constraint.
bool update_generators() const
Updates generators starting from constraints and minimizes them.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
static Poly_Con_Relation saturates()
The polyhedron is included in the set of points saturating the constraint.
bool is_strict_inequality() const
Returns true if and only if *this is a strict inequality constraint.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
bool is_inconsistent() const
Returns true if and only if *this is inconsistent (i.e., an always false constraint).
Definition: Constraint.cc:148
Parma_Polyhedra_Library::Poly_Con_Relation relation_with(const Constraint &c) const
Returns the relations holding between the generator system and the constraint c.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool process_pending_constraints() const
Processes the pending constraints and obtains a minimized polyhedron.
Coefficient_traits::const_reference inhomogeneous_term() const
Returns the inhomogeneous term of *this.
PPL::Poly_Gen_Relation Parma_Polyhedra_Library::Polyhedron::relation_with ( const Generator g) const

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

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

Definition at line 255 of file Polyhedron_public.cc.

References Parma_Polyhedra_Library::Poly_Gen_Relation::nothing(), Parma_Polyhedra_Library::Generator::space_dimension(), and Parma_Polyhedra_Library::Poly_Gen_Relation::subsumes().

255  {
256  // Dimension-compatibility check.
257  if (space_dim < g.space_dimension()) {
258  throw_dimension_incompatible("relation_with(g)", "g", g);
259  }
260 
261  // The empty polyhedron cannot subsume a generator.
262  if (marked_empty()) {
264  }
265 
266  // A universe polyhedron in a zero-dimensional space subsumes
267  // all the generators of a zero-dimensional space.
268  if (space_dim == 0) {
270  }
271 
272  if (has_pending_generators()) {
274  }
275  else if (!constraints_are_up_to_date()) {
277  }
278  return
281  : Poly_Gen_Relation::nothing();
282 }
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
static Poly_Gen_Relation subsumes()
Adding the generator would not change the polyhedron.
void update_constraints() const
Updates constraints starting from generators and minimizes them.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
Constraint_System con_sys
The system of constraints.
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void process_pending_generators() const
Processes the pending generators and obtains a minimized polyhedron.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool has_pending_generators() const
Returns true if there are pending generators.
static Poly_Gen_Relation nothing()
The assertion that says nothing.
The relation between a polyhedron and a generator.
bool satisfies_all_constraints(const Generator &g) const
Returns true if g satisfies all the constraints.
PPL::Poly_Con_Relation Parma_Polyhedra_Library::Polyhedron::relation_with ( const Congruence cg) const

Returns the relations holding between the polyhedron *this and the congruence c.

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

Definition at line 285 of file Polyhedron_public.cc.

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

285  {
286  const dimension_type cg_space_dim = cg.space_dimension();
287  // Dimension-compatibility check.
288  if (space_dim < cg_space_dim) {
289  throw_dimension_incompatible("relation_with(cg)", "cg", cg);
290  }
291 
292  if (cg.is_equality()) {
293  const Constraint c(cg);
294  return relation_with(c);
295  }
296 
297  if (marked_empty()) {
301  }
302 
303  if (space_dim == 0) {
304  if (cg.is_inconsistent()) {
306  }
307  else {
310  }
311  }
312 
315  // The polyhedron is empty.
319  }
320  // Build the equality corresponding to the congruence (ignoring the modulus).
321  Linear_Expression expr(cg.expression());
322  const Constraint c(expr == 0);
323 
324  // The polyhedron is non-empty so that there exists a point.
325  // For an arbitrary generator point, compute the scalar product with
326  // the equality.
327  PPL_DIRTY_TEMP_COEFFICIENT(sp_point);
329  gs_end = gen_sys.end(); gs_i != gs_end; ++gs_i) {
330  if (gs_i->is_point()) {
331  Scalar_Products::assign(sp_point, c, *gs_i);
332  expr -= sp_point;
333  break;
334  }
335  }
336 
337  // Find two hyperplanes that satisfy the congruence and are near to
338  // the generating point (so that the point lies on or between these
339  // two hyperplanes).
340  // Then use the relations between the polyhedron and the halfspaces
341  // corresponding to the hyperplanes to determine the result.
342 
343  // Compute the distance from the point to an hyperplane.
344  const Coefficient& modulus = cg.modulus();
345  PPL_DIRTY_TEMP_COEFFICIENT(signed_distance);
346  signed_distance = sp_point % modulus;
347  if (signed_distance == 0) {
348  // The point is lying on the hyperplane.
349  return relation_with(expr == 0);
350  }
351  else {
352  // The point is not lying on the hyperplane.
353  expr += signed_distance;
354  }
355  // Build first halfspace constraint.
356  const bool positive = (signed_distance > 0);
357  const Constraint first_halfspace = positive ? (expr >= 0) : (expr <= 0);
358 
359  const Poly_Con_Relation first_rels = relation_with(first_halfspace);
360  PPL_ASSERT(!first_rels.implies(Poly_Con_Relation::saturates())
361  && !first_rels.implies(Poly_Con_Relation::is_disjoint()));
364  }
365 
366  // Build second halfspace.
367  if (positive) {
368  expr -= modulus;
369  }
370  else {
371  expr += modulus;
372  }
373  const Constraint second_halfspace = positive ? (expr <= 0) : (expr >= 0);
374 
375  PPL_ASSERT(first_rels == Poly_Con_Relation::is_included());
376  const Poly_Con_Relation second_rels = relation_with(second_halfspace);
377  PPL_ASSERT(!second_rels.implies(Poly_Con_Relation::saturates())
378  && !second_rels.implies(Poly_Con_Relation::is_disjoint()));
379  if (second_rels.implies(Poly_Con_Relation::strictly_intersects())) {
381  }
382 
383  PPL_ASSERT(second_rels == Poly_Con_Relation::is_included());
385 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
static Poly_Con_Relation is_disjoint()
The polyhedron and the set of points satisfying the constraint are disjoint.
Coefficient_traits::const_reference modulus() const
Returns a const reference to the modulus of *this.
A linear equality or inequality.
static bool implies(flags_t x, flags_t y)
True if and only if the conjunction x implies the conjunction y.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
bool is_inconsistent() const
Returns true if and only if *this is inconsistent (i.e., an always false congruence).
Definition: Congruence.cc:218
static Poly_Con_Relation is_included()
The polyhedron is included in the set of points satisfying the constraint.
bool update_generators() const
Updates generators starting from constraints and minimizes them.
expr_type expression() const
Partial read access to the (adapted) internal expression.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
static Poly_Con_Relation saturates()
The polyhedron is included in the set of points saturating the constraint.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
bool is_equality() const
Returns true if *this is an equality.
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
const_iterator end() const
Returns the past-the-end const_iterator.
const_iterator begin() const
Returns the const_iterator pointing to the first generator, if *this is not empty; otherwise...
bool process_pending_constraints() const
Processes the pending constraints and obtains a minimized polyhedron.
static void assign(Coefficient &z, const Linear_Expression &x, const Linear_Expression &y)
Computes the scalar product of x and y and assigns it to z.
Coefficient c
Definition: PIP_Tree.cc:64
static Poly_Con_Relation strictly_intersects()
The polyhedron intersects the set of points satisfying the constraint, but it is not included in it...
Poly_Con_Relation relation_with(const Constraint &c) const
Returns the relations holding between the polyhedron *this and the constraint c.
The relation between a polyhedron and a constraint.
void Parma_Polyhedra_Library::Polyhedron::remove_higher_space_dimensions ( dimension_type  new_dimension)

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

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

Definition at line 353 of file Polyhedron_chdims.cc.

Referenced by Parma_Polyhedra_Library::Implementation::Termination::all_affine_quasi_ranking_functions_MS(), Parma_Polyhedra_Library::Implementation::Termination::all_affine_ranking_functions_MS(), and Parma_Polyhedra_Library::Termination_Helpers::all_affine_ranking_functions_PR().

353  {
354  // Dimension-compatibility check.
355  if (new_dimension > space_dim) {
356  throw_dimension_incompatible("remove_higher_space_dimensions(nd)",
357  new_dimension);
358  }
359 
360  // The removal of no dimensions from any polyhedron is a no-op.
361  // Note that this case also captures the only legal removal of
362  // dimensions from a polyhedron in a 0-dim space.
363  if (new_dimension == space_dim) {
364  PPL_ASSERT_HEAVY(OK());
365  return;
366  }
367 
368  // We need updated generators; note that keeping pending generators
369  // is useless because constraints will be dropped anyway.
370  if (marked_empty()
373  // Removing dimensions from the empty polyhedron:
374  // just updates the space dimension.
375  space_dim = new_dimension;
376  con_sys.clear();
377  PPL_ASSERT_HEAVY(OK());
378  return;
379  }
380 
381  if (new_dimension == 0) {
382  // Removing all dimensions from a non-empty polyhedron:
383  // just return the zero-dimensional universe polyhedron.
385  return;
386  }
387 
388  gen_sys.set_space_dimension(new_dimension);
389 
390  // Constraints are not up-to-date and generators are not minimized.
393 
394  // Update the space dimension.
395  space_dim = new_dimension;
396 
397  PPL_ASSERT_HEAVY(OK(true));
398 }
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
void clear_constraints_up_to_date()
Sets status to express that constraints are no longer up-to-date.
bool remove_pending_to_obtain_generators() const
Lazily integrates the pending descriptions of the polyhedron to obtain a generator system without pen...
Generator_System gen_sys
The system of generators.
bool update_generators() const
Updates generators starting from constraints and minimizes them.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
void clear()
Removes all the constraints from the constraint system and sets its space dimension to 0...
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
Constraint_System con_sys
The system of constraints.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
void set_space_dimension(dimension_type space_dim)
Sets the space dimension of the rows in the system to space_dim .
void set_zero_dim_univ()
Sets status to express that the polyhedron is the universe 0-dimension vector space, clearing all corresponding matrices.
void clear_generators_minimized()
Sets status to express that generators are no longer minimized.
bool has_something_pending() const
Returns true if there are either pending constraints or pending generators.
void Parma_Polyhedra_Library::Polyhedron::remove_pending_to_obtain_constraints ( ) const
private

Lazily integrates the pending descriptions of the polyhedron to obtain a constraint system without pending rows.

It is assumed that the polyhedron does have some constraints or generators pending.

Definition at line 810 of file Polyhedron_nonpublic.cc.

References clear_constraints_minimized(), clear_generators_up_to_date(), clear_pending_constraints(), con_sys, has_pending_constraints(), has_pending_generators(), process_pending_generators(), Parma_Polyhedra_Library::Constraint_System::set_sorted(), and Parma_Polyhedra_Library::Constraint_System::unset_pending_rows().

810  {
811  PPL_ASSERT(has_something_pending());
812 
813  Polyhedron& x = const_cast<Polyhedron&>(*this);
814 
815  // If the polyhedron has pending constraints, simply unset them.
816  if (x.has_pending_constraints()) {
817  // Integrate the pending constraints, which are possibly not sorted.
818  x.con_sys.set_sorted(false);
819  x.con_sys.unset_pending_rows();
820  x.clear_pending_constraints();
821  x.clear_constraints_minimized();
822  x.clear_generators_up_to_date();
823  }
824  else {
825  PPL_ASSERT(x.has_pending_generators());
826  // We must process the pending generators and obtain the
827  // corresponding system of constraints.
828  x.process_pending_generators();
829  }
830  PPL_ASSERT_HEAVY(OK(true));
831 }
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
bool has_something_pending() const
Returns true if there are either pending constraints or pending generators.
bool Parma_Polyhedra_Library::Polyhedron::remove_pending_to_obtain_generators ( ) const
private

Lazily integrates the pending descriptions of the polyhedron to obtain a generator system without pending rows.

Returns
false if and only if *this turns out to be an empty polyhedron.

It is assumed that the polyhedron does have some constraints or generators pending.

Definition at line 834 of file Polyhedron_nonpublic.cc.

References clear_constraints_up_to_date(), clear_generators_minimized(), clear_pending_generators(), gen_sys, has_pending_constraints(), has_pending_generators(), process_pending_constraints(), Parma_Polyhedra_Library::Generator_System::set_sorted(), and Parma_Polyhedra_Library::Generator_System::unset_pending_rows().

Referenced by map_space_dimensions().

834  {
835  PPL_ASSERT(has_something_pending());
836 
837  Polyhedron& x = const_cast<Polyhedron&>(*this);
838 
839  // If the polyhedron has pending generators, simply unset them.
840  if (x.has_pending_generators()) {
841  // Integrate the pending generators, which are possibly not sorted.
842  x.gen_sys.set_sorted(false);
843  x.gen_sys.unset_pending_rows();
844  x.clear_pending_generators();
845  x.clear_generators_minimized();
846  x.clear_constraints_up_to_date();
847  PPL_ASSERT_HEAVY(OK(true));
848  return true;
849  }
850  else {
851  PPL_ASSERT(x.has_pending_constraints());
852  // We must integrate the pending constraints and obtain the
853  // corresponding system of generators.
854  return x.process_pending_constraints();
855  }
856 }
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
bool has_something_pending() const
Returns true if there are either pending constraints or pending generators.
void Parma_Polyhedra_Library::Polyhedron::remove_space_dimensions ( const Variables_Set vars)

Removes all the specified dimensions from the vector space.

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

Definition at line 301 of file Polyhedron_chdims.cc.

References Parma_Polyhedra_Library::Variables_Set::space_dimension().

Referenced by Parma_Polyhedra_Library::Termination_Helpers::all_affine_ranking_functions_PR_original().

301  {
302  // The removal of no dimensions from any polyhedron is a no-op.
303  // Note that this case also captures the only legal removal of
304  // dimensions from a polyhedron in a 0-dim space.
305  if (vars.empty()) {
306  PPL_ASSERT_HEAVY(OK());
307  return;
308  }
309 
310  // Dimension-compatibility check.
311  const dimension_type min_space_dim = vars.space_dimension();
312  if (space_dim < min_space_dim) {
313  throw_dimension_incompatible("remove_space_dimensions(vs)", min_space_dim);
314  }
315 
316  const dimension_type new_space_dim = space_dim - vars.size();
317 
318  // We need updated generators; note that keeping pending generators
319  // is useless because the constraints will be dropped anyway.
320  if (marked_empty()
323  // Removing dimensions from the empty polyhedron:
324  // we clear `con_sys' since it could have contained the
325  // unsatisfiable constraint of the wrong dimension.
326  con_sys.clear();
327  // Update the space dimension.
328  space_dim = new_space_dim;
329  PPL_ASSERT_HEAVY(OK());
330  return;
331  }
332 
333  // When removing _all_ dimensions from a non-empty polyhedron,
334  // we obtain the zero-dimensional universe polyhedron.
335  if (new_space_dim == 0) {
337  return;
338  }
339 
341 
342  // Constraints are not up-to-date and generators are not minimized.
345 
346  // Update the space dimension.
347  space_dim = new_space_dim;
348 
349  PPL_ASSERT_HEAVY(OK(true));
350 }
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
void clear_constraints_up_to_date()
Sets status to express that constraints are no longer up-to-date.
bool remove_pending_to_obtain_generators() const
Lazily integrates the pending descriptions of the polyhedron to obtain a generator system without pen...
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
void remove_space_dimensions(const Variables_Set &vars)
Removes all the specified dimensions from the generator system.
bool update_generators() const
Updates generators starting from constraints and minimizes them.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
void clear()
Removes all the constraints from the constraint system and sets its space dimension to 0...
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
Constraint_System con_sys
The system of constraints.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
void set_zero_dim_univ()
Sets status to express that the polyhedron is the universe 0-dimension vector space, clearing all corresponding matrices.
void clear_generators_minimized()
Sets status to express that generators are no longer minimized.
bool has_something_pending() const
Returns true if there are either pending constraints or pending generators.
bool Parma_Polyhedra_Library::Polyhedron::sat_c_is_up_to_date ( ) const
inlineprivate
bool Parma_Polyhedra_Library::Polyhedron::sat_g_is_up_to_date ( ) const
inlineprivate
void Parma_Polyhedra_Library::Polyhedron::select_CH78_constraints ( const Polyhedron y,
Constraint_System cs_selection 
) const
private

Copies to cs_selection the constraints of y corresponding to the definition of the CH78-widening of *this and y.

Definition at line 40 of file Polyhedron_widenings.cc.

References c, con_sys, constraints_are_minimized(), has_something_pending(), Parma_Polyhedra_Library::Constraint_System::insert(), marked_empty(), Parma_Polyhedra_Library::Constraint_System::num_rows(), space_dim, Parma_Polyhedra_Library::Constraint_System::topology(), and topology().

Referenced by H79_widening_assign().

41  {
42  // Private method: the caller must ensure the following conditions.
43  PPL_ASSERT(topology() == y.topology()
44  && topology() == cs_selection.topology()
45  && space_dim == y.space_dim);
46  PPL_ASSERT(!marked_empty()
49  PPL_ASSERT(!y.marked_empty()
50  && !y.has_something_pending()
51  && y.constraints_are_minimized());
52 
53  // A constraint in `y.con_sys' is copied to `cs_selection'
54  // if it is satisfied by all the generators of `gen_sys'.
55 
56  // Note: the loop index `i' goes upward to avoid reversing
57  // the ordering of the chosen constraints.
58  for (dimension_type i = 0, end = y.con_sys.num_rows(); i < end; ++i) {
59  const Constraint& c = y.con_sys[i];
61  cs_selection.insert(c);
62  }
63  }
64 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
bool satisfied_by_all_generators(const Constraint &c) const
Returns true if all the generators satisfy c.
Topology topology() const
Returns the topological kind of the polyhedron.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
Coefficient c
Definition: PIP_Tree.cc:64
void Parma_Polyhedra_Library::Polyhedron::select_H79_constraints ( const Polyhedron y,
Constraint_System cs_selected,
Constraint_System cs_not_selected 
) const
private

Splits the constraints of `x' into two subsets, depending on whether or not they are selected to compute the H79-widening of *this and y.

Definition at line 68 of file Polyhedron_widenings.cc.

References Parma_Polyhedra_Library::Bit_Row::clear(), con_sys, constraints_are_minimized(), gen_sys, generators_are_up_to_date(), has_something_pending(), Parma_Polyhedra_Library::Constraint_System::insert(), is_necessarily_closed(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), marked_empty(), Parma_Polyhedra_Library::Generator_System::num_rows(), Parma_Polyhedra_Library::Constraint_System::num_rows(), Parma_Polyhedra_Library::Bit_Matrix::remove_trailing_rows(), sat_g, sat_g_is_up_to_date(), Parma_Polyhedra_Library::Bit_Row::set(), Parma_Polyhedra_Library::Scalar_Products::sign(), Parma_Polyhedra_Library::Bit_Matrix::sort_rows(), Parma_Polyhedra_Library::Bit_Matrix::sorted_contains(), space_dim, strongly_minimize_constraints(), Parma_Polyhedra_Library::Affine_Space::swap(), Parma_Polyhedra_Library::swap(), Parma_Polyhedra_Library::Constraint_System::topology(), topology(), update_generators(), and update_sat_g().

Referenced by BHRZ03_widening_assign(), and H79_widening_assign().

70  {
71  // Private method: the caller must ensure the following conditions
72  // (beside the inclusion `y <= x').
73  PPL_ASSERT(topology() == y.topology()
74  && topology() == cs_selected.topology()
75  && topology() == cs_not_selected.topology());
76  PPL_ASSERT(space_dim == y.space_dim);
77  PPL_ASSERT(!marked_empty()
80  PPL_ASSERT(!y.marked_empty()
81  && !y.has_something_pending()
82  && y.constraints_are_minimized()
83  && y.generators_are_up_to_date());
84 
85  // FIXME: this is a workaround for NNC polyhedra.
86  if (!y.is_necessarily_closed()) {
87  // Force strong minimization of constraints.
88  y.strongly_minimize_constraints();
89  // Recompute generators (without compromising constraint minimization).
90  y.update_generators();
91  }
92 
93  // Obtain a sorted copy of `y.sat_g'.
94  if (!y.sat_g_is_up_to_date()) {
95  y.update_sat_g();
96  }
97  Bit_Matrix tmp_sat_g = y.sat_g;
98  // Remove from `tmp_sat_g' the rows corresponding to tautologies
99  // (i.e., the positivity or epsilon-bounding constraints):
100  // this is needed in order to widen the polyhedron and not the
101  // corresponding homogenized polyhedral cone.
102  const Constraint_System& y_cs = y.con_sys;
103  const dimension_type old_num_rows = y_cs.num_rows();
104  dimension_type num_rows = old_num_rows;
105  for (dimension_type i = 0; i < num_rows; ++i) {
106  if (y_cs[i].is_tautological()) {
107  using std::swap;
108  --num_rows;
109  swap(tmp_sat_g[i], tmp_sat_g[num_rows]);
110  }
111  }
112  tmp_sat_g.remove_trailing_rows(old_num_rows - num_rows);
113  tmp_sat_g.sort_rows();
114 
115  // A constraint in `con_sys' is copied to `cs_selected'
116  // if its behavior with respect to `y.gen_sys' is the same
117  // as that of another constraint in `y.con_sys'.
118  // otherwise it is copied to `cs_not_selected'.
119  // Namely, we check whether the saturation row `buffer'
120  // (built starting from the given constraint and `y.gen_sys')
121  // is a row of the saturation matrix `tmp_sat_g'.
122 
123  // CHECKME: the following comment is only applicable when `y.gen_sys'
124  // is minimized. In that case, the comment suggests that it would be
125  // possible to use a fast (but incomplete) redundancy test based on
126  // the number of saturators in `buffer'.
127  // NOTE: If the considered constraint of `con_sys' does not
128  // satisfy the saturation rule (see Section \ref prelims), then
129  // it will not appear in the resulting constraint system,
130  // because `tmp_sat_g' is built starting from a minimized polyhedron.
131 
132  // The size of `buffer' will reach sat.num_columns() bits.
133  Bit_Row buffer;
134  // Note: the loop index `i' goes upward to avoid reversing
135  // the ordering of the chosen constraints.
136  for (dimension_type i = 0, end = con_sys.num_rows(); i < end; ++i) {
137  const Constraint& ci = con_sys[i];
138  // The saturation row `buffer' is built considering
139  // the `i'-th constraint of the polyhedron `x' and
140  // all the generators of the polyhedron `y'.
141  buffer.clear();
142  for (dimension_type j = y.gen_sys.num_rows(); j-- > 0; ) {
143  const int sp_sgn = Scalar_Products::sign(ci, y.gen_sys[j]);
144  // We are assuming that `y <= x'.
145  PPL_ASSERT(sp_sgn >= 0
146  || (!is_necessarily_closed()
147  && ci.is_strict_inequality()
148  && y.gen_sys[j].is_point()));
149  if (sp_sgn > 0) {
150  buffer.set(j);
151  }
152  }
153  // We check whether `buffer' is a row of `tmp_sat_g',
154  // exploiting its sortedness in order to have faster comparisons.
155  if (tmp_sat_g.sorted_contains(buffer)) {
156  cs_selected.insert(ci);
157  }
158  else {
159  cs_not_selected.insert(ci);
160  }
161  }
162 }
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
void swap(CO_Tree &x, CO_Tree &y)
size_t dimension_type
An unsigned integral type for representing space dimensions.
void swap(Polyhedron &x, Polyhedron &y)
Swaps x with y.
void clear()
Removes all the constraints from the constraint system and sets its space dimension to 0...
Topology topology() const
Returns the topological kind of the polyhedron.
Constraint_System con_sys
The system of constraints.
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
static int sign(const Linear_Expression &x, const Linear_Expression &y)
Returns the sign of the scalar product between x and y.
bool has_pending_generators() const
Returns true if there are pending generators.
void Parma_Polyhedra_Library::Polyhedron::set_constraints_minimized ( )
inlineprivate

Sets status to express that constraints are minimized.

Definition at line 211 of file Polyhedron_inlines.hh.

References Parma_Polyhedra_Library::Polyhedron::Status::set_c_minimized(), set_constraints_up_to_date(), and status.

Referenced by Polyhedron(), update_constraints(), and update_generators().

211  {
214 }
void set_constraints_up_to_date()
Sets status to express that constraints are up-to-date.
Status status
The status flags to keep track of the polyhedron's internal state.
void Parma_Polyhedra_Library::Polyhedron::set_constraints_pending ( )
inlineprivate

Sets status to express that constraints are pending.

Definition at line 223 of file Polyhedron_inlines.hh.

References Parma_Polyhedra_Library::Polyhedron::Status::set_c_pending(), and status.

Referenced by intersection_assign().

223  {
225 }
Status status
The status flags to keep track of the polyhedron's internal state.
void Parma_Polyhedra_Library::Polyhedron::set_constraints_up_to_date ( )
inlineprivate

Sets status to express that constraints are up-to-date.

Definition at line 201 of file Polyhedron_inlines.hh.

References Parma_Polyhedra_Library::Polyhedron::Status::set_c_up_to_date(), and status.

Referenced by Polyhedron(), and set_constraints_minimized().

201  {
203 }
Status status
The status flags to keep track of the polyhedron's internal state.
void Parma_Polyhedra_Library::Polyhedron::set_empty ( )
private

Sets status to express that the polyhedron is empty, clearing all corresponding matrices.

Definition at line 727 of file Polyhedron_nonpublic.cc.

Referenced by intersection_assign(), poly_difference_assign(), Polyhedron(), positive_time_elapse_assign_impl(), process_pending_constraints(), time_elapse_assign(), and update_generators().

727  {
728  status.set_empty();
729  // The polyhedron is empty: we can thus throw away everything.
730  con_sys.clear();
731  gen_sys.clear();
732  sat_c.clear();
733  sat_g.clear();
734 }
Generator_System gen_sys
The system of generators.
void clear()
Removes all the constraints from the constraint system and sets its space dimension to 0...
void clear()
Removes all the generators from the generator system and sets its space dimension to 0...
Constraint_System con_sys
The system of constraints.
void clear()
Clears the matrix deallocating all its rows.
Bit_Matrix sat_g
The saturation matrix having generators on its columns.
Status status
The status flags to keep track of the polyhedron's internal state.
Bit_Matrix sat_c
The saturation matrix having constraints on its columns.
void Parma_Polyhedra_Library::Polyhedron::set_generators_minimized ( )
inlineprivate

Sets status to express that generators are minimized.

Definition at line 217 of file Polyhedron_inlines.hh.

References Parma_Polyhedra_Library::Polyhedron::Status::set_g_minimized(), set_generators_up_to_date(), and status.

Referenced by update_constraints(), and update_generators().

217  {
220 }
void set_generators_up_to_date()
Sets status to express that generators are up-to-date.
Status status
The status flags to keep track of the polyhedron's internal state.
void Parma_Polyhedra_Library::Polyhedron::set_generators_pending ( )
inlineprivate

Sets status to express that generators are pending.

Definition at line 228 of file Polyhedron_inlines.hh.

References Parma_Polyhedra_Library::Polyhedron::Status::set_g_pending(), and status.

Referenced by poly_hull_assign(), and time_elapse_assign().

228  {
230 }
Status status
The status flags to keep track of the polyhedron's internal state.
void Parma_Polyhedra_Library::Polyhedron::set_generators_up_to_date ( )
inlineprivate

Sets status to express that generators are up-to-date.

Definition at line 206 of file Polyhedron_inlines.hh.

References Parma_Polyhedra_Library::Polyhedron::Status::set_g_up_to_date(), and status.

Referenced by Polyhedron(), and set_generators_minimized().

206  {
208 }
Status status
The status flags to keep track of the polyhedron's internal state.
void Parma_Polyhedra_Library::Polyhedron::set_sat_c_up_to_date ( )
inlineprivate
void Parma_Polyhedra_Library::Polyhedron::set_sat_g_up_to_date ( )
inlineprivate
void Parma_Polyhedra_Library::Polyhedron::set_zero_dim_univ ( )
private

Sets status to express that the polyhedron is the universe 0-dimension vector space, clearing all corresponding matrices.

Definition at line 719 of file Polyhedron_nonpublic.cc.

Referenced by map_space_dimensions(), Polyhedron(), and simplify_using_context_assign().

719  {
721  space_dim = 0;
722  con_sys.clear();
723  gen_sys.clear();
724 }
Generator_System gen_sys
The system of generators.
void clear()
Removes all the constraints from the constraint system and sets its space dimension to 0...
void clear()
Removes all the generators from the generator system and sets its space dimension to 0...
Constraint_System con_sys
The system of constraints.
Status status
The status flags to keep track of the polyhedron's internal state.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
Constraint_System Parma_Polyhedra_Library::Polyhedron::simplified_constraints ( ) const
inlineprivate

If constraints are up-to-date, obtain a simplified copy of them.

Definition at line 354 of file Polyhedron_inlines.hh.

References con_sys, constraints_are_minimized(), constraints_are_up_to_date(), has_pending_constraints(), Parma_Polyhedra_Library::Constraint_System::num_pending_rows(), Parma_Polyhedra_Library::Constraint_System::simplify(), and Parma_Polyhedra_Library::Constraint_System::unset_pending_rows().

Referenced by Parma_Polyhedra_Library::Box< ITV >::Box().

354  {
355  PPL_ASSERT(constraints_are_up_to_date());
356  Constraint_System cs(con_sys);
357  if (cs.num_pending_rows() > 0) {
358  cs.unset_pending_rows();
359  }
361  cs.simplify();
362  }
363  return cs;
364 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
bool constraints_are_minimized() const
Returns true if the system of constraints is minimized.
Constraint_System con_sys
The system of constraints.
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
template<typename Linear_System1 >
dimension_type Parma_Polyhedra_Library::Polyhedron::simplify ( Linear_System1 &  sys,
Bit_Matrix sat 
)
staticprivate

Uses Gauss' elimination method to simplify the result of conversion().

Returns
The rank of sys.
Parameters
sysThe system to simplify: it will be modified;
satThe saturation matrix corresponding to sys.

sys may be modified by swapping some of its rows and by possibly removing some of them, if they turn out to be redundant.

If sys is a system of constraints, then the rows of sat are indexed by constraints and its columns are indexed by generators; otherwise, if sys is a system of generators, then the rows of sat are indexed by generators and its columns by constraints.

Given a system of constraints or a system of generators, this function simplifies it using Gauss' elimination method (to remove redundant equalities/lines), deleting redundant inequalities/rays/points and making back-substitution. The explanation that follows assumes that sys is a system of constraints. For the case when sys is a system of generators, a similar explanation can be obtain by applying duality.

The explanation relies on the notion of redundancy. (See the Introduction.)

First we make some observations that can help the reader in understanding the function:

Proposition: An inequality that is saturated by all the generators can be transformed to an equality.

In fact, by combining any number of generators that saturate the constraints, we obtain a generator that saturates the constraints too:

\[ \langle \vect{c}, \vect{r}_1 \rangle = 0 \land \langle \vect{c}, \vect{r}_2 \rangle = 0 \Rightarrow \langle \vect{c}, (\lambda_1 \vect{r}_1 + \lambda_2 \vect{r}_2) \rangle = \lambda_1 \langle \vect{c}, \vect{r}_1 \rangle + \lambda_2 \langle \vect{c}, \vect{r}_2 \rangle = 0, \]

where $\lambda_1, \lambda_2$ can be any real number.

Definition at line 84 of file Polyhedron_simplify_templates.hh.

References Parma_Polyhedra_Library::compute_capacity(), Parma_Polyhedra_Library::Implementation::BD_Shapes::empty, Parma_Polyhedra_Library::NECESSARILY_CLOSED, Parma_Polyhedra_Library::Bit_Matrix::num_columns(), Parma_Polyhedra_Library::Bit_Matrix::remove_trailing_rows(), simplify_num_saturators_p, simplify_num_saturators_size, swap(), and Parma_Polyhedra_Library::swap().

Referenced by add_and_minimize(), and minimize().

84  {
85  dimension_type num_rows = sys.num_rows();
86  const dimension_type num_cols_sat = sat.num_columns();
87 
88  using std::swap;
89 
90  // Looking for the first inequality in `sys'.
91  dimension_type num_lines_or_equalities = 0;
92  while (num_lines_or_equalities < num_rows
93  && sys[num_lines_or_equalities].is_line_or_equality()) {
94  ++num_lines_or_equalities;
95  }
96 
97  // `num_saturators[i]' will contain the number of generators
98  // that saturate the constraint `sys[i]'.
99  if (num_rows > simplify_num_saturators_size) {
100  delete [] simplify_num_saturators_p;
103  const size_t max_size
104  = std::numeric_limits<size_t>::max() / sizeof(dimension_type);
105  const size_t new_size = compute_capacity(num_rows, max_size);
107  simplify_num_saturators_size = new_size;
108  }
109  dimension_type* const num_saturators = simplify_num_saturators_p;
110 
111  bool sys_sorted = sys.is_sorted();
112 
113  // Computing the number of saturators for each inequality,
114  // possibly identifying and swapping those that happen to be
115  // equalities (see Proposition above).
116  for (dimension_type i = num_lines_or_equalities; i < num_rows; ++i) {
117  if (sat[i].empty()) {
118  // The constraint `sys_rows[i]' is saturated by all the generators.
119  // Thus, either it is already an equality or it can be transformed
120  // to an equality (see Proposition above).
121  sys.sys.rows[i].set_is_line_or_equality();
122  // Note: simple normalization already holds.
123  sys.sys.rows[i].sign_normalize();
124  // We also move it just after all the other equalities,
125  // so that system `sys_rows' keeps its partial sortedness.
126  if (i != num_lines_or_equalities) {
127  sys.sys.rows[i].m_swap(sys.sys.rows[num_lines_or_equalities]);
128  swap(sat[i], sat[num_lines_or_equalities]);
129  swap(num_saturators[i], num_saturators[num_lines_or_equalities]);
130  }
131  ++num_lines_or_equalities;
132  // `sys' is no longer sorted.
133  sys_sorted = false;
134  }
135  else {
136  // There exists a generator which does not saturate `sys[i]',
137  // so that `sys[i]' is indeed an inequality.
138  // We store the number of its saturators.
139  num_saturators[i] = num_cols_sat - sat[i].count_ones();
140  }
141  }
142 
143  sys.set_sorted(sys_sorted);
144  PPL_ASSERT(sys.OK());
145 
146  // At this point, all the equalities of `sys' (included those
147  // inequalities that we just transformed to equalities) have
148  // indexes between 0 and `num_lines_or_equalities' - 1,
149  // which is the property needed by method gauss().
150  // We can simplify the system of equalities, obtaining the rank
151  // of `sys' as result.
152  const dimension_type rank = sys.gauss(num_lines_or_equalities);
153 
154  // Now the irredundant equalities of `sys' have indexes from 0
155  // to `rank' - 1, whereas the equalities having indexes from `rank'
156  // to `num_lines_or_equalities' - 1 are all redundant.
157  // (The inequalities in `sys' have been left untouched.)
158  // The rows containing equalities are not sorted.
159 
160  if (rank < num_lines_or_equalities) {
161  // We identified some redundant equalities.
162  // Moving them at the bottom of `sys':
163  // - index `redundant' runs through the redundant equalities
164  // - index `erasing' identifies the first row that should
165  // be erased after this loop.
166  // Note that we exit the loop either because we have removed all
167  // redundant equalities or because we have moved all the
168  // inequalities.
169  for (dimension_type redundant = rank,
170  erasing = num_rows;
171  redundant < num_lines_or_equalities
172  && erasing > num_lines_or_equalities;
173  ) {
174  --erasing;
175  sys.remove_row(redundant);
176  swap(sat[redundant], sat[erasing]);
177  swap(num_saturators[redundant], num_saturators[erasing]);
178  ++redundant;
179  }
180  // Adjusting the value of `num_rows' to the number of meaningful
181  // rows of `sys': `num_lines_or_equalities' - `rank' is the number of
182  // redundant equalities moved to the bottom of `sys', which are
183  // no longer meaningful.
184  num_rows -= num_lines_or_equalities - rank;
185 
186  // If the above loop exited because it moved all inequalities, it may not
187  // have removed all the rendundant rows.
188  sys.remove_trailing_rows(sys.num_rows() - num_rows);
189 
190  PPL_ASSERT(sys.num_rows() == num_rows);
191 
192  sat.remove_trailing_rows(num_lines_or_equalities - rank);
193 
194  // Adjusting the value of `num_lines_or_equalities'.
195  num_lines_or_equalities = rank;
196  }
197 
198  const dimension_type old_num_rows = sys.num_rows();
199 
200  // Now we use the definition of redundancy (given in the Introduction)
201  // to remove redundant inequalities.
202 
203  // First we check the saturation rule, which provides a necessary
204  // condition for an inequality to be irredundant (i.e., it provides
205  // a sufficient condition for identifying redundant inequalities).
206  // Let
207  //
208  // num_saturators[i] = num_sat_lines[i] + num_sat_rays_or_points[i],
209  // dim_lin_space = num_irredundant_lines,
210  // dim_ray_space
211  // = dim_vector_space - num_irredundant_equalities - dim_lin_space
212  // = num_columns - 1 - num_lines_or_equalities - dim_lin_space,
213  // min_sat_rays_or_points = dim_ray_space.
214  //
215  // An inequality saturated by less than `dim_ray_space' _rays/points_
216  // is redundant. Thus we have the implication
217  //
218  // (num_saturators[i] - num_sat_lines[i] < dim_ray_space)
219  // ==>
220  // redundant(sys[i]).
221  //
222  // Moreover, since every line saturates all inequalities, we also have
223  // dim_lin_space = num_sat_lines[i]
224  // so that we can rewrite the condition above as follows:
225  //
226  // (num_saturators[i] < num_columns - num_lines_or_equalities - 1)
227  // ==>
228  // redundant(sys[i]).
229  //
230  const dimension_type sys_num_columns
231  = sys.topology() == NECESSARILY_CLOSED ? sys.space_dimension() + 1
232  : sys.space_dimension() + 2;
233  const dimension_type min_saturators
234  = sys_num_columns - num_lines_or_equalities - 1;
235  for (dimension_type i = num_lines_or_equalities; i < num_rows; ) {
236  if (num_saturators[i] < min_saturators) {
237  // The inequality `sys[i]' is redundant.
238  --num_rows;
239  sys.remove_row(i);
240  swap(sat[i], sat[num_rows]);
241  swap(num_saturators[i], num_saturators[num_rows]);
242  }
243  else {
244  ++i;
245  }
246  }
247 
248  // Now we check the independence rule.
249  for (dimension_type i = num_lines_or_equalities; i < num_rows; ) {
250  bool redundant = false;
251  // NOTE: in the inner loop, index `j' runs through _all_ the
252  // inequalities and we do not test if `sat[i]' is strictly
253  // contained into `sat[j]'. Experimentation has shown that this
254  // is faster than having `j' only run through the indexes greater
255  // than `i' and also doing the test `strict_subset(sat[i],
256  // sat[k])'.
257  for (dimension_type j = num_lines_or_equalities; j < num_rows; ) {
258  if (i == j) {
259  // We want to compare different rows of `sys'.
260  ++j;
261  }
262  else {
263  // Let us recall that each generator lies on a facet of the
264  // polyhedron (see the Introduction).
265  // Given two constraints `c_1' and `c_2', if there are `m'
266  // generators lying on the hyper-plane corresponding to `c_1',
267  // the same `m' generators lie on the hyper-plane
268  // corresponding to `c_2', too, and there is another one lying
269  // on the latter but not on the former, then `c_2' is more
270  // restrictive than `c_1', i.e., `c_1' is redundant.
271  bool strict_subset;
272  if (subset_or_equal(sat[j], sat[i], strict_subset)) {
273  if (strict_subset) {
274  // All the saturators of the inequality `sys[i]' are
275  // saturators of the inequality `sys[j]' too,
276  // and there exists at least one saturator of `sys[j]'
277  // which is not a saturator of `sys[i]'.
278  // It follows that inequality `sys[i]' is redundant.
279  redundant = true;
280  break;
281  }
282  else {
283  // We have `sat[j] == sat[i]'. Hence inequalities
284  // `sys[i]' and `sys[j]' are saturated by the same set of
285  // generators. Then we can remove either one of the two
286  // inequalities: we remove `sys[j]'.
287  --num_rows;
288  sys.remove_row(j);
289  PPL_ASSERT(sys.num_rows() == num_rows);
290  swap(sat[j], sat[num_rows]);
291  swap(num_saturators[j], num_saturators[num_rows]);
292  }
293  }
294  else {
295  // If we reach this point then we know that `sat[i]' does
296  // not contain (and is different from) `sat[j]', so that
297  // `sys[i]' is not made redundant by inequality `sys[j]'.
298  ++j;
299  }
300  }
301  }
302  if (redundant) {
303  // The inequality `sys[i]' is redundant.
304  --num_rows;
305  sys.remove_row(i);
306  PPL_ASSERT(sys.num_rows() == num_rows);
307  swap(sat[i], sat[num_rows]);
308  swap(num_saturators[i], num_saturators[num_rows]);
309  }
310  else {
311  // The inequality `sys[i]' is not redundant.
312  ++i;
313  }
314  }
315 
316  // Here we physically remove the `sat' rows corresponding to the redundant
317  // inequalities previously removed from `sys'.
318  sat.remove_trailing_rows(old_num_rows - num_rows);
319 
320  // At this point the first `num_lines_or_equalities' rows of 'sys'
321  // represent the irredundant equalities, while the remaining rows
322  // (i.e., those having indexes from `num_lines_or_equalities' to
323  // `num_rows' - 1) represent the irredundant inequalities.
324 #ifndef NDEBUG
325  // Check if the flag is set (that of the equalities is already set).
326  for (dimension_type i = num_lines_or_equalities; i < num_rows; ++i) {
327  PPL_ASSERT(sys[i].is_ray_or_point_or_inequality());
328  }
329 #endif
330 
331  // Finally, since now the sub-system (of `sys') of the irredundant
332  // equalities is in triangular form, we back substitute each
333  // variables with the expression obtained considering the equalities
334  // starting from the last one.
335  sys.back_substitute(num_lines_or_equalities);
336 
337  // The returned value is the number of irredundant equalities i.e.,
338  // the rank of the sub-system of `sys' containing only equalities.
339  // (See the Introduction for definition of lineality space dimension.)
340  return num_lines_or_equalities;
341 }
void swap(CO_Tree &x, CO_Tree &y)
size_t dimension_type
An unsigned integral type for representing space dimensions.
void swap(Polyhedron &x, Polyhedron &y)
Swaps x with y.
dimension_type compute_capacity(dimension_type requested_size, dimension_type maximum_size)
Speculative allocation function.
static dimension_type * simplify_num_saturators_p
Pointer to an array used by simplify().
static size_t simplify_num_saturators_size
Dimension of an array used by simplify().
bool Parma_Polyhedra_Library::Polyhedron::simplify_using_context_assign ( const Polyhedron y)

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

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

Definition at line 2155 of file Polyhedron_public.cc.

References Parma_Polyhedra_Library::MIP_Problem::add_constraint(), Parma_Polyhedra_Library::MIP_Problem::add_constraints(), add_constraints(), add_recycled_constraints(), Parma_Polyhedra_Library::MIP_Problem::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Generator_System::begin(), c, Parma_Polyhedra_Library::Generator::CLOSURE_POINT, con_sys, constraints_are_minimized(), constraints_are_up_to_date(), Parma_Polyhedra_Library::Bit_Row::empty(), Parma_Polyhedra_Library::Generator_System::end(), Parma_Polyhedra_Library::Constraint::EQUALITY, Parma_Polyhedra_Library::Constraint::expression(), gen_sys, generators_are_minimized(), has_pending_generators(), has_something_pending(), Parma_Polyhedra_Library::Constraint_System::insert(), is_empty(), Parma_Polyhedra_Library::Constraint::is_inequality(), Parma_Polyhedra_Library::Generator::is_line(), is_necessarily_closed(), Parma_Polyhedra_Library::Constraint::is_tautological(), Parma_Polyhedra_Library::Boundary_NS::le(), Parma_Polyhedra_Library::Generator::LINE, minimize(), Parma_Polyhedra_Library::Constraint::NONSTRICT_INEQUALITY, Parma_Polyhedra_Library::Generator_System::num_rows(), Parma_Polyhedra_Library::Constraint_System::num_rows(), OK(), Parma_Polyhedra_Library::MIP_Problem::optimal_value(), Parma_Polyhedra_Library::OPTIMIZED_MIP_PROBLEM, Parma_Polyhedra_Library::Generator::POINT, Parma_Polyhedra_Library::Generator::RAY, Parma_Polyhedra_Library::Generator_System::satisfied_by_all_generators(), Parma_Polyhedra_Library::Bit_Row::set(), Parma_Polyhedra_Library::Constraint::set_is_line_or_equality(), Parma_Polyhedra_Library::MIP_Problem::set_objective_function(), set_zero_dim_univ(), Parma_Polyhedra_Library::Scalar_Products::sign(), Parma_Polyhedra_Library::Constraint::sign_normalize(), Parma_Polyhedra_Library::MIP_Problem::solve(), space_dim, Parma_Polyhedra_Library::Constraint::STRICT_INEQUALITY, Parma_Polyhedra_Library::swap(), topology(), Parma_Polyhedra_Library::Constraint::type(), Parma_Polyhedra_Library::Generator::type(), Parma_Polyhedra_Library::UNFEASIBLE_MIP_PROBLEM, and Parma_Polyhedra_Library::UNIVERSE.

2155  {
2156  Polyhedron& x = *this;
2157  // Topology compatibility check.
2158  if (x.topology() != y.topology()) {
2159  throw_topology_incompatible("simplify_using_context_assign(y)", "y", y);
2160  }
2161  // Dimension-compatibility check.
2162  if (x.space_dim != y.space_dim) {
2163  throw_dimension_incompatible("simplify_using_context_assign(y)", "y", y);
2164  }
2165 
2166  // Filter away the zero-dimensional case.
2167  if (x.space_dim == 0) {
2168  if (y.is_empty()) {
2169  x.set_zero_dim_univ();
2170  return false;
2171  }
2172  else {
2173  return !x.is_empty();
2174  }
2175  }
2176 
2177  // If `y' is empty, the biggest enlargement for `x' is the universe.
2178  if (!y.minimize()) {
2179  Polyhedron ph(x.topology(), x.space_dim, UNIVERSE);
2180  m_swap(ph);
2181  return false;
2182  }
2183 
2184  // If `x' is empty, the intersection is empty.
2185  if (!x.minimize()) {
2186  // Search for a constraint of `y' that is not a tautology.
2187  PPL_ASSERT(!y.has_pending_generators() && y.constraints_are_up_to_date());
2188  for (dimension_type i = y.con_sys.num_rows(); i-- > 0; ) {
2189  const Constraint& y_con_sys_i = y.con_sys[i];
2190  if (!y_con_sys_i.is_tautological()) {
2191  // Found: we obtain a constraint `c' contradicting the one we
2192  // found, and assign to `x' the polyhedron `ph' with `c' as
2193  // the only constraint.
2194  Polyhedron ph(x.topology(), x.space_dim, UNIVERSE);
2195  const Linear_Expression le(y_con_sys_i.expression());
2196  switch (y_con_sys_i.type()) {
2197  case Constraint::EQUALITY:
2198  ph.refine_no_check(le == 1);
2199  break;
2201  ph.refine_no_check(le <= -1);
2202  break;
2204  ph.refine_no_check(le == 0);
2205  break;
2206  }
2207  m_swap(ph);
2208  PPL_ASSERT_HEAVY(OK());
2209  return false;
2210  }
2211  }
2212  // `y' is the universe: `x' cannot be enlarged.
2213  return false;
2214  }
2215 
2216  PPL_ASSERT(x.constraints_are_minimized()
2217  && !x.has_something_pending()
2219  && !y.has_something_pending());
2220  const Constraint_System& x_cs = x.con_sys;
2221  const dimension_type x_cs_num_rows = x_cs.num_rows();
2222  const Generator_System& y_gs = y.gen_sys;
2223 
2224  // Record into `redundant_by_y' the info about which constraints of
2225  // `x' are redundant in the context `y'. Count the number of
2226  // redundancies found.
2227  std::vector<bool> redundant_by_y(x_cs_num_rows, false);
2228  dimension_type num_redundant_by_y = 0;
2229  for (dimension_type i = 0; i < x_cs_num_rows; ++i) {
2230  if (y_gs.satisfied_by_all_generators(x_cs[i])) {
2231  redundant_by_y[i] = true;
2232  ++num_redundant_by_y;
2233  }
2234  }
2235 
2236  Constraint_System result_cs;
2237 
2238  if (num_redundant_by_y < x_cs_num_rows) {
2239  // Some constraints were not identified as redundant (yet?).
2240  const Constraint_System& y_cs = y.con_sys;
2241  const dimension_type y_cs_num_rows = y_cs.num_rows();
2242  // Compute into `z' the minimized intersection of `x' and `y'.
2243  const bool x_first = (x_cs_num_rows > y_cs_num_rows);
2244  Polyhedron z(x_first ? x : y);
2245  if (x_first) {
2246  z.add_constraints(y_cs);
2247  }
2248  else {
2249  // Only copy (and then recycle) the non-redundant constraints.
2250  Constraint_System tmp_cs;
2251  for (dimension_type i = 0; i < x_cs_num_rows; ++i) {
2252  if (!redundant_by_y[i]) {
2253  tmp_cs.insert(x_cs[i]);
2254  }
2255  }
2256  z.add_recycled_constraints(tmp_cs);
2257  }
2258  if (!z.minimize()) {
2259  // For necessarily closed polyhedra, the objective function is
2260  // the default, zero. Moreover, the default maximization mode is
2261  // OK, since we are only interested in satisfiability.
2262  MIP_Problem lp;
2263  if (x.is_necessarily_closed()) {
2265  lp.add_constraints(y_cs);
2266  }
2267  else {
2268  // KLUDGE: temporarily mark `y_cs' if it was necessarily
2269  // closed, so that we can interpret the epsilon dimension as a
2270  // standard dimension. Be careful to reset the topology of `cs'
2271  // even on exceptional execution path.
2272  const_cast<Constraint_System&>(y_cs).mark_as_necessarily_closed();
2273  try {
2275  lp.add_constraints(y_cs);
2276  const_cast<Constraint_System&>(y_cs).mark_as_not_necessarily_closed();
2277  }
2278  catch (...) {
2279  const_cast<Constraint_System&>(y_cs).mark_as_not_necessarily_closed();
2280  throw;
2281  }
2282  // For not necessarily closed polyhedra, we maximize the
2283  // epsilon dimension as we want to rule out the possibility
2284  // that all solutions have epsilon = 0. We are in this case
2285  // if and only if the maximal value for epsilon is 0.
2287  }
2288  // We apply the following heuristics here: constraints of `x' that
2289  // are not made redundant by `y' are added to `lp' depending on
2290  // the number of generators of `y' they rule out (the more generators
2291  // they rule out, the sooner they are added). Of course, as soon
2292  // as `lp' becomes unsatisfiable, we stop adding.
2293  std::vector<Ruled_Out_Pair>
2294  ruled_out_vec(x_cs_num_rows - num_redundant_by_y);
2295  for (dimension_type i = 0, j = 0; i < x_cs_num_rows; ++i) {
2296  if (!redundant_by_y[i]) {
2297  const Constraint& c = x_cs[i];
2299  dimension_type num_ruled_out_generators = 0;
2300  for (Generator_System::const_iterator k = y_gs.begin(),
2301  y_gs_end = y_gs.end(); k != y_gs_end; ++k) {
2302  const Generator& g = *k;
2303  const int sp_sign = sps(g, c);
2304  if (x.is_necessarily_closed()) {
2305  if (g.is_line()) {
2306  // Lines must saturate the constraint.
2307  if (sp_sign != 0) {
2308  goto ruled_out;
2309  }
2310  }
2311  else {
2312  // `g' is either a ray, a point or a closure point.
2313  if (c.is_inequality()) {
2314  // `c' is a non-strict inequality.
2315  if (sp_sign < 0) {
2316  goto ruled_out;
2317  }
2318  }
2319  else {
2320  // `c' is an equality.
2321  if (sp_sign != 0) {
2322  goto ruled_out;
2323  }
2324  }
2325  }
2326  }
2327  else {
2328  // The topology is not necessarily closed.
2329  switch (g.type()) {
2330  case Generator::LINE:
2331  // Lines must saturate the constraint.
2332  if (sp_sign != 0) {
2333  goto ruled_out;
2334  }
2335  break;
2336  case Generator::POINT:
2337  // Have to perform the special test when dealing with
2338  // a strict inequality.
2339  switch (c.type()) {
2340  case Constraint::EQUALITY:
2341  if (sp_sign != 0) {
2342  goto ruled_out;
2343  }
2344  break;
2346  if (sp_sign < 0) {
2347  goto ruled_out;
2348  }
2349  break;
2351  if (sp_sign <= 0) {
2352  goto ruled_out;
2353  }
2354  break;
2355  }
2356  break;
2357  case Generator::RAY:
2358  // Intentionally fall through.
2360  if (c.is_inequality()) {
2361  // Constraint `c' is either a strict or a non-strict
2362  // inequality.
2363  if (sp_sign < 0) {
2364  goto ruled_out;
2365  }
2366  }
2367  else {
2368  // Constraint `c' is an equality.
2369  if (sp_sign != 0) {
2370  goto ruled_out;
2371  }
2372  }
2373  break;
2374  }
2375  }
2376  // If we reach this point, `g' satisfies `c'.
2377  continue;
2378  ruled_out:
2379  ++num_ruled_out_generators;
2380  }
2381  ruled_out_vec[j].constraint_index = i;
2382  ruled_out_vec[j].num_ruled_out = num_ruled_out_generators;
2383  ++j;
2384  }
2385  }
2386  std::sort(ruled_out_vec.begin(), ruled_out_vec.end(),
2387  Ruled_Out_Less_Than());
2388 
2389  for (std::vector<Ruled_Out_Pair>::const_iterator
2390  j = ruled_out_vec.begin(),
2391  ruled_out_vec_end = ruled_out_vec.end();
2392  j != ruled_out_vec_end;
2393  ++j) {
2394  const Constraint& c = x_cs[j->constraint_index];
2395  result_cs.insert(c);
2396  if (x.is_necessarily_closed()) {
2397  lp.add_constraint(c);
2398  }
2399  else {
2400  // KLUDGE: temporarily mark `c' as if it was necessarily
2401  // closed, so that we can interpret the epsilon dimension as a
2402  // standard dimension. Be careful to reset the topology of `c'
2403  // also on exceptional execution paths.
2404  const_cast<Constraint&>(c).mark_as_necessarily_closed();
2405  try {
2406  lp.add_constraint(c);
2407  const_cast<Constraint&>(c).mark_as_not_necessarily_closed();
2408  }
2409  catch (...) {
2410  const_cast<Constraint&>(c).mark_as_not_necessarily_closed();
2411  throw;
2412  }
2413  }
2414  const MIP_Problem_Status status = lp.solve();
2415  switch (status) {
2417  break;
2418  case OPTIMIZED_MIP_PROBLEM:
2419  if (x.is_necessarily_closed()) {
2420  continue;
2421  }
2422  else {
2423  Coefficient num;
2424  Coefficient den;
2425  lp.optimal_value(num, den);
2426  if (num != 0) {
2427  continue;
2428  }
2429  }
2430  break;
2431  default:
2432  PPL_UNREACHABLE;
2433  break;
2434  }
2435  Polyhedron result_ph(x.topology(), x.space_dim, UNIVERSE);
2436  result_ph.add_constraints(result_cs);
2437  swap(x, result_ph);
2438  PPL_ASSERT_HEAVY(x.OK());
2439  return false;
2440  }
2441  // Cannot exit from here.
2442  PPL_UNREACHABLE;
2443  }
2444  else {
2445  // Here `z' is not empty and minimized.
2446  PPL_ASSERT(z.constraints_are_minimized()
2447  && z.generators_are_minimized()
2448  && !z.has_something_pending());
2449  const Constraint_System& z_cs = z.con_sys;
2450  const Generator_System& z_gs = z.gen_sys;
2451  const dimension_type z_gs_num_rows = z_gs.num_rows();
2452 
2453  // Compute the number of equalities in x_cs, y_cs and z_cs
2454  // (exploiting minimal form knowledge).
2455  dimension_type x_cs_num_eq = 0;
2456  while (x_cs[x_cs_num_eq].is_equality()) {
2457  ++x_cs_num_eq;
2458  }
2459  dimension_type y_cs_num_eq = 0;
2460  while (y_cs[y_cs_num_eq].is_equality()) {
2461  ++y_cs_num_eq;
2462  }
2463  dimension_type z_cs_num_eq = 0;
2464  while (z_cs[z_cs_num_eq].is_equality()) {
2465  ++z_cs_num_eq;
2466  }
2467  PPL_ASSERT(x_cs_num_eq <= z_cs_num_eq && y_cs_num_eq <= z_cs_num_eq);
2468 
2469  // Identify non-redundant equalities.
2470  Constraint_System non_redundant_eq;
2471  dimension_type num_non_redundant_eq = 0;
2472  const dimension_type needed_non_redundant_eq = z_cs_num_eq - y_cs_num_eq;
2473  Constraint_System eqs(x.topology());
2474  if (needed_non_redundant_eq > 0) {
2475  // Populate eqs with the equalities from y.
2476  for (dimension_type i = 0; i < y_cs_num_eq; ++i) {
2477  eqs.insert(y_cs[i]);
2478  }
2479  // Try to find another `needed_non_redundant_eq' linear independent
2480  // equalities among those from x.
2481  for (dimension_type i = 0; i < x_cs_num_eq; ++i) {
2482  const Constraint& x_cs_i = x_cs[i];
2483  if (add_to_system_and_check_independence(eqs, x_cs_i)) {
2484  // x_cs_i is linear independent.
2485  non_redundant_eq.insert(x_cs_i);
2486  ++num_non_redundant_eq;
2487  if (num_non_redundant_eq == needed_non_redundant_eq) {
2488  // Already found all the needed equalities.
2489  break;
2490  }
2491  }
2492  }
2493  // NOTE: if num_non_redundant_eq < needed_non_redundant_eq
2494  // then we haven't found all the needed equalities yet:
2495  // this means that some inequalities from x actually holds
2496  // as "masked" equalities in the context of y.
2497  PPL_ASSERT(eqs.num_rows() <= z_cs_num_eq);
2498  PPL_ASSERT(num_non_redundant_eq <= needed_non_redundant_eq);
2499  PPL_ASSERT(z_cs_num_eq - eqs.num_rows()
2500  == needed_non_redundant_eq - num_non_redundant_eq);
2501  }
2502 
2503  // Identify non-redundant inequalities.
2504  // Avoid useless copies (no modifications are needed).
2505  std::vector<const Constraint*> non_redundant_ineq_p;
2506  // Fill non_redundant_ineq_p with (pointers to) inequalities
2507  // from y_cs ...
2508  for (dimension_type i = y_cs_num_eq; i < y_cs_num_rows; ++i) {
2509  non_redundant_ineq_p.push_back(&y_cs[i]);
2510  }
2511  // ... and (pointers to) non-redundant inequalities from x_cs.
2512  for (dimension_type i = x_cs_num_eq; i < x_cs_num_rows; ++i) {
2513  if (!redundant_by_y[i]) {
2514  non_redundant_ineq_p.push_back(&x_cs[i]);
2515  }
2516  }
2517  const dimension_type non_redundant_ineq_p_size
2518  = non_redundant_ineq_p.size();
2519  const dimension_type y_cs_num_ineq = y_cs_num_rows - y_cs_num_eq;
2520 
2521  // Compute saturation info.
2522  const dimension_type sat_num_rows = non_redundant_ineq_p_size;
2523  Bit_Matrix sat(sat_num_rows, z_gs_num_rows);
2524  for (dimension_type i = sat_num_rows; i-- > 0; ) {
2525  const Constraint& non_redundant_ineq_i = *(non_redundant_ineq_p[i]);
2526  Bit_Row& sat_i = sat[i];
2527  for (dimension_type j = z_gs_num_rows; j-- > 0; ) {
2528  if (Scalar_Products::sign(non_redundant_ineq_i, z_gs[j]) != 0) {
2529  sat_i.set(j);
2530  }
2531  }
2532  if (sat_i.empty() && num_non_redundant_eq < needed_non_redundant_eq) {
2533  // `non_redundant_ineq_i' is actually masking an equality
2534  // and we are still looking for some masked inequalities.
2535  // Iteration goes downwards, so the inequality comes from x_cs.
2536  PPL_ASSERT(i >= y_cs_num_ineq);
2537  // Check if the equality is independent in eqs.
2538  Constraint masked_eq = non_redundant_ineq_i;
2539  masked_eq.set_is_line_or_equality();
2540  masked_eq.sign_normalize();
2541  if (add_to_system_and_check_independence(eqs, masked_eq)) {
2542  // It is independent: add the _inequality_ to non_redundant_eq.
2543  non_redundant_eq.insert(non_redundant_ineq_i);
2544  ++num_non_redundant_eq;
2545  }
2546  }
2547  }
2548  // Here we have already found all the needed (masked) equalities.
2549  PPL_ASSERT(num_non_redundant_eq == needed_non_redundant_eq);
2550 
2551  drop_redundant_inequalities(non_redundant_ineq_p, x.topology(),
2552  sat, z_cs_num_eq);
2553 
2554  // Place the non-redundant (masked) equalities into result_cs.
2555  swap(result_cs, non_redundant_eq);
2556  // Add to result_cs the non-redundant inequalities from x_cs,
2557  // i.e., those having indices no smaller than y_cs_num_ineq.
2558  for (dimension_type i = y_cs_num_ineq;
2559  i < non_redundant_ineq_p_size;
2560  ++i) {
2561  if (non_redundant_ineq_p[i] != 0) {
2562  result_cs.insert(*non_redundant_ineq_p[i]);
2563  }
2564  }
2565  }
2566  }
2567 
2568  Polyhedron result_ph(x.topology(), x.space_dim, UNIVERSE);
2569  result_ph.add_recycled_constraints(result_cs);
2570  swap(x, result_ph);
2571  PPL_ASSERT_HEAVY(x.OK());
2572  return true;
2573 }
bool constraints_are_minimized() const
Returns true if the system of constraints is minimized.
Scalar product sign function object depending on topology.
bool is_tautological() const
Returns true if and only if *this is a tautology (i.e., an always true constraint).
Definition: Constraint.cc:105
A linear equality or inequality.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Type type() const
Returns the constraint type of *this.
Generator_System gen_sys
The system of generators.
A line, ray, point or closure point.
void add_constraints(const Constraint_System &cs)
Adds a copy of the constraints in cs to the MIP problem.
Definition: MIP_Problem.cc:184
bool generators_are_minimized() const
Returns true if the system of generators is minimized.
bool is_empty() const
Returns true if and only if *this is an empty polyhedron.
void insert(const Constraint &c)
Inserts in *this a copy of the constraint c, increasing the number of space dimensions if needed...
void set(unsigned long k)
Sets the bit in position k.
static bool add_to_system_and_check_independence(Linear_System1 &eq_sys, const Row2 &eq)
void swap(Polyhedron &x, Polyhedron &y)
Swaps x with y.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
A row in a matrix of bits.
void add_constraint(const Constraint &c)
Adds a copy of constraint c to the MIP problem.
Definition: MIP_Problem.cc:164
void add_recycled_constraints(Constraint_System &cs)
Adds the constraints in cs to the system of constraints of *this (without minimizing the result)...
A dimension of the vector space.
The base class for convex polyhedra.
bool is_inequality() const
Returns true if and only if *this is an inequality constraint (either strict or non-strict).
bool satisfied_by_all_generators(const Constraint &c) const
Returns true if all the generators satisfy c.
Topology topology() const
Returns the topological kind of the polyhedron.
Constraint_System con_sys
The system of constraints.
Type type() const
Returns the generator type of *this.
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
void throw_topology_incompatible(const char *method, const char *ph_name, const Polyhedron &ph) const
void optimal_value(Coefficient &numer, Coefficient &denom) const
Sets numer and denom so that is the solution of the optimization problem.
A Mixed Integer (linear) Programming problem.
bool empty() const
Returns true if no bit is set in the row.
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
Status status
The status flags to keep track of the polyhedron's internal state.
The universe element, i.e., the whole vector space.
void add_constraints(const Constraint_System &cs)
Adds a copy of the constraints in cs to the system of constraints of *this (without minimizing the re...
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.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
void set_is_line_or_equality()
Sets to LINE_OR_EQUALITY the kind of *this row.
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
const_iterator end() const
Returns the past-the-end const_iterator.
const_iterator begin() const
Returns the const_iterator pointing to the first generator, if *this is not empty; otherwise...
void set_objective_function(const Linear_Expression &obj)
Sets the objective function to obj.
Definition: MIP_Problem.cc:208
MIP_Problem_Status solve() const
Optimizes the MIP problem.
Definition: MIP_Problem.cc:293
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
static int sign(const Linear_Expression &x, const Linear_Expression &y)
Returns the sign of the scalar product between x and y.
bool has_pending_generators() const
Returns true if there are pending generators.
Coefficient c
Definition: PIP_Tree.cc:64
void add_space_dimensions_and_embed(dimension_type m)
Adds m new space dimensions and embeds the old MIP problem in the new vector space.
Definition: MIP_Problem.cc:374
expr_type expression() const
Partial read access to the (adapted) internal expression.
bool is_line() const
Returns true if and only if *this is a line.
void sign_normalize()
Normalizes the sign of the coefficients so that the first non-zero (homogeneous) coefficient of a lin...
Definition: Constraint.cc:252
void m_swap(Polyhedron &y)
Swaps *this with polyhedron y. (*this and y can be dimension-incompatible.)
bool le(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
void set_zero_dim_univ()
Sets status to express that the polyhedron is the universe 0-dimension vector space, clearing all corresponding matrices.
The problem has an optimal solution.
MIP_Problem_Status
Possible outcomes of the MIP_Problem solver.
bool has_something_pending() const
Returns true if there are either pending constraints or pending generators.
bool Parma_Polyhedra_Library::Polyhedron::strictly_contains ( const Polyhedron y) const
inline

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

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

Definition at line 436 of file Polyhedron_inlines.hh.

References contains().

436  {
437  const Polyhedron& x = *this;
438  return x.contains(y) && !y.contains(x);
439 }
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
bool Parma_Polyhedra_Library::Polyhedron::strongly_minimize_constraints ( ) const
private

Applies strong minimization to the constraints of an NNC polyhedron.

Returns
false if and only if *this turns out to be an empty polyhedron.

Definition at line 1148 of file Polyhedron_nonpublic.cc.

References Parma_Polyhedra_Library::MIP_Problem::add_constraints(), Parma_Polyhedra_Library::MIP_Problem::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Expression_Hide_Last< T >::all_homogeneous_terms_are_zero(), c, clear_generators_up_to_date(), Parma_Polyhedra_Library::Generator::CLOSURE_POINT, con_sys, Parma_Polyhedra_Library::Constraint::epsilon_coefficient(), Parma_Polyhedra_Library::Constraint::epsilon_leq_one(), Parma_Polyhedra_Library::Constraint::expression(), Parma_Polyhedra_Library::Expression_Adapter< T >::inhomogeneous_term(), Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::Generator::LINE, Parma_Polyhedra_Library::Constraint_System::mark_as_necessarily_closed(), Parma_Polyhedra_Library::Constraint_System::mark_as_not_necessarily_closed(), Parma_Polyhedra_Library::MAXIMIZATION, Parma_Polyhedra_Library::Constraint_System::num_pending_rows(), Parma_Polyhedra_Library::Constraint_System::num_rows(), Parma_Polyhedra_Library::Generator::POINT, Parma_Polyhedra_Library::Generator::RAY, Parma_Polyhedra_Library::Constraint_System::remove_row(), sat_g, Parma_Polyhedra_Library::Bit_Row::set(), Parma_Polyhedra_Library::MIP_Problem::set_objective_function(), Parma_Polyhedra_Library::MIP_Problem::set_optimization_mode(), Parma_Polyhedra_Library::MIP_Problem::solve(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), Parma_Polyhedra_Library::swap(), Parma_Polyhedra_Library::Bit_Matrix::transpose_assign(), Parma_Polyhedra_Library::UNBOUNDED_MIP_PROBLEM, Parma_Polyhedra_Library::UNFEASIBLE_MIP_PROBLEM, and Parma_Polyhedra_Library::Bit_Row::union_assign().

Referenced by select_H79_constraints().

1148  {
1149  PPL_ASSERT(!is_necessarily_closed());
1150 
1151  // From the user perspective, the polyhedron will not change.
1152  Polyhedron& x = const_cast<Polyhedron&>(*this);
1153 
1154  // We need `con_sys' (weakly) minimized and `gen_sys' up-to-date.
1155  // `minimize()' will process any pending constraints or generators.
1156  if (!minimize()) {
1157  return false;
1158  }
1159  // If the polyhedron `*this' is zero-dimensional
1160  // at this point it must be a universe polyhedron.
1161  if (x.space_dim == 0) {
1162  return true;
1163  }
1164  // We also need `sat_g' up-to-date.
1165  if (!sat_g_is_up_to_date()) {
1166  PPL_ASSERT(sat_c_is_up_to_date());
1167  x.sat_g.transpose_assign(sat_c);
1168  }
1169 
1170  // These Bit_Row's will be later used as masks in order to
1171  // check saturation conditions restricted to particular subsets of
1172  // the generator system.
1173  Bit_Row sat_all_but_rays;
1174  Bit_Row sat_all_but_points;
1175  Bit_Row sat_all_but_closure_points;
1176 
1177  const dimension_type gs_rows = gen_sys.num_rows();
1178  const dimension_type n_lines = gen_sys.num_lines();
1179  for (dimension_type i = gs_rows; i-- > n_lines; ) {
1180  switch (gen_sys[i].type()) {
1181  case Generator::RAY:
1182  sat_all_but_rays.set(i);
1183  break;
1184  case Generator::POINT:
1185  sat_all_but_points.set(i);
1186  break;
1188  sat_all_but_closure_points.set(i);
1189  break;
1190  case Generator::LINE:
1191  // Found a line with index i >= n_lines !
1192  PPL_UNREACHABLE;
1193  break;
1194  }
1195  }
1196  const Bit_Row
1197  sat_lines_and_rays(sat_all_but_points, sat_all_but_closure_points);
1198  const Bit_Row
1199  sat_lines_and_closure_points(sat_all_but_rays, sat_all_but_points);
1200  const Bit_Row
1201  sat_lines(sat_lines_and_rays, sat_lines_and_closure_points);
1202 
1203  // These flags are maintained to later decide if we have to add the
1204  // eps_leq_one constraint and whether or not the constraint system
1205  // was changed.
1206  bool changed = false;
1207  bool found_eps_leq_one = false;
1208 
1209  // For all the strict inequalities in `con_sys', check for
1210  // eps-redundancy and eventually move them to the bottom part of the
1211  // system.
1212  Constraint_System& cs = x.con_sys;
1213  Bit_Matrix& sat = x.sat_g;
1214  const Variable eps_var(cs.space_dimension());
1215  // Note that cs.num_rows() is *not* constant because the calls to
1216  // cs.remove_row() decrease it.
1217  for (dimension_type i = 0; i < cs.num_rows(); ) {
1218  if (cs[i].is_strict_inequality()) {
1219  // First, check if it is saturated by no closure points
1220  Bit_Row sat_ci;
1221  sat_ci.union_assign(sat[i], sat_lines_and_closure_points);
1222  if (sat_ci == sat_lines) {
1223  // It is saturated by no closure points.
1224  if (!found_eps_leq_one) {
1225  // Check if it is the eps_leq_one constraint.
1226  const Constraint& c = cs[i];
1227  if (c.expression().all_homogeneous_terms_are_zero()
1228  && (c.expression().inhomogeneous_term() + c.epsilon_coefficient() == 0)) {
1229  // We found the eps_leq_one constraint.
1230  found_eps_leq_one = true;
1231  // Consider next constraint.
1232  ++i;
1233  continue;
1234  }
1235  }
1236  // Here `cs[i]' is not the eps_leq_one constraint,
1237  // so it is eps-redundant.
1238  // Remove it, while keeping `sat_g' consistent.
1239  cs.remove_row(i, false);
1240  swap(sat[i], sat[cs.num_rows()]);
1241  // The constraint system is changed.
1242  changed = true;
1243  // Continue by considering next constraint,
1244  // which is already in place due to the swap.
1245  continue;
1246  }
1247  // Now we check if there exists another strict inequality
1248  // constraint having a superset of its saturators,
1249  // when disregarding points.
1250  sat_ci.union_assign(sat[i], sat_all_but_points);
1251  bool eps_redundant = false;
1252  for (dimension_type j = 0; j < cs.num_rows(); ++j) {
1253  if (i != j && cs[j].is_strict_inequality()
1254  && subset_or_equal(sat[j], sat_ci)) {
1255  // Constraint `cs[i]' is eps-redundant:
1256  // remove it, while keeping `sat_g' consistent.
1257  cs.remove_row(i, false);
1258  swap(sat[i], sat[cs.num_rows()]);
1259  eps_redundant = true;
1260  // The constraint system is changed.
1261  changed = true;
1262  break;
1263  }
1264  }
1265  // Continue with next constraint, which is already in place
1266  // due to the swap if we have found an eps-redundant constraint.
1267  if (!eps_redundant) {
1268  ++i;
1269  }
1270  }
1271  else {
1272  // `cs[i]' is not a strict inequality: consider next constraint.
1273  ++i;
1274  }
1275  }
1276 
1277  PPL_ASSERT(cs.num_pending_rows() == 0);
1278 
1279  if (changed) {
1280  // If the constraint system has been changed, we have erased
1281  // the epsilon-redundant constraints.
1282 
1283  // The generator system is no longer up-to-date.
1284  x.clear_generators_up_to_date();
1285 
1286  // If we haven't found an upper bound for the epsilon dimension,
1287  // then we have to check whether such an upper bound is implied
1288  // by the remaining constraints (exploiting the simplex algorithm).
1289  if (!found_eps_leq_one) {
1290  MIP_Problem lp;
1291  // KLUDGE: temporarily mark the constraint system as if it was
1292  // necessarily closed, so that we can interpret the epsilon
1293  // dimension as a standard dimension. Be careful to reset the
1294  // topology of `cs' even on exceptional execution path.
1295  cs.mark_as_necessarily_closed();
1296  try {
1297  lp.add_space_dimensions_and_embed(cs.space_dimension());
1298  lp.add_constraints(cs);
1299  cs.mark_as_not_necessarily_closed();
1300  }
1301  catch (...) {
1302  cs.mark_as_not_necessarily_closed();
1303  throw;
1304  }
1305  // The objective function is `epsilon'.
1306  lp.set_objective_function(Variable(x.space_dim));
1307  lp.set_optimization_mode(MAXIMIZATION);
1308  const MIP_Problem_Status status = lp.solve();
1309  PPL_ASSERT(status != UNFEASIBLE_MIP_PROBLEM);
1310  // If the epsilon dimension is actually unbounded,
1311  // then add the eps_leq_one constraint.
1312  if (status == UNBOUNDED_MIP_PROBLEM) {
1313  cs.insert(Constraint::epsilon_leq_one());
1314  }
1315  }
1316  }
1317 
1318  PPL_ASSERT_HEAVY(OK());
1319  return true;
1320 }
bool minimize() const
Applies (weak) minimization to both the constraints and generators.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
bool sat_c_is_up_to_date() const
Returns true if the saturation matrix sat_c is up-to-date.
void swap(Polyhedron &x, Polyhedron &y)
Swaps x with y.
bool sat_g_is_up_to_date() const
Returns true if the saturation matrix sat_g is up-to-date.
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
Status status
The status flags to keep track of the polyhedron's internal state.
Maximization is requested.
static const Constraint & epsilon_leq_one()
The zero-dimension space constraint (used to implement NNC polyhedra).
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
dimension_type num_lines() const
Returns the number of lines of the system.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
Coefficient c
Definition: PIP_Tree.cc:64
Bit_Matrix sat_c
The saturation matrix having constraints on its columns.
MIP_Problem_Status
Possible outcomes of the MIP_Problem solver.
bool Parma_Polyhedra_Library::Polyhedron::strongly_minimize_generators ( ) const
private

Applies strong minimization to the generators of an NNC polyhedron.

Returns
false if and only if *this turns out to be an empty polyhedron.

Definition at line 1323 of file Polyhedron_nonpublic.cc.

References clear_constraints_up_to_date(), Parma_Polyhedra_Library::Generator::epsilon_coefficient(), Parma_Polyhedra_Library::Generator::expr, Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Generator::is_point(), Parma_Polyhedra_Library::Generator_System::is_sorted(), Parma_Polyhedra_Library::Linear_Expression::normalize(), Parma_Polyhedra_Library::Generator_System::num_lines(), Parma_Polyhedra_Library::Generator_System::num_rows(), Parma_Polyhedra_Library::Generator::OK(), sat_c, Parma_Polyhedra_Library::Bit_Row::set(), Parma_Polyhedra_Library::Generator::set_epsilon_coefficient(), Parma_Polyhedra_Library::Generator_System::set_sorted(), space_dim, Parma_Polyhedra_Library::swap(), Parma_Polyhedra_Library::Generator_System::sys, and Parma_Polyhedra_Library::Bit_Matrix::transpose_assign().

1323  {
1324  PPL_ASSERT(!is_necessarily_closed());
1325 
1326  // From the user perspective, the polyhedron will not change.
1327  Polyhedron& x = const_cast<Polyhedron&>(*this);
1328 
1329  // We need `gen_sys' (weakly) minimized and `con_sys' up-to-date.
1330  // `minimize()' will process any pending constraints or generators.
1331  if (!minimize()) {
1332  return false;
1333  }
1334  // If the polyhedron `*this' is zero-dimensional
1335  // at this point it must be a universe polyhedron.
1336  if (x.space_dim == 0) {
1337  return true;
1338  }
1339 
1340  // We also need `sat_c' up-to-date.
1341  if (!sat_c_is_up_to_date()) {
1342  PPL_ASSERT(sat_g_is_up_to_date());
1343  x.sat_c.transpose_assign(sat_g);
1344  }
1345 
1346  // This Bit_Row will have all and only the indexes
1347  // of strict inequalities set to 1.
1348  Bit_Row sat_all_but_strict_ineq;
1349  const dimension_type cs_rows = con_sys.num_rows();
1350  const dimension_type n_equals = con_sys.num_equalities();
1351  for (dimension_type i = cs_rows; i-- > n_equals; ) {
1352  if (con_sys[i].is_strict_inequality()) {
1353  sat_all_but_strict_ineq.set(i);
1354  }
1355  }
1356 
1357  // Will record whether or not we changed the generator system.
1358  bool changed = false;
1359 
1360  // For all points in the generator system, check for eps-redundancy
1361  // and eventually move them to the bottom part of the system.
1362  Generator_System& gs = const_cast<Generator_System&>(gen_sys);
1363  Bit_Matrix& sat = const_cast<Bit_Matrix&>(sat_c);
1364  const dimension_type old_gs_rows = gs.num_rows();
1365  dimension_type gs_rows = old_gs_rows;
1366  const dimension_type n_lines = gs.num_lines();
1367  bool gs_sorted = gs.is_sorted();
1368 
1369  for (dimension_type i = n_lines; i < gs_rows; ) {
1370  Generator& g = gs.sys.rows[i];
1371  if (g.is_point()) {
1372  // Compute the Bit_Row corresponding to the candidate point
1373  // when strict inequality constraints are ignored.
1374  const Bit_Row sat_gs_i(sat[i], sat_all_but_strict_ineq);
1375  // Check if the candidate point is actually eps-redundant:
1376  // namely, if there exists another point that saturates
1377  // all the non-strict inequalities saturated by the candidate.
1378  bool eps_redundant = false;
1379  for (dimension_type j = n_lines; j < gs_rows; ++j) {
1380  const Generator& g2 = gs.sys.rows[j];
1381  if (i != j && g2.is_point() && subset_or_equal(sat[j], sat_gs_i)) {
1382  // Point `g' is eps-redundant:
1383  // move it to the bottom of the generator system,
1384  // while keeping `sat_c' consistent.
1385  --gs_rows;
1386  swap(g, gs.sys.rows[gs_rows]);
1387  swap(sat[i], sat[gs_rows]);
1388  eps_redundant = true;
1389  changed = true;
1390  break;
1391  }
1392  }
1393  if (!eps_redundant) {
1394  // Let all point encodings have epsilon coordinate 1.
1395  if (g.epsilon_coefficient() != g.expr.inhomogeneous_term()) {
1396  g.set_epsilon_coefficient(g.expr.inhomogeneous_term());
1397  // Enforce normalization.
1398  g.expr.normalize();
1399  PPL_ASSERT(g.OK());
1400  changed = true;
1401  }
1402  // Consider next generator.
1403  ++i;
1404  }
1405  }
1406  else {
1407  // Consider next generator.
1408  ++i;
1409  }
1410  }
1411 
1412  // If needed, erase the eps-redundant generators.
1413  if (gs_rows < old_gs_rows) {
1414  gs.sys.rows.resize(gs_rows);
1415  }
1416 
1417  if (changed) {
1418  // The generator system is no longer sorted.
1419  gs_sorted = false;
1420  // The constraint system is no longer up-to-date.
1421  x.clear_constraints_up_to_date();
1422  }
1423 
1424  gs.sys.index_first_pending = gs.num_rows();
1425  gs.set_sorted(gs_sorted);
1426 
1427  PPL_ASSERT(gs.sys.OK());
1428 
1429  PPL_ASSERT_HEAVY(OK());
1430  return true;
1431 }
bool minimize() const
Applies (weak) minimization to both the constraints and generators.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
bool sat_c_is_up_to_date() const
Returns true if the saturation matrix sat_c is up-to-date.
void swap(Polyhedron &x, Polyhedron &y)
Swaps x with y.
bool sat_g_is_up_to_date() const
Returns true if the saturation matrix sat_g is up-to-date.
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
Constraint_System con_sys
The system of constraints.
dimension_type num_equalities() const
Returns the number of equality constraints.
Bit_Matrix sat_g
The saturation matrix having generators on its columns.
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
Bit_Matrix sat_c
The saturation matrix having constraints on its columns.
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible ( const char *  method,
const char *  other_name,
dimension_type  other_dim 
) const
protected

Definition at line 2609 of file Polyhedron_nonpublic.cc.

Referenced by affine_form_image(), H79_widening_assign(), refine_with_linear_form_inequality(), and throw_dimension_incompatible().

2611  {
2612  std::ostringstream s;
2613  s << "PPL::"
2614  << (is_necessarily_closed() ? "C_" : "NNC_")
2615  << "Polyhedron::" << method << ":\n"
2616  << "this->space_dimension() == " << space_dimension() << ", "
2617  << other_name << ".space_dimension() == " << other_dim << ".";
2618  throw std::invalid_argument(s.str());
2619 }
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible ( const char *  method,
const char *  ph_name,
const Polyhedron ph 
) const
protected

Definition at line 2622 of file Polyhedron_nonpublic.cc.

References space_dimension().

2624  {
2625  throw_dimension_incompatible(method, ph_name, ph.space_dimension());
2626 }
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible ( const char *  method,
const char *  le_name,
const Linear_Expression le 
) const
protected

Definition at line 2630 of file Polyhedron_nonpublic.cc.

References Parma_Polyhedra_Library::Linear_Expression::space_dimension().

2632  {
2633  throw_dimension_incompatible(method, le_name, le.space_dimension());
2634 }
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
bool le(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible ( const char *  method,
const char *  c_name,
const Constraint c 
) const
protected

Definition at line 2637 of file Polyhedron_nonpublic.cc.

References Parma_Polyhedra_Library::Constraint::space_dimension().

2639  {
2640  throw_dimension_incompatible(method, c_name, c.space_dimension());
2641 }
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
Coefficient c
Definition: PIP_Tree.cc:64
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible ( const char *  method,
const char *  g_name,
const Generator g 
) const
protected

Definition at line 2644 of file Polyhedron_nonpublic.cc.

References Parma_Polyhedra_Library::Generator::space_dimension().

2646  {
2647  throw_dimension_incompatible(method, g_name, g.space_dimension());
2648 }
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible ( const char *  method,
const char *  cg_name,
const Congruence cg 
) const
protected

Definition at line 2651 of file Polyhedron_nonpublic.cc.

References Parma_Polyhedra_Library::Congruence::space_dimension().

2653  {
2654  throw_dimension_incompatible(method, cg_name, cg.space_dimension());
2655 }
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible ( const char *  method,
const char *  cs_name,
const Constraint_System cs 
) const
protected

Definition at line 2658 of file Polyhedron_nonpublic.cc.

References Parma_Polyhedra_Library::Constraint_System::space_dimension().

2660  {
2661  throw_dimension_incompatible(method, cs_name, cs.space_dimension());
2662 }
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible ( const char *  method,
const char *  gs_name,
const Generator_System gs 
) const
protected

Definition at line 2666 of file Polyhedron_nonpublic.cc.

References Parma_Polyhedra_Library::Generator_System::space_dimension().

2668  {
2669  throw_dimension_incompatible(method, gs_name, gs.space_dimension());
2670 }
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible ( const char *  method,
const char *  cgs_name,
const Congruence_System cgs 
) const
protected

Definition at line 2674 of file Polyhedron_nonpublic.cc.

References Parma_Polyhedra_Library::Congruence_System::space_dimension().

2676  {
2677  throw_dimension_incompatible(method, cgs_name, cgs.space_dimension());
2678 }
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
template<typename C >
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible ( const char *  method,
const char *  lf_name,
const Linear_Form< C > &  lf 
) const
protected

Definition at line 591 of file Polyhedron_templates.hh.

References Parma_Polyhedra_Library::Linear_Form< C >::space_dimension(), and throw_dimension_incompatible().

593  {
594  throw_dimension_incompatible(method, lf_name, lf.space_dimension());
595 }
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible ( const char *  method,
const char *  var_name,
Variable  var 
) const
protected

Definition at line 2681 of file Polyhedron_nonpublic.cc.

References Parma_Polyhedra_Library::Variable::space_dimension().

2683  {
2684  std::ostringstream s;
2685  s << "PPL::";
2686  if (is_necessarily_closed()) {
2687  s << "C_";
2688  }
2689  else {
2690  s << "NNC_";
2691  }
2692  s << "Polyhedron::" << method << ":" << std::endl
2693  << "this->space_dimension() == " << space_dimension() << ", "
2694  << var_name << ".space_dimension() == " << var.space_dimension() << ".";
2695  throw std::invalid_argument(s.str());
2696 }
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible ( const char *  method,
dimension_type  required_space_dim 
) const
protected

Definition at line 2700 of file Polyhedron_nonpublic.cc.

2701  {
2702  std::ostringstream s;
2703  s << "PPL::";
2704  if (is_necessarily_closed()) {
2705  s << "C_";
2706  }
2707  else {
2708  s << "NNC_";
2709  }
2710  s << "Polyhedron::" << method << ":" << std::endl
2711  << "this->space_dimension() == " << space_dimension()
2712  << ", required space dimension == " << required_space_dim << ".";
2713  throw std::invalid_argument(s.str());
2714 }
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void Parma_Polyhedra_Library::Polyhedron::throw_invalid_argument ( const char *  method,
const char *  reason 
) const
protected

Definition at line 2526 of file Polyhedron_nonpublic.cc.

Referenced by map_space_dimensions().

2527  {
2528  std::ostringstream s;
2529  s << "PPL::";
2530  if (is_necessarily_closed()) {
2531  s << "C_";
2532  }
2533  else {
2534  s << "NNC_";
2535  }
2536  s << "Polyhedron::" << method << ":" << std::endl
2537  << reason << ".";
2538  throw std::invalid_argument(s.str());
2539 }
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
void Parma_Polyhedra_Library::Polyhedron::throw_invalid_generator ( const char *  method,
const char *  g_name 
) const
protected

Definition at line 2737 of file Polyhedron_nonpublic.cc.

2738  {
2739  std::ostringstream s;
2740  s << "PPL::";
2741  if (is_necessarily_closed()) {
2742  s << "C_";
2743  }
2744  else {
2745  s << "NNC_";
2746  }
2747  s << "Polyhedron::" << method << ":" << std::endl
2748  << "*this is an empty polyhedron and "
2749  << g_name << " is not a point.";
2750  throw std::invalid_argument(s.str());
2751 }
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
void Parma_Polyhedra_Library::Polyhedron::throw_invalid_generators ( const char *  method,
const char *  gs_name 
) const
protected

Definition at line 2754 of file Polyhedron_nonpublic.cc.

Referenced by Polyhedron().

2755  {
2756  std::ostringstream s;
2757  s << "PPL::";
2758  if (is_necessarily_closed()) {
2759  s << "C_";
2760  }
2761  else {
2762  s << "NNC_";
2763  }
2764  s << "Polyhedron::" << method << ":" << std::endl
2765  << "*this is an empty polyhedron and" << std::endl
2766  << "the non-empty generator system " << gs_name << " contains no points.";
2767  throw std::invalid_argument(s.str());
2768 }
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
void Parma_Polyhedra_Library::Polyhedron::throw_topology_incompatible ( const char *  method,
const char *  ph_name,
const Polyhedron ph 
) const
protected

Definition at line 2542 of file Polyhedron_nonpublic.cc.

References is_necessarily_closed().

Referenced by H79_widening_assign(), m_swap(), and Polyhedron().

2544  {
2545  std::ostringstream s;
2546  s << "PPL::";
2547  if (is_necessarily_closed()) {
2548  s << "C_";
2549  }
2550  else {
2551  s << "NNC_";
2552  }
2553  s << "Polyhedron::" << method << ":" << std::endl
2554  << ph_name << " is a ";
2555  if (ph.is_necessarily_closed()) {
2556  s << "C_";
2557  }
2558  else {
2559  s << "NNC_";
2560  }
2561  s << "Polyhedron." << std::endl;
2562  throw std::invalid_argument(s.str());
2563 }
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
void Parma_Polyhedra_Library::Polyhedron::throw_topology_incompatible ( const char *  method,
const char *  c_name,
const Constraint c 
) const
protected

Definition at line 2566 of file Polyhedron_nonpublic.cc.

2568  {
2569  PPL_ASSERT(is_necessarily_closed());
2570  std::ostringstream s;
2571  s << "PPL::C_Polyhedron::" << method << ":" << std::endl
2572  << c_name << " is a strict inequality.";
2573  throw std::invalid_argument(s.str());
2574 }
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
void Parma_Polyhedra_Library::Polyhedron::throw_topology_incompatible ( const char *  method,
const char *  g_name,
const Generator g 
) const
protected

Definition at line 2577 of file Polyhedron_nonpublic.cc.

2579  {
2580  PPL_ASSERT(is_necessarily_closed());
2581  std::ostringstream s;
2582  s << "PPL::C_Polyhedron::" << method << ":" << std::endl
2583  << g_name << " is a closure point.";
2584  throw std::invalid_argument(s.str());
2585 }
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
void Parma_Polyhedra_Library::Polyhedron::throw_topology_incompatible ( const char *  method,
const char *  cs_name,
const Constraint_System cs 
) const
protected

Definition at line 2588 of file Polyhedron_nonpublic.cc.

2590  {
2591  PPL_ASSERT(is_necessarily_closed());
2592  std::ostringstream s;
2593  s << "PPL::C_Polyhedron::" << method << ":" << std::endl
2594  << cs_name << " contains strict inequalities.";
2595  throw std::invalid_argument(s.str());
2596 }
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
void Parma_Polyhedra_Library::Polyhedron::throw_topology_incompatible ( const char *  method,
const char *  gs_name,
const Generator_System gs 
) const
protected

Definition at line 2599 of file Polyhedron_nonpublic.cc.

2601  {
2602  std::ostringstream s;
2603  s << "PPL::C_Polyhedron::" << method << ":" << std::endl
2604  << gs_name << " contains closure points.";
2605  throw std::invalid_argument(s.str());
2606 }
void Parma_Polyhedra_Library::Polyhedron::time_elapse_assign ( const Polyhedron y)

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

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

Definition at line 3603 of file Polyhedron_public.cc.

References Parma_Polyhedra_Library::Expression_Hide_Last< T >::all_homogeneous_terms_are_zero(), Parma_Polyhedra_Library::Linear_Expression::all_homogeneous_terms_are_zero(), can_have_something_pending(), clear_constraints_up_to_date(), clear_generators_minimized(), Parma_Polyhedra_Library::Generator::CLOSURE_POINT, Parma_Polyhedra_Library::Generator::expr, Parma_Polyhedra_Library::Generator::expression(), gen_sys, generators_are_up_to_date(), has_pending_constraints(), Parma_Polyhedra_Library::Generator_System::insert_pending(), is_necessarily_closed(), Parma_Polyhedra_Library::Generator_System::is_sorted(), Parma_Polyhedra_Library::Generator::LINE, marked_empty(), Parma_Polyhedra_Library::Generator_System::merge_rows_assign(), Parma_Polyhedra_Library::Linear_Expression::normalize(), Parma_Polyhedra_Library::Generator_System::num_rows(), Parma_Polyhedra_Library::Generator::OK(), OK(), Parma_Polyhedra_Library::Generator::POINT, process_pending_constraints(), Parma_Polyhedra_Library::Generator::RAY, set_empty(), set_generators_pending(), Parma_Polyhedra_Library::Linear_Expression::set_inhomogeneous_term(), Parma_Polyhedra_Library::Generator_System::sort_rows(), space_dim, Parma_Polyhedra_Library::swap(), Parma_Polyhedra_Library::Generator_System::sys, topology(), Parma_Polyhedra_Library::Generator::type(), Parma_Polyhedra_Library::Generator_System::unset_pending_rows(), and update_generators().

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

3603  {
3604  Polyhedron& x = *this;
3605  // Topology compatibility check.
3606  if (x.topology() != y.topology()) {
3607  throw_topology_incompatible("time_elapse_assign(y)", "y", y);
3608  }
3609  // Dimension-compatibility checks.
3610  if (x.space_dim != y.space_dim) {
3611  throw_dimension_incompatible("time_elapse_assign(y)", "y", y);
3612  }
3613 
3614  // Dealing with the zero-dimensional case.
3615  if (x.space_dim == 0) {
3616  if (y.marked_empty()) {
3617  x.set_empty();
3618  }
3619  return;
3620  }
3621 
3622  // If either one of `x' or `y' is empty, the result is empty too.
3623  if (x.marked_empty() || y.marked_empty()
3627  || (!y.generators_are_up_to_date() && !y.update_generators())) {
3628  x.set_empty();
3629  return;
3630  }
3631 
3632  // At this point both generator systems are up-to-date,
3633  // possibly containing pending generators.
3634  Generator_System gs = y.gen_sys;
3635  const dimension_type old_gs_num_rows = gs.num_rows();
3636  dimension_type gs_num_rows = old_gs_num_rows;
3637 
3638  if (!x.is_necessarily_closed()) {
3639  // `x' and `y' are NNC polyhedra.
3640  for (dimension_type i = gs_num_rows; i-- > 0; ) {
3641  Generator& g = gs.sys.rows[i];
3642  switch (g.type()) {
3643  case Generator::POINT:
3644  // The points of `gs' can be erased,
3645  // since their role can be played by closure points.
3646  --gs_num_rows;
3647  swap(g, gs.sys.rows[gs_num_rows]);
3648  break;
3650  {
3651  // If it is the origin, erase it.
3653  --gs_num_rows;
3654  swap(g, gs.sys.rows[gs_num_rows]);
3655  }
3656  // Otherwise, transform the closure point into a ray.
3657  else {
3659  // Enforce normalization.
3660  g.expr.normalize();
3661  PPL_ASSERT(g.OK());
3662  }
3663  }
3664  break;
3665  case Generator::RAY:
3666  case Generator::LINE:
3667  // For rays and lines, nothing to be done.
3668  break;
3669  }
3670  }
3671  }
3672  else {
3673  // `x' and `y' are C polyhedra.
3674  for (dimension_type i = gs_num_rows; i-- > 0; ) {
3675  // For rays and lines, nothing to be done.
3676  if (gs[i].is_point()) {
3677  Generator& p = gs.sys.rows[i];
3678  // If it is the origin, erase it.
3680  --gs_num_rows;
3681  swap(p, gs.sys.rows[gs_num_rows]);
3682  }
3683  // Otherwise, transform the point into a ray.
3684  else {
3686  // Enforce normalization.
3687  p.expr.normalize();
3688  PPL_ASSERT(p.OK());
3689  }
3690  }
3691  }
3692  }
3693  // If it was present, erase the origin point or closure point,
3694  // which cannot be transformed into a valid ray or line.
3695  // For NNC polyhedra, also erase all the points of `gs',
3696  // whose role can be played by the closure points.
3697  // These have been previously moved to the end of `gs'.
3698  gs.sys.rows.resize(gs_num_rows);
3699 
3700  gs.unset_pending_rows();
3701  PPL_ASSERT(gs.sys.OK());
3702 
3703  // `gs' may now have no rows.
3704  // Namely, this happens when `y' was the singleton polyhedron
3705  // having the origin as the one and only point.
3706  // In such a case, the resulting polyhedron is equal to `x'.
3707  if (gs_num_rows == 0) {
3708  return;
3709  }
3710  // If the polyhedron can have something pending, we add `gs'
3711  // to `gen_sys' as pending rows
3712  if (x.can_have_something_pending()) {
3713  x.gen_sys.insert_pending(gs);
3715  }
3716  // Otherwise, the two systems are merged.
3717  // `Linear_System::merge_rows_assign()' requires both systems to be sorted.
3718  else {
3719  if (!x.gen_sys.is_sorted()) {
3720  x.gen_sys.sort_rows();
3721  }
3722  gs.sort_rows();
3723  x.gen_sys.merge_rows_assign(gs);
3724  // Only the system of generators is up-to-date.
3727  }
3728  PPL_ASSERT_HEAVY(x.OK(true) && y.OK(true));
3729 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
void merge_rows_assign(const Generator_System &y)
Assigns to *this the result of merging its rows with those of y, obtaining a sorted system...
void clear_constraints_up_to_date()
Sets status to express that constraints are no longer up-to-date.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
A line, ray, point or closure point.
Linear_Expression expr
The linear expression encoding *this.
bool update_generators() const
Updates generators starting from constraints and minimizes them.
expr_type expression() const
Partial read access to the (adapted) internal expression.
void swap(Polyhedron &x, Polyhedron &y)
Swaps x with y.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
void set_inhomogeneous_term(Coefficient_traits::const_reference n)
Sets the inhomogeneous term of *this to n.
bool is_sorted() const
Returns the value of the sortedness flag.
bool can_have_something_pending() const
Returns true if the polyhedron can have something pending.
The base class for convex polyhedra.
Topology topology() const
Returns the topological kind of the polyhedron.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
Type type() const
Returns the generator type of *this.
bool OK() const
Checks if all the invariants are satisfied.
Definition: Generator.cc:432
void throw_topology_incompatible(const char *method, const char *ph_name, const Polyhedron &ph) const
void insert_pending(const Generator_System &r)
Adds a copy of the rows of `y' to the pending part of `*this'.
bool all_homogeneous_terms_are_zero() const
Returns true if and only if all the homogeneous terms of *this are .
bool all_homogeneous_terms_are_zero() const
Returns true if and only if all the homogeneous terms of *this are zero.
void sort_rows()
Sorts the non-pending rows (in growing order) and eliminates duplicated ones.
void set_empty()
Sets status to express that the polyhedron is empty, clearing all corresponding matrices.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
bool process_pending_constraints() const
Processes the pending constraints and obtains a minimized polyhedron.
void set_generators_pending()
Sets status to express that generators are pending.
void unset_pending_rows()
Sets the index to indicate that the system has no pending rows.
void clear_generators_minimized()
Sets status to express that generators are no longer minimized.
void Parma_Polyhedra_Library::Polyhedron::topological_closure_assign ( )

Assigns to *this its topological closure.

Definition at line 3817 of file Polyhedron_public.cc.

References c, Parma_Polyhedra_Library::Constraint::epsilon_coefficient(), Parma_Polyhedra_Library::Constraint::epsilon_leq_one(), Parma_Polyhedra_Library::Constraint::expr, Parma_Polyhedra_Library::Constraint::is_tautological(), Parma_Polyhedra_Library::Linear_Expression::normalize(), Parma_Polyhedra_Library::Constraint::OK(), and Parma_Polyhedra_Library::Constraint::set_epsilon_coefficient().

3817  {
3818  // Necessarily closed polyhedra are trivially closed.
3819  if (is_necessarily_closed()) {
3820  return;
3821  }
3822  // Any empty or zero-dimensional polyhedron is closed.
3823  if (marked_empty() || space_dim == 0) {
3824  return;
3825  }
3826 
3827  // The computation can be done using constraints or generators.
3828  // If we use constraints, we will change them, so that having pending
3829  // constraints would be useless. If we use generators, we add generators,
3830  // so that having pending generators still makes sense.
3831 
3832  // Process any pending constraints.
3834  return;
3835  }
3836 
3837  // Use constraints only if they are available and
3838  // there are no pending generators.
3840  bool changed = false;
3841 
3842  // Transform all strict inequalities into non-strict ones.
3843  for (dimension_type i = con_sys.num_rows(); i-- > 0; ) {
3844  Constraint& c = con_sys.sys.rows[i];
3845  if (c.epsilon_coefficient() < 0 && !c.is_tautological()) {
3847  // Enforce normalization.
3848  c.expr.normalize();
3849  PPL_ASSERT(c.OK());
3850  changed = true;
3851  }
3852  }
3853 
3854  PPL_ASSERT(con_sys.sys.OK());
3855 
3856  if (changed) {
3858  con_sys.set_sorted(false);
3859  // After changing the system of constraints, the generators
3860  // are no longer up-to-date and the constraints are no longer
3861  // minimized.
3864  }
3865  }
3866  else {
3867  // Here we use generators, possibly keeping constraints.
3868  PPL_ASSERT(generators_are_up_to_date());
3869  // Add the corresponding point to each closure point.
3873  }
3874  else {
3875  // We cannot have pending generators; this also implies
3876  // that generators may have lost their sortedness.
3878  gen_sys.set_sorted(false);
3879  // Constraints are not up-to-date and generators are not minimized.
3882  }
3883  }
3884  PPL_ASSERT_HEAVY(OK());
3885 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
bool is_tautological() const
Returns true if and only if *this is a tautology (i.e., an always true constraint).
Definition: Constraint.cc:105
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
A linear equality or inequality.
void clear_constraints_up_to_date()
Sets status to express that constraints are no longer up-to-date.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
void insert(const Constraint &c)
Inserts in *this a copy of the constraint c, increasing the number of space dimensions if needed...
bool can_have_something_pending() const
Returns true if the polyhedron can have something pending.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
Constraint_System con_sys
The system of constraints.
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
void set_epsilon_coefficient(Coefficient_traits::const_reference n)
Sets the epsilon coefficient to n. The constraint must be NNC.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
void set_sorted(bool b)
Sets the sortedness flag of the system to b.
static const Constraint & epsilon_leq_one()
The zero-dimension space constraint (used to implement NNC polyhedra).
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
Coefficient_traits::const_reference epsilon_coefficient() const
Returns the epsilon coefficient. The constraint must be NNC.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
bool process_pending_constraints() const
Processes the pending constraints and obtains a minimized polyhedron.
void clear_constraints_minimized()
Sets status to express that constraints are no longer minimized.
bool OK() const
Checks if all the invariants are satisfied.
Definition: Constraint.cc:467
bool has_pending_generators() const
Returns true if there are pending generators.
void set_sorted(bool b)
Sets the sortedness flag of the system to b.
Coefficient c
Definition: PIP_Tree.cc:64
void set_generators_pending()
Sets status to express that generators are pending.
void add_corresponding_points()
For each unmatched closure point in *this, adds the corresponding point.
void clear_generators_up_to_date()
Sets status to express that generators are no longer up-to-date.
void unset_pending_rows()
Sets the index to indicate that the system has no pending rows.
void clear_generators_minimized()
Sets status to express that generators are no longer minimized.
memory_size_type Parma_Polyhedra_Library::Polyhedron::total_memory_in_bytes ( ) const
inline

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

Definition at line 35 of file Polyhedron_inlines.hh.

References external_memory_in_bytes().

35  {
36  return sizeof(*this) + external_memory_in_bytes();
37 }
memory_size_type external_memory_in_bytes() const
Returns the size in bytes of the memory managed by *this.
void Parma_Polyhedra_Library::Polyhedron::unconstrain ( Variable  var)

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

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

Definition at line 1910 of file Polyhedron_public.cc.

References Parma_Polyhedra_Library::Generator::line(), and Parma_Polyhedra_Library::Variable::space_dimension().

1910  {
1911  // Dimension-compatibility check.
1912  if (space_dim < var.space_dimension()) {
1913  throw_dimension_incompatible("unconstrain(var)", var.space_dimension());
1914  }
1915  // Do something only if the polyhedron is non-empty.
1916  if (marked_empty()
1919  // Empty: do nothing.
1920  return;
1921  }
1922 
1923  PPL_ASSERT(generators_are_up_to_date());
1924  // Since `gen_sys' is not empty, the topology and space dimension
1925  // of the inserted generator are automatically adjusted.
1929  }
1930  else {
1932  // After adding the new generator,
1933  // constraints are no longer up-to-date.
1936  }
1937  PPL_ASSERT_HEAVY(OK(true));
1938 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
void clear_constraints_up_to_date()
Sets status to express that constraints are no longer up-to-date.
Generator_System gen_sys
The system of generators.
bool update_generators() const
Updates generators starting from constraints and minimizes them.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
static Generator line(const Linear_Expression &e, Representation r=default_representation)
Returns the line of direction e.
Definition: Generator.cc:143
bool can_have_something_pending() const
Returns true if the polyhedron can have something pending.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
void insert_pending(const Generator_System &r)
Adds a copy of the rows of `y' to the pending part of `*this'.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
bool process_pending_constraints() const
Processes the pending constraints and obtains a minimized polyhedron.
void set_generators_pending()
Sets status to express that generators are pending.
void insert(const Generator &g)
Inserts in *this a copy of the generator g, increasing the number of space dimensions if needed...
void clear_generators_minimized()
Sets status to express that generators are no longer minimized.
void Parma_Polyhedra_Library::Polyhedron::unconstrain ( const Variables_Set vars)

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

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

Definition at line 1941 of file Polyhedron_public.cc.

References Parma_Polyhedra_Library::Generator::line(), and Parma_Polyhedra_Library::Variables_Set::space_dimension().

1941  {
1942  // The cylindrification with respect to no dimensions is a no-op.
1943  // This case also captures the only legal cylindrification
1944  // of a polyhedron in a 0-dim space.
1945  if (vars.empty()) {
1946  return;
1947  }
1948  // Dimension-compatibility check.
1949  const dimension_type min_space_dim = vars.space_dimension();
1950  if (space_dim < min_space_dim) {
1951  throw_dimension_incompatible("unconstrain(vs)", min_space_dim);
1952  }
1953 
1954  // Do something only if the polyhedron is non-empty.
1955  if (marked_empty()
1958  // Empty: do nothing.
1959  return;
1960  }
1961 
1962  PPL_ASSERT(generators_are_up_to_date());
1963  // Since `gen_sys' is not empty, the topology and space dimension
1964  // of the inserted generators are automatically adjusted.
1965  Variables_Set::const_iterator vsi = vars.begin();
1966  Variables_Set::const_iterator vsi_end = vars.end();
1968  for ( ; vsi != vsi_end; ++vsi) {
1970  }
1972  }
1973  else {
1974  for ( ; vsi != vsi_end; ++vsi) {
1976  }
1977  // After adding the new generators,
1978  // constraints are no longer up-to-date.
1981  }
1982  PPL_ASSERT_HEAVY(OK(true));
1983 }
bool has_pending_constraints() const
Returns true if there are pending constraints.
dimension_type space_dimension() const
Returns the dimension of the smallest vector space enclosing all the variables whose indexes are in t...
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
void clear_constraints_up_to_date()
Sets status to express that constraints are no longer up-to-date.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
bool update_generators() const
Updates generators starting from constraints and minimizes them.
void throw_dimension_incompatible(const char *method, const char *other_name, dimension_type other_dim) const
static Generator line(const Linear_Expression &e, Representation r=default_representation)
Returns the line of direction e.
Definition: Generator.cc:143
bool can_have_something_pending() const
Returns true if the polyhedron can have something pending.
A dimension of the vector space.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
void insert_pending(const Generator_System &r)
Adds a copy of the rows of `y' to the pending part of `*this'.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
bool process_pending_constraints() const
Processes the pending constraints and obtains a minimized polyhedron.
void set_generators_pending()
Sets status to express that generators are pending.
void insert(const Generator &g)
Inserts in *this a copy of the generator g, increasing the number of space dimensions if needed...
void clear_generators_minimized()
Sets status to express that generators are no longer minimized.
void Parma_Polyhedra_Library::Polyhedron::update_constraints ( ) const
private

Updates constraints starting from generators and minimizes them.

The resulting system of constraints is only partially sorted: the equalities are in the upper part of the matrix, while the inequalities in the lower part.

Definition at line 859 of file Polyhedron_nonpublic.cc.

References clear_sat_g_up_to_date(), con_sys, gen_sys, sat_c, set_constraints_minimized(), set_generators_minimized(), and set_sat_c_up_to_date().

Referenced by H79_widening_assign(), intersection_assign(), and is_included_in().

859  {
860  PPL_ASSERT(space_dim > 0);
861  PPL_ASSERT(!marked_empty());
862  PPL_ASSERT(generators_are_up_to_date());
863  // We assume the polyhedron has no pending constraints or generators.
864  PPL_ASSERT(!has_something_pending());
865 
866  Polyhedron& x = const_cast<Polyhedron&>(*this);
867  minimize(false, x.gen_sys, x.con_sys, x.sat_c);
868  // `sat_c' is the only saturation matrix up-to-date.
869  x.set_sat_c_up_to_date();
870  x.clear_sat_g_up_to_date();
871  // The system of constraints and the system of generators
872  // are minimized.
873  x.set_constraints_minimized();
874  x.set_generators_minimized();
875 }
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
bool minimize() const
Applies (weak) minimization to both the constraints and generators.
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool has_something_pending() const
Returns true if there are either pending constraints or pending generators.
bool Parma_Polyhedra_Library::Polyhedron::update_generators ( ) const
private

Updates generators starting from constraints and minimizes them.

Returns
false if and only if *this turns out to be an empty polyhedron.

The resulting system of generators is only partially sorted: the lines are in the upper part of the matrix, while rays and points are in the lower part. It is illegal to call this method when the Status field already declares the polyhedron to be empty.

Definition at line 878 of file Polyhedron_nonpublic.cc.

References clear_sat_c_up_to_date(), con_sys, Parma_Polyhedra_Library::Implementation::BD_Shapes::empty, gen_sys, sat_g, set_constraints_minimized(), set_empty(), set_generators_minimized(), and set_sat_g_up_to_date().

Referenced by limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), map_space_dimensions(), poly_hull_assign(), positive_time_elapse_assign_impl(), select_H79_constraints(), and time_elapse_assign().

878  {
879  PPL_ASSERT(space_dim > 0);
880  PPL_ASSERT(!marked_empty());
881  PPL_ASSERT(constraints_are_up_to_date());
882  // We assume the polyhedron has no pending constraints or generators.
883  PPL_ASSERT(!has_something_pending());
884 
885  Polyhedron& x = const_cast<Polyhedron&>(*this);
886  // If the system of constraints is not consistent the
887  // polyhedron is empty.
888  const bool empty = minimize(true, x.con_sys, x.gen_sys, x.sat_g);
889  if (empty) {
890  x.set_empty();
891  }
892  else {
893  // `sat_g' is the only saturation matrix up-to-date.
894  x.set_sat_g_up_to_date();
895  x.clear_sat_c_up_to_date();
896  // The system of constraints and the system of generators
897  // are minimized.
898  x.set_constraints_minimized();
899  x.set_generators_minimized();
900  }
901  return !empty;
902 }
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
bool minimize() const
Applies (weak) minimization to both the constraints and generators.
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool has_something_pending() const
Returns true if there are either pending constraints or pending generators.
void Parma_Polyhedra_Library::Polyhedron::update_sat_c ( ) const
private

Updates sat_c using the updated constraints and generators.

It is assumed that constraints and generators are up-to-date and minimized and that the Status field does not already flag sat_c to be up-to-date. The values of the saturation matrix are computed as follows:

\[ \begin{cases} sat\_c[i][j] = 0, \quad \text{if } G[i] \cdot C^\mathrm{T}[j] = 0; \\ sat\_c[i][j] = 1, \quad \text{if } G[i] \cdot C^\mathrm{T}[j] > 0. \end{cases} \]

Definition at line 905 of file Polyhedron_nonpublic.cc.

References Parma_Polyhedra_Library::Bit_Matrix::clear(), Parma_Polyhedra_Library::Bit_Matrix::resize(), sat_c, set_sat_c_up_to_date(), and Parma_Polyhedra_Library::Scalar_Products::sign().

Referenced by add_space_dimensions_and_embed(), and obtain_sorted_constraints_with_sat_c().

905  {
906  PPL_ASSERT(constraints_are_minimized());
907  PPL_ASSERT(generators_are_minimized());
908  PPL_ASSERT(!sat_c_is_up_to_date());
909 
910  // We only consider non-pending rows.
913  Polyhedron& x = const_cast<Polyhedron&>(*this);
914 
915  // The columns of `sat_c' represent the constraints and
916  // its rows represent the generators: resize accordingly.
917  x.sat_c.resize(gsr, csr);
918  for (dimension_type i = gsr; i-- > 0; ) {
919  for (dimension_type j = csr; j-- > 0; ) {
920  const int sp_sign = Scalar_Products::sign(con_sys[j], gen_sys[i]);
921  // The negativity of this scalar product would mean
922  // that the generator `gen_sys[i]' violates the constraint
923  // `con_sys[j]' and it is not possible because both generators
924  // and constraints are up-to-date.
925  PPL_ASSERT(sp_sign >= 0);
926  if (sp_sign > 0) {
927  // `gen_sys[i]' satisfies (without saturate) `con_sys[j]'.
928  x.sat_c[i].set(j);
929  }
930  else {
931  // `gen_sys[i]' saturates `con_sys[j]'.
932  x.sat_c[i].clear(j);
933  }
934  }
935  }
936  x.set_sat_c_up_to_date();
937 }
bool constraints_are_minimized() const
Returns true if the system of constraints is minimized.
dimension_type first_pending_row() const
Returns the index of the first pending row.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
bool generators_are_minimized() const
Returns true if the system of generators is minimized.
dimension_type first_pending_row() const
Returns the index of the first pending row.
bool sat_c_is_up_to_date() const
Returns true if the saturation matrix sat_c is up-to-date.
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
Constraint_System con_sys
The system of constraints.
static int sign(const Linear_Expression &x, const Linear_Expression &y)
Returns the sign of the scalar product between x and y.
void Parma_Polyhedra_Library::Polyhedron::update_sat_g ( ) const
private

Updates sat_g using the updated constraints and generators.

It is assumed that constraints and generators are up-to-date and minimized and that the Status field does not already flag sat_g to be up-to-date. The values of the saturation matrix are computed as follows:

\[ \begin{cases} sat\_g[i][j] = 0, \quad \text{if } C[i] \cdot G^\mathrm{T}[j] = 0; \\ sat\_g[i][j] = 1, \quad \text{if } C[i] \cdot G^\mathrm{T}[j] > 0. \end{cases} \]

Definition at line 940 of file Polyhedron_nonpublic.cc.

References Parma_Polyhedra_Library::Bit_Matrix::clear(), Parma_Polyhedra_Library::Bit_Matrix::resize(), sat_g, set_sat_g_up_to_date(), and Parma_Polyhedra_Library::Scalar_Products::sign().

Referenced by BHZ09_C_poly_hull_assign_if_exact(), BHZ09_NNC_poly_hull_assign_if_exact(), obtain_sorted_generators_with_sat_g(), and select_H79_constraints().

940  {
941  PPL_ASSERT(constraints_are_minimized());
942  PPL_ASSERT(generators_are_minimized());
943  PPL_ASSERT(!sat_g_is_up_to_date());
944 
945  // We only consider non-pending rows.
948  Polyhedron& x = const_cast<Polyhedron&>(*this);
949 
950  // The columns of `sat_g' represent generators and its
951  // rows represent the constraints: resize accordingly.
952  x.sat_g.resize(csr, gsr);
953  for (dimension_type i = csr; i-- > 0; ) {
954  for (dimension_type j = gsr; j-- > 0; ) {
955  const int sp_sign = Scalar_Products::sign(con_sys[i], gen_sys[j]);
956  // The negativity of this scalar product would mean
957  // that the generator `gen_sys[j]' violates the constraint
958  // `con_sys[i]' and it is not possible because both generators
959  // and constraints are up-to-date.
960  PPL_ASSERT(sp_sign >= 0);
961  if (sp_sign > 0) {
962  // `gen_sys[j]' satisfies (without saturate) `con_sys[i]'.
963  x.sat_g[i].set(j);
964  }
965  else {
966  // `gen_sys[j]' saturates `con_sys[i]'.
967  x.sat_g[i].clear(j);
968  }
969  }
970  }
971  x.set_sat_g_up_to_date();
972 }
bool constraints_are_minimized() const
Returns true if the system of constraints is minimized.
dimension_type first_pending_row() const
Returns the index of the first pending row.
size_t dimension_type
An unsigned integral type for representing space dimensions.
Generator_System gen_sys
The system of generators.
bool generators_are_minimized() const
Returns true if the system of generators is minimized.
dimension_type first_pending_row() const
Returns the index of the first pending row.
bool sat_g_is_up_to_date() const
Returns true if the saturation matrix sat_g is up-to-date.
Polyhedron(Topology topol, dimension_type num_dimensions, Degenerate_Element kind)
Builds a polyhedron having the specified properties.
Constraint_System con_sys
The system of constraints.
static int sign(const Linear_Expression &x, const Linear_Expression &y)
Returns the sign of the scalar product between x and y.
void Parma_Polyhedra_Library::Polyhedron::upper_bound_assign ( const Polyhedron y)
inline

Same as poly_hull_assign(y).

Definition at line 81 of file Polyhedron_inlines.hh.

References poly_hull_assign().

Referenced by BHZ09_poly_hull_assign_if_exact().

81  {
83 }
void poly_hull_assign(const Polyhedron &y)
Assigns to *this the poly-hull of *this and y.
void Parma_Polyhedra_Library::Polyhedron::widening_assign ( const Polyhedron y,
unsigned *  tp = 0 
)
inline

Same as H79_widening_assign(y, tp).

Definition at line 91 of file Polyhedron_inlines.hh.

References H79_widening_assign().

91  {
92  H79_widening_assign(y, tp);
93 }
void H79_widening_assign(const Polyhedron &y, unsigned *tp=0)
Assigns to *this the result of computing the H79_widening between *this and y.
void Parma_Polyhedra_Library::Polyhedron::wrap_assign ( const Variables_Set vars,
Bounded_Integer_Type_Width  w,
Bounded_Integer_Type_Representation  r,
Bounded_Integer_Type_Overflow  o,
const Constraint_System cs_p = 0,
unsigned  complexity_threshold = 16,
bool  wrap_individually = true 
)

Wraps the specified dimensions of the vector space.

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

Definition at line 4058 of file Polyhedron_public.cc.

References Parma_Polyhedra_Library::Implementation::wrap_assign().

4064  {
4065  if (is_necessarily_closed()) {
4066  Implementation::wrap_assign(static_cast<C_Polyhedron&>(*this),
4067  vars, w, r, o, cs_p,
4068  complexity_threshold, wrap_individually,
4069  "C_Polyhedron");
4070  }
4071  else {
4072  Implementation::wrap_assign(static_cast<NNC_Polyhedron&>(*this),
4073  vars, w, r, o, cs_p,
4074  complexity_threshold, wrap_individually,
4075  "NNC_Polyhedron");
4076  }
4077 }
void wrap_assign(PSET &pointset, const Variables_Set &vars, const Bounded_Integer_Type_Width w, const Bounded_Integer_Type_Representation r, const Bounded_Integer_Type_Overflow o, const Constraint_System *cs_p, const unsigned complexity_threshold, const bool wrap_individually, const char *class_name)
Definition: wrap_assign.hh:152
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.

Friends And Related Function Documentation

bool operator!= ( const Polyhedron x,
const Polyhedron y 
)
related

Returns true if and only if x and y are different polyhedra.

Note that x and y may be topology- and/or dimension-incompatible polyhedra: in those cases, the value true is returned.

bool operator!= ( const Polyhedron x,
const Polyhedron y 
)
related

Definition at line 431 of file Polyhedron_inlines.hh.

431  {
432  return !(x == y);
433 }
std::ostream & operator<< ( std::ostream &  s,
const Polyhedron ph 
)
related

Output operator.

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

std::ostream & operator<< ( std::ostream &  s,
const Polyhedron ph 
)
related

Definition at line 4081 of file Polyhedron_public.cc.

References is_empty(), and minimized_constraints().

4081  {
4082  if (ph.is_empty()) {
4083  s << "false";
4084  }
4085  else {
4086  s << ph.minimized_constraints();
4087  }
4088  return s;
4089 }
bool is_empty() const
Returns true if and only if *this is an empty polyhedron.
const Constraint_System & minimized_constraints() const
Returns the system of constraints, with no redundant constraint.
bool operator== ( const Polyhedron x,
const Polyhedron y 
)
related

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

Note that x and y may be topology- and/or dimension-incompatible polyhedra: in those cases, the value false is returned.

bool operator== ( const Polyhedron x,
const Polyhedron y 
)
friend
bool operator== ( const Polyhedron x,
const Polyhedron y 
)
related

Definition at line 3889 of file Polyhedron_public.cc.

References is_empty(), is_included_in(), marked_empty(), quick_equivalence_test(), space_dim, topology(), TVB_FALSE, and TVB_TRUE.

3889  {
3890  // If the two polyhedra are topology-incompatible or dimension-incompatible,
3891  // then they cannot be the same polyhedron.
3892  if (x.topology() != y.topology() || x.space_dim != y.space_dim) {
3893  return false;
3894  }
3895 
3896  if (x.marked_empty()) {
3897  return y.is_empty();
3898  }
3899  else if (y.marked_empty()) {
3900  return x.is_empty();
3901  }
3902  else if (x.space_dim == 0) {
3903  return true;
3904  }
3905 
3906  switch (x.quick_equivalence_test(y)) {
3907  case Polyhedron::TVB_TRUE:
3908  return true;
3909  case Polyhedron::TVB_FALSE:
3910  return false;
3911  default:
3912  if (x.is_included_in(y)) {
3913  if (x.marked_empty()) {
3914  return y.is_empty();
3915  }
3916  else {
3917  return y.is_included_in(x);
3918  }
3919  }
3920  else {
3921  return false;
3922  }
3923  }
3924 }
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
bool is_empty() const
Returns true if and only if *this is an empty polyhedron.
Topology topology() const
Returns the topological kind of the polyhedron.
bool is_included_in(const Polyhedron &y) const
Returns true if and only if *this is included in y.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
Three_Valued_Boolean quick_equivalence_test(const Polyhedron &y) const
Polynomial but incomplete equivalence test between polyhedra.
template<typename T >
friend class Parma_Polyhedra_Library::BD_Shape
friend

Definition at line 2621 of file Polyhedron_defs.hh.

Definition at line 2624 of file Polyhedron_defs.hh.

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

Definition at line 2620 of file Polyhedron_defs.hh.

friend class Parma_Polyhedra_Library::Grid
friend

Definition at line 2623 of file Polyhedron_defs.hh.

Definition at line 2625 of file Polyhedron_defs.hh.

template<typename T >
friend class Parma_Polyhedra_Library::Octagonal_Shape
friend

Definition at line 2622 of file Polyhedron_defs.hh.

template<typename PH >
bool poly_hull_assign_if_exact ( PH &  p,
const PH &  q 
)
related

If the poly-hull of p and q is exact it is assigned to p and true is returned, otherwise false is returned.

template<typename PH >
bool poly_hull_assign_if_exact ( PH &  p,
const PH &  q 
)
related

Definition at line 51 of file algorithms.hh.

References Parma_Polyhedra_Library::Powerset< Parma_Polyhedra_Library::Determinate< PSET > >::begin(), contains(), and Parma_Polyhedra_Library::Powerset< Parma_Polyhedra_Library::Determinate< PSET > >::end().

51  {
52  PH poly_hull = p;
53  NNC_Polyhedron nnc_p(p);
54  poly_hull.poly_hull_assign(q);
55  std::pair<PH, Pointset_Powerset<NNC_Polyhedron> >
56  partition = linear_partition(q, poly_hull);
57  const Pointset_Powerset<NNC_Polyhedron>& s = partition.second;
58  typedef Pointset_Powerset<NNC_Polyhedron>::const_iterator iter;
59  for (iter i = s.begin(), s_end = s.end(); i != s_end; ++i) {
60  // The polyhedral hull is exact if and only if all the elements
61  // of the partition of the polyhedral hull of `p' and `q' with
62  // respect to `q' are included in `p'
63  if (!nnc_p.contains(i->pointset())) {
64  return false;
65  }
66  }
67  p = poly_hull;
68  return true;
69 }
void swap ( Polyhedron x,
Polyhedron y 
)
related

Swaps x with y.

Referenced by add_space_dimensions(), conversion(), m_swap(), Polyhedron(), and simplify().

void swap ( Polyhedron x,
Polyhedron y 
)
related

Definition at line 115 of file Polyhedron_inlines.hh.

References m_swap().

115  {
116  x.m_swap(y);
117 }

Member Data Documentation

const Representation Parma_Polyhedra_Library::Polyhedron::default_con_sys_repr = DENSE
staticprivate

Definition at line 2026 of file Polyhedron_defs.hh.

const Representation Parma_Polyhedra_Library::Polyhedron::default_gen_sys_repr = DENSE
staticprivate

Definition at line 2027 of file Polyhedron_defs.hh.

PPL::dimension_type * Parma_Polyhedra_Library::Polyhedron::simplify_num_saturators_p = 0
staticprivate

Pointer to an array used by simplify().

Holds (between class initialization and finalization) a pointer to an array, allocated with operator new[](), of simplify_num_saturators_size elements.

Definition at line 2610 of file Polyhedron_defs.hh.

Referenced by initialize(), and simplify().

size_t Parma_Polyhedra_Library::Polyhedron::simplify_num_saturators_size = 0
staticprivate

Dimension of an array used by simplify().

Holds (between class initialization and finalization) the size of the array pointed to by simplify_num_saturators_p.

Definition at line 2618 of file Polyhedron_defs.hh.

Referenced by initialize(), and simplify().


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