The base class for convex polyhedra. More...
#include <Polyhedron.defs.hh>


Classes | |
| class | Status |
| A conjunctive assertion about a polyhedron. More... | |
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 , if *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 | frequency (const Linear_Expression &expr, Coefficient &freq_n, Coefficient &freq_d, Coefficient &val_n, Coefficient &val_d) const |
Returns true if and only if there exist a unique value val such that *this saturates the equality expr = val. | |
| bool | contains (const 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). | |
| void | add_generator (const Generator &g) |
Adds a copy of generator g to the system of generators of *this (without 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. | |
| 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). | |
| 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). | |
| 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. | |
| 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. | |
| 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 &vars) |
Computes the cylindrification of *this with respect to the set of space dimensions vars, assigning the result to *this. | |
| void | intersection_assign (const Polyhedron &y) |
Assigns to *this the intersection of *this and y. | |
| void | poly_hull_assign (const Polyhedron &y) |
Assigns to *this the poly-hull of *this and y. | |
| 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. | |
| 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 , where is the relation symbol encoded by relsym. | |
| void | generalized_affine_preimage (Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one()) |
Assigns to *this the preimage of *this with respect to the generalized affine relation , where is the relation symbol encoded by relsym. | |
| void | generalized_affine_image (const Linear_Expression &lhs, Relation_Symbol relsym, const Linear_Expression &rhs) |
Assigns to *this the image of *this with respect to the generalized affine relation , where is the relation symbol encoded by relsym. | |
| void | generalized_affine_preimage (const Linear_Expression &lhs, Relation_Symbol relsym, const Linear_Expression &rhs) |
Assigns to *this the preimage of *this with respect to the generalized affine relation , where is the relation symbol encoded by relsym. | |
| void | bounded_affine_image (Variable var, const Linear_Expression &lb_expr, const Linear_Expression &ub_expr, Coefficient_traits::const_reference denominator=Coefficient_one()) |
Assigns to *this the image of *this with respect to the bounded affine relation . | |
| 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 | wrap_assign (const Variables_Set &vars, Bounded_Integer_Type_Width w, Bounded_Integer_Type_Representation r, Bounded_Integer_Type_Overflow o, const Constraint_System *pcs=0, unsigned complexity_threshold=16, bool wrap_individually=true) |
| Wraps the specified dimensions of the vector space. | |
| void | drop_some_non_integer_points (Complexity_Class complexity=ANY_COMPLEXITY) |
Possibly tightens *this by dropping some points with non-integer coordinates. | |
| void | drop_some_non_integer_points (const Variables_Set &vars, Complexity_Class complexity=ANY_COMPLEXITY) |
Possibly tightens *this by dropping some points with non-integer coordinates for the space dimensions corresponding to vars. | |
| void | topological_closure_assign () |
Assigns to *this its topological closure. | |
| void | 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) |
Assigns to *this the result of computing the limited extrapolation between *this and y using the BHRZ03-widening operator. | |
| void | bounded_BHRZ03_extrapolation_assign (const Polyhedron &y, const Constraint_System &cs, unsigned *tp=0) |
Assigns to *this the result of computing the bounded extrapolation between *this and y using the BHRZ03-widening operator. | |
| 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) |
Assigns to *this the result of computing the limited extrapolation between *this and y using the H79-widening operator. | |
| void | bounded_H79_extrapolation_assign (const Polyhedron &y, const Constraint_System &cs, unsigned *tp=0) |
Assigns to *this the result of computing the bounded extrapolation between *this and y using the H79-widening operator. | |
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 &vars) |
| 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 &vars, Variable dest) |
Folds the space dimensions in vars into dest. | |
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.). | |
| bool | BFT00_poly_hull_assign_if_exact (const Polyhedron &y) |
If the poly-hull of *this and y is exact it is assigned to *this and true is returned, otherwise false is returned. | |
| bool | BHZ09_poly_hull_assign_if_exact (const Polyhedron &y) |
| bool | BHZ09_C_poly_hull_assign_if_exact (const Polyhedron &y) |
| bool | BHZ09_NNC_poly_hull_assign_if_exact (const Polyhedron &y) |
| void | drop_some_non_integer_points (const Variables_Set *pvars, Complexity_Class complexity) |
Possibly tightens *this by dropping some points with non-integer coordinates for the space dimensions corresponding to *pvars. | |
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 | Parma_Polyhedra_Library::Interfaces::is_necessarily_closed_for_interfaces (const Polyhedron &) |
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. | |
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) |
The base class for convex polyhedra.
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);
, given as a system of constraints: Constraint_System cs; cs.insert(x >= 0); cs.insert(x <= 3); cs.insert(y >= 0); cs.insert(y <= 3); C_Polyhedron ph(cs);
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);
, given as a system of constraints: Constraint_System cs; cs.insert(x >= 0); cs.insert(x - y <= 0); cs.insert(x - y + 1 >= 0); C_Polyhedron ph(cs);
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);
and inserting the appropriate generators (a point, a ray and a line). C_Polyhedron ph(2, EMPTY); ph.add_generator(point(0*x + 0*y)); ph.add_generator(ray(y)); ph.add_generator(line(x));
add_space_dimensions_and_embed: C_Polyhedron ph(1); ph.add_constraint(x == 2); ph.add_space_dimensions_and_embed(1);
. Then we add a single equality constraint, thus obtaining the polyhedron corresponding to the singleton set
. After the last line of code, the resulting polyhedron is
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);
, the considered variable is
and the affine expression is
. The resulting polyhedron is the same square translated to the right. Moreover, if the affine transformation for the same variable x is
: Linear_Expression expr = x + y;
. Instead, if we do not use an invertible transformation for the same variable; for example, the affine expression
: 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;
. Instead, if we do not use an invertible transformation for the same variable x, for example, the affine expression
: Linear_Expression expr = y;
axis.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 vars; vars.insert(y); vars.insert(z); ph.remove_space_dimensions(vars);
, while the resulting polyhedron is
. Be careful when removing space dimensions incrementally: since dimensions are automatically renamed after each application of the remove_space_dimensions operator, unexpected results can be obtained. For instance, by using the following code we would obtain a different result: set<Variable> vars1; vars1.insert(y); ph.remove_space_dimensions(vars1); set<Variable> vars2; vars2.insert(z); ph.remove_space_dimensions(vars2);
: when removing the set of dimensions vars2 we are actually removing variable
of the original polyhedron. For the same reason, the operator remove_space_dimensions is not idempotent: removing twice the same non-empty set of dimensions is never the same as removing them just once. Definition at line 365 of file Polyhedron.defs.hh.
The numeric type of coefficients.
Definition at line 368 of file Polyhedron.defs.hh.
enum Parma_Polyhedra_Library::Polyhedron::Three_Valued_Boolean [private] |
Definition at line 2296 of file Polyhedron.defs.hh.
02296 { 02297 TVB_TRUE, 02298 TVB_FALSE, 02299 TVB_DONT_KNOW 02300 };
| 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 50 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.
00053 : con_sys(topol), 00054 gen_sys(topol), 00055 sat_c(), 00056 sat_g() { 00057 // Protecting against space dimension overflow is up to the caller. 00058 PPL_ASSERT(num_dimensions <= max_space_dimension()); 00059 00060 if (kind == EMPTY) 00061 status.set_empty(); 00062 else if (num_dimensions > 0) { 00063 con_sys.add_low_level_constraints(); 00064 con_sys.adjust_topology_and_space_dimension(topol, num_dimensions); 00065 set_constraints_minimized(); 00066 } 00067 space_dim = num_dimensions; 00068 PPL_ASSERT_HEAVY(OK()); 00069 }
| 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 71 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().
00072 : con_sys(y.topology()), 00073 gen_sys(y.topology()), 00074 status(y.status), 00075 space_dim(y.space_dim) { 00076 // Being a protected method, we simply assert that topologies do match. 00077 PPL_ASSERT(topology() == y.topology()); 00078 if (y.constraints_are_up_to_date()) 00079 con_sys.assign_with_pending(y.con_sys); 00080 if (y.generators_are_up_to_date()) 00081 gen_sys.assign_with_pending(y.gen_sys); 00082 if (y.sat_c_is_up_to_date()) 00083 sat_c = y.sat_c; 00084 if (y.sat_g_is_up_to_date()) 00085 sat_g = y.sat_g; 00086 }
| 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 88 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(), swap(), throw_topology_incompatible(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
00089 : con_sys(topol), 00090 gen_sys(topol), 00091 sat_c(), 00092 sat_g() { 00093 // Protecting against space dimension overflow is up to the caller. 00094 PPL_ASSERT(ccs.space_dimension() <= max_space_dimension()); 00095 00096 // TODO: this implementation is just an executable specification. 00097 Constraint_System cs = ccs; 00098 00099 // Try to adapt `cs' to the required topology. 00100 const dimension_type cs_space_dim = cs.space_dimension(); 00101 if (!cs.adjust_topology_and_space_dimension(topol, cs_space_dim)) 00102 throw_topology_incompatible((topol == NECESSARILY_CLOSED) 00103 ? "C_Polyhedron(cs)" 00104 : "NNC_Polyhedron(cs)", "cs", cs); 00105 00106 // Set the space dimension. 00107 space_dim = cs_space_dim; 00108 00109 if (space_dim > 0) { 00110 // Stealing the rows from `cs'. 00111 std::swap(con_sys, cs); 00112 if (con_sys.num_pending_rows() > 0) { 00113 // Even though `cs' has pending constraints, since the generators 00114 // of the polyhedron are not up-to-date, the polyhedron cannot 00115 // have pending constraints. By integrating the pending part 00116 // of `con_sys' we may loose sortedness. 00117 con_sys.unset_pending_rows(); 00118 con_sys.set_sorted(false); 00119 } 00120 con_sys.add_low_level_constraints(); 00121 set_constraints_up_to_date(); 00122 } 00123 else { 00124 // Here `space_dim == 0'. 00125 if (cs.num_columns() > 0) 00126 // See if an inconsistent constraint has been passed. 00127 for (dimension_type i = cs.num_rows(); i-- > 0; ) 00128 if (cs[i].is_inconsistent()) { 00129 // Inconsistent constraint found: the polyhedron is empty. 00130 set_empty(); 00131 break; 00132 } 00133 } 00134 PPL_ASSERT_HEAVY(OK()); 00135 }
| 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 137 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(), swap(), throw_topology_incompatible(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
00140 : con_sys(topol), 00141 gen_sys(topol), 00142 sat_c(), 00143 sat_g() { 00144 // Protecting against space dimension overflow is up to the caller. 00145 PPL_ASSERT(cs.space_dimension() <= max_space_dimension()); 00146 00147 // Try to adapt `cs' to the required topology. 00148 const dimension_type cs_space_dim = cs.space_dimension(); 00149 if (!cs.adjust_topology_and_space_dimension(topol, cs_space_dim)) 00150 throw_topology_incompatible((topol == NECESSARILY_CLOSED) 00151 ? "C_Polyhedron(cs, recycle)" 00152 : "NNC_Polyhedron(cs, recycle)", "cs", cs); 00153 00154 // Set the space dimension. 00155 space_dim = cs_space_dim; 00156 00157 if (space_dim > 0) { 00158 // Stealing the rows from `cs'. 00159 std::swap(con_sys, cs); 00160 if (con_sys.num_pending_rows() > 0) { 00161 // Even though `cs' has pending constraints, since the generators 00162 // of the polyhedron are not up-to-date, the polyhedron cannot 00163 // have pending constraints. By integrating the pending part 00164 // of `con_sys' we may loose sortedness. 00165 con_sys.unset_pending_rows(); 00166 con_sys.set_sorted(false); 00167 } 00168 con_sys.add_low_level_constraints(); 00169 set_constraints_up_to_date(); 00170 } 00171 else { 00172 // Here `space_dim == 0'. 00173 if (cs.num_columns() > 0) 00174 // See if an inconsistent constraint has been passed. 00175 for (dimension_type i = cs.num_rows(); i-- > 0; ) 00176 if (cs[i].is_inconsistent()) { 00177 // Inconsistent constraint found: the polyhedron is empty. 00178 set_empty(); 00179 break; 00180 } 00181 } 00182 PPL_ASSERT_HEAVY(OK()); 00183 }
| 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 185 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, swap(), throw_invalid_generators(), throw_topology_incompatible(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
00186 : con_sys(topol), 00187 gen_sys(topol), 00188 sat_c(), 00189 sat_g() { 00190 // Protecting against space dimension overflow is up to the caller. 00191 PPL_ASSERT(cgs.space_dimension() <= max_space_dimension()); 00192 00193 // TODO: this implementation is just an executable specification. 00194 Generator_System gs = cgs; 00195 00196 // An empty set of generators defines the empty polyhedron. 00197 if (gs.has_no_rows()) { 00198 space_dim = gs.space_dimension(); 00199 status.set_empty(); 00200 PPL_ASSERT_HEAVY(OK()); 00201 return; 00202 } 00203 00204 // Non-empty valid generator systems have a supporting point, at least. 00205 if (!gs.has_points()) 00206 throw_invalid_generators((topol == NECESSARILY_CLOSED) 00207 ? "C_Polyhedron(gs)" 00208 : "NNC_Polyhedron(gs)", "gs"); 00209 00210 const dimension_type gs_space_dim = gs.space_dimension(); 00211 // Try to adapt `gs' to the required topology. 00212 if (!gs.adjust_topology_and_space_dimension(topol, gs_space_dim)) 00213 throw_topology_incompatible((topol == NECESSARILY_CLOSED) 00214 ? "C_Polyhedron(gs)" 00215 : "NNC_Polyhedron(gs)", "gs", gs); 00216 00217 if (gs_space_dim > 0) { 00218 // Stealing the rows from `gs'. 00219 std::swap(gen_sys, gs); 00220 // In a generator system describing a NNC polyhedron, 00221 // for each point we must also have the corresponding closure point. 00222 if (topol == NOT_NECESSARILY_CLOSED) 00223 gen_sys.add_corresponding_closure_points(); 00224 if (gen_sys.num_pending_rows() > 0) { 00225 // Even though `gs' has pending generators, since the constraints 00226 // of the polyhedron are not up-to-date, the polyhedron cannot 00227 // have pending generators. By integrating the pending part 00228 // of `gen_sys' we may loose sortedness. 00229 gen_sys.unset_pending_rows(); 00230 gen_sys.set_sorted(false); 00231 } 00232 // Generators are now up-to-date. 00233 set_generators_up_to_date(); 00234 00235 // Set the space dimension. 00236 space_dim = gs_space_dim; 00237 PPL_ASSERT_HEAVY(OK()); 00238 return; 00239 } 00240 00241 // Here `gs.num_rows > 0' and `gs_space_dim == 0': 00242 // we already checked for both the topology-compatibility 00243 // and the supporting point. 00244 space_dim = 0; 00245 PPL_ASSERT_HEAVY(OK()); 00246 }
| 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 248 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, swap(), throw_invalid_generators(), throw_topology_incompatible(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
00251 : con_sys(topol), 00252 gen_sys(topol), 00253 sat_c(), 00254 sat_g() { 00255 // Protecting against space dimension overflow is up to the caller. 00256 PPL_ASSERT(gs.space_dimension() <= max_space_dimension()); 00257 00258 // An empty set of generators defines the empty polyhedron. 00259 if (gs.has_no_rows()) { 00260 space_dim = gs.space_dimension(); 00261 status.set_empty(); 00262 PPL_ASSERT_HEAVY(OK()); 00263 return; 00264 } 00265 00266 // Non-empty valid generator systems have a supporting point, at least. 00267 if (!gs.has_points()) 00268 throw_invalid_generators((topol == NECESSARILY_CLOSED) 00269 ? "C_Polyhedron(gs, recycle)" 00270 : "NNC_Polyhedron(gs, recycle)", "gs"); 00271 00272 const dimension_type gs_space_dim = gs.space_dimension(); 00273 // Try to adapt `gs' to the required topology. 00274 if (!gs.adjust_topology_and_space_dimension(topol, gs_space_dim)) 00275 throw_topology_incompatible((topol == NECESSARILY_CLOSED) 00276 ? "C_Polyhedron(gs, recycle)" 00277 : "NNC_Polyhedron(gs, recycle)", "gs", gs); 00278 00279 if (gs_space_dim > 0) { 00280 // Stealing the rows from `gs'. 00281 std::swap(gen_sys, gs); 00282 // In a generator system describing a NNC polyhedron, 00283 // for each point we must also have the corresponding closure point. 00284 if (topol == NOT_NECESSARILY_CLOSED) 00285 gen_sys.add_corresponding_closure_points(); 00286 if (gen_sys.num_pending_rows() > 0) { 00287 // Even though `gs' has pending generators, since the constraints 00288 // of the polyhedron are not up-to-date, the polyhedron cannot 00289 // have pending generators. By integrating the pending part 00290 // of `gen_sys' we may loose sortedness. 00291 gen_sys.unset_pending_rows(); 00292 gen_sys.set_sorted(false); 00293 } 00294 // Generators are now up-to-date. 00295 set_generators_up_to_date(); 00296 00297 // Set the space dimension. 00298 space_dim = gs_space_dim; 00299 PPL_ASSERT_HEAVY(OK()); 00300 return; 00301 } 00302 00303 // Here `gs.num_rows > 0' and `gs_space_dim == 0': 00304 // we already checked for both the topology-compatibility 00305 // and the supporting point. 00306 space_dim = 0; 00307 PPL_ASSERT_HEAVY(OK()); 00308 }
| 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 36 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(), PPL_DIRTY_TEMP_COEFFICIENT, 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(), and Parma_Polyhedra_Library::Constraint_System::swap().
00039 : con_sys(topol), 00040 gen_sys(topol), 00041 sat_c(), 00042 sat_g() { 00043 // Initialize the space dimension as indicated by the box. 00044 space_dim = box.space_dimension(); 00045 00046 // Check for emptiness. 00047 if (box.is_empty()) { 00048 set_empty(); 00049 return; 00050 } 00051 00052 // Zero-dim universe polyhedron. 00053 if (space_dim == 0) { 00054 set_zero_dim_univ(); 00055 return; 00056 } 00057 00058 // Insert a dummy constraint of the highest dimension to avoid the 00059 // need of resizing the matrix of constraints later; 00060 // this constraint will be removed at the end. 00061 con_sys.insert(Variable(space_dim - 1) >= 0); 00062 00063 PPL_DIRTY_TEMP_COEFFICIENT(l_n); 00064 PPL_DIRTY_TEMP_COEFFICIENT(l_d); 00065 PPL_DIRTY_TEMP_COEFFICIENT(u_n); 00066 PPL_DIRTY_TEMP_COEFFICIENT(u_d); 00067 00068 if (topol == NECESSARILY_CLOSED) { 00069 for (dimension_type k = space_dim; k-- > 0; ) { 00070 // See if we have a valid lower bound. 00071 bool l_closed = false; 00072 bool l_bounded = box.get_lower_bound(k, l_closed, l_n, l_d); 00073 // See if we have a valid upper bound. 00074 bool u_closed = false; 00075 bool u_bounded = box.get_upper_bound(k, u_closed, u_n, u_d); 00076 00077 // See if we have an implicit equality constraint. 00078 if (l_bounded && u_bounded 00079 && l_closed && u_closed 00080 && l_n == u_n && l_d == u_d) { 00081 // Add the constraint `l_d*v_k == l_n'. 00082 con_sys.insert(l_d * Variable(k) == l_n); 00083 } 00084 else { 00085 if (l_bounded) 00086 // Add the constraint `l_d*v_k >= l_n'. 00087 con_sys.insert(l_d * Variable(k) >= l_n); 00088 if (u_bounded) 00089 // Add the constraint `u_d*v_k <= u_n'. 00090 con_sys.insert(u_d * Variable(k) <= u_n); 00091 } 00092 } 00093 } 00094 else { 00095 // topol == NOT_NECESSARILY_CLOSED 00096 for (dimension_type k = space_dim; k-- > 0; ) { 00097 // See if we have a valid lower bound. 00098 bool l_closed = false; 00099 bool l_bounded = box.get_lower_bound(k, l_closed, l_n, l_d); 00100 // See if we have a valid upper bound. 00101 bool u_closed = false; 00102 bool u_bounded = box.get_upper_bound(k, u_closed, u_n, u_d); 00103 00104 // See if we have an implicit equality constraint. 00105 if (l_bounded && u_bounded 00106 && l_closed && u_closed 00107 && l_n == u_n && l_d == u_d) { 00108 // Add the constraint `l_d*v_k == l_n'. 00109 con_sys.insert(l_d * Variable(k) == l_n); 00110 } 00111 else { 00112 // Check if a lower bound constraint is required. 00113 if (l_bounded) { 00114 if (l_closed) 00115 // Add the constraint `l_d*v_k >= l_n'. 00116 con_sys.insert(l_d * Variable(k) >= l_n); 00117 else 00118 // Add the constraint `l_d*v_k > l_n'. 00119 con_sys.insert(l_d * Variable(k) > l_n); 00120 } 00121 // Check if an upper bound constraint is required. 00122 if (u_bounded) { 00123 if (u_closed) 00124 // Add the constraint `u_d*v_k <= u_n'. 00125 con_sys.insert(u_d * Variable(k) <= u_n); 00126 else 00127 // Add the constraint `u_d*v_k < u_n'. 00128 con_sys.insert(u_d * Variable(k) < u_n); 00129 } 00130 } 00131 } 00132 } 00133 00134 // Adding the low-level constraints. 00135 con_sys.add_low_level_constraints(); 00136 // Now removing the dummy constraint inserted before. 00137 dimension_type n_rows = con_sys.num_rows() - 1; 00138 con_sys[0].swap(con_sys[n_rows]); 00139 con_sys.set_sorted(false); 00140 // NOTE: here there are no pending constraints. 00141 con_sys.set_index_first_pending_row(n_rows); 00142 con_sys.erase_to_end(n_rows); 00143 00144 // Constraints are up-to-date. 00145 set_constraints_up_to_date(); 00146 PPL_ASSERT_HEAVY(OK()); 00147 }
| Parma_Polyhedra_Library::Polyhedron::~Polyhedron | ( | ) | [inline] |
| 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. |
On entry, the rows of sat are indexed by the rows of dest and its columns are indexed by the non-pending rows of source. On exit, the rows of sat are indexed by the rows of dest and its columns are indexed by the rows of source.
Let us suppose that source is a system of constraints. This method assumes that the non-pending part of source and system dest form a double description pair in minimal form and will build a new DD pair in minimal form by processing the pending constraints in source. To this end, it will call conversion()) and simplify.
This method treats also the dual case, i.e., processing pending generators. In this case source contains generators and dest is the system of constraints corresponding to the non-pending part of source.
Definition at line 335 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().
00338 { 00339 PPL_ASSERT(source.num_pending_rows() > 0); 00340 PPL_ASSERT(source.num_columns() == dest.num_columns()); 00341 PPL_ASSERT(source.is_sorted()); 00342 00343 // First, pad the saturation matrix with new columns (of zeroes) 00344 // to accommodate for the pending rows of `source'. 00345 sat.resize(dest.num_rows(), source.num_rows()); 00346 00347 // Incrementally compute the new system of generators. 00348 // Parameter `start' is set to the index of the first pending constraint. 00349 const dimension_type num_lines_or_equalities 00350 = conversion(source, source.first_pending_row(), 00351 dest, sat, 00352 dest.num_lines_or_equalities()); 00353 00354 // conversion() may have modified the number of rows in `dest'. 00355 const dimension_type dest_num_rows = dest.num_rows(); 00356 00357 // Checking if the generators in `dest' represent an empty polyhedron: 00358 // the polyhedron is empty if there are no points 00359 // (because rays, lines and closure points need a supporting point). 00360 // Points can be detected by looking at: 00361 // - the divisor, for necessarily closed polyhedra; 00362 // - the epsilon coordinate, for NNC polyhedra. 00363 const dimension_type checking_index 00364 = dest.is_necessarily_closed() 00365 ? 0 00366 : dest.num_columns() - 1; 00367 dimension_type first_point; 00368 for (first_point = num_lines_or_equalities; 00369 first_point < dest_num_rows; 00370 ++first_point) 00371 if (dest[first_point][checking_index] > 0) 00372 break; 00373 00374 if (first_point == dest_num_rows) 00375 if (con_to_gen) 00376 // No point has been found: the polyhedron is empty. 00377 return true; 00378 else 00379 // Here `con_to_gen' is false: `dest' is a system of constraints. 00380 // In this case the condition `first_point == dest_num_rows' 00381 // actually means that all the constraints in `dest' have their 00382 // inhomogeneous term equal to 0. 00383 // This is an ILLEGAL situation, because it implies that 00384 // the constraint system `dest' lacks the positivity constraint 00385 // and no linear combination of the constraints in `dest' 00386 // can reintroduce the positivity constraint. 00387 throw std::runtime_error("PPL internal error"); 00388 else { 00389 // A point has been found: the polyhedron is not empty. 00390 // Now invoking `simplify()' to remove all the redundant constraints 00391 // from the system `source'. 00392 // Since the saturation matrix `sat' returned by `conversion()' 00393 // has rows indexed by generators (the rows of `dest') and columns 00394 // indexed by constraints (the rows of `source'), we have to 00395 // transpose it to obtain the saturation matrix needed by `simplify()'. 00396 sat.transpose(); 00397 simplify(source, sat); 00398 // Transposing back. 00399 sat.transpose(); 00400 return false; 00401 } 00402 }
| 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. |
It is assumed that source1 and source2 are sorted and have no pending rows. It is also assumed that dest has no pending rows. On entry, the rows of sat are indexed by the rows of dest and its columns are indexed by the rows of source1. On exit, the rows of sat are indexed by the rows of dest and its columns are indexed by the rows of the system obtained by merging source1 and source2.
Let us suppose we want to add some constraints to a given system of constraints source1. This method, given a minimized double description pair (source1, dest) and a system of new constraints source2, modifies source1 by adding to it the constraints of source2 that are not in source1. Then, by invoking add_and_minimize(bool, Linear_System&, 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 234 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 process_pending_constraints(), and process_pending_generators().
00238 { 00239 // `source1' and `source2' cannot be empty. 00240 PPL_ASSERT(!source1.has_no_rows() && !source2.has_no_rows()); 00241 // `source1' and `source2' must have the same number of columns 00242 // to be merged. 00243 PPL_ASSERT(source1.num_columns() == source2.num_columns()); 00244 // `source1' and `source2' are fully sorted. 00245 PPL_ASSERT(source1.is_sorted() && source1.num_pending_rows() == 0); 00246 PPL_ASSERT(source2.is_sorted() && source2.num_pending_rows() == 0); 00247 PPL_ASSERT(dest.num_pending_rows() == 0); 00248 00249 const dimension_type old_source1_num_rows = source1.num_rows(); 00250 // `k1' and `k2' run through the rows of `source1' and `source2', resp. 00251 dimension_type k1 = 0; 00252 dimension_type k2 = 0; 00253 dimension_type source2_num_rows = source2.num_rows(); 00254 while (k1 < old_source1_num_rows && k2 < source2_num_rows) { 00255 // Add to `source1' the constraints from `source2', as pending rows. 00256 // We exploit the property that initially both `source1' and `source2' 00257 // are sorted and index `k1' only scans the non-pending rows of `source1', 00258 // so that it is not influenced by the pending rows appended to it. 00259 // This way no duplicate (i.e., trivially redundant) constraint 00260 // is introduced in `source1'. 00261 const int cmp = compare(source1[k1], source2[k2]); 00262 if (cmp == 0) { 00263 // We found the same row: there is no need to add `source2[k2]'. 00264 ++k2; 00265 // By sortedness, since `k1 < old_source1_num_rows', 00266 // we can increment index `k1' too. 00267 ++k1; 00268 } 00269 else if (cmp < 0) 00270 // By sortedness, we can increment `k1'. 00271 ++k1; 00272 else { 00273 // Here `cmp > 0'. 00274 // By sortedness, `source2[k2]' cannot be in `source1'. 00275 // We add it as a pending row of `source1' (sortedness unaffected). 00276 source1.add_pending_row(source2[k2]); 00277 // We can increment `k2'. 00278 ++k2; 00279 } 00280 } 00281 // Have we scanned all the rows in `source2'? 00282 if (k2 < source2_num_rows) 00283 // By sortedness, all the rows in `source2' having indexes 00284 // greater than or equal to `k2' were not in `source1'. 00285 // We add them as pending rows of 'source1' (sortedness not affected). 00286 for ( ; k2 < source2_num_rows; ++k2) 00287 source1.add_pending_row(source2[k2]); 00288 00289 if (source1.num_pending_rows() == 0) 00290 // No row was appended to `source1', because all the constraints 00291 // in `source2' were already in `source1'. 00292 // There is nothing left to do ... 00293 return false; 00294 00295 return add_and_minimize(con_to_gen, source1, dest, sat); 00296 }
| 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 1274 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().
01274 { 01275 // Dimension-compatibility check: 01276 // the dimension of `cg' can not be greater than space_dim. 01277 if (space_dim < cg.space_dimension()) 01278 throw_dimension_incompatible("add_congruence(cg)", "cg", cg); 01279 01280 // Handle the case of proper congruences first. 01281 if (cg.is_proper_congruence()) { 01282 if (cg.is_tautological()) 01283 return; 01284 if (cg.is_inconsistent()) { 01285 set_empty(); 01286 return; 01287 } 01288 // Non-trivial and proper congruences are not allowed. 01289 throw_invalid_argument("add_congruence(cg)", 01290 "cg is a non-trivial, proper congruence"); 01291 } 01292 01293 PPL_ASSERT(cg.is_equality()); 01294 // Handle empty and 0-dim cases first. 01295 if (marked_empty()) 01296 return; 01297 if (space_dim == 0) { 01298 if (cg.is_inconsistent()) 01299 set_empty(); 01300 return; 01301 } 01302 01303 // Add the equality. 01304 Linear_Expression le(cg); 01305 Constraint c(le, Constraint::EQUALITY, NECESSARILY_CLOSED); 01306 // Enforce normalization. 01307 c.strong_normalize(); 01308 refine_no_check(c); 01309 }
| 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 1647 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_recycled_congruences(), Parma_Polyhedra_Library::C_Polyhedron::C_Polyhedron(), and Parma_Polyhedra_Library::NNC_Polyhedron::NNC_Polyhedron().
01647 { 01648 // Dimension-compatibility check. 01649 if (space_dim < cgs.space_dimension()) 01650 throw_dimension_incompatible("add_congruences(cgs)", "cgs", cgs); 01651 01652 Constraint_System cs; 01653 bool inserted = false; 01654 for (Congruence_System::const_iterator i = cgs.begin(), 01655 cgs_end = cgs.end(); i != cgs_end; ++i) { 01656 const Congruence& cg = *i; 01657 if (cg.is_equality()) { 01658 Linear_Expression le(cg); 01659 Constraint c(le, Constraint::EQUALITY, NECESSARILY_CLOSED); 01660 // Enforce normalization. 01661 c.strong_normalize(); 01662 // TODO: Consider stealing the row in c when adding it to cs. 01663 cs.insert(c); 01664 inserted = true; 01665 } 01666 else { 01667 PPL_ASSERT(cg.is_proper_congruence()); 01668 if (cg.is_inconsistent()) { 01669 set_empty(); 01670 return; 01671 } 01672 if (!cg.is_tautological()) 01673 throw_invalid_argument("add_congruences(cgs)", 01674 "cgs has a non-trivial, proper congruence"); 01675 } 01676 } 01677 // Only add cs if it contains something. 01678 if (inserted) 01679 add_recycled_constraints(cs); 01680 }
| 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 1250 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< PSET >::affine_dimension(), BHZ09_NNC_poly_hull_assign_if_exact(), Parma_Polyhedra_Library::C_Polyhedron::C_Polyhedron(), and Parma_Polyhedra_Library::Pointset_Powerset< PSET >::linear_partition_aux().
01250 { 01251 // Topology-compatibility check. 01252 if (c.is_strict_inequality() && is_necessarily_closed()) { 01253 // Trivially true/false strict inequalities are legal. 01254 if (c.is_tautological()) 01255 return; 01256 if (c.is_inconsistent()) { 01257 set_empty(); 01258 return; 01259 } 01260 // Here c is a non-trivial strict inequality. 01261 throw_topology_incompatible("add_constraint(c)", "c", c); 01262 } 01263 01264 // Dimension-compatibility check: 01265 // the dimension of `c' can not be greater than space_dim. 01266 if (space_dim < c.space_dimension()) 01267 throw_dimension_incompatible("add_constraint(c)", "c", c); 01268 01269 if (!marked_empty()) 01270 refine_no_check(c); 01271 }
| 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_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 1312 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(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Generator::space_dimension(), throw_dimension_incompatible(), throw_invalid_generator(), throw_runtime_error(), throw_topology_incompatible(), topology(), Parma_Polyhedra_Library::Generator::type(), and update_generators().
Referenced by BFT00_poly_hull_assign_if_exact(), BHZ09_C_poly_hull_assign_if_exact(), BHZ09_NNC_poly_hull_assign_if_exact(), and generalized_affine_image().
01312 { 01313 // Topology-compatibility check. 01314 if (g.is_closure_point() && is_necessarily_closed()) 01315 throw_topology_incompatible("add_generator(g)", "g", g); 01316 // Dimension-compatibility check: 01317 // the dimension of `g' can not be greater than space_dim. 01318 const dimension_type g_space_dim = g.space_dimension(); 01319 if (space_dim < g_space_dim) 01320 throw_dimension_incompatible("add_generator(g)", "g", g); 01321 01322 // Dealing with a zero-dimensional space polyhedron first. 01323 if (space_dim == 0) { 01324 // It is not possible to create 0-dim rays or lines. 01325 PPL_ASSERT(g.is_point() || g.is_closure_point()); 01326 // Closure points can only be inserted in non-empty polyhedra. 01327 if (marked_empty()) { 01328 if (g.type() != Generator::POINT) 01329 throw_invalid_generator("add_generator(g)", "g"); 01330 else 01331 set_zero_dim_univ(); 01332 } 01333 PPL_ASSERT_HEAVY(OK()); 01334 return; 01335 } 01336 01337 if (marked_empty() 01338 || (has_pending_constraints() && !process_pending_constraints()) 01339 || (!generators_are_up_to_date() && !update_generators())) { 01340 // Here the polyhedron is empty: 01341 // the specification says we can only insert a point. 01342 if (!g.is_point()) 01343 throw_invalid_generator("add_generator(g)", "g"); 01344 if (g.is_necessarily_closed() || !is_necessarily_closed()) { 01345 gen_sys.insert(g); 01346 // Since `gen_sys' was empty, after inserting `g' we have to resize 01347 // the system of generators to have the right dimension. 01348 gen_sys.adjust_topology_and_space_dimension(topology(), space_dim); 01349 if (!is_necessarily_closed()) { 01350 // In the NNC topology, each point has to be matched by 01351 // a corresponding closure point: 01352 // turn the just inserted point into the corresponding 01353 // (normalized) closure point. 01354 Generator& cp = gen_sys[gen_sys.num_rows() - 1]; 01355 cp[space_dim + 1] = 0; 01356 cp.normalize(); 01357 // Re-insert the point (which is already normalized). 01358 gen_sys.insert(g); 01359 } 01360 } 01361 else { 01362 // Note: here we have a _legal_ topology mismatch, 01363 // because `g' is NOT a closure point (it is a point!) 01364 // However, by barely invoking `gen_sys.insert(g)' we would 01365 // cause a change in the topology of `gen_sys', which is wrong. 01366 // Thus, we insert a "topology corrected" copy of `g'. 01367 const Linear_Expression nc_expr = Linear_Expression(g); 01368 gen_sys.insert(Generator::point(nc_expr, g.divisor())); 01369 // Since `gen_sys' was empty, after inserting `g' we have to resize 01370 // the system of generators to have the right dimension. 01371 gen_sys.adjust_topology_and_space_dimension(topology(), space_dim); 01372 } 01373 // No longer empty, generators up-to-date and minimized. 01374 clear_empty(); 01375 set_generators_minimized(); 01376 } 01377 else { 01378 PPL_ASSERT(generators_are_up_to_date()); 01379 const bool has_pending = can_have_something_pending(); 01380 if (g.is_necessarily_closed() || !is_necessarily_closed()) { 01381 // Since `gen_sys' is not empty, the topology and space dimension 01382 // of the inserted generator are automatically adjusted. 01383 if (has_pending) 01384 gen_sys.insert_pending(g); 01385 else 01386 gen_sys.insert(g); 01387 if (!is_necessarily_closed() && g.is_point()) { 01388 // In the NNC topology, each point has to be matched by 01389 // a corresponding closure point: 01390 // turn the just inserted point into the corresponding 01391 // (normalized) closure point. 01392 Generator& cp = gen_sys[gen_sys.num_rows() - 1]; 01393 cp[space_dim + 1] = 0; 01394 cp.normalize(); 01395 // Re-insert the point (which is already normalized). 01396 if (has_pending) 01397 gen_sys.insert_pending(g); 01398 else 01399 gen_sys.insert(g); 01400 } 01401 } 01402 else { 01403 PPL_ASSERT(!g.is_closure_point()); 01404 // Note: here we have a _legal_ topology mismatch, because 01405 // `g' is NOT a closure point. 01406 // However, by barely invoking `gen_sys.insert(g)' we would 01407 // cause a change in the topology of `gen_sys', which is wrong. 01408 // Thus, we insert a "topology corrected" copy of `g'. 01409 const Linear_Expression nc_expr = Linear_Expression(g); 01410 switch (g.type()) { 01411 case Generator::LINE: 01412 if (has_pending) 01413 gen_sys.insert_pending(Generator::line(nc_expr)); 01414 else 01415 gen_sys.insert(Generator::line(nc_expr)); 01416 break; 01417 case Generator::RAY: 01418 if (has_pending) 01419 gen_sys.insert_pending(Generator::ray(nc_expr)); 01420 else 01421 gen_sys.insert(Generator::ray(nc_expr)); 01422 break; 01423 case Generator::POINT: 01424 if (has_pending) 01425 gen_sys.insert_pending(Generator::point(nc_expr, g.divisor())); 01426 else 01427 gen_sys.insert(Generator::point(nc_expr, g.divisor())); 01428 break; 01429 default: 01430 throw_runtime_error("add_generator(const Generator& g)"); 01431 } 01432 } 01433 01434 if (has_pending) 01435 set_generators_pending(); 01436 else { 01437 // After adding the new generator, 01438 // constraints are no longer up-to-date. 01439 clear_generators_minimized(); 01440 clear_constraints_up_to_date(); 01441 } 01442 } 01443 PPL_ASSERT_HEAVY(OK()); 01444 }
| 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 1640 of file Polyhedron_public.cc.
References add_recycled_generators().
01640 { 01641 // TODO: this is just an executable specification. 01642 Generator_System gs_copy = gs; 01643 add_recycled_generators(gs_copy); 01644 }
| 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 372 of file Polyhedron.inlines.hh.
References add_congruences().
00372 { 00373 add_congruences(cgs); 00374 }
| 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(), 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 PPL_ASSERT_HEAVY(OK()); 01537 }
| 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 1547 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(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Generator_System::space_dimension(), Parma_Polyhedra_Library::swap(), 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().
01547 { 01548 // Topology compatibility check. 01549 if (is_necessarily_closed() && gs.has_closure_points()) 01550 throw_topology_incompatible("add_recycled_generators(gs)", "gs", gs); 01551 // Dimension-compatibility check: 01552 // the dimension of `gs' can not be greater than space_dim. 01553 const dimension_type gs_space_dim = gs.space_dimension(); 01554 if (space_dim < gs_space_dim) 01555 throw_dimension_incompatible("add_recycled_generators(gs)", "gs", gs); 01556 01557 // Adding no generators is a no-op. 01558 if (gs.has_no_rows()) 01559 return; 01560 01561 // Adding valid generators to a zero-dimensional polyhedron 01562 // transform it in the zero-dimensional universe polyhedron. 01563 if (space_dim == 0) { 01564 if (marked_empty() && !gs.has_points()) 01565 throw_invalid_generators("add_recycled_generators(gs)", "gs"); 01566 set_zero_dim_univ(); 01567 PPL_ASSERT_HEAVY(OK(true)); 01568 return; 01569 } 01570 01571 // Adjust `gs' to the right topology and dimensions. 01572 // NOTE: we already checked for topology compatibility. 01573 gs.adjust_topology_and_space_dimension(topology(), space_dim); 01574 // For NNC polyhedra, each point must be matched by 01575 // the corresponding closure point. 01576 if (!is_necessarily_closed()) 01577 gs.add_corresponding_closure_points(); 01578 01579 // The generators (possibly with pending rows) are required. 01580 if ((has_pending_constraints() && !process_pending_constraints()) 01581 || (!generators_are_up_to_date() && !minimize())) { 01582 // We have just discovered that `*this' is empty. 01583 // So `gs' must contain at least one point. 01584 if (!gs.has_points()) 01585 throw_invalid_generators("add_recycled_generators(gs)", "gs"); 01586 // The polyhedron is no longer empty and generators are up-to-date. 01587 std::swap(gen_sys, gs); 01588 if (gen_sys.num_pending_rows() > 0) { 01589 // Even though `gs' has pending generators, since the constraints 01590 // of the polyhedron are not up-to-date, the polyhedron cannot 01591 // have pending generators. By integrating the pending part 01592 // of `gen_sys' we may loose sortedness. 01593 gen_sys.unset_pending_rows(); 01594 gen_sys.set_sorted(false); 01595 } 01596 set_generators_up_to_date(); 01597 clear_empty(); 01598 PPL_ASSERT_HEAVY(OK()); 01599 return; 01600 } 01601 01602 const bool adding_pending = can_have_something_pending(); 01603 01604 // Here we do not require `gen_sys' to be sorted. 01605 // also, we _swap_ (instead of copying) the coefficients of `gs' 01606 // (which is not a const). 01607 const dimension_type old_num_rows = gen_sys.num_rows(); 01608 const dimension_type gs_num_rows = gs.num_rows(); 01609 const dimension_type gs_num_columns = gs.num_columns(); 01610 gen_sys.add_zero_rows(gs_num_rows, 01611 Linear_Row::Flags(topology(), 01612 Linear_Row::RAY_OR_POINT_OR_INEQUALITY)); 01613 for (dimension_type i = gs_num_rows; i-- > 0; ) { 01614 // NOTE: we cannot directly swap the rows, since they might have 01615 // different capacities (besides possibly having different sizes): 01616 // thus, we steal one coefficient at a time. 01617 Generator& new_g = gen_sys[old_num_rows + i]; 01618 Generator& old_g = gs[i]; 01619 if (old_g.is_line()) 01620 new_g.set_is_line(); 01621 for (dimension_type j = gs_num_columns; j-- > 0; ) 01622 std::swap(new_g[j], old_g[j]); 01623 } 01624 01625 if (adding_pending) 01626 set_generators_pending(); 01627 else { 01628 // The newly added ones are not pending generators. 01629 gen_sys.unset_pending_rows(); 01630 // They have been simply appended. 01631 gen_sys.set_sorted(false); 01632 // Constraints are not up-to-date and generators are not minimized. 01633 clear_constraints_up_to_date(); 01634 clear_generators_minimized(); 01635 } 01636 PPL_ASSERT_HEAVY(OK(true)); 01637 }
| 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. |
Adds new space dimensions to the vector space modifying the matrices. This function is invoked only by 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 36 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(), swap(), 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().
00040 { 00041 PPL_ASSERT(sys1.topology() == sys2.topology()); 00042 PPL_ASSERT(sys1.num_columns() == sys2.num_columns()); 00043 PPL_ASSERT(add_dim != 0); 00044 00045 sys1.add_zero_columns(add_dim); 00046 dimension_type old_index = sys2.first_pending_row(); 00047 sys2.add_rows_and_columns(add_dim); 00048 // The added rows are in the non-pending part. 00049 sys2.set_index_first_pending_row(old_index + add_dim); 00050 00051 // The resulting saturation matrix will be as follows: 00052 // from row 0 to add_dim-1 : only zeroes 00053 // add_dim add_dim+num_rows-1 : old saturation matrix 00054 00055 // In fact all the old generators saturate all the new constraints 00056 // because the polyhedron has not been embedded in the new space. 00057 sat1.resize(sat1.num_rows() + add_dim, sat1.num_columns()); 00058 // The old matrix is moved to the end of the new matrix. 00059 for (dimension_type i = sat1.num_rows() - add_dim; i-- > 0; ) 00060 std::swap(sat1[i], sat1[i+add_dim]); 00061 // Computes the "sat_c", too. 00062 sat2.transpose_assign(sat1); 00063 00064 if (!sys1.is_necessarily_closed()) { 00065 // Moving the epsilon coefficients to the new last column. 00066 dimension_type new_eps_index = sys1.num_columns() - 1; 00067 dimension_type old_eps_index = new_eps_index - add_dim; 00068 // This swap preserves sortedness of `sys1'. 00069 sys1.swap_columns(old_eps_index, new_eps_index); 00070 00071 // Try to preserve sortedness of `sys2'. 00072 if (!sys2.is_sorted()) 00073 sys2.swap_columns(old_eps_index, new_eps_index); 00074 else { 00075 for (dimension_type i = sys2.num_rows(); i-- > add_dim; ) { 00076 Linear_Row& r = sys2[i]; 00077 std::swap(r[old_eps_index], r[new_eps_index]); 00078 } 00079 // The upper-right corner of `sys2' contains the J matrix: 00080 // swap coefficients to preserve sortedness. 00081 for (dimension_type i = add_dim; i-- > 0; ++old_eps_index) { 00082 Linear_Row& r = sys2[i]; 00083 std::swap(r[old_eps_index], r[old_eps_index + 1]); 00084 } 00085 } 00086 // NOTE: since we swapped columns in both `sys1' and `sys2', 00087 // no swapping is required for `sat1' and `sat2'. 00088 } 00089 }
| 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(). |
The new space dimensions will be those having the highest indexes in the new polyhedron, which is characterized by a system of constraints in which the variables running through the new dimensions are not constrained. For instance, when starting from the polyhedron
and adding a third space dimension, the result will be the polyhedron
Definition at line 92 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, 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().
00092 { 00093 // The space dimension of the resulting polyhedron should not 00094 // overflow the maximum allowed space dimension. 00095 if (m > max_space_dimension() - space_dimension()) 00096 throw_space_dimension_overflow(topology(), 00097 "add_space_dimensions_and_embed(m)", 00098 "adding m new space dimensions exceeds " 00099 "the maximum allowed space dimension"); 00100 00101 // Adding no dimensions to any polyhedron is a no-op. 00102 if (m == 0) 00103 return; 00104 00105 // Adding dimensions to an empty polyhedron is obtained by adjusting 00106 // `space_dim' and clearing `con_sys' (since it can contain the 00107 // unsatisfiable constraint system of the wrong dimension). 00108 if (marked_empty()) { 00109 space_dim += m; 00110 con_sys.clear(); 00111 return; 00112 } 00113 00114 // The case of a zero-dimensional space polyhedron. 00115 if (space_dim == 0) { 00116 // Since it is not empty, it has to be the universe polyhedron. 00117 PPL_ASSERT(status.test_zero_dim_univ()); 00118 // We swap `*this' with a newly created 00119 // universe polyhedron of dimension `m'. 00120 Polyhedron ph(topology(), m, UNIVERSE); 00121 swap(ph); 00122 return; 00123 } 00124 00125 // To embed an n-dimension space polyhedron in a (n+m)-dimension space, 00126 // we just add `m' zero-columns to the rows in the system of constraints; 00127 // in contrast, the system of generators needs additional rows, 00128 // corresponding to the vectors of the canonical basis 00129 // for the added dimensions. That is, for each new dimension `x[k]' 00130 // we add the line having that direction. This is done by invoking 00131 // the function add_space_dimensions() giving the system of generators 00132 // as the second argument. 00133 if (constraints_are_up_to_date()) 00134 if (generators_are_up_to_date()) { 00135 // `sat_c' must be up to date for add_space_dimensions(). 00136 if (!sat_c_is_up_to_date()) 00137 update_sat_c(); 00138 // Adds rows and/or columns to both matrices. 00139 // `add_space_dimensions' correctly handles pending constraints 00140 // or generators. 00141 add_space_dimensions(con_sys, gen_sys, sat_c, sat_g, m); 00142 } 00143 else { 00144 // Only constraints are up-to-date: no need to modify the generators. 00145 con_sys.add_zero_columns(m); 00146 // If the polyhedron is not necessarily closed, 00147 // move the epsilon coefficients to the last column. 00148 if (!is_necessarily_closed()) 00149 con_sys.swap_columns(space_dim + 1, space_dim + 1 + m); 00150 } 00151 else { 00152 // Only generators are up-to-date: no need to modify the constraints. 00153 PPL_ASSERT(generators_are_up_to_date()); 00154 gen_sys.add_rows_and_columns(m); 00155 // The polyhedron does not support pending generators. 00156 gen_sys.unset_pending_rows(); 00157 // If the polyhedron is not necessarily closed, 00158 // move the epsilon coefficients to the last column. 00159 if (!is_necessarily_closed()) { 00160 // Try to preserve sortedness of `gen_sys'. 00161 if (!gen_sys.is_sorted()) 00162 gen_sys.swap_columns(space_dim + 1, space_dim + 1 + m); 00163 else { 00164 dimension_type old_eps_index = space_dim + 1; 00165 dimension_type new_eps_index = old_eps_index + m; 00166 for (dimension_type i = gen_sys.num_rows(); i-- > m; ) { 00167 Generator& r = gen_sys[i]; 00168 std::swap(r[old_eps_index], r[new_eps_index]); 00169 } 00170 // The upper-right corner of `gen_sys' contains the J matrix: 00171 // swap coefficients to preserve sortedness. 00172 for (dimension_type i = m; i-- > 0; ++old_eps_index) { 00173 Generator& r = gen_sys[i]; 00174 std::swap(r[old_eps_index], r[old_eps_index + 1]); 00175 } 00176 } 00177 } 00178 } 00179 // Update the space dimension. 00180 space_dim += m; 00181 00182 // Note: we do not check for satisfiability, because the system of 00183 // constraints may be unsatisfiable. 00184 PPL_ASSERT_HEAVY(OK()); 00185 }
| 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(). |
The new space dimensions will be those having the highest indexes in the new polyhedron, which is characterized by a system of constraints in which the variables running through the new dimensions are all constrained to be equal to 0. For instance, when starting from the polyhedron
and adding a third space dimension, the result will be the polyhedron
Definition at line 188 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, 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().
00188 { 00189 // The space dimension of the resulting polyhedron should not 00190 // overflow the maximum allowed space dimension. 00191 if (m > max_space_dimension() - space_dimension()) 00192 throw_space_dimension_overflow(topology(), 00193 "add_space_dimensions_and_project(m)", 00194 "adding m new space dimensions exceeds " 00195 "the maximum allowed space dimension"); 00196 00197 // Adding no dimensions to any polyhedron is a no-op. 00198 if (m == 0) 00199 return; 00200 00201 // Adding dimensions to an empty polyhedron is obtained 00202 // by merely adjusting `space_dim'. 00203 if (marked_empty()) { 00204 space_dim += m; 00205 con_sys.clear(); 00206 return; 00207 } 00208 00209 if (space_dim == 0) { 00210 PPL_ASSERT(status.test_zero_dim_univ() && gen_sys.has_no_rows()); 00211 // The system of generators for this polyhedron has only 00212 // the origin as a point. 00213 // In an NNC polyhedron, all points have to be accompanied 00214 // by the corresponding closure points 00215 // (this time, dimensions are automatically adjusted). 00216 if (!is_necessarily_closed()) 00217 gen_sys.insert(Generator::zero_dim_closure_point()); 00218 gen_sys.insert(Generator::zero_dim_point()); 00219 gen_sys.adjust_topology_and_space_dimension(topology(), m); 00220 set_generators_minimized(); 00221 space_dim = m; 00222 PPL_ASSERT_HEAVY(OK()); 00223 return; 00224 } 00225 00226 // To project an n-dimension space polyhedron in a (n+m)-dimension space, 00227 // we just add to the system of generators `m' zero-columns; 00228 // In contrast, in the system of constraints, new rows are needed 00229 // in order to avoid embedding the old polyhedron in the new space. 00230 // Thus, for each new dimensions `x[k]', we add the constraint 00231 // x[k] = 0; this is done by invoking the function add_space_dimensions() 00232 // giving the system of constraints as the second argument. 00233 if (constraints_are_up_to_date()) 00234 if (generators_are_up_to_date()) { 00235 // `sat_g' must be up to date for add_space_dimensions(). 00236 if (!sat_g_is_up_to_date()) 00237 update_sat_g(); 00238 // Adds rows and/or columns to both matrices. 00239 // `add_space_dimensions' correctly handles pending constraints 00240 // or generators. 00241 add_space_dimensions(gen_sys, con_sys, sat_g, sat_c, m); 00242 } 00243 else { 00244 // Only constraints are up-to-date: no need to modify the generators. 00245 con_sys.add_rows_and_columns(m); 00246 // The polyhedron does not support pending constraints. 00247 con_sys.unset_pending_rows(); 00248 // If the polyhedron is not necessarily closed, 00249 // move the epsilon coefficients to the last column. 00250 if (!is_necessarily_closed()) { 00251 // Try to preserve sortedness of `con_sys'. 00252 if (!con_sys.is_sorted()) 00253 con_sys.swap_columns(space_dim + 1, space_dim + 1 + m); 00254 else { 00255 dimension_type old_eps_index = space_dim + 1; 00256 dimension_type new_eps_index = old_eps_index + m; 00257 for (dimension_type i = con_sys.num_rows(); i-- > m; ) { 00258 Constraint& r = con_sys[i]; 00259 std::swap(r[old_eps_index], r[new_eps_index]); 00260 } 00261 // The upper-right corner of `con_sys' contains the J matrix: 00262 // swap coefficients to preserve sortedness. 00263 for (dimension_type i = m; i-- > 0; ++old_eps_index) { 00264 Constraint& r = con_sys[i]; 00265 std::swap(r[old_eps_index], r[old_eps_index + 1]); 00266 } 00267 } 00268 } 00269 } 00270 else { 00271 // Only generators are up-to-date: no need to modify the constraints. 00272 PPL_ASSERT(generators_are_up_to_date()); 00273 gen_sys.add_zero_columns(m); 00274 // If the polyhedron is not necessarily closed, 00275 // move the epsilon coefficients to the last column. 00276 if (!is_necessarily_closed()) 00277 gen_sys.swap_columns(space_dim + 1, space_dim + 1 + m); 00278 } 00279 // Now we update the space dimension. 00280 space_dim += m; 00281 00282 // Note: we do not check for satisfiability, because the system of 00283 // constraints may be unsatisfiable. 00284 PPL_ASSERT_HEAVY(OK()); 00285 }
| 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 60 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< PSET >::affine_dimension(), BHZ09_C_poly_hull_assign_if_exact(), and is_discrete().
00060 { 00061 if (is_empty()) 00062 return 0; 00063 00064 const Constraint_System& cs = minimized_constraints(); 00065 dimension_type d = space_dim; 00066 for (Constraint_System::const_iterator i = cs.begin(), 00067 cs_end = cs.end(); i != cs_end; ++i) 00068 if (i->is_equality()) 00069 --d; 00070 return d; 00071 }
| 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. |
When considering the generators of a polyhedron, the affine transformation
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.,
) is different from zero.
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 2557 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(), 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().
02559 { 02560 // The denominator cannot be zero. 02561 if (denominator == 0) 02562 throw_invalid_argument("affine_image(v, e, d)", "d == 0"); 02563 02564 // Dimension-compatibility checks. 02565 // The dimension of `expr' should not be greater than the dimension 02566 // of `*this'. 02567 if (space_dim < expr.space_dimension()) 02568 throw_dimension_incompatible("affine_image(v, e, d)", "e", expr); 02569 // `var' should be one of the dimensions of the polyhedron. 02570 const dimension_type var_space_dim = var.space_dimension(); 02571 if (space_dim < var_space_dim) 02572 throw_dimension_incompatible("affine_image(v, e, d)", "v", var); 02573 02574 if (marked_empty()) 02575 return; 02576 02577 if (expr.coefficient(var) != 0) { 02578 // The transformation is invertible: 02579 // minimality and saturators are preserved, so that 02580 // pending rows, if present, are correctly handled. 02581 if (generators_are_up_to_date()) { 02582 // Generator_System::affine_image() requires the third argument 02583 // to be a positive Coefficient. 02584 if (denominator > 0) 02585 gen_sys.affine_image(var_space_dim, expr, denominator); 02586 else 02587 gen_sys.affine_image(var_space_dim, -expr, -denominator); 02588 } 02589 if (constraints_are_up_to_date()) { 02590 // To build the inverse transformation, 02591 // after copying and negating `expr', 02592 // we exchange the roles of `expr[var_space_dim]' and `denominator'. 02593 Linear_Expression inverse; 02594 if (expr[var_space_dim] > 0) { 02595 inverse = -expr; 02596 inverse[var_space_dim] = denominator; 02597 con_sys.affine_preimage(var_space_dim, inverse, expr[var_space_dim]); 02598 } 02599 else { 02600 // The new denominator is negative: we negate everything once 02601 // more, as Constraint_System::affine_preimage() requires the 02602 // third argument to be positive. 02603 inverse = expr; 02604 inverse[var_space_dim] = denominator; 02605 neg_assign(inverse[var_space_dim]); 02606 con_sys.affine_preimage(var_space_dim, inverse, -expr[var_space_dim]); 02607 } 02608 } 02609 } 02610 else { 02611 // The transformation is not invertible. 02612 // We need an up-to-date system of generators. 02613 if (has_something_pending()) 02614 remove_pending_to_obtain_generators(); 02615 else if (!generators_are_up_to_date()) 02616 minimize(); 02617 if (!marked_empty()) { 02618 // Generator_System::affine_image() requires the third argument 02619 // to be a positive Coefficient. 02620 if (denominator > 0) 02621 gen_sys.affine_image(var_space_dim, expr, denominator); 02622 else 02623 gen_sys.affine_image(var_space_dim, -expr, -denominator); 02624 02625 clear_constraints_up_to_date(); 02626 clear_generators_minimized(); 02627 clear_sat_c_up_to_date(); 02628 clear_sat_g_up_to_date(); 02629 } 02630 } 02631 PPL_ASSERT_HEAVY(OK()); 02632 }
| 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. |
When considering constraints of a polyhedron, the affine transformation
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.
) is different from zero.
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 2637 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(), 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().
02639 { 02640 // The denominator cannot be zero. 02641 if (denominator == 0) 02642 throw_invalid_argument("affine_preimage(v, e, d)", "d == 0"); 02643 02644 // Dimension-compatibility checks. 02645 // The dimension of `expr' should not be greater than the dimension 02646 // of `*this'. 02647 if (space_dim < expr.space_dimension()) 02648 throw_dimension_incompatible("affine_preimage(v, e, d)", "e", expr); 02649 // `var' should be one of the dimensions of the polyhedron. 02650 const dimension_type var_space_dim = var.space_dimension(); 02651 if (space_dim < var_space_dim) 02652 throw_dimension_incompatible("affine_preimage(v, e, d)", "v", var); 02653 02654 if (marked_empty()) 02655 return; 02656 02657 if (expr.coefficient(var) != 0) { 02658 // The transformation is invertible: 02659 // minimality and saturators are preserved. 02660 if (constraints_are_up_to_date()) { 02661 // Constraint_System::affine_preimage() requires the third argument 02662 // to be a positive Coefficient. 02663 if (denominator > 0) 02664 con_sys.affine_preimage(var_space_dim, expr, denominator); 02665 else 02666 con_sys.affine_preimage(var_space_dim, -expr, -denominator); 02667 } 02668 if (generators_are_up_to_date()) { 02669 // To build the inverse transformation, 02670 // after copying and negating `expr', 02671 // we exchange the roles of `expr[var_space_dim]' and `denominator'. 02672 Linear_Expression inverse; 02673 if (expr[var_space_dim] > 0) { 02674 inverse = -expr; 02675 inverse[var_space_dim] = denominator; 02676 gen_sys.affine_image(var_space_dim, inverse, expr[var_space_dim]); 02677 } 02678 else { 02679 // The new denominator is negative: 02680 // we negate everything once more, as Generator_System::affine_image() 02681 // requires the third argument to be positive. 02682 inverse = expr; 02683 inverse[var_space_dim] = denominator; 02684 neg_assign(inverse[var_space_dim]); 02685 gen_sys.affine_image(var_space_dim, inverse, -expr[var_space_dim]); 02686 } 02687 } 02688 } 02689 else { 02690 // The transformation is not invertible. 02691 // We need an up-to-date system of constraints. 02692 if (has_something_pending()) 02693 remove_pending_to_obtain_constraints(); 02694 else if (!constraints_are_up_to_date()) 02695 minimize(); 02696 // Constraint_System::affine_preimage() requires the third argument 02697 // to be a positive Coefficient. 02698 if (denominator > 0) 02699 con_sys.affine_preimage(var_space_dim, expr, denominator); 02700 else 02701 con_sys.affine_preimage(var_space_dim, -expr, -denominator); 02702 // Generators, minimality and saturators are no longer valid. 02703 clear_generators_up_to_date(); 02704 clear_constraints_minimized(); 02705 clear_sat_c_up_to_date(); 02706 clear_sat_g_up_to_date(); 02707 } 02708 PPL_ASSERT_HEAVY(OK()); 02709 }
| void Parma_Polyhedra_Library::Polyhedron::ascii_dump | ( | std::ostream & | s | ) | const |
Writes to s an ASCII representation of *this.
Definition at line 3676 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, and status.
03676 { 03677 s << "space_dim " << space_dim << "\n"; 03678 status.ascii_dump(s); 03679 s << "\ncon_sys (" 03680 << (constraints_are_up_to_date() ? "" : "not_") 03681 << "up-to-date)" 03682 << "\n"; 03683 con_sys.ascii_dump(s); 03684 s << "\ngen_sys (" 03685 << (generators_are_up_to_date() ? "" : "not_") 03686 << "up-to-date)" 03687 << "\n"; 03688 gen_sys.ascii_dump(s); 03689 s << "\nsat_c\n"; 03690 sat_c.ascii_dump(s); 03691 s << "\nsat_g\n"; 03692 sat_g.ascii_dump(s); 03693 s << "\n"; 03694 }
| void Parma_Polyhedra_Library::Polyhedron::ascii_dump | ( | ) | const |
Writes to std::cerr an ASCII representation of *this.
Referenced by OK().
| 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 3699 of file Polyhedron_public.cc.
03699 { 03700 std::string str; 03701 03702 if (!(s >> str) || str != "space_dim") 03703 return false; 03704 03705 if (!(s >> space_dim)) 03706 return false; 03707 03708 if (!status.ascii_load(s)) 03709 return false; 03710 03711 if (!(s >> str) || str != "con_sys") 03712 return false; 03713 03714 if (!(s >> str) || (str != "(not_up-to-date)" && str != "(up-to-date)")) 03715 return false; 03716 03717 if (!con_sys.ascii_load(s)) 03718 return false; 03719 03720 if (!(s >> str) || str != "gen_sys") 03721 return false; 03722 03723 if (!(s >> str) || (str != "(not_up-to-date)" && str != "(up-to-date)")) 03724 return false; 03725 03726 if (!gen_sys.ascii_load(s)) 03727 return false; 03728 03729 if (!(s >> str) || str != "sat_c") 03730 return false; 03731 03732 if (!sat_c.ascii_load(s)) 03733 return false; 03734 03735 if (!(s >> str) || str != "sat_g") 03736 return false; 03737 03738 if (!sat_g.ascii_load(s)) 03739 return false; 03740 03741 // Check invariants. 03742 PPL_ASSERT_HEAVY(OK()); 03743 return true; 03744 }
| bool Parma_Polyhedra_Library::Polyhedron::BFT00_poly_hull_assign_if_exact | ( | const Polyhedron & | y | ) | [protected] |
If the poly-hull of *this and y is exact it is assigned to *this and true is returned, otherwise false is returned.
Current implementation is based on (a variant of) Algorithm 8.1 in A. Bemporad, K. Fukuda, and F. D. Torrisi Convexity Recognition of the Union of Polyhedra Technical Report AUT00-13, ETH Zurich, 2000
*this and y are topologically closed and dimension-compatible; if the assumption does not hold, the behavior is undefined. Definition at line 1883 of file Polyhedron_nonpublic.cc.
References add_generator(), Parma_Polyhedra_Library::Linear_Row::all_homogeneous_terms_are_zero(), con_sys, gen_sys, Parma_Polyhedra_Library::Poly_Con_Relation::implies(), is_empty(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Linear_Row::is_line_or_equality(), is_necessarily_closed(), marked_empty(), minimize(), Parma_Polyhedra_Library::Row::normalize(), Parma_Polyhedra_Library::Poly_Gen_Relation::nothing(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), relation_with(), Parma_Polyhedra_Library::Linear_Row::set_is_ray_or_point_or_inequality(), Parma_Polyhedra_Library::Linear_Row::sign_normalize(), Parma_Polyhedra_Library::Row::size(), space_dim, Parma_Polyhedra_Library::Poly_Gen_Relation::subsumes(), topology(), and upper_bound_assign().
Referenced by Parma_Polyhedra_Library::C_Polyhedron::poly_hull_assign_if_exact().
01883 { 01884 // Declare a const reference to *this (to avoid accidental modifications). 01885 const Polyhedron& x = *this; 01886 // Private method: the caller must ensure the following. 01887 PPL_ASSERT(x.is_necessarily_closed()); 01888 PPL_ASSERT(x.topology() == y.topology()); 01889 PPL_ASSERT(x.space_dim == y.space_dim); 01890 01891 // The zero-dim case is trivial. 01892 if (x.space_dim == 0) { 01893 upper_bound_assign(y); 01894 return true; 01895 } 01896 // If `x' or `y' is (known to be) empty, the convex union is exact. 01897 if (x.marked_empty()) { 01898 *this = y; 01899 return true; 01900 } 01901 else if (y.is_empty()) 01902 return true; 01903 else if (x.is_empty()) { 01904 *this = y; 01905 return true; 01906 } 01907 01908 // Here both `x' and `y' are known to be non-empty. 01909 01910 // Implementation based on Algorithm 8.1 (page 15) in [BemporadFT00TR], 01911 // generalized so as to also allow for unbounded polyhedra. 01912 // The extension to unbounded polyhedra is obtained by mimicking 01913 // what done in Algorithm 8.2 (page 19) wrt Algorithm 6.2 (page 13). 01914 // We also apply a couple of improvements (see steps 2.1, 3.1, 6.1, 7.1) 01915 // so as to quickly handle special cases and avoid the splitting 01916 // of equalities/lines into pairs of inequalities/rays. 01917 01918 (void) x.minimize(); 01919 (void) y.minimize(); 01920 const Constraint_System& x_cs = x.con_sys; 01921 const Constraint_System& y_cs = y.con_sys; 01922 const Generator_System& x_gs = x.gen_sys; 01923 const Generator_System& y_gs = y.gen_sys; 01924 const dimension_type x_gs_num_rows = x_gs.num_rows(); 01925 const dimension_type y_gs_num_rows = y_gs.num_rows(); 01926 01927 // Step 1: generators of `x' that are redundant in `y', and vice versa. 01928 std::vector<bool> x_gs_red_in_y(x_gs_num_rows, false); 01929 dimension_type num_x_gs_red_in_y = 0; 01930 for (dimension_type i = x_gs_num_rows; i-- > 0; ) 01931 if (y.relation_with(x_gs[i]).implies(Poly_Gen_Relation::subsumes())) { 01932 x_gs_red_in_y[i] = true; 01933 ++num_x_gs_red_in_y; 01934 } 01935 std::vector<bool> y_gs_red_in_x(y_gs_num_rows, false); 01936 dimension_type num_y_gs_red_in_x = 0; 01937 for (dimension_type i = y_gs_num_rows; i-- > 0; ) 01938 if (x.relation_with(y_gs[i]).implies(Poly_Gen_Relation::subsumes())) { 01939 y_gs_red_in_x[i] = true; 01940 ++num_y_gs_red_in_x; 01941 } 01942 01943 // Step 2: if no redundant generator has been identified, 01944 // then the union is not convex. CHECKME: why? 01945 if (num_x_gs_red_in_y == 0 && num_y_gs_red_in_x == 0) 01946 return false; 01947 01948 // Step 2.1: while at it, also perform quick inclusion tests. 01949 if (num_y_gs_red_in_x == y_gs_num_rows) 01950 // `y' is included into `x': union is convex. 01951 return true; 01952 if (num_x_gs_red_in_y == x_gs_num_rows) { 01953 // `x' is included into `y': union is convex. 01954 *this = y; 01955 return true; 01956 } 01957 01958 // Here we know that `x' is not included in `y', and vice versa. 01959 01960 // Step 3: constraints of `x' that are satisfied by `y', and vice versa. 01961 const dimension_type x_cs_num_rows = x_cs.num_rows(); 01962 std::vector<bool> x_cs_red_in_y(x_cs_num_rows, false); 01963 for (dimension_type i = x_cs_num_rows; i-- > 0; ) { 01964 const Constraint& x_cs_i = x_cs[i]; 01965 if (y.relation_with(x_cs_i).implies(Poly_Con_Relation::is_included())) 01966 x_cs_red_in_y[i] = true; 01967 else if (x_cs_i.is_equality()) 01968 // Step 3.1: `x' has an equality not satified by `y': 01969 // union is not convex (recall that `y' does not contain `x'). 01970 // NOTE: this would be false for NNC polyhedra. 01971 // Example: x = { A == 0 }, y = { 0 < A <= 1 }. 01972 return false; 01973 } 01974 const dimension_type y_cs_num_rows = y_cs.num_rows(); 01975 std::vector<bool> y_cs_red_in_x(y_cs_num_rows, false); 01976 for (dimension_type i = y_cs_num_rows; i-- > 0; ) { 01977 const Constraint& y_cs_i = y_cs[i]; 01978 if (x.relation_with(y_cs_i).implies(Poly_Con_Relation::is_included())) 01979 y_cs_red_in_x[i] = true; 01980 else if (y_cs_i.is_equality()) 01981 // Step 3.1: `y' has an equality not satified by `x': 01982 // union is not convex (see explanation above). 01983 return false; 01984 } 01985 01986 // Loop in steps 5-9: for each pair of non-redundant generators, 01987 // compute their "mid-point" and check if it is both in `x' and `y'. 01988 01989 // Note: reasoning at the polyhedral cone level. 01990 // CHECKME, FIXME: Polyhedron is a (deprecated) friend of Generator. 01991 // Here below we systematically exploit such a friendship, so as to 01992 // freely reinterpret a Generator as a Linear_Row and vice versa. 01993 Linear_Row mid_row; 01994 const Generator& mid_g = static_cast<const Generator&>(mid_row); 01995 01996 for (dimension_type i = x_gs_num_rows; i-- > 0; ) { 01997 if (x_gs_red_in_y[i]) 01998 continue; 01999 const Linear_Row& x_row = static_cast<const Linear_Row&>(x_gs[i]); 02000 const dimension_type row_sz = x_row.size(); 02001 const bool x_row_is_line = x_row.is_line_or_equality(); 02002 for (dimension_type j = y_gs_num_rows; j-- > 0; ) { 02003 if (y_gs_red_in_x[j]) 02004 continue; 02005 const Linear_Row& y_row = static_cast<const Linear_Row&>(y_gs[j]); 02006 const bool y_row_is_line = y_row.is_line_or_equality(); 02007 02008 // Step 6: compute mid_row = x_row + y_row. 02009 // NOTE: no need to actually compute the "mid-point", 02010 // since any strictly positive combination would do. 02011 mid_row = x_row; 02012 for (dimension_type k = row_sz; k-- > 0; ) 02013 mid_row[k] += y_row[k]; 02014 // A zero ray is not a well formed generator. 02015 const bool illegal_ray 02016 = (mid_row[0] == 0 && mid_row.all_homogeneous_terms_are_zero()); 02017 // A zero ray cannot be generated from a line: this holds 02018 // because x_row (resp., y_row) is not subsumed by y (resp., x). 02019 PPL_ASSERT(!(illegal_ray && (x_row_is_line || y_row_is_line))); 02020 if (illegal_ray) 02021 continue; 02022 if (x_row_is_line) { 02023 mid_row.normalize(); 02024 if (y_row_is_line) 02025 // mid_row is a line too: sign normalization is needed. 02026 mid_row.sign_normalize(); 02027 else 02028 // mid_row is a ray/point. 02029 mid_row.set_is_ray_or_point_or_inequality(); 02030 } 02031 02032 // Step 7: check if mid_g is in the union of x and y. 02033 if (x.relation_with(mid_g) == Poly_Gen_Relation::nothing() 02034 && y.relation_with(mid_g) == Poly_Gen_Relation::nothing()) 02035 return false; 02036 02037 // If either x_row or y_row is a line, we should use its 02038 // negation to produce another generator to be tested too. 02039 // NOTE: exclusive-or is meant. 02040 if (!x_row_is_line && y_row_is_line) { 02041 // Step 6.1: (re-)compute mid_row = x_row - y_row. 02042 mid_row = x_row; 02043 for (dimension_type k = row_sz; k-- > 0; ) 02044 mid_row[k] -= y_row[k]; 02045 mid_row.normalize(); 02046 // Step 7.1: check if mid_g is in the union of x and y. 02047 if (x.relation_with(mid_g) == Poly_Gen_Relation::nothing() 02048 && y.relation_with(mid_g) == Poly_Gen_Relation::nothing()) 02049 return false; 02050 } 02051 else if (x_row_is_line && !y_row_is_line) { 02052 // Step 6.1: (re-)compute mid_row = - x_row + y_row. 02053 mid_row = y_row; 02054 for (dimension_type k = row_sz; k-- > 0; ) 02055 mid_row[k] -= x_row[k]; 02056 mid_row.normalize(); 02057 // Step 7.1: check if mid_g is in the union of x and y. 02058 if (x.relation_with(mid_g) == Poly_Gen_Relation::nothing() 02059 && y.relation_with(mid_g) == Poly_Gen_Relation::nothing()) 02060 return false; 02061 } 02062 } 02063 } 02064 02065 // Here we know that the union of x and y is convex. 02066 // TODO: exploit knowledge on the cardinality of non-redudnant 02067 // constraints/generators to improve the convex-hull computation. 02068 // Using generators allows for exploiting incrementality. 02069 for (dimension_type j = 0; j < y_gs_num_rows; ++j) { 02070 if (!y_gs_red_in_x[j]) 02071 add_generator(y_gs[j]); 02072 } 02073 PPL_ASSERT_HEAVY(OK()); 02074 return true; 02075 }
| 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 385 of file Polyhedron_widenings.cc.
References add_recycled_constraints(), Parma_Polyhedra_Library::Linear_Expression::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(), swap(), Parma_Polyhedra_Library::Linear_System::topology(), and topology().
Referenced by BHRZ03_widening_assign().
00388 { 00389 Polyhedron& x = *this; 00390 // It is assumed that `y <= x <= H79'. 00391 PPL_ASSERT(x.topology() == y.topology() 00392 && x.topology() == H79.topology() 00393 && x.topology() == x_minus_H79_cs.topology()); 00394 PPL_ASSERT(x.space_dim == y.space_dim 00395 && x.space_dim == H79.space_dim 00396 && x.space_dim == x_minus_H79_cs.space_dimension()); 00397 PPL_ASSERT(!x.marked_empty() && !x.has_something_pending() 00398 && x.constraints_are_minimized() && x.generators_are_minimized()); 00399 PPL_ASSERT(!y.marked_empty() && !y.has_something_pending() 00400 && y.constraints_are_minimized() && y.generators_are_minimized()); 00401 PPL_ASSERT(!H79.marked_empty() && !H79.has_something_pending() 00402 && H79.constraints_are_minimized() && H79.generators_are_minimized()); 00403 00404 // We will choose from `x_minus_H79_cs' many subsets of constraints, 00405 // that will be collected (one at a time) in `combining_cs'. 00406 // For each group collected, we compute an average constraint, 00407 // that will be stored in `new_cs'. 00408 00409 // There is no point in applying this technique when `x_minus_H79_cs' 00410 // has one constraint at most (no ``new'' constraint can be computed). 00411 const dimension_type x_minus_H79_cs_num_rows = x_minus_H79_cs.num_rows(); 00412 if (x_minus_H79_cs_num_rows <= 1) 00413 return false; 00414 00415 const Topology topol = x.topology(); 00416 Constraint_System combining_cs(topol); 00417 Constraint_System new_cs(topol); 00418 00419 // Consider the points that belong to both `x.gen_sys' and `y.gen_sys'. 00420 // For NNC polyhedra, the role of points is played by closure points. 00421 const bool closed = x.is_necessarily_closed(); 00422 for (dimension_type i = y.gen_sys.num_rows(); i-- > 0; ) { 00423 const Generator& g = y.gen_sys[i]; 00424 if ((g.is_point() && closed) || (g.is_closure_point() && !closed)) { 00425 // If in `H79.con_sys' there is already an inequality constraint 00426 // saturating this point, then there is no need to produce another 00427 // constraint. 00428 bool lies_on_the_boundary_of_H79 = false; 00429 const Constraint_System& H79_cs = H79.con_sys; 00430 for (dimension_type j = H79_cs.num_rows(); j-- > 0; ) { 00431 const Constraint& c = H79_cs[j]; 00432 if (c.is_inequality() && Scalar_Products::sign(c, g) == 0) { 00433 lies_on_the_boundary_of_H79 = true; 00434 break; 00435 } 00436 } 00437 if (lies_on_the_boundary_of_H79) 00438 continue; 00439 00440 // Consider all the constraints in `x_minus_H79_cs' 00441 // that are saturated by the point `g'. 00442 combining_cs.clear(); 00443 for (dimension_type j = x_minus_H79_cs_num_rows; j-- > 0; ) { 00444 const Constraint& c = x_minus_H79_cs[j]; 00445 if (Scalar_Products::sign(c, g) == 0) 00446 combining_cs.insert(c); 00447 } 00448 // Build a new constraint by combining all the chosen constraints. 00449 const dimension_type combining_cs_num_rows = combining_cs.num_rows(); 00450 if (combining_cs_num_rows > 0) { 00451 if (combining_cs_num_rows == 1) 00452 // No combination is needed. 00453 new_cs.insert(combining_cs[0]); 00454 else { 00455 Linear_Expression e(0); 00456 bool strict_inequality = false; 00457 for (dimension_type h = combining_cs_num_rows; h-- > 0; ) { 00458 if (combining_cs[h].is_strict_inequality()) 00459 strict_inequality = true; 00460 e += Linear_Expression(combining_cs[h]); 00461 } 00462 00463 if (!e.all_homogeneous_terms_are_zero()) { 00464 if (strict_inequality) 00465 new_cs.insert(e > 0); 00466 else 00467 new_cs.insert(e >= 0); 00468 } 00469 } 00470 } 00471 } 00472 } 00473 00474 // If none of the collected constraints strictly intersects `H79', 00475 // then the technique was unsuccessful. 00476 bool improves_upon_H79 = false; 00477 const Poly_Con_Relation si = Poly_Con_Relation::strictly_intersects(); 00478 for (dimension_type i = new_cs.num_rows(); i-- > 0; ) 00479 if (H79.relation_with(new_cs[i]) == si) { 00480 improves_upon_H79 = true; 00481 break; 00482 } 00483 if (!improves_upon_H79) 00484 return false; 00485 00486 // The resulting polyhedron is obtained by adding the constraints 00487 // in `new_cs' to polyhedron `H79'. 00488 Polyhedron result = H79; 00489 result.add_recycled_constraints(new_cs); 00490 // Force minimization. 00491 result.minimize(); 00492 00493 // Check for stabilization with respect to `y_cert' and improvement 00494 // over `H79'. 00495 if (y_cert.is_stabilizing(result) && !result.contains(H79)) { 00496 // The technique was successful. 00497 std::swap(x, result); 00498 PPL_ASSERT_HEAVY(x.OK(true)); 00499 return true; 00500 } 00501 else 00502 // The technique was unsuccessful. 00503 return false; 00504 }
| bool Parma_Polyhedra_Library::Polyhedron::BHRZ03_evolving_points | ( | const Polyhedron & | y, | |
| const BHRZ03_Certificate & | y_cert, | |||
| const Polyhedron & | H79 | |||
| ) | [private] |
Definition at line 507 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, swap(), and topology().
Referenced by BHRZ03_widening_assign().
00509 { 00510 Polyhedron& x = *this; 00511 // It is assumed that `y <= x <= H79'. 00512 PPL_ASSERT(x.topology() == y.topology() 00513 && x.topology() == H79.topology()); 00514 PPL_ASSERT(x.space_dim == y.space_dim 00515 && x.space_dim == H79.space_dim); 00516 PPL_ASSERT(!x.marked_empty() && !x.has_something_pending() 00517 && x.constraints_are_minimized() && x.generators_are_minimized()); 00518 PPL_ASSERT(!y.marked_empty() && !y.has_something_pending() 00519 && y.constraints_are_minimized() && y.generators_are_minimized()); 00520 PPL_ASSERT(!H79.marked_empty() && !H79.has_something_pending() 00521 && H79.constraints_are_minimized() && H79.generators_are_minimized()); 00522 00523 // For each point in `x.gen_sys' that is not in `y', 00524 // this technique tries to identify a set of rays that: 00525 // - are included in polyhedron `H79'; 00526 // - when added to `y' will subsume the point. 00527 Generator_System candidate_rays; 00528 00529 const dimension_type x_gen_sys_num_rows = x.gen_sys.num_rows(); 00530 const dimension_type y_gen_sys_num_rows = y.gen_sys.num_rows(); 00531 const bool closed = x.is_necessarily_closed(); 00532 for (dimension_type i = x_gen_sys_num_rows; i-- > 0; ) { 00533 Generator& g1 = x.gen_sys[i]; 00534 // For C polyhedra, we choose a point of `x.gen_sys' 00535 // that is not included in `y'. 00536 // In the case of NNC polyhedra, we can restrict attention to 00537 // closure points (considering also points will only add redundancy). 00538 if (((g1.is_point() && closed) || (g1.is_closure_point() && !closed)) 00539 && y.relation_with(g1) == Poly_Gen_Relation::nothing()) { 00540 // For each point (resp., closure point) `g2' in `y.gen_sys', 00541 // where `g1' and `g2' are different, 00542 // build the candidate ray `g1 - g2'. 00543 for (dimension_type j = y_gen_sys_num_rows; j-- > 0; ) { 00544 const Generator& g2 = y.gen_sys[j]; 00545 if ((g2.is_point() && closed) 00546 || (g2.is_closure_point() && !closed)) { 00547 PPL_ASSERT(compare(g1, g2) != 0); 00548 Generator ray_from_g2_to_g1 = g1; 00549 ray_from_g2_to_g1.linear_combine(g2, 0); 00550 candidate_rays.insert(ray_from_g2_to_g1); 00551 } 00552 } 00553 } 00554 } 00555 00556 // Be non-intrusive. 00557 Polyhedron result = x; 00558 result.add_recycled_generators(candidate_rays); 00559 result.intersection_assign(H79); 00560 // Force minimization. 00561 result.minimize(); 00562 00563 // Check for stabilization with respect to `y_cert' and improvement 00564 // over `H79'. 00565 if (y_cert.is_stabilizing(result) && !result.contains(H79)) { 00566 // The technique was successful. 00567 std::swap(x, result); 00568 PPL_ASSERT_HEAVY(x.OK(true)); 00569 return true; 00570 } 00571 else 00572 // The technique was unsuccessful. 00573 return false; 00574 }
| bool Parma_Polyhedra_Library::Polyhedron::BHRZ03_evolving_rays | ( | const Polyhedron & | y, | |
| const BHRZ03_Certificate & | y_cert, | |||
| const Polyhedron & | H79 | |||
| ) | [private] |
Definition at line 577 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(), PPL_DIRTY_TEMP_COEFFICIENT, relation_with(), space_dim, Parma_Polyhedra_Library::sub_mul_assign(), swap(), and topology().
Referenced by BHRZ03_widening_assign().
00579 { 00580 Polyhedron& x = *this; 00581 // It is assumed that `y <= x <= H79'. 00582 PPL_ASSERT(x.topology() == y.topology() 00583 && x.topology() == H79.topology()); 00584 PPL_ASSERT(x.space_dim == y.space_dim 00585 && x.space_dim == H79.space_dim); 00586 PPL_ASSERT(!x.marked_empty() && !x.has_something_pending() 00587 && x.constraints_are_minimized() && x.generators_are_minimized()); 00588 PPL_ASSERT(!y.marked_empty() && !y.has_something_pending() 00589 && y.constraints_are_minimized() && y.generators_are_minimized()); 00590 PPL_ASSERT(!H79.marked_empty() && !H79.has_something_pending() 00591 && H79.constraints_are_minimized() && H79.generators_are_minimized()); 00592 00593 const dimension_type x_gen_sys_num_rows = x.gen_sys.num_rows(); 00594 const dimension_type y_gen_sys_num_rows = y.gen_sys.num_rows(); 00595 00596 // Candidate rays are kept in a temporary generator system. 00597 Generator_System candidate_rays; 00598 PPL_DIRTY_TEMP_COEFFICIENT(tmp); 00599 for (dimension_type i = x_gen_sys_num_rows; i-- > 0; ) { 00600 const Generator& x_g = x.gen_sys[i]; 00601 // We choose a ray of `x' that does not belong to `y'. 00602 if (x_g.is_ray() && y.relation_with(x_g) == Poly_Gen_Relation::nothing()) { 00603 for (dimension_type j = y_gen_sys_num_rows; j-- > 0; ) { 00604 const Generator& y_g = y.gen_sys[j]; 00605 if (y_g.is_ray()) { 00606 Generator new_ray(x_g); 00607 // Modify `new_ray' according to the evolution of `x_g' with 00608 // respect to `y_g'. 00609 std::deque<bool> considered(x.space_dim + 1); 00610 for (dimension_type k = 1; k < x.space_dim; ++k) 00611 if (!considered[k]) 00612 for (dimension_type h = k + 1; h <= x.space_dim; ++h) 00613 if (!considered[h]) { 00614 tmp = x_g[k] * y_g[h]; 00615 // The following line optimizes the computation of 00616 // tmp -= x_g[h] * y_g[k]; 00617 sub_mul_assign(tmp, x_g[h], y_g[k]); 00618 const int clockwise 00619 = sgn(tmp); 00620 const int first_or_third_quadrant 00621 = sgn(x_g[k]) * sgn(x_g[h]); 00622 switch (clockwise * first_or_third_quadrant) { 00623 case -1: 00624 new_ray[k] = 0; 00625 considered[k] = true; 00626 break; 00627 case 1: 00628 new_ray[h] = 0; 00629 considered[h] = true; 00630 break; 00631 default: 00632 break; 00633 } 00634 } 00635 new_ray.normalize(); 00636 candidate_rays.insert(new_ray); 00637 } 00638 } 00639 } 00640 } 00641 00642 // If there are no candidate rays, we cannot obtain stabilization. 00643 if (candidate_rays.has_no_rows()) 00644 return false; 00645 00646 // Be non-intrusive. 00647 Polyhedron result = x; 00648 result.add_recycled_generators(candidate_rays); 00649 result.intersection_assign(H79); 00650 // Force minimization. 00651 result.minimize(); 00652 00653 // Check for stabilization with respect to `y' and improvement over `H79'. 00654 if (y_cert.is_stabilizing(result) && !result.contains(H79)) { 00655 // The technique was successful. 00656 std::swap(x, result); 00657 PPL_ASSERT_HEAVY(x.OK(true)); 00658 return true; 00659 } 00660 else 00661 // The technique was unsuccessful. 00662 return false; 00663 }
| 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 666 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, swap(), throw_dimension_incompatible(), throw_topology_incompatible(), topology(), and Parma_Polyhedra_Library::UNIVERSE.
Referenced by limited_BHRZ03_extrapolation_assign().
00666 { 00667 Polyhedron& x = *this; 00668 // Topology compatibility check. 00669 if (x.topology() != y.topology()) 00670 throw_topology_incompatible("BHRZ03_widening_assign(y)", "y", y); 00671 // Dimension-compatibility check. 00672 if (x.space_dim != y.space_dim) 00673 throw_dimension_incompatible("BHRZ03_widening_assign(y)", "y", y); 00674 00675 #ifndef NDEBUG 00676 { 00677 // We assume that y is contained in or equal to x. 00678 const Polyhedron x_copy = x; 00679 const Polyhedron y_copy = y; 00680 PPL_ASSERT_HEAVY(x_copy.contains(y_copy)); 00681 } 00682 #endif 00683 00684 // If any argument is zero-dimensional or empty, 00685 // the BHRZ03-widening behaves as the identity function. 00686 if (x.space_dim == 0 || x.marked_empty() || y.marked_empty()) 00687 return; 00688 00689 // `y.con_sys' and `y.gen_sys' should be in minimal form. 00690 if (!y.minimize()) 00691 // `y' is empty: the result is `x'. 00692 return; 00693 // `x.con_sys' and `x.gen_sys' should be in minimal form. 00694 x.minimize(); 00695 00696 // Compute certificate info for polyhedron `y'. 00697 BHRZ03_Certificate y_cert(y); 00698 00699 // If the iteration is stabilizing, the resulting polyhedron is `x'. 00700 // At this point, also check if the two polyhedra are the same 00701 // (exploiting the knowledge that `y <= x'). 00702 if (y_cert.is_stabilizing(x) || y.contains(x)) { 00703 PPL_ASSERT_HEAVY(OK()); 00704 return; 00705 } 00706 00707 // Here the iteration is not immediately stabilizing. 00708 // If we are using the widening-with-tokens technique and 00709 // there are tokens available, use one of them and return `x'. 00710 if (tp != 0 && *tp > 0) { 00711 --(*tp); 00712 PPL_ASSERT_HEAVY(OK()); 00713 return; 00714 } 00715 00716 // Copy into `H79_cs' the constraints that are common to `x' and `y', 00717 // according to the definition of the H79 widening. 00718 // The other ones are copied into `x_minus_H79_cs'. 00719 const Topology topol = x.topology(); 00720 Constraint_System H79_cs(topol); 00721 Constraint_System x_minus_H79_cs(topol); 00722 x.select_H79_constraints(y, H79_cs, x_minus_H79_cs); 00723 00724 // We cannot have selected all of the rows, since otherwise 00725 // the iteration should have been immediately stabilizing. 00726 PPL_ASSERT(!x_minus_H79_cs.has_no_rows()); 00727 // Be careful to obtain the right space dimension 00728 // (because `H79_cs' may be empty). 00729 Polyhedron H79(topol, x.space_dim, UNIVERSE); 00730 H79.add_recycled_constraints(H79_cs); 00731 // Force minimization. 00732 H79.minimize(); 00733 00734 // NOTE: none of the following widening heuristics is intrusive: 00735 // they will modify `x' only when returning successfully. 00736 if (x.BHRZ03_combining_constraints(y, y_cert, H79, x_minus_H79_cs)) 00737 return; 00738 00739 PPL_ASSERT_HEAVY(H79.OK() && x.OK() && y.OK()); 00740 00741 if (x.BHRZ03_evolving_points(y, y_cert, H79)) 00742 return; 00743 00744 PPL_ASSERT_HEAVY(H79.OK() && x.OK() && y.OK()); 00745 00746 if (x.BHRZ03_evolving_rays(y, y_cert, H79)) 00747 return; 00748 00749 PPL_ASSERT_HEAVY(H79.OK() && x.OK() && y.OK()); 00750 00751 // No previous technique was successful: fall back to the H79 widening. 00752 std::swap(x, H79); 00753 PPL_ASSERT_HEAVY(x.OK(true)); 00754 00755 #ifndef NDEBUG 00756 // The H79 widening is always stabilizing. 00757 PPL_ASSERT(y_cert.is_stabilizing(x)); 00758 #endif 00759 }
| bool Parma_Polyhedra_Library::Polyhedron::BHZ09_C_poly_hull_assign_if_exact | ( | const Polyhedron & | y | ) | [protected] |
Definition at line 1445 of file Polyhedron_nonpublic.cc.
References add_generator(), affine_dimension(), con_sys, gen_sys, Parma_Polyhedra_Library::Poly_Con_Relation::implies(), is_empty(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), is_included_in(), is_necessarily_closed(), minimize(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), relation_with(), sat_g, sat_g_is_up_to_date(), Parma_Polyhedra_Library::Bit_Row::set(), Parma_Polyhedra_Library::Bit_Row::set_until(), space_dim, Parma_Polyhedra_Library::Poly_Gen_Relation::subsumes(), and update_sat_g().
Referenced by BHZ09_poly_hull_assign_if_exact().
01445 { 01446 Polyhedron& x = *this; 01447 // Private method: the caller must ensure the following. 01448 PPL_ASSERT(x.is_necessarily_closed() && y.is_necessarily_closed()); 01449 PPL_ASSERT(x.space_dim > 0 && x.space_dim == y.space_dim); 01450 PPL_ASSERT(!x.is_empty() && !y.is_empty()); 01451 01452 // Minimization is not really required, but it is probably the best 01453 // way of getting constraints, generators and saturation matrices 01454 // up-to-date; it also removes redundant constraints/generators. 01455 (void) x.minimize(); 01456 (void) y.minimize(); 01457 01458 // Handle a special case: for topologically closed polyhedra P and Q, 01459 // if the affine dimension of P is greater than that of Q, then 01460 // their upper bound is exact if and only if P includes Q. 01461 const dimension_type x_affine_dim = x.affine_dimension(); 01462 const dimension_type y_affine_dim = y.affine_dimension(); 01463 if (x_affine_dim > y_affine_dim) 01464 return y.is_included_in(x); 01465 else if (x_affine_dim < y_affine_dim) { 01466 if (x.is_included_in(y)) { 01467 x = y; 01468 return true; 01469 } 01470 else 01471 return false; 01472 } 01473 01474 const Constraint_System& x_cs = x.con_sys; 01475 const Generator_System& x_gs = x.gen_sys; 01476 const Generator_System& y_gs = y.gen_sys; 01477 const dimension_type x_gs_num_rows = x_gs.num_rows(); 01478 const dimension_type y_gs_num_rows = y_gs.num_rows(); 01479 01480 // Step 1: generators of `x' that are redundant in `y', and vice versa. 01481 Bit_Row x_gs_red_in_y; 01482 dimension_type num_x_gs_red_in_y = 0; 01483 for (dimension_type i = x_gs_num_rows; i-- > 0; ) 01484 if (y.relation_with(x_gs[i]).implies(Poly_Gen_Relation::subsumes())) { 01485 x_gs_red_in_y.set(i); 01486 ++num_x_gs_red_in_y; 01487 } 01488 Bit_Row y_gs_red_in_x; 01489 dimension_type num_y_gs_red_in_x = 0; 01490 for (dimension_type i = y_gs_num_rows; i-- > 0; ) 01491 if (x.relation_with(y_gs[i]).implies(Poly_Gen_Relation::subsumes())) { 01492 y_gs_red_in_x.set(i); 01493 ++num_y_gs_red_in_x; 01494 } 01495 01496 // Step 2: filter away special cases. 01497 01498 // Step 2.1: inclusion tests. 01499 if (num_y_gs_red_in_x == y_gs_num_rows) 01500 // `y' is included into `x': upper bound `x' is exact. 01501 return true; 01502 if (num_x_gs_red_in_y == x_gs_num_rows) { 01503 // `x' is included into `y': upper bound `y' is exact. 01504 x = y; 01505 return true; 01506 } 01507 01508 // Step 2.2: if no generator of `x' is redundant for `y', then 01509 // (as by 2.1 there exists a constraint of `x' non-redundant for `y') 01510 // the upper bound is not exact; the same if exchanging `x' and `y'. 01511 if (num_x_gs_red_in_y == 0 || num_y_gs_red_in_x == 0) 01512 return false; 01513 01514 // Step 3: see if `x' has a non-redundant constraint `c_x' that is not 01515 // satisfied by `y' and a non-redundant generator in `y' (see Step 1) 01516 // saturating `c_x'. If so, the upper bound is not exact. 01517 01518 // Make sure the saturation matrix for `x' is up to date. 01519 // Any sat matrix would do: we choose `sat_g' because it matches 01520 // the two nested loops (constraints on rows and generators on columns). 01521 if (!x.sat_g_is_up_to_date()) 01522 x.update_sat_g(); 01523 const Bit_Matrix& x_sat = x.sat_g; 01524 01525 Bit_Row all_ones; 01526 all_ones.set_until(x_gs_num_rows); 01527 Bit_Row row_union; 01528 for (dimension_type i = x_cs.num_rows(); i-- > 0; ) { 01529 const bool included 01530 = y.relation_with(x_cs[i]).implies(Poly_Con_Relation::is_included()); 01531 if (!included) { 01532 set_union(x_gs_red_in_y, x_sat[i], row_union); 01533 if (row_union != all_ones) 01534 return false; 01535 } 01536 } 01537 01538 // Here we know that the upper bound is exact: compute it. 01539 for (dimension_type j = y_gs_num_rows; j-- > 0; ) 01540 if (!y_gs_red_in_x[j]) 01541 add_generator(y_gs[j]); 01542 01543 PPL_ASSERT_HEAVY(OK()); 01544 return true; 01545 }
| bool Parma_Polyhedra_Library::Polyhedron::BHZ09_NNC_poly_hull_assign_if_exact | ( | const Polyhedron & | y | ) | [protected] |
Definition at line 1548 of file Polyhedron_nonpublic.cc.
References add_constraint(), add_generator(), Parma_Polyhedra_Library::Bit_Row::clear(), con_sys, constraints(), contains(), Parma_Polyhedra_Library::Bit_Row::empty(), Parma_Polyhedra_Library::Bit_Row::first(), gen_sys, Parma_Polyhedra_Library::Poly_Con_Relation::implies(), Parma_Polyhedra_Library::Generator::is_closure_point(), Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), is_empty(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), is_necessarily_closed(), Parma_Polyhedra_Library::Generator::is_point(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), minimize(), Parma_Polyhedra_Library::Bit_Row::next(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Scalar_Products::reduced_sign(), relation_with(), sat_g, sat_g_is_up_to_date(), Parma_Polyhedra_Library::Bit_Row::set(), Parma_Polyhedra_Library::Bit_Row::set_until(), space_dim, Parma_Polyhedra_Library::Poly_Gen_Relation::subsumes(), swap(), and update_sat_g().
Referenced by BHZ09_poly_hull_assign_if_exact().
01548 { 01549 const Polyhedron& x = *this; 01550 // Private method: the caller must ensure the following. 01551 PPL_ASSERT(!x.is_necessarily_closed() && !y.is_necessarily_closed()); 01552 PPL_ASSERT(x.space_dim > 0 && x.space_dim == y.space_dim); 01553 PPL_ASSERT(!x.is_empty() && !y.is_empty()); 01554 01555 // Minimization is not really required, but it is probably the best 01556 // way of getting constraints, generators and saturation matrices 01557 // up-to-date; it also removes redundant constraints/generators. 01558 (void) x.minimize(); 01559 (void) y.minimize(); 01560 01561 const Generator_System& x_gs = x.gen_sys; 01562 const Generator_System& y_gs = y.gen_sys; 01563 const dimension_type x_gs_num_rows = x_gs.num_rows(); 01564 const dimension_type y_gs_num_rows = y_gs.num_rows(); 01565 01566 // Compute generators of `x' that are non-redundant in `y' ... 01567 Bit_Row x_gs_nonred_in_y; 01568 Bit_Row x_points_nonred_in_y; 01569 Bit_Row x_closure_points; 01570 dimension_type num_x_gs_nonred_in_y = 0; 01571 for (dimension_type i = x_gs_num_rows; i-- > 0; ) { 01572 const Generator& x_gs_i = x_gs[i]; 01573 if (x_gs_i.is_closure_point()) 01574 x_closure_points.set(i); 01575 if (y.relation_with(x_gs[i]).implies(Poly_Gen_Relation::subsumes())) 01576 continue; 01577 x_gs_nonred_in_y.set(i); 01578 ++num_x_gs_nonred_in_y; 01579 if (x_gs_i.is_point()) 01580 x_points_nonred_in_y.set(i); 01581 } 01582 01583 // If `x' is included into `y', the upper bound `y' is exact. 01584 if (num_x_gs_nonred_in_y == 0) { 01585 *this = y; 01586 return true; 01587 } 01588 01589 // ... and vice versa, generators of `y' that are non-redundant in `x'. 01590 Bit_Row y_gs_nonred_in_x; 01591 Bit_Row y_points_nonred_in_x; 01592 Bit_Row y_closure_points; 01593 dimension_type num_y_gs_nonred_in_x = 0; 01594 for (dimension_type i = y_gs_num_rows; i-- > 0; ) { 01595 const Generator& y_gs_i = y_gs[i]; 01596 if (y_gs_i.is_closure_point()) 01597 y_closure_points.set(i); 01598 if (x.relation_with(y_gs_i).implies(Poly_Gen_Relation::subsumes())) 01599 continue; 01600 y_gs_nonred_in_x.set(i); 01601 ++num_y_gs_nonred_in_x; 01602 if (y_gs_i.is_point()) 01603 y_points_nonred_in_x.set(i); 01604 } 01605 01606 // If `y' is included into `x', the upper bound `x' is exact. 01607 if (num_y_gs_nonred_in_x == 0) 01608 return true; 01609 01610 Bit_Row x_nonpoints_nonred_in_y; 01611 set_difference(x_gs_nonred_in_y, x_points_nonred_in_y, 01612 x_nonpoints_nonred_in_y); 01613 01614 const Constraint_System& x_cs = x.con_sys; 01615 const Constraint_System& y_cs = y.con_sys; 01616 const dimension_type x_cs_num_rows = x_cs.num_rows(); 01617 const dimension_type y_cs_num_rows = y_cs.num_rows(); 01618 01619 // Filter away the points of `x_gs' that would be redundant 01620 // in the topological closure of `y'. 01621 Bit_Row x_points_nonred_in_y_closure; 01622 for (dimension_type i = x_points_nonred_in_y.first(); 01623 i != ULONG_MAX; i = x_points_nonred_in_y.next(i)) { 01624 const Generator& x_p = x_gs[i]; 01625 PPL_ASSERT(x_p.is_point()); 01626 // NOTE: we cannot use Constraint_System::relation_with() 01627 // as we need to treat strict inequalities as if they were nonstrict. 01628 for (dimension_type j = y_cs_num_rows; j-- > 0; ) { 01629 const Constraint& y_c = y_cs[j]; 01630 const int sp_sign = Scalar_Products::reduced_sign(y_c, x_p); 01631 if (sp_sign < 0 || (y_c.is_equality() && sp_sign > 0)) { 01632 x_points_nonred_in_y_closure.set(i); 01633 break; 01634 } 01635 } 01636 } 01637 01638 // Make sure the saturation matrix for `x' is up to date. 01639 // Any sat matrix would do: we choose `sat_g' because it matches 01640 // the two nested loops (constraints on rows and generators on columns). 01641 if (!x.sat_g_is_up_to_date()) 01642 x.update_sat_g(); 01643 const Bit_Matrix& x_sat = x.sat_g; 01644 01645 Bit_Row x_cs_condition_3; 01646 Bit_Row x_gs_condition_3; 01647 Bit_Row all_ones; 01648 all_ones.set_until(x_gs_num_rows); 01649 Bit_Row saturators; 01650 Bit_Row tmp_set; 01651 for (dimension_type i = x_cs_num_rows; i-- > 0; ) { 01652 const Constraint& x_c = x_cs[i]; 01653 // Skip constraint if it is not violated by `y'. 01654 if (y.relation_with(x_c).implies(Poly_Con_Relation::is_included())) 01655 continue; 01656 set_difference(all_ones, x_sat[i], saturators); 01657 // Check condition 1. 01658 set_intersection(x_nonpoints_nonred_in_y, saturators, tmp_set); 01659 if (!tmp_set.empty()) 01660 return false; 01661 if (x_c.is_strict_inequality()) { 01662 // Postpone check for condition 3. 01663 x_cs_condition_3.set(i); 01664 set_intersection(x_closure_points, saturators, tmp_set); 01665 set_union(x_gs_condition_3, tmp_set, x_gs_condition_3); 01666 } 01667 else { 01668 // Check condition 2. 01669 set_intersection(x_points_nonred_in_y_closure, saturators, tmp_set); 01670 if (!tmp_set.empty()) 01671 return false; 01672 } 01673 } 01674 01675 // Now exchange the roles of `x' and `y' 01676 // (the statement of the NNC theorem in BHZ09 is symmetric). 01677 01678 Bit_Row y_nonpoints_nonred_in_x; 01679 set_difference(y_gs_nonred_in_x, y_points_nonred_in_x, 01680 y_nonpoints_nonred_in_x); 01681 01682 // Filter away the points of `y_gs' that would be redundant 01683 // in the topological closure of `x'. 01684 Bit_Row y_points_nonred_in_x_closure; 01685 for (dimension_type i = y_points_nonred_in_x.first(); 01686 i != ULONG_MAX; i = y_points_nonred_in_x.next(i)) { 01687 const Generator& y_p = y_gs[i]; 01688 PPL_ASSERT(y_p.is_point()); 01689 // NOTE: we cannot use Constraint_System::relation_with() 01690 // as we need to treat strict inequalities as if they were nonstrict. 01691 for (dimension_type j = x_cs_num_rows; j-- > 0; ) { 01692 const Constraint& x_c = x_cs[j]; 01693 const int sp_sign = Scalar_Products::reduced_sign(x_c, y_p); 01694 if (sp_sign < 0 || (x_c.is_equality() && sp_sign > 0)) { 01695 y_points_nonred_in_x_closure.set(i); 01696 break; 01697 } 01698 } 01699 } 01700 01701 // Make sure the saturation matrix `sat_g' for `y' is up to date. 01702 if (!y.sat_g_is_up_to_date()) 01703 y.update_sat_g(); 01704 const Bit_Matrix& y_sat = y.sat_g; 01705 01706 Bit_Row y_cs_condition_3; 01707 Bit_Row y_gs_condition_3; 01708 all_ones.clear(); 01709 all_ones.set_until(y_gs_num_rows); 01710 for (dimension_type i = y_cs_num_rows; i-- > 0; ) { 01711 const Constraint& y_c = y_cs[i]; 01712 // Skip constraint if it is not violated by `x'. 01713 if (x.relation_with(y_c).implies(Poly_Con_Relation::is_included())) 01714 continue; 01715 set_difference(all_ones, y_sat[i], saturators); 01716 // Check condition 1. 01717 set_intersection(y_nonpoints_nonred_in_x, saturators, tmp_set); 01718 if (!tmp_set.empty()) 01719 return false; 01720 if (y_c.is_strict_inequality()) { 01721 // Postpone check for condition 3. 01722 y_cs_condition_3.set(i); 01723 set_intersection(y_closure_points, saturators, tmp_set); 01724 set_union(y_gs_condition_3, tmp_set, y_gs_condition_3); 01725 } 01726 else { 01727 // Check condition 2. 01728 set_intersection(y_points_nonred_in_x_closure, saturators, tmp_set); 01729 if (!tmp_set.empty()) 01730 return false; 01731 } 01732 } 01733 01734 // Now considering condition 3. 01735 01736 if (x_cs_condition_3.empty() && y_cs_condition_3.empty()) { 01737 // No test for condition 3 is needed. 01738 // The hull is exact: compute it. 01739 for (dimension_type j = y_gs_num_rows; j-- > 0; ) 01740 if (y_gs_nonred_in_x[j]) 01741 add_generator(y_gs[j]); 01742 return true; 01743 } 01744 01745 // We have anyway to compute the upper bound and its constraints too. 01746 Polyhedron ub(x); 01747 for (dimension_type j = y_gs_num_rows; j-- > 0; ) 01748 if (y_gs_nonred_in_x[j]) 01749 ub.add_generator(y_gs[j]); 01750 (void) ub.minimize(); 01751 PPL_ASSERT(!ub.is_empty()); 01752 01753 // NOTE: the following computation of x_gs_condition_3_not_in_y 01754 // (resp., y_gs_condition_3_not_in_x) is not required for correctness. 01755 // It is done so as to later apply a speculative test 01756 // (i.e., a non-conclusive but computationally lighter test). 01757 01758 // Filter away from `x_gs_condition_3' those closure points 01759 // that, when considered as points, would belong to `y', 01760 // i.e., those that violate no strict constraint in `y_cs'. 01761 Bit_Row x_gs_condition_3_not_in_y; 01762 for (dimension_type i = y_cs_num_rows; i-- > 0; ) { 01763 const Constraint& y_c = y_cs[i]; 01764 if (y_c.is_strict_inequality()) { 01765 for (dimension_type j = x_gs_condition_3.first(); 01766 j != ULONG_MAX; j = x_gs_condition_3.next(j)) { 01767 const Generator& x_cp = x_gs[j]; 01768 PPL_ASSERT(x_cp.is_closure_point()); 01769 const int sp_sign = Scalar_Products::reduced_sign(y_c, x_cp); 01770 PPL_ASSERT(sp_sign >= 0); 01771 if (sp_sign == 0) { 01772 x_gs_condition_3.clear(j); 01773 x_gs_condition_3_not_in_y.set(j); 01774 } 01775 } 01776 if (x_gs_condition_3.empty()) 01777 break; 01778 } 01779 } 01780 // Symmetrically, filter away from `y_gs_condition_3' those 01781 // closure points that, when considered as points, would belong to `x', 01782 // i.e., those that violate no strict constraint in `x_cs'. 01783 Bit_Row y_gs_condition_3_not_in_x; 01784 for (dimension_type i = x_cs_num_rows; i-- > 0; ) { 01785 if (x_cs[i].is_strict_inequality()) { 01786 const Constraint& x_c = x_cs[i]; 01787 for (dimension_type j = y_gs_condition_3.first(); 01788 j != ULONG_MAX; j = y_gs_condition_3.next(j)) { 01789 const Generator& y_cp = y_gs[j]; 01790 PPL_ASSERT(y_cp.is_closure_point()); 01791 const int sp_sign = Scalar_Products::reduced_sign(x_c, y_cp); 01792 PPL_ASSERT(sp_sign >= 0); 01793 if (sp_sign == 0) { 01794 y_gs_condition_3.clear(j); 01795 y_gs_condition_3_not_in_x.set(j); 01796 } 01797 } 01798 if (y_gs_condition_3.empty()) 01799 break; 01800 } 01801 } 01802 01803 // NOTE: here we apply the speculative test. 01804 // Check if there exists a closure point in `x_gs_condition_3_not_in_y' 01805 // or `y_gs_condition_3_not_in_x' that belongs (as point) to the hull. 01806 // If so, the hull is not exact. 01807 const Constraint_System& ub_cs = ub.constraints(); 01808 for (dimension_type i = ub_cs.num_rows(); i-- > 0; ) { 01809 if (ub_cs[i].is_strict_inequality()) { 01810 const Constraint& ub_c = ub_cs[i]; 01811 for (dimension_type j = x_gs_condition_3_not_in_y.first(); 01812 j != ULONG_MAX; j = x_gs_condition_3_not_in_y.next(j)) { 01813 const Generator& x_cp = x_gs[j]; 01814 PPL_ASSERT(x_cp.is_closure_point()); 01815 const int sp_sign = Scalar_Products::reduced_sign(ub_c, x_cp); 01816 PPL_ASSERT(sp_sign >= 0); 01817 if (sp_sign == 0) 01818 x_gs_condition_3_not_in_y.clear(j); 01819 } 01820 for (dimension_type j = y_gs_condition_3_not_in_x.first(); 01821 j != ULONG_MAX; j = y_gs_condition_3_not_in_x.next(j)) { 01822 const Generator& y_cp = y_gs[j]; 01823 PPL_ASSERT(y_cp.is_closure_point()); 01824 const int sp_sign = Scalar_Products::reduced_sign(ub_c, y_cp); 01825 PPL_ASSERT(sp_sign >= 0); 01826 if (sp_sign == 0) 01827 y_gs_condition_3_not_in_x.clear(j); 01828 } 01829 } 01830 } 01831 01832 if (!(x_gs_condition_3_not_in_y.empty() 01833 && y_gs_condition_3_not_in_x.empty())) 01834 // There exist a closure point satisfying condition 3, 01835 // hence the hull is not exact. 01836 return false; 01837 01838 // The speculative test was not successful: 01839 // apply the expensive (but conclusive) test for condition 3. 01840 01841 // Consider strict inequalities in `x' violated by `y'. 01842 for (dimension_type i = x_cs_condition_3.first(); 01843 i != ULONG_MAX; i = x_cs_condition_3.next(i)) { 01844 const Constraint& x_cs_i = x_cs[i]; 01845 PPL_ASSERT(x_cs_i.is_strict_inequality()); 01846 // Build the equality constraint induced by x_cs_i. 01847 Constraint eq_i(Linear_Expression(x_cs_i) == 0); 01848 PPL_ASSERT(!(ub.relation_with(eq_i) 01849 .implies(Poly_Con_Relation::is_disjoint()))); 01850 Polyhedron ub_inters_hyperplane(ub); 01851 ub_inters_hyperplane.add_constraint(eq_i); 01852 Polyhedron y_inters_hyperplane(y); 01853 y_inters_hyperplane.add_constraint(eq_i); 01854 if (!y_inters_hyperplane.contains(ub_inters_hyperplane)) 01855 // The hull is not exact. 01856 return false; 01857 } 01858 01859 // Consider strict inequalities in `y' violated by `x'. 01860 for (dimension_type i = y_cs_condition_3.first(); 01861 i != ULONG_MAX; i = y_cs_condition_3.next(i)) { 01862 const Constraint& y_cs_i = y_cs[i]; 01863 PPL_ASSERT(y_cs_i.is_strict_inequality()); 01864 // Build the equality constraint induced by y_cs_i. 01865 Constraint eq_i(Linear_Expression(y_cs_i) == 0); 01866 PPL_ASSERT(!(ub.relation_with(eq_i) 01867 .implies(Poly_Con_Relation::is_disjoint()))); 01868 Polyhedron ub_inters_hyperplane(ub); 01869 ub_inters_hyperplane.add_constraint(eq_i); 01870 Polyhedron x_inters_hyperplane(x); 01871 x_inters_hyperplane.add_constraint(eq_i); 01872 if (!x_inters_hyperplane.contains(ub_inters_hyperplane)) 01873 // The hull is not exact. 01874 return false; 01875 } 01876 01877 // The hull is exact. 01878 swap(ub); 01879 return true; 01880 }
| bool Parma_Polyhedra_Library::Polyhedron::BHZ09_poly_hull_assign_if_exact | ( | const Polyhedron & | y | ) | [protected] |
Definition at line 1413 of file Polyhedron_nonpublic.cc.
References BHZ09_C_poly_hull_assign_if_exact(), BHZ09_NNC_poly_hull_assign_if_exact(), is_empty(), is_necessarily_closed(), marked_empty(), space_dim, topology(), and upper_bound_assign().
Referenced by Parma_Polyhedra_Library::NNC_Polyhedron::poly_hull_assign_if_exact(), and Parma_Polyhedra_Library::C_Polyhedron::poly_hull_assign_if_exact().
01413 { 01414 Polyhedron& x = *this; 01415 01416 // Private method: the caller must ensure the following. 01417 PPL_ASSERT(x.topology() == y.topology()); 01418 PPL_ASSERT(x.space_dim == y.space_dim); 01419 01420 // The zero-dim case is trivial. 01421 if (x.space_dim == 0) { 01422 x.upper_bound_assign(y); 01423 return true; 01424 } 01425 01426 // If `x' or `y' are (known to be) empty, the upper bound is exact. 01427 if (x.marked_empty()) { 01428 x = y; 01429 return true; 01430 } 01431 else if (y.is_empty()) 01432 return true; 01433 else if (x.is_empty()) { 01434 x = y; 01435 return true; 01436 } 01437 01438 if (x.is_necessarily_closed()) 01439 return x.BHZ09_C_poly_hull_assign_if_exact(y); 01440 else 01441 return x.BHZ09_NNC_poly_hull_assign_if_exact(y); 01442 }
| 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 2713 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(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
02716 { 02717 // The denominator cannot be zero. 02718 if (denominator == 0) 02719 throw_invalid_argument("bounded_affine_image(v, lb, ub, d)", "d == 0"); 02720 02721 // Dimension-compatibility checks. 02722 // `var' should be one of the dimensions of the polyhedron. 02723 const dimension_type var_space_dim = var.space_dimension(); 02724 if (space_dim < var_space_dim) 02725 throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)", 02726 "v", var); 02727 // The dimension of `lb_expr' and `ub_expr' should not be 02728 // greater than the dimension of `*this'. 02729 const dimension_type lb_space_dim = lb_expr.space_dimension(); 02730 if (space_dim < lb_space_dim) 02731 throw_dimension_incompatible("bounded_affine_image(v, lb, ub)", 02732 "lb", lb_expr); 02733 const dimension_type ub_space_dim = ub_expr.space_dimension(); 02734 if (space_dim < ub_space_dim) 02735 throw_dimension_incompatible("bounded_affine_image(v, lb, ub)", 02736 "ub", ub_expr); 02737 02738 // Any image of an empty polyhedron is empty. 02739 if (marked_empty()) 02740 return; 02741 02742 // Check whether `var' occurs in `lb_expr' and/or `ub_expr'. 02743 if (lb_expr.coefficient(var) == 0) { 02744 // Here `var' may only occur in `ub_expr'. 02745 generalized_affine_image(var, 02746 LESS_OR_EQUAL, 02747 ub_expr, 02748 denominator); 02749 if (denominator > 0) 02750 refine_no_check(lb_expr <= denominator*var); 02751 else 02752 refine_no_check(denominator*var <= lb_expr); 02753 } 02754 else if (ub_expr.coefficient(var) == 0) { 02755 // Here `var' only occurs in `lb_expr'. 02756 generalized_affine_image(var, 02757 GREATER_OR_EQUAL, 02758 lb_expr, 02759 denominator); 02760 if (denominator > 0) 02761 refine_no_check(denominator*var <= ub_expr); 02762 else 02763 refine_no_check(ub_expr <= denominator*var); 02764 } 02765 else { 02766 // Here `var' occurs in both `lb_expr' and `ub_expr'. 02767 // To ease the computation, we add an additional dimension. 02768 const Variable new_var = Variable(space_dim); 02769 add_space_dimensions_and_embed(1); 02770 // Constrain the new dimension to be equal to `ub_expr'. 02771 refine_no_check(denominator*new_var == ub_expr); 02772 // Apply the affine lower bound. 02773 generalized_affine_image(var, 02774 GREATER_OR_EQUAL, 02775 lb_expr, 02776 denominator); 02777 if (!marked_empty()) 02778 // Now apply the affine upper bound, as recorded in `new_var'. 02779 refine_no_check(new_var >= var); 02780 // Remove the temporarily added dimension. 02781 remove_higher_space_dimensions(space_dim-1); 02782 } 02783 PPL_ASSERT_HEAVY(OK()); 02784 }
| 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 2788 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(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), throw_dimension_incompatible(), throw_invalid_argument(), and unconstrain().
02791 { 02792 // The denominator cannot be zero. 02793 if (denominator == 0) 02794 throw_invalid_argument("bounded_affine_preimage(v, lb, ub, d)", "d == 0"); 02795 02796 // Dimension-compatibility checks. 02797 // `var' should be one of the dimensions of the polyhedron. 02798 const dimension_type var_space_dim = var.space_dimension(); 02799 if (space_dim < var_space_dim) 02800 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)", 02801 "v", var); 02802 // The dimension of `lb_expr' and `ub_expr' should not be 02803 // greater than the dimension of `*this'. 02804 const dimension_type lb_space_dim = lb_expr.space_dimension(); 02805 if (space_dim < lb_space_dim) 02806 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)", 02807 "lb", lb_expr); 02808 const dimension_type ub_space_dim = ub_expr.space_dimension(); 02809 if (space_dim < ub_space_dim) 02810 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)", 02811 "ub", ub_expr); 02812 02813 // Any preimage of an empty polyhedron is empty. 02814 if (marked_empty()) 02815 return; 02816 02817 // Check whether `var' occurs in neither `lb_expr' nor `ub_expr'. 02818 if (lb_expr.coefficient(var) == 0 && ub_expr.coefficient(var) == 0) { 02819 if (denominator > 0) { 02820 refine_no_check(lb_expr <= denominator*var); 02821 refine_no_check(denominator*var <= ub_expr); 02822 } 02823 else { 02824 refine_no_check(ub_expr <= denominator*var); 02825 refine_no_check(denominator*var <= lb_expr); 02826 } 02827 unconstrain(var); 02828 } 02829 else { 02830 // Here `var' occurs in `lb_expr' or `ub_expr'. 02831 // To ease the computation, add an additional dimension. 02832 const Variable new_var = Variable(space_dim); 02833 add_space_dimensions_and_embed(1); 02834 // Swap dimensions `var' and `new_var'. 02835 std::vector<dimension_type> swapping_cycle; 02836 swapping_cycle.push_back(var_space_dim); 02837 swapping_cycle.push_back(space_dim); 02838 swapping_cycle.push_back(0); 02839 if (constraints_are_up_to_date()) 02840 con_sys.permute_columns(swapping_cycle); 02841 if (generators_are_up_to_date()) 02842 gen_sys.permute_columns(swapping_cycle); 02843 // Constrain the new dimension as dictated by `lb_expr' and `ub_expr'. 02844 // (we force minimization because we will need the generators). 02845 if (denominator > 0) { 02846 refine_no_check(lb_expr <= denominator*new_var); 02847 refine_no_check(denominator*new_var <= ub_expr); 02848 } 02849 else { 02850 refine_no_check(ub_expr <= denominator*new_var); 02851 refine_no_check(denominator*new_var <= lb_expr); 02852 } 02853 // Remove the temporarily added dimension. 02854 remove_higher_space_dimensions(space_dim-1); 02855 } 02856 PPL_ASSERT_HEAVY(OK()); 02857 }
| void Parma_Polyhedra_Library::Polyhedron::bounded_BHRZ03_extrapolation_assign | ( | const Polyhedron & | y, | |
| const Constraint_System & | cs, | |||
| unsigned * | tp = 0 | |||
| ) |
Assigns to *this the result of computing the bounded extrapolation between *this and y using the BHRZ03-widening operator.
| 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 847 of file Polyhedron_widenings.cc.
References add_recycled_constraints(), Parma_Polyhedra_Library::ANY_COMPLEXITY, and limited_BHRZ03_extrapolation_assign().
00849 { 00850 Rational_Box x_box(*this, ANY_COMPLEXITY); 00851 Rational_Box y_box(y, ANY_COMPLEXITY); 00852 x_box.CC76_widening_assign(y_box); 00853 limited_BHRZ03_extrapolation_assign(y, cs, tp); 00854 Constraint_System x_box_cs = x_box.constraints(); 00855 add_recycled_constraints(x_box_cs); 00856 }
| void Parma_Polyhedra_Library::Polyhedron::bounded_H79_extrapolation_assign | ( | const Polyhedron & | y, | |
| const Constraint_System & | cs, | |||
| unsigned * | tp = 0 | |||
| ) |
Assigns to *this the result of computing the bounded extrapolation between *this and y using the H79-widening operator.
| 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 372 of file Polyhedron_widenings.cc.
References add_recycled_constraints(), Parma_Polyhedra_Library::ANY_COMPLEXITY, and limited_H79_extrapolation_assign().
00374 { 00375 Rational_Box x_box(*this, ANY_COMPLEXITY); 00376 Rational_Box y_box(y, ANY_COMPLEXITY); 00377 x_box.CC76_widening_assign(y_box); 00378 limited_H79_extrapolation_assign(y, cs, tp); 00379 Constraint_System x_box_cs = x_box.constraints(); 00380 add_recycled_constraints(x_box_cs); 00381 }
| 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 519 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().
00520 { 00521 // The dimension of `expr' should not be greater than the dimension 00522 // of `*this'. 00523 const dimension_type expr_space_dim = expr.space_dimension(); 00524 if (space_dim < expr_space_dim) 00525 throw_dimension_incompatible((from_above 00526 ? "bounds_from_above(e)" 00527 : "bounds_from_below(e)"), "e", expr); 00528 00529 // A zero-dimensional or empty polyhedron bounds everything. 00530 if (space_dim == 0 00531 || marked_empty() 00532 || (has_pending_constraints() && !process_pending_constraints()) 00533 || (!generators_are_up_to_date() && !update_generators())) 00534 return true; 00535 00536 // The polyhedron has updated, possibly pending generators. 00537 for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) { 00538 const Generator& g = gen_sys[i]; 00539 // Only lines and rays in `*this' can cause `expr' to be unbounded. 00540 if (g.is_line_or_ray()) { 00541 const int sp_sign = Scalar_Products::homogeneous_sign(expr, g); 00542 if (sp_sign != 0 00543 && (g.is_line() 00544 || (from_above && sp_sign > 0) 00545 || (!from_above && sp_sign < 0))) 00546 // `*this' does not bound `expr'. 00547 return false; 00548 } 00549 } 00550 // No sources of unboundedness have been found for `expr' 00551 // in the given direction. 00552 return true; 00553 }
| 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 306 of file Polyhedron.inlines.hh.
References bounds().
00306 { 00307 return bounds(expr, true); 00308 }
| 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 311 of file Polyhedron.inlines.hh.
References bounds().
00311 { 00312 return bounds(expr, false); 00313 }
| bool Parma_Polyhedra_Library::Polyhedron::can_have_something_pending | ( | ) | const [inline, private] |
Returns true if the polyhedron can have something pending.
Definition at line 173 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().
00173 { 00174 return constraints_are_minimized() 00175 && generators_are_minimized() 00176 && (sat_c_is_up_to_date() || sat_g_is_up_to_date()); 00177 }
| bool Parma_Polyhedra_Library::Polyhedron::can_recycle_congruence_systems | ( | ) | [inline, static] |
Returns false indicating that this domain cannot recycle congruences.
Definition at line 118 of file Polyhedron.inlines.hh.
| 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 112 of file Polyhedron.inlines.hh.
| void Parma_Polyhedra_Library::Polyhedron::clear_constraints_minimized | ( | ) | [inline, private] |
Sets status to express that constraints are no longer minimized.
Definition at line 239 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(), drop_some_non_integer_points(), intersection_assign(), refine_no_check(), refine_with_constraints(), remove_pending_to_obtain_constraints(), and topological_closure_assign().
00239 { 00240 status.reset_c_minimized(); 00241 }
| 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 271 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().
00271 { 00272 clear_pending_constraints(); 00273 clear_constraints_minimized(); 00274 clear_sat_c_up_to_date(); 00275 clear_sat_g_up_to_date(); 00276 status.reset_c_up_to_date(); 00277 // Can get rid of con_sys here. 00278 }
| void Parma_Polyhedra_Library::Polyhedron::clear_empty | ( | ) | [inline, private] |
Clears the status flag indicating that the polyhedron is empty.
Definition at line 234 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::reset_empty(), and status.
Referenced by add_generator(), and add_recycled_generators().
00234 { 00235 status.reset_empty(); 00236 }
| void Parma_Polyhedra_Library::Polyhedron::clear_generators_minimized | ( | ) | [inline, private] |
Sets status to express that generators are no longer minimized.
Definition at line 244 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().
00244 { 00245 status.reset_g_minimized(); 00246 }
| 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 281 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(), drop_some_non_integer_points(), intersection_assign(), refine_no_check(), refine_with_constraints(), remove_pending_to_obtain_constraints(), strongly_minimize_constraints(), and topological_closure_assign().
00281 { 00282 clear_pending_generators(); 00283 clear_generators_minimized(); 00284 clear_sat_c_up_to_date(); 00285 clear_sat_g_up_to_date(); 00286 status.reset_g_up_to_date(); 00287 // Can get rid of gen_sys here. 00288 }
| void Parma_Polyhedra_Library::Polyhedron::clear_pending_constraints | ( | ) | [inline, private] |
Sets status to express that there are no longer pending constraints.
Definition at line 249 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::reset_c_pending(), and status.
Referenced by clear_constraints_up_to_date(), process_pending_constraints(), and remove_pending_to_obtain_constraints().
00249 { 00250 status.reset_c_pending(); 00251 }
| void Parma_Polyhedra_Library::Polyhedron::clear_pending_generators | ( | ) | [inline, private] |
Sets status to express that there are no longer pending generators.
Definition at line 254 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::reset_g_pending(), and status.
Referenced by clear_generators_up_to_date(), process_pending_generators(), and remove_pending_to_obtain_generators().
00254 { 00255 status.reset_g_pending(); 00256 }
| 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 259 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::reset_sat_c_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(), obtain_sorted_constraints(), process_pending_generators(), and update_generators().
00259 { 00260 status.reset_sat_c_up_to_date(); 00261 // Can get rid of sat_c here. 00262 }
| 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 265 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(), obtain_sorted_generators(), process_pending_constraints(), and update_constraints().
00265 { 00266 status.reset_sat_g_up_to_date(); 00267 // Can get rid of sat_g here. 00268 }
| 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 288 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(), 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().
00288 { 00289 if (topology() != y.topology()) 00290 throw_topology_incompatible("concatenate_assign(y)", "y", y); 00291 00292 // The space dimension of the resulting polyhedron should not 00293 // overflow the maximum allowed space dimension. 00294 const dimension_type added_columns = y.space_dim; 00295 if (added_columns > max_space_dimension() - space_dim) 00296 throw_space_dimension_overflow(topology(), 00297 "concatenate_assign(y)", 00298 "concatenation exceeds the maximum " 00299 "allowed space dimension"); 00300 00301 // If `*this' or `y' are empty polyhedra, it is sufficient to adjust 00302 // the dimension of the space. 00303 if (marked_empty() || y.marked_empty()) { 00304 space_dim += added_columns; 00305 set_empty(); 00306 return; 00307 } 00308 00309 // If `y' is a non-empty 0-dim space polyhedron, the result is `*this'. 00310 if (added_columns == 0) 00311 return; 00312 00313 // If `*this' is a non-empty 0-dim space polyhedron, the result is `y'. 00314 if (space_dim == 0) { 00315 *this = y; 00316 return; 00317 } 00318 00319 // TODO: this implementation is just an executable specification. 00320 Constraint_System cs = y.constraints(); 00321 00322 // The constraints of `x' (possibly with pending rows) are required. 00323 if (has_pending_generators()) 00324 process_pending_generators(); 00325 else if (!constraints_are_up_to_date()) 00326 update_constraints(); 00327 00328 // The matrix for the new system of constraints is obtained 00329 // by leaving the old system of constraints in the upper left-hand side 00330 // and placing the constraints of `cs' in the lower right-hand side. 00331 // NOTE: here topologies agree, whereas dimensions may not agree. 00332 dimension_type old_num_rows = con_sys.num_rows(); 00333 dimension_type old_num_columns = con_sys.num_columns(); 00334 dimension_type added_rows = cs.num_rows(); 00335 00336 // We already dealt with the cases of an empty or zero-dim `y' polyhedron; 00337 // also, `cs' contains the low-level constraints, at least. 00338 PPL_ASSERT(added_rows > 0 && added_columns > 0); 00339 00340 con_sys.add_zero_rows_and_columns(added_rows, added_columns, 00341 Linear_Row::Flags(topology(), 00342 Linear_Row::RAY_OR_POINT_OR_INEQUALITY)); 00343 // Move the epsilon coefficient to the last column, if needed. 00344 if (!is_necessarily_closed()) 00345 con_sys.swap_columns(old_num_columns - 1, 00346 old_num_columns - 1 + added_columns); 00347 dimension_type cs_num_columns = cs.num_columns(); 00348 // Steal the constraints from `cs' and put them in `con_sys' 00349 // using the right displacement for coefficients. 00350 for (dimension_type i = added_rows; i-- > 0; ) { 00351 Constraint& c_old = cs[i]; 00352 Constraint& c_new = con_sys[old_num_rows + i]; 00353 // Method `add_zero_rows_and_columns', by default, added inequalities. 00354 if (c_old.is_equality()) 00355 c_new.set_is_equality(); 00356 // The inhomogeneous term is not displaced. 00357 std::swap(c_new[0], c_old[0]); 00358 // All homogeneous terms (included the epsilon coefficient, 00359 // if present) are displaced by `space_dim' columns. 00360 for (dimension_type j = 1; j < cs_num_columns; ++j) 00361 std::swap(c_old[j], c_new[space_dim + j]); 00362 } 00363 00364 if (can_have_something_pending()) { 00365 // If `*this' can support pending constraints, then, since we have 00366 // resized the system of constraints, we must also add to the generator 00367 // system those lines corresponding to the newly added dimensions, 00368 // because the non-pending parts of `con_sys' and `gen_sys' must still 00369 // be a DD pair in minimal form. 00370 gen_sys.add_rows_and_columns(added_columns); 00371 gen_sys.set_sorted(false); 00372 if (!is_necessarily_closed()) 00373 gen_sys.swap_columns(old_num_columns - 1, 00374 old_num_columns - 1 + added_columns); 00375 // The added lines are not pending. 00376 gen_sys.unset_pending_rows(); 00377 // Since we added new lines at the beginning of `x.gen_sys', 00378 // we also have to adjust the saturation matrix `sat_c'. 00379 // FIXME: if `sat_c' is not up-to-date, couldn't we directly update 00380 // `sat_g' by resizing it and shifting its columns? 00381 if (!sat_c_is_up_to_date()) { 00382 sat_c.transpose_assign(sat_g); 00383 set_sat_c_up_to_date(); 00384 } 00385 clear_sat_g_up_to_date(); 00386 sat_c.resize(sat_c.num_rows() + added_columns, sat_c.num_columns()); 00387 // The old saturation rows are copied at the end of the matrix. 00388 // The newly introduced lines saturate all the non-pending constraints, 00389 // thus their saturation rows are made of zeroes. 00390 for (dimension_type i = sat_c.num_rows() - added_columns; i-- > 0; ) 00391 std::swap(sat_c[i], sat_c[i+added_columns]); 00392 // Since `added_rows > 0', we now have pending constraints. 00393 set_constraints_pending(); 00394 } 00395 else { 00396 // The polyhedron cannot have pending constraints. 00397 con_sys.unset_pending_rows(); 00398 #if BE_LAZY 00399 con_sys.set_sorted(false); 00400 #else 00401 con_sys.sort_rows(); 00402 #endif 00403 clear_constraints_minimized(); 00404 clear_generators_up_to_date(); 00405 clear_sat_g_up_to_date(); 00406 clear_sat_c_up_to_date(); 00407 } 00408 // Update space dimension. 00409 space_dim += added_columns; 00410 00411 // The system of constraints may be unsatisfiable, 00412 // thus we do not check for satisfiability. 00413 PPL_ASSERT_HEAVY(OK()); 00414 }
| Congruence_System Parma_Polyhedra_Library::Polyhedron::congruences | ( | ) | const [inline] |
Returns a system of (equality) congruences satisfied by *this.
Definition at line 357 of file Polyhedron.inlines.hh.
References minimized_constraints().
00357 { 00358 return Congruence_System(minimized_constraints()); 00359 }
| 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 690 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().
00690 { 00691 // `var' should be one of the dimensions of the polyhedron. 00692 const dimension_type var_space_dim = var.space_dimension(); 00693 if (space_dim < var_space_dim) 00694 throw_dimension_incompatible("constrains(v)", "v", var); 00695 00696 // An empty polyhedron constrains all variables. 00697 if (marked_empty()) 00698 return true; 00699 00700 if (generators_are_up_to_date() && !has_pending_constraints()) { 00701 // Since generators are up-to-date and there are no pending 00702 // constraints, the generator system (since it is well formed) 00703 // contains a point. Hence the polyhedron is not empty. 00704 if (constraints_are_up_to_date() && !has_pending_generators()) 00705 // Here a variable is constrained if and only if it is 00706 // syntactically constrained. 00707 goto syntactic_check; 00708 00709 if (generators_are_minimized()) { 00710 // Try a quick, incomplete check for the universe polyhedron: 00711 // a universe polyhedron constrains no variable. 00712 // Count the number of non-pending 00713 // (hence, linearly independent) lines. 00714 dimension_type num_lines = 0; 00715 const dimension_type first_pending = gen_sys.first_pending_row(); 00716 for (dimension_type i = first_pending; i-- > 0; ) 00717 if (gen_sys[i].is_line()) 00718 ++num_lines; 00719 00720 if (num_lines == space_dim) 00721 return false; 00722 } 00723 00724 // Scan generators: perhaps we will find a generator equivalent to 00725 // line(var) or a pair of generators equivalent to ray(-var) and 00726 // ray(var). 00727 bool have_positive_ray = false; 00728 bool have_negative_ray = false; 00729 const dimension_type var_id = var.id(); 00730 for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) { 00731 const Generator& gen_sys_i = gen_sys[i]; 00732 if (gen_sys_i.is_line_or_ray()) { 00733 const Linear_Row& row = gen_sys_i; 00734 const int sign = sgn(row.coefficient(var_id)); 00735 if (sign != 0) { 00736 for (dimension_type j = space_dim+1; --j > 0; ) 00737 if (j != var_id && row[j] != 0) 00738 goto next; 00739 if (gen_sys_i.is_line()) 00740 return true; 00741 if (sign > 0) 00742 if (have_negative_ray) 00743 return true; 00744 else 00745 have_positive_ray = true; 00746 else if (have_positive_ray) 00747 return true; 00748 else 00749 have_negative_ray = true; 00750 } 00751 } 00752 next: 00753 ; 00754 } 00755 00756 // We are still here: at least we know that, since generators are 00757 // up-to-date and there are no pending constraints, then the 00758 // generator system (since it is well formed) contains a point. 00759 // Hence the polyhedron is not empty. 00760 if (has_pending_generators()) 00761 process_pending_generators(); 00762 else if (!constraints_are_up_to_date()) 00763 update_constraints(); 00764 goto syntactic_check; 00765 } 00766 00767 // We must minimize to detect emptiness and obtain constraints. 00768 if (!minimize()) 00769 return true; 00770 00771 syntactic_check: 00772 for (dimension_type i = con_sys.num_rows(); i-- > 0; ) 00773 if (con_sys[i].coefficient(var) != 0) 00774 return true; 00775 return false; 00776 }
| const PPL::Constraint_System & Parma_Polyhedra_Library::Polyhedron::constraints | ( | ) | const |
Returns the system of constraints.
Definition at line 74 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(), BHZ09_NNC_poly_hull_assign_if_exact(), 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().
00074 { 00075 if (marked_empty()) { 00076 // We want `con_sys' to only contain the unsatisfiable constraint 00077 // of the appropriate dimension. 00078 if (con_sys.has_no_rows()) { 00079 // The 0-dim unsatisfiable constraint is extended to 00080 // the appropriate dimension and then stored in `con_sys'. 00081 Constraint_System unsat_cs = Constraint_System::zero_dim_empty(); 00082 unsat_cs.adjust_topology_and_space_dimension(topology(), space_dim); 00083 const_cast<Constraint_System&>(con_sys).swap(unsat_cs); 00084 } 00085 else { 00086 // Checking that `con_sys' contains the right thing. 00087 PPL_ASSERT(con_sys.space_dimension() == space_dim); 00088 PPL_ASSERT(con_sys.num_rows() == 1); 00089 PPL_ASSERT(con_sys[0].is_inconsistent()); 00090 } 00091 return con_sys; 00092 } 00093 00094 if (space_dim == 0) { 00095 // Zero-dimensional universe. 00096 PPL_ASSERT(con_sys.num_rows() == 0 && con_sys.num_columns() == 0); 00097 return con_sys; 00098 } 00099 00100 // If the polyhedron has pending generators, we process them to obtain 00101 // the constraints. No processing is needed if the polyhedron has 00102 // pending constraints. 00103 if (has_pending_generators()) 00104 process_pending_generators(); 00105 else if (!constraints_are_up_to_date()) 00106 update_constraints(); 00107 00108 // TODO: reconsider whether to really sort constraints at this stage. 00109 #if ENSURE_SORTEDNESS 00110 // We insist in returning a sorted system of constraints, 00111 // but sorting is useless if there are pending constraints. 00112 if (!has_pending_constraints()) 00113 obtain_sorted_constraints(); 00114 #endif 00115 return con_sys; 00116 }
| 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 138 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().
00138 { 00139 return status.test_c_minimized(); 00140 }
| 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 128 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(), drop_some_non_integer_points(), Parma_Polyhedra_Library::Grid::Grid(), H79_widening_assign(), intersection_assign(), 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().
00128 { 00129 return status.test_c_up_to_date(); 00130 }
| 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 3645 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(), BHZ09_NNC_poly_hull_assign_if_exact(), Parma_Polyhedra_Library::Pointset_Powerset< PSET >::check_containment(), H79_widening_assign(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), poly_difference_assign(), poly_hull_assign_if_exact(), and strictly_contains().
03645 { 03646 const Polyhedron& x = *this; 03647 03648 // Topology compatibility check. 03649 if (x.topology() != y.topology()) 03650 throw_topology_incompatible("contains(y)", "y", y); 03651 03652 // Dimension-compatibility check. 03653 if (x.space_dim != y.space_dim) 03654 throw_dimension_incompatible("contains(y)", "y", y); 03655 03656 if (y.marked_empty()) 03657 return true; 03658 else if (x.marked_empty()) 03659 return y.is_empty(); 03660 else if (y.space_dim == 0) 03661 return true; 03662 else if (x.quick_equivalence_test(y) == Polyhedron::TVB_TRUE) 03663 return true; 03664 else 03665 return y.is_included_in(x); 03666 }
| 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::Constraint::is_inconsistent(), Parma_Polyhedra_Library::Checked::le, marked_empty(), Parma_Polyhedra_Library::Matrix::num_rows(), PPL_DIRTY_TEMP_COEFFICIENT, process_pending(), space_dim, Parma_Polyhedra_Library::Constraint::STRICT_INEQUALITY, 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 false; 00574 00575 // FIXME: do also exploit info regarding rays and lines, if possible. 00576 // Is any integer point already available? 00577 PPL_ASSERT(!has_pending_constraints()); 00578 if (generators_are_up_to_date()) 00579 for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) 00580 if (gen_sys[i].is_point() && gen_sys[i].divisor() == 1) 00581 return true; 00582 00583 const Constraint_System& cs = constraints(); 00584 #if 0 // TEMPORARILY DISABLED. 00585 MIP_Problem mip(space_dim, 00586 cs.begin(), cs.end(), 00587 Variables_Set(Variable(0), Variable(space_dim-1))); 00588 #else 00589 // FIXME: temporary workaround, to be removed as soon as the MIP 00590 // problem class will correctly and precisely handle 00591 // ((strict) in-) equality constraints having all integer variables. 00592 MIP_Problem mip(space_dim); 00593 mip.add_to_integer_space_dimensions(Variables_Set(Variable(0), 00594 Variable(space_dim-1))); 00595 PPL_DIRTY_TEMP_COEFFICIENT(homogeneous_gcd); 00596 PPL_DIRTY_TEMP_COEFFICIENT(gcd); 00597 PPL_DIRTY_TEMP0(mpq_class, rational_inhomogeneous); 00598 PPL_DIRTY_TEMP_COEFFICIENT(tightened_inhomogeneous); 00599 for (Constraint_System::const_iterator cs_i = cs.begin(), 00600 cs_end = cs.end(); cs_i != cs_end; ++cs_i) { 00601 const Constraint& c = *cs_i; 00602 const Constraint::Type c_type = c.type(); 00603 const Coefficient& inhomogeneous = c.inhomogeneous_term(); 00604 if (c_type == Constraint::STRICT_INEQUALITY) { 00605 // CHECKME: should we change the behavior of Linear_Expression(c) ? 00606 // Compute the GCD of the coefficients of c 00607 // (disregarding the inhomogeneous term and the espilon dimension). 00608 homogeneous_gcd = 0; 00609 for (dimension_type i = space_dim; i-- > 0; ) 00610 gcd_assign(homogeneous_gcd, 00611 homogeneous_gcd, c.coefficient(Variable(i))); 00612 if (homogeneous_gcd == 0) { 00613 // NOTE: since tautological constraints are already filtered away 00614 // by iterators, here we must have an inconsistent constraint. 00615 PPL_ASSERT(c.is_inconsistent()); 00616 return false; 00617 } 00618 Linear_Expression le; 00619 for (dimension_type i = space_dim; i-- > 0; ) 00620 le += (c.coefficient(Variable(i)) / homogeneous_gcd) * Variable(i); 00621 // Add the integer part of `inhomogeneous'. 00622 le += (inhomogeneous / homogeneous_gcd); 00623 // Further tighten the constraint if the inhomogeneous term 00624 // was integer, i.e., if `homogeneous_gcd' divides `inhomogeneous'. 00625 gcd_assign(gcd, homogeneous_gcd, inhomogeneous); 00626 if (gcd == homogeneous_gcd) 00627 le -= 1; 00628 mip.add_constraint(le >= 0); 00629 } 00630 else { 00631 // Equality or non-strict inequality. 00632 // If possible, avoid useless gcd computations. 00633 if (inhomogeneous == 0) 00634 // The inhomogeneous term cannot be tightened. 00635 mip.add_constraint(c); 00636 else { 00637 // Compute the GCD of the coefficients of c 00638 // (disregarding the inhomogeneous term) 00639 // to see whether or not the inhomogeneous term can be tightened. 00640 homogeneous_gcd = 0; 00641 for (dimension_type i = space_dim; i-- > 0; ) 00642 gcd_assign(homogeneous_gcd, 00643 homogeneous_gcd, c.coefficient(Variable(i))); 00644 if (homogeneous_gcd == 0) { 00645 // NOTE: since tautological constraints are already filtered away 00646 // by iterators, here we must have an inconsistent constraint. 00647 PPL_ASSERT(c.is_inconsistent()); 00648 return false; 00649 } 00650 else if (homogeneous_gcd == 1) 00651 // The normalized inhomogeneous term is integer: 00652 // add the constraint as-is. 00653 mip.add_constraint(c); 00654 else { 00655 PPL_ASSERT(homogeneous_gcd > 1); 00656 // Here the normalized inhomogeneous term is rational: 00657 // the constraint has to be tightened. 00658 #ifndef NDEBUG 00659 // `homogeneous_gcd' does not divide `inhomogeneous'. 00660 // FIXME: add a divisibility test for Coefficient. 00661 gcd_assign(gcd, homogeneous_gcd, inhomogeneous); 00662 PPL_ASSERT(gcd == 1); 00663 #endif 00664 if (c.type() == Constraint::EQUALITY) 00665 return false; 00666 // Extract the homogeneous part of the constraint. 00667 Linear_Expression le = Linear_Expression(c); 00668 le -= inhomogeneous; 00669 // Tighten the inhomogeneous term. 00670 assign_r(rational_inhomogeneous.get_num(), 00671 inhomogeneous, ROUND_NOT_NEEDED); 00672 assign_r(rational_inhomogeneous.get_den(), 00673 homogeneous_gcd, ROUND_NOT_NEEDED); 00674 // Note: canonicalization is not needed (as gcd == 1). 00675 PPL_ASSERT(is_canonical(rational_inhomogeneous)); 00676 assign_r(tightened_inhomogeneous, 00677 rational_inhomogeneous, ROUND_DOWN); 00678 tightened_inhomogeneous *= homogeneous_gcd; 00679 le += tightened_inhomogeneous; 00680 mip.add_constraint(le >= 0); 00681 } 00682 } 00683 } 00684 } 00685 #endif // TEMPORARY WORKAROUND. 00686 return mip.is_satisfiable(); 00687 }
| 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). |
For simplicity, all the following comments assume we are converting a constraint system source to a generator system dest; the comments for the symmetric case can be obtained by duality.
If some of the constraints in source are redundant, they will be removed. This is why the source is not declared to be a constant parameter.
If start is 0, then source is a sorted system; also, dest is a generator system corresponding to an empty constraint system. If otherwise start is greater than 0, then the two sub-systems of source made by the non-pending rows and the pending rows, respectively, are both sorted; also, dest is the generator system corresponding to the non-pending constraints of source.
Independently from the value of start, dest has lines from index 0 to index num_lines_or_equalities - 1 and rays/points from index num_lines_or_equalities to the last of its rows.
Note that here the rows of sat are indexed by rows of dest and its columns are indexed by rows of source.
We know that polyhedra can be represented by both a system of constraints or a system of generators (points, rays and lines) (see Section Representations of Convex Polyhedra). When we have both descriptions for a polyhedron
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:
find
such that
is a DD pair;
find
such that
is a DD pair.Using Farkas' Lemma we can prove that these two problems are computationally equivalent (i.e., linear-time reducible to each other). Farkas' Lemma establishes a fundamental property of vectors in
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
and
such that the first one satisfies the constraint and the other does not satisfy it. If the adjacency property is not taken in account, the new set of rays is not irredundant, in general.In fact, if
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 348 of file conversion.cc.
References Parma_Polyhedra_Library::Linear_System::add_pending_row(), Parma_Polyhedra_Library::Bit_Matrix::add_recycled_row(), Parma_Polyhedra_Library::Scalar_Products::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(), PPL_DIRTY_TEMP_COEFFICIENT, 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::Bit_Matrix::swap(), swap(), Parma_Polyhedra_Library::Linear_System::topology(), Parma_Polyhedra_Library::Linear_System::unset_pending_rows(), WEIGHT_ADD_MUL, and WEIGHT_BEGIN.
Referenced by add_and_minimize(), and minimize().
00352 { 00353 dimension_type source_num_rows = source.num_rows(); 00354 dimension_type dest_num_rows = dest.num_rows(); 00355 const dimension_type source_num_columns = source.num_columns(); 00356 const dimension_type dest_num_columns = dest.num_columns(); 00357 00358 // By construction, the number of columns of `sat' is the same as 00359 // the number of rows of `source'; also, the number of rows of `sat' 00360 // is the same as the number of rows of `dest'. 00361 PPL_ASSERT(source_num_rows == sat.num_columns()); 00362 PPL_ASSERT(dest_num_rows == sat.num_rows()); 00363 00364 // If `start > 0', then we are converting the pending constraints. 00365 PPL_ASSERT(start == 0 || start == source.first_pending_row()); 00366 00367 // During the iteration on the constraints in `source' we may identify 00368 // constraints that are redundant: these have to be removed by swapping 00369 // the rows of `source', taking care not to compromise the sortedness 00370 // of the constraints that still have to be considered. 00371 // To this end, the following counter keeps the number of redundant 00372 // constraints seen so far, to be used as a displacement when swapping rows. 00373 dimension_type source_num_redundant = 0; 00374 00375 PPL_DIRTY_TEMP_COEFFICIENT(normalized_sp_i); 00376 PPL_DIRTY_TEMP_COEFFICIENT(normalized_sp_o); 00377 00378 // Converting the sub-system of `source' having rows with indexes 00379 // from `start' to the last one (i.e., `source_num_rows' - 1). 00380 for (dimension_type k = start; k < source_num_rows; ) { 00381 00382 // All the `source_num_redundant' redundant constraints identified so far 00383 // have consecutive indices starting from `k'. 00384 if (source_num_redundant > 0) 00385 // Let the next constraint have index `k'. 00386 // There is no need to swap the columns of `sat' (all zeroes). 00387 std::swap(source[k], source[k+source_num_redundant]); 00388 00389 Linear_Row& source_k = source[k]; 00390 00391 // Constraints and generators must have the same dimension, 00392 // otherwise the scalar product below will bomb. 00393 PPL_ASSERT(source_num_columns == dest_num_columns); 00394 00395 // `scalar_prod[i]' will contain the scalar product of the 00396 // constraint `source_k' and the generator `dest[i]'. This 00397 // product is 0 if and only if the generator saturates the 00398 // constraint. 00399 PPL_DIRTY_TEMP0(std::vector<Coefficient>, scalar_prod); 00400 const int needed_space = dest_num_rows - scalar_prod.size(); 00401 if (needed_space > 0) 00402 scalar_prod.insert(scalar_prod.end(), needed_space, Coefficient_zero()); 00403 // `index_non_zero' will indicate the first generator in `dest' 00404 // that does not saturate the constraint `source_k'. 00405 dimension_type index_non_zero = 0; 00406 for ( ; index_non_zero < dest_num_rows; ++index_non_zero) { 00407 WEIGHT_BEGIN(); 00408 Scalar_Products::assign(scalar_prod[index_non_zero], 00409 source_k, 00410 dest[index_non_zero]); 00411 WEIGHT_ADD_MUL(17, source_num_columns); 00412 if (scalar_prod[index_non_zero] != 0) 00413 // The generator does not saturate the constraint. 00414 break; 00415 // Check if the client has requested abandoning all expensive 00416 // computations. If so, the exception specified by the client 00417 // is thrown now. 00418 maybe_abandon(); 00419 } 00420 for (dimension_type i = index_non_zero + 1; i < dest_num_rows; ++i) { 00421 WEIGHT_BEGIN(); 00422 Scalar_Products::assign(scalar_prod[i], source_k, dest[i]); 00423 WEIGHT_ADD_MUL(25, source_num_columns); 00424 // Check if the client has requested abandoning all expensive 00425 // computations. If so, the exception specified by the client 00426 // is thrown now. 00427 maybe_abandon(); 00428 } 00429 00430 // We first treat the case when `index_non_zero' is less than 00431 // `num_lines_or_equalities', i.e., when the generator that 00432 // does not saturate the constraint `source_k' is a line. 00433 // The other case (described later) is when all the lines 00434 // in `dest' (i.e., all the rows having indexes less than 00435 // `num_lines_or_equalities') do saturate the constraint. 00436 00437 if (index_non_zero < num_lines_or_equalities) { 00438 // Since the generator `dest[index_non_zero]' does not saturate 00439 // the constraint `source_k', it can no longer be a line 00440 // (see saturation rule in Section \ref prelims). 00441 // Therefore, we first transform it to a ray. 00442 dest[index_non_zero].set_is_ray_or_point_or_inequality(); 00443 // Of the two possible choices, we select the ray satisfying 00444 // the constraint (namely, the ray whose scalar product 00445 // with the constraint gives a positive result). 00446 if (scalar_prod[index_non_zero] < 0) { 00447 // The ray `dest[index_non_zero]' lies on the wrong half-space: 00448 // we change it to have the opposite direction. 00449 neg_assign(scalar_prod[index_non_zero]); 00450 for (dimension_type j = dest_num_columns; j-- > 0; ) 00451 neg_assign(dest[index_non_zero][j]); 00452 } 00453 // Having changed a line to a ray, we set `dest' to be a 00454 // non-sorted system, we decrement the number of lines of `dest' and, 00455 // if necessary, we move the new ray below all the remaining lines. 00456 dest.set_sorted(false); 00457 --num_lines_or_equalities; 00458 if (index_non_zero != num_lines_or_equalities) { 00459 std::swap(dest[index_non_zero], 00460 dest[num_lines_or_equalities]); 00461 std::swap(scalar_prod[index_non_zero], 00462 scalar_prod[num_lines_or_equalities]); 00463 } 00464 Linear_Row& dest_nle = dest[num_lines_or_equalities]; 00465 00466 // Computing the new lineality space. 00467 // Since each line must lie on the hyper-plane corresponding to 00468 // the constraint `source_k', the scalar product between 00469 // the line and the constraint must be 0. 00470 // This property already holds for the lines having indexes 00471 // between 0 and `index_non_zero' - 1. 00472 // We have to consider the remaining lines, having indexes 00473 // between `index_non_zero' and `num_lines_or_equalities' - 1. 00474 // Each line that does not saturate the constraint has to be 00475 // linearly combined with generator `dest_nle' so that the 00476 // resulting new line saturates the constraint. 00477 // Note that, by Observation 1 above, the resulting new line 00478 // will still saturate all the constraints that were saturated by 00479 // the old line. 00480 00481 Coefficient& scalar_prod_nle = scalar_prod[num_lines_or_equalities]; 00482 for (dimension_type 00483 i = index_non_zero; i < num_lines_or_equalities; ++i) { 00484 if (scalar_prod[i] != 0) { 00485 // The following fragment optimizes the computation of 00486 // 00487 // Coefficient scale = scalar_prod[i]; 00488 // scale.gcd_assign(scalar_prod_nle); 00489 // Coefficient normalized_sp_i = scalar_prod[i] / scale; 00490 // Coefficient normalized_sp_n = scalar_prod_nle / scale; 00491 // for (dimension_type c = dest_num_columns; c-- > 0; ) { 00492 // dest[i][c] *= normalized_sp_n; 00493 // dest[i][c] -= normalized_sp_i * dest_nle[c]; 00494 // } 00495 normalize2(scalar_prod[i], 00496 scalar_prod_nle, 00497 normalized_sp_i, 00498 normalized_sp_o); 00499 Linear_Row& dest_i = dest[i]; 00500 for (dimension_type c = dest_num_columns; c-- > 0; ) { 00501 Coefficient& dest_i_c = dest_i[c]; 00502 dest_i_c *= normalized_sp_o; 00503 sub_mul_assign(dest_i_c, normalized_sp_i, dest_nle[c]); 00504 } 00505 dest_i.strong_normalize(); 00506 scalar_prod[i] = 0; 00507 // `dest' has already been set as non-sorted. 00508 } 00509 } 00510 00511 // Computing the new pointed cone. 00512 // Similarly to what we have done during the computation of 00513 // the lineality space, we consider all the remaining rays 00514 // (having indexes strictly greater than `num_lines_or_equalities') 00515 // that do not saturate the constraint `source_k'. These rays 00516 // are positively combined with the ray `dest_nle' so that the 00517 // resulting new rays saturate the constraint. 00518 for (dimension_type 00519 i = num_lines_or_equalities + 1; i < dest_num_rows; ++i) { 00520 if (scalar_prod[i] != 0) { 00521 // The following fragment optimizes the computation of 00522 // 00523 // Coefficient scale = scalar_prod[i]; 00524 // scale.gcd_assign(scalar_prod_nle); 00525 // Coefficient normalized_sp_i = scalar_prod[i] / scale; 00526 // Coefficient normalized_sp_n = scalar_prod_nle / scale; 00527 // for (dimension_type c = dest_num_columns; c-- > 0; ) { 00528 // dest[i][c] *= normalized_sp_n; 00529 // dest[i][c] -= normalized_sp_i * dest_nle[c]; 00530 // } 00531 normalize2(scalar_prod[i], 00532 scalar_prod_nle, 00533 normalized_sp_i, 00534 normalized_sp_o); 00535 Linear_Row& dest_i = dest[i]; 00536 WEIGHT_BEGIN(); 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 WEIGHT_ADD_MUL(41, dest_num_columns); 00546 } 00547 // Check if the client has requested abandoning all expensive 00548 // computations. If so, the exception specified by the client 00549 // is thrown now. 00550 maybe_abandon(); 00551 } 00552 // Since the `scalar_prod_nle' is positive (by construction), it 00553 // does not saturate the constraint `source_k'. Therefore, if 00554 // the constraint is an inequality, we set to 1 the 00555 // corresponding element of `sat' ... 00556 Bit_Row& sat_nle = sat[num_lines_or_equalities]; 00557 if (source_k.is_ray_or_point_or_inequality()) 00558 sat_nle.set(k); 00559 // ... otherwise, the constraint is an equality which is 00560 // violated by the generator `dest_nle': the generator has to be 00561 // removed from `dest'. 00562 else { 00563 --dest_num_rows; 00564 std::swap(dest_nle, dest[dest_num_rows]); 00565 std::swap(scalar_prod_nle, scalar_prod[dest_num_rows]); 00566 std::swap(sat_nle, sat[dest_num_rows]); 00567 // `dest' has already been set as non-sorted. 00568 } 00569 // We continue with the next constraint. 00570 ++k; 00571 } 00572 // Here we have `index_non_zero' >= `num_lines_or_equalities', 00573 // so that all the lines in `dest' saturate the constraint `source_k'. 00574 else { 00575 // First, we reorder the generators in `dest' as follows: 00576 // -# all the lines should have indexes between 0 and 00577 // `num_lines_or_equalities' - 1 (this already holds); 00578 // -# all the rays that saturate the constraint should have 00579 // indexes between `num_lines_or_equalities' and 00580 // `lines_or_equal_bound' - 1; these rays form the set Q=. 00581 // -# all the rays that have a positive scalar product with the 00582 // constraint should have indexes between `lines_or_equal_bound' 00583 // and `sup_bound' - 1; these rays form the set Q+. 00584 // -# all the rays that have a negative scalar product with the 00585 // constraint should have indexes between `sup_bound' and 00586 // `dest_num_rows' - 1; these rays form the set Q-. 00587 dimension_type lines_or_equal_bound = num_lines_or_equalities; 00588 dimension_type inf_bound = dest_num_rows; 00589 // While we find saturating generators, we simply increment 00590 // `lines_or_equal_bound'. 00591 while (inf_bound > lines_or_equal_bound 00592 && scalar_prod[lines_or_equal_bound] == 0) 00593 ++lines_or_equal_bound; 00594 dimension_type sup_bound = lines_or_equal_bound; 00595 while (inf_bound > sup_bound) { 00596 const int sp_sign = sgn(scalar_prod[sup_bound]); 00597 if (sp_sign == 0) { 00598 // This generator has to be moved in Q=. 00599 std::swap(dest[sup_bound], dest[lines_or_equal_bound]); 00600 std::swap(scalar_prod[sup_bound], scalar_prod[lines_or_equal_bound]); 00601 std::swap(sat[sup_bound], sat[lines_or_equal_bound]); 00602 ++lines_or_equal_bound; 00603 ++sup_bound; 00604 dest.set_sorted(false); 00605 } 00606 else if (sp_sign < 0) { 00607 // This generator has to be moved in Q-. 00608 --inf_bound; 00609 std::swap(dest[sup_bound], dest[inf_bound]); 00610 std::swap(scalar_prod[sup_bound], scalar_prod[inf_bound]); 00611 std::swap(sat[sup_bound], sat[inf_bound]); 00612 dest.set_sorted(false); 00613 } 00614 else 00615 // sp_sign > 0: this generator has to be moved in Q+. 00616 ++sup_bound; 00617 } 00618 00619 if (sup_bound == dest_num_rows) { 00620 // Here the set Q- is empty. 00621 // If the constraint is an inequality, then all the generators 00622 // in Q= and Q+ satisfy the constraint. The constraint is redundant 00623 // and it can be safely removed from the constraint system. 00624 // This is why the `source' parameter is not declared `const'. 00625 if (source_k.is_ray_or_point_or_inequality()) { 00626 ++source_num_redundant; 00627 --source_num_rows; 00628 // NOTE: we continue with the next cycle of the loop 00629 // without incrementing the index `k', because: 00630 // -# either `k == source_num_rows', and we will exit the loop; 00631 // -# or, having increased `source_num_redundant', we will swap 00632 // in position `k' a constraint that still has to be examined. 00633 } 00634 else { 00635 // The constraint is an equality, so that all the generators 00636 // in Q+ violate it. Since the set Q- is empty, we can simply 00637 // remove from `dest' all the generators of Q+. 00638 dest_num_rows = lines_or_equal_bound; 00639 // We continue with the next constraint. 00640 ++k; 00641 } 00642 } 00643 else { 00644 // The set Q- is not empty, i.e., at least one generator 00645 // violates the constraint `source_k'. 00646 // We have to further distinguish two cases: 00647 if (sup_bound == num_lines_or_equalities) 00648 // The set Q+ is empty, so that all generators that satisfy 00649 // the constraint also saturate it. 00650 // We can simply remove from `dest' all the generators in Q-. 00651 dest_num_rows = sup_bound; 00652 else { 00653 // The sets Q+ and Q- are both non-empty. 00654 // The generators of the new pointed cone are all those satisfying 00655 // the constraint `source_k' plus a set of new rays enjoying 00656 // the following properties: 00657 // -# they lie on the hyper-plane represented by the constraint 00658 // -# they are obtained as a positive combination of two 00659 // adjacent rays, the first taken from Q+ and the second 00660 // taken from Q-. 00661 00662 // The adjacency property is necessary to have an irredundant 00663 // set of new rays (see proposition 2). 00664 const dimension_type bound = dest_num_rows; 00665 00666 // In the following loop, 00667 // `i' runs through the generators in the set Q+ and 00668 // `j' runs through the generators in the set Q-. 00669 for (dimension_type i = lines_or_equal_bound; i < sup_bound; ++i) { 00670 for(dimension_type j = sup_bound; j < bound; ++j) { 00671 // Checking if generators `dest[i]' and `dest[j]' are adjacent. 00672 // If there exist another generator that saturates 00673 // all the constraints saturated by both `dest[i]' and 00674 // `dest[j]', then they are NOT adjacent. 00675 PPL_ASSERT(sat[i].last() == ULONG_MAX || sat[i].last() < k); 00676 PPL_ASSERT(sat[j].last() == ULONG_MAX || sat[j].last() < k); 00677 00678 // Being the union of `sat[i]' and `sat[j]', 00679 // `new_satrow' corresponds to a ray that saturates all the 00680 // constraints saturated by both `dest[i]' and `dest[j]'. 00681 Bit_Row new_satrow(sat[i], sat[j]); 00682 00683 // Compute the number of common saturators. 00684 // NOTE: this number has to be less than `k' because 00685 // we are treating the `k'-th constraint. 00686 const dimension_type 00687 num_common_satur = k - new_satrow.count_ones(); 00688 00689 // Even before actually creating the new ray as a 00690 // positive combination of `dest[i]' and `dest[j]', 00691 // we exploit saturation information to check if 00692 // it can be an extremal ray. To this end, we refer 00693 // to the definition of a minimal proper face 00694 // (see comments in Polyhedron.defs.hh): 00695 // an extremal ray saturates at least `n' - `t' - 1 00696 // constraints, where `n' is the dimension of the space 00697 // and `t' is the dimension of the lineality space. 00698 // Since `n == source_num_columns - 1' and 00699 // `t == num_lines_or_equalities', we obtain that 00700 // an extremal ray saturates at least 00701 // `source_num_columns - num_lines_or_equalities - 2' 00702 // constraints. 00703 if (num_common_satur 00704 >= source_num_columns - num_lines_or_equalities - 2) { 00705 // The minimal proper face rule is satisfied. 00706 // Now we actually check for redundancy by computing 00707 // adjacency information. 00708 bool redundant = false; 00709 WEIGHT_BEGIN(); 00710 for (dimension_type 00711 l = num_lines_or_equalities; l < bound; ++l) 00712 if (l != i && l != j 00713 && subset_or_equal(sat[l], new_satrow)) { 00714 // Found another generator saturating all the 00715 // constraints saturated by both `dest[i]' and `dest[j]'. 00716 redundant = true; 00717 break; 00718 } 00719 PPL_ASSERT(bound >= num_lines_or_equalities); 00720 WEIGHT_ADD_MUL(15, bound - num_lines_or_equalities); 00721 if (!redundant) { 00722 // Adding the new ray to `dest' and the corresponding 00723 // saturation row to `sat'. 00724 if (dest_num_rows == dest.num_rows()) { 00725 // Make room for one more row. 00726 dest.add_pending_row(Linear_Row::Flags(dest.topology(), 00727 Linear_Row::RAY_OR_POINT_OR_INEQUALITY)); 00728 sat.add_recycled_row(new_satrow); 00729 } 00730 else 00731 sat[dest_num_rows].swap(new_satrow); 00732 00733 Linear_Row& new_row = dest[dest_num_rows]; 00734 // The following fragment optimizes the computation of 00735 // 00736 // Coefficient scale = scalar_prod[i]; 00737 // scale.gcd_assign(scalar_prod[j]); 00738 // Coefficient normalized_sp_i = scalar_prod[i] / scale; 00739 // Coefficient normalized_sp_j = scalar_prod[j] / scale; 00740 // for (dimension_type c = dest_num_columns; c-- > 0; ) { 00741 // new_row[c] = normalized_sp_i * dest[j][c]; 00742 // new_row[c] -= normalized_sp_j * dest[i][c]; 00743 // } 00744 normalize2(scalar_prod[i], 00745 scalar_prod[j], 00746 normalized_sp_i, 00747 normalized_sp_o); 00748 WEIGHT_BEGIN(); 00749 for (dimension_type c = dest_num_columns; c-- > 0; ) { 00750 Coefficient& new_row_c = new_row[c]; 00751 new_row_c = normalized_sp_i * dest[j][c]; 00752 sub_mul_assign(new_row_c, normalized_sp_o, dest[i][c]); 00753 } 00754 WEIGHT_ADD_MUL(86, dest_num_columns); 00755 new_row.strong_normalize(); 00756 // Since we added a new generator to `dest', 00757 // we also add a new element to `scalar_prod'; 00758 // by construction, the new ray lies on the hyper-plane 00759 // represented by the constraint `source_k'. 00760 // Thus, the added scalar product is 0. 00761 PPL_ASSERT(scalar_prod.size() >= dest_num_rows); 00762 if (scalar_prod.size() <= dest_num_rows) 00763 scalar_prod.push_back(Coefficient_zero()); 00764 else 00765 scalar_prod[dest_num_rows] = Coefficient_zero(); 00766 // Increment the number of generators. 00767 ++dest_num_rows; 00768 } // if (!redundant) 00769 } 00770 } 00771 // Check if the client has requested abandoning all expensive 00772 // computations. If so, the exception specified by the client 00773 // is thrown now. 00774 maybe_abandon(); 00775 } 00776 // Now we substitute the rays in Q- (i.e., the rays violating 00777 // the constraint) with the newly added rays. 00778 dimension_type j; 00779 if (source_k.is_ray_or_point_or_inequality()) { 00780 // The constraint is an inequality: 00781 // the violating generators are those in Q-. 00782 j = sup_bound; 00783 // For all the generators in Q+, set to 1 the corresponding 00784 // entry for the constraint `source_k' in the saturation matrix. 00785 for (dimension_type l = lines_or_equal_bound; l < sup_bound; ++l) 00786 sat[l].set(k); 00787 } 00788 else 00789 // The constraint is an equality: 00790 // the violating generators are those in the union of Q+ and Q-. 00791 j = lines_or_equal_bound; 00792 00793 // Swapping the newly added rays 00794 // (index `i' running through `dest_num_rows - 1' down-to `bound') 00795 // with the generators violating the constraint 00796 // (index `j' running through `j' up-to `bound - 1'). 00797 dimension_type i = dest_num_rows; 00798 while (j < bound && i > bound) { 00799 --i; 00800 std::swap(dest[i], dest[j]); 00801 std::swap(scalar_prod[i], scalar_prod[j]); 00802 std::swap(sat[i], sat[j]); 00803 ++j; 00804 dest.set_sorted(false); 00805 } 00806 // Setting the number of generators in `dest': 00807 // - if the number of generators violating the constraint 00808 // is less than or equal to the number of the newly added 00809 // generators, we assign `i' to `dest_num_rows' because 00810 // all generators above this index are significant; 00811 // - otherwise, we assign `j' to `dest_num_rows' because 00812 // all generators below index `j-1' violates the constraint. 00813 dest_num_rows = (j == bound) ? i : j; 00814 } 00815 // We continue with the next constraint. 00816 ++k; 00817 } 00818 } 00819 } 00820 00821 // We may have identified some redundant constraints in `source', 00822 // which have been swapped at the end of the system. 00823 if (source_num_redundant > 0) { 00824 PPL_ASSERT(source_num_redundant == source.num_rows() - source_num_rows); 00825 source.erase_to_end(source_num_rows); 00826 sat.columns_erase_to_end(source_num_rows); 00827 } 00828 // If `start == 0', then `source' was sorted and remained so. 00829 // If otherwise `start > 0', then the two sub-system made by the 00830 // non-pending rows and the pending rows, respectively, were both sorted. 00831 // Thus, the overall system is sorted if and only if either 00832 // `start == source_num_rows' (i.e., the second sub-system is empty) 00833 // or the row ordering holds for the two rows at the boundary between 00834 // the two sub-systems. 00835 if (start > 0 && start < source_num_rows) 00836 source.set_sorted(compare(source[start - 1], source[start]) <= 0); 00837 // There are no longer pending constraints in `source'. 00838 source.unset_pending_rows(); 00839 00840 // We may have identified some redundant rays in `dest', 00841 // which have been swapped at the end of the system. 00842 if (dest_num_rows < dest.num_rows()) { 00843 dest.erase_to_end(dest_num_rows); 00844 // Be careful: we might have erased some of the non-pending rows. 00845 if (dest.first_pending_row() > dest_num_rows) 00846 dest.unset_pending_rows(); 00847 sat.rows_erase_to_end(dest_num_rows); 00848 } 00849 if (dest.is_sorted()) 00850 // If the non-pending generators in `dest' are still declared to be 00851 // sorted, then we have to also check for the sortedness of the 00852 // pending generators. 00853 for (dimension_type i = dest.first_pending_row(); i < dest_num_rows; ++i) 00854 if (compare(dest[i - 1], dest[i]) > 0) { 00855 dest.set_sorted(false); 00856 break; 00857 } 00858 // There are no pending generators in `dest'. 00859 dest.unset_pending_rows(); 00860 00861 return num_lines_or_equalities; 00862 }
| void Parma_Polyhedra_Library::Polyhedron::difference_assign | ( | const Polyhedron & | y | ) | [inline] |
Same as poly_difference_assign(y).
Definition at line 86 of file Polyhedron.inlines.hh.
References poly_difference_assign().
00086 { 00087 poly_difference_assign(y); 00088 }
| void Parma_Polyhedra_Library::Polyhedron::drop_some_non_integer_points | ( | const Variables_Set * | pvars, | |
| Complexity_Class | complexity | |||
| ) | [protected] |
Possibly tightens *this by dropping some points with non-integer coordinates for the space dimensions corresponding to *pvars.
| pvars | When nonzero, points with non-integer coordinates for the variables/space-dimensions contained in *pvars can be discarded. | |
| complexity | The maximal complexity of any algorithms used. |
complexity is ANY_COMPLEXITY. Definition at line 2078 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::ANY_COMPLEXITY, clear_constraints_minimized(), clear_generators_up_to_date(), con_sys, constraints_are_up_to_date(), Parma_Polyhedra_Library::Constraint::epsilon_leq_one(), Parma_Polyhedra_Library::exact_div_assign(), Parma_Polyhedra_Library::gcd_assign(), has_pending_constraints(), has_pending_generators(), Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::Constraint::is_equality(), is_necessarily_closed(), Parma_Polyhedra_Library::Constraint::is_tautological(), marked_empty(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Row::normalize(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), PPL_DIRTY_TEMP_COEFFICIENT, process_pending_constraints(), process_pending_generators(), set_empty(), Parma_Polyhedra_Library::Linear_System::set_sorted(), space_dim, and update_constraints().
02079 { 02080 // There is nothing to do for an empty set of variables. 02081 if (pvars != 0 && pvars->empty()) 02082 return; 02083 02084 // Any empty polyhedron does not contain integer points. 02085 if (marked_empty()) 02086 return; 02087 02088 // A zero-dimensional, universe polyhedron has, by convention, an 02089 // integer point. 02090 if (space_dim == 0) { 02091 set_empty(); 02092 return; 02093 } 02094 02095 // The constraints (possibly with pending rows) are required. 02096 if (has_pending_generators()) { 02097 // Processing of pending generators is exponential in the worst case. 02098 if (complexity != ANY_COMPLEXITY) 02099 return; 02100 else 02101 process_pending_generators(); 02102 } 02103 if (!constraints_are_up_to_date()) { 02104 // Constraints update is exponential in the worst case. 02105 if (complexity != ANY_COMPLEXITY) 02106 return; 02107 else 02108 update_constraints(); 02109 } 02110 // For NNC polyhedra we need to process any pending constraints. 02111 if (!is_necessarily_closed() && has_pending_constraints()) { 02112 if (complexity != ANY_COMPLEXITY) 02113 return; 02114 else if (!process_pending_constraints()) 02115 // We just discovered the polyhedron is empty. 02116 return; 02117 } 02118 02119 PPL_ASSERT(!has_pending_generators() && constraints_are_up_to_date()); 02120 PPL_ASSERT(is_necessarily_closed() || !has_pending_constraints()); 02121 02122 bool changed = false; 02123 const dimension_type eps_index = space_dim + 1; 02124 PPL_DIRTY_TEMP_COEFFICIENT(gcd); 02125 02126 for (dimension_type j = con_sys.num_rows(); j-- > 0; ) { 02127 Constraint& c = con_sys[j]; 02128 if (c.is_tautological()) 02129 goto next_constraint; 02130 02131 if (pvars != 0) { 02132 for (dimension_type i = space_dim; i-- > 0; ) 02133 if (c[i+1] != 0 && pvars->find(i) == pvars->end()) 02134 goto next_constraint; 02135 } 02136 02137 if (!is_necessarily_closed()) { 02138 // Transform all strict inequalities into non-strict ones, 02139 // with the inhomogeneous term incremented by 1. 02140 if (c[eps_index] < 0) { 02141 c[eps_index] = 0; 02142 --c[0]; 02143 // Enforce normalization. 02144 // FIXME: is this really necessary? 02145 c.normalize(); 02146 changed = true; 02147 } 02148 } 02149 02150 { 02151 // Compute the GCD of all the homogeneous terms. 02152 dimension_type i = space_dim+1; 02153 while (i > 1) { 02154 const Coefficient& c_i = c[--i]; 02155 if (const int c_i_sign = sgn(c_i)) { 02156 gcd = c_i; 02157 if (c_i_sign < 0) 02158 neg_assign(gcd); 02159 goto compute_gcd; 02160 } 02161 } 02162 // We reach this point only if all the coefficients were zero. 02163 goto next_constraint; 02164 02165 compute_gcd: 02166 if (gcd == 1) 02167 goto next_constraint; 02168 while (i > 1) { 02169 const Coefficient& c_i = c[--i]; 02170 if (c_i != 0) { 02171 // See the comment in Row::normalize(). 02172 gcd_assign(gcd, c_i, gcd); 02173 if (gcd == 1) 02174 goto next_constraint; 02175 } 02176 } 02177 PPL_ASSERT(gcd != 1); 02178 PPL_ASSERT(c[0] % gcd != 0); 02179 02180 // If we have an equality, the polyhedron becomes empty. 02181 if (c.is_equality()) { 02182 set_empty(); 02183 return; 02184 } 02185 02186 // Divide the inhomogeneous coefficients by the GCD. 02187 for (dimension_type k = space_dim+1; --k > 0; ) { 02188 Coefficient& c_k = c[k]; 02189 exact_div_assign(c_k, c_k, gcd); 02190 } 02191 Coefficient& c_0 = c[0]; 02192 const int c_0_sign = sgn(c_0); 02193 c_0 /= gcd; 02194 if (c_0_sign < 0) 02195 --c_0; 02196 changed = true; 02197 } 02198 02199 next_constraint: 02200 ; 02201 } 02202 02203 if (changed) { 02204 if (!is_necessarily_closed()) { 02205 con_sys.insert(Constraint::epsilon_leq_one()); 02206 // FIXME: make sure that the following line really can stay here 02207 // and should not be moved below the brace. 02208 con_sys.set_sorted(false); 02209 } 02210 02211 // After changing the system of constraints, the generators 02212 // are no longer up-to-date and the constraints are no longer 02213 // minimized. 02214 clear_generators_up_to_date(); 02215 clear_constraints_minimized(); 02216 } 02217 PPL_ASSERT_HEAVY(OK()); 02218 }
| void Parma_Polyhedra_Library::Polyhedron::drop_some_non_integer_points | ( | const Variables_Set & | vars, | |
| Complexity_Class | complexity = ANY_COMPLEXITY | |||
| ) | [inline] |
Possibly tightens *this by dropping some points with non-integer coordinates for the space dimensions corresponding to vars.
| vars | Points with non-integer coordinates for these variables/space-dimensions can be discarded. | |
| complexity | The maximal complexity of any algorithms used. |
complexity is ANY_COMPLEXITY. Definition at line 395 of file Polyhedron.inlines.hh.
References drop_some_non_integer_points().
00396 { 00397 drop_some_non_integer_points(&vars, complexity); 00398 }
| void Parma_Polyhedra_Library::Polyhedron::drop_some_non_integer_points | ( | Complexity_Class | complexity = ANY_COMPLEXITY |
) | [inline] |
Possibly tightens *this by dropping some points with non-integer coordinates.
| complexity | The maximal complexity of any algorithms used. |
complexity is ANY_COMPLEXITY. Definition at line 389 of file Polyhedron.inlines.hh.
Referenced by drop_some_non_integer_points().
00389 { 00390 const Variables_Set* p_vs = 0; 00391 drop_some_non_integer_points(p_vs, complexity); 00392 }
| 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(). |
If *this has space dimension
, with
, and var has space dimension
, then the
-th space dimension is expanded to m new space dimensions
,
,
,
.
Definition at line 548 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().
00548 { 00549 // TODO: this implementation is _really_ an executable specification. 00550 00551 // `var' should be one of the dimensions of the vector space. 00552 if (var.space_dimension() > space_dim) 00553 throw_dimension_incompatible("expand_space_dimension(v, m)", "v", var); 00554 00555 // The space dimension of the resulting polyhedron should not 00556 // overflow the maximum allowed space dimension. 00557 if (m > max_space_dimension() - space_dimension()) 00558 throw_space_dimension_overflow(topology(), 00559 "expand_dimension(v, m)", 00560 "adding m new space dimensions exceeds " 00561 "the maximum allowed space dimension"); 00562 00563 // Nothing to do, if no dimensions must be added. 00564 if (m == 0) 00565 return; 00566 00567 // Keep track of the dimension before adding the new ones. 00568 dimension_type old_dim = space_dim; 00569 00570 // Add the required new dimensions. 00571 add_space_dimensions_and_embed(m); 00572 00573 const dimension_type src_d = var.id(); 00574 const Constraint_System& cs = constraints(); 00575 Constraint_System new_constraints; 00576 for (Constraint_System::const_iterator i = cs.begin(), 00577 cs_end = cs.end(); i != cs_end; ++i) { 00578 const Constraint& c = *i; 00579 00580 // If `c' does not constrain `var', skip it. 00581 if (c.coefficient(var) == 0) 00582 continue; 00583 00584 // Each relevant constraint results in `m' new constraints. 00585 for (dimension_type dst_d = old_dim; dst_d < old_dim+m; ++dst_d) { 00586 Linear_Expression e; 00587 for (dimension_type j = old_dim; j-- > 0; ) 00588 e += 00589 c.coefficient(Variable(j)) 00590 * (j == src_d ? Variable(dst_d) : Variable(j)); 00591 e += c.inhomogeneous_term(); 00592 new_constraints.insert(c.is_equality() 00593 ? (e == 0) 00594 : (c.is_nonstrict_inequality() 00595 ? (e >= 0) 00596 : (e > 0))); 00597 } 00598 } 00599 add_recycled_constraints(new_constraints); 00600 PPL_ASSERT_HEAVY(OK()); 00601 }
| 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 3747 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().
| void Parma_Polyhedra_Library::Polyhedron::finalize | ( | ) | [static] |
Finalizes the class.
Definition at line 53 of file Polyhedron_public.cc.
References simplify_num_saturators_p, and simplify_num_saturators_size.
00053 { 00054 delete [] simplify_num_saturators_p; 00055 simplify_num_saturators_p = 0; 00056 simplify_num_saturators_size = 0; 00057 }
| void Parma_Polyhedra_Library::Polyhedron::fold_space_dimensions | ( | const Variables_Set & | vars, | |
| Variable | dest | |||
| ) |
Folds the space dimensions in vars into dest.
| vars | The set of Variable objects corresponding to the space dimensions to be folded; | |
| dest | The variable corresponding to the space dimension that is the destination of the folding operation. |
| std::invalid_argument | Thrown if *this is dimension-incompatible with dest or with one of the Variable objects contained in vars. Also thrown if dest is contained in vars. |
If *this has space dimension
, with
, dest has space dimension
, vars is a set of variables whose maximum space dimension is also less than or equal to
, and dest is not a member of vars, then the space dimensions corresponding to variables in vars are folded into the
-th space dimension.
Definition at line 604 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::Variables_Set::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
00605 { 00606 // TODO: this implementation is _really_ an executable specification. 00607 00608 // `dest' should be one of the dimensions of the polyhedron. 00609 if (dest.space_dimension() > space_dim) 00610 throw_dimension_incompatible("fold_space_dimensions(vs, v)", "v", dest); 00611 00612 // The folding of no dimensions is a no-op. 00613 if (vars.empty()) 00614 return; 00615 00616 // All variables in `vars' should be dimensions of the polyhedron. 00617 if (vars.space_dimension() > space_dim) 00618 throw_dimension_incompatible("fold_space_dimensions(vs, v)", 00619 "vs.space_dimension()", 00620 vars.space_dimension()); 00621 00622 // Moreover, `dest.id()' should not occur in `vars'. 00623 if (vars.find(dest.id()) != vars.end()) 00624 throw_invalid_argument("fold_space_dimensions(vs, v)", 00625 "v should not occur in vs"); 00626 00627 // All of the affine images we are going to compute are not invertible, 00628 // hence we will need to compute the generators of the polyehdron. 00629 // Since we keep taking copies, make sure that a single conversion 00630 // from constraints to generators is computed. 00631 (void) generators(); 00632 // Having generators, we now know if the polyhedron is empty: 00633 // in that case, folding is equivalent to just removing space dimensions. 00634 if (!marked_empty()) { 00635 for (Variables_Set::const_iterator i = vars.begin(), 00636 vs_end = vars.end(); i != vs_end; ++i) { 00637 Polyhedron copy = *this; 00638 copy.affine_image(dest, Linear_Expression(Variable(*i))); 00639 poly_hull_assign(copy); 00640 } 00641 } 00642 remove_space_dimensions(vars); 00643 PPL_ASSERT_HEAVY(OK()); 00644 }
| bool Parma_Polyhedra_Library::Polyhedron::frequency | ( | const Linear_Expression & | expr, | |
| Coefficient & | freq_n, | |||
| Coefficient & | freq_d, | |||
| Coefficient & | val_n, | |||
| Coefficient & | val_d | |||
| ) | const |
Returns true if and only if there exist a unique value val such that *this saturates the equality expr = val.
| expr | The linear expression for which the frequency is needed; | |
| freq_n | If true is returned, the value is set to ; Present for interface compatibility with class Grid, where the frequency can have a non-zero value; | |
| freq_d | If true is returned, the value is set to ; | |
| val_n | The numerator of val; | |
| val_d | The denominator of val; |
| std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
If false is returned, then freq_n, freq_d, val_n and val_d are left untouched.
Definition at line 3462 of file Polyhedron_public.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(), is_empty(), Parma_Polyhedra_Library::Generator::is_line_or_ray(), Parma_Polyhedra_Library::Generator::is_point(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_rows(), PPL_DIRTY_TEMP_COEFFICIENT, process_pending_constraints(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and update_generators().
03464 { 03465 // The dimension of `expr' must be at most the dimension of *this. 03466 if (space_dim < expr.space_dimension()) 03467 throw_dimension_incompatible("frequency(e, ...)", "e", expr); 03468 03469 // If the `expr' has a constant value, then the frequency 03470 // `freq_n' is 0. Otherwise the values for \p expr are not discrete 03471 // and we return false. 03472 03473 // Space dimension = 0: if empty, then return false; 03474 // otherwise the frequency is 1 and the value is 0 03475 if (space_dim == 0) { 03476 if (is_empty()) 03477 return false; 03478 freq_n = 0; 03479 freq_d = 1; 03480 val_n = expr.inhomogeneous_term(); 03481 val_d = 1; 03482 return true; 03483 } 03484 03485 // For an empty polyhedron, we simply return false. 03486 if (marked_empty() 03487 || (has_pending_constraints() && !process_pending_constraints()) 03488 || (!generators_are_up_to_date() && !update_generators())) 03489 return false; 03490 03491 // The polyhedron has updated, possibly pending generators. 03492 // The following loop will iterate through the generator 03493 // to see if `expr' has a constant value. 03494 PPL_DIRTY_TEMP0(mpq_class, value); 03495 03496 // True if we have no other candidate value to compare with. 03497 bool first_candidate = true; 03498 03499 PPL_DIRTY_TEMP_COEFFICIENT(sp); 03500 PPL_DIRTY_TEMP0(mpq_class, candidate); 03501 for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) { 03502 const Generator& gen_sys_i = gen_sys[i]; 03503 Scalar_Products::homogeneous_assign(sp, expr, gen_sys_i); 03504 // Lines and rays in `*this' can cause `expr' to be non-constant. 03505 if (gen_sys_i.is_line_or_ray()) { 03506 const int sp_sign = sgn(sp); 03507 if (sp_sign != 0) 03508 // `expr' is unbounded in `*this'. 03509 return false; 03510 } 03511 else { 03512 // We have a point or a closure point. 03513 PPL_ASSERT(gen_sys_i.is_point() || gen_sys_i.is_closure_point()); 03514 // Notice that we are ignoring the constant term in `expr' here. 03515 // We will add it to the value if there is a constant value. 03516 assign_r(candidate.get_num(), sp, ROUND_NOT_NEEDED); 03517 assign_r(candidate.get_den(), gen_sys_i[0], ROUND_NOT_NEEDED); 03518 candidate.canonicalize(); 03519 if (first_candidate) { 03520 // We have a (new) candidate value. 03521 first_candidate = false; 03522 value = candidate; 03523 } 03524 else if (candidate != value) 03525 return false; 03526 } 03527 } 03528 03529 // Add in the constant term in `expr'. 03530 PPL_DIRTY_TEMP0(mpz_class, n); 03531 assign_r(n, expr.inhomogeneous_term(), ROUND_NOT_NEEDED); 03532 value += n; 03533 // FIXME: avoid these temporaries, if possible. 03534 // This can be done adding an `assign' function working on native 03535 // and checked or an operator= that have on one side a checked and 03536 // on the other a native or checked. 03537 // The reason why now we can't use operator= is the fact that we 03538 // still can have Coefficient defined to mpz_class (and not 03539 // Checked_Number<mpz_class>). 03540 val_n = Coefficient(value.get_num()); 03541 val_d = Coefficient(value.get_den()); 03542 03543 freq_n = 0; 03544 freq_d = 1; 03545 return true; 03546 }
| 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 3054 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(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
03056 { 03057 // Dimension-compatibility checks. 03058 // The dimension of `lhs' should not be greater than the dimension 03059 // of `*this'. 03060 dimension_type lhs_space_dim = lhs.space_dimension(); 03061 if (space_dim < lhs_space_dim) 03062 throw_dimension_incompatible("generalized_affine_image(e1, r, e2)", 03063 "e1", lhs); 03064 // The dimension of `rhs' should not be greater than the dimension 03065 // of `*this'. 03066 const dimension_type rhs_space_dim = rhs.space_dimension(); 03067 if (space_dim < rhs_space_dim) 03068 throw_dimension_incompatible("generalized_affine_image(e1, r, e2)", 03069 "e2", rhs); 03070 03071 // Strict relation symbols are only admitted for NNC polyhedra. 03072 if (is_necessarily_closed() 03073 && (relsym == LESS_THAN || relsym == GREATER_THAN)) 03074 throw_invalid_argument("generalized_affine_image(e1, r, e2)", 03075 "r is a strict relation symbol"); 03076 // The relation symbol cannot be a disequality. 03077 if (relsym == NOT_EQUAL) 03078 throw_invalid_argument("generalized_affine_image(e1, r, e2)", 03079 "r is the disequality relation symbol"); 03080 03081 // Any image of an empty polyhedron is empty. 03082 if (marked_empty()) 03083 return; 03084 03085 // Compute the actual space dimension of `lhs', 03086 // i.e., the highest dimension having a non-zero coefficient in `lhs'. 03087 for ( ; lhs_space_dim > 0; lhs_space_dim--) 03088 if (lhs.coefficient(Variable(lhs_space_dim - 1)) != 0) 03089 break; 03090 // If all variables have a zero coefficient, then `lhs' is a constant: 03091 // we can simply add the constraint `lhs relsym rhs'. 03092 if (lhs_space_dim == 0) { 03093 switch (relsym) { 03094 case LESS_THAN: 03095 refine_no_check(lhs < rhs); 03096 break; 03097 case LESS_OR_EQUAL: 03098 refine_no_check(lhs <= rhs); 03099 break; 03100 case EQUAL: 03101 refine_no_check(lhs == rhs); 03102 break; 03103 case GREATER_OR_EQUAL: 03104 refine_no_check(lhs >= rhs); 03105 break; 03106 case GREATER_THAN: 03107 refine_no_check(lhs > rhs); 03108 break; 03109 case NOT_EQUAL: 03110 // The NOT_EQUAL case has been already dealt with. 03111 throw std::runtime_error("PPL internal error"); 03112 } 03113 return; 03114 } 03115 03116 // Gather in `new_lines' the collections of all the lines having 03117 // the direction of variables occurring in `lhs'. 03118 // While at it, check whether or not there exists a variable 03119 // occurring in both `lhs' and `rhs'. 03120 Generator_System new_lines; 03121 bool lhs_vars_intersects_rhs_vars = false; 03122 for (dimension_type i = lhs_space_dim; i-- > 0; ) 03123 if (lhs.coefficient(Variable(i)) != 0) { 03124 new_lines.insert(line(Variable(i))); 03125 if (rhs.coefficient(Variable(i)) != 0) 03126 lhs_vars_intersects_rhs_vars = true; 03127 } 03128 03129 if (lhs_vars_intersects_rhs_vars) { 03130 // Some variables in `lhs' also occur in `rhs'. 03131 // To ease the computation, we add an additional dimension. 03132 const Variable new_var = Variable(space_dim); 03133 add_space_dimensions_and_embed(1); 03134 03135 // Constrain the new dimension to be equal to the right hand side. 03136 // (check for emptiness because we will add lines). 03137 refine_no_check(new_var == rhs); 03138 if (!is_empty()) { 03139 // Existentially quantify the variables in the left hand side. 03140 add_recycled_generators(new_lines); 03141 03142 // Constrain the new dimension so that it is related to 03143 // the left hand side as dictated by `relsym' 03144 // (we force minimization because we will need the generators). 03145 switch (relsym) { 03146 case LESS_THAN: 03147 refine_no_check(lhs < new_var); 03148 break; 03149 case LESS_OR_EQUAL: 03150 refine_no_check(lhs <= new_var); 03151 break; 03152 case EQUAL: 03153 refine_no_check(lhs == new_var); 03154 break; 03155 case GREATER_OR_EQUAL: 03156 refine_no_check(lhs >= new_var); 03157 break; 03158 case GREATER_THAN: 03159 refine_no_check(lhs > new_var); 03160 break; 03161 case NOT_EQUAL: 03162 // The NOT_EQUAL case has been already dealt with. 03163 throw std::runtime_error("PPL internal error"); 03164 } 03165 } 03166 // Remove the temporarily added dimension. 03167 remove_higher_space_dimensions(space_dim-1); 03168 } 03169 else { 03170 // `lhs' and `rhs' variables are disjoint: 03171 // there is no need to add a further dimension. 03172 03173 // Any image of an empty polyhedron is empty. 03174 // Note: DO check for emptiness here, as we will add lines. 03175 if (is_empty()) 03176 return; 03177 03178 // Existentially quantify the variables in the left hand side. 03179 add_recycled_generators(new_lines); 03180 03181 // Constrain the left hand side expression so that it is related to 03182 // the right hand side expression as dictated by `relsym'. 03183 switch (relsym) { 03184 case LESS_THAN: 03185 refine_no_check(lhs < rhs); 03186 break; 03187 case LESS_OR_EQUAL: 03188 refine_no_check(lhs <= rhs); 03189 break; 03190 case EQUAL: 03191 refine_no_check(lhs == rhs); 03192 break; 03193 case GREATER_OR_EQUAL: 03194 refine_no_check(lhs >= rhs); 03195 break; 03196 case GREATER_THAN: 03197 refine_no_check(lhs > rhs); 03198 break; 03199 case NOT_EQUAL: 03200 // The NOT_EQUAL case has been already dealt with. 03201 throw std::runtime_error("PPL internal error"); 03202 } 03203 } 03204 PPL_ASSERT_HEAVY(OK()); 03205 }
| 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 2861 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(), 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().
02864 { 02865 // The denominator cannot be zero. 02866 if (denominator == 0) 02867 throw_invalid_argument("generalized_affine_image(v, r, e, d)", "d == 0"); 02868 02869 // Dimension-compatibility checks. 02870 // The dimension of `expr' should not be greater than the dimension 02871 // of `*this'. 02872 if (space_dim < expr.space_dimension()) 02873 throw_dimension_incompatible("generalized_affine_image(v, r, e, d)", 02874 "e", expr); 02875 // `var' should be one of the dimensions of the polyhedron. 02876 const dimension_type var_space_dim = var.space_dimension(); 02877 if (space_dim < var_space_dim) 02878 throw_dimension_incompatible("generalized_affine_image(v, r, e, d)", 02879 "v", var); 02880 02881 // Strict relation symbols are only admitted for NNC polyhedra. 02882 if (is_necessarily_closed() 02883 && (relsym == LESS_THAN || relsym == GREATER_THAN)) 02884 throw_invalid_argument("generalized_affine_image(v, r, e, d)", 02885 "r is a strict relation symbol"); 02886 // The relation symbol cannot be a disequality. 02887 if (relsym == NOT_EQUAL) 02888 throw_invalid_argument("generalized_affine_image(v, r, e, d)", 02889 "r is the disequality relation symbol"); 02890 02891 // First compute the affine image. 02892 affine_image(var, expr, denominator); 02893 02894 if (relsym == EQUAL) 02895 // The affine relation is indeed an affine function. 02896 return; 02897 02898 // Any image of an empty polyhedron is empty. 02899 // Note: DO check for emptiness here, as we will later add a ray. 02900 if (is_empty()) 02901 return; 02902 02903 switch (relsym) { 02904 case LESS_OR_EQUAL: 02905 add_generator(ray(-var)); 02906 break; 02907 case GREATER_OR_EQUAL: 02908 add_generator(ray(var)); 02909 break; 02910 case LESS_THAN: 02911 // Intentionally fall through. 02912 case GREATER_THAN: 02913 { 02914 // The relation symbol is strict. 02915 PPL_ASSERT(!is_necessarily_closed()); 02916 // While adding the ray, we minimize the generators 02917 // in order to avoid adding too many redundant generators later. 02918 add_generator(ray(relsym == GREATER_THAN ? var : -var)); 02919 minimize(); 02920 // We split each point of the generator system into two generators: 02921 // a closure point, having the same coordinates of the given point, 02922 // and another point, having the same coordinates for all but the 02923 // `var' dimension, which is displaced along the direction of the 02924 // newly introduced ray. 02925 const dimension_type eps_index = space_dim + 1; 02926 for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) 02927 if (gen_sys[i].is_point()) { 02928 // Add a `var'-displaced copy of `gen_sys[i]' to the generator system. 02929 gen_sys.add_row(gen_sys[i]); 02930 if (relsym == GREATER_THAN) 02931 ++gen_sys[gen_sys.num_rows()-1][var_space_dim]; 02932 else 02933 --gen_sys[gen_sys.num_rows()-1][var_space_dim]; 02934 // Transform `gen_sys[i]' into a closure point. 02935 gen_sys[i][eps_index] = 0; 02936 } 02937 clear_constraints_up_to_date(); 02938 clear_generators_minimized(); 02939 gen_sys.set_sorted(false); 02940 clear_sat_c_up_to_date(); 02941 clear_sat_g_up_to_date(); 02942 } 02943 break; 02944 default: 02945 // The EQUAL and NOT_EQUAL cases have been already dealt with. 02946 throw std::runtime_error("PPL internal error"); 02947 } 02948 PPL_ASSERT_HEAVY(OK()); 02949 }
| 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 3208 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(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
03210 { 03211 // Dimension-compatibility checks. 03212 // The dimension of `lhs' should not be greater than the dimension 03213 // of `*this'. 03214 dimension_type lhs_space_dim = lhs.space_dimension(); 03215 if (space_dim < lhs_space_dim) 03216 throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)", 03217 "e1", lhs); 03218 // The dimension of `rhs' should not be greater than the dimension 03219 // of `*this'. 03220 const dimension_type rhs_space_dim = rhs.space_dimension(); 03221 if (space_dim < rhs_space_dim) 03222 throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)", 03223 "e2", rhs); 03224 03225 // Strict relation symbols are only admitted for NNC polyhedra. 03226 if (is_necessarily_closed() 03227 && (relsym == LESS_THAN || relsym == GREATER_THAN)) 03228 throw_invalid_argument("generalized_affine_preimage(e1, r, e2)", 03229 "r is a strict relation symbol"); 03230 // The relation symbol cannot be a disequality. 03231 if (relsym == NOT_EQUAL) 03232 throw_invalid_argument("generalized_affine_preimage(e1, r, e2)", 03233 "r is the disequality relation symbol"); 03234 03235 // Any preimage of an empty polyhedron is empty. 03236 if (marked_empty()) 03237 return; 03238 03239 // Compute the actual space dimension of `lhs', 03240 // i.e., the highest dimension having a non-zero coefficient in `lhs'. 03241 for ( ; lhs_space_dim > 0; lhs_space_dim--) 03242 if (lhs.coefficient(Variable(lhs_space_dim - 1)) != 0) 03243 break; 03244 03245 // If all variables have a zero coefficient, then `lhs' is a constant: 03246 // in this case, preimage and image happen to be the same. 03247 if (lhs_space_dim == 0) { 03248 generalized_affine_image(lhs, relsym, rhs); 03249 return; 03250 } 03251 03252 // Gather in `new_lines' the collections of all the lines having 03253 // the direction of variables occurring in `lhs'. 03254 // While at it, check whether or not there exists a variable 03255 // occurring in both `lhs' and `rhs'. 03256 Generator_System new_lines; 03257 bool lhs_vars_intersects_rhs_vars = false; 03258 for (dimension_type i = lhs_space_dim; i-- > 0; ) 03259 if (lhs.coefficient(Variable(i)) != 0) { 03260 new_lines.insert(line(Variable(i))); 03261 if (rhs.coefficient(Variable(i)) != 0) 03262 lhs_vars_intersects_rhs_vars = true; 03263 } 03264 03265 if (lhs_vars_intersects_rhs_vars) { 03266 // Some variables in `lhs' also occur in `rhs'. 03267 // To ease the computation, we add an additional dimension. 03268 const Variable new_var = Variable(space_dim); 03269 add_space_dimensions_and_embed(1); 03270 03271 // Constrain the new dimension to be equal to `lhs' 03272 // (also check for emptiness because we have to add lines). 03273 refine_no_check(new_var == lhs); 03274 if (!is_empty()) { 03275 // Existentially quantify the variables in the left hand side. 03276 add_recycled_generators(new_lines); 03277 03278 // Constrain the new dimension so that it is related to 03279 // the right hand side as dictated by `relsym'. 03280 switch (relsym) { 03281 case LESS_THAN: 03282 refine_no_check(new_var < rhs); 03283 break; 03284 case LESS_OR_EQUAL: 03285 refine_no_check(new_var <= rhs); 03286 break; 03287 case EQUAL: 03288 refine_no_check(new_var == rhs); 03289 break; 03290 case GREATER_OR_EQUAL: 03291 refine_no_check(new_var >= rhs); 03292 break; 03293 case GREATER_THAN: 03294 refine_no_check(new_var > rhs); 03295 break; 03296 case NOT_EQUAL: 03297 // The NOT_EQUAL case has been already dealt with. 03298 throw std::runtime_error("PPL internal error"); 03299 } 03300 } 03301 // Remove the temporarily added dimension. 03302 remove_higher_space_dimensions(space_dim-1); 03303 } 03304 else { 03305 // `lhs' and `rhs' variables are disjoint: 03306 // there is no need to add a further dimension. 03307 03308 // Constrain the left hand side expression so that it is related to 03309 // the right hand side expression as dictated by `relsym'. 03310 switch (relsym) { 03311 case LESS_THAN: 03312 refine_no_check(lhs < rhs); 03313 break; 03314 case LESS_OR_EQUAL: 03315 refine_no_check(lhs <= rhs); 03316 break; 03317 case EQUAL: 03318 refine_no_check(lhs == rhs); 03319 break; 03320 case GREATER_OR_EQUAL: 03321 refine_no_check(lhs >= rhs); 03322 break; 03323 case GREATER_THAN: 03324 refine_no_check(lhs > rhs); 03325 break; 03326 case NOT_EQUAL: 03327 // The NOT_EQUAL case has been already dealt with. 03328 throw std::runtime_error("PPL internal error"); 03329 } 03330 // Any image of an empty polyhedron is empty. 03331 // Note: DO check for emptiness here, as we will add lines. 03332 if (is_empty()) 03333 return; 03334 // Existentially quantify all the variables occurring in `lhs'. 03335 add_recycled_generators(new_lines); 03336 } 03337 PPL_ASSERT_HEAVY(OK()); 03338 }
| 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 2953 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(), PPL_DIRTY_TEMP_COEFFICIENT, refine_no_check(), Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), throw_invalid_argument(), and unconstrain().
02956 { 02957 // The denominator cannot be zero. 02958 if (denominator == 0) 02959 throw_invalid_argument("generalized_affine_preimage(v, r, e, d)", 02960 "d == 0"); 02961 02962 // Dimension-compatibility checks. 02963 // The dimension of `expr' should not be greater than the dimension 02964 // of `*this'. 02965 if (space_dim < expr.space_dimension()) 02966 throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)", 02967 "e", expr); 02968 // `var' should be one of the dimensions of the polyhedron. 02969 const dimension_type var_space_dim = var.space_dimension(); 02970 if (space_dim < var_space_dim) 02971 throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)", 02972 "v", var); 02973 02974 // Strict relation symbols are only admitted for NNC polyhedra. 02975 if (is_necessarily_closed() 02976 && (relsym == LESS_THAN || relsym == GREATER_THAN)) 02977 throw_invalid_argument("generalized_affine_preimage(v, r, e, d)", 02978 "r is a strict relation symbol"); 02979 // The relation symbol cannot be a disequality. 02980 if (relsym == NOT_EQUAL) 02981 throw_invalid_argument("generalized_affine_preimage(v, r, e, d)", 02982 "r is the disequality relation symbol"); 02983 02984 // Check whether the affine relation is indeed an affine function. 02985 if (relsym == EQUAL) { 02986 affine_preimage(var, expr, denominator); 02987 return; 02988 } 02989 02990 // Compute the reversed relation symbol to simplify later coding. 02991 Relation_Symbol reversed_relsym; 02992 switch (relsym) { 02993 case LESS_THAN: 02994 reversed_relsym = GREATER_THAN; 02995 break; 02996 case LESS_OR_EQUAL: 02997 reversed_relsym = GREATER_OR_EQUAL; 02998 break; 02999 case GREATER_OR_EQUAL: 03000 reversed_relsym = LESS_OR_EQUAL; 03001 break; 03002 case GREATER_THAN: 03003 reversed_relsym = LESS_THAN; 03004 break; 03005 default: 03006 // The EQUAL and NOT_EQUAL cases have been already dealt with. 03007 throw std::runtime_error("PPL internal error"); 03008 } 03009 03010 // Check whether the preimage of this affine relation can be easily 03011 // computed as the image of its inverse relation. 03012 const Coefficient& var_coefficient = expr.coefficient(var); 03013 if (var_coefficient != 0) { 03014 Linear_Expression inverse_expr 03015 = expr - (denominator + var_coefficient) * var; 03016 PPL_DIRTY_TEMP_COEFFICIENT(inverse_denominator); 03017 neg_assign(inverse_denominator, var_coefficient); 03018 Relation_Symbol inverse_relsym 03019 = (sgn(denominator) == sgn(inverse_denominator)) 03020 ? relsym : reversed_relsym; 03021 generalized_affine_image(var, inverse_relsym, inverse_expr, 03022 inverse_denominator); 03023 return; 03024 } 03025 03026 // Here `var_coefficient == 0', so that the preimage cannot 03027 // be easily computed by inverting the affine relation. 03028 // Shrink the polyhedron by adding the constraint induced 03029 // by the affine relation. 03030 const Relation_Symbol corrected_relsym 03031 = (denominator > 0) ? relsym : reversed_relsym; 03032 switch (corrected_relsym) { 03033 case LESS_THAN: 03034 refine_no_check(denominator*var < expr); 03035 break; 03036 case LESS_OR_EQUAL: 03037 refine_no_check(denominator*var <= expr); 03038 break; 03039 case GREATER_OR_EQUAL: 03040 refine_no_check(denominator*var >= expr); 03041 break; 03042 case GREATER_THAN: 03043 refine_no_check(denominator*var > expr); 03044 break; 03045 default: 03046 // The EQUAL and NOT_EQUAL cases have been already dealt with. 03047 throw std::runtime_error("PPL internal error"); 03048 } 03049 unconstrain(var); 03050 PPL_ASSERT_HEAVY(OK()); 03051 }
| const PPL::Generator_System & Parma_Polyhedra_Library::Polyhedron::generators | ( | ) | const |
Returns the system of generators.
Definition at line 130 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 Parma_Polyhedra_Library::Generator_System::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().
00130 { 00131 if (marked_empty()) { 00132 PPL_ASSERT(gen_sys.has_no_rows()); 00133 // We want `gen_sys' to have the appropriate space dimension, 00134 // even though it is an empty generator system. 00135 if (gen_sys.space_dimension() != space_dim) { 00136 Generator_System gs; 00137 gs.adjust_topology_and_space_dimension(topology(), space_dim); 00138 const_cast<Generator_System&>(gen_sys).swap(gs); 00139 } 00140 return gen_sys; 00141 } 00142 00143 if (space_dim == 0) { 00144 PPL_ASSERT(gen_sys.num_rows() == 0 && gen_sys.num_columns() == 0); 00145 return Generator_System::zero_dim_univ(); 00146 } 00147 00148 // If the polyhedron has pending constraints, we process them to obtain 00149 // the generators (we may discover that the polyhedron is empty). 00150 // No processing is needed if the polyhedron has pending generators. 00151 if ((has_pending_constraints() && !process_pending_constraints()) 00152 || (!generators_are_up_to_date() && !update_generators())) { 00153 // We have just discovered that `*this' is empty. 00154 PPL_ASSERT(gen_sys.has_no_rows()); 00155 // We want `gen_sys' to have the appropriate space dimension, 00156 // even though it is an empty generator system. 00157 if (gen_sys.space_dimension() != space_dim) { 00158 Generator_System gs; 00159 gs.adjust_topology_and_space_dimension(topology(), space_dim); 00160 const_cast<Generator_System&>(gen_sys).swap(gs); 00161 } 00162 return gen_sys; 00163 } 00164 00165 // TODO: reconsider whether to really sort generators at this stage. 00166 #if ENSURE_SORTEDNESS 00167 // We insist in returning a sorted system of generators, 00168 // but sorting is useless if there are pending generators. 00169 if (!has_pending_generators()) 00170 obtain_sorted_generators(); 00171 #else 00172 // In the case of an NNC polyhedron, if the generator system is fully 00173 // minimized (i.e., minimized and with no pending generator), then 00174 // return a sorted system of generators: this is needed so that the 00175 // const_iterator could correctly filter out the matched closure points. 00176 if (!is_necessarily_closed() 00177 && generators_are_minimized() && !has_pending_generators()) 00178 obtain_sorted_generators(); 00179 #endif 00180 return gen_sys; 00181 }
| 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 143 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().
00143 { 00144 return status.test_g_minimized(); 00145 }
| 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 133 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(), frequency(), 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(), 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().
00133 { 00134 return status.test_g_up_to_date(); 00135 }
| PPL::Grid_Generator_System Parma_Polyhedra_Library::Polyhedron::grid_generators | ( | ) | const |
Returns a universe system of grid generators.
Definition at line 198 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Grid_Generator_System::insert(), and space_dim.
Referenced by minimized_grid_generators().
00198 { 00199 Grid_Generator_System ggs(space_dim); 00200 // Trivially true point. 00201 ggs.insert(grid_point(0*(Variable(0)))); 00202 // A line for each dimension. 00203 dimension_type dim = 0; 00204 while (dim < space_dim) 00205 ggs.insert(grid_line(Variable(dim))); 00206 return ggs; 00207 }
| 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 157 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, 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().
00157 { 00158 Polyhedron& x = *this; 00159 // Topology compatibility check. 00160 const Topology topol = x.topology(); 00161 if (topol != y.topology()) 00162 throw_topology_incompatible("H79_widening_assign(y)", "y", y); 00163 // Dimension-compatibility check. 00164 if (x.space_dim != y.space_dim) 00165 throw_dimension_incompatible("H79_widening_assign(y)", "y", y); 00166 00167 #ifndef NDEBUG 00168 { 00169 // We assume that y is contained in or equal to x. 00170 const Polyhedron x_copy = x; 00171 const Polyhedron y_copy = y; 00172 PPL_ASSERT_HEAVY(x_copy.contains(y_copy)); 00173 } 00174 #endif 00175 00176 // If any argument is zero-dimensional or empty, 00177 // the H79-widening behaves as the identity function. 00178 if (x.space_dim == 0 || x.marked_empty() || y.marked_empty()) 00179 return; 00180 00181 // `y.gen_sys' should be in minimal form and 00182 // `y.sat_g' should be up-to-date. 00183 if (y.is_necessarily_closed()) { 00184 if (!y.minimize()) 00185 // `y' is empty: the result is `x'. 00186 return; 00187 } 00188 else { 00189 // Dealing with a NNC polyhedron. 00190 // To obtain a correct reasoning when comparing 00191 // the constraints of `x' with the generators of `y', 00192 // we enforce the inclusion relation holding between 00193 // the two NNC polyhedra `x' and `y' (i.e., `y <= x') 00194 // to also hold for the corresponding eps-representations: 00195 // this is obtained by intersecting the two eps-representations. 00196 Polyhedron& yy = const_cast<Polyhedron&>(y); 00197 yy.intersection_assign(x); 00198 if (yy.is_empty()) 00199 // The result is `x'. 00200 return; 00201 } 00202 00203 // If we only have the generators of `x' and the dimensions of 00204 // the two polyhedra are the same, we can compute the standard 00205 // widening by using the specification in [CousotH78], therefore 00206 // avoiding converting from generators to constraints. 00207 if (x.has_pending_generators() || !x.constraints_are_up_to_date()) { 00208 Constraint_System CH78_cs(topol); 00209 x.select_CH78_constraints(y, CH78_cs); 00210 00211 if (CH78_cs.num_rows() == y.con_sys.num_rows()) { 00212 // Having selected all the constraints, the result is `y'. 00213 x = y; 00214 return; 00215 } 00216 // Otherwise, check if `x' and `y' have the same dimension. 00217 // Note that `y.con_sys' is minimized and `CH78_cs' has no redundant 00218 // constraints, since it is a subset of the former. 00219 else if (CH78_cs.num_equalities() == y.con_sys.num_equalities()) { 00220 // Let `x' be defined by the constraints in `CH78_cs'. 00221 Polyhedron CH78(topol, x.space_dim, UNIVERSE); 00222 CH78.add_recycled_constraints(CH78_cs); 00223 00224 // Check whether we are using the widening-with-tokens technique 00225 // and there still are tokens available. 00226 if (tp != 0 && *tp > 0) { 00227 // There are tokens available. If `CH78' is not a subset of `x', 00228 // then it is less precise and we use one of the available tokens. 00229 if (!x.contains(CH78)) 00230 --(*tp); 00231 } 00232 else 00233 // No tokens. 00234 std::swap(x, CH78); 00235 PPL_ASSERT_HEAVY(x.OK(true)); 00236 return; 00237 } 00238 } 00239 00240 // As the dimension of `x' is strictly greater than the dimension of `y', 00241 // we have to compute the standard widening by selecting a subset of 00242 // the constraints of `x'. 00243 // `x.con_sys' is just required to be up-to-date, because: 00244 // - if `x.con_sys' is unsatisfiable, then by assumption 00245 // also `y' is empty, so that the resulting polyhedron is `x'; 00246 // - redundant constraints in `x.con_sys' do not affect the result 00247 // of the widening, because if they are selected they will be 00248 // redundant even in the result. 00249 if (has_pending_generators()) 00250 process_pending_generators(); 00251 else if (!x.constraints_are_up_to_date()) 00252 x.update_constraints(); 00253 00254 // Copy into `H79_cs' the constraints of `x' that are common to `y', 00255 // according to the definition of the H79 widening. 00256 Constraint_System H79_cs(topol); 00257 Constraint_System x_minus_H79_cs(topol); 00258 x.select_H79_constraints(y, H79_cs, x_minus_H79_cs); 00259 00260 if (x_minus_H79_cs.has_no_rows()) 00261 // We selected all of the constraints of `x', 00262 // thus the result of the widening is `x'. 00263 return; 00264 else { 00265 // We selected a strict subset of the constraints of `x'. 00266 // NOTE: as `x.con_sys' was not necessarily in minimal form, 00267 // this does not imply that the result strictly includes `x'. 00268 // Let `H79' be defined by the constraints in `H79_cs'. 00269 Polyhedron H79(topol, x.space_dim, UNIVERSE); 00270 H79.add_recycled_constraints(H79_cs); 00271 00272 // Check whether we are using the widening-with-tokens technique 00273 // and there still are tokens available. 00274 if (tp != 0 && *tp > 0) { 00275 // There are tokens available. If `H79' is not a subset of `x', 00276 // then it is less precise and we use one of the available tokens. 00277 if (!x.contains(H79)) 00278 --(*tp); 00279 } 00280 else 00281 // No tokens. 00282 std::swap(x, H79); 00283 PPL_ASSERT_HEAVY(x.OK(true)); 00284 } 00285 }
| bool Parma_Polyhedra_Library::Polyhedron::has_pending_constraints | ( | ) | const [inline, private] |
Returns true if there are pending constraints.
Definition at line 158 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(), drop_some_non_integer_points(), frequency(), 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(), 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().
00158 { 00159 return status.test_c_pending(); 00160 }
| bool Parma_Polyhedra_Library::Polyhedron::has_pending_generators | ( | ) | const [inline, private] |
Returns true if there are pending generators.
Definition at line 163 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(), drop_some_non_integer_points(), generators(), H79_widening_assign(), intersection_assign(), 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().
00163 { 00164 return status.test_g_pending(); 00165 }
| 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 168 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().
00168 { 00169 return status.test_c_pending() || status.test_g_pending(); 00170 }
| int32_t Parma_Polyhedra_Library::Polyhedron::hash_code | ( | ) | const [inline] |
Returns a 32-bit hash code for *this.
If x and y are such that x == y, then x.hash_code() == y.hash_code().
Definition at line 45 of file Polyhedron.inlines.hh.
References space_dimension().
00045 { 00046 return space_dimension() & 0x7fffffff; 00047 }
| void Parma_Polyhedra_Library::Polyhedron::initialize | ( | ) | [static] |
Initializes the class.
Definition at line 46 of file Polyhedron_public.cc.
References simplify_num_saturators_p, and simplify_num_saturators_size.
00046 { 00047 PPL_ASSERT(simplify_num_saturators_p == 0); 00048 PPL_ASSERT(simplify_num_saturators_size == 0); 00049 simplify_num_saturators_p = new dimension_type[simplify_num_saturators_size]; 00050 }
| void Parma_Polyhedra_Library::Polyhedron::intersection_assign | ( | const Polyhedron & | y | ) |
Assigns to *this the intersection of *this and y.
| std::invalid_argument | Thrown if *this and y are topology-incompatible or dimension-incompatible. |
Definition at line 1900 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().
01900 { 01901 Polyhedron& x = *this; 01902 // Topology compatibility check. 01903 if (x.topology() != y.topology()) 01904 throw_topology_incompatible("intersection_assign(y)", "y", y); 01905 // Dimension-compatibility check. 01906 if (x.space_dim != y.space_dim) 01907 throw_dimension_incompatible("intersection_assign(y)", "y", y); 01908 01909 // If one of the two polyhedra is empty, the intersection is empty. 01910 if (x.marked_empty()) 01911 return; 01912 if (y.marked_empty()) { 01913 x.set_empty(); 01914 return; 01915 } 01916 01917 // If both polyhedra are zero-dimensional, 01918 // then at this point they are necessarily non-empty, 01919 // so that their intersection is non-empty too. 01920 if (x.space_dim == 0) 01921 return; 01922 01923 // Both systems of constraints have to be up-to-date, 01924 // possibly having pending constraints. 01925 if (x.has_pending_generators()) 01926 x.process_pending_generators(); 01927 else if (!x.constraints_are_up_to_date()) 01928 x.update_constraints(); 01929 01930 if (y.has_pending_generators()) 01931 y.process_pending_generators(); 01932 else if (!y.constraints_are_up_to_date()) 01933 y.update_constraints(); 01934 01935 // Here both systems are up-to-date and possibly have pending constraints 01936 // (but they cannot have pending generators). 01937 PPL_ASSERT(!x.has_pending_generators() && x.constraints_are_up_to_date()); 01938 PPL_ASSERT(!y.has_pending_generators() && y.constraints_are_up_to_date()); 01939 01940 // If `x' can support pending constraints, 01941 // the constraints of `y' are added as pending constraints of `x'. 01942 if (x.can_have_something_pending()) { 01943 x.con_sys.add_pending_rows(y.con_sys); 01944 x.set_constraints_pending(); 01945 } 01946 else { 01947 // `x' cannot support pending constraints. 01948 // If both constraint systems are (fully) sorted, then we can 01949 // merge them; otherwise we simply add the second to the first. 01950 if (x.con_sys.is_sorted() 01951 && y.con_sys.is_sorted() && !y.has_pending_constraints()) 01952 x.con_sys.merge_rows_assign(y.con_sys); 01953 else 01954 x.con_sys.add_rows(y.con_sys); 01955 // Generators are no longer up-to-date and constraints are no 01956 // longer minimized. 01957 x.clear_generators_up_to_date(); 01958 x.clear_constraints_minimized(); 01959 } 01960 PPL_ASSERT_HEAVY(x.OK() && y.OK()); 01961 }
| 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::is_discrete | ( | ) | const [inline] |
Returns true if and only if *this is discrete.
Definition at line 69 of file Polyhedron.inlines.hh.
References affine_dimension().
00069 { 00070 return affine_dimension() == 0; 00071 }
| 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 3669 of file Polyhedron_public.cc.
References intersection_assign(), and is_empty().
Referenced by Parma_Polyhedra_Library::Pointset_Powerset< PSET >::check_containment().
03669 { 03670 Polyhedron z = *this; 03671 z.intersection_assign(y); 03672 return z.is_empty(); 03673 }
| bool Parma_Polyhedra_Library::Polyhedron::is_empty | ( | ) | const [inline] |
Returns true if and only if *this is an empty polyhedron.
Definition at line 180 of file Polyhedron.inlines.hh.
References generators_are_up_to_date(), has_pending_constraints(), marked_empty(), and minimize().
Referenced by affine_dimension(), BFT00_poly_hull_assign_if_exact(), BHZ09_C_poly_hull_assign_if_exact(), BHZ09_NNC_poly_hull_assign_if_exact(), BHZ09_poly_hull_assign_if_exact(), Parma_Polyhedra_Library::Box< ITV >::Box(), Parma_Polyhedra_Library::Pointset_Powerset< PSET >::check_containment(), contains(), frequency(), generalized_affine_image(), generalized_affine_preimage(), Parma_Polyhedra_Library::Grid::Grid(), H79_widening_assign(), is_disjoint_from(), Parma_Polyhedra_Library::Pointset_Powerset< PSET >::linear_partition_aux(), operator<<(), Parma_Polyhedra_Library::Pointset_Powerset< PSET >::Pointset_Powerset(), and simplify_using_context_assign().
00180 { 00181 if (marked_empty()) 00182 return true; 00183 // Try a fast-fail test: if generators are up-to-date and 00184 // there are no pending constraints, then the generator system 00185 // (since it is well formed) contains a point. 00186 if (generators_are_up_to_date() && !has_pending_constraints()) 00187 return false; 00188 return !minimize(); 00189 }
| 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 395 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 BHZ09_C_poly_hull_assign_if_exact(), and contains().
00395 { 00396 // Private method: the caller must ensure the following. 00397 PPL_ASSERT(topology() == y.topology()); 00398 PPL_ASSERT(space_dim == y.space_dim); 00399 PPL_ASSERT(!marked_empty() && !y.marked_empty() && space_dim > 0); 00400 00401 const Polyhedron& x = *this; 00402 00403 // `x' cannot have pending constraints, because we need its generators. 00404 if (x.has_pending_constraints() && !x.process_pending_constraints()) 00405 return true; 00406 // `y' cannot have pending generators, because we need its constraints. 00407 if (y.has_pending_generators()) 00408 y.process_pending_generators(); 00409 00410 #if BE_LAZY 00411 if (!x.generators_are_up_to_date() && !x.update_generators()) 00412 return true; 00413 if (!y.constraints_are_up_to_date()) 00414 y.update_constraints(); 00415 #else 00416 if (!x.generators_are_minimized()) 00417 x.minimize(); 00418 if (!y.constraints_are_minimized()) 00419 y.minimize(); 00420 #endif 00421 00422 PPL_ASSERT_HEAVY(x.OK()); 00423 PPL_ASSERT_HEAVY(y.OK()); 00424 00425 const Generator_System& gs = x.gen_sys; 00426 const Constraint_System& cs = y.con_sys; 00427 00428 if (x.is_necessarily_closed()) 00429 // When working with necessarily closed polyhedra, 00430 // `x' is contained in `y' if and only if all the generators of `x' 00431 // satisfy all the inequalities and saturate all the equalities of `y'. 00432 // This comes from the definition of a polyhedron as the set of 00433 // vectors satisfying a constraint system and the fact that all 00434 // vectors in `x' can be obtained by suitably combining its generators. 00435 for (dimension_type i = cs.num_rows(); i-- > 0; ) { 00436 const Constraint& c = cs[i]; 00437 if (c.is_inequality()) { 00438 for (dimension_type j = gs.num_rows(); j-- > 0; ) { 00439 const Generator& g = gs[j]; 00440 const int sp_sign = Scalar_Products::sign(c, g); 00441 if (g.is_line()) { 00442 if (sp_sign != 0) 00443 return false; 00444 } 00445 else 00446 // `g' is a ray or a point. 00447 if (sp_sign < 0) 00448 return false; 00449 } 00450 } 00451 else { 00452 // `c' is an equality. 00453 for (dimension_type j = gs.num_rows(); j-- > 0; ) 00454 if (Scalar_Products::sign(c, gs[j]) != 0) 00455 return false; 00456 } 00457 } 00458 else { 00459 // Here we have an NNC polyhedron: using the reduced scalar product, 00460 // which ignores the epsilon coefficient. 00461 for (dimension_type i = cs.num_rows(); i-- > 0; ) { 00462 const Constraint& c = cs[i]; 00463 switch (c.type()) { 00464 case Constraint::NONSTRICT_INEQUALITY: 00465 for (dimension_type j = gs.num_rows(); j-- > 0; ) { 00466 const Generator& g = gs[j]; 00467 const int sp_sign = Scalar_Products::reduced_sign(c, g); 00468 if (g.is_line()) { 00469 if (sp_sign != 0) 00470 return false; 00471 } 00472 else 00473 // `g' is a ray or a point or a closure point. 00474 if (sp_sign < 0) 00475 return false; 00476 } 00477 break; 00478 case Constraint::EQUALITY: 00479 for (dimension_type j = gs.num_rows(); j-- > 0; ) 00480 if (Scalar_Products::reduced_sign(c, gs[j]) != 0) 00481 return false; 00482 break; 00483 case Constraint::STRICT_INEQUALITY: 00484 for (dimension_type j = gs.num_rows(); j-- > 0; ) { 00485 const Generator& g = gs[j]; 00486 const int sp_sign = Scalar_Products::reduced_sign(c, g); 00487 switch (g.type()) { 00488 case Generator::POINT: 00489 // If a point violates or saturates a strict inequality 00490 // (when ignoring the epsilon coefficients) then it is 00491 // not included in the polyhedron. 00492 if (sp_sign <= 0) 00493 return false; 00494 break; 00495 case Generator::LINE: 00496 // Lines have to saturate all constraints. 00497 if (sp_sign != 0) 00498 return false; 00499 break; 00500 case Generator::RAY: 00501 // Intentionally fall through. 00502 case Generator::CLOSURE_POINT: 00503 // The generator is a ray or closure point: usual test. 00504 if (sp_sign < 0) 00505 return false; 00506 break; 00507 } 00508 } 00509 break; 00510 } 00511 } 00512 } 00513 00514 // Inclusion holds. 00515 return true; 00516 }
| 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 74 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_space_dimensions_and_embed(), add_space_dimensions_and_project(), BFT00_poly_hull_assign_if_exact(), Parma_Polyhedra_Library::BHRZ03_Certificate::BHRZ03_Certificate(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHZ09_C_poly_hull_assign_if_exact(), BHZ09_NNC_poly_hull_assign_if_exact(), BHZ09_poly_hull_assign_if_exact(), Parma_Polyhedra_Library::H79_Certificate::compare(), Parma_Polyhedra_Library::BHRZ03_Certificate::compare(), concatenate_assign(), drop_some_non_integer_points(), 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(), topological_closure_assign(), and wrap_assign().
00074 { 00075 // We can check either one of the two matrices. 00076 // (`con_sys' is slightly better, since it is placed at offset 0.) 00077 return con_sys.is_necessarily_closed(); 00078 }
| 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 PPL_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_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 PPL_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 PPL_ASSERT(generators_are_minimized()); 00408 if (num_lines == space_dim) { 00409 PPL_ASSERT(num_rays == 0); 00410 return true; 00411 } 00412 PPL_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 PPL_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 PPL_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 PPL_ASSERT(eps_leq_one[i] == 0 && eps_geq_zero[i] == 0); 00487 #endif 00488 return true; 00489 } 00490 } 00491 }
| void Parma_Polyhedra_Library::Polyhedron::limited_BHRZ03_extrapolation_assign | ( | const Polyhedron & | y, | |
| const Constraint_System & | cs, | |||
| unsigned * | tp = 0 | |||
| ) |
Assigns to *this the result of computing the limited extrapolation between *this and y using the BHRZ03-widening operator.
| 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 763 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().
00765 { 00766 Polyhedron& x = *this; 00767 const dimension_type cs_num_rows = cs.num_rows(); 00768 // If `cs' is empty, we fall back to ordinary, non-limited widening. 00769 if (cs_num_rows == 0) { 00770 x.BHRZ03_widening_assign(y, tp); 00771 return; 00772 } 00773 00774 // Topology compatibility check. 00775 if (x.is_necessarily_closed()) { 00776 if (!y.is_necessarily_closed()) 00777 throw_topology_incompatible("limited_BHRZ03_extrapolation_assign(y, cs)", 00778 "y", y); 00779 if (cs.has_strict_inequalities()) 00780 throw_topology_incompatible("limited_BHRZ03_extrapolation_assign(y, cs)", 00781 "cs", cs); 00782 } 00783 else if (y.is_necessarily_closed()) 00784 throw_topology_incompatible("limited_BHRZ03_extrapolation_assign(y, cs)", 00785 "y", y); 00786 00787 // Dimension-compatibility check. 00788 if (x.space_dim != y.space_dim) 00789 throw_dimension_incompatible("limited_BHRZ03_extrapolation_assign(y, cs)", 00790 "y", y); 00791 // `cs' must be dimension-compatible with the two polyhedra. 00792 const dimension_type cs_space_dim = cs.space_dimension(); 00793 if (x.space_dim < cs_space_dim) 00794 throw_dimension_incompatible("limited_BHRZ03_extrapolation_assign(y, cs)", 00795 "cs", cs); 00796 00797 #ifndef NDEBUG 00798 { 00799 // We assume that y is contained in or equal to x. 00800 const Polyhedron x_copy = x; 00801 const Polyhedron y_copy = y; 00802 PPL_ASSERT_HEAVY(x_copy.contains(y_copy)); 00803 } 00804 #endif 00805 00806 if (y.marked_empty()) 00807 return; 00808 if (x.marked_empty()) 00809 return; 00810 00811 // The limited BHRZ03-widening between two polyhedra in a 00812 // zero-dimensional space is a polyhedron in a zero-dimensional 00813 // space, too. 00814 if (x.space_dim == 0) 00815 return; 00816 00817 if (!y.minimize()) 00818 // We have just discovered that `y' is empty. 00819 return; 00820 00821 // Update the generators of `x': these are used to select, 00822 // from the constraints in `cs', those that must be added 00823 // to the resulting polyhedron. 00824 if ((x.has_pending_constraints() && !x.process_pending_constraints()) 00825 || (!x.generators_are_up_to_date() && !x.update_generators())) 00826 // We have just discovered that `x' is empty. 00827 return; 00828 00829 Constraint_System new_cs; 00830 // The constraints to be added must be satisfied by all the 00831 // generators of `x'. We can disregard `y' because `y <= x'. 00832 const Generator_System& x_gen_sys = x.gen_sys; 00833 // Iterate upwards here so as to keep the relative ordering of constraints. 00834 // Not really an issue: just aesthetics. 00835 for (dimension_type i = 0; i < cs_num_rows; ++i) { 00836 const Constraint& c = cs[i]; 00837 if (x_gen_sys.satisfied_by_all_generators(c)) 00838 new_cs.insert(c); 00839 } 00840 x.BHRZ03_widening_assign(y, tp); 00841 x.add_recycled_constraints(new_cs); 00842 PPL_ASSERT_HEAVY(OK()); 00843 }
| void Parma_Polyhedra_Library::Polyhedron::limited_H79_extrapolation_assign | ( | const Polyhedron & | y, | |
| const Constraint_System & | cs, | |||
| unsigned * | tp = 0 | |||
| ) |
Assigns to *this the result of computing the limited extrapolation between *this and y using the H79-widening operator.
| 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 288 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().
00290 { 00291 Polyhedron& x = *this; 00292 00293 const dimension_type cs_num_rows = cs.num_rows(); 00294 // If `cs' is empty, we fall back to ordinary, non-limited widening. 00295 if (cs_num_rows == 0) { 00296 x.H79_widening_assign(y, tp); 00297 return; 00298 } 00299 00300 // Topology compatibility check. 00301 if (x.is_necessarily_closed()) { 00302 if (!y.is_necessarily_closed()) 00303 throw_topology_incompatible("limited_H79_extrapolation_assign(y, cs)", 00304 "y", y); 00305 if (cs.has_strict_inequalities()) 00306 throw_topology_incompatible("limited_H79_extrapolation_assign(y, cs)", 00307 "cs", cs); 00308 } 00309 else if (y.is_necessarily_closed()) 00310 throw_topology_incompatible("limited_H79_extrapolation_assign(y, cs)", 00311 "y", y); 00312 00313 // Dimension-compatibility check. 00314 if (x.space_dim != y.space_dim) 00315 throw_dimension_incompatible("limited_H79_extrapolation_assign(y, cs)", 00316 "y", y); 00317 // `cs' must be dimension-compatible with the two polyhedra. 00318 const dimension_type cs_space_dim = cs.space_dimension(); 00319 if (x.space_dim < cs_space_dim) 00320 throw_dimension_incompatible("limited_H79_extrapolation_assign(y, cs)", 00321 "cs", cs); 00322 00323 #ifndef NDEBUG 00324 { 00325 // We assume that y is contained in or equal to x. 00326 const Polyhedron x_copy = x; 00327 const Polyhedron y_copy = y; 00328 PPL_ASSERT_HEAVY(x_copy.contains(y_copy)); 00329 } 00330 #endif 00331 00332 if (y.marked_empty()) 00333 return; 00334 if (x.marked_empty()) 00335 return; 00336 00337 // The limited H79-widening between two polyhedra in a 00338 // zero-dimensional space is a polyhedron in a zero-dimensional 00339 // space, too. 00340 if (x.space_dim == 0) 00341 return; 00342 00343 if (!y.minimize()) 00344 // We have just discovered that `y' is empty. 00345 return; 00346 00347 // Update the generators of `x': these are used to select, 00348 // from the constraints in `cs', those that must be added 00349 // to the resulting polyhedron. 00350 if ((x.has_pending_constraints() && !x.process_pending_constraints()) 00351 || (!x.generators_are_up_to_date() && !x.update_generators())) 00352 // We have just discovered that `x' is empty. 00353 return; 00354 00355 Constraint_System new_cs; 00356 // The constraints to be added must be satisfied by all the 00357 // generators of `x'. We can disregard `y' because `y <= x'. 00358 const Generator_System& x_gen_sys = x.gen_sys; 00359 // Iterate upwards here so as to keep the relative ordering of constraints. 00360 // Not really an issue: just aesthetics. 00361 for (dimension_type i = 0; i < cs_num_rows; ++i) { 00362 const Constraint& c = cs[i]; 00363 if (x_gen_sys.satisfied_by_all_generators(c)) 00364 new_cs.insert(c); 00365 } 00366 x.H79_widening_assign(y, tp); 00367 x.add_recycled_constraints(new_cs); 00368 PPL_ASSERT_HEAVY(OK()); 00369 }
| 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. |
The template type parameter Partial_Function must provide the following methods.
bool has_empty_codomain() const
returns true if and only if the represented partial function has an empty codomain (i.e., it is always undefined). The has_empty_codomain() method will always be called before the methods below. However, if has_empty_codomain() returns true, none of the functions below will be called.
dimension_type max_in_codomain() const
returns the maximum value that belongs to the codomain of the partial function. The max_in_codomain() method is called at most once.
bool maps(dimension_type i, dimension_type& j) const
Let
be the represented function and
be the value of i. If
is defined in
, then
is assigned to j and true is returned. If
is undefined in
, then false is returned. This method is called at most
times, where
is the dimension of the vector space enclosing the polyhedron.
The result is undefined if pfunc does not encode a partial function with the properties described in the specification of the mapping operator.
Definition at line 151 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, swap(), throw_invalid_argument(), topology(), Parma_Polyhedra_Library::Generator::type(), and update_generators().
00151 { 00152 if (space_dim == 0) 00153 return; 00154 00155 if (pfunc.has_empty_codomain()) { 00156 // All dimensions vanish: the polyhedron becomes zero_dimensional. 00157 if (marked_empty() 00158 || (has_pending_constraints() 00159 && !remove_pending_to_obtain_generators()) 00160 || (!generators_are_up_to_date() && !update_generators())) { 00161 // Removing all dimensions from the empty polyhedron. 00162 space_dim = 0; 00163 con_sys.clear(); 00164 } 00165 else 00166 // Removing all dimensions from a non-empty polyhedron. 00167 set_zero_dim_univ(); 00168 00169 PPL_ASSERT_HEAVY(OK()); 00170 return; 00171 } 00172 00173 const dimension_type new_space_dimension = pfunc.max_in_codomain() + 1; 00174 00175 if (new_space_dimension == space_dim) { 00176 // The partial function `pfunc' is indeed total and thus specifies 00177 // a permutation, that is, a renaming of the dimensions. For 00178 // maximum efficiency, we will simply permute the columns of the 00179 // constraint system and/or the generator system. 00180 00181 // We first compute suitable permutation cycles for the columns of 00182 // the `con_sys' and `gen_sys' matrices. We will represent them 00183 // with a linear array, using 0 as a terminator for each cycle 00184 // (notice that the columns with index 0 of `con_sys' and 00185 // `gen_sys' represent the inhomogeneous terms, and thus are 00186 // unaffected by the permutation of dimensions). 00187 // Cycles of length 1 will be omitted so that, in the worst case, 00188 // we will have `space_dim' elements organized in `space_dim/2' 00189 // cycles, which means we will have at most `space_dim/2' 00190 // terminators. 00191 std::vector<dimension_type> cycles; 00192 cycles.reserve(space_dim + space_dim/2); 00193 00194 // Used to mark elements as soon as they are inserted in a cycle. 00195 std::deque<bool> visited(space_dim); 00196 00197 for (dimension_type i = space_dim; i-- > 0; ) { 00198 if (!visited[i]) { 00199 dimension_type j = i; 00200 do { 00201 visited[j] = true; 00202 // The following initialization is only to make the compiler happy. 00203 dimension_type k = 0; 00204 if (!pfunc.maps(j, k)) 00205 throw_invalid_argument("map_space_dimensions(pfunc)", 00206 " pfunc is inconsistent"); 00207 if (k == j) 00208 // Cycle of length 1: skip it. 00209 goto skip; 00210 00211 cycles.push_back(j+1); 00212 // Go along the cycle. 00213 j = k; 00214 } while (!visited[j]); 00215 // End of cycle: mark it. 00216 cycles.push_back(0); 00217 skip: 00218 ; 00219 } 00220 } 00221 00222 // If `cycles' is empty then `pfunc' is the identity. 00223 if (cycles.empty()) 00224 return; 00225 00226 // Permute all that is up-to-date. Notice that the contents of 00227 // the saturation matrices is unaffected by the permutation of 00228 // columns: they remain valid, if they were so. 00229 if (constraints_are_up_to_date()) 00230 con_sys.permute_columns(cycles); 00231 00232 if (generators_are_up_to_date()) 00233 gen_sys.permute_columns(cycles); 00234 00235 PPL_ASSERT_HEAVY(OK()); 00236 return; 00237 } 00238 00239 // If control gets here, then `pfunc' is not a permutation and some 00240 // dimensions must be projected away. 00241 00242 // If there are pending constraints, using `generators()' we process them. 00243 const Generator_System& old_gensys = generators(); 00244 00245 if (old_gensys.has_no_rows()) { 00246 // The polyhedron is empty. 00247 Polyhedron new_polyhedron(topology(), new_space_dimension, EMPTY); 00248 std::swap(*this, new_polyhedron); 00249 PPL_ASSERT_HEAVY(OK()); 00250 return; 00251 } 00252 00253 // Make a local copy of the partial function. 00254 std::vector<dimension_type> pfunc_maps(space_dim, not_a_dimension()); 00255 for (dimension_type j = space_dim; j-- > 0; ) { 00256 dimension_type pfunc_j; 00257 if (pfunc.maps(j, pfunc_j)) 00258 pfunc_maps[j] = pfunc_j; 00259 } 00260 00261 Generator_System new_gensys; 00262 for (Generator_System::const_iterator i = old_gensys.begin(), 00263 old_gensys_end = old_gensys.end(); i != old_gensys_end; ++i) { 00264 const Generator& old_g = *i; 00265 Linear_Expression e(0 * Variable(new_space_dimension-1)); 00266 bool all_zeroes = true; 00267 for (dimension_type j = space_dim; j-- > 0; ) { 00268 if (old_g.coefficient(Variable(j)) != 0 00269 && pfunc_maps[j] != not_a_dimension()) { 00270 e += Variable(pfunc_maps[j]) * old_g.coefficient(Variable(j)); 00271 all_zeroes = false; 00272 } 00273 } 00274 switch (old_g.type()) { 00275 case Generator::LINE: 00276 if (!all_zeroes) 00277 new_gensys.insert(line(e)); 00278 break; 00279 case Generator::RAY: 00280 if (!all_zeroes) 00281 new_gensys.insert(ray(e)); 00282 break; 00283 case Generator::POINT: 00284 // A point in the origin has all zero homogeneous coefficients. 00285 new_gensys.insert(point(e, old_g.divisor())); 00286 break; 00287 case Generator::CLOSURE_POINT: 00288 // A closure point in the origin has all zero homogeneous coefficients. 00289 new_gensys.insert(closure_point(e, old_g.divisor())); 00290 break; 00291 } 00292 } 00293 Polyhedron new_polyhedron(topology(), new_gensys); 00294 std::swap(*this, new_polyhedron); 00295 PPL_ASSERT_HEAVY(OK(true)); 00296 }
| 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 123 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_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_image(), affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), BFT00_poly_hull_assign_if_exact(), Parma_Polyhedra_Library::BHRZ03_Certificate::BHRZ03_Certificate(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHRZ03_widening_assign(), BHZ09_poly_hull_assign_if_exact(), 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(), drop_some_non_integer_points(), fold_space_dimensions(), frequency(), generalized_affine_image(), generalized_affine_preimage(), generators(), Parma_Polyhedra_Library::Grid::Grid(), Parma_Polyhedra_Library::H79_Certificate::H79_Certificate(), H79_widening_assign(), intersection_assign(), 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(), 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().
00123 { 00124 return status.test_empty(); 00125 }
| 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. |
If *this is empty or expr is not bounded in the appropriate direction, false is returned and ext_n, ext_d, included and g are left untouched.
Definition at line 556 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(), PPL_DIRTY_TEMP_COEFFICIENT, process_pending_constraints(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and update_generators().
Referenced by maximize(), and minimize().
00560 { 00561 // The dimension of `expr' should not be greater than the dimension 00562 // of `*this'. 00563 const dimension_type expr_space_dim = expr.space_dimension(); 00564 if (space_dim < expr_space_dim) 00565 throw_dimension_incompatible((maximize 00566 ? "maximize(e, ...)" 00567 : "minimize(e, ...)"), "e", expr); 00568 00569 // Deal with zero-dim polyhedra first. 00570 if (space_dim == 0) { 00571 if (marked_empty()) 00572 return false; 00573 else { 00574 ext_n = expr.inhomogeneous_term(); 00575 ext_d = 1; 00576 included = true; 00577 g = point(); 00578 return true; 00579 } 00580 } 00581 00582 // For an empty polyhedron we simply return false. 00583 if (marked_empty() 00584 || (has_pending_constraints() && !process_pending_constraints()) 00585 || (!generators_are_up_to_date() && !update_generators())) 00586 return false; 00587 00588 // The polyhedron has updated, possibly pending generators. 00589 // The following loop will iterate through the generator 00590 // to find the extremum. 00591 PPL_DIRTY_TEMP0(mpq_class, extremum); 00592 00593 // True if we have no other candidate extremum to compare with. 00594 bool first_candidate = true; 00595 00596 // To store the position of the current candidate extremum. 00597 PPL_UNINITIALIZED(dimension_type, ext_position); 00598 00599 // Whether the current candidate extremum is included or not. 00600 PPL_UNINITIALIZED(bool, ext_included); 00601 00602 PPL_DIRTY_TEMP_COEFFICIENT(sp); 00603 for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) { 00604 const Generator& gen_sys_i = gen_sys[i]; 00605 Scalar_Products::homogeneous_assign(sp, expr, gen_sys_i); 00606 // Lines and rays in `*this' can cause `expr' to be unbounded. 00607 if (gen_sys_i.is_line_or_ray()) { 00608 const int sp_sign = sgn(sp); 00609 if (sp_sign != 0 00610 && (gen_sys_i.is_line() 00611 || (maximize && sp_sign > 0) 00612 || (!maximize && sp_sign < 0))) 00613 // `expr' is unbounded in `*this'. 00614 return false; 00615 } 00616 else { 00617 // We have a point or a closure point. 00618 PPL_ASSERT(gen_sys_i.is_point() || gen_sys_i.is_closure_point()); 00619 // Notice that we are ignoring the constant term in `expr' here. 00620 // We will add it to the extremum as soon as we find it. 00621 PPL_DIRTY_TEMP0(mpq_class, candidate); 00622 assign_r(candidate.get_num(), sp, ROUND_NOT_NEEDED); 00623 assign_r(candidate.get_den(), gen_sys_i[0], ROUND_NOT_NEEDED); 00624 candidate.canonicalize(); 00625 const bool g_is_point = gen_sys_i.is_point(); 00626 if (first_candidate 00627 || (maximize 00628 && (candidate > extremum 00629 || (g_is_point 00630 && !ext_included 00631 && candidate == extremum))) 00632 || (!maximize 00633 && (candidate < extremum 00634 || (g_is_point 00635 && !ext_included 00636 && candidate == extremum)))) { 00637 // We have a (new) candidate extremum. 00638 first_candidate = false; 00639 extremum = candidate; 00640 ext_position = i; 00641 ext_included = g_is_point; 00642 } 00643 } 00644 } 00645 00646 // Add in the constant term in `expr'. 00647 PPL_DIRTY_TEMP0(mpz_class, n); 00648 assign_r(n, expr.inhomogeneous_term(), ROUND_NOT_NEEDED); 00649 extremum += n; 00650 00651 // The polyhedron is bounded in the right direction and we have 00652 // computed the extremum: write the result into the caller's structures. 00653 PPL_ASSERT(!first_candidate); 00654 // FIXME: avoid these temporaries, if possible. 00655 // This can be done adding an `assign' function working on native 00656 // and checked or an operator= that have on one side a checked and 00657 // on the other a native or checked. 00658 // The reason why now we can't use operator= is the fact that we 00659 // still can have Coefficient defined to mpz_class (and not 00660 // Checked_Number<mpz_class>). 00661 ext_n = Coefficient(extremum.get_num()); 00662 ext_d = Coefficient(extremum.get_den()); 00663 included = ext_included; 00664 g = gen_sys[ext_position]; 00665 00666 return true; 00667 }
| 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 50 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().
00050 { 00051 using std::min; 00052 // One dimension is reserved to have a value of type dimension_type 00053 // that does not represent a legal dimension. 00054 return min(std::numeric_limits<dimension_type>::max() - 1, 00055 min(Constraint_System::max_space_dimension(), 00056 Generator_System::max_space_dimension() 00057 ) 00058 ); 00059 }
| 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. |
If *this is empty or expr is not bounded from above, false is returned and sup_n, sup_d, maximum and g are left untouched.
Definition at line 324 of file Polyhedron.inlines.hh.
References max_min().
00326 { 00327 return max_min(expr, true, sup_n, sup_d, maximum, g); 00328 }
| 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. |
If *this is empty or expr is not bounded from above, false is returned and sup_n, sup_d and maximum are left untouched.
Definition at line 316 of file Polyhedron.inlines.hh.
References max_min().
00318 { 00319 Generator g(point()); 00320 return max_min(expr, true, sup_n, sup_d, maximum, g); 00321 }
| 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 70 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().
00073 { 00074 // Topologies have to agree. 00075 PPL_ASSERT(source.topology() == dest.topology()); 00076 // `source' cannot be empty: even if it is an empty constraint system, 00077 // representing the universe polyhedron, homogenization has added 00078 // the positive constraint. It also cannot be an empty generator system, 00079 // since this function is always called starting from a non-empty 00080 // polyhedron. 00081 PPL_ASSERT(!source.has_no_rows()); 00082 00083 // Sort the source system, if necessary. 00084 if (!source.is_sorted()) 00085 source.sort_rows(); 00086 00087 // Initialization of the system of generators `dest'. 00088 // The algorithm works incrementally and we haven't seen any 00089 // constraint yet: as a consequence, `dest' should describe 00090 // the universe polyhedron of the appropriate dimension. 00091 // To this end, we initialize it to the identity matrix of dimension 00092 // `source.num_columns()': the rows represent the lines corresponding 00093 // to the canonical basis of the vector space. 00094 00095 // Resizing `dest' to be the appropriate square matrix. 00096 dimension_type dest_num_rows = source.num_columns(); 00097 // Note that before calling `resize_no_copy()' we must update 00098 // `index_first_pending'. 00099 dest.set_index_first_pending_row(dest_num_rows); 00100 dest.resize_no_copy(dest_num_rows, dest_num_rows); 00101 00102 // Initialize `dest' to the identity matrix. 00103 for (dimension_type i = dest_num_rows; i-- > 0; ) { 00104 Linear_Row& dest_i = dest[i]; 00105 for (dimension_type j = dest_num_rows; j-- > 0; ) 00106 dest_i[j] = (i == j) ? 1 : 0; 00107 dest_i.set_is_line_or_equality(); 00108 } 00109 // The identity matrix `dest' is not sorted (see the sorting rules 00110 // in Linear_Row.cc). 00111 dest.set_sorted(false); 00112 00113 // NOTE: the system `dest', as it is now, is not a _legal_ system of 00114 // generators, because in the first row we have a line with a 00115 // non-zero divisor (which should only happen for 00116 // points). However, this is NOT a problem, because `source' 00117 // necessarily contains the positivity constraint (or a 00118 // combination of it with another constraint) which will 00119 // restore things as they should be. 00120 00121 00122 // Building a saturation matrix and initializing it by setting 00123 // all of its elements to zero. This matrix will be modified together 00124 // with `dest' during the conversion. 00125 // NOTE: since we haven't seen any constraint yet, the relevant 00126 // portion of `tmp_sat' is the sub-matrix consisting of 00127 // the first 0 columns: thus the relevant portion correctly 00128 // characterizes the initial saturation information. 00129 Bit_Matrix tmp_sat(dest_num_rows, source.num_rows()); 00130 00131 // By invoking the function conversion(), we populate `dest' with 00132 // the generators characterizing the polyhedron described by all 00133 // the constraints in `source'. 00134 // The `start' parameter is zero (we haven't seen any constraint yet) 00135 // and the 5th parameter (representing the number of lines in `dest'), 00136 // by construction, is equal to `dest_num_rows'. 00137 const dimension_type num_lines_or_equalities 00138 = conversion(source, 0, dest, tmp_sat, dest_num_rows); 00139 // conversion() may have modified the number of rows in `dest'. 00140 dest_num_rows = dest.num_rows(); 00141 00142 // Checking if the generators in `dest' represent an empty polyhedron: 00143 // the polyhedron is empty if there are no points 00144 // (because rays, lines and closure points need a supporting point). 00145 // Points can be detected by looking at: 00146 // - the divisor, for necessarily closed polyhedra; 00147 // - the epsilon coordinate, for NNC polyhedra. 00148 const dimension_type checking_index 00149 = dest.is_necessarily_closed() 00150 ? 0 00151 : dest.num_columns() - 1; 00152 dimension_type first_point; 00153 for (first_point = num_lines_or_equalities; 00154 first_point < dest_num_rows; 00155 ++first_point) 00156 if (dest[first_point][checking_index] > 0) 00157 break; 00158 00159 if (first_point == dest_num_rows) 00160 if (con_to_gen) 00161 // No point has been found: the polyhedron is empty. 00162 return true; 00163 else 00164 // Here `con_to_gen' is false: `dest' is a system of constraints. 00165 // In this case the condition `first_point == dest_num_rows' 00166 // actually means that all the constraints in `dest' have their 00167 // inhomogeneous term equal to 0. 00168 // This is an ILLEGAL situation, because it implies that 00169 // the constraint system `dest' lacks the positivity constraint 00170 // and no linear combination of the constraints in `dest' 00171 // can reintroduce the positivity constraint. 00172 throw std::runtime_error("PPL internal error"); 00173 else { 00174 // A point has been found: the polyhedron is not empty. 00175 // Now invoking simplify() to remove all the redundant constraints 00176 // from the system `source'. 00177 // Since the saturation matrix `tmp_sat' returned by conversion() 00178 // has rows indexed by generators (the rows of `dest') and columns 00179 // indexed by constraints (the rows of `source'), we have to 00180 // transpose it to obtain the saturation matrix needed by simplify(). 00181 sat.transpose_assign(tmp_sat); 00182 simplify(source, sat); 00183 return false; 00184 } 00185 }
| 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.Minimization is not attempted if the Status field already declares both systems to be minimized.
Definition at line 1039 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_recycled_generators(), affine_image(), affine_preimage(), constrains(), generalized_affine_image(), is_empty(), is_universe(), minimized_constraints(), minimized_generators(), OK(), strongly_minimize_constraints(), strongly_minimize_generators(), update_constraints(), and update_generators().
01039 { 01040 // 0-dim space or empty polyhedra are already minimized. 01041 if (marked_empty()) 01042 return false; 01043 if (space_dim == 0) 01044 return true; 01045 01046 // If the polyhedron has something pending, process it. 01047 if (has_something_pending()) { 01048 const bool not_empty = process_pending(); 01049 PPL_ASSERT_HEAVY(OK()); 01050 return not_empty; 01051 } 01052 01053 // Here there are no pending constraints or generators. 01054 // Is the polyhedron already minimized? 01055 if (constraints_are_minimized() && generators_are_minimized()) 01056 return true; 01057 01058 // If constraints or generators are up-to-date, invoking 01059 // update_generators() or update_constraints(), respectively, 01060 // minimizes both constraints and generators. 01061 // If both are up-to-date it does not matter whether we use 01062 // update_generators() or update_constraints(): 01063 // both minimize constraints and generators. 01064 if (constraints_are_up_to_date()) { 01065 // We may discover here that `*this' is empty. 01066 const bool ret = update_generators(); 01067 PPL_ASSERT_HEAVY(OK()); 01068 return ret; 01069 } 01070 else { 01071 PPL_ASSERT(generators_are_up_to_date()); 01072 update_constraints(); 01073 PPL_ASSERT_HEAVY(OK()); 01074 return true; 01075 } 01076 }
| 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. |
If *this is empty or expr is not bounded from below, false is returned and inf_n, inf_d, minimum and g are left untouched.
Definition at line 339 of file Polyhedron.inlines.hh.
References max_min().
00341 { 00342 return max_min(expr, false, inf_n, inf_d, minimum, g); 00343 }
| 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. |
If *this is empty or expr is not bounded from below, false is returned and inf_n, inf_d and minimum are left untouched.
Definition at line 331 of file Polyhedron.inlines.hh.
References max_min().
Referenced by BFT00_poly_hull_assign_if_exact(), Parma_Polyhedra_Library::BHRZ03_Certificate::BHRZ03_Certificate(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHRZ03_widening_assign(), BHZ09_C_poly_hull_assign_if_exact(), BHZ09_NNC_poly_hull_assign_if_exact(), Parma_Polyhedra_Library::H79_Certificate::compare(), Parma_Polyhedra_Library::BHRZ03_Certificate::compare(), Parma_Polyhedra_Library::Grid::Grid(), Parma_Polyhedra_Library::H79_Certificate::H79_Certificate(), H79_widening_assign(), is_included_in(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), poly_difference_assign(), and simplify_using_context_assign().
00333 { 00334 Generator g(point()); 00335 return max_min(expr, false, inf_n, inf_d, minimum, g); 00336 }
| 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 362 of file Polyhedron.inlines.hh.
References minimized_constraints().
00362 { 00363 return Congruence_System(minimized_constraints()); 00364 }
| const PPL::Constraint_System & Parma_Polyhedra_Library::Polyhedron::minimized_constraints | ( | ) | const |
Returns the system of constraints, with no redundant constraint.
Definition at line 119 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<<().
00119 { 00120 // `minimize()' or `strongly_minimize_constraints()' 00121 // will process any pending constraints or generators. 00122 if (is_necessarily_closed()) 00123 minimize(); 00124 else 00125 strongly_minimize_constraints(); 00126 return constraints(); 00127 }
| const PPL::Generator_System & Parma_Polyhedra_Library::Polyhedron::minimized_generators | ( | ) | const |
Returns the system of generators, with no redundant generator.
Definition at line 184 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().
00184 { 00185 // `minimize()' or `strongly_minimize_generators()' 00186 // will process any pending constraints or generators. 00187 if (is_necessarily_closed()) 00188 minimize(); 00189 else 00190 strongly_minimize_generators(); 00191 // Note: calling generators() on a strongly minimized NNC generator 00192 // system will also ensure sortedness, which is required to correctly 00193 // filter away the matched closure points. 00194 return generators(); 00195 }
| Grid_Generator_System Parma_Polyhedra_Library::Polyhedron::minimized_grid_generators | ( | ) | const [inline] |
Returns a universe system of grid generators.
Definition at line 367 of file Polyhedron.inlines.hh.
References grid_generators().
00367 { 00368 return grid_generators(); 00369 }
| 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 914 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(), is_universe(), and quick_equivalence_test().
00914 { 00915 PPL_ASSERT(constraints_are_up_to_date()); 00916 // `con_sys' will be sorted up to `index_first_pending'. 00917 Polyhedron& x = const_cast<Polyhedron&>(*this); 00918 if (!x.con_sys.is_sorted()) { 00919 if (x.sat_g_is_up_to_date()) { 00920 // Sorting constraints keeping `sat_g' consistent. 00921 x.con_sys.sort_and_remove_with_sat(x.sat_g); 00922 // `sat_c' is not up-to-date anymore. 00923 x.clear_sat_c_up_to_date(); 00924 } 00925 else if (x.sat_c_is_up_to_date()) { 00926 // Using `sat_c' to obtain `sat_g', then it is like previous case. 00927 x.sat_g.transpose_assign(x.sat_c); 00928 x.con_sys.sort_and_remove_with_sat(x.sat_g); 00929 x.set_sat_g_up_to_date(); 00930 x.clear_sat_c_up_to_date(); 00931 } 00932 else 00933 // If neither `sat_g' nor `sat_c' are up-to-date, 00934 // we just sort the constraints. 00935 x.con_sys.sort_rows(); 00936 } 00937 00938 PPL_ASSERT(con_sys.check_sorted()); 00939 }
| 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 970 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 process_pending_constraints().
00970 { 00971 PPL_ASSERT(constraints_are_up_to_date()); 00972 PPL_ASSERT(constraints_are_minimized()); 00973 // `con_sys' will be sorted up to `index_first_pending'. 00974 Polyhedron& x = const_cast<Polyhedron&>(*this); 00975 // At least one of the saturation matrices must be up-to-date. 00976 if (!x.sat_c_is_up_to_date() && !x.sat_g_is_up_to_date()) 00977 x.update_sat_c(); 00978 00979 if (x.con_sys.is_sorted()) { 00980 if (x.sat_c_is_up_to_date()) 00981 // If constraints are already sorted and sat_c is up to 00982 // date there is nothing to do. 00983 return; 00984 } 00985 else { 00986 if (!x.sat_g_is_up_to_date()) { 00987 // If constraints are not sorted and sat_g is not up-to-date 00988 // we obtain sat_g from sat_c (that has to be up-to-date)... 00989 x.sat_g.transpose_assign(x.sat_c); 00990 x.set_sat_g_up_to_date(); 00991 } 00992 // ... and sort it together with constraints. 00993 x.con_sys.sort_and_remove_with_sat(x.sat_g); 00994 } 00995 // Obtaining sat_c from sat_g. 00996 x.sat_c.transpose_assign(x.sat_g); 00997 x.set_sat_c_up_to_date(); 00998 // Constraints are sorted now. 00999 x.con_sys.set_sorted(true); 01000 01001 PPL_ASSERT(con_sys.check_sorted()); 01002 }
| 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 942 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(), and quick_equivalence_test().
00942 { 00943 PPL_ASSERT(generators_are_up_to_date()); 00944 // `gen_sys' will be sorted up to `index_first_pending'. 00945 Polyhedron& x = const_cast<Polyhedron&>(*this); 00946 if (!x.gen_sys.is_sorted()) { 00947 if (x.sat_c_is_up_to_date()) { 00948 // Sorting generators keeping 'sat_c' consistent. 00949 x.gen_sys.sort_and_remove_with_sat(x.sat_c); 00950 // `sat_g' is not up-to-date anymore. 00951 x.clear_sat_g_up_to_date(); 00952 } 00953 else if (x.sat_g_is_up_to_date()) { 00954 // Obtaining `sat_c' from `sat_g' and proceeding like previous case. 00955 x.sat_c.transpose_assign(x.sat_g); 00956 x.gen_sys.sort_and_remove_with_sat(x.sat_c); 00957 x.set_sat_c_up_to_date(); 00958 x.clear_sat_g_up_to_date(); 00959 } 00960 else 00961 // If neither `sat_g' nor `sat_c' are up-to-date, we just sort 00962 // the generators. 00963 x.gen_sys.sort_rows(); 00964 } 00965 00966 PPL_ASSERT(gen_sys.check_sorted()); 00967 }
| 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 1005 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 process_pending_generators().
01005 { 01006 PPL_ASSERT(generators_are_up_to_date()); 01007 // `gen_sys' will be sorted up to `index_first_pending'. 01008 Polyhedron& x = const_cast<Polyhedron&>(*this); 01009 // At least one of the saturation matrices must be up-to-date. 01010 if (!x.sat_c_is_up_to_date() && !x.sat_g_is_up_to_date()) 01011 x.update_sat_g(); 01012 01013 if (x.gen_sys.is_sorted()) { 01014 if (x.sat_g_is_up_to_date()) 01015 // If generators are already sorted and sat_g is up to 01016 // date there is nothing to do. 01017 return; 01018 } 01019 else { 01020 if (!x.sat_c_is_up_to_date()) { 01021 // If generators are not sorted and sat_c is not up-to-date 01022 // we obtain sat_c from sat_g (that has to be up-to-date)... 01023 x.sat_c.transpose_assign(x.sat_g); 01024 x.set_sat_c_up_to_date(); 01025 } 01026 // ... and sort it together with generators. 01027 x.gen_sys.sort_and_remove_with_sat(x.sat_c); 01028 } 01029 // Obtaining sat_g from sat_c. 01030 x.sat_g.transpose_assign(sat_c); 01031 x.set_sat_g_up_to_date(); 01032 // Generators are sorted now. 01033 x.gen_sys.set_sorted(true); 01034 01035 PPL_ASSERT(gen_sys.check_sorted()); 01036 }
| 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. |
The check is performed so as to intrude as little as possible. If the library has been compiled with run-time assertions enabled, error messages are written on std::cerr in case invariants are violated. This is useful for the purpose of debugging the library.
Definition at line 779 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(), 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_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_image(), affine_preimage(), Parma_Polyhedra_Library::Polyhedron::Status::ascii_load(), BFT00_poly_hull_assign_if_exact(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHRZ03_widening_assign(), BHZ09_C_poly_hull_assign_if_exact(), bounded_affine_image(), bounded_affine_preimage(), Parma_Polyhedra_Library::C_Polyhedron::C_Polyhedron(), concatenate_assign(), drop_some_non_integer_points(), expand_space_dimension(), fold_space_dimensions(), generalized_affine_image(), generalized_affine_preimage(), H79_widening_assign(), intersection_assign(), 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(), 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().
00779 { 00780 #ifndef NDEBUG 00781 using std::endl; 00782 using std::cerr; 00783 #endif 00784 00785 // The expected number of columns in the constraint and generator 00786 // systems, if they are not empty. 00787 const dimension_type poly_num_columns 00788 = space_dim + (is_necessarily_closed() ? 1 : 2); 00789 00790 // Check whether the topologies of `con_sys' and `gen_sys' agree. 00791 if (con_sys.topology() != gen_sys.topology()) { 00792 #ifndef NDEBUG 00793 cerr << "Constraints and generators have different topologies!" 00794 << endl; 00795 #endif 00796 goto bomb; 00797 } 00798 00799 // Check whether the saturation matrices are well-formed. 00800 if (!sat_c.OK()) 00801 goto bomb; 00802 if (!sat_g.OK()) 00803 goto bomb; 00804 00805 // Check whether the status information is legal. 00806 if (!status.OK()) 00807 goto bomb; 00808 00809 if (marked_empty()) { 00810 if (check_not_empty) { 00811 // The caller does not want the polyhedron to be empty. 00812 #ifndef NDEBUG 00813 cerr << "Empty polyhedron!" << endl; 00814 #endif 00815 goto bomb; 00816 } 00817 00818 // An empty polyhedron is allowed if the system of constraints 00819 // either has no rows or only contains an unsatisfiable constraint 00820 // and if it has no pending constraints or generators. 00821 if (has_something_pending()) { 00822 #ifndef NDEBUG 00823 cerr << "The polyhedron is empty, " 00824 << "but it has something pending" << endl; 00825 #endif 00826 goto bomb; 00827 } 00828 if (con_sys.has_no_rows()) 00829 return true; 00830 else { 00831 if (con_sys.space_dimension() != space_dim) { 00832 #ifndef NDEBUG 00833 cerr << "The polyhedron is in a space of dimension " 00834 << space_dim 00835 << " while the system of constraints is in a space of dimension " 00836 << con_sys.space_dimension() 00837 << endl; 00838 #endif 00839 goto bomb; 00840 } 00841 if (con_sys.num_rows() != 1) { 00842 #ifndef NDEBUG 00843 cerr << "The system of constraints for an empty polyhedron " 00844 << "has more then one row" 00845 << endl; 00846 #endif 00847 goto bomb; 00848 } 00849 if (!con_sys[0].is_inconsistent()) { 00850 #ifndef NDEBUG 00851 cerr << "Empty polyhedron with a satisfiable system of constraints" 00852 << endl; 00853 #endif 00854 goto bomb; 00855 } 00856 // Here we have only one, inconsistent constraint. 00857 return true; 00858 } 00859 } 00860 00861 // A zero-dimensional, non-empty polyhedron is legal only if the 00862 // system of constraint `con_sys' and the system of generators 00863 // `gen_sys' have no rows. 00864 if (space_dim == 0) { 00865 if (has_something_pending()) { 00866 #ifndef NDEBUG 00867 cerr << "Zero-dimensional polyhedron with something pending" 00868 << endl; 00869 #endif 00870 goto bomb; 00871 } 00872 if (!con_sys.has_no_rows() || !gen_sys.has_no_rows()) { 00873 #ifndef NDEBUG 00874 cerr << "Zero-dimensional polyhedron with a non-empty" 00875 << endl 00876 << "system of constraints or generators." 00877 << endl; 00878 #endif 00879 goto bomb; 00880 } 00881 return true; 00882 } 00883 00884 // A polyhedron is defined by a system of constraints 00885 // or a system of generators: at least one of them must be up to date. 00886 if (!constraints_are_up_to_date() && !generators_are_up_to_date()) { 00887 #ifndef NDEBUG 00888 cerr << "Polyhedron not empty, not zero-dimensional" 00889 << endl 00890 << "and with neither constraints nor generators up-to-date!" 00891 << endl; 00892 #endif 00893 goto bomb; 00894 } 00895 00896 // Here we check if the size of the matrices is consistent. 00897 // Let us suppose that all the matrices are up-to-date; this means: 00898 // `con_sys' : number of constraints x poly_num_columns 00899 // `gen_sys' : number of generators x poly_num_columns 00900 // `sat_c' : number of generators x number of constraints 00901 // `sat_g' : number of constraints x number of generators. 00902 if (constraints_are_up_to_date()) { 00903 if (con_sys.num_columns() != poly_num_columns) { 00904 #ifndef NDEBUG 00905 cerr << "Incompatible size! (con_sys and space_dim)" 00906 << endl; 00907 #endif 00908 goto bomb; 00909 } 00910 if (sat_c_is_up_to_date()) 00911 if (con_sys.first_pending_row() != sat_c.num_columns()) { 00912 #ifndef NDEBUG 00913 cerr << "Incompatible size! (con_sys and sat_c)" 00914 << endl; 00915 #endif 00916 goto bomb; 00917 } 00918 if (sat_g_is_up_to_date()) 00919 if (con_sys.first_pending_row() != sat_g.num_rows()) { 00920 #ifndef NDEBUG 00921 cerr << "Incompatible size! (con_sys and sat_g)" 00922 << endl; 00923 #endif 00924 goto bomb; 00925 } 00926 if (generators_are_up_to_date()) 00927 if (con_sys.num_columns() != gen_sys.num_columns()) { 00928 #ifndef NDEBUG 00929 cerr << "Incompatible size! (con_sys and gen_sys)" 00930 << endl; 00931 #endif 00932 goto bomb; 00933 } 00934 } 00935 00936 if (generators_are_up_to_date()) { 00937 if (gen_sys.num_columns() != poly_num_columns) { 00938 #ifndef NDEBUG 00939 cerr << "Incompatible size! (gen_sys and space_dim)" 00940 << endl; 00941 #endif 00942 goto bomb; 00943 } 00944 if (sat_c_is_up_to_date()) 00945 if (gen_sys.first_pending_row() != sat_c.num_rows()) { 00946 #ifndef NDEBUG 00947 cerr << "Incompatible size! (gen_sys and sat_c)" 00948 << endl; 00949 #endif 00950 goto bomb; 00951 } 00952 if (sat_g_is_up_to_date()) 00953 if (gen_sys.first_pending_row() != sat_g.num_columns()) { 00954 #ifndef NDEBUG 00955 cerr << "Incompatible size! (gen_sys and sat_g)" 00956 << endl; 00957 #endif 00958 goto bomb; 00959 } 00960 00961 // Check if the system of generators is well-formed. 00962 if (!gen_sys.OK()) 00963 goto bomb; 00964 00965 if (gen_sys.first_pending_row() == 0) { 00966 #ifndef NDEBUG 00967 cerr << "Up-to-date generator system with all rows pending!" 00968 << endl; 00969 #endif 00970 goto bomb; 00971 } 00972 00973 // A non-empty system of generators describing a polyhedron 00974 // is valid if and only if it contains a point. 00975 if (!gen_sys.has_no_rows() && !gen_sys.has_points()) { 00976 #ifndef NDEBUG 00977 cerr << "Non-empty generator system declared up-to-date " 00978 << "has no points!" 00979 << endl; 00980 #endif 00981 goto bomb; 00982 } 00983 00984 #if 0 // To be activated when Status keeps strong minimization flags. 00985 //================================================= 00986 // TODO: this test is wrong in the general case. 00987 // However, such an invariant does hold for a 00988 // strongly-minimized Generator_System. 00989 // We will activate this test as soon as the Status 00990 // flags will be able to remember if a system is 00991 // strongly minimized. 00992 00993 // Checking that the number of closure points is always 00994 // greater than the number of points. 00995 if (!is_necessarily_closed()) { 00996 dimension_type num_points = 0; 00997 dimension_type num_closure_points = 0; 00998 dimension_type eps_index = gen_sys.num_columns() - 1; 00999 for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) 01000 if (!gen_sys[i].is_line_or_ray()) 01001 if (gen_sys[i][eps_index] > 0) 01002 ++num_points; 01003 else 01004 ++num_closure_points; 01005 if (num_points > num_closure_points) { 01006 #ifndef NDEBUG 01007 cerr << "# POINTS > # CLOSURE_POINTS" << endl; 01008 #endif 01009 goto bomb; 01010 } 01011 } 01012 //================================================= 01013 #endif 01014 01015 if (generators_are_minimized()) { 01016 // If the system of generators is minimized, the number of 01017 // lines, rays and points of the polyhedron must be the same as 01018 // of a temporary, minimized one. If this does not happen then 01019 // the polyhedron is not OK. 01020 Constraint_System new_con_sys(topology()); 01021 Generator_System gs_without_pending = gen_sys; 01022 gs_without_pending.erase_to_end(gen_sys.first_pending_row()); 01023 gs_without_pending.unset_pending_rows(); 01024 Generator_System copy_of_gen_sys = gs_without_pending; 01025 Bit_Matrix new_sat_c; 01026 minimize(false, copy_of_gen_sys, new_con_sys, new_sat_c); 01027 const dimension_type copy_num_lines = copy_of_gen_sys.num_lines(); 01028 if (gs_without_pending.num_rows() != copy_of_gen_sys.num_rows() 01029 || gs_without_pending.num_lines() != copy_num_lines 01030 || gs_without_pending.num_rays() != copy_of_gen_sys.num_rays()) { 01031 #ifndef NDEBUG 01032 cerr << "Generators are declared minimized, but they are not!\n" 01033 << "Here is the minimized form of the generators:\n"; 01034 copy_of_gen_sys.ascii_dump(cerr); 01035 cerr << endl; 01036 #endif 01037 goto bomb; 01038 } 01039 01040 // CHECKME : the following observation is not formally true 01041 // for a NNC_Polyhedron. But it may be true for its 01042 // representation ... 01043 01044 // If the corresponding polyhedral cone is _pointed_, then 01045 // a minimal system of generators is unique up to positive scaling. 01046 // We thus verify if the cone is pointed (i.e., there are no lines) 01047 // and, after normalizing and sorting a copy of the system `gen_sys' 01048 // of the polyhedron (we use a copy not to modify the polyhedron's 01049 // system) and the system `copy_of_gen_sys' that has been just 01050 // minimized, we check if the two matrices are identical. If 01051 // they are different it means that the generators of the 01052 // polyhedron are declared minimized, but they are not. 01053 if (copy_num_lines == 0) { 01054 copy_of_gen_sys.strong_normalize(); 01055 copy_of_gen_sys.sort_rows(); 01056 gs_without_pending.strong_normalize(); 01057 gs_without_pending.sort_rows(); 01058 if (copy_of_gen_sys != gs_without_pending) { 01059 #ifndef NDEBUG 01060 cerr << "Generators are declared minimized, but they are not!\n" 01061 << "(we are in the case:\n" 01062 << "dimension of lineality space equal to 0)\n" 01063 << "Here is the minimized form of the generators:\n"; 01064 copy_of_gen_sys.ascii_dump(cerr); 01065 cerr << endl; 01066 #endif 01067 goto bomb; 01068 } 01069 } 01070 } 01071 } 01072 01073 if (constraints_are_up_to_date()) { 01074 // Check if the system of constraints is well-formed. 01075 if (!con_sys.OK()) 01076 goto bomb; 01077 01078 if (con_sys.first_pending_row() == 0) { 01079 #ifndef NDEBUG 01080 cerr << "Up-to-date constraint system with all rows pending!" 01081 << endl; 01082 #endif 01083 goto bomb; 01084 } 01085 01086 // A non-empty system of constraints describing a polyhedron 01087 // must contain a constraint with a non-zero inhomogeneous term; 01088 // such a constraint corresponds to (a combination of other 01089 // constraints with): 01090 // -* the positivity constraint, for necessarily closed polyhedra; 01091 // -* the epsilon <= 1 constraint, for NNC polyhedra. 01092 bool no_positivity_constraint = true; 01093 for (dimension_type i = con_sys.num_rows(); i-- > 0; ) 01094 if (con_sys[i].inhomogeneous_term() != 0) { 01095 no_positivity_constraint = false; 01096 break; 01097 } 01098 if (no_positivity_constraint) { 01099 #ifndef NDEBUG 01100 cerr << "Non-empty constraint system has no positivity constraint" 01101 << endl; 01102 #endif 01103 goto bomb; 01104 } 01105 01106 if (!is_necessarily_closed()) { 01107 // A non-empty system of constraints describing a NNC polyhedron 01108 // must also contain a (combination of) the constraint epsilon >= 0, 01109 // i.e., a constraint with a positive epsilon coefficient. 01110 bool no_epsilon_geq_zero = true; 01111 const dimension_type eps_index = con_sys.num_columns() - 1; 01112 for (dimension_type i = con_sys.num_rows(); i-- > 0; ) 01113 if (con_sys[i][eps_index] > 0) { 01114 no_epsilon_geq_zero = false; 01115 break; 01116 } 01117 if (no_epsilon_geq_zero) { 01118 #ifndef NDEBUG 01119 cerr << "Non-empty constraint system for NNC polyhedron " 01120 << "has no epsilon >= 0 constraint" 01121 << endl; 01122 #endif 01123 goto bomb; 01124 } 01125 } 01126 01127 Constraint_System cs_without_pending = con_sys; 01128 cs_without_pending.erase_to_end(con_sys.first_pending_row()); 01129 cs_without_pending.unset_pending_rows(); 01130 Constraint_System copy_of_con_sys = cs_without_pending; 01131 bool empty = false; 01132 if (check_not_empty || constraints_are_minimized()) { 01133 Generator_System new_gen_sys(topology()); 01134 Bit_Matrix new_sat_g; 01135 empty = minimize(true, copy_of_con_sys, new_gen_sys, new_sat_g); 01136 } 01137 01138 if (empty && check_not_empty) { 01139 #ifndef NDEBUG 01140 cerr << "Unsatisfiable system of constraints!" 01141 << endl; 01142 #endif 01143 goto bomb; 01144 } 01145 01146 if (constraints_are_minimized()) { 01147 // If the constraints are minimized, the number of equalities 01148 // and of inequalities of the system of the polyhedron must be 01149 // the same of the temporary minimized one. 01150 // If it does not happen, the polyhedron is not OK. 01151 if (cs_without_pending.num_rows() != copy_of_con_sys.num_rows() 01152 || cs_without_pending.num_equalities() 01153 != copy_of_con_sys.num_equalities()) { 01154 #ifndef NDEBUG 01155 cerr << "Constraints are declared minimized, but they are not!\n" 01156 << "Here is the minimized form of the constraints:\n"; 01157 copy_of_con_sys.ascii_dump(cerr); 01158 cerr << endl; 01159 #endif 01160 goto bomb; 01161 } 01162 // The system `copy_of_con_sys' has the form that is obtained 01163 // after applying methods gauss() and back_substitute(). 01164 // A system of constraints can be minimal even if it does not 01165 // have this form. So, to verify if the polyhedron is correct, 01166 // we copy the system `con_sys' in a temporary one and then 01167 // modify it using method simplify() (which calls both gauss() 01168 // and back_substitute()). 01169 // If the temporary system and `copy_of_con_sys' are different, 01170 // the polyhedron is not OK. 01171 copy_of_con_sys.strong_normalize(); 01172 copy_of_con_sys.sort_rows(); 01173 cs_without_pending.simplify(); 01174 cs_without_pending.strong_normalize(); 01175 cs_without_pending.sort_rows(); 01176 if (cs_without_pending != copy_of_con_sys) { 01177 #ifndef NDEBUG 01178 cerr << "Constraints are declared minimized, but they are not!\n" 01179 << "Here is the minimized form of the constraints:\n"; 01180 copy_of_con_sys.ascii_dump(cerr); 01181 cerr << endl; 01182 #endif 01183 goto bomb; 01184 } 01185 } 01186 } 01187 01188 if (sat_c_is_up_to_date()) 01189 for (dimension_type i = sat_c.num_rows(); i-- > 0; ) { 01190 const Generator tmp_gen = gen_sys[i]; 01191 const Bit_Row tmp_sat = sat_c[i]; 01192 for (dimension_type j = sat_c.num_columns(); j-- > 0; ) 01193 if (Scalar_Products::sign(con_sys[j], tmp_gen) != tmp_sat[j]) { 01194 #ifndef NDEBUG 01195 cerr << "sat_c is declared up-to-date, but it is not!" 01196 << endl; 01197 #endif 01198 goto bomb; 01199 } 01200 } 01201 01202 if (sat_g_is_up_to_date()) 01203 for (dimension_type i = sat_g.num_rows(); i-- > 0; ) { 01204 const Constraint tmp_con = con_sys[i]; 01205 const Bit_Row tmp_sat = sat_g[i]; 01206 for (dimension_type j = sat_g.num_columns(); j-- > 0; ) 01207 if (Scalar_Products::sign(tmp_con, gen_sys[j]) != tmp_sat[j]) { 01208 #ifndef NDEBUG 01209 cerr << "sat_g is declared up-to-date, but it is not!" 01210 << endl; 01211 #endif 01212 goto bomb; 01213 } 01214 } 01215 01216 if (has_pending_constraints()) { 01217 if (con_sys.num_pending_rows() == 0) { 01218 #ifndef NDEBUG 01219 cerr << "The polyhedron is declared to have pending constraints, " 01220 << "but con_sys has no pending rows!" 01221 << endl; 01222 #endif 01223 goto bomb; 01224 } 01225 } 01226 01227 if (has_pending_generators()) { 01228 if (gen_sys.num_pending_rows() == 0) { 01229 #ifndef NDEBUG 01230 cerr << "The polyhedron is declared to have pending generators, " 01231 << "but gen_sys has no pending rows!" 01232 << endl; 01233 #endif 01234 goto bomb; 01235 } 01236 } 01237 01238 return true; 01239 01240 bomb: 01241 #ifndef NDEBUG 01242 cerr << "Here is the guilty polyhedron:" 01243 << endl; 01244 ascii_dump(cerr); 01245 #endif 01246 return false; 01247 }
| PPL::Polyhedron & Parma_Polyhedra_Library::Polyhedron::operator= | ( | const Polyhedron & | y | ) | [protected] |
The assignment operator. (*this and y can be dimension-incompatible.).
Definition at line 311 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().
00311 { 00312 // Being a protected method, we simply assert that topologies do match. 00313 PPL_ASSERT(topology() == y.topology()); 00314 space_dim = y.space_dim; 00315 if (y.marked_empty()) 00316 set_empty(); 00317 else if (space_dim == 0) 00318 set_zero_dim_univ(); 00319 else { 00320 status = y.status; 00321 if (y.constraints_are_up_to_date()) 00322 con_sys.assign_with_pending(y.con_sys); 00323 if (y.generators_are_up_to_date()) 00324 gen_sys.assign_with_pending(y.gen_sys); 00325 if (y.sat_c_is_up_to_date()) 00326 sat_c = y.sat_c; 00327 if (y.sat_g_is_up_to_date()) 00328 sat_g = y.sat_g; 00329 } 00330 return *this; 00331 }
| void Parma_Polyhedra_Library::Polyhedron::poly_difference_assign | ( | const Polyhedron & | y | ) |
Assigns to *this the poly-difference of *this and y.
| std::invalid_argument | Thrown if *this and y are topology-incompatible or dimension-incompatible. |
Definition at line 2469 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().
02469 { 02470 Polyhedron& x = *this; 02471 // Topology compatibility check. 02472 if (x.topology() != y.topology()) 02473 throw_topology_incompatible("poly_difference_assign(y)", "y", y); 02474 // Dimension-compatibility check. 02475 if (x.space_dim != y.space_dim) 02476 throw_dimension_incompatible("poly_difference_assign(y)", "y", y); 02477 02478 // The difference of a polyhedron `p' and an empty polyhedron is `p'. 02479 if (y.marked_empty()) 02480 return; 02481 // The difference of an empty polyhedron and of a polyhedron `p' is empty. 02482 if (x.marked_empty()) 02483 return; 02484 02485 // If both polyhedra are zero-dimensional, 02486 // then at this point they are necessarily universe polyhedra, 02487 // so that their difference is empty. 02488 if (x.space_dim == 0) { 02489 x.set_empty(); 02490 return; 02491 } 02492 02493 // TODO: This is just an executable specification. 02494 // Have to find a more efficient method. 02495 02496 if (y.contains(x)) { 02497 x.set_empty(); 02498 return; 02499 } 02500 02501 // Being lazy here is only harmful. 02502 // `minimize()' will process any pending constraints or generators. 02503 if (!y.minimize()) 02504 return; 02505 x.minimize(); 02506 02507 Polyhedron new_polyhedron(topology(), x.space_dim, EMPTY); 02508 02509 const Constraint_System& y_cs = y.constraints(); 02510 for (Constraint_System::const_iterator i = y_cs.begin(), 02511 y_cs_end = y_cs.end(); i != y_cs_end; ++i) { 02512 const Constraint& c = *i; 02513 PPL_ASSERT(!c.is_tautological()); 02514 PPL_ASSERT(!c.is_inconsistent()); 02515 // If the polyhedron `x' is included in the polyhedron defined by 02516 // `c', then `c' can be skipped, as adding its complement to `x' 02517 // would result in the empty polyhedron. Moreover, if we operate 02518 // on C-polyhedra and `c' is a non-strict inequality, c _must_ be 02519 // skipped for otherwise we would obtain a result that is less 02520 // precise than the poly-difference. 02521 if (x.relation_with(c).implies(Poly_Con_Relation::is_included())) 02522 continue; 02523 Polyhedron z = x; 02524 const Linear_Expression e = Linear_Expression(c); 02525 switch (c.type()) { 02526 case Constraint::NONSTRICT_INEQUALITY: 02527 if (is_necessarily_closed()) 02528 z.refine_no_check(e <= 0); 02529 else 02530 z.refine_no_check(e < 0); 02531 break; 02532 case Constraint::STRICT_INEQUALITY: 02533 z.refine_no_check(e <= 0); 02534 break; 02535 case Constraint::EQUALITY: 02536 if (is_necessarily_closed()) 02537 // We have already filtered out the case 02538 // when `x' is included in `y': the result is `x'. 02539 return; 02540 else { 02541 Polyhedron w = x; 02542 w.refine_no_check(e < 0); 02543 new_polyhedron.poly_hull_assign(w); 02544 z.refine_no_check(e > 0); 02545 } 02546 break; 02547 } 02548 new_polyhedron.poly_hull_assign(z); 02549 } 02550 *this = new_polyhedron; 02551 02552 PPL_ASSERT_HEAVY(OK()); 02553 }
| void Parma_Polyhedra_Library::Polyhedron::poly_hull_assign | ( | const Polyhedron & | y | ) |
Assigns to *this the poly-hull of *this and y.
| std::invalid_argument | Thrown if *this and y are topology-incompatible or dimension-incompatible. |
Definition at line 2403 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< PSET >::affine_dimension(), fold_space_dimensions(), poly_difference_assign(), and upper_bound_assign().
02403 { 02404 Polyhedron& x = *this; 02405 // Topology compatibility check. 02406 if (x.topology() != y.topology()) 02407 throw_topology_incompatible("poly_hull_assign(y)", "y", y); 02408 // Dimension-compatibility check. 02409 if (x.space_dim != y.space_dim) 02410 throw_dimension_incompatible("poly_hull_assign(y)", "y", y); 02411 02412 // The poly-hull of a polyhedron `p' with an empty polyhedron is `p'. 02413 if (y.marked_empty()) 02414 return; 02415 if (x.marked_empty()) { 02416 x = y; 02417 return; 02418 } 02419 02420 // If both polyhedra are zero-dimensional, 02421 // then at this point they are necessarily universe polyhedra, 02422 // so that their poly-hull is the universe polyhedron too. 02423 if (x.space_dim == 0) 02424 return; 02425 02426 // Both systems of generators have to be up-to-date, 02427 // possibly having pending generators. 02428 if ((x.has_pending_constraints() && !x.process_pending_constraints()) 02429 || (!x.generators_are_up_to_date() && !x.update_generators())) { 02430 // Discovered `x' empty when updating generators. 02431 x = y; 02432 return; 02433 } 02434 if ((y.has_pending_constraints() && !y.process_pending_constraints()) 02435 || (!y.generators_are_up_to_date() && !y.update_generators())) 02436 // Discovered `y' empty when updating generators. 02437 return; 02438 02439 // Here both systems are up-to-date and possibly have pending generators 02440 // (but they cannot have pending constraints). 02441 PPL_ASSERT(!x.has_pending_constraints() && x.generators_are_up_to_date()); 02442 PPL_ASSERT(!y.has_pending_constraints() && y.generators_are_up_to_date()); 02443 02444 // If `x' can support pending generators, 02445 // the generators of `y' are added as pending generators of `x'. 02446 if (x.can_have_something_pending()) { 02447 x.gen_sys.add_pending_rows(y.gen_sys); 02448 x.set_generators_pending(); 02449 } 02450 else { 02451 // `x' cannot support pending generators. 02452 // If both generator systems are (fully) sorted, then we can merge 02453 // them; otherwise we simply add the second to the first. 02454 if (x.gen_sys.is_sorted() 02455 && y.gen_sys.is_sorted() && !y.has_pending_generators()) 02456 x.gen_sys.merge_rows_assign(y.gen_sys); 02457 else 02458 x.gen_sys.add_rows(y.gen_sys); 02459 // Constraints are no longer up-to-date 02460 // and generators are no longer minimized. 02461 x.clear_constraints_up_to_date(); 02462 x.clear_generators_minimized(); 02463 } 02464 // At this point both `x' and `y' are not empty. 02465 PPL_ASSERT_HEAVY(x.OK(true) && y.OK(true)); 02466 }
| void Parma_Polyhedra_Library::Polyhedron::print | ( | ) | const |
Prints *this to std::cerr using operator<<.
| 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.It is assumed that the polyhedron does have some constraints or generators pending.
Definition at line 291 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().
00291 { 00292 PPL_ASSERT(space_dim > 0 && !marked_empty()); 00293 PPL_ASSERT(has_something_pending()); 00294 00295 Polyhedron& x = const_cast<Polyhedron&>(*this); 00296 00297 if (x.has_pending_constraints()) 00298 return x.process_pending_constraints(); 00299 00300 PPL_ASSERT(x.has_pending_generators()); 00301 x.process_pending_generators(); 00302 return true; 00303 }
| 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.It is assumed that the polyhedron does have some pending constraints.
Definition at line 688 of file Polyhedron_nonpublic.cc.
References add_and_minimize(), clear_pending_constraints(), clear_sat_g_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_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(), drop_some_non_integer_points(), frequency(), generators(), is_bounded(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), max_min(), poly_hull_assign(), process_pending(), relation_with(), remove_pending_to_obtain_generators(), time_elapse_assign(), topological_closure_assign(), and unconstrain().
00688 { 00689 PPL_ASSERT(space_dim > 0 && !marked_empty()); 00690 PPL_ASSERT(has_pending_constraints() && !has_pending_generators()); 00691 00692 Polyhedron& x = const_cast<Polyhedron&>(*this); 00693 00694 // Integrate the pending part of the system of constraints and minimize. 00695 // We need `sat_c' up-to-date and `con_sys' sorted (together with `sat_c'). 00696 if (!x.sat_c_is_up_to_date()) 00697 x.sat_c.transpose_assign(x.sat_g); 00698 if (!x.con_sys.is_sorted()) 00699 x.obtain_sorted_constraints_with_sat_c(); 00700 // We sort in place the pending constraints, erasing those constraints 00701 // that also occur in the non-pending part of `con_sys'. 00702 x.con_sys.sort_pending_and_remove_duplicates(); 00703 if (x.con_sys.num_pending_rows() == 0) { 00704 // All pending constraints were duplicates. 00705 x.clear_pending_constraints(); 00706 PPL_ASSERT_HEAVY(OK(true)); 00707 return true; 00708 } 00709 00710 const bool empty = add_and_minimize(true, x.con_sys, x.gen_sys, x.sat_c); 00711 PPL_ASSERT(x.con_sys.num_pending_rows() == 0); 00712 00713 if (empty) 00714 x.set_empty(); 00715 else { 00716 x.clear_pending_constraints(); 00717 x.clear_sat_g_up_to_date(); 00718 x.set_sat_c_up_to_date(); 00719 } 00720 PPL_ASSERT_HEAVY(OK(!empty)); 00721 return !empty; 00722 }
| 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 725 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(), drop_some_non_integer_points(), H79_widening_assign(), intersection_assign(), is_included_in(), is_universe(), process_pending(), refine_no_check(), refine_with_constraints(), relation_with(), and remove_pending_to_obtain_constraints().
00725 { 00726 PPL_ASSERT(space_dim > 0 && !marked_empty()); 00727 PPL_ASSERT(has_pending_generators() && !has_pending_constraints()); 00728 00729 Polyhedron& x = const_cast<Polyhedron&>(*this); 00730 00731 // Integrate the pending part of the system of generators and minimize. 00732 // We need `sat_g' up-to-date and `gen_sys' sorted (together with `sat_g'). 00733 if (!x.sat_g_is_up_to_date()) 00734 x.sat_g.transpose_assign(x.sat_c); 00735 if (!x.gen_sys.is_sorted()) 00736 x.obtain_sorted_generators_with_sat_g(); 00737 // We sort in place the pending generators, erasing those generators 00738 // that also occur in the non-pending part of `gen_sys'. 00739 x.gen_sys.sort_pending_and_remove_duplicates(); 00740 if (x.gen_sys.num_pending_rows() == 0) { 00741 // All pending generators were duplicates. 00742 x.clear_pending_generators(); 00743 PPL_ASSERT_HEAVY(OK(true)); 00744 return; 00745 } 00746 00747 add_and_minimize(false, x.gen_sys, x.con_sys, x.sat_g); 00748 PPL_ASSERT(x.gen_sys.num_pending_rows() == 0); 00749 00750 x.clear_pending_generators(); 00751 x.clear_sat_c_up_to_date(); 00752 x.set_sat_g_up_to_date(); 00753 }
| 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 334 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().
00334 { 00335 // Private method: the caller must ensure the following. 00336 PPL_ASSERT(topology() == y.topology()); 00337 PPL_ASSERT(space_dim == y.space_dim); 00338 PPL_ASSERT(!marked_empty() && !y.marked_empty() && space_dim > 0); 00339 00340 const Polyhedron& x = *this; 00341 00342 if (x.is_necessarily_closed()) { 00343 if (!x.has_something_pending() && !y.has_something_pending()) { 00344 bool css_normalized = false; 00345 if (x.constraints_are_minimized() && y.constraints_are_minimized()) { 00346 // Equivalent minimized constraint systems have: 00347 // - the same number of constraints; ... 00348 if (x.con_sys.num_rows() != y.con_sys.num_rows()) 00349 return Polyhedron::TVB_FALSE; 00350 // - the same number of equalities; ... 00351 dimension_type x_num_equalities = x.con_sys.num_equalities(); 00352 if (x_num_equalities != y.con_sys.num_equalities()) 00353 return Polyhedron::TVB_FALSE; 00354 // - if there are no equalities, they have the same constraints. 00355 // Delay this test: try cheaper tests on generators first. 00356 css_normalized = (x_num_equalities == 0); 00357 } 00358 00359 if (x.generators_are_minimized() && y.generators_are_minimized()) { 00360 // Equivalent minimized generator systems have: 00361 // - the same number of generators; ... 00362 if (x.gen_sys.num_rows() != y.gen_sys.num_rows()) 00363 return Polyhedron::TVB_FALSE; 00364 // - the same number of lines; ... 00365 const dimension_type x_num_lines = x.gen_sys.num_lines(); 00366 if (x_num_lines != y.gen_sys.num_lines()) 00367 return Polyhedron::TVB_FALSE; 00368 // - if there are no lines, they have the same generators. 00369 if (x_num_lines == 0) { 00370 // Sort the two systems and check for syntactic identity. 00371 x.obtain_sorted_generators(); 00372 y.obtain_sorted_generators(); 00373 if (x.gen_sys == y.gen_sys) 00374 return Polyhedron::TVB_TRUE; 00375 else 00376 return Polyhedron::TVB_FALSE; 00377 } 00378 } 00379 00380 if (css_normalized) { 00381 // Sort the two systems and check for identity. 00382 x.obtain_sorted_constraints(); 00383 y.obtain_sorted_constraints(); 00384 if (x.con_sys == y.con_sys) 00385 return Polyhedron::TVB_TRUE; 00386 else 00387 return Polyhedron::TVB_FALSE; 00388 } 00389 } 00390 } 00391 return Polyhedron::TVB_DONT_KNOW; 00392 }
| 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 1355 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().
01355 { 01356 PPL_ASSERT(!marked_empty()); 01357 PPL_ASSERT(space_dim >= c.space_dimension()); 01358 01359 // Dealing with a zero-dimensional space polyhedron first. 01360 if (space_dim == 0) { 01361 if (c.is_inconsistent()) 01362 set_empty(); 01363 return; 01364 } 01365 01366 // The constraints (possibly with pending rows) are required. 01367 if (has_pending_generators()) 01368 process_pending_generators(); 01369 else if (!constraints_are_up_to_date()) 01370 update_constraints(); 01371 01372 const bool adding_pending = can_have_something_pending(); 01373 01374 if (c.is_necessarily_closed() || !is_necessarily_closed()) 01375 // Since `con_sys' is not empty, the topology and space dimension 01376 // of the inserted constraint are automatically adjusted. 01377 if (adding_pending) 01378 con_sys.insert_pending(c); 01379 else 01380 con_sys.insert(c); 01381 else { 01382 // Here we know that the system of constraints has at least a row. 01383 // However, by barely invoking `con_sys.insert(c)' we would 01384 // cause a change in the topology of `con_sys', which is wrong. 01385 // Thus, we insert a "topology corrected" copy of `c'. 01386 Linear_Expression nc_expr = Linear_Expression(c); 01387 if (c.is_equality()) 01388 if (adding_pending) 01389 con_sys.insert_pending(nc_expr == 0); 01390 else 01391 con_sys.insert(nc_expr == 0); 01392 else 01393 if (adding_pending) 01394 con_sys.insert_pending(nc_expr >= 0); 01395 else 01396 con_sys.insert(nc_expr >= 0); 01397 } 01398 01399 if (adding_pending) 01400 set_constraints_pending(); 01401 else { 01402 // Constraints are not minimized and generators are not up-to-date. 01403 clear_constraints_minimized(); 01404 clear_generators_up_to_date(); 01405 } 01406 01407 // Note: the constraint system may have become unsatisfiable, thus 01408 // we do not check for satisfiability. 01409 PPL_ASSERT_HEAVY(OK()); 01410 }
| 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 1693 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().
01693 { 01694 // Dimension-compatibility check. 01695 if (space_dim < cg.space_dimension()) 01696 throw_dimension_incompatible("refine_with_congruence(cg)", "cg", cg); 01697 01698 // If the polyhedron is known to be empty, do nothing. 01699 if (marked_empty()) 01700 return; 01701 01702 // Dealing with a zero-dimensional space polyhedron first. 01703 if (space_dim == 0) { 01704 if (!cg.is_tautological()) 01705 set_empty(); 01706 return; 01707 } 01708 01709 if (cg.is_equality()) { 01710 Linear_Expression le(cg); 01711 Constraint c(le, Constraint::EQUALITY, NECESSARILY_CLOSED); 01712 // Enforce normalization. 01713 c.strong_normalize(); 01714 refine_no_check(c); 01715 } 01716 }
| 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 1799 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().
01799 { 01800 // Dimension-compatibility check. 01801 if (space_dim < cgs.space_dimension()) 01802 throw_dimension_incompatible("refine_with_congruences(cgs)", "cgs", cgs); 01803 01804 Constraint_System cs; 01805 bool inserted = false; 01806 for (Congruence_System::const_iterator i = cgs.begin(), 01807 cgs_end = cgs.end(); i != cgs_end; ++i) { 01808 if (i->is_equality()) { 01809 Linear_Expression le(*i); 01810 Constraint c(le, Constraint::EQUALITY, NECESSARILY_CLOSED); 01811 // Enforce normalization. 01812 c.strong_normalize(); 01813 // TODO: Consider stealing the row in c when adding it to cs. 01814 cs.insert(c); 01815 inserted = true; 01816 } 01817 else if (i->is_inconsistent()) { 01818 set_empty(); 01819 return; 01820 } 01821 } 01822 // Only add cgs if congruences were inserted into cgs, as the 01823 // dimension of cs must be at most that of the polyhedron. 01824 if (inserted) 01825 add_recycled_constraints(cs); 01826 }
| 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 1683 of file Polyhedron_public.cc.
References marked_empty(), refine_no_check(), space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), and throw_dimension_incompatible().
01683 { 01684 // Dimension-compatibility check. 01685 if (space_dim < c.space_dimension()) 01686 throw_dimension_incompatible("refine_with_constraint(c)", "c", c); 01687 // If the polyhedron is known to be empty, do nothing. 01688 if (!marked_empty()) 01689 refine_no_check(c); 01690 }
| 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 1719 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().
01719 { 01720 // TODO: this is just an executable specification. 01721 01722 // Dimension-compatibility check. 01723 const dimension_type cs_space_dim = cs.space_dimension(); 01724 if (space_dim < cs_space_dim) 01725 throw_dimension_incompatible("refine_with_constraints(cs)a", 01726 "cs", cs); 01727 01728 // Adding no constraints is a no-op. 01729 if (cs.has_no_rows()) 01730 return; 01731 01732 if (space_dim == 0) { 01733 // In a 0-dimensional space the constraints are 01734 // tautologies (e.g., 0 == 0 or 1 >= 0 or 1 > 0) or 01735 // inconsistent (e.g., 1 == 0 or -1 >= 0 or 0 > 0). 01736 // In a system of constraints `begin()' and `end()' are equal 01737 // if and only if the system only contains tautologies. 01738 if (cs.begin() != cs.end()) 01739 // There is a constraint, it must be inconsistent, 01740 // the polyhedron is empty. 01741 status.set_empty(); 01742 return; 01743 } 01744 01745 if (marked_empty()) 01746 return; 01747 01748 // The constraints (possibly with pending rows) are required. 01749 if (has_pending_generators()) 01750 process_pending_generators(); 01751 else if (!constraints_are_up_to_date()) 01752 update_constraints(); 01753 01754 const bool adding_pending = can_have_something_pending(); 01755 for (dimension_type i = cs.num_rows(); i-- > 0; ) { 01756 const Constraint& c = cs[i]; 01757 01758 if (c.is_necessarily_closed() || !is_necessarily_closed()) 01759 // Since `con_sys' is not empty, the topology and space dimension 01760 // of the inserted constraint are automatically adjusted. 01761 if (adding_pending) 01762 con_sys.insert_pending(c); 01763 else 01764 con_sys.insert(c); 01765 else { 01766 // Here we know that *this is necessarily closed so even if c is 01767 // topologically closed, by barely invoking `con_sys.insert(c)' we 01768 // would cause a change in the topology of `con_sys', which is 01769 // wrong. Thus, we insert a topology closed and "topology 01770 // corrected" version of `c'. 01771 Linear_Expression nc_expr = Linear_Expression(c); 01772 if (c.is_equality()) 01773 if (adding_pending) 01774 con_sys.insert_pending(nc_expr == 0); 01775 else 01776 con_sys.insert(nc_expr == 0); 01777 else 01778 if (adding_pending) 01779 con_sys.insert_pending(nc_expr >= 0); 01780 else 01781 con_sys.insert(nc_expr >= 0); 01782 } 01783 } 01784 01785 if (adding_pending) 01786 set_constraints_pending(); 01787 else { 01788 // Constraints are not minimized and generators are not up-to-date. 01789 clear_constraints_minimized(); 01790 clear_generators_up_to_date(); 01791 } 01792 01793 // Note: the constraint system may have become unsatisfiable, thus 01794 // we do not check for satisfiability. 01795 PPL_ASSERT_HEAVY(OK()); 01796 }
| 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 276 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Scalar_Products::assign(), Parma_Polyhedra_Library::Generator_System::begin(), 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::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(), PPL_DIRTY_TEMP_COEFFICIENT, 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(), throw_dimension_incompatible(), and update_generators().
00276 { 00277 dimension_type cg_space_dim = cg.space_dimension(); 00278 // Dimension-compatibility check. 00279 if (space_dim < cg_space_dim) 00280 throw_dimension_incompatible("relation_with(cg)", "cg", cg); 00281 00282 if (cg.is_equality()) { 00283 const Constraint c(cg); 00284 return relation_with(c); 00285 } 00286 00287 if (marked_empty()) 00288 return Poly_Con_Relation::saturates() 00289 && Poly_Con_Relation::is_included() 00290 && Poly_Con_Relation::is_disjoint(); 00291 00292 if (space_dim == 0) { 00293 if (cg.is_inconsistent()) 00294 return Poly_Con_Relation::is_disjoint(); 00295 else 00296 return Poly_Con_Relation::saturates() 00297 && Poly_Con_Relation::is_included(); 00298 } 00299 00300 if ((has_pending_constraints() && !process_pending_constraints()) 00301 || (!generators_are_up_to_date() && !update_generators())) 00302 // The polyhedron is empty. 00303 return Poly_Con_Relation::saturates() 00304 && Poly_Con_Relation::is_included() 00305 && Poly_Con_Relation::is_disjoint(); 00306 00307 // Build the equality corresponding to the congruence (ignoring the modulus). 00308 Linear_Expression expr = Linear_Expression(cg); 00309 Constraint c(expr == 0); 00310 00311 // The polyhedron is non-empty so that there exists a point. 00312 // For an arbitrary generator point, compute the scalar product with 00313 // the equality. 00314 PPL_DIRTY_TEMP_COEFFICIENT(sp_point); 00315 for (Generator_System::const_iterator gs_i = gen_sys.begin(), 00316 gs_end = gen_sys.end(); gs_i != gs_end; ++gs_i) { 00317 if (gs_i->is_point()) { 00318 Scalar_Products::assign(sp_point, c, *gs_i); 00319 expr -= sp_point; 00320 break; 00321 } 00322 } 00323 00324 // Find two hyperplanes that satisfy the congruence and are near to 00325 // the generating point (so that the point lies on or between these 00326 // two hyperplanes). 00327 // Then use the relations between the polyhedron and the halfspaces 00328 // corresponding to the hyperplanes to determine the result. 00329 00330 // Compute the distance from the point to an hyperplane. 00331 const Coefficient& modulus = cg.modulus(); 00332 PPL_DIRTY_TEMP_COEFFICIENT(signed_distance); 00333 signed_distance = sp_point % modulus; 00334 if (signed_distance == 0) 00335 // The point is lying on the hyperplane. 00336 return relation_with(expr == 0); 00337 else 00338 // The point is not lying on the hyperplane. 00339 expr += signed_distance; 00340 00341 // Build first halfspace constraint. 00342 const bool positive = (signed_distance > 0); 00343 Constraint first_halfspace = positive ? (expr >= 0) : (expr <= 0); 00344 00345 Poly_Con_Relation first_rels = relation_with(first_halfspace); 00346 PPL_ASSERT(!first_rels.implies(Poly_Con_Relation::saturates()) 00347 && !first_rels.implies(Poly_Con_Relation::is_disjoint())); 00348 if (first_rels.implies(Poly_Con_Relation::strictly_intersects())) 00349 return Poly_Con_Relation::strictly_intersects(); 00350 00351 // Build second halfspace. 00352 if (positive) 00353 expr -= modulus; 00354 else 00355 expr += modulus; 00356 Constraint second_halfspace = positive ? (expr <= 0) : (expr >= 0); 00357 00358 PPL_ASSERT(first_rels == Poly_Con_Relation::is_included()); 00359 Poly_Con_Relation second_rels = relation_with(second_halfspace); 00360 PPL_ASSERT(!second_rels.implies(Poly_Con_Relation::saturates()) 00361 && !second_rels.implies(Poly_Con_Relation::is_disjoint())); 00362 if (second_rels.implies(Poly_Con_Relation::strictly_intersects())) 00363 return Poly_Con_Relation::strictly_intersects(); 00364 00365 PPL_ASSERT(second_rels == Poly_Con_Relation::is_included()); 00366 return Poly_Con_Relation::is_disjoint(); 00367 }
| 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 250 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().
00250 { 00251 // Dimension-compatibility check. 00252 if (space_dim < g.space_dimension()) 00253 throw_dimension_incompatible("relation_with(g)", "g", g); 00254 00255 // The empty polyhedron cannot subsume a generator. 00256 if (marked_empty()) 00257 return Poly_Gen_Relation::nothing(); 00258 00259 // A universe polyhedron in a zero-dimensional space subsumes 00260 // all the generators of a zero-dimensional space. 00261 if (space_dim == 0) 00262 return Poly_Gen_Relation::subsumes(); 00263 00264 if (has_pending_generators()) 00265 process_pending_generators(); 00266 else if (!constraints_are_up_to_date()) 00267 update_constraints(); 00268 00269 return 00270 con_sys.satisfies_all_constraints(g) 00271 ? Poly_Gen_Relation::subsumes() 00272 : Poly_Gen_Relation::nothing(); 00273 }
| 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 210 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 BFT00_poly_hull_assign_if_exact(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHZ09_C_poly_hull_assign_if_exact(), BHZ09_NNC_poly_hull_assign_if_exact(), poly_difference_assign(), and relation_with().
00210 { 00211 // Dimension-compatibility check. 00212 if (space_dim < c.space_dimension()) 00213 throw_dimension_incompatible("relation_with(c)", "c", c); 00214 00215 if (marked_empty()) 00216 return Poly_Con_Relation::saturates() 00217 && Poly_Con_Relation::is_included() 00218 && Poly_Con_Relation::is_disjoint(); 00219 00220 if (space_dim == 0) { 00221 if (c.is_inconsistent()) 00222 if (c.is_strict_inequality() && c.inhomogeneous_term() == 0) 00223 // The constraint 0 > 0 implicitly defines the hyperplane 0 = 0; 00224 // thus, the zero-dimensional point also saturates it. 00225 return Poly_Con_Relation::saturates() 00226 && Poly_Con_Relation::is_disjoint(); 00227 else 00228 return Poly_Con_Relation::is_disjoint(); 00229 else if (c.is_equality() || c.inhomogeneous_term() == 0) 00230 return Poly_Con_Relation::saturates() 00231 && Poly_Con_Relation::is_included(); 00232 else 00233 // The zero-dimensional point saturates 00234 // neither the positivity constraint 1 >= 0, 00235 // nor the strict positivity constraint 1 > 0. 00236 return Poly_Con_Relation::is_included(); 00237 } 00238 00239 if ((has_pending_constraints() && !process_pending_constraints()) 00240 || (!generators_are_up_to_date() && !update_generators())) 00241 // The polyhedron is empty. 00242 return Poly_Con_Relation::saturates() 00243 && Poly_Con_Relation::is_included() 00244 && Poly_Con_Relation::is_disjoint(); 00245 00246 return gen_sys.relation_with(c); 00247 }
| 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 490 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().
00490 { 00491 // Dimension-compatibility check. 00492 if (new_dimension > space_dim) 00493 throw_dimension_incompatible("remove_higher_space_dimensions(nd)", 00494 new_dimension); 00495 00496 // The removal of no dimensions from any polyhedron is a no-op. 00497 // Note that this case also captures the only legal removal of 00498 // dimensions from a polyhedron in a 0-dim space. 00499 if (new_dimension == space_dim) { 00500 PPL_ASSERT_HEAVY(OK()); 00501 return; 00502 } 00503 00504 // We need updated generators; note that keeping pending generators 00505 // is useless because constraints will be dropped anyway. 00506 if (marked_empty() 00507 || (has_something_pending() && !remove_pending_to_obtain_generators()) 00508 || (!generators_are_up_to_date() && !update_generators())) { 00509 // Removing dimensions from the empty polyhedron: 00510 // just updates the space dimension. 00511 space_dim = new_dimension; 00512 con_sys.clear(); 00513 PPL_ASSERT_HEAVY(OK()); 00514 return; 00515 } 00516 00517 if (new_dimension == 0) { 00518 // Removing all dimensions from a non-empty polyhedron: 00519 // just return the zero-dimensional universe polyhedron. 00520 set_zero_dim_univ(); 00521 return; 00522 } 00523 00524 dimension_type new_num_cols = new_dimension + 1; 00525 if (!is_necessarily_closed()) { 00526 // The polyhedron is not necessarily closed: move the column 00527 // of the epsilon coefficients to its new place. 00528 gen_sys.swap_columns(gen_sys.num_columns() - 1, new_num_cols); 00529 // The number of remaining columns is `new_dimension + 2'. 00530 ++new_num_cols; 00531 } 00532 // Note that resizing also calls `set_sorted(false)'. 00533 gen_sys.remove_trailing_columns(space_dim - new_dimension); 00534 // We may have invalid lines and rays now. 00535 gen_sys.remove_invalid_lines_and_rays(); 00536 00537 // Constraints are not up-to-date and generators are not minimized. 00538 clear_constraints_up_to_date(); 00539 clear_generators_minimized(); 00540 00541 // Update the space dimension. 00542 space_dim = new_dimension; 00543 00544 PPL_ASSERT_HEAVY(OK(true)); 00545 }
| 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 756 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().
00756 { 00757 PPL_ASSERT(has_something_pending()); 00758 00759 Polyhedron& x = const_cast<Polyhedron&>(*this); 00760 00761 // If the polyhedron has pending constraints, simply unset them. 00762 if (x.has_pending_constraints()) { 00763 // Integrate the pending constraints, which are possibly not sorted. 00764 x.con_sys.unset_pending_rows(); 00765 x.con_sys.set_sorted(false); 00766 x.clear_pending_constraints(); 00767 x.clear_constraints_minimized(); 00768 x.clear_generators_up_to_date(); 00769 } 00770 else { 00771 PPL_ASSERT(x.has_pending_generators()); 00772 // We must process the pending generators and obtain the 00773 // corresponding system of constraints. 00774 x.process_pending_generators(); 00775 } 00776 PPL_ASSERT_HEAVY(OK(true)); 00777 }
| 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.It is assumed that the polyhedron does have some constraints or generators pending.
Definition at line 780 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().
00780 { 00781 PPL_ASSERT(has_something_pending()); 00782 00783 Polyhedron& x = const_cast<Polyhedron&>(*this); 00784 00785 // If the polyhedron has pending generators, simply unset them. 00786 if (x.has_pending_generators()) { 00787 // Integrate the pending generators, which are possibly not sorted. 00788 x.gen_sys.unset_pending_rows(); 00789 x.gen_sys.set_sorted(false); 00790 x.clear_pending_generators(); 00791 x.clear_generators_minimized(); 00792 x.clear_constraints_up_to_date(); 00793 PPL_ASSERT_HEAVY(OK(true)); 00794 return true; 00795 } 00796 else { 00797 PPL_ASSERT(x.has_pending_constraints()); 00798 // We must integrate the pending constraints and obtain the 00799 // corresponding system of generators. 00800 return x.process_pending_constraints(); 00801 } 00802 }
| void Parma_Polyhedra_Library::Polyhedron::remove_space_dimensions | ( | const Variables_Set & | vars | ) |
Removes all the specified dimensions from the vector space.
| vars | 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 vars. |
Definition at line 417 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, Parma_Polyhedra_Library::Variables_Set::space_dimension(), throw_dimension_incompatible(), and update_generators().
Referenced by fold_space_dimensions().
00417 { 00418 // The removal of no dimensions from any polyhedron is a no-op. 00419 // Note that this case also captures the only legal removal of 00420 // dimensions from a polyhedron in a 0-dim space. 00421 if (vars.empty()) { 00422 PPL_ASSERT_HEAVY(OK()); 00423 return; 00424 } 00425 00426 // Dimension-compatibility check. 00427 const dimension_type min_space_dim = vars.space_dimension(); 00428 if (space_dim < min_space_dim) 00429 throw_dimension_incompatible("remove_space_dimensions(vs)", min_space_dim); 00430 00431 const dimension_type new_space_dim = space_dim - vars.size(); 00432 00433 // We need updated generators; note that keeping pending generators 00434 // is useless because the constraints will be dropped anyway. 00435 if (marked_empty() 00436 || (has_something_pending() && !remove_pending_to_obtain_generators()) 00437 || (!generators_are_up_to_date() && !update_generators())) { 00438 // Removing dimensions from the empty polyhedron: 00439 // we clear `con_sys' since it could have contained the 00440 // unsatisfiable constraint of the wrong dimension. 00441 con_sys.clear(); 00442 // Update the space dimension. 00443 space_dim = new_space_dim; 00444 PPL_ASSERT_HEAVY(OK()); 00445 return; 00446 } 00447 00448 // When removing _all_ dimensions from a non-empty polyhedron, 00449 // we obtain the zero-dimensional universe polyhedron. 00450 if (new_space_dim == 0) { 00451 set_zero_dim_univ(); 00452 return; 00453 } 00454 00455 // For each variable to be removed, we fill the corresponding column 00456 // by shifting left those columns that will not be removed. 00457 Variables_Set::const_iterator vsi = vars.begin(); 00458 Variables_Set::const_iterator vsi_end = vars.end(); 00459 dimension_type dst_col = *vsi + 1; 00460 dimension_type src_col = dst_col + 1; 00461 for (++vsi; vsi != vsi_end; ++vsi) { 00462 const dimension_type vsi_col = *vsi + 1; 00463 // All columns in between are moved to the left. 00464 while (src_col < vsi_col) 00465 gen_sys.Matrix::swap_columns(dst_col++, src_col++); 00466 ++src_col; 00467 } 00468 // Moving the remaining columns. 00469 const dimension_type gen_sys_num_columns = gen_sys.num_columns(); 00470 while (src_col < gen_sys_num_columns) 00471 gen_sys.Matrix::swap_columns(dst_col++, src_col++); 00472 00473 // The number of remaining columns is `dst_col'. 00474 // Note that resizing also calls `set_sorted(false)'. 00475 gen_sys.remove_trailing_columns(gen_sys_num_columns - dst_col); 00476 // We may have invalid lines and rays now. 00477 gen_sys.remove_invalid_lines_and_rays(); 00478 00479 // Constraints are not up-to-date and generators are not minimized. 00480 clear_constraints_up_to_date(); 00481 clear_generators_minimized(); 00482 00483 // Update the space dimension. 00484 space_dim = new_space_dim; 00485 00486 PPL_ASSERT_HEAVY(OK(true)); 00487 }
| 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 148 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().
00148 { 00149 return status.test_sat_c_up_to_date(); 00150 }
| 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 153 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(), BHZ09_C_poly_hull_assign_if_exact(), BHZ09_NNC_poly_hull_assign_if_exact(), 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().
00153 { 00154 return status.test_sat_g_up_to_date(); 00155 }
| 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 40 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().
00041 { 00042 // Private method: the caller must ensure the following conditions. 00043 PPL_ASSERT(topology() == y.topology() 00044 && topology() == cs_selection.topology() 00045 && space_dim == y.space_dim); 00046 PPL_ASSERT(!marked_empty() 00047 && !has_pending_constraints() 00048 && generators_are_up_to_date()); 00049 PPL_ASSERT(!y.marked_empty() 00050 && !y.has_something_pending() 00051 && y.constraints_are_minimized()); 00052 00053 // A constraint in `y.con_sys' is copied to `cs_selection' 00054 // if it is satisfied by all the generators of `gen_sys'. 00055 00056 // Note: the loop index `i' goes upward to avoid reversing 00057 // the ordering of the chosen constraints. 00058 for (dimension_type i = 0, end = y.con_sys.num_rows(); i < end; ++i) { 00059 const Constraint& c = y.con_sys[i]; 00060 if (gen_sys.satisfied_by_all_generators(c)) 00061 cs_selection.insert(c); 00062 } 00063 }
| 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 67 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(), swap(), Parma_Polyhedra_Library::Linear_System::topology(), topology(), update_generators(), and update_sat_g().
Referenced by BHRZ03_widening_assign(), and H79_widening_assign().
00069 { 00070 // Private method: the caller must ensure the following conditions 00071 // (beside the inclusion `y <= x'). 00072 PPL_ASSERT(topology() == y.topology() 00073 && topology() == cs_selected.topology() 00074 && topology() == cs_not_selected.topology()); 00075 PPL_ASSERT(space_dim == y.space_dim); 00076 PPL_ASSERT(!marked_empty() 00077 && !has_pending_generators() 00078 && constraints_are_up_to_date()); 00079 PPL_ASSERT(!y.marked_empty() 00080 && !y.has_something_pending() 00081 && y.constraints_are_minimized() 00082 && y.generators_are_up_to_date()); 00083 00084 // FIXME: this is a workaround for NNC polyhedra. 00085 if (!y.is_necessarily_closed()) { 00086 // Force strong minimization of constraints. 00087 y.strongly_minimize_constraints(); 00088 // Recompute generators (without compromising constraint minimization). 00089 y.update_generators(); 00090 } 00091 00092 // Obtain a sorted copy of `y.sat_g'. 00093 if (!y.sat_g_is_up_to_date()) 00094 y.update_sat_g(); 00095 Bit_Matrix tmp_sat_g = y.sat_g; 00096 // Remove from `tmp_sat_g' the rows corresponding to tautologies 00097 // (i.e., the positivity or epsilon-bounding constraints): 00098 // this is needed in order to widen the polyhedron and not the 00099 // corresponding homogenized polyhedral cone. 00100 const Constraint_System& y_cs = y.con_sys; 00101 dimension_type num_rows = y_cs.num_rows(); 00102 for (dimension_type i = 0; i < num_rows; ++i) 00103 if (y_cs[i].is_tautological()) { 00104 --num_rows; 00105 std::swap(tmp_sat_g[i], tmp_sat_g[num_rows]); 00106 } 00107 tmp_sat_g.rows_erase_to_end(num_rows); 00108 tmp_sat_g.sort_rows(); 00109 00110 // A constraint in `con_sys' is copied to `cs_selected' 00111 // if its behavior with respect to `y.gen_sys' is the same 00112 // as that of another constraint in `y.con_sys'. 00113 // otherwise it is copied to `cs_not_selected'. 00114 // Namely, we check whether the saturation row `buffer' 00115 // (built starting from the given constraint and `y.gen_sys') 00116 // is a row of the saturation matrix `tmp_sat_g'. 00117 00118 // CHECKME: the following comment is only applicable when `y.gen_sys' 00119 // is minimized. In that case, the comment suggests that it would be 00120 // possible to use a fast (but incomplete) redundancy test based on 00121 // the number of saturators in `buffer'. 00122 // NOTE: If the considered constraint of `con_sys' does not 00123 // satisfy the saturation rule (see Section \ref prelims), then 00124 // it will not appear in the resulting constraint system, 00125 // because `tmp_sat_g' is built starting from a minimized polyhedron. 00126 00127 // The size of `buffer' will reach sat.num_columns() bits. 00128 Bit_Row buffer; 00129 // Note: the loop index `i' goes upward to avoid reversing 00130 // the ordering of the chosen constraints. 00131 for (dimension_type i = 0, end = con_sys.num_rows(); i < end; ++i) { 00132 const Constraint& ci = con_sys[i]; 00133 // The saturation row `buffer' is built considering 00134 // the `i'-th constraint of the polyhedron `x' and 00135 // all the generators of the polyhedron `y'. 00136 buffer.clear(); 00137 for (dimension_type j = y.gen_sys.num_rows(); j-- > 0; ) { 00138 const int sp_sgn = Scalar_Products::sign(ci, y.gen_sys[j]); 00139 // We are assuming that `y <= x'. 00140 PPL_ASSERT(sp_sgn >= 0 00141 || (!is_necessarily_closed() 00142 && ci.is_strict_inequality() 00143 && y.gen_sys[j].is_point())); 00144 if (sp_sgn > 0) 00145 buffer.set(j); 00146 } 00147 // We check whether `buffer' is a row of `tmp_sat_g', 00148 // exploiting its sortedness in order to have faster comparisons. 00149 if (tmp_sat_g.sorted_contains(buffer)) 00150 cs_selected.insert(ci); 00151 else 00152 cs_not_selected.insert(ci); 00153 } 00154 }
| void Parma_Polyhedra_Library::Polyhedron::set_constraints_minimized | ( | ) | [inline, private] |
Sets status to express that constraints are minimized.
Definition at line 202 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().
00202 { 00203 set_constraints_up_to_date(); 00204 status.set_c_minimized(); 00205 }
| void Parma_Polyhedra_Library::Polyhedron::set_constraints_pending | ( | ) | [inline, private] |
Sets status to express that constraints are pending.
Definition at line 214 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().
00214 { 00215 status.set_c_pending(); 00216 }
| 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 192 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().
00192 { 00193 status.set_c_up_to_date(); 00194 }
| void Parma_Polyhedra_Library::Polyhedron::set_empty | ( | ) | [private] |
Sets status to express that the polyhedron is empty, clearing all corresponding matrices.
Definition at line 678 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(), Parma_Polyhedra_Library::Polyhedron::Status::ascii_load(), concatenate_assign(), drop_some_non_integer_points(), intersection_assign(), operator=(), poly_difference_assign(), Polyhedron(), process_pending_constraints(), refine_no_check(), refine_with_congruence(), refine_with_congruences(), time_elapse_assign(), and update_generators().
| void Parma_Polyhedra_Library::Polyhedron::set_generators_minimized | ( | ) | [inline, private] |
Sets status to express that generators are minimized.
Definition at line 208 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().
00208 { 00209 set_generators_up_to_date(); 00210 status.set_g_minimized(); 00211 }
| void Parma_Polyhedra_Library::Polyhedron::set_generators_pending | ( | ) | [inline, private] |
Sets status to express that generators are pending.
Definition at line 219 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().
00219 { 00220 status.set_g_pending(); 00221 }
| 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 197 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::set_g_up_to_date(), and status.
Referenced by add_recycled_generators(), Polyhedron(), and set_generators_minimized().
00197 { 00198 status.set_g_up_to_date(); 00199 }
| 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 224 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::set_sat_c_up_to_date(), and status.
Referenced by Parma_Polyhedra_Library::Polyhedron::Status::ascii_load(), concatenate_assign(), obtain_sorted_constraints_with_sat_c(), obtain_sorted_generators(), obtain_sorted_generators_with_sat_g(), process_pending_constraints(), update_constraints(), and update_sat_c().
00224 { 00225 status.set_sat_c_up_to_date(); 00226 }
| 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 229 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::set_sat_g_up_to_date(), and status.
Referenced by Parma_Polyhedra_Library::Polyhedron::Status::ascii_load(), obtain_sorted_constraints(), obtain_sorted_constraints_with_sat_c(), obtain_sorted_generators_with_sat_g(), process_pending_generators(), update_generators(), and update_sat_g().
00229 { 00230 status.set_sat_g_up_to_date(); 00231 }
| 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 670 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 add_generator(), add_recycled_generators(), Parma_Polyhedra_Library::Polyhedron::Status::ascii_load(), map_space_dimensions(), operator=(), Polyhedron(), remove_higher_space_dimensions(), remove_space_dimensions(), and simplify_using_context_assign().
00670 { 00671 status.set_zero_dim_univ(); 00672 space_dim = 0; 00673 con_sys.clear(); 00674 gen_sys.clear(); 00675 }
| 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 346 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().
00346 { 00347 PPL_ASSERT(constraints_are_up_to_date()); 00348 Constraint_System cs(con_sys); 00349 if (cs.num_pending_rows() > 0) 00350 cs.unset_pending_rows(); 00351 if (has_pending_constraints() || !constraints_are_minimized()) 00352 cs.simplify(); 00353 return cs; 00354 }
| 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 84 of file simplify.cc.
References Parma_Polyhedra_Library::Linear_System::back_substitute(), Parma_Polyhedra_Library::compute_capacity(), 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, swap(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
Referenced by add_and_minimize(), and minimize().
00084 { 00085 // This method is only applied to a well-formed system `sys'. 00086 PPL_ASSERT(sys.OK(true)); 00087 PPL_ASSERT(sys.num_columns() >= 1); 00088 00089 dimension_type num_rows = sys.num_rows(); 00090 const dimension_type num_columns = sys.num_columns(); 00091 const dimension_type num_cols_sat = sat.num_columns(); 00092 00093 // Looking for the first inequality in `sys'. 00094 dimension_type num_lines_or_equalities = 0; 00095 while (num_lines_or_equalities < num_rows 00096 && sys[num_lines_or_equalities].is_line_or_equality()) 00097 ++num_lines_or_equalities; 00098 00099 // `num_saturators[i]' will contain the number of generators 00100 // that saturate the constraint `sys[i]'. 00101 if (num_rows > simplify_num_saturators_size) { 00102 delete [] simplify_num_saturators_p; 00103 simplify_num_saturators_p = 0; 00104 simplify_num_saturators_size = 0; 00105 const size_t max_size 00106 = std::numeric_limits<size_t>::max() / sizeof(dimension_type); 00107 const size_t new_size = compute_capacity(num_rows, max_size); 00108 simplify_num_saturators_p = new dimension_type[new_size]; 00109 simplify_num_saturators_size = new_size; 00110 } 00111 dimension_type* num_saturators = simplify_num_saturators_p; 00112 00113 // Computing the number of saturators for each inequality, 00114 // possibly identifying and swapping those that happen to be 00115 // equalities (see Proposition above). 00116 for (dimension_type i = num_lines_or_equalities; i < num_rows; ++i) { 00117 if (sat[i].empty()) { 00118 // The constraint `sys[i]' is saturated by all the generators. 00119 // Thus, either it is already an equality or it can be transformed 00120 // to an equality (see Proposition above). 00121 sys[i].set_is_line_or_equality(); 00122 // Note: simple normalization already holds. 00123 sys[i].sign_normalize(); 00124 // We also move it just after all the other equalities, 00125 // so that system `sys' keeps its partial sortedness. 00126 if (i != num_lines_or_equalities) { 00127 std::swap(sys[i], sys[num_lines_or_equalities]); 00128 std::swap(sat[i], sat[num_lines_or_equalities]); 00129 std::swap(num_saturators[i], num_saturators[num_lines_or_equalities]); 00130 } 00131 ++num_lines_or_equalities; 00132 // `sys' is no longer sorted. 00133 sys.set_sorted(false); 00134 } 00135 else 00136 // There exists a generator which does not saturate `sys[i]', 00137 // so that `sys[i]' is indeed an inequality. 00138 // We store the number of its saturators. 00139 num_saturators[i] = num_cols_sat - sat[i].count_ones(); 00140 } 00141 00142 // At this point, all the equalities of `sys' (included those 00143 // inequalities that we just transformed to equalities) have 00144 // indexes between 0 and `num_lines_or_equalities' - 1, 00145 // which is the property needed by method gauss(). 00146 // We can simplify the system of equalities, obtaining the rank 00147 // of `sys' as result. 00148 const dimension_type rank = sys.gauss(num_lines_or_equalities); 00149 00150 // Now the irredundant equalities of `sys' have indexes from 0 00151 // to `rank' - 1, whereas the equalities having indexes from `rank' 00152 // to `num_lines_or_equalities' - 1 are all redundant. 00153 // (The inequalities in `sys' have been left untouched.) 00154 // The rows containing equalities are not sorted. 00155 00156 if (rank < num_lines_or_equalities) { 00157 // We identified some redundant equalities. 00158 // Moving them at the bottom of `sys': 00159 // - index `redundant' runs through the redundant equalities 00160 // - index `erasing' identifies the first row that should 00161 // be erased after this loop. 00162 // Note that we exit the loop either because we have moved all 00163 // redundant equalities or because we have moved all the 00164 // inequalities. 00165 for (dimension_type redundant = rank, 00166 erasing = num_rows; 00167 redundant < num_lines_or_equalities 00168 && erasing > num_lines_or_equalities; 00169 ) { 00170 --erasing; 00171 std::swap(sys[redundant], sys[erasing]); 00172 std::swap(sat[redundant], sat[erasing]); 00173 std::swap(num_saturators[redundant], num_saturators[erasing]); 00174 sys.set_sorted(false); 00175 ++redundant; 00176 } 00177 // Adjusting the value of `num_rows' to the number of meaningful 00178 // rows of `sys': `num_lines_or_equalities' - `rank' is the number of 00179 // redundant equalities moved to the bottom of `sys', which are 00180 // no longer meaningful. 00181 num_rows -= num_lines_or_equalities - rank; 00182 // Adjusting the value of `num_lines_or_equalities'. 00183 num_lines_or_equalities = rank; 00184 } 00185 00186 // Now we use the definition of redundancy (given in the Introduction) 00187 // to remove redundant inequalities. 00188 00189 // First we check the saturation rule, which provides a necessary 00190 // condition for an inequality to be irredundant (i.e., it provides 00191 // a sufficient condition for identifying redundant inequalities). 00192 // Let 00193 // num_saturators[i] = num_sat_lines[i] + num_sat_rays_or_points[i]; 00194 // dim_lin_space = num_irred_lines; 00195 // dim_ray_space 00196 // = dim_vector_space - num_irred_equalities - dim_lin_space 00197 // = num_columns - 1 - num_lines_or_equalities - dim_lin_space; 00198 // min_sat_rays_or_points = dim_ray_space. 00199 // 00200 // An inequality saturated by less than `dim_ray_space' _rays/points_ 00201 // is redundant. Thus we have the implication 00202 // 00203 // (num_saturators[i] - num_sat_lines[i] < dim_ray_space) 00204 // ==> 00205 // redundant(sys[i]). 00206 // 00207 // Moreover, since every line saturates all inequalities, we also have 00208 // dim_lin_space = num_sat_lines[i] 00209 // so that we can rewrite the condition above as follows: 00210 // 00211 // (num_saturators[i] < num_columns - num_lines_or_equalities - 1) 00212 // ==> 00213 // redundant(sys[i]). 00214 // 00215 const dimension_type min_saturators 00216 = num_columns - num_lines_or_equalities - 1; 00217 for (dimension_type i = num_lines_or_equalities; i < num_rows; ) { 00218 if (num_saturators[i] < min_saturators) { 00219 // The inequality `sys[i]' is redundant. 00220 --num_rows; 00221 std::swap(sys[i], sys[num_rows]); 00222 std::swap(sat[i], sat[num_rows]); 00223 std::swap(num_saturators[i], num_saturators[num_rows]); 00224 sys.set_sorted(false); 00225 } 00226 else 00227 ++i; 00228 } 00229 00230 // Now we check the independence rule. 00231 for (dimension_type i = num_lines_or_equalities; i < num_rows; ) { 00232 bool redundant = false; 00233 // NOTE: in the inner loop, index `j' runs through _all_ the 00234 // inequalities and we do not test if `sat[i]' is strictly 00235 // contained into `sat[j]'. Experimentation has shown that this 00236 // is faster than having `j' only run through the indexes greater 00237 // than `i' and also doing the test `strict_subset(sat[i], 00238 // sat[k])'. 00239 for (dimension_type j = num_lines_or_equalities; j < num_rows; ) { 00240 if (i == j) 00241 // We want to compare different rows of `sys'. 00242 ++j; 00243 else { 00244 // Let us recall that each generator lies on a facet of the 00245 // polyhedron (see the Introduction). 00246 // Given two constraints `c_1' and `c_2', if there are `m' 00247 // generators lying on the hyper-plane corresponding to `c_1', 00248 // the same `m' generators lie on the hyper-plane 00249 // corresponding to `c_2', too, and there is another one lying 00250 // on the latter but not on the former, then `c_2' is more 00251 // restrictive than `c_1', i.e., `c_1' is redundant. 00252 bool strict_subset; 00253 if (subset_or_equal(sat[j], sat[i], strict_subset)) 00254 if (strict_subset) { 00255 // All the saturators of the inequality `sys[i]' are 00256 // saturators of the inequality `sys[j]' too, 00257 // and there exists at least one saturator of `sys[j]' 00258 // which is not a saturator of `sys[i]'. 00259 // It follows that inequality `sys[i]' is redundant. 00260 redundant = true; 00261 break; 00262 } 00263 else { 00264 // We have `sat[j] == sat[i]'. Hence inequalities 00265 // `sys[i]' and `sys[j]' are saturated by the same set of 00266 // generators. Then we can remove either one of the two 00267 // inequalities: we remove `sys[j]'. 00268 --num_rows; 00269 std::swap(sys[j], sys[num_rows]); 00270 std::swap(sat[j], sat[num_rows]); 00271 std::swap(num_saturators[j], num_saturators[num_rows]); 00272 sys.set_sorted(false); 00273 } 00274 else 00275 // If we reach this point then we know that `sat[i]' does 00276 // not contain (and is different from) `sat[j]', so that 00277 // `sys[i]' is not made redundant by inequality `sys[j]'. 00278 ++j; 00279 } 00280 } 00281 if (redundant) { 00282 // The inequality `sys[i]' is redundant. 00283 --num_rows; 00284 std::swap(sys[i], sys[num_rows]); 00285 std::swap(sat[i], sat[num_rows]); 00286 std::swap(num_saturators[i], num_saturators[num_rows]); 00287 sys.set_sorted(false); 00288 } 00289 else 00290 // The inequality `sys[i]' is not redundant. 00291 ++i; 00292 } 00293 00294 // Here we physically remove the redundant inequalities previously 00295 // moved to the bottom of `sys' and the corresponding `sat' rows. 00296 sys.erase_to_end(num_rows); 00297 sys.unset_pending_rows(); 00298 sat.rows_erase_to_end(num_rows); 00299 // At this point the first `num_lines_or_equalities' rows of 'sys' 00300 // represent the irredundant equalities, while the remaining rows 00301 // (i.e., those having indexes from `num_lines_or_equalities' to 00302 // `num_rows' - 1) represent the irredundant inequalities. 00303 #ifndef NDEBUG 00304 // Check if the flag is set (that of the equalities is already set). 00305 for (dimension_type i = num_lines_or_equalities; i < num_rows; ++i) 00306 PPL_ASSERT(sys[i].is_ray_or_point_or_inequality()); 00307 #endif 00308 00309 // Finally, since now the sub-system (of `sys') of the irredundant 00310 // equalities is in triangular form, we back substitute each 00311 // variables with the expression obtained considering the equalities 00312 // starting from the last one. 00313 sys.back_substitute(num_lines_or_equalities); 00314 00315 // The returned value is the number of irredundant equalities i.e., 00316 // the rank of the sub-system of `sys' containing only equalities. 00317 // (See the Introduction for definition of lineality space dimension.) 00318 return num_lines_or_equalities; 00319 }
| 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 2055 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::MIP_Problem::add_constraint(), Parma_Polyhedra_Library::MIP_Problem::add_constraints(), add_constraints(), add_recycled_constraints(), Parma_Polyhedra_Library::MIP_Problem::add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Generator_System::begin(), Parma_Polyhedra_Library::Generator::CLOSURE_POINT, con_sys, constraints_are_minimized(), constraints_are_up_to_date(), Parma_Polyhedra_Library::Bit_Row::empty(), Parma_Polyhedra_Library::Generator_System::end(), Parma_Polyhedra_Library::Constraint::EQUALITY, 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(), 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.
02055 { 02056 Polyhedron& x = *this; 02057 // Topology compatibility check. 02058 if (x.topology() != y.topology()) 02059 throw_topology_incompatible("simplify_using_context_assign(y)", "y", y); 02060 // Dimension-compatibility check. 02061 if (x.space_dim != y.space_dim) 02062 throw_dimension_incompatible("simplify_using_context_assign(y)", "y", y); 02063 02064 // Filter away the zero-dimensional case. 02065 if (x.space_dim == 0) { 02066 if (y.is_empty()) { 02067 x.set_zero_dim_univ(); 02068 return false; 02069 } 02070 else 02071 return !x.is_empty(); 02072 } 02073 02074 // If `y' is empty, the biggest enlargement for `x' is the universe. 02075 if (!y.minimize()) { 02076 Polyhedron ph(x.topology(), x.space_dim, UNIVERSE); 02077 swap(ph); 02078 return false; 02079 } 02080 02081 // If `x' is empty, the intersection is empty. 02082 if (!x.minimize()) { 02083 // Search for a constraint of `y' that is not a tautology. 02084 PPL_ASSERT(!y.has_pending_generators() && y.constraints_are_up_to_date()); 02085 for (dimension_type i = y.con_sys.num_rows(); i-- > 0; ) { 02086 const Constraint& y_con_sys_i = y.con_sys[i]; 02087 if (!y_con_sys_i.is_tautological()) { 02088 // Found: we obtain a constraint `c' contradicting the one we 02089 // found, and assign to `x' the polyhedron `ph' with `c' as 02090 // the only constraint. 02091 Polyhedron ph(x.topology(), x.space_dim, UNIVERSE); 02092 Linear_Expression le(y_con_sys_i); 02093 switch (y_con_sys_i.type()) { 02094 case Constraint::EQUALITY: 02095 ph.refine_no_check(le == 1); 02096 break; 02097 case Constraint::NONSTRICT_INEQUALITY: 02098 ph.refine_no_check(le <= -1); 02099 break; 02100 case Constraint::STRICT_INEQUALITY: 02101 ph.refine_no_check(le == 0); 02102 break; 02103 } 02104 swap(ph); 02105 PPL_ASSERT_HEAVY(OK()); 02106 return false; 02107 } 02108 } 02109 // `y' is the universe: `x' cannot be enlarged. 02110 return false; 02111 } 02112 02113 PPL_ASSERT(x.constraints_are_minimized() 02114 && !x.has_something_pending() 02115 && y.generators_are_minimized() 02116 && !y.has_something_pending()); 02117 const Constraint_System& x_cs = x.con_sys; 02118 const dimension_type x_cs_num_rows = x_cs.num_rows(); 02119 const Generator_System& y_gs = y.gen_sys; 02120 02121 // Record into `redundant_by_y' the info about which constraints of 02122 // `x' are redundant in the context `y'. Count the number of 02123 // redundancies found. 02124 std::vector<bool> redundant_by_y(x_cs_num_rows, false); 02125 dimension_type num_redundant_by_y = 0; 02126 for (dimension_type i = 0; i < x_cs_num_rows; ++i) 02127 if (y_gs.satisfied_by_all_generators(x_cs[i])) { 02128 redundant_by_y[i] = true; 02129 ++num_redundant_by_y; 02130 } 02131 02132 Constraint_System result_cs; 02133 02134 if (num_redundant_by_y < x_cs_num_rows) { 02135 // Some constraints were not identified as redundant (yet?). 02136 const Constraint_System& y_cs = y.con_sys; 02137 const dimension_type y_cs_num_rows = y_cs.num_rows(); 02138 // Compute into `z' the minimized intersection of `x' and `y'. 02139 const bool x_first = (x_cs_num_rows > y_cs_num_rows); 02140 Polyhedron z(x_first ? x : y); 02141 if (x_first) 02142 z.add_constraints(y_cs); 02143 else { 02144 // Only copy (and then recycle) the non-redundant constraints. 02145 Constraint_System tmp_cs; 02146 for (dimension_type i = 0; i < x_cs_num_rows; ++i) { 02147 if (!redundant_by_y[i]) 02148 tmp_cs.insert(x_cs[i]); 02149 } 02150 z.add_recycled_constraints(tmp_cs); 02151 } 02152 if (!z.minimize()) { 02153 // The objective function is the default, zero. 02154 // We do not care about minimization or maximization, since 02155 // we are only interested in satisfiability. 02156 MIP_Problem lp; 02157 if (x.is_necessarily_closed()) { 02158 lp.add_space_dimensions_and_embed(x.space_dim); 02159 lp.add_constraints(y_cs); 02160 } 02161 else { 02162 // KLUDGE: temporarily mark `y_cs' if it was necessarily 02163 // closed, so that we can interpret the epsilon dimension as a 02164 // standard dimension. Be careful to reset the topology of `cs' 02165 // even on exceptional execution path. 02166 const_cast<Constraint_System&>(y_cs).set_necessarily_closed(); 02167 try { 02168 lp.add_space_dimensions_and_embed(x.space_dim+1); 02169 lp.add_constraints(y_cs); 02170 const_cast<Constraint_System&>(y_cs).set_not_necessarily_closed(); 02171 } 02172 catch (...) { 02173 const_cast<Constraint_System&>(y_cs).set_not_necessarily_closed(); 02174 throw; 02175 } 02176 } 02177 // We apply the following heuristics here: constraints of `x' that 02178 // are not made redundant by `y' are added to `lp' depending on 02179 // the number of generators of `y' they rule out (the more generators 02180 // they rule out, the sooner they are added). Of course, as soon 02181 // as `lp' becomes unsatisfiable, we stop adding. 02182 std::vector<Ruled_Out_Pair> 02183 ruled_out_vec(x_cs_num_rows - num_redundant_by_y); 02184 for (dimension_type i = 0, j = 0; i < x_cs_num_rows; ++i) { 02185 if (!redundant_by_y[i]) { 02186 const Constraint& c = x_cs[i]; 02187 Topology_Adjusted_Scalar_Product_Sign sps(c); 02188 dimension_type num_ruled_out_generators = 0; 02189 for (Generator_System::const_iterator k = y_gs.begin(), 02190 y_gs_end = y_gs.end(); k != y_gs_end; ++k) { 02191 const Generator& g = *k; 02192 const int sp_sign = sps(g, c); 02193 if (x.is_necessarily_closed()) { 02194 if (g.is_line()) { 02195 // Lines must saturate the constraint. 02196 if (sp_sign != 0) 02197 goto ruled_out; 02198 } 02199 else { 02200 // `g' is either a ray, a point or a closure point. 02201 if (c.is_inequality()) { 02202 // `c' is a non-strict inequality. 02203 if (sp_sign < 0) 02204 goto ruled_out; 02205 } 02206 else 02207 // `c' is an equality. 02208 if (sp_sign != 0) 02209 goto ruled_out; 02210 } 02211 } 02212 else 02213 // The topology is not necessarily closed. 02214 switch (g.type()) { 02215 case Generator::LINE: 02216 // Lines must saturate the constraint. 02217 if (sp_sign != 0) 02218 goto ruled_out; 02219 break; 02220 case Generator::POINT: 02221 // Have to perform the special test when dealing with 02222 // a strict inequality. 02223 switch (c.type()) { 02224 case Constraint::EQUALITY: 02225 if (sp_sign != 0) 02226 goto ruled_out; 02227 break; 02228 case Constraint::NONSTRICT_INEQUALITY: 02229 if (sp_sign < 0) 02230 goto ruled_out; 02231 break; 02232 case Constraint::STRICT_INEQUALITY: 02233 if (sp_sign <= 0) 02234 goto ruled_out; 02235 break; 02236 } 02237 break; 02238 case Generator::RAY: 02239 // Intentionally fall through. 02240 case Generator::CLOSURE_POINT: 02241 if (c.is_inequality()) { 02242 // Constraint `c' is either a strict or a non-strict 02243 // inequality. 02244 if (sp_sign < 0) 02245 goto ruled_out; 02246 } 02247 else 02248 // Constraint `c' is an equality. 02249 if (sp_sign != 0) 02250 goto ruled_out; 02251 break; 02252 } 02253 02254 // If we reach this point, `g' satisfies `c'. 02255 continue; 02256 ruled_out: 02257 ++num_ruled_out_generators; 02258 } 02259 ruled_out_vec[j].constraint_index = i; 02260 ruled_out_vec[j].num_ruled_out = num_ruled_out_generators; 02261 ++j; 02262 } 02263 } 02264 std::sort(ruled_out_vec.begin(), ruled_out_vec.end(), 02265 Ruled_Out_Less_Than()); 02266 02267 for (std::vector<Ruled_Out_Pair>::const_iterator 02268 j = ruled_out_vec.begin(), rov_end = ruled_out_vec.end(); 02269 j != rov_end; 02270 ++j) { 02271 const Constraint& c = x_cs[j->constraint_index]; 02272 result_cs.insert(c); 02273 lp.add_constraint(c); 02274 MIP_Problem_Status status = lp.solve(); 02275 if (status == UNFEASIBLE_MIP_PROBLEM) { 02276 Polyhedron result_ph(x.topology(), x.space_dim, UNIVERSE); 02277 result_ph.add_constraints(result_cs); 02278 x.swap(result_ph); 02279 PPL_ASSERT_HEAVY(x.OK()); 02280 return false; 02281 } 02282 } 02283 // Cannot exit from here. 02284 PPL_ASSERT(false); 02285 } 02286 else { 02287 // Here `z' is not empty and minimized. 02288 PPL_ASSERT(z.constraints_are_minimized() 02289 && z.generators_are_minimized() 02290 && !z.has_something_pending()); 02291 const Constraint_System& z_cs = z.con_sys; 02292 const Generator_System& z_gs = z.gen_sys; 02293 const dimension_type z_gs_num_rows = z_gs.num_rows(); 02294 02295 // Compute the number of equalities in x_cs, y_cs and z_cs 02296 // (exploiting minimal form knowledge). 02297 dimension_type x_cs_num_eq = 0; 02298 while (x_cs[x_cs_num_eq].is_equality()) 02299 ++x_cs_num_eq; 02300 dimension_type y_cs_num_eq = 0; 02301 while (y_cs[y_cs_num_eq].is_equality()) 02302 ++y_cs_num_eq; 02303 dimension_type z_cs_num_eq = 0; 02304 while (z_cs[z_cs_num_eq].is_equality()) 02305 ++z_cs_num_eq; 02306 PPL_ASSERT(x_cs_num_eq <= z_cs_num_eq && y_cs_num_eq <= z_cs_num_eq); 02307 02308 // Identify non-redundant equalities. 02309 Constraint_System nonred_eq; 02310 dimension_type num_nonred_eq = 0; 02311 const dimension_type needed_nonred_eq = z_cs_num_eq - y_cs_num_eq; 02312 Linear_System eqs(x.topology()); 02313 if (needed_nonred_eq > 0) { 02314 // Populate eqs with the equalities from y. 02315 for (dimension_type i = 0; i < y_cs_num_eq; ++i) 02316 eqs.insert(y_cs[i]); 02317 // Try to find another `needed_nonred_eq' linear independent 02318 // equalities among those from x. 02319 for (dimension_type i = 0; i < x_cs_num_eq; ++i) { 02320 const Constraint& x_cs_i = x_cs[i]; 02321 if (add_to_system_and_check_independence(eqs, x_cs_i)) { 02322 // x_cs_i is linear independent. 02323 nonred_eq.insert(x_cs_i); 02324 ++num_nonred_eq; 02325 if (num_nonred_eq == needed_nonred_eq) 02326 // Already found all the needed equalities. 02327 break; 02328 } 02329 } 02330 // NOTE: if num_nonred_eq < needed_nonred_eq 02331 // then we haven't found all the needed equalities yet: 02332 // this means that some inequalities from x actually holds 02333 // as "masked" equalities in the context of y. 02334 PPL_ASSERT(eqs.num_rows() <= z_cs_num_eq); 02335 PPL_ASSERT(num_nonred_eq <= needed_nonred_eq); 02336 PPL_ASSERT(z_cs_num_eq - eqs.num_rows() 02337 == needed_nonred_eq - num_nonred_eq); 02338 } 02339 02340 // Identify non-redundant inequalities. 02341 // Avoid useless copies (no modifications are needed). 02342 std::vector<const Constraint*> p_nonred_ineq; 02343 // Fill p_nonred_ineq with (pointers to) inequalities from y_cs ... 02344 for (dimension_type i = y_cs_num_eq; i < y_cs_num_rows; ++i) 02345 p_nonred_ineq.push_back(&y_cs[i]); 02346 // ... and (pointers to) non-redundant inequalities from x_cs. 02347 for (dimension_type i = x_cs_num_eq; i < x_cs_num_rows; ++i) 02348 if (!redundant_by_y[i]) 02349 p_nonred_ineq.push_back(&x_cs[i]); 02350 02351 const dimension_type p_nonred_ineq_size = p_nonred_ineq.size(); 02352 const dimension_type y_cs_num_ineq = y_cs_num_rows - y_cs_num_eq; 02353 02354 // Compute saturation info. 02355 const dimension_type sat_num_rows = p_nonred_ineq_size; 02356 Bit_Matrix sat(sat_num_rows, z_gs_num_rows); 02357 for (dimension_type i = sat_num_rows; i-- > 0; ) { 02358 const Constraint& nonred_ineq_i = *(p_nonred_ineq[i]); 02359 Bit_Row& sat_i = sat[i]; 02360 for (dimension_type j = z_gs_num_rows; j-- > 0; ) 02361 if (Scalar_Products::sign(nonred_ineq_i, z_gs[j])) 02362 sat_i.set(j); 02363 if (sat_i.empty() && num_nonred_eq < needed_nonred_eq) { 02364 // `nonred_ineq_i' is actually masking an equality 02365 // and we are still looking for some masked inequalities. 02366 // Iteration goes downwards, so the inequality comes from x_cs. 02367 PPL_ASSERT(i >= y_cs_num_ineq); 02368 // Check if the equality is independent in eqs. 02369 Linear_Row masked_eq = Linear_Row(nonred_ineq_i); 02370 masked_eq.set_is_line_or_equality(); 02371 masked_eq.sign_normalize(); 02372 if (add_to_system_and_check_independence(eqs, masked_eq)) { 02373 // It is independent: add the _inequality_ to nonred_eq. 02374 nonred_eq.insert(nonred_ineq_i); 02375 ++num_nonred_eq; 02376 } 02377 } 02378 } 02379 // Here we have already found all the needed (masked) equalities. 02380 PPL_ASSERT(num_nonred_eq == needed_nonred_eq); 02381 02382 drop_redundant_inequalities(p_nonred_ineq, x.topology(), 02383 sat, z_cs_num_eq); 02384 02385 // Place the nonredundant (masked) equalities into result_cs. 02386 result_cs.swap(nonred_eq); 02387 // Add to result_cs the nonredundant inequalities from x_cs, 02388 // i.e., those having indices no smaller than y_cs_num_ineq. 02389 for (dimension_type i = y_cs_num_ineq; i < p_nonred_ineq_size; ++i) 02390 if (p_nonred_ineq[i]) 02391 result_cs.insert(*p_nonred_ineq[i]); 02392 } 02393 } 02394 02395 Polyhedron result_ph(x.topology(), x.space_dim, UNIVERSE); 02396 result_ph.add_recycled_constraints(result_cs); 02397 x.swap(result_ph); 02398 PPL_ASSERT_HEAVY(x.OK()); 02399 return true; 02400 }
| dimension_type Parma_Polyhedra_Library::Polyhedron::space_dimension | ( | ) | const [inline] |
Returns the dimension of the vector space enclosing *this.
Definition at line 40 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< PSET >::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(), Parma_Polyhedra_Library::NNC_Polyhedron::poly_hull_assign_if_exact(), Parma_Polyhedra_Library::C_Polyhedron::poly_hull_assign_if_exact(), and throw_dimension_incompatible().
00040 { 00041 return space_dim; 00042 }
| 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 383 of file Polyhedron.inlines.hh.
References contains().
00383 { 00384 const Polyhedron& x = *this; 00385 return x.contains(y) && !y.contains(x); 00386 }
| 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 1079 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, 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().
01079 { 01080 PPL_ASSERT(!is_necessarily_closed()); 01081 01082 // From the user perspective, the polyhedron will not change. 01083 Polyhedron& x = const_cast<Polyhedron&>(*this); 01084 01085 // We need `con_sys' (weakly) minimized and `gen_sys' up-to-date. 01086 // `minimize()' will process any pending constraints or generators. 01087 if (!minimize()) 01088 return false; 01089 01090 // If the polyhedron `*this' is zero-dimensional 01091 // at this point it must be a universe polyhedron. 01092 if (x.space_dim == 0) 01093 return true; 01094 01095 // We also need `sat_g' up-to-date. 01096 if (!sat_g_is_up_to_date()) { 01097 PPL_ASSERT(sat_c_is_up_to_date()); 01098 x.sat_g.transpose_assign(sat_c); 01099 } 01100 01101 // These Bit_Row's will be later used as masks in order to 01102 // check saturation conditions restricted to particular subsets of 01103 // the generator system. 01104 Bit_Row sat_all_but_rays; 01105 Bit_Row sat_all_but_points; 01106 Bit_Row sat_all_but_closure_points; 01107 01108 const dimension_type gs_rows = gen_sys.num_rows(); 01109 const dimension_type n_lines = gen_sys.num_lines(); 01110 for (dimension_type i = gs_rows; i-- > n_lines; ) 01111 switch (gen_sys[i].type()) { 01112 case Generator::RAY: 01113 sat_all_but_rays.set(i); 01114 break; 01115 case Generator::POINT: 01116 sat_all_but_points.set(i); 01117 break; 01118 case Generator::CLOSURE_POINT: 01119 sat_all_but_closure_points.set(i); 01120 break; 01121 default: 01122 // Found a line with index i >= n_lines. 01123 throw std::runtime_error("PPL internal error: " 01124 "strongly_minimize_constraints."); 01125 } 01126 Bit_Row sat_lines_and_rays(sat_all_but_points, sat_all_but_closure_points); 01127 Bit_Row sat_lines_and_closure_points(sat_all_but_rays, sat_all_but_points); 01128 Bit_Row sat_lines(sat_lines_and_rays, sat_lines_and_closure_points); 01129 01130 // These flags are maintained to later decide if we have to add the 01131 // eps_leq_one constraint and whether or not the constraint system 01132 // was changed. 01133 bool changed = false; 01134 bool found_eps_leq_one = false; 01135 01136 // For all the strict inequalities in `con_sys', check for 01137 // eps-redundancy and eventually move them to the bottom part of the 01138 // system. 01139 Constraint_System& cs = x.con_sys; 01140 Bit_Matrix& sat = x.sat_g; 01141 dimension_type cs_rows = cs.num_rows(); 01142 const dimension_type eps_index = cs.num_columns() - 1; 01143 for (dimension_type i = 0; i < cs_rows; ) 01144 if (cs[i].is_strict_inequality()) { 01145 // First, check if it is saturated by no closure points 01146 Bit_Row sat_ci; 01147 set_union(sat[i], sat_lines_and_closure_points, sat_ci); 01148 if (sat_ci == sat_lines) { 01149 // It is saturated by no closure points. 01150 if (!found_eps_leq_one) { 01151 // Check if it is the eps_leq_one constraint. 01152 const Constraint& c = cs[i]; 01153 bool all_zeroes = true; 01154 for (dimension_type k = eps_index; k-- > 1; ) 01155 if (c[k] != 0) { 01156 all_zeroes = false; 01157 break; 01158 } 01159 if (all_zeroes && (c[0] + c[eps_index] == 0)) { 01160 // We found the eps_leq_one constraint. 01161 found_eps_leq_one = true; 01162 // Consider next constraint. 01163 ++i; 01164 continue; 01165 } 01166 } 01167 // Here `cs[i]' is not the eps_leq_one constraint, 01168 // so it is eps-redundant. 01169 // Move it to the bottom of the constraint system, 01170 // while keeping `sat_g' consistent. 01171 --cs_rows; 01172 std::swap(cs[i], cs[cs_rows]); 01173 std::swap(sat[i], sat[cs_rows]); 01174 // The constraint system is changed. 01175 changed = true; 01176 // Continue by considering next constraint, 01177 // which is already in place due to the swap. 01178 continue; 01179 } 01180 // Now we check if there exists another strict inequality 01181 // constraint having a superset of its saturators, 01182 // when disregarding points. 01183 sat_ci.clear(); 01184 set_union(sat[i], sat_all_but_points, sat_ci); 01185 bool eps_redundant = false; 01186 for (dimension_type j = 0; j < cs_rows; ++j) 01187 if (i != j && cs[j].is_strict_inequality() 01188 && subset_or_equal(sat[j], sat_ci)) { 01189 // Constraint `cs[i]' is eps-redundant: 01190 // move it to the bottom of the constraint system, 01191 // while keeping `sat_g' consistent. 01192 --cs_rows; 01193 std::swap(cs[i], cs[cs_rows]); 01194 std::swap(sat[i], sat[cs_rows]); 01195 eps_redundant = true; 01196 // The constraint system is changed. 01197 changed = true; 01198 break; 01199 } 01200 // Continue with next constraint, which is already in place 01201 // due to the swap if we have found an eps-redundant constraint. 01202 if (!eps_redundant) 01203 ++i; 01204 } 01205 else 01206 // `cs[i]' is not a strict inequality: consider next constraint. 01207 ++i; 01208 01209 if (changed) { 01210 // If the constraint system has been changed, we have to erase 01211 // the epsilon-redundant constraints. 01212 PPL_ASSERT(cs_rows < cs.num_rows()); 01213 cs.erase_to_end(cs_rows); 01214 // The remaining constraints are not pending. 01215 cs.unset_pending_rows(); 01216 // The constraint system is no longer sorted. 01217 cs.set_sorted(false); 01218 // The generator system is no longer up-to-date. 01219 x.clear_generators_up_to_date(); 01220 01221 // If we haven't found an upper bound for the epsilon dimension, 01222 // then we have to check whether such an upper bound is implied 01223 // by the remaining constraints (exploiting the simplex algorithm). 01224 if (!found_eps_leq_one) { 01225 MIP_Problem lp; 01226 // KLUDGE: temporarily mark the constraint system as if it was 01227 // necessarily closed, so that we can interpret the epsilon 01228 // dimension as a standard dimension. Be careful to reset the 01229 // topology of `cs' even on exceptional execution path. 01230 cs.set_necessarily_closed(); 01231 try { 01232 lp.add_space_dimensions_and_embed(cs.space_dimension()); 01233 lp.add_constraints(cs); 01234 cs.set_not_necessarily_closed(); 01235 } 01236 catch (...) { 01237 cs.set_not_necessarily_closed(); 01238 throw; 01239 } 01240 // The objective function is `epsilon'. 01241 lp.set_objective_function(Variable(x.space_dim)); 01242 lp.set_optimization_mode(MAXIMIZATION); 01243 MIP_Problem_Status status = lp.solve(); 01244 PPL_ASSERT(status != UNFEASIBLE_MIP_PROBLEM); 01245 // If the epsilon dimension is actually unbounded, 01246 // then add the eps_leq_one constraint. 01247 if (status == UNBOUNDED_MIP_PROBLEM) 01248 cs.insert(Constraint::epsilon_leq_one()); 01249 } 01250 } 01251 01252 PPL_ASSERT_HEAVY(OK()); 01253 return true; 01254 }
| 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 1257 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, swap(), Parma_Polyhedra_Library::Bit_Matrix::transpose_assign(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
Referenced by minimized_generators().
01257 { 01258 PPL_ASSERT(!is_necessarily_closed()); 01259 01260 // From the user perspective, the polyhedron will not change. 01261 Polyhedron& x = const_cast<Polyhedron&>(*this); 01262 01263 // We need `gen_sys' (weakly) minimized and `con_sys' up-to-date. 01264 // `minimize()' will process any pending constraints or generators. 01265 if (!minimize()) 01266 return false; 01267 01268 // If the polyhedron `*this' is zero-dimensional 01269 // at this point it must be a universe polyhedron. 01270 if (x.space_dim == 0) 01271 return true; 01272 01273 // We also need `sat_c' up-to-date. 01274 if (!sat_c_is_up_to_date()) { 01275 PPL_ASSERT(sat_g_is_up_to_date()); 01276 x.sat_c.transpose_assign(sat_g); 01277 } 01278 01279 // This Bit_Row will have all and only the indexes 01280 // of strict inequalities set to 1. 01281 Bit_Row sat_all_but_strict_ineq; 01282 const dimension_type cs_rows = con_sys.num_rows(); 01283 const dimension_type n_equals = con_sys.num_equalities(); 01284 for (dimension_type i = cs_rows; i-- > n_equals; ) 01285 if (con_sys[i].is_strict_inequality()) 01286 sat_all_but_strict_ineq.set(i); 01287 01288 // Will record whether or not we changed the generator system. 01289 bool changed = false; 01290 01291 // For all points in the generator system, check for eps-redundancy 01292 // and eventually move them to the bottom part of the system. 01293 Generator_System& gs = const_cast<Generator_System&>(gen_sys); 01294 Bit_Matrix& sat = const_cast<Bit_Matrix&>(sat_c); 01295 dimension_type gs_rows = gs.num_rows(); 01296 const dimension_type n_lines = gs.num_lines(); 01297 const dimension_type eps_index = gs.num_columns() - 1; 01298 for (dimension_type i = n_lines; i < gs_rows; ) 01299 if (gs[i].is_point()) { 01300 // Compute the Bit_Row corresponding to the candidate point 01301 // when strict inequality constraints are ignored. 01302 Bit_Row sat_gi(sat[i], sat_all_but_strict_ineq); 01303 // Check if the candidate point is actually eps-redundant: 01304 // namely, if there exists another point that saturates 01305 // all the non-strict inequalities saturated by the candidate. 01306 bool eps_redundant = false; 01307 for (dimension_type j = n_lines; j < gs_rows; ++j) 01308 if (i != j && gs[j].is_point() && subset_or_equal(sat[j], sat_gi)) { 01309 // Point `gs[i]' is eps-redundant: 01310 // move it to the bottom of the generator system, 01311 // while keeping `sat_c' consistent. 01312 --gs_rows; 01313 std::swap(gs[i], gs[gs_rows]); 01314 std::swap(sat[i], sat[gs_rows]); 01315 eps_redundant = true; 01316 changed = true; 01317 break; 01318 } 01319 if (!eps_redundant) { 01320 // Let all point encodings have epsilon coordinate 1. 01321 Generator& gi = gs[i]; 01322 if (gi[eps_index] != gi[0]) { 01323 gi[eps_index] = gi[0]; 01324 // Enforce normalization. 01325 gi.normalize(); 01326 changed = true; 01327 } 01328 // Consider next generator. 01329 ++i; 01330 } 01331 } 01332 else 01333 // Consider next generator. 01334 ++i; 01335 01336 // If needed, erase the eps-redundant generators (also updating 01337 // `index_first_pending'). 01338 if (gs_rows < gs.num_rows()) { 01339 gs.erase_to_end(gs_rows); 01340 gs.unset_pending_rows(); 01341 } 01342 01343 if (changed) { 01344 // The generator system is no longer sorted. 01345 x.gen_sys.set_sorted(false); 01346 // The constraint system is no longer up-to-date. 01347 x.clear_constraints_up_to_date(); 01348 } 01349 01350 PPL_ASSERT_HEAVY(OK()); 01351 return true; 01352 }
| 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 100 of file Polyhedron.inlines.hh.
References con_sys, gen_sys, sat_c, sat_g, space_dim, status, throw_topology_incompatible(), and topology().
Referenced by add_recycled_generators(), add_space_dimensions(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHRZ03_widening_assign(), BHZ09_NNC_poly_hull_assign_if_exact(), concatenate_assign(), constraints(), conversion(), generators(), H79_widening_assign(), map_space_dimensions(), Parma_Polyhedra_Library::NNC_Polyhedron::operator=(), Parma_Polyhedra_Library::C_Polyhedron::operator=(), Polyhedron(), select_H79_constraints(), simplify(), simplify_using_context_assign(), strongly_minimize_constraints(), strongly_minimize_generators(), swap(), and time_elapse_assign().
00100 { 00101 if (topology() != y.topology()) 00102 throw_topology_incompatible("swap(y)", "y", y); 00103 std::swap(con_sys, y.con_sys); 00104 std::swap(gen_sys, y.gen_sys); 00105 std::swap(sat_c, y.sat_c); 00106 std::swap(sat_g, y.sat_g); 00107 std::swap(status, y.status); 00108 std::swap(space_dim, y.space_dim); 00109 }
| void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
| dimension_type | required_space_dim | |||
| ) | const [protected] |
Definition at line 2396 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed(), and space_dimension().
02397 { 02398 std::ostringstream s; 02399 s << "PPL::"; 02400 if (is_necessarily_closed()) 02401 s << "C_"; 02402 else 02403 s << "NNC_"; 02404 s << "Polyhedron::" << method << ":" << std::endl 02405 << "this->space_dimension() == " << space_dimension() 02406 << ", required space dimension == " << required_space_dim << "."; 02407 throw std::invalid_argument(s.str()); 02408 }
| void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
| const char * | var_name, | |||
| Variable | var | |||
| ) | const [protected] |
Definition at line 2379 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed(), Parma_Polyhedra_Library::Variable::space_dimension(), and space_dimension().
02381 { 02382 std::ostringstream s; 02383 s << "PPL::"; 02384 if (is_necessarily_closed()) 02385 s << "C_"; 02386 else 02387 s << "NNC_"; 02388 s << "Polyhedron::" << method << ":" << std::endl 02389 << "this->space_dimension() == " << space_dimension() << ", " 02390 << var_name << ".space_dimension() == " << var.space_dimension() << "."; 02391 throw std::invalid_argument(s.str()); 02392 }
| void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
| const char * | cgs_name, | |||
| const Congruence_System & | cgs | |||
| ) | const [protected] |
Definition at line 2372 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Congruence_System::space_dimension(), and throw_dimension_incompatible().
02374 { 02375 throw_dimension_incompatible(method, cgs_name, cgs.space_dimension()); 02376 }
| void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
| const char * | gs_name, | |||
| const Generator_System & | gs | |||
| ) | const [protected] |
Definition at line 2365 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Generator_System::space_dimension(), and throw_dimension_incompatible().
02367 { 02368 throw_dimension_incompatible(method, gs_name, gs.space_dimension()); 02369 }
| void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
| const char * | cs_name, | |||
| const Constraint_System & | cs | |||
| ) | const [protected] |
Definition at line 2358 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Constraint_System::space_dimension(), and throw_dimension_incompatible().
02360 { 02361 throw_dimension_incompatible(method, cs_name, cs.space_dimension()); 02362 }
| void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
| const char * | cg_name, | |||
| const Congruence & | cg | |||
| ) | const [protected] |
Definition at line 2351 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Congruence::space_dimension(), and throw_dimension_incompatible().
02353 { 02354 throw_dimension_incompatible(method, cg_name, cg.space_dimension()); 02355 }
| void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
| const char * | g_name, | |||
| const Generator & | g | |||
| ) | const [protected] |
Definition at line 2344 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Generator::space_dimension(), and throw_dimension_incompatible().
02346 { 02347 throw_dimension_incompatible(method, g_name, g.space_dimension()); 02348 }
| void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
| const char * | c_name, | |||
| const Constraint & | c | |||
| ) | const [protected] |
Definition at line 2337 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Constraint::space_dimension(), and throw_dimension_incompatible().
02339 { 02340 throw_dimension_incompatible(method, c_name, c.space_dimension()); 02341 }
| void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
| const char * | e_name, | |||
| const Linear_Expression & | e | |||
| ) | const [protected] |
Definition at line 2330 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and throw_dimension_incompatible().
02332 { 02333 throw_dimension_incompatible(method, e_name, e.space_dimension()); 02334 }
| void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
| const char * | ph_name, | |||
| const Polyhedron & | ph | |||
| ) | const [protected] |
Definition at line 2323 of file Polyhedron_nonpublic.cc.
References space_dimension(), and throw_dimension_incompatible().
02325 { 02326 throw_dimension_incompatible(method, ph_name, ph.space_dimension()); 02327 }
| void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
| const char * | other_name, | |||
| dimension_type | other_dim | |||
| ) | const [protected] |
Definition at line 2310 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(), affine_image(), affine_preimage(), BHRZ03_widening_assign(), bounded_affine_image(), bounded_affine_preimage(), bounds(), constrains(), contains(), expand_space_dimension(), fold_space_dimensions(), frequency(), generalized_affine_image(), generalized_affine_preimage(), H79_widening_assign(), intersection_assign(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), max_min(), poly_difference_assign(), poly_hull_assign(), Parma_Polyhedra_Library::NNC_Polyhedron::poly_hull_assign_if_exact(), Parma_Polyhedra_Library::C_Polyhedron::poly_hull_assign_if_exact(), 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().
02312 { 02313 std::ostringstream s; 02314 s << "PPL::" 02315 << (is_necessarily_closed() ? "C_" : "NNC_") 02316 << "Polyhedron::" << method << ":\n" 02317 << "this->space_dimension() == " << space_dimension() << ", " 02318 << other_name << ".space_dimension() == " << other_dim << "."; 02319 throw std::invalid_argument(s.str()); 02320 }
| void Parma_Polyhedra_Library::Polyhedron::throw_invalid_argument | ( | const char * | method, | |
| const char * | reason | |||
| ) | const [protected] |
Definition at line 2233 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().
02234 { 02235 std::ostringstream s; 02236 s << "PPL::"; 02237 if (is_necessarily_closed()) 02238 s << "C_"; 02239 else 02240 s << "NNC_"; 02241 s << "Polyhedron::" << method << ":" << std::endl 02242 << reason << "."; 02243 throw std::invalid_argument(s.str()); 02244 }
| void Parma_Polyhedra_Library::Polyhedron::throw_invalid_generator | ( | const char * | method, | |
| const char * | g_name | |||
| ) | const [protected] |
Definition at line 2426 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed().
Referenced by add_generator().
02427 { 02428 std::ostringstream s; 02429 s << "PPL::"; 02430 if (is_necessarily_closed()) 02431 s << "C_"; 02432 else 02433 s << "NNC_"; 02434 s << "Polyhedron::" << method << ":" << std::endl 02435 << "*this is an empty polyhedron and " 02436 << g_name << " is not a point."; 02437 throw std::invalid_argument(s.str()); 02438 }
| void Parma_Polyhedra_Library::Polyhedron::throw_invalid_generators | ( | const char * | method, | |
| const char * | gs_name | |||
| ) | const [protected] |
Definition at line 2441 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed().
Referenced by add_recycled_generators(), and Polyhedron().
02442 { 02443 std::ostringstream s; 02444 s << "PPL::"; 02445 if (is_necessarily_closed()) 02446 s << "C_"; 02447 else 02448 s << "NNC_"; 02449 s << "Polyhedron::" << method << ":" << std::endl 02450 << "*this is an empty polyhedron and" << std::endl 02451 << "the non-empty generator system " << gs_name << " contains no points."; 02452 throw std::invalid_argument(s.str()); 02453 }
| void Parma_Polyhedra_Library::Polyhedron::throw_runtime_error | ( | const char * | method | ) | const [protected] |
Definition at line 2221 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed().
Referenced by add_generator().
02221 { 02222 std::ostringstream s; 02223 s << "PPL::"; 02224 if (is_necessarily_closed()) 02225 s << "C_"; 02226 else 02227 s << "NNC_"; 02228 s << "Polyhedron::" << method << "." << std::endl; 02229 throw std::runtime_error(s.str()); 02230 }
| void Parma_Polyhedra_Library::Polyhedron::throw_space_dimension_overflow | ( | Topology | topol, | |
| const char * | method, | |||
| const char * | reason | |||
| ) | [static, protected] |
Definition at line 2411 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().
02413 { 02414 std::ostringstream s; 02415 s << "PPL::"; 02416 if (topol == NECESSARILY_CLOSED) 02417 s << "C_"; 02418 else 02419 s << "NNC_"; 02420 s << "Polyhedron::" << method << ":" << std::endl 02421 << reason << "."; 02422 throw std::length_error(s.str()); 02423 }
| void Parma_Polyhedra_Library::Polyhedron::throw_topology_incompatible | ( | const char * | method, | |
| const char * | gs_name, | |||
| const Generator_System & | gs | |||
| ) | const [protected] |
Definition at line 2300 of file Polyhedron_nonpublic.cc.
| void Parma_Polyhedra_Library::Polyhedron::throw_topology_incompatible | ( | const char * | method, | |
| const char * | cs_name, | |||
| const Constraint_System & | cs | |||
| ) | const [protected] |
Definition at line 2289 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed().
02291 { 02292 PPL_ASSERT(is_necessarily_closed()); 02293 std::ostringstream s; 02294 s << "PPL::C_Polyhedron::" << method << ":" << std::endl 02295 << cs_name << " contains strict inequalities."; 02296 throw std::invalid_argument(s.str()); 02297 }
| void Parma_Polyhedra_Library::Polyhedron::throw_topology_incompatible | ( | const char * | method, | |
| const char * | g_name, | |||
| const Generator & | g | |||
| ) | const [protected] |
Definition at line 2278 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed().
02280 { 02281 PPL_ASSERT(is_necessarily_closed()); 02282 std::ostringstream s; 02283 s << "PPL::C_Polyhedron::" << method << ":" << std::endl 02284 << g_name << " is a closure point."; 02285 throw std::invalid_argument(s.str()); 02286 }
| void Parma_Polyhedra_Library::Polyhedron::throw_topology_incompatible | ( | const char * | method, | |
| const char * | c_name, | |||
| const Constraint & | c | |||
| ) | const [protected] |
Definition at line 2267 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed().
02269 { 02270 PPL_ASSERT(is_necessarily_closed()); 02271 std::ostringstream s; 02272 s << "PPL::C_Polyhedron::" << method << ":" << std::endl 02273 << c_name << " is a strict inequality."; 02274 throw std::invalid_argument(s.str()); 02275 }
| void Parma_Polyhedra_Library::Polyhedron::throw_topology_incompatible | ( | const char * | method, | |
| const char * | ph_name, | |||
| const Polyhedron & | ph | |||
| ) | const [protected] |
Definition at line 2247 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed().
Referenced by add_constraint(), add_generator(), add_recycled_constraints(), add_recycled_generators(), BHRZ03_widening_assign(), concatenate_assign(), contains(), H79_widening_assign(), intersection_assign(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), poly_difference_assign(), poly_hull_assign(), Polyhedron(), simplify_using_context_assign(), swap(), and time_elapse_assign().
02249 { 02250 std::ostringstream s; 02251 s << "PPL::"; 02252 if (is_necessarily_closed()) 02253 s << "C_"; 02254 else 02255 s << "NNC_"; 02256 s << "Polyhedron::" << method << ":" << std::endl 02257 << ph_name << " is a "; 02258 if (ph.is_necessarily_closed()) 02259 s << "C_"; 02260 else 02261 s << "NNC_"; 02262 s << "Polyhedron." << std::endl; 02263 throw std::invalid_argument(s.str()); 02264 }
| 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 3341 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, 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().
03341 { 03342 Polyhedron& x = *this; 03343 // Topology compatibility check. 03344 if (x.topology() != y.topology()) 03345 throw_topology_incompatible("time_elapse_assign(y)", "y", y); 03346 // Dimension-compatibility checks. 03347 if (x.space_dim != y.space_dim) 03348 throw_dimension_incompatible("time_elapse_assign(y)", "y", y); 03349 03350 // Dealing with the zero-dimensional case. 03351 if (x.space_dim == 0) { 03352 if (y.marked_empty()) 03353 x.set_empty(); 03354 return; 03355 } 03356 03357 // If either one of `x' or `y' is empty, the result is empty too. 03358 if (x.marked_empty() || y.marked_empty() 03359 || (x.has_pending_constraints() && !x.process_pending_constraints()) 03360 || (!x.generators_are_up_to_date() && !x.update_generators()) 03361 || (y.has_pending_constraints() && !y.process_pending_constraints()) 03362 || (!y.generators_are_up_to_date() && !y.update_generators())) { 03363 x.set_empty(); 03364 return; 03365 } 03366 03367 // At this point both generator systems are up-to-date, 03368 // possibly containing pending generators. 03369 Generator_System gs = y.gen_sys; 03370 dimension_type gs_num_rows = gs.num_rows(); 03371 03372 if (!x.is_necessarily_closed()) 03373 // `x' and `y' are NNC polyhedra. 03374 for (dimension_type i = gs_num_rows; i-- > 0; ) 03375 switch (gs[i].type()) { 03376 case Generator::POINT: 03377 // The points of `gs' can be erased, 03378 // since their role can be played by closure points. 03379 --gs_num_rows; 03380 std::swap(gs[i], gs[gs_num_rows]); 03381 break; 03382 case Generator::CLOSURE_POINT: 03383 { 03384 Generator& cp = gs[i]; 03385 // If it is the origin, erase it. 03386 if (cp.all_homogeneous_terms_are_zero()) { 03387 --gs_num_rows; 03388 std::swap(cp, gs[gs_num_rows]); 03389 } 03390 // Otherwise, transform the closure point into a ray. 03391 else { 03392 cp[0] = 0; 03393 // Enforce normalization. 03394 cp.normalize(); 03395 } 03396 } 03397 break; 03398 default: 03399 // For rays and lines, nothing to be done. 03400 break; 03401 } 03402 else 03403 // `x' and `y' are C polyhedra. 03404 for (dimension_type i = gs_num_rows; i-- > 0; ) 03405 switch (gs[i].type()) { 03406 case Generator::POINT: 03407 { 03408 Generator& p = gs[i]; 03409 // If it is the origin, erase it. 03410 if (p.all_homogeneous_terms_are_zero()) { 03411 --gs_num_rows; 03412 std::swap(p, gs[gs_num_rows]); 03413 } 03414 // Otherwise, transform the point into a ray. 03415 else { 03416 p[0] = 0; 03417 // Enforce normalization. 03418 p.normalize(); 03419 } 03420 } 03421 break; 03422 default: 03423 // For rays and lines, nothing to be done. 03424 break; 03425 } 03426 // If it was present, erase the origin point or closure point, 03427 // which cannot be transformed into a valid ray or line. 03428 // For NNC polyhedra, also erase all the points of `gs', 03429 // whose role can be played by the closure points. 03430 // These have been previously moved to the end of `gs'. 03431 gs.erase_to_end(gs_num_rows); 03432 gs.unset_pending_rows(); 03433 03434 // `gs' may now have no rows. 03435 // Namely, this happens when `y' was the singleton polyhedron 03436 // having the origin as the one and only point. 03437 // In such a case, the resulting polyhedron is equal to `x'. 03438 if (gs_num_rows == 0) 03439 return; 03440 03441 // If the polyhedron can have something pending, we add `gs' 03442 // to `gen_sys' as pending rows 03443 if (x.can_have_something_pending()) { 03444 x.gen_sys.add_pending_rows(gs); 03445 x.set_generators_pending(); 03446 } 03447 // Otherwise, the two systems are merged. 03448 // `Linear_System::merge_rows_assign()' requires both systems to be sorted. 03449 else { 03450 if (!x.gen_sys.is_sorted()) 03451 x.gen_sys.sort_rows(); 03452 gs.sort_rows(); 03453 x.gen_sys.merge_rows_assign(gs); 03454 // Only the system of generators is up-to-date. 03455 x.clear_constraints_up_to_date(); 03456 x.clear_generators_minimized(); 03457 } 03458 PPL_ASSERT_HEAVY(x.OK(true) && y.OK(true)); 03459 }
| void Parma_Polyhedra_Library::Polyhedron::topological_closure_assign | ( | ) |
Assigns to *this its topological closure.
Definition at line 3549 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(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
03549 { 03550 // Necessarily closed polyhedra are trivially closed. 03551 if (is_necessarily_closed()) 03552 return; 03553 // Any empty or zero-dimensional polyhedron is closed. 03554 if (marked_empty() || space_dim == 0) 03555 return; 03556 03557 // The computation can be done using constraints or generators. 03558 // If we use constraints, we will change them, so that having pending 03559 // constraints would be useless. If we use generators, we add generators, 03560 // so that having pending generators still makes sense. 03561 03562 // Process any pending constraints. 03563 if (has_pending_constraints() && !process_pending_constraints()) 03564 return; 03565 03566 // Use constraints only if they are available and 03567 // there are no pending generators. 03568 if (!has_pending_generators() && constraints_are_up_to_date()) { 03569 const dimension_type eps_index = space_dim + 1; 03570 bool changed = false; 03571 // Transform all strict inequalities into non-strict ones. 03572 for (dimension_type i = con_sys.num_rows(); i-- > 0; ) { 03573 Constraint& c = con_sys[i]; 03574 if (c[eps_index] < 0 && !c.is_tautological()) { 03575 c[eps_index] = 0; 03576 // Enforce normalization. 03577 c.normalize(); 03578 changed = true; 03579 } 03580 } 03581 if (changed) { 03582 con_sys.insert(Constraint::epsilon_leq_one()); 03583 con_sys.set_sorted(false); 03584 // After changing the system of constraints, the generators 03585 // are no longer up-to-date and the constraints are no longer 03586 // minimized. 03587 clear_generators_up_to_date(); 03588 clear_constraints_minimized(); 03589 } 03590 } 03591 else { 03592 // Here we use generators, possibly keeping constraints. 03593 PPL_ASSERT(generators_are_up_to_date()); 03594 // Add the corresponding point to each closure point. 03595 gen_sys.add_corresponding_points(); 03596 if (can_have_something_pending()) 03597 set_generators_pending(); 03598 else { 03599 // We cannot have pending generators; this also implies 03600 // that generators may have lost their sortedness. 03601 gen_sys.unset_pending_rows(); 03602 gen_sys.set_sorted(false); 03603 // Constraints are not up-to-date and generators are not minimized. 03604 clear_constraints_up_to_date(); 03605 clear_generators_minimized(); 03606 } 03607 } 03608 PPL_ASSERT_HEAVY(OK()); 03609 }
| Topology Parma_Polyhedra_Library::Polyhedron::topology | ( | ) | const [inline, private] |
Returns the topological kind of the polyhedron.
Definition at line 62 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_space_dimensions_and_embed(), add_space_dimensions_and_project(), BFT00_poly_hull_assign_if_exact(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHRZ03_widening_assign(), BHZ09_poly_hull_assign_if_exact(), concatenate_assign(), constraints(), contains(), expand_space_dimension(), generators(), H79_widening_assign(), intersection_assign(), is_included_in(), map_space_dimensions(), OK(), operator=(), poly_difference_assign(), poly_hull_assign(), Polyhedron(), quick_equivalence_test(), select_CH78_constraints(), select_H79_constraints(), simplify_using_context_assign(), swap(), and time_elapse_assign().
00062 { 00063 // We can check either one of the two matrices. 00064 // (`con_sys' is slightly better, since it is placed at offset 0.) 00065 return con_sys.topology(); 00066 }
| memory_size_type Parma_Polyhedra_Library::Polyhedron::total_memory_in_bytes | ( | ) | const [inline] |
Returns the total size in bytes of the memory occupied by *this.
Definition at line 35 of file Polyhedron.inlines.hh.
References external_memory_in_bytes().
00035 { 00036 return sizeof(*this) + external_memory_in_bytes(); 00037 }
| void Parma_Polyhedra_Library::Polyhedron::unconstrain | ( | const Variables_Set & | vars | ) |
Computes the cylindrification of *this with respect to the set of space dimensions vars, assigning the result to *this.
| vars | 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 vars. |
Definition at line 1859 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, Parma_Polyhedra_Library::Variables_Set::space_dimension(), throw_dimension_incompatible(), and update_generators().
01859 { 01860 // The cylindrification wrt no dimensions is a no-op. 01861 // This case also captures the only legal cylindrification 01862 // of a polyhedron in a 0-dim space. 01863 if (vars.empty()) 01864 return; 01865 01866 // Dimension-compatibility check. 01867 const dimension_type min_space_dim = vars.space_dimension(); 01868 if (space_dim < min_space_dim) 01869 throw_dimension_incompatible("unconstrain(vs)", min_space_dim); 01870 01871 // Do something only if the polyhedron is non-empty. 01872 if (marked_empty() 01873 || (has_pending_constraints() && !process_pending_constraints()) 01874 || (!generators_are_up_to_date() && !update_generators())) 01875 // Empty: do nothing. 01876 return; 01877 01878 PPL_ASSERT(generators_are_up_to_date()); 01879 // Since `gen_sys' is not empty, the topology and space dimension 01880 // of the inserted generators are automatically adjusted. 01881 Variables_Set::const_iterator vsi = vars.begin(); 01882 Variables_Set::const_iterator vsi_end = vars.end(); 01883 if (can_have_something_pending()) { 01884 for ( ; vsi != vsi_end; ++vsi) 01885 gen_sys.insert_pending(Generator::line(Variable(*vsi))); 01886 set_generators_pending(); 01887 } 01888 else { 01889 for ( ; vsi != vsi_end; ++vsi) 01890 gen_sys.insert(Generator::line(Variable(*vsi))); 01891 // After adding the new generators, 01892 // constraints are no longer up-to-date. 01893 clear_generators_minimized(); 01894 clear_constraints_up_to_date(); 01895 } 01896 PPL_ASSERT_HEAVY(OK(true)); 01897 }
| 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 1829 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, Parma_Polyhedra_Library::Variable::space_dimension(), throw_dimension_incompatible(), and update_generators().
Referenced by bounded_affine_preimage(), and generalized_affine_preimage().
01829 { 01830 // Dimension-compatibility check. 01831 if (space_dim < var.space_dimension()) 01832 throw_dimension_incompatible("unconstrain(var)", var.space_dimension()); 01833 01834 // Do something only if the polyhedron is non-empty. 01835 if (marked_empty() 01836 || (has_pending_constraints() && !process_pending_constraints()) 01837 || (!generators_are_up_to_date() && !update_generators())) 01838 // Empty: do nothing. 01839 return; 01840 01841 PPL_ASSERT(generators_are_up_to_date()); 01842 // Since `gen_sys' is not empty, the topology and space dimension 01843 // of the inserted generator are automatically adjusted. 01844 if (can_have_something_pending()) { 01845 gen_sys.insert_pending(Generator::line(var)); 01846 set_generators_pending(); 01847 } 01848 else { 01849 gen_sys.insert(Generator::line(var)); 01850 // After adding the new generator, 01851 // constraints are no longer up-to-date. 01852 clear_generators_minimized(); 01853 clear_constraints_up_to_date(); 01854 } 01855 PPL_ASSERT_HEAVY(OK(true)); 01856 }
| 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 805 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(), drop_some_non_integer_points(), H79_widening_assign(), intersection_assign(), is_included_in(), minimize(), refine_no_check(), refine_with_constraints(), and relation_with().
00805 { 00806 PPL_ASSERT(space_dim > 0); 00807 PPL_ASSERT(!marked_empty()); 00808 PPL_ASSERT(generators_are_up_to_date()); 00809 // We assume the polyhedron has no pending constraints or generators. 00810 PPL_ASSERT(!has_something_pending()); 00811 00812 Polyhedron& x = const_cast<Polyhedron&>(*this); 00813 minimize(false, x.gen_sys, x.con_sys, x.sat_c); 00814 // `sat_c' is the only saturation matrix up-to-date. 00815 x.set_sat_c_up_to_date(); 00816 x.clear_sat_g_up_to_date(); 00817 // The system of constraints and the system of generators 00818 // are minimized. 00819 x.set_constraints_minimized(); 00820 x.set_generators_minimized(); 00821 }
| 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.The resulting system of generators is only partially sorted: the lines are in the upper part of the matrix, while rays and points are in the lower part. It is illegal to call this method when the Status field already declares the polyhedron to be empty.
Definition at line 824 of file Polyhedron_nonpublic.cc.
References clear_sat_c_up_to_date(), con_sys, constraints_are_up_to_date(), 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(), frequency(), generators(), is_bounded(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), map_space_dimensions(), max_min(), minimize(), poly_hull_assign(), relation_with(), remove_higher_space_dimensions(), remove_space_dimensions(), select_H79_constraints(), time_elapse_assign(), and unconstrain().
00824 { 00825 PPL_ASSERT(space_dim > 0); 00826 PPL_ASSERT(!marked_empty()); 00827 PPL_ASSERT(constraints_are_up_to_date()); 00828 // We assume the polyhedron has no pending constraints or generators. 00829 PPL_ASSERT(!has_something_pending()); 00830 00831 Polyhedron& x = const_cast<Polyhedron&>(*this); 00832 // If the system of constraints is not consistent the 00833 // polyhedron is empty. 00834 const bool empty = minimize(true, x.con_sys, x.gen_sys, x.sat_g); 00835 if (empty) 00836 x.set_empty(); 00837 else { 00838 // `sat_g' is the only saturation matrix up-to-date. 00839 x.set_sat_g_up_to_date(); 00840 x.clear_sat_c_up_to_date(); 00841 // The system of constraints and the system of generators 00842 // are minimized. 00843 x.set_constraints_minimized(); 00844 x.set_generators_minimized(); 00845 } 00846 return !empty; 00847 }
| 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 850 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().
00850 { 00851 PPL_ASSERT(constraints_are_minimized()); 00852 PPL_ASSERT(generators_are_minimized()); 00853 PPL_ASSERT(!sat_c_is_up_to_date()); 00854 00855 // We only consider non-pending rows. 00856 const dimension_type csr = con_sys.first_pending_row(); 00857 const dimension_type gsr = gen_sys.first_pending_row(); 00858 Polyhedron& x = const_cast<Polyhedron&>(*this); 00859 00860 // The columns of `sat_c' represent the constraints and 00861 // its rows represent the generators: resize accordingly. 00862 x.sat_c.resize(gsr, csr); 00863 for (dimension_type i = gsr; i-- > 0; ) 00864 for (dimension_type j = csr; j-- > 0; ) { 00865 const int sp_sign = Scalar_Products::sign(con_sys[j], gen_sys[i]); 00866 // The negativity of this scalar product would mean 00867 // that the generator `gen_sys[i]' violates the constraint 00868 // `con_sys[j]' and it is not possible because both generators 00869 // and constraints are up-to-date. 00870 PPL_ASSERT(sp_sign >= 0); 00871 if (sp_sign > 0) 00872 // `gen_sys[i]' satisfies (without saturate) `con_sys[j]'. 00873 x.sat_c[i].set(j); 00874 else 00875 // `gen_sys[i]' saturates `con_sys[j]'. 00876 x.sat_c[i].clear(j); 00877 } 00878 x.set_sat_c_up_to_date(); 00879 }
| 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 882 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(), BHZ09_C_poly_hull_assign_if_exact(), BHZ09_NNC_poly_hull_assign_if_exact(), obtain_sorted_generators_with_sat_g(), and select_H79_constraints().
00882 { 00883 PPL_ASSERT(constraints_are_minimized()); 00884 PPL_ASSERT(generators_are_minimized()); 00885 PPL_ASSERT(!sat_g_is_up_to_date()); 00886 00887 // We only consider non-pending rows. 00888 const dimension_type csr = con_sys.first_pending_row(); 00889 const dimension_type gsr = gen_sys.first_pending_row(); 00890 Polyhedron& x = const_cast<Polyhedron&>(*this); 00891 00892 // The columns of `sat_g' represent generators and its 00893 // rows represent the constraints: resize accordingly. 00894 x.sat_g.resize(csr, gsr); 00895 for (dimension_type i = csr; i-- > 0; ) 00896 for (dimension_type j = gsr; j-- > 0; ) { 00897 const int sp_sign = Scalar_Products::sign(con_sys[i], gen_sys[j]); 00898 // The negativity of this scalar product would mean 00899 // that the generator `gen_sys[j]' violates the constraint 00900 // `con_sys[i]' and it is not possible because both generators 00901 // and constraints are up-to-date. 00902 PPL_ASSERT(sp_sign >= 0); 00903 if (sp_sign > 0) 00904 // `gen_sys[j]' satisfies (without saturate) `con_sys[i]'. 00905 x.sat_g[i].set(j); 00906 else 00907 // `gen_sys[j]' saturates `con_sys[i]'. 00908 x.sat_g[i].clear(j); 00909 } 00910 x.set_sat_g_up_to_date(); 00911 }
| void Parma_Polyhedra_Library::Polyhedron::upper_bound_assign | ( | const Polyhedron & | y | ) | [inline] |
Same as poly_hull_assign(y).
Definition at line 81 of file Polyhedron.inlines.hh.
References poly_hull_assign().
Referenced by BFT00_poly_hull_assign_if_exact(), and BHZ09_poly_hull_assign_if_exact().
00081 { 00082 poly_hull_assign(y); 00083 }
| void Parma_Polyhedra_Library::Polyhedron::widening_assign | ( | const Polyhedron & | y, | |
| unsigned * | tp = 0 | |||
| ) | [inline] |
Same as H79_widening_assign(y, tp).
Definition at line 91 of file Polyhedron.inlines.hh.
References H79_widening_assign().
00091 { 00092 H79_widening_assign(y, tp); 00093 }
| void Parma_Polyhedra_Library::Polyhedron::wrap_assign | ( | const Variables_Set & | vars, | |
| Bounded_Integer_Type_Width | w, | |||
| Bounded_Integer_Type_Representation | r, | |||
| Bounded_Integer_Type_Overflow | o, | |||
| const Constraint_System * | pcs = 0, |
|||
| unsigned | complexity_threshold = 16, |
|||
| bool | wrap_individually = true | |||
| ) |
Wraps the specified dimensions of the vector space.
| vars | The set of Variable objects corresponding to the space dimensions to be wrapped. | |
| w | The width of the bounded integer type corresponding to all the dimensions to be wrapped. | |
| r | The representation of the bounded integer type corresponding to all the dimensions to be wrapped. | |
| o | The overflow behavior of the bounded integer type corresponding to all the dimensions to be wrapped. | |
| pcs | Possibly null pointer to a constraint system whose variables are contained in vars. If *pcs depends on variables not in vars, the behavior is undefined. When non-null, the pointed-to constraint system is assumed to represent the conditional or looping construct guard with respect to which wrapping is performed. Since wrapping requires the computation of upper bounds and due to non-distributivity of constraint refinement over upper bounds, passing a constraint system in this way can be more precise than refining the result of the wrapping operation with the constraints in *pcs. | |
| complexity_threshold | A precision parameter of the wrapping operator: higher values result in possibly improved precision. | |
| wrap_individually | true if the dimensions should be wrapped individually (something that results in much greater efficiency to the detriment of precision). |
| std::invalid_argument | Thrown if *pcs is dimension-incompatible with vars, or if *this is dimension-incompatible vars or with *pcs. |
Definition at line 3756 of file Polyhedron_public.cc.
References is_necessarily_closed().
03762 { 03763 if (is_necessarily_closed()) 03764 Implementation::wrap_assign(static_cast<C_Polyhedron&>(*this), 03765 vars, w, r, o, pcs, 03766 complexity_threshold, wrap_individually, 03767 "C_Polyhedron"); 03768 else 03769 Implementation::wrap_assign(static_cast<NNC_Polyhedron&>(*this), 03770 vars, w, r, o, pcs, 03771 complexity_threshold, wrap_individually, 03772 "NNC_Polyhedron"); 03773 }
| 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 378 of file Polyhedron.inlines.hh.
| 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 3777 of file Polyhedron_public.cc.
References is_empty(), and minimized_constraints().
| bool operator== | ( | const Polyhedron & | x, | |
| const Polyhedron & | y | |||
| ) | [friend] |
friend class Parma_Polyhedra_Library::BD_Shape [friend] |
Definition at line 2495 of file Polyhedron.defs.hh.
friend class Parma_Polyhedra_Library::BHRZ03_Certificate [friend] |
Definition at line 2498 of file Polyhedron.defs.hh.
friend class Parma_Polyhedra_Library::Box [friend] |
Definition at line 2494 of file Polyhedron.defs.hh.
friend class Parma_Polyhedra_Library::Grid [friend] |
Definition at line 2497 of file Polyhedron.defs.hh.
friend class Parma_Polyhedra_Library::H79_Certificate [friend] |
Definition at line 2499 of file Polyhedron.defs.hh.
| bool Parma_Polyhedra_Library::Interfaces::is_necessarily_closed_for_interfaces | ( | const Polyhedron & | ) | [friend] |
friend class Parma_Polyhedra_Library::Octagonal_Shape [friend] |
Definition at line 2496 of file Polyhedron.defs.hh.
| 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 52 of file algorithms.hh.
References Parma_Polyhedra_Library::Powerset< Parma_Polyhedra_Library::Determinate< PSET > >::begin(), contains(), and Parma_Polyhedra_Library::Powerset< Parma_Polyhedra_Library::Determinate< PSET > >::end().
00052 { 00053 PH phull = p; 00054 NNC_Polyhedron nnc_p(p); 00055 phull.poly_hull_assign(q); 00056 std::pair<PH, Pointset_Powerset<NNC_Polyhedron> > 00057 partition = linear_partition(q, phull); 00058 const Pointset_Powerset<NNC_Polyhedron>& s = partition.second; 00059 typedef Pointset_Powerset<NNC_Polyhedron>::const_iterator iter; 00060 for (iter i = s.begin(), s_end = s.end(); i != s_end; ++i) 00061 // The polyhedral hull is exact if and only if all the elements 00062 // of the partition of the polyhedral hull of `p' and `q' with 00063 // respect to `q' are included in `p' 00064 if (!nnc_p.contains(i->pointset())) 00065 return false; 00066 p = phull; 00067 return true; 00068 }
| void swap | ( | Parma_Polyhedra_Library::Polyhedron & | x, | |
| Parma_Polyhedra_Library::Polyhedron & | y | |||
| ) | [related] |
Specializes std::swap.
Definition at line 416 of file Polyhedron.inlines.hh.
References swap().
00417 { 00418 x.swap(y); 00419 }
The system of constraints.
Definition at line 1917 of file Polyhedron.defs.hh.
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(), BFT00_poly_hull_assign_if_exact(), BHRZ03_combining_constraints(), BHZ09_C_poly_hull_assign_if_exact(), BHZ09_NNC_poly_hull_assign_if_exact(), bounded_affine_preimage(), concatenate_assign(), constrains(), constraints(), drop_some_non_integer_points(), external_memory_in_bytes(), H79_widening_assign(), intersection_assign(), 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=(), 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 1920 of file Polyhedron.defs.hh.
Referenced by add_generator(), add_recycled_generators(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_image(), affine_preimage(), ascii_dump(), BFT00_poly_hull_assign_if_exact(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHZ09_C_poly_hull_assign_if_exact(), BHZ09_NNC_poly_hull_assign_if_exact(), bounded_affine_preimage(), bounds(), concatenate_assign(), constrains(), contains_integer_point(), external_memory_in_bytes(), frequency(), generalized_affine_image(), generators(), 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(), 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 1923 of file Polyhedron.defs.hh.
Referenced by add_space_dimensions_and_embed(), add_space_dimensions_and_project(), ascii_dump(), 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=(), 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 1926 of file Polyhedron.defs.hh.
Referenced by add_space_dimensions_and_embed(), add_space_dimensions_and_project(), ascii_dump(), BHZ09_C_poly_hull_assign_if_exact(), BHZ09_NNC_poly_hull_assign_if_exact(), 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=(), 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().
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 2484 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 2492 of file Polyhedron.defs.hh.
Referenced by finalize(), initialize(), and simplify().
The number of dimensions of the enclosing vector space.
Definition at line 1936 of file Polyhedron.defs.hh.
Referenced by add_congruence(), add_congruences(), add_constraint(), add_generator(), add_recycled_constraints(), add_recycled_generators(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_dimension(), BFT00_poly_hull_assign_if_exact(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHRZ03_widening_assign(), BHZ09_C_poly_hull_assign_if_exact(), BHZ09_NNC_poly_hull_assign_if_exact(), BHZ09_poly_hull_assign_if_exact(), bounds(), Parma_Polyhedra_Library::BHRZ03_Certificate::compare(), concatenate_assign(), constrains(), constraints(), contains(), contains_integer_point(), drop_some_non_integer_points(), expand_space_dimension(), fold_space_dimensions(), generators(), grid_generators(), H79_widening_assign(), intersection_assign(), 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(), 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(), unconstrain(), update_constraints(), and update_generators().
The status flags to keep track of the polyhedron's internal state.
Definition at line 1933 of file Polyhedron.defs.hh.
Referenced by add_recycled_constraints(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), ascii_dump(), 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().
1.6.3