#include <Polyhedron.defs.hh>
Exception Throwers | |
void | throw_runtime_error (const char *method) const |
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 *e_name, const Linear_Expression &e) 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 |
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 void | throw_space_dimension_overflow (Topology topol, const char *method, const char *reason) |
Public Types | |
typedef Coefficient | coefficient_type |
The numeric type of coefficients. | |
Public Member Functions | |
Member Functions that Do Not Modify the Polyhedron | |
dimension_type | space_dimension () const |
Returns the dimension of the vector space enclosing *this . | |
dimension_type | affine_dimension () const |
Returns ![]() *this is empty; otherwise, returns the affine dimension of *this . | |
const Constraint_System & | constraints () const |
Returns the system of constraints. | |
const Constraint_System & | minimized_constraints () const |
Returns the system of constraints, with no redundant constraint. | |
const Generator_System & | generators () const |
Returns the system of generators. | |
const Generator_System & | minimized_generators () const |
Returns the system of generators, with no redundant generator. | |
Congruence_System | congruences () const |
Returns a system of (equality) congruences satisfied by *this . | |
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 . | |
Grid_Generator_System | grid_generators () const |
Returns a universe system of grid generators. | |
Grid_Generator_System | minimized_grid_generators () const |
Returns a universe system of grid generators. | |
Poly_Con_Relation | relation_with (const Constraint &c) const |
Returns the relations holding between the polyhedron *this and the constraint c . | |
Poly_Gen_Relation | relation_with (const Generator &g) const |
Returns the relations holding between the polyhedron *this and the generator g . | |
Poly_Con_Relation | relation_with (const Congruence &cg) const |
Returns the relations holding between the polyhedron *this and the congruence c . | |
bool | is_empty () const |
Returns true if and only if *this is an empty polyhedron. | |
bool | is_universe () const |
Returns true if and only if *this is a universe polyhedron. | |
bool | is_topologically_closed () const |
Returns true if and only if *this is a topologically closed subset of the vector space. | |
bool | is_disjoint_from (const Polyhedron &y) const |
Returns true if and only if *this and y are disjoint. | |
bool | is_discrete () const |
Returns true if and only if *this is discrete. | |
bool | is_bounded () const |
Returns true if and only if *this is a bounded polyhedron. | |
bool | contains_integer_point () const |
Returns true if and only if *this contains at least one integer point. | |
bool | constrains (Variable var) const |
Returns true if and only if var is constrained in *this . | |
bool | bounds_from_above (const Linear_Expression &expr) const |
Returns true if and only if expr is bounded from above in *this . | |
bool | bounds_from_below (const Linear_Expression &expr) const |
Returns true if and only if expr is bounded from below in *this . | |
bool | maximize (const Linear_Expression &expr, Coefficient &sup_n, Coefficient &sup_d, bool &maximum) const |
Returns true if and only if *this is not empty and expr is bounded from above in *this , in which case the supremum value is computed. | |
bool | maximize (const Linear_Expression &expr, Coefficient &sup_n, Coefficient &sup_d, bool &maximum, Generator &g) const |
Returns true if and only if *this is not empty and expr is bounded from above in *this , in which case the supremum value and a point where expr reaches it are computed. | |
bool | minimize (const Linear_Expression &expr, Coefficient &inf_n, Coefficient &inf_d, bool &minimum) const |
Returns true if and only if *this is not empty and expr is bounded from below in *this , in which case the infimum value is computed. | |
bool | minimize (const Linear_Expression &expr, Coefficient &inf_n, Coefficient &inf_d, bool &minimum, Generator &g) const |
Returns true if and only if *this is not empty and expr is bounded from below in *this , in which case the infimum value and a point where expr reaches it are computed. | |
bool | contains (const Polyhedron &y) const |
Returns true if and only if *this contains y . | |
bool | strictly_contains (const Polyhedron &y) const |
Returns true if and only if *this strictly contains y . | |
bool | OK (bool check_not_empty=false) const |
Checks if all the invariants are satisfied. | |
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). | |
bool | add_constraint_and_minimize (const Constraint &c) |
Adds a copy of constraint c to the system of constraints of *this , minimizing the result. | |
void | add_generator (const Generator &g) |
Adds a copy of generator g to the system of generators of *this (without minimizing the result). | |
bool | add_generator_and_minimize (const Generator &g) |
Adds a copy of generator g to the system of generators of *this , minimizing the result. | |
void | add_congruence (const Congruence &cg) |
Adds a copy of congruence cg to *this , if cg can be exactly represented by a polyhedron. | |
bool | add_congruence_and_minimize (const Congruence &cg) |
Adds a copy of congruence cg to *this , if cg can be exactly represented by a polyhedron, minimizing the result. | |
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). | |
void | add_recycled_constraints (Constraint_System &cs) |
Adds the constraints in cs to the system of constraints of *this (without minimizing the result). | |
bool | add_constraints_and_minimize (const Constraint_System &cs) |
Adds a copy of the constraints in cs to the system of constraints of *this , minimizing the result. | |
bool | add_recycled_constraints_and_minimize (Constraint_System &cs) |
Adds the constraints in cs to the system of constraints of *this , minimizing the result. | |
void | add_generators (const Generator_System &gs) |
Adds a copy of the generators in gs to the system of generators of *this (without minimizing the result). | |
void | add_recycled_generators (Generator_System &gs) |
Adds the generators in gs to the system of generators of *this (without minimizing the result). | |
bool | add_generators_and_minimize (const Generator_System &gs) |
Adds a copy of the generators in gs to the system of generators of *this , minimizing the result. | |
bool | add_recycled_generators_and_minimize (Generator_System &gs) |
Adds the generators in gs to the system of generators of *this , minimizing the result. | |
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. | |
bool | add_congruences_and_minimize (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, minimizing the result. | |
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. | |
bool | add_recycled_congruences_and_minimize (Congruence_System &cgs) |
Adds the congruences in cgs to *this , if all the congruences can be exactly represented by a polyhedron, minimizing the result. | |
void | refine_with_constraint (const Constraint &c) |
Uses a copy of constraint c to refine *this . | |
void | refine_with_congruence (const Congruence &cg) |
Uses a copy of congruence cg to refine *this . | |
void | refine_with_constraints (const Constraint_System &cs) |
Uses a copy of the constraints in cs to refine *this . | |
void | refine_with_congruences (const Congruence_System &cgs) |
Uses a copy of the congruences in cgs to refine *this . | |
void | unconstrain (Variable var) |
Computes the cylindrification of *this with respect to space dimension var , assigning the result to *this . | |
void | unconstrain (const Variables_Set &to_be_unconstrained) |
Computes the cylindrification of *this with respect to the set of space dimensions to_be_unconstrained , assigning the result to *this . | |
void | intersection_assign (const Polyhedron &y) |
Assigns to *this the intersection of *this and y . The result is not guaranteed to be minimized. | |
bool | intersection_assign_and_minimize (const Polyhedron &y) |
Assigns to *this the intersection of *this and y , minimizing the result. | |
void | poly_hull_assign (const Polyhedron &y) |
Assigns to *this the poly-hull of *this and y . The result is not guaranteed to be minimized. | |
bool | poly_hull_assign_and_minimize (const Polyhedron &y) |
Assigns to *this the poly-hull of *this and y , minimizing the result. | |
void | upper_bound_assign (const Polyhedron &y) |
Same as poly_hull_assign(y). | |
void | poly_difference_assign (const Polyhedron &y) |
Assigns to *this the poly-difference of *this and y . The result is not guaranteed to be minimized. | |
void | difference_assign (const Polyhedron &y) |
Same as poly_difference_assign(y). | |
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. | |
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 . | |
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 . | |
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 ![]() ![]() relsym . | |
void | generalized_affine_preimage (Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one()) |
Assigns to *this the preimage of *this with respect to the generalized affine relation ![]() ![]() relsym . | |
void | generalized_affine_image (const Linear_Expression &lhs, Relation_Symbol relsym, const Linear_Expression &rhs) |
Assigns to *this the image of *this with respect to the generalized affine relation ![]() ![]() relsym . | |
void | generalized_affine_preimage (const Linear_Expression &lhs, Relation_Symbol relsym, const Linear_Expression &rhs) |
Assigns to *this the preimage of *this with respect to the generalized affine relation ![]() ![]() relsym . | |
void | bounded_affine_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 | bounded_affine_preimage (Variable var, const Linear_Expression &lb_expr, const Linear_Expression &ub_expr, Coefficient_traits::const_reference denominator=Coefficient_one()) |
Assigns to *this the preimage of *this with respect to the bounded affine relation ![]() | |
void | time_elapse_assign (const Polyhedron &y) |
Assigns to *this the result of computing the time-elapse between *this and y . | |
void | topological_closure_assign () |
Assigns to *this its topological closure. | |
void | BHRZ03_widening_assign (const Polyhedron &y, unsigned *tp=0) |
Assigns to *this the result of computing the BHRZ03-widening between *this and y . | |
void | limited_BHRZ03_extrapolation_assign (const Polyhedron &y, const Constraint_System &cs, unsigned *tp=0) |
Improves the result of the BHRZ03-widening computation by also enforcing those constraints in cs that are satisfied by all the points of *this . | |
void | bounded_BHRZ03_extrapolation_assign (const Polyhedron &y, const Constraint_System &cs, unsigned *tp=0) |
Improves the result of the BHRZ03-widening computation by also enforcing those constraints in cs that are satisfied by all the points of *this , plus all the constraints of the form ![]() ![]() ![]() *this . | |
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 | widening_assign (const Polyhedron &y, unsigned *tp=0) |
Same as H79_widening_assign(y, tp). | |
void | limited_H79_extrapolation_assign (const Polyhedron &y, const Constraint_System &cs, unsigned *tp=0) |
Improves the result of the H79-widening computation by also enforcing those constraints in cs that are satisfied by all the points of *this . | |
void | bounded_H79_extrapolation_assign (const Polyhedron &y, const Constraint_System &cs, unsigned *tp=0) |
Improves the result of the H79-widening computation by also enforcing those constraints in cs that are satisfied by all the points of *this , plus all the constraints of the form ![]() ![]() ![]() *this . | |
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. | |
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. | |
void | concatenate_assign (const Polyhedron &y) |
Assigns to *this the concatenation of *this and y , taken in this order. | |
void | remove_space_dimensions (const Variables_Set &to_be_removed) |
Removes all the specified dimensions from the vector space. | |
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 . | |
template<typename Partial_Function> | |
void | map_space_dimensions (const Partial_Function &pfunc) |
Remaps the dimensions of the vector space according to a partial function. | |
void | expand_space_dimension (Variable var, dimension_type m) |
Creates m copies of the space dimension corresponding to var . | |
void | fold_space_dimensions (const Variables_Set &to_be_folded, Variable var) |
Folds the space dimensions in to_be_folded into var . | |
Miscellaneous Member Functions | |
~Polyhedron () | |
Destructor. | |
void | swap (Polyhedron &y) |
Swaps *this with polyhedron y . (*this and y can be dimension-incompatible.). | |
void | ascii_dump () const |
Writes to std::cerr an ASCII representation of *this . | |
void | ascii_dump (std::ostream &s) const |
Writes to s an ASCII representation of *this . | |
void | print () const |
Prints *this to std::cerr using operator<< . | |
bool | ascii_load (std::istream &s) |
Loads from s an ASCII representation (as produced by ascii_dump(std::ostream&) const) and sets *this accordingly. Returns true if successful, false otherwise. | |
memory_size_type | total_memory_in_bytes () const |
Returns the total size in bytes of the memory occupied by *this . | |
memory_size_type | external_memory_in_bytes () const |
Returns the size in bytes of the memory managed by *this . | |
int32_t | hash_code () const |
Returns a 32-bit hash code for *this . | |
Static Public Member Functions | |
static dimension_type | max_space_dimension () |
Returns the maximum space dimension all kinds of Polyhedron can handle. | |
static bool | can_recycle_constraint_systems () |
Returns true indicating that this domain has methods that can recycle constraints. | |
static void | initialize () |
Initializes the class. | |
static void | finalize () |
Finalizes the class. | |
static bool | can_recycle_congruence_systems () |
Returns false indicating that this domain cannot recycle congruences. | |
Protected Member Functions | |
Polyhedron (Topology topol, dimension_type num_dimensions, Degenerate_Element kind) | |
Builds a polyhedron having the specified properties. | |
Polyhedron (const Polyhedron &y, Complexity_Class complexity=ANY_COMPLEXITY) | |
Ordinary copy-constructor. | |
Polyhedron (Topology topol, const Constraint_System &cs) | |
Builds a polyhedron from a system of constraints. | |
Polyhedron (Topology topol, Constraint_System &cs, Recycle_Input dummy) | |
Builds a polyhedron recycling a system of constraints. | |
Polyhedron (Topology topol, const Generator_System &gs) | |
Builds a polyhedron from a system of generators. | |
Polyhedron (Topology topol, Generator_System &gs, Recycle_Input dummy) | |
Builds a polyhedron recycling a system of generators. | |
template<typename Interval> | |
Polyhedron (Topology topol, const Box< Interval > &box, Complexity_Class complexity=ANY_COMPLEXITY) | |
Builds a polyhedron from a box. | |
Polyhedron & | operator= (const Polyhedron &y) |
The assignment operator. (*this and y can be dimension-incompatible.). | |
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. | |
bool | is_necessarily_closed () const |
Returns true if and only if the polyhedron is necessarily closed. | |
void | refine_no_check (const Constraint &c) |
Uses a copy of constraint c to refine the system of constraints of *this . | |
Three_Valued_Boolean | quick_equivalence_test (const Polyhedron &y) const |
Polynomial but incomplete equivalence test between polyhedra. | |
bool | is_included_in (const Polyhedron &y) const |
Returns true if and only if *this is included in y . | |
bool | bounds (const Linear_Expression &expr, bool from_above) const |
Checks if and how expr is bounded in *this . | |
bool | max_min (const Linear_Expression &expr, bool maximize, Coefficient &ext_n, Coefficient &ext_d, bool &included, Generator &g) const |
Maximizes or minimizes expr subject to *this . | |
Private Verifiers: Verify if Individual Flags are Set | |
bool | marked_empty () const |
Returns true if the polyhedron is known to be empty. | |
bool | constraints_are_up_to_date () const |
Returns true if the system of constraints is up-to-date. | |
bool | generators_are_up_to_date () const |
Returns true if the system of generators is up-to-date. | |
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 | has_pending_constraints () const |
Returns true if there are pending constraints. | |
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 | can_have_something_pending () const |
Returns true if the polyhedron can have something pending. | |
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. | |
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. | |
void | set_empty () |
Sets status to express that the polyhedron is empty, clearing all corresponding matrices. | |
void | set_constraints_up_to_date () |
Sets status to express that constraints are up-to-date. | |
void | set_generators_up_to_date () |
Sets status to express that generators are up-to-date. | |
void | set_constraints_minimized () |
Sets status to express that constraints are minimized. | |
void | set_generators_minimized () |
Sets status to express that generators are minimized. | |
void | set_constraints_pending () |
Sets status to express that constraints are pending. | |
void | set_generators_pending () |
Sets status to express that generators are pending. | |
void | set_sat_c_up_to_date () |
Sets status to express that sat_c is up-to-date. | |
void | set_sat_g_up_to_date () |
Sets status to express that sat_g is up-to-date. | |
State Flag Cleaners: Clear Only the Specified Flag | |
void | clear_empty () |
Clears the status flag indicating that the polyhedron is empty. | |
void | clear_constraints_up_to_date () |
Sets status to express that constraints are no longer up-to-date. | |
void | clear_generators_up_to_date () |
Sets status to express that generators are no longer up-to-date. | |
void | clear_constraints_minimized () |
Sets status to express that constraints are no longer minimized. | |
void | clear_generators_minimized () |
Sets status to express that generators are no longer minimized. | |
void | clear_pending_constraints () |
Sets status to express that there are no longer pending constraints. | |
void | clear_pending_generators () |
Sets status to express that there are no longer pending generators. | |
void | clear_sat_c_up_to_date () |
Sets status to express that sat_c is no longer up-to-date. | |
void | clear_sat_g_up_to_date () |
Sets status to express that sat_g is no longer up-to-date. | |
The Handling of Pending Rows | |
bool | process_pending () const |
Processes the pending rows of either description of the polyhedron and obtains a minimized polyhedron. | |
bool | process_pending_constraints () const |
Processes the pending constraints and obtains a minimized polyhedron. | |
void | process_pending_generators () const |
Processes the pending generators and obtains a minimized polyhedron. | |
void | remove_pending_to_obtain_constraints () const |
Lazily integrates the pending descriptions of the polyhedron to obtain a constraint system without pending rows. | |
bool | remove_pending_to_obtain_generators () const |
Lazily integrates the pending descriptions of the polyhedron to obtain a generator system without pending rows. | |
Updating and Sorting Matrices | |
void | update_constraints () const |
Updates constraints starting from generators and minimizes them. | |
bool | update_generators () const |
Updates generators starting from constraints and minimizes them. | |
void | update_sat_c () const |
Updates sat_c using the updated constraints and generators. | |
void | update_sat_g () const |
Updates sat_g using the updated constraints and generators. | |
void | obtain_sorted_constraints () const |
Sorts the matrix of constraints keeping status consistency. | |
void | obtain_sorted_generators () const |
Sorts the matrix of generators keeping status consistency. | |
void | obtain_sorted_constraints_with_sat_c () const |
Sorts the matrix of constraints and updates sat_c . | |
void | obtain_sorted_generators_with_sat_g () const |
Sorts the matrix of generators and updates sat_g . | |
Weak and Strong Minimization of Descriptions | |
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. | |
bool | strongly_minimize_generators () const |
Applies strong minimization to the generators of an NNC polyhedron. | |
Constraint_System | simplified_constraints () const |
If constraints are up-to-date, obtain a simplified copy of them. | |
Widening- and Extrapolation-Related Functions | |
void | select_CH78_constraints (const Polyhedron &y, Constraint_System &cs_selected) const |
Copies to cs_selection the constraints of y corresponding to the definition of the CH78-widening of *this and y . | |
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 . | |
bool | BHRZ03_combining_constraints (const Polyhedron &y, const BHRZ03_Certificate &y_cert, const Polyhedron &H79, const Constraint_System &x_minus_H79_con_sys) |
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 Private Member Functions | |
static void | add_space_dimensions (Linear_System &mat1, Linear_System &mat2, Bit_Matrix &sat1, Bit_Matrix &sat2, dimension_type add_dim) |
Adds new space dimensions to the given matrices. | |
Minimization-Related Static Member Functions | |
static bool | minimize (bool con_to_gen, Linear_System &source, Linear_System &dest, Bit_Matrix &sat) |
Builds and simplifies constraints from generators (or vice versa). | |
static bool | add_and_minimize (bool con_to_gen, Linear_System &source1, Linear_System &dest, Bit_Matrix &sat, const Linear_System &source2) |
Adds given constraints and builds minimized corresponding generators or vice versa. | |
static bool | add_and_minimize (bool con_to_gen, Linear_System &source, Linear_System &dest, Bit_Matrix &sat) |
Adds given constraints and builds minimized corresponding generators or vice versa. The given constraints are in source . | |
static dimension_type | conversion (Linear_System &source, dimension_type start, Linear_System &dest, Bit_Matrix &sat, dimension_type num_lines_or_equalities) |
Performs the conversion from constraints to generators and vice versa. | |
static dimension_type | simplify (Linear_System &mat, Bit_Matrix &sat) |
Uses Gauss' elimination method to simplify the result of conversion() . | |
Private Attributes | |
Constraint_System | con_sys |
The system of constraints. | |
Generator_System | gen_sys |
The system of generators. | |
Bit_Matrix | sat_c |
The saturation matrix having constraints on its columns. | |
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 Private Attributes | |
static dimension_type * | simplify_num_saturators_p = 0 |
Pointer to an array used by simplify(). | |
static size_t | simplify_num_saturators_size = 0 |
Dimension of an array used by simplify(). | |
Friends | |
class | Parma_Polyhedra_Library::Box |
class | Parma_Polyhedra_Library::BD_Shape |
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 | is_necessarily_closed_for_interfaces (const Polyhedron &) |
Returns true if and only if ph.topology() == NECESSARILY_CLOSED . | |
Related Functions | |
(Note that these are not member functions.) | |
std::ostream & | operator<< (std::ostream &s, const Polyhedron &ph) |
Output operator. | |
bool | operator!= (const Polyhedron &x, const Polyhedron &y) |
Returns true if and only if x and y are different polyhedra. | |
void | swap (Parma_Polyhedra_Library::Polyhedron &x, Parma_Polyhedra_Library::Polyhedron &y) |
Specializes std::swap . | |
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. | |
Classes | |
class | Status |
A conjunctive assertion about a polyhedron. More... |
An object of the class Polyhedron represents a convex polyhedron in the vector space .
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 of the enclosing vector space):
Note that four different polyhedra can be defined on the zero-dimension space: the empty polyhedron, either closed or NNC, and the universe polyhedron , again either closed or NNC.
x
and y
are defined (where they are used) as follows: Variable x(0); Variable y(1);
Constraint_System cs; cs.insert(x >= 0); cs.insert(x <= 3); cs.insert(y >= 0); cs.insert(y <= 3); C_Polyhedron ph(cs);
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);
Constraint_System cs; cs.insert(x >= 0); cs.insert(x - y <= 0); cs.insert(x - y + 1 >= 0); C_Polyhedron ph(cs);
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);
C_Polyhedron ph(2); ph.add_constraint(y >= 0);
C_Polyhedron ph(2, EMPTY); ph.add_generator(point(0*x + 0*y)); ph.add_generator(ray(y)); ph.add_generator(line(x));
add_space_dimensions_and_embed
: C_Polyhedron ph(1); ph.add_constraint(x == 2); ph.add_space_dimensions_and_embed(1);
add_space_dimensions_and_project
: C_Polyhedron ph(1); ph.add_constraint(x == 2); ph.add_space_dimensions_and_project(1);
add_space_dimensions_and_embed
. After the last line of code, the resulting polyhedron is the singleton set 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);
x
is Linear_Expression expr = x + y;
Linear_Expression expr = y;
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);
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 Linear_Expression expr = x + y;
x
, for example, the affine expression Linear_Expression expr = y;
Variable z(2); Variable w(3);
remove_space_dimensions
: Generator_System gs; gs.insert(point(3*x + y +0*z + 2*w)); C_Polyhedron ph(gs); Variables_Set to_be_removed; to_be_removed.insert(y); to_be_removed.insert(z); ph.remove_space_dimensions(to_be_removed);
remove_space_dimensions
operator, unexpected results can be obtained. For instance, by using the following code we would obtain a different result: set<Variable> to_be_removed1; to_be_removed1.insert(y); ph.remove_space_dimensions(to_be_removed1); set<Variable> to_be_removed2; to_be_removed2.insert(z); ph.remove_space_dimensions(to_be_removed2);
to_be_removed2
we are actually removing variable 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 364 of file Polyhedron.defs.hh.
enum Parma_Polyhedra_Library::Polyhedron::Three_Valued_Boolean [private] |
Parma_Polyhedra_Library::Polyhedron::Polyhedron | ( | Topology | topol, | |
dimension_type | num_dimensions, | |||
Degenerate_Element | kind | |||
) | [protected] |
Builds a polyhedron having the specified properties.
topol | The topology of the polyhedron; | |
num_dimensions | The number of dimensions of the vector space enclosing the polyhedron; | |
kind | Specifies whether the universe or the empty polyhedron has to be built. |
Definition at line 49 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.
00052 : con_sys(topol), 00053 gen_sys(topol), 00054 sat_c(), 00055 sat_g() { 00056 // Protecting against space dimension overflow is up to the caller. 00057 assert(num_dimensions <= max_space_dimension()); 00058 00059 if (kind == EMPTY) 00060 status.set_empty(); 00061 else if (num_dimensions > 0) { 00062 con_sys.add_low_level_constraints(); 00063 con_sys.adjust_topology_and_space_dimension(topol, num_dimensions); 00064 set_constraints_minimized(); 00065 } 00066 space_dim = num_dimensions; 00067 assert(OK()); 00068 }
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 70 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Linear_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().
00071 : con_sys(y.topology()), 00072 gen_sys(y.topology()), 00073 status(y.status), 00074 space_dim(y.space_dim) { 00075 // Being a protected method, we simply assert that topologies do match. 00076 assert(topology() == y.topology()); 00077 if (y.constraints_are_up_to_date()) 00078 con_sys.assign_with_pending(y.con_sys); 00079 if (y.generators_are_up_to_date()) 00080 gen_sys.assign_with_pending(y.gen_sys); 00081 if (y.sat_c_is_up_to_date()) 00082 sat_c = y.sat_c; 00083 if (y.sat_g_is_up_to_date()) 00084 sat_g = y.sat_g; 00085 }
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.
topol | The topology of the polyhedron; | |
cs | The system of constraints defining the polyhedron. |
std::invalid_argument | Thrown if the topology of cs is incompatible with topol . |
Definition at line 87 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::Linear_System::num_pending_rows(), OK(), set_constraints_up_to_date(), set_empty(), Parma_Polyhedra_Library::Linear_System::set_sorted(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), Parma_Polyhedra_Library::swap(), throw_topology_incompatible(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
00088 : con_sys(topol), 00089 gen_sys(topol), 00090 sat_c(), 00091 sat_g() { 00092 // Protecting against space dimension overflow is up to the caller. 00093 assert(ccs.space_dimension() <= max_space_dimension()); 00094 00095 // TODO: this implementation is just an executable specification. 00096 Constraint_System cs = ccs; 00097 00098 // Try to adapt `cs' to the required topology. 00099 const dimension_type cs_space_dim = cs.space_dimension(); 00100 if (!cs.adjust_topology_and_space_dimension(topol, cs_space_dim)) 00101 throw_topology_incompatible((topol == NECESSARILY_CLOSED) 00102 ? "C_Polyhedron(cs)" 00103 : "NNC_Polyhedron(cs)", "cs", cs); 00104 00105 // Set the space dimension. 00106 space_dim = cs_space_dim; 00107 00108 if (space_dim > 0) { 00109 // Stealing the rows from `cs'. 00110 std::swap(con_sys, cs); 00111 if (con_sys.num_pending_rows() > 0) { 00112 // Even though `cs' has pending constraints, since the generators 00113 // of the polyhedron are not up-to-date, the polyhedron cannot 00114 // have pending constraints. By integrating the pending part 00115 // of `con_sys' we may loose sortedness. 00116 con_sys.unset_pending_rows(); 00117 con_sys.set_sorted(false); 00118 } 00119 con_sys.add_low_level_constraints(); 00120 set_constraints_up_to_date(); 00121 } 00122 else { 00123 // Here `space_dim == 0'. 00124 if (cs.num_columns() > 0) 00125 // See if an inconsistent constraint has been passed. 00126 for (dimension_type i = cs.num_rows(); i-- > 0; ) 00127 if (cs[i].is_inconsistent()) { 00128 // Inconsistent constraint found: the polyhedron is empty. 00129 set_empty(); 00130 break; 00131 } 00132 } 00133 assert(OK()); 00134 }
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.
topol | The topology of the polyhedron; | |
cs | The system of constraints defining the polyhedron. It is not declared const because its data-structures may be recycled to build the polyhedron. | |
dummy | A dummy tag to syntactically differentiate this one from the other constructors. |
std::invalid_argument | Thrown if the topology of cs is incompatible with topol . |
Definition at line 136 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::Matrix::num_columns(), Parma_Polyhedra_Library::Linear_System::num_pending_rows(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), set_constraints_up_to_date(), set_empty(), Parma_Polyhedra_Library::Linear_System::set_sorted(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), Parma_Polyhedra_Library::swap(), throw_topology_incompatible(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
00139 : con_sys(topol), 00140 gen_sys(topol), 00141 sat_c(), 00142 sat_g() { 00143 // Protecting against space dimension overflow is up to the caller. 00144 assert(cs.space_dimension() <= max_space_dimension()); 00145 00146 // Try to adapt `cs' to the required topology. 00147 const dimension_type cs_space_dim = cs.space_dimension(); 00148 if (!cs.adjust_topology_and_space_dimension(topol, cs_space_dim)) 00149 throw_topology_incompatible((topol == NECESSARILY_CLOSED) 00150 ? "C_Polyhedron(cs, recycle)" 00151 : "NNC_Polyhedron(cs, recycle)", "cs", cs); 00152 00153 // Set the space dimension. 00154 space_dim = cs_space_dim; 00155 00156 if (space_dim > 0) { 00157 // Stealing the rows from `cs'. 00158 std::swap(con_sys, cs); 00159 if (con_sys.num_pending_rows() > 0) { 00160 // Even though `cs' has pending constraints, since the generators 00161 // of the polyhedron are not up-to-date, the polyhedron cannot 00162 // have pending constraints. By integrating the pending part 00163 // of `con_sys' we may loose sortedness. 00164 con_sys.unset_pending_rows(); 00165 con_sys.set_sorted(false); 00166 } 00167 con_sys.add_low_level_constraints(); 00168 set_constraints_up_to_date(); 00169 } 00170 else { 00171 // Here `space_dim == 0'. 00172 if (cs.num_columns() > 0) 00173 // See if an inconsistent constraint has been passed. 00174 for (dimension_type i = cs.num_rows(); i-- > 0; ) 00175 if (cs[i].is_inconsistent()) { 00176 // Inconsistent constraint found: the polyhedron is empty. 00177 set_empty(); 00178 break; 00179 } 00180 } 00181 assert(OK()); 00182 }
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.
topol | The topology of the polyhedron; | |
gs | The system of generators defining the polyhedron. |
std::invalid_argument | Thrown 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 184 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Generator_System::add_corresponding_closure_points(), gen_sys, max_space_dimension(), Parma_Polyhedra_Library::NECESSARILY_CLOSED, Parma_Polyhedra_Library::NOT_NECESSARILY_CLOSED, Parma_Polyhedra_Library::Linear_System::num_pending_rows(), OK(), Parma_Polyhedra_Library::Polyhedron::Status::set_empty(), set_generators_up_to_date(), Parma_Polyhedra_Library::Linear_System::set_sorted(), space_dim, Parma_Polyhedra_Library::Generator_System::space_dimension(), status, Parma_Polyhedra_Library::swap(), throw_invalid_generators(), throw_topology_incompatible(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
00185 : con_sys(topol), 00186 gen_sys(topol), 00187 sat_c(), 00188 sat_g() { 00189 // Protecting against space dimension overflow is up to the caller. 00190 assert(cgs.space_dimension() <= max_space_dimension()); 00191 00192 // TODO: this implementation is just an executable specification. 00193 Generator_System gs = cgs; 00194 00195 // An empty set of generators defines the empty polyhedron. 00196 if (gs.has_no_rows()) { 00197 space_dim = gs.space_dimension(); 00198 status.set_empty(); 00199 assert(OK()); 00200 return; 00201 } 00202 00203 // Non-empty valid generator systems have a supporting point, at least. 00204 if (!gs.has_points()) 00205 throw_invalid_generators((topol == NECESSARILY_CLOSED) 00206 ? "C_Polyhedron(gs)" 00207 : "NNC_Polyhedron(gs)", "gs"); 00208 00209 const dimension_type gs_space_dim = gs.space_dimension(); 00210 // Try to adapt `gs' to the required topology. 00211 if (!gs.adjust_topology_and_space_dimension(topol, gs_space_dim)) 00212 throw_topology_incompatible((topol == NECESSARILY_CLOSED) 00213 ? "C_Polyhedron(gs)" 00214 : "NNC_Polyhedron(gs)", "gs", gs); 00215 00216 if (gs_space_dim > 0) { 00217 // Stealing the rows from `gs'. 00218 std::swap(gen_sys, gs); 00219 // In a generator system describing a NNC polyhedron, 00220 // for each point we must also have the corresponding closure point. 00221 if (topol == NOT_NECESSARILY_CLOSED) 00222 gen_sys.add_corresponding_closure_points(); 00223 if (gen_sys.num_pending_rows() > 0) { 00224 // Even though `gs' has pending generators, since the constraints 00225 // of the polyhedron are not up-to-date, the polyhedron cannot 00226 // have pending generators. By integrating the pending part 00227 // of `gen_sys' we may loose sortedness. 00228 gen_sys.unset_pending_rows(); 00229 gen_sys.set_sorted(false); 00230 } 00231 // Generators are now up-to-date. 00232 set_generators_up_to_date(); 00233 00234 // Set the space dimension. 00235 space_dim = gs_space_dim; 00236 assert(OK()); 00237 return; 00238 } 00239 00240 // Here `gs.num_rows > 0' and `gs_space_dim == 0': 00241 // we already checked for both the topology-compatibility 00242 // and the supporting point. 00243 space_dim = 0; 00244 assert(OK()); 00245 }
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.
topol | The topology of the polyhedron; | |
gs | The system of generators defining the polyhedron. It is not declared const because its data-structures may be recycled to build the polyhedron. | |
dummy | A dummy tag to syntactically differentiate this one from the other constructors. |
std::invalid_argument | Thrown 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 247 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::Matrix::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::Linear_System::num_pending_rows(), OK(), Parma_Polyhedra_Library::Polyhedron::Status::set_empty(), set_generators_up_to_date(), Parma_Polyhedra_Library::Linear_System::set_sorted(), space_dim, Parma_Polyhedra_Library::Generator_System::space_dimension(), status, Parma_Polyhedra_Library::swap(), throw_invalid_generators(), throw_topology_incompatible(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
00250 : con_sys(topol), 00251 gen_sys(topol), 00252 sat_c(), 00253 sat_g() { 00254 // Protecting against space dimension overflow is up to the caller. 00255 assert(gs.space_dimension() <= max_space_dimension()); 00256 00257 // An empty set of generators defines the empty polyhedron. 00258 if (gs.has_no_rows()) { 00259 space_dim = gs.space_dimension(); 00260 status.set_empty(); 00261 assert(OK()); 00262 return; 00263 } 00264 00265 // Non-empty valid generator systems have a supporting point, at least. 00266 if (!gs.has_points()) 00267 throw_invalid_generators((topol == NECESSARILY_CLOSED) 00268 ? "C_Polyhedron(gs, recycle)" 00269 : "NNC_Polyhedron(gs, recycle)", "gs"); 00270 00271 const dimension_type gs_space_dim = gs.space_dimension(); 00272 // Try to adapt `gs' to the required topology. 00273 if (!gs.adjust_topology_and_space_dimension(topol, gs_space_dim)) 00274 throw_topology_incompatible((topol == NECESSARILY_CLOSED) 00275 ? "C_Polyhedron(gs, recycle)" 00276 : "NNC_Polyhedron(gs, recycle)", "gs", gs); 00277 00278 if (gs_space_dim > 0) { 00279 // Stealing the rows from `gs'. 00280 std::swap(gen_sys, gs); 00281 // In a generator system describing a NNC polyhedron, 00282 // for each point we must also have the corresponding closure point. 00283 if (topol == NOT_NECESSARILY_CLOSED) 00284 gen_sys.add_corresponding_closure_points(); 00285 if (gen_sys.num_pending_rows() > 0) { 00286 // Even though `gs' has pending generators, since the constraints 00287 // of the polyhedron are not up-to-date, the polyhedron cannot 00288 // have pending generators. By integrating the pending part 00289 // of `gen_sys' we may loose sortedness. 00290 gen_sys.unset_pending_rows(); 00291 gen_sys.set_sorted(false); 00292 } 00293 // Generators are now up-to-date. 00294 set_generators_up_to_date(); 00295 00296 // Set the space dimension. 00297 space_dim = gs_space_dim; 00298 assert(OK()); 00299 return; 00300 } 00301 00302 // Here `gs.num_rows > 0' and `gs_space_dim == 0': 00303 // we already checked for both the topology-compatibility 00304 // and the supporting point. 00305 space_dim = 0; 00306 assert(OK()); 00307 }
Parma_Polyhedra_Library::Polyhedron::Polyhedron | ( | Topology | topol, | |
const Box< Interval > & | box, | |||
Complexity_Class | complexity = ANY_COMPLEXITY | |||
) | [inline, 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
.
topol | The topology of the polyhedron; | |
box | The box representing the polyhedron to be built; | |
complexity | This argument is ignored. |
Definition at line 34 of file Polyhedron.templates.hh.
References Parma_Polyhedra_Library::Constraint_System::add_low_level_constraints(), con_sys, Parma_Polyhedra_Library::Matrix::erase_to_end(), Parma_Polyhedra_Library::Box< ITV >::get_lower_bound(), Parma_Polyhedra_Library::Box< ITV >::get_upper_bound(), Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::Box< ITV >::is_empty(), Parma_Polyhedra_Library::NECESSARILY_CLOSED, Parma_Polyhedra_Library::Matrix::num_rows(), OK(), set_constraints_up_to_date(), set_empty(), Parma_Polyhedra_Library::Linear_System::set_index_first_pending_row(), Parma_Polyhedra_Library::Linear_System::set_sorted(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Box< ITV >::space_dimension(), Parma_Polyhedra_Library::Constraint_System::swap(), and TEMP_INTEGER.
00037 : con_sys(topol), 00038 gen_sys(topol), 00039 sat_c(), 00040 sat_g() { 00041 // Initialize the space dimension as indicated by the box. 00042 space_dim = box.space_dimension(); 00043 00044 // Check for emptiness. 00045 if (box.is_empty()) { 00046 set_empty(); 00047 return; 00048 } 00049 00050 // Zero-dim universe polyhedron. 00051 if (space_dim == 0) { 00052 set_zero_dim_univ(); 00053 return; 00054 } 00055 00056 // Insert a dummy constraint of the highest dimension to avoid the 00057 // need of resizing the matrix of constraints later; 00058 // this constraint will be removed at the end. 00059 con_sys.insert(Variable(space_dim - 1) >= 0); 00060 00061 TEMP_INTEGER(l_n); 00062 TEMP_INTEGER(l_d); 00063 TEMP_INTEGER(u_n); 00064 TEMP_INTEGER(u_d); 00065 00066 if (topol == NECESSARILY_CLOSED) { 00067 for (dimension_type k = space_dim; k-- > 0; ) { 00068 // See if we have a valid lower bound. 00069 bool l_closed = false; 00070 bool l_bounded = box.get_lower_bound(k, l_closed, l_n, l_d); 00071 // See if we have a valid upper bound. 00072 bool u_closed = false; 00073 bool u_bounded = box.get_upper_bound(k, u_closed, u_n, u_d); 00074 00075 // See if we have an implicit equality constraint. 00076 if (l_bounded && u_bounded 00077 && l_closed && u_closed 00078 && l_n == u_n && l_d == u_d) { 00079 // Add the constraint `l_d*v_k == l_n'. 00080 con_sys.insert(l_d * Variable(k) == l_n); 00081 } 00082 else { 00083 if (l_bounded) 00084 // Add the constraint `l_d*v_k >= l_n'. 00085 con_sys.insert(l_d * Variable(k) >= l_n); 00086 if (u_bounded) 00087 // Add the constraint `u_d*v_k <= u_n'. 00088 con_sys.insert(u_d * Variable(k) <= u_n); 00089 } 00090 } 00091 } 00092 else { 00093 // topol == NOT_NECESSARILY_CLOSED 00094 for (dimension_type k = space_dim; k-- > 0; ) { 00095 // See if we have a valid lower bound. 00096 bool l_closed = false; 00097 bool l_bounded = box.get_lower_bound(k, l_closed, l_n, l_d); 00098 // See if we have a valid upper bound. 00099 bool u_closed = false; 00100 bool u_bounded = box.get_upper_bound(k, u_closed, u_n, u_d); 00101 00102 // See if we have an implicit equality constraint. 00103 if (l_bounded && u_bounded 00104 && l_closed && u_closed 00105 && l_n == u_n && l_d == u_d) { 00106 // Add the constraint `l_d*v_k == l_n'. 00107 con_sys.insert(l_d * Variable(k) == l_n); 00108 } 00109 else { 00110 // Check if a lower bound constraint is required. 00111 if (l_bounded) { 00112 if (l_closed) 00113 // Add the constraint `l_d*v_k >= l_n'. 00114 con_sys.insert(l_d * Variable(k) >= l_n); 00115 else 00116 // Add the constraint `l_d*v_k > l_n'. 00117 con_sys.insert(l_d * Variable(k) > l_n); 00118 } 00119 // Check if an upper bound constraint is required. 00120 if (u_bounded) { 00121 if (u_closed) 00122 // Add the constraint `u_d*v_k <= u_n'. 00123 con_sys.insert(u_d * Variable(k) <= u_n); 00124 else 00125 // Add the constraint `u_d*v_k < u_n'. 00126 con_sys.insert(u_d * Variable(k) < u_n); 00127 } 00128 } 00129 } 00130 } 00131 00132 // Adding the low-level constraints. 00133 con_sys.add_low_level_constraints(); 00134 // Now removing the dummy constraint inserted before. 00135 dimension_type n_rows = con_sys.num_rows() - 1; 00136 con_sys[0].swap(con_sys[n_rows]); 00137 con_sys.set_sorted(false); 00138 // NOTE: here there are no pending constraints. 00139 con_sys.set_index_first_pending_row(n_rows); 00140 con_sys.erase_to_end(n_rows); 00141 00142 // Constraints are up-to-date. 00143 set_constraints_up_to_date(); 00144 assert(OK()); 00145 }
Parma_Polyhedra_Library::Polyhedron::~Polyhedron | ( | ) | [inline] |
dimension_type Parma_Polyhedra_Library::Polyhedron::max_space_dimension | ( | ) | [inline, static] |
Returns the maximum space dimension all kinds of Polyhedron can handle.
Definition at line 49 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Generator_System::max_space_dimension(), and Parma_Polyhedra_Library::Constraint_System::max_space_dimension().
Referenced by add_space_dimensions_and_embed(), add_space_dimensions_and_project(), concatenate_assign(), expand_space_dimension(), and Polyhedron().
00049 { 00050 using std::min; 00051 // One dimension is reserved to have a value of type dimension_type 00052 // that does not represent a legal dimension. 00053 return min(std::numeric_limits<dimension_type>::max() - 1, 00054 min(Constraint_System::max_space_dimension(), 00055 Generator_System::max_space_dimension() 00056 ) 00057 ); 00058 }
bool Parma_Polyhedra_Library::Polyhedron::can_recycle_constraint_systems | ( | ) | [inline, static] |
Returns true
indicating that this domain has methods that can recycle constraints.
Definition at line 111 of file Polyhedron.inlines.hh.
void Parma_Polyhedra_Library::Polyhedron::initialize | ( | ) | [static] |
Initializes the class.
Definition at line 42 of file Polyhedron_public.cc.
References simplify_num_saturators_p, and simplify_num_saturators_size.
00042 { 00043 assert(simplify_num_saturators_p == 0); 00044 assert(simplify_num_saturators_size == 0); 00045 simplify_num_saturators_p = new dimension_type[simplify_num_saturators_size]; 00046 }
void Parma_Polyhedra_Library::Polyhedron::finalize | ( | ) | [static] |
Finalizes the class.
Definition at line 49 of file Polyhedron_public.cc.
References simplify_num_saturators_p, and simplify_num_saturators_size.
00049 { 00050 delete [] simplify_num_saturators_p; 00051 simplify_num_saturators_p = 0; 00052 simplify_num_saturators_size = 0; 00053 }
bool Parma_Polyhedra_Library::Polyhedron::can_recycle_congruence_systems | ( | ) | [inline, static] |
Returns false
indicating that this domain cannot recycle congruences.
Definition at line 117 of file Polyhedron.inlines.hh.
PPL::Polyhedron & Parma_Polyhedra_Library::Polyhedron::operator= | ( | const Polyhedron & | y | ) | [protected] |
The assignment operator. (*this
and y
can be dimension-incompatible.).
Definition at line 310 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Linear_System::assign_with_pending(), 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(), set_empty(), set_zero_dim_univ(), space_dim, status, and topology().
Referenced by Parma_Polyhedra_Library::NNC_Polyhedron::operator=(), and Parma_Polyhedra_Library::C_Polyhedron::operator=().
00310 { 00311 // Being a protected method, we simply assert that topologies do match. 00312 assert(topology() == y.topology()); 00313 space_dim = y.space_dim; 00314 if (y.marked_empty()) 00315 set_empty(); 00316 else if (space_dim == 0) 00317 set_zero_dim_univ(); 00318 else { 00319 status = y.status; 00320 if (y.constraints_are_up_to_date()) 00321 con_sys.assign_with_pending(y.con_sys); 00322 if (y.generators_are_up_to_date()) 00323 gen_sys.assign_with_pending(y.gen_sys); 00324 if (y.sat_c_is_up_to_date()) 00325 sat_c = y.sat_c; 00326 if (y.sat_g_is_up_to_date()) 00327 sat_g = y.sat_g; 00328 } 00329 return *this; 00330 }
dimension_type Parma_Polyhedra_Library::Polyhedron::space_dimension | ( | ) | const [inline] |
Returns the dimension of the vector space enclosing *this
.
Definition at line 39 of file Polyhedron.inlines.hh.
References space_dim.
Referenced by add_space_dimensions_and_embed(), add_space_dimensions_and_project(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::BHRZ03_Certificate::BHRZ03_Certificate(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::Pointset_Powerset< PS >::check_containment(), Parma_Polyhedra_Library::H79_Certificate::compare(), Parma_Polyhedra_Library::BHRZ03_Certificate::compare(), expand_space_dimension(), Parma_Polyhedra_Library::Grid::Grid(), Parma_Polyhedra_Library::H79_Certificate::H79_Certificate(), hash_code(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), and throw_dimension_incompatible().
00039 { 00040 return space_dim; 00041 }
PPL::dimension_type Parma_Polyhedra_Library::Polyhedron::affine_dimension | ( | ) | const |
Returns , if
*this
is empty; otherwise, returns the affine dimension of *this
.
Definition at line 56 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Constraint_System::end(), is_empty(), minimized_constraints(), and space_dim.
Referenced by Parma_Polyhedra_Library::Pointset_Powerset< PS >::affine_dimension(), and is_discrete().
00056 { 00057 if (is_empty()) 00058 return 0; 00059 00060 const Constraint_System& cs = minimized_constraints(); 00061 dimension_type d = space_dim; 00062 for (Constraint_System::const_iterator i = cs.begin(), 00063 cs_end = cs.end(); i != cs_end; ++i) 00064 if (i->is_equality()) 00065 --d; 00066 return d; 00067 }
const PPL::Constraint_System & Parma_Polyhedra_Library::Polyhedron::constraints | ( | ) | const |
Returns the system of constraints.
Definition at line 70 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Constraint_System::adjust_topology_and_space_dimension(), con_sys, constraints_are_up_to_date(), Parma_Polyhedra_Library::Matrix::has_no_rows(), has_pending_constraints(), has_pending_generators(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), obtain_sorted_constraints(), process_pending_generators(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), swap(), topology(), update_constraints(), and Parma_Polyhedra_Library::Constraint_System::zero_dim_empty().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::C_Polyhedron::C_Polyhedron(), concatenate_assign(), contains_integer_point(), expand_space_dimension(), Parma_Polyhedra_Library::Grid::Grid(), minimized_constraints(), Parma_Polyhedra_Library::NNC_Polyhedron::NNC_Polyhedron(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), and poly_difference_assign().
00070 { 00071 if (marked_empty()) { 00072 // We want `con_sys' to only contain the unsatisfiable constraint 00073 // of the appropriate dimension. 00074 if (con_sys.has_no_rows()) { 00075 // The 0-dim unsatisfiable constraint is extended to 00076 // the appropriate dimension and then stored in `con_sys'. 00077 Constraint_System unsat_cs = Constraint_System::zero_dim_empty(); 00078 unsat_cs.adjust_topology_and_space_dimension(topology(), space_dim); 00079 const_cast<Constraint_System&>(con_sys).swap(unsat_cs); 00080 } 00081 else { 00082 // Checking that `con_sys' contains the right thing. 00083 assert(con_sys.space_dimension() == space_dim); 00084 assert(con_sys.num_rows() == 1); 00085 assert(con_sys[0].is_inconsistent()); 00086 } 00087 return con_sys; 00088 } 00089 00090 if (space_dim == 0) { 00091 // Zero-dimensional universe. 00092 assert(con_sys.num_rows() == 0 && con_sys.num_columns() == 0); 00093 return con_sys; 00094 } 00095 00096 // If the polyhedron has pending generators, we process them to obtain 00097 // the constraints. No processing is needed if the polyhedron has 00098 // pending constraints. 00099 if (has_pending_generators()) 00100 process_pending_generators(); 00101 else if (!constraints_are_up_to_date()) 00102 update_constraints(); 00103 00104 // TODO: reconsider whether to really sort constraints at this stage. 00105 #if ENSURE_SORTEDNESS 00106 // We insist in returning a sorted system of constraints, 00107 // but sorting is useless if there are pending constraints. 00108 if (!has_pending_constraints()) 00109 obtain_sorted_constraints(); 00110 #endif 00111 return con_sys; 00112 }
const PPL::Constraint_System & Parma_Polyhedra_Library::Polyhedron::minimized_constraints | ( | ) | const |
Returns the system of constraints, with no redundant constraint.
Definition at line 115 of file Polyhedron_public.cc.
References constraints(), is_necessarily_closed(), minimize(), and strongly_minimize_constraints().
Referenced by affine_dimension(), Parma_Polyhedra_Library::BHRZ03_Certificate::BHRZ03_Certificate(), Parma_Polyhedra_Library::H79_Certificate::compare(), Parma_Polyhedra_Library::BHRZ03_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<<().
00115 { 00116 // `minimize()' or `strongly_minimize_constraints()' 00117 // will process any pending constraints or generators. 00118 if (is_necessarily_closed()) 00119 minimize(); 00120 else 00121 strongly_minimize_constraints(); 00122 return constraints(); 00123 }
const PPL::Generator_System & Parma_Polyhedra_Library::Polyhedron::generators | ( | ) | const |
Returns the system of generators.
Definition at line 126 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Generator_System::adjust_topology_and_space_dimension(), gen_sys, generators_are_minimized(), generators_are_up_to_date(), Parma_Polyhedra_Library::Matrix::has_no_rows(), has_pending_constraints(), has_pending_generators(), is_necessarily_closed(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), obtain_sorted_generators(), process_pending_constraints(), space_dim, Parma_Polyhedra_Library::Generator_System::space_dimension(), swap(), topology(), update_generators(), and zero_dim_univ.
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::Box< ITV >::Box(), fold_space_dimensions(), Parma_Polyhedra_Library::Grid::Grid(), map_space_dimensions(), minimized_generators(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape().
00126 { 00127 if (marked_empty()) { 00128 assert(gen_sys.has_no_rows()); 00129 // We want `gen_sys' to have the appropriate space dimension, 00130 // even though it is an empty generator system. 00131 if (gen_sys.space_dimension() != space_dim) { 00132 Generator_System gs; 00133 gs.adjust_topology_and_space_dimension(topology(), space_dim); 00134 const_cast<Generator_System&>(gen_sys).swap(gs); 00135 } 00136 return gen_sys; 00137 } 00138 00139 if (space_dim == 0) { 00140 assert(gen_sys.num_rows() == 0 && gen_sys.num_columns() == 0); 00141 return Generator_System::zero_dim_univ(); 00142 } 00143 00144 // If the polyhedron has pending constraints, we process them to obtain 00145 // the generators (we may discover that the polyhedron is empty). 00146 // No processing is needed if the polyhedron has pending generators. 00147 if ((has_pending_constraints() && !process_pending_constraints()) 00148 || (!generators_are_up_to_date() && !update_generators())) { 00149 // We have just discovered that `*this' is empty. 00150 assert(gen_sys.has_no_rows()); 00151 // We want `gen_sys' to have the appropriate space dimension, 00152 // even though it is an empty generator system. 00153 if (gen_sys.space_dimension() != space_dim) { 00154 Generator_System gs; 00155 gs.adjust_topology_and_space_dimension(topology(), space_dim); 00156 const_cast<Generator_System&>(gen_sys).swap(gs); 00157 } 00158 return gen_sys; 00159 } 00160 00161 // TODO: reconsider whether to really sort generators at this stage. 00162 #if ENSURE_SORTEDNESS 00163 // We insist in returning a sorted system of generators, 00164 // but sorting is useless if there are pending generators. 00165 if (!has_pending_generators()) 00166 obtain_sorted_generators(); 00167 #else 00168 // In the case of an NNC polyhedron, if the generator system is fully 00169 // minimized (i.e., minimized and with no pending generator), then 00170 // return a sorted system of generators: this is needed so that the 00171 // const_iterator could correctly filter out the matched closure points. 00172 if (!is_necessarily_closed() 00173 && generators_are_minimized() && !has_pending_generators()) 00174 obtain_sorted_generators(); 00175 #endif 00176 return gen_sys; 00177 }
const PPL::Generator_System & Parma_Polyhedra_Library::Polyhedron::minimized_generators | ( | ) | const |
Returns the system of generators, with no redundant generator.
Definition at line 180 of file Polyhedron_public.cc.
References generators(), is_necessarily_closed(), minimize(), and strongly_minimize_generators().
Referenced by Parma_Polyhedra_Library::BHRZ03_Certificate::BHRZ03_Certificate(), and Parma_Polyhedra_Library::BHRZ03_Certificate::compare().
00180 { 00181 // `minimize()' or `strongly_minimize_generators()' 00182 // will process any pending constraints or generators. 00183 if (is_necessarily_closed()) 00184 minimize(); 00185 else 00186 strongly_minimize_generators(); 00187 // Note: calling generators() on a strongly minimized NNC generator 00188 // system will also ensure sortedness, which is required to correctly 00189 // filter away the matched closure points. 00190 return generators(); 00191 }
Congruence_System Parma_Polyhedra_Library::Polyhedron::congruences | ( | ) | const [inline] |
Returns a system of (equality) congruences satisfied by *this
.
Definition at line 356 of file Polyhedron.inlines.hh.
References minimized_constraints().
00356 { 00357 return Congruence_System(minimized_constraints()); 00358 }
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 361 of file Polyhedron.inlines.hh.
References minimized_constraints().
00361 { 00362 return Congruence_System(minimized_constraints()); 00363 }
PPL::Grid_Generator_System Parma_Polyhedra_Library::Polyhedron::grid_generators | ( | ) | const |
Returns a universe system of grid generators.
Definition at line 194 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Grid_Generator_System::insert(), and space_dim.
Referenced by minimized_grid_generators().
00194 { 00195 Grid_Generator_System ggs(space_dim); 00196 // Trivially true point. 00197 ggs.insert(grid_point(0*(Variable(0)))); 00198 // A line for each dimension. 00199 dimension_type dim = 0; 00200 while (dim < space_dim) 00201 ggs.insert(grid_line(Variable(dim))); 00202 return ggs; 00203 }
Grid_Generator_System Parma_Polyhedra_Library::Polyhedron::minimized_grid_generators | ( | ) | const [inline] |
Returns a universe system of grid generators.
Definition at line 366 of file Polyhedron.inlines.hh.
References grid_generators().
00366 { 00367 return grid_generators(); 00368 }
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
.
std::invalid_argument | Thrown if *this and constraint c are dimension-incompatible. |
Definition at line 206 of file Polyhedron_public.cc.
References gen_sys, generators_are_up_to_date(), has_pending_constraints(), 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(), marked_empty(), process_pending_constraints(), Parma_Polyhedra_Library::Generator_System::relation_with(), Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), throw_dimension_incompatible(), and update_generators().
Referenced by BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), poly_difference_assign(), and relation_with().
00206 { 00207 // Dimension-compatibility check. 00208 if (space_dim < c.space_dimension()) 00209 throw_dimension_incompatible("relation_with(c)", "c", c); 00210 00211 if (marked_empty()) 00212 return Poly_Con_Relation::saturates() 00213 && Poly_Con_Relation::is_included() 00214 && Poly_Con_Relation::is_disjoint(); 00215 00216 if (space_dim == 0) { 00217 if (c.is_inconsistent()) 00218 if (c.is_strict_inequality() && c.inhomogeneous_term() == 0) 00219 // The constraint 0 > 0 implicitly defines the hyperplane 0 = 0; 00220 // thus, the zero-dimensional point also saturates it. 00221 return Poly_Con_Relation::saturates() 00222 && Poly_Con_Relation::is_disjoint(); 00223 else 00224 return Poly_Con_Relation::is_disjoint(); 00225 else if (c.is_equality() || c.inhomogeneous_term() == 0) 00226 return Poly_Con_Relation::saturates() 00227 && Poly_Con_Relation::is_included(); 00228 else 00229 // The zero-dimensional point saturates 00230 // neither the positivity constraint 1 >= 0, 00231 // nor the strict positivity constraint 1 > 0. 00232 return Poly_Con_Relation::is_included(); 00233 } 00234 00235 if ((has_pending_constraints() && !process_pending_constraints()) 00236 || (!generators_are_up_to_date() && !update_generators())) 00237 // The polyhedron is empty. 00238 return Poly_Con_Relation::saturates() 00239 && Poly_Con_Relation::is_included() 00240 && Poly_Con_Relation::is_disjoint(); 00241 00242 return gen_sys.relation_with(c); 00243 }
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
.
std::invalid_argument | Thrown if *this and generator g are dimension-incompatible. |
Definition at line 246 of file Polyhedron_public.cc.
References con_sys, constraints_are_up_to_date(), has_pending_generators(), marked_empty(), Parma_Polyhedra_Library::Poly_Gen_Relation::nothing(), process_pending_generators(), Parma_Polyhedra_Library::Constraint_System::satisfies_all_constraints(), space_dim, Parma_Polyhedra_Library::Generator::space_dimension(), Parma_Polyhedra_Library::Poly_Gen_Relation::subsumes(), throw_dimension_incompatible(), and update_constraints().
00246 { 00247 // Dimension-compatibility check. 00248 if (space_dim < g.space_dimension()) 00249 throw_dimension_incompatible("relation_with(g)", "g", g); 00250 00251 // The empty polyhedron cannot subsume a generator. 00252 if (marked_empty()) 00253 return Poly_Gen_Relation::nothing(); 00254 00255 // A universe polyhedron in a zero-dimensional space subsumes 00256 // all the generators of a zero-dimensional space. 00257 if (space_dim == 0) 00258 return Poly_Gen_Relation::subsumes(); 00259 00260 if (has_pending_generators()) 00261 process_pending_generators(); 00262 else if (!constraints_are_up_to_date()) 00263 update_constraints(); 00264 00265 return 00266 con_sys.satisfies_all_constraints(g) 00267 ? Poly_Gen_Relation::subsumes() 00268 : Poly_Gen_Relation::nothing(); 00269 }
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
.
std::invalid_argument | Thrown if *this and congruence c are dimension-incompatible. |
Definition at line 272 of file Polyhedron_public.cc.
References assign(), Parma_Polyhedra_Library::Generator_System::begin(), Parma_Polyhedra_Library::Congruence::coefficient(), Parma_Polyhedra_Library::Generator_System::end(), gen_sys, generators_are_up_to_date(), has_pending_constraints(), Parma_Polyhedra_Library::Poly_Con_Relation::implies(), Parma_Polyhedra_Library::Congruence::inhomogeneous_term(), Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Congruence::is_inconsistent(), marked_empty(), Parma_Polyhedra_Library::Congruence::modulus(), process_pending_constraints(), relation_with(), Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), space_dim, Parma_Polyhedra_Library::Congruence::space_dimension(), Parma_Polyhedra_Library::Poly_Con_Relation::strictly_intersects(), TEMP_INTEGER, throw_dimension_incompatible(), and update_generators().
00272 { 00273 dimension_type cg_space_dim = cg.space_dimension(); 00274 // Dimension-compatibility check. 00275 if (space_dim < cg_space_dim) 00276 throw_dimension_incompatible("relation_with(cg)", "cg", cg); 00277 00278 if (cg.is_equality()) { 00279 const Constraint c(cg); 00280 return relation_with(c); 00281 } 00282 00283 if (marked_empty()) 00284 return Poly_Con_Relation::saturates() 00285 && Poly_Con_Relation::is_included() 00286 && Poly_Con_Relation::is_disjoint(); 00287 00288 if (space_dim == 0) { 00289 if (cg.is_inconsistent()) 00290 return Poly_Con_Relation::is_disjoint(); 00291 else 00292 return Poly_Con_Relation::saturates() 00293 && Poly_Con_Relation::is_included(); 00294 } 00295 00296 if ((has_pending_constraints() && !process_pending_constraints()) 00297 || (!generators_are_up_to_date() && !update_generators())) 00298 // The polyhedron is empty. 00299 return Poly_Con_Relation::saturates() 00300 && Poly_Con_Relation::is_included() 00301 && Poly_Con_Relation::is_disjoint(); 00302 00303 // Find the equality corresponding to the congruence (ignoring the modulus). 00304 Linear_Expression expr; 00305 for (dimension_type i = cg_space_dim; i-- > 0; ) { 00306 const Variable v(i); 00307 expr += cg.coefficient(v) * v; 00308 } 00309 expr += cg.inhomogeneous_term(); 00310 Constraint c(expr == 0); 00311 00312 // The polyhedron is non-empty so that there exists a point. 00313 // For an arbitrary generator point find the scalar product with 00314 // the equality. 00315 TEMP_INTEGER(point_val); 00316 00317 for (Generator_System::const_iterator g = gen_sys.begin(), 00318 gen_sys_end = gen_sys.end(); g != gen_sys_end; ++g) { 00319 if (g->is_point()) { 00320 Scalar_Products::assign(point_val, c, *g); 00321 break; 00322 } 00323 } 00324 00325 // Find the 2 hyperplanes that satisfies the congruence and are 00326 // nearest to the point such that the point lies on or between these 00327 // hyperplanes. 00328 // Then use the relations between the polyhedron and the corresponding 00329 // half-spaces to determine its relation with the congruence. 00330 const Coefficient& modulus = cg.modulus(); 00331 00332 TEMP_INTEGER(div); 00333 div = modulus; 00334 00335 TEMP_INTEGER(nearest); 00336 nearest = (point_val / div) * div; 00337 00338 point_val -= nearest; 00339 expr -= nearest; 00340 if (point_val == 0) 00341 return relation_with(expr == 0); 00342 00343 Linear_Expression next_expr; 00344 if (point_val > 0) { 00345 next_expr = expr - modulus; 00346 } 00347 else { 00348 expr = - (expr); 00349 next_expr = expr - modulus; 00350 } 00351 00352 Poly_Con_Relation relations = relation_with(expr >= 0); 00353 assert(!relations.implies(Poly_Con_Relation::saturates()) 00354 && !relations.implies(Poly_Con_Relation::is_disjoint())); 00355 if (relations.implies(Poly_Con_Relation::strictly_intersects())) 00356 return Poly_Con_Relation::strictly_intersects(); 00357 00358 assert(relations == Poly_Con_Relation::is_included()); 00359 Poly_Con_Relation next_relations = relation_with(next_expr <= 0); 00360 assert(!next_relations.implies(Poly_Con_Relation::saturates()) 00361 && !next_relations.implies(Poly_Con_Relation::is_disjoint())); 00362 if (next_relations.implies(Poly_Con_Relation::strictly_intersects())) 00363 return Poly_Con_Relation::strictly_intersects(); 00364 00365 assert(next_relations == Poly_Con_Relation::is_included()); 00366 return Poly_Con_Relation::is_disjoint(); 00367 }
bool Parma_Polyhedra_Library::Polyhedron::is_empty | ( | ) | const [inline] |
Returns true
if and only if *this
is an empty polyhedron.
Definition at line 179 of file Polyhedron.inlines.hh.
References generators_are_up_to_date(), has_pending_constraints(), marked_empty(), and minimize().
Referenced by affine_dimension(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::Pointset_Powerset< PS >::check_containment(), contains(), generalized_affine_image(), generalized_affine_preimage(), Parma_Polyhedra_Library::Grid::Grid(), H79_widening_assign(), is_disjoint_from(), Parma_Polyhedra_Library::Pointset_Powerset< PS >::linear_partition_aux(), operator<<(), Parma_Polyhedra_Library::Pointset_Powerset< PS >::Pointset_Powerset(), and simplify_using_context_assign().
00179 { 00180 if (marked_empty()) 00181 return true; 00182 // Try a fast-fail test: if generators are up-to-date and 00183 // there are no pending constraints, then the generator system 00184 // (since it is well formed) contains a point. 00185 if (generators_are_up_to_date() && !has_pending_constraints()) 00186 return false; 00187 return !minimize(); 00188 }
bool Parma_Polyhedra_Library::Polyhedron::is_universe | ( | ) | const |
Returns true
if and only if *this
is a universe polyhedron.
Definition at line 370 of file Polyhedron_public.cc.
References con_sys, constraints_are_minimized(), constraints_are_up_to_date(), Parma_Polyhedra_Library::Linear_System::first_pending_row(), gen_sys, generators_are_minimized(), generators_are_up_to_date(), has_pending_constraints(), has_pending_generators(), is_necessarily_closed(), Parma_Polyhedra_Library::Generator::LINE, marked_empty(), minimize(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), obtain_sorted_constraints(), process_pending_generators(), Parma_Polyhedra_Library::Generator::RAY, and space_dim.
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), and Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape().
00370 { 00371 if (marked_empty()) 00372 return false; 00373 00374 if (space_dim == 0) 00375 return true; 00376 00377 if (!has_pending_generators() && constraints_are_up_to_date()) { 00378 // Search for a constraint that is not a tautology. 00379 for (dimension_type i = con_sys.num_rows(); i-- > 0; ) 00380 if (!con_sys[i].is_tautological()) 00381 return false; 00382 // All the constraints are tautologies. 00383 return true; 00384 } 00385 00386 assert(!has_pending_constraints() && generators_are_up_to_date()); 00387 00388 // Try a fast-fail test. 00389 dimension_type num_lines = 0; 00390 dimension_type num_rays = 0; 00391 const dimension_type first_pending = gen_sys.first_pending_row(); 00392 for (dimension_type i = first_pending; i-- > 0; ) 00393 switch (gen_sys[i].type()) { 00394 case Generator::RAY: 00395 ++num_rays; 00396 break; 00397 case Generator::LINE: 00398 ++num_lines; 00399 break; 00400 default: 00401 break; 00402 } 00403 00404 if (has_pending_generators()) { 00405 // The non-pending part of `gen_sys' was minimized: 00406 // a success-first test is possible in this case. 00407 assert(generators_are_minimized()); 00408 if (num_lines == space_dim) { 00409 assert(num_rays == 0); 00410 return true; 00411 } 00412 assert(num_lines < space_dim); 00413 // Now scan the pending generators. 00414 dimension_type num_pending_lines = 0; 00415 dimension_type num_pending_rays = 0; 00416 const dimension_type gs_num_rows = gen_sys.num_rows(); 00417 for (dimension_type i = first_pending; i < gs_num_rows; ++i) 00418 switch (gen_sys[i].type()) { 00419 case Generator::RAY: 00420 ++num_pending_rays; 00421 break; 00422 case Generator::LINE: 00423 ++num_pending_lines; 00424 break; 00425 default: 00426 break; 00427 } 00428 // If no pending rays and lines were found, 00429 // then it is not the universe polyhedron. 00430 if (num_pending_rays == 0 && num_pending_lines == 0) 00431 return false; 00432 // Factor away the lines already seen (to be on the safe side, 00433 // we assume they are all linearly independent). 00434 if (num_lines + num_pending_lines < space_dim) { 00435 const dimension_type num_dims_missing 00436 = space_dim - (num_lines + num_pending_lines); 00437 // In order to span an n dimensional space (where n = num_dims_missing), 00438 // at least n+1 rays are needed. 00439 if (num_rays + num_pending_rays <= num_dims_missing) 00440 return false; 00441 } 00442 } 00443 else { 00444 // There is nothing pending. 00445 if (generators_are_minimized()) { 00446 // The exact test is possible. 00447 assert(num_rays == 0 || num_lines < space_dim); 00448 return num_lines == space_dim; 00449 } 00450 else 00451 // Only the fast-fail test can be computed: in order to span 00452 // an n dimensional space (where n = space_dim - num_lines), 00453 // at least n+1 rays are needed. 00454 if (num_lines < space_dim && num_lines + num_rays <= space_dim) 00455 return false; 00456 } 00457 00458 // We need the polyhedron in minimal form. 00459 if (has_pending_generators()) 00460 process_pending_generators(); 00461 else if (!constraints_are_minimized()) 00462 minimize(); 00463 if (is_necessarily_closed()) 00464 return (con_sys.num_rows() == 1 00465 && con_sys[0].is_inequality() 00466 && con_sys[0].is_tautological()); 00467 else { 00468 // NNC polyhedron. 00469 if (con_sys.num_rows() != 2 00470 || con_sys[0].is_equality() 00471 || con_sys[1].is_equality()) 00472 return false; 00473 else { 00474 // If the system of constraints contains two rows that 00475 // are not equalities, we are sure that they are 00476 // epsilon constraints: in this case we know that 00477 // the polyhedron is universe. 00478 #ifndef NDEBUG 00479 obtain_sorted_constraints(); 00480 const Constraint& eps_leq_one = con_sys[0]; 00481 const Constraint& eps_geq_zero = con_sys[1]; 00482 const dimension_type eps_index = con_sys.num_columns() - 1; 00483 assert(eps_leq_one[0] > 0 && eps_leq_one[eps_index] < 0 00484 && eps_geq_zero[0] == 0 && eps_geq_zero[eps_index] > 0); 00485 for (dimension_type i = 1; i < eps_index; ++i) 00486 assert(eps_leq_one[i] == 0 && eps_geq_zero[i] == 0); 00487 #endif 00488 return true; 00489 } 00490 } 00491 }
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 514 of file Polyhedron_public.cc.
References con_sys, gen_sys, generators_are_minimized(), has_something_pending(), Parma_Polyhedra_Library::Constraint_System::has_strict_inequalities(), Parma_Polyhedra_Library::Generator::is_closure_point(), Parma_Polyhedra_Library::Generator::is_matching_closure_point(), is_necessarily_closed(), Parma_Polyhedra_Library::Generator::is_point(), marked_empty(), Parma_Polyhedra_Library::Generator_System::num_lines(), Parma_Polyhedra_Library::Matrix::num_rows(), process_pending(), space_dim, and strongly_minimize_constraints().
00514 { 00515 // Necessarily closed polyhedra are trivially closed. 00516 if (is_necessarily_closed()) 00517 return true; 00518 // Any empty or zero-dimensional polyhedron is closed. 00519 if (marked_empty() 00520 || space_dim == 0 00521 || (has_something_pending() && !process_pending())) 00522 return true; 00523 00524 // At this point there are no pending constraints or generators. 00525 assert(!has_something_pending()); 00526 00527 if (generators_are_minimized()) { 00528 // A polyhedron is closed if and only if all of its (non-redundant) 00529 // closure points are matched by a corresponding point. 00530 const dimension_type n_rows = gen_sys.num_rows(); 00531 const dimension_type n_lines = gen_sys.num_lines(); 00532 for (dimension_type i = n_rows; i-- > n_lines; ) { 00533 const Generator& gi = gen_sys[i]; 00534 if (gi.is_closure_point()) { 00535 bool gi_has_no_matching_point = true; 00536 for (dimension_type j = n_rows; j-- > n_lines; ) { 00537 const Generator& gj = gen_sys[j]; 00538 if (i != j 00539 && gj.is_point() 00540 && gi.is_matching_closure_point(gj)) { 00541 gi_has_no_matching_point = false; 00542 break; 00543 } 00544 } 00545 if (gi_has_no_matching_point) 00546 return false; 00547 } 00548 } 00549 // All closure points are matched. 00550 return true; 00551 } 00552 00553 // A polyhedron is closed if, after strong minimization 00554 // of its constraint system, it has no strict inequalities. 00555 strongly_minimize_constraints(); 00556 return marked_empty() || !con_sys.has_strict_inequalities(); 00557 }
bool Parma_Polyhedra_Library::Polyhedron::is_disjoint_from | ( | const Polyhedron & | y | ) | const |
Returns true
if and only if *this
and y
are disjoint.
std::invalid_argument | Thrown if x and y are topology-incompatible or dimension-incompatible. |
Definition at line 3810 of file Polyhedron_public.cc.
References intersection_assign(), and is_empty().
Referenced by Parma_Polyhedra_Library::Pointset_Powerset< PS >::check_containment().
03810 { 03811 Polyhedron z = *this; 03812 z.intersection_assign(y); 03813 return z.is_empty(); 03814 }
bool Parma_Polyhedra_Library::Polyhedron::is_discrete | ( | ) | const [inline] |
Returns true
if and only if *this
is discrete.
Definition at line 68 of file Polyhedron.inlines.hh.
References affine_dimension().
00068 { 00069 return affine_dimension() == 0; 00070 }
bool Parma_Polyhedra_Library::Polyhedron::is_bounded | ( | ) | const |
Returns true
if and only if *this
is a bounded polyhedron.
Definition at line 494 of file Polyhedron_public.cc.
References gen_sys, generators_are_up_to_date(), has_pending_constraints(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_rows(), process_pending_constraints(), space_dim, and update_generators().
00494 { 00495 // A zero-dimensional or empty polyhedron is bounded. 00496 if (space_dim == 0 00497 || marked_empty() 00498 || (has_pending_constraints() && !process_pending_constraints()) 00499 || (!generators_are_up_to_date() && !update_generators())) 00500 return true; 00501 00502 // If the system of generators contains any line or a ray, 00503 // then the polyhedron is unbounded. 00504 for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) 00505 if (gen_sys[i].is_line_or_ray()) 00506 return false; 00507 00508 // The system of generators is composed only by 00509 // points and closure points: the polyhedron is bounded. 00510 return true; 00511 }
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 560 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Constraint::coefficient(), constraints(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Constraint::EQUALITY, Parma_Polyhedra_Library::gcd_assign(), gen_sys, generators_are_up_to_date(), has_pending_constraints(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::is_canonical(), Parma_Polyhedra_Library::Checked::le(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_rows(), process_pending(), space_dim, Parma_Polyhedra_Library::Constraint::STRICT_INEQUALITY, TEMP_INTEGER, and Parma_Polyhedra_Library::Constraint::type().
00560 { 00561 // Any empty polyhedron does not contain integer points. 00562 if (marked_empty()) 00563 return false; 00564 00565 // A zero-dimensional, universe polyhedron has, by convention, an 00566 // integer point. 00567 if (space_dim == 0) 00568 return true; 00569 00570 // CHECKME: do we really want to call conversion to check for emptiness? 00571 if (has_pending_constraints() && !process_pending()) 00572 // Empty again. 00573 return true; 00574 00575 // FIXME: do also exploit info regarding rays and lines, if possible. 00576 // Is any integer point already available? 00577 if (generators_are_up_to_date() && !has_pending_constraints()) 00578 for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) 00579 if (gen_sys[i].is_point() && gen_sys[i].divisor() == 1) 00580 return true; 00581 00582 const Constraint_System& cs = constraints(); 00583 #if 0 // TEMPORARILY DISABLED. 00584 MIP_Problem mip(space_dim, 00585 cs.begin(), cs.end(), 00586 Variables_Set(Variable(0), Variable(space_dim-1))); 00587 #else 00588 // FIXME: temporary workaround, to be removed as soon as the MIP 00589 // problem class will correctly and precisely handle 00590 // ((strict) in-) equality constraints having all integer variables. 00591 MIP_Problem mip(space_dim); 00592 mip.add_to_integer_space_dimensions(Variables_Set(Variable(0), 00593 Variable(space_dim-1))); 00594 TEMP_INTEGER(homogeneous_gcd); 00595 TEMP_INTEGER(gcd); 00596 DIRTY_TEMP0(mpq_class, rational_inhomogeneous); 00597 TEMP_INTEGER(tightened_inhomogeneous); 00598 for (Constraint_System::const_iterator cs_i = cs.begin(), 00599 cs_end = cs.end(); cs_i != cs_end; ++cs_i) { 00600 const Constraint& c = *cs_i; 00601 const Constraint::Type c_type = c.type(); 00602 const Coefficient& inhomogeneous = c.inhomogeneous_term(); 00603 if (c_type == Constraint::STRICT_INEQUALITY) { 00604 // CHECKME: should we change the behavior of Linear_Expression(c) ? 00605 // Compute the GCD of the coefficients of c 00606 // (disregarding the inhomogeneous term and the espilon dimension). 00607 homogeneous_gcd = 0; 00608 for (dimension_type i = space_dim; i-- > 0; ) 00609 gcd_assign(homogeneous_gcd, 00610 homogeneous_gcd, c.coefficient(Variable(i))); 00611 Linear_Expression le; 00612 for (dimension_type i = space_dim; i-- > 0; ) 00613 le += (c.coefficient(Variable(i)) / homogeneous_gcd) * Variable(i); 00614 // Add the integer part of `inhomogeneous'. 00615 le += (inhomogeneous / homogeneous_gcd); 00616 // Further tighten the constraint if the inhomogeneous term 00617 // was integer, i.e., if `homogeneous_gcd' divides `inhomogeneous'. 00618 gcd_assign(gcd, homogeneous_gcd, inhomogeneous); 00619 if (gcd == homogeneous_gcd) 00620 le -= 1; 00621 mip.add_constraint(le >= 0); 00622 } 00623 else { 00624 // Equality or non-strict inequality. 00625 // If possible, avoid useless gcd computations. 00626 if (inhomogeneous == 0) 00627 // The inhomogeneous term cannot be tightened. 00628 mip.add_constraint(c); 00629 else { 00630 // Compute the GCD of the coefficients of c 00631 // (disregarding the inhomogeneous term) 00632 // to see whether or not the inhomogeneous term can be tightened. 00633 homogeneous_gcd = 0; 00634 for (dimension_type i = space_dim; i-- > 0; ) 00635 gcd_assign(homogeneous_gcd, 00636 homogeneous_gcd, c.coefficient(Variable(i))); 00637 if (homogeneous_gcd == 1) 00638 // The normalized inhomogeneous term is integer: 00639 // add the constraint as-is. 00640 mip.add_constraint(c); 00641 else { 00642 assert(homogeneous_gcd > 1); 00643 // Here the normalized inhomogeneous term is rational: 00644 // the constraint has to be tightened. 00645 #ifndef NDEBUG 00646 // `homogeneous_gcd' does not divide `inhomogeneous'. 00647 // FIXME: add a divisibility test for Coefficient. 00648 gcd_assign(gcd, homogeneous_gcd, inhomogeneous); 00649 assert(gcd == 1); 00650 #endif 00651 if (c.type() == Constraint::EQUALITY) 00652 return false; 00653 // Extract the homogeneous part of the constraint. 00654 Linear_Expression le = Linear_Expression(c); 00655 le -= inhomogeneous; 00656 // Tighten the inhomogeneous term. 00657 assign_r(rational_inhomogeneous.get_num(), 00658 inhomogeneous, ROUND_NOT_NEEDED); 00659 assign_r(rational_inhomogeneous.get_den(), 00660 homogeneous_gcd, ROUND_NOT_NEEDED); 00661 // Note: canonicalization is not needed (as gcd == 1). 00662 assert(is_canonical(rational_inhomogeneous)); 00663 assign_r(tightened_inhomogeneous, 00664 rational_inhomogeneous, ROUND_DOWN); 00665 tightened_inhomogeneous *= homogeneous_gcd; 00666 le += tightened_inhomogeneous; 00667 mip.add_constraint(le >= 0); 00668 } 00669 } 00670 } 00671 } 00672 #endif // TEMPORARY WORKAROUND. 00673 return mip.is_satisfiable(); 00674 }
bool Parma_Polyhedra_Library::Polyhedron::constrains | ( | Variable | var | ) | const |
Returns true
if and only if var
is constrained in *this
.
std::invalid_argument | Thrown if var is not a space dimension of *this . |
Definition at line 677 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Linear_Row::coefficient(), con_sys, constraints_are_up_to_date(), Parma_Polyhedra_Library::Linear_System::first_pending_row(), gen_sys, generators_are_minimized(), generators_are_up_to_date(), has_pending_constraints(), has_pending_generators(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Generator::is_line(), Parma_Polyhedra_Library::Generator::is_line_or_ray(), marked_empty(), minimize(), Parma_Polyhedra_Library::Matrix::num_rows(), process_pending_generators(), space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), throw_dimension_incompatible(), and update_constraints().
00677 { 00678 // `var' should be one of the dimensions of the polyhedron. 00679 const dimension_type var_space_dim = var.space_dimension(); 00680 if (space_dim < var_space_dim) 00681 throw_dimension_incompatible("constrains(v)", "v", var); 00682 00683 // An empty polyhedron constrains all variables. 00684 if (marked_empty()) 00685 return true; 00686 00687 if (generators_are_up_to_date() && !has_pending_constraints()) { 00688 // Since generators are up-to-date and there are no pending 00689 // constraints, the generator system (since it is well formed) 00690 // contains a point. Hence the polyhedron is not empty. 00691 if (constraints_are_up_to_date() && !has_pending_generators()) 00692 // Here a variable is constrained if and only if it is 00693 // syntactically constrained. 00694 goto syntactic_check; 00695 00696 if (generators_are_minimized()) { 00697 // Try a quick, incomplete check for the universe polyhedron: 00698 // a universe polyhedron constrains no variable. 00699 // Count the number of non-pending 00700 // (hence, linearly independent) lines. 00701 dimension_type num_lines = 0; 00702 const dimension_type first_pending = gen_sys.first_pending_row(); 00703 for (dimension_type i = first_pending; i-- > 0; ) 00704 if (gen_sys[i].is_line()) 00705 ++num_lines; 00706 00707 if (num_lines == space_dim) 00708 return false; 00709 } 00710 00711 // Scan generators: perhaps we will find a generator equivalent to 00712 // line(var) or a pair of generators equivalent to ray(-var) and 00713 // ray(var). 00714 bool have_positive_ray = false; 00715 bool have_negative_ray = false; 00716 const dimension_type var_id = var.id(); 00717 for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) { 00718 const Generator& gen_sys_i = gen_sys[i]; 00719 if (gen_sys_i.is_line_or_ray()) { 00720 const Linear_Row& row = gen_sys_i; 00721 const int sign = sgn(row.coefficient(var_id)); 00722 if (sign != 0) { 00723 for (dimension_type j = space_dim+1; --j > 0; ) 00724 if (j != var_id && row[j] != 0) 00725 goto next; 00726 if (gen_sys_i.is_line()) 00727 return true; 00728 if (sign > 0) 00729 if (have_negative_ray) 00730 return true; 00731 else 00732 have_positive_ray = true; 00733 else if (have_positive_ray) 00734 return true; 00735 else 00736 have_negative_ray = true; 00737 } 00738 } 00739 next: 00740 ; 00741 } 00742 00743 // We are still here: at least we know that, since generators are 00744 // up-to-date and there are no pending constraints, then the 00745 // generator system (since it is well formed) contains a point. 00746 // Hence the polyhedron is not empty. 00747 if (has_pending_generators()) 00748 process_pending_generators(); 00749 else if (!constraints_are_up_to_date()) 00750 update_constraints(); 00751 goto syntactic_check; 00752 } 00753 00754 // We must minimize to detect emptiness and obtain constraints. 00755 if (!minimize()) 00756 return true; 00757 00758 syntactic_check: 00759 for (dimension_type i = con_sys.num_rows(); i-- > 0; ) 00760 if (con_sys[i].coefficient(var) != 0) 00761 return true; 00762 return false; 00763 }
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
.
std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
Definition at line 305 of file Polyhedron.inlines.hh.
References bounds().
00305 { 00306 return bounds(expr, true); 00307 }
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
.
std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
Definition at line 310 of file Polyhedron.inlines.hh.
References bounds().
00310 { 00311 return bounds(expr, false); 00312 }
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.
expr | The linear expression to be maximized subject to *this ; | |
sup_n | The numerator of the supremum value; | |
sup_d | The denominator of the supremum value; | |
maximum | true if and only if the supremum is also the maximum value. |
std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
*this
is empty or expr
is not bounded from above, false
is returned and sup_n
, sup_d
and maximum
are left untouched.
Definition at line 315 of file Polyhedron.inlines.hh.
References max_min().
00317 { 00318 Generator g(point()); 00319 return max_min(expr, true, sup_n, sup_d, maximum, g); 00320 }
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.
expr | The linear expression to be maximized subject to *this ; | |
sup_n | The numerator of the supremum value; | |
sup_d | The denominator of the supremum value; | |
maximum | true if and only if the supremum is also the maximum value; | |
g | When maximization succeeds, will be assigned the point or closure point where expr reaches its supremum value. |
std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
*this
is empty or expr
is not bounded from above, false
is returned and sup_n
, sup_d
, maximum
and g
are left untouched.
Definition at line 323 of file Polyhedron.inlines.hh.
References max_min().
00325 { 00326 return max_min(expr, true, sup_n, sup_d, maximum, g); 00327 }
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.
expr | The linear expression to be minimized subject to *this ; | |
inf_n | The numerator of the infimum value; | |
inf_d | The denominator of the infimum value; | |
minimum | true if and only if the infimum is also the minimum value. |
std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
*this
is empty or expr
is not bounded from below, false
is returned and inf_n
, inf_d
and minimum
are left untouched.
Definition at line 330 of file Polyhedron.inlines.hh.
References max_min().
Referenced by Parma_Polyhedra_Library::BHRZ03_Certificate::BHRZ03_Certificate(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHRZ03_widening_assign(), Parma_Polyhedra_Library::H79_Certificate::compare(), Parma_Polyhedra_Library::BHRZ03_Certificate::compare(), Parma_Polyhedra_Library::Grid::Grid(), Parma_Polyhedra_Library::H79_Certificate::H79_Certificate(), H79_widening_assign(), intersection_assign_and_minimize(), is_included_in(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), poly_difference_assign(), poly_hull_assign_and_minimize(), and simplify_using_context_assign().
00332 { 00333 Generator g(point()); 00334 return max_min(expr, false, inf_n, inf_d, minimum, g); 00335 }
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.
expr | The linear expression to be minimized subject to *this ; | |
inf_n | The numerator of the infimum value; | |
inf_d | The denominator of the infimum value; | |
minimum | true if and only if the infimum is also the minimum value; | |
g | When minimization succeeds, will be assigned a point or closure point where expr reaches its infimum value. |
std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
*this
is empty or expr
is not bounded from below, false
is returned and inf_n
, inf_d
, minimum
and g
are left untouched.
Definition at line 338 of file Polyhedron.inlines.hh.
References max_min().
00340 { 00341 return max_min(expr, false, inf_n, inf_d, minimum, g); 00342 }
bool Parma_Polyhedra_Library::Polyhedron::contains | ( | const Polyhedron & | y | ) | const |
Returns true
if and only if *this
contains y
.
std::invalid_argument | Thrown if *this and y are topology-incompatible or dimension-incompatible. |
Definition at line 3786 of file Polyhedron_public.cc.
References is_empty(), is_included_in(), marked_empty(), quick_equivalence_test(), space_dim, throw_dimension_incompatible(), throw_topology_incompatible(), topology(), and TVB_TRUE.
Referenced by BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHRZ03_widening_assign(), Parma_Polyhedra_Library::Pointset_Powerset< PS >::check_containment(), H79_widening_assign(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), poly_difference_assign(), poly_hull_assign_if_exact(), and strictly_contains().
03786 { 03787 const Polyhedron& x = *this; 03788 03789 // Topology compatibility check. 03790 if (x.topology() != y.topology()) 03791 throw_topology_incompatible("contains(y)", "y", y); 03792 03793 // Dimension-compatibility check. 03794 if (x.space_dim != y.space_dim) 03795 throw_dimension_incompatible("contains(y)", "y", y); 03796 03797 if (y.marked_empty()) 03798 return true; 03799 else if (x.marked_empty()) 03800 return y.is_empty(); 03801 else if (y.space_dim == 0) 03802 return true; 03803 else if (x.quick_equivalence_test(y) == Polyhedron::TVB_TRUE) 03804 return true; 03805 else 03806 return y.is_included_in(x); 03807 }
bool Parma_Polyhedra_Library::Polyhedron::strictly_contains | ( | const Polyhedron & | y | ) | const [inline] |
Returns true
if and only if *this
strictly contains y
.
std::invalid_argument | Thrown if *this and y are topology-incompatible or dimension-incompatible. |
Definition at line 399 of file Polyhedron.inlines.hh.
References contains().
00399 { 00400 const Polyhedron& x = *this; 00401 return x.contains(y) && !y.contains(x); 00402 }
bool Parma_Polyhedra_Library::Polyhedron::OK | ( | bool | check_not_empty = false |
) | const |
Checks if all the invariants are satisfied.
true
if and only if *this
satisfies all the invariants and either check_not_empty
is false
or *this
is not empty.check_not_empty | true if and only if, in addition to checking the invariants, *this must be checked to be not empty. |
std::cerr
in case invariants are violated. This is useful for the purpose of debugging the library.
Definition at line 766 of file Polyhedron_public.cc.
References ascii_dump(), Parma_Polyhedra_Library::Constraint_System::ascii_dump(), Parma_Polyhedra_Library::Generator_System::ascii_dump(), con_sys, constraints_are_minimized(), constraints_are_up_to_date(), empty, Parma_Polyhedra_Library::Matrix::erase_to_end(), Parma_Polyhedra_Library::Linear_System::first_pending_row(), gen_sys, generators_are_minimized(), generators_are_up_to_date(), Parma_Polyhedra_Library::Matrix::has_no_rows(), has_pending_constraints(), has_pending_generators(), Parma_Polyhedra_Library::Generator_System::has_points(), has_something_pending(), is_necessarily_closed(), marked_empty(), minimize(), Parma_Polyhedra_Library::Bit_Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Constraint_System::num_equalities(), Parma_Polyhedra_Library::Generator_System::num_lines(), Parma_Polyhedra_Library::Linear_System::num_pending_rows(), Parma_Polyhedra_Library::Generator_System::num_rays(), Parma_Polyhedra_Library::Bit_Matrix::num_rows(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Constraint_System::OK(), Parma_Polyhedra_Library::Generator_System::OK(), Parma_Polyhedra_Library::Polyhedron::Status::OK(), Parma_Polyhedra_Library::Bit_Matrix::OK(), sat_c, sat_c_is_up_to_date(), sat_g, sat_g_is_up_to_date(), Parma_Polyhedra_Library::Scalar_Products::sign(), Parma_Polyhedra_Library::Constraint_System::simplify(), Parma_Polyhedra_Library::Linear_System::sort_rows(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), status, Parma_Polyhedra_Library::Linear_System::strong_normalize(), topology(), Parma_Polyhedra_Library::Linear_System::topology(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
Referenced by add_generator(), add_recycled_constraints(), add_recycled_generators(), add_recycled_generators_and_minimize(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_image(), affine_preimage(), ascii_load(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHRZ03_widening_assign(), bounded_affine_image(), bounded_affine_preimage(), Parma_Polyhedra_Library::C_Polyhedron::C_Polyhedron(), concatenate_assign(), expand_space_dimension(), fold_space_dimensions(), generalized_affine_image(), generalized_affine_preimage(), H79_widening_assign(), intersection_assign(), intersection_assign_and_minimize(), is_included_in(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), map_space_dimensions(), minimize(), Parma_Polyhedra_Library::NNC_Polyhedron::NNC_Polyhedron(), poly_difference_assign(), poly_hull_assign(), poly_hull_assign_and_minimize(), Polyhedron(), process_pending_constraints(), process_pending_generators(), refine_no_check(), refine_with_constraints(), remove_higher_space_dimensions(), remove_pending_to_obtain_constraints(), remove_pending_to_obtain_generators(), remove_space_dimensions(), simplify_using_context_assign(), strongly_minimize_constraints(), strongly_minimize_generators(), time_elapse_assign(), topological_closure_assign(), and unconstrain().
00766 { 00767 #ifndef NDEBUG 00768 using std::endl; 00769 using std::cerr; 00770 #endif 00771 00772 // The expected number of columns in the constraint and generator 00773 // systems, if they are not empty. 00774 const dimension_type poly_num_columns 00775 = space_dim + (is_necessarily_closed() ? 1 : 2); 00776 00777 // Check whether the topologies of `con_sys' and `gen_sys' agree. 00778 if (con_sys.topology() != gen_sys.topology()) { 00779 #ifndef NDEBUG 00780 cerr << "Constraints and generators have different topologies!" 00781 << endl; 00782 #endif 00783 goto bomb; 00784 } 00785 00786 // Check whether the saturation matrices are well-formed. 00787 if (!sat_c.OK()) 00788 goto bomb; 00789 if (!sat_g.OK()) 00790 goto bomb; 00791 00792 // Check whether the status information is legal. 00793 if (!status.OK()) 00794 goto bomb; 00795 00796 if (marked_empty()) { 00797 if (check_not_empty) { 00798 // The caller does not want the polyhedron to be empty. 00799 #ifndef NDEBUG 00800 cerr << "Empty polyhedron!" << endl; 00801 #endif 00802 goto bomb; 00803 } 00804 00805 // An empty polyhedron is allowed if the system of constraints 00806 // either has no rows or only contains an unsatisfiable constraint 00807 // and if it has no pending constraints or generators. 00808 if (has_something_pending()) { 00809 #ifndef NDEBUG 00810 cerr << "The polyhedron is empty, " 00811 << "but it has something pending" << endl; 00812 #endif 00813 goto bomb; 00814 } 00815 if (con_sys.has_no_rows()) 00816 return true; 00817 else { 00818 if (con_sys.space_dimension() != space_dim) { 00819 #ifndef NDEBUG 00820 cerr << "The polyhedron is in a space of dimension " 00821 << space_dim 00822 << " while the system of constraints is in a space of dimension " 00823 << con_sys.space_dimension() 00824 << endl; 00825 #endif 00826 goto bomb; 00827 } 00828 if (con_sys.num_rows() != 1) { 00829 #ifndef NDEBUG 00830 cerr << "The system of constraints for an empty polyhedron " 00831 << "has more then one row" 00832 << endl; 00833 #endif 00834 goto bomb; 00835 } 00836 if (!con_sys[0].is_inconsistent()) { 00837 #ifndef NDEBUG 00838 cerr << "Empty polyhedron with a satisfiable system of constraints" 00839 << endl; 00840 #endif 00841 goto bomb; 00842 } 00843 // Here we have only one, inconsistent constraint. 00844 return true; 00845 } 00846 } 00847 00848 // A zero-dimensional, non-empty polyhedron is legal only if the 00849 // system of constraint `con_sys' and the system of generators 00850 // `gen_sys' have no rows. 00851 if (space_dim == 0) { 00852 if (has_something_pending()) { 00853 #ifndef NDEBUG 00854 cerr << "Zero-dimensional polyhedron with something pending" 00855 << endl; 00856 #endif 00857 goto bomb; 00858 } 00859 if (!con_sys.has_no_rows() || !gen_sys.has_no_rows()) { 00860 #ifndef NDEBUG 00861 cerr << "Zero-dimensional polyhedron with a non-empty" 00862 << endl 00863 << "system of constraints or generators." 00864 << endl; 00865 #endif 00866 goto bomb; 00867 } 00868 return true; 00869 } 00870 00871 // A polyhedron is defined by a system of constraints 00872 // or a system of generators: at least one of them must be up to date. 00873 if (!constraints_are_up_to_date() && !generators_are_up_to_date()) { 00874 #ifndef NDEBUG 00875 cerr << "Polyhedron not empty, not zero-dimensional" 00876 << endl 00877 << "and with neither constraints nor generators up-to-date!" 00878 << endl; 00879 #endif 00880 goto bomb; 00881 } 00882 00883 // Here we check if the size of the matrices is consistent. 00884 // Let us suppose that all the matrices are up-to-date; this means: 00885 // `con_sys' : number of constraints x poly_num_columns 00886 // `gen_sys' : number of generators x poly_num_columns 00887 // `sat_c' : number of generators x number of constraints 00888 // `sat_g' : number of constraints x number of generators. 00889 if (constraints_are_up_to_date()) { 00890 if (con_sys.num_columns() != poly_num_columns) { 00891 #ifndef NDEBUG 00892 cerr << "Incompatible size! (con_sys and space_dim)" 00893 << endl; 00894 #endif 00895 goto bomb; 00896 } 00897 if (sat_c_is_up_to_date()) 00898 if (con_sys.first_pending_row() != sat_c.num_columns()) { 00899 #ifndef NDEBUG 00900 cerr << "Incompatible size! (con_sys and sat_c)" 00901 << endl; 00902 #endif 00903 goto bomb; 00904 } 00905 if (sat_g_is_up_to_date()) 00906 if (con_sys.first_pending_row() != sat_g.num_rows()) { 00907 #ifndef NDEBUG 00908 cerr << "Incompatible size! (con_sys and sat_g)" 00909 << endl; 00910 #endif 00911 goto bomb; 00912 } 00913 if (generators_are_up_to_date()) 00914 if (con_sys.num_columns() != gen_sys.num_columns()) { 00915 #ifndef NDEBUG 00916 cerr << "Incompatible size! (con_sys and gen_sys)" 00917 << endl; 00918 #endif 00919 goto bomb; 00920 } 00921 } 00922 00923 if (generators_are_up_to_date()) { 00924 if (gen_sys.num_columns() != poly_num_columns) { 00925 #ifndef NDEBUG 00926 cerr << "Incompatible size! (gen_sys and space_dim)" 00927 << endl; 00928 #endif 00929 goto bomb; 00930 } 00931 if (sat_c_is_up_to_date()) 00932 if (gen_sys.first_pending_row() != sat_c.num_rows()) { 00933 #ifndef NDEBUG 00934 cerr << "Incompatible size! (gen_sys and sat_c)" 00935 << endl; 00936 #endif 00937 goto bomb; 00938 } 00939 if (sat_g_is_up_to_date()) 00940 if (gen_sys.first_pending_row() != sat_g.num_columns()) { 00941 #ifndef NDEBUG 00942 cerr << "Incompatible size! (gen_sys and sat_g)" 00943 << endl; 00944 #endif 00945 goto bomb; 00946 } 00947 00948 // Check if the system of generators is well-formed. 00949 if (!gen_sys.OK()) 00950 goto bomb; 00951 00952 if (gen_sys.first_pending_row() == 0) { 00953 #ifndef NDEBUG 00954 cerr << "Up-to-date generator system with all rows pending!" 00955 << endl; 00956 #endif 00957 goto bomb; 00958 } 00959 00960 // A non-empty system of generators describing a polyhedron 00961 // is valid if and only if it contains a point. 00962 if (!gen_sys.has_no_rows() && !gen_sys.has_points()) { 00963 #ifndef NDEBUG 00964 cerr << "Non-empty generator system declared up-to-date " 00965 << "has no points!" 00966 << endl; 00967 #endif 00968 goto bomb; 00969 } 00970 00971 #if 0 // To be activated when Status keeps strong minimization flags. 00972 //================================================= 00973 // TODO: this test is wrong in the general case. 00974 // However, such an invariant does hold for a 00975 // strongly-minimized Generator_System. 00976 // We will activate this test as soon as the Status 00977 // flags will be able to remember if a system is 00978 // strongly minimized. 00979 00980 // Checking that the number of closure points is always 00981 // greater than the number of points. 00982 if (!is_necessarily_closed()) { 00983 dimension_type num_points = 0; 00984 dimension_type num_closure_points = 0; 00985 dimension_type eps_index = gen_sys.num_columns() - 1; 00986 for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) 00987 if (!gen_sys[i].is_line_or_ray()) 00988 if (gen_sys[i][eps_index] > 0) 00989 ++num_points; 00990 else 00991 ++num_closure_points; 00992 if (num_points > num_closure_points) { 00993 #ifndef NDEBUG 00994 cerr << "# POINTS > # CLOSURE_POINTS" << endl; 00995 #endif 00996 goto bomb; 00997 } 00998 } 00999 //================================================= 01000 #endif 01001 01002 if (generators_are_minimized()) { 01003 // If the system of generators is minimized, the number of 01004 // lines, rays and points of the polyhedron must be the same as 01005 // of a temporary, minimized one. If this does not happen then 01006 // the polyhedron is not OK. 01007 Constraint_System new_con_sys(topology()); 01008 Generator_System gs_without_pending = gen_sys; 01009 gs_without_pending.erase_to_end(gen_sys.first_pending_row()); 01010 gs_without_pending.unset_pending_rows(); 01011 Generator_System copy_of_gen_sys = gs_without_pending; 01012 Bit_Matrix new_sat_c; 01013 minimize(false, copy_of_gen_sys, new_con_sys, new_sat_c); 01014 const dimension_type copy_num_lines = copy_of_gen_sys.num_lines(); 01015 if (gs_without_pending.num_rows() != copy_of_gen_sys.num_rows() 01016 || gs_without_pending.num_lines() != copy_num_lines 01017 || gs_without_pending.num_rays() != copy_of_gen_sys.num_rays()) { 01018 #ifndef NDEBUG 01019 cerr << "Generators are declared minimized, but they are not!\n" 01020 << "Here is the minimized form of the generators:\n"; 01021 copy_of_gen_sys.ascii_dump(cerr); 01022 cerr << endl; 01023 #endif 01024 goto bomb; 01025 } 01026 01027 // CHECKME : the following observation is not formally true 01028 // for a NNC_Polyhedron. But it may be true for its 01029 // representation ... 01030 01031 // If the corresponding polyhedral cone is _pointed_, then 01032 // a minimal system of generators is unique up to positive scaling. 01033 // We thus verify if the cone is pointed (i.e., there are no lines) 01034 // and, after normalizing and sorting a copy of the system `gen_sys' 01035 // of the polyhedron (we use a copy not to modify the polyhedron's 01036 // system) and the system `copy_of_gen_sys' that has been just 01037 // minimized, we check if the two matrices are identical. If 01038 // they are different it means that the generators of the 01039 // polyhedron are declared minimized, but they are not. 01040 if (copy_num_lines == 0) { 01041 copy_of_gen_sys.strong_normalize(); 01042 copy_of_gen_sys.sort_rows(); 01043 gs_without_pending.strong_normalize(); 01044 gs_without_pending.sort_rows(); 01045 if (copy_of_gen_sys != gs_without_pending) { 01046 #ifndef NDEBUG 01047 cerr << "Generators are declared minimized, but they are not!\n" 01048 << "(we are in the case:\n" 01049 << "dimension of lineality space equal to 0)\n" 01050 << "Here is the minimized form of the generators:\n"; 01051 copy_of_gen_sys.ascii_dump(cerr); 01052 cerr << endl; 01053 #endif 01054 goto bomb; 01055 } 01056 } 01057 } 01058 } 01059 01060 if (constraints_are_up_to_date()) { 01061 // Check if the system of constraints is well-formed. 01062 if (!con_sys.OK()) 01063 goto bomb; 01064 01065 if (con_sys.first_pending_row() == 0) { 01066 #ifndef NDEBUG 01067 cerr << "Up-to-date constraint system with all rows pending!" 01068 << endl; 01069 #endif 01070 goto bomb; 01071 } 01072 01073 // A non-empty system of constraints describing a polyhedron 01074 // must contain a constraint with a non-zero inhomogeneous term; 01075 // such a constraint corresponds to (a combination of other 01076 // constraints with): 01077 // -* the positivity constraint, for necessarily closed polyhedra; 01078 // -* the epsilon <= 1 constraint, for NNC polyhedra. 01079 bool no_positivity_constraint = true; 01080 for (dimension_type i = con_sys.num_rows(); i-- > 0; ) 01081 if (con_sys[i].inhomogeneous_term() != 0) { 01082 no_positivity_constraint = false; 01083 break; 01084 } 01085 if (no_positivity_constraint) { 01086 #ifndef NDEBUG 01087 cerr << "Non-empty constraint system has no positivity constraint" 01088 << endl; 01089 #endif 01090 goto bomb; 01091 } 01092 01093 if (!is_necessarily_closed()) { 01094 // A non-empty system of constraints describing a NNC polyhedron 01095 // must also contain a (combination of) the constraint epsilon >= 0, 01096 // i.e., a constraint with a positive epsilon coefficient. 01097 bool no_epsilon_geq_zero = true; 01098 const dimension_type eps_index = con_sys.num_columns() - 1; 01099 for (dimension_type i = con_sys.num_rows(); i-- > 0; ) 01100 if (con_sys[i][eps_index] > 0) { 01101 no_epsilon_geq_zero = false; 01102 break; 01103 } 01104 if (no_epsilon_geq_zero) { 01105 #ifndef NDEBUG 01106 cerr << "Non-empty constraint system for NNC polyhedron " 01107 << "has no epsilon >= 0 constraint" 01108 << endl; 01109 #endif 01110 goto bomb; 01111 } 01112 } 01113 01114 Constraint_System cs_without_pending = con_sys; 01115 cs_without_pending.erase_to_end(con_sys.first_pending_row()); 01116 cs_without_pending.unset_pending_rows(); 01117 Constraint_System copy_of_con_sys = cs_without_pending; 01118 bool empty = false; 01119 if (check_not_empty || constraints_are_minimized()) { 01120 Generator_System new_gen_sys(topology()); 01121 Bit_Matrix new_sat_g; 01122 empty = minimize(true, copy_of_con_sys, new_gen_sys, new_sat_g); 01123 } 01124 01125 if (empty && check_not_empty) { 01126 #ifndef NDEBUG 01127 cerr << "Unsatisfiable system of constraints!" 01128 << endl; 01129 #endif 01130 goto bomb; 01131 } 01132 01133 if (constraints_are_minimized()) { 01134 // If the constraints are minimized, the number of equalities 01135 // and of inequalities of the system of the polyhedron must be 01136 // the same of the temporary minimized one. 01137 // If it does not happen, the polyhedron is not OK. 01138 if (cs_without_pending.num_rows() != copy_of_con_sys.num_rows() 01139 || cs_without_pending.num_equalities() 01140 != copy_of_con_sys.num_equalities()) { 01141 #ifndef NDEBUG 01142 cerr << "Constraints are declared minimized, but they are not!\n" 01143 << "Here is the minimized form of the constraints:\n"; 01144 copy_of_con_sys.ascii_dump(cerr); 01145 cerr << endl; 01146 #endif 01147 goto bomb; 01148 } 01149 // The system `copy_of_con_sys' has the form that is obtained 01150 // after applying methods gauss() and back_substitute(). 01151 // A system of constraints can be minimal even if it does not 01152 // have this form. So, to verify if the polyhedron is correct, 01153 // we copy the system `con_sys' in a temporary one and then 01154 // modify it using method simplify() (which calls both gauss() 01155 // and back_substitute()). 01156 // If the temporary system and `copy_of_con_sys' are different, 01157 // the polyhedron is not OK. 01158 copy_of_con_sys.strong_normalize(); 01159 copy_of_con_sys.sort_rows(); 01160 cs_without_pending.simplify(); 01161 cs_without_pending.strong_normalize(); 01162 cs_without_pending.sort_rows(); 01163 if (cs_without_pending != copy_of_con_sys) { 01164 #ifndef NDEBUG 01165 cerr << "Constraints are declared minimized, but they are not!\n" 01166 << "Here is the minimized form of the constraints:\n"; 01167 copy_of_con_sys.ascii_dump(cerr); 01168 cerr << endl; 01169 #endif 01170 goto bomb; 01171 } 01172 } 01173 } 01174 01175 if (sat_c_is_up_to_date()) 01176 for (dimension_type i = sat_c.num_rows(); i-- > 0; ) { 01177 const Generator tmp_gen = gen_sys[i]; 01178 const Bit_Row tmp_sat = sat_c[i]; 01179 for (dimension_type j = sat_c.num_columns(); j-- > 0; ) 01180 if (Scalar_Products::sign(con_sys[j], tmp_gen) != tmp_sat[j]) { 01181 #ifndef NDEBUG 01182 cerr << "sat_c is declared up-to-date, but it is not!" 01183 << endl; 01184 #endif 01185 goto bomb; 01186 } 01187 } 01188 01189 if (sat_g_is_up_to_date()) 01190 for (dimension_type i = sat_g.num_rows(); i-- > 0; ) { 01191 const Constraint tmp_con = con_sys[i]; 01192 const Bit_Row tmp_sat = sat_g[i]; 01193 for (dimension_type j = sat_g.num_columns(); j-- > 0; ) 01194 if (Scalar_Products::sign(tmp_con, gen_sys[j]) != tmp_sat[j]) { 01195 #ifndef NDEBUG 01196 cerr << "sat_g is declared up-to-date, but it is not!" 01197 << endl; 01198 #endif 01199 goto bomb; 01200 } 01201 } 01202 01203 if (has_pending_constraints()) { 01204 if (con_sys.num_pending_rows() == 0) { 01205 #ifndef NDEBUG 01206 cerr << "The polyhedron is declared to have pending constraints, " 01207 << "but con_sys has no pending rows!" 01208 << endl; 01209 #endif 01210 goto bomb; 01211 } 01212 } 01213 01214 if (has_pending_generators()) { 01215 if (gen_sys.num_pending_rows() == 0) { 01216 #ifndef NDEBUG 01217 cerr << "The polyhedron is declared to have pending generators, " 01218 << "but gen_sys has no pending rows!" 01219 << endl; 01220 #endif 01221 goto bomb; 01222 } 01223 } 01224 01225 return true; 01226 01227 bomb: 01228 #ifndef NDEBUG 01229 cerr << "Here is the guilty polyhedron:" 01230 << endl; 01231 ascii_dump(cerr); 01232 #endif 01233 return false; 01234 }
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).
c | The constraint that will be added to the system of constraints of *this . |
std::invalid_argument | Thrown if *this and constraint c are topology-incompatible or dimension-incompatible. |
Definition at line 1237 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Constraint::is_inconsistent(), is_necessarily_closed(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Constraint::is_tautological(), marked_empty(), refine_no_check(), set_empty(), space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), throw_dimension_incompatible(), and throw_topology_incompatible().
Referenced by Parma_Polyhedra_Library::Pointset_Powerset< PS >::affine_dimension(), Parma_Polyhedra_Library::C_Polyhedron::C_Polyhedron(), and Parma_Polyhedra_Library::Pointset_Powerset< PS >::linear_partition_aux().
01237 { 01238 // Topology-compatibility check. 01239 if (c.is_strict_inequality() && is_necessarily_closed()) { 01240 // Trivially true/false strict inequalities are legal. 01241 if (c.is_tautological()) 01242 return; 01243 if (c.is_inconsistent()) { 01244 set_empty(); 01245 return; 01246 } 01247 // Here c is a non-trivial strict inequality. 01248 throw_topology_incompatible("add_constraint(c)", "c", c); 01249 } 01250 01251 // Dimension-compatibility check: 01252 // the dimension of `c' can not be greater than space_dim. 01253 if (space_dim < c.space_dimension()) 01254 throw_dimension_incompatible("add_constraint(c)", "c", c); 01255 01256 if (!marked_empty()) 01257 refine_no_check(c); 01258 }
bool Parma_Polyhedra_Library::Polyhedron::add_constraint_and_minimize | ( | const Constraint & | c | ) |
Adds a copy of constraint c
to the system of constraints of *this
, minimizing the result.
c | The constraint that will be added to the system of constraints of *this . |
false
if and only if the result is empty.std::invalid_argument | Thrown if *this and constraint c are topology-incompatible or dimension-incompatible. |
Definition at line 1299 of file Polyhedron_public.cc.
References add_recycled_constraints_and_minimize().
01299 { 01300 Constraint_System cs(c); 01301 return add_recycled_constraints_and_minimize(cs); 01302 }
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).
std::invalid_argument | Thrown 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 1305 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Generator_System::adjust_topology_and_space_dimension(), can_have_something_pending(), clear_constraints_up_to_date(), clear_empty(), clear_generators_minimized(), Parma_Polyhedra_Library::Generator::divisor(), gen_sys, generators_are_up_to_date(), has_pending_constraints(), Parma_Polyhedra_Library::Generator_System::insert(), Parma_Polyhedra_Library::Generator_System::insert_pending(), Parma_Polyhedra_Library::Generator::is_closure_point(), Parma_Polyhedra_Library::Linear_Row::is_necessarily_closed(), is_necessarily_closed(), Parma_Polyhedra_Library::Generator::is_point(), Parma_Polyhedra_Library::Generator::line(), Parma_Polyhedra_Library::Generator::LINE, marked_empty(), Parma_Polyhedra_Library::Row::normalize(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), Parma_Polyhedra_Library::Generator::point(), Parma_Polyhedra_Library::Generator::POINT, process_pending_constraints(), Parma_Polyhedra_Library::Generator::ray(), Parma_Polyhedra_Library::Generator::RAY, set_generators_minimized(), set_generators_pending(), Parma_Polyhedra_Library::Polyhedron::Status::set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Generator::space_dimension(), status, throw_dimension_incompatible(), throw_invalid_generator(), throw_runtime_error(), throw_topology_incompatible(), topology(), Parma_Polyhedra_Library::Generator::type(), and update_generators().
Referenced by generalized_affine_image().
01305 { 01306 // Topology-compatibility check. 01307 if (g.is_closure_point() && is_necessarily_closed()) 01308 throw_topology_incompatible("add_generator(g)", "g", g); 01309 // Dimension-compatibility check: 01310 // the dimension of `g' can not be greater than space_dim. 01311 const dimension_type g_space_dim = g.space_dimension(); 01312 if (space_dim < g_space_dim) 01313 throw_dimension_incompatible("add_generator(g)", "g", g); 01314 01315 // Dealing with a zero-dimensional space polyhedron first. 01316 if (space_dim == 0) { 01317 // It is not possible to create 0-dim rays or lines. 01318 assert(g.is_point() || g.is_closure_point()); 01319 // Closure points can only be inserted in non-empty polyhedra. 01320 if (marked_empty()) { 01321 if (g.type() != Generator::POINT) 01322 throw_invalid_generator("add_generator(g)", "g"); 01323 else 01324 status.set_zero_dim_univ(); 01325 } 01326 assert(OK()); 01327 return; 01328 } 01329 01330 if (marked_empty() 01331 || (has_pending_constraints() && !process_pending_constraints()) 01332 || (!generators_are_up_to_date() && !update_generators())) { 01333 // Here the polyhedron is empty: 01334 // the specification says we can only insert a point. 01335 if (!g.is_point()) 01336 throw_invalid_generator("add_generator(g)", "g"); 01337 if (g.is_necessarily_closed() || !is_necessarily_closed()) { 01338 gen_sys.insert(g); 01339 // Since `gen_sys' was empty, after inserting `g' we have to resize 01340 // the system of generators to have the right dimension. 01341 gen_sys.adjust_topology_and_space_dimension(topology(), space_dim); 01342 if (!is_necessarily_closed()) { 01343 // In the NNC topology, each point has to be matched by 01344 // a corresponding closure point: 01345 // turn the just inserted point into the corresponding 01346 // (normalized) closure point. 01347 Generator& cp = gen_sys[gen_sys.num_rows() - 1]; 01348 cp[space_dim + 1] = 0; 01349 cp.normalize(); 01350 // Re-insert the point (which is already normalized). 01351 gen_sys.insert(g); 01352 } 01353 } 01354 else { 01355 // Note: here we have a _legal_ topology mismatch, 01356 // because `g' is NOT a closure point (it is a point!) 01357 // However, by barely invoking `gen_sys.insert(g)' we would 01358 // cause a change in the topology of `gen_sys', which is wrong. 01359 // Thus, we insert a "topology corrected" copy of `g'. 01360 const Linear_Expression nc_expr = Linear_Expression(g); 01361 gen_sys.insert(Generator::point(nc_expr, g.divisor())); 01362 // Since `gen_sys' was empty, after inserting `g' we have to resize 01363 // the system of generators to have the right dimension. 01364 gen_sys.adjust_topology_and_space_dimension(topology(), space_dim); 01365 } 01366 // No longer empty, generators up-to-date and minimized. 01367 clear_empty(); 01368 set_generators_minimized(); 01369 } 01370 else { 01371 assert(generators_are_up_to_date()); 01372 const bool has_pending = can_have_something_pending(); 01373 if (g.is_necessarily_closed() || !is_necessarily_closed()) { 01374 // Since `gen_sys' is not empty, the topology and space dimension 01375 // of the inserted generator are automatically adjusted. 01376 if (has_pending) 01377 gen_sys.insert_pending(g); 01378 else 01379 gen_sys.insert(g); 01380 if (!is_necessarily_closed() && g.is_point()) { 01381 // In the NNC topology, each point has to be matched by 01382 // a corresponding closure point: 01383 // turn the just inserted point into the corresponding 01384 // (normalized) closure point. 01385 Generator& cp = gen_sys[gen_sys.num_rows() - 1]; 01386 cp[space_dim + 1] = 0; 01387 cp.normalize(); 01388 // Re-insert the point (which is already normalized). 01389 if (has_pending) 01390 gen_sys.insert_pending(g); 01391 else 01392 gen_sys.insert(g); 01393 } 01394 } 01395 else { 01396 assert(!g.is_closure_point()); 01397 // Note: here we have a _legal_ topology mismatch, because 01398 // `g' is NOT a closure point. 01399 // However, by barely invoking `gen_sys.insert(g)' we would 01400 // cause a change in the topology of `gen_sys', which is wrong. 01401 // Thus, we insert a "topology corrected" copy of `g'. 01402 const Linear_Expression nc_expr = Linear_Expression(g); 01403 switch (g.type()) { 01404 case Generator::LINE: 01405 if (has_pending) 01406 gen_sys.insert_pending(Generator::line(nc_expr)); 01407 else 01408 gen_sys.insert(Generator::line(nc_expr)); 01409 break; 01410 case Generator::RAY: 01411 if (has_pending) 01412 gen_sys.insert_pending(Generator::ray(nc_expr)); 01413 else 01414 gen_sys.insert(Generator::ray(nc_expr)); 01415 break; 01416 case Generator::POINT: 01417 if (has_pending) 01418 gen_sys.insert_pending(Generator::point(nc_expr, g.divisor())); 01419 else 01420 gen_sys.insert(Generator::point(nc_expr, g.divisor())); 01421 break; 01422 default: 01423 throw_runtime_error("add_generator(const Generator& g)"); 01424 } 01425 } 01426 01427 if (has_pending) 01428 set_generators_pending(); 01429 else { 01430 // After adding the new generator, 01431 // constraints are no longer up-to-date. 01432 clear_generators_minimized(); 01433 clear_constraints_up_to_date(); 01434 } 01435 } 01436 assert(OK()); 01437 }
bool Parma_Polyhedra_Library::Polyhedron::add_generator_and_minimize | ( | const Generator & | g | ) |
Adds a copy of generator g
to the system of generators of *this
, minimizing the result.
false
if and only if the result is empty.std::invalid_argument | Thrown 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 1440 of file Polyhedron_public.cc.
References add_recycled_generators_and_minimize().
01440 { 01441 // TODO: this is just an executable specification. 01442 Generator_System gs(g); 01443 return add_recycled_generators_and_minimize(gs); 01444 }
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.
std::invalid_argument | Thrown 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 1261 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Constraint::EQUALITY, 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::Checked::le(), marked_empty(), Parma_Polyhedra_Library::NECESSARILY_CLOSED, refine_no_check(), set_empty(), space_dim, Parma_Polyhedra_Library::Congruence::space_dimension(), Parma_Polyhedra_Library::Linear_Row::strong_normalize(), throw_dimension_incompatible(), and throw_invalid_argument().
Referenced by add_congruence_and_minimize().
01261 { 01262 // Dimension-compatibility check: 01263 // the dimension of `cg' can not be greater than space_dim. 01264 if (space_dim < cg.space_dimension()) 01265 throw_dimension_incompatible("add_congruence(cg)", "cg", cg); 01266 01267 // Handle the case of proper congruences first. 01268 if (cg.is_proper_congruence()) { 01269 if (cg.is_tautological()) 01270 return; 01271 if (cg.is_inconsistent()) { 01272 set_empty(); 01273 return; 01274 } 01275 // Non-trivial and proper congruences are not allowed. 01276 throw_invalid_argument("add_congruence(cg)", 01277 "cg is a non-trivial, proper congruence"); 01278 } 01279 01280 assert(cg.is_equality()); 01281 // Handle empty and 0-dim cases first. 01282 if (marked_empty()) 01283 return; 01284 if (space_dim == 0) { 01285 if (cg.is_inconsistent()) 01286 set_empty(); 01287 return; 01288 } 01289 01290 // Add the equality. 01291 Linear_Expression le(cg); 01292 Constraint c(le, Constraint::EQUALITY, NECESSARILY_CLOSED); 01293 // Enforce normalization. 01294 c.strong_normalize(); 01295 refine_no_check(c); 01296 }
bool Parma_Polyhedra_Library::Polyhedron::add_congruence_and_minimize | ( | const Congruence & | cg | ) | [inline] |
Adds a copy of congruence cg
to *this
, if cg
can be exactly represented by a polyhedron, minimizing the result.
false
if and only if the result is empty.std::invalid_argument | Thrown 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 371 of file Polyhedron.inlines.hh.
References add_congruence(), and minimize().
00371 { 00372 add_congruence(cg); 00373 return minimize(); 00374 }
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).
cs | Contains the constraints that will be added to the system of constraints of *this . |
std::invalid_argument | Thrown if *this and cs are topology-incompatible or dimension-incompatible. |
Definition at line 1540 of file Polyhedron_public.cc.
References add_recycled_constraints().
Referenced by Parma_Polyhedra_Library::C_Polyhedron::C_Polyhedron(), Parma_Polyhedra_Library::NNC_Polyhedron::NNC_Polyhedron(), and simplify_using_context_assign().
01540 { 01541 // TODO: this is just an executable specification. 01542 Constraint_System cs_copy = cs; 01543 add_recycled_constraints(cs_copy); 01544 }
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).
cs | The constraint system to be added to *this . The constraints in cs may be recycled. |
std::invalid_argument | Thrown if *this and cs are topology-incompatible or dimension-incompatible. |
cs
upon successful or exceptional return is that it can be safely destroyed. Definition at line 1447 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Matrix::add_zero_rows(), Parma_Polyhedra_Library::Constraint_System::adjust_topology_and_space_dimension(), Parma_Polyhedra_Library::Constraint_System::begin(), can_have_something_pending(), clear_constraints_minimized(), clear_generators_up_to_date(), con_sys, constraints_are_up_to_date(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Matrix::has_no_rows(), has_pending_generators(), Parma_Polyhedra_Library::Constraint_System::has_strict_inequalities(), Parma_Polyhedra_Library::Constraint::is_equality(), is_necessarily_closed(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), process_pending_generators(), Parma_Polyhedra_Library::Linear_Row::RAY_OR_POINT_OR_INEQUALITY, set_constraints_pending(), Parma_Polyhedra_Library::Polyhedron::Status::set_empty(), set_empty(), Parma_Polyhedra_Library::Constraint::set_is_equality(), Parma_Polyhedra_Library::Linear_System::set_sorted(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), status, Parma_Polyhedra_Library::swap(), throw_dimension_incompatible(), throw_topology_incompatible(), topology(), Parma_Polyhedra_Library::Linear_System::unset_pending_rows(), and update_constraints().
Referenced by add_congruences(), add_constraints(), add_recycled_constraints_and_minimize(), BHRZ03_combining_constraints(), bounded_BHRZ03_extrapolation_assign(), bounded_H79_extrapolation_assign(), expand_space_dimension(), H79_widening_assign(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), refine_with_congruences(), and simplify_using_context_assign().
01447 { 01448 // Topology compatibility check. 01449 if (is_necessarily_closed() && cs.has_strict_inequalities()) { 01450 // We check if _all_ strict inequalities in cs are trivially false. 01451 // (The iterators already filter away trivially true constraints.) 01452 for (Constraint_System::const_iterator i = cs.begin(), 01453 i_end = cs.end(); i != i_end; ++i) { 01454 if (i->is_strict_inequality() 01455 && !i->is_inconsistent()) 01456 throw_topology_incompatible("add_recycled_constraints(cs)", 01457 "cs", cs); 01458 } 01459 // If we reach this point, all strict inequalities were inconsistent. 01460 set_empty(); 01461 return; 01462 } 01463 01464 // Dimension-compatibility check: 01465 // the dimension of `cs' can not be greater than space_dim. 01466 const dimension_type cs_space_dim = cs.space_dimension(); 01467 if (space_dim < cs_space_dim) 01468 throw_dimension_incompatible("add_recycled_constraints(cs)", "cs", cs); 01469 01470 // Adding no constraints is a no-op. 01471 if (cs.has_no_rows()) 01472 return; 01473 01474 if (space_dim == 0) { 01475 // In a 0-dimensional space the constraints are 01476 // tautologies (e.g., 0 == 0 or 1 >= 0 or 1 > 0) or 01477 // inconsistent (e.g., 1 == 0 or -1 >= 0 or 0 > 0). 01478 // In a system of constraints `begin()' and `end()' are equal 01479 // if and only if the system only contains tautologies. 01480 if (cs.begin() != cs.end()) 01481 // There is a constraint, it must be inconsistent, 01482 // the polyhedron is empty. 01483 status.set_empty(); 01484 return; 01485 } 01486 01487 if (marked_empty()) 01488 return; 01489 01490 // The constraints (possibly with pending rows) are required. 01491 if (has_pending_generators()) 01492 process_pending_generators(); 01493 else if (!constraints_are_up_to_date()) 01494 update_constraints(); 01495 01496 // Adjust `cs' to the right topology and space dimension. 01497 // NOTE: we already checked for topology compatibility. 01498 cs.adjust_topology_and_space_dimension(topology(), space_dim); 01499 01500 const bool adding_pending = can_have_something_pending(); 01501 01502 // Here we do not require `con_sys' to be sorted. 01503 // also, we _swap_ (instead of copying) the coefficients of `cs' 01504 // (which is not a const). 01505 const dimension_type old_num_rows = con_sys.num_rows(); 01506 const dimension_type cs_num_rows = cs.num_rows(); 01507 const dimension_type cs_num_columns = cs.num_columns(); 01508 con_sys.add_zero_rows(cs_num_rows, 01509 Linear_Row::Flags(topology(), 01510 Linear_Row::RAY_OR_POINT_OR_INEQUALITY)); 01511 for (dimension_type i = cs_num_rows; i-- > 0; ) { 01512 // NOTE: we cannot directly swap the rows, since they might have 01513 // different capacities (besides possibly having different sizes): 01514 // thus, we steal one coefficient at a time. 01515 Constraint& new_c = con_sys[old_num_rows + i]; 01516 Constraint& old_c = cs[i]; 01517 if (old_c.is_equality()) 01518 new_c.set_is_equality(); 01519 for (dimension_type j = cs_num_columns; j-- > 0; ) 01520 std::swap(new_c[j], old_c[j]); 01521 } 01522 01523 if (adding_pending) 01524 set_constraints_pending(); 01525 else { 01526 // The newly added ones are not pending constraints. 01527 con_sys.unset_pending_rows(); 01528 // They have been simply appended. 01529 con_sys.set_sorted(false); 01530 // Constraints are not minimized and generators are not up-to-date. 01531 clear_constraints_minimized(); 01532 clear_generators_up_to_date(); 01533 } 01534 // Note: the constraint system may have become unsatisfiable, thus 01535 // we do not check for satisfiability. 01536 assert(OK()); 01537 }
bool Parma_Polyhedra_Library::Polyhedron::add_constraints_and_minimize | ( | const Constraint_System & | cs | ) |
Adds a copy of the constraints in cs
to the system of constraints of *this
, minimizing the result.
false
if and only if the result is empty.cs | Contains the constraints that will be added to the system of constraints of *this . |
std::invalid_argument | Thrown if *this and cs are topology-incompatible or dimension-incompatible. |
Definition at line 1553 of file Polyhedron_public.cc.
References add_recycled_constraints_and_minimize().
01553 { 01554 Constraint_System cs_copy = cs; 01555 return add_recycled_constraints_and_minimize(cs_copy); 01556 }
bool Parma_Polyhedra_Library::Polyhedron::add_recycled_constraints_and_minimize | ( | Constraint_System & | cs | ) |
Adds the constraints in cs
to the system of constraints of *this
, minimizing the result.
false
if and only if the result is empty.cs | The constraint system to be added to *this . The constraints in cs may be recycled. |
std::invalid_argument | Thrown if *this and cs are topology-incompatible or dimension-incompatible. |
cs
upon successful or exceptional return is that it can be safely destroyed.Definition at line 1547 of file Polyhedron_public.cc.
References add_recycled_constraints(), and minimize().
Referenced by add_constraint_and_minimize(), and add_constraints_and_minimize().
01547 { 01548 add_recycled_constraints(cs); 01549 return minimize(); 01550 }
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).
gs | Contains the generators that will be added to the system of generators of *this . |
std::invalid_argument | Thrown 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 1652 of file Polyhedron_public.cc.
References add_recycled_generators().
01652 { 01653 // TODO: this is just an executable specification. 01654 Generator_System gs_copy = gs; 01655 add_recycled_generators(gs_copy); 01656 }
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).
gs | The generator system to be added to *this . The generators in gs may be recycled. |
std::invalid_argument | Thrown 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. |
gs
upon successful or exceptional return is that it can be safely destroyed. Definition at line 1559 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Generator_System::add_corresponding_closure_points(), Parma_Polyhedra_Library::Matrix::add_zero_rows(), Parma_Polyhedra_Library::Generator_System::adjust_topology_and_space_dimension(), can_have_something_pending(), clear_constraints_up_to_date(), clear_empty(), clear_generators_minimized(), gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Generator_System::has_closure_points(), Parma_Polyhedra_Library::Matrix::has_no_rows(), has_pending_constraints(), Parma_Polyhedra_Library::Generator_System::has_points(), Parma_Polyhedra_Library::Generator::is_line(), is_necessarily_closed(), marked_empty(), minimize(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Linear_System::num_pending_rows(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), process_pending_constraints(), Parma_Polyhedra_Library::Linear_Row::RAY_OR_POINT_OR_INEQUALITY, set_generators_pending(), set_generators_up_to_date(), Parma_Polyhedra_Library::Generator::set_is_line(), Parma_Polyhedra_Library::Linear_System::set_sorted(), Parma_Polyhedra_Library::Polyhedron::Status::set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Generator_System::space_dimension(), status, Parma_Polyhedra_Library::swap(), throw_dimension_incompatible(), throw_invalid_generators(), throw_topology_incompatible(), topology(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
Referenced by add_generators(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), generalized_affine_image(), and generalized_affine_preimage().
01559 { 01560 // Topology compatibility check. 01561 if (is_necessarily_closed() && gs.has_closure_points()) 01562 throw_topology_incompatible("add_recycled_generators(gs)", "gs", gs); 01563 // Dimension-compatibility check: 01564 // the dimension of `gs' can not be greater than space_dim. 01565 const dimension_type gs_space_dim = gs.space_dimension(); 01566 if (space_dim < gs_space_dim) 01567 throw_dimension_incompatible("add_recycled_generators(gs)", "gs", gs); 01568 01569 // Adding no generators is a no-op. 01570 if (gs.has_no_rows()) 01571 return; 01572 01573 // Adding valid generators to a zero-dimensional polyhedron 01574 // transform it in the zero-dimensional universe polyhedron. 01575 if (space_dim == 0) { 01576 if (marked_empty() && !gs.has_points()) 01577 throw_invalid_generators("add_recycled_generators(gs)", "gs"); 01578 status.set_zero_dim_univ(); 01579 assert(OK(true)); 01580 return; 01581 } 01582 01583 // Adjust `gs' to the right topology and dimensions. 01584 // NOTE: we already checked for topology compatibility. 01585 gs.adjust_topology_and_space_dimension(topology(), space_dim); 01586 // For NNC polyhedra, each point must be matched by 01587 // the corresponding closure point. 01588 if (!is_necessarily_closed()) 01589 gs.add_corresponding_closure_points(); 01590 01591 // The generators (possibly with pending rows) are required. 01592 if ((has_pending_constraints() && !process_pending_constraints()) 01593 || (!generators_are_up_to_date() && !minimize())) { 01594 // We have just discovered that `*this' is empty. 01595 // So `gs' must contain at least one point. 01596 if (!gs.has_points()) 01597 throw_invalid_generators("add_recycled_generators(gs)", "gs"); 01598 // The polyhedron is no longer empty and generators are up-to-date. 01599 std::swap(gen_sys, gs); 01600 if (gen_sys.num_pending_rows() > 0) { 01601 // Even though `gs' has pending generators, since the constraints 01602 // of the polyhedron are not up-to-date, the polyhedron cannot 01603 // have pending generators. By integrating the pending part 01604 // of `gen_sys' we may loose sortedness. 01605 gen_sys.unset_pending_rows(); 01606 gen_sys.set_sorted(false); 01607 } 01608 set_generators_up_to_date(); 01609 clear_empty(); 01610 assert(OK()); 01611 return; 01612 } 01613 01614 const bool adding_pending = can_have_something_pending(); 01615 01616 // Here we do not require `gen_sys' to be sorted. 01617 // also, we _swap_ (instead of copying) the coefficients of `gs' 01618 // (which is not a const). 01619 const dimension_type old_num_rows = gen_sys.num_rows(); 01620 const dimension_type gs_num_rows = gs.num_rows(); 01621 const dimension_type gs_num_columns = gs.num_columns(); 01622 gen_sys.add_zero_rows(gs_num_rows, 01623 Linear_Row::Flags(topology(), 01624 Linear_Row::RAY_OR_POINT_OR_INEQUALITY)); 01625 for (dimension_type i = gs_num_rows; i-- > 0; ) { 01626 // NOTE: we cannot directly swap the rows, since they might have 01627 // different capacities (besides possibly having different sizes): 01628 // thus, we steal one coefficient at a time. 01629 Generator& new_g = gen_sys[old_num_rows + i]; 01630 Generator& old_g = gs[i]; 01631 if (old_g.is_line()) 01632 new_g.set_is_line(); 01633 for (dimension_type j = gs_num_columns; j-- > 0; ) 01634 std::swap(new_g[j], old_g[j]); 01635 } 01636 01637 if (adding_pending) 01638 set_generators_pending(); 01639 else { 01640 // The newly added ones are not pending generators. 01641 gen_sys.unset_pending_rows(); 01642 // They have been simply appended. 01643 gen_sys.set_sorted(false); 01644 // Constraints are not up-to-date and generators are not minimized. 01645 clear_constraints_up_to_date(); 01646 clear_generators_minimized(); 01647 } 01648 assert(OK(true)); 01649 }
bool Parma_Polyhedra_Library::Polyhedron::add_generators_and_minimize | ( | const Generator_System & | gs | ) |
Adds a copy of the generators in gs
to the system of generators of *this
, minimizing the result.
false
if and only if the result is empty.gs | Contains the generators that will be added to the system of generators of *this . |
std::invalid_argument | Thrown if *this and gs are topology-incompatible or dimension-incompatible, or if *this is empty and the the system of generators gs is not empty, but has no points. |
Definition at line 1733 of file Polyhedron_public.cc.
References add_recycled_generators_and_minimize().
01733 { 01734 // TODO: this is just an executable specification. 01735 Generator_System gs_copy = gs; 01736 return add_recycled_generators_and_minimize(gs_copy); 01737 }
bool Parma_Polyhedra_Library::Polyhedron::add_recycled_generators_and_minimize | ( | Generator_System & | gs | ) |
Adds the generators in gs
to the system of generators of *this
, minimizing the result.
false
if and only if the result is empty.gs | The generator system to be added to *this . The generators in gs may be recycled. |
std::invalid_argument | Thrown if *this and gs are topology-incompatible or dimension-incompatible, or if *this is empty and the the system of generators gs is not empty, but has no points. |
gs
upon successful or exceptional return is that it can be safely destroyed.Definition at line 1659 of file Polyhedron_public.cc.
References add_and_minimize(), Parma_Polyhedra_Library::Generator_System::add_corresponding_closure_points(), Parma_Polyhedra_Library::Generator_System::adjust_topology_and_space_dimension(), clear_empty(), clear_sat_c_up_to_date(), con_sys, gen_sys, Parma_Polyhedra_Library::Generator_System::has_closure_points(), Parma_Polyhedra_Library::Matrix::has_no_rows(), Parma_Polyhedra_Library::Generator_System::has_points(), is_necessarily_closed(), Parma_Polyhedra_Library::Linear_System::is_sorted(), marked_empty(), minimize(), Parma_Polyhedra_Library::Linear_System::num_pending_rows(), obtain_sorted_generators_with_sat_g(), OK(), sat_g, set_generators_up_to_date(), Parma_Polyhedra_Library::Polyhedron::Status::set_zero_dim_univ(), Parma_Polyhedra_Library::Linear_System::sort_rows(), space_dim, Parma_Polyhedra_Library::Generator_System::space_dimension(), status, Parma_Polyhedra_Library::swap(), throw_dimension_incompatible(), throw_invalid_generators(), throw_topology_incompatible(), topology(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
Referenced by add_generator_and_minimize(), and add_generators_and_minimize().
01659 { 01660 // Topology compatibility check. 01661 if (is_necessarily_closed() && gs.has_closure_points()) 01662 throw_topology_incompatible("add_recycled_generators_and_minimize(gs)", 01663 "gs", gs); 01664 // Dimension-compatibility check: 01665 // the dimension of `gs' can not be greater than space_dim. 01666 const dimension_type gs_space_dim = gs.space_dimension(); 01667 if (space_dim < gs_space_dim) 01668 throw_dimension_incompatible("add_recycled_generators_and_minimize(gs)", 01669 "gs", gs); 01670 01671 // Adding no generators is equivalent to just requiring minimization. 01672 if (gs.has_no_rows()) 01673 return minimize(); 01674 01675 // Adding valid generators to a zero-dimensional polyhedron 01676 // transform it in the zero-dimensional universe polyhedron. 01677 if (space_dim == 0) { 01678 if (marked_empty() && !gs.has_points()) 01679 throw_invalid_generators("add_recycled_generators_and_minimize(gs)", 01680 "gs"); 01681 status.set_zero_dim_univ(); 01682 assert(OK(true)); 01683 return true; 01684 } 01685 01686 // Adjust `gs' to the right topology. 01687 // NOTE: we already checked for topology compatibility; 01688 // also, we do NOT adjust dimensions now, so that we will 01689 // spend less time to sort rows. 01690 gs.adjust_topology_and_space_dimension(topology(), gs_space_dim); 01691 01692 // For NNC polyhedra, each point must be matched by 01693 // the corresponding closure point. 01694 if (!is_necessarily_closed()) 01695 gs.add_corresponding_closure_points(); 01696 01697 // `gs' has to be fully sorted, thus it cannot have pending rows. 01698 if (gs.num_pending_rows() > 0) { 01699 gs.unset_pending_rows(); 01700 gs.sort_rows(); 01701 } 01702 else if (!gs.is_sorted()) 01703 gs.sort_rows(); 01704 01705 // Now adjusting dimensions (topology already adjusted). 01706 // NOTE: sortedness is preserved. 01707 gs.adjust_topology_and_space_dimension(topology(), space_dim); 01708 01709 if (minimize()) { 01710 obtain_sorted_generators_with_sat_g(); 01711 // This call to `add_and_minimize()' cannot return `false'. 01712 add_and_minimize(false, gen_sys, con_sys, sat_g, gs); 01713 clear_sat_c_up_to_date(); 01714 } 01715 else { 01716 // The polyhedron was empty: check if `gs' contains a point. 01717 if (!gs.has_points()) 01718 throw_invalid_generators("add_recycled_generators_and_minimize(gs)", 01719 "gs"); 01720 // `gs' has a point: the polyhedron is no longer empty 01721 // and generators are up-to-date. 01722 std::swap(gen_sys, gs); 01723 clear_empty(); 01724 set_generators_up_to_date(); 01725 // This call to `minimize()' cannot return `false'. 01726 minimize(); 01727 } 01728 assert(OK(true)); 01729 return true; 01730 }
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.
cgs | The congruences to be added. |
std::invalid_argument | Thrown 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 1740 of file Polyhedron_public.cc.
References add_recycled_constraints(), Parma_Polyhedra_Library::Congruence_System::begin(), Parma_Polyhedra_Library::Congruence_System::end(), Parma_Polyhedra_Library::Constraint::EQUALITY, 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::Checked::le(), Parma_Polyhedra_Library::NECESSARILY_CLOSED, set_empty(), space_dim, Parma_Polyhedra_Library::Congruence_System::space_dimension(), Parma_Polyhedra_Library::Linear_Row::strong_normalize(), throw_dimension_incompatible(), and throw_invalid_argument().
Referenced by add_congruences_and_minimize(), add_recycled_congruences(), Parma_Polyhedra_Library::C_Polyhedron::C_Polyhedron(), and Parma_Polyhedra_Library::NNC_Polyhedron::NNC_Polyhedron().
01740 { 01741 // Dimension-compatibility check. 01742 if (space_dim < cgs.space_dimension()) 01743 throw_dimension_incompatible("add_congruences(cgs)", "cgs", cgs); 01744 01745 Constraint_System cs; 01746 bool inserted = false; 01747 for (Congruence_System::const_iterator i = cgs.begin(), 01748 cgs_end = cgs.end(); i != cgs_end; ++i) { 01749 const Congruence& cg = *i; 01750 if (cg.is_equality()) { 01751 Linear_Expression le(cg); 01752 Constraint c(le, Constraint::EQUALITY, NECESSARILY_CLOSED); 01753 // Enforce normalization. 01754 c.strong_normalize(); 01755 // TODO: Consider stealing the row in c when adding it to cs. 01756 cs.insert(c); 01757 inserted = true; 01758 } 01759 else { 01760 assert(cg.is_proper_congruence()); 01761 if (cg.is_inconsistent()) { 01762 set_empty(); 01763 return; 01764 } 01765 if (!cg.is_tautological()) 01766 throw_invalid_argument("add_congruences(cgs)", 01767 "cgs has a non-trivial, proper congruence"); 01768 } 01769 } 01770 // Only add cs if it contains something. 01771 if (inserted) 01772 add_recycled_constraints(cs); 01773 }
bool Parma_Polyhedra_Library::Polyhedron::add_congruences_and_minimize | ( | const Congruence_System & | cgs | ) | [inline] |
Adds a copy of the congruences in cgs
to *this
, if all the congruences can be exactly represented by a polyhedron, minimizing the result.
false
if and only if the result is empty.cgs | The congruences to be added. |
std::invalid_argument | Thrown 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 377 of file Polyhedron.inlines.hh.
References add_congruences(), and minimize().
Referenced by add_recycled_congruences_and_minimize().
00377 { 00378 add_congruences(cgs); 00379 return minimize(); 00380 }
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.
cgs | The congruences to be added. Its elements may be recycled. |
std::invalid_argument | Thrown if *this and cgs are dimension-incompatible, of if there exists in cgs a proper congruence which is neither a tautology, nor a contradiction |
cgs
upon successful or exceptional return is that it can be safely destroyed. Definition at line 383 of file Polyhedron.inlines.hh.
References add_congruences().
00383 { 00384 add_congruences(cgs); 00385 }
bool Parma_Polyhedra_Library::Polyhedron::add_recycled_congruences_and_minimize | ( | Congruence_System & | cgs | ) | [inline] |
Adds the congruences in cgs
to *this
, if all the congruences can be exactly represented by a polyhedron, minimizing the result.
false
if and only if the result is empty.cgs | The congruences to be added. Its elements may be recycled. |
std::invalid_argument | Thrown if *this and cgs are dimension-incompatible, of if there exists in cgs a proper congruence which is neither a tautology, nor a contradiction |
cgs
upon successful or exceptional return is that it can be safely destroyed.Definition at line 388 of file Polyhedron.inlines.hh.
References add_congruences_and_minimize().
00388 { 00389 return add_congruences_and_minimize(cgs); 00390 }
void Parma_Polyhedra_Library::Polyhedron::refine_with_constraint | ( | const Constraint & | c | ) |
Uses a copy of constraint c
to refine *this
.
std::invalid_argument | Thrown if *this and constraint c are dimension-incompatible. |
Definition at line 1776 of file Polyhedron_public.cc.
References marked_empty(), refine_no_check(), space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), and throw_dimension_incompatible().
01776 { 01777 // Dimension-compatibility check. 01778 if (space_dim < c.space_dimension()) 01779 throw_dimension_incompatible("refine_with_constraint(c)", "c", c); 01780 // If the polyhedron is known to be empty, do nothing. 01781 if (!marked_empty()) 01782 refine_no_check(c); 01783 }
void Parma_Polyhedra_Library::Polyhedron::refine_with_congruence | ( | const Congruence & | cg | ) |
Uses a copy of congruence cg
to refine *this
.
std::invalid_argument | Thrown if *this and congruence cg are dimension-incompatible. |
Definition at line 1786 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Constraint::EQUALITY, Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Congruence::is_tautological(), Parma_Polyhedra_Library::Checked::le(), marked_empty(), Parma_Polyhedra_Library::NECESSARILY_CLOSED, refine_no_check(), set_empty(), space_dim, Parma_Polyhedra_Library::Congruence::space_dimension(), Parma_Polyhedra_Library::Linear_Row::strong_normalize(), and throw_dimension_incompatible().
01786 { 01787 // Dimension-compatibility check. 01788 if (space_dim < cg.space_dimension()) 01789 throw_dimension_incompatible("refine_with_congruence(cg)", "cg", cg); 01790 01791 // If the polyhedron is known to be empty, do nothing. 01792 if (marked_empty()) 01793 return; 01794 01795 // Dealing with a zero-dimensional space polyhedron first. 01796 if (space_dim == 0) { 01797 if (!cg.is_tautological()) 01798 set_empty(); 01799 return; 01800 } 01801 01802 if (cg.is_equality()) { 01803 Linear_Expression le(cg); 01804 Constraint c(le, Constraint::EQUALITY, NECESSARILY_CLOSED); 01805 // Enforce normalization. 01806 c.strong_normalize(); 01807 refine_no_check(c); 01808 } 01809 }
void Parma_Polyhedra_Library::Polyhedron::refine_with_constraints | ( | const Constraint_System & | cs | ) |
Uses a copy of the constraints in cs
to refine *this
.
cs | Contains the constraints used to refine the system of constraints of *this . |
std::invalid_argument | Thrown if *this and cs are dimension-incompatible. |
Definition at line 1812 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Constraint_System::begin(), can_have_something_pending(), clear_constraints_minimized(), clear_generators_up_to_date(), con_sys, constraints_are_up_to_date(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Matrix::has_no_rows(), has_pending_generators(), Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::Constraint_System::insert_pending(), Parma_Polyhedra_Library::Constraint::is_equality(), is_necessarily_closed(), Parma_Polyhedra_Library::Linear_Row::is_necessarily_closed(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), process_pending_generators(), set_constraints_pending(), Parma_Polyhedra_Library::Polyhedron::Status::set_empty(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), status, throw_dimension_incompatible(), and update_constraints().
01812 { 01813 // TODO: this is just an executable specification. 01814 01815 // Dimension-compatibility check. 01816 const dimension_type cs_space_dim = cs.space_dimension(); 01817 if (space_dim < cs_space_dim) 01818 throw_dimension_incompatible("refine_with_constraints(cs)a", 01819 "cs", cs); 01820 01821 // Adding no constraints is a no-op. 01822 if (cs.has_no_rows()) 01823 return; 01824 01825 if (space_dim == 0) { 01826 // In a 0-dimensional space the constraints are 01827 // tautologies (e.g., 0 == 0 or 1 >= 0 or 1 > 0) or 01828 // inconsistent (e.g., 1 == 0 or -1 >= 0 or 0 > 0). 01829 // In a system of constraints `begin()' and `end()' are equal 01830 // if and only if the system only contains tautologies. 01831 if (cs.begin() != cs.end()) 01832 // There is a constraint, it must be inconsistent, 01833 // the polyhedron is empty. 01834 status.set_empty(); 01835 return; 01836 } 01837 01838 if (marked_empty()) 01839 return; 01840 01841 // The constraints (possibly with pending rows) are required. 01842 if (has_pending_generators()) 01843 process_pending_generators(); 01844 else if (!constraints_are_up_to_date()) 01845 update_constraints(); 01846 01847 const bool adding_pending = can_have_something_pending(); 01848 for (dimension_type i = cs.num_rows(); i-- > 0; ) { 01849 const Constraint& c = cs[i]; 01850 01851 if (c.is_necessarily_closed() || !is_necessarily_closed()) 01852 // Since `con_sys' is not empty, the topology and space dimension 01853 // of the inserted constraint are automatically adjusted. 01854 if (adding_pending) 01855 con_sys.insert_pending(c); 01856 else 01857 con_sys.insert(c); 01858 else { 01859 // Here we know that *this is necessarily closed so even if c is 01860 // topologically closed, by barely invoking `con_sys.insert(c)' we 01861 // would cause a change in the topology of `con_sys', which is 01862 // wrong. Thus, we insert a topology closed and "topology 01863 // corrected" version of `c'. 01864 Linear_Expression nc_expr = Linear_Expression(c); 01865 if (c.is_equality()) 01866 if (adding_pending) 01867 con_sys.insert_pending(nc_expr == 0); 01868 else 01869 con_sys.insert(nc_expr == 0); 01870 else 01871 if (adding_pending) 01872 con_sys.insert_pending(nc_expr >= 0); 01873 else 01874 con_sys.insert(nc_expr >= 0); 01875 } 01876 } 01877 01878 if (adding_pending) 01879 set_constraints_pending(); 01880 else { 01881 // Constraints are not minimized and generators are not up-to-date. 01882 clear_constraints_minimized(); 01883 clear_generators_up_to_date(); 01884 } 01885 01886 // Note: the constraint system may have become unsatisfiable, thus 01887 // we do not check for satisfiability. 01888 assert(OK()); 01889 }
void Parma_Polyhedra_Library::Polyhedron::refine_with_congruences | ( | const Congruence_System & | cgs | ) |
Uses a copy of the congruences in cgs
to refine *this
.
cgs | Contains the congruences used to refine the system of constraints of *this . |
std::invalid_argument | Thrown if *this and cgs are dimension-incompatible. |
Definition at line 1892 of file Polyhedron_public.cc.
References add_recycled_constraints(), Parma_Polyhedra_Library::Congruence_System::begin(), Parma_Polyhedra_Library::Congruence_System::end(), Parma_Polyhedra_Library::Constraint::EQUALITY, Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::Checked::le(), Parma_Polyhedra_Library::NECESSARILY_CLOSED, set_empty(), space_dim, Parma_Polyhedra_Library::Congruence_System::space_dimension(), Parma_Polyhedra_Library::Linear_Row::strong_normalize(), and throw_dimension_incompatible().
01892 { 01893 // Dimension-compatibility check. 01894 if (space_dim < cgs.space_dimension()) 01895 throw_dimension_incompatible("refine_with_congruences(cgs)", "cgs", cgs); 01896 01897 Constraint_System cs; 01898 bool inserted = false; 01899 for (Congruence_System::const_iterator i = cgs.begin(), 01900 cgs_end = cgs.end(); i != cgs_end; ++i) { 01901 if (i->is_equality()) { 01902 Linear_Expression le(*i); 01903 Constraint c(le, Constraint::EQUALITY, NECESSARILY_CLOSED); 01904 // Enforce normalization. 01905 c.strong_normalize(); 01906 // TODO: Consider stealing the row in c when adding it to cs. 01907 cs.insert(c); 01908 inserted = true; 01909 } 01910 else if (i->is_inconsistent()) { 01911 set_empty(); 01912 return; 01913 } 01914 } 01915 // Only add cgs if congruences were inserted into cgs, as the 01916 // dimension of cs must be at most that of the polyhedron. 01917 if (inserted) 01918 add_recycled_constraints(cs); 01919 }
void Parma_Polyhedra_Library::Polyhedron::unconstrain | ( | Variable | var | ) |
Computes the cylindrification of *this
with respect to space dimension var
, assigning the result to *this
.
var | The space dimension that will be unconstrained. |
std::invalid_argument | Thrown if var is not a space dimension of *this . |
Definition at line 1922 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(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Generator_System::insert(), Parma_Polyhedra_Library::Generator_System::insert_pending(), Parma_Polyhedra_Library::Generator::line(), marked_empty(), OK(), process_pending_constraints(), set_generators_pending(), space_dim, throw_dimension_incompatible(), and update_generators().
Referenced by bounded_affine_preimage(), and generalized_affine_preimage().
01922 { 01923 // Dimension-compatibility check. 01924 if (space_dim < var.id()) 01925 throw_dimension_incompatible("unconstrain(var)", var.id()); 01926 01927 // Do something only if the polyhedron is non-empty. 01928 if (marked_empty() 01929 || (has_pending_constraints() && !process_pending_constraints()) 01930 || (!generators_are_up_to_date() && !update_generators())) 01931 // Empty: do nothing. 01932 return; 01933 01934 assert(generators_are_up_to_date()); 01935 // Since `gen_sys' is not empty, the topology and space dimension 01936 // of the inserted generator are automatically adjusted. 01937 if (can_have_something_pending()) { 01938 gen_sys.insert_pending(Generator::line(var)); 01939 set_generators_pending(); 01940 } 01941 else { 01942 gen_sys.insert(Generator::line(var)); 01943 // After adding the new generator, 01944 // constraints are no longer up-to-date. 01945 clear_generators_minimized(); 01946 clear_constraints_up_to_date(); 01947 } 01948 assert(OK(true)); 01949 }
void Parma_Polyhedra_Library::Polyhedron::unconstrain | ( | const Variables_Set & | to_be_unconstrained | ) |
Computes the cylindrification of *this
with respect to the set of space dimensions to_be_unconstrained
, assigning the result to *this
.
to_be_unconstrained | The set of space dimension that will be unconstrained. |
std::invalid_argument | Thrown if *this is dimension-incompatible with one of the Variable objects contained in to_be_removed . |
Definition at line 1952 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(), Parma_Polyhedra_Library::Generator_System::insert(), Parma_Polyhedra_Library::Generator_System::insert_pending(), Parma_Polyhedra_Library::Generator::line(), marked_empty(), OK(), process_pending_constraints(), set_generators_pending(), space_dim, throw_dimension_incompatible(), and update_generators().
01952 { 01953 // The cylindrification wrt no dimensions is a no-op. 01954 // This case also captures the only legal cylindrification 01955 // of a polyhedron in a 0-dim space. 01956 if (to_be_unconstrained.empty()) 01957 return; 01958 01959 // Dimension-compatibility check. 01960 const dimension_type min_space_dim = to_be_unconstrained.space_dimension(); 01961 if (space_dim < min_space_dim) 01962 throw_dimension_incompatible("unconstrain(vs)", min_space_dim); 01963 01964 // Do something only if the polyhedron is non-empty. 01965 if (marked_empty() 01966 || (has_pending_constraints() && !process_pending_constraints()) 01967 || (!generators_are_up_to_date() && !update_generators())) 01968 // Empty: do nothing. 01969 return; 01970 01971 assert(generators_are_up_to_date()); 01972 // Since `gen_sys' is not empty, the topology and space dimension 01973 // of the inserted generators are automatically adjusted. 01974 Variables_Set::const_iterator tbu = to_be_unconstrained.begin(); 01975 Variables_Set::const_iterator tbu_end = to_be_unconstrained.end(); 01976 if (can_have_something_pending()) { 01977 for ( ; tbu != tbu_end; ++tbu) 01978 gen_sys.insert_pending(Generator::line(Variable(*tbu))); 01979 set_generators_pending(); 01980 } 01981 else { 01982 for ( ; tbu != tbu_end; ++tbu) 01983 gen_sys.insert(Generator::line(Variable(*tbu))); 01984 // After adding the new generators, 01985 // constraints are no longer up-to-date. 01986 clear_generators_minimized(); 01987 clear_constraints_up_to_date(); 01988 } 01989 assert(OK(true)); 01990 }
void Parma_Polyhedra_Library::Polyhedron::intersection_assign | ( | const Polyhedron & | y | ) |
Assigns to *this
the intersection of *this
and y
. The result is not guaranteed to be minimized.
std::invalid_argument | Thrown if *this and y are topology-incompatible or dimension-incompatible. |
Definition at line 1993 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Linear_System::add_pending_rows(), Parma_Polyhedra_Library::Linear_System::add_rows(), 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::Linear_System::is_sorted(), marked_empty(), Parma_Polyhedra_Library::Linear_System::merge_rows_assign(), OK(), process_pending_generators(), set_constraints_pending(), set_empty(), space_dim, throw_dimension_incompatible(), throw_topology_incompatible(), topology(), and update_constraints().
Referenced by BHRZ03_evolving_points(), BHRZ03_evolving_rays(), H79_widening_assign(), and is_disjoint_from().
01993 { 01994 Polyhedron& x = *this; 01995 // Topology compatibility check. 01996 if (x.topology() != y.topology()) 01997 throw_topology_incompatible("intersection_assign(y)", "y", y); 01998 // Dimension-compatibility check. 01999 if (x.space_dim != y.space_dim) 02000 throw_dimension_incompatible("intersection_assign(y)", "y", y); 02001 02002 // If one of the two polyhedra is empty, the intersection is empty. 02003 if (x.marked_empty()) 02004 return; 02005 if (y.marked_empty()) { 02006 x.set_empty(); 02007 return; 02008 } 02009 02010 // If both polyhedra are zero-dimensional, 02011 // then at this point they are necessarily non-empty, 02012 // so that their intersection is non-empty too. 02013 if (x.space_dim == 0) 02014 return; 02015 02016 // Both systems of constraints have to be up-to-date, 02017 // possibly having pending constraints. 02018 if (x.has_pending_generators()) 02019 x.process_pending_generators(); 02020 else if (!x.constraints_are_up_to_date()) 02021 x.update_constraints(); 02022 02023 if (y.has_pending_generators()) 02024 y.process_pending_generators(); 02025 else if (!y.constraints_are_up_to_date()) 02026 y.update_constraints(); 02027 02028 // Here both systems are up-to-date and possibly have pending constraints 02029 // (but they cannot have pending generators). 02030 assert(!x.has_pending_generators() && x.constraints_are_up_to_date()); 02031 assert(!y.has_pending_generators() && y.constraints_are_up_to_date()); 02032 02033 // If `x' can support pending constraints, 02034 // the constraints of `y' are added as pending constraints of `x'. 02035 if (x.can_have_something_pending()) { 02036 x.con_sys.add_pending_rows(y.con_sys); 02037 x.set_constraints_pending(); 02038 } 02039 else { 02040 // `x' cannot support pending constraints. 02041 // If both constraint systems are (fully) sorted, then we can 02042 // merge them; otherwise we simply add the second to the first. 02043 if (x.con_sys.is_sorted() 02044 && y.con_sys.is_sorted() && !y.has_pending_constraints()) 02045 x.con_sys.merge_rows_assign(y.con_sys); 02046 else 02047 x.con_sys.add_rows(y.con_sys); 02048 // Generators are no longer up-to-date and constraints are no 02049 // longer minimized. 02050 x.clear_generators_up_to_date(); 02051 x.clear_constraints_minimized(); 02052 } 02053 assert(x.OK() && y.OK()); 02054 }
bool Parma_Polyhedra_Library::Polyhedron::intersection_assign_and_minimize | ( | const Polyhedron & | y | ) |
Assigns to *this
the intersection of *this
and y
, minimizing the result.
false
if and only if the result is empty.std::invalid_argument | Thrown if *this and y are topology-incompatible or dimension-incompatible. |
Definition at line 2057 of file Polyhedron_public.cc.
References add_and_minimize(), Parma_Polyhedra_Library::Linear_System::add_pending_rows(), clear_pending_constraints(), clear_sat_g_up_to_date(), con_sys, constraints_are_up_to_date(), empty, gen_sys, has_pending_generators(), marked_empty(), minimize(), Parma_Polyhedra_Library::Linear_System::num_pending_rows(), obtain_sorted_constraints(), obtain_sorted_constraints_with_sat_c(), OK(), process_pending_generators(), sat_c, set_empty(), set_sat_c_up_to_date(), Parma_Polyhedra_Library::Linear_System::sort_pending_and_remove_duplicates(), space_dim, throw_dimension_incompatible(), throw_topology_incompatible(), topology(), and update_constraints().
02057 { 02058 Polyhedron& x = *this; 02059 // Topology compatibility check. 02060 if (x.topology() != y.topology()) 02061 throw_topology_incompatible("intersection_assign_and_minimize(y)", 02062 "y", y); 02063 // Dimension-compatibility check. 02064 if (x.space_dim != y.space_dim) 02065 throw_dimension_incompatible("intersection_assign_and_minimize(y)", 02066 "y", y); 02067 02068 // If one of the two polyhedra is empty, the intersection is empty. 02069 if (x.marked_empty()) 02070 return false; 02071 if (y.marked_empty()) { 02072 x.set_empty(); 02073 return false; 02074 } 02075 02076 // If both polyhedra are zero-dimensional, 02077 // then at this point they are necessarily non-empty, 02078 // so that their intersection is non-empty too. 02079 if (x.space_dim == 0) 02080 return true; 02081 02082 // `x' must be minimized and have sorted constraints. 02083 // `minimize()' will process any pending constraints or generators. 02084 if (!x.minimize()) 02085 // We have just discovered that `x' is empty. 02086 return false; 02087 x.obtain_sorted_constraints_with_sat_c(); 02088 02089 // `y' must have updated, possibly pending constraints. 02090 if (y.has_pending_generators()) 02091 y.process_pending_generators(); 02092 else if (!y.constraints_are_up_to_date()) 02093 y.update_constraints(); 02094 02095 bool empty; 02096 if (y.con_sys.num_pending_rows() > 0) { 02097 // Integrate `y.con_sys' as pending constraints of `x', 02098 // sort them in place and then call `add_and_minimize()'. 02099 x.con_sys.add_pending_rows(y.con_sys); 02100 x.con_sys.sort_pending_and_remove_duplicates(); 02101 if (x.con_sys.num_pending_rows() == 0) { 02102 // All pending constraints were duplicates. 02103 x.clear_pending_constraints(); 02104 assert(OK(true)); 02105 return true; 02106 } 02107 empty = add_and_minimize(true, x.con_sys, x.gen_sys, x.sat_c); 02108 } 02109 else { 02110 y.obtain_sorted_constraints(); 02111 empty = add_and_minimize(true, x.con_sys, x.gen_sys, x.sat_c, y.con_sys); 02112 } 02113 02114 if (empty) 02115 x.set_empty(); 02116 else { 02117 // On exit of the function `intersection_assign_and_minimize()' 02118 // the polyhedron is up-to-date and `sat_c' is meaningful. 02119 x.set_sat_c_up_to_date(); 02120 x.clear_sat_g_up_to_date(); 02121 } 02122 assert(x.OK(!empty)); 02123 return !empty; 02124 }
void Parma_Polyhedra_Library::Polyhedron::poly_hull_assign | ( | const Polyhedron & | y | ) |
Assigns to *this
the poly-hull of *this
and y
. The result is not guaranteed to be minimized.
std::invalid_argument | Thrown if *this and y are topology-incompatible or dimension-incompatible. |
Definition at line 2566 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Linear_System::add_pending_rows(), Parma_Polyhedra_Library::Linear_System::add_rows(), 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::Linear_System::is_sorted(), marked_empty(), Parma_Polyhedra_Library::Linear_System::merge_rows_assign(), OK(), process_pending_constraints(), set_generators_pending(), space_dim, throw_dimension_incompatible(), throw_topology_incompatible(), topology(), and update_generators().
Referenced by Parma_Polyhedra_Library::Pointset_Powerset< PS >::affine_dimension(), fold_space_dimensions(), poly_difference_assign(), and upper_bound_assign().
02566 { 02567 Polyhedron& x = *this; 02568 // Topology compatibility check. 02569 if (x.topology() != y.topology()) 02570 throw_topology_incompatible("poly_hull_assign(y)", "y", y); 02571 // Dimension-compatibility check. 02572 if (x.space_dim != y.space_dim) 02573 throw_dimension_incompatible("poly_hull_assign(y)", "y", y); 02574 02575 // The poly-hull of a polyhedron `p' with an empty polyhedron is `p'. 02576 if (y.marked_empty()) 02577 return; 02578 if (x.marked_empty()) { 02579 x = y; 02580 return; 02581 } 02582 02583 // If both polyhedra are zero-dimensional, 02584 // then at this point they are necessarily universe polyhedra, 02585 // so that their poly-hull is the universe polyhedron too. 02586 if (x.space_dim == 0) 02587 return; 02588 02589 // Both systems of generators have to be up-to-date, 02590 // possibly having pending generators. 02591 if ((x.has_pending_constraints() && !x.process_pending_constraints()) 02592 || (!x.generators_are_up_to_date() && !x.update_generators())) { 02593 // Discovered `x' empty when updating generators. 02594 x = y; 02595 return; 02596 } 02597 if ((y.has_pending_constraints() && !y.process_pending_constraints()) 02598 || (!y.generators_are_up_to_date() && !y.update_generators())) 02599 // Discovered `y' empty when updating generators. 02600 return; 02601 02602 // Here both systems are up-to-date and possibly have pending generators 02603 // (but they cannot have pending constraints). 02604 assert(!x.has_pending_constraints() && x.generators_are_up_to_date()); 02605 assert(!y.has_pending_constraints() && y.generators_are_up_to_date()); 02606 02607 // If `x' can support pending generators, 02608 // the generators of `y' are added as pending generators of `x'. 02609 if (x.can_have_something_pending()) { 02610 x.gen_sys.add_pending_rows(y.gen_sys); 02611 x.set_generators_pending(); 02612 } 02613 else { 02614 // `x' cannot support pending generators. 02615 // If both generator systems are (fully) sorted, then we can merge 02616 // them; otherwise we simply add the second to the first. 02617 if (x.gen_sys.is_sorted() 02618 && y.gen_sys.is_sorted() && !y.has_pending_generators()) 02619 x.gen_sys.merge_rows_assign(y.gen_sys); 02620 else 02621 x.gen_sys.add_rows(y.gen_sys); 02622 // Constraints are no longer up-to-date 02623 // and generators are no longer minimized. 02624 x.clear_constraints_up_to_date(); 02625 x.clear_generators_minimized(); 02626 } 02627 // At this point both `x' and `y' are not empty. 02628 assert(x.OK(true) && y.OK(true)); 02629 }
bool Parma_Polyhedra_Library::Polyhedron::poly_hull_assign_and_minimize | ( | const Polyhedron & | y | ) |
Assigns to *this
the poly-hull of *this
and y
, minimizing the result.
false
if and only if the result is empty.std::invalid_argument | Thrown if *this and y are topology-incompatible or dimension-incompatible. |
Definition at line 2632 of file Polyhedron_public.cc.
References add_and_minimize(), Parma_Polyhedra_Library::Linear_System::add_pending_rows(), clear_pending_generators(), clear_sat_c_up_to_date(), con_sys, gen_sys, generators_are_up_to_date(), has_pending_constraints(), marked_empty(), minimize(), Parma_Polyhedra_Library::Linear_System::num_pending_rows(), obtain_sorted_generators(), obtain_sorted_generators_with_sat_g(), OK(), process_pending_constraints(), sat_g, Parma_Polyhedra_Library::Linear_System::sort_pending_and_remove_duplicates(), space_dim, throw_dimension_incompatible(), throw_topology_incompatible(), topology(), and update_generators().
02632 { 02633 Polyhedron& x = *this; 02634 // Topology compatibility check. 02635 if (x.topology() != y.topology()) 02636 throw_topology_incompatible("poly_hull_assign_and_minimize(y)", "y", y); 02637 // Dimension-compatibility check. 02638 if (x.space_dim != y.space_dim) 02639 throw_dimension_incompatible("poly_hull_assign_and_minimize(y)", "y", y); 02640 02641 // The poly-hull of a polyhedron `p' with an empty polyhedron is `p'. 02642 if (y.marked_empty()) 02643 return minimize(); 02644 if (x.marked_empty()) { 02645 x = y; 02646 return minimize(); 02647 } 02648 02649 // If both polyhedra are zero-dimensional, 02650 // then at this point they are necessarily universe polyhedra, 02651 // so that their poly-hull is the universe polyhedron too. 02652 if (x.space_dim == 0) 02653 return true; 02654 02655 // `x' must have minimized constraints and generators. 02656 // `minimize()' will process any pending constraints or generators. 02657 if (!x.minimize()) { 02658 // We have just discovered that `x' is empty. 02659 x = y; 02660 return minimize(); 02661 } 02662 // x must have `sat_g' up-to-date and sorted generators. 02663 x.obtain_sorted_generators_with_sat_g(); 02664 02665 // `y' must have updated, possibly pending generators. 02666 if ((y.has_pending_constraints() && !y.process_pending_constraints()) 02667 || (!y.generators_are_up_to_date() && !y.update_generators())) 02668 // We have just discovered that `y' is empty 02669 // (and we know that `x' is not empty). 02670 return true; 02671 02672 if (y.gen_sys.num_pending_rows() > 0) { 02673 // Integrate `y.gen_sys' as pending generators of `x', 02674 // sort them in place and then call `add_and_minimize()'. 02675 x.gen_sys.add_pending_rows(y.gen_sys); 02676 x.gen_sys.sort_pending_and_remove_duplicates(); 02677 if (x.gen_sys.num_pending_rows() == 0) { 02678 // All pending generators were duplicates. 02679 x.clear_pending_generators(); 02680 assert(OK(true) && y.OK()); 02681 return true; 02682 } 02683 add_and_minimize(false, x.gen_sys, x.con_sys, x.sat_g); 02684 } 02685 else { 02686 y.obtain_sorted_generators(); 02687 add_and_minimize(false, x.gen_sys, x.con_sys, x.sat_g, y.gen_sys); 02688 } 02689 x.clear_sat_c_up_to_date(); 02690 02691 assert(x.OK(true) && y.OK()); 02692 return true; 02693 }
void Parma_Polyhedra_Library::Polyhedron::upper_bound_assign | ( | const Polyhedron & | y | ) | [inline] |
Same as poly_hull_assign(y).
Definition at line 80 of file Polyhedron.inlines.hh.
References poly_hull_assign().
00080 { 00081 poly_hull_assign(y); 00082 }
void Parma_Polyhedra_Library::Polyhedron::poly_difference_assign | ( | const Polyhedron & | y | ) |
Assigns to *this
the poly-difference of *this
and y
. The result is not guaranteed to be minimized.
std::invalid_argument | Thrown if *this and y are topology-incompatible or dimension-incompatible. |
Definition at line 2696 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Constraint_System::begin(), constraints(), contains(), Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Constraint::EQUALITY, Parma_Polyhedra_Library::Poly_Con_Relation::implies(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Constraint::is_inconsistent(), is_necessarily_closed(), Parma_Polyhedra_Library::Constraint::is_tautological(), marked_empty(), minimize(), Parma_Polyhedra_Library::Constraint::NONSTRICT_INEQUALITY, OK(), poly_hull_assign(), refine_no_check(), relation_with(), set_empty(), space_dim, Parma_Polyhedra_Library::Constraint::STRICT_INEQUALITY, throw_dimension_incompatible(), throw_topology_incompatible(), topology(), and Parma_Polyhedra_Library::Constraint::type().
Referenced by difference_assign().
02696 { 02697 Polyhedron& x = *this; 02698 // Topology compatibility check. 02699 if (x.topology() != y.topology()) 02700 throw_topology_incompatible("poly_difference_assign(y)", "y", y); 02701 // Dimension-compatibility check. 02702 if (x.space_dim != y.space_dim) 02703 throw_dimension_incompatible("poly_difference_assign(y)", "y", y); 02704 02705 // The difference of a polyhedron `p' and an empty polyhedron is `p'. 02706 if (y.marked_empty()) 02707 return; 02708 // The difference of an empty polyhedron and of a polyhedron `p' is empty. 02709 if (x.marked_empty()) 02710 return; 02711 02712 // If both polyhedra are zero-dimensional, 02713 // then at this point they are necessarily universe polyhedra, 02714 // so that their difference is empty. 02715 if (x.space_dim == 0) { 02716 x.set_empty(); 02717 return; 02718 } 02719 02720 // TODO: This is just an executable specification. 02721 // Have to find a more efficient method. 02722 02723 if (y.contains(x)) { 02724 x.set_empty(); 02725 return; 02726 } 02727 02728 // Being lazy here is only harmful. 02729 // `minimize()' will process any pending constraints or generators. 02730 if (!y.minimize()) 02731 return; 02732 x.minimize(); 02733 02734 Polyhedron new_polyhedron(topology(), x.space_dim, EMPTY); 02735 02736 const Constraint_System& y_cs = y.constraints(); 02737 for (Constraint_System::const_iterator i = y_cs.begin(), 02738 y_cs_end = y_cs.end(); i != y_cs_end; ++i) { 02739 const Constraint& c = *i; 02740 assert(!c.is_tautological()); 02741 assert(!c.is_inconsistent()); 02742 // If the polyhedron `x' is included in the polyhedron defined by 02743 // `c', then `c' can be skipped, as adding its complement to `x' 02744 // would result in the empty polyhedron. Moreover, if we operate 02745 // on C-polyhedra and `c' is a non-strict inequality, c _must_ be 02746 // skipped for otherwise we would obtain a result that is less 02747 // precise than the poly-difference. 02748 if (x.relation_with(c).implies(Poly_Con_Relation::is_included())) 02749 continue; 02750 Polyhedron z = x; 02751 const Linear_Expression e = Linear_Expression(c); 02752 switch (c.type()) { 02753 case Constraint::NONSTRICT_INEQUALITY: 02754 if (is_necessarily_closed()) 02755 z.refine_no_check(e <= 0); 02756 else 02757 z.refine_no_check(e < 0); 02758 break; 02759 case Constraint::STRICT_INEQUALITY: 02760 z.refine_no_check(e <= 0); 02761 break; 02762 case Constraint::EQUALITY: 02763 if (is_necessarily_closed()) 02764 // We have already filtered out the case 02765 // when `x' is included in `y': the result is `x'. 02766 return; 02767 else { 02768 Polyhedron w = x; 02769 w.refine_no_check(e < 0); 02770 new_polyhedron.poly_hull_assign(w); 02771 z.refine_no_check(e > 0); 02772 } 02773 break; 02774 } 02775 new_polyhedron.poly_hull_assign(z); 02776 } 02777 *this = new_polyhedron; 02778 02779 assert(OK()); 02780 }
void Parma_Polyhedra_Library::Polyhedron::difference_assign | ( | const Polyhedron & | y | ) | [inline] |
Same as poly_difference_assign(y).
Definition at line 85 of file Polyhedron.inlines.hh.
References poly_difference_assign().
00085 { 00086 poly_difference_assign(y); 00087 }
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.
std::invalid_argument | Thrown if *this and y are topology-incompatible or dimension-incompatible. |
Definition at line 2218 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(), add_to_system_and_check_independence(), Parma_Polyhedra_Library::Generator_System::begin(), Parma_Polyhedra_Library::Generator::CLOSURE_POINT, con_sys, constraints_are_minimized(), constraints_are_up_to_date(), drop_redundant_inequalities(), Parma_Polyhedra_Library::Bit_Row::empty(), Parma_Polyhedra_Library::Generator_System::end(), Parma_Polyhedra_Library::Constraint::EQUALITY, 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::Checked::le(), Parma_Polyhedra_Library::Generator::LINE, minimize(), Parma_Polyhedra_Library::Constraint::NONSTRICT_INEQUALITY, Parma_Polyhedra_Library::Matrix::num_rows(), OK(), 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::Linear_Row::set_is_line_or_equality(), Parma_Polyhedra_Library::Polyhedron::Status::set_zero_dim_univ(), Parma_Polyhedra_Library::Scalar_Products::sign(), Parma_Polyhedra_Library::Linear_Row::sign_normalize(), Parma_Polyhedra_Library::MIP_Problem::solve(), space_dim, status, Parma_Polyhedra_Library::Constraint::STRICT_INEQUALITY, Parma_Polyhedra_Library::Constraint_System::swap(), swap(), throw_dimension_incompatible(), throw_topology_incompatible(), topology(), Parma_Polyhedra_Library::Generator::type(), Parma_Polyhedra_Library::Constraint::type(), Parma_Polyhedra_Library::UNFEASIBLE_MIP_PROBLEM, and Parma_Polyhedra_Library::UNIVERSE.
02218 { 02219 Polyhedron& x = *this; 02220 // Topology compatibility check. 02221 if (x.topology() != y.topology()) 02222 throw_topology_incompatible("simplify_using_context_assign(y)", "y", y); 02223 // Dimension-compatibility check. 02224 if (x.space_dim != y.space_dim) 02225 throw_dimension_incompatible("simplify_using_context_assign(y)", "y", y); 02226 02227 // Filter away the zero-dimensional case. 02228 if (x.space_dim == 0) { 02229 if (y.is_empty()) { 02230 x.status.set_zero_dim_univ(); 02231 return false; 02232 } 02233 else 02234 return !x.is_empty(); 02235 } 02236 02237 // If `y' is empty, the biggest enlargement for `x' is the universe. 02238 if (!y.minimize()) { 02239 Polyhedron ph(x.topology(), x.space_dim, UNIVERSE); 02240 swap(ph); 02241 return false; 02242 } 02243 02244 // If `x' is empty, the intersection is empty. 02245 if (!x.minimize()) { 02246 // Search for a constraint of `y' that is not a tautology. 02247 assert(!y.has_pending_generators() && y.constraints_are_up_to_date()); 02248 for (dimension_type i = y.con_sys.num_rows(); i-- > 0; ) { 02249 const Constraint& y_con_sys_i = y.con_sys[i]; 02250 if (!y_con_sys_i.is_tautological()) { 02251 // Found: we obtain a constraint `c' contradicting the one we 02252 // found, and assign to `x' the polyhedron `ph' with `c' as 02253 // the only constraint. 02254 Polyhedron ph(x.topology(), x.space_dim, UNIVERSE); 02255 Linear_Expression le(y_con_sys_i); 02256 switch (y_con_sys_i.type()) { 02257 case Constraint::EQUALITY: 02258 ph.refine_no_check(le == 1); 02259 break; 02260 case Constraint::NONSTRICT_INEQUALITY: 02261 ph.refine_no_check(le <= -1); 02262 break; 02263 case Constraint::STRICT_INEQUALITY: 02264 ph.refine_no_check(le == 0); 02265 break; 02266 } 02267 swap(ph); 02268 assert(OK()); 02269 return false; 02270 } 02271 } 02272 // `y' is the universe: `x' cannot be enlarged. 02273 return false; 02274 } 02275 02276 assert(x.constraints_are_minimized() 02277 && !x.has_something_pending() 02278 && y.generators_are_minimized() 02279 && !y.has_something_pending()); 02280 const Constraint_System& x_cs = x.con_sys; 02281 const dimension_type x_cs_num_rows = x_cs.num_rows(); 02282 const Generator_System& y_gs = y.gen_sys; 02283 02284 // Record into `redundant_by_y' the info about which constraints of 02285 // `x' are redundant in the context `y'. Count the number of 02286 // redundancies found. 02287 std::vector<bool> redundant_by_y(x_cs_num_rows, false); 02288 dimension_type num_redundant_by_y = 0; 02289 for (dimension_type i = 0; i < x_cs_num_rows; ++i) 02290 if (y_gs.satisfied_by_all_generators(x_cs[i])) { 02291 redundant_by_y[i] = true; 02292 ++num_redundant_by_y; 02293 } 02294 02295 Constraint_System result_cs; 02296 02297 if (num_redundant_by_y < x_cs_num_rows) { 02298 // Some constraints were not identified as redundant (yet?). 02299 const Constraint_System& y_cs = y.con_sys; 02300 const dimension_type y_cs_num_rows = y_cs.num_rows(); 02301 // Compute into `z' the minimized intersection of `x' and `y'. 02302 const bool x_first = (x_cs_num_rows > y_cs_num_rows); 02303 Polyhedron z(x_first ? x : y); 02304 if (x_first) 02305 z.add_constraints(y_cs); 02306 else { 02307 // Only copy (and then recycle) the non-redundant constraints. 02308 Constraint_System tmp_cs; 02309 for (dimension_type i = 0; i < x_cs_num_rows; ++i) { 02310 if (!redundant_by_y[i]) 02311 tmp_cs.insert(x_cs[i]); 02312 } 02313 z.add_recycled_constraints(tmp_cs); 02314 } 02315 if (!z.minimize()) { 02316 // The objective function is the default, zero. 02317 // We do not care about minimization or maximization, since 02318 // we are only interested in satisfiability. 02319 MIP_Problem lp; 02320 if (x.is_necessarily_closed()) { 02321 lp.add_space_dimensions_and_embed(x.space_dim); 02322 lp.add_constraints(y_cs); 02323 } 02324 else { 02325 // KLUDGE: temporarily mark `y_cs' if it was necessarily 02326 // closed, so that we can interpret the epsilon dimension as a 02327 // standard dimension. Be careful to reset the topology of `cs' 02328 // even on exceptional execution path. 02329 const_cast<Constraint_System&>(y_cs).set_necessarily_closed(); 02330 try { 02331 lp.add_space_dimensions_and_embed(x.space_dim+1); 02332 lp.add_constraints(y_cs); 02333 const_cast<Constraint_System&>(y_cs).set_not_necessarily_closed(); 02334 } 02335 catch (...) { 02336 const_cast<Constraint_System&>(y_cs).set_not_necessarily_closed(); 02337 throw; 02338 } 02339 } 02340 // We apply the following heuristics here: constraints of `x' that 02341 // are not made redundant by `y' are added to `lp' depending on 02342 // the number of generators of `y' they rule out (the more generators 02343 // they rule out, the sooner they are added). Of course, as soon 02344 // as `lp' becomes unsatisfiable, we stopp adding. 02345 std::vector<Ruled_Out_Pair> 02346 ruled_out_vec(x_cs_num_rows - num_redundant_by_y); 02347 for (dimension_type i = 0, j = 0; i < x_cs_num_rows; ++i) { 02348 if (!redundant_by_y[i]) { 02349 const Constraint& c = x_cs[i]; 02350 Topology_Adjusted_Scalar_Product_Sign sps(c); 02351 dimension_type num_ruled_out_generators = 0; 02352 for (Generator_System::const_iterator k = y_gs.begin(), 02353 y_gs_end = y_gs.end(); k != y_gs_end; ++k) { 02354 const Generator& g = *k; 02355 const int sp_sign = sps(g, c); 02356 if (x.is_necessarily_closed()) { 02357 if (g.is_line()) { 02358 // Lines must saturate the constraint. 02359 if (sp_sign != 0) 02360 goto ruled_out; 02361 } 02362 else { 02363 // `g' is either a ray, a point or a closure point. 02364 if (c.is_inequality()) { 02365 // `c' is a non-strict inequality. 02366 if (sp_sign < 0) 02367 goto ruled_out; 02368 } 02369 else 02370 // `c' is an equality. 02371 if (sp_sign != 0) 02372 goto ruled_out; 02373 } 02374 } 02375 else 02376 // The topology is not necessarily closed. 02377 switch (g.type()) { 02378 case Generator::LINE: 02379 // Lines must saturate the constraint. 02380 if (sp_sign != 0) 02381 goto ruled_out; 02382 break; 02383 case Generator::POINT: 02384 // Have to perform the special test when dealing with 02385 // a strict inequality. 02386 switch (c.type()) { 02387 case Constraint::EQUALITY: 02388 if (sp_sign != 0) 02389 goto ruled_out; 02390 break; 02391 case Constraint::NONSTRICT_INEQUALITY: 02392 if (sp_sign < 0) 02393 goto ruled_out; 02394 break; 02395 case Constraint::STRICT_INEQUALITY: 02396 if (sp_sign <= 0) 02397 goto ruled_out; 02398 break; 02399 } 02400 break; 02401 case Generator::RAY: 02402 // Intentionally fall through. 02403 case Generator::CLOSURE_POINT: 02404 if (c.is_inequality()) { 02405 // Constraint `c' is either a strict or a non-strict 02406 // inequality. 02407 if (sp_sign < 0) 02408 goto ruled_out; 02409 } 02410 else 02411 // Constraint `c' is an equality. 02412 if (sp_sign != 0) 02413 goto ruled_out; 02414 break; 02415 } 02416 02417 // If we reach this point, `g' satisfies `c'. 02418 continue; 02419 ruled_out: 02420 ++num_ruled_out_generators; 02421 } 02422 ruled_out_vec[j].constraint_index = i; 02423 ruled_out_vec[j].num_ruled_out = num_ruled_out_generators; 02424 ++j; 02425 } 02426 } 02427 std::sort(ruled_out_vec.begin(), ruled_out_vec.end(), 02428 Ruled_Out_Less_Than()); 02429 02430 for (std::vector<Ruled_Out_Pair>::const_iterator 02431 j = ruled_out_vec.begin(), rov_end = ruled_out_vec.end(); 02432 j != rov_end; 02433 ++j) { 02434 const Constraint& c = x_cs[j->constraint_index]; 02435 result_cs.insert(c); 02436 lp.add_constraint(c); 02437 MIP_Problem_Status status = lp.solve(); 02438 if (status == UNFEASIBLE_MIP_PROBLEM) { 02439 Polyhedron result_ph(x.topology(), x.space_dim, UNIVERSE); 02440 result_ph.add_constraints(result_cs); 02441 x.swap(result_ph); 02442 assert(x.OK()); 02443 return false; 02444 } 02445 } 02446 // Cannot exit from here. 02447 assert(false); 02448 } 02449 else { 02450 // Here `z' is not empty and minimized. 02451 assert(z.constraints_are_minimized() 02452 && z.generators_are_minimized() 02453 && !z.has_something_pending()); 02454 const Constraint_System& z_cs = z.con_sys; 02455 const Generator_System& z_gs = z.gen_sys; 02456 const dimension_type z_gs_num_rows = z_gs.num_rows(); 02457 02458 // Compute the number of equalities in x_cs, y_cs and z_cs 02459 // (exploiting minimal form knowledge). 02460 dimension_type x_cs_num_eq = 0; 02461 while (x_cs[x_cs_num_eq].is_equality()) 02462 ++x_cs_num_eq; 02463 dimension_type y_cs_num_eq = 0; 02464 while (y_cs[y_cs_num_eq].is_equality()) 02465 ++y_cs_num_eq; 02466 dimension_type z_cs_num_eq = 0; 02467 while (z_cs[z_cs_num_eq].is_equality()) 02468 ++z_cs_num_eq; 02469 assert(x_cs_num_eq <= z_cs_num_eq && y_cs_num_eq <= z_cs_num_eq); 02470 02471 // Identify non-redundant equalities. 02472 Constraint_System nonred_eq; 02473 dimension_type num_nonred_eq = 0; 02474 const dimension_type needed_nonred_eq = z_cs_num_eq - y_cs_num_eq; 02475 Linear_System eqs(x.topology()); 02476 if (needed_nonred_eq > 0) { 02477 // Populate eqs with the equalities from y. 02478 for (dimension_type i = 0; i < y_cs_num_eq; ++i) 02479 eqs.insert(y_cs[i]); 02480 // Try to find another `needed_nonred_eq' linear independent 02481 // equalities among those from x. 02482 for (dimension_type i = 0; i < x_cs_num_eq; ++i) { 02483 const Constraint& x_cs_i = x_cs[i]; 02484 if (add_to_system_and_check_independence(eqs, x_cs_i)) { 02485 // x_cs_i is linear independent. 02486 nonred_eq.insert(x_cs_i); 02487 ++num_nonred_eq; 02488 if (num_nonred_eq == needed_nonred_eq) 02489 // Already found all the needed equalities. 02490 break; 02491 } 02492 } 02493 // NOTE: if num_nonred_eq < needed_nonred_eq 02494 // then we haven't found all the needed equalities yet: 02495 // this means that some inequalities from x actually holds 02496 // as "masked" equalities in the context of y. 02497 assert(eqs.num_rows() <= z_cs_num_eq); 02498 assert(num_nonred_eq <= needed_nonred_eq); 02499 assert(z_cs_num_eq - eqs.num_rows() 02500 == needed_nonred_eq - num_nonred_eq); 02501 } 02502 02503 // Identify non-redundant inequalities. 02504 // Avoid useless copies (no modifications are needed). 02505 std::vector<const Constraint*> p_nonred_ineq; 02506 // Fill p_nonred_ineq with (pointers to) inequalities from y_cs ... 02507 for (dimension_type i = y_cs_num_eq; i < y_cs_num_rows; ++i) 02508 p_nonred_ineq.push_back(&y_cs[i]); 02509 // ... and (pointers to) non-redundant inequalities from x_cs. 02510 for (dimension_type i = x_cs_num_eq; i < x_cs_num_rows; ++i) 02511 if (!redundant_by_y[i]) 02512 p_nonred_ineq.push_back(&x_cs[i]); 02513 02514 const dimension_type p_nonred_ineq_size = p_nonred_ineq.size(); 02515 const dimension_type y_cs_num_ineq = y_cs_num_rows - y_cs_num_eq; 02516 02517 // Compute saturation info. 02518 const dimension_type sat_num_rows = p_nonred_ineq_size; 02519 Bit_Matrix sat(sat_num_rows, z_gs_num_rows); 02520 for (dimension_type i = sat_num_rows; i-- > 0; ) { 02521 const Constraint& nonred_ineq_i = *(p_nonred_ineq[i]); 02522 Bit_Row& sat_i = sat[i]; 02523 for (dimension_type j = z_gs_num_rows; j-- > 0; ) 02524 if (Scalar_Products::sign(nonred_ineq_i, z_gs[j])) 02525 sat_i.set(j); 02526 if (sat_i.empty() && num_nonred_eq < needed_nonred_eq) { 02527 // `nonred_ineq_i' is actually masking an equality 02528 // and we are still looking for some masked inequalities. 02529 // Iteration goes downwards, so the inequality comes from x_cs. 02530 assert(i >= y_cs_num_ineq); 02531 // Check if the equality is independent in eqs. 02532 Linear_Row masked_eq = Linear_Row(nonred_ineq_i); 02533 masked_eq.set_is_line_or_equality(); 02534 masked_eq.sign_normalize(); 02535 if (add_to_system_and_check_independence(eqs, masked_eq)) { 02536 // It is independent: add the _inequality_ to nonred_eq. 02537 nonred_eq.insert(nonred_ineq_i); 02538 ++num_nonred_eq; 02539 } 02540 } 02541 } 02542 // Here we have already found all the needed (masked) equalities. 02543 assert(num_nonred_eq == needed_nonred_eq); 02544 02545 drop_redundant_inequalities(p_nonred_ineq, x.topology(), 02546 sat, z_cs_num_eq); 02547 02548 // Place the nonredundant (masked) equalities into result_cs. 02549 result_cs.swap(nonred_eq); 02550 // Add to result_cs the nonredundant inequalities from x_cs, 02551 // i.e., those having indices no smaller than y_cs_num_ineq. 02552 for (dimension_type i = y_cs_num_ineq; i < p_nonred_ineq_size; ++i) 02553 if (p_nonred_ineq[i]) 02554 result_cs.insert(*p_nonred_ineq[i]); 02555 } 02556 } 02557 02558 Polyhedron result_ph(x.topology(), x.space_dim, UNIVERSE); 02559 result_ph.add_recycled_constraints(result_cs); 02560 x.swap(result_ph); 02561 assert(x.OK()); 02562 return true; 02563 }
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
.
var | The variable to which the affine expression is assigned; | |
expr | The numerator of the affine expression; | |
denominator | The denominator of the affine expression (optional argument with default value 1). |
std::invalid_argument | Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a space dimension of *this . |
is assigned to var
where expr
is (
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:
var
in this transformation (i.e.,
so that the inverse transformation is
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 is a
matrix representing the rays of the polyhedron,
is a
matrix representing the points of the polyhedron and
and is the affine transformation to apply to
, then the resulting polyhedron is
Affine transformations are, for example:
Definition at line 2784 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Generator_System::affine_image(), Parma_Polyhedra_Library::Constraint_System::affine_preimage(), clear_constraints_up_to_date(), clear_generators_minimized(), clear_sat_c_up_to_date(), clear_sat_g_up_to_date(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), con_sys, constraints_are_up_to_date(), gen_sys, generators_are_up_to_date(), has_something_pending(), marked_empty(), minimize(), Parma_Polyhedra_Library::neg_assign(), OK(), remove_pending_to_obtain_generators(), space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
Referenced by fold_space_dimensions(), and generalized_affine_image().
02786 { 02787 // The denominator cannot be zero. 02788 if (denominator == 0) 02789 throw_invalid_argument("affine_image(v, e, d)", "d == 0"); 02790 02791 // Dimension-compatibility checks. 02792 // The dimension of `expr' should not be greater than the dimension 02793 // of `*this'. 02794 if (space_dim < expr.space_dimension()) 02795 throw_dimension_incompatible("affine_image(v, e, d)", "e", expr); 02796 // `var' should be one of the dimensions of the polyhedron. 02797 const dimension_type var_space_dim = var.space_dimension(); 02798 if (space_dim < var_space_dim) 02799 throw_dimension_incompatible("affine_image(v, e, d)", "v", var); 02800 02801 if (marked_empty()) 02802 return; 02803 02804 if (expr.coefficient(var) != 0) { 02805 // The transformation is invertible: 02806 // minimality and saturators are preserved, so that 02807 // pending rows, if present, are correctly handled. 02808 if (generators_are_up_to_date()) { 02809 // Generator_System::affine_image() requires the third argument 02810 // to be a positive Coefficient. 02811 if (denominator > 0) 02812 gen_sys.affine_image(var_space_dim, expr, denominator); 02813 else 02814 gen_sys.affine_image(var_space_dim, -expr, -denominator); 02815 } 02816 if (constraints_are_up_to_date()) { 02817 // To build the inverse transformation, 02818 // after copying and negating `expr', 02819 // we exchange the roles of `expr[var_space_dim]' and `denominator'. 02820 Linear_Expression inverse; 02821 if (expr[var_space_dim] > 0) { 02822 inverse = -expr; 02823 inverse[var_space_dim] = denominator; 02824 con_sys.affine_preimage(var_space_dim, inverse, expr[var_space_dim]); 02825 } 02826 else { 02827 // The new denominator is negative: we negate everything once 02828 // more, as Constraint_System::affine_preimage() requires the 02829 // third argument to be positive. 02830 inverse = expr; 02831 inverse[var_space_dim] = denominator; 02832 neg_assign(inverse[var_space_dim]); 02833 con_sys.affine_preimage(var_space_dim, inverse, -expr[var_space_dim]); 02834 } 02835 } 02836 } 02837 else { 02838 // The transformation is not invertible. 02839 // We need an up-to-date system of generators. 02840 if (has_something_pending()) 02841 remove_pending_to_obtain_generators(); 02842 else if (!generators_are_up_to_date()) 02843 minimize(); 02844 if (!marked_empty()) { 02845 // Generator_System::affine_image() requires the third argument 02846 // to be a positive Coefficient. 02847 if (denominator > 0) 02848 gen_sys.affine_image(var_space_dim, expr, denominator); 02849 else 02850 gen_sys.affine_image(var_space_dim, -expr, -denominator); 02851 02852 clear_constraints_up_to_date(); 02853 clear_generators_minimized(); 02854 clear_sat_c_up_to_date(); 02855 clear_sat_g_up_to_date(); 02856 } 02857 } 02858 assert(OK()); 02859 }
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
.
var | The variable to which the affine expression is substituted; | |
expr | The numerator of the affine expression; | |
denominator | The denominator of the affine expression (optional argument with default value 1). |
std::invalid_argument | Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a space dimension of *this . |
is assigned to var
where expr
is (
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:
var
in this transformation (i.e.
, the inverse transformation is
.
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 is a
matrix representing the constraints of the polyhedron,
is the affine transformation to apply to
and
The resulting polyhedron is
where is defined as follows:
Definition at line 2864 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Generator_System::affine_image(), Parma_Polyhedra_Library::Constraint_System::affine_preimage(), clear_constraints_minimized(), clear_generators_up_to_date(), clear_sat_c_up_to_date(), clear_sat_g_up_to_date(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), con_sys, constraints_are_up_to_date(), gen_sys, generators_are_up_to_date(), has_something_pending(), marked_empty(), minimize(), Parma_Polyhedra_Library::neg_assign(), OK(), remove_pending_to_obtain_constraints(), space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
Referenced by generalized_affine_preimage().
02866 { 02867 // The denominator cannot be zero. 02868 if (denominator == 0) 02869 throw_invalid_argument("affine_preimage(v, e, d)", "d == 0"); 02870 02871 // Dimension-compatibility checks. 02872 // The dimension of `expr' should not be greater than the dimension 02873 // of `*this'. 02874 if (space_dim < expr.space_dimension()) 02875 throw_dimension_incompatible("affine_preimage(v, e, d)", "e", expr); 02876 // `var' should be one of the dimensions of the polyhedron. 02877 const dimension_type var_space_dim = var.space_dimension(); 02878 if (space_dim < var_space_dim) 02879 throw_dimension_incompatible("affine_preimage(v, e, d)", "v", var); 02880 02881 if (marked_empty()) 02882 return; 02883 02884 if (expr.coefficient(var) != 0) { 02885 // The transformation is invertible: 02886 // minimality and saturators are preserved. 02887 if (constraints_are_up_to_date()) { 02888 // Constraint_System::affine_preimage() requires the third argument 02889 // to be a positive Coefficient. 02890 if (denominator > 0) 02891 con_sys.affine_preimage(var_space_dim, expr, denominator); 02892 else 02893 con_sys.affine_preimage(var_space_dim, -expr, -denominator); 02894 } 02895 if (generators_are_up_to_date()) { 02896 // To build the inverse transformation, 02897 // after copying and negating `expr', 02898 // we exchange the roles of `expr[var_space_dim]' and `denominator'. 02899 Linear_Expression inverse; 02900 if (expr[var_space_dim] > 0) { 02901 inverse = -expr; 02902 inverse[var_space_dim] = denominator; 02903 gen_sys.affine_image(var_space_dim, inverse, expr[var_space_dim]); 02904 } 02905 else { 02906 // The new denominator is negative: 02907 // we negate everything once more, as Generator_System::affine_image() 02908 // requires the third argument to be positive. 02909 inverse = expr; 02910 inverse[var_space_dim] = denominator; 02911 neg_assign(inverse[var_space_dim]); 02912 gen_sys.affine_image(var_space_dim, inverse, -expr[var_space_dim]); 02913 } 02914 } 02915 } 02916 else { 02917 // The transformation is not invertible. 02918 // We need an up-to-date system of constraints. 02919 if (has_something_pending()) 02920 remove_pending_to_obtain_constraints(); 02921 else if (!constraints_are_up_to_date()) 02922 minimize(); 02923 // Constraint_System::affine_preimage() requires the third argument 02924 // to be a positive Coefficient. 02925 if (denominator > 0) 02926 con_sys.affine_preimage(var_space_dim, expr, denominator); 02927 else 02928 con_sys.affine_preimage(var_space_dim, -expr, -denominator); 02929 // Generators, minimality and saturators are no longer valid. 02930 clear_generators_up_to_date(); 02931 clear_constraints_minimized(); 02932 clear_sat_c_up_to_date(); 02933 clear_sat_g_up_to_date(); 02934 } 02935 assert(OK()); 02936 }
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 , where
is the relation symbol encoded by
relsym
.
var | The left hand side variable of the generalized affine relation; | |
relsym | The relation symbol; | |
expr | The numerator of the right hand side affine expression; | |
denominator | The denominator of the right hand side affine expression (optional argument with default value 1). |
std::invalid_argument | Thrown 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 3088 of file Polyhedron_public.cc.
References add_generator(), Parma_Polyhedra_Library::Linear_System::add_row(), affine_image(), clear_constraints_up_to_date(), clear_generators_minimized(), clear_sat_c_up_to_date(), clear_sat_g_up_to_date(), Parma_Polyhedra_Library::EQUAL, gen_sys, Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, is_empty(), is_necessarily_closed(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, minimize(), Parma_Polyhedra_Library::NOT_EQUAL, Parma_Polyhedra_Library::Matrix::num_rows(), OK(), Parma_Polyhedra_Library::Linear_System::set_sorted(), space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
Referenced by bounded_affine_image(), and generalized_affine_preimage().
03091 { 03092 // The denominator cannot be zero. 03093 if (denominator == 0) 03094 throw_invalid_argument("generalized_affine_image(v, r, e, d)", "d == 0"); 03095 03096 // Dimension-compatibility checks. 03097 // The dimension of `expr' should not be greater than the dimension 03098 // of `*this'. 03099 if (space_dim < expr.space_dimension()) 03100 throw_dimension_incompatible("generalized_affine_image(v, r, e, d)", 03101 "e", expr); 03102 // `var' should be one of the dimensions of the polyhedron. 03103 const dimension_type var_space_dim = var.space_dimension(); 03104 if (space_dim < var_space_dim) 03105 throw_dimension_incompatible("generalized_affine_image(v, r, e, d)", 03106 "v", var); 03107 03108 // Strict relation symbols are only admitted for NNC polyhedra. 03109 if (is_necessarily_closed() 03110 && (relsym == LESS_THAN || relsym == GREATER_THAN)) 03111 throw_invalid_argument("generalized_affine_image(v, r, e, d)", 03112 "r is a strict relation symbol"); 03113 // The relation symbol cannot be a disequality. 03114 if (relsym == NOT_EQUAL) 03115 throw_invalid_argument("generalized_affine_image(v, r, e, d)", 03116 "r is the disequality relation symbol"); 03117 03118 // First compute the affine image. 03119 affine_image(var, expr, denominator); 03120 03121 if (relsym == EQUAL) 03122 // The affine relation is indeed an affine function. 03123 return; 03124 03125 // Any image of an empty polyhedron is empty. 03126 // Note: DO check for emptiness here, as we will later add a ray. 03127 if (is_empty()) 03128 return; 03129 03130 switch (relsym) { 03131 case LESS_OR_EQUAL: 03132 add_generator(ray(-var)); 03133 break; 03134 case GREATER_OR_EQUAL: 03135 add_generator(ray(var)); 03136 break; 03137 case LESS_THAN: 03138 // Intentionally fall through. 03139 case GREATER_THAN: 03140 { 03141 // The relation symbol is strict. 03142 assert(!is_necessarily_closed()); 03143 // While adding the ray, we minimize the generators 03144 // in order to avoid adding too many redundant generators later. 03145 add_generator(ray(relsym == GREATER_THAN ? var : -var)); 03146 minimize(); 03147 // We split each point of the generator system into two generators: 03148 // a closure point, having the same coordinates of the given point, 03149 // and another point, having the same coordinates for all but the 03150 // `var' dimension, which is displaced along the direction of the 03151 // newly introduced ray. 03152 const dimension_type eps_index = space_dim + 1; 03153 for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) 03154 if (gen_sys[i].is_point()) { 03155 Generator& g = gen_sys[i]; 03156 // Add a `var'-displaced copy of `g' to the generator system. 03157 gen_sys.add_row(g); 03158 if (relsym == GREATER_THAN) 03159 ++gen_sys[gen_sys.num_rows()-1][var_space_dim]; 03160 else 03161 --gen_sys[gen_sys.num_rows()-1][var_space_dim]; 03162 // Transform `g' into a closure point. 03163 g[eps_index] = 0; 03164 } 03165 clear_constraints_up_to_date(); 03166 clear_generators_minimized(); 03167 gen_sys.set_sorted(false); 03168 clear_sat_c_up_to_date(); 03169 clear_sat_g_up_to_date(); 03170 } 03171 break; 03172 default: 03173 // The EQUAL and NOT_EQUAL cases have been already dealt with. 03174 throw std::runtime_error("PPL internal error"); 03175 } 03176 assert(OK()); 03177 }
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 , where
is the relation symbol encoded by
relsym
.
var | The left hand side variable of the generalized affine relation; | |
relsym | The relation symbol; | |
expr | The numerator of the right hand side affine expression; | |
denominator | The denominator of the right hand side affine expression (optional argument with default value 1). |
std::invalid_argument | Thrown 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 3181 of file Polyhedron_public.cc.
References affine_preimage(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, generalized_affine_image(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, is_necessarily_closed(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::NOT_EQUAL, OK(), refine_no_check(), space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), TEMP_INTEGER, throw_dimension_incompatible(), throw_invalid_argument(), and unconstrain().
03184 { 03185 // The denominator cannot be zero. 03186 if (denominator == 0) 03187 throw_invalid_argument("generalized_affine_preimage(v, r, e, d)", 03188 "d == 0"); 03189 03190 // Dimension-compatibility checks. 03191 // The dimension of `expr' should not be greater than the dimension 03192 // of `*this'. 03193 if (space_dim < expr.space_dimension()) 03194 throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)", 03195 "e", expr); 03196 // `var' should be one of the dimensions of the polyhedron. 03197 const dimension_type var_space_dim = var.space_dimension(); 03198 if (space_dim < var_space_dim) 03199 throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)", 03200 "v", var); 03201 03202 // Strict relation symbols are only admitted for NNC polyhedra. 03203 if (is_necessarily_closed() 03204 && (relsym == LESS_THAN || relsym == GREATER_THAN)) 03205 throw_invalid_argument("generalized_affine_preimage(v, r, e, d)", 03206 "r is a strict relation symbol"); 03207 // The relation symbol cannot be a disequality. 03208 if (relsym == NOT_EQUAL) 03209 throw_invalid_argument("generalized_affine_preimage(v, r, e, d)", 03210 "r is the disequality relation symbol"); 03211 03212 // Check whether the affine relation is indeed an affine function. 03213 if (relsym == EQUAL) { 03214 affine_preimage(var, expr, denominator); 03215 return; 03216 } 03217 03218 // Compute the reversed relation symbol to simplify later coding. 03219 Relation_Symbol reversed_relsym; 03220 switch (relsym) { 03221 case LESS_THAN: 03222 reversed_relsym = GREATER_THAN; 03223 break; 03224 case LESS_OR_EQUAL: 03225 reversed_relsym = GREATER_OR_EQUAL; 03226 break; 03227 case GREATER_OR_EQUAL: 03228 reversed_relsym = LESS_OR_EQUAL; 03229 break; 03230 case GREATER_THAN: 03231 reversed_relsym = LESS_THAN; 03232 break; 03233 default: 03234 // The EQUAL and NOT_EQUAL cases have been already dealt with. 03235 throw std::runtime_error("PPL internal error"); 03236 } 03237 03238 // Check whether the preimage of this affine relation can be easily 03239 // computed as the image of its inverse relation. 03240 const Coefficient& var_coefficient = expr.coefficient(var); 03241 if (var_coefficient != 0) { 03242 Linear_Expression inverse_expr 03243 = expr - (denominator + var_coefficient) * var; 03244 TEMP_INTEGER(inverse_denominator); 03245 neg_assign(inverse_denominator, var_coefficient); 03246 Relation_Symbol inverse_relsym 03247 = (sgn(denominator) == sgn(inverse_denominator)) 03248 ? relsym : reversed_relsym; 03249 generalized_affine_image(var, inverse_relsym, inverse_expr, 03250 inverse_denominator); 03251 return; 03252 } 03253 03254 // Here `var_coefficient == 0', so that the preimage cannot 03255 // be easily computed by inverting the affine relation. 03256 // Shrink the polyhedron by adding the constraint induced 03257 // by the affine relation. 03258 const Relation_Symbol corrected_relsym 03259 = (denominator > 0) ? relsym : reversed_relsym; 03260 switch (corrected_relsym) { 03261 case LESS_THAN: 03262 refine_no_check(denominator*var < expr); 03263 break; 03264 case LESS_OR_EQUAL: 03265 refine_no_check(denominator*var <= expr); 03266 break; 03267 case GREATER_OR_EQUAL: 03268 refine_no_check(denominator*var >= expr); 03269 break; 03270 case GREATER_THAN: 03271 refine_no_check(denominator*var > expr); 03272 break; 03273 default: 03274 // The EQUAL and NOT_EQUAL cases have been already dealt with. 03275 throw std::runtime_error("PPL internal error"); 03276 } 03277 unconstrain(var); 03278 assert(OK()); 03279 }
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 , where
is the relation symbol encoded by
relsym
.
lhs | The left hand side affine expression; | |
relsym | The relation symbol; | |
rhs | The right hand side affine expression. |
std::invalid_argument | Thrown if *this is dimension-incompatible with lhs or rhs or if *this is a C_Polyhedron and relsym is a strict relation symbol. |
Definition at line 3282 of file Polyhedron_public.cc.
References add_recycled_generators(), add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Generator_System::insert(), is_empty(), is_necessarily_closed(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, marked_empty(), Parma_Polyhedra_Library::NOT_EQUAL, OK(), refine_no_check(), remove_higher_space_dimensions(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
03284 { 03285 // Dimension-compatibility checks. 03286 // The dimension of `lhs' should not be greater than the dimension 03287 // of `*this'. 03288 dimension_type lhs_space_dim = lhs.space_dimension(); 03289 if (space_dim < lhs_space_dim) 03290 throw_dimension_incompatible("generalized_affine_image(e1, r, e2)", 03291 "e1", lhs); 03292 // The dimension of `rhs' should not be greater than the dimension 03293 // of `*this'. 03294 const dimension_type rhs_space_dim = rhs.space_dimension(); 03295 if (space_dim < rhs_space_dim) 03296 throw_dimension_incompatible("generalized_affine_image(e1, r, e2)", 03297 "e2", rhs); 03298 03299 // Strict relation symbols are only admitted for NNC polyhedra. 03300 if (is_necessarily_closed() 03301 && (relsym == LESS_THAN || relsym == GREATER_THAN)) 03302 throw_invalid_argument("generalized_affine_image(e1, r, e2)", 03303 "r is a strict relation symbol"); 03304 // The relation symbol cannot be a disequality. 03305 if (relsym == NOT_EQUAL) 03306 throw_invalid_argument("generalized_affine_image(e1, r, e2)", 03307 "r is the disequality relation symbol"); 03308 03309 // Any image of an empty polyhedron is empty. 03310 if (marked_empty()) 03311 return; 03312 03313 // Compute the actual space dimension of `lhs', 03314 // i.e., the highest dimension having a non-zero coefficient in `lhs'. 03315 for ( ; lhs_space_dim > 0; lhs_space_dim--) 03316 if (lhs.coefficient(Variable(lhs_space_dim - 1)) != 0) 03317 break; 03318 // If all variables have a zero coefficient, then `lhs' is a constant: 03319 // we can simply add the constraint `lhs relsym rhs'. 03320 if (lhs_space_dim == 0) { 03321 switch (relsym) { 03322 case LESS_THAN: 03323 refine_no_check(lhs < rhs); 03324 break; 03325 case LESS_OR_EQUAL: 03326 refine_no_check(lhs <= rhs); 03327 break; 03328 case EQUAL: 03329 refine_no_check(lhs == rhs); 03330 break; 03331 case GREATER_OR_EQUAL: 03332 refine_no_check(lhs >= rhs); 03333 break; 03334 case GREATER_THAN: 03335 refine_no_check(lhs > rhs); 03336 break; 03337 case NOT_EQUAL: 03338 // The NOT_EQUAL case has been already dealt with. 03339 throw std::runtime_error("PPL internal error"); 03340 } 03341 return; 03342 } 03343 03344 // Gather in `new_lines' the collections of all the lines having 03345 // the direction of variables occurring in `lhs'. 03346 // While at it, check whether or not there exists a variable 03347 // occurring in both `lhs' and `rhs'. 03348 Generator_System new_lines; 03349 bool lhs_vars_intersects_rhs_vars = false; 03350 for (dimension_type i = lhs_space_dim; i-- > 0; ) 03351 if (lhs.coefficient(Variable(i)) != 0) { 03352 new_lines.insert(line(Variable(i))); 03353 if (rhs.coefficient(Variable(i)) != 0) 03354 lhs_vars_intersects_rhs_vars = true; 03355 } 03356 03357 if (lhs_vars_intersects_rhs_vars) { 03358 // Some variables in `lhs' also occur in `rhs'. 03359 // To ease the computation, we add an additional dimension. 03360 const Variable new_var = Variable(space_dim); 03361 add_space_dimensions_and_embed(1); 03362 03363 // Constrain the new dimension to be equal to the right hand side. 03364 // (check for emptiness because we will add lines). 03365 refine_no_check(new_var == rhs); 03366 if (!is_empty()) { 03367 // Existentially quantify the variables in the left hand side. 03368 add_recycled_generators(new_lines); 03369 03370 // Constrain the new dimension so that it is related to 03371 // the left hand side as dictated by `relsym' 03372 // (we force minimization because we will need the generators). 03373 switch (relsym) { 03374 case LESS_THAN: 03375 refine_no_check(lhs < new_var); 03376 break; 03377 case LESS_OR_EQUAL: 03378 refine_no_check(lhs <= new_var); 03379 break; 03380 case EQUAL: 03381 refine_no_check(lhs == new_var); 03382 break; 03383 case GREATER_OR_EQUAL: 03384 refine_no_check(lhs >= new_var); 03385 break; 03386 case GREATER_THAN: 03387 refine_no_check(lhs > new_var); 03388 break; 03389 case NOT_EQUAL: 03390 // The NOT_EQUAL case has been already dealt with. 03391 throw std::runtime_error("PPL internal error"); 03392 } 03393 } 03394 // Remove the temporarily added dimension. 03395 remove_higher_space_dimensions(space_dim-1); 03396 } 03397 else { 03398 // `lhs' and `rhs' variables are disjoint: 03399 // there is no need to add a further dimension. 03400 03401 // Any image of an empty polyhedron is empty. 03402 // Note: DO check for emptiness here, as we will add lines. 03403 if (is_empty()) 03404 return; 03405 03406 // Existentially quantify the variables in the left hand side. 03407 add_recycled_generators(new_lines); 03408 03409 // Constrain the left hand side expression so that it is related to 03410 // the right hand side expression as dictated by `relsym'. 03411 switch (relsym) { 03412 case LESS_THAN: 03413 refine_no_check(lhs < rhs); 03414 break; 03415 case LESS_OR_EQUAL: 03416 refine_no_check(lhs <= rhs); 03417 break; 03418 case EQUAL: 03419 refine_no_check(lhs == rhs); 03420 break; 03421 case GREATER_OR_EQUAL: 03422 refine_no_check(lhs >= rhs); 03423 break; 03424 case GREATER_THAN: 03425 refine_no_check(lhs > rhs); 03426 break; 03427 case NOT_EQUAL: 03428 // The NOT_EQUAL case has been already dealt with. 03429 throw std::runtime_error("PPL internal error"); 03430 } 03431 } 03432 assert(OK()); 03433 }
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 , where
is the relation symbol encoded by
relsym
.
lhs | The left hand side affine expression; | |
relsym | The relation symbol; | |
rhs | The right hand side affine expression. |
std::invalid_argument | Thrown if *this is dimension-incompatible with lhs or rhs or if *this is a C_Polyhedron and relsym is a strict relation symbol. |
Definition at line 3436 of file Polyhedron_public.cc.
References add_recycled_generators(), add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, generalized_affine_image(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::Generator_System::insert(), is_empty(), is_necessarily_closed(), Parma_Polyhedra_Library::LESS_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN, marked_empty(), Parma_Polyhedra_Library::NOT_EQUAL, OK(), refine_no_check(), remove_higher_space_dimensions(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
03438 { 03439 // Dimension-compatibility checks. 03440 // The dimension of `lhs' should not be greater than the dimension 03441 // of `*this'. 03442 dimension_type lhs_space_dim = lhs.space_dimension(); 03443 if (space_dim < lhs_space_dim) 03444 throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)", 03445 "e1", lhs); 03446 // The dimension of `rhs' should not be greater than the dimension 03447 // of `*this'. 03448 const dimension_type rhs_space_dim = rhs.space_dimension(); 03449 if (space_dim < rhs_space_dim) 03450 throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)", 03451 "e2", rhs); 03452 03453 // Strict relation symbols are only admitted for NNC polyhedra. 03454 if (is_necessarily_closed() 03455 && (relsym == LESS_THAN || relsym == GREATER_THAN)) 03456 throw_invalid_argument("generalized_affine_preimage(e1, r, e2)", 03457 "r is a strict relation symbol"); 03458 // The relation symbol cannot be a disequality. 03459 if (relsym == NOT_EQUAL) 03460 throw_invalid_argument("generalized_affine_preimage(e1, r, e2)", 03461 "r is the disequality relation symbol"); 03462 03463 // Any preimage of an empty polyhedron is empty. 03464 if (marked_empty()) 03465 return; 03466 03467 // Compute the actual space dimension of `lhs', 03468 // i.e., the highest dimension having a non-zero coefficient in `lhs'. 03469 for ( ; lhs_space_dim > 0; lhs_space_dim--) 03470 if (lhs.coefficient(Variable(lhs_space_dim - 1)) != 0) 03471 break; 03472 03473 // If all variables have a zero coefficient, then `lhs' is a constant: 03474 // in this case, preimage and image happen to be the same. 03475 if (lhs_space_dim == 0) { 03476 generalized_affine_image(lhs, relsym, rhs); 03477 return; 03478 } 03479 03480 // Gather in `new_lines' the collections of all the lines having 03481 // the direction of variables occurring in `lhs'. 03482 // While at it, check whether or not there exists a variable 03483 // occurring in both `lhs' and `rhs'. 03484 Generator_System new_lines; 03485 bool lhs_vars_intersects_rhs_vars = false; 03486 for (dimension_type i = lhs_space_dim; i-- > 0; ) 03487 if (lhs.coefficient(Variable(i)) != 0) { 03488 new_lines.insert(line(Variable(i))); 03489 if (rhs.coefficient(Variable(i)) != 0) 03490 lhs_vars_intersects_rhs_vars = true; 03491 } 03492 03493 if (lhs_vars_intersects_rhs_vars) { 03494 // Some variables in `lhs' also occur in `rhs'. 03495 // To ease the computation, we add an additional dimension. 03496 const Variable new_var = Variable(space_dim); 03497 add_space_dimensions_and_embed(1); 03498 03499 // Constrain the new dimension to be equal to `lhs' 03500 // (also check for emptiness because we have to add lines). 03501 refine_no_check(new_var == lhs); 03502 if (!is_empty()) { 03503 // Existentially quantify the variables in the left hand side. 03504 add_recycled_generators(new_lines); 03505 03506 // Constrain the new dimension so that it is related to 03507 // the right hand side as dictated by `relsym'. 03508 switch (relsym) { 03509 case LESS_THAN: 03510 refine_no_check(new_var < rhs); 03511 break; 03512 case LESS_OR_EQUAL: 03513 refine_no_check(new_var <= rhs); 03514 break; 03515 case EQUAL: 03516 refine_no_check(new_var == rhs); 03517 break; 03518 case GREATER_OR_EQUAL: 03519 refine_no_check(new_var >= rhs); 03520 break; 03521 case GREATER_THAN: 03522 refine_no_check(new_var > rhs); 03523 break; 03524 case NOT_EQUAL: 03525 // The NOT_EQUAL case has been already dealt with. 03526 throw std::runtime_error("PPL internal error"); 03527 } 03528 } 03529 // Remove the temporarily added dimension. 03530 remove_higher_space_dimensions(space_dim-1); 03531 } 03532 else { 03533 // `lhs' and `rhs' variables are disjoint: 03534 // there is no need to add a further dimension. 03535 03536 // Constrain the left hand side expression so that it is related to 03537 // the right hand side expression as dictated by `relsym'. 03538 switch (relsym) { 03539 case LESS_THAN: 03540 refine_no_check(lhs < rhs); 03541 break; 03542 case LESS_OR_EQUAL: 03543 refine_no_check(lhs <= rhs); 03544 break; 03545 case EQUAL: 03546 refine_no_check(lhs == rhs); 03547 break; 03548 case GREATER_OR_EQUAL: 03549 refine_no_check(lhs >= rhs); 03550 break; 03551 case GREATER_THAN: 03552 refine_no_check(lhs > rhs); 03553 break; 03554 case NOT_EQUAL: 03555 // The NOT_EQUAL case has been already dealt with. 03556 throw std::runtime_error("PPL internal error"); 03557 } 03558 // Any image of an empty polyhedron is empty. 03559 // Note: DO check for emptiness here, as we will add lines. 03560 if (is_empty()) 03561 return; 03562 // Existentially quantify all the variables occurring in `lhs'. 03563 add_recycled_generators(new_lines); 03564 } 03565 assert(OK()); 03566 }
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 .
var | The variable updated by the affine relation; | |
lb_expr | The numerator of the lower bounding affine expression; | |
ub_expr | The numerator of the upper bounding affine expression; | |
denominator | The (common) denominator for the lower and upper bounding affine expressions (optional argument with default value 1). |
std::invalid_argument | Thrown if denominator is zero or if lb_expr (resp., ub_expr ) and *this are dimension-incompatible or if var is not a space dimension of *this . |
Definition at line 2940 of file Polyhedron_public.cc.
References add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), generalized_affine_image(), Parma_Polyhedra_Library::GREATER_OR_EQUAL, Parma_Polyhedra_Library::LESS_OR_EQUAL, marked_empty(), OK(), refine_no_check(), remove_higher_space_dimensions(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
02943 { 02944 // The denominator cannot be zero. 02945 if (denominator == 0) 02946 throw_invalid_argument("bounded_affine_image(v, lb, ub, d)", "d == 0"); 02947 02948 // Dimension-compatibility checks. 02949 // `var' should be one of the dimensions of the polyhedron. 02950 const dimension_type var_space_dim = var.space_dimension(); 02951 if (space_dim < var_space_dim) 02952 throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)", 02953 "v", var); 02954 // The dimension of `lb_expr' and `ub_expr' should not be 02955 // greater than the dimension of `*this'. 02956 const dimension_type lb_space_dim = lb_expr.space_dimension(); 02957 if (space_dim < lb_space_dim) 02958 throw_dimension_incompatible("bounded_affine_image(v, lb, ub)", 02959 "lb", lb_expr); 02960 const dimension_type ub_space_dim = ub_expr.space_dimension(); 02961 if (space_dim < ub_space_dim) 02962 throw_dimension_incompatible("bounded_affine_image(v, lb, ub)", 02963 "ub", ub_expr); 02964 02965 // Any image of an empty polyhedron is empty. 02966 if (marked_empty()) 02967 return; 02968 02969 // Check whether `var' occurs in `lb_expr' and/or `ub_expr'. 02970 if (lb_expr.coefficient(var) == 0) { 02971 // Here `var' may only occur in `ub_expr'. 02972 generalized_affine_image(var, 02973 LESS_OR_EQUAL, 02974 ub_expr, 02975 denominator); 02976 if (denominator > 0) 02977 refine_no_check(lb_expr <= denominator*var); 02978 else 02979 refine_no_check(denominator*var <= lb_expr); 02980 } 02981 else if (ub_expr.coefficient(var) == 0) { 02982 // Here `var' only occurs in `lb_expr'. 02983 generalized_affine_image(var, 02984 GREATER_OR_EQUAL, 02985 lb_expr, 02986 denominator); 02987 if (denominator > 0) 02988 refine_no_check(denominator*var <= ub_expr); 02989 else 02990 refine_no_check(ub_expr <= denominator*var); 02991 } 02992 else { 02993 // Here `var' occurs in both `lb_expr' and `ub_expr'. 02994 // To ease the computation, we add an additional dimension. 02995 const Variable new_var = Variable(space_dim); 02996 add_space_dimensions_and_embed(1); 02997 // Constrain the new dimension to be equal to `ub_expr'. 02998 refine_no_check(denominator*new_var == ub_expr); 02999 // Apply the affine lower bound. 03000 generalized_affine_image(var, 03001 GREATER_OR_EQUAL, 03002 lb_expr, 03003 denominator); 03004 if (!marked_empty()) 03005 // Now apply the affine upper bound, as recorded in `new_var'. 03006 refine_no_check(new_var >= var); 03007 // Remove the temporarily added dimension. 03008 remove_higher_space_dimensions(space_dim-1); 03009 } 03010 assert(OK()); 03011 }
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 .
var | The variable updated by the affine relation; | |
lb_expr | The numerator of the lower bounding affine expression; | |
ub_expr | The numerator of the upper bounding affine expression; | |
denominator | The (common) denominator for the lower and upper bounding affine expressions (optional argument with default value 1). |
std::invalid_argument | Thrown if denominator is zero or if lb_expr (resp., ub_expr ) and *this are dimension-incompatible or if var is not a space dimension of *this . |
Definition at line 3015 of file Polyhedron_public.cc.
References add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), con_sys, constraints_are_up_to_date(), gen_sys, generators_are_up_to_date(), marked_empty(), OK(), Parma_Polyhedra_Library::Linear_System::permute_columns(), refine_no_check(), remove_higher_space_dimensions(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), throw_dimension_incompatible(), throw_invalid_argument(), and unconstrain().
03018 { 03019 // The denominator cannot be zero. 03020 if (denominator == 0) 03021 throw_invalid_argument("bounded_affine_preimage(v, lb, ub, d)", "d == 0"); 03022 03023 // Dimension-compatibility checks. 03024 // `var' should be one of the dimensions of the polyhedron. 03025 const dimension_type var_space_dim = var.space_dimension(); 03026 if (space_dim < var_space_dim) 03027 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)", 03028 "v", var); 03029 // The dimension of `lb_expr' and `ub_expr' should not be 03030 // greater than the dimension of `*this'. 03031 const dimension_type lb_space_dim = lb_expr.space_dimension(); 03032 if (space_dim < lb_space_dim) 03033 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)", 03034 "lb", lb_expr); 03035 const dimension_type ub_space_dim = ub_expr.space_dimension(); 03036 if (space_dim < ub_space_dim) 03037 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)", 03038 "ub", ub_expr); 03039 03040 // Any preimage of an empty polyhedron is empty. 03041 if (marked_empty()) 03042 return; 03043 03044 // Check whether `var' occurs in neither `lb_expr' nor `ub_expr'. 03045 if (lb_expr.coefficient(var) == 0 && ub_expr.coefficient(var) == 0) { 03046 if (denominator > 0) { 03047 refine_no_check(lb_expr <= denominator*var); 03048 refine_no_check(denominator*var <= ub_expr); 03049 } 03050 else { 03051 refine_no_check(ub_expr <= denominator*var); 03052 refine_no_check(denominator*var <= lb_expr); 03053 } 03054 unconstrain(var); 03055 } 03056 else { 03057 // Here `var' occurs in `lb_expr' or `ub_expr'. 03058 // To ease the computation, add an additional dimension. 03059 const Variable new_var = Variable(space_dim); 03060 add_space_dimensions_and_embed(1); 03061 // Swap dimensions `var' and `new_var'. 03062 std::vector<dimension_type> swapping_cycle; 03063 swapping_cycle.push_back(var_space_dim); 03064 swapping_cycle.push_back(space_dim); 03065 swapping_cycle.push_back(0); 03066 if (constraints_are_up_to_date()) 03067 con_sys.permute_columns(swapping_cycle); 03068 if (generators_are_up_to_date()) 03069 gen_sys.permute_columns(swapping_cycle); 03070 // Constrain the new dimension as dictated by `lb_expr' and `ub_expr'. 03071 // (we force minimization because we will need the generators). 03072 if (denominator > 0) { 03073 refine_no_check(lb_expr <= denominator*new_var); 03074 refine_no_check(denominator*new_var <= ub_expr); 03075 } 03076 else { 03077 refine_no_check(ub_expr <= denominator*new_var); 03078 refine_no_check(denominator*new_var <= lb_expr); 03079 } 03080 // Remove the temporarily added dimension. 03081 remove_higher_space_dimensions(space_dim-1); 03082 } 03083 assert(OK()); 03084 }
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
.
std::invalid_argument | Thrown if *this and y are topology-incompatible or dimension-incompatible. |
Definition at line 3569 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Linear_System::add_pending_rows(), Parma_Polyhedra_Library::Linear_Row::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::Matrix::erase_to_end(), gen_sys, generators_are_up_to_date(), has_pending_constraints(), is_necessarily_closed(), Parma_Polyhedra_Library::Linear_System::is_sorted(), marked_empty(), Parma_Polyhedra_Library::Linear_System::merge_rows_assign(), Parma_Polyhedra_Library::Row::normalize(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), Parma_Polyhedra_Library::Generator::POINT, process_pending_constraints(), set_empty(), set_generators_pending(), Parma_Polyhedra_Library::Linear_System::sort_rows(), space_dim, Parma_Polyhedra_Library::swap(), throw_dimension_incompatible(), throw_topology_incompatible(), topology(), Parma_Polyhedra_Library::Linear_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().
03569 { 03570 Polyhedron& x = *this; 03571 // Topology compatibility check. 03572 if (x.topology() != y.topology()) 03573 throw_topology_incompatible("time_elapse_assign(y)", "y", y); 03574 // Dimension-compatibility checks. 03575 if (x.space_dim != y.space_dim) 03576 throw_dimension_incompatible("time_elapse_assign(y)", "y", y); 03577 03578 // Dealing with the zero-dimensional case. 03579 if (x.space_dim == 0) { 03580 if (y.marked_empty()) 03581 x.set_empty(); 03582 return; 03583 } 03584 03585 // If either one of `x' or `y' is empty, the result is empty too. 03586 if (x.marked_empty() || y.marked_empty() 03587 || (x.has_pending_constraints() && !x.process_pending_constraints()) 03588 || (!x.generators_are_up_to_date() && !x.update_generators()) 03589 || (y.has_pending_constraints() && !y.process_pending_constraints()) 03590 || (!y.generators_are_up_to_date() && !y.update_generators())) { 03591 x.set_empty(); 03592 return; 03593 } 03594 03595 // At this point both generator systems are up-to-date, 03596 // possibly containing pending generators. 03597 Generator_System gs = y.gen_sys; 03598 dimension_type gs_num_rows = gs.num_rows(); 03599 03600 if (!x.is_necessarily_closed()) 03601 // `x' and `y' are NNC polyhedra. 03602 for (dimension_type i = gs_num_rows; i-- > 0; ) 03603 switch (gs[i].type()) { 03604 case Generator::POINT: 03605 // The points of `gs' can be erased, 03606 // since their role can be played by closure points. 03607 --gs_num_rows; 03608 std::swap(gs[i], gs[gs_num_rows]); 03609 break; 03610 case Generator::CLOSURE_POINT: 03611 { 03612 Generator& cp = gs[i]; 03613 // If it is the origin, erase it. 03614 if (cp.all_homogeneous_terms_are_zero()) { 03615 --gs_num_rows; 03616 std::swap(cp, gs[gs_num_rows]); 03617 } 03618 // Otherwise, transform the closure point into a ray. 03619 else { 03620 cp[0] = 0; 03621 // Enforce normalization. 03622 cp.normalize(); 03623 } 03624 } 03625 break; 03626 default: 03627 // For rays and lines, nothing to be done. 03628 break; 03629 } 03630 else 03631 // `x' and `y' are C polyhedra. 03632 for (dimension_type i = gs_num_rows; i-- > 0; ) 03633 switch (gs[i].type()) { 03634 case Generator::POINT: 03635 { 03636 Generator& p = gs[i]; 03637 // If it is the origin, erase it. 03638 if (p.all_homogeneous_terms_are_zero()) { 03639 --gs_num_rows; 03640 std::swap(p, gs[gs_num_rows]); 03641 } 03642 // Otherwise, transform the point into a ray. 03643 else { 03644 p[0] = 0; 03645 // Enforce normalization. 03646 p.normalize(); 03647 } 03648 } 03649 break; 03650 default: 03651 // For rays and lines, nothing to be done. 03652 break; 03653 } 03654 // If it was present, erase the origin point or closure point, 03655 // which cannot be transformed into a valid ray or line. 03656 // For NNC polyhedra, also erase all the points of `gs', 03657 // whose role can be played by the closure points. 03658 // These have been previously moved to the end of `gs'. 03659 gs.erase_to_end(gs_num_rows); 03660 gs.unset_pending_rows(); 03661 03662 // `gs' may now have no rows. 03663 // Namely, this happens when `y' was the singleton polyhedron 03664 // having the origin as the one and only point. 03665 // In such a case, the resulting polyhedron is equal to `x'. 03666 if (gs_num_rows == 0) 03667 return; 03668 03669 // If the polyhedron can have something pending, we add `gs' 03670 // to `gen_sys' as pending rows 03671 if (x.can_have_something_pending()) { 03672 x.gen_sys.add_pending_rows(gs); 03673 x.set_generators_pending(); 03674 } 03675 // Otherwise, the two systems are merged. 03676 // `Linear_System::merge_rows_assign()' requires both systems to be sorted. 03677 else { 03678 if (!x.gen_sys.is_sorted()) 03679 x.gen_sys.sort_rows(); 03680 gs.sort_rows(); 03681 x.gen_sys.merge_rows_assign(gs); 03682 // Only the system of generators is up-to-date. 03683 x.clear_constraints_up_to_date(); 03684 x.clear_generators_minimized(); 03685 } 03686 assert(x.OK(true) && y.OK(true)); 03687 }
void Parma_Polyhedra_Library::Polyhedron::topological_closure_assign | ( | ) |
Assigns to *this
its topological closure.
Definition at line 3690 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Generator_System::add_corresponding_points(), can_have_something_pending(), clear_constraints_minimized(), clear_constraints_up_to_date(), clear_generators_minimized(), clear_generators_up_to_date(), con_sys, constraints_are_up_to_date(), Parma_Polyhedra_Library::Constraint::epsilon_leq_one(), gen_sys, generators_are_up_to_date(), has_pending_constraints(), has_pending_generators(), Parma_Polyhedra_Library::Constraint_System::insert(), is_necessarily_closed(), Parma_Polyhedra_Library::Constraint::is_tautological(), marked_empty(), Parma_Polyhedra_Library::Row::normalize(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), process_pending_constraints(), set_generators_pending(), Parma_Polyhedra_Library::Linear_System::set_sorted(), space_dim, and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
03690 { 03691 // Necessarily closed polyhedra are trivially closed. 03692 if (is_necessarily_closed()) 03693 return; 03694 // Any empty or zero-dimensional polyhedron is closed. 03695 if (marked_empty() || space_dim == 0) 03696 return; 03697 03698 // The computation can be done using constraints or generators. 03699 // If we use constraints, we will change them, so that having pending 03700 // constraints would be useless. If we use generators, we add generators, 03701 // so that having pending generators still makes sense. 03702 03703 // Process any pending constraints. 03704 if (has_pending_constraints() && !process_pending_constraints()) 03705 return; 03706 03707 // Use constraints only if they are available and 03708 // there are no pending generators. 03709 if (!has_pending_generators() && constraints_are_up_to_date()) { 03710 const dimension_type eps_index = space_dim + 1; 03711 bool changed = false; 03712 // Transform all strict inequalities into non-strict ones. 03713 for (dimension_type i = con_sys.num_rows(); i-- > 0; ) { 03714 Constraint& c = con_sys[i]; 03715 if (c[eps_index] < 0 && !c.is_tautological()) { 03716 c[eps_index] = 0; 03717 // Enforce normalization. 03718 c.normalize(); 03719 changed = true; 03720 } 03721 } 03722 if (changed) { 03723 con_sys.insert(Constraint::epsilon_leq_one()); 03724 con_sys.set_sorted(false); 03725 // After changing the system of constraints, the generators 03726 // are no longer up-to-date and the constraints are no longer 03727 // minimized. 03728 clear_generators_up_to_date(); 03729 clear_constraints_minimized(); 03730 } 03731 } 03732 else { 03733 // Here we use generators, possibly keeping constraints. 03734 assert(generators_are_up_to_date()); 03735 // Add the corresponding point to each closure point. 03736 gen_sys.add_corresponding_points(); 03737 if (can_have_something_pending()) 03738 set_generators_pending(); 03739 else { 03740 // We cannot have pending generators; this also implies 03741 // that generators may have lost their sortedness. 03742 gen_sys.unset_pending_rows(); 03743 gen_sys.set_sorted(false); 03744 // Constraints are not up-to-date and generators are not minimized. 03745 clear_constraints_up_to_date(); 03746 clear_generators_minimized(); 03747 } 03748 } 03749 assert(OK()); 03750 }
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
.
y | A polyhedron that must be contained in *this ; | |
tp | An optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique). |
std::invalid_argument | Thrown if *this and y are topology-incompatible or dimension-incompatible. |
Definition at line 665 of file Polyhedron_widenings.cc.
References BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), contains(), Parma_Polyhedra_Library::Matrix::has_no_rows(), Parma_Polyhedra_Library::BHRZ03_Certificate::is_stabilizing(), marked_empty(), minimize(), OK(), select_H79_constraints(), space_dim, Parma_Polyhedra_Library::swap(), throw_dimension_incompatible(), throw_topology_incompatible(), topology(), and Parma_Polyhedra_Library::UNIVERSE.
Referenced by limited_BHRZ03_extrapolation_assign().
00665 { 00666 Polyhedron& x = *this; 00667 // Topology compatibility check. 00668 if (x.topology() != y.topology()) 00669 throw_topology_incompatible("BHRZ03_widening_assign(y)", "y", y); 00670 // Dimension-compatibility check. 00671 if (x.space_dim != y.space_dim) 00672 throw_dimension_incompatible("BHRZ03_widening_assign(y)", "y", y); 00673 00674 #ifndef NDEBUG 00675 { 00676 // We assume that y is contained in or equal to x. 00677 const Polyhedron x_copy = x; 00678 const Polyhedron y_copy = y; 00679 assert(x_copy.contains(y_copy)); 00680 } 00681 #endif 00682 00683 // If any argument is zero-dimensional or empty, 00684 // the BHRZ03-widening behaves as the identity function. 00685 if (x.space_dim == 0 || x.marked_empty() || y.marked_empty()) 00686 return; 00687 00688 // `y.con_sys' and `y.gen_sys' should be in minimal form. 00689 if (!y.minimize()) 00690 // `y' is empty: the result is `x'. 00691 return; 00692 // `x.con_sys' and `x.gen_sys' should be in minimal form. 00693 x.minimize(); 00694 00695 // Compute certificate info for polyhedron `y'. 00696 BHRZ03_Certificate y_cert(y); 00697 00698 // If the iteration is stabilizing, the resulting polyhedron is `x'. 00699 // At this point, also check if the two polyhedra are the same 00700 // (exploiting the knowledge that `y <= x'). 00701 if (y_cert.is_stabilizing(x) || y.contains(x)) { 00702 assert(OK()); 00703 return; 00704 } 00705 00706 // Here the iteration is not immediately stabilizing. 00707 // If we are using the widening-with-tokens technique and 00708 // there are tokens available, use one of them and return `x'. 00709 if (tp != 0 && *tp > 0) { 00710 --(*tp); 00711 assert(OK()); 00712 return; 00713 } 00714 00715 // Copy into `H79_cs' the constraints that are common to `x' and `y', 00716 // according to the definition of the H79 widening. 00717 // The other ones are copied into `x_minus_H79_cs'. 00718 const Topology topol = x.topology(); 00719 Constraint_System H79_cs(topol); 00720 Constraint_System x_minus_H79_cs(topol); 00721 x.select_H79_constraints(y, H79_cs, x_minus_H79_cs); 00722 00723 // We cannot have selected all of the rows, since otherwise 00724 // the iteration should have been immediately stabilizing. 00725 assert(!x_minus_H79_cs.has_no_rows()); 00726 // Be careful to obtain the right space dimension 00727 // (because `H79_cs' may be empty). 00728 Polyhedron H79(topol, x.space_dim, UNIVERSE); 00729 H79.add_recycled_constraints(H79_cs); 00730 // Force minimization. 00731 H79.minimize(); 00732 00733 // NOTE: none of the following widening heuristics is intrusive: 00734 // they will modify `x' only when returning successfully. 00735 if (x.BHRZ03_combining_constraints(y, y_cert, H79, x_minus_H79_cs)) 00736 return; 00737 00738 assert(H79.OK() && x.OK() && y.OK()); 00739 00740 if (x.BHRZ03_evolving_points(y, y_cert, H79)) 00741 return; 00742 00743 assert(H79.OK() && x.OK() && y.OK()); 00744 00745 if (x.BHRZ03_evolving_rays(y, y_cert, H79)) 00746 return; 00747 00748 assert(H79.OK() && x.OK() && y.OK()); 00749 00750 // No previous technique was successful: fall back to the H79 widening. 00751 std::swap(x, H79); 00752 assert(x.OK(true)); 00753 00754 #ifndef NDEBUG 00755 // The H79 widening is always stabilizing. 00756 assert(y_cert.is_stabilizing(x)); 00757 #endif 00758 }
void Parma_Polyhedra_Library::Polyhedron::limited_BHRZ03_extrapolation_assign | ( | const Polyhedron & | y, | |
const Constraint_System & | cs, | |||
unsigned * | tp = 0 | |||
) |
Improves the result of the BHRZ03-widening computation by also enforcing those constraints in cs
that are satisfied by all the points of *this
.
y | A polyhedron that must be contained in *this ; | |
cs | The system of constraints used to improve the widened polyhedron; | |
tp | An optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique). |
std::invalid_argument | Thrown if *this , y and cs are topology-incompatible or dimension-incompatible. |
Definition at line 762 of file Polyhedron_widenings.cc.
References add_recycled_constraints(), BHRZ03_widening_assign(), contains(), 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::Matrix::num_rows(), OK(), process_pending_constraints(), Parma_Polyhedra_Library::Generator_System::satisfied_by_all_generators(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), throw_dimension_incompatible(), throw_topology_incompatible(), and update_generators().
Referenced by bounded_BHRZ03_extrapolation_assign().
00764 { 00765 Polyhedron& x = *this; 00766 const dimension_type cs_num_rows = cs.num_rows(); 00767 // If `cs' is empty, we fall back to ordinary, non-limited widening. 00768 if (cs_num_rows == 0) { 00769 x.BHRZ03_widening_assign(y, tp); 00770 return; 00771 } 00772 00773 // Topology compatibility check. 00774 if (x.is_necessarily_closed()) { 00775 if (!y.is_necessarily_closed()) 00776 throw_topology_incompatible("limited_BHRZ03_extrapolation_assign(y, cs)", 00777 "y", y); 00778 if (cs.has_strict_inequalities()) 00779 throw_topology_incompatible("limited_BHRZ03_extrapolation_assign(y, cs)", 00780 "cs", cs); 00781 } 00782 else if (y.is_necessarily_closed()) 00783 throw_topology_incompatible("limited_BHRZ03_extrapolation_assign(y, cs)", 00784 "y", y); 00785 00786 // Dimension-compatibility check. 00787 if (x.space_dim != y.space_dim) 00788 throw_dimension_incompatible("limited_BHRZ03_extrapolation_assign(y, cs)", 00789 "y", y); 00790 // `cs' must be dimension-compatible with the two polyhedra. 00791 const dimension_type cs_space_dim = cs.space_dimension(); 00792 if (x.space_dim < cs_space_dim) 00793 throw_dimension_incompatible("limited_BHRZ03_extrapolation_assign(y, cs)", 00794 "cs", cs); 00795 00796 #ifndef NDEBUG 00797 { 00798 // We assume that y is contained in or equal to x. 00799 const Polyhedron x_copy = x; 00800 const Polyhedron y_copy = y; 00801 assert(x_copy.contains(y_copy)); 00802 } 00803 #endif 00804 00805 if (y.marked_empty()) 00806 return; 00807 if (x.marked_empty()) 00808 return; 00809 00810 // The limited BHRZ03-widening between two polyhedra in a 00811 // zero-dimensional space is a polyhedron in a zero-dimensional 00812 // space, too. 00813 if (x.space_dim == 0) 00814 return; 00815 00816 if (!y.minimize()) 00817 // We have just discovered that `y' is empty. 00818 return; 00819 00820 // Update the generators of `x': these are used to select, 00821 // from the constraints in `cs', those that must be added 00822 // to the resulting polyhedron. 00823 if ((x.has_pending_constraints() && !x.process_pending_constraints()) 00824 || (!x.generators_are_up_to_date() && !x.update_generators())) 00825 // We have just discovered that `x' is empty. 00826 return; 00827 00828 Constraint_System new_cs; 00829 // The constraints to be added must be satisfied by all the 00830 // generators of `x'. We can disregard `y' because `y <= x'. 00831 const Generator_System& x_gen_sys = x.gen_sys; 00832 // Iterate upwards here so as to keep the relative ordering of constraints. 00833 // Not really an issue: just aesthetics. 00834 for (dimension_type i = 0; i < cs_num_rows; ++i) { 00835 const Constraint& c = cs[i]; 00836 if (x_gen_sys.satisfied_by_all_generators(c)) 00837 new_cs.insert(c); 00838 } 00839 x.BHRZ03_widening_assign(y, tp); 00840 x.add_recycled_constraints(new_cs); 00841 assert(OK()); 00842 }
void Parma_Polyhedra_Library::Polyhedron::bounded_BHRZ03_extrapolation_assign | ( | const Polyhedron & | y, | |
const Constraint_System & | cs, | |||
unsigned * | tp = 0 | |||
) |
Improves the result of the BHRZ03-widening computation by also enforcing those constraints in cs
that are satisfied by all the points of *this
, plus all the constraints of the form and
, with
, that are satisfied by all the points of
*this
.
y | A polyhedron that must be contained in *this ; | |
cs | The system of constraints used to improve the widened polyhedron; | |
tp | An optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique). |
std::invalid_argument | Thrown if *this , y and cs are topology-incompatible or dimension-incompatible. |
Definition at line 846 of file Polyhedron_widenings.cc.
References add_recycled_constraints(), Parma_Polyhedra_Library::ANY_COMPLEXITY, and limited_BHRZ03_extrapolation_assign().
00848 { 00849 Rational_Box x_box(*this, ANY_COMPLEXITY); 00850 Rational_Box y_box(y, ANY_COMPLEXITY); 00851 x_box.CC76_widening_assign(y_box); 00852 limited_BHRZ03_extrapolation_assign(y, cs, tp); 00853 Constraint_System x_box_cs = x_box.constraints(); 00854 add_recycled_constraints(x_box_cs); 00855 }
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
.
y | A polyhedron that must be contained in *this ; | |
tp | An optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique). |
std::invalid_argument | Thrown if *this and y are topology-incompatible or dimension-incompatible. |
Definition at line 156 of file Polyhedron_widenings.cc.
References add_recycled_constraints(), con_sys, constraints_are_up_to_date(), contains(), Parma_Polyhedra_Library::Matrix::has_no_rows(), has_pending_generators(), intersection_assign(), is_empty(), is_necessarily_closed(), marked_empty(), minimize(), Parma_Polyhedra_Library::Constraint_System::num_equalities(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), process_pending_generators(), select_CH78_constraints(), select_H79_constraints(), space_dim, Parma_Polyhedra_Library::swap(), 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().
00156 { 00157 Polyhedron& x = *this; 00158 // Topology compatibility check. 00159 const Topology topol = x.topology(); 00160 if (topol != y.topology()) 00161 throw_topology_incompatible("H79_widening_assign(y)", "y", y); 00162 // Dimension-compatibility check. 00163 if (x.space_dim != y.space_dim) 00164 throw_dimension_incompatible("H79_widening_assign(y)", "y", y); 00165 00166 #ifndef NDEBUG 00167 { 00168 // We assume that y is contained in or equal to x. 00169 const Polyhedron x_copy = x; 00170 const Polyhedron y_copy = y; 00171 assert(x_copy.contains(y_copy)); 00172 } 00173 #endif 00174 00175 // If any argument is zero-dimensional or empty, 00176 // the H79-widening behaves as the identity function. 00177 if (x.space_dim == 0 || x.marked_empty() || y.marked_empty()) 00178 return; 00179 00180 // `y.gen_sys' should be in minimal form and 00181 // `y.sat_g' should be up-to-date. 00182 if (y.is_necessarily_closed()) { 00183 if (!y.minimize()) 00184 // `y' is empty: the result is `x'. 00185 return; 00186 } 00187 else { 00188 // Dealing with a NNC polyhedron. 00189 // To obtain a correct reasoning when comparing 00190 // the constraints of `x' with the generators of `y', 00191 // we enforce the inclusion relation holding between 00192 // the two NNC polyhedra `x' and `y' (i.e., `y <= x') 00193 // to also hold for the corresponding eps-representations: 00194 // this is obtained by intersecting the two eps-representations. 00195 Polyhedron& yy = const_cast<Polyhedron&>(y); 00196 yy.intersection_assign(x); 00197 if (yy.is_empty()) 00198 // The result is `x'. 00199 return; 00200 } 00201 00202 // If we only have the generators of `x' and the dimensions of 00203 // the two polyhedra are the same, we can compute the standard 00204 // widening by using the specification in [CousotH78], therefore 00205 // avoiding converting from generators to constraints. 00206 if (x.has_pending_generators() || !x.constraints_are_up_to_date()) { 00207 Constraint_System CH78_cs(topol); 00208 x.select_CH78_constraints(y, CH78_cs); 00209 00210 if (CH78_cs.num_rows() == y.con_sys.num_rows()) { 00211 // Having selected all the constraints, the result is `y'. 00212 x = y; 00213 return; 00214 } 00215 // Otherwise, check if `x' and `y' have the same dimension. 00216 // Note that `y.con_sys' is minimized and `CH78_cs' has no redundant 00217 // constraints, since it is a subset of the former. 00218 else if (CH78_cs.num_equalities() == y.con_sys.num_equalities()) { 00219 // Let `x' be defined by the constraints in `CH78_cs'. 00220 Polyhedron CH78(topol, x.space_dim, UNIVERSE); 00221 CH78.add_recycled_constraints(CH78_cs); 00222 00223 // Check whether we are using the widening-with-tokens technique 00224 // and there still are tokens available. 00225 if (tp != 0 && *tp > 0) { 00226 // There are tokens available. If `CH78' is not a subset of `x', 00227 // then it is less precise and we use one of the available tokens. 00228 if (!x.contains(CH78)) 00229 --(*tp); 00230 } 00231 else 00232 // No tokens. 00233 std::swap(x, CH78); 00234 assert(x.OK(true)); 00235 return; 00236 } 00237 } 00238 00239 // As the dimension of `x' is strictly greater than the dimension of `y', 00240 // we have to compute the standard widening by selecting a subset of 00241 // the constraints of `x'. 00242 // `x.con_sys' is just required to be up-to-date, because: 00243 // - if `x.con_sys' is unsatisfiable, then by assumption 00244 // also `y' is empty, so that the resulting polyhedron is `x'; 00245 // - redundant constraints in `x.con_sys' do not affect the result 00246 // of the widening, because if they are selected they will be 00247 // redundant even in the result. 00248 if (has_pending_generators()) 00249 process_pending_generators(); 00250 else if (!x.constraints_are_up_to_date()) 00251 x.update_constraints(); 00252 00253 // Copy into `H79_cs' the constraints of `x' that are common to `y', 00254 // according to the definition of the H79 widening. 00255 Constraint_System H79_cs(topol); 00256 Constraint_System x_minus_H79_cs(topol); 00257 x.select_H79_constraints(y, H79_cs, x_minus_H79_cs); 00258 00259 if (x_minus_H79_cs.has_no_rows()) 00260 // We selected all of the constraints of `x', 00261 // thus the result of the widening is `x'. 00262 return; 00263 else { 00264 // We selected a strict subset of the constraints of `x'. 00265 // NOTE: as `x.con_sys' was not necessarily in minimal form, 00266 // this does not imply that the result strictly includes `x'. 00267 // Let `H79' be defined by the constraints in `H79_cs'. 00268 Polyhedron H79(topol, x.space_dim, UNIVERSE); 00269 H79.add_recycled_constraints(H79_cs); 00270 00271 // Check whether we are using the widening-with-tokens technique 00272 // and there still are tokens available. 00273 if (tp != 0 && *tp > 0) { 00274 // There are tokens available. If `H79' is not a subset of `x', 00275 // then it is less precise and we use one of the available tokens. 00276 if (!x.contains(H79)) 00277 --(*tp); 00278 } 00279 else 00280 // No tokens. 00281 std::swap(x, H79); 00282 assert(x.OK(true)); 00283 } 00284 }
void Parma_Polyhedra_Library::Polyhedron::widening_assign | ( | const Polyhedron & | y, | |
unsigned * | tp = 0 | |||
) | [inline] |
Same as H79_widening_assign(y, tp).
Definition at line 90 of file Polyhedron.inlines.hh.
References H79_widening_assign().
00090 { 00091 H79_widening_assign(y, tp); 00092 }
void Parma_Polyhedra_Library::Polyhedron::limited_H79_extrapolation_assign | ( | const Polyhedron & | y, | |
const Constraint_System & | cs, | |||
unsigned * | tp = 0 | |||
) |
Improves the result of the H79-widening computation by also enforcing those constraints in cs
that are satisfied by all the points of *this
.
y | A polyhedron that must be contained in *this ; | |
cs | The system of constraints used to improve the widened polyhedron; | |
tp | An optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique). |
std::invalid_argument | Thrown if *this , y and cs are topology-incompatible or dimension-incompatible. |
Definition at line 287 of file Polyhedron_widenings.cc.
References add_recycled_constraints(), contains(), 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::Matrix::num_rows(), OK(), process_pending_constraints(), Parma_Polyhedra_Library::Generator_System::satisfied_by_all_generators(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), throw_dimension_incompatible(), throw_topology_incompatible(), and update_generators().
Referenced by bounded_H79_extrapolation_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::limited_H79_extrapolation_assign().
00289 { 00290 Polyhedron& x = *this; 00291 00292 const dimension_type cs_num_rows = cs.num_rows(); 00293 // If `cs' is empty, we fall back to ordinary, non-limited widening. 00294 if (cs_num_rows == 0) { 00295 x.H79_widening_assign(y, tp); 00296 return; 00297 } 00298 00299 // Topology compatibility check. 00300 if (x.is_necessarily_closed()) { 00301 if (!y.is_necessarily_closed()) 00302 throw_topology_incompatible("limited_H79_extrapolation_assign(y, cs)", 00303 "y", y); 00304 if (cs.has_strict_inequalities()) 00305 throw_topology_incompatible("limited_H79_extrapolation_assign(y, cs)", 00306 "cs", cs); 00307 } 00308 else if (y.is_necessarily_closed()) 00309 throw_topology_incompatible("limited_H79_extrapolation_assign(y, cs)", 00310 "y", y); 00311 00312 // Dimension-compatibility check. 00313 if (x.space_dim != y.space_dim) 00314 throw_dimension_incompatible("limited_H79_extrapolation_assign(y, cs)", 00315 "y", y); 00316 // `cs' must be dimension-compatible with the two polyhedra. 00317 const dimension_type cs_space_dim = cs.space_dimension(); 00318 if (x.space_dim < cs_space_dim) 00319 throw_dimension_incompatible("limited_H79_extrapolation_assign(y, cs)", 00320 "cs", cs); 00321 00322 #ifndef NDEBUG 00323 { 00324 // We assume that y is contained in or equal to x. 00325 const Polyhedron x_copy = x; 00326 const Polyhedron y_copy = y; 00327 assert(x_copy.contains(y_copy)); 00328 } 00329 #endif 00330 00331 if (y.marked_empty()) 00332 return; 00333 if (x.marked_empty()) 00334 return; 00335 00336 // The limited H79-widening between two polyhedra in a 00337 // zero-dimensional space is a polyhedron in a zero-dimensional 00338 // space, too. 00339 if (x.space_dim == 0) 00340 return; 00341 00342 if (!y.minimize()) 00343 // We have just discovered that `y' is empty. 00344 return; 00345 00346 // Update the generators of `x': these are used to select, 00347 // from the constraints in `cs', those that must be added 00348 // to the resulting polyhedron. 00349 if ((x.has_pending_constraints() && !x.process_pending_constraints()) 00350 || (!x.generators_are_up_to_date() && !x.update_generators())) 00351 // We have just discovered that `x' is empty. 00352 return; 00353 00354 Constraint_System new_cs; 00355 // The constraints to be added must be satisfied by all the 00356 // generators of `x'. We can disregard `y' because `y <= x'. 00357 const Generator_System& x_gen_sys = x.gen_sys; 00358 // Iterate upwards here so as to keep the relative ordering of constraints. 00359 // Not really an issue: just aesthetics. 00360 for (dimension_type i = 0; i < cs_num_rows; ++i) { 00361 const Constraint& c = cs[i]; 00362 if (x_gen_sys.satisfied_by_all_generators(c)) 00363 new_cs.insert(c); 00364 } 00365 x.H79_widening_assign(y, tp); 00366 x.add_recycled_constraints(new_cs); 00367 assert(OK()); 00368 }
void Parma_Polyhedra_Library::Polyhedron::bounded_H79_extrapolation_assign | ( | const Polyhedron & | y, | |
const Constraint_System & | cs, | |||
unsigned * | tp = 0 | |||
) |
Improves the result of the H79-widening computation by also enforcing those constraints in cs
that are satisfied by all the points of *this
, plus all the constraints of the form and
, with
, that are satisfied by all the points of
*this
.
y | A polyhedron that must be contained in *this ; | |
cs | The system of constraints used to improve the widened polyhedron; | |
tp | An optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique). |
std::invalid_argument | Thrown if *this , y and cs are topology-incompatible or dimension-incompatible. |
Definition at line 371 of file Polyhedron_widenings.cc.
References add_recycled_constraints(), Parma_Polyhedra_Library::ANY_COMPLEXITY, and limited_H79_extrapolation_assign().
00373 { 00374 Rational_Box x_box(*this, ANY_COMPLEXITY); 00375 Rational_Box y_box(y, ANY_COMPLEXITY); 00376 x_box.CC76_widening_assign(y_box); 00377 limited_H79_extrapolation_assign(y, cs, tp); 00378 Constraint_System x_box_cs = x_box.constraints(); 00379 add_recycled_constraints(x_box_cs); 00380 }
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.
m | The number of dimensions to add. |
std::length_error | Thrown if adding m new space dimensions would cause the vector space to exceed dimension max_space_dimension() . |
Definition at line 91 of file Polyhedron_chdims.cc.
References Parma_Polyhedra_Library::Linear_System::add_rows_and_columns(), add_space_dimensions(), Parma_Polyhedra_Library::Matrix::add_zero_columns(), Parma_Polyhedra_Library::Constraint_System::clear(), con_sys, constraints_are_up_to_date(), gen_sys, generators_are_up_to_date(), is_necessarily_closed(), Parma_Polyhedra_Library::Linear_System::is_sorted(), marked_empty(), max_space_dimension(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), sat_c, sat_c_is_up_to_date(), sat_g, space_dim, space_dimension(), status, Parma_Polyhedra_Library::swap(), swap(), Parma_Polyhedra_Library::Matrix::swap_columns(), Parma_Polyhedra_Library::Polyhedron::Status::test_zero_dim_univ(), throw_space_dimension_overflow(), topology(), Parma_Polyhedra_Library::UNIVERSE, Parma_Polyhedra_Library::Linear_System::unset_pending_rows(), and update_sat_c().
Referenced by bounded_affine_image(), bounded_affine_preimage(), expand_space_dimension(), generalized_affine_image(), and generalized_affine_preimage().
00091 { 00092 // The space dimension of the resulting polyhedron should not 00093 // overflow the maximum allowed space dimension. 00094 if (m > max_space_dimension() - space_dimension()) 00095 throw_space_dimension_overflow(topology(), 00096 "add_space_dimensions_and_embed(m)", 00097 "adding m new space dimensions exceeds " 00098 "the maximum allowed space dimension"); 00099 00100 // Adding no dimensions to any polyhedron is a no-op. 00101 if (m == 0) 00102 return; 00103 00104 // Adding dimensions to an empty polyhedron is obtained by adjusting 00105 // `space_dim' and clearing `con_sys' (since it can contain the 00106 // unsatisfiable constraint system of the wrong dimension). 00107 if (marked_empty()) { 00108 space_dim += m; 00109 con_sys.clear(); 00110 return; 00111 } 00112 00113 // The case of a zero-dimensional space polyhedron. 00114 if (space_dim == 0) { 00115 // Since it is not empty, it has to be the universe polyhedron. 00116 assert(status.test_zero_dim_univ()); 00117 // We swap `*this' with a newly created 00118 // universe polyhedron of dimension `m'. 00119 Polyhedron ph(topology(), m, UNIVERSE); 00120 swap(ph); 00121 return; 00122 } 00123 00124 // To embed an n-dimension space polyhedron in a (n+m)-dimension space, 00125 // we just add `m' zero-columns to the rows in the system of constraints; 00126 // in contrast, the system of generators needs additional rows, 00127 // corresponding to the vectors of the canonical basis 00128 // for the added dimensions. That is, for each new dimension `x[k]' 00129 // we add the line having that direction. This is done by invoking 00130 // the function add_space_dimensions() giving the system of generators 00131 // as the second argument. 00132 if (constraints_are_up_to_date()) 00133 if (generators_are_up_to_date()) { 00134 // `sat_c' must be up to date for add_space_dimensions(). 00135 if (!sat_c_is_up_to_date()) 00136 update_sat_c(); 00137 // Adds rows and/or columns to both matrices. 00138 // `add_space_dimensions' correctly handles pending constraints 00139 // or generators. 00140 add_space_dimensions(con_sys, gen_sys, sat_c, sat_g, m); 00141 } 00142 else { 00143 // Only constraints are up-to-date: no need to modify the generators. 00144 con_sys.add_zero_columns(m); 00145 // If the polyhedron is not necessarily closed, 00146 // move the epsilon coefficients to the last column. 00147 if (!is_necessarily_closed()) 00148 con_sys.swap_columns(space_dim + 1, space_dim + 1 + m); 00149 } 00150 else { 00151 // Only generators are up-to-date: no need to modify the constraints. 00152 assert(generators_are_up_to_date()); 00153 gen_sys.add_rows_and_columns(m); 00154 // The polyhedron does not support pending generators. 00155 gen_sys.unset_pending_rows(); 00156 // If the polyhedron is not necessarily closed, 00157 // move the epsilon coefficients to the last column. 00158 if (!is_necessarily_closed()) { 00159 // Try to preserve sortedness of `gen_sys'. 00160 if (!gen_sys.is_sorted()) 00161 gen_sys.swap_columns(space_dim + 1, space_dim + 1 + m); 00162 else { 00163 dimension_type old_eps_index = space_dim + 1; 00164 dimension_type new_eps_index = old_eps_index + m; 00165 for (dimension_type i = gen_sys.num_rows(); i-- > m; ) { 00166 Generator& r = gen_sys[i]; 00167 std::swap(r[old_eps_index], r[new_eps_index]); 00168 } 00169 // The upper-right corner of `gen_sys' contains the J matrix: 00170 // swap coefficients to preserve sortedness. 00171 for (dimension_type i = m; i-- > 0; ++old_eps_index) { 00172 Generator& r = gen_sys[i]; 00173 std::swap(r[old_eps_index], r[old_eps_index + 1]); 00174 } 00175 } 00176 } 00177 } 00178 // Update the space dimension. 00179 space_dim += m; 00180 00181 // Note: we do not check for satisfiability, because the system of 00182 // constraints may be unsatisfiable. 00183 assert(OK()); 00184 }
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.
m | The number of space dimensions to add. |
std::length_error | Thrown if adding m new space dimensions would cause the vector space to exceed dimension max_space_dimension() . |
Definition at line 187 of file Polyhedron_chdims.cc.
References Parma_Polyhedra_Library::Linear_System::add_rows_and_columns(), add_space_dimensions(), Parma_Polyhedra_Library::Matrix::add_zero_columns(), Parma_Polyhedra_Library::Generator_System::adjust_topology_and_space_dimension(), Parma_Polyhedra_Library::Constraint_System::clear(), con_sys, constraints_are_up_to_date(), gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Matrix::has_no_rows(), Parma_Polyhedra_Library::Generator_System::insert(), is_necessarily_closed(), Parma_Polyhedra_Library::Linear_System::is_sorted(), marked_empty(), max_space_dimension(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), sat_c, sat_g, sat_g_is_up_to_date(), set_generators_minimized(), space_dim, space_dimension(), status, Parma_Polyhedra_Library::swap(), Parma_Polyhedra_Library::Matrix::swap_columns(), Parma_Polyhedra_Library::Polyhedron::Status::test_zero_dim_univ(), throw_space_dimension_overflow(), topology(), Parma_Polyhedra_Library::Linear_System::unset_pending_rows(), update_sat_g(), Parma_Polyhedra_Library::Generator::zero_dim_closure_point(), and Parma_Polyhedra_Library::Generator::zero_dim_point().
00187 { 00188 // The space dimension of the resulting polyhedron should not 00189 // overflow the maximum allowed space dimension. 00190 if (m > max_space_dimension() - space_dimension()) 00191 throw_space_dimension_overflow(topology(), 00192 "add_space_dimensions_and_project(m)", 00193 "adding m new space dimensions exceeds " 00194 "the maximum allowed space dimension"); 00195 00196 // Adding no dimensions to any polyhedron is a no-op. 00197 if (m == 0) 00198 return; 00199 00200 // Adding dimensions to an empty polyhedron is obtained 00201 // by merely adjusting `space_dim'. 00202 if (marked_empty()) { 00203 space_dim += m; 00204 con_sys.clear(); 00205 return; 00206 } 00207 00208 if (space_dim == 0) { 00209 assert(status.test_zero_dim_univ() && gen_sys.has_no_rows()); 00210 // The system of generators for this polyhedron has only 00211 // the origin as a point. 00212 // In an NNC polyhedron, all points have to be accompanied 00213 // by the corresponding closure points 00214 // (this time, dimensions are automatically adjusted). 00215 if (!is_necessarily_closed()) 00216 gen_sys.insert(Generator::zero_dim_closure_point()); 00217 gen_sys.insert(Generator::zero_dim_point()); 00218 gen_sys.adjust_topology_and_space_dimension(topology(), m); 00219 set_generators_minimized(); 00220 space_dim = m; 00221 assert(OK()); 00222 return; 00223 } 00224 00225 // To project an n-dimension space polyhedron in a (n+m)-dimension space, 00226 // we just add to the system of generators `m' zero-columns; 00227 // In contrast, in the system of constraints, new rows are needed 00228 // in order to avoid embedding the old polyhedron in the new space. 00229 // Thus, for each new dimensions `x[k]', we add the constraint 00230 // x[k] = 0; this is done by invoking the function add_space_dimensions() 00231 // giving the system of constraints as the second argument. 00232 if (constraints_are_up_to_date()) 00233 if (generators_are_up_to_date()) { 00234 // `sat_g' must be up to date for add_space_dimensions(). 00235 if (!sat_g_is_up_to_date()) 00236 update_sat_g(); 00237 // Adds rows and/or columns to both matrices. 00238 // `add_space_dimensions' correctly handles pending constraints 00239 // or generators. 00240 add_space_dimensions(gen_sys, con_sys, sat_g, sat_c, m); 00241 } 00242 else { 00243 // Only constraints are up-to-date: no need to modify the generators. 00244 con_sys.add_rows_and_columns(m); 00245 // The polyhedron does not support pending constraints. 00246 con_sys.unset_pending_rows(); 00247 // If the polyhedron is not necessarily closed, 00248 // move the epsilon coefficients to the last column. 00249 if (!is_necessarily_closed()) { 00250 // Try to preserve sortedness of `con_sys'. 00251 if (!con_sys.is_sorted()) 00252 con_sys.swap_columns(space_dim + 1, space_dim + 1 + m); 00253 else { 00254 dimension_type old_eps_index = space_dim + 1; 00255 dimension_type new_eps_index = old_eps_index + m; 00256 for (dimension_type i = con_sys.num_rows(); i-- > m; ) { 00257 Constraint& r = con_sys[i]; 00258 std::swap(r[old_eps_index], r[new_eps_index]); 00259 } 00260 // The upper-right corner of `con_sys' contains the J matrix: 00261 // swap coefficients to preserve sortedness. 00262 for (dimension_type i = m; i-- > 0; ++old_eps_index) { 00263 Constraint& r = con_sys[i]; 00264 std::swap(r[old_eps_index], r[old_eps_index + 1]); 00265 } 00266 } 00267 } 00268 } 00269 else { 00270 // Only generators are up-to-date: no need to modify the constraints. 00271 assert(generators_are_up_to_date()); 00272 gen_sys.add_zero_columns(m); 00273 // If the polyhedron is not necessarily closed, 00274 // move the epsilon coefficients to the last column. 00275 if (!is_necessarily_closed()) 00276 gen_sys.swap_columns(space_dim + 1, space_dim + 1 + m); 00277 } 00278 // Now we update the space dimension. 00279 space_dim += m; 00280 00281 // Note: we do not check for satisfiability, because the system of 00282 // constraints may be unsatisfiable. 00283 assert(OK()); 00284 }
void Parma_Polyhedra_Library::Polyhedron::concatenate_assign | ( | const Polyhedron & | y | ) |
Assigns to *this
the concatenation of *this
and y
, taken in this order.
std::invalid_argument | Thrown if *this and y are topology-incompatible. | |
std::length_error | Thrown if the concatenation would cause the vector space to exceed dimension max_space_dimension() . |
Definition at line 287 of file Polyhedron_chdims.cc.
References Parma_Polyhedra_Library::Linear_System::add_rows_and_columns(), Parma_Polyhedra_Library::Matrix::add_zero_rows_and_columns(), can_have_something_pending(), clear_constraints_minimized(), clear_generators_up_to_date(), clear_sat_c_up_to_date(), clear_sat_g_up_to_date(), con_sys, constraints(), constraints_are_up_to_date(), gen_sys, has_pending_generators(), Parma_Polyhedra_Library::Constraint::is_equality(), is_necessarily_closed(), marked_empty(), max_space_dimension(), Parma_Polyhedra_Library::Bit_Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Bit_Matrix::num_rows(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), process_pending_generators(), Parma_Polyhedra_Library::Linear_Row::RAY_OR_POINT_OR_INEQUALITY, Parma_Polyhedra_Library::Bit_Matrix::resize(), sat_c, sat_c_is_up_to_date(), sat_g, set_constraints_pending(), set_empty(), Parma_Polyhedra_Library::Constraint::set_is_equality(), set_sat_c_up_to_date(), Parma_Polyhedra_Library::Linear_System::set_sorted(), Parma_Polyhedra_Library::Linear_System::sort_rows(), space_dim, Parma_Polyhedra_Library::swap(), Parma_Polyhedra_Library::Matrix::swap_columns(), throw_space_dimension_overflow(), throw_topology_incompatible(), topology(), Parma_Polyhedra_Library::Bit_Matrix::transpose_assign(), Parma_Polyhedra_Library::Linear_System::unset_pending_rows(), and update_constraints().
00287 { 00288 if (topology() != y.topology()) 00289 throw_topology_incompatible("concatenate_assign(y)", "y", y); 00290 00291 // The space dimension of the resulting polyhedron should not 00292 // overflow the maximum allowed space dimension. 00293 const dimension_type added_columns = y.space_dim; 00294 if (added_columns > max_space_dimension() - space_dim) 00295 throw_space_dimension_overflow(topology(), 00296 "concatenate_assign(y)", 00297 "concatenation exceeds the maximum " 00298 "allowed space dimension"); 00299 00300 // If `*this' or `y' are empty polyhedra, it is sufficient to adjust 00301 // the dimension of the space. 00302 if (marked_empty() || y.marked_empty()) { 00303 space_dim += added_columns; 00304 set_empty(); 00305 return; 00306 } 00307 00308 // If `y' is a non-empty 0-dim space polyhedron, the result is `*this'. 00309 if (added_columns == 0) 00310 return; 00311 00312 // If `*this' is a non-empty 0-dim space polyhedron, the result is `y'. 00313 if (space_dim == 0) { 00314 *this = y; 00315 return; 00316 } 00317 00318 // TODO: this implementation is just an executable specification. 00319 Constraint_System cs = y.constraints(); 00320 00321 // The constraints of `x' (possibly with pending rows) are required. 00322 if (has_pending_generators()) 00323 process_pending_generators(); 00324 else if (!constraints_are_up_to_date()) 00325 update_constraints(); 00326 00327 // The matrix for the new system of constraints is obtained 00328 // by leaving the old system of constraints in the upper left-hand side 00329 // and placing the constraints of `cs' in the lower right-hand side. 00330 // NOTE: here topologies agree, whereas dimensions may not agree. 00331 dimension_type old_num_rows = con_sys.num_rows(); 00332 dimension_type old_num_columns = con_sys.num_columns(); 00333 dimension_type added_rows = cs.num_rows(); 00334 00335 // We already dealt with the cases of an empty or zero-dim `y' polyhedron; 00336 // also, `cs' contains the low-level constraints, at least. 00337 assert(added_rows > 0 && added_columns > 0); 00338 00339 con_sys.add_zero_rows_and_columns(added_rows, added_columns, 00340 Linear_Row::Flags(topology(), 00341 Linear_Row::RAY_OR_POINT_OR_INEQUALITY)); 00342 // Move the epsilon coefficient to the last column, if needed. 00343 if (!is_necessarily_closed()) 00344 con_sys.swap_columns(old_num_columns - 1, 00345 old_num_columns - 1 + added_columns); 00346 dimension_type cs_num_columns = cs.num_columns(); 00347 // Steal the constraints from `cs' and put them in `con_sys' 00348 // using the right displacement for coefficients. 00349 for (dimension_type i = added_rows; i-- > 0; ) { 00350 Constraint& c_old = cs[i]; 00351 Constraint& c_new = con_sys[old_num_rows + i]; 00352 // Method `add_zero_rows_and_columns', by default, added inequalities. 00353 if (c_old.is_equality()) 00354 c_new.set_is_equality(); 00355 // The inhomogeneous term is not displaced. 00356 std::swap(c_new[0], c_old[0]); 00357 // All homogeneous terms (included the epsilon coefficient, 00358 // if present) are displaced by `space_dim' columns. 00359 for (dimension_type j = 1; j < cs_num_columns; ++j) 00360 std::swap(c_old[j], c_new[space_dim + j]); 00361 } 00362 00363 if (can_have_something_pending()) { 00364 // If `*this' can support pending constraints, then, since we have 00365 // resized the system of constraints, we must also add to the generator 00366 // system those lines corresponding to the newly added dimensions, 00367 // because the non-pending parts of `con_sys' and `gen_sys' must still 00368 // be a DD pair in minimal form. 00369 gen_sys.add_rows_and_columns(added_columns); 00370 gen_sys.set_sorted(false); 00371 if (!is_necessarily_closed()) 00372 gen_sys.swap_columns(old_num_columns - 1, 00373 old_num_columns - 1 + added_columns); 00374 // The added lines are not pending. 00375 gen_sys.unset_pending_rows(); 00376 // Since we added new lines at the beginning of `x.gen_sys', 00377 // we also have to adjust the saturation matrix `sat_c'. 00378 // FIXME: if `sat_c' is not up-to-date, couldn't we directly update 00379 // `sat_g' by resizing it and shifting its columns? 00380 if (!sat_c_is_up_to_date()) { 00381 sat_c.transpose_assign(sat_g); 00382 set_sat_c_up_to_date(); 00383 } 00384 clear_sat_g_up_to_date(); 00385 sat_c.resize(sat_c.num_rows() + added_columns, sat_c.num_columns()); 00386 // The old saturation rows are copied at the end of the matrix. 00387 // The newly introduced lines saturate all the non-pending constraints, 00388 // thus their saturation rows are made of zeroes. 00389 for (dimension_type i = sat_c.num_rows() - added_columns; i-- > 0; ) 00390 std::swap(sat_c[i], sat_c[i+added_columns]); 00391 // Since `added_rows > 0', we now have pending constraints. 00392 set_constraints_pending(); 00393 } 00394 else { 00395 // The polyhedron cannot have pending constraints. 00396 con_sys.unset_pending_rows(); 00397 #if BE_LAZY 00398 con_sys.set_sorted(false); 00399 #else 00400 con_sys.sort_rows(); 00401 #endif 00402 clear_constraints_minimized(); 00403 clear_generators_up_to_date(); 00404 clear_sat_g_up_to_date(); 00405 clear_sat_c_up_to_date(); 00406 } 00407 // Update space dimension. 00408 space_dim += added_columns; 00409 00410 // The system of constraints may be unsatisfiable, 00411 // thus we do not check for satisfiability. 00412 assert(OK()); 00413 }
void Parma_Polyhedra_Library::Polyhedron::remove_space_dimensions | ( | const Variables_Set & | to_be_removed | ) |
Removes all the specified dimensions from the vector space.
to_be_removed | The set of Variable objects corresponding to the space dimensions to be removed. |
std::invalid_argument | Thrown if *this is dimension-incompatible with one of the Variable objects contained in to_be_removed . |
Definition at line 416 of file Polyhedron_chdims.cc.
References Parma_Polyhedra_Library::Constraint_System::clear(), clear_constraints_up_to_date(), clear_generators_minimized(), con_sys, gen_sys, generators_are_up_to_date(), has_something_pending(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_columns(), OK(), Parma_Polyhedra_Library::Generator_System::remove_invalid_lines_and_rays(), remove_pending_to_obtain_generators(), Parma_Polyhedra_Library::Linear_System::remove_trailing_columns(), set_zero_dim_univ(), space_dim, throw_dimension_incompatible(), and update_generators().
Referenced by fold_space_dimensions().
00416 { 00417 // The removal of no dimensions from any polyhedron is a no-op. 00418 // Note that this case also captures the only legal removal of 00419 // dimensions from a polyhedron in a 0-dim space. 00420 if (to_be_removed.empty()) { 00421 assert(OK()); 00422 return; 00423 } 00424 00425 // Dimension-compatibility check. 00426 const dimension_type min_space_dim = to_be_removed.space_dimension(); 00427 if (space_dim < min_space_dim) 00428 throw_dimension_incompatible("remove_space_dimensions(vs)", min_space_dim); 00429 00430 const dimension_type new_space_dim = space_dim - to_be_removed.size(); 00431 00432 // We need updated generators; note that keeping pending generators 00433 // is useless because the constraints will be dropped anyway. 00434 if (marked_empty() 00435 || (has_something_pending() && !remove_pending_to_obtain_generators()) 00436 || (!generators_are_up_to_date() && !update_generators())) { 00437 // Removing dimensions from the empty polyhedron: 00438 // we clear `con_sys' since it could have contained the 00439 // unsatisfiable constraint of the wrong dimension. 00440 con_sys.clear(); 00441 // Update the space dimension. 00442 space_dim = new_space_dim; 00443 assert(OK()); 00444 return; 00445 } 00446 00447 // When removing _all_ dimensions from a non-empty polyhedron, 00448 // we obtain the zero-dimensional universe polyhedron. 00449 if (new_space_dim == 0) { 00450 set_zero_dim_univ(); 00451 return; 00452 } 00453 00454 // For each variable to be removed, we fill the corresponding column 00455 // by shifting left those columns that will not be removed. 00456 Variables_Set::const_iterator tbr = to_be_removed.begin(); 00457 Variables_Set::const_iterator tbr_end = to_be_removed.end(); 00458 dimension_type dst_col = *tbr + 1; 00459 dimension_type src_col = dst_col + 1; 00460 for (++tbr; tbr != tbr_end; ++tbr) { 00461 const dimension_type tbr_col = *tbr + 1; 00462 // All columns in between are moved to the left. 00463 while (src_col < tbr_col) 00464 gen_sys.Matrix::swap_columns(dst_col++, src_col++); 00465 ++src_col; 00466 } 00467 // Moving the remaining columns. 00468 const dimension_type gen_sys_num_columns = gen_sys.num_columns(); 00469 while (src_col < gen_sys_num_columns) 00470 gen_sys.Matrix::swap_columns(dst_col++, src_col++); 00471 00472 // The number of remaining columns is `dst_col'. 00473 // Note that resizing also calls `set_sorted(false)'. 00474 gen_sys.remove_trailing_columns(gen_sys_num_columns - dst_col); 00475 // We may have invalid lines and rays now. 00476 gen_sys.remove_invalid_lines_and_rays(); 00477 00478 // Constraints are not up-to-date and generators are not minimized. 00479 clear_constraints_up_to_date(); 00480 clear_generators_minimized(); 00481 00482 // Update the space dimension. 00483 space_dim = new_space_dim; 00484 00485 assert(OK(true)); 00486 }
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
.
std::invalid_argument | Thrown if new_dimensions is greater than the space dimension of *this . |
Definition at line 489 of file Polyhedron_chdims.cc.
References Parma_Polyhedra_Library::Constraint_System::clear(), clear_constraints_up_to_date(), clear_generators_minimized(), con_sys, gen_sys, generators_are_up_to_date(), has_something_pending(), is_necessarily_closed(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_columns(), OK(), Parma_Polyhedra_Library::Generator_System::remove_invalid_lines_and_rays(), remove_pending_to_obtain_generators(), Parma_Polyhedra_Library::Linear_System::remove_trailing_columns(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Matrix::swap_columns(), throw_dimension_incompatible(), and update_generators().
Referenced by bounded_affine_image(), bounded_affine_preimage(), generalized_affine_image(), and generalized_affine_preimage().
00489 { 00490 // Dimension-compatibility check. 00491 if (new_dimension > space_dim) 00492 throw_dimension_incompatible("remove_higher_space_dimensions(nd)", 00493 new_dimension); 00494 00495 // The removal of no dimensions from any polyhedron is a no-op. 00496 // Note that this case also captures the only legal removal of 00497 // dimensions from a polyhedron in a 0-dim space. 00498 if (new_dimension == space_dim) { 00499 assert(OK()); 00500 return; 00501 } 00502 00503 // We need updated generators; note that keeping pending generators 00504 // is useless because constraints will be dropped anyway. 00505 if (marked_empty() 00506 || (has_something_pending() && !remove_pending_to_obtain_generators()) 00507 || (!generators_are_up_to_date() && !update_generators())) { 00508 // Removing dimensions from the empty polyhedron: 00509 // just updates the space dimension. 00510 space_dim = new_dimension; 00511 con_sys.clear(); 00512 assert(OK()); 00513 return; 00514 } 00515 00516 if (new_dimension == 0) { 00517 // Removing all dimensions from a non-empty polyhedron: 00518 // just return the zero-dimensional universe polyhedron. 00519 set_zero_dim_univ(); 00520 return; 00521 } 00522 00523 dimension_type new_num_cols = new_dimension + 1; 00524 if (!is_necessarily_closed()) { 00525 // The polyhedron is not necessarily closed: move the column 00526 // of the epsilon coefficients to its new place. 00527 gen_sys.swap_columns(gen_sys.num_columns() - 1, new_num_cols); 00528 // The number of remaining columns is `new_dimension + 2'. 00529 ++new_num_cols; 00530 } 00531 // Note that resizing also calls `set_sorted(false)'. 00532 gen_sys.remove_trailing_columns(space_dim - new_dimension); 00533 // We may have invalid lines and rays now. 00534 gen_sys.remove_invalid_lines_and_rays(); 00535 00536 // Constraints are not up-to-date and generators are not minimized. 00537 clear_constraints_up_to_date(); 00538 clear_generators_minimized(); 00539 00540 // Update the space dimension. 00541 space_dim = new_dimension; 00542 00543 assert(OK(true)); 00544 }
void Parma_Polyhedra_Library::Polyhedron::map_space_dimensions | ( | const Partial_Function & | pfunc | ) | [inline] |
Remaps the dimensions of the vector space according to a partial function.
pfunc | The partial function specifying the destiny of each space dimension. |
bool has_empty_codomain() const
true
if and only if the represented partial function has an empty codomain (i.e., it is always undefined). The has_empty_codomain()
method will always be called before the methods below. However, if has_empty_codomain()
returns true
, none of the functions below will be called. dimension_type max_in_codomain() const
max_in_codomain()
method is called at most once. bool maps(dimension_type i, dimension_type& j) const
i
. If j
and true
is returned. If false
is returned. This method is called at most
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 149 of file Polyhedron.templates.hh.
References Parma_Polyhedra_Library::Generator_System::begin(), Parma_Polyhedra_Library::Constraint_System::clear(), Parma_Polyhedra_Library::Generator::CLOSURE_POINT, Parma_Polyhedra_Library::Generator::coefficient(), con_sys, constraints_are_up_to_date(), Parma_Polyhedra_Library::Generator::divisor(), Parma_Polyhedra_Library::EMPTY, Parma_Polyhedra_Library::Generator_System::end(), gen_sys, generators(), generators_are_up_to_date(), Parma_Polyhedra_Library::Matrix::has_no_rows(), has_pending_constraints(), Parma_Polyhedra_Library::Generator_System::insert(), Parma_Polyhedra_Library::Generator::LINE, marked_empty(), Parma_Polyhedra_Library::not_a_dimension(), OK(), Parma_Polyhedra_Library::Linear_System::permute_columns(), Parma_Polyhedra_Library::Generator::POINT, Parma_Polyhedra_Library::Generator::RAY, remove_pending_to_obtain_generators(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::swap(), throw_invalid_argument(), topology(), Parma_Polyhedra_Library::Generator::type(), and update_generators().
00149 { 00150 if (space_dim == 0) 00151 return; 00152 00153 if (pfunc.has_empty_codomain()) { 00154 // All dimensions vanish: the polyhedron becomes zero_dimensional. 00155 if (marked_empty() 00156 || (has_pending_constraints() 00157 && !remove_pending_to_obtain_generators()) 00158 || (!generators_are_up_to_date() && !update_generators())) { 00159 // Removing all dimensions from the empty polyhedron. 00160 space_dim = 0; 00161 con_sys.clear(); 00162 } 00163 else 00164 // Removing all dimensions from a non-empty polyhedron. 00165 set_zero_dim_univ(); 00166 00167 assert(OK()); 00168 return; 00169 } 00170 00171 const dimension_type new_space_dimension = pfunc.max_in_codomain() + 1; 00172 00173 if (new_space_dimension == space_dim) { 00174 // The partial function `pfunc' is indeed total and thus specifies 00175 // a permutation, that is, a renaming of the dimensions. For 00176 // maximum efficiency, we will simply permute the columns of the 00177 // constraint system and/or the generator system. 00178 00179 // We first compute suitable permutation cycles for the columns of 00180 // the `con_sys' and `gen_sys' matrices. We will represent them 00181 // with a linear array, using 0 as a terminator for each cycle 00182 // (notice that the columns with index 0 of `con_sys' and 00183 // `gen_sys' represent the inhomogeneous terms, and thus are 00184 // unaffected by the permutation of dimensions). 00185 // Cycles of length 1 will be omitted so that, in the worst case, 00186 // we will have `space_dim' elements organized in `space_dim/2' 00187 // cycles, which means we will have at most `space_dim/2' 00188 // terminators. 00189 std::vector<dimension_type> cycles; 00190 cycles.reserve(space_dim + space_dim/2); 00191 00192 // Used to mark elements as soon as they are inserted in a cycle. 00193 std::deque<bool> visited(space_dim); 00194 00195 for (dimension_type i = space_dim; i-- > 0; ) { 00196 if (!visited[i]) { 00197 dimension_type j = i; 00198 do { 00199 visited[j] = true; 00200 // The following initialization is only to make the compiler happy. 00201 dimension_type k = 0; 00202 if (!pfunc.maps(j, k)) 00203 throw_invalid_argument("map_space_dimensions(pfunc)", 00204 " pfunc is inconsistent"); 00205 if (k == j) 00206 // Cycle of length 1: skip it. 00207 goto skip; 00208 00209 cycles.push_back(j+1); 00210 // Go along the cycle. 00211 j = k; 00212 } while (!visited[j]); 00213 // End of cycle: mark it. 00214 cycles.push_back(0); 00215 skip: 00216 ; 00217 } 00218 } 00219 00220 // If `cycles' is empty then `pfunc' is the identity. 00221 if (cycles.empty()) 00222 return; 00223 00224 // Permute all that is up-to-date. Notice that the contents of 00225 // the saturation matrices is unaffected by the permutation of 00226 // columns: they remain valid, if they were so. 00227 if (constraints_are_up_to_date()) 00228 con_sys.permute_columns(cycles); 00229 00230 if (generators_are_up_to_date()) 00231 gen_sys.permute_columns(cycles); 00232 00233 assert(OK()); 00234 return; 00235 } 00236 00237 // If control gets here, then `pfunc' is not a permutation and some 00238 // dimensions must be projected away. 00239 00240 // If there are pending constraints, using `generators()' we process them. 00241 const Generator_System& old_gensys = generators(); 00242 00243 if (old_gensys.has_no_rows()) { 00244 // The polyhedron is empty. 00245 Polyhedron new_polyhedron(topology(), new_space_dimension, EMPTY); 00246 std::swap(*this, new_polyhedron); 00247 assert(OK()); 00248 return; 00249 } 00250 00251 // Make a local copy of the partial function. 00252 std::vector<dimension_type> pfunc_maps(space_dim, not_a_dimension()); 00253 for (dimension_type j = space_dim; j-- > 0; ) { 00254 dimension_type pfunc_j; 00255 if (pfunc.maps(j, pfunc_j)) 00256 pfunc_maps[j] = pfunc_j; 00257 } 00258 00259 Generator_System new_gensys; 00260 for (Generator_System::const_iterator i = old_gensys.begin(), 00261 old_gensys_end = old_gensys.end(); i != old_gensys_end; ++i) { 00262 const Generator& old_g = *i; 00263 Linear_Expression e(0 * Variable(new_space_dimension-1)); 00264 bool all_zeroes = true; 00265 for (dimension_type j = space_dim; j-- > 0; ) { 00266 if (old_g.coefficient(Variable(j)) != 0 00267 && pfunc_maps[j] != not_a_dimension()) { 00268 e += Variable(pfunc_maps[j]) * old_g.coefficient(Variable(j)); 00269 all_zeroes = false; 00270 } 00271 } 00272 switch (old_g.type()) { 00273 case Generator::LINE: 00274 if (!all_zeroes) 00275 new_gensys.insert(line(e)); 00276 break; 00277 case Generator::RAY: 00278 if (!all_zeroes) 00279 new_gensys.insert(ray(e)); 00280 break; 00281 case Generator::POINT: 00282 // A point in the origin has all zero homogeneous coefficients. 00283 new_gensys.insert(point(e, old_g.divisor())); 00284 break; 00285 case Generator::CLOSURE_POINT: 00286 // A closure point in the origin has all zero homogeneous coefficients. 00287 new_gensys.insert(closure_point(e, old_g.divisor())); 00288 break; 00289 } 00290 } 00291 Polyhedron new_polyhedron(topology(), new_gensys); 00292 std::swap(*this, new_polyhedron); 00293 assert(OK(true)); 00294 }
void Parma_Polyhedra_Library::Polyhedron::expand_space_dimension | ( | Variable | var, | |
dimension_type | m | |||
) |
Creates m
copies of the space dimension corresponding to var
.
var | The variable corresponding to the space dimension to be replicated; | |
m | The number of replicas to be created. |
std::invalid_argument | Thrown if var does not correspond to a dimension of the vector space. | |
std::length_error | Thrown if adding m new space dimensions would cause the vector space to exceed dimension max_space_dimension() . |
*this
has space dimension var
has space dimension m
new space dimensions Definition at line 547 of file Polyhedron_chdims.cc.
References add_recycled_constraints(), add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Constraint::coefficient(), constraints(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Variable::id(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Constraint::is_nonstrict_inequality(), max_space_dimension(), OK(), space_dim, space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), throw_dimension_incompatible(), throw_space_dimension_overflow(), and topology().
00547 { 00548 // TODO: this implementation is _really_ an executable specification. 00549 00550 // `var' should be one of the dimensions of the vector space. 00551 if (var.space_dimension() > space_dim) 00552 throw_dimension_incompatible("expand_space_dimension(v, m)", "v", var); 00553 00554 // The space dimension of the resulting polyhedron should not 00555 // overflow the maximum allowed space dimension. 00556 if (m > max_space_dimension() - space_dimension()) 00557 throw_space_dimension_overflow(topology(), 00558 "expand_dimension(v, m)", 00559 "adding m new space dimensions exceeds " 00560 "the maximum allowed space dimension"); 00561 00562 // Nothing to do, if no dimensions must be added. 00563 if (m == 0) 00564 return; 00565 00566 // Keep track of the dimension before adding the new ones. 00567 dimension_type old_dim = space_dim; 00568 00569 // Add the required new dimensions. 00570 add_space_dimensions_and_embed(m); 00571 00572 const dimension_type src_d = var.id(); 00573 const Constraint_System& cs = constraints(); 00574 Constraint_System new_constraints; 00575 for (Constraint_System::const_iterator i = cs.begin(), 00576 cs_end = cs.end(); i != cs_end; ++i) { 00577 const Constraint& c = *i; 00578 00579 // If `c' does not constrain `var', skip it. 00580 if (c.coefficient(var) == 0) 00581 continue; 00582 00583 // Each relevant constraint results in `m' new constraints. 00584 for (dimension_type dst_d = old_dim; dst_d < old_dim+m; ++dst_d) { 00585 Linear_Expression e; 00586 for (dimension_type j = old_dim; j-- > 0; ) 00587 e += 00588 c.coefficient(Variable(j)) 00589 * (j == src_d ? Variable(dst_d) : Variable(j)); 00590 e += c.inhomogeneous_term(); 00591 new_constraints.insert(c.is_equality() 00592 ? (e == 0) 00593 : (c.is_nonstrict_inequality() 00594 ? (e >= 0) 00595 : (e > 0))); 00596 } 00597 } 00598 add_recycled_constraints(new_constraints); 00599 assert(OK()); 00600 }
void Parma_Polyhedra_Library::Polyhedron::fold_space_dimensions | ( | const Variables_Set & | to_be_folded, | |
Variable | var | |||
) |
Folds the space dimensions in to_be_folded
into var
.
to_be_folded | The set of Variable objects corresponding to the space dimensions to be folded; | |
var | The variable corresponding to the space dimension that is the destination of the folding operation. |
std::invalid_argument | Thrown if *this is dimension-incompatible with var or with one of the Variable objects contained in to_be_folded . Also thrown if var is contained in to_be_folded . |
*this
has space dimension var
has space dimension to_be_folded
is a set of variables whose maximum space dimension is also less than or equal to var
is not a member of to_be_folded
, then the space dimensions corresponding to variables in to_be_folded
are folded into the Definition at line 603 of file Polyhedron_chdims.cc.
References affine_image(), generators(), Parma_Polyhedra_Library::Variable::id(), marked_empty(), OK(), poly_hull_assign(), remove_space_dimensions(), space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
00604 { 00605 // TODO: this implementation is _really_ an executable specification. 00606 00607 // `var' should be one of the dimensions of the polyhedron. 00608 if (var.space_dimension() > space_dim) 00609 throw_dimension_incompatible("fold_space_dimensions(tbf, v)", "v", var); 00610 00611 // The folding of no dimensions is a no-op. 00612 if (to_be_folded.empty()) 00613 return; 00614 00615 // All variables in `to_be_folded' should be dimensions of the polyhedron. 00616 if (to_be_folded.space_dimension() > space_dim) 00617 throw_dimension_incompatible("fold_space_dimensions(tbf, v)", 00618 "tbf.space_dimension()", 00619 to_be_folded.space_dimension()); 00620 00621 // Moreover, `var.id()' should not occur in `to_be_folded'. 00622 if (to_be_folded.find(var.id()) != to_be_folded.end()) 00623 throw_invalid_argument("fold_space_dimensions(tbf, v)", 00624 "v should not occur in tbf"); 00625 00626 // All of the affine images we are going to compute are not invertible, 00627 // hence we will need to compute the generators of the polyehdron. 00628 // Since we keep taking copies, make sure that a single conversion 00629 // from constraints to generators is computed. 00630 (void) generators(); 00631 // Having generators, we now know if the polyhedron is empty: 00632 // in that case, folding is equivalent to just removing space dimensions. 00633 if (!marked_empty()) { 00634 for (Variables_Set::const_iterator i = to_be_folded.begin(), 00635 tbf_end = to_be_folded.end(); i != tbf_end; ++i) { 00636 Polyhedron copy = *this; 00637 copy.affine_image(var, Linear_Expression(Variable(*i))); 00638 poly_hull_assign(copy); 00639 } 00640 } 00641 remove_space_dimensions(to_be_folded); 00642 assert(OK()); 00643 }
void Parma_Polyhedra_Library::Polyhedron::swap | ( | Polyhedron & | y | ) | [inline] |
Swaps *this
with polyhedron y
. (*this
and y
can be dimension-incompatible.).
std::invalid_argument | Thrown if x and y are topology-incompatible. |
Definition at line 99 of file Polyhedron.inlines.hh.
References con_sys, gen_sys, sat_c, sat_g, space_dim, status, Parma_Polyhedra_Library::swap(), throw_topology_incompatible(), and topology().
Referenced by add_space_dimensions_and_embed(), constraints(), generators(), Parma_Polyhedra_Library::NNC_Polyhedron::operator=(), Parma_Polyhedra_Library::C_Polyhedron::operator=(), simplify_using_context_assign(), and swap().
00099 { 00100 if (topology() != y.topology()) 00101 throw_topology_incompatible("swap(y)", "y", y); 00102 std::swap(con_sys, y.con_sys); 00103 std::swap(gen_sys, y.gen_sys); 00104 std::swap(sat_c, y.sat_c); 00105 std::swap(sat_g, y.sat_g); 00106 std::swap(status, y.status); 00107 std::swap(space_dim, y.space_dim); 00108 }
void Parma_Polyhedra_Library::Polyhedron::ascii_dump | ( | ) | const |
void Parma_Polyhedra_Library::Polyhedron::ascii_dump | ( | std::ostream & | s | ) | const |
Writes to s
an ASCII representation of *this
.
Definition at line 3817 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Bit_Matrix::ascii_dump(), Parma_Polyhedra_Library::Generator_System::ascii_dump(), Parma_Polyhedra_Library::Constraint_System::ascii_dump(), Parma_Polyhedra_Library::Polyhedron::Status::ascii_dump(), con_sys, constraints_are_up_to_date(), gen_sys, generators_are_up_to_date(), sat_c, sat_g, space_dim, and status.
03817 { 03818 s << "space_dim " << space_dim << "\n"; 03819 status.ascii_dump(s); 03820 s << "\ncon_sys (" 03821 << (constraints_are_up_to_date() ? "" : "not_") 03822 << "up-to-date)" 03823 << "\n"; 03824 con_sys.ascii_dump(s); 03825 s << "\ngen_sys (" 03826 << (generators_are_up_to_date() ? "" : "not_") 03827 << "up-to-date)" 03828 << "\n"; 03829 gen_sys.ascii_dump(s); 03830 s << "\nsat_c\n"; 03831 sat_c.ascii_dump(s); 03832 s << "\nsat_g\n"; 03833 sat_g.ascii_dump(s); 03834 s << "\n"; 03835 }
void Parma_Polyhedra_Library::Polyhedron::print | ( | ) | const |
Prints *this
to std::cerr
using operator<<
.
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 3840 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Bit_Matrix::ascii_load(), Parma_Polyhedra_Library::Generator_System::ascii_load(), Parma_Polyhedra_Library::Constraint_System::ascii_load(), Parma_Polyhedra_Library::Polyhedron::Status::ascii_load(), con_sys, gen_sys, OK(), sat_c, sat_g, space_dim, and status.
03840 { 03841 std::string str; 03842 03843 if (!(s >> str) || str != "space_dim") 03844 return false; 03845 03846 if (!(s >> space_dim)) 03847 return false; 03848 03849 if (!status.ascii_load(s)) 03850 return false; 03851 03852 if (!(s >> str) || str != "con_sys") 03853 return false; 03854 03855 if (!(s >> str) || (str != "(not_up-to-date)" && str != "(up-to-date)")) 03856 return false; 03857 03858 if (!con_sys.ascii_load(s)) 03859 return false; 03860 03861 if (!(s >> str) || str != "gen_sys") 03862 return false; 03863 03864 if (!(s >> str) || (str != "(not_up-to-date)" && str != "(up-to-date)")) 03865 return false; 03866 03867 if (!gen_sys.ascii_load(s)) 03868 return false; 03869 03870 if (!(s >> str) || str != "sat_c") 03871 return false; 03872 03873 if (!sat_c.ascii_load(s)) 03874 return false; 03875 03876 if (!(s >> str) || str != "sat_g") 03877 return false; 03878 03879 if (!sat_g.ascii_load(s)) 03880 return false; 03881 03882 // Check invariants. 03883 assert(OK()); 03884 return true; 03885 }
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 34 of file Polyhedron.inlines.hh.
References external_memory_in_bytes().
00034 { 00035 return sizeof(*this) + external_memory_in_bytes(); 00036 }
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 3888 of file Polyhedron_public.cc.
References con_sys, Parma_Polyhedra_Library::Bit_Matrix::external_memory_in_bytes(), Parma_Polyhedra_Library::Generator_System::external_memory_in_bytes(), Parma_Polyhedra_Library::Constraint_System::external_memory_in_bytes(), gen_sys, sat_c, and sat_g.
Referenced by total_memory_in_bytes().
03888 { 03889 return 03890 con_sys.external_memory_in_bytes() 03891 + gen_sys.external_memory_in_bytes() 03892 + sat_c.external_memory_in_bytes() 03893 + sat_g.external_memory_in_bytes(); 03894 }
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 44 of file Polyhedron.inlines.hh.
References space_dimension().
00044 { 00045 return space_dimension() & 0x7fffffff; 00046 }
Topology Parma_Polyhedra_Library::Polyhedron::topology | ( | ) | const [inline, private] |
Returns the topological kind of the polyhedron.
Definition at line 61 of file Polyhedron.inlines.hh.
References con_sys, and Parma_Polyhedra_Library::Linear_System::topology().
Referenced by add_generator(), add_recycled_constraints(), add_recycled_generators(), add_recycled_generators_and_minimize(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHRZ03_widening_assign(), concatenate_assign(), constraints(), contains(), expand_space_dimension(), generators(), H79_widening_assign(), intersection_assign(), intersection_assign_and_minimize(), is_included_in(), map_space_dimensions(), OK(), operator=(), poly_difference_assign(), poly_hull_assign(), poly_hull_assign_and_minimize(), Polyhedron(), quick_equivalence_test(), select_CH78_constraints(), select_H79_constraints(), simplify_using_context_assign(), swap(), and time_elapse_assign().
00061 { 00062 // We can check either one of the two matrices. 00063 // (`con_sys' is slightly better, since it is placed at offset 0.) 00064 return con_sys.topology(); 00065 }
bool Parma_Polyhedra_Library::Polyhedron::is_necessarily_closed | ( | ) | const [inline, private] |
Returns true
if and only if the polyhedron is necessarily closed.
Definition at line 73 of file Polyhedron.inlines.hh.
References con_sys, and Parma_Polyhedra_Library::Linear_System::is_necessarily_closed().
Referenced by add_constraint(), add_generator(), add_recycled_constraints(), add_recycled_generators(), add_recycled_generators_and_minimize(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), Parma_Polyhedra_Library::BHRZ03_Certificate::BHRZ03_Certificate(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), Parma_Polyhedra_Library::H79_Certificate::compare(), Parma_Polyhedra_Library::BHRZ03_Certificate::compare(), concatenate_assign(), generalized_affine_image(), generalized_affine_preimage(), generators(), Parma_Polyhedra_Library::H79_Certificate::H79_Certificate(), H79_widening_assign(), Parma_Polyhedra_Library::Interfaces::is_necessarily_closed_for_interfaces(), is_topologically_closed(), is_universe(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), minimized_constraints(), minimized_generators(), OK(), poly_difference_assign(), refine_no_check(), refine_with_constraints(), remove_higher_space_dimensions(), select_H79_constraints(), simplify_using_context_assign(), strongly_minimize_constraints(), strongly_minimize_generators(), throw_dimension_incompatible(), throw_invalid_argument(), throw_invalid_generator(), throw_invalid_generators(), throw_runtime_error(), throw_topology_incompatible(), time_elapse_assign(), and topological_closure_assign().
00073 { 00074 // We can check either one of the two matrices. 00075 // (`con_sys' is slightly better, since it is placed at offset 0.) 00076 return con_sys.is_necessarily_closed(); 00077 }
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
.
c | The constraint to be added. If it is dimension-incompatible with *this , the behavior is undefined. |
Definition at line 1354 of file Polyhedron_nonpublic.cc.
References can_have_something_pending(), clear_constraints_minimized(), clear_generators_up_to_date(), con_sys, constraints_are_up_to_date(), has_pending_generators(), Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::Constraint_System::insert_pending(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Constraint::is_inconsistent(), is_necessarily_closed(), Parma_Polyhedra_Library::Linear_Row::is_necessarily_closed(), marked_empty(), OK(), process_pending_generators(), set_constraints_pending(), set_empty(), space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), and update_constraints().
Referenced by add_congruence(), add_constraint(), bounded_affine_image(), bounded_affine_preimage(), generalized_affine_image(), generalized_affine_preimage(), poly_difference_assign(), refine_with_congruence(), and refine_with_constraint().
01354 { 01355 assert(!marked_empty()); 01356 assert(space_dim >= c.space_dimension()); 01357 01358 // Dealing with a zero-dimensional space polyhedron first. 01359 if (space_dim == 0) { 01360 if (c.is_inconsistent()) 01361 set_empty(); 01362 return; 01363 } 01364 01365 // The constraints (possibly with pending rows) are required. 01366 if (has_pending_generators()) 01367 process_pending_generators(); 01368 else if (!constraints_are_up_to_date()) 01369 update_constraints(); 01370 01371 const bool adding_pending = can_have_something_pending(); 01372 01373 if (c.is_necessarily_closed() || !is_necessarily_closed()) 01374 // Since `con_sys' is not empty, the topology and space dimension 01375 // of the inserted constraint are automatically adjusted. 01376 if (adding_pending) 01377 con_sys.insert_pending(c); 01378 else 01379 con_sys.insert(c); 01380 else { 01381 // Here we know that the system of constraints has at least a row. 01382 // However, by barely invoking `con_sys.insert(c)' we would 01383 // cause a change in the topology of `con_sys', which is wrong. 01384 // Thus, we insert a "topology corrected" copy of `c'. 01385 Linear_Expression nc_expr = Linear_Expression(c); 01386 if (c.is_equality()) 01387 if (adding_pending) 01388 con_sys.insert_pending(nc_expr == 0); 01389 else 01390 con_sys.insert(nc_expr == 0); 01391 else 01392 if (adding_pending) 01393 con_sys.insert_pending(nc_expr >= 0); 01394 else 01395 con_sys.insert(nc_expr >= 0); 01396 } 01397 01398 if (adding_pending) 01399 set_constraints_pending(); 01400 else { 01401 // Constraints are not minimized and generators are not up-to-date. 01402 clear_constraints_minimized(); 01403 clear_generators_up_to_date(); 01404 } 01405 01406 // Note: the constraint system may have become unsatisfiable, thus 01407 // we do not check for satisfiability. 01408 assert(OK()); 01409 }
bool Parma_Polyhedra_Library::Polyhedron::marked_empty | ( | ) | const [inline, private] |
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 122 of file Polyhedron.inlines.hh.
References status, and Parma_Polyhedra_Library::Polyhedron::Status::test_empty().
Referenced by add_congruence(), add_constraint(), add_generator(), add_recycled_constraints(), add_recycled_generators(), add_recycled_generators_and_minimize(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_image(), affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::BHRZ03_Certificate::BHRZ03_Certificate(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHRZ03_widening_assign(), bounded_affine_image(), bounded_affine_preimage(), bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::H79_Certificate::compare(), Parma_Polyhedra_Library::BHRZ03_Certificate::compare(), concatenate_assign(), constrains(), constraints(), contains(), contains_integer_point(), fold_space_dimensions(), generalized_affine_image(), generalized_affine_preimage(), generators(), Parma_Polyhedra_Library::Grid::Grid(), Parma_Polyhedra_Library::H79_Certificate::H79_Certificate(), H79_widening_assign(), intersection_assign(), intersection_assign_and_minimize(), is_bounded(), is_empty(), is_included_in(), is_topologically_closed(), is_universe(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), map_space_dimensions(), max_min(), minimize(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), OK(), operator=(), poly_difference_assign(), poly_hull_assign(), poly_hull_assign_and_minimize(), process_pending(), process_pending_constraints(), process_pending_generators(), quick_equivalence_test(), refine_no_check(), refine_with_congruence(), refine_with_constraint(), refine_with_constraints(), relation_with(), remove_higher_space_dimensions(), remove_space_dimensions(), select_CH78_constraints(), select_H79_constraints(), time_elapse_assign(), topological_closure_assign(), unconstrain(), update_constraints(), and update_generators().
00122 { 00123 return status.test_empty(); 00124 }
bool Parma_Polyhedra_Library::Polyhedron::constraints_are_up_to_date | ( | ) | const [inline, private] |
Returns true
if the system of constraints is up-to-date.
Definition at line 127 of file Polyhedron.inlines.hh.
References status, and Parma_Polyhedra_Library::Polyhedron::Status::test_c_up_to_date().
Referenced by add_recycled_constraints(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_image(), affine_preimage(), ascii_dump(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), bounded_affine_preimage(), Parma_Polyhedra_Library::Box< ITV >::Box(), concatenate_assign(), constrains(), constraints(), Parma_Polyhedra_Library::Grid::Grid(), H79_widening_assign(), intersection_assign(), intersection_assign_and_minimize(), is_included_in(), is_universe(), map_space_dimensions(), minimize(), obtain_sorted_constraints(), obtain_sorted_constraints_with_sat_c(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), OK(), operator=(), Polyhedron(), refine_no_check(), refine_with_constraints(), relation_with(), select_H79_constraints(), simplified_constraints(), simplify_using_context_assign(), topological_closure_assign(), and update_generators().
00127 { 00128 return status.test_c_up_to_date(); 00129 }
bool Parma_Polyhedra_Library::Polyhedron::generators_are_up_to_date | ( | ) | const [inline, private] |
Returns true
if the system of generators is up-to-date.
Definition at line 132 of file Polyhedron.inlines.hh.
References status, and Parma_Polyhedra_Library::Polyhedron::Status::test_g_up_to_date().
Referenced by add_generator(), add_recycled_generators(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_image(), affine_preimage(), ascii_dump(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), bounded_affine_preimage(), bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), constrains(), contains_integer_point(), generators(), Parma_Polyhedra_Library::Grid::Grid(), is_bounded(), is_empty(), is_universe(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), map_space_dimensions(), max_min(), minimize(), obtain_sorted_generators(), obtain_sorted_generators_with_sat_g(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), OK(), operator=(), poly_hull_assign(), poly_hull_assign_and_minimize(), Polyhedron(), relation_with(), remove_higher_space_dimensions(), remove_space_dimensions(), select_CH78_constraints(), select_H79_constraints(), time_elapse_assign(), topological_closure_assign(), unconstrain(), and update_constraints().
00132 { 00133 return status.test_g_up_to_date(); 00134 }
bool Parma_Polyhedra_Library::Polyhedron::constraints_are_minimized | ( | ) | const [inline, private] |
Returns true
if the system of constraints is minimized.
Note that only weak minimization is entailed, so that an NNC polyhedron may still have -redundant constraints.
Definition at line 137 of file Polyhedron.inlines.hh.
References status, and Parma_Polyhedra_Library::Polyhedron::Status::test_c_minimized().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), can_have_something_pending(), Parma_Polyhedra_Library::Grid::Grid(), is_included_in(), is_universe(), minimize(), obtain_sorted_constraints_with_sat_c(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), OK(), quick_equivalence_test(), select_CH78_constraints(), select_H79_constraints(), simplified_constraints(), simplify_using_context_assign(), update_sat_c(), and update_sat_g().
00137 { 00138 return status.test_c_minimized(); 00139 }
bool Parma_Polyhedra_Library::Polyhedron::generators_are_minimized | ( | ) | const [inline, private] |
Returns true
if the system of generators is minimized.
Note that only weak minimization is entailed, so that an NNC polyhedron may still have -redundant generators.
Definition at line 142 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(), constrains(), generators(), is_topologically_closed(), is_universe(), minimize(), OK(), quick_equivalence_test(), simplify_using_context_assign(), update_sat_c(), and update_sat_g().
00142 { 00143 return status.test_g_minimized(); 00144 }
bool Parma_Polyhedra_Library::Polyhedron::has_pending_constraints | ( | ) | const [inline, private] |
Returns true
if there are pending constraints.
Definition at line 157 of file Polyhedron.inlines.hh.
References status, and Parma_Polyhedra_Library::Polyhedron::Status::test_c_pending().
Referenced by add_generator(), add_recycled_generators(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), bounds(), Parma_Polyhedra_Library::Box< ITV >::Box(), constrains(), constraints(), contains_integer_point(), generators(), intersection_assign(), is_bounded(), is_empty(), is_universe(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), map_space_dimensions(), max_min(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), OK(), poly_hull_assign(), poly_hull_assign_and_minimize(), process_pending(), process_pending_constraints(), process_pending_generators(), relation_with(), remove_pending_to_obtain_constraints(), remove_pending_to_obtain_generators(), select_CH78_constraints(), simplified_constraints(), time_elapse_assign(), topological_closure_assign(), and unconstrain().
00157 { 00158 return status.test_c_pending(); 00159 }
bool Parma_Polyhedra_Library::Polyhedron::has_pending_generators | ( | ) | const [inline, private] |
Returns true
if there are pending generators.
Definition at line 162 of file Polyhedron.inlines.hh.
References status, and Parma_Polyhedra_Library::Polyhedron::Status::test_g_pending().
Referenced by add_recycled_constraints(), concatenate_assign(), constrains(), constraints(), generators(), H79_widening_assign(), intersection_assign(), intersection_assign_and_minimize(), is_included_in(), is_universe(), OK(), poly_hull_assign(), process_pending(), process_pending_constraints(), process_pending_generators(), refine_no_check(), refine_with_constraints(), relation_with(), remove_pending_to_obtain_constraints(), remove_pending_to_obtain_generators(), select_H79_constraints(), simplify_using_context_assign(), and topological_closure_assign().
00162 { 00163 return status.test_g_pending(); 00164 }
bool Parma_Polyhedra_Library::Polyhedron::has_something_pending | ( | ) | const [inline, private] |
Returns true
if there are either pending constraints or pending generators.
Definition at line 167 of file Polyhedron.inlines.hh.
References status, Parma_Polyhedra_Library::Polyhedron::Status::test_c_pending(), and Parma_Polyhedra_Library::Polyhedron::Status::test_g_pending().
Referenced by affine_image(), affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), is_topologically_closed(), minimize(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), OK(), process_pending(), quick_equivalence_test(), remove_higher_space_dimensions(), remove_pending_to_obtain_constraints(), remove_pending_to_obtain_generators(), remove_space_dimensions(), select_CH78_constraints(), select_H79_constraints(), simplify_using_context_assign(), update_constraints(), and update_generators().
00167 { 00168 return status.test_c_pending() || status.test_g_pending(); 00169 }
bool Parma_Polyhedra_Library::Polyhedron::can_have_something_pending | ( | ) | const [inline, private] |
Returns true
if the polyhedron can have something pending.
Definition at line 172 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 add_generator(), add_recycled_constraints(), add_recycled_generators(), concatenate_assign(), intersection_assign(), poly_hull_assign(), refine_no_check(), refine_with_constraints(), time_elapse_assign(), topological_closure_assign(), and unconstrain().
00172 { 00173 return constraints_are_minimized() 00174 && generators_are_minimized() 00175 && (sat_c_is_up_to_date() || sat_g_is_up_to_date()); 00176 }
bool Parma_Polyhedra_Library::Polyhedron::sat_c_is_up_to_date | ( | ) | const [inline, private] |
Returns true
if the saturation matrix sat_c
is up-to-date.
Definition at line 147 of file Polyhedron.inlines.hh.
References status, and Parma_Polyhedra_Library::Polyhedron::Status::test_sat_c_up_to_date().
Referenced by add_space_dimensions_and_embed(), can_have_something_pending(), concatenate_assign(), obtain_sorted_constraints(), obtain_sorted_constraints_with_sat_c(), obtain_sorted_generators(), obtain_sorted_generators_with_sat_g(), OK(), operator=(), Polyhedron(), process_pending_constraints(), strongly_minimize_constraints(), strongly_minimize_generators(), and update_sat_c().
00147 { 00148 return status.test_sat_c_up_to_date(); 00149 }
bool Parma_Polyhedra_Library::Polyhedron::sat_g_is_up_to_date | ( | ) | const [inline, private] |
Returns true
if the saturation matrix sat_g
is up-to-date.
Definition at line 152 of file Polyhedron.inlines.hh.
References status, and Parma_Polyhedra_Library::Polyhedron::Status::test_sat_g_up_to_date().
Referenced by add_space_dimensions_and_project(), can_have_something_pending(), obtain_sorted_constraints(), obtain_sorted_constraints_with_sat_c(), obtain_sorted_generators(), obtain_sorted_generators_with_sat_g(), OK(), operator=(), Polyhedron(), process_pending_generators(), select_H79_constraints(), strongly_minimize_constraints(), strongly_minimize_generators(), and update_sat_g().
00152 { 00153 return status.test_sat_g_up_to_date(); 00154 }
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 662 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Generator_System::clear(), Parma_Polyhedra_Library::Constraint_System::clear(), con_sys, gen_sys, Parma_Polyhedra_Library::Polyhedron::Status::set_zero_dim_univ(), space_dim, and status.
Referenced by map_space_dimensions(), operator=(), Polyhedron(), remove_higher_space_dimensions(), and remove_space_dimensions().
00662 { 00663 status.set_zero_dim_univ(); 00664 space_dim = 0; 00665 con_sys.clear(); 00666 gen_sys.clear(); 00667 }
void Parma_Polyhedra_Library::Polyhedron::set_empty | ( | ) | [private] |
Sets status
to express that the polyhedron is empty, clearing all corresponding matrices.
Definition at line 670 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Bit_Matrix::clear(), Parma_Polyhedra_Library::Generator_System::clear(), Parma_Polyhedra_Library::Constraint_System::clear(), con_sys, gen_sys, sat_c, sat_g, Parma_Polyhedra_Library::Polyhedron::Status::set_empty(), and status.
Referenced by add_congruence(), add_congruences(), add_constraint(), add_recycled_constraints(), concatenate_assign(), intersection_assign(), intersection_assign_and_minimize(), operator=(), poly_difference_assign(), Polyhedron(), process_pending_constraints(), refine_no_check(), refine_with_congruence(), refine_with_congruences(), time_elapse_assign(), and update_generators().
00670 { 00671 status.set_empty(); 00672 // The polyhedron is empty: we can thus throw away everything. 00673 con_sys.clear(); 00674 gen_sys.clear(); 00675 sat_c.clear(); 00676 sat_g.clear(); 00677 }
void Parma_Polyhedra_Library::Polyhedron::set_constraints_up_to_date | ( | ) | [inline, private] |
Sets status
to express that constraints are up-to-date.
Definition at line 191 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().
00191 { 00192 status.set_c_up_to_date(); 00193 }
void Parma_Polyhedra_Library::Polyhedron::set_generators_up_to_date | ( | ) | [inline, private] |
Sets status
to express that generators are up-to-date.
Definition at line 196 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::set_g_up_to_date(), and status.
Referenced by add_recycled_generators(), add_recycled_generators_and_minimize(), Polyhedron(), and set_generators_minimized().
00196 { 00197 status.set_g_up_to_date(); 00198 }
void Parma_Polyhedra_Library::Polyhedron::set_constraints_minimized | ( | ) | [inline, private] |
Sets status
to express that constraints are minimized.
Definition at line 201 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().
00201 { 00202 set_constraints_up_to_date(); 00203 status.set_c_minimized(); 00204 }
void Parma_Polyhedra_Library::Polyhedron::set_generators_minimized | ( | ) | [inline, private] |
Sets status
to express that generators are minimized.
Definition at line 207 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::set_g_minimized(), set_generators_up_to_date(), and status.
Referenced by add_generator(), add_space_dimensions_and_project(), update_constraints(), and update_generators().
00207 { 00208 set_generators_up_to_date(); 00209 status.set_g_minimized(); 00210 }
void Parma_Polyhedra_Library::Polyhedron::set_constraints_pending | ( | ) | [inline, private] |
Sets status
to express that constraints are pending.
Definition at line 213 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::set_c_pending(), and status.
Referenced by add_recycled_constraints(), concatenate_assign(), intersection_assign(), refine_no_check(), and refine_with_constraints().
00213 { 00214 status.set_c_pending(); 00215 }
void Parma_Polyhedra_Library::Polyhedron::set_generators_pending | ( | ) | [inline, private] |
Sets status
to express that generators are pending.
Definition at line 218 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::set_g_pending(), and status.
Referenced by add_generator(), add_recycled_generators(), poly_hull_assign(), time_elapse_assign(), topological_closure_assign(), and unconstrain().
00218 { 00219 status.set_g_pending(); 00220 }
void Parma_Polyhedra_Library::Polyhedron::set_sat_c_up_to_date | ( | ) | [inline, private] |
Sets status
to express that sat_c
is up-to-date.
Definition at line 223 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::set_sat_c_up_to_date(), and status.
Referenced by concatenate_assign(), intersection_assign_and_minimize(), obtain_sorted_constraints_with_sat_c(), obtain_sorted_generators(), obtain_sorted_generators_with_sat_g(), process_pending_constraints(), update_constraints(), and update_sat_c().
00223 { 00224 status.set_sat_c_up_to_date(); 00225 }
void Parma_Polyhedra_Library::Polyhedron::set_sat_g_up_to_date | ( | ) | [inline, private] |
Sets status
to express that sat_g
is up-to-date.
Definition at line 228 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::set_sat_g_up_to_date(), and status.
Referenced by obtain_sorted_constraints(), obtain_sorted_constraints_with_sat_c(), obtain_sorted_generators_with_sat_g(), process_pending_generators(), update_generators(), and update_sat_g().
00228 { 00229 status.set_sat_g_up_to_date(); 00230 }
void Parma_Polyhedra_Library::Polyhedron::clear_empty | ( | ) | [inline, private] |
Clears the status
flag indicating that the polyhedron is empty.
Definition at line 233 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::reset_empty(), and status.
Referenced by add_generator(), add_recycled_generators(), and add_recycled_generators_and_minimize().
00233 { 00234 status.reset_empty(); 00235 }
void Parma_Polyhedra_Library::Polyhedron::clear_constraints_up_to_date | ( | ) | [inline, private] |
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 270 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 add_generator(), add_recycled_generators(), affine_image(), generalized_affine_image(), poly_hull_assign(), remove_higher_space_dimensions(), remove_pending_to_obtain_generators(), remove_space_dimensions(), strongly_minimize_generators(), time_elapse_assign(), topological_closure_assign(), and unconstrain().
00270 { 00271 clear_pending_constraints(); 00272 clear_constraints_minimized(); 00273 clear_sat_c_up_to_date(); 00274 clear_sat_g_up_to_date(); 00275 status.reset_c_up_to_date(); 00276 // Can get rid of con_sys here. 00277 }
void Parma_Polyhedra_Library::Polyhedron::clear_generators_up_to_date | ( | ) | [inline, private] |
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 280 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 add_recycled_constraints(), affine_preimage(), concatenate_assign(), intersection_assign(), refine_no_check(), refine_with_constraints(), remove_pending_to_obtain_constraints(), strongly_minimize_constraints(), and topological_closure_assign().
00280 { 00281 clear_pending_generators(); 00282 clear_generators_minimized(); 00283 clear_sat_c_up_to_date(); 00284 clear_sat_g_up_to_date(); 00285 status.reset_g_up_to_date(); 00286 // Can get rid of gen_sys here. 00287 }
void Parma_Polyhedra_Library::Polyhedron::clear_constraints_minimized | ( | ) | [inline, private] |
Sets status
to express that constraints are no longer minimized.
Definition at line 238 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::reset_c_minimized(), and status.
Referenced by add_recycled_constraints(), affine_preimage(), clear_constraints_up_to_date(), concatenate_assign(), intersection_assign(), refine_no_check(), refine_with_constraints(), remove_pending_to_obtain_constraints(), and topological_closure_assign().
00238 { 00239 status.reset_c_minimized(); 00240 }
void Parma_Polyhedra_Library::Polyhedron::clear_generators_minimized | ( | ) | [inline, private] |
Sets status
to express that generators are no longer minimized.
Definition at line 243 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::reset_g_minimized(), and status.
Referenced by add_generator(), add_recycled_generators(), affine_image(), clear_generators_up_to_date(), generalized_affine_image(), poly_hull_assign(), remove_higher_space_dimensions(), remove_pending_to_obtain_generators(), remove_space_dimensions(), time_elapse_assign(), topological_closure_assign(), and unconstrain().
00243 { 00244 status.reset_g_minimized(); 00245 }
void Parma_Polyhedra_Library::Polyhedron::clear_pending_constraints | ( | ) | [inline, private] |
Sets status
to express that there are no longer pending constraints.
Definition at line 248 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::reset_c_pending(), and status.
Referenced by clear_constraints_up_to_date(), intersection_assign_and_minimize(), process_pending_constraints(), and remove_pending_to_obtain_constraints().
00248 { 00249 status.reset_c_pending(); 00250 }
void Parma_Polyhedra_Library::Polyhedron::clear_pending_generators | ( | ) | [inline, private] |
Sets status
to express that there are no longer pending generators.
Definition at line 253 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::reset_g_pending(), and status.
Referenced by clear_generators_up_to_date(), poly_hull_assign_and_minimize(), process_pending_generators(), and remove_pending_to_obtain_generators().
00253 { 00254 status.reset_g_pending(); 00255 }
void Parma_Polyhedra_Library::Polyhedron::clear_sat_c_up_to_date | ( | ) | [inline, private] |
Sets status
to express that sat_c
is no longer up-to-date.
Definition at line 258 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::reset_sat_c_up_to_date(), and status.
Referenced by add_recycled_generators_and_minimize(), affine_image(), affine_preimage(), clear_constraints_up_to_date(), clear_generators_up_to_date(), concatenate_assign(), generalized_affine_image(), obtain_sorted_constraints(), poly_hull_assign_and_minimize(), process_pending_generators(), and update_generators().
00258 { 00259 status.reset_sat_c_up_to_date(); 00260 // Can get rid of sat_c here. 00261 }
void Parma_Polyhedra_Library::Polyhedron::clear_sat_g_up_to_date | ( | ) | [inline, private] |
Sets status
to express that sat_g
is no longer up-to-date.
Definition at line 264 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::reset_sat_g_up_to_date(), and status.
Referenced by affine_image(), affine_preimage(), clear_constraints_up_to_date(), clear_generators_up_to_date(), concatenate_assign(), generalized_affine_image(), intersection_assign_and_minimize(), obtain_sorted_generators(), process_pending_constraints(), and update_constraints().
00264 { 00265 status.reset_sat_g_up_to_date(); 00266 // Can get rid of sat_g here. 00267 }
bool Parma_Polyhedra_Library::Polyhedron::process_pending | ( | ) | const [inline, private] |
Processes the pending rows of either description of the polyhedron and obtains a minimized polyhedron.
false
if and only if *this
turns out to be an empty polyhedron.Definition at line 290 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.
Referenced by contains_integer_point(), is_topologically_closed(), and minimize().
00290 { 00291 assert(space_dim > 0 && !marked_empty()); 00292 assert(has_something_pending()); 00293 00294 Polyhedron& x = const_cast<Polyhedron&>(*this); 00295 00296 if (x.has_pending_constraints()) 00297 return x.process_pending_constraints(); 00298 00299 assert(x.has_pending_generators()); 00300 x.process_pending_generators(); 00301 return true; 00302 }
bool Parma_Polyhedra_Library::Polyhedron::process_pending_constraints | ( | ) | const [private] |
Processes the pending constraints and obtains a minimized polyhedron.
false
if and only if *this
turns out to be an empty polyhedron.Definition at line 680 of file Polyhedron_nonpublic.cc.
References add_and_minimize(), clear_pending_constraints(), clear_sat_g_up_to_date(), con_sys, empty, gen_sys, has_pending_constraints(), has_pending_generators(), Parma_Polyhedra_Library::Linear_System::is_sorted(), marked_empty(), Parma_Polyhedra_Library::Linear_System::num_pending_rows(), obtain_sorted_constraints_with_sat_c(), OK(), sat_c, sat_c_is_up_to_date(), sat_g, set_empty(), set_sat_c_up_to_date(), Parma_Polyhedra_Library::Linear_System::sort_pending_and_remove_duplicates(), space_dim, and Parma_Polyhedra_Library::Bit_Matrix::transpose_assign().
Referenced by add_generator(), add_recycled_generators(), bounds(), generators(), is_bounded(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), max_min(), poly_hull_assign(), poly_hull_assign_and_minimize(), process_pending(), relation_with(), remove_pending_to_obtain_generators(), time_elapse_assign(), topological_closure_assign(), and unconstrain().
00680 { 00681 assert(space_dim > 0 && !marked_empty()); 00682 assert(has_pending_constraints() && !has_pending_generators()); 00683 00684 Polyhedron& x = const_cast<Polyhedron&>(*this); 00685 00686 // Integrate the pending part of the system of constraints and minimize. 00687 // We need `sat_c' up-to-date and `con_sys' sorted (together with `sat_c'). 00688 if (!x.sat_c_is_up_to_date()) 00689 x.sat_c.transpose_assign(x.sat_g); 00690 if (!x.con_sys.is_sorted()) 00691 x.obtain_sorted_constraints_with_sat_c(); 00692 // We sort in place the pending constraints, erasing those constraints 00693 // that also occur in the non-pending part of `con_sys'. 00694 x.con_sys.sort_pending_and_remove_duplicates(); 00695 if (x.con_sys.num_pending_rows() == 0) { 00696 // All pending constraints were duplicates. 00697 x.clear_pending_constraints(); 00698 assert(OK(true)); 00699 return true; 00700 } 00701 00702 const bool empty = add_and_minimize(true, x.con_sys, x.gen_sys, x.sat_c); 00703 assert(x.con_sys.num_pending_rows() == 0); 00704 00705 if (empty) 00706 x.set_empty(); 00707 else { 00708 x.clear_pending_constraints(); 00709 x.clear_sat_g_up_to_date(); 00710 x.set_sat_c_up_to_date(); 00711 } 00712 assert(OK(!empty)); 00713 return !empty; 00714 }
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 717 of file Polyhedron_nonpublic.cc.
References add_and_minimize(), clear_pending_generators(), clear_sat_c_up_to_date(), con_sys, gen_sys, has_pending_constraints(), has_pending_generators(), Parma_Polyhedra_Library::Linear_System::is_sorted(), marked_empty(), Parma_Polyhedra_Library::Linear_System::num_pending_rows(), obtain_sorted_generators_with_sat_g(), OK(), sat_c, sat_g, sat_g_is_up_to_date(), set_sat_g_up_to_date(), Parma_Polyhedra_Library::Linear_System::sort_pending_and_remove_duplicates(), space_dim, and Parma_Polyhedra_Library::Bit_Matrix::transpose_assign().
Referenced by add_recycled_constraints(), concatenate_assign(), constrains(), constraints(), H79_widening_assign(), intersection_assign(), intersection_assign_and_minimize(), is_included_in(), is_universe(), process_pending(), refine_no_check(), refine_with_constraints(), relation_with(), and remove_pending_to_obtain_constraints().
00717 { 00718 assert(space_dim > 0 && !marked_empty()); 00719 assert(has_pending_generators() && !has_pending_constraints()); 00720 00721 Polyhedron& x = const_cast<Polyhedron&>(*this); 00722 00723 // Integrate the pending part of the system of generators and minimize. 00724 // We need `sat_g' up-to-date and `gen_sys' sorted (together with `sat_g'). 00725 if (!x.sat_g_is_up_to_date()) 00726 x.sat_g.transpose_assign(x.sat_c); 00727 if (!x.gen_sys.is_sorted()) 00728 x.obtain_sorted_generators_with_sat_g(); 00729 // We sort in place the pending generators, erasing those generators 00730 // that also occur in the non-pending part of `gen_sys'. 00731 x.gen_sys.sort_pending_and_remove_duplicates(); 00732 if (x.gen_sys.num_pending_rows() == 0) { 00733 // All pending generators were duplicates. 00734 x.clear_pending_generators(); 00735 assert(OK(true)); 00736 return; 00737 } 00738 00739 add_and_minimize(false, x.gen_sys, x.con_sys, x.sat_g); 00740 assert(x.gen_sys.num_pending_rows() == 0); 00741 00742 x.clear_pending_generators(); 00743 x.clear_sat_c_up_to_date(); 00744 x.set_sat_g_up_to_date(); 00745 }
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 748 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(), has_something_pending(), OK(), process_pending_generators(), Parma_Polyhedra_Library::Linear_System::set_sorted(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
Referenced by affine_preimage().
00748 { 00749 assert(has_something_pending()); 00750 00751 Polyhedron& x = const_cast<Polyhedron&>(*this); 00752 00753 // If the polyhedron has pending constraints, simply unset them. 00754 if (x.has_pending_constraints()) { 00755 // Integrate the pending constraints, which are possibly not sorted. 00756 x.con_sys.unset_pending_rows(); 00757 x.con_sys.set_sorted(false); 00758 x.clear_pending_constraints(); 00759 x.clear_constraints_minimized(); 00760 x.clear_generators_up_to_date(); 00761 } 00762 else { 00763 assert(x.has_pending_generators()); 00764 // We must process the pending generators and obtain the 00765 // corresponding system of constraints. 00766 x.process_pending_generators(); 00767 } 00768 assert(OK(true)); 00769 }
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.
false
if and only if *this
turns out to be an empty polyhedron.Definition at line 772 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(), has_something_pending(), OK(), process_pending_constraints(), Parma_Polyhedra_Library::Linear_System::set_sorted(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
Referenced by affine_image(), map_space_dimensions(), remove_higher_space_dimensions(), and remove_space_dimensions().
00772 { 00773 assert(has_something_pending()); 00774 00775 Polyhedron& x = const_cast<Polyhedron&>(*this); 00776 00777 // If the polyhedron has pending generators, simply unset them. 00778 if (x.has_pending_generators()) { 00779 // Integrate the pending generators, which are possibly not sorted. 00780 x.gen_sys.unset_pending_rows(); 00781 x.gen_sys.set_sorted(false); 00782 x.clear_pending_generators(); 00783 x.clear_generators_minimized(); 00784 x.clear_constraints_up_to_date(); 00785 assert(OK(true)); 00786 return true; 00787 } 00788 else { 00789 assert(x.has_pending_constraints()); 00790 // We must integrate the pending constraints and obtain the 00791 // corresponding system of generators. 00792 return x.process_pending_constraints(); 00793 } 00794 }
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 797 of file Polyhedron_nonpublic.cc.
References clear_sat_g_up_to_date(), con_sys, gen_sys, generators_are_up_to_date(), has_something_pending(), marked_empty(), minimize(), sat_c, set_constraints_minimized(), set_generators_minimized(), set_sat_c_up_to_date(), and space_dim.
Referenced by add_recycled_constraints(), concatenate_assign(), constrains(), constraints(), H79_widening_assign(), intersection_assign(), intersection_assign_and_minimize(), is_included_in(), minimize(), refine_no_check(), refine_with_constraints(), and relation_with().
00797 { 00798 assert(space_dim > 0); 00799 assert(!marked_empty()); 00800 assert(generators_are_up_to_date()); 00801 // We assume the polyhedron has no pending constraints or generators. 00802 assert(!has_something_pending()); 00803 00804 Polyhedron& x = const_cast<Polyhedron&>(*this); 00805 minimize(false, x.gen_sys, x.con_sys, x.sat_c); 00806 // `sat_c' is the only saturation matrix up-to-date. 00807 x.set_sat_c_up_to_date(); 00808 x.clear_sat_g_up_to_date(); 00809 // The system of constraints and the system of generators 00810 // are minimized. 00811 x.set_constraints_minimized(); 00812 x.set_generators_minimized(); 00813 }
bool Parma_Polyhedra_Library::Polyhedron::update_generators | ( | ) | const [private] |
Updates generators starting from constraints and minimizes them.
false
if and only if *this
turns out to be an empty polyhedron.Definition at line 816 of file Polyhedron_nonpublic.cc.
References clear_sat_c_up_to_date(), con_sys, constraints_are_up_to_date(), empty, gen_sys, has_something_pending(), marked_empty(), minimize(), sat_g, set_constraints_minimized(), set_empty(), set_generators_minimized(), set_sat_g_up_to_date(), and space_dim.
Referenced by add_generator(), bounds(), generators(), is_bounded(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), map_space_dimensions(), max_min(), minimize(), poly_hull_assign(), poly_hull_assign_and_minimize(), relation_with(), remove_higher_space_dimensions(), remove_space_dimensions(), select_H79_constraints(), time_elapse_assign(), and unconstrain().
00816 { 00817 assert(space_dim > 0); 00818 assert(!marked_empty()); 00819 assert(constraints_are_up_to_date()); 00820 // We assume the polyhedron has no pending constraints or generators. 00821 assert(!has_something_pending()); 00822 00823 Polyhedron& x = const_cast<Polyhedron&>(*this); 00824 // If the system of constraints is not consistent the 00825 // polyhedron is empty. 00826 const bool empty = minimize(true, x.con_sys, x.gen_sys, x.sat_g); 00827 if (empty) 00828 x.set_empty(); 00829 else { 00830 // `sat_g' is the only saturation matrix up-to-date. 00831 x.set_sat_g_up_to_date(); 00832 x.clear_sat_c_up_to_date(); 00833 // The system of constraints and the system of generators 00834 // are minimized. 00835 x.set_constraints_minimized(); 00836 x.set_generators_minimized(); 00837 } 00838 return !empty; 00839 }
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:
Definition at line 842 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Bit_Matrix::clear(), con_sys, constraints_are_minimized(), Parma_Polyhedra_Library::Linear_System::first_pending_row(), gen_sys, generators_are_minimized(), Parma_Polyhedra_Library::Bit_Matrix::resize(), sat_c, sat_c_is_up_to_date(), 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().
00842 { 00843 assert(constraints_are_minimized()); 00844 assert(generators_are_minimized()); 00845 assert(!sat_c_is_up_to_date()); 00846 00847 // We only consider non-pending rows. 00848 const dimension_type csr = con_sys.first_pending_row(); 00849 const dimension_type gsr = gen_sys.first_pending_row(); 00850 Polyhedron& x = const_cast<Polyhedron&>(*this); 00851 00852 // The columns of `sat_c' represent the constraints and 00853 // its rows represent the generators: resize accordingly. 00854 x.sat_c.resize(gsr, csr); 00855 for (dimension_type i = gsr; i-- > 0; ) 00856 for (dimension_type j = csr; j-- > 0; ) { 00857 const int sp_sign = Scalar_Products::sign(con_sys[j], gen_sys[i]); 00858 // The negativity of this scalar product would mean 00859 // that the generator `gen_sys[i]' violates the constraint 00860 // `con_sys[j]' and it is not possible because both generators 00861 // and constraints are up-to-date. 00862 assert(sp_sign >= 0); 00863 if (sp_sign > 0) 00864 // `gen_sys[i]' satisfies (without saturate) `con_sys[j]'. 00865 x.sat_c[i].set(j); 00866 else 00867 // `gen_sys[i]' saturates `con_sys[j]'. 00868 x.sat_c[i].clear(j); 00869 } 00870 x.set_sat_c_up_to_date(); 00871 }
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:
Definition at line 874 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Bit_Matrix::clear(), con_sys, constraints_are_minimized(), Parma_Polyhedra_Library::Linear_System::first_pending_row(), gen_sys, generators_are_minimized(), Parma_Polyhedra_Library::Bit_Matrix::resize(), sat_g, sat_g_is_up_to_date(), set_sat_g_up_to_date(), and Parma_Polyhedra_Library::Scalar_Products::sign().
Referenced by add_space_dimensions_and_project(), obtain_sorted_generators_with_sat_g(), and select_H79_constraints().
00874 { 00875 assert(constraints_are_minimized()); 00876 assert(generators_are_minimized()); 00877 assert(!sat_g_is_up_to_date()); 00878 00879 // We only consider non-pending rows. 00880 const dimension_type csr = con_sys.first_pending_row(); 00881 const dimension_type gsr = gen_sys.first_pending_row(); 00882 Polyhedron& x = const_cast<Polyhedron&>(*this); 00883 00884 // The columns of `sat_g' represent generators and its 00885 // rows represent the constraints: resize accordingly. 00886 x.sat_g.resize(csr, gsr); 00887 for (dimension_type i = csr; i-- > 0; ) 00888 for (dimension_type j = gsr; j-- > 0; ) { 00889 const int sp_sign = Scalar_Products::sign(con_sys[i], gen_sys[j]); 00890 // The negativity of this scalar product would mean 00891 // that the generator `gen_sys[j]' violates the constraint 00892 // `con_sys[i]' and it is not possible because both generators 00893 // and constraints are up-to-date. 00894 assert(sp_sign >= 0); 00895 if (sp_sign > 0) 00896 // `gen_sys[j]' satisfies (without saturate) `con_sys[i]'. 00897 x.sat_g[i].set(j); 00898 else 00899 // `gen_sys[j]' saturates `con_sys[i]'. 00900 x.sat_g[i].clear(j); 00901 } 00902 x.set_sat_g_up_to_date(); 00903 }
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 906 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Linear_System::check_sorted(), clear_sat_c_up_to_date(), con_sys, constraints_are_up_to_date(), Parma_Polyhedra_Library::Linear_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::Linear_System::sort_and_remove_with_sat(), Parma_Polyhedra_Library::Linear_System::sort_rows(), and Parma_Polyhedra_Library::Bit_Matrix::transpose_assign().
Referenced by constraints(), intersection_assign_and_minimize(), is_universe(), and quick_equivalence_test().
00906 { 00907 assert(constraints_are_up_to_date()); 00908 // `con_sys' will be sorted up to `index_first_pending'. 00909 Polyhedron& x = const_cast<Polyhedron&>(*this); 00910 if (!x.con_sys.is_sorted()) { 00911 if (x.sat_g_is_up_to_date()) { 00912 // Sorting constraints keeping `sat_g' consistent. 00913 x.con_sys.sort_and_remove_with_sat(x.sat_g); 00914 // `sat_c' is not up-to-date anymore. 00915 x.clear_sat_c_up_to_date(); 00916 } 00917 else if (x.sat_c_is_up_to_date()) { 00918 // Using `sat_c' to obtain `sat_g', then it is like previous case. 00919 x.sat_g.transpose_assign(x.sat_c); 00920 x.con_sys.sort_and_remove_with_sat(x.sat_g); 00921 x.set_sat_g_up_to_date(); 00922 x.clear_sat_c_up_to_date(); 00923 } 00924 else 00925 // If neither `sat_g' nor `sat_c' are up-to-date, 00926 // we just sort the constraints. 00927 x.con_sys.sort_rows(); 00928 } 00929 00930 assert(con_sys.check_sorted()); 00931 }
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 934 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Linear_System::check_sorted(), clear_sat_g_up_to_date(), gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Linear_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::Linear_System::sort_and_remove_with_sat(), Parma_Polyhedra_Library::Linear_System::sort_rows(), and Parma_Polyhedra_Library::Bit_Matrix::transpose_assign().
Referenced by generators(), poly_hull_assign_and_minimize(), and quick_equivalence_test().
00934 { 00935 assert(generators_are_up_to_date()); 00936 // `gen_sys' will be sorted up to `index_first_pending'. 00937 Polyhedron& x = const_cast<Polyhedron&>(*this); 00938 if (!x.gen_sys.is_sorted()) { 00939 if (x.sat_c_is_up_to_date()) { 00940 // Sorting generators keeping 'sat_c' consistent. 00941 x.gen_sys.sort_and_remove_with_sat(x.sat_c); 00942 // `sat_g' is not up-to-date anymore. 00943 x.clear_sat_g_up_to_date(); 00944 } 00945 else if (x.sat_g_is_up_to_date()) { 00946 // Obtaining `sat_c' from `sat_g' and proceeding like previous case. 00947 x.sat_c.transpose_assign(x.sat_g); 00948 x.gen_sys.sort_and_remove_with_sat(x.sat_c); 00949 x.set_sat_c_up_to_date(); 00950 x.clear_sat_g_up_to_date(); 00951 } 00952 else 00953 // If neither `sat_g' nor `sat_c' are up-to-date, we just sort 00954 // the generators. 00955 x.gen_sys.sort_rows(); 00956 } 00957 00958 assert(gen_sys.check_sorted()); 00959 }
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 962 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Linear_System::check_sorted(), con_sys, constraints_are_minimized(), constraints_are_up_to_date(), Parma_Polyhedra_Library::Linear_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::Linear_System::set_sorted(), Parma_Polyhedra_Library::Linear_System::sort_and_remove_with_sat(), Parma_Polyhedra_Library::Bit_Matrix::transpose_assign(), and update_sat_c().
Referenced by intersection_assign_and_minimize(), and process_pending_constraints().
00962 { 00963 assert(constraints_are_up_to_date()); 00964 assert(constraints_are_minimized()); 00965 // `con_sys' will be sorted up to `index_first_pending'. 00966 Polyhedron& x = const_cast<Polyhedron&>(*this); 00967 // At least one of the saturation matrices must be up-to-date. 00968 if (!x.sat_c_is_up_to_date() && !x.sat_g_is_up_to_date()) 00969 x.update_sat_c(); 00970 00971 if (x.con_sys.is_sorted()) { 00972 if (x.sat_c_is_up_to_date()) 00973 // If constraints are already sorted and sat_c is up to 00974 // date there is nothing to do. 00975 return; 00976 } 00977 else { 00978 if (!x.sat_g_is_up_to_date()) { 00979 // If constraints are not sorted and sat_g is not up-to-date 00980 // we obtain sat_g from sat_c (that has to be up-to-date)... 00981 x.sat_g.transpose_assign(x.sat_c); 00982 x.set_sat_g_up_to_date(); 00983 } 00984 // ... and sort it together with constraints. 00985 x.con_sys.sort_and_remove_with_sat(x.sat_g); 00986 } 00987 // Obtaining sat_c from sat_g. 00988 x.sat_c.transpose_assign(x.sat_g); 00989 x.set_sat_c_up_to_date(); 00990 // Constraints are sorted now. 00991 x.con_sys.set_sorted(true); 00992 00993 assert(con_sys.check_sorted()); 00994 }
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 997 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Linear_System::check_sorted(), gen_sys, generators_are_up_to_date(), Parma_Polyhedra_Library::Linear_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::Linear_System::set_sorted(), Parma_Polyhedra_Library::Linear_System::sort_and_remove_with_sat(), Parma_Polyhedra_Library::Bit_Matrix::transpose_assign(), and update_sat_g().
Referenced by add_recycled_generators_and_minimize(), poly_hull_assign_and_minimize(), and process_pending_generators().
00997 { 00998 assert(generators_are_up_to_date()); 00999 // `gen_sys' will be sorted up to `index_first_pending'. 01000 Polyhedron& x = const_cast<Polyhedron&>(*this); 01001 // At least one of the saturation matrices must be up-to-date. 01002 if (!x.sat_c_is_up_to_date() && !x.sat_g_is_up_to_date()) 01003 x.update_sat_g(); 01004 01005 if (x.gen_sys.is_sorted()) { 01006 if (x.sat_g_is_up_to_date()) 01007 // If generators are already sorted and sat_g is up to 01008 // date there is nothing to do. 01009 return; 01010 } 01011 else { 01012 if (!x.sat_c_is_up_to_date()) { 01013 // If generators are not sorted and sat_c is not up-to-date 01014 // we obtain sat_c from sat_g (that has to be up-to-date)... 01015 x.sat_c.transpose_assign(x.sat_g); 01016 x.set_sat_c_up_to_date(); 01017 } 01018 // ... and sort it together with generators. 01019 x.gen_sys.sort_and_remove_with_sat(x.sat_c); 01020 } 01021 // Obtaining sat_g from sat_c. 01022 x.sat_g.transpose_assign(sat_c); 01023 x.set_sat_g_up_to_date(); 01024 // Generators are sorted now. 01025 x.gen_sys.set_sorted(true); 01026 01027 assert(gen_sys.check_sorted()); 01028 }
bool Parma_Polyhedra_Library::Polyhedron::minimize | ( | ) | const [private] |
Applies (weak) minimization to both the constraints and generators.
false
if and only if *this
turns out to be an empty polyhedron.Definition at line 1031 of file Polyhedron_nonpublic.cc.
References constraints_are_minimized(), constraints_are_up_to_date(), generators_are_minimized(), generators_are_up_to_date(), has_something_pending(), marked_empty(), OK(), process_pending(), space_dim, update_constraints(), and update_generators().
Referenced by add_congruence_and_minimize(), add_congruences_and_minimize(), add_recycled_constraints_and_minimize(), add_recycled_generators(), add_recycled_generators_and_minimize(), affine_image(), affine_preimage(), constrains(), generalized_affine_image(), is_empty(), is_universe(), minimized_constraints(), minimized_generators(), OK(), poly_hull_assign_and_minimize(), strongly_minimize_constraints(), strongly_minimize_generators(), update_constraints(), and update_generators().
01031 { 01032 // 0-dim space or empty polyhedra are already minimized. 01033 if (marked_empty()) 01034 return false; 01035 if (space_dim == 0) 01036 return true; 01037 01038 // If the polyhedron has something pending, process it. 01039 if (has_something_pending()) { 01040 const bool not_empty = process_pending(); 01041 assert(OK()); 01042 return not_empty; 01043 } 01044 01045 // Here there are no pending constraints or generators. 01046 // Is the polyhedron already minimized? 01047 if (constraints_are_minimized() && generators_are_minimized()) 01048 return true; 01049 01050 // If constraints or generators are up-to-date, invoking 01051 // update_generators() or update_constraints(), respectively, 01052 // minimizes both constraints and generators. 01053 // If both are up-to-date it does not matter whether we use 01054 // update_generators() or update_constraints(): 01055 // both minimize constraints and generators. 01056 if (constraints_are_up_to_date()) { 01057 // We may discover here that `*this' is empty. 01058 const bool ret = update_generators(); 01059 assert(OK()); 01060 return ret; 01061 } 01062 else { 01063 assert(generators_are_up_to_date()); 01064 update_constraints(); 01065 assert(OK()); 01066 return true; 01067 } 01068 }
bool Parma_Polyhedra_Library::Polyhedron::strongly_minimize_constraints | ( | ) | const [private] |
Applies strong minimization to the constraints of an NNC polyhedron.
false
if and only if *this
turns out to be an empty polyhedron. Definition at line 1071 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::Bit_Row::clear(), clear_generators_up_to_date(), Parma_Polyhedra_Library::Generator::CLOSURE_POINT, con_sys, Parma_Polyhedra_Library::Constraint::epsilon_leq_one(), Parma_Polyhedra_Library::Matrix::erase_to_end(), gen_sys, Parma_Polyhedra_Library::Constraint_System::insert(), is_necessarily_closed(), Parma_Polyhedra_Library::MAXIMIZATION, minimize(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Generator_System::num_lines(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), Parma_Polyhedra_Library::Generator::POINT, Parma_Polyhedra_Library::Generator::RAY, sat_c, sat_c_is_up_to_date(), sat_g, sat_g_is_up_to_date(), Parma_Polyhedra_Library::Bit_Row::set(), Parma_Polyhedra_Library::Linear_System::set_necessarily_closed(), Parma_Polyhedra_Library::Linear_System::set_not_necessarily_closed(), Parma_Polyhedra_Library::MIP_Problem::set_objective_function(), Parma_Polyhedra_Library::MIP_Problem::set_optimization_mode(), Parma_Polyhedra_Library::Linear_System::set_sorted(), Parma_Polyhedra_Library::MIP_Problem::solve(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), status, 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::Linear_System::unset_pending_rows().
Referenced by is_topologically_closed(), minimized_constraints(), and select_H79_constraints().
01071 { 01072 assert(!is_necessarily_closed()); 01073 01074 // From the user perspective, the polyhedron will not change. 01075 Polyhedron& x = const_cast<Polyhedron&>(*this); 01076 01077 // We need `con_sys' (weakly) minimized and `gen_sys' up-to-date. 01078 // `minimize()' will process any pending constraints or generators. 01079 if (!minimize()) 01080 return false; 01081 01082 // If the polyhedron `*this' is zero-dimensional 01083 // at this point it must be a universe polyhedron. 01084 if (x.space_dim == 0) 01085 return true; 01086 01087 // We also need `sat_g' up-to-date. 01088 if (!sat_g_is_up_to_date()) { 01089 assert(sat_c_is_up_to_date()); 01090 x.sat_g.transpose_assign(sat_c); 01091 } 01092 01093 // These Bit_Row's will be later used as masks in order to 01094 // check saturation conditions restricted to particular subsets of 01095 // the generator system. 01096 Bit_Row sat_all_but_rays; 01097 Bit_Row sat_all_but_points; 01098 Bit_Row sat_all_but_closure_points; 01099 01100 const dimension_type gs_rows = gen_sys.num_rows(); 01101 const dimension_type n_lines = gen_sys.num_lines(); 01102 for (dimension_type i = gs_rows; i-- > n_lines; ) 01103 switch (gen_sys[i].type()) { 01104 case Generator::RAY: 01105 sat_all_but_rays.set(i); 01106 break; 01107 case Generator::POINT: 01108 sat_all_but_points.set(i); 01109 break; 01110 case Generator::CLOSURE_POINT: 01111 sat_all_but_closure_points.set(i); 01112 break; 01113 default: 01114 // Found a line with index i >= n_lines. 01115 throw std::runtime_error("PPL internal error: " 01116 "strongly_minimize_constraints."); 01117 } 01118 Bit_Row sat_lines_and_rays; 01119 set_union(sat_all_but_points, sat_all_but_closure_points, 01120 sat_lines_and_rays); 01121 Bit_Row sat_lines_and_closure_points; 01122 set_union(sat_all_but_rays, sat_all_but_points, 01123 sat_lines_and_closure_points); 01124 Bit_Row sat_lines; 01125 set_union(sat_lines_and_rays, sat_lines_and_closure_points, 01126 sat_lines); 01127 01128 // These flags are maintained to later decide if we have to add the 01129 // eps_leq_one constraint and whether or not the constraint system 01130 // was changed. 01131 bool changed = false; 01132 bool found_eps_leq_one = false; 01133 01134 // For all the strict inequalities in `con_sys', check for 01135 // eps-redundancy and eventually move them to the bottom part of the 01136 // system. 01137 Constraint_System& cs = x.con_sys; 01138 Bit_Matrix& sat = x.sat_g; 01139 dimension_type cs_rows = cs.num_rows(); 01140 const dimension_type eps_index = cs.num_columns() - 1; 01141 for (dimension_type i = 0; i < cs_rows; ) 01142 if (cs[i].is_strict_inequality()) { 01143 // First, check if it is saturated by no closure points 01144 Bit_Row sat_ci; 01145 set_union(sat[i], sat_lines_and_closure_points, sat_ci); 01146 if (sat_ci == sat_lines) { 01147 // It is saturated by no closure points. 01148 if (!found_eps_leq_one) { 01149 // Check if it is the eps_leq_one constraint. 01150 const Constraint& c = cs[i]; 01151 bool all_zeroes = true; 01152 for (dimension_type k = eps_index; k-- > 1; ) 01153 if (c[k] != 0) { 01154 all_zeroes = false; 01155 break; 01156 } 01157 if (all_zeroes && (c[0] + c[eps_index] == 0)) { 01158 // We found the eps_leq_one constraint. 01159 found_eps_leq_one = true; 01160 // Consider next constraint. 01161 ++i; 01162 continue; 01163 } 01164 } 01165 // Here `cs[i]' is not the eps_leq_one constraint, 01166 // so it is eps-redundant. 01167 // Move it to the bottom of the constraint system, 01168 // while keeping `sat_g' consistent. 01169 --cs_rows; 01170 std::swap(cs[i], cs[cs_rows]); 01171 std::swap(sat[i], sat[cs_rows]); 01172 // The constraint system is changed. 01173 changed = true; 01174 // Continue by considering next constraint, 01175 // which is already in place due to the swap. 01176 continue; 01177 } 01178 // Now we check if there exists another strict inequality 01179 // constraint having a superset of its saturators, 01180 // when disregarding points. 01181 sat_ci.clear(); 01182 set_union(sat[i], sat_all_but_points, sat_ci); 01183 bool eps_redundant = false; 01184 for (dimension_type j = 0; j < cs_rows; ++j) 01185 if (i != j && cs[j].is_strict_inequality() 01186 && subset_or_equal(sat[j], sat_ci)) { 01187 // Constraint `cs[i]' is eps-redundant: 01188 // move it to the bottom of the constraint system, 01189 // while keeping `sat_g' consistent. 01190 --cs_rows; 01191 std::swap(cs[i], cs[cs_rows]); 01192 std::swap(sat[i], sat[cs_rows]); 01193 eps_redundant = true; 01194 // The constraint system is changed. 01195 changed = true; 01196 break; 01197 } 01198 // Continue with next constraint, which is already in place 01199 // due to the swap if we have found an eps-redundant constraint. 01200 if (!eps_redundant) 01201 ++i; 01202 } 01203 else 01204 // `cs[i]' is not a strict inequality: consider next constraint. 01205 ++i; 01206 01207 if (changed) { 01208 // If the constraint system has been changed, we have to erase 01209 // the epsilon-redundant constraints. 01210 assert(cs_rows < cs.num_rows()); 01211 cs.erase_to_end(cs_rows); 01212 // The remaining constraints are not pending. 01213 cs.unset_pending_rows(); 01214 // The constraint system is no longer sorted. 01215 cs.set_sorted(false); 01216 // The generator system is no longer up-to-date. 01217 x.clear_generators_up_to_date(); 01218 01219 // If we haven't found an upper bound for the epsilon dimension, 01220 // then we have to check whether such an upper bound is implied 01221 // by the remaining constraints (exploiting the simplex algorithm). 01222 if (!found_eps_leq_one) { 01223 MIP_Problem lp; 01224 // KLUDGE: temporarily mark the constraint system as if it was 01225 // necessarily closed, so that we can interpret the epsilon 01226 // dimension as a standard dimension. Be careful to reset the 01227 // topology of `cs' even on exceptional execution path. 01228 cs.set_necessarily_closed(); 01229 try { 01230 lp.add_space_dimensions_and_embed(cs.space_dimension()); 01231 lp.add_constraints(cs); 01232 cs.set_not_necessarily_closed(); 01233 } 01234 catch (...) { 01235 cs.set_not_necessarily_closed(); 01236 throw; 01237 } 01238 // The objective function is `epsilon'. 01239 lp.set_objective_function(Variable(x.space_dim)); 01240 lp.set_optimization_mode(MAXIMIZATION); 01241 MIP_Problem_Status status = lp.solve(); 01242 assert(status != UNFEASIBLE_MIP_PROBLEM); 01243 // If the epsilon dimension is actually unbounded, 01244 // then add the eps_leq_one constraint. 01245 if (status == UNBOUNDED_MIP_PROBLEM) 01246 cs.insert(Constraint::epsilon_leq_one()); 01247 } 01248 } 01249 01250 assert(OK()); 01251 return true; 01252 }
bool Parma_Polyhedra_Library::Polyhedron::strongly_minimize_generators | ( | ) | const [private] |
Applies strong minimization to the generators of an NNC polyhedron.
false
if and only if *this
turns out to be an empty polyhedron. Definition at line 1255 of file Polyhedron_nonpublic.cc.
References clear_constraints_up_to_date(), con_sys, Parma_Polyhedra_Library::Matrix::erase_to_end(), gen_sys, is_necessarily_closed(), minimize(), Parma_Polyhedra_Library::Row::normalize(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Constraint_System::num_equalities(), Parma_Polyhedra_Library::Generator_System::num_lines(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), sat_c, sat_c_is_up_to_date(), sat_g, sat_g_is_up_to_date(), Parma_Polyhedra_Library::Bit_Row::set(), Parma_Polyhedra_Library::Linear_System::set_sorted(), space_dim, Parma_Polyhedra_Library::swap(), Parma_Polyhedra_Library::Bit_Matrix::transpose_assign(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
Referenced by minimized_generators().
01255 { 01256 assert(!is_necessarily_closed()); 01257 01258 // From the user perspective, the polyhedron will not change. 01259 Polyhedron& x = const_cast<Polyhedron&>(*this); 01260 01261 // We need `gen_sys' (weakly) minimized and `con_sys' up-to-date. 01262 // `minimize()' will process any pending constraints or generators. 01263 if (!minimize()) 01264 return false; 01265 01266 // If the polyhedron `*this' is zero-dimensional 01267 // at this point it must be a universe polyhedron. 01268 if (x.space_dim == 0) 01269 return true; 01270 01271 // We also need `sat_c' up-to-date. 01272 if (!sat_c_is_up_to_date()) { 01273 assert(sat_g_is_up_to_date()); 01274 x.sat_c.transpose_assign(sat_g); 01275 } 01276 01277 // This Bit_Row will have all and only the indexes 01278 // of strict inequalities set to 1. 01279 Bit_Row sat_all_but_strict_ineq; 01280 const dimension_type cs_rows = con_sys.num_rows(); 01281 const dimension_type n_equals = con_sys.num_equalities(); 01282 for (dimension_type i = cs_rows; i-- > n_equals; ) 01283 if (con_sys[i].is_strict_inequality()) 01284 sat_all_but_strict_ineq.set(i); 01285 01286 // Will record whether or not we changed the generator system. 01287 bool changed = false; 01288 01289 // For all points in the generator system, check for eps-redundancy 01290 // and eventually move them to the bottom part of the system. 01291 Generator_System& gs = const_cast<Generator_System&>(gen_sys); 01292 Bit_Matrix& sat = const_cast<Bit_Matrix&>(sat_c); 01293 dimension_type gs_rows = gs.num_rows(); 01294 const dimension_type n_lines = gs.num_lines(); 01295 const dimension_type eps_index = gs.num_columns() - 1; 01296 for (dimension_type i = n_lines; i < gs_rows; ) 01297 if (gs[i].is_point()) { 01298 // Compute the Bit_Row corresponding to the candidate point 01299 // when strict inequality constraints are ignored. 01300 Bit_Row sat_gi; 01301 set_union(sat[i], sat_all_but_strict_ineq, sat_gi); 01302 // Check if the candidate point is actually eps-redundant: 01303 // namely, if there exists another point that saturates 01304 // all the non-strict inequalities saturated by the candidate. 01305 bool eps_redundant = false; 01306 for (dimension_type j = n_lines; j < gs_rows; ++j) 01307 if (i != j && gs[j].is_point() && subset_or_equal(sat[j], sat_gi)) { 01308 // Point `gs[i]' is eps-redundant: 01309 // move it to the bottom of the generator system, 01310 // while keeping `sat_c' consistent. 01311 --gs_rows; 01312 std::swap(gs[i], gs[gs_rows]); 01313 std::swap(sat[i], sat[gs_rows]); 01314 eps_redundant = true; 01315 changed = true; 01316 break; 01317 } 01318 if (!eps_redundant) { 01319 // Let all point encodings have epsilon coordinate 1. 01320 Generator& gi = gs[i]; 01321 if (gi[eps_index] != gi[0]) { 01322 gi[eps_index] = gi[0]; 01323 // Enforce normalization. 01324 gi.normalize(); 01325 changed = true; 01326 } 01327 // Consider next generator. 01328 ++i; 01329 } 01330 } 01331 else 01332 // Consider next generator. 01333 ++i; 01334 01335 // If needed, erase the eps-redundant generators (also updating 01336 // `index_first_pending'). 01337 if (gs_rows < gs.num_rows()) { 01338 gs.erase_to_end(gs_rows); 01339 gs.unset_pending_rows(); 01340 } 01341 01342 if (changed) { 01343 // The generator system is no longer sorted. 01344 x.gen_sys.set_sorted(false); 01345 // The constraint system is no longer up-to-date. 01346 x.clear_constraints_up_to_date(); 01347 } 01348 01349 assert(OK()); 01350 return true; 01351 }
Constraint_System Parma_Polyhedra_Library::Polyhedron::simplified_constraints | ( | ) | const [inline, private] |
If constraints are up-to-date, obtain a simplified copy of them.
Definition at line 345 of file Polyhedron.inlines.hh.
References con_sys, constraints_are_minimized(), constraints_are_up_to_date(), has_pending_constraints(), Parma_Polyhedra_Library::Linear_System::num_pending_rows(), Parma_Polyhedra_Library::Constraint_System::simplify(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
Referenced by Parma_Polyhedra_Library::Box< ITV >::Box().
00345 { 00346 assert(constraints_are_up_to_date()); 00347 Constraint_System cs(con_sys); 00348 if (cs.num_pending_rows() > 0) 00349 cs.unset_pending_rows(); 00350 if (has_pending_constraints() || !constraints_are_minimized()) 00351 cs.simplify(); 00352 return cs; 00353 }
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 333 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::Matrix::num_rows(), obtain_sorted_constraints(), obtain_sorted_generators(), space_dim, topology(), TVB_DONT_KNOW, TVB_FALSE, and TVB_TRUE.
Referenced by contains().
00333 { 00334 // Private method: the caller must ensure the following. 00335 assert(topology() == y.topology()); 00336 assert(space_dim == y.space_dim); 00337 assert(!marked_empty() && !y.marked_empty() && space_dim > 0); 00338 00339 const Polyhedron& x = *this; 00340 00341 if (x.is_necessarily_closed()) { 00342 if (!x.has_something_pending() && !y.has_something_pending()) { 00343 bool css_normalized = false; 00344 if (x.constraints_are_minimized() && y.constraints_are_minimized()) { 00345 // Equivalent minimized constraint systems have: 00346 // - the same number of constraints; ... 00347 if (x.con_sys.num_rows() != y.con_sys.num_rows()) 00348 return Polyhedron::TVB_FALSE; 00349 // - the same number of equalities; ... 00350 dimension_type x_num_equalities = x.con_sys.num_equalities(); 00351 if (x_num_equalities != y.con_sys.num_equalities()) 00352 return Polyhedron::TVB_FALSE; 00353 // - if there are no equalities, they have the same constraints. 00354 // Delay this test: try cheaper tests on generators first. 00355 css_normalized = (x_num_equalities == 0); 00356 } 00357 00358 if (x.generators_are_minimized() && y.generators_are_minimized()) { 00359 // Equivalent minimized generator systems have: 00360 // - the same number of generators; ... 00361 if (x.gen_sys.num_rows() != y.gen_sys.num_rows()) 00362 return Polyhedron::TVB_FALSE; 00363 // - the same number of lines; ... 00364 const dimension_type x_num_lines = x.gen_sys.num_lines(); 00365 if (x_num_lines != y.gen_sys.num_lines()) 00366 return Polyhedron::TVB_FALSE; 00367 // - if there are no lines, they have the same generators. 00368 if (x_num_lines == 0) { 00369 // Sort the two systems and check for syntactic identity. 00370 x.obtain_sorted_generators(); 00371 y.obtain_sorted_generators(); 00372 if (x.gen_sys == y.gen_sys) 00373 return Polyhedron::TVB_TRUE; 00374 else 00375 return Polyhedron::TVB_FALSE; 00376 } 00377 } 00378 00379 if (css_normalized) { 00380 // Sort the two systems and check for identity. 00381 x.obtain_sorted_constraints(); 00382 y.obtain_sorted_constraints(); 00383 if (x.con_sys == y.con_sys) 00384 return Polyhedron::TVB_TRUE; 00385 else 00386 return Polyhedron::TVB_FALSE; 00387 } 00388 } 00389 } 00390 return Polyhedron::TVB_DONT_KNOW; 00391 }
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 394 of file Polyhedron_nonpublic.cc.
References 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::Matrix::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::Generator::type(), Parma_Polyhedra_Library::Constraint::type(), and update_constraints().
Referenced by contains().
00394 { 00395 // Private method: the caller must ensure the following. 00396 assert(topology() == y.topology()); 00397 assert(space_dim == y.space_dim); 00398 assert(!marked_empty() && !y.marked_empty() && space_dim > 0); 00399 00400 const Polyhedron& x = *this; 00401 00402 // `x' cannot have pending constraints, because we need its generators. 00403 if (x.has_pending_constraints() && !x.process_pending_constraints()) 00404 return true; 00405 // `y' cannot have pending generators, because we need its constraints. 00406 if (y.has_pending_generators()) 00407 y.process_pending_generators(); 00408 00409 #if BE_LAZY 00410 if (!x.generators_are_up_to_date() && !x.update_generators()) 00411 return true; 00412 if (!y.constraints_are_up_to_date()) 00413 y.update_constraints(); 00414 #else 00415 if (!x.generators_are_minimized()) 00416 x.minimize(); 00417 if (!y.constraints_are_minimized()) 00418 y.minimize(); 00419 #endif 00420 00421 assert(x.OK()); 00422 assert(y.OK()); 00423 00424 const Generator_System& gs = x.gen_sys; 00425 const Constraint_System& cs = y.con_sys; 00426 00427 if (x.is_necessarily_closed()) 00428 // When working with necessarily closed polyhedra, 00429 // `x' is contained in `y' if and only if all the generators of `x' 00430 // satisfy all the inequalities and saturate all the equalities of `y'. 00431 // This comes from the definition of a polyhedron as the set of 00432 // vectors satisfying a constraint system and the fact that all 00433 // vectors in `x' can be obtained by suitably combining its generators. 00434 for (dimension_type i = cs.num_rows(); i-- > 0; ) { 00435 const Constraint& c = cs[i]; 00436 if (c.is_inequality()) { 00437 for (dimension_type j = gs.num_rows(); j-- > 0; ) { 00438 const Generator& g = gs[j]; 00439 const int sp_sign = Scalar_Products::sign(c, g); 00440 if (g.is_line()) { 00441 if (sp_sign != 0) 00442 return false; 00443 } 00444 else 00445 // `g' is a ray or a point. 00446 if (sp_sign < 0) 00447 return false; 00448 } 00449 } 00450 else { 00451 // `c' is an equality. 00452 for (dimension_type j = gs.num_rows(); j-- > 0; ) 00453 if (Scalar_Products::sign(c, gs[j]) != 0) 00454 return false; 00455 } 00456 } 00457 else { 00458 // Here we have an NNC polyhedron: using the reduced scalar product, 00459 // which ignores the epsilon coefficient. 00460 for (dimension_type i = cs.num_rows(); i-- > 0; ) { 00461 const Constraint& c = cs[i]; 00462 switch (c.type()) { 00463 case Constraint::NONSTRICT_INEQUALITY: 00464 for (dimension_type j = gs.num_rows(); j-- > 0; ) { 00465 const Generator& g = gs[j]; 00466 const int sp_sign = Scalar_Products::reduced_sign(c, g); 00467 if (g.is_line()) { 00468 if (sp_sign != 0) 00469 return false; 00470 } 00471 else 00472 // `g' is a ray or a point or a closure point. 00473 if (sp_sign < 0) 00474 return false; 00475 } 00476 break; 00477 case Constraint::EQUALITY: 00478 for (dimension_type j = gs.num_rows(); j-- > 0; ) 00479 if (Scalar_Products::reduced_sign(c, gs[j]) != 0) 00480 return false; 00481 break; 00482 case Constraint::STRICT_INEQUALITY: 00483 for (dimension_type j = gs.num_rows(); j-- > 0; ) { 00484 const Generator& g = gs[j]; 00485 const int sp_sign = Scalar_Products::reduced_sign(c, g); 00486 switch (g.type()) { 00487 case Generator::POINT: 00488 // If a point violates or saturates a strict inequality 00489 // (when ignoring the epsilon coefficients) then it is 00490 // not included in the polyhedron. 00491 if (sp_sign <= 0) 00492 return false; 00493 break; 00494 case Generator::LINE: 00495 // Lines have to saturate all constraints. 00496 if (sp_sign != 0) 00497 return false; 00498 break; 00499 case Generator::RAY: 00500 // Intentionally fall through. 00501 case Generator::CLOSURE_POINT: 00502 // The generator is a ray or closure point: usual test. 00503 if (sp_sign < 0) 00504 return false; 00505 break; 00506 } 00507 } 00508 break; 00509 } 00510 } 00511 } 00512 00513 // Inclusion holds. 00514 return true; 00515 }
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
.
expr | The linear expression to test; | |
from_above | true if and only if the boundedness of interest is "from above". |
std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
Definition at line 518 of file Polyhedron_nonpublic.cc.
References gen_sys, generators_are_up_to_date(), has_pending_constraints(), Parma_Polyhedra_Library::Scalar_Products::homogeneous_sign(), Parma_Polyhedra_Library::Generator::is_line(), Parma_Polyhedra_Library::Generator::is_line_or_ray(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_rows(), process_pending_constraints(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and update_generators().
Referenced by bounds_from_above(), and bounds_from_below().
00519 { 00520 // The dimension of `expr' should not be greater than the dimension 00521 // of `*this'. 00522 const dimension_type expr_space_dim = expr.space_dimension(); 00523 if (space_dim < expr_space_dim) 00524 throw_dimension_incompatible((from_above 00525 ? "bounds_from_above(e)" 00526 : "bounds_from_below(e)"), "e", expr); 00527 00528 // A zero-dimensional or empty polyhedron bounds everything. 00529 if (space_dim == 0 00530 || marked_empty() 00531 || (has_pending_constraints() && !process_pending_constraints()) 00532 || (!generators_are_up_to_date() && !update_generators())) 00533 return true; 00534 00535 // The polyhedron has updated, possibly pending generators. 00536 for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) { 00537 const Generator& g = gen_sys[i]; 00538 // Only lines and rays in `*this' can cause `expr' to be unbounded. 00539 if (g.is_line_or_ray()) { 00540 const int sp_sign = Scalar_Products::homogeneous_sign(expr, g); 00541 if (sp_sign != 0 00542 && (g.is_line() 00543 || (from_above && sp_sign > 0) 00544 || (!from_above && sp_sign < 0))) 00545 // `*this' does not bound `expr'. 00546 return false; 00547 } 00548 } 00549 // No sources of unboundedness have been found for `expr' 00550 // in the given direction. 00551 return true; 00552 }
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
.
expr | The linear expression to be maximized or minimized subject to this ; | |
maximize | true if maximization is what is wanted; | |
ext_n | The numerator of the extremum value; | |
ext_d | The denominator of the extremum value; | |
included | true if and only if the extremum of expr can actually be reached in * this; | |
g | When maximization or minimization succeeds, will be assigned a point or closure point where expr reaches the corresponding extremum value. |
std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
*this
is empty or expr
is not bounded in the appropriate direction, false
is returned and ext_n
, ext_d
, included
and g
are left untouched.
Definition at line 555 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::assign_r(), gen_sys, generators_are_up_to_date(), has_pending_constraints(), 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(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_rows(), process_pending_constraints(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), TEMP_INTEGER, throw_dimension_incompatible(), and update_generators().
Referenced by maximize(), and minimize().
00559 { 00560 // The dimension of `expr' should not be greater than the dimension 00561 // of `*this'. 00562 const dimension_type expr_space_dim = expr.space_dimension(); 00563 if (space_dim < expr_space_dim) 00564 throw_dimension_incompatible((maximize 00565 ? "maximize(e, ...)" 00566 : "minimize(e, ...)"), "e", expr); 00567 00568 // Deal with zero-dim polyhedra first. 00569 if (space_dim == 0) { 00570 if (marked_empty()) 00571 return false; 00572 else { 00573 ext_n = expr.inhomogeneous_term(); 00574 ext_d = 1; 00575 included = true; 00576 g = point(); 00577 return true; 00578 } 00579 } 00580 00581 // For an empty polyhedron we simply return false. 00582 if (marked_empty() 00583 || (has_pending_constraints() && !process_pending_constraints()) 00584 || (!generators_are_up_to_date() && !update_generators())) 00585 return false; 00586 00587 // The polyhedron has updated, possibly pending generators. 00588 // The following loop will iterate through the generator 00589 // to find the extremum. 00590 DIRTY_TEMP0(mpq_class, extremum); 00591 00592 // True if we have no other candidate extremum to compare with. 00593 bool first_candidate = true; 00594 00595 // To store the position of the current candidate extremum. 00596 PPL_UNINITIALIZED(dimension_type, ext_position); 00597 00598 // Whether the current candidate extremum is included or not. 00599 PPL_UNINITIALIZED(bool, ext_included); 00600 00601 TEMP_INTEGER(sp); 00602 for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) { 00603 const Generator& gen_sys_i = gen_sys[i]; 00604 Scalar_Products::homogeneous_assign(sp, expr, gen_sys_i); 00605 // Lines and rays in `*this' can cause `expr' to be unbounded. 00606 if (gen_sys_i.is_line_or_ray()) { 00607 const int sp_sign = sgn(sp); 00608 if (sp_sign != 0 00609 && (gen_sys_i.is_line() 00610 || (maximize && sp_sign > 0) 00611 || (!maximize && sp_sign < 0))) 00612 // `expr' is unbounded in `*this'. 00613 return false; 00614 } 00615 else { 00616 // We have a point or a closure point. 00617 assert(gen_sys_i.is_point() || gen_sys_i.is_closure_point()); 00618 // Notice that we are ignoring the constant term in `expr' here. 00619 // We will add it to the extremum as soon as we find it. 00620 DIRTY_TEMP0(mpq_class, candidate); 00621 assign_r(candidate.get_num(), sp, ROUND_NOT_NEEDED); 00622 assign_r(candidate.get_den(), gen_sys_i[0], ROUND_NOT_NEEDED); 00623 candidate.canonicalize(); 00624 const bool g_is_point = gen_sys_i.is_point(); 00625 if (first_candidate 00626 || (maximize 00627 && (candidate > extremum 00628 || (g_is_point 00629 && !ext_included 00630 && candidate == extremum))) 00631 || (!maximize 00632 && (candidate < extremum 00633 || (g_is_point 00634 && !ext_included 00635 && candidate == extremum)))) { 00636 // We have a (new) candidate extremum. 00637 first_candidate = false; 00638 extremum = candidate; 00639 ext_position = i; 00640 ext_included = g_is_point; 00641 } 00642 } 00643 } 00644 00645 // Add in the constant term in `expr'. 00646 DIRTY_TEMP0(mpz_class, n); 00647 assign_r(n, expr.inhomogeneous_term(), ROUND_NOT_NEEDED); 00648 extremum += n; 00649 00650 // The polyhedron is bounded in the right direction and we have 00651 // computed the extremum: write the result into the caller's structures. 00652 assert(!first_candidate); 00653 ext_n = Coefficient(extremum.get_num()); 00654 ext_d = Coefficient(extremum.get_den()); 00655 included = ext_included; 00656 g = gen_sys[ext_position]; 00657 00658 return true; 00659 }
void Parma_Polyhedra_Library::Polyhedron::select_CH78_constraints | ( | const Polyhedron & | y, | |
Constraint_System & | cs_selected | |||
) | 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 39 of file Polyhedron_widenings.cc.
References con_sys, constraints_are_minimized(), gen_sys, generators_are_up_to_date(), has_pending_constraints(), has_something_pending(), Parma_Polyhedra_Library::Constraint_System::insert(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Generator_System::satisfied_by_all_generators(), space_dim, Parma_Polyhedra_Library::Linear_System::topology(), and topology().
Referenced by H79_widening_assign().
00040 { 00041 // Private method: the caller must ensure the following conditions. 00042 assert(topology() == y.topology() 00043 && topology() == cs_selection.topology() 00044 && space_dim == y.space_dim); 00045 assert(!marked_empty() 00046 && !has_pending_constraints() 00047 && generators_are_up_to_date()); 00048 assert(!y.marked_empty() 00049 && !y.has_something_pending() 00050 && y.constraints_are_minimized()); 00051 00052 // A constraint in `y.con_sys' is copied to `cs_selection' 00053 // if it is satisfied by all the generators of `gen_sys'. 00054 00055 // Note: the loop index `i' goes upward to avoid reversing 00056 // the ordering of the chosen constraints. 00057 for (dimension_type i = 0, end = y.con_sys.num_rows(); i < end; ++i) { 00058 const Constraint& c = y.con_sys[i]; 00059 if (gen_sys.satisfied_by_all_generators(c)) 00060 cs_selection.insert(c); 00061 } 00062 }
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 66 of file Polyhedron_widenings.cc.
References Parma_Polyhedra_Library::Bit_Row::clear(), con_sys, constraints_are_minimized(), constraints_are_up_to_date(), gen_sys, generators_are_up_to_date(), has_pending_generators(), has_something_pending(), Parma_Polyhedra_Library::Constraint_System::insert(), is_necessarily_closed(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Bit_Matrix::rows_erase_to_end(), 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::swap(), Parma_Polyhedra_Library::Linear_System::topology(), topology(), update_generators(), and update_sat_g().
Referenced by BHRZ03_widening_assign(), and H79_widening_assign().
00068 { 00069 // Private method: the caller must ensure the following conditions 00070 // (beside the inclusion `y <= x'). 00071 assert(topology() == y.topology() 00072 && topology() == cs_selected.topology() 00073 && topology() == cs_not_selected.topology()); 00074 assert(space_dim == y.space_dim); 00075 assert(!marked_empty() 00076 && !has_pending_generators() 00077 && constraints_are_up_to_date()); 00078 assert(!y.marked_empty() 00079 && !y.has_something_pending() 00080 && y.constraints_are_minimized() 00081 && y.generators_are_up_to_date()); 00082 00083 // FIXME: this is a workaround for NNC polyhedra. 00084 if (!y.is_necessarily_closed()) { 00085 // Force strong minimization of constraints. 00086 y.strongly_minimize_constraints(); 00087 // Recompute generators (without compromising constraint minimization). 00088 y.update_generators(); 00089 } 00090 00091 // Obtain a sorted copy of `y.sat_g'. 00092 if (!y.sat_g_is_up_to_date()) 00093 y.update_sat_g(); 00094 Bit_Matrix tmp_sat_g = y.sat_g; 00095 // Remove from `tmp_sat_g' the rows corresponding to tautologies 00096 // (i.e., the positivity or epsilon-bounding constraints): 00097 // this is needed in order to widen the polyhedron and not the 00098 // corresponding homogenized polyhedral cone. 00099 const Constraint_System& y_cs = y.con_sys; 00100 dimension_type num_rows = y_cs.num_rows(); 00101 for (dimension_type i = 0; i < num_rows; ++i) 00102 if (y_cs[i].is_tautological()) { 00103 --num_rows; 00104 std::swap(tmp_sat_g[i], tmp_sat_g[num_rows]); 00105 } 00106 tmp_sat_g.rows_erase_to_end(num_rows); 00107 tmp_sat_g.sort_rows(); 00108 00109 // A constraint in `con_sys' is copied to `cs_selected' 00110 // if its behavior with respect to `y.gen_sys' is the same 00111 // as that of another constraint in `y.con_sys'. 00112 // otherwise it is copied to `cs_not_selected'. 00113 // Namely, we check whether the saturation row `buffer' 00114 // (built starting from the given constraint and `y.gen_sys') 00115 // is a row of the saturation matrix `tmp_sat_g'. 00116 00117 // CHECKME: the following comment is only applicable when `y.gen_sys' 00118 // is minimized. In that case, the comment suggests that it would be 00119 // possible to use a fast (but incomplete) redundancy test based on 00120 // the number of saturators in `buffer'. 00121 // NOTE: If the considered constraint of `con_sys' does not 00122 // satisfy the saturation rule (see Section \ref prelims), then 00123 // it will not appear in the resulting constraint system, 00124 // because `tmp_sat_g' is built starting from a minimized polyhedron. 00125 00126 // The size of `buffer' will reach sat.num_columns() bits. 00127 Bit_Row buffer; 00128 // Note: the loop index `i' goes upward to avoid reversing 00129 // the ordering of the chosen constraints. 00130 for (dimension_type i = 0, end = con_sys.num_rows(); i < end; ++i) { 00131 const Constraint& ci = con_sys[i]; 00132 // The saturation row `buffer' is built considering 00133 // the `i'-th constraint of the polyhedron `x' and 00134 // all the generators of the polyhedron `y'. 00135 buffer.clear(); 00136 for (dimension_type j = y.gen_sys.num_rows(); j-- > 0; ) { 00137 const int sp_sgn = Scalar_Products::sign(ci, y.gen_sys[j]); 00138 // We are assuming that `y <= x'. 00139 assert(sp_sgn >= 0 00140 || (!is_necessarily_closed() 00141 && ci.is_strict_inequality() 00142 && y.gen_sys[j].is_point())); 00143 if (sp_sgn > 0) 00144 buffer.set(j); 00145 } 00146 // We check whether `buffer' is a row of `tmp_sat_g', 00147 // exploiting its sortedness in order to have faster comparisons. 00148 if (tmp_sat_g.sorted_contains(buffer)) 00149 cs_selected.insert(ci); 00150 else 00151 cs_not_selected.insert(ci); 00152 } 00153 }
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_con_sys | |||
) | [private] |
Definition at line 384 of file Polyhedron_widenings.cc.
References add_recycled_constraints(), Parma_Polyhedra_Library::Linear_Row::all_homogeneous_terms_are_zero(), 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(), marked_empty(), minimize(), Parma_Polyhedra_Library::Matrix::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::swap(), Parma_Polyhedra_Library::Linear_System::topology(), and topology().
Referenced by BHRZ03_widening_assign().
00387 { 00388 Polyhedron& x = *this; 00389 // It is assumed that `y <= x <= H79'. 00390 assert(x.topology() == y.topology() 00391 && x.topology() == H79.topology() 00392 && x.topology() == x_minus_H79_cs.topology()); 00393 assert(x.space_dim == y.space_dim 00394 && x.space_dim == H79.space_dim 00395 && x.space_dim == x_minus_H79_cs.space_dimension()); 00396 assert(!x.marked_empty() && !x.has_something_pending() 00397 && x.constraints_are_minimized() && x.generators_are_minimized()); 00398 assert(!y.marked_empty() && !y.has_something_pending() 00399 && y.constraints_are_minimized() && y.generators_are_minimized()); 00400 assert(!H79.marked_empty() && !H79.has_something_pending() 00401 && H79.constraints_are_minimized() && H79.generators_are_minimized()); 00402 00403 // We will choose from `x_minus_H79_cs' many subsets of constraints, 00404 // that will be collected (one at a time) in `combining_cs'. 00405 // For each group collected, we compute an average constraint, 00406 // that will be stored in `new_cs'. 00407 00408 // There is no point in applying this technique when `x_minus_H79_cs' 00409 // has one constraint at most (no ``new'' constraint can be computed). 00410 const dimension_type x_minus_H79_cs_num_rows = x_minus_H79_cs.num_rows(); 00411 if (x_minus_H79_cs_num_rows <= 1) 00412 return false; 00413 00414 const Topology topol = x.topology(); 00415 Constraint_System combining_cs(topol); 00416 Constraint_System new_cs(topol); 00417 00418 // Consider the points that belong to both `x.gen_sys' and `y.gen_sys'. 00419 // For NNC polyhedra, the role of points is played by closure points. 00420 const bool closed = x.is_necessarily_closed(); 00421 for (dimension_type i = y.gen_sys.num_rows(); i-- > 0; ) { 00422 const Generator& g = y.gen_sys[i]; 00423 if ((g.is_point() && closed) || (g.is_closure_point() && !closed)) { 00424 // If in `H79.con_sys' there is already an inequality constraint 00425 // saturating this point, then there is no need to produce another 00426 // constraint. 00427 bool lies_on_the_boundary_of_H79 = false; 00428 const Constraint_System& H79_cs = H79.con_sys; 00429 for (dimension_type j = H79_cs.num_rows(); j-- > 0; ) { 00430 const Constraint& c = H79_cs[j]; 00431 if (c.is_inequality() && Scalar_Products::sign(c, g) == 0) { 00432 lies_on_the_boundary_of_H79 = true; 00433 break; 00434 } 00435 } 00436 if (lies_on_the_boundary_of_H79) 00437 continue; 00438 00439 // Consider all the constraints in `x_minus_H79_cs' 00440 // that are saturated by the point `g'. 00441 combining_cs.clear(); 00442 for (dimension_type j = x_minus_H79_cs_num_rows; j-- > 0; ) { 00443 const Constraint& c = x_minus_H79_cs[j]; 00444 if (Scalar_Products::sign(c, g) == 0) 00445 combining_cs.insert(c); 00446 } 00447 // Build a new constraint by combining all the chosen constraints. 00448 const dimension_type combining_cs_num_rows = combining_cs.num_rows(); 00449 if (combining_cs_num_rows > 0) { 00450 if (combining_cs_num_rows == 1) 00451 // No combination is needed. 00452 new_cs.insert(combining_cs[0]); 00453 else { 00454 Linear_Expression e(0); 00455 bool strict_inequality = false; 00456 for (dimension_type h = combining_cs_num_rows; h-- > 0; ) { 00457 if (combining_cs[h].is_strict_inequality()) 00458 strict_inequality = true; 00459 e += Linear_Expression(combining_cs[h]); 00460 } 00461 00462 if (!e.all_homogeneous_terms_are_zero()) { 00463 if (strict_inequality) 00464 new_cs.insert(e > 0); 00465 else 00466 new_cs.insert(e >= 0); 00467 } 00468 } 00469 } 00470 } 00471 } 00472 00473 // If none of the collected constraints strictly intersects `H79', 00474 // then the technique was unsuccessful. 00475 bool improves_upon_H79 = false; 00476 const Poly_Con_Relation si = Poly_Con_Relation::strictly_intersects(); 00477 for (dimension_type i = new_cs.num_rows(); i-- > 0; ) 00478 if (H79.relation_with(new_cs[i]) == si) { 00479 improves_upon_H79 = true; 00480 break; 00481 } 00482 if (!improves_upon_H79) 00483 return false; 00484 00485 // The resulting polyhedron is obtained by adding the constraints 00486 // in `new_cs' to polyhedron `H79'. 00487 Polyhedron result = H79; 00488 result.add_recycled_constraints(new_cs); 00489 // Force minimization. 00490 result.minimize(); 00491 00492 // Check for stabilization with respect to `y_cert' and improvement 00493 // over `H79'. 00494 if (y_cert.is_stabilizing(result) && !result.contains(H79)) { 00495 // The technique was successful. 00496 std::swap(x, result); 00497 assert(x.OK(true)); 00498 return true; 00499 } 00500 else 00501 // The technique was unsuccessful. 00502 return false; 00503 }
bool Parma_Polyhedra_Library::Polyhedron::BHRZ03_evolving_points | ( | const Polyhedron & | y, | |
const BHRZ03_Certificate & | y_cert, | |||
const Polyhedron & | H79 | |||
) | [private] |
Definition at line 506 of file Polyhedron_widenings.cc.
References add_recycled_generators(), 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::Linear_Row::linear_combine(), marked_empty(), minimize(), Parma_Polyhedra_Library::Poly_Gen_Relation::nothing(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), relation_with(), space_dim, Parma_Polyhedra_Library::swap(), and topology().
Referenced by BHRZ03_widening_assign().
00508 { 00509 Polyhedron& x = *this; 00510 // It is assumed that `y <= x <= H79'. 00511 assert(x.topology() == y.topology() 00512 && x.topology() == H79.topology()); 00513 assert(x.space_dim == y.space_dim 00514 && x.space_dim == H79.space_dim); 00515 assert(!x.marked_empty() && !x.has_something_pending() 00516 && x.constraints_are_minimized() && x.generators_are_minimized()); 00517 assert(!y.marked_empty() && !y.has_something_pending() 00518 && y.constraints_are_minimized() && y.generators_are_minimized()); 00519 assert(!H79.marked_empty() && !H79.has_something_pending() 00520 && H79.constraints_are_minimized() && H79.generators_are_minimized()); 00521 00522 // For each point in `x.gen_sys' that is not in `y', 00523 // this technique tries to identify a set of rays that: 00524 // - are included in polyhedron `H79'; 00525 // - when added to `y' will subsume the point. 00526 Generator_System candidate_rays; 00527 00528 const dimension_type x_gen_sys_num_rows = x.gen_sys.num_rows(); 00529 const dimension_type y_gen_sys_num_rows = y.gen_sys.num_rows(); 00530 const bool closed = x.is_necessarily_closed(); 00531 for (dimension_type i = x_gen_sys_num_rows; i-- > 0; ) { 00532 Generator& g1 = x.gen_sys[i]; 00533 // For C polyhedra, we choose a point of `x.gen_sys' 00534 // that is not included in `y'. 00535 // In the case of NNC polyhedra, we can restrict attention to 00536 // closure points (considering also points will only add redundancy). 00537 if (((g1.is_point() && closed) || (g1.is_closure_point() && !closed)) 00538 && y.relation_with(g1) == Poly_Gen_Relation::nothing()) { 00539 // For each point (resp., closure point) `g2' in `y.gen_sys', 00540 // where `g1' and `g2' are different, 00541 // build the candidate ray `g1 - g2'. 00542 for (dimension_type j = y_gen_sys_num_rows; j-- > 0; ) { 00543 const Generator& g2 = y.gen_sys[j]; 00544 if ((g2.is_point() && closed) 00545 || (g2.is_closure_point() && !closed)) { 00546 assert(compare(g1, g2) != 0); 00547 Generator ray_from_g2_to_g1 = g1; 00548 ray_from_g2_to_g1.linear_combine(g2, 0); 00549 candidate_rays.insert(ray_from_g2_to_g1); 00550 } 00551 } 00552 } 00553 } 00554 00555 // Be non-intrusive. 00556 Polyhedron result = x; 00557 result.add_recycled_generators(candidate_rays); 00558 result.intersection_assign(H79); 00559 // Force minimization. 00560 result.minimize(); 00561 00562 // Check for stabilization with respect to `y_cert' and improvement 00563 // over `H79'. 00564 if (y_cert.is_stabilizing(result) && !result.contains(H79)) { 00565 // The technique was successful. 00566 std::swap(x, result); 00567 assert(x.OK(true)); 00568 return true; 00569 } 00570 else 00571 // The technique was unsuccessful. 00572 return false; 00573 }
bool Parma_Polyhedra_Library::Polyhedron::BHRZ03_evolving_rays | ( | const Polyhedron & | y, | |
const BHRZ03_Certificate & | y_cert, | |||
const Polyhedron & | H79 | |||
) | [private] |
Definition at line 576 of file Polyhedron_widenings.cc.
References add_recycled_generators(), constraints_are_minimized(), contains(), gen_sys, generators_are_minimized(), Parma_Polyhedra_Library::Matrix::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(), marked_empty(), minimize(), Parma_Polyhedra_Library::Row::normalize(), Parma_Polyhedra_Library::Poly_Gen_Relation::nothing(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), relation_with(), space_dim, Parma_Polyhedra_Library::sub_mul_assign(), Parma_Polyhedra_Library::swap(), TEMP_INTEGER, and topology().
Referenced by BHRZ03_widening_assign().
00578 { 00579 Polyhedron& x = *this; 00580 // It is assumed that `y <= x <= H79'. 00581 assert(x.topology() == y.topology() 00582 && x.topology() == H79.topology()); 00583 assert(x.space_dim == y.space_dim 00584 && x.space_dim == H79.space_dim); 00585 assert(!x.marked_empty() && !x.has_something_pending() 00586 && x.constraints_are_minimized() && x.generators_are_minimized()); 00587 assert(!y.marked_empty() && !y.has_something_pending() 00588 && y.constraints_are_minimized() && y.generators_are_minimized()); 00589 assert(!H79.marked_empty() && !H79.has_something_pending() 00590 && H79.constraints_are_minimized() && H79.generators_are_minimized()); 00591 00592 const dimension_type x_gen_sys_num_rows = x.gen_sys.num_rows(); 00593 const dimension_type y_gen_sys_num_rows = y.gen_sys.num_rows(); 00594 00595 // Candidate rays are kept in a temporary generator system. 00596 Generator_System candidate_rays; 00597 TEMP_INTEGER(tmp); 00598 for (dimension_type i = x_gen_sys_num_rows; i-- > 0; ) { 00599 const Generator& x_g = x.gen_sys[i]; 00600 // We choose a ray of `x' that does not belong to `y'. 00601 if (x_g.is_ray() && y.relation_with(x_g) == Poly_Gen_Relation::nothing()) { 00602 for (dimension_type j = y_gen_sys_num_rows; j-- > 0; ) { 00603 const Generator& y_g = y.gen_sys[j]; 00604 if (y_g.is_ray()) { 00605 Generator new_ray(x_g); 00606 // Modify `new_ray' according to the evolution of `x_g' with 00607 // respect to `y_g'. 00608 std::deque<bool> considered(x.space_dim + 1); 00609 for (dimension_type k = 1; k < x.space_dim; ++k) 00610 if (!considered[k]) 00611 for (dimension_type h = k + 1; h <= x.space_dim; ++h) 00612 if (!considered[h]) { 00613 tmp = x_g[k] * y_g[h]; 00614 // The following line optimizes the computation of 00615 // tmp -= x_g[h] * y_g[k]; 00616 sub_mul_assign(tmp, x_g[h], y_g[k]); 00617 const int clockwise 00618 = sgn(tmp); 00619 const int first_or_third_quadrant 00620 = sgn(x_g[k]) * sgn(x_g[h]); 00621 switch (clockwise * first_or_third_quadrant) { 00622 case -1: 00623 new_ray[k] = 0; 00624 considered[k] = true; 00625 break; 00626 case 1: 00627 new_ray[h] = 0; 00628 considered[h] = true; 00629 break; 00630 default: 00631 break; 00632 } 00633 } 00634 new_ray.normalize(); 00635 candidate_rays.insert(new_ray); 00636 } 00637 } 00638 } 00639 } 00640 00641 // If there are no candidate rays, we cannot obtain stabilization. 00642 if (candidate_rays.has_no_rows()) 00643 return false; 00644 00645 // Be non-intrusive. 00646 Polyhedron result = x; 00647 result.add_recycled_generators(candidate_rays); 00648 result.intersection_assign(H79); 00649 // Force minimization. 00650 result.minimize(); 00651 00652 // Check for stabilization with respect to `y' and improvement over `H79'. 00653 if (y_cert.is_stabilizing(result) && !result.contains(H79)) { 00654 // The technique was successful. 00655 std::swap(x, result); 00656 assert(x.OK(true)); 00657 return true; 00658 } 00659 else 00660 // The technique was unsuccessful. 00661 return false; 00662 }
void Parma_Polyhedra_Library::Polyhedron::add_space_dimensions | ( | Linear_System & | mat1, | |
Linear_System & | mat2, | |||
Bit_Matrix & | sat1, | |||
Bit_Matrix & | sat2, | |||
dimension_type | add_dim | |||
) | [static, private] |
Adds new space dimensions to the given matrices.
mat1 | The matrix to which columns are added; | |
mat2 | The matrix to which rows and columns are added; | |
sat1 | The saturation matrix whose columns are indexed by the rows of matrix mat1 . On entry it is up-to-date; | |
sat2 | The saturation matrix whose columns are indexed by the rows of mat2 ; | |
add_dim | The number of space dimensions to add. |
add_space_dimensions_and_embed()
and add_space_dimensions_and_project()
, passing the matrix of constraints and that of generators (and the corresponding saturation matrices) in different order (see those methods for details).
Definition at line 35 of file Polyhedron_chdims.cc.
References Parma_Polyhedra_Library::Linear_System::add_rows_and_columns(), Parma_Polyhedra_Library::Matrix::add_zero_columns(), Parma_Polyhedra_Library::Linear_System::first_pending_row(), Parma_Polyhedra_Library::Linear_System::is_necessarily_closed(), Parma_Polyhedra_Library::Linear_System::is_sorted(), Parma_Polyhedra_Library::Bit_Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Bit_Matrix::num_rows(), Parma_Polyhedra_Library::Bit_Matrix::resize(), Parma_Polyhedra_Library::Linear_System::set_index_first_pending_row(), Parma_Polyhedra_Library::swap(), Parma_Polyhedra_Library::Matrix::swap_columns(), Parma_Polyhedra_Library::Linear_System::topology(), and Parma_Polyhedra_Library::Bit_Matrix::transpose_assign().
Referenced by add_space_dimensions_and_embed(), and add_space_dimensions_and_project().
00039 { 00040 assert(sys1.topology() == sys2.topology()); 00041 assert(sys1.num_columns() == sys2.num_columns()); 00042 assert(add_dim != 0); 00043 00044 sys1.add_zero_columns(add_dim); 00045 dimension_type old_index = sys2.first_pending_row(); 00046 sys2.add_rows_and_columns(add_dim); 00047 // The added rows are in the non-pending part. 00048 sys2.set_index_first_pending_row(old_index + add_dim); 00049 00050 // The resulting saturation matrix will be as follows: 00051 // from row 0 to add_dim-1 : only zeroes 00052 // add_dim add_dim+num_rows-1 : old saturation matrix 00053 00054 // In fact all the old generators saturate all the new constraints 00055 // because the polyhedron has not been embedded in the new space. 00056 sat1.resize(sat1.num_rows() + add_dim, sat1.num_columns()); 00057 // The old matrix is moved to the end of the new matrix. 00058 for (dimension_type i = sat1.num_rows() - add_dim; i-- > 0; ) 00059 std::swap(sat1[i], sat1[i+add_dim]); 00060 // Computes the "sat_c", too. 00061 sat2.transpose_assign(sat1); 00062 00063 if (!sys1.is_necessarily_closed()) { 00064 // Moving the epsilon coefficients to the new last column. 00065 dimension_type new_eps_index = sys1.num_columns() - 1; 00066 dimension_type old_eps_index = new_eps_index - add_dim; 00067 // This swap preserves sortedness of `sys1'. 00068 sys1.swap_columns(old_eps_index, new_eps_index); 00069 00070 // Try to preserve sortedness of `sys2'. 00071 if (!sys2.is_sorted()) 00072 sys2.swap_columns(old_eps_index, new_eps_index); 00073 else { 00074 for (dimension_type i = sys2.num_rows(); i-- > add_dim; ) { 00075 Linear_Row& r = sys2[i]; 00076 std::swap(r[old_eps_index], r[new_eps_index]); 00077 } 00078 // The upper-right corner of `sys2' contains the J matrix: 00079 // swap coefficients to preserve sortedness. 00080 for (dimension_type i = add_dim; i-- > 0; ++old_eps_index) { 00081 Linear_Row& r = sys2[i]; 00082 std::swap(r[old_eps_index], r[old_eps_index + 1]); 00083 } 00084 } 00085 // NOTE: since we swapped columns in both `sys1' and `sys2', 00086 // no swapping is required for `sat1' and `sat2'. 00087 } 00088 }
bool Parma_Polyhedra_Library::Polyhedron::minimize | ( | bool | con_to_gen, | |
Linear_System & | source, | |||
Linear_System & | dest, | |||
Bit_Matrix & | sat | |||
) | [static, private] |
Builds and simplifies constraints from generators (or vice versa).
true
if the polyhedron is empty, false
otherwise.con_to_gen | true if source represents the constraints, false otherwise; | |
source | The given system, which is not empty; | |
dest | The system to build and minimize; | |
sat | The 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 69 of file minimize.cc.
References conversion(), Parma_Polyhedra_Library::Matrix::has_no_rows(), Parma_Polyhedra_Library::Linear_System::is_necessarily_closed(), Parma_Polyhedra_Library::Linear_System::is_sorted(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Linear_System::resize_no_copy(), Parma_Polyhedra_Library::Linear_System::set_index_first_pending_row(), Parma_Polyhedra_Library::Linear_Row::set_is_line_or_equality(), Parma_Polyhedra_Library::Linear_System::set_sorted(), simplify(), Parma_Polyhedra_Library::Linear_System::sort_rows(), Parma_Polyhedra_Library::Linear_System::topology(), and Parma_Polyhedra_Library::Bit_Matrix::transpose_assign().
00072 { 00073 // Topologies have to agree. 00074 assert(source.topology() == dest.topology()); 00075 // `source' cannot be empty: even if it is an empty constraint system, 00076 // representing the universe polyhedron, homogenization has added 00077 // the positive constraint. It also cannot be an empty generator system, 00078 // since this function is always called starting from a non-empty 00079 // polyhedron. 00080 assert(!source.has_no_rows()); 00081 00082 // Sort the source system, if necessary. 00083 if (!source.is_sorted()) 00084 source.sort_rows(); 00085 00086 // Initialization of the system of generators `dest'. 00087 // The algorithm works incrementally and we haven't seen any 00088 // constraint yet: as a consequence, `dest' should describe 00089 // the universe polyhedron of the appropriate dimension. 00090 // To this end, we initialize it to the identity matrix of dimension 00091 // `source.num_columns()': the rows represent the lines corresponding 00092 // to the canonical basis of the vector space. 00093 00094 // Resizing `dest' to be the appropriate square matrix. 00095 dimension_type dest_num_rows = source.num_columns(); 00096 // Note that before calling `resize_no_copy()' we must update 00097 // `index_first_pending'. 00098 dest.set_index_first_pending_row(dest_num_rows); 00099 dest.resize_no_copy(dest_num_rows, dest_num_rows); 00100 00101 // Initialize `dest' to the identity matrix. 00102 for (dimension_type i = dest_num_rows; i-- > 0; ) { 00103 Linear_Row& dest_i = dest[i]; 00104 for (dimension_type j = dest_num_rows; j-- > 0; ) 00105 dest_i[j] = (i == j) ? 1 : 0; 00106 dest_i.set_is_line_or_equality(); 00107 } 00108 // The identity matrix `dest' is not sorted (see the sorting rules 00109 // in Linear_Row.cc). 00110 dest.set_sorted(false); 00111 00112 // NOTE: the system `dest', as it is now, is not a _legal_ system of 00113 // generators, because in the first row we have a line with a 00114 // non-zero divisor (which should only happen for 00115 // points). However, this is NOT a problem, because `source' 00116 // necessarily contains the positivity constraint (or a 00117 // combination of it with another constraint) which will 00118 // restore things as they should be. 00119 00120 00121 // Building a saturation matrix and initializing it by setting 00122 // all of its elements to zero. This matrix will be modified together 00123 // with `dest' during the conversion. 00124 // NOTE: since we haven't seen any constraint yet, the relevant 00125 // portion of `tmp_sat' is the sub-matrix consisting of 00126 // the first 0 columns: thus the relevant portion correctly 00127 // characterizes the initial saturation information. 00128 Bit_Matrix tmp_sat(dest_num_rows, source.num_rows()); 00129 00130 // By invoking the function conversion(), we populate `dest' with 00131 // the generators characterizing the polyhedron described by all 00132 // the constraints in `source'. 00133 // The `start' parameter is zero (we haven't seen any constraint yet) 00134 // and the 5th parameter (representing the number of lines in `dest'), 00135 // by construction, is equal to `dest_num_rows'. 00136 const dimension_type num_lines_or_equalities 00137 = conversion(source, 0, dest, tmp_sat, dest_num_rows); 00138 // conversion() may have modified the number of rows in `dest'. 00139 dest_num_rows = dest.num_rows(); 00140 00141 // Checking if the generators in `dest' represent an empty polyhedron: 00142 // the polyhedron is empty if there are no points 00143 // (because rays, lines and closure points need a supporting point). 00144 // Points can be detected by looking at: 00145 // - the divisor, for necessarily closed polyhedra; 00146 // - the epsilon coordinate, for NNC polyhedra. 00147 const dimension_type checking_index 00148 = dest.is_necessarily_closed() 00149 ? 0 00150 : dest.num_columns() - 1; 00151 dimension_type first_point; 00152 for (first_point = num_lines_or_equalities; 00153 first_point < dest_num_rows; 00154 ++first_point) 00155 if (dest[first_point][checking_index] > 0) 00156 break; 00157 00158 if (first_point == dest_num_rows) 00159 if (con_to_gen) 00160 // No point has been found: the polyhedron is empty. 00161 return true; 00162 else 00163 // Here `con_to_gen' is false: `dest' is a system of constraints. 00164 // In this case the condition `first_point == dest_num_rows' 00165 // actually means that all the constraints in `dest' have their 00166 // inhomogeneous term equal to 0. 00167 // This is an ILLEGAL situation, because it implies that 00168 // the constraint system `dest' lacks the positivity constraint 00169 // and no linear combination of the constraints in `dest' 00170 // can reintroduce the positivity constraint. 00171 throw std::runtime_error("PPL internal error"); 00172 else { 00173 // A point has been found: the polyhedron is not empty. 00174 // Now invoking simplify() to remove all the redundant constraints 00175 // from the system `source'. 00176 // Since the saturation matrix `tmp_sat' returned by conversion() 00177 // has rows indexed by generators (the rows of `dest') and columns 00178 // indexed by constraints (the rows of `source'), we have to 00179 // transpose it to obtain the saturation matrix needed by simplify(). 00180 sat.transpose_assign(tmp_sat); 00181 simplify(source, sat); 00182 return false; 00183 } 00184 }
bool Parma_Polyhedra_Library::Polyhedron::add_and_minimize | ( | bool | con_to_gen, | |
Linear_System & | source1, | |||
Linear_System & | dest, | |||
Bit_Matrix & | sat, | |||
const Linear_System & | source2 | |||
) | [static, private] |
Adds given constraints and builds minimized corresponding generators or vice versa.
true
if the obtained polyhedron is empty, false
otherwise.con_to_gen | true if source1 and source2 are system of constraints, false otherwise; | |
source1 | The first element of the given DD pair; | |
dest | The second element of the given DD pair; | |
sat | The saturation matrix that bind source1 to dest ; | |
source2 | The new system of generators or constraints. |
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&, Linear_System&, 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 233 of file minimize.cc.
References Parma_Polyhedra_Library::Linear_System::add_pending_row(), Parma_Polyhedra_Library::cmp(), Parma_Polyhedra_Library::Matrix::has_no_rows(), Parma_Polyhedra_Library::Linear_System::is_sorted(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Linear_System::num_pending_rows(), and Parma_Polyhedra_Library::Matrix::num_rows().
Referenced by add_recycled_generators_and_minimize(), intersection_assign_and_minimize(), poly_hull_assign_and_minimize(), process_pending_constraints(), and process_pending_generators().
00237 { 00238 // `source1' and `source2' cannot be empty. 00239 assert(!source1.has_no_rows() && !source2.has_no_rows()); 00240 // `source1' and `source2' must have the same number of columns 00241 // to be merged. 00242 assert(source1.num_columns() == source2.num_columns()); 00243 // `source1' and `source2' are fully sorted. 00244 assert(source1.is_sorted() && source1.num_pending_rows() == 0); 00245 assert(source2.is_sorted() && source2.num_pending_rows() == 0); 00246 assert(dest.num_pending_rows() == 0); 00247 00248 const dimension_type old_source1_num_rows = source1.num_rows(); 00249 // `k1' and `k2' run through the rows of `source1' and `source2', resp. 00250 dimension_type k1 = 0; 00251 dimension_type k2 = 0; 00252 dimension_type source2_num_rows = source2.num_rows(); 00253 while (k1 < old_source1_num_rows && k2 < source2_num_rows) { 00254 // Add to `source1' the constraints from `source2', as pending rows. 00255 // We exploit the property that initially both `source1' and `source2' 00256 // are sorted and index `k1' only scans the non-pending rows of `source1', 00257 // so that it is not influenced by the pending rows appended to it. 00258 // This way no duplicate (i.e., trivially redundant) constraint 00259 // is introduced in `source1'. 00260 const int cmp = compare(source1[k1], source2[k2]); 00261 if (cmp == 0) { 00262 // We found the same row: there is no need to add `source2[k2]'. 00263 ++k2; 00264 // By sortedness, since `k1 < old_source1_num_rows', 00265 // we can increment index `k1' too. 00266 ++k1; 00267 } 00268 else if (cmp < 0) 00269 // By sortedness, we can increment `k1'. 00270 ++k1; 00271 else { 00272 // Here `cmp > 0'. 00273 // By sortedness, `source2[k2]' cannot be in `source1'. 00274 // We add it as a pending row of `source1' (sortedness unaffected). 00275 source1.add_pending_row(source2[k2]); 00276 // We can increment `k2'. 00277 ++k2; 00278 } 00279 } 00280 // Have we scanned all the rows in `source2'? 00281 if (k2 < source2_num_rows) 00282 // By sortedness, all the rows in `source2' having indexes 00283 // greater than or equal to `k2' were not in `source1'. 00284 // We add them as pending rows of 'source1' (sortedness not affected). 00285 for ( ; k2 < source2_num_rows; ++k2) 00286 source1.add_pending_row(source2[k2]); 00287 00288 if (source1.num_pending_rows() == 0) 00289 // No row was appended to `source1', because all the constraints 00290 // in `source2' were already in `source1'. 00291 // There is nothing left to do ... 00292 return false; 00293 00294 return add_and_minimize(con_to_gen, source1, dest, sat); 00295 }
bool Parma_Polyhedra_Library::Polyhedron::add_and_minimize | ( | bool | con_to_gen, | |
Linear_System & | source, | |||
Linear_System & | dest, | |||
Bit_Matrix & | sat | |||
) | [static, private] |
Adds given constraints and builds minimized corresponding generators or vice versa. The given constraints are in source
.
true
if the obtained polyhedron is empty, false
otherwise.con_to_gen | true if source is a system of constraints, false otherwise; | |
source | The first element of the given DD pair. It also contains the pending rows to be processed; | |
dest | The second element of the given DD pair. It cannot have pending rows; | |
sat | The saturation matrix that bind the upper part of source to dest . |
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 334 of file minimize.cc.
References conversion(), Parma_Polyhedra_Library::Linear_System::first_pending_row(), Parma_Polyhedra_Library::Linear_System::is_necessarily_closed(), Parma_Polyhedra_Library::Linear_System::is_sorted(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Linear_System::num_lines_or_equalities(), Parma_Polyhedra_Library::Linear_System::num_pending_rows(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Bit_Matrix::resize(), and simplify().
00337 { 00338 assert(source.num_pending_rows() > 0); 00339 assert(source.num_columns() == dest.num_columns()); 00340 assert(source.is_sorted()); 00341 00342 // First, pad the saturation matrix with new columns (of zeroes) 00343 // to accommodate for the pending rows of `source'. 00344 sat.resize(dest.num_rows(), source.num_rows()); 00345 00346 // Incrementally compute the new system of generators. 00347 // Parameter `start' is set to the index of the first pending constraint. 00348 const dimension_type num_lines_or_equalities 00349 = conversion(source, source.first_pending_row(), 00350 dest, sat, 00351 dest.num_lines_or_equalities()); 00352 00353 // conversion() may have modified the number of rows in `dest'. 00354 const dimension_type dest_num_rows = dest.num_rows(); 00355 00356 // Checking if the generators in `dest' represent an empty polyhedron: 00357 // the polyhedron is empty if there are no points 00358 // (because rays, lines and closure points need a supporting point). 00359 // Points can be detected by looking at: 00360 // - the divisor, for necessarily closed polyhedra; 00361 // - the epsilon coordinate, for NNC polyhedra. 00362 const dimension_type checking_index 00363 = dest.is_necessarily_closed() 00364 ? 0 00365 : dest.num_columns() - 1; 00366 dimension_type first_point; 00367 for (first_point = num_lines_or_equalities; 00368 first_point < dest_num_rows; 00369 ++first_point) 00370 if (dest[first_point][checking_index] > 0) 00371 break; 00372 00373 if (first_point == dest_num_rows) 00374 if (con_to_gen) 00375 // No point has been found: the polyhedron is empty. 00376 return true; 00377 else 00378 // Here `con_to_gen' is false: `dest' is a system of constraints. 00379 // In this case the condition `first_point == dest_num_rows' 00380 // actually means that all the constraints in `dest' have their 00381 // inhomogeneous term equal to 0. 00382 // This is an ILLEGAL situation, because it implies that 00383 // the constraint system `dest' lacks the positivity constraint 00384 // and no linear combination of the constraints in `dest' 00385 // can reintroduce the positivity constraint. 00386 throw std::runtime_error("PPL internal error"); 00387 else { 00388 // A point has been found: the polyhedron is not empty. 00389 // Now invoking `simplify()' to remove all the redundant constraints 00390 // from the system `source'. 00391 // Since the saturation matrix `sat' returned by `conversion()' 00392 // has rows indexed by generators (the rows of `dest') and columns 00393 // indexed by constraints (the rows of `source'), we have to 00394 // transpose it to obtain the saturation matrix needed by `simplify()'. 00395 sat.transpose(); 00396 simplify(source, sat); 00397 // Transposing back. 00398 sat.transpose(); 00399 return false; 00400 } 00401 }
PPL::dimension_type Parma_Polyhedra_Library::Polyhedron::conversion | ( | Linear_System & | source, | |
dimension_type | start, | |||
Linear_System & | dest, | |||
Bit_Matrix & | sat, | |||
dimension_type | num_lines_or_equalities | |||
) | [static, private] |
Performs the conversion from constraints to generators and vice versa.
source | The system to use to convert dest: it may be modified; | |
start | The index of source row from which conversion begin; | |
dest | The result of the conversion; | |
sat | The 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_equalities | The 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). |
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 we have what is called a double description (or DD pair) for
.
Here, the representation system refers to the system whose rows represent the constraints that characterize
and the generating system, the system
whose rows represent the generators of
. We say that a pair
of (real) systems is a double description pair if
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 and we call
and
the systems of constraints and rays respectively, we have
Because of the theorem of Minkowski (see Section Further Notation and Terminology), we can say that, given a representation system
such that
for a non-empty polyhedron
, it is always possible to find a generating system
for
such that
is a DD pair. Conversely, Weyl's theorem ensures that, for each generating system
, it is possible to find a representation system
such that
is a DD pair.
For efficiency reasons, our representation of polyhedra makes use of a double description. We are thus left with two problems:
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 that, in a sense, captures the essence of duality. Consider a matrix
and let
be its set of row vectors. Consider also another vector
such that, whenever a vector
has a non-negative projection on the
's, it also has a non-negative projection on
. The lemma states that
has this property if and only if it is in the cone generated by the
's. Formally, the lemma states the equivalence of the two following assertions:
With this result we can prove that is a DD pair if and only if
is a DD pair.
Suppose is a DD pair. Thus, for each
of the appropriate dimension,
if and only if
, which is of course equivalent to
.
First, we assume that is such that
and we will show that
. Let
be such that
. Since
is a DD pair, this is equivalent to
, which, by Farkas' Lemma is equivalent to
. Taking
and recalling our assumption that
we can conclude that
, that is equivalent to
. We have thus established that
. By Farkas' Lemma, this is equivalent to
, which is equivalent to what we wanted to prove, that is,
.
In order to prove the reverse implication, the following observation turns out to be useful: when is a DD pair,
. In fact, let
be the vector whose components are all
apart from the
-th one, which is
. Clearly
and, taking
and
, we have
, since
is a DD pair. Thus, as
is the
-th column of
and since the choice of
was arbitrary,
.
We now assume that is such that
and we will prove that
. By Farkas' Lemma, the assumption
, is equivalent to
. If we take
then
, since
. So
, that is, the
-th component of
is non-negative. The arbitrary choice of
allows us to conclude that
, 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 be a system of constraints that generate the polyhedron
and
a new constraint that must be added. Suppose that there is a line
that does not saturate the constraint
. If we combine the old lines and rays that do not saturate
(except
) with
such that the new ones saturate
, the new lines and rays also saturate the constraints saturated by the old lines and rays.
In fact, if is the old generator that does not saturate
,
is the new one such that
and is a previous constraint that
and
saturates, we can see
and
Proposition 1: Let and
be distinct rays of
. Then the following statements are equivalent: a)
and
are adjacent extreme rays (see Section Further Notation and Terminology); b)
and
are extreme rays and the rank of the system composed by the constraints saturated by both
and
is equal to
, where
is the rank of the system of constraints.
In fact, let be the system of generators that saturate the constraints saturated by both
and
. If b) holds, the set
is 2-dimensional and
and
generate this set. So, every generator
of
can be built as a combination of
and
, i.e.
This combination is non-negative because there exists at least a constraint saturated by
and not
(or vice versa) (because they are distinct) for which
and
So, there is no other extreme ray in and a) holds. Otherwise, if b) does not hold, the rank of the system generated by the constraints saturated by both
and
is equal to
, with
k
>= 3, the set is
k
-dimensional and at least k
extreme rays are necessary to generate . So,
and
are not adjacent and a) does not hold.
Proposition 2: When we build the new system of generators starting from a system of constraints of
, if
is the constraint to add to
and all lines of
saturate
, the new set of rays is the union of those rays that saturate, of those that satisfy and of a set
of rays such that each of them
In fact, if and
are not adjacent, the rank of the system composed by the constraints saturated by both
and
is different from
(see the previous proposition) or neither
nor
are extreme rays. Since the new ray
is a combination of
and
, it saturates the same constraints saturated by both
and
. If the rank is less than
, the rank of the system composed by
(that is saturated by
) and by the constraints of
saturated by
is less than
. It means that
is redundant (see Section Further Notation and Terminology). If neither
nor
are extreme rays, they belong to a 2-dimensional face containing exactly two extreme rays of
. These two adjacent rays build a ray equal to
and so
is redundant.
Definition at line 352 of file conversion.cc.
References Parma_Polyhedra_Library::Linear_System::add_pending_row(), Parma_Polyhedra_Library::Bit_Matrix::add_row(), assign(), Parma_Polyhedra_Library::Coefficient_zero(), Parma_Polyhedra_Library::Bit_Matrix::columns_erase_to_end(), Parma_Polyhedra_Library::Bit_Row::count_ones(), Parma_Polyhedra_Library::Matrix::erase_to_end(), Parma_Polyhedra_Library::Linear_System::first_pending_row(), Parma_Polyhedra_Library::Linear_Row::is_ray_or_point_or_inequality(), Parma_Polyhedra_Library::Linear_System::is_sorted(), Parma_Polyhedra_Library::maybe_abandon(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::normalize2(), Parma_Polyhedra_Library::Bit_Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Bit_Matrix::num_rows(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Linear_Row::RAY_OR_POINT_OR_INEQUALITY, Parma_Polyhedra_Library::Bit_Matrix::rows_erase_to_end(), Parma_Polyhedra_Library::Bit_Row::set(), Parma_Polyhedra_Library::Linear_System::set_sorted(), Parma_Polyhedra_Library::Linear_Row::strong_normalize(), Parma_Polyhedra_Library::sub_mul_assign(), Parma_Polyhedra_Library::swap(), TEMP_INTEGER, Parma_Polyhedra_Library::Linear_System::topology(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
Referenced by add_and_minimize(), and minimize().
00356 { 00357 dimension_type source_num_rows = source.num_rows(); 00358 dimension_type dest_num_rows = dest.num_rows(); 00359 const dimension_type source_num_columns = source.num_columns(); 00360 const dimension_type dest_num_columns = dest.num_columns(); 00361 00362 // By construction, the number of columns of `sat' is the same as 00363 // the number of rows of `source'; also, the number of rows of `sat' 00364 // is the same as the number of rows of `dest'. 00365 assert(source_num_rows == sat.num_columns()); 00366 assert(dest_num_rows == sat.num_rows()); 00367 00368 // If `start > 0', then we are converting the pending constraints. 00369 assert(start == 0 || start == source.first_pending_row()); 00370 00371 // During the iteration on the constraints in `source' we may identify 00372 // constraints that are redundant: these have to be removed by swapping 00373 // the rows of `source', taking care not to compromise the sortedness 00374 // of the constraints that still have to be considered. 00375 // To this end, the following counter keeps the number of redundant 00376 // constraints seen so far, to be used as a displacement when swapping rows. 00377 dimension_type source_num_redundant = 0; 00378 00379 TEMP_INTEGER(normalized_sp_i); 00380 TEMP_INTEGER(normalized_sp_o); 00381 00382 // Converting the sub-system of `source' having rows with indexes 00383 // from `start' to the last one (i.e., `source_num_rows' - 1). 00384 for (dimension_type k = start; k < source_num_rows; ) { 00385 00386 // All the `source_num_redundant' redundant constraints identified so far 00387 // have consecutive indices starting from `k'. 00388 if (source_num_redundant > 0) 00389 // Let the next constraint have index `k'. 00390 // There is no need to swap the columns of `sat' (all zeroes). 00391 std::swap(source[k], source[k+source_num_redundant]); 00392 00393 Linear_Row& source_k = source[k]; 00394 00395 // Constraints and generators must have the same dimension, 00396 // otherwise the scalar product below will bomb. 00397 assert(source_num_columns == dest_num_columns); 00398 00399 // `scalar_prod[i]' will contain the scalar product of the 00400 // constraint `source_k' and the generator `dest[i]'. This 00401 // product is 0 if and only if the generator saturates the 00402 // constraint. 00403 DIRTY_TEMP0(std::vector<Coefficient>, scalar_prod); 00404 const int needed_space = dest_num_rows - scalar_prod.size(); 00405 if (needed_space > 0) 00406 scalar_prod.insert(scalar_prod.end(), needed_space, Coefficient_zero()); 00407 // `index_non_zero' will indicate the first generator in `dest' 00408 // that does not saturate the constraint `source_k'. 00409 dimension_type index_non_zero = 0; 00410 for ( ; index_non_zero < dest_num_rows; ++index_non_zero) { 00411 Scalar_Products::assign(scalar_prod[index_non_zero], 00412 source_k, 00413 dest[index_non_zero]); 00414 if (scalar_prod[index_non_zero] != 0) 00415 // The generator does not saturate the constraint. 00416 break; 00417 #if REACTIVE_ABANDONING 00418 // Check if the client has requested abandoning all expensive 00419 // computations. If so, the exception specified by the client 00420 // is thrown now. 00421 maybe_abandon(); 00422 #endif 00423 } 00424 for (dimension_type i = index_non_zero + 1; i < dest_num_rows; ++i) { 00425 Scalar_Products::assign(scalar_prod[i], source_k, dest[i]); 00426 #if REACTIVE_ABANDONING 00427 maybe_abandon(); 00428 #endif 00429 } 00430 00431 // We first treat the case when `index_non_zero' is less than 00432 // `num_lines_or_equalities', i.e., when the generator that 00433 // does not saturate the constraint `source_k' is a line. 00434 // The other case (described later) is when all the lines 00435 // in `dest' (i.e., all the rows having indexes less than 00436 // `num_lines_or_equalities') do saturate the constraint. 00437 00438 if (index_non_zero < num_lines_or_equalities) { 00439 // Since the generator `dest[index_non_zero]' does not saturate 00440 // the constraint `source_k', it can no longer be a line 00441 // (see saturation rule in Section \ref prelims). 00442 // Therefore, we first transform it to a ray. 00443 dest[index_non_zero].set_is_ray_or_point_or_inequality(); 00444 // Of the two possible choices, we select the ray satisfying 00445 // the constraint (namely, the ray whose scalar product 00446 // with the constraint gives a positive result). 00447 if (scalar_prod[index_non_zero] < 0) { 00448 // The ray `dest[index_non_zero]' lies on the wrong half-space: 00449 // we change it to have the opposite direction. 00450 neg_assign(scalar_prod[index_non_zero]); 00451 for (dimension_type j = dest_num_columns; j-- > 0; ) 00452 neg_assign(dest[index_non_zero][j]); 00453 } 00454 // Having changed a line to a ray, we set `dest' to be a 00455 // non-sorted system, we decrement the number of lines of `dest' and, 00456 // if necessary, we move the new ray below all the remaining lines. 00457 dest.set_sorted(false); 00458 --num_lines_or_equalities; 00459 if (index_non_zero != num_lines_or_equalities) { 00460 std::swap(dest[index_non_zero], 00461 dest[num_lines_or_equalities]); 00462 std::swap(scalar_prod[index_non_zero], 00463 scalar_prod[num_lines_or_equalities]); 00464 } 00465 Linear_Row& dest_nle = dest[num_lines_or_equalities]; 00466 00467 // Computing the new lineality space. 00468 // Since each line must lie on the hyper-plane corresponding to 00469 // the constraint `source_k', the scalar product between 00470 // the line and the constraint must be 0. 00471 // This property already holds for the lines having indexes 00472 // between 0 and `index_non_zero' - 1. 00473 // We have to consider the remaining lines, having indexes 00474 // between `index_non_zero' and `num_lines_or_equalities' - 1. 00475 // Each line that does not saturate the constraint has to be 00476 // linearly combined with generator `dest_nle' so that the 00477 // resulting new line saturates the constraint. 00478 // Note that, by Observation 1 above, the resulting new line 00479 // will still saturate all the constraints that were saturated by 00480 // the old line. 00481 00482 Coefficient& scalar_prod_nle = scalar_prod[num_lines_or_equalities]; 00483 for (dimension_type 00484 i = index_non_zero; i < num_lines_or_equalities; ++i) { 00485 if (scalar_prod[i] != 0) { 00486 // The following fragment optimizes the computation of 00487 // 00488 // Coefficient scale = scalar_prod[i]; 00489 // scale.gcd_assign(scalar_prod_nle); 00490 // Coefficient normalized_sp_i = scalar_prod[i] / scale; 00491 // Coefficient normalized_sp_n = scalar_prod_nle / scale; 00492 // for (dimension_type c = dest_num_columns; c-- > 0; ) { 00493 // dest[i][c] *= normalized_sp_n; 00494 // dest[i][c] -= normalized_sp_i * dest_nle[c]; 00495 // } 00496 normalize2(scalar_prod[i], 00497 scalar_prod_nle, 00498 normalized_sp_i, 00499 normalized_sp_o); 00500 Linear_Row& dest_i = dest[i]; 00501 for (dimension_type c = dest_num_columns; c-- > 0; ) { 00502 Coefficient& dest_i_c = dest_i[c]; 00503 dest_i_c *= normalized_sp_o; 00504 sub_mul_assign(dest_i_c, normalized_sp_i, dest_nle[c]); 00505 } 00506 dest_i.strong_normalize(); 00507 scalar_prod[i] = 0; 00508 // `dest' has already been set as non-sorted. 00509 } 00510 } 00511 00512 // Computing the new pointed cone. 00513 // Similarly to what we have done during the computation of 00514 // the lineality space, we consider all the remaining rays 00515 // (having indexes strictly greater than `num_lines_or_equalities') 00516 // that do not saturate the constraint `source_k'. These rays 00517 // are positively combined with the ray `dest_nle' so that the 00518 // resulting new rays saturate the constraint. 00519 for (dimension_type 00520 i = num_lines_or_equalities + 1; i < dest_num_rows; ++i) { 00521 if (scalar_prod[i] != 0) { 00522 // The following fragment optimizes the computation of 00523 // 00524 // Coefficient scale = scalar_prod[i]; 00525 // scale.gcd_assign(scalar_prod_nle); 00526 // Coefficient normalized_sp_i = scalar_prod[i] / scale; 00527 // Coefficient normalized_sp_n = scalar_prod_nle / scale; 00528 // for (dimension_type c = dest_num_columns; c-- > 0; ) { 00529 // dest[i][c] *= normalized_sp_n; 00530 // dest[i][c] -= normalized_sp_i * dest_nle[c]; 00531 // } 00532 normalize2(scalar_prod[i], 00533 scalar_prod_nle, 00534 normalized_sp_i, 00535 normalized_sp_o); 00536 Linear_Row& dest_i = dest[i]; 00537 for (dimension_type c = dest_num_columns; c-- > 0; ) { 00538 Coefficient& dest_i_c = dest_i[c]; 00539 dest_i_c *= normalized_sp_o; 00540 sub_mul_assign(dest_i_c, normalized_sp_i, dest_nle[c]); 00541 } 00542 dest_i.strong_normalize(); 00543 scalar_prod[i] = 0; 00544 // `dest' has already been set as non-sorted. 00545 } 00546 #if REACTIVE_ABANDONING 00547 maybe_abandon(); 00548 #endif 00549 } 00550 // Since the `scalar_prod_nle' is positive (by construction), it 00551 // does not saturate the constraint `source_k'. Therefore, if 00552 // the constraint is an inequality, we set to 1 the 00553 // corresponding element of `sat' ... 00554 Bit_Row& sat_nle = sat[num_lines_or_equalities]; 00555 if (source_k.is_ray_or_point_or_inequality()) 00556 sat_nle.set(k); 00557 // ... otherwise, the constraint is an equality which is 00558 // violated by the generator `dest_nle': the generator has to be 00559 // removed from `dest'. 00560 else { 00561 --dest_num_rows; 00562 std::swap(dest_nle, dest[dest_num_rows]); 00563 std::swap(scalar_prod_nle, scalar_prod[dest_num_rows]); 00564 std::swap(sat_nle, sat[dest_num_rows]); 00565 // `dest' has already been set as non-sorted. 00566 } 00567 // We continue with the next constraint. 00568 ++k; 00569 } 00570 // Here we have `index_non_zero' >= `num_lines_or_equalities', 00571 // so that all the lines in `dest' saturate the constraint `source_k'. 00572 else { 00573 // First, we reorder the generators in `dest' as follows: 00574 // -# all the lines should have indexes between 0 and 00575 // `num_lines_or_equalities' - 1 (this already holds); 00576 // -# all the rays that saturate the constraint should have 00577 // indexes between `num_lines_or_equalities' and 00578 // `lines_or_equal_bound' - 1; these rays form the set Q=. 00579 // -# all the rays that have a positive scalar product with the 00580 // constraint should have indexes between `lines_or_equal_bound' 00581 // and `sup_bound' - 1; these rays form the set Q+. 00582 // -# all the rays that have a negative scalar product with the 00583 // constraint should have indexes between `sup_bound' and 00584 // `dest_num_rows' - 1; these rays form the set Q-. 00585 dimension_type lines_or_equal_bound = num_lines_or_equalities; 00586 dimension_type inf_bound = dest_num_rows; 00587 // While we find saturating generators, we simply increment 00588 // `lines_or_equal_bound'. 00589 while (inf_bound > lines_or_equal_bound 00590 && scalar_prod[lines_or_equal_bound] == 0) 00591 ++lines_or_equal_bound; 00592 dimension_type sup_bound = lines_or_equal_bound; 00593 while (inf_bound > sup_bound) { 00594 const int sp_sign = sgn(scalar_prod[sup_bound]); 00595 if (sp_sign == 0) { 00596 // This generator has to be moved in Q=. 00597 std::swap(dest[sup_bound], dest[lines_or_equal_bound]); 00598 std::swap(scalar_prod[sup_bound], scalar_prod[lines_or_equal_bound]); 00599 std::swap(sat[sup_bound], sat[lines_or_equal_bound]); 00600 ++lines_or_equal_bound; 00601 ++sup_bound; 00602 dest.set_sorted(false); 00603 } 00604 else if (sp_sign < 0) { 00605 // This generator has to be moved in Q-. 00606 --inf_bound; 00607 std::swap(dest[sup_bound], dest[inf_bound]); 00608 std::swap(scalar_prod[sup_bound], scalar_prod[inf_bound]); 00609 std::swap(sat[sup_bound], sat[inf_bound]); 00610 dest.set_sorted(false); 00611 } 00612 else 00613 // sp_sign > 0: this generator has to be moved in Q+. 00614 ++sup_bound; 00615 } 00616 00617 if (sup_bound == dest_num_rows) { 00618 // Here the set Q- is empty. 00619 // If the constraint is an inequality, then all the generators 00620 // in Q= and Q+ satisfy the constraint. The constraint is redundant 00621 // and it can be safely removed from the constraint system. 00622 // This is why the `source' parameter is not declared `const'. 00623 if (source_k.is_ray_or_point_or_inequality()) { 00624 ++source_num_redundant; 00625 --source_num_rows; 00626 // NOTE: we continue with the next cycle of the loop 00627 // without incrementing the index `k', because: 00628 // -# either `k == source_num_rows', and we will exit the loop; 00629 // -# or, having increased `source_num_redundant', we will swap 00630 // in position `k' a constraint that still has to be examined. 00631 } 00632 else { 00633 // The constraint is an equality, so that all the generators 00634 // in Q+ violate it. Since the set Q- is empty, we can simply 00635 // remove from `dest' all the generators of Q+. 00636 dest_num_rows = lines_or_equal_bound; 00637 // We continue with the next constraint. 00638 ++k; 00639 } 00640 } 00641 else { 00642 // The set Q- is not empty, i.e., at least one generator 00643 // violates the constraint `source_k'. 00644 // We have to further distinguish two cases: 00645 if (sup_bound == num_lines_or_equalities) 00646 // The set Q+ is empty, so that all generators that satisfy 00647 // the constraint also saturate it. 00648 // We can simply remove from `dest' all the generators in Q-. 00649 dest_num_rows = sup_bound; 00650 else { 00651 // The sets Q+ and Q- are both non-empty. 00652 // The generators of the new pointed cone are all those satisfying 00653 // the constraint `source_k' plus a set of new rays enjoying 00654 // the following properties: 00655 // -# they lie on the hyper-plane represented by the constraint 00656 // -# they are obtained as a positive combination of two 00657 // adjacent rays, the first taken from Q+ and the second 00658 // taken from Q-. 00659 00660 // The adjacency property is necessary to have an irredundant 00661 // set of new rays (see proposition 2). 00662 const dimension_type bound = dest_num_rows; 00663 00664 // In the following loop, 00665 // `i' runs through the generators in the set Q+ and 00666 // `j' runs through the generators in the set Q-. 00667 for (dimension_type i = lines_or_equal_bound; i < sup_bound; ++i) { 00668 for(dimension_type j = sup_bound; j < bound; ++j) { 00669 // Checking if generators `dest[i]' and `dest[j]' are adjacent. 00670 // If there exist another generator that saturates 00671 // all the constraints saturated by both `dest[i]' and 00672 // `dest[j]', then they are NOT adjacent. 00673 Bit_Row new_satrow; 00674 assert(sat[i].last() == ULONG_MAX || sat[i].last() < k); 00675 assert(sat[j].last() == ULONG_MAX || sat[j].last() < k); 00676 // Being the union of `sat[i]' and `sat[j]', 00677 // `new_satrow' corresponds to a ray that saturates all the 00678 // constraints saturated by both `dest[i]' and `dest[j]'. 00679 set_union(sat[i], sat[j], new_satrow); 00680 00681 // Computing the number of common saturators. 00682 // NOTE: this number has to be less than `k' because 00683 // we are treating the `k'-th constraint. 00684 const dimension_type 00685 num_common_satur = k - new_satrow.count_ones(); 00686 00687 // Even before actually creating the new ray as a 00688 // positive combination of `dest[i]' and `dest[j]', 00689 // we exploit saturation information to check if 00690 // it can be an extremal ray. To this end, we refer 00691 // to the definition of a minimal proper face 00692 // (see comments in Polyhedron.defs.hh): 00693 // an extremal ray saturates at least `n' - `t' - 1 00694 // constraints, where `n' is the dimension of the space 00695 // and `t' is the dimension of the lineality space. 00696 // Since `n == source_num_columns - 1' and 00697 // `t == num_lines_or_equalities', we obtain that 00698 // an extremal ray saturates at least 00699 // `source_num_columns - num_lines_or_equalities - 2' 00700 // constraints. 00701 if (num_common_satur 00702 >= source_num_columns - num_lines_or_equalities - 2) { 00703 // The minimal proper face rule is satisfied. 00704 // Now we actually check for redundancy by computing 00705 // adjacency information. 00706 bool redundant = false; 00707 for (dimension_type 00708 l = num_lines_or_equalities; l < bound; ++l) 00709 if (l != i && l != j 00710 && subset_or_equal(sat[l], new_satrow)) { 00711 // Found another generator saturating all the 00712 // constraints saturated by both `dest[i]' and `dest[j]'. 00713 redundant = true; 00714 break; 00715 } 00716 if (!redundant) { 00717 // Adding the new ray to `dest' and the corresponding 00718 // saturation row to `sat'. 00719 if (dest_num_rows == dest.num_rows()) { 00720 // Make room for one more row. 00721 dest.add_pending_row(Linear_Row::Flags(dest.topology(), 00722 Linear_Row::RAY_OR_POINT_OR_INEQUALITY)); 00723 sat.add_row(new_satrow); 00724 } 00725 else 00726 sat[dest_num_rows] = new_satrow; 00727 Linear_Row& new_row = dest[dest_num_rows]; 00728 // The following fragment optimizes the computation of 00729 // 00730 // Coefficient scale = scalar_prod[i]; 00731 // scale.gcd_assign(scalar_prod[j]); 00732 // Coefficient normalized_sp_i = scalar_prod[i] / scale; 00733 // Coefficient normalized_sp_j = scalar_prod[j] / scale; 00734 // for (dimension_type c = dest_num_columns; c-- > 0; ) { 00735 // new_row[c] = normalized_sp_i * dest[j][c]; 00736 // new_row[c] -= normalized_sp_j * dest[i][c]; 00737 // } 00738 normalize2(scalar_prod[i], 00739 scalar_prod[j], 00740 normalized_sp_i, 00741 normalized_sp_o); 00742 for (dimension_type c = dest_num_columns; c-- > 0; ) { 00743 Coefficient& new_row_c = new_row[c]; 00744 new_row_c = normalized_sp_i * dest[j][c]; 00745 sub_mul_assign(new_row_c, normalized_sp_o, dest[i][c]); 00746 } 00747 new_row.strong_normalize(); 00748 // Since we added a new generator to `dest', 00749 // we also add a new element to `scalar_prod'; 00750 // by construction, the new ray lies on the hyper-plane 00751 // represented by the constraint `source_k'. 00752 // Thus, the added scalar product is 0. 00753 assert(scalar_prod.size() >= dest_num_rows); 00754 if (scalar_prod.size() <= dest_num_rows) 00755 scalar_prod.push_back(Coefficient_zero()); 00756 else 00757 scalar_prod[dest_num_rows] = Coefficient_zero(); 00758 // Increment the number of generators. 00759 ++dest_num_rows; 00760 } 00761 } 00762 } 00763 #if REACTIVE_ABANDONING 00764 maybe_abandon(); 00765 #endif 00766 } 00767 // Now we substitute the rays in Q- (i.e., the rays violating 00768 // the constraint) with the newly added rays. 00769 dimension_type j; 00770 if (source_k.is_ray_or_point_or_inequality()) { 00771 // The constraint is an inequality: 00772 // the violating generators are those in Q-. 00773 j = sup_bound; 00774 // For all the generators in Q+, set to 1 the corresponding 00775 // entry for the constraint `source_k' in the saturation matrix. 00776 for (dimension_type l = lines_or_equal_bound; l < sup_bound; ++l) 00777 sat[l].set(k); 00778 } 00779 else 00780 // The constraint is an equality: 00781 // the violating generators are those in the union of Q+ and Q-. 00782 j = lines_or_equal_bound; 00783 00784 // Swapping the newly added rays 00785 // (index `i' running through `dest_num_rows - 1' down-to `bound') 00786 // with the generators violating the constraint 00787 // (index `j' running through `j' up-to `bound - 1'). 00788 dimension_type i = dest_num_rows; 00789 while (j < bound && i > bound) { 00790 --i; 00791 std::swap(dest[i], dest[j]); 00792 std::swap(scalar_prod[i], scalar_prod[j]); 00793 std::swap(sat[i], sat[j]); 00794 ++j; 00795 dest.set_sorted(false); 00796 } 00797 // Setting the number of generators in `dest': 00798 // - if the number of generators violating the constraint 00799 // is less than or equal to the number of the newly added 00800 // generators, we assign `i' to `dest_num_rows' because 00801 // all generators above this index are significant; 00802 // - otherwise, we assign `j' to `dest_num_rows' because 00803 // all generators below index `j-1' violates the constraint. 00804 dest_num_rows = (j == bound) ? i : j; 00805 } 00806 // We continue with the next constraint. 00807 ++k; 00808 } 00809 } 00810 #if !REACTIVE_ABANDONING 00811 // Check if the client has requested abandoning all expensive 00812 // computations. If so, the exception specified by the client 00813 // is thrown now. 00814 maybe_abandon(); 00815 #endif 00816 } 00817 00818 // We may have identified some redundant constraints in `source', 00819 // which have been swapped at the end of the system. 00820 if (source_num_redundant > 0) { 00821 assert(source_num_redundant == source.num_rows() - source_num_rows); 00822 source.erase_to_end(source_num_rows); 00823 sat.columns_erase_to_end(source_num_rows); 00824 } 00825 // If `start == 0', then `source' was sorted and remained so. 00826 // If otherwise `start > 0', then the two sub-system made by the 00827 // non-pending rows and the pending rows, respectively, were both sorted. 00828 // Thus, the overall system is sorted if and only if either 00829 // `start == source_num_rows' (i.e., the second sub-system is empty) 00830 // or the row ordering holds for the two rows at the boundary between 00831 // the two sub-systems. 00832 if (start > 0 && start < source_num_rows) 00833 source.set_sorted(compare(source[start - 1], source[start]) <= 0); 00834 // There are no longer pending constraints in `source'. 00835 source.unset_pending_rows(); 00836 00837 // We may have identified some redundant rays in `dest', 00838 // which have been swapped at the end of the system. 00839 if (dest_num_rows < dest.num_rows()) { 00840 dest.erase_to_end(dest_num_rows); 00841 // Be careful: we might have erased some of the non-pending rows. 00842 if (dest.first_pending_row() > dest_num_rows) 00843 dest.unset_pending_rows(); 00844 sat.rows_erase_to_end(dest_num_rows); 00845 } 00846 if (dest.is_sorted()) 00847 // If the non-pending generators in `dest' are still declared to be 00848 // sorted, then we have to also check for the sortedness of the 00849 // pending generators. 00850 for (dimension_type i = dest.first_pending_row(); i < dest_num_rows; ++i) 00851 if (compare(dest[i - 1], dest[i]) > 0) { 00852 dest.set_sorted(false); 00853 break; 00854 } 00855 // There are no pending generators in `dest'. 00856 dest.unset_pending_rows(); 00857 00858 return num_lines_or_equalities; 00859 }
PPL::dimension_type Parma_Polyhedra_Library::Polyhedron::simplify | ( | Linear_System & | sys, | |
Bit_Matrix & | sat | |||
) | [static, private] |
Uses Gauss' elimination method to simplify the result of conversion()
.
sys
.sys | The system to simplify: it will be modified; | |
sat | The 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:
where can be any real number.
Definition at line 81 of file simplify.cc.
References Parma_Polyhedra_Library::Linear_System::back_substitute(), Parma_Polyhedra_Library::compute_capacity(), empty, Parma_Polyhedra_Library::Matrix::erase_to_end(), Parma_Polyhedra_Library::Linear_System::gauss(), Parma_Polyhedra_Library::Bit_Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Linear_System::OK(), Parma_Polyhedra_Library::Bit_Matrix::rows_erase_to_end(), Parma_Polyhedra_Library::Linear_System::set_sorted(), Parma_Polyhedra_Library::Linear_System::sign_normalize(), simplify_num_saturators_p, simplify_num_saturators_size, Parma_Polyhedra_Library::swap(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
Referenced by add_and_minimize(), and minimize().
00081 { 00082 // This method is only applied to a well-formed system `sys'. 00083 assert(sys.OK(true)); 00084 assert(sys.num_columns() >= 1); 00085 00086 dimension_type num_rows = sys.num_rows(); 00087 const dimension_type num_columns = sys.num_columns(); 00088 const dimension_type num_cols_sat = sat.num_columns(); 00089 00090 // Looking for the first inequality in `sys'. 00091 dimension_type num_lines_or_equalities = 0; 00092 while (num_lines_or_equalities < num_rows 00093 && sys[num_lines_or_equalities].is_line_or_equality()) 00094 ++num_lines_or_equalities; 00095 00096 // `num_saturators[i]' will contain the number of generators 00097 // that saturate the constraint `sys[i]'. 00098 if (num_rows > simplify_num_saturators_size) { 00099 delete [] simplify_num_saturators_p; 00100 simplify_num_saturators_p = 0; 00101 simplify_num_saturators_size = 0; 00102 size_t new_size = compute_capacity(num_rows); 00103 simplify_num_saturators_p = new dimension_type[new_size]; 00104 simplify_num_saturators_size = new_size; 00105 } 00106 dimension_type* num_saturators = simplify_num_saturators_p; 00107 00108 // Computing the number of saturators for each inequality, 00109 // possibly identifying and swapping those that happen to be 00110 // equalities (see Proposition above). 00111 for (dimension_type i = num_lines_or_equalities; i < num_rows; ++i) { 00112 if (sat[i].empty()) { 00113 // The constraint `sys[i]' is saturated by all the generators. 00114 // Thus, either it is already an equality or it can be transformed 00115 // to an equality (see Proposition above). 00116 sys[i].set_is_line_or_equality(); 00117 // Note: simple normalization already holds. 00118 sys[i].sign_normalize(); 00119 // We also move it just after all the other equalities, 00120 // so that system `sys' keeps its partial sortedness. 00121 if (i != num_lines_or_equalities) { 00122 std::swap(sys[i], sys[num_lines_or_equalities]); 00123 std::swap(sat[i], sat[num_lines_or_equalities]); 00124 std::swap(num_saturators[i], num_saturators[num_lines_or_equalities]); 00125 } 00126 ++num_lines_or_equalities; 00127 // `sys' is no longer sorted. 00128 sys.set_sorted(false); 00129 } 00130 else 00131 // There exists a generator which does not saturate `sys[i]', 00132 // so that `sys[i]' is indeed an inequality. 00133 // We store the number of its saturators. 00134 num_saturators[i] = num_cols_sat - sat[i].count_ones(); 00135 } 00136 00137 // At this point, all the equalities of `sys' (included those 00138 // inequalities that we just transformed to equalities) have 00139 // indexes between 0 and `num_lines_or_equalities' - 1, 00140 // which is the property needed by method gauss(). 00141 // We can simplify the system of equalities, obtaining the rank 00142 // of `sys' as result. 00143 const dimension_type rank = sys.gauss(num_lines_or_equalities); 00144 00145 // Now the irredundant equalities of `sys' have indexes from 0 00146 // to `rank' - 1, whereas the equalities having indexes from `rank' 00147 // to `num_lines_or_equalities' - 1 are all redundant. 00148 // (The inequalities in `sys' have been left untouched.) 00149 // The rows containing equalities are not sorted. 00150 00151 if (rank < num_lines_or_equalities) { 00152 // We identified some redundant equalities. 00153 // Moving them at the bottom of `sys': 00154 // - index `redundant' runs through the redundant equalities 00155 // - index `erasing' identifies the first row that should 00156 // be erased after this loop. 00157 // Note that we exit the loop either because we have moved all 00158 // redundant equalities or because we have moved all the 00159 // inequalities. 00160 for (dimension_type redundant = rank, 00161 erasing = num_rows; 00162 redundant < num_lines_or_equalities 00163 && erasing > num_lines_or_equalities; 00164 ) { 00165 --erasing; 00166 std::swap(sys[redundant], sys[erasing]); 00167 std::swap(sat[redundant], sat[erasing]); 00168 std::swap(num_saturators[redundant], num_saturators[erasing]); 00169 sys.set_sorted(false); 00170 ++redundant; 00171 } 00172 // Adjusting the value of `num_rows' to the number of meaningful 00173 // rows of `sys': `num_lines_or_equalities' - `rank' is the number of 00174 // redundant equalities moved to the bottom of `sys', which are 00175 // no longer meaningful. 00176 num_rows -= num_lines_or_equalities - rank; 00177 // Adjusting the value of `num_lines_or_equalities'. 00178 num_lines_or_equalities = rank; 00179 } 00180 00181 // Now we use the definition of redundancy (given in the Introduction) 00182 // to remove redundant inequalities. 00183 00184 // First we check the saturation rule, which provides a necessary 00185 // condition for an inequality to be irredundant (i.e., it provides 00186 // a sufficient condition for identifying redundant inequalities). 00187 // Let 00188 // num_saturators[i] = num_sat_lines[i] + num_sat_rays_or_points[i]; 00189 // dim_lin_space = num_irred_lines; 00190 // dim_ray_space 00191 // = dim_vector_space - num_irred_equalities - dim_lin_space 00192 // = num_columns - 1 - num_lines_or_equalities - dim_lin_space; 00193 // min_sat_rays_or_points = dim_ray_space. 00194 // 00195 // An inequality saturated by less than `dim_ray_space' _rays/points_ 00196 // is redundant. Thus we have the implication 00197 // 00198 // (num_saturators[i] - num_sat_lines[i] < dim_ray_space) 00199 // ==> 00200 // redundant(sys[i]). 00201 // 00202 // Moreover, since every line saturates all inequalities, we also have 00203 // dim_lin_space = num_sat_lines[i] 00204 // so that we can rewrite the condition above as follows: 00205 // 00206 // (num_saturators[i] < num_columns - num_lines_or_equalities - 1) 00207 // ==> 00208 // redundant(sys[i]). 00209 // 00210 const dimension_type min_saturators 00211 = num_columns - num_lines_or_equalities - 1; 00212 for (dimension_type i = num_lines_or_equalities; i < num_rows; ) { 00213 if (num_saturators[i] < min_saturators) { 00214 // The inequality `sys[i]' is redundant. 00215 --num_rows; 00216 std::swap(sys[i], sys[num_rows]); 00217 std::swap(sat[i], sat[num_rows]); 00218 std::swap(num_saturators[i], num_saturators[num_rows]); 00219 sys.set_sorted(false); 00220 } 00221 else 00222 ++i; 00223 } 00224 00225 // Now we check the independence rule. 00226 for (dimension_type i = num_lines_or_equalities; i < num_rows; ) { 00227 bool redundant = false; 00228 // NOTE: in the inner loop, index `j' runs through _all_ the 00229 // inequalities and we do not test if `sat[i]' is strictly 00230 // contained into `sat[j]'. Experimentation has shown that this 00231 // is faster than having `j' only run through the indexes greater 00232 // than `i' and also doing the test `strict_subset(sat[i], 00233 // sat[k])'. 00234 for (dimension_type j = num_lines_or_equalities; j < num_rows; ) { 00235 if (i == j) 00236 // We want to compare different rows of `sys'. 00237 ++j; 00238 else { 00239 // Let us recall that each generator lies on a facet of the 00240 // polyhedron (see the Introduction). 00241 // Given two constraints `c_1' and `c_2', if there are `m' 00242 // generators lying on the hyper-plane corresponding to `c_1', 00243 // the same `m' generators lie on the hyper-plane 00244 // corresponding to `c_2', too, and there is another one lying 00245 // on the latter but not on the former, then `c_2' is more 00246 // restrictive than `c_1', i.e., `c_1' is redundant. 00247 bool strict_subset; 00248 if (subset_or_equal(sat[j], sat[i], strict_subset)) 00249 if (strict_subset) { 00250 // All the saturators of the inequality `sys[i]' are 00251 // saturators of the inequality `sys[j]' too, 00252 // and there exists at least one saturator of `sys[j]' 00253 // which is not a saturator of `sys[i]'. 00254 // It follows that inequality `sys[i]' is redundant. 00255 redundant = true; 00256 break; 00257 } 00258 else { 00259 // We have `sat[j] == sat[i]'. Hence inequalities 00260 // `sys[i]' and `sys[j]' are saturated by the same set of 00261 // generators. Then we can remove either one of the two 00262 // inequalities: we remove `sys[j]'. 00263 --num_rows; 00264 std::swap(sys[j], sys[num_rows]); 00265 std::swap(sat[j], sat[num_rows]); 00266 std::swap(num_saturators[j], num_saturators[num_rows]); 00267 sys.set_sorted(false); 00268 } 00269 else 00270 // If we reach this point then we know that `sat[i]' does 00271 // not contain (and is different from) `sat[j]', so that 00272 // `sys[i]' is not made redundant by inequality `sys[j]'. 00273 ++j; 00274 } 00275 } 00276 if (redundant) { 00277 // The inequality `sys[i]' is redundant. 00278 --num_rows; 00279 std::swap(sys[i], sys[num_rows]); 00280 std::swap(sat[i], sat[num_rows]); 00281 std::swap(num_saturators[i], num_saturators[num_rows]); 00282 sys.set_sorted(false); 00283 } 00284 else 00285 // The inequality `sys[i]' is not redundant. 00286 ++i; 00287 } 00288 00289 // Here we physically remove the redundant inequalities previously 00290 // moved to the bottom of `sys' and the corresponding `sat' rows. 00291 sys.erase_to_end(num_rows); 00292 sys.unset_pending_rows(); 00293 sat.rows_erase_to_end(num_rows); 00294 // At this point the first `num_lines_or_equalities' rows of 'sys' 00295 // represent the irredundant equalities, while the remaining rows 00296 // (i.e., those having indexes from `num_lines_or_equalities' to 00297 // `num_rows' - 1) represent the irredundant inequalities. 00298 #ifndef NDEBUG 00299 // Check if the flag is set (that of the equalities is already set). 00300 for (dimension_type i = num_lines_or_equalities; i < num_rows; ++i) 00301 assert(sys[i].is_ray_or_point_or_inequality()); 00302 #endif 00303 00304 // Finally, since now the sub-system (of `sys') of the irredundant 00305 // equalities is in triangular form, we back substitute each 00306 // variables with the expression obtained considering the equalities 00307 // starting from the last one. 00308 sys.back_substitute(num_lines_or_equalities); 00309 00310 // The returned value is the number of irredundant equalities i.e., 00311 // the rank of the sub-system of `sys' containing only equalities. 00312 // (See the Introduction for definition of lineality space dimension.) 00313 return num_lines_or_equalities; 00314 }
void Parma_Polyhedra_Library::Polyhedron::throw_runtime_error | ( | const char * | method | ) | const [protected] |
Definition at line 1412 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed().
Referenced by add_generator().
01412 { 01413 std::ostringstream s; 01414 s << "PPL::"; 01415 if (is_necessarily_closed()) 01416 s << "C_"; 01417 else 01418 s << "NNC_"; 01419 s << "Polyhedron::" << method << "." << std::endl; 01420 throw std::runtime_error(s.str()); 01421 }
void Parma_Polyhedra_Library::Polyhedron::throw_invalid_argument | ( | const char * | method, | |
const char * | reason | |||
) | const [protected] |
Definition at line 1424 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed().
Referenced by add_congruence(), add_congruences(), affine_image(), affine_preimage(), bounded_affine_image(), bounded_affine_preimage(), fold_space_dimensions(), generalized_affine_image(), generalized_affine_preimage(), and map_space_dimensions().
01425 { 01426 std::ostringstream s; 01427 s << "PPL::"; 01428 if (is_necessarily_closed()) 01429 s << "C_"; 01430 else 01431 s << "NNC_"; 01432 s << "Polyhedron::" << method << ":" << std::endl 01433 << reason << "."; 01434 throw std::invalid_argument(s.str()); 01435 }
void Parma_Polyhedra_Library::Polyhedron::throw_topology_incompatible | ( | const char * | method, | |
const char * | ph_name, | |||
const Polyhedron & | ph | |||
) | const [protected] |
Definition at line 1438 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed().
Referenced by add_constraint(), add_generator(), add_recycled_constraints(), add_recycled_generators(), add_recycled_generators_and_minimize(), BHRZ03_widening_assign(), concatenate_assign(), contains(), H79_widening_assign(), intersection_assign(), intersection_assign_and_minimize(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), poly_difference_assign(), poly_hull_assign(), poly_hull_assign_and_minimize(), Polyhedron(), simplify_using_context_assign(), swap(), and time_elapse_assign().
01440 { 01441 std::ostringstream s; 01442 s << "PPL::"; 01443 if (is_necessarily_closed()) 01444 s << "C_"; 01445 else 01446 s << "NNC_"; 01447 s << "Polyhedron::" << method << ":" << std::endl 01448 << ph_name << " is a "; 01449 if (ph.is_necessarily_closed()) 01450 s << "C_"; 01451 else 01452 s << "NNC_"; 01453 s << "Polyhedron." << std::endl; 01454 throw std::invalid_argument(s.str()); 01455 }
void Parma_Polyhedra_Library::Polyhedron::throw_topology_incompatible | ( | const char * | method, | |
const char * | c_name, | |||
const Constraint & | c | |||
) | const [protected] |
Definition at line 1458 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed().
01460 { 01461 assert(is_necessarily_closed()); 01462 std::ostringstream s; 01463 s << "PPL::C_Polyhedron::" << method << ":" << std::endl 01464 << c_name << " is a strict inequality."; 01465 throw std::invalid_argument(s.str()); 01466 }
void Parma_Polyhedra_Library::Polyhedron::throw_topology_incompatible | ( | const char * | method, | |
const char * | g_name, | |||
const Generator & | g | |||
) | const [protected] |
Definition at line 1469 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed().
01471 { 01472 assert(is_necessarily_closed()); 01473 std::ostringstream s; 01474 s << "PPL::C_Polyhedron::" << method << ":" << std::endl 01475 << g_name << " is a closure point."; 01476 throw std::invalid_argument(s.str()); 01477 }
void Parma_Polyhedra_Library::Polyhedron::throw_topology_incompatible | ( | const char * | method, | |
const char * | cs_name, | |||
const Constraint_System & | cs | |||
) | const [protected] |
Definition at line 1480 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed().
01482 { 01483 assert(is_necessarily_closed()); 01484 std::ostringstream s; 01485 s << "PPL::C_Polyhedron::" << method << ":" << std::endl 01486 << cs_name << " contains strict inequalities."; 01487 throw std::invalid_argument(s.str()); 01488 }
void Parma_Polyhedra_Library::Polyhedron::throw_topology_incompatible | ( | const char * | method, | |
const char * | gs_name, | |||
const Generator_System & | gs | |||
) | const [protected] |
Definition at line 1491 of file Polyhedron_nonpublic.cc.
01493 { 01494 std::ostringstream s; 01495 s << "PPL::C_Polyhedron::" << method << ":" << std::endl 01496 << gs_name << " contains closure points."; 01497 throw std::invalid_argument(s.str()); 01498 }
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
const char * | other_name, | |||
dimension_type | other_dim | |||
) | const [protected] |
Definition at line 1501 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed(), and space_dimension().
Referenced by add_congruence(), add_congruences(), add_constraint(), add_generator(), add_recycled_constraints(), add_recycled_generators(), add_recycled_generators_and_minimize(), affine_image(), affine_preimage(), BHRZ03_widening_assign(), bounded_affine_image(), bounded_affine_preimage(), bounds(), constrains(), contains(), expand_space_dimension(), fold_space_dimensions(), generalized_affine_image(), generalized_affine_preimage(), H79_widening_assign(), intersection_assign(), intersection_assign_and_minimize(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), max_min(), poly_difference_assign(), poly_hull_assign(), poly_hull_assign_and_minimize(), refine_with_congruence(), refine_with_congruences(), refine_with_constraint(), refine_with_constraints(), relation_with(), remove_higher_space_dimensions(), remove_space_dimensions(), simplify_using_context_assign(), throw_dimension_incompatible(), time_elapse_assign(), and unconstrain().
01503 { 01504 std::ostringstream s; 01505 s << "PPL::" 01506 << (is_necessarily_closed() ? "C_" : "NNC_") 01507 << "Polyhedron::" << method << ":\n" 01508 << "this->space_dimension() == " << space_dimension() << ", " 01509 << other_name << ".space_dimension() == " << other_dim << "."; 01510 throw std::invalid_argument(s.str()); 01511 }
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
const char * | ph_name, | |||
const Polyhedron & | ph | |||
) | const [protected] |
Definition at line 1514 of file Polyhedron_nonpublic.cc.
References space_dimension(), and throw_dimension_incompatible().
01516 { 01517 throw_dimension_incompatible(method, ph_name, ph.space_dimension()); 01518 }
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
const char * | e_name, | |||
const Linear_Expression & | e | |||
) | const [protected] |
Definition at line 1521 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and throw_dimension_incompatible().
01523 { 01524 throw_dimension_incompatible(method, e_name, e.space_dimension()); 01525 }
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
const char * | c_name, | |||
const Constraint & | c | |||
) | const [protected] |
Definition at line 1528 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Constraint::space_dimension(), and throw_dimension_incompatible().
01530 { 01531 throw_dimension_incompatible(method, c_name, c.space_dimension()); 01532 }
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
const char * | g_name, | |||
const Generator & | g | |||
) | const [protected] |
Definition at line 1535 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Generator::space_dimension(), and throw_dimension_incompatible().
01537 { 01538 throw_dimension_incompatible(method, g_name, g.space_dimension()); 01539 }
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
const char * | cg_name, | |||
const Congruence & | cg | |||
) | const [protected] |
Definition at line 1542 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Congruence::space_dimension(), and throw_dimension_incompatible().
01544 { 01545 throw_dimension_incompatible(method, cg_name, cg.space_dimension()); 01546 }
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
const char * | cs_name, | |||
const Constraint_System & | cs | |||
) | const [protected] |
Definition at line 1549 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Constraint_System::space_dimension(), and throw_dimension_incompatible().
01551 { 01552 throw_dimension_incompatible(method, cs_name, cs.space_dimension()); 01553 }
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
const char * | gs_name, | |||
const Generator_System & | gs | |||
) | const [protected] |
Definition at line 1556 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Generator_System::space_dimension(), and throw_dimension_incompatible().
01558 { 01559 throw_dimension_incompatible(method, gs_name, gs.space_dimension()); 01560 }
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
const char * | cgs_name, | |||
const Congruence_System & | cgs | |||
) | const [protected] |
Definition at line 1563 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Congruence_System::space_dimension(), and throw_dimension_incompatible().
01565 { 01566 throw_dimension_incompatible(method, cgs_name, cgs.space_dimension()); 01567 }
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
const char * | var_name, | |||
Variable | var | |||
) | const [protected] |
Definition at line 1570 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed(), Parma_Polyhedra_Library::Variable::space_dimension(), and space_dimension().
01572 { 01573 std::ostringstream s; 01574 s << "PPL::"; 01575 if (is_necessarily_closed()) 01576 s << "C_"; 01577 else 01578 s << "NNC_"; 01579 s << "Polyhedron::" << method << ":" << std::endl 01580 << "this->space_dimension() == " << space_dimension() << ", " 01581 << var_name << ".space_dimension() == " << var.space_dimension() << "."; 01582 throw std::invalid_argument(s.str()); 01583 }
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
dimension_type | required_space_dim | |||
) | const [protected] |
Definition at line 1587 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed(), and space_dimension().
01588 { 01589 std::ostringstream s; 01590 s << "PPL::"; 01591 if (is_necessarily_closed()) 01592 s << "C_"; 01593 else 01594 s << "NNC_"; 01595 s << "Polyhedron::" << method << ":" << std::endl 01596 << "this->space_dimension() == " << space_dimension() 01597 << ", required space dimension == " << required_space_dim << "."; 01598 throw std::invalid_argument(s.str()); 01599 }
void Parma_Polyhedra_Library::Polyhedron::throw_space_dimension_overflow | ( | Topology | topol, | |
const char * | method, | |||
const char * | reason | |||
) | [static, protected] |
Definition at line 1602 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::NECESSARILY_CLOSED.
Referenced by add_space_dimensions_and_embed(), add_space_dimensions_and_project(), concatenate_assign(), and expand_space_dimension().
01604 { 01605 std::ostringstream s; 01606 s << "PPL::"; 01607 if (topol == NECESSARILY_CLOSED) 01608 s << "C_"; 01609 else 01610 s << "NNC_"; 01611 s << "Polyhedron::" << method << ":" << std::endl 01612 << reason << "."; 01613 throw std::length_error(s.str()); 01614 }
void Parma_Polyhedra_Library::Polyhedron::throw_invalid_generator | ( | const char * | method, | |
const char * | g_name | |||
) | const [protected] |
Definition at line 1617 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed().
Referenced by add_generator().
01618 { 01619 std::ostringstream s; 01620 s << "PPL::"; 01621 if (is_necessarily_closed()) 01622 s << "C_"; 01623 else 01624 s << "NNC_"; 01625 s << "Polyhedron::" << method << ":" << std::endl 01626 << "*this is an empty polyhedron and " 01627 << g_name << " is not a point."; 01628 throw std::invalid_argument(s.str()); 01629 }
void Parma_Polyhedra_Library::Polyhedron::throw_invalid_generators | ( | const char * | method, | |
const char * | gs_name | |||
) | const [protected] |
Definition at line 1632 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed().
Referenced by add_recycled_generators(), add_recycled_generators_and_minimize(), and Polyhedron().
01633 { 01634 std::ostringstream s; 01635 s << "PPL::"; 01636 if (is_necessarily_closed()) 01637 s << "C_"; 01638 else 01639 s << "NNC_"; 01640 s << "Polyhedron::" << method << ":" << std::endl 01641 << "*this is an empty polyhedron and" << std::endl 01642 << "the non-empty generator system " << gs_name << " contains no points."; 01643 throw std::invalid_argument(s.str()); 01644 }
friend class Parma_Polyhedra_Library::Box [friend] |
Definition at line 2782 of file Polyhedron.defs.hh.
friend class Parma_Polyhedra_Library::BD_Shape [friend] |
Definition at line 2783 of file Polyhedron.defs.hh.
friend class Parma_Polyhedra_Library::Octagonal_Shape [friend] |
Definition at line 2784 of file Polyhedron.defs.hh.
friend class Parma_Polyhedra_Library::Grid [friend] |
Definition at line 2785 of file Polyhedron.defs.hh.
friend class Parma_Polyhedra_Library::BHRZ03_Certificate [friend] |
Definition at line 2786 of file Polyhedron.defs.hh.
friend class Parma_Polyhedra_Library::H79_Certificate [friend] |
Definition at line 2787 of file Polyhedron.defs.hh.
bool operator== | ( | const Polyhedron & | x, | |
const Polyhedron & | y | |||
) | [friend] |
bool is_necessarily_closed_for_interfaces | ( | const Polyhedron & | ph | ) | [friend] |
Returns true
if and only if ph.topology() == NECESSARILY_CLOSED
.
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 ", ".
Definition at line 3898 of file Polyhedron_public.cc.
References is_empty(), and minimized_constraints().
03898 { 03899 if (ph.is_empty()) 03900 s << "false"; 03901 else 03902 s << ph.minimized_constraints(); 03903 return s; 03904 }
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.
Definition at line 394 of file Polyhedron.inlines.hh.
void swap | ( | Parma_Polyhedra_Library::Polyhedron & | x, | |
Parma_Polyhedra_Library::Polyhedron & | y | |||
) | [related] |
Specializes std::swap
.
Definition at line 419 of file Polyhedron.inlines.hh.
References swap().
00420 { 00421 x.swap(y); 00422 }
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.
Definition at line 51 of file algorithms.hh.
References Parma_Polyhedra_Library::Powerset< Parma_Polyhedra_Library::Determinate< PS > >::begin(), contains(), and Parma_Polyhedra_Library::Powerset< Parma_Polyhedra_Library::Determinate< PS > >::end().
00051 { 00052 PH phull = p; 00053 NNC_Polyhedron nnc_p(p); 00054 phull.poly_hull_assign(q); 00055 std::pair<PH, Pointset_Powerset<NNC_Polyhedron> > 00056 partition = linear_partition(q, phull); 00057 const Pointset_Powerset<NNC_Polyhedron>& s = partition.second; 00058 typedef Pointset_Powerset<NNC_Polyhedron>::const_iterator iter; 00059 for (iter i = s.begin(), s_end = s.end(); i != s_end; ++i) 00060 // The polyhedral hull is exact if and only if all the elements 00061 // of the partition of the polyhedral hull of `p' and `q' with 00062 // respect to `q' are included in `p' 00063 if (!nnc_p.contains(i->element())) 00064 return false; 00065 p = phull; 00066 return true; 00067 }
The system of constraints.
Definition at line 2024 of file Polyhedron.defs.hh.
Referenced by add_recycled_constraints(), add_recycled_generators_and_minimize(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_image(), affine_preimage(), ascii_dump(), ascii_load(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), BHRZ03_combining_constraints(), bounded_affine_preimage(), concatenate_assign(), constrains(), constraints(), external_memory_in_bytes(), H79_widening_assign(), intersection_assign(), intersection_assign_and_minimize(), is_included_in(), is_necessarily_closed(), is_topologically_closed(), is_universe(), map_space_dimensions(), obtain_sorted_constraints(), obtain_sorted_constraints_with_sat_c(), Parma_Polyhedra_Library::Octagonal_Shape< T >::Octagonal_Shape(), OK(), operator=(), poly_hull_assign_and_minimize(), Polyhedron(), process_pending_constraints(), process_pending_generators(), quick_equivalence_test(), refine_no_check(), refine_with_constraints(), relation_with(), remove_higher_space_dimensions(), remove_pending_to_obtain_constraints(), remove_space_dimensions(), select_CH78_constraints(), select_H79_constraints(), set_empty(), set_zero_dim_univ(), simplified_constraints(), simplify_using_context_assign(), strongly_minimize_constraints(), strongly_minimize_generators(), swap(), topological_closure_assign(), topology(), update_constraints(), update_generators(), update_sat_c(), and update_sat_g().
The system of generators.
Definition at line 2027 of file Polyhedron.defs.hh.
Referenced by add_generator(), add_recycled_generators(), add_recycled_generators_and_minimize(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_image(), affine_preimage(), ascii_dump(), ascii_load(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), bounded_affine_preimage(), bounds(), concatenate_assign(), constrains(), contains_integer_point(), external_memory_in_bytes(), generalized_affine_image(), generators(), intersection_assign_and_minimize(), is_bounded(), is_topologically_closed(), is_universe(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), map_space_dimensions(), max_min(), obtain_sorted_generators(), obtain_sorted_generators_with_sat_g(), OK(), operator=(), poly_hull_assign(), poly_hull_assign_and_minimize(), Polyhedron(), process_pending_constraints(), process_pending_generators(), quick_equivalence_test(), relation_with(), remove_higher_space_dimensions(), remove_pending_to_obtain_generators(), remove_space_dimensions(), select_CH78_constraints(), select_H79_constraints(), set_empty(), set_zero_dim_univ(), simplify_using_context_assign(), strongly_minimize_constraints(), strongly_minimize_generators(), swap(), time_elapse_assign(), topological_closure_assign(), unconstrain(), update_constraints(), update_generators(), update_sat_c(), and update_sat_g().
The saturation matrix having constraints on its columns.
Definition at line 2030 of file Polyhedron.defs.hh.
Referenced by add_space_dimensions_and_embed(), add_space_dimensions_and_project(), ascii_dump(), ascii_load(), concatenate_assign(), external_memory_in_bytes(), intersection_assign_and_minimize(), obtain_sorted_constraints(), obtain_sorted_constraints_with_sat_c(), obtain_sorted_generators(), obtain_sorted_generators_with_sat_g(), OK(), operator=(), Polyhedron(), process_pending_constraints(), process_pending_generators(), set_empty(), strongly_minimize_constraints(), strongly_minimize_generators(), swap(), update_constraints(), and update_sat_c().
The saturation matrix having generators on its columns.
Definition at line 2033 of file Polyhedron.defs.hh.
Referenced by add_recycled_generators_and_minimize(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), ascii_dump(), ascii_load(), concatenate_assign(), external_memory_in_bytes(), obtain_sorted_constraints(), obtain_sorted_constraints_with_sat_c(), obtain_sorted_generators(), obtain_sorted_generators_with_sat_g(), OK(), operator=(), poly_hull_assign_and_minimize(), Polyhedron(), process_pending_constraints(), process_pending_generators(), select_H79_constraints(), set_empty(), strongly_minimize_constraints(), strongly_minimize_generators(), swap(), update_generators(), and update_sat_g().
The status flags to keep track of the polyhedron's internal state.
Definition at line 2221 of file Polyhedron.defs.hh.
Referenced by add_generator(), add_recycled_constraints(), add_recycled_generators(), add_recycled_generators_and_minimize(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), ascii_dump(), ascii_load(), clear_constraints_minimized(), clear_constraints_up_to_date(), clear_empty(), clear_generators_minimized(), clear_generators_up_to_date(), clear_pending_constraints(), clear_pending_generators(), clear_sat_c_up_to_date(), clear_sat_g_up_to_date(), constraints_are_minimized(), constraints_are_up_to_date(), generators_are_minimized(), generators_are_up_to_date(), has_pending_constraints(), has_pending_generators(), has_something_pending(), marked_empty(), OK(), operator=(), Polyhedron(), refine_with_constraints(), sat_c_is_up_to_date(), sat_g_is_up_to_date(), set_constraints_minimized(), set_constraints_pending(), set_constraints_up_to_date(), set_empty(), set_generators_minimized(), set_generators_pending(), set_generators_up_to_date(), set_sat_c_up_to_date(), set_sat_g_up_to_date(), set_zero_dim_univ(), simplify_using_context_assign(), strongly_minimize_constraints(), and swap().
The number of dimensions of the enclosing vector space.
Definition at line 2224 of file Polyhedron.defs.hh.
Referenced by add_congruence(), add_congruences(), add_constraint(), add_generator(), add_recycled_constraints(), add_recycled_generators(), add_recycled_generators_and_minimize(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_dimension(), affine_image(), affine_preimage(), ascii_dump(), ascii_load(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHRZ03_widening_assign(), bounded_affine_image(), bounded_affine_preimage(), bounds(), Parma_Polyhedra_Library::BHRZ03_Certificate::compare(), concatenate_assign(), constrains(), constraints(), contains(), contains_integer_point(), drop_redundant_inequalities(), expand_space_dimension(), fold_space_dimensions(), generalized_affine_image(), generalized_affine_preimage(), generators(), grid_generators(), H79_widening_assign(), intersection_assign(), intersection_assign_and_minimize(), is_bounded(), is_included_in(), is_topologically_closed(), is_universe(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), map_space_dimensions(), max_min(), minimize(), OK(), operator=(), poly_difference_assign(), poly_hull_assign(), poly_hull_assign_and_minimize(), Polyhedron(), process_pending(), process_pending_constraints(), process_pending_generators(), quick_equivalence_test(), refine_no_check(), refine_with_congruence(), refine_with_congruences(), refine_with_constraint(), refine_with_constraints(), relation_with(), remove_higher_space_dimensions(), remove_space_dimensions(), select_CH78_constraints(), select_H79_constraints(), set_zero_dim_univ(), simplify_using_context_assign(), space_dimension(), strongly_minimize_constraints(), strongly_minimize_generators(), swap(), time_elapse_assign(), topological_closure_assign(), unconstrain(), update_constraints(), and update_generators().
PPL::dimension_type * Parma_Polyhedra_Library::Polyhedron::simplify_num_saturators_p = 0 [static, private] |
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 2772 of file Polyhedron.defs.hh.
Referenced by finalize(), initialize(), and simplify().
size_t Parma_Polyhedra_Library::Polyhedron::simplify_num_saturators_size = 0 [static, private] |
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 2780 of file Polyhedron.defs.hh.
Referenced by finalize(), initialize(), and simplify().