#include <Polyhedron.defs.hh>
Exception Throwers | |
void | throw_runtime_error (const char *method) const |
void | throw_invalid_argument (const char *method, const char *reason) const |
void | throw_topology_incompatible (const char *method, const char *ph_name, const Polyhedron &ph) const |
void | throw_topology_incompatible (const char *method, const char *c_name, const Constraint &c) const |
void | throw_topology_incompatible (const char *method, const char *g_name, const Generator &g) const |
void | throw_topology_incompatible (const char *method, const char *cs_name, const Constraint_System &cs) const |
void | throw_topology_incompatible (const char *method, const char *gs_name, const Generator_System &gs) const |
void | throw_dimension_incompatible (const char *method, const char *other_name, dimension_type other_dim) const |
void | throw_dimension_incompatible (const char *method, const char *ph_name, const Polyhedron &ph) const |
void | throw_dimension_incompatible (const char *method, const char *e_name, const Linear_Expression &e) const |
void | throw_dimension_incompatible (const char *method, const char *c_name, const Constraint &c) const |
void | throw_dimension_incompatible (const char *method, const char *g_name, const Generator &g) const |
void | throw_dimension_incompatible (const char *method, const char *cg_name, const Congruence &cg) const |
void | throw_dimension_incompatible (const char *method, const char *cs_name, const Constraint_System &cs) const |
void | throw_dimension_incompatible (const char *method, const char *gs_name, const Generator_System &gs) const |
void | throw_dimension_incompatible (const char *method, const char *cgs_name, const Congruence_System &cgs) const |
void | throw_dimension_incompatible (const char *method, const char *var_name, const Variable var) const |
void | throw_dimension_incompatible (const char *method, dimension_type required_space_dim) const |
void | throw_invalid_generator (const char *method, const char *g_name) const |
void | throw_invalid_generators (const char *method, const char *gs_name) const |
static void | throw_space_dimension_overflow (Topology topol, const char *method, const char *reason) |
Public Member Functions | |
Member Functions that Do Not Modify the Polyhedron | |
dimension_type | space_dimension () const |
Returns the dimension of the vector space enclosing *this . | |
dimension_type | affine_dimension () const |
Returns ![]() *this is empty; otherwise, returns the affine dimension of *this . | |
const Constraint_System & | constraints () const |
Returns the system of constraints. | |
const Constraint_System & | minimized_constraints () const |
Returns the system of constraints, with no redundant constraint. | |
const Generator_System & | generators () const |
Returns the system of generators. | |
const Generator_System & | minimized_generators () const |
Returns the system of generators, with no redundant generator. | |
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 . | |
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_bounded () const |
Returns true if and only if *this is a bounded polyhedron. | |
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 &point) 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 &point) const |
Returns true if and only if *this is not empty and expr is bounded from below in *this , in which case the infimum value and a point where expr reaches it are computed. | |
bool | contains (const Polyhedron &y) const |
Returns true if and only if *this contains y . | |
bool | strictly_contains (const Polyhedron &y) const |
Returns true if and only if *this strictly contains y . | |
template<typename Box> | |
void | shrink_bounding_box (Box &box, Complexity_Class complexity=ANY_COMPLEXITY) const |
Uses *this to shrink a generic, interval-based bounding box. Assigns to box the intersection of box with the smallest bounding box containing *this . | |
bool | OK (bool check_not_empty=false) const |
Checks if all the invariants are satisfied. | |
Space Dimension Preserving Member Functions that May Modify the Polyhedron | |
void | add_constraint (const Constraint &c) |
Adds a copy of constraint c to the system of constraints of *this (without minimizing the result). | |
bool | add_constraint_and_minimize (const Constraint &c) |
Adds a copy of constraint c to the system of constraints of *this , minimizing the result. | |
void | add_generator (const Generator &g) |
Adds a copy of generator g to the system of generators of *this (without minimizing the result). | |
bool | add_generator_and_minimize (const Generator &g) |
Adds a copy of generator g to the system of generators of *this , minimizing the result. | |
void | add_congruence (const Congruence &cg) |
Adds a copy of congruence cg to the system of congruences of this (without minimizing the result). | |
void | add_constraints (const Constraint_System &cs) |
Adds a copy of the constraints in cs to the system of constraints of *this (without minimizing the result). | |
void | add_recycled_constraints (Constraint_System &cs) |
Adds the constraints in cs to the system of constraints of *this (without minimizing the result). | |
bool | add_constraints_and_minimize (const Constraint_System &cs) |
Adds a copy of the constraints in cs to the system of constraints of *this , minimizing the result. | |
bool | add_recycled_constraints_and_minimize (Constraint_System &cs) |
Adds the constraints in cs to the system of constraints of *this , minimizing the result. | |
void | add_generators (const Generator_System &gs) |
Adds a copy of the generators in gs to the system of generators of *this (without minimizing the result). | |
void | add_recycled_generators (Generator_System &gs) |
Adds the generators in gs to the system of generators of *this (without minimizing the result). | |
bool | add_generators_and_minimize (const Generator_System &gs) |
Adds a copy of the generators in gs to the system of generators of *this , minimizing the result. | |
bool | add_recycled_generators_and_minimize (Generator_System &gs) |
Adds the generators in gs to the system of generators of *this , minimizing the result. | |
void | add_congruences (const Congruence_System &cgs) |
Adds to *this constraints equivalent to the congruences in cgs (without minimizing the result). | |
void | intersection_assign (const Polyhedron &y) |
Assigns to *this the intersection of *this and y . The result is not guaranteed to be minimized. | |
bool | intersection_assign_and_minimize (const Polyhedron &y) |
Assigns to *this the intersection of *this and y , minimizing the result. | |
void | poly_hull_assign (const Polyhedron &y) |
Assigns to *this the poly-hull of *this and y . The result is not guaranteed to be minimized. | |
bool | poly_hull_assign_and_minimize (const Polyhedron &y) |
Assigns to *this the poly-hull of *this and y , minimizing the result. | |
void | upper_bound_assign (const Polyhedron &y) |
Same as poly_hull_assign(y). | |
void | poly_difference_assign (const Polyhedron &y) |
Assigns to *this the poly-difference of *this and y . The result is not guaranteed to be minimized. | |
void | difference_assign (const Polyhedron &y) |
Same as poly_difference_assign(y). | |
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, const Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one()) |
Assigns to *this the image of *this with respect to the generalized affine relation ![]() ![]() relsym . | |
void | generalized_affine_preimage (Variable var, const Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one()) |
Assigns to *this the preimage of *this with respect to the generalized affine relation ![]() ![]() relsym . | |
void | generalized_affine_image (const Linear_Expression &lhs, const Relation_Symbol relsym, const Linear_Expression &rhs) |
Assigns to *this the image of *this with respect to the generalized affine relation ![]() ![]() relsym . | |
void | generalized_affine_preimage (const Linear_Expression &lhs, const Relation_Symbol relsym, const Linear_Expression &rhs) |
Assigns to *this the preimage of *this with respect to the generalized affine relation ![]() ![]() relsym . | |
void | bounded_affine_image (Variable var, const Linear_Expression &lb_expr, const Linear_Expression &ub_expr, Coefficient_traits::const_reference denominator=Coefficient_one()) |
Assigns to *this the image of *this with respect to the bounded affine relation ![]() | |
void | bounded_affine_preimage (Variable var, const Linear_Expression &lb_expr, const Linear_Expression &ub_expr, Coefficient_traits::const_reference denominator=Coefficient_one()) |
Assigns to *this the preimage of *this with respect to the bounded affine relation ![]() | |
void | time_elapse_assign (const Polyhedron &y) |
Assigns to *this the result of computing the time-elapse between *this and y . | |
void | topological_closure_assign () |
Assigns to *this its topological closure. | |
void | BHRZ03_widening_assign (const Polyhedron &y, unsigned *tp=0) |
Assigns to *this the result of computing the BHRZ03-widening between *this and y . | |
void | limited_BHRZ03_extrapolation_assign (const Polyhedron &y, const Constraint_System &cs, unsigned *tp=0) |
Improves the result of the BHRZ03-widening computation by also enforcing those constraints in cs that are satisfied by all the points of *this . | |
void | bounded_BHRZ03_extrapolation_assign (const Polyhedron &y, const Constraint_System &cs, unsigned *tp=0) |
Improves the result of the BHRZ03-widening computation by also enforcing those constraints in cs that are satisfied by all the points of *this , plus all the constraints of the form ![]() ![]() ![]() *this . | |
void | H79_widening_assign (const Polyhedron &y, unsigned *tp=0) |
Assigns to *this the result of computing the H79-widening between *this and y . | |
void | limited_H79_extrapolation_assign (const Polyhedron &y, const Constraint_System &cs, unsigned *tp=0) |
Improves the result of the H79-widening computation by also enforcing those constraints in cs that are satisfied by all the points of *this . | |
void | bounded_H79_extrapolation_assign (const Polyhedron &y, const Constraint_System &cs, unsigned *tp=0) |
Improves the result of the H79-widening computation by also enforcing those constraints in cs that are satisfied by all the points of *this , plus all the constraints of the form ![]() ![]() ![]() *this . | |
Member Functions that May Modify the Dimension of the Vector Space | |
void | add_space_dimensions_and_embed (dimension_type m) |
Adds m new space dimensions and embeds the old polyhedron in the new vector space. | |
void | add_space_dimensions_and_project (dimension_type m) |
Adds m new space dimensions to the polyhedron and does not embed it in the new vector space. | |
void | concatenate_assign (const Polyhedron &y) |
Assigns to *this the concatenation of *this and y , taken in this order. | |
void | remove_space_dimensions (const Variables_Set &to_be_removed) |
Removes all the specified dimensions from the vector space. | |
void | remove_higher_space_dimensions (dimension_type new_dimension) |
Removes the higher dimensions of the vector space so that the resulting space will have dimension new_dimension . | |
template<typename Partial_Function> | |
void | map_space_dimensions (const Partial_Function &pfunc) |
Remaps the dimensions of the vector space according to a partial function. | |
void | expand_space_dimension (Variable var, dimension_type m) |
Creates m copies of the space dimension corresponding to var . | |
void | fold_space_dimensions (const Variables_Set &to_be_folded, Variable var) |
Folds the space dimensions in to_be_folded into var . | |
Miscellaneous Member Functions | |
~Polyhedron () | |
Destructor. | |
void | swap (Polyhedron &y) |
Swaps *this with polyhedron y . (*this and y can be dimension-incompatible.). | |
void | ascii_dump () const |
Writes to std::cerr an ASCII representation of *this . | |
void | ascii_dump (std::ostream &s) const |
Writes to s an ASCII representation of *this . | |
void | print () const |
Prints *this to std::cerr using operator<< . | |
bool | ascii_load (std::istream &s) |
Loads from s an ASCII representation (as produced by ascii_dump) 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 . | |
Static Public Member Functions | |
static dimension_type | max_space_dimension () |
Returns the maximum space dimension all kinds of Polyhedron can handle. | |
Protected Member Functions | |
Polyhedron (Topology topol, dimension_type num_dimensions, Degenerate_Element kind) | |
Builds a polyhedron having the specified properties. | |
Polyhedron (const Polyhedron &y) | |
Ordinary copy-constructor. | |
Polyhedron (Topology topol, const Constraint_System &cs) | |
Builds a polyhedron from a system of constraints. | |
Polyhedron (Topology topol, Constraint_System &cs) | |
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) | |
Builds a polyhedron recycling a system of generators. | |
template<typename Box> | |
Polyhedron (Topology topol, const Box &box) | |
Builds a polyhedron out of a generic, interval-based bounding box. | |
Polyhedron & | operator= (const Polyhedron &y) |
The assignment operator. (*this and y can be dimension-incompatible.). | |
Private Types | |
enum | Three_Valued_Boolean { TVB_TRUE, TVB_FALSE, TVB_DONT_KNOW } |
Private Member Functions | |
Topology | topology () const |
Returns the topological kind of the polyhedron. | |
bool | is_necessarily_closed () const |
Returns true if and only if the polyhedron is necessarily closed. | |
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, const bool maximize, Coefficient &ext_n, Coefficient &ext_d, bool &included, Generator &point) 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. | |
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, Saturation_Matrix &sat1, Saturation_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, Saturation_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, Saturation_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, Saturation_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, Saturation_Matrix &sat, dimension_type num_lines_or_equalities) |
Performs the conversion from constraints to generators and vice versa. | |
static int | simplify (Linear_System &mat, Saturation_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. | |
Saturation_Matrix | sat_c |
The saturation matrix having constraints on its columns. | |
Saturation_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. | |
Friends | |
class | Parma_Polyhedra_Library::BD_Shape |
class | Parma_Polyhedra_Library::BHRZ03_Certificate |
class | Parma_Polyhedra_Library::H79_Certificate |
bool | operator== (const Polyhedron &x, const Polyhedron &y) |
Related Functions | |
(Note that these are not member functions.) | |
std::ostream & | operator<< (std::ostream &s, const Polyhedron &ph) |
Output operator. | |
bool | operator!= (const Polyhedron &x, const Polyhedron &y) |
Returns true if and only if x and y are different polyhedra. | |
void | swap (Parma_Polyhedra_Library::Polyhedron &x, Parma_Polyhedra_Library::Polyhedron &y) |
Specializes std::swap . | |
template<typename PH> | |
bool | poly_hull_assign_if_exact (PH &p, const PH &q) |
If the poly-hull of p and q is exact it is assigned to p and true is returned, otherwise false is returned. | |
Classes | |
class | Status |
A conjunctive assertion about a polyhedron. More... |
An object of the class Polyhedron represents a convex polyhedron in the vector space .
A polyhedron can be specified as either a finite system of constraints or a finite system of generators (see Section Representations of Convex Polyhedra) and it is always possible to obtain either representation. That is, if we know the system of constraints, we can obtain from this the system of generators that define the same polyhedron and vice versa. These systems can contain redundant members: in this case we say that they are not in the minimal form. Most operators on polyhedra are provided with two implementations: one of these, denoted <operator-name>_and_minimize
, also enforces the minimization of the representations, and returns the Boolean value false
whenever the resulting polyhedron turns out to be empty.
Two key attributes of any polyhedron are its topological kind (recording whether it is a C_Polyhedron or an NNC_Polyhedron object) and its space dimension (the dimension of the enclosing vector space):
Note that four different polyhedra can be defined on the zero-dimension space: the empty polyhedron, either closed or NNC, and the universe polyhedron , again either closed or NNC.
x
and y
are defined (where they are used) as follows: Variable x(0); Variable y(1);
Constraint_System cs; cs.insert(x >= 0); cs.insert(x <= 3); cs.insert(y >= 0); cs.insert(y <= 3); C_Polyhedron ph(cs);
Generator_System gs; gs.insert(point(0*x + 0*y)); gs.insert(point(0*x + 3*y)); gs.insert(point(3*x + 0*y)); gs.insert(point(3*x + 3*y)); C_Polyhedron ph(gs);
Constraint_System cs; cs.insert(x >= 0); cs.insert(x - y <= 0); cs.insert(x - y + 1 >= 0); C_Polyhedron ph(cs);
Generator_System gs; gs.insert(point(0*x + 0*y)); gs.insert(point(0*x + y)); gs.insert(ray(x - y)); C_Polyhedron ph(gs);
C_Polyhedron ph(2); ph.add_constraint(y >= 0);
C_Polyhedron ph(2, EMPTY); ph.add_generator(point(0*x + 0*y)); ph.add_generator(ray(y)); ph.add_generator(line(x));
add_space_dimensions_and_embed
: C_Polyhedron ph(1); ph.add_constraint(x == 2); ph.add_space_dimensions_and_embed(1);
add_space_dimensions_and_project
: C_Polyhedron ph(1); ph.add_constraint(x == 2); ph.add_space_dimensions_and_project(1);
add_space_dimensions_and_embed
. After the last line of code, the resulting polyhedron is the singleton set affine_image
: C_Polyhedron ph(2, EMPTY); ph.add_generator(point(0*x + 0*y)); ph.add_generator(point(0*x + 3*y)); ph.add_generator(point(3*x + 0*y)); ph.add_generator(point(3*x + 3*y)); Linear_Expression expr = x + 4; ph.affine_image(x, expr);
x
is Linear_Expression expr = x + y;
Linear_Expression expr = y;
affine_preimage
: C_Polyhedron ph(2); ph.add_constraint(x >= 0); ph.add_constraint(x <= 3); ph.add_constraint(y >= 0); ph.add_constraint(y <= 3); Linear_Expression expr = x + 4; ph.affine_preimage(x, expr);
var
and the affine expression and the denominator are the same as in Example 6, while the resulting polyhedron is again the same square, but translated to the left. Moreover, if the affine transformation for x
is Linear_Expression expr = x + y;
x
, for example, the affine expression Linear_Expression expr = y;
Variable z(2); Variable w(3);
remove_space_dimensions
: Generator_System gs; gs.insert(point(3*x + y +0*z + 2*w)); C_Polyhedron ph(gs); Variables_Set to_be_removed; to_be_removed.insert(y); to_be_removed.insert(z); ph.remove_space_dimensions(to_be_removed);
remove_space_dimensions
operator, unexpected results can be obtained. For instance, by using the following code we would obtain a different result: set<Variable> to_be_removed1; to_be_removed1.insert(y); ph.remove_space_dimensions(to_be_removed1); set<Variable> to_be_removed2; to_be_removed2.insert(z); ph.remove_space_dimensions(to_be_removed2);
to_be_removed2
we are actually removing variable remove_space_dimensions
is not idempotent: removing twice the same non-empty set of dimensions is never the same as removing them just once. Definition at line 351 of file Polyhedron.defs.hh.
enum Parma_Polyhedra_Library::Polyhedron::Three_Valued_Boolean [private] |
Parma_Polyhedra_Library::Polyhedron::Polyhedron | ( | Topology | topol, | |
dimension_type | num_dimensions, | |||
Degenerate_Element | kind | |||
) | [protected] |
Builds a polyhedron having the specified properties.
topol | The topology of the polyhedron; | |
num_dimensions | The number of dimensions of the vector space enclosing the polyhedron; | |
kind | Specifies whether the universe or the empty polyhedron has to be built. |
Definition at line 49 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Constraint_System::add_low_level_constraints(), Parma_Polyhedra_Library::Constraint_System::adjust_topology_and_space_dimension(), con_sys, Parma_Polyhedra_Library::EMPTY, max_space_dimension(), OK(), set_constraints_minimized(), Parma_Polyhedra_Library::Polyhedron::Status::set_empty(), space_dim, and status.
00052 : con_sys(topol), 00053 gen_sys(topol), 00054 sat_c(), 00055 sat_g() { 00056 // Protecting against space dimension overflow is up to the caller. 00057 assert(num_dimensions <= max_space_dimension()); 00058 00059 if (kind == EMPTY) 00060 status.set_empty(); 00061 else if (num_dimensions > 0) { 00062 con_sys.add_low_level_constraints(); 00063 con_sys.adjust_topology_and_space_dimension(topol, num_dimensions); 00064 set_constraints_minimized(); 00065 } 00066 space_dim = num_dimensions; 00067 assert(OK()); 00068 }
Parma_Polyhedra_Library::Polyhedron::Polyhedron | ( | const Polyhedron & | y | ) | [protected] |
Ordinary copy-constructor.
Definition at line 70 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Linear_System::assign_with_pending(), con_sys, constraints_are_up_to_date(), gen_sys, generators_are_up_to_date(), sat_c, sat_c_is_up_to_date(), sat_g, sat_g_is_up_to_date(), and topology().
00071 : con_sys(y.topology()), 00072 gen_sys(y.topology()), 00073 status(y.status), 00074 space_dim(y.space_dim) { 00075 // Being a protected method, we simply assert that topologies do match. 00076 assert(topology() == y.topology()); 00077 if (y.constraints_are_up_to_date()) 00078 con_sys.assign_with_pending(y.con_sys); 00079 if (y.generators_are_up_to_date()) 00080 gen_sys.assign_with_pending(y.gen_sys); 00081 if (y.sat_c_is_up_to_date()) 00082 sat_c = y.sat_c; 00083 if (y.sat_g_is_up_to_date()) 00084 sat_g = y.sat_g; 00085 }
Parma_Polyhedra_Library::Polyhedron::Polyhedron | ( | Topology | topol, | |
const Constraint_System & | cs | |||
) | [protected] |
Builds a polyhedron from a system of constraints.
The polyhedron inherits the space dimension of the constraint system.
topol | The topology of the polyhedron; | |
cs | The system of constraints defining the polyhedron. |
std::invalid_argument | Thrown if the topology of cs is incompatible with topol . |
Definition at line 87 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Constraint_System::add_low_level_constraints(), con_sys, max_space_dimension(), Parma_Polyhedra_Library::NECESSARILY_CLOSED, Parma_Polyhedra_Library::Linear_System::num_pending_rows(), OK(), set_constraints_up_to_date(), set_empty(), Parma_Polyhedra_Library::Linear_System::set_sorted(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), throw_topology_incompatible(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
00088 : con_sys(topol), 00089 gen_sys(topol), 00090 sat_c(), 00091 sat_g() { 00092 // Protecting against space dimension overflow is up to the caller. 00093 assert(ccs.space_dimension() <= max_space_dimension()); 00094 00095 // TODO: this implementation is just an executable specification. 00096 Constraint_System cs = ccs; 00097 00098 // Try to adapt `cs' to the required topology. 00099 const dimension_type cs_space_dim = cs.space_dimension(); 00100 if (!cs.adjust_topology_and_space_dimension(topol, cs_space_dim)) 00101 throw_topology_incompatible((topol == NECESSARILY_CLOSED) 00102 ? "C_Polyhedron(cs)" 00103 : "NNC_Polyhedron(cs)", "cs", cs); 00104 00105 // Set the space dimension. 00106 space_dim = cs_space_dim; 00107 00108 if (space_dim > 0) { 00109 // Stealing the rows from `cs'. 00110 std::swap(con_sys, cs); 00111 if (con_sys.num_pending_rows() > 0) { 00112 // Even though `cs' has pending constraints, since the generators 00113 // of the polyhedron are not up-to-date, the polyhedron cannot 00114 // have pending constraints. By integrating the pending part 00115 // of `con_sys' we may loose sortedness. 00116 con_sys.unset_pending_rows(); 00117 con_sys.set_sorted(false); 00118 } 00119 con_sys.add_low_level_constraints(); 00120 set_constraints_up_to_date(); 00121 } 00122 else { 00123 // Here `space_dim == 0'. 00124 if (cs.num_columns() > 0) 00125 // See if an inconsistent constraint has been passed. 00126 for (dimension_type i = cs.num_rows(); i-- > 0; ) 00127 if (cs[i].is_inconsistent()) { 00128 // Inconsistent constraint found: the polyhedron is empty. 00129 set_empty(); 00130 break; 00131 } 00132 } 00133 assert(OK()); 00134 }
Parma_Polyhedra_Library::Polyhedron::Polyhedron | ( | Topology | topol, | |
Constraint_System & | cs | |||
) | [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 will be recycled to build the polyhedron. |
std::invalid_argument | Thrown if the topology of cs is incompatible with topol . |
Definition at line 136 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Constraint_System::add_low_level_constraints(), Parma_Polyhedra_Library::Constraint_System::adjust_topology_and_space_dimension(), con_sys, max_space_dimension(), Parma_Polyhedra_Library::NECESSARILY_CLOSED, Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Linear_System::num_pending_rows(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), set_constraints_up_to_date(), set_empty(), Parma_Polyhedra_Library::Linear_System::set_sorted(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), throw_topology_incompatible(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
00137 : con_sys(topol), 00138 gen_sys(topol), 00139 sat_c(), 00140 sat_g() { 00141 // Protecting against space dimension overflow is up to the caller. 00142 assert(cs.space_dimension() <= max_space_dimension()); 00143 00144 // Try to adapt `cs' to the required topology. 00145 const dimension_type cs_space_dim = cs.space_dimension(); 00146 if (!cs.adjust_topology_and_space_dimension(topol, cs_space_dim)) 00147 throw_topology_incompatible((topol == NECESSARILY_CLOSED) 00148 ? "C_Polyhedron(cs)" 00149 : "NNC_Polyhedron(cs)", "cs", cs); 00150 00151 // Set the space dimension. 00152 space_dim = cs_space_dim; 00153 00154 if (space_dim > 0) { 00155 // Stealing the rows from `cs'. 00156 std::swap(con_sys, cs); 00157 if (con_sys.num_pending_rows() > 0) { 00158 // Even though `cs' has pending constraints, since the generators 00159 // of the polyhedron are not up-to-date, the polyhedron cannot 00160 // have pending constraints. By integrating the pending part 00161 // of `con_sys' we may loose sortedness. 00162 con_sys.unset_pending_rows(); 00163 con_sys.set_sorted(false); 00164 } 00165 con_sys.add_low_level_constraints(); 00166 set_constraints_up_to_date(); 00167 } 00168 else { 00169 // Here `space_dim == 0'. 00170 if (cs.num_columns() > 0) 00171 // See if an inconsistent constraint has been passed. 00172 for (dimension_type i = cs.num_rows(); i-- > 0; ) 00173 if (cs[i].is_inconsistent()) { 00174 // Inconsistent constraint found: the polyhedron is empty. 00175 set_empty(); 00176 break; 00177 } 00178 } 00179 assert(OK()); 00180 }
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 182 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, throw_invalid_generators(), throw_topology_incompatible(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
00183 : con_sys(topol), 00184 gen_sys(topol), 00185 sat_c(), 00186 sat_g() { 00187 // Protecting against space dimension overflow is up to the caller. 00188 assert(cgs.space_dimension() <= max_space_dimension()); 00189 00190 // TODO: this implementation is just an executable specification. 00191 Generator_System gs = cgs; 00192 00193 // An empty set of generators defines the empty polyhedron. 00194 if (gs.num_rows() == 0) { 00195 space_dim = gs.space_dimension(); 00196 status.set_empty(); 00197 assert(OK()); 00198 return; 00199 } 00200 00201 // Non-empty valid generator systems have a supporting point, at least. 00202 if (!gs.has_points()) 00203 throw_invalid_generators((topol == NECESSARILY_CLOSED) 00204 ? "C_Polyhedron(gs)" 00205 : "NNC_Polyhedron(gs)", "gs"); 00206 00207 const dimension_type gs_space_dim = gs.space_dimension(); 00208 // Try to adapt `gs' to the required topology. 00209 if (!gs.adjust_topology_and_space_dimension(topol, gs_space_dim)) 00210 throw_topology_incompatible((topol == NECESSARILY_CLOSED) 00211 ? "C_Polyhedron(gs)" 00212 : "NNC_Polyhedron(gs)", "gs", gs); 00213 00214 if (gs_space_dim > 0) { 00215 // Stealing the rows from `gs'. 00216 std::swap(gen_sys, gs); 00217 // In a generator system describing a NNC polyhedron, 00218 // for each point we must also have the corresponding closure point. 00219 if (topol == NOT_NECESSARILY_CLOSED) 00220 gen_sys.add_corresponding_closure_points(); 00221 if (gen_sys.num_pending_rows() > 0) { 00222 // Even though `gs' has pending generators, since the constraints 00223 // of the polyhedron are not up-to-date, the polyhedron cannot 00224 // have pending generators. By integrating the pending part 00225 // of `gen_sys' we may loose sortedness. 00226 gen_sys.unset_pending_rows(); 00227 gen_sys.set_sorted(false); 00228 } 00229 // Generators are now up-to-date. 00230 set_generators_up_to_date(); 00231 00232 // Set the space dimension. 00233 space_dim = gs_space_dim; 00234 assert(OK()); 00235 return; 00236 } 00237 00238 // Here `gs.num_rows > 0' and `gs_space_dim == 0': 00239 // we already checked for both the topology-compatibility 00240 // and the supporting point. 00241 space_dim = 0; 00242 assert(OK()); 00243 }
Parma_Polyhedra_Library::Polyhedron::Polyhedron | ( | Topology | topol, | |
Generator_System & | gs | |||
) | [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 will be recycled to build 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 245 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Generator_System::add_corresponding_closure_points(), Parma_Polyhedra_Library::Generator_System::adjust_topology_and_space_dimension(), gen_sys, Parma_Polyhedra_Library::Generator_System::has_points(), max_space_dimension(), Parma_Polyhedra_Library::NECESSARILY_CLOSED, Parma_Polyhedra_Library::NOT_NECESSARILY_CLOSED, Parma_Polyhedra_Library::Linear_System::num_pending_rows(), Parma_Polyhedra_Library::Matrix::num_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, throw_invalid_generators(), throw_topology_incompatible(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
00246 : con_sys(topol), 00247 gen_sys(topol), 00248 sat_c(), 00249 sat_g() { 00250 // Protecting against space dimension overflow is up to the caller. 00251 assert(gs.space_dimension() <= max_space_dimension()); 00252 00253 // An empty set of generators defines the empty polyhedron. 00254 if (gs.num_rows() == 0) { 00255 space_dim = gs.space_dimension(); 00256 status.set_empty(); 00257 assert(OK()); 00258 return; 00259 } 00260 00261 // Non-empty valid generator systems have a supporting point, at least. 00262 if (!gs.has_points()) 00263 throw_invalid_generators((topol == NECESSARILY_CLOSED) 00264 ? "C_Polyhedron(gs)" 00265 : "NNC_Polyhedron(gs)", "gs"); 00266 00267 const dimension_type gs_space_dim = gs.space_dimension(); 00268 // Try to adapt `gs' to the required topology. 00269 if (!gs.adjust_topology_and_space_dimension(topol, gs_space_dim)) 00270 throw_topology_incompatible((topol == NECESSARILY_CLOSED) 00271 ? "C_Polyhedron(gs)" 00272 : "NNC_Polyhedron(gs)", "gs", gs); 00273 00274 if (gs_space_dim > 0) { 00275 // Stealing the rows from `gs'. 00276 std::swap(gen_sys, gs); 00277 // In a generator system describing a NNC polyhedron, 00278 // for each point we must also have the corresponding closure point. 00279 if (topol == NOT_NECESSARILY_CLOSED) 00280 gen_sys.add_corresponding_closure_points(); 00281 if (gen_sys.num_pending_rows() > 0) { 00282 // Even though `gs' has pending generators, since the constraints 00283 // of the polyhedron are not up-to-date, the polyhedron cannot 00284 // have pending generators. By integrating the pending part 00285 // of `gen_sys' we may loose sortedness. 00286 gen_sys.unset_pending_rows(); 00287 gen_sys.set_sorted(false); 00288 } 00289 // Generators are now up-to-date. 00290 set_generators_up_to_date(); 00291 00292 // Set the space dimension. 00293 space_dim = gs_space_dim; 00294 assert(OK()); 00295 return; 00296 } 00297 00298 // Here `gs.num_rows > 0' and `gs_space_dim == 0': 00299 // we already checked for both the topology-compatibility 00300 // and the supporting point. 00301 space_dim = 0; 00302 assert(OK()); 00303 }
Parma_Polyhedra_Library::Polyhedron::Polyhedron | ( | Topology | topol, | |
const Box & | box | |||
) | [inline, protected] |
Builds a polyhedron out of a generic, interval-based bounding box.
topol | The topology of the polyhedron; | |
box | The bounding box representing the polyhedron to be built. |
std::invalid_argument | Thrown if box has intervals that are incompatible with topol . |
dimension_type space_dimension() const
bool is_empty() const
true
if and only if the bounding box describes the empty set. The is_empty()
method will always be called before the methods below. However, if is_empty()
returns true
, none of the functions below will be called. bool get_lower_bound(dimension_type k, bool closed, Coefficient& n, Coefficient& d) const
k
-th space dimension. If false
. Otherwise, set closed
, n
and d
as follows: closed
is set to true
if the the lower boundary of false
otherwise; n
and d
are assigned the integers bool get_upper_bound(dimension_type k, bool closed, Coefficient& n, Coefficient& d) const
k
-th space dimension. If false
. Otherwise, set closed
, n
and d
as follows: closed
is set to true
if the the upper boundary of false
otherwise; n
and d
are assigned the integers Definition at line 35 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::Constraint_System::insert(), Parma_Polyhedra_Library::NECESSARILY_CLOSED, Parma_Polyhedra_Library::Matrix::num_rows(), OK(), set_constraints_up_to_date(), set_empty(), Parma_Polyhedra_Library::Linear_System::set_index_first_pending_row(), Parma_Polyhedra_Library::Linear_System::set_sorted(), set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Constraint_System::swap(), and throw_invalid_argument().
00036 : con_sys(topol), 00037 gen_sys(topol), 00038 sat_c(), 00039 sat_g() { 00040 // Initialize the space dimension as indicated by the box. 00041 space_dim = box.space_dimension(); 00042 00043 // Check for emptiness. 00044 if (box.is_empty()) { 00045 set_empty(); 00046 return; 00047 } 00048 00049 // Zero-dim universe polyhedron. 00050 if (space_dim == 0) { 00051 set_zero_dim_univ(); 00052 return; 00053 } 00054 00055 // Insert a dummy constraint of the highest dimension to avoid the 00056 // need of resizing the matrix of constraints later; 00057 // this constraint will be removed at the end. 00058 con_sys.insert(Variable(space_dim - 1) >= 0); 00059 00060 for (dimension_type k = space_dim; k-- > 0; ) { 00061 // See if we have a valid lower bound. 00062 bool l_closed = false; 00063 Coefficient l_n, l_d; 00064 bool l_bounded = box.get_lower_bound(k, l_closed, l_n, l_d); 00065 if (l_bounded && topol == NECESSARILY_CLOSED && !l_closed) 00066 throw_invalid_argument("C_Polyhedron(const Box& box):", 00067 " box has an open lower bound"); 00068 // See if we have a valid upper bound. 00069 bool u_closed = false; 00070 Coefficient u_n, u_d; 00071 bool u_bounded = box.get_upper_bound(k, u_closed, u_n, u_d); 00072 if (u_bounded && topol == NECESSARILY_CLOSED && !u_closed) 00073 throw_invalid_argument("C_Polyhedron(const Box& box):", 00074 " box has an open upper bound"); 00075 00076 // See if we have an implicit equality constraint. 00077 if (l_bounded && u_bounded 00078 && l_closed && u_closed 00079 && l_n == u_n && l_d == u_d) { 00080 // Add the constraint `l_d*v_k == l_n'. 00081 con_sys.insert(l_d * Variable(k) == l_n); 00082 } 00083 else { 00084 // Check if a lower bound constraint is required. 00085 if (l_bounded) { 00086 if (l_closed) 00087 // Add the constraint `l_d*v_k >= l_n'. 00088 con_sys.insert(l_d * Variable(k) >= l_n); 00089 else 00090 // Add the constraint `l_d*v_k > l_n'. 00091 con_sys.insert(l_d * Variable(k) > l_n); 00092 } 00093 // Check if an upper bound constraint is required. 00094 if (u_bounded) { 00095 if (u_closed) 00096 // Add the constraint `u_d*v_k <= u_n'. 00097 con_sys.insert(u_d * Variable(k) <= u_n); 00098 else 00099 // Add the constraint `u_d*v_k < u_n'. 00100 con_sys.insert(u_d * Variable(k) < u_n); 00101 } 00102 } 00103 } 00104 00105 // Adding the low-level constraints. 00106 con_sys.add_low_level_constraints(); 00107 // Now removing the dummy constraint inserted before. 00108 dimension_type n_rows = con_sys.num_rows() - 1; 00109 con_sys[0].swap(con_sys[n_rows]); 00110 con_sys.set_sorted(false); 00111 // NOTE: here there are no pending constraints. 00112 con_sys.set_index_first_pending_row(n_rows); 00113 con_sys.erase_to_end(n_rows); 00114 00115 // Constraints are up-to-date. 00116 set_constraints_up_to_date(); 00117 assert(OK()); 00118 }
Parma_Polyhedra_Library::Polyhedron::~Polyhedron | ( | ) | [inline] |
dimension_type Parma_Polyhedra_Library::Polyhedron::max_space_dimension | ( | ) | [inline, static] |
Returns the maximum space dimension all kinds of Polyhedron can handle.
Definition at line 40 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().
00040 { 00041 using std::min; 00042 // One dimension is reserved to have a value of type dimension_type 00043 // that does not represent a legal dimension. 00044 return min(std::numeric_limits<dimension_type>::max() - 1, 00045 min(Constraint_System::max_space_dimension(), 00046 Generator_System::max_space_dimension() 00047 ) 00048 ); 00049 }
PPL::Polyhedron & Parma_Polyhedra_Library::Polyhedron::operator= | ( | const Polyhedron & | y | ) | [protected] |
The assignment operator. (*this
and y
can be dimension-incompatible.).
Definition at line 306 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Linear_System::assign_with_pending(), con_sys, constraints_are_up_to_date(), gen_sys, generators_are_up_to_date(), marked_empty(), sat_c, sat_c_is_up_to_date(), sat_g, sat_g_is_up_to_date(), set_empty(), set_zero_dim_univ(), space_dim, status, and topology().
Referenced by Parma_Polyhedra_Library::NNC_Polyhedron::operator=(), and Parma_Polyhedra_Library::C_Polyhedron::operator=().
00306 { 00307 // Being a protected method, we simply assert that topologies do match. 00308 assert(topology() == y.topology()); 00309 space_dim = y.space_dim; 00310 if (y.marked_empty()) 00311 set_empty(); 00312 else if (space_dim == 0) 00313 set_zero_dim_univ(); 00314 else { 00315 status = y.status; 00316 if (y.constraints_are_up_to_date()) 00317 con_sys.assign_with_pending(y.con_sys); 00318 if (y.generators_are_up_to_date()) 00319 gen_sys.assign_with_pending(y.gen_sys); 00320 if (y.sat_c_is_up_to_date()) 00321 sat_c = y.sat_c; 00322 if (y.sat_g_is_up_to_date()) 00323 sat_g = y.sat_g; 00324 } 00325 return *this; 00326 }
dimension_type Parma_Polyhedra_Library::Polyhedron::space_dimension | ( | ) | const [inline] |
Returns the dimension of the vector space enclosing *this
.
Definition at line 66 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(), bounded_BHRZ03_extrapolation_assign(), bounded_H79_extrapolation_assign(), Parma_Polyhedra_Library::Polyhedra_Powerset< PH >::check_containment(), Parma_Polyhedra_Library::H79_Certificate::compare(), Parma_Polyhedra_Library::BHRZ03_Certificate::compare(), concatenate_assign(), expand_space_dimension(), Parma_Polyhedra_Library::H79_Certificate::H79_Certificate(), ppl_Polyhedron_get_bounding_box(), ppl_Polyhedron_map_space_dimensions(), ppl_Polyhedron_space_dimension(), and throw_dimension_incompatible().
00066 { 00067 return space_dim; 00068 }
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 38 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 ppl_Polyhedron_affine_dimension().
00038 { 00039 if (is_empty()) 00040 return 0; 00041 00042 const Constraint_System& cs = minimized_constraints(); 00043 dimension_type d = space_dim; 00044 for (Constraint_System::const_iterator i = cs.begin(), 00045 cs_end = cs.end(); i != cs_end; ++i) 00046 if (i->is_equality()) 00047 --d; 00048 return d; 00049 }
const PPL::Constraint_System & Parma_Polyhedra_Library::Polyhedron::constraints | ( | ) | const |
Returns the system of constraints.
Definition at line 52 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Constraint_System::adjust_topology_and_space_dimension(), con_sys, constraints_are_up_to_date(), has_pending_constraints(), has_pending_generators(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), obtain_sorted_constraints(), process_pending_generators(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), swap(), topology(), update_constraints(), and Parma_Polyhedra_Library::Constraint_System::zero_dim_empty().
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::C_Polyhedron::C_Polyhedron(), concatenate_assign(), expand_space_dimension(), minimized_constraints(), Parma_Polyhedra_Library::NNC_Polyhedron::NNC_Polyhedron(), poly_difference_assign(), ppl_Polyhedron_constraints(), and ppl_Polyhedron_get_constraints().
00052 { 00053 if (marked_empty()) { 00054 // We want `con_sys' to only contain the unsatisfiable constraint 00055 // of the appropriate dimension. 00056 if (con_sys.num_rows() == 0) { 00057 // The 0-dim unsatisfiable constraint is extended to 00058 // the appropriate dimension and then stored in `con_sys'. 00059 Constraint_System unsat_cs = Constraint_System::zero_dim_empty(); 00060 unsat_cs.adjust_topology_and_space_dimension(topology(), space_dim); 00061 const_cast<Constraint_System&>(con_sys).swap(unsat_cs); 00062 } 00063 else { 00064 // Checking that `con_sys' contains the right thing. 00065 assert(con_sys.space_dimension() == space_dim); 00066 assert(con_sys.num_rows() == 1); 00067 assert(con_sys[0].is_inconsistent()); 00068 } 00069 return con_sys; 00070 } 00071 00072 if (space_dim == 0) { 00073 // zero-dimensional universe. 00074 assert(con_sys.num_columns() == 0 && con_sys.num_rows() == 0); 00075 return con_sys; 00076 } 00077 00078 // If the polyhedron has pending generators, we process them to obtain 00079 // the constraints. No processing is needed if the polyhedron has 00080 // pending constraints. 00081 if (has_pending_generators()) 00082 process_pending_generators(); 00083 else if (!constraints_are_up_to_date()) 00084 update_constraints(); 00085 00086 // TODO: reconsider whether to really sort constraints at this stage. 00087 #if ENSURE_SORTEDNESS 00088 // We insist in returning a sorted system of constraints, 00089 // but sorting is useless if there are pending constraints. 00090 if (!has_pending_constraints()) 00091 obtain_sorted_constraints(); 00092 #endif 00093 return con_sys; 00094 }
const PPL::Constraint_System & Parma_Polyhedra_Library::Polyhedron::minimized_constraints | ( | ) | const |
Returns the system of constraints, with no redundant constraint.
Definition at line 97 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(), Parma_Polyhedra_Library::H79_Certificate::H79_Certificate(), operator<<(), ppl_Polyhedron_get_minimized_constraints(), and ppl_Polyhedron_minimized_constraints().
00097 { 00098 // `minimize()' or `strongly_minimize_constraints()' 00099 // will process any pending constraints or generators. 00100 if (is_necessarily_closed()) 00101 minimize(); 00102 else 00103 strongly_minimize_constraints(); 00104 return constraints(); 00105 }
const PPL::Generator_System & Parma_Polyhedra_Library::Polyhedron::generators | ( | ) | const |
Returns the system of generators.
Definition at line 108 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(), has_pending_constraints(), has_pending_generators(), is_necessarily_closed(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), obtain_sorted_generators(), process_pending_constraints(), space_dim, Parma_Polyhedra_Library::Generator_System::space_dimension(), swap(), topology(), update_generators(), and zero_dim_univ.
Referenced by Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), map_space_dimensions(), minimized_generators(), ppl_Polyhedron_generators(), and ppl_Polyhedron_get_generators().
00108 { 00109 if (marked_empty()) { 00110 assert(gen_sys.num_rows() == 0); 00111 // We want `gen_sys' to have the appropriate space dimension, 00112 // even though it is an empty generator system. 00113 if (gen_sys.space_dimension() != space_dim) { 00114 Generator_System gs; 00115 gs.adjust_topology_and_space_dimension(topology(), space_dim); 00116 const_cast<Generator_System&>(gen_sys).swap(gs); 00117 } 00118 return gen_sys; 00119 } 00120 00121 if (space_dim == 0) { 00122 assert(gen_sys.num_columns() == 0 && gen_sys.num_rows() == 0); 00123 return Generator_System::zero_dim_univ(); 00124 } 00125 00126 // If the polyhedron has pending constraints, we process them to obtain 00127 // the generators (we may discover that the polyhedron is empty). 00128 // No processing is needed if the polyhedron has pending generators. 00129 if ((has_pending_constraints() && !process_pending_constraints()) 00130 || (!generators_are_up_to_date() && !update_generators())) { 00131 // We have just discovered that `*this' is empty. 00132 assert(gen_sys.num_rows() == 0); 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 // TODO: reconsider whether to really sort generators at this stage. 00144 #if ENSURE_SORTEDNESS 00145 // We insist in returning a sorted system of generators, 00146 // but sorting is useless if there are pending generators. 00147 if (!has_pending_generators()) 00148 obtain_sorted_generators(); 00149 #else 00150 // In the case of an NNC polyhedron, if the generator system is fully 00151 // minimized (i.e., minimized and with no pending generator), then 00152 // return a sorted system of generators: this is needed so that the 00153 // const_iterator could correctly filter out the matched closure points. 00154 if (!is_necessarily_closed() 00155 && generators_are_minimized() && !has_pending_generators()) 00156 obtain_sorted_generators(); 00157 #endif 00158 return gen_sys; 00159 }
const PPL::Generator_System & Parma_Polyhedra_Library::Polyhedron::minimized_generators | ( | ) | const |
Returns the system of generators, with no redundant generator.
Definition at line 162 of file Polyhedron_public.cc.
References generators(), is_necessarily_closed(), minimize(), and strongly_minimize_generators().
Referenced by Parma_Polyhedra_Library::BHRZ03_Certificate::BHRZ03_Certificate(), Parma_Polyhedra_Library::BHRZ03_Certificate::compare(), ppl_Polyhedron_get_minimized_generators(), and ppl_Polyhedron_minimized_generators().
00162 { 00163 // `minimize()' or `strongly_minimize_generators()' 00164 // will process any pending constraints or generators. 00165 if (is_necessarily_closed()) 00166 minimize(); 00167 else 00168 strongly_minimize_generators(); 00169 // Note: calling generators() on a strongly minimized NNC generator 00170 // system will also ensure sortedness, which is required to correctly 00171 // filter away the matched closure points. 00172 return generators(); 00173 }
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 176 of file Polyhedron_public.cc.
References gen_sys, generators_are_up_to_date(), has_pending_constraints(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Poly_Con_Relation::is_disjoint(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Poly_Con_Relation::is_included(), Parma_Polyhedra_Library::Constraint::is_inconsistent(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), marked_empty(), process_pending_constraints(), Parma_Polyhedra_Library::Generator_System::relation_with(), Parma_Polyhedra_Library::Poly_Con_Relation::saturates(), space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), throw_dimension_incompatible(), and update_generators().
Referenced by BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), poly_difference_assign(), ppl_Polyhedron_relation_with_constraint(), ppl_Polyhedron_relation_with_Constraint(), ppl_Polyhedron_relation_with_generator(), and ppl_Polyhedron_relation_with_Generator().
00176 { 00177 // Dimension-compatibility check. 00178 if (space_dim < c.space_dimension()) 00179 throw_dimension_incompatible("relation_with(c)", "c", c); 00180 00181 if (marked_empty()) 00182 return Poly_Con_Relation::saturates() 00183 && Poly_Con_Relation::is_included() 00184 && Poly_Con_Relation::is_disjoint(); 00185 00186 if (space_dim == 0) 00187 if (c.is_inconsistent()) 00188 if (c.is_strict_inequality() && c.inhomogeneous_term() == 0) 00189 // The constraint 0 > 0 implicitly defines the hyperplane 0 = 0; 00190 // thus, the zero-dimensional point also saturates it. 00191 return Poly_Con_Relation::saturates() 00192 && Poly_Con_Relation::is_disjoint(); 00193 else 00194 return Poly_Con_Relation::is_disjoint(); 00195 else if (c.is_equality() || c.inhomogeneous_term() == 0) 00196 return Poly_Con_Relation::saturates() 00197 && Poly_Con_Relation::is_included(); 00198 else 00199 // The zero-dimensional point saturates 00200 // neither the positivity constraint 1 >= 0, 00201 // nor the strict positivity constraint 1 > 0. 00202 return Poly_Con_Relation::is_included(); 00203 00204 if ((has_pending_constraints() && !process_pending_constraints()) 00205 || (!generators_are_up_to_date() && !update_generators())) 00206 // The polyhedron is empty. 00207 return Poly_Con_Relation::saturates() 00208 && Poly_Con_Relation::is_included() 00209 && Poly_Con_Relation::is_disjoint(); 00210 00211 return gen_sys.relation_with(c); 00212 }
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 215 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().
00215 { 00216 // Dimension-compatibility check. 00217 if (space_dim < g.space_dimension()) 00218 throw_dimension_incompatible("relation_with(g)", "g", g); 00219 00220 // The empty polyhedron cannot subsume a generator. 00221 if (marked_empty()) 00222 return Poly_Gen_Relation::nothing(); 00223 00224 // A universe polyhedron in a zero-dimensional space subsumes 00225 // all the generators of a zero-dimensional space. 00226 if (space_dim == 0) 00227 return Poly_Gen_Relation::subsumes(); 00228 00229 if (has_pending_generators()) 00230 process_pending_generators(); 00231 else if (!constraints_are_up_to_date()) 00232 update_constraints(); 00233 00234 return 00235 con_sys.satisfies_all_constraints(g) 00236 ? Poly_Gen_Relation::subsumes() 00237 : Poly_Gen_Relation::nothing(); 00238 }
bool Parma_Polyhedra_Library::Polyhedron::is_empty | ( | ) | const [inline] |
Returns true
if and only if *this
is an empty polyhedron.
Definition at line 279 of file Polyhedron.inlines.hh.
References generators_are_up_to_date(), has_pending_constraints(), marked_empty(), and minimize().
Referenced by affine_dimension(), bounded_affine_preimage(), contains(), generalized_affine_image(), generalized_affine_preimage(), is_disjoint_from(), operator<<(), ppl_Polyhedron_is_empty(), and shrink_bounding_box().
00279 { 00280 if (marked_empty()) 00281 return true; 00282 // Try a fast-fail test: if generators are up-to-date and 00283 // there are no pending constraints, then the generator system 00284 // (since it is well formed) contains a point. 00285 if (generators_are_up_to_date() && !has_pending_constraints()) 00286 return false; 00287 return !minimize(); 00288 }
bool Parma_Polyhedra_Library::Polyhedron::is_universe | ( | ) | const |
Returns true
if and only if *this
is a universe polyhedron.
Definition at line 241 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(), ppl_Polyhedron_is_universe(), and shrink_bounding_box().
00241 { 00242 if (marked_empty()) 00243 return false; 00244 00245 if (space_dim == 0) 00246 return true; 00247 00248 if (!has_pending_generators() && constraints_are_up_to_date()) { 00249 // Search for a constraint that is not a tautology. 00250 for (dimension_type i = con_sys.num_rows(); i-- > 0; ) 00251 if (!con_sys[i].is_tautological()) 00252 return false; 00253 // All the constraints are tautologies. 00254 return true; 00255 } 00256 00257 assert(!has_pending_constraints() && generators_are_up_to_date()); 00258 00259 // Try a fast-fail test. 00260 dimension_type num_lines = 0; 00261 dimension_type num_rays = 0; 00262 const dimension_type first_pending = gen_sys.first_pending_row(); 00263 for (dimension_type i = first_pending; i-- > 0; ) 00264 switch (gen_sys[i].type()) { 00265 case Generator::RAY: 00266 ++num_rays; 00267 break; 00268 case Generator::LINE: 00269 ++num_lines; 00270 break; 00271 default: 00272 break; 00273 } 00274 00275 if (has_pending_generators()) { 00276 // The non-pending part of `gen_sys' was minimized: 00277 // a success-first test is possible in this case. 00278 assert(generators_are_minimized()); 00279 if (num_lines == space_dim) { 00280 assert(num_rays == 0); 00281 return true; 00282 } 00283 assert(num_lines < space_dim); 00284 // Now scan the pending generators. 00285 dimension_type num_pending_lines = 0; 00286 dimension_type num_pending_rays = 0; 00287 const dimension_type gs_num_rows = gen_sys.num_rows(); 00288 for (dimension_type i = first_pending; i < gs_num_rows; ++i) 00289 switch (gen_sys[i].type()) { 00290 case Generator::RAY: 00291 ++num_pending_rays; 00292 break; 00293 case Generator::LINE: 00294 ++num_pending_lines; 00295 break; 00296 default: 00297 break; 00298 } 00299 // If no pending rays and lines were found, 00300 // then it is not the universe polyhedron. 00301 if (num_pending_rays == 0 && num_pending_lines == 0) 00302 return false; 00303 // Factor away the lines already seen (to be on the safe side, 00304 // we assume they are all linearly independent). 00305 if (num_lines + num_pending_lines < space_dim) { 00306 const dimension_type num_dims_missing 00307 = space_dim - (num_lines + num_pending_lines); 00308 // In order to span an n dimensional space (where n = num_dims_missing), 00309 // at least n+1 rays are needed. 00310 if (num_rays + num_pending_rays <= num_dims_missing) 00311 return false; 00312 } 00313 } 00314 else { 00315 // There is nothing pending. 00316 if (generators_are_minimized()) { 00317 // The exact test is possible. 00318 assert(num_rays == 0 || num_lines < space_dim); 00319 return num_lines == space_dim; 00320 } 00321 else 00322 // Only the fast-fail test can be computed: in order to span 00323 // an n dimensional space (where n = space_dim - num_lines), 00324 // at least n+1 rays are needed. 00325 if (num_lines < space_dim && num_lines + num_rays <= space_dim) 00326 return false; 00327 } 00328 00329 // We need the polyhedron in minimal form. 00330 if (has_pending_generators()) 00331 process_pending_generators(); 00332 else if (!constraints_are_minimized()) 00333 minimize(); 00334 if (is_necessarily_closed()) 00335 return (con_sys.num_rows() == 1 00336 && con_sys[0].is_inequality() 00337 && con_sys[0].is_tautological()); 00338 else { 00339 // NNC polyhedron. 00340 if (con_sys.num_rows() != 2 00341 || con_sys[0].is_equality() 00342 || con_sys[1].is_equality()) 00343 return false; 00344 else { 00345 // If the system of constraints contains two rows that 00346 // are not equalities, we are sure that they are 00347 // epsilon constraints: in this case we know that 00348 // the polyhedron is universe. 00349 #ifndef NDEBUG 00350 obtain_sorted_constraints(); 00351 const Constraint& eps_leq_one = con_sys[0]; 00352 const Constraint& eps_geq_zero = con_sys[1]; 00353 const dimension_type eps_index = con_sys.num_columns() - 1; 00354 assert(eps_leq_one[0] > 0 && eps_leq_one[eps_index] < 0 00355 && eps_geq_zero[0] == 0 && eps_geq_zero[eps_index] > 0); 00356 for (dimension_type i = 1; i < eps_index; ++i) 00357 assert(eps_leq_one[i] == 0 && eps_geq_zero[i] == 0); 00358 #endif 00359 return true; 00360 } 00361 } 00362 }
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 385 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().
Referenced by ppl_Polyhedron_is_topologically_closed().
00385 { 00386 // Necessarily closed polyhedra are trivially closed. 00387 if (is_necessarily_closed()) 00388 return true; 00389 // Any empty or zero-dimensional polyhedron is closed. 00390 if (marked_empty() 00391 || space_dim == 0 00392 || (has_something_pending() && !process_pending())) 00393 return true; 00394 00395 // At this point there are no pending constraints or generators. 00396 assert(!has_something_pending()); 00397 00398 if (generators_are_minimized()) { 00399 // A polyhedron is closed if and only if all of its (non-redundant) 00400 // closure points are matched by a corresponding point. 00401 const dimension_type n_rows = gen_sys.num_rows(); 00402 const dimension_type n_lines = gen_sys.num_lines(); 00403 for (dimension_type i = n_rows; i-- > n_lines; ) { 00404 const Generator& gi = gen_sys[i]; 00405 if (gi.is_closure_point()) { 00406 bool gi_has_no_matching_point = true; 00407 for (dimension_type j = n_rows; j-- > n_lines; ) { 00408 const Generator& gj = gen_sys[j]; 00409 if (i != j 00410 && gj.is_point() 00411 && gi.is_matching_closure_point(gj)) { 00412 gi_has_no_matching_point = false; 00413 break; 00414 } 00415 } 00416 if (gi_has_no_matching_point) 00417 return false; 00418 } 00419 } 00420 // All closure points are matched. 00421 return true; 00422 } 00423 00424 // A polyhedron is closed if, after strong minimization 00425 // of its constraint system, it has no strict inequalities. 00426 strongly_minimize_constraints(); 00427 return marked_empty() || !con_sys.has_strict_inequalities(); 00428 }
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 2871 of file Polyhedron_public.cc.
References intersection_assign_and_minimize(), and is_empty().
Referenced by Parma_Polyhedra_Library::Polyhedra_Powerset< PH >::check_containment(), and ppl_Polyhedron_is_disjoint_from_Polyhedron().
02871 { 02872 Polyhedron z = *this; 02873 z.intersection_assign_and_minimize(y); 02874 return z.is_empty(); 02875 }
bool Parma_Polyhedra_Library::Polyhedron::is_bounded | ( | ) | const |
Returns true
if and only if *this
is a bounded polyhedron.
Definition at line 365 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().
Referenced by ppl_Polyhedron_is_bounded().
00365 { 00366 // A zero-dimensional or empty polyhedron is bounded. 00367 if (space_dim == 0 00368 || marked_empty() 00369 || (has_pending_constraints() && !process_pending_constraints()) 00370 || (!generators_are_up_to_date() && !update_generators())) 00371 return true; 00372 00373 // If the system of generators contains any line or a ray, 00374 // then the polyhedron is unbounded. 00375 for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) 00376 if (gen_sys[i].is_line_or_ray()) 00377 return false; 00378 00379 // The system of generators is composed only by 00380 // points and closure points: the polyhedron is bounded. 00381 return true; 00382 }
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 291 of file Polyhedron.inlines.hh.
References bounds().
Referenced by ppl_Polyhedron_bounds_from_above().
00291 { 00292 return bounds(expr, true); 00293 }
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 296 of file Polyhedron.inlines.hh.
References bounds().
Referenced by ppl_Polyhedron_bounds_from_below().
00296 { 00297 return bounds(expr, false); 00298 }
bool Parma_Polyhedra_Library::Polyhedron::maximize | ( | const Linear_Expression & | expr, | |
Coefficient & | sup_n, | |||
Coefficient & | sup_d, | |||
bool & | maximum | |||
) | const [inline] |
Returns true
if and only if *this
is not empty and expr
is bounded from above in *this
, in which case the supremum value is computed.
expr | The linear expression to be maximized subject to *this ; | |
sup_n | The numerator of the supremum value; | |
sup_d | The denominator of the supremum value; | |
maximum | true if and only if the supremum is also the maximum value. |
std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
*this
is empty or expr
is not bounded from above, false
is returned and sup_n
, sup_d
and maximum
are left untouched.
Definition at line 301 of file Polyhedron.inlines.hh.
References max_min().
Referenced by ppl_Polyhedron_maximize(), and ppl_Polyhedron_maximize_with_point().
00303 { 00304 Generator g(point()); 00305 return max_min(expr, true, sup_n, sup_d, maximum, g); 00306 }
bool Parma_Polyhedra_Library::Polyhedron::maximize | ( | const Linear_Expression & | expr, | |
Coefficient & | sup_n, | |||
Coefficient & | sup_d, | |||
bool & | maximum, | |||
Generator & | point | |||
) | 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; | |
point | When maximization succeeds, will be assigned the point or closure point where expr reaches its supremum value. |
std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
*this
is empty or expr
is not bounded from above, false
is returned and sup_n
, sup_d
, maximum
and point
are left untouched.
Definition at line 309 of file Polyhedron.inlines.hh.
References max_min().
00311 { 00312 return max_min(expr, true, sup_n, sup_d, maximum, g); 00313 }
bool Parma_Polyhedra_Library::Polyhedron::minimize | ( | const Linear_Expression & | expr, | |
Coefficient & | inf_n, | |||
Coefficient & | inf_d, | |||
bool & | minimum | |||
) | const [inline] |
Returns true
if and only if *this
is not empty and expr
is bounded from below in *this
, in which case the infimum value is computed.
expr | The linear expression to be minimized subject to *this ; | |
inf_n | The numerator of the infimum value; | |
inf_d | The denominator of the infimum value; | |
minimum | true if and only if the infimum is also the minimum value. |
std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
*this
is empty or expr
is not bounded from below, false
is returned and inf_n
, inf_d
and minimum
are left untouched.
Definition at line 316 of file Polyhedron.inlines.hh.
References max_min().
Referenced by Parma_Polyhedra_Library::BHRZ03_Certificate::BHRZ03_Certificate(), BHRZ03_widening_assign(), Parma_Polyhedra_Library::H79_Certificate::compare(), Parma_Polyhedra_Library::BHRZ03_Certificate::compare(), Parma_Polyhedra_Library::H79_Certificate::H79_Certificate(), H79_widening_assign(), intersection_assign_and_minimize(), is_included_in(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), poly_difference_assign(), poly_hull_assign_and_minimize(), ppl_Polyhedron_minimize(), and ppl_Polyhedron_minimize_with_point().
00318 { 00319 Generator g(point()); 00320 return max_min(expr, false, inf_n, inf_d, minimum, g); 00321 }
bool Parma_Polyhedra_Library::Polyhedron::minimize | ( | const Linear_Expression & | expr, | |
Coefficient & | inf_n, | |||
Coefficient & | inf_d, | |||
bool & | minimum, | |||
Generator & | point | |||
) | 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; | |
point | When minimization succeeds, will be assigned a point or closure point where expr reaches its infimum value. |
std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
*this
is empty or expr
is not bounded from below, false
is returned and inf_n
, inf_d
, minimum
and point
are left untouched.
Definition at line 324 of file Polyhedron.inlines.hh.
References max_min().
00326 { 00327 return max_min(expr, false, inf_n, inf_d, minimum, g); 00328 }
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 2847 of file Polyhedron_public.cc.
References is_empty(), is_included_in(), marked_empty(), quick_equivalence_test(), space_dim, throw_dimension_incompatible(), throw_topology_incompatible(), topology(), and TVB_TRUE.
Referenced by BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHRZ03_widening_assign(), Parma_Polyhedra_Library::Polyhedra_Powerset< PH >::check_containment(), H79_widening_assign(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), poly_difference_assign(), poly_hull_assign_if_exact(), ppl_Polyhedron_contains_Polyhedron(), and strictly_contains().
02847 { 02848 const Polyhedron& x = *this; 02849 02850 // Topology compatibility check. 02851 if (x.topology() != y.topology()) 02852 throw_topology_incompatible("contains(y)", "y", y); 02853 02854 // Dimension-compatibility check. 02855 if (x.space_dim != y.space_dim) 02856 throw_dimension_incompatible("contains(y)", "y", y); 02857 02858 if (y.marked_empty()) 02859 return true; 02860 else if (x.marked_empty()) 02861 return y.is_empty(); 02862 else if (y.space_dim == 0) 02863 return true; 02864 else if (x.quick_equivalence_test(y) == Polyhedron::TVB_TRUE) 02865 return true; 02866 else 02867 return y.is_included_in(x); 02868 }
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 337 of file Polyhedron.inlines.hh.
References contains().
Referenced by ppl_Polyhedron_strictly_contains_Polyhedron().
00337 { 00338 const Polyhedron& x = *this; 00339 return x.contains(y) && !y.contains(x); 00340 }
void Parma_Polyhedra_Library::Polyhedron::shrink_bounding_box | ( | Box & | box, | |
Complexity_Class | complexity = ANY_COMPLEXITY | |||
) | const [inline] |
Uses *this
to shrink a generic, interval-based bounding box. Assigns to box
the intersection of box
with the smallest bounding box containing *this
.
box | The bounding box to be shrunk; | |
complexity | The complexity class of the algorithm to be used. |
*this
or box
is empty, then the empty box is returned.
If *this
and box
are non-empty, then, for each space dimension with variable
, let
be the upper and
the lower bound of the smallest interval containing
*this
.
If is infinite, then
box
is unaltered; if is finite, then the
box
interval for space dimension is (destructively) intersected with
if a point of
*this
satisfies and with
otherwise.
Similarly, if is infinite, then
box
is unaltered; if is finite, then the
box
interval for space dimension is (destructively) intersected with
if a point of
*this
satisfies and with
otherwise.
The template class Box must provide the following methods, whose return values, if any, are simply ignored.
causes the box to become empty, i.e., to represent the empty set.raise_lower_bound(dimension_type k, bool closed, Coefficient_traits::const_reference n, Coefficient_traits::const_reference d)
k
-th space dimension with closed
is true
, with closed
is false
. lower_upper_bound(dimension_type k, bool closed, Coefficient_traits::const_reference n, Coefficient_traits::const_reference d)
k
-th space dimension with closed
is true
, with closed
is false
.
The function raise_lower_bound(k, closed, n, d)
will be called at most once for each possible value for k
and for all such calls the fraction will be in canonical form, that is,
and
have no common factors and
is positive,
being the unique representation for zero. The same guarantee is offered for the function
lower_upper_bound(k, closed, n, d)
.
Definition at line 122 of file Polyhedron.templates.hh.
References Parma_Polyhedra_Library::ANY_COMPLEXITY, Parma_Polyhedra_Library::assign_r(), Parma_Polyhedra_Library::Generator_System::begin(), Parma_Polyhedra_Library::Constraint_System::begin(), Parma_Polyhedra_Library::Boundary::bound(), Parma_Polyhedra_Library::UBoundary::CLOSED, Parma_Polyhedra_Library::LBoundary::CLOSED, Parma_Polyhedra_Library::Generator::CLOSURE_POINT, Parma_Polyhedra_Library::Generator::coefficient(), Parma_Polyhedra_Library::Constraint::coefficient(), con_sys, constraints_are_minimized(), constraints_are_up_to_date(), Parma_Polyhedra_Library::Generator::divisor(), Parma_Polyhedra_Library::Generator_System::end(), Parma_Polyhedra_Library::Constraint_System::end(), Parma_Polyhedra_Library::Constraint::EQUALITY, gen_sys, generators_are_up_to_date(), has_pending_constraints(), has_something_pending(), Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), Parma_Polyhedra_Library::Boundary::is_closed(), is_empty(), Parma_Polyhedra_Library::Constraint::is_inconsistent(), Parma_Polyhedra_Library::is_minus_infinity(), is_necessarily_closed(), Parma_Polyhedra_Library::is_plus_infinity(), Parma_Polyhedra_Library::LP_Problem::is_satisfiable(), is_universe(), Parma_Polyhedra_Library::Generator::LINE, marked_empty(), Parma_Polyhedra_Library::MINUS_INFINITY, Parma_Polyhedra_Library::Constraint::NONSTRICT_INEQUALITY, Parma_Polyhedra_Library::Linear_System::num_pending_rows(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::UBoundary::OPEN, Parma_Polyhedra_Library::LBoundary::OPEN, Parma_Polyhedra_Library::PLUS_INFINITY, Parma_Polyhedra_Library::Generator::POINT, process_pending(), Parma_Polyhedra_Library::raw_value(), Parma_Polyhedra_Library::Generator::RAY, Parma_Polyhedra_Library::SIMPLEX_COMPLEXITY, Parma_Polyhedra_Library::Constraint_System::simplify(), space_dim, Parma_Polyhedra_Library::Constraint::STRICT_INEQUALITY, TEMP_INTEGER, Parma_Polyhedra_Library::Generator::type(), Parma_Polyhedra_Library::Constraint::type(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
Referenced by bounded_BHRZ03_extrapolation_assign(), bounded_H79_extrapolation_assign(), ppl_Polyhedron_get_bounding_box(), and ppl_Polyhedron_shrink_bounding_box().
00122 { 00123 bool reduce_complexity = (complexity != ANY_COMPLEXITY); 00124 if (!reduce_complexity 00125 || (!has_something_pending() && constraints_are_minimized())) { 00126 // If the constraint system is minimized, the test `is_universe()' 00127 // is not exponential. 00128 if (is_universe()) 00129 return; 00130 } 00131 if (reduce_complexity) { 00132 if (marked_empty() 00133 || (generators_are_up_to_date() && gen_sys.num_rows() == 0)) { 00134 box.set_empty(); 00135 return; 00136 } 00137 else if (constraints_are_up_to_date()) { 00138 // See if there is at least one inconsistent constraint in `con_sys'. 00139 for (Constraint_System::const_iterator i = con_sys.begin(), 00140 cs_end = con_sys.end(); i != cs_end; ++i) 00141 if (i->is_inconsistent()) { 00142 box.set_empty(); 00143 return; 00144 } 00145 // If `complexity' allows it, use the LP_Problem solver to determine 00146 // whether or not the polyhedron is empty. 00147 if (complexity == SIMPLEX_COMPLEXITY 00148 // TODO: find a workaround for NNC polyhedra. 00149 && is_necessarily_closed()) { 00150 LP_Problem lp(con_sys); 00151 if (!lp.is_satisfiable()) { 00152 box.set_empty(); 00153 return; 00154 } 00155 } 00156 } 00157 } 00158 else 00159 // The flag `reduce_complexity' is `false'. 00160 // Note that the test `is_empty()' is exponential in the worst case. 00161 if (is_empty()) { 00162 box.set_empty(); 00163 return; 00164 } 00165 00166 if (space_dim == 0) 00167 return; 00168 00169 // The following vectors will store the lower and upper bound 00170 // for each dimension. 00171 // Lower bounds are initialized to open plus infinity. 00172 std::vector<LBoundary> 00173 lower_bound(space_dim, 00174 LBoundary(ERational(PLUS_INFINITY), LBoundary::OPEN)); 00175 // Upper bounds are initialized to open minus infinity. 00176 std::vector<UBoundary> 00177 upper_bound(space_dim, 00178 UBoundary(ERational(MINUS_INFINITY), UBoundary::OPEN)); 00179 00180 if (!reduce_complexity && has_something_pending()) 00181 process_pending(); 00182 00183 // TODO: use simplex to derive variable bounds, if the complexity 00184 // is SIMPLEX_COMPLEXITY. 00185 00186 if (reduce_complexity && 00187 (!generators_are_up_to_date() || has_pending_constraints())) { 00188 // Extract easy-to-find bounds from constraints. 00189 assert(constraints_are_up_to_date()); 00190 00191 // We must copy `con_sys' to a temporary matrix, 00192 // as we need to simplify all of the matrix 00193 // (not just the non-pending part of it). 00194 Constraint_System cs(con_sys); 00195 if (cs.num_pending_rows() > 0) 00196 cs.unset_pending_rows(); 00197 if (has_pending_constraints() || !constraints_are_minimized()) 00198 cs.simplify(); 00199 00200 const Constraint_System::const_iterator cs_begin = cs.begin(); 00201 const Constraint_System::const_iterator cs_end = cs.end(); 00202 00203 for (Constraint_System::const_iterator i = cs_begin; i != cs_end; ++i) { 00204 dimension_type varid = space_dim; 00205 const Constraint& c = *i; 00206 // After `simplify()' some constraints may have become inconsistent. 00207 if (c.is_inconsistent()) { 00208 box.set_empty(); 00209 return; 00210 } 00211 for (dimension_type j = space_dim; j-- > 0; ) { 00212 // We look for constraints of the form `Variable(j) == k', 00213 // `Variable(j) >= k', and `Variable(j) > k'. 00214 if (c.coefficient(Variable(j)) != 0) 00215 if (varid != space_dim) { 00216 varid = space_dim; 00217 break; 00218 } 00219 else 00220 varid = j; 00221 } 00222 if (varid != space_dim) { 00223 Coefficient_traits::const_reference d = c.coefficient(Variable(varid)); 00224 Coefficient_traits::const_reference n = c.inhomogeneous_term(); 00225 // The constraint `c' is of the form 00226 // `Variable(varid) + n / d rel 0', where 00227 // `rel' is either the relation `==', `>=', or `>'. 00228 // For the purpose of shrinking intervals, this is 00229 // (morally) turned into `Variable(varid) rel -n/d'. 00230 mpq_class q; 00231 assign_r(q.get_num(), n, ROUND_NOT_NEEDED); 00232 assign_r(q.get_den(), d, ROUND_NOT_NEEDED); 00233 q.canonicalize(); 00234 // Turn `n/d' into `-n/d'. 00235 q = -q; 00236 const ERational r(q, ROUND_NOT_NEEDED); 00237 const Constraint::Type c_type = c.type(); 00238 switch (c_type) { 00239 case Constraint::EQUALITY: 00240 lower_bound[varid] = LBoundary(r, LBoundary::CLOSED); 00241 upper_bound[varid] = UBoundary(r, UBoundary::CLOSED); 00242 break; 00243 case Constraint::NONSTRICT_INEQUALITY: 00244 case Constraint::STRICT_INEQUALITY: 00245 if (d > 0) 00246 // If `d' is strictly positive, we have a constraint of the 00247 // form `Variable(varid) >= k' or `Variable(varid) > k'. 00248 lower_bound[varid] 00249 = LBoundary(r, (c_type == Constraint::NONSTRICT_INEQUALITY 00250 ? LBoundary::CLOSED 00251 : LBoundary::OPEN)); 00252 else { 00253 // Otherwise, we are sure that `d' is strictly negative 00254 // and, in this case, we have a constraint of the form 00255 // `Variable(varid) <= k' or `Variable(varid) < k'. 00256 assert(d < 0); 00257 upper_bound[varid] 00258 = UBoundary(r, (c_type == Constraint::NONSTRICT_INEQUALITY 00259 ? UBoundary::CLOSED 00260 : UBoundary::OPEN)); 00261 } 00262 break; 00263 } 00264 } 00265 } 00266 } 00267 else { 00268 // We are in the case where either the generators are up-to-date 00269 // or reduced complexity is not required. 00270 // Get the generators for *this. 00271 00272 // We have not to copy `gen_sys', because in this case 00273 // we only read the generators. 00274 const Generator_System& gs = gen_sys; 00275 00276 // We first need to identify those axes that are unbounded below 00277 // and/or above. 00278 for (Generator_System::const_iterator i = gs.begin(), 00279 gs_end = gs.end(); i != gs_end; ++i) { 00280 // Note: using an iterator, we read also the pending part of the matrix. 00281 const Generator& g = *i; 00282 Generator::Type g_type = g.type(); 00283 switch (g_type) { 00284 case Generator::LINE: 00285 // Any axes `j' in which the coefficient is non-zero is unbounded 00286 // both below and above. 00287 for (dimension_type j = space_dim; j-- > 0; ) 00288 if (g.coefficient(Variable(j)) != 0) { 00289 lower_bound[j] = LBoundary(ERational(MINUS_INFINITY), 00290 LBoundary::OPEN); 00291 upper_bound[j] = UBoundary(ERational(PLUS_INFINITY), 00292 UBoundary::OPEN); 00293 } 00294 break; 00295 case Generator::RAY: 00296 // Axes in which the coefficient is negative are unbounded below. 00297 // Axes in which the coefficient is positive are unbounded above. 00298 for (dimension_type j = space_dim; j-- > 0; ) { 00299 int sign = sgn(g.coefficient(Variable(j))); 00300 if (sign < 0) 00301 lower_bound[j] = LBoundary(ERational(MINUS_INFINITY), 00302 LBoundary::OPEN); 00303 else if (sign > 0) 00304 upper_bound[j] = UBoundary(ERational(PLUS_INFINITY), 00305 UBoundary::OPEN); 00306 } 00307 break; 00308 case Generator::POINT: 00309 case Generator::CLOSURE_POINT: 00310 { 00311 Coefficient_traits::const_reference d = g.divisor(); 00312 for (dimension_type j = space_dim; j-- > 0; ) { 00313 Coefficient_traits::const_reference n = g.coefficient(Variable(j)); 00314 mpq_class q; 00315 assign_r(q.get_num(), n, ROUND_NOT_NEEDED); 00316 assign_r(q.get_den(), d, ROUND_NOT_NEEDED); 00317 q.canonicalize(); 00318 const ERational r(q, ROUND_NOT_NEEDED); 00319 LBoundary lb(r,(g_type == Generator::CLOSURE_POINT 00320 ? LBoundary::OPEN 00321 : LBoundary::CLOSED)); 00322 if (lb < lower_bound[j]) 00323 lower_bound[j] = lb; 00324 UBoundary ub(r, (g_type == Generator::CLOSURE_POINT 00325 ? UBoundary::OPEN 00326 : UBoundary::CLOSED)); 00327 if (ub > upper_bound[j]) 00328 upper_bound[j] = ub; 00329 } 00330 } 00331 break; 00332 } 00333 } 00334 } 00335 00336 TEMP_INTEGER(n); 00337 TEMP_INTEGER(d); 00338 00339 // Now shrink the bounded axes. 00340 for (dimension_type j = space_dim; j-- > 0; ) { 00341 // Lower bound. 00342 const LBoundary& lb = lower_bound[j]; 00343 const ERational& lr = lb.bound(); 00344 if (!is_plus_infinity(lr) && !is_minus_infinity(lr)) { 00345 n = raw_value(lr).get_num(); 00346 d = raw_value(lr).get_den(); 00347 box.raise_lower_bound(j, lb.is_closed(), n, d); 00348 } 00349 00350 // Upper bound. 00351 const UBoundary& ub = upper_bound[j]; 00352 const ERational& ur = ub.bound(); 00353 if (!is_plus_infinity(ur) && !is_minus_infinity(ur)) { 00354 n = raw_value(ur).get_num(); 00355 d = raw_value(ur).get_den(); 00356 box.lower_upper_bound(j, ub.is_closed(), n, d); 00357 } 00358 } 00359 }
bool Parma_Polyhedra_Library::Polyhedron::OK | ( | bool | check_not_empty = false |
) | const |
Checks if all the invariants are satisfied.
true
if and only if *this
satisfies all the invariants and either check_not_empty
is false
or *this
is not empty.check_not_empty | true if and only if, in addition to checking the invariants, *this must be checked to be not empty. |
std::cerr
in case invariants are violated. This is useful for the purpose of debugging the library.
Definition at line 431 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(), 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::Saturation_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::Saturation_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::Saturation_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_constraint(), add_generator(), add_recycled_constraints(), add_recycled_constraints_and_minimize(), add_recycled_generators(), add_recycled_generators_and_minimize(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_image(), affine_preimage(), ascii_load(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHRZ03_widening_assign(), bounded_affine_image(), bounded_affine_preimage(), Parma_Polyhedra_Library::C_Polyhedron::C_Polyhedron(), concatenate_assign(), expand_space_dimension(), fold_space_dimensions(), generalized_affine_image(), generalized_affine_preimage(), H79_widening_assign(), intersection_assign(), intersection_assign_and_minimize(), is_included_in(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), map_space_dimensions(), minimize(), Parma_Polyhedra_Library::NNC_Polyhedron::NNC_Polyhedron(), poly_difference_assign(), poly_hull_assign(), poly_hull_assign_and_minimize(), Polyhedron(), ppl_Polyhedron_OK(), process_pending_constraints(), process_pending_generators(), remove_higher_space_dimensions(), remove_pending_to_obtain_constraints(), remove_pending_to_obtain_generators(), remove_space_dimensions(), strongly_minimize_constraints(), strongly_minimize_generators(), time_elapse_assign(), and topological_closure_assign().
00431 { 00432 #ifndef NDEBUG 00433 using std::endl; 00434 using std::cerr; 00435 #endif 00436 00437 // The expected number of columns in the constraint and generator 00438 // systems, if they are not empty. 00439 const dimension_type poly_num_columns 00440 = space_dim + (is_necessarily_closed() ? 1 : 2); 00441 00442 // Check whether the topologies of `con_sys' and `gen_sys' agree. 00443 if (con_sys.topology() != gen_sys.topology()) { 00444 #ifndef NDEBUG 00445 cerr << "Constraints and generators have different topologies!" 00446 << endl; 00447 #endif 00448 goto bomb; 00449 } 00450 00451 // Check whether the saturation matrices are well-formed. 00452 if (!sat_c.OK()) 00453 goto bomb; 00454 if (!sat_g.OK()) 00455 goto bomb; 00456 00457 // Check whether the status information is legal. 00458 if (!status.OK()) 00459 goto bomb; 00460 00461 if (marked_empty()) { 00462 if (check_not_empty) { 00463 // The caller does not want the polyhedron to be empty. 00464 #ifndef NDEBUG 00465 cerr << "Empty polyhedron!" << endl; 00466 #endif 00467 goto bomb; 00468 } 00469 00470 // An empty polyhedron is allowed if the system of constraints 00471 // either has no rows or only contains an unsatisfiable constraint 00472 // and if it has no pending constraints or generators. 00473 if (has_something_pending()) { 00474 #ifndef NDEBUG 00475 cerr << "The polyhedron is empty, " 00476 << "but it has something pending" << endl; 00477 #endif 00478 goto bomb; 00479 } 00480 if (con_sys.num_rows() == 0) 00481 return true; 00482 else { 00483 if (con_sys.space_dimension() != space_dim) { 00484 #ifndef NDEBUG 00485 cerr << "The polyhedron is in a space of dimension " 00486 << space_dim 00487 << " while the system of constraints is in a space of dimension " 00488 << con_sys.space_dimension() 00489 << endl; 00490 #endif 00491 goto bomb; 00492 } 00493 if (con_sys.num_rows() != 1) { 00494 #ifndef NDEBUG 00495 cerr << "The system of constraints for an empty polyhedron " 00496 << "has more then one row" 00497 << endl; 00498 #endif 00499 goto bomb; 00500 } 00501 if (!con_sys[0].is_inconsistent()) { 00502 #ifndef NDEBUG 00503 cerr << "Empty polyhedron with a satisfiable system of constraints" 00504 << endl; 00505 #endif 00506 goto bomb; 00507 } 00508 // Here we have only one, inconsistent constraint. 00509 return true; 00510 } 00511 } 00512 00513 // A zero-dimensional, non-empty polyhedron is legal only if the 00514 // system of constraint `con_sys' and the system of generators 00515 // `gen_sys' have no rows. 00516 if (space_dim == 0) { 00517 if (has_something_pending()) { 00518 #ifndef NDEBUG 00519 cerr << "Zero-dimensional polyhedron with something pending" 00520 << endl; 00521 #endif 00522 goto bomb; 00523 } 00524 if (con_sys.num_rows() != 0 || gen_sys.num_rows() != 0) { 00525 #ifndef NDEBUG 00526 cerr << "Zero-dimensional polyhedron with a non-empty" 00527 << endl 00528 << "system of constraints or generators." 00529 << endl; 00530 #endif 00531 goto bomb; 00532 } 00533 return true; 00534 } 00535 00536 // A polyhedron is defined by a system of constraints 00537 // or a system of generators: at least one of them must be up to date. 00538 if (!constraints_are_up_to_date() && !generators_are_up_to_date()) { 00539 #ifndef NDEBUG 00540 cerr << "Polyhedron not empty, not zero-dimensional" 00541 << endl 00542 << "and with neither constraints nor generators up-to-date!" 00543 << endl; 00544 #endif 00545 goto bomb; 00546 } 00547 00548 // Here we check if the size of the matrices is consistent. 00549 // Let us suppose that all the matrices are up-to-date; this means: 00550 // `con_sys' : number of constraints x poly_num_columns 00551 // `gen_sys' : number of generators x poly_num_columns 00552 // `sat_c' : number of generators x number of constraints 00553 // `sat_g' : number of constraints x number of generators. 00554 if (constraints_are_up_to_date()) { 00555 if (con_sys.num_columns() != poly_num_columns) { 00556 #ifndef NDEBUG 00557 cerr << "Incompatible size! (con_sys and space_dim)" 00558 << endl; 00559 #endif 00560 goto bomb; 00561 } 00562 if (sat_c_is_up_to_date()) 00563 if (con_sys.first_pending_row() != sat_c.num_columns()) { 00564 #ifndef NDEBUG 00565 cerr << "Incompatible size! (con_sys and sat_c)" 00566 << endl; 00567 #endif 00568 goto bomb; 00569 } 00570 if (sat_g_is_up_to_date()) 00571 if (con_sys.first_pending_row() != sat_g.num_rows()) { 00572 #ifndef NDEBUG 00573 cerr << "Incompatible size! (con_sys and sat_g)" 00574 << endl; 00575 #endif 00576 goto bomb; 00577 } 00578 if (generators_are_up_to_date()) 00579 if (con_sys.num_columns() != gen_sys.num_columns()) { 00580 #ifndef NDEBUG 00581 cerr << "Incompatible size! (con_sys and gen_sys)" 00582 << endl; 00583 #endif 00584 goto bomb; 00585 } 00586 } 00587 00588 if (generators_are_up_to_date()) { 00589 if (gen_sys.num_columns() != poly_num_columns) { 00590 #ifndef NDEBUG 00591 cerr << "Incompatible size! (gen_sys and space_dim)" 00592 << endl; 00593 #endif 00594 goto bomb; 00595 } 00596 if (sat_c_is_up_to_date()) 00597 if (gen_sys.first_pending_row() != sat_c.num_rows()) { 00598 #ifndef NDEBUG 00599 cerr << "Incompatible size! (gen_sys and sat_c)" 00600 << endl; 00601 #endif 00602 goto bomb; 00603 } 00604 if (sat_g_is_up_to_date()) 00605 if (gen_sys.first_pending_row() != sat_g.num_columns()) { 00606 #ifndef NDEBUG 00607 cerr << "Incompatible size! (gen_sys and sat_g)" 00608 << endl; 00609 #endif 00610 goto bomb; 00611 } 00612 00613 // Check if the system of generators is well-formed. 00614 if (!gen_sys.OK()) 00615 goto bomb; 00616 00617 if (gen_sys.first_pending_row() == 0) { 00618 #ifndef NDEBUG 00619 cerr << "Up-to-date generator system with all rows pending!" 00620 << endl; 00621 #endif 00622 goto bomb; 00623 } 00624 00625 // A non-empty system of generators describing a polyhedron 00626 // is valid if and only if it contains a point. 00627 if (gen_sys.num_rows() > 0 && !gen_sys.has_points()) { 00628 #ifndef NDEBUG 00629 cerr << "Non-empty generator system declared up-to-date " 00630 << "has no points!" 00631 << endl; 00632 #endif 00633 goto bomb; 00634 } 00635 00636 #if 0 00637 //================================================= 00638 // TODO: this test is wrong in the general case. 00639 // However, such an invariant does hold for a 00640 // strongly-minimized Generator_System. 00641 // We will activate this test as soon as the Status 00642 // flags will be able to remember if a system is 00643 // strongly minimized. 00644 00645 // Checking that the number of closure points is always 00646 // greater than the number of points. 00647 if (!is_necessarily_closed()) { 00648 dimension_type num_points = 0; 00649 dimension_type num_closure_points = 0; 00650 dimension_type eps_index = gen_sys.num_columns() - 1; 00651 for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) 00652 if (!gen_sys[i].is_line_or_ray()) 00653 if (gen_sys[i][eps_index] > 0) 00654 ++num_points; 00655 else 00656 ++num_closure_points; 00657 if (num_points > num_closure_points) { 00658 #ifndef NDEBUG 00659 cerr << "# POINTS > # CLOSURE_POINTS" << endl; 00660 #endif 00661 goto bomb; 00662 } 00663 } 00664 //================================================= 00665 #endif 00666 00667 if (generators_are_minimized()) { 00668 // If the system of generators is minimized, the number of 00669 // lines, rays and points of the polyhedron must be the same as 00670 // of a temporary, minimized one. If this does not happen then 00671 // the polyhedron is not OK. 00672 Constraint_System new_con_sys(topology()); 00673 Generator_System gs_without_pending = gen_sys; 00674 gs_without_pending.erase_to_end(gen_sys.first_pending_row()); 00675 gs_without_pending.unset_pending_rows(); 00676 Generator_System copy_of_gen_sys = gs_without_pending; 00677 Saturation_Matrix new_sat_c; 00678 minimize(false, copy_of_gen_sys, new_con_sys, new_sat_c); 00679 const dimension_type copy_num_lines = copy_of_gen_sys.num_lines(); 00680 if (gs_without_pending.num_rows() != copy_of_gen_sys.num_rows() 00681 || gs_without_pending.num_lines() != copy_num_lines 00682 || gs_without_pending.num_rays() != copy_of_gen_sys.num_rays()) { 00683 #ifndef NDEBUG 00684 cerr << "Generators are declared minimized, but they are not!\n" 00685 << "Here is the minimized form of the generators:\n"; 00686 copy_of_gen_sys.ascii_dump(cerr); 00687 cerr << endl; 00688 #endif 00689 goto bomb; 00690 } 00691 00692 // CHECKME : the following observation is not formally true 00693 // for a NNC_Polyhedron. But it may be true for its 00694 // representation ... 00695 00696 // If the corresponding polyhedral cone is _pointed_, then 00697 // a minimal system of generators is unique up to positive scaling. 00698 // We thus verify if the cone is pointed (i.e., there are no lines) 00699 // and, after normalizing and sorting a copy of the system `gen_sys' 00700 // of the polyhedron (we use a copy not to modify the polyhedron's 00701 // system) and the system `copy_of_gen_sys' that has been just 00702 // minimized, we check if the two matrices are identical. If 00703 // they are different it means that the generators of the 00704 // polyhedron are declared minimized, but they are not. 00705 if (copy_num_lines == 0) { 00706 copy_of_gen_sys.strong_normalize(); 00707 copy_of_gen_sys.sort_rows(); 00708 gs_without_pending.strong_normalize(); 00709 gs_without_pending.sort_rows(); 00710 if (copy_of_gen_sys != gs_without_pending) { 00711 #ifndef NDEBUG 00712 cerr << "Generators are declared minimized, but they are not!\n" 00713 << "(we are in the case:\n" 00714 << "dimension of lineality space equal to 0)\n" 00715 << "Here is the minimized form of the generators:\n"; 00716 copy_of_gen_sys.ascii_dump(cerr); 00717 cerr << endl; 00718 #endif 00719 goto bomb; 00720 } 00721 } 00722 } 00723 } 00724 00725 if (constraints_are_up_to_date()) { 00726 // Check if the system of constraints is well-formed. 00727 if (!con_sys.OK()) 00728 goto bomb; 00729 00730 if (con_sys.first_pending_row() == 0) { 00731 #ifndef NDEBUG 00732 cerr << "Up-to-date constraint system with all rows pending!" 00733 << endl; 00734 #endif 00735 goto bomb; 00736 } 00737 00738 // A non-empty system of constraints describing a polyhedron 00739 // must contain a constraint with a non-zero inhomogeneous term; 00740 // such a constraint corresponds to (a combination of other 00741 // constraints with): 00742 // -* the positivity constraint, for necessarily closed polyhedra; 00743 // -* the epsilon <= 1 constraint, for NNC polyhedra. 00744 bool no_positivity_constraint = true; 00745 for (dimension_type i = con_sys.num_rows(); i-- > 0; ) 00746 if (con_sys[i].inhomogeneous_term() != 0) { 00747 no_positivity_constraint = false; 00748 break; 00749 } 00750 if (no_positivity_constraint) { 00751 #ifndef NDEBUG 00752 cerr << "Non-empty constraint system has no positivity constraint" 00753 << endl; 00754 #endif 00755 goto bomb; 00756 } 00757 00758 if (!is_necessarily_closed()) { 00759 // A non-empty system of constraints describing a NNC polyhedron 00760 // must also contain a (combination of) the constraint epsilon >= 0, 00761 // i.e., a constraint with a positive epsilon coefficient. 00762 bool no_epsilon_geq_zero = true; 00763 const dimension_type eps_index = con_sys.num_columns() - 1; 00764 for (dimension_type i = con_sys.num_rows(); i-- > 0; ) 00765 if (con_sys[i][eps_index] > 0) { 00766 no_epsilon_geq_zero = false; 00767 break; 00768 } 00769 if (no_epsilon_geq_zero) { 00770 #ifndef NDEBUG 00771 cerr << "Non-empty constraint system for NNC polyhedron " 00772 << "has no epsilon >= 0 constraint" 00773 << endl; 00774 #endif 00775 goto bomb; 00776 } 00777 } 00778 00779 Constraint_System cs_without_pending = con_sys; 00780 cs_without_pending.erase_to_end(con_sys.first_pending_row()); 00781 cs_without_pending.unset_pending_rows(); 00782 Constraint_System copy_of_con_sys = cs_without_pending; 00783 Generator_System new_gen_sys(topology()); 00784 Saturation_Matrix new_sat_g; 00785 00786 if (minimize(true, copy_of_con_sys, new_gen_sys, new_sat_g)) { 00787 if (check_not_empty) { 00788 // Want to know the satisfiability of the constraints. 00789 #ifndef NDEBUG 00790 cerr << "Unsatisfiable system of constraints!" 00791 << endl; 00792 #endif 00793 goto bomb; 00794 } 00795 // The polyhedron is empty, there is nothing else to check. 00796 return true; 00797 } 00798 00799 if (constraints_are_minimized()) { 00800 // If the constraints are minimized, the number of equalities 00801 // and of inequalities of the system of the polyhedron must be 00802 // the same of the temporary minimized one. 00803 // If it does not happen, the polyhedron is not OK. 00804 if (cs_without_pending.num_rows() != copy_of_con_sys.num_rows() 00805 || cs_without_pending.num_equalities() 00806 != copy_of_con_sys.num_equalities()) { 00807 #ifndef NDEBUG 00808 cerr << "Constraints are declared minimized, but they are not!\n" 00809 << "Here is the minimized form of the constraints:\n"; 00810 copy_of_con_sys.ascii_dump(cerr); 00811 cerr << endl; 00812 #endif 00813 goto bomb; 00814 } 00815 // The system `copy_of_con_sys' has the form that is obtained 00816 // after applying methods gauss() and back_substitute(). 00817 // A system of constraints can be minimal even if it does not 00818 // have this form. So, to verify if the polyhedron is correct, 00819 // we copy the system `con_sys' in a temporary one and then 00820 // modify it using method simplify() (which calls both gauss() 00821 // and back_substitute()). 00822 // If the temporary system and `copy_of_con_sys' are different, 00823 // the polyhedron is not OK. 00824 copy_of_con_sys.strong_normalize(); 00825 copy_of_con_sys.sort_rows(); 00826 cs_without_pending.simplify(); 00827 cs_without_pending.strong_normalize(); 00828 cs_without_pending.sort_rows(); 00829 if (cs_without_pending != copy_of_con_sys) { 00830 #ifndef NDEBUG 00831 cerr << "Constraints are declared minimized, but they are not!\n" 00832 << "Here is the minimized form of the constraints:\n"; 00833 copy_of_con_sys.ascii_dump(cerr); 00834 cerr << endl; 00835 #endif 00836 goto bomb; 00837 } 00838 } 00839 } 00840 00841 if (sat_c_is_up_to_date()) 00842 for (dimension_type i = sat_c.num_rows(); i-- > 0; ) { 00843 const Generator tmp_gen = gen_sys[i]; 00844 const Saturation_Row tmp_sat = sat_c[i]; 00845 for (dimension_type j = sat_c.num_columns(); j-- > 0; ) 00846 if (Scalar_Products::sign(con_sys[j], tmp_gen) != tmp_sat[j]) { 00847 #ifndef NDEBUG 00848 cerr << "sat_c is declared up-to-date, but it is not!" 00849 << endl; 00850 #endif 00851 goto bomb; 00852 } 00853 } 00854 00855 if (sat_g_is_up_to_date()) 00856 for (dimension_type i = sat_g.num_rows(); i-- > 0; ) { 00857 const Constraint tmp_con = con_sys[i]; 00858 const Saturation_Row tmp_sat = sat_g[i]; 00859 for (dimension_type j = sat_g.num_columns(); j-- > 0; ) 00860 if (Scalar_Products::sign(tmp_con, gen_sys[j]) != tmp_sat[j]) { 00861 #ifndef NDEBUG 00862 cerr << "sat_g is declared up-to-date, but it is not!" 00863 << endl; 00864 #endif 00865 goto bomb; 00866 } 00867 } 00868 00869 if (has_pending_constraints()) { 00870 if (con_sys.num_pending_rows() == 0) { 00871 #ifndef NDEBUG 00872 cerr << "The polyhedron is declared to have pending constraints, " 00873 << "but con_sys has no pending rows!" 00874 << endl; 00875 #endif 00876 goto bomb; 00877 } 00878 } 00879 00880 if (has_pending_generators()) { 00881 if (gen_sys.num_pending_rows() == 0) { 00882 #ifndef NDEBUG 00883 cerr << "The polyhedron is declared to have pending generators, " 00884 << "but gen_sys has no pending rows!" 00885 << endl; 00886 #endif 00887 goto bomb; 00888 } 00889 } 00890 00891 return true; 00892 00893 bomb: 00894 #ifndef NDEBUG 00895 cerr << "Here is the guilty polyhedron:" 00896 << endl; 00897 ascii_dump(cerr); 00898 #endif 00899 return false; 00900 }
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).
std::invalid_argument | Thrown if *this and constraint c are topology-incompatible or dimension-incompatible. |
Definition at line 903 of file Polyhedron_public.cc.
References can_have_something_pending(), clear_constraints_minimized(), clear_generators_up_to_date(), con_sys, constraints_are_up_to_date(), has_pending_generators(), Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::Constraint_System::insert_pending(), Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Linear_Row::is_necessarily_closed(), is_necessarily_closed(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::Constraint::is_tautological(), marked_empty(), OK(), process_pending_generators(), set_constraints_pending(), set_empty(), space_dim, Parma_Polyhedra_Library::Constraint::space_dimension(), throw_dimension_incompatible(), throw_topology_incompatible(), and update_constraints().
Referenced by add_congruence(), bounded_affine_image(), bounded_affine_preimage(), Parma_Polyhedra_Library::C_Polyhedron::C_Polyhedron(), generalized_affine_image(), generalized_affine_preimage(), poly_difference_assign(), and ppl_Polyhedron_add_constraint().
00903 { 00904 // Topology-compatibility check. 00905 if (c.is_strict_inequality() && is_necessarily_closed()) 00906 throw_topology_incompatible("add_constraint(c)", "c", c); 00907 // Dimension-compatibility check: 00908 // the dimension of `c' can not be greater than space_dim. 00909 if (space_dim < c.space_dimension()) 00910 throw_dimension_incompatible("add_constraint(c)", "c", c); 00911 00912 // Adding a new constraint to an empty polyhedron 00913 // results in an empty polyhedron. 00914 if (marked_empty()) 00915 return; 00916 00917 // Dealing with a zero-dimensional space polyhedron first. 00918 if (space_dim == 0) { 00919 if (!c.is_tautological()) 00920 set_empty(); 00921 return; 00922 } 00923 00924 // The constraints (possibly with pending rows) are required. 00925 if (has_pending_generators()) 00926 process_pending_generators(); 00927 else if (!constraints_are_up_to_date()) 00928 update_constraints(); 00929 00930 const bool adding_pending = can_have_something_pending(); 00931 00932 // Here we know that the system of constraints has at least a row. 00933 if (c.is_necessarily_closed() || !is_necessarily_closed()) 00934 // Since `con_sys' is not empty, the topology and space dimension 00935 // of the inserted constraint are automatically adjusted. 00936 if (adding_pending) 00937 con_sys.insert_pending(c); 00938 else 00939 con_sys.insert(c); 00940 else { 00941 // Note: here we have a _legal_ topology mismatch, because 00942 // `c' is NOT a strict inequality. 00943 // However, by barely invoking `con_sys.insert(c)' we would 00944 // cause a change in the topology of `con_sys', which is wrong. 00945 // Thus, we insert a "topology corrected" copy of `c'. 00946 Linear_Expression nc_expr = Linear_Expression(c); 00947 if (c.is_equality()) 00948 if (adding_pending) 00949 con_sys.insert_pending(nc_expr == 0); 00950 else 00951 con_sys.insert(nc_expr == 0); 00952 else 00953 if (adding_pending) 00954 con_sys.insert_pending(nc_expr >= 0); 00955 else 00956 con_sys.insert(nc_expr >= 0); 00957 } 00958 00959 if (adding_pending) 00960 set_constraints_pending(); 00961 else { 00962 // Constraints are not minimized and generators are not up-to-date. 00963 clear_constraints_minimized(); 00964 clear_generators_up_to_date(); 00965 } 00966 // Note: the constraint system may have become unsatisfiable, thus 00967 // we do not check for satisfiability. 00968 assert(OK()); 00969 }
bool Parma_Polyhedra_Library::Polyhedron::add_constraint_and_minimize | ( | const Constraint & | c | ) |
Adds a copy of constraint c
to the system of constraints of *this
, minimizing the result.
false
if and only if the result is empty.std::invalid_argument | Thrown if *this and constraint c are topology-incompatible or dimension-incompatible. |
Definition at line 998 of file Polyhedron_public.cc.
References add_recycled_constraints_and_minimize().
Referenced by bounded_affine_image(), generalized_affine_image(), generalized_affine_preimage(), Parma_Polyhedra_Library::Polyhedra_Powerset< PH >::linear_partition_aux(), and ppl_Polyhedron_add_constraint_and_minimize().
00998 { 00999 // TODO: this is just an executable specification. 01000 Constraint_System cs(c); 01001 return add_recycled_constraints_and_minimize(cs); 01002 }
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 1005 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Generator_System::adjust_topology_and_space_dimension(), can_have_something_pending(), clear_constraints_up_to_date(), clear_empty(), clear_generators_minimized(), Parma_Polyhedra_Library::Generator::divisor(), gen_sys, generators_are_up_to_date(), has_pending_constraints(), Parma_Polyhedra_Library::Generator_System::insert(), Parma_Polyhedra_Library::Generator_System::insert_pending(), Parma_Polyhedra_Library::Generator::is_closure_point(), Parma_Polyhedra_Library::Linear_Row::is_necessarily_closed(), is_necessarily_closed(), Parma_Polyhedra_Library::Generator::is_point(), Parma_Polyhedra_Library::Generator::line(), Parma_Polyhedra_Library::Generator::LINE, marked_empty(), Parma_Polyhedra_Library::Row::normalize(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), Parma_Polyhedra_Library::Generator::point(), Parma_Polyhedra_Library::Generator::POINT, process_pending_constraints(), Parma_Polyhedra_Library::Generator::ray(), Parma_Polyhedra_Library::Generator::RAY, set_generators_minimized(), set_generators_pending(), Parma_Polyhedra_Library::Polyhedron::Status::set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Generator::space_dimension(), status, throw_dimension_incompatible(), throw_invalid_generator(), throw_runtime_error(), throw_topology_incompatible(), topology(), Parma_Polyhedra_Library::Generator::type(), and update_generators().
Referenced by bounded_affine_preimage(), generalized_affine_image(), generalized_affine_preimage(), and ppl_Polyhedron_add_generator().
01005 { 01006 // Topology-compatibility check. 01007 if (g.is_closure_point() && is_necessarily_closed()) 01008 throw_topology_incompatible("add_generator(g)", "g", g); 01009 // Dimension-compatibility check: 01010 // the dimension of `g' can not be greater than space_dim. 01011 const dimension_type g_space_dim = g.space_dimension(); 01012 if (space_dim < g_space_dim) 01013 throw_dimension_incompatible("add_generator(g)", "g", g); 01014 01015 // Dealing with a zero-dimensional space polyhedron first. 01016 if (space_dim == 0) { 01017 // It is not possible to create 0-dim rays or lines. 01018 assert(g.is_point() || g.is_closure_point()); 01019 // Closure points can only be inserted in non-empty polyhedra. 01020 if (marked_empty()) 01021 if (g.type() != Generator::POINT) 01022 throw_invalid_generator("add_generator(g)", "g"); 01023 else 01024 status.set_zero_dim_univ(); 01025 assert(OK()); 01026 return; 01027 } 01028 01029 if (marked_empty() 01030 || (has_pending_constraints() && !process_pending_constraints()) 01031 || (!generators_are_up_to_date() && !update_generators())) { 01032 // Here the polyhedron is empty: 01033 // the specification says we can only insert a point. 01034 if (!g.is_point()) 01035 throw_invalid_generator("add_generator(g)", "g"); 01036 if (g.is_necessarily_closed() || !is_necessarily_closed()) { 01037 gen_sys.insert(g); 01038 // Since `gen_sys' was empty, after inserting `g' we have to resize 01039 // the system of generators to have the right dimension. 01040 gen_sys.adjust_topology_and_space_dimension(topology(), space_dim); 01041 if (!is_necessarily_closed()) { 01042 // In the NNC topology, each point has to be matched by 01043 // a corresponding closure point: 01044 // turn the just inserted point into the corresponding 01045 // (normalized) closure point. 01046 Generator& cp = gen_sys[gen_sys.num_rows() - 1]; 01047 cp[space_dim + 1] = 0; 01048 cp.normalize(); 01049 // Re-insert the point (which is already normalized). 01050 gen_sys.insert(g); 01051 } 01052 } 01053 else { 01054 // Note: here we have a _legal_ topology mismatch, 01055 // because `g' is NOT a closure point (it is a point!) 01056 // However, by barely invoking `gen_sys.insert(g)' we would 01057 // cause a change in the topology of `gen_sys', which is wrong. 01058 // Thus, we insert a "topology corrected" copy of `g'. 01059 const Linear_Expression nc_expr = Linear_Expression(g); 01060 gen_sys.insert(Generator::point(nc_expr, g.divisor())); 01061 // Since `gen_sys' was empty, after inserting `g' we have to resize 01062 // the system of generators to have the right dimension. 01063 gen_sys.adjust_topology_and_space_dimension(topology(), space_dim); 01064 } 01065 // No longer empty, generators up-to-date and minimized. 01066 clear_empty(); 01067 set_generators_minimized(); 01068 } 01069 else { 01070 assert(generators_are_up_to_date()); 01071 const bool has_pending = can_have_something_pending(); 01072 if (g.is_necessarily_closed() || !is_necessarily_closed()) { 01073 // Since `gen_sys' is not empty, the topology and space dimension 01074 // of the inserted generator are automatically adjusted. 01075 if (has_pending) 01076 gen_sys.insert_pending(g); 01077 else 01078 gen_sys.insert(g); 01079 if (!is_necessarily_closed() && g.is_point()) { 01080 // In the NNC topology, each point has to be matched by 01081 // a corresponding closure point: 01082 // turn the just inserted point into the corresponding 01083 // (normalized) closure point. 01084 Generator& cp = gen_sys[gen_sys.num_rows() - 1]; 01085 cp[space_dim + 1] = 0; 01086 cp.normalize(); 01087 // Re-insert the point (which is already normalized). 01088 if (has_pending) 01089 gen_sys.insert_pending(g); 01090 else 01091 gen_sys.insert(g); 01092 } 01093 } 01094 else { 01095 assert(!g.is_closure_point()); 01096 // Note: here we have a _legal_ topology mismatch, because 01097 // `g' is NOT a closure point. 01098 // However, by barely invoking `gen_sys.insert(g)' we would 01099 // cause a change in the topology of `gen_sys', which is wrong. 01100 // Thus, we insert a "topology corrected" copy of `g'. 01101 const Linear_Expression nc_expr = Linear_Expression(g); 01102 switch (g.type()) { 01103 case Generator::LINE: 01104 if (has_pending) 01105 gen_sys.insert_pending(Generator::line(nc_expr)); 01106 else 01107 gen_sys.insert(Generator::line(nc_expr)); 01108 break; 01109 case Generator::RAY: 01110 if (has_pending) 01111 gen_sys.insert_pending(Generator::ray(nc_expr)); 01112 else 01113 gen_sys.insert(Generator::ray(nc_expr)); 01114 break; 01115 case Generator::POINT: 01116 if (has_pending) 01117 gen_sys.insert_pending(Generator::point(nc_expr, g.divisor())); 01118 else 01119 gen_sys.insert(Generator::point(nc_expr, g.divisor())); 01120 break; 01121 default: 01122 throw_runtime_error("add_generator(const Generator& g)"); 01123 } 01124 } 01125 01126 if (has_pending) 01127 set_generators_pending(); 01128 else { 01129 // After adding the new generator, 01130 // constraints are no longer up-to-date. 01131 clear_generators_minimized(); 01132 clear_constraints_up_to_date(); 01133 } 01134 } 01135 assert(OK()); 01136 }
bool Parma_Polyhedra_Library::Polyhedron::add_generator_and_minimize | ( | const Generator & | g | ) |
Adds a copy of generator g
to the system of generators of *this
, minimizing the result.
false
if and only if the result is empty.std::invalid_argument | Thrown if *this and generator g are topology-incompatible or dimension-incompatible, or if *this is an empty polyhedron and g is not a point. |
Definition at line 1139 of file Polyhedron_public.cc.
References add_recycled_generators_and_minimize().
Referenced by generalized_affine_image(), and ppl_Polyhedron_add_generator_and_minimize().
01139 { 01140 // TODO: this is just an executable specification. 01141 Generator_System gs(g); 01142 return add_recycled_generators_and_minimize(gs); 01143 }
void Parma_Polyhedra_Library::Polyhedron::add_congruence | ( | const Congruence & | cg | ) |
Adds a copy of congruence cg
to the system of congruences of this
(without minimizing the result).
std::invalid_argument | Thrown if *this and congruence cg are topology-incompatible or dimension-incompatible. |
Definition at line 972 of file Polyhedron_public.cc.
References add_constraint(), Parma_Polyhedra_Library::Constraint::EQUALITY, Parma_Polyhedra_Library::Congruence::is_equality(), Parma_Polyhedra_Library::Congruence::is_trivial_true(), marked_empty(), Parma_Polyhedra_Library::NECESSARILY_CLOSED, set_empty(), space_dim, Parma_Polyhedra_Library::Congruence::space_dimension(), and throw_dimension_incompatible().
00972 { 00973 // Dimension-compatibility check: 00974 // the dimension of `cg' can not be greater than space_dim. 00975 if (space_dim < cg.space_dimension()) 00976 throw_dimension_incompatible("add_congruence(cg)", "cg", cg); 00977 00978 // Adding a new congruence to an empty polyhedron results in an 00979 // empty polyhedron. 00980 if (marked_empty()) 00981 return; 00982 00983 // Dealing with a zero-dimensional space polyhedron first. 00984 if (space_dim == 0) { 00985 if (!cg.is_trivial_true()) 00986 set_empty(); 00987 return; 00988 } 00989 00990 if (cg.is_equality()) { 00991 Linear_Expression le(cg); 00992 Constraint c(le, Constraint::EQUALITY, NECESSARILY_CLOSED); 00993 add_constraint(c); 00994 } 00995 }
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 1226 of file Polyhedron_public.cc.
References add_recycled_constraints().
Referenced by bounded_BHRZ03_extrapolation_assign(), bounded_H79_extrapolation_assign(), expand_space_dimension(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), Parma_Polyhedra_Library::NNC_Polyhedron::NNC_Polyhedron(), and ppl_Polyhedron_add_constraints().
01226 { 01227 // TODO: this is just an executable specification. 01228 Constraint_System cs_copy = cs; 01229 add_recycled_constraints(cs_copy); 01230 }
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 that will be recycled, adding its constraints to the system of constraints of *this . |
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 1146 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(), 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(), Parma_Polyhedra_Library::Constraint::set_is_equality(), Parma_Polyhedra_Library::Linear_System::set_sorted(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), status, throw_dimension_incompatible(), throw_topology_incompatible(), topology(), Parma_Polyhedra_Library::Linear_System::unset_pending_rows(), and update_constraints().
Referenced by add_congruences(), add_constraints(), H79_widening_assign(), and ppl_Polyhedron_add_recycled_constraints().
01146 { 01147 // Topology compatibility check. 01148 if (is_necessarily_closed() && cs.has_strict_inequalities()) 01149 throw_topology_incompatible("add_constraints(cs)", "cs", cs); 01150 // Dimension-compatibility check: 01151 // the dimension of `cs' can not be greater than space_dim. 01152 const dimension_type cs_space_dim = cs.space_dimension(); 01153 if (space_dim < cs_space_dim) 01154 throw_dimension_incompatible("add_recycled_constraints(cs)", "cs", cs); 01155 01156 // Adding no constraints is a no-op. 01157 if (cs.num_rows() == 0) 01158 return; 01159 01160 if (space_dim == 0) { 01161 // In a 0-dimensional space the constraints are 01162 // tautologies (e.g., 0 == 0 or 1 >= 0 or 1 > 0) or 01163 // inconsistent (e.g., 1 == 0 or -1 >= 0 or 0 > 0). 01164 // In a system of constraints `begin()' and `end()' are equal 01165 // if and only if the system only contains tautologies. 01166 if (cs.begin() != cs.end()) 01167 // There is a constraint, it must be inconsistent, 01168 // the polyhedron is empty. 01169 status.set_empty(); 01170 return; 01171 } 01172 01173 if (marked_empty()) 01174 return; 01175 01176 // The constraints (possibly with pending rows) are required. 01177 if (has_pending_generators()) 01178 process_pending_generators(); 01179 else if (!constraints_are_up_to_date()) 01180 update_constraints(); 01181 01182 // Adjust `cs' to the right topology and space dimension. 01183 // NOTE: we already checked for topology compatibility. 01184 cs.adjust_topology_and_space_dimension(topology(), space_dim); 01185 01186 const bool adding_pending = can_have_something_pending(); 01187 01188 // Here we do not require `con_sys' to be sorted. 01189 // also, we _swap_ (instead of copying) the coefficients of `cs' 01190 // (which is not a const). 01191 const dimension_type old_num_rows = con_sys.num_rows(); 01192 const dimension_type cs_num_rows = cs.num_rows(); 01193 const dimension_type cs_num_columns = cs.num_columns(); 01194 con_sys.add_zero_rows(cs_num_rows, 01195 Linear_Row::Flags(topology(), 01196 Linear_Row::RAY_OR_POINT_OR_INEQUALITY)); 01197 for (dimension_type i = cs_num_rows; i-- > 0; ) { 01198 // NOTE: we cannot directly swap the rows, since they might have 01199 // different capacities (besides possibly having different sizes): 01200 // thus, we steal one coefficient at a time. 01201 Constraint& new_c = con_sys[old_num_rows + i]; 01202 Constraint& old_c = cs[i]; 01203 if (old_c.is_equality()) 01204 new_c.set_is_equality(); 01205 for (dimension_type j = cs_num_columns; j-- > 0; ) 01206 std::swap(new_c[j], old_c[j]); 01207 } 01208 01209 if (adding_pending) 01210 set_constraints_pending(); 01211 else { 01212 // The newly added ones are not pending constraints. 01213 con_sys.unset_pending_rows(); 01214 // They have been simply appended. 01215 con_sys.set_sorted(false); 01216 // Constraints are not minimized and generators are not up-to-date. 01217 clear_constraints_minimized(); 01218 clear_generators_up_to_date(); 01219 } 01220 // Note: the constraint system may have become unsatisfiable, thus 01221 // we do not check for satisfiability. 01222 assert(OK()); 01223 }
bool Parma_Polyhedra_Library::Polyhedron::add_constraints_and_minimize | ( | const Constraint_System & | cs | ) |
Adds a copy of the constraints in cs
to the system of constraints of *this
, minimizing the result.
false
if and only if the result is empty.cs | Contains the constraints that will be added to the system of constraints of *this . |
std::invalid_argument | Thrown if *this and cs are topology-incompatible or dimension-incompatible. |
Definition at line 1299 of file Polyhedron_public.cc.
References add_recycled_constraints_and_minimize().
Referenced by ppl_Polyhedron_add_constraints_and_minimize().
01299 { 01300 // TODO: this is just an executable specification. 01301 Constraint_System cs_copy = cs; 01302 return add_recycled_constraints_and_minimize(cs_copy); 01303 }
bool Parma_Polyhedra_Library::Polyhedron::add_recycled_constraints_and_minimize | ( | Constraint_System & | cs | ) |
Adds the constraints in cs
to the system of constraints of *this
, minimizing the result.
false
if and only if the result is empty.cs | The constraint system that will be recycled, adding its constraints to the system of constraints of *this . |
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 1233 of file Polyhedron_public.cc.
References add_and_minimize(), Parma_Polyhedra_Library::Constraint_System::adjust_topology_and_space_dimension(), Parma_Polyhedra_Library::Constraint_System::begin(), clear_sat_g_up_to_date(), con_sys, empty, Parma_Polyhedra_Library::Constraint_System::end(), gen_sys, Parma_Polyhedra_Library::Constraint_System::has_strict_inequalities(), is_necessarily_closed(), Parma_Polyhedra_Library::Linear_System::is_sorted(), minimize(), Parma_Polyhedra_Library::Linear_System::num_pending_rows(), Parma_Polyhedra_Library::Matrix::num_rows(), obtain_sorted_constraints_with_sat_c(), OK(), sat_c, set_empty(), Parma_Polyhedra_Library::Polyhedron::Status::set_empty(), set_sat_c_up_to_date(), Parma_Polyhedra_Library::Linear_System::sort_rows(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), status, throw_dimension_incompatible(), throw_topology_incompatible(), topology(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
Referenced by add_constraint_and_minimize(), add_constraints_and_minimize(), BHRZ03_combining_constraints(), and ppl_Polyhedron_add_recycled_constraints_and_minimize().
01233 { 01234 // Topology-compatibility check. 01235 if (is_necessarily_closed() && cs.has_strict_inequalities()) 01236 throw_topology_incompatible("add_recycled_constraints_and_minimize(cs)", 01237 "cs", cs); 01238 // Dimension-compatibility check: 01239 // the dimension of `cs' can not be greater than space_dim. 01240 const dimension_type cs_space_dim = cs.space_dimension(); 01241 if (space_dim < cs_space_dim) 01242 throw_dimension_incompatible("add_recycled_constraints_and_minimize(cs)", 01243 "cs", cs); 01244 01245 // Adding no constraints: just minimize. 01246 if (cs.num_rows() == 0) 01247 return minimize(); 01248 01249 // Dealing with zero-dimensional space polyhedra first. 01250 if (space_dim == 0) { 01251 // In a 0-dimensional space the constraints are 01252 // tautologies (e.g., 0 == 0 or 1 >= 0 or 1 > 0) or 01253 // inconsistent (e.g., 1 == 0 or -1 >= 0 or 0 > 0). 01254 // In a system of constraints `begin()' and `end()' are equal 01255 // if and only if the system only contains tautologies. 01256 if (cs.begin() == cs.end()) 01257 return true; 01258 // There is a constraint, it must be inconsistent, 01259 // the polyhedron is empty. 01260 status.set_empty(); 01261 return false; 01262 } 01263 01264 // The polyhedron must be minimized and have sorted constraints. 01265 // `minimize()' will process any pending constraints or generators. 01266 if (!minimize()) 01267 // We have just discovered that `x' is empty. 01268 return false; 01269 // Fully sort the system of constraints for `x'. 01270 obtain_sorted_constraints_with_sat_c(); 01271 01272 // Fully sort the system of constraints to be added 01273 // (before adjusting dimensions in order to save time). 01274 if (cs.num_pending_rows() > 0) { 01275 cs.unset_pending_rows(); 01276 cs.sort_rows(); 01277 } 01278 else if (!cs.is_sorted()) 01279 cs.sort_rows(); 01280 // Adjust `cs' to the right topology and space dimension. 01281 // NOTE: we already checked for topology compatibility. 01282 cs.adjust_topology_and_space_dimension(topology(), space_dim); 01283 01284 const bool empty = add_and_minimize(true, con_sys, gen_sys, sat_c, cs); 01285 01286 if (empty) 01287 set_empty(); 01288 else { 01289 // `sat_c' is up-to-date, while `sat_g' is no longer up-to-date. 01290 set_sat_c_up_to_date(); 01291 clear_sat_g_up_to_date(); 01292 } 01293 assert(OK()); 01294 01295 return !empty; 01296 }
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 1399 of file Polyhedron_public.cc.
References add_recycled_generators().
Referenced by ppl_Polyhedron_add_generators().
01399 { 01400 // TODO: this is just an executable specification. 01401 Generator_System gs_copy = gs; 01402 add_recycled_generators(gs_copy); 01403 }
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 that will be recycled, adding its generators 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. |
gs
upon successful or exceptional return is that it can be safely destroyed. Definition at line 1306 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(), has_pending_constraints(), Parma_Polyhedra_Library::Generator_System::has_points(), Parma_Polyhedra_Library::Generator::is_line(), is_necessarily_closed(), marked_empty(), minimize(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Linear_System::num_pending_rows(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), process_pending_constraints(), Parma_Polyhedra_Library::Linear_Row::RAY_OR_POINT_OR_INEQUALITY, set_generators_pending(), set_generators_up_to_date(), Parma_Polyhedra_Library::Generator::set_is_line(), Parma_Polyhedra_Library::Linear_System::set_sorted(), Parma_Polyhedra_Library::Polyhedron::Status::set_zero_dim_univ(), space_dim, Parma_Polyhedra_Library::Generator_System::space_dimension(), status, throw_dimension_incompatible(), throw_invalid_generators(), throw_topology_incompatible(), topology(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
Referenced by add_generators(), generalized_affine_preimage(), and ppl_Polyhedron_add_recycled_generators().
01306 { 01307 // Topology compatibility check. 01308 if (is_necessarily_closed() && gs.has_closure_points()) 01309 throw_topology_incompatible("add_recycled_generators(gs)", "gs", gs); 01310 // Dimension-compatibility check: 01311 // the dimension of `gs' can not be greater than space_dim. 01312 const dimension_type gs_space_dim = gs.space_dimension(); 01313 if (space_dim < gs_space_dim) 01314 throw_dimension_incompatible("add_recycled_generators(gs)", "gs", gs); 01315 01316 // Adding no generators is a no-op. 01317 if (gs.num_rows() == 0) 01318 return; 01319 01320 // Adding valid generators to a zero-dimensional polyhedron 01321 // transform it in the zero-dimensional universe polyhedron. 01322 if (space_dim == 0) { 01323 if (marked_empty() && !gs.has_points()) 01324 throw_invalid_generators("add_recycled_generators(gs)", "gs"); 01325 status.set_zero_dim_univ(); 01326 assert(OK(true)); 01327 return; 01328 } 01329 01330 // Adjust `gs' to the right topology and dimensions. 01331 // NOTE: we already checked for topology compatibility. 01332 gs.adjust_topology_and_space_dimension(topology(), space_dim); 01333 // For NNC polyhedra, each point must be matched by 01334 // the corresponding closure point. 01335 if (!is_necessarily_closed()) 01336 gs.add_corresponding_closure_points(); 01337 01338 // The generators (possibly with pending rows) are required. 01339 if ((has_pending_constraints() && !process_pending_constraints()) 01340 || (!generators_are_up_to_date() && !minimize())) { 01341 // We have just discovered that `*this' is empty. 01342 // So `gs' must contain at least one point. 01343 if (!gs.has_points()) 01344 throw_invalid_generators("add_recycled_generators(gs)", "gs"); 01345 // The polyhedron is no longer empty and generators are up-to-date. 01346 std::swap(gen_sys, gs); 01347 if (gen_sys.num_pending_rows() > 0) { 01348 // Even though `gs' has pending generators, since the constraints 01349 // of the polyhedron are not up-to-date, the polyhedron cannot 01350 // have pending generators. By integrating the pending part 01351 // of `gen_sys' we may loose sortedness. 01352 gen_sys.unset_pending_rows(); 01353 gen_sys.set_sorted(false); 01354 } 01355 set_generators_up_to_date(); 01356 clear_empty(); 01357 assert(OK()); 01358 return; 01359 } 01360 01361 const bool adding_pending = can_have_something_pending(); 01362 01363 // Here we do not require `gen_sys' to be sorted. 01364 // also, we _swap_ (instead of copying) the coefficients of `gs' 01365 // (which is not a const). 01366 const dimension_type old_num_rows = gen_sys.num_rows(); 01367 const dimension_type gs_num_rows = gs.num_rows(); 01368 const dimension_type gs_num_columns = gs.num_columns(); 01369 gen_sys.add_zero_rows(gs_num_rows, 01370 Linear_Row::Flags(topology(), 01371 Linear_Row::RAY_OR_POINT_OR_INEQUALITY)); 01372 for (dimension_type i = gs_num_rows; i-- > 0; ) { 01373 // NOTE: we cannot directly swap the rows, since they might have 01374 // different capacities (besides possibly having different sizes): 01375 // thus, we steal one coefficient at a time. 01376 Generator& new_g = gen_sys[old_num_rows + i]; 01377 Generator& old_g = gs[i]; 01378 if (old_g.is_line()) 01379 new_g.set_is_line(); 01380 for (dimension_type j = gs_num_columns; j-- > 0; ) 01381 std::swap(new_g[j], old_g[j]); 01382 } 01383 01384 if (adding_pending) 01385 set_generators_pending(); 01386 else { 01387 // The newly added ones are not pending generators. 01388 gen_sys.unset_pending_rows(); 01389 // They have been simply appended. 01390 gen_sys.set_sorted(false); 01391 // Constraints are not up-to-date and generators are not minimized. 01392 clear_constraints_up_to_date(); 01393 clear_generators_minimized(); 01394 } 01395 assert(OK(true)); 01396 }
bool Parma_Polyhedra_Library::Polyhedron::add_generators_and_minimize | ( | const Generator_System & | gs | ) |
Adds a copy of the generators in gs
to the system of generators of *this
, minimizing the result.
false
if and only if the result is empty.gs | Contains the generators that will be added to the system of generators of *this . |
std::invalid_argument | Thrown if *this and gs are topology-incompatible or dimension-incompatible, or if *this is empty and the the system of generators gs is not empty, but has no points. |
Definition at line 1480 of file Polyhedron_public.cc.
References add_recycled_generators_and_minimize().
Referenced by ppl_Polyhedron_add_generators_and_minimize().
01480 { 01481 // TODO: this is just an executable specification. 01482 Generator_System gs_copy = gs; 01483 return add_recycled_generators_and_minimize(gs_copy); 01484 }
bool Parma_Polyhedra_Library::Polyhedron::add_recycled_generators_and_minimize | ( | Generator_System & | gs | ) |
Adds the generators in gs
to the system of generators of *this
, minimizing the result.
false
if and only if the result is empty.gs | The generator system that will be recycled, adding its generators to the system of generators of *this . |
std::invalid_argument | Thrown if *this and gs are topology-incompatible or dimension-incompatible, or if *this is empty and the the system of generators gs is not empty, but has no points. |
gs
upon successful or exceptional return is that it can be safely destroyed. Definition at line 1406 of file Polyhedron_public.cc.
References add_and_minimize(), Parma_Polyhedra_Library::Generator_System::add_corresponding_closure_points(), Parma_Polyhedra_Library::Generator_System::adjust_topology_and_space_dimension(), clear_empty(), clear_sat_c_up_to_date(), con_sys, gen_sys, Parma_Polyhedra_Library::Generator_System::has_closure_points(), Parma_Polyhedra_Library::Generator_System::has_points(), is_necessarily_closed(), Parma_Polyhedra_Library::Linear_System::is_sorted(), marked_empty(), minimize(), Parma_Polyhedra_Library::Linear_System::num_pending_rows(), Parma_Polyhedra_Library::Matrix::num_rows(), obtain_sorted_generators_with_sat_g(), OK(), sat_g, set_generators_up_to_date(), Parma_Polyhedra_Library::Polyhedron::Status::set_zero_dim_univ(), Parma_Polyhedra_Library::Linear_System::sort_rows(), space_dim, Parma_Polyhedra_Library::Generator_System::space_dimension(), status, throw_dimension_incompatible(), throw_invalid_generators(), throw_topology_incompatible(), topology(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
Referenced by add_generator_and_minimize(), add_generators_and_minimize(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), generalized_affine_image(), generalized_affine_preimage(), and ppl_Polyhedron_add_recycled_generators_and_minimize().
01406 { 01407 // Topology compatibility check. 01408 if (is_necessarily_closed() && gs.has_closure_points()) 01409 throw_topology_incompatible("add_recycled_generators_and_minimize(gs)", 01410 "gs", gs); 01411 // Dimension-compatibility check: 01412 // the dimension of `gs' can not be greater than space_dim. 01413 const dimension_type gs_space_dim = gs.space_dimension(); 01414 if (space_dim < gs_space_dim) 01415 throw_dimension_incompatible("add_recycled_generators_and_minimize(gs)", 01416 "gs", gs); 01417 01418 // Adding no generators is equivalent to just requiring minimization. 01419 if (gs.num_rows() == 0) 01420 return minimize(); 01421 01422 // Adding valid generators to a zero-dimensional polyhedron 01423 // transform it in the zero-dimensional universe polyhedron. 01424 if (space_dim == 0) { 01425 if (marked_empty() && !gs.has_points()) 01426 throw_invalid_generators("add_recycled_generators_and_minimize(gs)", 01427 "gs"); 01428 status.set_zero_dim_univ(); 01429 assert(OK(true)); 01430 return true; 01431 } 01432 01433 // Adjust `gs' to the right topology. 01434 // NOTE: we already checked for topology compatibility; 01435 // also, we do NOT adjust dimensions now, so that we will 01436 // spend less time to sort rows. 01437 gs.adjust_topology_and_space_dimension(topology(), gs_space_dim); 01438 01439 // For NNC polyhedra, each point must be matched by 01440 // the corresponding closure point. 01441 if (!is_necessarily_closed()) 01442 gs.add_corresponding_closure_points(); 01443 01444 // `gs' has to be fully sorted, thus it cannot have pending rows. 01445 if (gs.num_pending_rows() > 0) { 01446 gs.unset_pending_rows(); 01447 gs.sort_rows(); 01448 } 01449 else if (!gs.is_sorted()) 01450 gs.sort_rows(); 01451 01452 // Now adjusting dimensions (topology already adjusted). 01453 // NOTE: sortedness is preserved. 01454 gs.adjust_topology_and_space_dimension(topology(), space_dim); 01455 01456 if (minimize()) { 01457 obtain_sorted_generators_with_sat_g(); 01458 // This call to `add_and_minimize(...)' cannot return `false'. 01459 add_and_minimize(false, gen_sys, con_sys, sat_g, gs); 01460 clear_sat_c_up_to_date(); 01461 } 01462 else { 01463 // The polyhedron was empty: check if `gs' contains a point. 01464 if (!gs.has_points()) 01465 throw_invalid_generators("add_recycled_generators_and_minimize(gs)", 01466 "gs"); 01467 // `gs' has a point: the polyhedron is no longer empty 01468 // and generators are up-to-date. 01469 std::swap(gen_sys, gs); 01470 clear_empty(); 01471 set_generators_up_to_date(); 01472 // This call to `minimize()' cannot return `false'. 01473 minimize(); 01474 } 01475 assert(OK(true)); 01476 return true; 01477 }
void Parma_Polyhedra_Library::Polyhedron::add_congruences | ( | const Congruence_System & | cgs | ) |
Adds to *this
constraints equivalent to the congruences in cgs
(without minimizing the result).
cgs | Contains the congruences that will be added to the system of constraints of *this . |
std::invalid_argument | Thrown if *this and cgs are topology-incompatible or dimension-incompatible. |
Definition at line 1487 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::NECESSARILY_CLOSED, space_dim, Parma_Polyhedra_Library::Congruence_System::space_dimension(), and throw_dimension_incompatible().
Referenced by Parma_Polyhedra_Library::C_Polyhedron::C_Polyhedron(), and Parma_Polyhedra_Library::NNC_Polyhedron::NNC_Polyhedron().
01487 { 01488 // Dimension-compatibility check: 01489 // the dimension of `cgs' can not be greater than space_dim. 01490 if (space_dim < cgs.space_dimension()) 01491 throw_dimension_incompatible("add_congruences(cgs)", "cgs", cgs); 01492 01493 Constraint_System cs; 01494 bool inserted = false; 01495 for (Congruence_System::const_iterator i = cgs.begin(), 01496 cgs_end = cgs.end(); i != cgs_end; ++i) 01497 if (i->is_equality()) { 01498 Linear_Expression le(*i); 01499 Constraint c(le, Constraint::EQUALITY, NECESSARILY_CLOSED); 01500 // FIXME: Steal the row in c when adding it to cs. 01501 cs.insert(c); 01502 inserted = true; 01503 } 01504 // Only add cgs if congruences were inserted into cgs, as the 01505 // dimension of cs must be at most that of the polyhedron. 01506 if (inserted) 01507 add_recycled_constraints(cs); 01508 }
void Parma_Polyhedra_Library::Polyhedron::intersection_assign | ( | const Polyhedron & | y | ) |
Assigns to *this
the intersection of *this
and y
. The result is not guaranteed to be minimized.
std::invalid_argument | Thrown if *this and y are topology-incompatible or dimension-incompatible. |
Definition at line 1511 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 ppl_Polyhedron_intersection_assign().
01511 { 01512 Polyhedron& x = *this; 01513 // Topology compatibility check. 01514 if (x.topology() != y.topology()) 01515 throw_topology_incompatible("intersection_assign(y)", "y", y); 01516 // Dimension-compatibility check. 01517 if (x.space_dim != y.space_dim) 01518 throw_dimension_incompatible("intersection_assign(y)", "y", y); 01519 01520 // If one of the two polyhedra is empty, the intersection is empty. 01521 if (x.marked_empty()) 01522 return; 01523 if (y.marked_empty()) { 01524 x.set_empty(); 01525 return; 01526 } 01527 01528 // If both polyhedra are zero-dimensional, 01529 // then at this point they are necessarily non-empty, 01530 // so that their intersection is non-empty too. 01531 if (x.space_dim == 0) 01532 return; 01533 01534 // Both systems of constraints have to be up-to-date, 01535 // possibly having pending constraints. 01536 if (x.has_pending_generators()) 01537 x.process_pending_generators(); 01538 else if (!x.constraints_are_up_to_date()) 01539 x.update_constraints(); 01540 01541 if (y.has_pending_generators()) 01542 y.process_pending_generators(); 01543 else if (!y.constraints_are_up_to_date()) 01544 y.update_constraints(); 01545 01546 // Here both systems are up-to-date and possibly have pending constraints 01547 // (but they cannot have pending generators). 01548 assert(!x.has_pending_generators() && x.constraints_are_up_to_date()); 01549 assert(!y.has_pending_generators() && y.constraints_are_up_to_date()); 01550 01551 // If `x' can support pending constraints, 01552 // the constraints of `y' are added as pending constraints of `x'. 01553 if (x.can_have_something_pending()) { 01554 x.con_sys.add_pending_rows(y.con_sys); 01555 x.set_constraints_pending(); 01556 } 01557 else { 01558 // `x' cannot support pending constraints. 01559 // If both constraint systems are (fully) sorted, then we can 01560 // merge them; otherwise we simply add the second to the first. 01561 if (x.con_sys.is_sorted() 01562 && y.con_sys.is_sorted() && !y.has_pending_constraints()) 01563 x.con_sys.merge_rows_assign(y.con_sys); 01564 else 01565 x.con_sys.add_rows(y.con_sys); 01566 // Generators are no longer up-to-date and constraints are no 01567 // longer minimized. 01568 x.clear_generators_up_to_date(); 01569 x.clear_constraints_minimized(); 01570 } 01571 assert(x.OK() && y.OK()); 01572 }
bool Parma_Polyhedra_Library::Polyhedron::intersection_assign_and_minimize | ( | const Polyhedron & | y | ) |
Assigns to *this
the intersection of *this
and y
, minimizing the result.
false
if and only if the result is empty.std::invalid_argument | Thrown if *this and y are topology-incompatible or dimension-incompatible. |
Definition at line 1575 of file Polyhedron_public.cc.
References add_and_minimize(), Parma_Polyhedra_Library::Linear_System::add_pending_rows(), clear_pending_constraints(), clear_sat_g_up_to_date(), con_sys, constraints_are_up_to_date(), empty, gen_sys, has_pending_generators(), marked_empty(), minimize(), Parma_Polyhedra_Library::Linear_System::num_pending_rows(), obtain_sorted_constraints(), obtain_sorted_constraints_with_sat_c(), OK(), process_pending_generators(), sat_c, set_empty(), set_sat_c_up_to_date(), Parma_Polyhedra_Library::Linear_System::sort_pending_and_remove_duplicates(), space_dim, throw_dimension_incompatible(), throw_topology_incompatible(), topology(), and update_constraints().
Referenced by BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHRZ03_widening_assign(), H79_widening_assign(), is_disjoint_from(), and ppl_Polyhedron_intersection_assign_and_minimize().
01575 { 01576 Polyhedron& x = *this; 01577 // Topology compatibility check. 01578 if (x.topology() != y.topology()) 01579 throw_topology_incompatible("intersection_assign_and_minimize(y)", 01580 "y", y); 01581 // Dimension-compatibility check. 01582 if (x.space_dim != y.space_dim) 01583 throw_dimension_incompatible("intersection_assign_and_minimize(y)", 01584 "y", y); 01585 01586 // If one of the two polyhedra is empty, the intersection is empty. 01587 if (x.marked_empty()) 01588 return false; 01589 if (y.marked_empty()) { 01590 x.set_empty(); 01591 return false; 01592 } 01593 01594 // If both polyhedra are zero-dimensional, 01595 // then at this point they are necessarily non-empty, 01596 // so that their intersection is non-empty too. 01597 if (x.space_dim == 0) 01598 return true; 01599 01600 // `x' must be minimized and have sorted constraints. 01601 // `minimize()' will process any pending constraints or generators. 01602 if (!x.minimize()) 01603 // We have just discovered that `x' is empty. 01604 return false; 01605 x.obtain_sorted_constraints_with_sat_c(); 01606 01607 // `y' must have updated, possibly pending constraints. 01608 if (y.has_pending_generators()) 01609 y.process_pending_generators(); 01610 else if (!y.constraints_are_up_to_date()) 01611 y.update_constraints(); 01612 01613 bool empty; 01614 if (y.con_sys.num_pending_rows() > 0) { 01615 // Integrate `y.con_sys' as pending constraints of `x', 01616 // sort them in place and then call `add_and_minimize()'. 01617 x.con_sys.add_pending_rows(y.con_sys); 01618 x.con_sys.sort_pending_and_remove_duplicates(); 01619 if (x.con_sys.num_pending_rows() == 0) { 01620 // All pending constraints were duplicates. 01621 x.clear_pending_constraints(); 01622 assert(OK(true)); 01623 return true; 01624 } 01625 empty = add_and_minimize(true, x.con_sys, x.gen_sys, x.sat_c); 01626 } 01627 else { 01628 y.obtain_sorted_constraints(); 01629 empty = add_and_minimize(true, x.con_sys, x.gen_sys, x.sat_c, y.con_sys); 01630 } 01631 01632 if (empty) 01633 x.set_empty(); 01634 else { 01635 // On exit of the function `intersection_assign_and_minimize()' 01636 // the polyhedron is up-to-date and `sat_c' is meaningful. 01637 x.set_sat_c_up_to_date(); 01638 x.clear_sat_g_up_to_date(); 01639 } 01640 assert(x.OK(!empty)); 01641 return !empty; 01642 }
void Parma_Polyhedra_Library::Polyhedron::poly_hull_assign | ( | const Polyhedron & | y | ) |
Assigns to *this
the poly-hull of *this
and y
. The result is not guaranteed to be minimized.
std::invalid_argument | Thrown if *this and y are topology-incompatible or dimension-incompatible. |
Definition at line 1645 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 fold_space_dimensions(), poly_difference_assign(), ppl_Polyhedron_poly_hull_assign(), and upper_bound_assign().
01645 { 01646 Polyhedron& x = *this; 01647 // Topology compatibility check. 01648 if (x.topology() != y.topology()) 01649 throw_topology_incompatible("poly_hull_assign(y)", "y", y); 01650 // Dimension-compatibility check. 01651 if (x.space_dim != y.space_dim) 01652 throw_dimension_incompatible("poly_hull_assign(y)", "y", y); 01653 01654 // The poly-hull of a polyhedron `p' with an empty polyhedron is `p'. 01655 if (y.marked_empty()) 01656 return; 01657 if (x.marked_empty()) { 01658 x = y; 01659 return; 01660 } 01661 01662 // If both polyhedra are zero-dimensional, 01663 // then at this point they are necessarily universe polyhedra, 01664 // so that their poly-hull is the universe polyhedron too. 01665 if (x.space_dim == 0) 01666 return; 01667 01668 // Both systems of generators have to be up-to-date, 01669 // possibly having pending generators. 01670 if ((x.has_pending_constraints() && !x.process_pending_constraints()) 01671 || (!x.generators_are_up_to_date() && !x.update_generators())) { 01672 // Discovered `x' empty when updating generators. 01673 x = y; 01674 return; 01675 } 01676 if ((y.has_pending_constraints() && !y.process_pending_constraints()) 01677 || (!y.generators_are_up_to_date() && !y.update_generators())) 01678 // Discovered `y' empty when updating generators. 01679 return; 01680 01681 // Here both systems are up-to-date and possibly have pending generators 01682 // (but they cannot have pending constraints). 01683 assert(!x.has_pending_constraints() && x.generators_are_up_to_date()); 01684 assert(!y.has_pending_constraints() && y.generators_are_up_to_date()); 01685 01686 // If `x' can support pending generators, 01687 // the generators of `y' are added as pending generators of `x'. 01688 if (x.can_have_something_pending()) { 01689 x.gen_sys.add_pending_rows(y.gen_sys); 01690 x.set_generators_pending(); 01691 } 01692 else { 01693 // `x' cannot support pending generators. 01694 // If both generator systems are (fully) sorted, then we can merge 01695 // them; otherwise we simply add the second to the first. 01696 if (x.gen_sys.is_sorted() 01697 && y.gen_sys.is_sorted() && !y.has_pending_generators()) 01698 x.gen_sys.merge_rows_assign(y.gen_sys); 01699 else 01700 x.gen_sys.add_rows(y.gen_sys); 01701 // Constraints are no longer up-to-date 01702 // and generators are no longer minimized. 01703 x.clear_constraints_up_to_date(); 01704 x.clear_generators_minimized(); 01705 } 01706 // At this point both `x' and `y' are not empty. 01707 assert(x.OK(true) && y.OK(true)); 01708 }
bool Parma_Polyhedra_Library::Polyhedron::poly_hull_assign_and_minimize | ( | const Polyhedron & | y | ) |
Assigns to *this
the poly-hull of *this
and y
, minimizing the result.
false
if and only if the result is empty.std::invalid_argument | Thrown if *this and y are topology-incompatible or dimension-incompatible. |
Definition at line 1711 of file Polyhedron_public.cc.
References add_and_minimize(), Parma_Polyhedra_Library::Linear_System::add_pending_rows(), clear_pending_generators(), clear_sat_c_up_to_date(), con_sys, gen_sys, generators_are_up_to_date(), has_pending_constraints(), marked_empty(), minimize(), Parma_Polyhedra_Library::Linear_System::num_pending_rows(), obtain_sorted_generators(), obtain_sorted_generators_with_sat_g(), OK(), process_pending_constraints(), sat_g, Parma_Polyhedra_Library::Linear_System::sort_pending_and_remove_duplicates(), space_dim, throw_dimension_incompatible(), throw_topology_incompatible(), topology(), and update_generators().
Referenced by ppl_Polyhedron_poly_hull_assign_and_minimize().
01711 { 01712 Polyhedron& x = *this; 01713 // Topology compatibility check. 01714 if (x.topology() != y.topology()) 01715 throw_topology_incompatible("poly_hull_assign_and_minimize(y)", "y", y); 01716 // Dimension-compatibility check. 01717 if (x.space_dim != y.space_dim) 01718 throw_dimension_incompatible("poly_hull_assign_and_minimize(y)", "y", y); 01719 01720 // The poly-hull of a polyhedron `p' with an empty polyhedron is `p'. 01721 if (y.marked_empty()) 01722 return minimize(); 01723 if (x.marked_empty()) { 01724 x = y; 01725 return minimize(); 01726 } 01727 01728 // If both polyhedra are zero-dimensional, 01729 // then at this point they are necessarily universe polyhedra, 01730 // so that their poly-hull is the universe polyhedron too. 01731 if (x.space_dim == 0) 01732 return true; 01733 01734 // `x' must have minimized constraints and generators. 01735 // `minimize()' will process any pending constraints or generators. 01736 if (!x.minimize()) { 01737 // We have just discovered that `x' is empty. 01738 x = y; 01739 return minimize(); 01740 } 01741 // x must have `sat_g' up-to-date and sorted generators. 01742 x.obtain_sorted_generators_with_sat_g(); 01743 01744 // `y' must have updated, possibly pending generators. 01745 if ((y.has_pending_constraints() && !y.process_pending_constraints()) 01746 || (!y.generators_are_up_to_date() && !y.update_generators())) 01747 // We have just discovered that `y' is empty 01748 // (and we know that `x' is not empty). 01749 return true; 01750 01751 if (y.gen_sys.num_pending_rows() > 0) { 01752 // Integrate `y.gen_sys' as pending generators of `x', 01753 // sort them in place and then call `add_and_minimize()'. 01754 x.gen_sys.add_pending_rows(y.gen_sys); 01755 x.gen_sys.sort_pending_and_remove_duplicates(); 01756 if (x.gen_sys.num_pending_rows() == 0) { 01757 // All pending generators were duplicates. 01758 x.clear_pending_generators(); 01759 assert(OK(true) && y.OK()); 01760 return true; 01761 } 01762 add_and_minimize(false, x.gen_sys, x.con_sys, x.sat_g); 01763 } 01764 else { 01765 y.obtain_sorted_generators(); 01766 add_and_minimize(false, x.gen_sys, x.con_sys, x.sat_g, y.gen_sys); 01767 } 01768 x.clear_sat_c_up_to_date(); 01769 01770 assert(x.OK(true) && y.OK()); 01771 return true; 01772 }
void Parma_Polyhedra_Library::Polyhedron::upper_bound_assign | ( | const Polyhedron & | y | ) | [inline] |
Same as poly_hull_assign(y).
Definition at line 71 of file Polyhedron.inlines.hh.
References poly_hull_assign().
00071 { 00072 poly_hull_assign(y); 00073 }
void Parma_Polyhedra_Library::Polyhedron::poly_difference_assign | ( | const Polyhedron & | y | ) |
Assigns to *this
the poly-difference of *this
and y
. The result is not guaranteed to be minimized.
std::invalid_argument | Thrown if *this and y are topology-incompatible or dimension-incompatible. |
Definition at line 1775 of file Polyhedron_public.cc.
References add_constraint(), 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(), 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(), and ppl_Polyhedron_poly_difference_assign().
01775 { 01776 Polyhedron& x = *this; 01777 // Topology compatibility check. 01778 if (x.topology() != y.topology()) 01779 throw_topology_incompatible("poly_difference_assign(y)", "y", y); 01780 // Dimension-compatibility check. 01781 if (x.space_dim != y.space_dim) 01782 throw_dimension_incompatible("poly_difference_assign(y)", "y", y); 01783 01784 // The difference of a polyhedron `p' and an empty polyhedron is `p'. 01785 if (y.marked_empty()) 01786 return; 01787 // The difference of an empty polyhedron and of a polyhedron `p' is empty. 01788 if (x.marked_empty()) 01789 return; 01790 01791 // If both polyhedra are zero-dimensional, 01792 // then at this point they are necessarily universe polyhedra, 01793 // so that their difference is empty. 01794 if (x.space_dim == 0) { 01795 x.set_empty(); 01796 return; 01797 } 01798 01799 // TODO: This is just an executable specification. 01800 // Have to find a more efficient method. 01801 01802 if (y.contains(x)) { 01803 x.set_empty(); 01804 return; 01805 } 01806 01807 Polyhedron new_polyhedron(topology(), x.space_dim, EMPTY); 01808 01809 // Being lazy here is only harmful. 01810 // `minimize()' will process any pending constraints or generators. 01811 x.minimize(); 01812 y.minimize(); 01813 01814 const Constraint_System& y_cs = y.constraints(); 01815 for (Constraint_System::const_iterator i = y_cs.begin(), 01816 y_cs_end = y_cs.end(); i != y_cs_end; ++i) { 01817 const Constraint& c = *i; 01818 assert(!c.is_tautological()); 01819 assert(!c.is_inconsistent()); 01820 // If the polyhedron `x' is included in the polyhedron defined by 01821 // `c', then `c' can be skipped, as adding its complement to `x' 01822 // would result in the empty polyhedron. Moreover, if we operate 01823 // on C-polyhedra and `c' is a non-strict inequality, c _must_ be 01824 // skipped for otherwise we would obtain a result that is less 01825 // precise than the poly-difference. 01826 if (x.relation_with(c).implies(Poly_Con_Relation::is_included())) 01827 continue; 01828 Polyhedron z = x; 01829 const Linear_Expression e = Linear_Expression(c); 01830 switch (c.type()) { 01831 case Constraint::NONSTRICT_INEQUALITY: 01832 if (is_necessarily_closed()) 01833 z.add_constraint(e <= 0); 01834 else 01835 z.add_constraint(e < 0); 01836 break; 01837 case Constraint::STRICT_INEQUALITY: 01838 z.add_constraint(e <= 0); 01839 break; 01840 case Constraint::EQUALITY: 01841 if (is_necessarily_closed()) 01842 // We have already filtered out the case 01843 // when `x' is included in `y': the result is `x'. 01844 return; 01845 else { 01846 Polyhedron w = x; 01847 w.add_constraint(e < 0); 01848 new_polyhedron.poly_hull_assign(w); 01849 z.add_constraint(e > 0); 01850 } 01851 break; 01852 } 01853 new_polyhedron.poly_hull_assign(z); 01854 } 01855 *this = new_polyhedron; 01856 01857 assert(OK()); 01858 }
void Parma_Polyhedra_Library::Polyhedron::difference_assign | ( | const Polyhedron & | y | ) | [inline] |
Same as poly_difference_assign(y).
Definition at line 76 of file Polyhedron.inlines.hh.
References poly_difference_assign().
00076 { 00077 poly_difference_assign(y); 00078 }
void Parma_Polyhedra_Library::Polyhedron::affine_image | ( | Variable | var, | |
const Linear_Expression & | expr, | |||
Coefficient_traits::const_reference | denominator = Coefficient_one() | |||
) |
Assigns to *this
the affine image of *this
under the function mapping variable var
to the affine expression specified by expr
and denominator
.
var | The variable to which the affine expression is assigned; | |
expr | The numerator of the affine expression; | |
denominator | The denominator of the affine expression (optional argument with default value 1.) |
std::invalid_argument | Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a space dimension of *this . |
is assigned to var
where expr
is (
is the inhomogeneous term).
If constraints are up-to-date, it uses the specialized function affine_preimage() (for the system of constraints) and inverse transformation to reach the same result. To obtain the inverse transformation we use the following observation.
Observation:
var
in this transformation (i.e.,
so that the inverse transformation is
Then, if the transformation is invertible, all the entities that were up-to-date remain up-to-date. Otherwise only generators remain up-to-date.
In other words, if is a
matrix representing the rays of the polyhedron,
is a
matrix representing the points of the polyhedron and
and is the affine transformation to apply to
, then the resulting polyhedron is
Affine transformations are, for example:
Definition at line 1862 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Generator_System::affine_image(), Parma_Polyhedra_Library::Constraint_System::affine_preimage(), clear_constraints_up_to_date(), clear_generators_minimized(), clear_sat_c_up_to_date(), clear_sat_g_up_to_date(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), con_sys, constraints_are_up_to_date(), gen_sys, generators_are_up_to_date(), has_something_pending(), marked_empty(), minimize(), Parma_Polyhedra_Library::neg_assign(), OK(), remove_pending_to_obtain_generators(), space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
Referenced by fold_space_dimensions(), generalized_affine_image(), and ppl_Polyhedron_affine_image().
01864 { 01865 // The denominator cannot be zero. 01866 if (denominator == 0) 01867 throw_invalid_argument("affine_image(v, e, d)", "d == 0"); 01868 01869 // Dimension-compatibility checks. 01870 // The dimension of `expr' should not be greater than the dimension 01871 // of `*this'. 01872 if (space_dim < expr.space_dimension()) 01873 throw_dimension_incompatible("affine_image(v, e, d)", "e", expr); 01874 // `var' should be one of the dimensions of the polyhedron. 01875 const dimension_type var_space_dim = var.space_dimension(); 01876 if (space_dim < var_space_dim) 01877 throw_dimension_incompatible("affine_image(v, e, d)", "v", var); 01878 01879 if (marked_empty()) 01880 return; 01881 01882 if (expr.coefficient(var) != 0) { 01883 // The transformation is invertible: 01884 // minimality and saturators are preserved, so that 01885 // pending rows, if present, are correctly handled. 01886 if (generators_are_up_to_date()) { 01887 // Generator_System::affine_image() requires the third argument 01888 // to be a positive Coefficient. 01889 if (denominator > 0) 01890 gen_sys.affine_image(var_space_dim, expr, denominator); 01891 else 01892 gen_sys.affine_image(var_space_dim, -expr, -denominator); 01893 } 01894 if (constraints_are_up_to_date()) { 01895 // To build the inverse transformation, 01896 // after copying and negating `expr', 01897 // we exchange the roles of `expr[var_space_dim]' and `denominator'. 01898 Linear_Expression inverse; 01899 if (expr[var_space_dim] > 0) { 01900 inverse = -expr; 01901 inverse[var_space_dim] = denominator; 01902 con_sys.affine_preimage(var_space_dim, inverse, expr[var_space_dim]); 01903 } 01904 else { 01905 // The new denominator is negative: we negate everything once 01906 // more, as Constraint_System::affine_preimage() requires the 01907 // third argument to be positive. 01908 inverse = expr; 01909 inverse[var_space_dim] = denominator; 01910 neg_assign(inverse[var_space_dim]); 01911 con_sys.affine_preimage(var_space_dim, inverse, -expr[var_space_dim]); 01912 } 01913 } 01914 } 01915 else { 01916 // The transformation is not invertible. 01917 // We need an up-to-date system of generators. 01918 if (has_something_pending()) 01919 remove_pending_to_obtain_generators(); 01920 else if (!generators_are_up_to_date()) 01921 minimize(); 01922 if (!marked_empty()) { 01923 // Generator_System::affine_image() requires the third argument 01924 // to be a positive Coefficient. 01925 if (denominator > 0) 01926 gen_sys.affine_image(var_space_dim, expr, denominator); 01927 else 01928 gen_sys.affine_image(var_space_dim, -expr, -denominator); 01929 01930 clear_constraints_up_to_date(); 01931 clear_generators_minimized(); 01932 clear_sat_c_up_to_date(); 01933 clear_sat_g_up_to_date(); 01934 } 01935 } 01936 assert(OK()); 01937 }
void Parma_Polyhedra_Library::Polyhedron::affine_preimage | ( | Variable | var, | |
const Linear_Expression & | expr, | |||
Coefficient_traits::const_reference | denominator = Coefficient_one() | |||
) |
Assigns to *this
the affine preimage of *this
under the function mapping variable var
to the affine expression specified by expr
and denominator
.
var | The variable to which the affine expression is substituted; | |
expr | The numerator of the affine expression; | |
denominator | The denominator of the affine expression (optional argument with default value 1.) |
std::invalid_argument | Thrown if denominator is zero or if expr and *this are dimension-incompatible or if var is not a space dimension of *this . |
is assigned to var
where expr
is (
is the inhomogeneous term).
If generators are up-to-date, then the specialized function affine_image() is used (for the system of generators) and inverse transformation to reach the same result. To obtain the inverse transformation, we use the following observation.
Observation:
var
in this transformation (i.e.
, the inverse transformation is
.
Then, if the transformation is invertible, all the entities that were up-to-date remain up-to-date. Otherwise only constraints remain up-to-date.
In other words, if is a
matrix representing the constraints of the polyhedron,
is the affine transformation to apply to
and
The resulting polyhedron is
where is defined as follows:
Definition at line 1942 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Generator_System::affine_image(), Parma_Polyhedra_Library::Constraint_System::affine_preimage(), clear_constraints_minimized(), clear_generators_up_to_date(), clear_sat_c_up_to_date(), clear_sat_g_up_to_date(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), con_sys, constraints_are_up_to_date(), gen_sys, generators_are_up_to_date(), has_something_pending(), marked_empty(), minimize(), Parma_Polyhedra_Library::neg_assign(), OK(), remove_pending_to_obtain_constraints(), space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
Referenced by generalized_affine_preimage(), and ppl_Polyhedron_affine_preimage().
01944 { 01945 // The denominator cannot be zero. 01946 if (denominator == 0) 01947 throw_invalid_argument("affine_preimage(v, e, d)", "d == 0"); 01948 01949 // Dimension-compatibility checks. 01950 // The dimension of `expr' should not be greater than the dimension 01951 // of `*this'. 01952 if (space_dim < expr.space_dimension()) 01953 throw_dimension_incompatible("affine_preimage(v, e, d)", "e", expr); 01954 // `var' should be one of the dimensions of the polyhedron. 01955 const dimension_type var_space_dim = var.space_dimension(); 01956 if (space_dim < var_space_dim) 01957 throw_dimension_incompatible("affine_preimage(v, e, d)", "v", var); 01958 01959 if (marked_empty()) 01960 return; 01961 01962 if (expr.coefficient(var) != 0) { 01963 // The transformation is invertible: 01964 // minimality and saturators are preserved. 01965 if (constraints_are_up_to_date()) { 01966 // Constraint_System::affine_preimage() requires the third argument 01967 // to be a positive Coefficient. 01968 if (denominator > 0) 01969 con_sys.affine_preimage(var_space_dim, expr, denominator); 01970 else 01971 con_sys.affine_preimage(var_space_dim, -expr, -denominator); 01972 } 01973 if (generators_are_up_to_date()) { 01974 // To build the inverse transformation, 01975 // after copying and negating `expr', 01976 // we exchange the roles of `expr[var_space_dim]' and `denominator'. 01977 Linear_Expression inverse; 01978 if (expr[var_space_dim] > 0) { 01979 inverse = -expr; 01980 inverse[var_space_dim] = denominator; 01981 gen_sys.affine_image(var_space_dim, inverse, expr[var_space_dim]); 01982 } 01983 else { 01984 // The new denominator is negative: 01985 // we negate everything once more, as Generator_System::affine_image() 01986 // requires the third argument to be positive. 01987 inverse = expr; 01988 inverse[var_space_dim] = denominator; 01989 neg_assign(inverse[var_space_dim]); 01990 gen_sys.affine_image(var_space_dim, inverse, -expr[var_space_dim]); 01991 } 01992 } 01993 } 01994 else { 01995 // The transformation is not invertible. 01996 // We need an up-to-date system of constraints. 01997 if (has_something_pending()) 01998 remove_pending_to_obtain_constraints(); 01999 else if (!constraints_are_up_to_date()) 02000 minimize(); 02001 // Constraint_System::affine_preimage() requires the third argument 02002 // to be a positive Coefficient. 02003 if (denominator > 0) 02004 con_sys.affine_preimage(var_space_dim, expr, denominator); 02005 else 02006 con_sys.affine_preimage(var_space_dim, -expr, -denominator); 02007 // Generators, minimality and saturators are no longer valid. 02008 clear_generators_up_to_date(); 02009 clear_constraints_minimized(); 02010 clear_sat_c_up_to_date(); 02011 clear_sat_g_up_to_date(); 02012 } 02013 assert(OK()); 02014 }
void Parma_Polyhedra_Library::Polyhedron::generalized_affine_image | ( | Variable | var, | |
const 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 2174 of file Polyhedron_public.cc.
References add_generator(), add_generator_and_minimize(), 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_THAN, Parma_Polyhedra_Library::GREATER_THAN_OR_EQUAL, is_empty(), is_necessarily_closed(), Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::LESS_THAN_OR_EQUAL, Parma_Polyhedra_Library::Matrix::num_rows(), OK(), Parma_Polyhedra_Library::Linear_System::set_sorted(), space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
Referenced by bounded_affine_image(), generalized_affine_preimage(), ppl_Polyhedron_generalized_affine_image(), and ppl_Polyhedron_generalized_affine_image_lhs_rhs().
02177 { 02178 // The denominator cannot be zero. 02179 if (denominator == 0) 02180 throw_invalid_argument("generalized_affine_image(v, r, e, d)", "d == 0"); 02181 02182 // Dimension-compatibility checks. 02183 // The dimension of `expr' should not be greater than the dimension 02184 // of `*this'. 02185 if (space_dim < expr.space_dimension()) 02186 throw_dimension_incompatible("generalized_affine_image(v, r, e, d)", 02187 "e", expr); 02188 // `var' should be one of the dimensions of the polyhedron. 02189 const dimension_type var_space_dim = var.space_dimension(); 02190 if (space_dim < var_space_dim) 02191 throw_dimension_incompatible("generalized_affine_image(v, r, e, d)", 02192 "v", var); 02193 02194 // Strict relation symbols are only admitted for NNC polyhedra. 02195 if (is_necessarily_closed() 02196 && (relsym == LESS_THAN || relsym == GREATER_THAN)) 02197 throw_invalid_argument("generalized_affine_image(v, r, e, d)", 02198 "r is a strict relation symbol"); 02199 02200 // First compute the affine image. 02201 affine_image(var, expr, denominator); 02202 02203 if (relsym == EQUAL) 02204 // The affine relation is indeed an affine function. 02205 return; 02206 02207 // Any image of an empty polyhedron is empty. 02208 // Note: DO check for emptyness here, as we will later add a ray. 02209 if (is_empty()) 02210 return; 02211 02212 switch (relsym) { 02213 case LESS_THAN_OR_EQUAL: 02214 add_generator(ray(-var)); 02215 break; 02216 case GREATER_THAN_OR_EQUAL: 02217 add_generator(ray(var)); 02218 break; 02219 case LESS_THAN: 02220 // Intentionally fall through. 02221 case GREATER_THAN: 02222 { 02223 // The relation symbol is strict. 02224 assert(!is_necessarily_closed()); 02225 // While adding the ray, we minimize the generators 02226 // in order to avoid adding too many redundant generators later. 02227 add_generator_and_minimize(ray(relsym == GREATER_THAN ? var : -var)); 02228 // We split each point of the generator system into two generators: 02229 // a closure point, having the same coordinates of the given point, 02230 // and another point, having the same coordinates for all but the 02231 // `var' dimension, which is displaced along the direction of the 02232 // newly introduced ray. 02233 const dimension_type eps_index = space_dim + 1; 02234 for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) 02235 if (gen_sys[i].is_point()) { 02236 Generator& g = gen_sys[i]; 02237 // Add a `var'-displaced copy of `g' to the generator system. 02238 gen_sys.add_row(g); 02239 if (relsym == GREATER_THAN) 02240 ++gen_sys[gen_sys.num_rows()-1][var_space_dim]; 02241 else 02242 --gen_sys[gen_sys.num_rows()-1][var_space_dim]; 02243 // Transform `g' into a closure point. 02244 g[eps_index] = 0; 02245 } 02246 clear_constraints_up_to_date(); 02247 clear_generators_minimized(); 02248 gen_sys.set_sorted(false); 02249 clear_sat_c_up_to_date(); 02250 clear_sat_g_up_to_date(); 02251 } 02252 break; 02253 case EQUAL: 02254 // This case was already dealt with before. 02255 throw std::runtime_error("PPL internal error"); 02256 } 02257 assert(OK()); 02258 }
void Parma_Polyhedra_Library::Polyhedron::generalized_affine_preimage | ( | Variable | var, | |
const 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 2262 of file Polyhedron_public.cc.
References add_constraint(), add_generator(), affine_preimage(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, generalized_affine_image(), Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::GREATER_THAN_OR_EQUAL, is_empty(), is_necessarily_closed(), Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::LESS_THAN_OR_EQUAL, OK(), space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
Referenced by ppl_Polyhedron_generalized_affine_preimage(), and ppl_Polyhedron_generalized_affine_preimage_lhs_rhs().
02265 { 02266 // The denominator cannot be zero. 02267 if (denominator == 0) 02268 throw_invalid_argument("generalized_affine_preimage(v, r, e, d)", 02269 "d == 0"); 02270 02271 // Dimension-compatibility checks. 02272 // The dimension of `expr' should not be greater than the dimension 02273 // of `*this'. 02274 if (space_dim < expr.space_dimension()) 02275 throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)", 02276 "e", expr); 02277 // `var' should be one of the dimensions of the polyhedron. 02278 const dimension_type var_space_dim = var.space_dimension(); 02279 if (space_dim < var_space_dim) 02280 throw_dimension_incompatible("generalized_affine_preimage(v, r, e, d)", 02281 "v", var); 02282 02283 // Strict relation symbols are only admitted for NNC polyhedra. 02284 if (is_necessarily_closed() 02285 && (relsym == LESS_THAN || relsym == GREATER_THAN)) 02286 throw_invalid_argument("generalized_affine_preimage(v, r, e, d)", 02287 "r is a strict relation symbol"); 02288 02289 // Check whether the affine relation is indeed an affine function. 02290 if (relsym == EQUAL) { 02291 affine_preimage(var, expr, denominator); 02292 return; 02293 } 02294 02295 // Compute the reversed relation symbol to simplify later coding. 02296 Relation_Symbol reversed_relsym; 02297 switch (relsym) { 02298 case LESS_THAN: 02299 reversed_relsym = GREATER_THAN; 02300 break; 02301 case LESS_THAN_OR_EQUAL: 02302 reversed_relsym = GREATER_THAN_OR_EQUAL; 02303 break; 02304 case GREATER_THAN_OR_EQUAL: 02305 reversed_relsym = LESS_THAN_OR_EQUAL; 02306 break; 02307 case GREATER_THAN: 02308 reversed_relsym = LESS_THAN; 02309 break; 02310 default: 02311 // The EQUAL case has been already dealt with. 02312 throw std::runtime_error("PPL internal error"); 02313 break; 02314 } 02315 02316 // Check whether the preimage of this affine relation can be easily 02317 // computed as the image of its inverse relation. 02318 const Coefficient& var_coefficient = expr.coefficient(var); 02319 if (var_coefficient != 0) { 02320 Linear_Expression inverse_expr 02321 = expr - (denominator + var_coefficient) * var; 02322 Coefficient inverse_denominator = - var_coefficient; 02323 Relation_Symbol inverse_relsym 02324 = (sgn(denominator) == sgn(inverse_denominator)) 02325 ? relsym : reversed_relsym; 02326 generalized_affine_image(var, inverse_relsym, inverse_expr, 02327 inverse_denominator); 02328 return; 02329 } 02330 02331 // Here `var_coefficient == 0', so that the preimage cannot 02332 // be easily computed by inverting the affine relation. 02333 // Shrink the polyhedron by adding the constraint induced 02334 // by the affine relation. 02335 const Relation_Symbol corrected_relsym 02336 = (denominator > 0) ? relsym : reversed_relsym; 02337 switch (corrected_relsym) { 02338 case LESS_THAN: 02339 add_constraint(denominator*var < expr); 02340 break; 02341 case LESS_THAN_OR_EQUAL: 02342 add_constraint(denominator*var <= expr); 02343 break; 02344 case GREATER_THAN_OR_EQUAL: 02345 add_constraint(denominator*var >= expr); 02346 break; 02347 case GREATER_THAN: 02348 add_constraint(denominator*var > expr); 02349 break; 02350 case EQUAL: 02351 // We already dealt with this case. 02352 throw std::runtime_error("PPL internal error"); 02353 break; 02354 } 02355 // If the shrunk polyhedron is empty, its preimage is empty too. 02356 // Note: DO check for emptyness here, as we will later add a line. 02357 if (is_empty()) 02358 return; 02359 add_generator(line(var)); 02360 assert(OK()); 02361 }
void Parma_Polyhedra_Library::Polyhedron::generalized_affine_image | ( | const Linear_Expression & | lhs, | |
const 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 2364 of file Polyhedron_public.cc.
References add_constraint(), add_constraint_and_minimize(), add_recycled_generators_and_minimize(), add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::GREATER_THAN_OR_EQUAL, Parma_Polyhedra_Library::Generator_System::insert(), is_empty(), is_necessarily_closed(), Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::LESS_THAN_OR_EQUAL, marked_empty(), OK(), remove_higher_space_dimensions(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
02366 { 02367 // Dimension-compatibility checks. 02368 // The dimension of `lhs' should not be greater than the dimension 02369 // of `*this'. 02370 dimension_type lhs_space_dim = lhs.space_dimension(); 02371 if (space_dim < lhs_space_dim) 02372 throw_dimension_incompatible("generalized_affine_image(e1, r, e2)", 02373 "e1", lhs); 02374 // The dimension of `rhs' should not be greater than the dimension 02375 // of `*this'. 02376 const dimension_type rhs_space_dim = rhs.space_dimension(); 02377 if (space_dim < rhs_space_dim) 02378 throw_dimension_incompatible("generalized_affine_image(e1, r, e2)", 02379 "e2", rhs); 02380 02381 // Strict relation symbols are only admitted for NNC polyhedra. 02382 if (is_necessarily_closed() 02383 && (relsym == LESS_THAN || relsym == GREATER_THAN)) 02384 throw_invalid_argument("generalized_affine_image(e1, r, e2)", 02385 "r is a strict relation symbol"); 02386 02387 // Any image of an empty polyhedron is empty. 02388 if (marked_empty()) 02389 return; 02390 02391 // Compute the actual space dimension of `lhs', 02392 // i.e., the highest dimension having a non-zero coefficient in `lhs'. 02393 for ( ; lhs_space_dim > 0; lhs_space_dim--) 02394 if (lhs.coefficient(Variable(lhs_space_dim - 1)) != 0) 02395 break; 02396 // If all variables have a zero coefficient, then `lhs' is a constant: 02397 // we can simply add the constraint `lhs relsym rhs'. 02398 if (lhs_space_dim == 0) { 02399 switch (relsym) { 02400 case LESS_THAN: 02401 add_constraint(lhs < rhs); 02402 break; 02403 case LESS_THAN_OR_EQUAL: 02404 add_constraint(lhs <= rhs); 02405 break; 02406 case EQUAL: 02407 add_constraint(lhs == rhs); 02408 break; 02409 case GREATER_THAN_OR_EQUAL: 02410 add_constraint(lhs >= rhs); 02411 break; 02412 case GREATER_THAN: 02413 add_constraint(lhs > rhs); 02414 break; 02415 } 02416 return; 02417 } 02418 02419 // Gather in `new_lines' the collections of all the lines having 02420 // the direction of variables occurring in `lhs'. 02421 // While at it, check whether or not there exists a variable 02422 // occurring in both `lhs' and `rhs'. 02423 Generator_System new_lines; 02424 bool lhs_vars_intersects_rhs_vars = false; 02425 for (dimension_type i = lhs_space_dim; i-- > 0; ) 02426 if (lhs.coefficient(Variable(i)) != 0) { 02427 new_lines.insert(line(Variable(i))); 02428 if (rhs.coefficient(Variable(i)) != 0) 02429 lhs_vars_intersects_rhs_vars = true; 02430 } 02431 02432 if (lhs_vars_intersects_rhs_vars) { 02433 // Some variables in `lhs' also occur in `rhs'. 02434 // To ease the computation, we add an additional dimension. 02435 const Variable new_var = Variable(space_dim); 02436 add_space_dimensions_and_embed(1); 02437 02438 // Constrain the new dimension to be equal to the right hand side. 02439 // (check for emptiness because we will add lines). 02440 if (add_constraint_and_minimize(new_var == rhs)) { 02441 // Cylindrificate on all the variables occurring in the left hand side 02442 // (we force minimization because we will need the constraints). 02443 add_recycled_generators_and_minimize(new_lines); 02444 02445 // Constrain the new dimension so that it is related to 02446 // the left hand side as dictated by `relsym' 02447 // (we force minimization because we will need the generators). 02448 switch (relsym) { 02449 case LESS_THAN: 02450 add_constraint_and_minimize(lhs < new_var); 02451 break; 02452 case LESS_THAN_OR_EQUAL: 02453 add_constraint_and_minimize(lhs <= new_var); 02454 break; 02455 case EQUAL: 02456 add_constraint_and_minimize(lhs == new_var); 02457 break; 02458 case GREATER_THAN_OR_EQUAL: 02459 add_constraint_and_minimize(lhs >= new_var); 02460 break; 02461 case GREATER_THAN: 02462 add_constraint_and_minimize(lhs > new_var); 02463 break; 02464 } 02465 } 02466 // Remove the temporarily added dimension. 02467 remove_higher_space_dimensions(space_dim-1); 02468 } 02469 else { 02470 // `lhs' and `rhs' variables are disjoint: 02471 // there is no need to add a further dimension. 02472 02473 // Any image of an empty polyhedron is empty. 02474 // Note: DO check for emptyness here, as we will add lines. 02475 if (is_empty()) 02476 return; 02477 02478 // Cylindrificate on all the variables occurring in the left hand side 02479 // (we force minimization because we will need the constraints). 02480 add_recycled_generators_and_minimize(new_lines); 02481 02482 // Constrain the left hand side expression so that it is related to 02483 // the right hand side expression as dictated by `relsym'. 02484 switch (relsym) { 02485 case LESS_THAN: 02486 add_constraint(lhs < rhs); 02487 break; 02488 case LESS_THAN_OR_EQUAL: 02489 add_constraint(lhs <= rhs); 02490 break; 02491 case EQUAL: 02492 add_constraint(lhs == rhs); 02493 break; 02494 case GREATER_THAN_OR_EQUAL: 02495 add_constraint(lhs >= rhs); 02496 break; 02497 case GREATER_THAN: 02498 add_constraint(lhs > rhs); 02499 break; 02500 } 02501 } 02502 assert(OK()); 02503 }
void Parma_Polyhedra_Library::Polyhedron::generalized_affine_preimage | ( | const Linear_Expression & | lhs, | |
const 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 2506 of file Polyhedron_public.cc.
References add_constraint(), add_constraint_and_minimize(), add_recycled_generators(), add_recycled_generators_and_minimize(), add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), Parma_Polyhedra_Library::EQUAL, generalized_affine_image(), Parma_Polyhedra_Library::GREATER_THAN, Parma_Polyhedra_Library::GREATER_THAN_OR_EQUAL, Parma_Polyhedra_Library::Generator_System::insert(), is_empty(), is_necessarily_closed(), Parma_Polyhedra_Library::LESS_THAN, Parma_Polyhedra_Library::LESS_THAN_OR_EQUAL, marked_empty(), OK(), remove_higher_space_dimensions(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
02508 { 02509 // Dimension-compatibility checks. 02510 // The dimension of `lhs' should not be greater than the dimension 02511 // of `*this'. 02512 dimension_type lhs_space_dim = lhs.space_dimension(); 02513 if (space_dim < lhs_space_dim) 02514 throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)", 02515 "e1", lhs); 02516 // The dimension of `rhs' should not be greater than the dimension 02517 // of `*this'. 02518 const dimension_type rhs_space_dim = rhs.space_dimension(); 02519 if (space_dim < rhs_space_dim) 02520 throw_dimension_incompatible("generalized_affine_preimage(e1, r, e2)", 02521 "e2", rhs); 02522 02523 // Strict relation symbols are only admitted for NNC polyhedra. 02524 if (is_necessarily_closed() 02525 && (relsym == LESS_THAN || relsym == GREATER_THAN)) 02526 throw_invalid_argument("generalized_affine_preimage(e1, r, e2)", 02527 "r is a strict relation symbol"); 02528 02529 // Any preimage of an empty polyhedron is empty. 02530 if (marked_empty()) 02531 return; 02532 02533 // Compute the actual space dimension of `lhs', 02534 // i.e., the highest dimension having a non-zero coefficient in `lhs'. 02535 for ( ; lhs_space_dim > 0; lhs_space_dim--) 02536 if (lhs.coefficient(Variable(lhs_space_dim - 1)) != 0) 02537 break; 02538 02539 // If all variables have a zero coefficient, then `lhs' is a constant: 02540 // in this case, preimage and image happen to be the same. 02541 if (lhs_space_dim == 0) { 02542 generalized_affine_image(lhs, relsym, rhs); 02543 return; 02544 } 02545 02546 // Gather in `new_lines' the collections of all the lines having 02547 // the direction of variables occurring in `lhs'. 02548 // While at it, check whether or not there exists a variable 02549 // occurring in both `lhs' and `rhs'. 02550 Generator_System new_lines; 02551 bool lhs_vars_intersects_rhs_vars = false; 02552 for (dimension_type i = lhs_space_dim; i-- > 0; ) 02553 if (lhs.coefficient(Variable(i)) != 0) { 02554 new_lines.insert(line(Variable(i))); 02555 if (rhs.coefficient(Variable(i)) != 0) 02556 lhs_vars_intersects_rhs_vars = true; 02557 } 02558 02559 if (lhs_vars_intersects_rhs_vars) { 02560 // Some variables in `lhs' also occur in `rhs'. 02561 // To ease the computation, we add an additional dimension. 02562 const Variable new_var = Variable(space_dim); 02563 add_space_dimensions_and_embed(1); 02564 02565 // Constrain the new dimension to be equal to `lhs' 02566 // (also check for emptiness because we have to add lines). 02567 if (add_constraint_and_minimize(new_var == lhs)) { 02568 // Cylindrificate on all the variables occurring in the left hand side 02569 // (we force minimization because we will need the constraints). 02570 add_recycled_generators_and_minimize(new_lines); 02571 02572 // Constrain the new dimension so that it is related to 02573 // the right hand side as dictated by `relsym' 02574 // (we force minimization because we will need the generators). 02575 switch (relsym) { 02576 case LESS_THAN: 02577 add_constraint_and_minimize(new_var < rhs); 02578 break; 02579 case LESS_THAN_OR_EQUAL: 02580 add_constraint_and_minimize(new_var <= rhs); 02581 break; 02582 case EQUAL: 02583 add_constraint_and_minimize(new_var == rhs); 02584 break; 02585 case GREATER_THAN_OR_EQUAL: 02586 add_constraint_and_minimize(new_var >= rhs); 02587 break; 02588 case GREATER_THAN: 02589 add_constraint_and_minimize(new_var > rhs); 02590 break; 02591 } 02592 } 02593 // Remove the temporarily added dimension. 02594 remove_higher_space_dimensions(space_dim-1); 02595 } 02596 else { 02597 // `lhs' and `rhs' variables are disjoint: 02598 // there is no need to add a further dimension. 02599 02600 // Constrain the left hand side expression so that it is related to 02601 // the right hand side expression as dictated by `relsym'. 02602 switch (relsym) { 02603 case LESS_THAN: 02604 add_constraint(lhs < rhs); 02605 break; 02606 case LESS_THAN_OR_EQUAL: 02607 add_constraint(lhs <= rhs); 02608 break; 02609 case EQUAL: 02610 add_constraint(lhs == rhs); 02611 break; 02612 case GREATER_THAN_OR_EQUAL: 02613 add_constraint(lhs >= rhs); 02614 break; 02615 case GREATER_THAN: 02616 add_constraint(lhs > rhs); 02617 break; 02618 } 02619 // Any image of an empty polyhedron is empty. 02620 // Note: DO check for emptyness here, as we will add lines. 02621 if (is_empty()) 02622 return; 02623 // Cylindrificate on all the variables occurring in `lhs'. 02624 add_recycled_generators(new_lines); 02625 } 02626 assert(OK()); 02627 }
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 2018 of file Polyhedron_public.cc.
References add_constraint(), add_constraint_and_minimize(), add_space_dimensions_and_embed(), Parma_Polyhedra_Library::Linear_Expression::coefficient(), generalized_affine_image(), Parma_Polyhedra_Library::GREATER_THAN_OR_EQUAL, Parma_Polyhedra_Library::LESS_THAN_OR_EQUAL, marked_empty(), OK(), remove_higher_space_dimensions(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
Referenced by ppl_Polyhedron_bounded_affine_image().
02021 { 02022 // The denominator cannot be zero. 02023 if (denominator == 0) 02024 throw_invalid_argument("bounded_affine_image(v, lb, ub, d)", "d == 0"); 02025 02026 // Dimension-compatibility checks. 02027 // `var' should be one of the dimensions of the polyhedron. 02028 const dimension_type var_space_dim = var.space_dimension(); 02029 if (space_dim < var_space_dim) 02030 throw_dimension_incompatible("bounded_affine_image(v, lb, ub, d)", 02031 "v", var); 02032 // The dimension of `lb_expr' and `ub_expr' should not be 02033 // greater than the dimension of `*this'. 02034 const dimension_type lb_space_dim = lb_expr.space_dimension(); 02035 if (space_dim < lb_space_dim) 02036 throw_dimension_incompatible("bounded_affine_image(v, lb, ub)", 02037 "lb", lb_expr); 02038 const dimension_type ub_space_dim = ub_expr.space_dimension(); 02039 if (space_dim < ub_space_dim) 02040 throw_dimension_incompatible("bounded_affine_image(v, lb, ub)", 02041 "ub", ub_expr); 02042 02043 // Any image of an empty polyhedron is empty. 02044 if (marked_empty()) 02045 return; 02046 02047 // Check whether `var' occurs in `lb_expr' and/or `ub_expr'. 02048 if (lb_expr.coefficient(var) == 0) { 02049 // Here `var' may only occur in `ub_expr'. 02050 generalized_affine_image(var, 02051 LESS_THAN_OR_EQUAL, 02052 ub_expr, 02053 denominator); 02054 if (denominator > 0) 02055 add_constraint(lb_expr <= denominator*var); 02056 else 02057 add_constraint(denominator*var <= lb_expr); 02058 } 02059 else if (ub_expr.coefficient(var) == 0) { 02060 // Here `var' only occurs in `lb_expr'. 02061 generalized_affine_image(var, 02062 GREATER_THAN_OR_EQUAL, 02063 lb_expr, 02064 denominator); 02065 if (denominator > 0) 02066 add_constraint(denominator*var <= ub_expr); 02067 else 02068 add_constraint(ub_expr <= denominator*var); 02069 } 02070 else { 02071 // Here `var' occurs in both `lb_expr' and `ub_expr'. 02072 // To ease the computation, we add an additional dimension. 02073 const Variable new_var = Variable(space_dim); 02074 add_space_dimensions_and_embed(1); 02075 // Constrain the new dimension to be equal to `ub_expr'. 02076 // (we force minimization because we will need the generators). 02077 add_constraint_and_minimize(denominator*new_var == ub_expr); 02078 // Apply the affine lower bound. 02079 generalized_affine_image(var, 02080 GREATER_THAN_OR_EQUAL, 02081 lb_expr, 02082 denominator); 02083 // Now apply the affine upper bound, as recorded in `new_var' 02084 // (we force minimization because we will need the generators). 02085 if (denominator > 0) 02086 add_constraint_and_minimize(var <= new_var); 02087 else 02088 add_constraint_and_minimize(new_var <= var); 02089 // Remove the temporarily added dimension. 02090 remove_higher_space_dimensions(space_dim-1); 02091 } 02092 assert(OK()); 02093 }
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 2097 of file Polyhedron_public.cc.
References add_constraint(), add_generator(), 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(), is_empty(), marked_empty(), OK(), Parma_Polyhedra_Library::Linear_System::permute_columns(), remove_higher_space_dimensions(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), Parma_Polyhedra_Library::Variable::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
Referenced by ppl_Polyhedron_bounded_affine_preimage().
02100 { 02101 // The denominator cannot be zero. 02102 if (denominator == 0) 02103 throw_invalid_argument("bounded_affine_preimage(v, lb, ub, d)", "d == 0"); 02104 02105 // Dimension-compatibility checks. 02106 // `var' should be one of the dimensions of the polyhedron. 02107 const dimension_type var_space_dim = var.space_dimension(); 02108 if (space_dim < var_space_dim) 02109 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub, d)", 02110 "v", var); 02111 // The dimension of `lb_expr' and `ub_expr' should not be 02112 // greater than the dimension of `*this'. 02113 const dimension_type lb_space_dim = lb_expr.space_dimension(); 02114 if (space_dim < lb_space_dim) 02115 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)", 02116 "lb", lb_expr); 02117 const dimension_type ub_space_dim = ub_expr.space_dimension(); 02118 if (space_dim < ub_space_dim) 02119 throw_dimension_incompatible("bounded_affine_preimage(v, lb, ub)", 02120 "ub", ub_expr); 02121 02122 // Any preimage of an empty polyhedron is empty. 02123 if (marked_empty()) 02124 return; 02125 02126 // Check whether `var' occurs in neither `lb_expr' nor `ub_expr'. 02127 if (lb_expr.coefficient(var) == 0 && ub_expr.coefficient(var) == 0) { 02128 if (denominator > 0) { 02129 add_constraint(lb_expr <= denominator*var); 02130 add_constraint(denominator*var <= ub_expr); 02131 } 02132 else { 02133 add_constraint(ub_expr <= denominator*var); 02134 add_constraint(denominator*var <= lb_expr); 02135 } 02136 // Any image of an empty polyhedron is empty. 02137 // Note: DO check for emptyness here, as we will later add a line. 02138 if (is_empty()) 02139 return; 02140 add_generator(line(var)); 02141 } 02142 else { 02143 // Here `var' occurs in `lb_expr' or `ub_expr'. 02144 // To ease the computation, add an additional dimension. 02145 const Variable new_var = Variable(space_dim); 02146 add_space_dimensions_and_embed(1); 02147 // Swap dimensions `var' and `new_var'. 02148 std::vector<dimension_type> swapping_cycle; 02149 swapping_cycle.push_back(var_space_dim); 02150 swapping_cycle.push_back(space_dim); 02151 swapping_cycle.push_back(0); 02152 if (constraints_are_up_to_date()) 02153 con_sys.permute_columns(swapping_cycle); 02154 if (generators_are_up_to_date()) 02155 gen_sys.permute_columns(swapping_cycle); 02156 // Constrain the new dimension as dictated by `lb_expr' and `ub_expr'. 02157 // (we force minimization because we will need the generators). 02158 if (denominator > 0) { 02159 add_constraint(lb_expr <= denominator*new_var); 02160 add_constraint(denominator*new_var <= ub_expr); 02161 } 02162 else { 02163 add_constraint(ub_expr <= denominator*new_var); 02164 add_constraint(denominator*new_var <= lb_expr); 02165 } 02166 // Remove the temporarily added dimension. 02167 remove_higher_space_dimensions(space_dim-1); 02168 } 02169 assert(OK()); 02170 }
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 2630 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, throw_dimension_incompatible(), throw_topology_incompatible(), topology(), Parma_Polyhedra_Library::Linear_System::unset_pending_rows(), and update_generators().
Referenced by ppl_Polyhedron_time_elapse_assign(), and Parma_Polyhedra_Library::BD_Shape< T >::time_elapse_assign().
02630 { 02631 Polyhedron& x = *this; 02632 // Topology compatibility check. 02633 if (x.topology() != y.topology()) 02634 throw_topology_incompatible("time_elapse_assign(y)", "y", y); 02635 // Dimension-compatibility checks. 02636 if (x.space_dim != y.space_dim) 02637 throw_dimension_incompatible("time_elapse_assign(y)", "y", y); 02638 02639 // Dealing with the zero-dimensional case. 02640 if (x.space_dim == 0) { 02641 if (y.marked_empty()) 02642 x.set_empty(); 02643 return; 02644 } 02645 02646 // If either one of `x' or `y' is empty, the result is empty too. 02647 if (x.marked_empty() || y.marked_empty() 02648 || (x.has_pending_constraints() && !x.process_pending_constraints()) 02649 || (!x.generators_are_up_to_date() && !x.update_generators()) 02650 || (y.has_pending_constraints() && !y.process_pending_constraints()) 02651 || (!y.generators_are_up_to_date() && !y.update_generators())) { 02652 x.set_empty(); 02653 return; 02654 } 02655 02656 // At this point both generator systems are up-to-date, 02657 // possibly containing pending generators. 02658 Generator_System gs = y.gen_sys; 02659 dimension_type gs_num_rows = gs.num_rows(); 02660 02661 if (!x.is_necessarily_closed()) 02662 // `x' and `y' are NNC polyhedra. 02663 for (dimension_type i = gs_num_rows; i-- > 0; ) 02664 switch (gs[i].type()) { 02665 case Generator::POINT: 02666 // The points of `gs' can be erased, 02667 // since their role can be played by closure points. 02668 --gs_num_rows; 02669 std::swap(gs[i], gs[gs_num_rows]); 02670 break; 02671 case Generator::CLOSURE_POINT: 02672 { 02673 Generator& cp = gs[i]; 02674 // If it is the origin, erase it. 02675 if (cp.all_homogeneous_terms_are_zero()) { 02676 --gs_num_rows; 02677 std::swap(cp, gs[gs_num_rows]); 02678 } 02679 // Otherwise, transform the closure point into a ray. 02680 else { 02681 cp[0] = 0; 02682 // Enforce normalization. 02683 cp.normalize(); 02684 } 02685 } 02686 break; 02687 default: 02688 // For rays and lines, nothing to be done. 02689 break; 02690 } 02691 else 02692 // `x' and `y' are C polyhedra. 02693 for (dimension_type i = gs_num_rows; i-- > 0; ) 02694 switch (gs[i].type()) { 02695 case Generator::POINT: 02696 { 02697 Generator& p = gs[i]; 02698 // If it is the origin, erase it. 02699 if (p.all_homogeneous_terms_are_zero()) { 02700 --gs_num_rows; 02701 std::swap(p, gs[gs_num_rows]); 02702 } 02703 // Otherwise, transform the point into a ray. 02704 else { 02705 p[0] = 0; 02706 // Enforce normalization. 02707 p.normalize(); 02708 } 02709 } 02710 break; 02711 default: 02712 // For rays and lines, nothing to be done. 02713 break; 02714 } 02715 // If it was present, erase the origin point or closure point, 02716 // which cannot be transformed into a valid ray or line. 02717 // For NNC polyhedra, also erase all the points of `gs', 02718 // whose role can be played by the closure points. 02719 // These have been previously moved to the end of `gs'. 02720 gs.erase_to_end(gs_num_rows); 02721 gs.unset_pending_rows(); 02722 02723 // `gs' may now have no rows. 02724 // Namely, this happens when `y' was the singleton polyhedron 02725 // having the origin as the one and only point. 02726 // In such a case, the resulting polyhedron is equal to `x'. 02727 if (gs_num_rows == 0) 02728 return; 02729 02730 // If the polyhedron can have something pending, we add `gs' 02731 // to `gen_sys' as pending rows 02732 if (x.can_have_something_pending()) { 02733 x.gen_sys.add_pending_rows(gs); 02734 x.set_generators_pending(); 02735 } 02736 // Otherwise, the two systems are merged. 02737 // `Linear_System::merge_rows_assign()' requires both systems to be sorted. 02738 else { 02739 if (!x.gen_sys.is_sorted()) 02740 x.gen_sys.sort_rows(); 02741 gs.sort_rows(); 02742 x.gen_sys.merge_rows_assign(gs); 02743 // Only the system of generators is up-to-date. 02744 x.clear_constraints_up_to_date(); 02745 x.clear_generators_minimized(); 02746 } 02747 assert(x.OK(true) && y.OK(true)); 02748 }
void Parma_Polyhedra_Library::Polyhedron::topological_closure_assign | ( | ) |
Assigns to *this
its topological closure.
Definition at line 2751 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Generator_System::add_corresponding_points(), can_have_something_pending(), clear_constraints_minimized(), clear_constraints_up_to_date(), clear_generators_minimized(), clear_generators_up_to_date(), con_sys, constraints_are_up_to_date(), Parma_Polyhedra_Library::Constraint::epsilon_leq_one(), gen_sys, generators_are_up_to_date(), has_pending_constraints(), has_pending_generators(), Parma_Polyhedra_Library::Constraint_System::insert(), is_necessarily_closed(), Parma_Polyhedra_Library::Constraint::is_tautological(), marked_empty(), Parma_Polyhedra_Library::Row::normalize(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), process_pending_constraints(), set_generators_pending(), Parma_Polyhedra_Library::Linear_System::set_sorted(), space_dim, and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
Referenced by ppl_Polyhedron_topological_closure_assign().
02751 { 02752 // Necessarily closed polyhedra are trivially closed. 02753 if (is_necessarily_closed()) 02754 return; 02755 // Any empty or zero-dimensional polyhedron is closed. 02756 if (marked_empty() || space_dim == 0) 02757 return; 02758 02759 // The computation can be done using constraints or generators. 02760 // If we use constraints, we will change them, so that having pending 02761 // constraints would be useless. If we use generators, we add generators, 02762 // so that having pending generators still makes sense. 02763 02764 // Process any pending constraints. 02765 if (has_pending_constraints() && !process_pending_constraints()) 02766 return; 02767 02768 // Use constraints only if they are available and 02769 // there are no pending generators. 02770 if (!has_pending_generators() && constraints_are_up_to_date()) { 02771 const dimension_type eps_index = space_dim + 1; 02772 bool changed = false; 02773 // Transform all strict inequalities into non-strict ones. 02774 for (dimension_type i = con_sys.num_rows(); i-- > 0; ) { 02775 Constraint& c = con_sys[i]; 02776 if (c[eps_index] < 0 && !c.is_tautological()) { 02777 c[eps_index] = 0; 02778 // Enforce normalization. 02779 c.normalize(); 02780 changed = true; 02781 } 02782 } 02783 if (changed) { 02784 con_sys.insert(Constraint::epsilon_leq_one()); 02785 con_sys.set_sorted(false); 02786 // After changing the system of constraints, the generators 02787 // are no longer up-to-date and the constraints are no longer 02788 // minimized. 02789 clear_generators_up_to_date(); 02790 clear_constraints_minimized(); 02791 } 02792 } 02793 else { 02794 // Here we use generators, possibly keeping constraints. 02795 assert(generators_are_up_to_date()); 02796 // Add the corresponding point to each closure point. 02797 gen_sys.add_corresponding_points(); 02798 if (can_have_something_pending()) 02799 set_generators_pending(); 02800 else { 02801 // We cannot have pending generators; this also implies 02802 // that generators may have lost their sortedness. 02803 gen_sys.unset_pending_rows(); 02804 gen_sys.set_sorted(false); 02805 // Constraints are not up-to-date and generators are not minimized. 02806 clear_constraints_up_to_date(); 02807 clear_generators_minimized(); 02808 } 02809 } 02810 assert(OK()); 02811 }
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 653 of file Polyhedron_widenings.cc.
References BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), contains(), intersection_assign_and_minimize(), is_necessarily_closed(), Parma_Polyhedra_Library::BHRZ03_Certificate::is_stabilizing(), marked_empty(), minimize(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), select_H79_constraints(), space_dim, throw_dimension_incompatible(), throw_topology_incompatible(), topology(), and Parma_Polyhedra_Library::UNIVERSE.
Referenced by limited_BHRZ03_extrapolation_assign(), and ppl_Polyhedron_BHRZ03_widening_assign_with_tokens().
00653 { 00654 Polyhedron& x = *this; 00655 // Topology compatibility check. 00656 if (x.topology() != y.topology()) 00657 throw_topology_incompatible("BHRZ03_widening_assign(y)", "y", y); 00658 // Dimension-compatibility check. 00659 if (x.space_dim != y.space_dim) 00660 throw_dimension_incompatible("BHRZ03_widening_assign(y)", "y", y); 00661 00662 #ifndef NDEBUG 00663 { 00664 // We assume that y is contained in or equal to x. 00665 const Polyhedron x_copy = x; 00666 const Polyhedron y_copy = y; 00667 assert(x_copy.contains(y_copy)); 00668 } 00669 #endif 00670 00671 // If any argument is zero-dimensional or empty, 00672 // the BHRZ03-widening behaves as the identity function. 00673 if (x.space_dim == 0 || x.marked_empty() || y.marked_empty()) 00674 return; 00675 00676 // `x.con_sys' and `x.gen_sys' should be in minimal form. 00677 x.minimize(); 00678 00679 // `y.con_sys' and `y.gen_sys' should be in minimal form. 00680 if (y.is_necessarily_closed()) { 00681 if (!y.minimize()) 00682 // `y' is empty: the result is `x'. 00683 return; 00684 } 00685 else { 00686 // Dealing with a NNC polyhedron. 00687 // To obtain a correct reasoning when comparing 00688 // the constraints of `x' with the generators of `y', 00689 // we enforce the inclusion relation holding between 00690 // the two NNC polyhedra `x' and `y' (i.e., `y <= x') 00691 // to also hold for the corresponding eps-representations: 00692 // this is obtained by intersecting the two eps-representations. 00693 Polyhedron& yy = const_cast<Polyhedron&>(y); 00694 if (!yy.intersection_assign_and_minimize(x)) 00695 // `y' is empty: the result is `x'. 00696 return; 00697 } 00698 00699 // Compute certificate info for polyhedron `y'. 00700 BHRZ03_Certificate y_cert(y); 00701 00702 // If the iteration is stabilizing, the resulting polyhedron is `x'. 00703 // At this point, also check if the two polyhedra are the same 00704 // (exploiting the knowledge that `y <= x'). 00705 if (y_cert.is_stabilizing(x) || y.contains(x)) { 00706 assert(OK()); 00707 return; 00708 } 00709 00710 // Here the iteration is not immediately stabilizing. 00711 // If we are using the widening-with-tokens technique and 00712 // there are tokens available, use one of them and return `x'. 00713 if (tp != 0 && *tp > 0) { 00714 --(*tp); 00715 assert(OK()); 00716 return; 00717 } 00718 00719 // Copy into `H79_cs' the constraints that are common to `x' and `y', 00720 // according to the definition of the H79 widening. 00721 // The other ones are copied into `x_minus_H79_cs'. 00722 const Topology tpl = x.topology(); 00723 Constraint_System H79_cs(tpl); 00724 Constraint_System x_minus_H79_cs(tpl); 00725 x.select_H79_constraints(y, H79_cs, x_minus_H79_cs); 00726 00727 // We cannot have selected all of the rows, since otherwise 00728 // the iteration should have been immediately stabilizing. 00729 assert(x_minus_H79_cs.num_rows() > 0); 00730 // Be careful to obtain the right space dimension 00731 // (because `H79_cs' may be empty). 00732 Polyhedron H79(tpl, x.space_dim, UNIVERSE); 00733 H79.add_recycled_constraints_and_minimize(H79_cs); 00734 00735 // NOTE: none of the following widening heuristics is intrusive: 00736 // they will modify `x' only when returning successfully. 00737 if (x.BHRZ03_combining_constraints(y, y_cert, H79, x_minus_H79_cs)) 00738 return; 00739 00740 assert(H79.OK() && x.OK() && y.OK()); 00741 00742 if (x.BHRZ03_evolving_points(y, y_cert, H79)) 00743 return; 00744 00745 assert(H79.OK() && x.OK() && y.OK()); 00746 00747 if (x.BHRZ03_evolving_rays(y, y_cert, H79)) 00748 return; 00749 00750 assert(H79.OK() && x.OK() && y.OK()); 00751 00752 // No previous technique was successful: fall back to the H79 widening. 00753 std::swap(x, H79); 00754 assert(x.OK(true)); 00755 00756 #ifndef NDEBUG 00757 // The H79 widening is always stabilizing. 00758 x.minimize(); 00759 assert(y_cert.is_stabilizing(x)); 00760 #endif 00761 }
void Parma_Polyhedra_Library::Polyhedron::limited_BHRZ03_extrapolation_assign | ( | const Polyhedron & | y, | |
const Constraint_System & | cs, | |||
unsigned * | tp = 0 | |||
) |
Improves the result of the BHRZ03-widening computation by also enforcing those constraints in cs
that are satisfied by all the points of *this
.
y | A polyhedron that must be contained in *this ; | |
cs | The system of constraints used to improve the widened polyhedron; | |
tp | An optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique). |
std::invalid_argument | Thrown if *this , y and cs are topology-incompatible or dimension-incompatible. |
Definition at line 765 of file Polyhedron_widenings.cc.
References add_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(), and ppl_Polyhedron_limited_BHRZ03_extrapolation_assign_with_tokens().
00767 { 00768 Polyhedron& x = *this; 00769 const dimension_type cs_num_rows = cs.num_rows(); 00770 // If `cs' is empty, we fall back to ordinary, non-limited widening. 00771 if (cs_num_rows == 0) { 00772 x.BHRZ03_widening_assign(y, tp); 00773 return; 00774 } 00775 00776 // Topology compatibility check. 00777 if (x.is_necessarily_closed()) { 00778 if (!y.is_necessarily_closed()) 00779 throw_topology_incompatible("limited_BHRZ03_extrapolation_assign(y, cs)", 00780 "y", y); 00781 if (cs.has_strict_inequalities()) 00782 throw_topology_incompatible("limited_BHRZ03_extrapolation_assign(y, cs)", 00783 "cs", cs); 00784 } 00785 else if (y.is_necessarily_closed()) 00786 throw_topology_incompatible("limited_BHRZ03_extrapolation_assign(y, cs)", 00787 "y", y); 00788 00789 // Dimension-compatibility check. 00790 if (x.space_dim != y.space_dim) 00791 throw_dimension_incompatible("limited_BHRZ03_extrapolation_assign(y, cs)", 00792 "y", y); 00793 // `cs' must be dimension-compatible with the two polyhedra. 00794 const dimension_type cs_space_dim = cs.space_dimension(); 00795 if (x.space_dim < cs_space_dim) 00796 throw_dimension_incompatible("limited_BHRZ03_extrapolation_assign(y, cs)", 00797 "cs", cs); 00798 00799 #ifndef NDEBUG 00800 { 00801 // We assume that y is contained in or equal to x. 00802 const Polyhedron x_copy = x; 00803 const Polyhedron y_copy = y; 00804 assert(x_copy.contains(y_copy)); 00805 } 00806 #endif 00807 00808 if (y.marked_empty()) 00809 return; 00810 if (x.marked_empty()) 00811 return; 00812 00813 // The limited BHRZ03-widening between two polyhedra in a 00814 // zero-dimensional space is a polyhedron in a zero-dimensional 00815 // space, too. 00816 if (x.space_dim == 0) 00817 return; 00818 00819 if (!y.minimize()) 00820 // We have just discovered that `y' is empty. 00821 return; 00822 00823 // Update the generators of `x': these are used to select, 00824 // from the constraints in `cs', those that must be added 00825 // to the resulting polyhedron. 00826 if ((x.has_pending_constraints() && !x.process_pending_constraints()) 00827 || (!x.generators_are_up_to_date() && !x.update_generators())) 00828 // We have just discovered that `x' is empty. 00829 return; 00830 00831 Constraint_System new_cs; 00832 // The constraints to be added must be satisfied by all the 00833 // generators of `x'. We can disregard `y' because `y <= x'. 00834 const Generator_System& x_gen_sys = x.gen_sys; 00835 // Iterate upwards here so as to keep the relative ordering of constraints. 00836 // Not really an issue: just aesthetics. 00837 for (dimension_type i = 0; i < cs_num_rows; ++i) { 00838 const Constraint& c = cs[i]; 00839 if (x_gen_sys.satisfied_by_all_generators(c)) 00840 new_cs.insert(c); 00841 } 00842 x.BHRZ03_widening_assign(y, tp); 00843 x.add_constraints(new_cs); 00844 assert(OK()); 00845 }
void Parma_Polyhedra_Library::Polyhedron::bounded_BHRZ03_extrapolation_assign | ( | const Polyhedron & | y, | |
const Constraint_System & | cs, | |||
unsigned * | tp = 0 | |||
) |
Improves the result of the BHRZ03-widening computation by also enforcing those constraints in cs
that are satisfied by all the points of *this
, plus all the constraints of the form and
, with
, that are satisfied by all the points of
*this
.
y | A polyhedron that must be contained in *this ; | |
cs | The system of constraints used to improve the widened polyhedron; | |
tp | An optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique). |
std::invalid_argument | Thrown if *this , y and cs are topology-incompatible or dimension-incompatible. |
Definition at line 849 of file Polyhedron_widenings.cc.
References add_constraints(), Parma_Polyhedra_Library::ANY_COMPLEXITY, Parma_Polyhedra_Library::Bounding_Box::CC76_widening_assign(), Parma_Polyhedra_Library::Bounding_Box::constraints(), limited_BHRZ03_extrapolation_assign(), shrink_bounding_box(), space_dim, and space_dimension().
Referenced by ppl_Polyhedron_bounded_BHRZ03_extrapolation_assign_with_tokens().
00851 { 00852 const dimension_type space_dim = space_dimension(); 00853 Bounding_Box x_box(space_dim); 00854 Bounding_Box y_box(space_dim); 00855 shrink_bounding_box(x_box, ANY_COMPLEXITY); 00856 y.shrink_bounding_box(y_box, ANY_COMPLEXITY); 00857 x_box.CC76_widening_assign(y_box); 00858 limited_BHRZ03_extrapolation_assign(y, cs, tp); 00859 // TODO: see if some copies can be avoided. 00860 // add_recycled_constraints(x_box.constraints()); 00861 add_constraints(x_box.constraints()); 00862 }
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 146 of file Polyhedron_widenings.cc.
References add_recycled_constraints(), con_sys, constraints_are_up_to_date(), contains(), has_pending_generators(), intersection_assign_and_minimize(), 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, 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 ppl_Polyhedron_H79_widening_assign_with_tokens().
00146 { 00147 Polyhedron& x = *this; 00148 // Topology compatibility check. 00149 const Topology tpl = x.topology(); 00150 if (tpl != y.topology()) 00151 throw_topology_incompatible("H79_widening_assign(y)", "y", y); 00152 // Dimension-compatibility check. 00153 if (x.space_dim != y.space_dim) 00154 throw_dimension_incompatible("H79_widening_assign(y)", "y", y); 00155 00156 #ifndef NDEBUG 00157 { 00158 // We assume that y is contained in or equal to x. 00159 const Polyhedron x_copy = x; 00160 const Polyhedron y_copy = y; 00161 assert(x_copy.contains(y_copy)); 00162 } 00163 #endif 00164 00165 // If any argument is zero-dimensional or empty, 00166 // the H79-widening behaves as the identity function. 00167 if (x.space_dim == 0 || x.marked_empty() || y.marked_empty()) 00168 return; 00169 00170 // `y.gen_sys' should be in minimal form and 00171 // `y.sat_g' should be up-to-date. 00172 if (y.is_necessarily_closed()) { 00173 if (!y.minimize()) 00174 // `y' is empty: the result is `x'. 00175 return; 00176 } 00177 else { 00178 // Dealing with a NNC polyhedron. 00179 // To obtain a correct reasoning when comparing 00180 // the constraints of `x' with the generators of `y', 00181 // we enforce the inclusion relation holding between 00182 // the two NNC polyhedra `x' and `y' (i.e., `y <= x') 00183 // to also hold for the corresponding eps-representations: 00184 // this is obtained by intersecting the two eps-representations. 00185 Polyhedron& yy = const_cast<Polyhedron&>(y); 00186 if (!yy.intersection_assign_and_minimize(x)) 00187 // `y' is empty: the result is `x'. 00188 return; 00189 } 00190 00191 // If we only have the generators of `x' and the dimensions of 00192 // the two polyhedra are the same, we can compute the standard 00193 // widening by using the specification in CousotH78, therefore 00194 // avoiding converting from generators to constraints. 00195 if (x.has_pending_generators() || !x.constraints_are_up_to_date()) { 00196 Constraint_System CH78_cs(tpl); 00197 x.select_CH78_constraints(y, CH78_cs); 00198 00199 if (CH78_cs.num_rows() == y.con_sys.num_rows()) { 00200 // Having selected all the constraints, the result is `y'. 00201 x = y; 00202 return; 00203 } 00204 // Otherwise, check if `x' and `y' have the same dimension. 00205 // Note that `y.con_sys' is minimized and `CH78_cs' has no redundant 00206 // constraints, since it is a subset of the former. 00207 else if (CH78_cs.num_equalities() == y.con_sys.num_equalities()) { 00208 // Let `x' be defined by the constraints in `CH78_cs'. 00209 Polyhedron CH78(tpl, x.space_dim, UNIVERSE); 00210 CH78.add_recycled_constraints(CH78_cs); 00211 00212 // Check whether we are using the widening-with-tokens technique 00213 // and there still are tokens available. 00214 if (tp != 0 && *tp > 0) { 00215 // There are tokens available. If `CH78' is not a subset of `x', 00216 // then it is less precise and we use one of the available tokens. 00217 if (!x.contains(CH78)) 00218 --(*tp); 00219 } 00220 else 00221 // No tokens. 00222 std::swap(x, CH78); 00223 assert(x.OK(true)); 00224 return; 00225 } 00226 } 00227 00228 // As the dimension of `x' is strictly greater than the dimension of `y', 00229 // we have to compute the standard widening by selecting a subset of 00230 // the constraints of `x'. 00231 // `x.con_sys' is just required to be up-to-date, because: 00232 // - if `x.con_sys' is unsatisfiable, then by assumption 00233 // also `y' is empty, so that the resulting polyhedron is `x'; 00234 // - redundant constraints in `x.con_sys' do not affect the result 00235 // of the widening, because if they are selected they will be 00236 // redundant even in the result. 00237 if (has_pending_generators()) 00238 process_pending_generators(); 00239 else if (!x.constraints_are_up_to_date()) 00240 x.update_constraints(); 00241 00242 // Copy into `H79_cs' the constraints of `x' that are common to `y', 00243 // according to the definition of the H79 widening. 00244 Constraint_System H79_cs(tpl); 00245 Constraint_System x_minus_H79_cs(tpl); 00246 x.select_H79_constraints(y, H79_cs, x_minus_H79_cs); 00247 00248 if (x_minus_H79_cs.num_rows() == 0) 00249 // We selected all of the constraints of `x', 00250 // thus the result of the widening is `x'. 00251 return; 00252 else { 00253 // We selected a strict subset of the constraints of `x'. 00254 // NOTE: as `x.con_sys' was not necessarily in minimal form, 00255 // this does not imply that the result strictly includes `x'. 00256 // Let `H79' be defined by the constraints in `H79_cs'. 00257 Polyhedron H79(tpl, x.space_dim, UNIVERSE); 00258 H79.add_recycled_constraints(H79_cs); 00259 00260 // Check whether we are using the widening-with-tokens technique 00261 // and there still are tokens available. 00262 if (tp != 0 && *tp > 0) { 00263 // There are tokens available. If `H79' is not a subset of `x', 00264 // then it is less precise and we use one of the available tokens. 00265 if (!x.contains(H79)) 00266 --(*tp); 00267 } 00268 else 00269 // No tokens. 00270 std::swap(x, H79); 00271 assert(x.OK(true)); 00272 } 00273 }
void Parma_Polyhedra_Library::Polyhedron::limited_H79_extrapolation_assign | ( | const Polyhedron & | y, | |
const Constraint_System & | cs, | |||
unsigned * | tp = 0 | |||
) |
Improves the result of the H79-widening computation by also enforcing those constraints in cs
that are satisfied by all the points of *this
.
y | A polyhedron that must be contained in *this ; | |
cs | The system of constraints used to improve the widened polyhedron; | |
tp | An optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique). |
std::invalid_argument | Thrown if *this , y and cs are topology-incompatible or dimension-incompatible. |
Definition at line 276 of file Polyhedron_widenings.cc.
References add_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(), Parma_Polyhedra_Library::BD_Shape< T >::limited_H79_extrapolation_assign(), and ppl_Polyhedron_limited_H79_extrapolation_assign_with_tokens().
00278 { 00279 Polyhedron& x = *this; 00280 00281 const dimension_type cs_num_rows = cs.num_rows(); 00282 // If `cs' is empty, we fall back to ordinary, non-limited widening. 00283 if (cs_num_rows == 0) { 00284 x.H79_widening_assign(y, tp); 00285 return; 00286 } 00287 00288 // Topology compatibility check. 00289 if (x.is_necessarily_closed()) { 00290 if (!y.is_necessarily_closed()) 00291 throw_topology_incompatible("limited_H79_extrapolation_assign(y, cs)", 00292 "y", y); 00293 if (cs.has_strict_inequalities()) 00294 throw_topology_incompatible("limited_H79_extrapolation_assign(y, cs)", 00295 "cs", cs); 00296 } 00297 else if (y.is_necessarily_closed()) 00298 throw_topology_incompatible("limited_H79_extrapolation_assign(y, cs)", 00299 "y", y); 00300 00301 // Dimension-compatibility check. 00302 if (x.space_dim != y.space_dim) 00303 throw_dimension_incompatible("limited_H79_extrapolation_assign(y, cs)", 00304 "y", y); 00305 // `cs' must be dimension-compatible with the two polyhedra. 00306 const dimension_type cs_space_dim = cs.space_dimension(); 00307 if (x.space_dim < cs_space_dim) 00308 throw_dimension_incompatible("limited_H79_extrapolation_assign(y, cs)", 00309 "cs", cs); 00310 00311 #ifndef NDEBUG 00312 { 00313 // We assume that y is contained in or equal to x. 00314 const Polyhedron x_copy = x; 00315 const Polyhedron y_copy = y; 00316 assert(x_copy.contains(y_copy)); 00317 } 00318 #endif 00319 00320 if (y.marked_empty()) 00321 return; 00322 if (x.marked_empty()) 00323 return; 00324 00325 // The limited H79-widening between two polyhedra in a 00326 // zero-dimensional space is a polyhedron in a zero-dimensional 00327 // space, too. 00328 if (x.space_dim == 0) 00329 return; 00330 00331 if (!y.minimize()) 00332 // We have just discovered that `y' is empty. 00333 return; 00334 00335 // Update the generators of `x': these are used to select, 00336 // from the constraints in `cs', those that must be added 00337 // to the resulting polyhedron. 00338 if ((x.has_pending_constraints() && !x.process_pending_constraints()) 00339 || (!x.generators_are_up_to_date() && !x.update_generators())) 00340 // We have just discovered that `x' is empty. 00341 return; 00342 00343 Constraint_System new_cs; 00344 // The constraints to be added must be satisfied by all the 00345 // generators of `x'. We can disregard `y' because `y <= x'. 00346 const Generator_System& x_gen_sys = x.gen_sys; 00347 // Iterate upwards here so as to keep the relative ordering of constraints. 00348 // Not really an issue: just aesthetics. 00349 for (dimension_type i = 0; i < cs_num_rows; ++i) { 00350 const Constraint& c = cs[i]; 00351 if (x_gen_sys.satisfied_by_all_generators(c)) 00352 new_cs.insert(c); 00353 } 00354 x.H79_widening_assign(y, tp); 00355 x.add_constraints(new_cs); 00356 assert(OK()); 00357 }
void Parma_Polyhedra_Library::Polyhedron::bounded_H79_extrapolation_assign | ( | const Polyhedron & | y, | |
const Constraint_System & | cs, | |||
unsigned * | tp = 0 | |||
) |
Improves the result of the H79-widening computation by also enforcing those constraints in cs
that are satisfied by all the points of *this
, plus all the constraints of the form and
, with
, that are satisfied by all the points of
*this
.
y | A polyhedron that must be contained in *this ; | |
cs | The system of constraints used to improve the widened polyhedron; | |
tp | An optional pointer to an unsigned variable storing the number of available tokens (to be used when applying the widening with tokens delay technique). |
std::invalid_argument | Thrown if *this , y and cs are topology-incompatible or dimension-incompatible. |
Definition at line 360 of file Polyhedron_widenings.cc.
References add_constraints(), Parma_Polyhedra_Library::ANY_COMPLEXITY, Parma_Polyhedra_Library::Bounding_Box::CC76_widening_assign(), Parma_Polyhedra_Library::Bounding_Box::constraints(), limited_H79_extrapolation_assign(), shrink_bounding_box(), space_dim, and space_dimension().
Referenced by ppl_Polyhedron_bounded_H79_extrapolation_assign_with_tokens().
00362 { 00363 const dimension_type space_dim = space_dimension(); 00364 Bounding_Box x_box(space_dim); 00365 Bounding_Box y_box(space_dim); 00366 shrink_bounding_box(x_box, ANY_COMPLEXITY); 00367 y.shrink_bounding_box(y_box, ANY_COMPLEXITY); 00368 x_box.CC76_widening_assign(y_box); 00369 limited_H79_extrapolation_assign(y, cs, tp); 00370 // TODO: see if some copies can be avoided. 00371 // add_recycled_constraints(x_box.constraints()); 00372 add_constraints(x_box.constraints()); 00373 }
void Parma_Polyhedra_Library::Polyhedron::add_space_dimensions_and_embed | ( | dimension_type | m | ) |
Adds m
new space dimensions and embeds the old polyhedron in the new vector space.
m | The number of dimensions to add. |
std::length_error | Thrown if adding m new space dimensions would cause the vector space to exceed dimension max_space_dimension() . |
Definition at line 90 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(), generalized_affine_preimage(), and ppl_Polyhedron_add_space_dimensions_and_embed().
00090 { 00091 // The space dimension of the resulting polyhedron should not 00092 // overflow the maximum allowed space dimension. 00093 if (m > max_space_dimension() - space_dimension()) 00094 throw_space_dimension_overflow(topology(), 00095 "add_space_dimensions_and_embed(m)", 00096 "adding m new space dimensions exceeds " 00097 "the maximum allowed space dimension"); 00098 00099 // Adding no dimensions to any polyhedron is a no-op. 00100 if (m == 0) 00101 return; 00102 00103 // Adding dimensions to an empty polyhedron is obtained by adjusting 00104 // `space_dim' and clearing `con_sys' (since it can contain the 00105 // unsatisfiable constraint system of the wrong dimension). 00106 if (marked_empty()) { 00107 space_dim += m; 00108 con_sys.clear(); 00109 return; 00110 } 00111 00112 // The case of a zero-dimensional space polyhedron. 00113 if (space_dim == 0) { 00114 // Since it is not empty, it has to be the universe polyhedron. 00115 assert(status.test_zero_dim_univ()); 00116 // We swap `*this' with a newly created 00117 // universe polyhedron of dimension `m'. 00118 Polyhedron ph(topology(), m, UNIVERSE); 00119 swap(ph); 00120 return; 00121 } 00122 00123 // To embed an n-dimension space polyhedron in a (n+m)-dimension space, 00124 // we just add `m' zero-columns to the rows in the system of constraints; 00125 // in contrast, the system of generators needs additional rows, 00126 // corresponding to the vectors of the canonical basis 00127 // for the added dimensions. That is, for each new dimension `x[k]' 00128 // we add the line having that direction. This is done by invoking 00129 // the function add_space_dimensions() giving the system of generators 00130 // as the second argument. 00131 if (constraints_are_up_to_date()) 00132 if (generators_are_up_to_date()) { 00133 // `sat_c' must be up to date for add_space_dimensions(...). 00134 if (!sat_c_is_up_to_date()) 00135 update_sat_c(); 00136 // Adds rows and/or columns to both matrices. 00137 // `add_space_dimensions' correctly handles pending constraints 00138 // or generators. 00139 add_space_dimensions(con_sys, gen_sys, sat_c, sat_g, m); 00140 } 00141 else { 00142 // Only constraints are up-to-date: no need to modify the generators. 00143 con_sys.add_zero_columns(m); 00144 // If the polyhedron is not necessarily closed, 00145 // move the epsilon coefficients to the last column. 00146 if (!is_necessarily_closed()) 00147 con_sys.swap_columns(space_dim + 1, space_dim + 1 + m); 00148 } 00149 else { 00150 // Only generators are up-to-date: no need to modify the constraints. 00151 assert(generators_are_up_to_date()); 00152 gen_sys.add_rows_and_columns(m); 00153 // The polyhedron does not support pending generators. 00154 gen_sys.unset_pending_rows(); 00155 // If the polyhedron is not necessarily closed, 00156 // move the epsilon coefficients to the last column. 00157 if (!is_necessarily_closed()) { 00158 // Try to preserve sortedness of `gen_sys'. 00159 if (!gen_sys.is_sorted()) 00160 gen_sys.swap_columns(space_dim + 1, space_dim + 1 + m); 00161 else { 00162 dimension_type old_eps_index = space_dim + 1; 00163 dimension_type new_eps_index = old_eps_index + m; 00164 for (dimension_type i = gen_sys.num_rows(); i-- > m; ) { 00165 Generator& r = gen_sys[i]; 00166 std::swap(r[old_eps_index], r[new_eps_index]); 00167 } 00168 // The upper-right corner of `gen_sys' contains the J matrix: 00169 // swap coefficients to preserve sortedness. 00170 for (dimension_type i = m; i-- > 0; ++old_eps_index) { 00171 Generator& r = gen_sys[i]; 00172 std::swap(r[old_eps_index], r[old_eps_index + 1]); 00173 } 00174 } 00175 } 00176 } 00177 // Update the space dimension. 00178 space_dim += m; 00179 00180 // Note: we do not check for satisfiability, because the system of 00181 // constraints may be unsatisfiable. 00182 assert(OK()); 00183 }
void Parma_Polyhedra_Library::Polyhedron::add_space_dimensions_and_project | ( | dimension_type | m | ) |
Adds m
new space dimensions to the polyhedron and does not embed it in the new vector space.
m | The number of space dimensions to add. |
std::length_error | Thrown if adding m new space dimensions would cause the vector space to exceed dimension max_space_dimension() . |
Definition at line 186 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::Generator_System::insert(), is_necessarily_closed(), Parma_Polyhedra_Library::Linear_System::is_sorted(), marked_empty(), max_space_dimension(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), sat_c, sat_g, sat_g_is_up_to_date(), set_generators_minimized(), space_dim, space_dimension(), status, Parma_Polyhedra_Library::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().
Referenced by ppl_Polyhedron_add_space_dimensions_and_project().
00186 { 00187 // The space dimension of the resulting polyhedron should not 00188 // overflow the maximum allowed space dimension. 00189 if (m > max_space_dimension() - space_dimension()) 00190 throw_space_dimension_overflow(topology(), 00191 "add_space_dimensions_and_project(m)", 00192 "adding m new space dimensions exceeds " 00193 "the maximum allowed space dimension"); 00194 00195 // Adding no dimensions to any polyhedron is a no-op. 00196 if (m == 0) 00197 return; 00198 00199 // Adding dimensions to an empty polyhedron is obtained 00200 // by merely adjusting `space_dim'. 00201 if (marked_empty()) { 00202 space_dim += m; 00203 con_sys.clear(); 00204 return; 00205 } 00206 00207 if (space_dim == 0) { 00208 assert(status.test_zero_dim_univ() && gen_sys.num_rows() == 0); 00209 // The system of generators for this polyhedron has only 00210 // the origin as a point. 00211 // In an NNC polyhedron, all points have to be accompanied 00212 // by the corresponding closure points 00213 // (this time, dimensions are automatically adjusted). 00214 if (!is_necessarily_closed()) 00215 gen_sys.insert(Generator::zero_dim_closure_point()); 00216 gen_sys.insert(Generator::zero_dim_point()); 00217 gen_sys.adjust_topology_and_space_dimension(topology(), m); 00218 set_generators_minimized(); 00219 space_dim = m; 00220 assert(OK()); 00221 return; 00222 } 00223 00224 // To project an n-dimension space polyhedron in a (n+m)-dimension space, 00225 // we just add to the system of generators `m' zero-columns; 00226 // In contrast, in the system of constraints, new rows are needed 00227 // in order to avoid embedding the old polyhedron in the new space. 00228 // Thus, for each new dimensions `x[k]', we add the constraint 00229 // x[k] = 0; this is done by invoking the function add_space_dimensions() 00230 // giving the system of constraints as the second argument. 00231 if (constraints_are_up_to_date()) 00232 if (generators_are_up_to_date()) { 00233 // `sat_g' must be up to date for add_space_dimensions(...). 00234 if (!sat_g_is_up_to_date()) 00235 update_sat_g(); 00236 // Adds rows and/or columns to both matrices. 00237 // `add_space_dimensions' correctly handles pending constraints 00238 // or generators. 00239 add_space_dimensions(gen_sys, con_sys, sat_g, sat_c, m); 00240 } 00241 else { 00242 // Only constraints are up-to-date: no need to modify the generators. 00243 con_sys.add_rows_and_columns(m); 00244 // The polyhedron does not support pending constraints. 00245 con_sys.unset_pending_rows(); 00246 // If the polyhedron is not necessarily closed, 00247 // move the epsilon coefficients to the last column. 00248 if (!is_necessarily_closed()) { 00249 // Try to preserve sortedness of `con_sys'. 00250 if (!con_sys.is_sorted()) 00251 con_sys.swap_columns(space_dim + 1, space_dim + 1 + m); 00252 else { 00253 dimension_type old_eps_index = space_dim + 1; 00254 dimension_type new_eps_index = old_eps_index + m; 00255 for (dimension_type i = con_sys.num_rows(); i-- > m; ) { 00256 Constraint& r = con_sys[i]; 00257 std::swap(r[old_eps_index], r[new_eps_index]); 00258 } 00259 // The upper-right corner of `con_sys' contains the J matrix: 00260 // swap coefficients to preserve sortedness. 00261 for (dimension_type i = m; i-- > 0; ++old_eps_index) { 00262 Constraint& r = con_sys[i]; 00263 std::swap(r[old_eps_index], r[old_eps_index + 1]); 00264 } 00265 } 00266 } 00267 } 00268 else { 00269 // Only generators are up-to-date: no need to modify the constraints. 00270 assert(generators_are_up_to_date()); 00271 gen_sys.add_zero_columns(m); 00272 // If the polyhedron is not necessarily closed, 00273 // move the epsilon coefficients to the last column. 00274 if (!is_necessarily_closed()) 00275 gen_sys.swap_columns(space_dim + 1, space_dim + 1 + m); 00276 } 00277 // Now we update the space dimension. 00278 space_dim += m; 00279 00280 // Note: we do not check for satisfiability, because the system of 00281 // constraints may be unsatisfiable. 00282 assert(OK()); 00283 }
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 286 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::Saturation_Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Saturation_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::Saturation_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, space_dimension(), Parma_Polyhedra_Library::Matrix::swap_columns(), throw_space_dimension_overflow(), throw_topology_incompatible(), topology(), Parma_Polyhedra_Library::Saturation_Matrix::transpose_assign(), Parma_Polyhedra_Library::Linear_System::unset_pending_rows(), and update_constraints().
Referenced by ppl_Polyhedron_concatenate_assign().
00286 { 00287 if (topology() != y.topology()) 00288 throw_topology_incompatible("concatenate_assign(y)", "y", y); 00289 00290 // The space dimension of the resulting polyhedron should not 00291 // overflow the maximum allowed space dimension. 00292 if (y.space_dim > max_space_dimension() - space_dimension()) 00293 throw_space_dimension_overflow(topology(), 00294 "concatenate_assign(y)", 00295 "concatenation exceeds the maximum " 00296 "allowed space dimension"); 00297 00298 const dimension_type added_columns = y.space_dim; 00299 00300 // If `*this' or `y' are empty polyhedra, it is sufficient to adjust 00301 // the dimension of the space. 00302 if (marked_empty() || y.marked_empty()) { 00303 space_dim += added_columns; 00304 set_empty(); 00305 return; 00306 } 00307 00308 // If `y' is a non-empty 0-dim space polyhedron, the result is `*this'. 00309 if (added_columns == 0) 00310 return; 00311 00312 // If `*this' is a non-empty 0-dim space polyhedron, the result is `y'. 00313 if (space_dim == 0) { 00314 *this = y; 00315 return; 00316 } 00317 00318 // TODO: this implementation is just an executable specification. 00319 Constraint_System cs = y.constraints(); 00320 00321 // The constraints of `x' (possibly with pending rows) are required. 00322 if (has_pending_generators()) 00323 process_pending_generators(); 00324 else if (!constraints_are_up_to_date()) 00325 update_constraints(); 00326 00327 // The matrix for the new system of constraints is obtained 00328 // by leaving the old system of constraints in the upper left-hand side 00329 // and placing the constraints of `cs' in the lower right-hand side. 00330 // NOTE: here topologies agree, whereas dimensions may not agree. 00331 dimension_type old_num_rows = con_sys.num_rows(); 00332 dimension_type old_num_columns = con_sys.num_columns(); 00333 dimension_type added_rows = cs.num_rows(); 00334 00335 // We already dealt with the cases of an empty or zero-dim `y' polyhedron; 00336 // also, `cs' contains the low-level constraints, at least. 00337 assert(added_rows > 0 && added_columns > 0); 00338 00339 con_sys.add_zero_rows_and_columns(added_rows, added_columns, 00340 Linear_Row::Flags(topology(), 00341 Linear_Row::RAY_OR_POINT_OR_INEQUALITY)); 00342 // Move the epsilon coefficient to the last column, if needed. 00343 if (!is_necessarily_closed()) 00344 con_sys.swap_columns(old_num_columns - 1, 00345 old_num_columns - 1 + added_columns); 00346 dimension_type cs_num_columns = cs.num_columns(); 00347 // Steal the constraints from `cs' and put them in `con_sys' 00348 // using the right displacement for coefficients. 00349 for (dimension_type i = added_rows; i-- > 0; ) { 00350 Constraint& c_old = cs[i]; 00351 Constraint& c_new = con_sys[old_num_rows + i]; 00352 // Method `add_zero_rows_and_columns', by default, added 00353 // 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 assert(OK()); 00414 }
void Parma_Polyhedra_Library::Polyhedron::remove_space_dimensions | ( | const Variables_Set & | to_be_removed | ) |
Removes all the specified dimensions from the vector space.
to_be_removed | The set of Variable objects corresponding to the space dimensions to be removed. |
std::invalid_argument | Thrown if *this is dimension-incompatible with one of the Variable objects contained in to_be_removed . |
Definition at line 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, throw_dimension_incompatible(), and update_generators().
Referenced by fold_space_dimensions(), and ppl_Polyhedron_remove_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 (to_be_removed.empty()) { 00422 assert(OK()); 00423 return; 00424 } 00425 00426 // Dimension-compatibility check: the variable having 00427 // maximum space dimension is the one occurring last in the set. 00428 const dimension_type 00429 min_space_dim = to_be_removed.rbegin()->space_dimension(); 00430 if (space_dim < min_space_dim) 00431 throw_dimension_incompatible("remove_space_dimensions(vs)", min_space_dim); 00432 00433 const dimension_type new_space_dim = space_dim - to_be_removed.size(); 00434 00435 // We need updated generators; note that keeping pending generators 00436 // is useless because the constraints will be dropped anyway. 00437 if (marked_empty() 00438 || (has_something_pending() && !remove_pending_to_obtain_generators()) 00439 || (!generators_are_up_to_date() && !update_generators())) { 00440 // Removing dimensions from the empty polyhedron: 00441 // we clear `con_sys' since it could have contained the 00442 // unsatisfiable constraint of the wrong dimension. 00443 con_sys.clear(); 00444 // Update the space dimension. 00445 space_dim = new_space_dim; 00446 assert(OK()); 00447 return; 00448 } 00449 00450 // When removing _all_ dimensions from a non-empty polyhedron, 00451 // we obtain the zero-dimensional universe polyhedron. 00452 if (new_space_dim == 0) { 00453 set_zero_dim_univ(); 00454 return; 00455 } 00456 00457 // For each variable to be removed, we fill the corresponding column 00458 // by shifting left those columns that will not be removed. 00459 Variables_Set::const_iterator tbr = to_be_removed.begin(); 00460 Variables_Set::const_iterator tbr_end = to_be_removed.end(); 00461 dimension_type dst_col = tbr->space_dimension(); 00462 dimension_type src_col = dst_col + 1; 00463 for (++tbr; tbr != tbr_end; ++tbr) { 00464 dimension_type tbr_col = tbr->space_dimension(); 00465 // All columns in between are moved to the left. 00466 while (src_col < tbr_col) 00467 gen_sys.Matrix::swap_columns(dst_col++, src_col++); 00468 ++src_col; 00469 } 00470 // Moving the remaining columns. 00471 const dimension_type gen_sys_num_columns = gen_sys.num_columns(); 00472 while (src_col < gen_sys_num_columns) 00473 gen_sys.Matrix::swap_columns(dst_col++, src_col++); 00474 00475 // The number of remaining columns is `dst_col'. 00476 // Note that resizing also calls `set_sorted(false)'. 00477 gen_sys.remove_trailing_columns(gen_sys_num_columns - dst_col); 00478 // We may have invalid lines and rays now. 00479 gen_sys.remove_invalid_lines_and_rays(); 00480 00481 // Constraints are not up-to-date and generators are not minimized. 00482 clear_constraints_up_to_date(); 00483 clear_generators_minimized(); 00484 00485 // Update the space dimension. 00486 space_dim = new_space_dim; 00487 00488 assert(OK(true)); 00489 }
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 492 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(), generalized_affine_preimage(), and ppl_Polyhedron_remove_higher_space_dimensions().
00492 { 00493 // Dimension-compatibility check. 00494 if (new_dimension > space_dim) 00495 throw_dimension_incompatible("remove_higher_space_dimensions(nd)", 00496 new_dimension); 00497 00498 // The removal of no dimensions from any polyhedron is a no-op. 00499 // Note that this case also captures the only legal removal of 00500 // dimensions from a polyhedron in a 0-dim space. 00501 if (new_dimension == space_dim) { 00502 assert(OK()); 00503 return; 00504 } 00505 00506 // We need updated generators; note that keeping pending generators 00507 // is useless because constraints will be dropped anyway. 00508 if (marked_empty() 00509 || (has_something_pending() && !remove_pending_to_obtain_generators()) 00510 || (!generators_are_up_to_date() && !update_generators())) { 00511 // Removing dimensions from the empty polyhedron: 00512 // just updates the space dimension. 00513 space_dim = new_dimension; 00514 con_sys.clear(); 00515 assert(OK()); 00516 return; 00517 } 00518 00519 if (new_dimension == 0) { 00520 // Removing all dimensions from a non-empty polyhedron: 00521 // just return the zero-dimensional universe polyhedron. 00522 set_zero_dim_univ(); 00523 return; 00524 } 00525 00526 dimension_type new_num_cols = new_dimension + 1; 00527 if (!is_necessarily_closed()) { 00528 // The polyhedron is not necessarily closed: move the column 00529 // of the epsilon coefficients to its new place. 00530 gen_sys.swap_columns(gen_sys.num_columns() - 1, new_num_cols); 00531 // The number of remaining columns is `new_dimension + 2'. 00532 ++new_num_cols; 00533 } 00534 // Note that resizing also calls `set_sorted(false)'. 00535 gen_sys.remove_trailing_columns(space_dim - new_dimension); 00536 // We may have invalid lines and rays now. 00537 gen_sys.remove_invalid_lines_and_rays(); 00538 00539 // Constraints are not up-to-date and generators are not minimized. 00540 clear_constraints_up_to_date(); 00541 clear_generators_minimized(); 00542 00543 // Update the space dimension. 00544 space_dim = new_dimension; 00545 00546 assert(OK(true)); 00547 }
void Parma_Polyhedra_Library::Polyhedron::map_space_dimensions | ( | const Partial_Function & | pfunc | ) | [inline] |
Remaps the dimensions of the vector space according to a partial function.
pfunc | The partial function specifying the destiny of each space dimension. |
bool has_empty_codomain() const
true
if and only if the represented partial function has an empty codomain (i.e., it is always undefined). The has_empty_codomain()
method will always be called before the methods below. However, if has_empty_codomain()
returns true
, none of the functions below will be called. dimension_type max_in_codomain() const
max_in_codomain()
method is called at most once. bool maps(dimension_type i, dimension_type& j) const
i
. If j
and true
is returned. If false
is returned. This method is called at most
The result is undefined if pfunc
does not encode a partial function with the properties described in the specification of the mapping operator.
Definition at line 363 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(), has_pending_constraints(), Parma_Polyhedra_Library::Generator_System::insert(), Parma_Polyhedra_Library::Generator::LINE, marked_empty(), Parma_Polyhedra_Library::not_a_dimension(), Parma_Polyhedra_Library::Matrix::num_rows(), 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, throw_invalid_argument(), topology(), Parma_Polyhedra_Library::Generator::type(), and update_generators().
Referenced by ppl_Polyhedron_map_space_dimensions().
00363 { 00364 if (space_dim == 0) 00365 return; 00366 00367 if (pfunc.has_empty_codomain()) { 00368 // All dimensions vanish: the polyhedron becomes zero_dimensional. 00369 if (marked_empty() 00370 || (has_pending_constraints() 00371 && !remove_pending_to_obtain_generators()) 00372 || (!generators_are_up_to_date() && !update_generators())) { 00373 // Removing all dimensions from the empty polyhedron. 00374 space_dim = 0; 00375 con_sys.clear(); 00376 } 00377 else 00378 // Removing all dimensions from a non-empty polyhedron. 00379 set_zero_dim_univ(); 00380 00381 assert(OK()); 00382 return; 00383 } 00384 00385 const dimension_type new_space_dimension = pfunc.max_in_codomain() + 1; 00386 00387 if (new_space_dimension == space_dim) { 00388 // The partial function `pfunc' is indeed total and thus specifies 00389 // a permutation, that is, a renaming of the dimensions. For 00390 // maximum efficiency, we will simply permute the columns of the 00391 // constraint system and/or the generator system. 00392 00393 // We first compute suitable permutation cycles for the columns of 00394 // the `con_sys' and `gen_sys' matrices. We will represent them 00395 // with a linear array, using 0 as a terminator for each cycle 00396 // (notice that the columns with index 0 of `con_sys' and 00397 // `gen_sys' represent the inhomogeneous terms, and thus are 00398 // unaffected by the permutation of dimensions). 00399 // Cycles of length 1 will be omitted so that, in the worst case, 00400 // we will have `space_dim' elements organized in `space_dim/2' 00401 // cycles, which means we will have at most `space_dim/2' 00402 // terminators. 00403 std::vector<dimension_type> cycles; 00404 cycles.reserve(space_dim + space_dim/2); 00405 00406 // Used to mark elements as soon as they are inserted in a cycle. 00407 std::deque<bool> visited(space_dim); 00408 00409 for (dimension_type i = space_dim; i-- > 0; ) { 00410 if (!visited[i]) { 00411 dimension_type j = i; 00412 do { 00413 visited[j] = true; 00414 // The following initialization is only to make the compiler happy. 00415 dimension_type k = 0; 00416 if (!pfunc.maps(j, k)) 00417 throw_invalid_argument("map_space_dimensions(pfunc)", 00418 " pfunc is inconsistent"); 00419 if (k == j) 00420 // Cycle of length 1: skip it. 00421 goto skip; 00422 00423 cycles.push_back(j+1); 00424 // Go along the cycle. 00425 j = k; 00426 } while (!visited[j]); 00427 // End of cycle: mark it. 00428 cycles.push_back(0); 00429 skip: 00430 ; 00431 } 00432 } 00433 00434 // If `cycles' is empty then `pfunc' is the identity. 00435 if (cycles.empty()) 00436 return; 00437 00438 // Permute all that is up-to-date. Notice that the contents of 00439 // the saturation matrices is unaffected by the permutation of 00440 // columns: they remain valid, if they were so. 00441 if (constraints_are_up_to_date()) 00442 con_sys.permute_columns(cycles); 00443 00444 if (generators_are_up_to_date()) 00445 gen_sys.permute_columns(cycles); 00446 00447 assert(OK()); 00448 return; 00449 } 00450 00451 // If control gets here, then `pfunc' is not a permutation and some 00452 // dimensions must be projected away. 00453 00454 // If there are pending constraints, using `generators()' we process them. 00455 const Generator_System& old_gensys = generators(); 00456 00457 if (old_gensys.num_rows() == 0) { 00458 // The polyhedron is empty. 00459 Polyhedron new_polyhedron(topology(), new_space_dimension, EMPTY); 00460 std::swap(*this, new_polyhedron); 00461 assert(OK()); 00462 return; 00463 } 00464 00465 // Make a local copy of the partial function. 00466 std::vector<dimension_type> pfunc_maps(space_dim, not_a_dimension()); 00467 for (dimension_type j = space_dim; j-- > 0; ) { 00468 dimension_type pfunc_j; 00469 if (pfunc.maps(j, pfunc_j)) 00470 pfunc_maps[j] = pfunc_j; 00471 } 00472 00473 Generator_System new_gensys; 00474 for (Generator_System::const_iterator i = old_gensys.begin(), 00475 old_gensys_end = old_gensys.end(); i != old_gensys_end; ++i) { 00476 const Generator& old_g = *i; 00477 Linear_Expression e(0 * Variable(new_space_dimension-1)); 00478 bool all_zeroes = true; 00479 for (dimension_type j = space_dim; j-- > 0; ) { 00480 if (old_g.coefficient(Variable(j)) != 0 00481 && pfunc_maps[j] != not_a_dimension()) { 00482 e += Variable(pfunc_maps[j]) * old_g.coefficient(Variable(j)); 00483 all_zeroes = false; 00484 } 00485 } 00486 switch (old_g.type()) { 00487 case Generator::LINE: 00488 if (!all_zeroes) 00489 new_gensys.insert(line(e)); 00490 break; 00491 case Generator::RAY: 00492 if (!all_zeroes) 00493 new_gensys.insert(ray(e)); 00494 break; 00495 case Generator::POINT: 00496 // A point in the origin has all zero homogeneous coefficients. 00497 new_gensys.insert(point(e, old_g.divisor())); 00498 break; 00499 case Generator::CLOSURE_POINT: 00500 // A closure point in the origin has all zero homogeneous coefficients. 00501 new_gensys.insert(closure_point(e, old_g.divisor())); 00502 break; 00503 } 00504 } 00505 Polyhedron new_polyhedron(topology(), new_gensys); 00506 std::swap(*this, new_polyhedron); 00507 assert(OK(true)); 00508 }
void Parma_Polyhedra_Library::Polyhedron::expand_space_dimension | ( | Variable | var, | |
dimension_type | m | |||
) |
Creates m
copies of the space dimension corresponding to var
.
var | The variable corresponding to the space dimension to be replicated; | |
m | The number of replicas to be created. |
std::invalid_argument | Thrown if var does not correspond to a dimension of the vector space. | |
std::length_error | Thrown if adding m new space dimensions would cause the vector space to exceed dimension max_space_dimension() . |
*this
has space dimension var
has space dimension m
new space dimensions Definition at line 550 of file Polyhedron_chdims.cc.
References add_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().
Referenced by ppl_Polyhedron_expand_space_dimension().
00550 { 00551 // TODO: this implementation is _really_ an executable specification. 00552 00553 // `var' should be one of the dimensions of the vector space. 00554 if (var.space_dimension() > space_dim) 00555 throw_dimension_incompatible("expand_space_dimension(v, m)", "v", var); 00556 00557 // The space dimension of the resulting polyhedron should not 00558 // overflow the maximum allowed space dimension. 00559 if (m > max_space_dimension() - space_dimension()) 00560 throw_space_dimension_overflow(topology(), 00561 "expand_dimension(v, m)", 00562 "adding m new space dimensions exceeds " 00563 "the maximum allowed space dimension"); 00564 00565 // Nothing to do, if no dimensions must be added. 00566 if (m == 0) 00567 return; 00568 00569 // Keep track of the dimension before adding the new ones. 00570 dimension_type old_dim = space_dim; 00571 00572 // Add the required new dimensions. 00573 add_space_dimensions_and_embed(m); 00574 00575 const dimension_type src_d = var.id(); 00576 const Constraint_System& cs = constraints(); 00577 Constraint_System new_constraints; 00578 for (Constraint_System::const_iterator i = cs.begin(), 00579 cs_end = cs.end(); i != cs_end; ++i) { 00580 const Constraint& c = *i; 00581 00582 // If `c' does not constrain `var', skip it. 00583 if (c.coefficient(var) == 0) 00584 continue; 00585 00586 // Each relevant constraint results in `m' new constraints. 00587 for (dimension_type dst_d = old_dim; dst_d < old_dim+m; ++dst_d) { 00588 Linear_Expression e; 00589 for (dimension_type j = old_dim; j-- > 0; ) 00590 e += 00591 c.coefficient(Variable(j)) 00592 * (j == src_d ? Variable(dst_d) : Variable(j)); 00593 e += c.inhomogeneous_term(); 00594 new_constraints.insert(c.is_equality() 00595 ? (e == 0) 00596 : (c.is_nonstrict_inequality() 00597 ? (e >= 0) 00598 : (e > 0))); 00599 } 00600 } 00601 add_constraints(new_constraints); 00602 assert(OK()); 00603 }
void Parma_Polyhedra_Library::Polyhedron::fold_space_dimensions | ( | const Variables_Set & | to_be_folded, | |
Variable | var | |||
) |
Folds the space dimensions in to_be_folded
into var
.
to_be_folded | The set of Variable objects corresponding to the space dimensions to be folded; | |
var | The variable corresponding to the space dimension that is the destination of the folding operation. |
std::invalid_argument | Thrown if *this is dimension-incompatible with var or with one of the Variable objects contained in to_be_folded . Also thrown if var is contained in to_be_folded . |
*this
has space dimension var
has space dimension to_be_folded
is a set of variables whose maximum space dimension is also less than or equal to var
is not a member of to_be_folded
, then the space dimensions corresponding to variables in to_be_folded
are folded into the Definition at line 606 of file Polyhedron_chdims.cc.
References affine_image(), OK(), poly_hull_assign(), remove_space_dimensions(), space_dim, Parma_Polyhedra_Library::Variable::space_dimension(), throw_dimension_incompatible(), and throw_invalid_argument().
Referenced by ppl_Polyhedron_fold_space_dimensions().
00607 { 00608 // TODO: this implementation is _really_ an executable specification. 00609 00610 // `var' should be one of the dimensions of the polyhedron. 00611 if (var.space_dimension() > space_dim) 00612 throw_dimension_incompatible("fold_space_dimensions(tbf, v)", "v", var); 00613 00614 // The folding of no dimensions is a no-op. 00615 if (to_be_folded.empty()) 00616 return; 00617 00618 // All variables in `to_be_folded' should be dimensions of the polyhedron. 00619 if (to_be_folded.rbegin()->space_dimension() > space_dim) 00620 throw_dimension_incompatible("fold_space_dimensions(tbf, v)", 00621 "*tbf.rbegin()", 00622 *to_be_folded.rbegin()); 00623 00624 // Moreover, `var' should not occur in `to_be_folded'. 00625 if (to_be_folded.find(var) != to_be_folded.end()) 00626 throw_invalid_argument("fold_space_dimensions(tbf, v)", 00627 "v should not occur in tbf"); 00628 00629 for (Variables_Set::const_iterator i = to_be_folded.begin(), 00630 tbf_end = to_be_folded.end(); i != tbf_end; ++i) { 00631 Polyhedron copy = *this; 00632 copy.affine_image(var, Linear_Expression(*i)); 00633 poly_hull_assign(copy); 00634 } 00635 remove_space_dimensions(to_be_folded); 00636 assert(OK()); 00637 }
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 85 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_space_dimensions_and_embed(), constraints(), generators(), Parma_Polyhedra_Library::NNC_Polyhedron::operator=(), Parma_Polyhedra_Library::C_Polyhedron::operator=(), ppl_Polyhedron_swap(), and swap().
00085 { 00086 if (topology() != y.topology()) 00087 throw_topology_incompatible("swap(y)", "y", y); 00088 std::swap(con_sys, y.con_sys); 00089 std::swap(gen_sys, y.gen_sys); 00090 std::swap(sat_c, y.sat_c); 00091 std::swap(sat_g, y.sat_g); 00092 std::swap(status, y.status); 00093 std::swap(space_dim, y.space_dim); 00094 }
void Parma_Polyhedra_Library::Polyhedron::ascii_dump | ( | ) | const |
void Parma_Polyhedra_Library::Polyhedron::ascii_dump | ( | std::ostream & | s | ) | const |
Writes to s
an ASCII representation of *this
.
Definition at line 2878 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Saturation_Matrix::ascii_dump(), Parma_Polyhedra_Library::Generator_System::ascii_dump(), Parma_Polyhedra_Library::Constraint_System::ascii_dump(), Parma_Polyhedra_Library::Polyhedron::Status::ascii_dump(), con_sys, constraints_are_up_to_date(), gen_sys, generators_are_up_to_date(), sat_c, sat_g, space_dim, and status.
02878 { 02879 s << "space_dim " << space_dim << "\n"; 02880 status.ascii_dump(s); 02881 s << "\ncon_sys (" 02882 << (constraints_are_up_to_date() ? "" : "not_") 02883 << "up-to-date)" 02884 << "\n"; 02885 con_sys.ascii_dump(s); 02886 s << "\ngen_sys (" 02887 << (generators_are_up_to_date() ? "" : "not_") 02888 << "up-to-date)" 02889 << "\n"; 02890 gen_sys.ascii_dump(s); 02891 s << "\nsat_c\n"; 02892 sat_c.ascii_dump(s); 02893 s << "\nsat_g\n"; 02894 sat_g.ascii_dump(s); 02895 s << "\n"; 02896 }
void Parma_Polyhedra_Library::Polyhedron::print | ( | ) | const |
Prints *this
to std::cerr
using operator<<
.
bool Parma_Polyhedra_Library::Polyhedron::ascii_load | ( | std::istream & | s | ) |
Loads from s
an ASCII representation (as produced by ascii_dump) and sets *this
accordingly. Returns true
if successful, false
otherwise.
Definition at line 2901 of file Polyhedron_public.cc.
References Parma_Polyhedra_Library::Saturation_Matrix::ascii_load(), Parma_Polyhedra_Library::Generator_System::ascii_load(), Parma_Polyhedra_Library::Constraint_System::ascii_load(), Parma_Polyhedra_Library::Polyhedron::Status::ascii_load(), con_sys, gen_sys, OK(), sat_c, sat_g, space_dim, and status.
02901 { 02902 std::string str; 02903 02904 if (!(s >> str) || str != "space_dim") 02905 return false; 02906 02907 if (!(s >> space_dim)) 02908 return false; 02909 02910 if (!status.ascii_load(s)) 02911 return false; 02912 02913 if (!(s >> str) || str != "con_sys") 02914 return false; 02915 02916 if (!(s >> str) || (str != "(not_up-to-date)" && str != "(up-to-date)")) 02917 return false; 02918 02919 if (!con_sys.ascii_load(s)) 02920 return false; 02921 02922 if (!(s >> str) || str != "gen_sys") 02923 return false; 02924 02925 if (!(s >> str) || (str != "(not_up-to-date)" && str != "(up-to-date)")) 02926 return false; 02927 02928 if (!gen_sys.ascii_load(s)) 02929 return false; 02930 02931 if (!(s >> str) || str != "sat_c") 02932 return false; 02933 02934 if (!sat_c.ascii_load(s)) 02935 return false; 02936 02937 if (!(s >> str) || str != "sat_g") 02938 return false; 02939 02940 if (!sat_g.ascii_load(s)) 02941 return false; 02942 02943 // Check for well-formedness. 02944 assert(OK()); 02945 return true; 02946 }
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 }
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 2949 of file Polyhedron_public.cc.
References con_sys, Parma_Polyhedra_Library::Saturation_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().
02949 { 02950 return 02951 con_sys.external_memory_in_bytes() 02952 + gen_sys.external_memory_in_bytes() 02953 + sat_c.external_memory_in_bytes() 02954 + sat_g.external_memory_in_bytes(); 02955 }
Topology Parma_Polyhedra_Library::Polyhedron::topology | ( | ) | const [inline, private] |
Returns the topological kind of the polyhedron.
Definition at line 52 of file Polyhedron.inlines.hh.
References con_sys, and Parma_Polyhedra_Library::Linear_System::topology().
Referenced by add_generator(), add_recycled_constraints(), add_recycled_constraints_and_minimize(), add_recycled_generators(), add_recycled_generators_and_minimize(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHRZ03_widening_assign(), concatenate_assign(), constraints(), contains(), expand_space_dimension(), generators(), H79_widening_assign(), intersection_assign(), intersection_assign_and_minimize(), is_included_in(), map_space_dimensions(), OK(), operator=(), poly_difference_assign(), poly_hull_assign(), poly_hull_assign_and_minimize(), Polyhedron(), quick_equivalence_test(), select_CH78_constraints(), select_H79_constraints(), swap(), and time_elapse_assign().
00052 { 00053 // We can check either one of the two matrices. 00054 // (`con_sys' is slightly better, since it is placed at offset 0.) 00055 return con_sys.topology(); 00056 }
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 59 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_constraints_and_minimize(), add_recycled_generators(), add_recycled_generators_and_minimize(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), Parma_Polyhedra_Library::BHRZ03_Certificate::BHRZ03_Certificate(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_widening_assign(), Parma_Polyhedra_Library::H79_Certificate::compare(), Parma_Polyhedra_Library::BHRZ03_Certificate::compare(), concatenate_assign(), generalized_affine_image(), generalized_affine_preimage(), generators(), Parma_Polyhedra_Library::H79_Certificate::H79_Certificate(), H79_widening_assign(), is_topologically_closed(), is_universe(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), minimized_constraints(), minimized_generators(), OK(), poly_difference_assign(), remove_higher_space_dimensions(), shrink_bounding_box(), strongly_minimize_constraints(), strongly_minimize_generators(), throw_dimension_incompatible(), throw_invalid_argument(), throw_invalid_generator(), throw_invalid_generators(), throw_runtime_error(), throw_topology_incompatible(), time_elapse_assign(), and topological_closure_assign().
00059 { 00060 // We can check either one of the two matrices. 00061 // (`con_sys' is slightly better, since it is placed at offset 0.) 00062 return con_sys.is_necessarily_closed(); 00063 }
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 108 of file Polyhedron.inlines.hh.
References status, and Parma_Polyhedra_Library::Polyhedron::Status::test_empty().
Referenced by add_congruence(), add_constraint(), add_generator(), add_recycled_constraints(), add_recycled_generators(), add_recycled_generators_and_minimize(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_image(), affine_preimage(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), Parma_Polyhedra_Library::BHRZ03_Certificate::BHRZ03_Certificate(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHRZ03_widening_assign(), bounded_affine_image(), bounded_affine_preimage(), bounds(), Parma_Polyhedra_Library::H79_Certificate::compare(), Parma_Polyhedra_Library::BHRZ03_Certificate::compare(), concatenate_assign(), constraints(), contains(), generalized_affine_image(), generalized_affine_preimage(), generators(), Parma_Polyhedra_Library::H79_Certificate::H79_Certificate(), H79_widening_assign(), intersection_assign(), intersection_assign_and_minimize(), is_bounded(), is_empty(), is_included_in(), is_topologically_closed(), is_universe(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), map_space_dimensions(), max_min(), minimize(), OK(), operator=(), poly_difference_assign(), poly_hull_assign(), poly_hull_assign_and_minimize(), process_pending(), process_pending_constraints(), process_pending_generators(), quick_equivalence_test(), relation_with(), remove_higher_space_dimensions(), remove_space_dimensions(), select_CH78_constraints(), select_H79_constraints(), shrink_bounding_box(), time_elapse_assign(), topological_closure_assign(), update_constraints(), and update_generators().
00108 { 00109 return status.test_empty(); 00110 }
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 113 of file Polyhedron.inlines.hh.
References status, and Parma_Polyhedra_Library::Polyhedron::Status::test_c_up_to_date().
Referenced by add_constraint(), 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(), concatenate_assign(), constraints(), H79_widening_assign(), intersection_assign(), intersection_assign_and_minimize(), is_included_in(), is_universe(), map_space_dimensions(), minimize(), obtain_sorted_constraints(), obtain_sorted_constraints_with_sat_c(), OK(), operator=(), Polyhedron(), relation_with(), select_H79_constraints(), shrink_bounding_box(), topological_closure_assign(), and update_generators().
00113 { 00114 return status.test_c_up_to_date(); 00115 }
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 118 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(), generators(), 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(), OK(), operator=(), poly_hull_assign(), poly_hull_assign_and_minimize(), Polyhedron(), relation_with(), remove_higher_space_dimensions(), remove_space_dimensions(), select_CH78_constraints(), select_H79_constraints(), shrink_bounding_box(), time_elapse_assign(), topological_closure_assign(), and update_constraints().
00118 { 00119 return status.test_g_up_to_date(); 00120 }
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 123 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(), is_included_in(), is_universe(), minimize(), obtain_sorted_constraints_with_sat_c(), OK(), quick_equivalence_test(), select_CH78_constraints(), select_H79_constraints(), shrink_bounding_box(), update_sat_c(), and update_sat_g().
00123 { 00124 return status.test_c_minimized(); 00125 }
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 128 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(), generators(), is_topologically_closed(), is_universe(), minimize(), OK(), quick_equivalence_test(), update_sat_c(), and update_sat_g().
00128 { 00129 return status.test_g_minimized(); 00130 }
bool Parma_Polyhedra_Library::Polyhedron::has_pending_constraints | ( | ) | const [inline, private] |
Returns true
if there are pending constraints.
Definition at line 143 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(), constraints(), generators(), intersection_assign(), is_bounded(), is_empty(), is_universe(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), map_space_dimensions(), max_min(), OK(), poly_hull_assign(), poly_hull_assign_and_minimize(), process_pending(), process_pending_constraints(), process_pending_generators(), relation_with(), remove_pending_to_obtain_constraints(), remove_pending_to_obtain_generators(), select_CH78_constraints(), shrink_bounding_box(), time_elapse_assign(), and topological_closure_assign().
00143 { 00144 return status.test_c_pending(); 00145 }
bool Parma_Polyhedra_Library::Polyhedron::has_pending_generators | ( | ) | const [inline, private] |
Returns true
if there are pending generators.
Definition at line 148 of file Polyhedron.inlines.hh.
References status, and Parma_Polyhedra_Library::Polyhedron::Status::test_g_pending().
Referenced by add_constraint(), add_recycled_constraints(), concatenate_assign(), constraints(), generators(), H79_widening_assign(), intersection_assign(), intersection_assign_and_minimize(), is_included_in(), is_universe(), OK(), poly_hull_assign(), process_pending(), process_pending_constraints(), process_pending_generators(), relation_with(), remove_pending_to_obtain_constraints(), remove_pending_to_obtain_generators(), select_H79_constraints(), and topological_closure_assign().
00148 { 00149 return status.test_g_pending(); 00150 }
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 153 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(), 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(), shrink_bounding_box(), update_constraints(), and update_generators().
00153 { 00154 return status.test_c_pending() || status.test_g_pending(); 00155 }
bool Parma_Polyhedra_Library::Polyhedron::can_have_something_pending | ( | ) | const [inline, private] |
Returns true
if the polyhedron can have something pending.
Definition at line 158 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_constraint(), add_generator(), add_recycled_constraints(), add_recycled_generators(), concatenate_assign(), intersection_assign(), poly_hull_assign(), time_elapse_assign(), and topological_closure_assign().
00158 { 00159 return constraints_are_minimized() 00160 && generators_are_minimized() 00161 && (sat_c_is_up_to_date() || sat_g_is_up_to_date()); 00162 }
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 133 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().
00133 { 00134 return status.test_sat_c_up_to_date(); 00135 }
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 138 of file Polyhedron.inlines.hh.
References status, and Parma_Polyhedra_Library::Polyhedron::Status::test_sat_g_up_to_date().
Referenced by add_space_dimensions_and_project(), can_have_something_pending(), obtain_sorted_constraints(), obtain_sorted_constraints_with_sat_c(), obtain_sorted_generators(), obtain_sorted_generators_with_sat_g(), OK(), operator=(), Polyhedron(), process_pending_generators(), select_H79_constraints(), strongly_minimize_constraints(), strongly_minimize_generators(), and update_sat_g().
00138 { 00139 return status.test_sat_g_up_to_date(); 00140 }
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 647 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Generator_System::clear(), Parma_Polyhedra_Library::Constraint_System::clear(), con_sys, gen_sys, Parma_Polyhedra_Library::Polyhedron::Status::set_zero_dim_univ(), space_dim, and status.
Referenced by map_space_dimensions(), operator=(), Polyhedron(), remove_higher_space_dimensions(), and remove_space_dimensions().
00647 { 00648 status.set_zero_dim_univ(); 00649 space_dim = 0; 00650 con_sys.clear(); 00651 gen_sys.clear(); 00652 }
void Parma_Polyhedra_Library::Polyhedron::set_empty | ( | ) | [private] |
Sets status
to express that the polyhedron is empty, clearing all corresponding matrices.
Definition at line 655 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Saturation_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_constraint(), add_recycled_constraints_and_minimize(), concatenate_assign(), intersection_assign(), intersection_assign_and_minimize(), operator=(), poly_difference_assign(), Polyhedron(), process_pending_constraints(), time_elapse_assign(), and update_generators().
00655 { 00656 status.set_empty(); 00657 // The polyhedron is empty: we can thus throw away everything. 00658 con_sys.clear(); 00659 gen_sys.clear(); 00660 sat_c.clear(); 00661 sat_g.clear(); 00662 }
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 165 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().
00165 { 00166 status.set_c_up_to_date(); 00167 }
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 170 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::set_g_up_to_date(), and status.
Referenced by add_recycled_generators(), add_recycled_generators_and_minimize(), Polyhedron(), and set_generators_minimized().
00170 { 00171 status.set_g_up_to_date(); 00172 }
void Parma_Polyhedra_Library::Polyhedron::set_constraints_minimized | ( | ) | [inline, private] |
Sets status
to express that constraints are minimized.
Definition at line 175 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().
00175 { 00176 set_constraints_up_to_date(); 00177 status.set_c_minimized(); 00178 }
void Parma_Polyhedra_Library::Polyhedron::set_generators_minimized | ( | ) | [inline, private] |
Sets status
to express that generators are minimized.
Definition at line 181 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().
00181 { 00182 set_generators_up_to_date(); 00183 status.set_g_minimized(); 00184 }
void Parma_Polyhedra_Library::Polyhedron::set_constraints_pending | ( | ) | [inline, private] |
Sets status
to express that constraints are pending.
Definition at line 187 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::set_c_pending(), and status.
Referenced by add_constraint(), add_recycled_constraints(), concatenate_assign(), and intersection_assign().
00187 { 00188 status.set_c_pending(); 00189 }
void Parma_Polyhedra_Library::Polyhedron::set_generators_pending | ( | ) | [inline, private] |
Sets status
to express that generators are pending.
Definition at line 192 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(), and topological_closure_assign().
00192 { 00193 status.set_g_pending(); 00194 }
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 197 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::set_sat_c_up_to_date(), and status.
Referenced by add_recycled_constraints_and_minimize(), concatenate_assign(), intersection_assign_and_minimize(), obtain_sorted_constraints_with_sat_c(), obtain_sorted_generators(), obtain_sorted_generators_with_sat_g(), process_pending_constraints(), update_constraints(), and update_sat_c().
00197 { 00198 status.set_sat_c_up_to_date(); 00199 }
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 202 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::set_sat_g_up_to_date(), and status.
Referenced by obtain_sorted_constraints(), obtain_sorted_constraints_with_sat_c(), obtain_sorted_generators_with_sat_g(), process_pending_generators(), update_generators(), and update_sat_g().
00202 { 00203 status.set_sat_g_up_to_date(); 00204 }
void Parma_Polyhedra_Library::Polyhedron::clear_empty | ( | ) | [inline, private] |
Clears the status
flag indicating that the polyhedron is empty.
Definition at line 207 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::reset_empty(), and status.
Referenced by add_generator(), add_recycled_generators(), and add_recycled_generators_and_minimize().
00207 { 00208 status.reset_empty(); 00209 }
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 244 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(), and topological_closure_assign().
00244 { 00245 clear_pending_constraints(); 00246 clear_constraints_minimized(); 00247 clear_sat_c_up_to_date(); 00248 clear_sat_g_up_to_date(); 00249 status.reset_c_up_to_date(); 00250 // Can get rid of con_sys here. 00251 }
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 254 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_constraint(), add_recycled_constraints(), affine_preimage(), concatenate_assign(), intersection_assign(), remove_pending_to_obtain_constraints(), strongly_minimize_constraints(), and topological_closure_assign().
00254 { 00255 clear_pending_generators(); 00256 clear_generators_minimized(); 00257 clear_sat_c_up_to_date(); 00258 clear_sat_g_up_to_date(); 00259 status.reset_g_up_to_date(); 00260 // Can get rid of gen_sys here. 00261 }
void Parma_Polyhedra_Library::Polyhedron::clear_constraints_minimized | ( | ) | [inline, private] |
Sets status
to express that constraints are no longer minimized.
Definition at line 212 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::reset_c_minimized(), and status.
Referenced by add_constraint(), add_recycled_constraints(), affine_preimage(), clear_constraints_up_to_date(), concatenate_assign(), intersection_assign(), remove_pending_to_obtain_constraints(), and topological_closure_assign().
00212 { 00213 status.reset_c_minimized(); 00214 }
void Parma_Polyhedra_Library::Polyhedron::clear_generators_minimized | ( | ) | [inline, private] |
Sets status
to express that generators are no longer minimized.
Definition at line 217 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(), and topological_closure_assign().
00217 { 00218 status.reset_g_minimized(); 00219 }
void Parma_Polyhedra_Library::Polyhedron::clear_pending_constraints | ( | ) | [inline, private] |
Sets status
to express that there are no longer pending constraints.
Definition at line 222 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::reset_c_pending(), and status.
Referenced by clear_constraints_up_to_date(), intersection_assign_and_minimize(), process_pending_constraints(), and remove_pending_to_obtain_constraints().
00222 { 00223 status.reset_c_pending(); 00224 }
void Parma_Polyhedra_Library::Polyhedron::clear_pending_generators | ( | ) | [inline, private] |
Sets status
to express that there are no longer pending generators.
Definition at line 227 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::reset_g_pending(), and status.
Referenced by clear_generators_up_to_date(), poly_hull_assign_and_minimize(), process_pending_generators(), and remove_pending_to_obtain_generators().
00227 { 00228 status.reset_g_pending(); 00229 }
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 232 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::reset_sat_c_up_to_date(), and status.
Referenced by add_recycled_generators_and_minimize(), affine_image(), affine_preimage(), clear_constraints_up_to_date(), clear_generators_up_to_date(), concatenate_assign(), generalized_affine_image(), obtain_sorted_constraints(), poly_hull_assign_and_minimize(), process_pending_generators(), and update_generators().
00232 { 00233 status.reset_sat_c_up_to_date(); 00234 // Can get rid of sat_c here. 00235 }
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 238 of file Polyhedron.inlines.hh.
References Parma_Polyhedra_Library::Polyhedron::Status::reset_sat_g_up_to_date(), and status.
Referenced by add_recycled_constraints_and_minimize(), affine_image(), affine_preimage(), clear_constraints_up_to_date(), clear_generators_up_to_date(), concatenate_assign(), generalized_affine_image(), intersection_assign_and_minimize(), obtain_sorted_generators(), process_pending_constraints(), and update_constraints().
00238 { 00239 status.reset_sat_g_up_to_date(); 00240 // Can get rid of sat_g here. 00241 }
bool Parma_Polyhedra_Library::Polyhedron::process_pending | ( | ) | const [inline, private] |
Processes the pending rows of either description of the polyhedron and obtains a minimized polyhedron.
false
if and only if *this
turns out to be an empty polyhedron.Definition at line 264 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 is_topologically_closed(), minimize(), and shrink_bounding_box().
00264 { 00265 assert(space_dim > 0 && !marked_empty()); 00266 assert(has_something_pending()); 00267 00268 Polyhedron& x = const_cast<Polyhedron&>(*this); 00269 00270 if (x.has_pending_constraints()) 00271 return x.process_pending_constraints(); 00272 00273 assert(x.has_pending_generators()); 00274 x.process_pending_generators(); 00275 return true; 00276 }
bool Parma_Polyhedra_Library::Polyhedron::process_pending_constraints | ( | ) | const [private] |
Processes the pending constraints and obtains a minimized polyhedron.
false
if and only if *this
turns out to be an empty polyhedron.Definition at line 665 of file Polyhedron_nonpublic.cc.
References add_and_minimize(), clear_pending_constraints(), clear_sat_g_up_to_date(), con_sys, empty, gen_sys, has_pending_constraints(), has_pending_generators(), Parma_Polyhedra_Library::Linear_System::is_sorted(), marked_empty(), Parma_Polyhedra_Library::Linear_System::num_pending_rows(), obtain_sorted_constraints_with_sat_c(), OK(), sat_c, sat_c_is_up_to_date(), sat_g, set_empty(), set_sat_c_up_to_date(), Parma_Polyhedra_Library::Linear_System::sort_pending_and_remove_duplicates(), space_dim, and Parma_Polyhedra_Library::Saturation_Matrix::transpose_assign().
Referenced by add_generator(), add_recycled_generators(), bounds(), generators(), is_bounded(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), max_min(), poly_hull_assign(), poly_hull_assign_and_minimize(), process_pending(), relation_with(), remove_pending_to_obtain_generators(), time_elapse_assign(), and topological_closure_assign().
00665 { 00666 assert(space_dim > 0 && !marked_empty()); 00667 assert(has_pending_constraints() && !has_pending_generators()); 00668 00669 Polyhedron& x = const_cast<Polyhedron&>(*this); 00670 00671 // Integrate the pending part of the system of constraints and minimize. 00672 // We need `sat_c' up-to-date and `con_sys' sorted (together with `sat_c'). 00673 if (!x.sat_c_is_up_to_date()) 00674 x.sat_c.transpose_assign(x.sat_g); 00675 if (!x.con_sys.is_sorted()) 00676 x.obtain_sorted_constraints_with_sat_c(); 00677 // We sort in place the pending constraints, erasing those constraints 00678 // that also occur in the non-pending part of `con_sys'. 00679 x.con_sys.sort_pending_and_remove_duplicates(); 00680 if (x.con_sys.num_pending_rows() == 0) { 00681 // All pending constraints were duplicates. 00682 x.clear_pending_constraints(); 00683 assert(OK(true)); 00684 return true; 00685 } 00686 00687 const bool empty = add_and_minimize(true, x.con_sys, x.gen_sys, x.sat_c); 00688 assert(x.con_sys.num_pending_rows() == 0); 00689 00690 if (empty) 00691 x.set_empty(); 00692 else { 00693 x.clear_pending_constraints(); 00694 x.clear_sat_g_up_to_date(); 00695 x.set_sat_c_up_to_date(); 00696 } 00697 assert(OK(!empty)); 00698 return !empty; 00699 }
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 702 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::Saturation_Matrix::transpose_assign().
Referenced by add_constraint(), add_recycled_constraints(), concatenate_assign(), constraints(), H79_widening_assign(), intersection_assign(), intersection_assign_and_minimize(), is_included_in(), is_universe(), process_pending(), relation_with(), and remove_pending_to_obtain_constraints().
00702 { 00703 assert(space_dim > 0 && !marked_empty()); 00704 assert(has_pending_generators() && !has_pending_constraints()); 00705 00706 Polyhedron& x = const_cast<Polyhedron&>(*this); 00707 00708 // Integrate the pending part of the system of generators and minimize. 00709 // We need `sat_g' up-to-date and `gen_sys' sorted (together with `sat_g'). 00710 if (!x.sat_g_is_up_to_date()) 00711 x.sat_g.transpose_assign(x.sat_c); 00712 if (!x.gen_sys.is_sorted()) 00713 x.obtain_sorted_generators_with_sat_g(); 00714 // We sort in place the pending generators, erasing those generators 00715 // that also occur in the non-pending part of `gen_sys'. 00716 x.gen_sys.sort_pending_and_remove_duplicates(); 00717 if (x.gen_sys.num_pending_rows() == 0) { 00718 // All pending generators were duplicates. 00719 x.clear_pending_generators(); 00720 assert(OK(true)); 00721 return; 00722 } 00723 00724 add_and_minimize(false, x.gen_sys, x.con_sys, x.sat_g); 00725 assert(x.gen_sys.num_pending_rows() == 0); 00726 00727 x.clear_pending_generators(); 00728 x.clear_sat_c_up_to_date(); 00729 x.set_sat_g_up_to_date(); 00730 }
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 733 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().
00733 { 00734 assert(has_something_pending()); 00735 00736 Polyhedron& x = const_cast<Polyhedron&>(*this); 00737 00738 // If the polyhedron has pending constraints, simply unset them. 00739 if (x.has_pending_constraints()) { 00740 // Integrate the pending constraints, which are possibly not sorted. 00741 x.con_sys.unset_pending_rows(); 00742 x.con_sys.set_sorted(false); 00743 x.clear_pending_constraints(); 00744 x.clear_constraints_minimized(); 00745 x.clear_generators_up_to_date(); 00746 } 00747 else { 00748 assert(x.has_pending_generators()); 00749 // We must process the pending generators and obtain the 00750 // corresponding system of constraints. 00751 x.process_pending_generators(); 00752 } 00753 assert(OK(true)); 00754 }
bool Parma_Polyhedra_Library::Polyhedron::remove_pending_to_obtain_generators | ( | ) | const [private] |
Lazily integrates the pending descriptions of the polyhedron to obtain a generator system without pending rows.
false
if and only if *this
turns out to be an empty polyhedron.Definition at line 757 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().
00757 { 00758 assert(has_something_pending()); 00759 00760 Polyhedron& x = const_cast<Polyhedron&>(*this); 00761 00762 // If the polyhedron has pending generators, simply unset them. 00763 if (x.has_pending_generators()) { 00764 // Integrate the pending generators, which are possibly not sorted. 00765 x.gen_sys.unset_pending_rows(); 00766 x.gen_sys.set_sorted(false); 00767 x.clear_pending_generators(); 00768 x.clear_generators_minimized(); 00769 x.clear_constraints_up_to_date(); 00770 assert(OK(true)); 00771 return true; 00772 } 00773 else { 00774 assert(x.has_pending_constraints()); 00775 // We must integrate the pending constraints and obtain the 00776 // corresponding system of generators. 00777 return x.process_pending_constraints(); 00778 } 00779 }
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 782 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_constraint(), add_recycled_constraints(), concatenate_assign(), constraints(), H79_widening_assign(), intersection_assign(), intersection_assign_and_minimize(), is_included_in(), minimize(), and relation_with().
00782 { 00783 assert(space_dim > 0); 00784 assert(!marked_empty()); 00785 assert(generators_are_up_to_date()); 00786 // We assume the polyhedron has no pending constraints or generators. 00787 assert(!has_something_pending()); 00788 00789 Polyhedron& x = const_cast<Polyhedron&>(*this); 00790 minimize(false, x.gen_sys, x.con_sys, x.sat_c); 00791 // `sat_c' is the only saturation matrix up-to-date. 00792 x.set_sat_c_up_to_date(); 00793 x.clear_sat_g_up_to_date(); 00794 // The system of constraints and the system of generators 00795 // are minimized. 00796 x.set_constraints_minimized(); 00797 x.set_generators_minimized(); 00798 }
bool Parma_Polyhedra_Library::Polyhedron::update_generators | ( | ) | const [private] |
Updates generators starting from constraints and minimizes them.
false
if and only if *this
turns out to be an empty polyhedron.Definition at line 801 of file Polyhedron_nonpublic.cc.
References clear_sat_c_up_to_date(), con_sys, constraints_are_up_to_date(), empty, gen_sys, has_something_pending(), marked_empty(), minimize(), sat_g, set_constraints_minimized(), set_empty(), set_generators_minimized(), set_sat_g_up_to_date(), and space_dim.
Referenced by add_generator(), bounds(), generators(), is_bounded(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), map_space_dimensions(), max_min(), minimize(), poly_hull_assign(), poly_hull_assign_and_minimize(), relation_with(), remove_higher_space_dimensions(), remove_space_dimensions(), and time_elapse_assign().
00801 { 00802 assert(space_dim > 0); 00803 assert(!marked_empty()); 00804 assert(constraints_are_up_to_date()); 00805 // We assume the polyhedron has no pending constraints or generators. 00806 assert(!has_something_pending()); 00807 00808 Polyhedron& x = const_cast<Polyhedron&>(*this); 00809 // If the system of constraints is not consistent the 00810 // polyhedron is empty. 00811 const bool empty = minimize(true, x.con_sys, x.gen_sys, x.sat_g); 00812 if (empty) 00813 x.set_empty(); 00814 else { 00815 // `sat_g' is the only saturation matrix up-to-date. 00816 x.set_sat_g_up_to_date(); 00817 x.clear_sat_c_up_to_date(); 00818 // The system of constraints and the system of generators 00819 // are minimized. 00820 x.set_constraints_minimized(); 00821 x.set_generators_minimized(); 00822 } 00823 return !empty; 00824 }
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 827 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Saturation_Matrix::clear(), con_sys, constraints_are_minimized(), Parma_Polyhedra_Library::Linear_System::first_pending_row(), gen_sys, generators_are_minimized(), Parma_Polyhedra_Library::Saturation_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().
00827 { 00828 assert(constraints_are_minimized()); 00829 assert(generators_are_minimized()); 00830 assert(!sat_c_is_up_to_date()); 00831 00832 // We only consider non-pending rows. 00833 const dimension_type csr = con_sys.first_pending_row(); 00834 const dimension_type gsr = gen_sys.first_pending_row(); 00835 Polyhedron& x = const_cast<Polyhedron&>(*this); 00836 00837 // The columns of `sat_c' represent the constraints and 00838 // its rows represent the generators: resize accordingly. 00839 x.sat_c.resize(gsr, csr); 00840 for (dimension_type i = gsr; i-- > 0; ) 00841 for (dimension_type j = csr; j-- > 0; ) { 00842 const int sp_sign = Scalar_Products::sign(con_sys[j], gen_sys[i]); 00843 // The negativity of this scalar product would mean 00844 // that the generator `gen_sys[i]' violates the constraint 00845 // `con_sys[j]' and it is not possible because both generators 00846 // and constraints are up-to-date. 00847 assert(sp_sign >= 0); 00848 if (sp_sign > 0) 00849 // `gen_sys[i]' satisfies (without saturate) `con_sys[j]'. 00850 x.sat_c[i].set(j); 00851 else 00852 // `gen_sys[i]' saturates `con_sys[j]'. 00853 x.sat_c[i].clear(j); 00854 } 00855 x.set_sat_c_up_to_date(); 00856 }
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 859 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Saturation_Matrix::clear(), con_sys, constraints_are_minimized(), Parma_Polyhedra_Library::Linear_System::first_pending_row(), gen_sys, generators_are_minimized(), Parma_Polyhedra_Library::Saturation_Matrix::resize(), sat_g, sat_g_is_up_to_date(), set_sat_g_up_to_date(), and Parma_Polyhedra_Library::Scalar_Products::sign().
Referenced by add_space_dimensions_and_project(), obtain_sorted_generators_with_sat_g(), and select_H79_constraints().
00859 { 00860 assert(constraints_are_minimized()); 00861 assert(generators_are_minimized()); 00862 assert(!sat_g_is_up_to_date()); 00863 00864 // We only consider non-pending rows. 00865 const dimension_type csr = con_sys.first_pending_row(); 00866 const dimension_type gsr = gen_sys.first_pending_row(); 00867 Polyhedron& x = const_cast<Polyhedron&>(*this); 00868 00869 // The columns of `sat_g' represent generators and its 00870 // rows represent the constraints: resize accordingly. 00871 x.sat_g.resize(csr, gsr); 00872 for (dimension_type i = csr; i-- > 0; ) 00873 for (dimension_type j = gsr; j-- > 0; ) { 00874 const int sp_sign = Scalar_Products::sign(con_sys[i], gen_sys[j]); 00875 // The negativity of this scalar product would mean 00876 // that the generator `gen_sys[j]' violates the constraint 00877 // `con_sys[i]' and it is not possible because both generators 00878 // and constraints are up-to-date. 00879 assert(sp_sign >= 0); 00880 if (sp_sign > 0) 00881 // `gen_sys[j]' satisfies (without saturate) `con_sys[i]'. 00882 x.sat_g[i].set(j); 00883 else 00884 // `gen_sys[j]' saturates `con_sys[i]'. 00885 x.sat_g[i].clear(j); 00886 } 00887 x.set_sat_g_up_to_date(); 00888 }
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 891 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::Saturation_Matrix::transpose_assign().
Referenced by constraints(), intersection_assign_and_minimize(), is_universe(), and quick_equivalence_test().
00891 { 00892 assert(constraints_are_up_to_date()); 00893 // `con_sys' will be sorted up to `index_first_pending'. 00894 Polyhedron& x = const_cast<Polyhedron&>(*this); 00895 if (!x.con_sys.is_sorted()) 00896 if (x.sat_g_is_up_to_date()) { 00897 // Sorting constraints keeping `sat_g' consistent. 00898 x.con_sys.sort_and_remove_with_sat(x.sat_g); 00899 // `sat_c' is not up-to-date anymore. 00900 x.clear_sat_c_up_to_date(); 00901 } 00902 else if (x.sat_c_is_up_to_date()) { 00903 // Using `sat_c' to obtain `sat_g', then it is like previous case. 00904 x.sat_g.transpose_assign(x.sat_c); 00905 x.con_sys.sort_and_remove_with_sat(x.sat_g); 00906 x.set_sat_g_up_to_date(); 00907 x.clear_sat_c_up_to_date(); 00908 } 00909 else 00910 // If neither `sat_g' nor `sat_c' are up-to-date, 00911 // we just sort the constraints. 00912 x.con_sys.sort_rows(); 00913 00914 assert(con_sys.check_sorted()); 00915 }
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 918 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::Saturation_Matrix::transpose_assign().
Referenced by generators(), poly_hull_assign_and_minimize(), and quick_equivalence_test().
00918 { 00919 assert(generators_are_up_to_date()); 00920 // `gen_sys' will be sorted up to `index_first_pending'. 00921 Polyhedron& x = const_cast<Polyhedron&>(*this); 00922 if (!x.gen_sys.is_sorted()) 00923 if (x.sat_c_is_up_to_date()) { 00924 // Sorting generators keeping 'sat_c' consistent. 00925 x.gen_sys.sort_and_remove_with_sat(x.sat_c); 00926 // `sat_g' is not up-to-date anymore. 00927 x.clear_sat_g_up_to_date(); 00928 } 00929 else if (x.sat_g_is_up_to_date()) { 00930 // Obtaining `sat_c' from `sat_g' and proceeding like previous case. 00931 x.sat_c.transpose_assign(x.sat_g); 00932 x.gen_sys.sort_and_remove_with_sat(x.sat_c); 00933 x.set_sat_c_up_to_date(); 00934 x.clear_sat_g_up_to_date(); 00935 } 00936 else 00937 // If neither `sat_g' nor `sat_c' are up-to-date, we just sort 00938 // the generators. 00939 x.gen_sys.sort_rows(); 00940 00941 assert(gen_sys.check_sorted()); 00942 }
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 945 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::Saturation_Matrix::transpose_assign(), and update_sat_c().
Referenced by add_recycled_constraints_and_minimize(), intersection_assign_and_minimize(), and process_pending_constraints().
00945 { 00946 assert(constraints_are_up_to_date()); 00947 assert(constraints_are_minimized()); 00948 // `con_sys' will be sorted up to `index_first_pending'. 00949 Polyhedron& x = const_cast<Polyhedron&>(*this); 00950 // At least one of the saturation matrices must be up-to-date. 00951 if (!x.sat_c_is_up_to_date() && !x.sat_g_is_up_to_date()) 00952 x.update_sat_c(); 00953 00954 if (x.con_sys.is_sorted()) { 00955 if (x.sat_c_is_up_to_date()) 00956 // If constraints are already sorted and sat_c is up to 00957 // date there is nothing to do. 00958 return; 00959 } 00960 else { 00961 if (!x.sat_g_is_up_to_date()) { 00962 // If constraints are not sorted and sat_g is not up-to-date 00963 // we obtain sat_g from sat_c (that has to be up-to-date)... 00964 x.sat_g.transpose_assign(x.sat_c); 00965 x.set_sat_g_up_to_date(); 00966 } 00967 // ... and sort it together with constraints. 00968 x.con_sys.sort_and_remove_with_sat(x.sat_g); 00969 } 00970 // Obtaining sat_c from sat_g. 00971 x.sat_c.transpose_assign(x.sat_g); 00972 x.set_sat_c_up_to_date(); 00973 // Constraints are sorted now. 00974 x.con_sys.set_sorted(true); 00975 00976 assert(con_sys.check_sorted()); 00977 }
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 980 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::Saturation_Matrix::transpose_assign(), and update_sat_g().
Referenced by add_recycled_generators_and_minimize(), poly_hull_assign_and_minimize(), and process_pending_generators().
00980 { 00981 assert(generators_are_up_to_date()); 00982 // `gen_sys' will be sorted up to `index_first_pending'. 00983 Polyhedron& x = const_cast<Polyhedron&>(*this); 00984 // At least one of the saturation matrices must be up-to-date. 00985 if (!x.sat_c_is_up_to_date() && !x.sat_g_is_up_to_date()) 00986 x.update_sat_g(); 00987 00988 if (x.gen_sys.is_sorted()) { 00989 if (x.sat_g_is_up_to_date()) 00990 // If generators are already sorted and sat_g is up to 00991 // date there is nothing to do. 00992 return; 00993 } 00994 else { 00995 if (!x.sat_c_is_up_to_date()) { 00996 // If generators are not sorted and sat_c is not up-to-date 00997 // we obtain sat_c from sat_g (that has to be up-to-date)... 00998 x.sat_c.transpose_assign(x.sat_g); 00999 x.set_sat_c_up_to_date(); 01000 } 01001 // ... and sort it together with generators. 01002 x.gen_sys.sort_and_remove_with_sat(x.sat_c); 01003 } 01004 // Obtaining sat_g from sat_c. 01005 x.sat_g.transpose_assign(sat_c); 01006 x.set_sat_g_up_to_date(); 01007 // Generators are sorted now. 01008 x.gen_sys.set_sorted(true); 01009 01010 assert(gen_sys.check_sorted()); 01011 }
bool Parma_Polyhedra_Library::Polyhedron::minimize | ( | ) | const [private] |
Applies (weak) minimization to both the constraints and generators.
false
if and only if *this
turns out to be an empty polyhedron.Definition at line 1014 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_constraints_and_minimize(), add_recycled_generators(), add_recycled_generators_and_minimize(), affine_image(), affine_preimage(), is_empty(), is_universe(), minimized_constraints(), minimized_generators(), OK(), poly_hull_assign_and_minimize(), strongly_minimize_constraints(), strongly_minimize_generators(), update_constraints(), and update_generators().
01014 { 01015 // 0-dim space or empty polyhedra are already minimized. 01016 if (marked_empty()) 01017 return false; 01018 if (space_dim == 0) 01019 return true; 01020 01021 // If the polyhedron has something pending, process it. 01022 if (has_something_pending()) { 01023 const bool not_empty = process_pending(); 01024 assert(OK()); 01025 return not_empty; 01026 } 01027 01028 // Here there are no pending constraints or generators. 01029 // Is the polyhedron already minimized? 01030 if (constraints_are_minimized() && generators_are_minimized()) 01031 return true; 01032 01033 // If constraints or generators are up-to-date, invoking 01034 // update_generators() or update_constraints(), respectively, 01035 // minimizes both constraints and generators. 01036 // If both are up-to-date it does not matter whether we use 01037 // update_generators() or update_constraints(): 01038 // both minimize constraints and generators. 01039 if (constraints_are_up_to_date()) { 01040 // We may discover here that `*this' is empty. 01041 const bool ret = update_generators(); 01042 assert(OK()); 01043 return ret; 01044 } 01045 else { 01046 assert(generators_are_up_to_date()); 01047 update_constraints(); 01048 assert(OK()); 01049 return true; 01050 } 01051 }
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 1054 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::LP_Problem::add_constraints(), Parma_Polyhedra_Library::Saturation_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::Saturation_Row::set(), Parma_Polyhedra_Library::Linear_System::set_necessarily_closed(), Parma_Polyhedra_Library::Linear_System::set_not_necessarily_closed(), Parma_Polyhedra_Library::LP_Problem::set_objective_function(), Parma_Polyhedra_Library::LP_Problem::set_optimization_mode(), Parma_Polyhedra_Library::Linear_System::set_sorted(), Parma_Polyhedra_Library::LP_Problem::solve(), space_dim, status, Parma_Polyhedra_Library::Saturation_Matrix::transpose_assign(), Parma_Polyhedra_Library::UNBOUNDED_LP_PROBLEM, Parma_Polyhedra_Library::UNFEASIBLE_LP_PROBLEM, and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
Referenced by is_topologically_closed(), and minimized_constraints().
01054 { 01055 assert(!is_necessarily_closed()); 01056 01057 // From the user perspective, the polyhedron will not change. 01058 Polyhedron& x = const_cast<Polyhedron&>(*this); 01059 01060 // We need `con_sys' (weakly) minimized and `gen_sys' up-to-date. 01061 // `minimize()' will process any pending constraints or generators. 01062 if (!minimize()) 01063 return false; 01064 01065 // If the polyhedron `*this' is zero-dimensional 01066 // at this point it must be a universe polyhedron. 01067 if (x.space_dim == 0) 01068 return true; 01069 01070 // We also need `sat_g' up-to-date. 01071 if (!sat_g_is_up_to_date()) { 01072 assert(sat_c_is_up_to_date()); 01073 x.sat_g.transpose_assign(sat_c); 01074 } 01075 01076 // These Saturation_Row's will be later used as masks in order to 01077 // check saturation conditions restricted to particular subsets of 01078 // the generator system. 01079 Saturation_Row sat_all_but_rays; 01080 Saturation_Row sat_all_but_points; 01081 Saturation_Row sat_all_but_closure_points; 01082 01083 const dimension_type gs_rows = gen_sys.num_rows(); 01084 const dimension_type n_lines = gen_sys.num_lines(); 01085 for (dimension_type i = gs_rows; i-- > n_lines; ) 01086 switch (gen_sys[i].type()) { 01087 case Generator::RAY: 01088 sat_all_but_rays.set(i); 01089 break; 01090 case Generator::POINT: 01091 sat_all_but_points.set(i); 01092 break; 01093 case Generator::CLOSURE_POINT: 01094 sat_all_but_closure_points.set(i); 01095 break; 01096 default: 01097 // Found a line with index i >= n_lines. 01098 throw std::runtime_error("PPL internal error: " 01099 "strongly_minimize_constraints."); 01100 } 01101 Saturation_Row sat_lines_and_rays; 01102 set_union(sat_all_but_points, sat_all_but_closure_points, 01103 sat_lines_and_rays); 01104 Saturation_Row sat_lines_and_closure_points; 01105 set_union(sat_all_but_rays, sat_all_but_points, 01106 sat_lines_and_closure_points); 01107 Saturation_Row sat_lines; 01108 set_union(sat_lines_and_rays, sat_lines_and_closure_points, 01109 sat_lines); 01110 01111 // These flags are maintained to later decide if we have to add the 01112 // eps_leq_one constraint and whether or not the constraint system 01113 // was changed. 01114 bool changed = false; 01115 bool found_eps_leq_one = false; 01116 01117 // For all the strict inequalities in `con_sys', check for 01118 // eps-redundancy and eventually move them to the bottom part of the 01119 // system. 01120 Constraint_System& cs = x.con_sys; 01121 Saturation_Matrix& sat = x.sat_g; 01122 dimension_type cs_rows = cs.num_rows(); 01123 const dimension_type eps_index = cs.num_columns() - 1; 01124 for (dimension_type i = 0; i < cs_rows; ) 01125 if (cs[i].is_strict_inequality()) { 01126 // First, check if it is saturated by no closure points 01127 Saturation_Row sat_ci; 01128 set_union(sat[i], sat_lines_and_closure_points, sat_ci); 01129 if (sat_ci == sat_lines) { 01130 // It is saturated by no closure points. 01131 if (!found_eps_leq_one) { 01132 // Check if it is the eps_leq_one constraint. 01133 const Constraint& c = cs[i]; 01134 bool all_zeroes = true; 01135 for (dimension_type k = eps_index; k-- > 1; ) 01136 if (c[k] != 0) { 01137 all_zeroes = false; 01138 break; 01139 } 01140 if (all_zeroes && (c[0] + c[eps_index] == 0)) { 01141 // We found the eps_leq_one constraint. 01142 found_eps_leq_one = true; 01143 // Consider next constraint. 01144 ++i; 01145 continue; 01146 } 01147 } 01148 // Here `cs[i]' is not the eps_leq_one constraint, 01149 // so it is eps-redundant. 01150 // Move it to the bottom of the constraint system, 01151 // while keeping `sat_g' consistent. 01152 --cs_rows; 01153 std::swap(cs[i], cs[cs_rows]); 01154 std::swap(sat[i], sat[cs_rows]); 01155 // The constraint system is changed. 01156 changed = true; 01157 // Continue by considering next constraint, 01158 // which is already in place due to the swap. 01159 continue; 01160 } 01161 // Now we check if there exists another strict inequality 01162 // constraint having a superset of its saturators, 01163 // when disregarding points. 01164 sat_ci.clear(); 01165 set_union(sat[i], sat_all_but_points, sat_ci); 01166 bool eps_redundant = false; 01167 for (dimension_type j = 0; j < cs_rows; ++j) 01168 if (i != j && cs[j].is_strict_inequality() 01169 && subset_or_equal(sat[j], sat_ci)) { 01170 // Constraint `cs[i]' is eps-redundant: 01171 // move it to the bottom of the constraint system, 01172 // while keeping `sat_g' consistent. 01173 --cs_rows; 01174 std::swap(cs[i], cs[cs_rows]); 01175 std::swap(sat[i], sat[cs_rows]); 01176 eps_redundant = true; 01177 // The constraint system is changed. 01178 changed = true; 01179 break; 01180 } 01181 // Continue with next constraint, which is already in place 01182 // due to the swap if we have found an eps-redundant constraint. 01183 if (!eps_redundant) 01184 ++i; 01185 } 01186 else 01187 // `cs[i]' is not a strict inequality: consider next constraint. 01188 ++i; 01189 01190 if (changed) { 01191 // If the constraint system has been changed, we have to erase 01192 // the epsilon-redundant constraints. 01193 assert(cs_rows < cs.num_rows()); 01194 cs.erase_to_end(cs_rows); 01195 // The remaining constraints are not pending. 01196 cs.unset_pending_rows(); 01197 // The constraint system is no longer sorted. 01198 cs.set_sorted(false); 01199 // The generator system is no longer up-to-date. 01200 x.clear_generators_up_to_date(); 01201 01202 // If we haven't found an upper bound for the epsilon dimension, 01203 // then we have to check whether such an upper bound is implied 01204 // by the remaining constraints (exploiting teh simplex algorithm). 01205 if (!found_eps_leq_one) { 01206 LP_Problem lp; 01207 // KLUDGE: temporarily mark the constraint system as if it was 01208 // necessarily closed, so that we can interpret the epsilon 01209 // dimension as a standard dimension. Be careful to reset the 01210 // topology of `cs' even on exceptional execution path. 01211 cs.set_necessarily_closed(); 01212 try { 01213 lp.add_constraints(cs); 01214 cs.set_not_necessarily_closed(); 01215 } 01216 catch (...) { 01217 cs.set_not_necessarily_closed(); 01218 throw; 01219 } 01220 // The objective function is `epsilon'. 01221 lp.set_objective_function(Variable(x.space_dim)); 01222 lp.set_optimization_mode(MAXIMIZATION); 01223 LP_Problem_Status status = lp.solve(); 01224 assert(status != UNFEASIBLE_LP_PROBLEM); 01225 // If the epsilon dimension is actually unbounded, 01226 // then add the eps_leq_one constraint. 01227 if (status == UNBOUNDED_LP_PROBLEM) 01228 cs.insert(Constraint::epsilon_leq_one()); 01229 } 01230 } 01231 01232 assert(OK()); 01233 return true; 01234 }
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 1237 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::Saturation_Row::set(), Parma_Polyhedra_Library::Linear_System::set_sorted(), space_dim, Parma_Polyhedra_Library::Saturation_Matrix::transpose_assign(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
Referenced by minimized_generators().
01237 { 01238 assert(!is_necessarily_closed()); 01239 01240 // From the user perspective, the polyhedron will not change. 01241 Polyhedron& x = const_cast<Polyhedron&>(*this); 01242 01243 // We need `gen_sys' (weakly) minimized and `con_sys' up-to-date. 01244 // `minimize()' will process any pending constraints or generators. 01245 if (!minimize()) 01246 return false; 01247 01248 // If the polyhedron `*this' is zero-dimensional 01249 // at this point it must be a universe polyhedron. 01250 if (x.space_dim == 0) 01251 return true; 01252 01253 // We also need `sat_c' up-to-date. 01254 if (!sat_c_is_up_to_date()) { 01255 assert(sat_g_is_up_to_date()); 01256 x.sat_c.transpose_assign(sat_g); 01257 } 01258 01259 // This Saturation_Row will have all and only the indexes 01260 // of strict inequalities set to 1. 01261 Saturation_Row sat_all_but_strict_ineq; 01262 const dimension_type cs_rows = con_sys.num_rows(); 01263 const dimension_type n_equals = con_sys.num_equalities(); 01264 for (dimension_type i = cs_rows; i-- > n_equals; ) 01265 if (con_sys[i].is_strict_inequality()) 01266 sat_all_but_strict_ineq.set(i); 01267 01268 // Will record whether or not we changed the generator system. 01269 bool changed = false; 01270 01271 // For all points in the generator system, check for eps-redundancy 01272 // and eventually move them to the bottom part of the system. 01273 Generator_System& gs = const_cast<Generator_System&>(gen_sys); 01274 Saturation_Matrix& sat = const_cast<Saturation_Matrix&>(sat_c); 01275 dimension_type gs_rows = gs.num_rows(); 01276 const dimension_type n_lines = gs.num_lines(); 01277 const dimension_type eps_index = gs.num_columns() - 1; 01278 for (dimension_type i = n_lines; i < gs_rows; ) 01279 if (gs[i].is_point()) { 01280 // Compute the Saturation_Row corresponding to the candidate point 01281 // when strict inequality constraints are ignored. 01282 Saturation_Row sat_gi; 01283 set_union(sat[i], sat_all_but_strict_ineq, sat_gi); 01284 // Check if the candidate point is actually eps-redundant: 01285 // namely, if there exists another point that saturates 01286 // all the non-strict inequalities saturated by the candidate. 01287 bool eps_redundant = false; 01288 for (dimension_type j = n_lines; j < gs_rows; ++j) 01289 if (i != j && gs[j].is_point() && subset_or_equal(sat[j], sat_gi)) { 01290 // Point `gs[i]' is eps-redundant: 01291 // move it to the bottom of the generator system, 01292 // while keeping `sat_c' consistent. 01293 --gs_rows; 01294 std::swap(gs[i], gs[gs_rows]); 01295 std::swap(sat[i], sat[gs_rows]); 01296 eps_redundant = true; 01297 changed = true; 01298 break; 01299 } 01300 if (!eps_redundant) { 01301 // Let all point encodings have epsilon coordinate 1. 01302 Generator& gi = gs[i]; 01303 if (gi[eps_index] != gi[0]) { 01304 gi[eps_index] = gi[0]; 01305 // Enforce normalization. 01306 gi.normalize(); 01307 changed = true; 01308 } 01309 // Consider next generator. 01310 ++i; 01311 } 01312 } 01313 else 01314 // Consider next generator. 01315 ++i; 01316 01317 // If needed, erase the eps-redundant generators (also updating 01318 // `index_first_pending'). 01319 if (gs_rows < gs.num_rows()) { 01320 gs.erase_to_end(gs_rows); 01321 gs.unset_pending_rows(); 01322 } 01323 01324 if (changed) { 01325 // The generator system is no longer sorted. 01326 x.gen_sys.set_sorted(false); 01327 // The constraint system is no longer up-to-date. 01328 x.clear_constraints_up_to_date(); 01329 } 01330 01331 assert(OK()); 01332 return true; 01333 }
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 329 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().
00329 { 00330 // Private method: the caller must ensure the following. 00331 assert(topology() == y.topology()); 00332 assert(space_dim == y.space_dim); 00333 assert(!marked_empty() && !y.marked_empty() && space_dim > 0); 00334 00335 const Polyhedron& x = *this; 00336 00337 if (x.is_necessarily_closed()) { 00338 if (!x.has_something_pending() && !y.has_something_pending()) { 00339 bool css_normalized = false; 00340 if (x.constraints_are_minimized() && y.constraints_are_minimized()) { 00341 // Equivalent minimized constraint systems have: 00342 // - the same number of constraints; ... 00343 if (x.con_sys.num_rows() != y.con_sys.num_rows()) 00344 return Polyhedron::TVB_FALSE; 00345 // - the same number of equalities; ... 00346 dimension_type x_num_equalities = x.con_sys.num_equalities(); 00347 if (x_num_equalities != y.con_sys.num_equalities()) 00348 return Polyhedron::TVB_FALSE; 00349 // - if there are no equalities, they have the same constraints. 00350 // Delay this test: try cheaper tests on generators first. 00351 css_normalized = (x_num_equalities == 0); 00352 } 00353 00354 if (x.generators_are_minimized() && y.generators_are_minimized()) { 00355 // Equivalent minimized generator systems have: 00356 // - the same number of generators; ... 00357 if (x.gen_sys.num_rows() != y.gen_sys.num_rows()) 00358 return Polyhedron::TVB_FALSE; 00359 // - the same number of lines; ... 00360 const dimension_type x_num_lines = x.gen_sys.num_lines(); 00361 if (x_num_lines != y.gen_sys.num_lines()) 00362 return Polyhedron::TVB_FALSE; 00363 // - if there are no lines, they have the same generators. 00364 if (x_num_lines == 0) { 00365 // Sort the two systems and check for syntactic identity. 00366 x.obtain_sorted_generators(); 00367 y.obtain_sorted_generators(); 00368 if (x.gen_sys == y.gen_sys) 00369 return Polyhedron::TVB_TRUE; 00370 else 00371 return Polyhedron::TVB_FALSE; 00372 } 00373 } 00374 00375 if (css_normalized) { 00376 // Sort the two systems and check for identity. 00377 x.obtain_sorted_constraints(); 00378 y.obtain_sorted_constraints(); 00379 if (x.con_sys == y.con_sys) 00380 return Polyhedron::TVB_TRUE; 00381 else 00382 return Polyhedron::TVB_FALSE; 00383 } 00384 } 00385 } 00386 return Polyhedron::TVB_DONT_KNOW; 00387 }
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 390 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Generator::CLOSURE_POINT, con_sys, constraints_are_minimized(), constraints_are_up_to_date(), Parma_Polyhedra_Library::Constraint::EQUALITY, has_pending_generators(), Parma_Polyhedra_Library::Constraint::is_inequality(), Parma_Polyhedra_Library::Generator::is_line(), Parma_Polyhedra_Library::Generator::LINE, marked_empty(), minimize(), Parma_Polyhedra_Library::Constraint::NONSTRICT_INEQUALITY, Parma_Polyhedra_Library::Matrix::num_rows(), OK(), Parma_Polyhedra_Library::Generator::POINT, process_pending_generators(), Parma_Polyhedra_Library::Generator::RAY, Parma_Polyhedra_Library::Scalar_Products::reduced_sign(), Parma_Polyhedra_Library::Scalar_Products::sign(), space_dim, Parma_Polyhedra_Library::Constraint::STRICT_INEQUALITY, topology(), Parma_Polyhedra_Library::Generator::type(), Parma_Polyhedra_Library::Constraint::type(), and update_constraints().
Referenced by contains().
00390 { 00391 // Private method: the caller must ensure the following. 00392 assert(topology() == y.topology()); 00393 assert(space_dim == y.space_dim); 00394 assert(!marked_empty() && !y.marked_empty() && space_dim > 0); 00395 00396 const Polyhedron& x = *this; 00397 00398 // `x' cannot have pending constraints, because we need its generators. 00399 if (x.has_pending_constraints() && !x.process_pending_constraints()) 00400 return true; 00401 // `y' cannot have pending generators, because we need its constraints. 00402 if (y.has_pending_generators()) 00403 y.process_pending_generators(); 00404 00405 #if BE_LAZY 00406 if (!x.generators_are_up_to_date() && !x.update_generators()) 00407 return true; 00408 if (!y.constraints_are_up_to_date()) 00409 y.update_constraints(); 00410 #else 00411 if (!x.generators_are_minimized()) 00412 x.minimize(); 00413 if (!y.constraints_are_minimized()) 00414 y.minimize(); 00415 #endif 00416 00417 assert(x.OK()); 00418 assert(y.OK()); 00419 00420 const Generator_System& gs = x.gen_sys; 00421 const Constraint_System& cs = y.con_sys; 00422 00423 if (x.is_necessarily_closed()) 00424 // When working with necessarily closed polyhedra, 00425 // `x' is contained in `y' if and only if all the generators of `x' 00426 // satisfy all the inequalities and saturate all the equalities of `y'. 00427 // This comes from the definition of a polyhedron as the set of 00428 // vectors satisfying a constraint system and the fact that all 00429 // vectors in `x' can be obtained by suitably combining its generators. 00430 for (dimension_type i = cs.num_rows(); i-- > 0; ) { 00431 const Constraint& c = cs[i]; 00432 if (c.is_inequality()) { 00433 for (dimension_type j = gs.num_rows(); j-- > 0; ) { 00434 const Generator& g = gs[j]; 00435 const int sp_sign = Scalar_Products::sign(c, g); 00436 if (g.is_line()) { 00437 if (sp_sign != 0) 00438 return false; 00439 } 00440 else 00441 // `g' is a ray or a point. 00442 if (sp_sign < 0) 00443 return false; 00444 } 00445 } 00446 else { 00447 // `c' is an equality. 00448 for (dimension_type j = gs.num_rows(); j-- > 0; ) 00449 if (Scalar_Products::sign(c, gs[j]) != 0) 00450 return false; 00451 } 00452 } 00453 else { 00454 // Here we have an NNC polyhedron: using the reduced scalar product, 00455 // which ignores the epsilon coefficient. 00456 for (dimension_type i = cs.num_rows(); i-- > 0; ) { 00457 const Constraint& c = cs[i]; 00458 switch (c.type()) { 00459 case Constraint::NONSTRICT_INEQUALITY: 00460 for (dimension_type j = gs.num_rows(); j-- > 0; ) { 00461 const Generator& g = gs[j]; 00462 const int sp_sign = Scalar_Products::reduced_sign(c, g); 00463 if (g.is_line()) { 00464 if (sp_sign != 0) 00465 return false; 00466 } 00467 else 00468 // `g' is a ray or a point or a closure point. 00469 if (sp_sign < 0) 00470 return false; 00471 } 00472 break; 00473 case Constraint::EQUALITY: 00474 for (dimension_type j = gs.num_rows(); j-- > 0; ) 00475 if (Scalar_Products::reduced_sign(c, gs[j]) != 0) 00476 return false; 00477 break; 00478 case Constraint::STRICT_INEQUALITY: 00479 for (dimension_type j = gs.num_rows(); j-- > 0; ) { 00480 const Generator& g = gs[j]; 00481 const int sp_sign = Scalar_Products::reduced_sign(c, g); 00482 switch (g.type()) { 00483 case Generator::POINT: 00484 // If a point violates or saturates a strict inequality 00485 // (when ignoring the epsilon coefficients) then it is 00486 // not included in the polyhedron. 00487 if (sp_sign <= 0) 00488 return false; 00489 break; 00490 case Generator::LINE: 00491 // Lines have to saturate all constraints. 00492 if (sp_sign != 0) 00493 return false; 00494 break; 00495 case Generator::RAY: 00496 // Intentionally fall through. 00497 case Generator::CLOSURE_POINT: 00498 // The generator is a ray or closure point: usual test. 00499 if (sp_sign < 0) 00500 return false; 00501 break; 00502 } 00503 } 00504 break; 00505 } 00506 } 00507 } 00508 00509 // Inclusion holds. 00510 return true; 00511 }
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 514 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().
00515 { 00516 // The dimension of `expr' should not be greater than the dimension 00517 // of `*this'. 00518 const dimension_type expr_space_dim = expr.space_dimension(); 00519 if (space_dim < expr_space_dim) 00520 throw_dimension_incompatible((from_above 00521 ? "bounds_from_above(e)" 00522 : "bounds_from_below(e)"), "e", expr); 00523 00524 // A zero-dimensional or empty polyhedron bounds everything. 00525 if (space_dim == 0 00526 || marked_empty() 00527 || (has_pending_constraints() && !process_pending_constraints()) 00528 || (!generators_are_up_to_date() && !update_generators())) 00529 return true; 00530 00531 // The polyhedron has updated, possibly pending generators. 00532 for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) { 00533 const Generator& g = gen_sys[i]; 00534 // Only lines and rays in `*this' can cause `expr' to be unbounded. 00535 if (g.is_line_or_ray()) { 00536 const int sp_sign = Scalar_Products::homogeneous_sign(expr, g); 00537 if (sp_sign != 0 00538 && (g.is_line() 00539 || (from_above && sp_sign > 0) 00540 || (!from_above && sp_sign < 0))) 00541 // `*this' does not bound `expr'. 00542 return false; 00543 } 00544 } 00545 // No sources of unboundedness have been found for `expr' 00546 // in the given direction. 00547 return true; 00548 }
bool Parma_Polyhedra_Library::Polyhedron::max_min | ( | const Linear_Expression & | expr, | |
const bool | maximize, | |||
Coefficient & | ext_n, | |||
Coefficient & | ext_d, | |||
bool & | included, | |||
Generator & | point | |||
) | 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; | |
point | When maximization or minimization succeeds, will be assigned a point or closure point where expr reaches the corresponding extremum value. |
std::invalid_argument | Thrown if expr and *this are dimension-incompatible. |
*this
is empty or expr
is not bounded in the appropriate direction, false
is returned and ext_n
, ext_d
, included
and point
are left untouched.
Definition at line 551 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::assign_r(), gen_sys, generators_are_up_to_date(), has_pending_constraints(), Parma_Polyhedra_Library::Scalar_Products::homogeneous_assign(), Parma_Polyhedra_Library::Linear_Expression::inhomogeneous_term(), Parma_Polyhedra_Library::Generator::is_closure_point(), Parma_Polyhedra_Library::Generator::is_line(), Parma_Polyhedra_Library::Generator::is_line_or_ray(), Parma_Polyhedra_Library::Generator::is_point(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_rows(), process_pending_constraints(), space_dim, Parma_Polyhedra_Library::Linear_Expression::space_dimension(), TEMP_INTEGER, throw_dimension_incompatible(), and update_generators().
Referenced by maximize(), and minimize().
00555 { 00556 // The dimension of `expr' should not be greater than the dimension 00557 // of `*this'. 00558 const dimension_type expr_space_dim = expr.space_dimension(); 00559 if (space_dim < expr_space_dim) 00560 throw_dimension_incompatible((maximize 00561 ? "maximize(e, ...)" 00562 : "minimize(e, ...)"), "e", expr); 00563 00564 // For an empty polyhedron we simply return false. 00565 if (marked_empty() 00566 || (has_pending_constraints() && !process_pending_constraints()) 00567 || (!generators_are_up_to_date() && !update_generators())) 00568 return false; 00569 00570 // The polyhedron has updated, possibly pending generators. 00571 // The following loop will iterate through the generator 00572 // to find the extremum. 00573 mpq_class extremum; 00574 00575 // True if we have no other candidate extremum to compare with. 00576 bool first_candidate = true; 00577 00578 // To store the position of the current candidate extremum. 00579 // Initialized only to avoid a compiler warning. 00580 dimension_type ext_position = 0; 00581 00582 // Whether the current candidate extremum is included or not. 00583 // Initialized only to avoid a compiler warning. 00584 bool ext_included = false; 00585 00586 TEMP_INTEGER(sp); 00587 for (dimension_type i = gen_sys.num_rows(); i-- > 0; ) { 00588 const Generator& g = gen_sys[i]; 00589 Scalar_Products::homogeneous_assign(sp, expr, g); 00590 // Lines and rays in `*this' can cause `expr' to be unbounded. 00591 if (g.is_line_or_ray()) { 00592 const int sp_sign = sgn(sp); 00593 if (sp_sign != 0 00594 && (g.is_line() 00595 || (maximize && sp_sign > 0) 00596 || (!maximize && sp_sign < 0))) 00597 // `expr' is unbounded in `*this'. 00598 return false; 00599 } 00600 else { 00601 // We have a point or a closure point. 00602 assert(g.is_point() || g.is_closure_point()); 00603 // Notice that we are ignoring the constant term in `expr' here. 00604 // We will add it to the extremum as soon as we find it. 00605 mpq_class candidate; 00606 assign_r(candidate.get_num(), sp, ROUND_NOT_NEEDED); 00607 assign_r(candidate.get_den(), g[0], ROUND_NOT_NEEDED); 00608 candidate.canonicalize(); 00609 const bool g_is_point = g.is_point(); 00610 if (first_candidate 00611 || (maximize 00612 && (candidate > extremum 00613 || (g_is_point 00614 && !ext_included 00615 && candidate == extremum))) 00616 || (!maximize 00617 && (candidate < extremum 00618 || (g_is_point 00619 && !ext_included 00620 && candidate == extremum)))) { 00621 // We have a (new) candidate extremum. 00622 first_candidate = false; 00623 extremum = candidate; 00624 ext_position = i; 00625 ext_included = g_is_point; 00626 } 00627 } 00628 } 00629 00630 // Add in the constant term in `expr'. 00631 mpz_class n; 00632 assign_r(n, expr.inhomogeneous_term(), ROUND_NOT_NEEDED); 00633 extremum += n; 00634 00635 // The polyhedron is bounded in the right direction and we have 00636 // computed the extremum: write the result into the caller's structures. 00637 assert(!first_candidate); 00638 ext_n = Coefficient(extremum.get_num()); 00639 ext_d = Coefficient(extremum.get_den()); 00640 included = ext_included; 00641 point = gen_sys[ext_position]; 00642 00643 return true; 00644 }
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 assert(topology() == y.topology() 00044 && topology() == cs_selection.topology() 00045 && space_dim == y.space_dim); 00046 assert(!marked_empty() 00047 && !has_pending_constraints() 00048 && generators_are_up_to_date()); 00049 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::Saturation_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(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Saturation_Matrix::rows_erase_to_end(), sat_g, sat_g_is_up_to_date(), Parma_Polyhedra_Library::Saturation_Row::set(), Parma_Polyhedra_Library::Scalar_Products::sign(), Parma_Polyhedra_Library::Saturation_Matrix::sort_rows(), Parma_Polyhedra_Library::Saturation_Matrix::sorted_contains(), space_dim, Parma_Polyhedra_Library::Linear_System::topology(), topology(), 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 assert(topology() == y.topology() 00073 && topology() == cs_selected.topology() 00074 && topology() == cs_not_selected.topology()); 00075 assert(space_dim == y.space_dim); 00076 assert(!marked_empty() 00077 && !has_pending_generators() 00078 && constraints_are_up_to_date()); 00079 assert(!y.marked_empty() 00080 && !y.has_something_pending() 00081 && y.constraints_are_minimized() 00082 && y.generators_are_up_to_date()); 00083 00084 // Obtain a sorted copy of `y.sat_g'. 00085 if (!y.sat_g_is_up_to_date()) 00086 y.update_sat_g(); 00087 Saturation_Matrix tmp_sat_g = y.sat_g; 00088 // Remove from `tmp_sat_g' the rows corresponding to tautologies 00089 // (i.e., the positivity or epsilon-bounding constraints): 00090 // this is needed in order to widen the polyhedron and not the 00091 // corresponding homogenized polyhedral cone. 00092 const Constraint_System& y_cs = y.con_sys; 00093 dimension_type num_rows = y_cs.num_rows(); 00094 for (dimension_type i = 0; i < num_rows; ++i) 00095 if (y_cs[i].is_tautological()) { 00096 --num_rows; 00097 std::swap(tmp_sat_g[i], tmp_sat_g[num_rows]); 00098 } 00099 tmp_sat_g.rows_erase_to_end(num_rows); 00100 tmp_sat_g.sort_rows(); 00101 00102 // A constraint in `con_sys' is copied to `cs_selected' 00103 // if its behavior with respect to `y.gen_sys' is the same 00104 // as that of another constraint in `y.con_sys'. 00105 // otherwise it is copied to `cs_not_selected'. 00106 // Namely, we check whether the saturation row `buffer' 00107 // (built starting from the given constraint and `y.gen_sys') 00108 // is a row of the saturation matrix `tmp_sat_g'. 00109 00110 // CHECK ME: the following comment is only applicable when `y.gen_sys' 00111 // is minimized. In that case, the comment suggests that it would be 00112 // possible to use a fast (but incomplete) redundancy test based on 00113 // the number of saturators in `buffer'. 00114 // NOTE: If the considered constraint of `con_sys' does not 00115 // satisfy the saturation rule (see Section \ref prelims), then 00116 // it will not appear in the resulting constraint system, 00117 // because `tmp_sat_g' is built starting from a minimized polyhedron. 00118 00119 // The size of `buffer' will reach sat.num_columns() bit. 00120 Saturation_Row buffer; 00121 // Note: the loop index `i' goes upward to avoid reversing 00122 // the ordering of the chosen constraints. 00123 for (dimension_type i = 0, end = con_sys.num_rows(); i < end; ++i) { 00124 const Constraint& ci = con_sys[i]; 00125 // The saturation row `buffer' is built considering 00126 // the `i'-th constraint of the polyhedron `x' and 00127 // all the generators of the polyhedron `y'. 00128 buffer.clear(); 00129 for (dimension_type j = y.gen_sys.num_rows(); j-- > 0; ) { 00130 const int sp_sgn = Scalar_Products::sign(ci, y.gen_sys[j]); 00131 // We are assuming that `y <= x'. 00132 assert(sp_sgn >= 0); 00133 if (sp_sgn > 0) 00134 buffer.set(j); 00135 } 00136 // We check whether `buffer' is a row of `tmp_sat_g', 00137 // exploiting its sortedness in order to have faster comparisons. 00138 if (tmp_sat_g.sorted_contains(buffer)) 00139 cs_selected.insert(ci); 00140 else 00141 cs_not_selected.insert(ci); 00142 } 00143 }
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 377 of file Polyhedron_widenings.cc.
References add_recycled_constraints_and_minimize(), Parma_Polyhedra_Library::Linear_Row::all_homogeneous_terms_are_zero(), Parma_Polyhedra_Library::Constraint_System::clear(), con_sys, constraints_are_minimized(), contains(), gen_sys, generators_are_minimized(), has_something_pending(), Parma_Polyhedra_Library::Constraint_System::insert(), Parma_Polyhedra_Library::Generator::is_closure_point(), Parma_Polyhedra_Library::Constraint::is_inequality(), is_necessarily_closed(), Parma_Polyhedra_Library::Generator::is_point(), Parma_Polyhedra_Library::BHRZ03_Certificate::is_stabilizing(), marked_empty(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), relation_with(), Parma_Polyhedra_Library::Scalar_Products::sign(), space_dim, Parma_Polyhedra_Library::Constraint_System::space_dimension(), Parma_Polyhedra_Library::Poly_Con_Relation::strictly_intersects(), Parma_Polyhedra_Library::Linear_System::topology(), and topology().
Referenced by BHRZ03_widening_assign().
00380 { 00381 Polyhedron& x = *this; 00382 // It is assumed that `y <= x <= H79'. 00383 assert(x.topology() == y.topology() 00384 && x.topology() == H79.topology() 00385 && x.topology() == x_minus_H79_cs.topology()); 00386 assert(x.space_dim == y.space_dim 00387 && x.space_dim == H79.space_dim 00388 && x.space_dim == x_minus_H79_cs.space_dimension()); 00389 assert(!x.marked_empty() && !x.has_something_pending() 00390 && x.constraints_are_minimized() && x.generators_are_minimized()); 00391 assert(!y.marked_empty() && !y.has_something_pending() 00392 && y.constraints_are_minimized() && y.generators_are_minimized()); 00393 assert(!H79.marked_empty() && !H79.has_something_pending() 00394 && H79.constraints_are_minimized() && H79.generators_are_minimized()); 00395 00396 // We will choose from `x_minus_H79_cs' many subsets of constraints, 00397 // that will be collected (one at a time) in `combining_cs'. 00398 // For each group collected, we compute an average constraint, 00399 // that will be stored in `new_cs'. 00400 00401 // There is no point in applying this technique when `x_minus_H79_cs' 00402 // has one constraint at most (no ``new'' constraint can be computed). 00403 const dimension_type x_minus_H79_cs_num_rows = x_minus_H79_cs.num_rows(); 00404 if (x_minus_H79_cs_num_rows <= 1) 00405 return false; 00406 00407 const Topology tpl = x.topology(); 00408 Constraint_System combining_cs(tpl); 00409 Constraint_System new_cs(tpl); 00410 00411 // Consider the points that belong to both `x.gen_sys' and `y.gen_sys'. 00412 // For NNC polyhedra, the role of points is played by closure points. 00413 const bool closed = x.is_necessarily_closed(); 00414 for (dimension_type i = y.gen_sys.num_rows(); i-- > 0; ) { 00415 const Generator& g = y.gen_sys[i]; 00416 if ((g.is_point() && closed) || (g.is_closure_point() && !closed)) { 00417 // If in `H79.con_sys' there is already an inequality constraint 00418 // saturating this point, then there is no need to produce another 00419 // constraint. 00420 bool lies_on_the_boundary_of_H79 = false; 00421 const Constraint_System& H79_cs = H79.con_sys; 00422 for (dimension_type j = H79_cs.num_rows(); j-- > 0; ) { 00423 const Constraint& c = H79_cs[j]; 00424 if (c.is_inequality() && Scalar_Products::sign(c, g) == 0) { 00425 lies_on_the_boundary_of_H79 = true; 00426 break; 00427 } 00428 } 00429 if (lies_on_the_boundary_of_H79) 00430 continue; 00431 00432 // Consider all the constraints in `x_minus_H79_cs' 00433 // that are saturated by the point `g'. 00434 combining_cs.clear(); 00435 for (dimension_type j = x_minus_H79_cs_num_rows; j-- > 0; ) { 00436 const Constraint& c = x_minus_H79_cs[j]; 00437 if (Scalar_Products::sign(c, g) == 0) 00438 combining_cs.insert(c); 00439 } 00440 // Build a new constraint by combining all the chosen constraints. 00441 const dimension_type combining_cs_num_rows = combining_cs.num_rows(); 00442 if (combining_cs_num_rows > 0) { 00443 if (combining_cs_num_rows == 1) 00444 // No combination is needed. 00445 new_cs.insert(combining_cs[0]); 00446 else { 00447 Linear_Expression e(0); 00448 bool strict_inequality = false; 00449 for (dimension_type h = combining_cs_num_rows; h-- > 0; ) { 00450 if (combining_cs[h].is_strict_inequality()) 00451 strict_inequality = true; 00452 e += Linear_Expression(combining_cs[h]); 00453 } 00454 00455 if (!e.all_homogeneous_terms_are_zero()) 00456 if (strict_inequality) 00457 new_cs.insert(e > 0); 00458 else 00459 new_cs.insert(e >= 0); 00460 } 00461 } 00462 } 00463 } 00464 00465 // If none of the collected constraints strictly intersects `H79', 00466 // then the technique was unsuccessful. 00467 bool improves_upon_H79 = false; 00468 const Poly_Con_Relation si = Poly_Con_Relation::strictly_intersects(); 00469 for (dimension_type i = new_cs.num_rows(); i-- > 0; ) 00470 if (H79.relation_with(new_cs[i]) == si) { 00471 improves_upon_H79 = true; 00472 break; 00473 } 00474 if (!improves_upon_H79) 00475 return false; 00476 00477 // The resulting polyhedron is obtained by adding the constraints 00478 // in `new_cs' to polyhedron `H79'. 00479 Polyhedron result = H79; 00480 result.add_recycled_constraints_and_minimize(new_cs); 00481 00482 // Check for stabilization with respect to `y_cert' and improvement 00483 // over `H79'. 00484 if (y_cert.is_stabilizing(result) && !result.contains(H79)) { 00485 // The technique was successful. 00486 std::swap(x, result); 00487 assert(x.OK(true)); 00488 return true; 00489 } 00490 else 00491 // The technique was unsuccessful. 00492 return false; 00493 }
bool Parma_Polyhedra_Library::Polyhedron::BHRZ03_evolving_points | ( | const Polyhedron & | y, | |
const BHRZ03_Certificate & | y_cert, | |||
const Polyhedron & | H79 | |||
) | [private] |
Definition at line 496 of file Polyhedron_widenings.cc.
References add_recycled_generators_and_minimize(), constraints_are_minimized(), contains(), gen_sys, generators_are_minimized(), has_something_pending(), intersection_assign_and_minimize(), 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(), Parma_Polyhedra_Library::Poly_Gen_Relation::nothing(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), relation_with(), space_dim, and topology().
Referenced by BHRZ03_widening_assign().
00498 { 00499 Polyhedron& x = *this; 00500 // It is assumed that `y <= x <= H79'. 00501 assert(x.topology() == y.topology() 00502 && x.topology() == H79.topology()); 00503 assert(x.space_dim == y.space_dim 00504 && x.space_dim == H79.space_dim); 00505 assert(!x.marked_empty() && !x.has_something_pending() 00506 && x.constraints_are_minimized() && x.generators_are_minimized()); 00507 assert(!y.marked_empty() && !y.has_something_pending() 00508 && y.constraints_are_minimized() && y.generators_are_minimized()); 00509 assert(!H79.marked_empty() && !H79.has_something_pending() 00510 && H79.constraints_are_minimized() && H79.generators_are_minimized()); 00511 00512 // For each point in `x.gen_sys' that is not in `y', 00513 // this technique tries to identify a set of rays that: 00514 // - are included in polyhedron `H79'; 00515 // - when added to `y' will subsume the point. 00516 Generator_System candidate_rays; 00517 00518 const dimension_type x_gen_sys_num_rows = x.gen_sys.num_rows(); 00519 const dimension_type y_gen_sys_num_rows = y.gen_sys.num_rows(); 00520 const bool closed = x.is_necessarily_closed(); 00521 for (dimension_type i = x_gen_sys_num_rows; i-- > 0; ) { 00522 Generator& g1 = x.gen_sys[i]; 00523 // For C polyhedra, we choose a point of `x.gen_sys' 00524 // that is not included in `y'. 00525 // In the case of NNC polyhedra, we can restrict attention to 00526 // closure points (considering also points will only add redundancy). 00527 if (((g1.is_point() && closed) || (g1.is_closure_point() && !closed)) 00528 && y.relation_with(g1) == Poly_Gen_Relation::nothing()) { 00529 // For each point (resp., closure point) `g2' in `y.gen_sys', 00530 // where `g1' and `g2' are different, 00531 // build the candidate ray `g1 - g2'. 00532 for (dimension_type j = y_gen_sys_num_rows; j-- > 0; ) { 00533 const Generator& g2 = y.gen_sys[j]; 00534 if ((g2.is_point() && closed) 00535 || (g2.is_closure_point() && !closed)) { 00536 assert(compare(g1, g2) != 0); 00537 Generator ray_from_g2_to_g1 = g1; 00538 ray_from_g2_to_g1.linear_combine(g2, 0); 00539 candidate_rays.insert(ray_from_g2_to_g1); 00540 } 00541 } 00542 } 00543 } 00544 00545 // Be non-intrusive. 00546 Polyhedron result = x; 00547 result.add_recycled_generators_and_minimize(candidate_rays); 00548 result.intersection_assign_and_minimize(H79); 00549 00550 // Check for stabilization with respect to `y_cert' and improvement 00551 // over `H79'. 00552 if (y_cert.is_stabilizing(result) && !result.contains(H79)) { 00553 // The technique was successful. 00554 std::swap(x, result); 00555 assert(x.OK(true)); 00556 return true; 00557 } 00558 else 00559 // The technique was unsuccessful. 00560 return false; 00561 }
bool Parma_Polyhedra_Library::Polyhedron::BHRZ03_evolving_rays | ( | const Polyhedron & | y, | |
const BHRZ03_Certificate & | y_cert, | |||
const Polyhedron & | H79 | |||
) | [private] |
Definition at line 564 of file Polyhedron_widenings.cc.
References add_recycled_generators_and_minimize(), constraints_are_minimized(), contains(), gen_sys, generators_are_minimized(), has_something_pending(), Parma_Polyhedra_Library::Generator_System::insert(), intersection_assign_and_minimize(), Parma_Polyhedra_Library::Generator::is_ray(), Parma_Polyhedra_Library::BHRZ03_Certificate::is_stabilizing(), marked_empty(), Parma_Polyhedra_Library::Row::normalize(), Parma_Polyhedra_Library::Poly_Gen_Relation::nothing(), Parma_Polyhedra_Library::Matrix::num_rows(), OK(), relation_with(), space_dim, Parma_Polyhedra_Library::sub_mul_assign(), TEMP_INTEGER, and topology().
Referenced by BHRZ03_widening_assign().
00566 { 00567 Polyhedron& x = *this; 00568 // It is assumed that `y <= x <= H79'. 00569 assert(x.topology() == y.topology() 00570 && x.topology() == H79.topology()); 00571 assert(x.space_dim == y.space_dim 00572 && x.space_dim == H79.space_dim); 00573 assert(!x.marked_empty() && !x.has_something_pending() 00574 && x.constraints_are_minimized() && x.generators_are_minimized()); 00575 assert(!y.marked_empty() && !y.has_something_pending() 00576 && y.constraints_are_minimized() && y.generators_are_minimized()); 00577 assert(!H79.marked_empty() && !H79.has_something_pending() 00578 && H79.constraints_are_minimized() && H79.generators_are_minimized()); 00579 00580 const dimension_type x_gen_sys_num_rows = x.gen_sys.num_rows(); 00581 const dimension_type y_gen_sys_num_rows = y.gen_sys.num_rows(); 00582 00583 // Candidate rays are kept in a temporary generator system. 00584 Generator_System candidate_rays; 00585 TEMP_INTEGER(tmp); 00586 for (dimension_type i = x_gen_sys_num_rows; i-- > 0; ) { 00587 const Generator& x_g = x.gen_sys[i]; 00588 // We choose a ray of `x' that does not belong to `y'. 00589 if (x_g.is_ray() && y.relation_with(x_g) == Poly_Gen_Relation::nothing()) { 00590 for (dimension_type j = y_gen_sys_num_rows; j-- > 0; ) { 00591 const Generator& y_g = y.gen_sys[j]; 00592 if (y_g.is_ray()) { 00593 Generator new_ray(x_g); 00594 // Modify `new_ray' according to the evolution of `x_g' with 00595 // respect to `y_g'. 00596 std::deque<bool> considered(x.space_dim + 1); 00597 for (dimension_type k = 1; k < x.space_dim; ++k) 00598 if (!considered[k]) 00599 for (dimension_type h = k + 1; h <= x.space_dim; ++h) 00600 if (!considered[h]) { 00601 tmp = x_g[k] * y_g[h]; 00602 // The following line optimizes the computation of 00603 // tmp -= x_g[h] * y_g[k]; 00604 sub_mul_assign(tmp, x_g[h], y_g[k]); 00605 const int clockwise 00606 = sgn(tmp); 00607 const int first_or_third_quadrant 00608 = sgn(x_g[k]) * sgn(x_g[h]); 00609 switch (clockwise * first_or_third_quadrant) { 00610 case -1: 00611 new_ray[k] = 0; 00612 considered[k] = true; 00613 break; 00614 case 1: 00615 new_ray[h] = 0; 00616 considered[h] = true; 00617 break; 00618 default: 00619 break; 00620 } 00621 } 00622 new_ray.normalize(); 00623 candidate_rays.insert(new_ray); 00624 } 00625 } 00626 } 00627 } 00628 00629 // If there are no candidate rays, we cannot obtain stabilization. 00630 if (candidate_rays.num_rows() == 0) 00631 return false; 00632 00633 // Be non-intrusive. 00634 Polyhedron result = x; 00635 // Add to `result' the rays in `candidate_rays' 00636 result.add_recycled_generators_and_minimize(candidate_rays); 00637 // Intersect with `H79'. 00638 result.intersection_assign_and_minimize(H79); 00639 00640 // Check for stabilization with respect to `y' and improvement over `H79'. 00641 if (y_cert.is_stabilizing(result) && !result.contains(H79)) { 00642 // The technique was successful. 00643 std::swap(x, result); 00644 assert(x.OK(true)); 00645 return true; 00646 } 00647 else 00648 // The technique was unsuccessful. 00649 return false; 00650 }
void Parma_Polyhedra_Library::Polyhedron::add_space_dimensions | ( | Linear_System & | mat1, | |
Linear_System & | mat2, | |||
Saturation_Matrix & | sat1, | |||
Saturation_Matrix & | sat2, | |||
dimension_type | add_dim | |||
) | [static, private] |
Adds new space dimensions to the given matrices.
mat1 | The matrix to which columns are added; | |
mat2 | The matrix to which rows and columns are added; | |
sat1 | The saturation matrix whose columns are indexed by the rows of matrix mat1 . On entry it is up-to-date; | |
sat2 | The saturation matrix whose columns are indexed by the rows of mat2 ; | |
add_dim | The number of space dimensions to add. |
add_space_dimensions_and_embed()
and add_space_dimensions_and_project()
, passing the matrix of constraints and that of generators (and the corresponding saturation matrices) in different order (see those methods for details).
Definition at line 34 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::Saturation_Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Saturation_Matrix::num_rows(), Parma_Polyhedra_Library::Saturation_Matrix::resize(), Parma_Polyhedra_Library::Linear_System::set_index_first_pending_row(), Parma_Polyhedra_Library::Matrix::swap_columns(), Parma_Polyhedra_Library::Linear_System::topology(), and Parma_Polyhedra_Library::Saturation_Matrix::transpose_assign().
Referenced by add_space_dimensions_and_embed(), and add_space_dimensions_and_project().
00038 { 00039 assert(sys1.topology() == sys2.topology()); 00040 assert(sys1.num_columns() == sys2.num_columns()); 00041 assert(add_dim != 0); 00042 00043 sys1.add_zero_columns(add_dim); 00044 dimension_type old_index = sys2.first_pending_row(); 00045 sys2.add_rows_and_columns(add_dim); 00046 // The added rows are in the non-pending part. 00047 sys2.set_index_first_pending_row(old_index + add_dim); 00048 00049 // The resulting saturation matrix will be as follows: 00050 // from row 0 to add_dim-1 : only zeroes 00051 // add_dim add_dim+num_rows-1 : old saturation matrix 00052 00053 // In fact all the old generators saturate all the new constraints 00054 // because the polyhedron has not been embedded in the new space. 00055 sat1.resize(sat1.num_rows() + add_dim, sat1.num_columns()); 00056 // The old matrix is moved to the end of the new matrix. 00057 for (dimension_type i = sat1.num_rows() - add_dim; i-- > 0; ) 00058 std::swap(sat1[i], sat1[i+add_dim]); 00059 // Computes the "sat_c", too. 00060 sat2.transpose_assign(sat1); 00061 00062 if (!sys1.is_necessarily_closed()) { 00063 // Moving the epsilon coefficients to the new last column. 00064 dimension_type new_eps_index = sys1.num_columns() - 1; 00065 dimension_type old_eps_index = new_eps_index - add_dim; 00066 // This swap preserves sortedness of `sys1'. 00067 sys1.swap_columns(old_eps_index, new_eps_index); 00068 00069 // Try to preserve sortedness of `sys2'. 00070 if (!sys2.is_sorted()) 00071 sys2.swap_columns(old_eps_index, new_eps_index); 00072 else { 00073 for (dimension_type i = sys2.num_rows(); i-- > add_dim; ) { 00074 Linear_Row& r = sys2[i]; 00075 std::swap(r[old_eps_index], r[new_eps_index]); 00076 } 00077 // The upper-right corner of `sys2' contains the J matrix: 00078 // swap coefficients to preserve sortedness. 00079 for (dimension_type i = add_dim; i-- > 0; ++old_eps_index) { 00080 Linear_Row& r = sys2[i]; 00081 std::swap(r[old_eps_index], r[old_eps_index + 1]); 00082 } 00083 } 00084 // NOTE: since we swapped columns in both `sys1' and `sys2', 00085 // no swapping is required for `sat1' and `sat2'. 00086 } 00087 }
bool Parma_Polyhedra_Library::Polyhedron::minimize | ( | bool | con_to_gen, | |
Linear_System & | source, | |||
Linear_System & | dest, | |||
Saturation_Matrix & | sat | |||
) | [static, private] |
Builds and simplifies constraints from generators (or vice versa).
true
if the polyhedron is empty, false
otherwise.con_to_gen | true if source represents the constraints, false otherwise; | |
source | The given system, which is not empty; | |
dest | The system to build and minimize; | |
sat | The saturation matrix. |
dest
is not const
because it will be built (and then modified) during minimize(). Also, sat
and source
are not const
because the former will be built during dest
creation and the latter will maybe be sorted and modified by conversion()
and simplify()
.
sat
has the generators on its columns and the constraints on its rows if con_to_gen
is true
, otherwise it has the generators on its rows and the constraints on its columns.
Given source
, this function builds (by means of conversion()
) dest
and then simplifies (invoking simplify()
) source
, erasing redundant rows. For the sequel we assume that source
is the system of constraints and dest
is the system of generators. This will simplify the description of the function; the dual case is similar.
Definition at line 69 of file minimize.cc.
References conversion(), Parma_Polyhedra_Library::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::Saturation_Matrix::transpose_assign().
00072 { 00073 // Topologies have to agree. 00074 assert(source.topology() == dest.topology()); 00075 // `source' cannot be empty: even if it is an empty constraint system, 00076 // representing the universe polyhedron, homogenization has added 00077 // the positive constraint. It also cannot be an empty generator system, 00078 // since this function is always called starting from a non-empty 00079 // polyhedron. 00080 assert(source.num_rows() > 0); 00081 00082 // Sort the source system, if necessary. 00083 if (!source.is_sorted()) 00084 source.sort_rows(); 00085 00086 // Initialization of the system of generators `dest'. 00087 // The algorithm works incrementally and we haven't seen any 00088 // constraint yet: as a consequence, `dest' should describe 00089 // the universe polyhedron of the appropriate dimension. 00090 // To this end, we initialize it to the identity matrix of dimension 00091 // `source.num_columns()': the rows represent the lines corresponding 00092 // to the canonical basis of the vector space. 00093 00094 // Resizing `dest' to be the appropriate square matrix. 00095 dimension_type dest_num_rows = source.num_columns(); 00096 // Note that before calling `resize_no_copy()' we must update 00097 // `index_first_pending'. 00098 dest.set_index_first_pending_row(dest_num_rows); 00099 dest.resize_no_copy(dest_num_rows, dest_num_rows); 00100 00101 // Initialize `dest' to the identity matrix. 00102 for (dimension_type i = dest_num_rows; i-- > 0; ) { 00103 Linear_Row& dest_i = dest[i]; 00104 for (dimension_type j = dest_num_rows; j-- > 0; ) 00105 dest_i[j] = (i == j) ? 1 : 0; 00106 dest_i.set_is_line_or_equality(); 00107 } 00108 // The identity matrix `dest' is not sorted (see the sorting rules 00109 // in Linear_Row.cc). 00110 dest.set_sorted(false); 00111 00112 // NOTE: the system `dest', as it is now, is not a _legal_ system of 00113 // generators, because in the first row we have a line with a 00114 // non-zero divisor (which should only happen for 00115 // points). However, this is NOT a problem, because `source' 00116 // necessarily contains the positivity constraint (or a 00117 // combination of it with another constraint) which will 00118 // restore things as they should be. 00119 00120 00121 // Building a saturation matrix and initializing it by setting 00122 // all of its elements to zero. This matrix will be modified together 00123 // with `dest' during the conversion. 00124 // NOTE: since we haven't seen any constraint yet, the relevant 00125 // portion of `tmp_sat' is the sub-matrix consisting of 00126 // the first 0 columns: thus the relevant portion correctly 00127 // characterizes the initial saturation information. 00128 Saturation_Matrix tmp_sat(dest_num_rows, source.num_rows()); 00129 00130 // By invoking the function conversion(), we populate `dest' with 00131 // the generators characterizing the polyhedron described by all 00132 // the constraints in `source'. 00133 // The `start' parameter is zero (we haven't seen any constraint yet) 00134 // and the 5th parameter (representing the number of lines in `dest'), 00135 // by construction, is equal to `dest_num_rows'. 00136 const dimension_type num_lines_or_equalities 00137 = conversion(source, 0, dest, tmp_sat, dest_num_rows); 00138 // conversion() may have modified the number of rows in `dest'. 00139 dest_num_rows = dest.num_rows(); 00140 00141 // Checking if the generators in `dest' represent an empty polyhedron: 00142 // the polyhedron is empty if there are no points 00143 // (because rays, lines and closure points need a supporting point). 00144 // Points can be detected by looking at: 00145 // - the divisor, for necessarily closed polyhedra; 00146 // - the epsilon coordinate, for NNC polyhedra. 00147 const dimension_type checking_index 00148 = dest.is_necessarily_closed() 00149 ? 0 00150 : dest.num_columns() - 1; 00151 dimension_type first_point; 00152 for (first_point = num_lines_or_equalities; 00153 first_point < dest_num_rows; 00154 ++first_point) 00155 if (dest[first_point][checking_index] > 0) 00156 break; 00157 00158 if (first_point == dest_num_rows) 00159 if (con_to_gen) 00160 // No point has been found: the polyhedron is empty. 00161 return true; 00162 else 00163 // Here `con_to_gen' is false: `dest' is a system of constraints. 00164 // In this case the condition `first_point == dest_num_rows' 00165 // actually means that all the constraints in `dest' have their 00166 // inhomogeneous term equal to 0. 00167 // This is an ILLEGAL situation, because it implies that 00168 // the constraint system `dest' lacks the positivity constraint 00169 // and no linear combination of the constraints in `dest' 00170 // can reintroduce the positivity constraint. 00171 throw std::runtime_error("PPL internal error"); 00172 else { 00173 // A point has been found: the polyhedron is not empty. 00174 // Now invoking simplify() to remove all the redundant constraints 00175 // from the system `source'. 00176 // Since the saturation matrix `tmp_sat' returned by conversion() 00177 // has rows indexed by generators (the rows of `dest') and columns 00178 // indexed by constraints (the rows of `source'), we have to 00179 // transpose it to obtain the saturation matrix needed by simplify(). 00180 sat.transpose_assign(tmp_sat); 00181 simplify(source, sat); 00182 return false; 00183 } 00184 }
bool Parma_Polyhedra_Library::Polyhedron::add_and_minimize | ( | bool | con_to_gen, | |
Linear_System & | source1, | |||
Linear_System & | dest, | |||
Saturation_Matrix & | sat, | |||
const Linear_System & | source2 | |||
) | [static, private] |
Adds given constraints and builds minimized corresponding generators or vice versa.
true
if the obtained polyhedron is empty, false
otherwise.con_to_gen | true if source1 and source2 are system of constraints, false otherwise; | |
source1 | The first element of the given DD pair; | |
dest | The second element of the given DD pair; | |
sat | The saturation matrix that bind source1 to dest ; | |
source2 | The new system of generators or constraints. |
source1
and source2
are sorted and have no pending rows. It is also assumed that dest
has no pending rows. On entry, the rows of sat
are indexed by the rows of dest
and its columns are indexed by the rows of source1
. On exit, the rows of sat
are indexed by the rows of dest
and its columns are indexed by the rows of the system obtained by merging source1
and source2
.
Let us suppose we want to add some constraints to a given system of constraints source1
. This method, given a minimized double description pair (source1
, dest
) and a system of new constraints source2
, modifies source1
by adding to it the constraints of source2
that are not in source1
. Then, by invoking add_and_minimize(bool, Linear_System&, Linear_System&, Saturation_Matrix&)
, processes the added constraints obtaining a new DD pair.
This method treats also the dual case, i.e., adding new generators to a previous system of generators. In this case source1
contains the old generators, source2
the new ones and dest
is the system of constraints in the given minimized DD pair.
Since source2
contains the constraints (or the generators) that will be added to source1
, it is constant: it will not be modified.
Definition at line 233 of file minimize.cc.
References Parma_Polyhedra_Library::Linear_System::add_pending_row(), Parma_Polyhedra_Library::cmp(), Parma_Polyhedra_Library::Linear_System::is_sorted(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Linear_System::num_pending_rows(), and Parma_Polyhedra_Library::Matrix::num_rows().
Referenced by add_recycled_constraints_and_minimize(), add_recycled_generators_and_minimize(), intersection_assign_and_minimize(), poly_hull_assign_and_minimize(), process_pending_constraints(), and process_pending_generators().
00237 { 00238 // `source1' and `source2' cannot be empty. 00239 assert(source1.num_rows() > 0 && source2.num_rows() > 0); 00240 // `source1' and `source2' must have the same number of columns 00241 // to be merged. 00242 assert(source1.num_columns() == source2.num_columns()); 00243 // `source1' and `source2' are fully sorted. 00244 assert(source1.is_sorted() && source1.num_pending_rows() == 0); 00245 assert(source2.is_sorted() && source2.num_pending_rows() == 0); 00246 assert(dest.num_pending_rows() == 0); 00247 00248 const dimension_type old_source1_num_rows = source1.num_rows(); 00249 // `k1' and `k2' run through the rows of `source1' and `source2', resp. 00250 dimension_type k1 = 0; 00251 dimension_type k2 = 0; 00252 dimension_type source2_num_rows = source2.num_rows(); 00253 while (k1 < old_source1_num_rows && k2 < source2_num_rows) { 00254 // Add to `source1' the constraints from `source2', as pending rows. 00255 // We exploit the property that initially both `source1' and `source2' 00256 // are sorted and index `k1' only scans the non-pending rows of `source1', 00257 // so that it is not influenced by the pending rows appended to it. 00258 // This way no duplicate (i.e., trivially redundant) constraint 00259 // is introduced in `source1'. 00260 const int cmp = compare(source1[k1], source2[k2]); 00261 if (cmp == 0) { 00262 // We found the same row: there is no need to add `source2[k2]'. 00263 ++k2; 00264 // By sortedness, since `k1 < old_source1_num_rows', 00265 // we can increment index `k1' too. 00266 ++k1; 00267 } 00268 else if (cmp < 0) 00269 // By sortedness, we can increment `k1'. 00270 ++k1; 00271 else { 00272 // Here `cmp > 0'. 00273 // By sortedness, `source2[k2]' cannot be in `source1'. 00274 // We add it as a pending row of `source1' (sortedness unaffected). 00275 source1.add_pending_row(source2[k2]); 00276 // We can increment `k2'. 00277 ++k2; 00278 } 00279 } 00280 // Have we scanned all the rows in `source2'? 00281 if (k2 < source2_num_rows) 00282 // By sortedness, all the rows in `source2' having indexes 00283 // greater than or equal to `k2' were not in `source1'. 00284 // We add them as pending rows of 'source1' (sortedness not affected). 00285 for ( ; k2 < source2_num_rows; ++k2) 00286 source1.add_pending_row(source2[k2]); 00287 00288 if (source1.num_pending_rows() == 0) 00289 // No row was appended to `source1', because all the constraints 00290 // in `source2' were already in `source1'. 00291 // There is nothing left to do ... 00292 return false; 00293 00294 return add_and_minimize(con_to_gen, source1, dest, sat); 00295 }
bool Parma_Polyhedra_Library::Polyhedron::add_and_minimize | ( | bool | con_to_gen, | |
Linear_System & | source, | |||
Linear_System & | dest, | |||
Saturation_Matrix & | sat | |||
) | [static, private] |
Adds given constraints and builds minimized corresponding generators or vice versa. The given constraints are in source
.
true
if the obtained polyhedron is empty, false
otherwise.con_to_gen | true if source is a system of constraints, false otherwise; | |
source | The first element of the given DD pair. It also contains the pending rows to be processed; | |
dest | The second element of the given DD pair. It cannot have pending rows; | |
sat | The saturation matrix that bind the upper part of source to dest . |
sat
are indexed by the rows of dest
and its columns are indexed by the non-pending rows of source
. On exit, the rows of sat
are indexed by the rows of dest
and its columns are indexed by the rows of source
.
Let us suppose that source
is a system of constraints. This method assumes that the non-pending part of source
and system dest
form a double description pair in minimal form and will build a new DD pair in minimal form by processing the pending constraints in source
. To this end, it will call conversion()
) and simplify
.
This method treats also the dual case, i.e., processing pending generators. In this case source
contains generators and dest
is the system of constraints corresponding to the non-pending part of source
.
Definition at line 334 of file minimize.cc.
References conversion(), Parma_Polyhedra_Library::Linear_System::first_pending_row(), Parma_Polyhedra_Library::Linear_System::is_necessarily_closed(), Parma_Polyhedra_Library::Linear_System::is_sorted(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Linear_System::num_lines_or_equalities(), Parma_Polyhedra_Library::Linear_System::num_pending_rows(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Saturation_Matrix::resize(), and simplify().
00337 { 00338 assert(source.num_pending_rows() > 0); 00339 assert(source.num_columns() == dest.num_columns()); 00340 assert(source.is_sorted()); 00341 00342 // First, pad the saturation matrix with new columns (of zeroes) 00343 // to accommodate for the pending rows of `source'. 00344 sat.resize(dest.num_rows(), source.num_rows()); 00345 00346 // Incrementally compute the new system of generators. 00347 // Parameter `start' is set to the index of the first pending constraint. 00348 const dimension_type num_lines_or_equalities 00349 = conversion(source, source.first_pending_row(), 00350 dest, sat, 00351 dest.num_lines_or_equalities()); 00352 00353 // conversion() may have modified the number of rows in `dest'. 00354 const dimension_type dest_num_rows = dest.num_rows(); 00355 00356 // Checking if the generators in `dest' represent an empty polyhedron: 00357 // the polyhedron is empty if there are no points 00358 // (because rays, lines and closure points need a supporting point). 00359 // Points can be detected by looking at: 00360 // - the divisor, for necessarily closed polyhedra; 00361 // - the epsilon coordinate, for NNC polyhedra. 00362 const dimension_type checking_index 00363 = dest.is_necessarily_closed() 00364 ? 0 00365 : dest.num_columns() - 1; 00366 dimension_type first_point; 00367 for (first_point = num_lines_or_equalities; 00368 first_point < dest_num_rows; 00369 ++first_point) 00370 if (dest[first_point][checking_index] > 0) 00371 break; 00372 00373 if (first_point == dest_num_rows) 00374 if (con_to_gen) 00375 // No point has been found: the polyhedron is empty. 00376 return true; 00377 else 00378 // Here `con_to_gen' is false: `dest' is a system of constraints. 00379 // In this case the condition `first_point == dest_num_rows' 00380 // actually means that all the constraints in `dest' have their 00381 // inhomogeneous term equal to 0. 00382 // This is an ILLEGAL situation, because it implies that 00383 // the constraint system `dest' lacks the positivity constraint 00384 // and no linear combination of the constraints in `dest' 00385 // can reintroduce the positivity constraint. 00386 throw std::runtime_error("PPL internal error"); 00387 else { 00388 // A point has been found: the polyhedron is not empty. 00389 // Now invoking `simplify()' to remove all the redundant constraints 00390 // from the system `source'. 00391 // Since the saturation matrix `sat' returned by `conversion()' 00392 // has rows indexed by generators (the rows of `dest') and columns 00393 // indexed by constraints (the rows of `source'), we have to 00394 // transpose it to obtain the saturation matrix needed by `simplify()'. 00395 sat.transpose(); 00396 simplify(source, sat); 00397 // Transposing back. 00398 sat.transpose(); 00399 return false; 00400 } 00401 }
PPL::dimension_type Parma_Polyhedra_Library::Polyhedron::conversion | ( | Linear_System & | source, | |
dimension_type | start, | |||
Linear_System & | dest, | |||
Saturation_Matrix & | sat, | |||
dimension_type | num_lines_or_equalities | |||
) | [static, private] |
Performs the conversion from constraints to generators and vice versa.
source | The system to use to convert dest: it may be modified; | |
start | The index of source row from which conversion begin; | |
dest | The result of the conversion; | |
sat | The saturation matrix telling us, for each row in source , which are the rows of dest that satisfy but do not saturate it; | |
num_lines_or_equalities | The number of rows in the system dest that are either lines of the polyhedron (when dest is a system of generators) or equality constraints (when dest is a system of constraints). |
source
to a generator system dest
; the comments for the symmetric case can be obtained by duality.
If some of the constraints in source
are redundant, they will be removed. This is why the source
is not declared to be a constant parameter.
If start
is 0, then source
is a sorted system; also, dest
is a generator system corresponding to an empty constraint system. If otherwise start
is greater than 0, then the two sub-systems of source
made by the non-pending rows and the pending rows, respectively, are both sorted; also, dest
is the generator system corresponding to the non-pending constraints of source
.
Independently from the value of start
, dest
has lines from index 0 to index num_lines_or_equalities
- 1 and rays/points from index num_lines_or_equalities
to the last of its rows.
Note that here the rows of sat
are indexed by rows of dest
and its columns are indexed by rows of source
.
We know that polyhedra can be represented by both a system of constraints or a system of generators (points, rays and lines) (see Section Representations of Convex Polyhedra). When we have both descriptions for a polyhedron we have what is called a double description (or DD pair) for
.
Here, the representation system refers to the system whose rows represent the constraints that characterize
and the generating system, the system
whose rows represent the generators of
. We say that a pair
of (real) systems is a double description pair if
The term "double description" is quite natural in the sense that such a pair contains two different description of the same object. In fact, if we refer to the cone representation of a polyhedron and we call
and
the systems of constraints and rays respectively, we have
Because of the theorem of Minkowski (see Section Further Notation and Terminology), we can say that, given a representation system
such that
for a non-empty polyhedron
, it is always possible to find a generating system
for
such that
is a DD pair. Conversely, Weyl's theorem ensures that, for each generating system
, it is possible to find a representation system
such that
is a DD pair.
For efficiency reasons, our representation of polyhedra makes use of a double description. We are thus left with two problems:
Using Farkas' lemma we can prove that these two problems are computationally equivalent (i.e., linear-time reducible to each other). Farkas' lemma establishes a fundamental property of vectors in that, in a sense, captures the essence of duality. Consider a matrix
and let
be its set of row vectors. Consider also another vector
such that, whenever a vector
has a non-negative projection on the
's, it also has a non-negative projection on
. The lemma states that
has this property if and only if it is in the cone generated by the
's. Formally, the lemma states the equivalence of the two following assertions:
With this result we can prove that is a DD pair if and only if
is a DD pair.
Suppose is a DD pair. Thus, for each
of the appropriate dimension,
if and only if
, which is of course equivalent to
.
First, we assume that is such that
and we will show that
. Let
be such that
. Since
is a DD pair, this is equivalent to
, which, by Farkas' lemma is equivalent to
. Taking
and recalling our assumption that
we can conclude that
, that is equivalent to
. We have thus established that
. By Farkas' lemma, this is equivalent to
, which is equivalent to what we wanted to prove, that is,
.
In order to prove the reverse implication, the following observation turns out to be useful: when is a DD pair,
. In fact, let
be the vector whose components are all
apart from the
-th one, which is
. Clearly
and, taking
and
, we have
, since
is a DD pair. Thus, as
is the
-th column of
and since the choice of
was arbitrary,
.
We now assume that is such that
and we will prove that
. By Farkas' lemma, the assumption
, is equivalent to
. If we take
then
, since
. So
, that is, the
-th component of
is non-negative. The arbitrary choice of
allows us to conclude that
, as required.
In view of this result, the following exposition assumes, for clarity, that the conversion being performed is from constraints to generators. Thus, even if the roles of source
and dest
can be interchanged, in the sequel we assume the source
system will contain the constraints that represent the polyhedron and the dest
system will contain the generator that generates it.
There are some observations that are useful to understand this function:
Observation 1: Let be a system of constraints that generate the polyhedron
and
a new constraint that must be added. Suppose that there is a line
that does not saturate the constraint
. If we combine the old lines and rays that do not saturate
(except
) with
such that the new ones saturate
, the new lines and rays also saturate the constraints saturated by the old lines and rays.
In fact, if is the old generator that does not saturate
,
is the new one such that
and is a previous constraint that
and
saturates, we can see
and
Proposition 1: Let and
be distinct rays of
. Then the following statements are equivalent: a)
and
are adjacent extreme rays (see Section Further Notation and Terminology); b)
and
are extreme rays and the rank of the system composed by the constraints saturated by both
and
is equal to
, where
is the rank of the system of constraints.
In fact, let be the system of generators that saturate the constraints saturated by both
and
. If b) holds, the set
is 2-dimensional and
and
generate this set. So, every generator
of
can be built as a combination of
and
, i.e.
This combination is non-negative because there exists at least a constraint saturated by
and not
(or vice versa) (because they are distinct) for which
and
So, there is no other extreme ray in and a) holds. Otherwise, if b) does not hold, the rank of the system generated by the constraints saturated by both
and
is equal to
, with
k
>= 3, the set is
k
-dimensional and at least k
extreme rays are necessary to generate . So,
and
are not adjacent and a) does not hold.
Proposition 2: When we build the new system of generators starting from a system of constraints of
, if
is the constraint to add to
and all lines of
saturate
, the new set of rays is the union of those rays that saturate, of those that satisfy and of a set
of rays such that each of them
In fact, if and
are not adjacent, the rank of the system composed by the constraints saturated by both
and
is different from
(see the previous proposition) or neither
nor
are extreme rays. Since the new ray
is a combination of
and
, it saturates the same constraints saturated by both
and
. If the rank is less than
, the rank of the system composed by
(that is saturated by
) and by the constraints of
saturated by
is less than
. It means that
is redundant (see Section Further Notation and Terminology). If neither
nor
are extreme rays, they belong to a 2-dimensional face containing exactly two extreme rays of
. These two adjacent rays build a ray equal to
and so
is redundant.
Definition at line 350 of file conversion.cc.
References Parma_Polyhedra_Library::Linear_System::add_pending_row(), Parma_Polyhedra_Library::Saturation_Matrix::add_row(), Parma_Polyhedra_Library::Scalar_Products::assign(), Parma_Polyhedra_Library::Coefficient_zero(), Parma_Polyhedra_Library::Saturation_Matrix::columns_erase_to_end(), Parma_Polyhedra_Library::Saturation_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::Saturation_Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Saturation_Matrix::num_rows(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Linear_Row::RAY_OR_POINT_OR_INEQUALITY, Parma_Polyhedra_Library::Saturation_Matrix::rows_erase_to_end(), Parma_Polyhedra_Library::Saturation_Row::set(), Parma_Polyhedra_Library::Linear_System::set_sorted(), Parma_Polyhedra_Library::Linear_Row::strong_normalize(), Parma_Polyhedra_Library::sub_mul_assign(), TEMP_INTEGER, Parma_Polyhedra_Library::Linear_System::topology(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
Referenced by add_and_minimize(), and minimize().
00354 { 00355 dimension_type source_num_rows = source.num_rows(); 00356 dimension_type dest_num_rows = dest.num_rows(); 00357 const dimension_type source_num_columns = source.num_columns(); 00358 const dimension_type dest_num_columns = dest.num_columns(); 00359 00360 // By construction, the number of columns of `sat' is the same as 00361 // the number of rows of `source'; also, the number of rows of `sat' 00362 // is the same as the number of rows of `dest'. 00363 assert(source_num_rows == sat.num_columns()); 00364 assert(dest_num_rows == sat.num_rows()); 00365 00366 // If `start > 0', then we are converting the pending constraints. 00367 assert(start == 0 || start == source.first_pending_row()); 00368 00369 // During the iteration on the constraints in `source' we may identify 00370 // constraints that are redundant: these have to be removed by swapping 00371 // the rows of `source', taking care not to compromise the sortedness 00372 // of the constraints that still have to be considered. 00373 // To this end, the following counter keeps the number of redundant 00374 // constraints seen so far, to be used as a displacement when swapping rows. 00375 dimension_type source_num_redundant = 0; 00376 00377 TEMP_INTEGER(normalized_sp_i); 00378 TEMP_INTEGER(normalized_sp_o); 00379 00380 // Converting the sub-system of `source' having rows with indexes 00381 // from `start' to the last one (i.e., `source_num_rows' - 1). 00382 for (dimension_type k = start; k < source_num_rows; ) { 00383 00384 // All the `source_num_redundant' redundant constraints identified so far 00385 // have consecutive indices starting from `k'. 00386 if (source_num_redundant > 0) 00387 // Let the next constraint have index `k'. 00388 // There is no need to swap the columns of `sat' (all zeroes). 00389 std::swap(source[k], source[k+source_num_redundant]); 00390 00391 Linear_Row& source_k = source[k]; 00392 00393 // Constraints and generators must have the same dimension, 00394 // otherwise the scalar product below will bomb. 00395 assert(source_num_columns == dest_num_columns); 00396 00397 // `scalar_prod[i]' will contain the scalar product 00398 // of the constraint `source_k' and the generator `dest[i]'. 00399 // This product is 0 iff the generator saturates the constraint. 00400 static std::vector<Coefficient> scalar_prod; 00401 const int needed_space = dest_num_rows - scalar_prod.size(); 00402 if (needed_space > 0) 00403 scalar_prod.insert(scalar_prod.end(), needed_space, Coefficient_zero()); 00404 // `index_non_zero' will indicate the first generator in `dest' 00405 // that does not saturate the constraint `source_k'. 00406 dimension_type index_non_zero = 0; 00407 for ( ; index_non_zero < dest_num_rows; ++index_non_zero) { 00408 Scalar_Products::assign(scalar_prod[index_non_zero], 00409 source_k, 00410 dest[index_non_zero]); 00411 if (scalar_prod[index_non_zero] != 0) 00412 // The generator does not saturate the constraint. 00413 break; 00414 #if REACTIVE_ABANDONING 00415 // Check if the client has requested abandoning all exponential 00416 // computations. If so, the exception specified by the client 00417 // is thrown now. 00418 maybe_abandon(); 00419 #endif 00420 } 00421 for (dimension_type i = index_non_zero + 1; i < dest_num_rows; ++i) { 00422 Scalar_Products::assign(scalar_prod[i], source_k, dest[i]); 00423 #if REACTIVE_ABANDONING 00424 maybe_abandon(); 00425 #endif 00426 } 00427 00428 // We first treat the case when `index_non_zero' is less than 00429 // `num_lines_or_equalities', i.e., when the generator that 00430 // does not saturate the constraint `source_k' is a line. 00431 // The other case (described later) is when all the lines 00432 // in `dest' (i.e., all the rows having indexes less than 00433 // `num_lines_or_equalities') do saturate the constraint. 00434 00435 if (index_non_zero < num_lines_or_equalities) { 00436 // Since the generator `dest[index_non_zero]' does not saturate 00437 // the constraint `source_k', it can no longer be a line 00438 // (see saturation rule in Section \ref prelims). 00439 // Therefore, we first transform it to a ray. 00440 dest[index_non_zero].set_is_ray_or_point_or_inequality(); 00441 // Of the two possible choices, we select the ray satisfying 00442 // the constraint (namely, the ray whose scalar product 00443 // with the constraint gives a positive result). 00444 if (scalar_prod[index_non_zero] < 0) { 00445 // The ray `dest[index_non_zero]' lies on the wrong half-space: 00446 // we change it to have the opposite direction. 00447 neg_assign(scalar_prod[index_non_zero]); 00448 for (dimension_type j = dest_num_columns; j-- > 0; ) 00449 neg_assign(dest[index_non_zero][j]); 00450 } 00451 // Having changed a line to a ray, we set `dest' to be a 00452 // non-sorted system, we decrement the number of lines of `dest' and, 00453 // if necessary, we move the new ray below all the remaining lines. 00454 dest.set_sorted(false); 00455 --num_lines_or_equalities; 00456 if (index_non_zero != num_lines_or_equalities) { 00457 std::swap(dest[index_non_zero], 00458 dest[num_lines_or_equalities]); 00459 std::swap(scalar_prod[index_non_zero], 00460 scalar_prod[num_lines_or_equalities]); 00461 } 00462 Linear_Row& dest_nle = dest[num_lines_or_equalities]; 00463 00464 // Computing the new lineality space. 00465 // Since each line must lie on the hyper-plane corresponding to 00466 // the constraint `source_k', the scalar product between 00467 // the line and the constraint must be 0. 00468 // This property already holds for the lines having indexes 00469 // between 0 and `index_non_zero' - 1. 00470 // We have to consider the remaining lines, having indexes 00471 // between `index_non_zero' and `num_lines_or_equalities' - 1. 00472 // Each line that does not saturate the constraint has to be 00473 // linearly combined with generator `dest_nle' so that the 00474 // resulting new line saturates the constraint. 00475 // Note that, by Observation 1 above, the resulting new line 00476 // will still saturate all the constraints that were saturated by 00477 // the old line. 00478 00479 Coefficient& scalar_prod_nle = scalar_prod[num_lines_or_equalities]; 00480 for (dimension_type 00481 i = index_non_zero; i < num_lines_or_equalities; ++i) { 00482 if (scalar_prod[i] != 0) { 00483 // The following fragment optimizes the computation of 00484 // 00485 // Coefficient scale = scalar_prod[i]; 00486 // scale.gcd_assign(scalar_prod_nle); 00487 // Coefficient normalized_sp_i = scalar_prod[i] / scale; 00488 // Coefficient normalized_sp_n = scalar_prod_nle / scale; 00489 // for (dimension_type c = dest_num_columns; c-- > 0; ) { 00490 // dest[i][c] *= normalized_sp_n; 00491 // dest[i][c] -= normalized_sp_i * dest_nle[c]; 00492 // } 00493 normalize2(scalar_prod[i], 00494 scalar_prod_nle, 00495 normalized_sp_i, 00496 normalized_sp_o); 00497 Linear_Row& dest_i = dest[i]; 00498 for (dimension_type c = dest_num_columns; c-- > 0; ) { 00499 Coefficient& dest_i_c = dest_i[c]; 00500 dest_i_c *= normalized_sp_o; 00501 sub_mul_assign(dest_i_c, normalized_sp_i, dest_nle[c]); 00502 } 00503 dest_i.strong_normalize(); 00504 scalar_prod[i] = 0; 00505 // `dest' has already been set as non-sorted. 00506 } 00507 } 00508 00509 // Computing the new pointed cone. 00510 // Similarly to what we have done during the computation of 00511 // the lineality space, we consider all the remaining rays 00512 // (having indexes strictly greater than `num_lines_or_equalities') 00513 // that do not saturate the constraint `source_k'. These rays 00514 // are positively combined with the ray `dest_nle' so that the 00515 // resulting new rays saturate the constraint. 00516 for (dimension_type 00517 i = num_lines_or_equalities + 1; i < dest_num_rows; ++i) { 00518 if (scalar_prod[i] != 0) { 00519 // The following fragment optimizes the computation of 00520 // 00521 // Coefficient scale = scalar_prod[i]; 00522 // scale.gcd_assign(scalar_prod_nle); 00523 // Coefficient normalized_sp_i = scalar_prod[i] / scale; 00524 // Coefficient normalized_sp_n = scalar_prod_nle / scale; 00525 // for (dimension_type c = dest_num_columns; c-- > 0; ) { 00526 // dest[i][c] *= normalized_sp_n; 00527 // dest[i][c] -= normalized_sp_i * dest_nle[c]; 00528 // } 00529 normalize2(scalar_prod[i], 00530 scalar_prod_nle, 00531 normalized_sp_i, 00532 normalized_sp_o); 00533 Linear_Row& dest_i = dest[i]; 00534 for (dimension_type c = dest_num_columns; c-- > 0; ) { 00535 Coefficient& dest_i_c = dest_i[c]; 00536 dest_i_c *= normalized_sp_o; 00537 sub_mul_assign(dest_i_c, normalized_sp_i, dest_nle[c]); 00538 } 00539 dest_i.strong_normalize(); 00540 scalar_prod[i] = 0; 00541 // `dest' has already been set as non-sorted. 00542 } 00543 #if REACTIVE_ABANDONING 00544 maybe_abandon(); 00545 #endif 00546 } 00547 // Since the `scalar_prod_nle' is positive (by construction), it 00548 // does not saturate the constraint `source_k'. Therefore, if 00549 // the constraint is an inequality, we set to 1 the 00550 // corresponding element of `sat' ... 00551 Saturation_Row& sat_nle = sat[num_lines_or_equalities]; 00552 if (source_k.is_ray_or_point_or_inequality()) 00553 sat_nle.set(k); 00554 // ... otherwise, the constraint is an equality which is 00555 // violated by the generator `dest_nle': the generator has to be 00556 // removed from `dest'. 00557 else { 00558 --dest_num_rows; 00559 std::swap(dest_nle, dest[dest_num_rows]); 00560 std::swap(scalar_prod_nle, scalar_prod[dest_num_rows]); 00561 std::swap(sat_nle, sat[dest_num_rows]); 00562 // `dest' has already been set as non-sorted. 00563 } 00564 // We continue with the next constraint. 00565 ++k; 00566 } 00567 // Here we have `index_non_zero' >= `num_lines_or_equalities', 00568 // so that all the lines in `dest' saturate the constraint `source_k'. 00569 else { 00570 // First, we reorder the generators in `dest' as follows: 00571 // -# all the lines should have indexes between 0 and 00572 // `num_lines_or_equalities' - 1 (this already holds); 00573 // -# all the rays that saturate the constraint should have 00574 // indexes between `num_lines_or_equalities' and 00575 // `lines_or_equal_bound' - 1; these rays form the set Q=. 00576 // -# all the rays that have a positive scalar product with the 00577 // constraint should have indexes between `lines_or_equal_bound' 00578 // and `sup_bound' - 1; these rays form the set Q+. 00579 // -# all the rays that have a negative scalar product with the 00580 // constraint should have indexes between `sup_bound' and 00581 // `dest_num_rows' - 1; these rays form the set Q-. 00582 dimension_type lines_or_equal_bound = num_lines_or_equalities; 00583 dimension_type inf_bound = dest_num_rows; 00584 // While we find saturating generators, we simply increment 00585 // `lines_or_equal_bound'. 00586 while (inf_bound > lines_or_equal_bound 00587 && scalar_prod[lines_or_equal_bound] == 0) 00588 ++lines_or_equal_bound; 00589 dimension_type sup_bound = lines_or_equal_bound; 00590 while (inf_bound > sup_bound) { 00591 const int sp_sign = sgn(scalar_prod[sup_bound]); 00592 if (sp_sign == 0) { 00593 // This generator has to be moved in Q=. 00594 std::swap(dest[sup_bound], dest[lines_or_equal_bound]); 00595 std::swap(scalar_prod[sup_bound], scalar_prod[lines_or_equal_bound]); 00596 std::swap(sat[sup_bound], sat[lines_or_equal_bound]); 00597 ++lines_or_equal_bound; 00598 ++sup_bound; 00599 dest.set_sorted(false); 00600 } 00601 else if (sp_sign < 0) { 00602 // This generator has to be moved in Q-. 00603 --inf_bound; 00604 std::swap(dest[sup_bound], dest[inf_bound]); 00605 std::swap(scalar_prod[sup_bound], scalar_prod[inf_bound]); 00606 std::swap(sat[sup_bound], sat[inf_bound]); 00607 dest.set_sorted(false); 00608 } 00609 else 00610 // sp_sign > 0: this generator has to be moved in Q+. 00611 ++sup_bound; 00612 } 00613 00614 if (sup_bound == dest_num_rows) { 00615 // Here the set Q- is empty. 00616 // If the constraint is an inequality, then all the generators 00617 // in Q= and Q+ satisfy the constraint. The constraint is redundant 00618 // and it can be safely removed from the constraint system. 00619 // This is why the `source' parameter is not declared `const'. 00620 if (source_k.is_ray_or_point_or_inequality()) { 00621 ++source_num_redundant; 00622 --source_num_rows; 00623 // NOTE: we continue with the next cycle of the loop 00624 // without incrementing the index `k', because: 00625 // -# either `k == source_num_rows', and we will exit the loop; 00626 // -# or, having increased `source_num_redundant', we will swap 00627 // in position `k' a constraint that still has to be examined. 00628 } 00629 else { 00630 // The constraint is an equality, so that all the generators 00631 // in Q+ violate it. Since the set Q- is empty, we can simply 00632 // remove from `dest' all the generators of Q+. 00633 dest_num_rows = lines_or_equal_bound; 00634 // We continue with the next constraint. 00635 ++k; 00636 } 00637 } 00638 else { 00639 // The set Q- is not empty, i.e., at least one generator 00640 // violates the constraint `source_k'. 00641 // We have to further distinguish two cases: 00642 if (sup_bound == num_lines_or_equalities) 00643 // The set Q+ is empty, so that all generators that satisfy 00644 // the constraint also saturate it. 00645 // We can simply remove from `dest' all the generators in Q-. 00646 dest_num_rows = sup_bound; 00647 else { 00648 // The sets Q+ and Q- are both non-empty. 00649 // The generators of the new pointed cone are all those satisfying 00650 // the constraint `source_k' plus a set of new rays enjoying 00651 // the following properties: 00652 // -# they lie on the hyper-plane represented by the constraint 00653 // -# they are obtained as a positive combination of two 00654 // adjacent rays, the first taken from Q+ and the second 00655 // taken from Q-. 00656 00657 // The adjacency property is necessary to have an irredundant 00658 // set of new rays (see proposition 2). 00659 const dimension_type bound = dest_num_rows; 00660 00661 // In the following loop, 00662 // `i' runs through the generators in the set Q+ and 00663 // `j' runs through the generators in the set Q-. 00664 for (dimension_type i = lines_or_equal_bound; i < sup_bound; ++i) { 00665 for(dimension_type j = sup_bound; j < bound; ++j) { 00666 // Checking if generators `dest[i]' and `dest[j]' are adjacent. 00667 // If there exist another generator that saturates 00668 // all the constraints saturated by both `dest[i]' and 00669 // `dest[j]', then they are NOT adjacent. 00670 Saturation_Row new_satrow; 00671 assert(sat[i].last() == ULONG_MAX || sat[i].last() < k); 00672 assert(sat[j].last() == ULONG_MAX || sat[j].last() < k); 00673 // Being the union of `sat[i]' and `sat[j]', 00674 // `new_satrow' corresponds to a ray that saturates all the 00675 // constraints saturated by both `dest[i]' and `dest[j]'. 00676 set_union(sat[i], sat[j], new_satrow); 00677 00678 // Computing the number of common saturators. 00679 // NOTE: this number has to be less than `k' because 00680 // we are treating the `k'-th constraint. 00681 const dimension_type 00682 num_common_satur = k - new_satrow.count_ones(); 00683 00684 // Even before actually creating the new ray as a 00685 // positive combination of `dest[i]' and `dest[j]', 00686 // we exploit saturation information to check if 00687 // it can be an extremal ray. To this end, we refer 00688 // to the definition of a minimal proper face 00689 // (see comments in Polyhedron.defs.hh): 00690 // an extremal ray saturates at least `n' - `t' - 1 00691 // constraints, where `n' is the dimension of the space 00692 // and `t' is the dimension of the lineality space. 00693 // Since `n == source_num_columns - 1' and 00694 // `t == num_lines_or_equalities', we obtain that 00695 // an extremal ray saturates at least 00696 // `source_num_columns - num_lines_or_equalities - 2' 00697 // constraints. 00698 if (num_common_satur 00699 >= source_num_columns - num_lines_or_equalities - 2) { 00700 // The minimal proper face rule is satisfied. 00701 // Now we actually check for redundancy by computing 00702 // adjacency information. 00703 bool redundant = false; 00704 for (dimension_type 00705 l = num_lines_or_equalities; l < bound; ++l) 00706 if (l != i && l != j 00707 && subset_or_equal(sat[l], new_satrow)) { 00708 // Found another generator saturating all the 00709 // constraints saturated by both `dest[i]' and `dest[j]'. 00710 redundant = true; 00711 break; 00712 } 00713 if (!redundant) { 00714 // Adding the new ray to `dest' and the corresponding 00715 // saturation row to `sat'. 00716 if (dest_num_rows == dest.num_rows()) { 00717 // Make room for one more row. 00718 dest.add_pending_row(Linear_Row::Flags(dest.topology(), 00719 Linear_Row::RAY_OR_POINT_OR_INEQUALITY)); 00720 sat.add_row(new_satrow); 00721 } 00722 else 00723 sat[dest_num_rows] = new_satrow; 00724 Linear_Row& new_row = dest[dest_num_rows]; 00725 // The following fragment optimizes the computation of 00726 // 00727 // Coefficient scale = scalar_prod[i]; 00728 // scale.gcd_assign(scalar_prod[j]); 00729 // Coefficient normalized_sp_i = scalar_prod[i] / scale; 00730 // Coefficient normalized_sp_j = scalar_prod[j] / scale; 00731 // for (dimension_type c = dest_num_columns; c-- > 0; ) { 00732 // new_row[c] = normalized_sp_i * dest[j][c]; 00733 // new_row[c] -= normalized_sp_j * dest[i][c]; 00734 // } 00735 normalize2(scalar_prod[i], 00736 scalar_prod[j], 00737 normalized_sp_i, 00738 normalized_sp_o); 00739 for (dimension_type c = dest_num_columns; c-- > 0; ) { 00740 Coefficient& new_row_c = new_row[c]; 00741 new_row_c = normalized_sp_i * dest[j][c]; 00742 sub_mul_assign(new_row_c, normalized_sp_o, dest[i][c]); 00743 } 00744 new_row.strong_normalize(); 00745 // Since we added a new generator to `dest', 00746 // we also add a new element to `scalar_prod'; 00747 // by construction, the new ray lies on the hyper-plane 00748 // represented by the constraint `source_k'. 00749 // Thus, the added scalar product is 0. 00750 assert(scalar_prod.size() >= dest_num_rows); 00751 if (scalar_prod.size() <= dest_num_rows) 00752 scalar_prod.push_back(Coefficient_zero()); 00753 else 00754 scalar_prod[dest_num_rows] = Coefficient_zero(); 00755 // Increment the number of generators. 00756 ++dest_num_rows; 00757 } 00758 } 00759 } 00760 #if REACTIVE_ABANDONING 00761 maybe_abandon(); 00762 #endif 00763 } 00764 // Now we substitute the rays in Q- (i.e., the rays violating 00765 // the constraint) with the newly added rays. 00766 dimension_type j; 00767 if (source_k.is_ray_or_point_or_inequality()) { 00768 // The constraint is an inequality: 00769 // the violating generators are those in Q-. 00770 j = sup_bound; 00771 // For all the generators in Q+, set to 1 the corresponding 00772 // entry for the constraint `source_k' in the saturation matrix. 00773 for (dimension_type l = lines_or_equal_bound; l < sup_bound; ++l) 00774 sat[l].set(k); 00775 } 00776 else 00777 // The constraint is an equality: 00778 // the violating generators are those in the union of Q+ and Q-. 00779 j = lines_or_equal_bound; 00780 00781 // Swapping the newly added rays 00782 // (index `i' running through `dest_num_rows - 1' down-to `bound') 00783 // with the generators violating the constraint 00784 // (index `j' running through `j' up-to `bound - 1'). 00785 dimension_type i = dest_num_rows; 00786 while (j < bound && i > bound) { 00787 --i; 00788 std::swap(dest[i], dest[j]); 00789 std::swap(scalar_prod[i], scalar_prod[j]); 00790 std::swap(sat[i], sat[j]); 00791 ++j; 00792 dest.set_sorted(false); 00793 } 00794 // Setting the number of generators in `dest': 00795 // - if the number of generators violating the constraint 00796 // is less than or equal to the number of the newly added 00797 // generators, we assign `i' to `dest_num_rows' because 00798 // all generators above this index are significant; 00799 // - otherwise, we assign `j' to `dest_num_rows' because 00800 // all generators below index `j-1' violates the constraint. 00801 dest_num_rows = (j == bound) ? i : j; 00802 } 00803 // We continue with the next constraint. 00804 ++k; 00805 } 00806 } 00807 #if !REACTIVE_ABANDONING 00808 // Check if the client has requested abandoning all exponential 00809 // computations. If so, the exception specified by the client 00810 // is thrown now. 00811 maybe_abandon(); 00812 #endif 00813 } 00814 00815 // We may have identified some redundant constraints in `source', 00816 // which have been swapped at the end of the system. 00817 if (source_num_redundant > 0) { 00818 assert(source_num_redundant == source.num_rows() - source_num_rows); 00819 source.erase_to_end(source_num_rows); 00820 sat.columns_erase_to_end(source_num_rows); 00821 } 00822 // If `start == 0', then `source' was sorted and remained so. 00823 // If otherwise `start > 0', then the two sub-system made by the 00824 // non-pending rows and the pending rows, respectively, were both sorted. 00825 // Thus, the overall system is sorted if and only if either 00826 // `start == source_num_rows' (i.e., the second sub-system is empty) 00827 // or the row ordering holds for the two rows at the boundary between 00828 // the two sub-systems. 00829 if (start > 0 && start < source_num_rows) 00830 source.set_sorted(compare(source[start - 1], source[start]) <= 0); 00831 // There are no longer pending constraints in `source'. 00832 source.unset_pending_rows(); 00833 00834 // We may have identified some redundant rays in `dest', 00835 // which have been swapped at the end of the system. 00836 if (dest_num_rows < dest.num_rows()) { 00837 dest.erase_to_end(dest_num_rows); 00838 // Be careful: we might have erased some of the non-pending rows. 00839 if (dest.first_pending_row() > dest_num_rows) 00840 dest.unset_pending_rows(); 00841 sat.rows_erase_to_end(dest_num_rows); 00842 } 00843 if (dest.is_sorted()) 00844 // If the non-pending generators in `dest' are still declared to be 00845 // sorted, then we have to also check for the sortedness of the 00846 // pending generators. 00847 for (dimension_type i = dest.first_pending_row(); i < dest_num_rows; ++i) 00848 if (compare(dest[i - 1], dest[i]) > 0) { 00849 dest.set_sorted(false); 00850 break; 00851 } 00852 // There are no pending generators in `dest'. 00853 dest.unset_pending_rows(); 00854 00855 return num_lines_or_equalities; 00856 }
int Parma_Polyhedra_Library::Polyhedron::simplify | ( | Linear_System & | sys, | |
Saturation_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 82 of file simplify.cc.
References Parma_Polyhedra_Library::Linear_System::back_substitute(), empty, Parma_Polyhedra_Library::Matrix::erase_to_end(), Parma_Polyhedra_Library::Linear_System::gauss(), Parma_Polyhedra_Library::Saturation_Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_columns(), Parma_Polyhedra_Library::Matrix::num_rows(), Parma_Polyhedra_Library::Linear_System::OK(), Parma_Polyhedra_Library::Saturation_Matrix::rows_erase_to_end(), Parma_Polyhedra_Library::Linear_System::set_sorted(), Parma_Polyhedra_Library::Linear_System::sign_normalize(), and Parma_Polyhedra_Library::Linear_System::unset_pending_rows().
Referenced by add_and_minimize(), and minimize().
00082 { 00083 // This method is only applied to a well-formed system `sys'. 00084 assert(sys.OK(true)); 00085 00086 dimension_type num_rows = sys.num_rows(); 00087 const dimension_type num_columns = sys.num_columns(); 00088 const dimension_type num_cols_sat = sat.num_columns(); 00089 00090 // Looking for the first inequality in `sys'. 00091 dimension_type num_lines_or_equalities = 0; 00092 while (num_lines_or_equalities < num_rows 00093 && sys[num_lines_or_equalities].is_line_or_equality()) 00094 ++num_lines_or_equalities; 00095 00096 // `num_saturators[i]' will contain the number of generators 00097 // that saturate the constraint `sys[i]'. 00098 static std::vector<dimension_type> num_saturators; 00099 num_saturators.reserve(num_rows); 00100 00101 // Computing the number of saturators for each inequality, 00102 // possibly identifying and swapping those that happen to be 00103 // equalities (see Proposition above). 00104 for (dimension_type i = num_lines_or_equalities; i < num_rows; ++i) { 00105 if (sat[i].empty()) { 00106 // The constraint `sys[i]' is saturated by all the generators. 00107 // Thus, either it is already an equality or it can be transformed 00108 // to an equality (see Proposition above). 00109 sys[i].set_is_line_or_equality(); 00110 // Note: simple normalization already holds. 00111 sys[i].sign_normalize(); 00112 // We also move it just after all the other equalities, 00113 // so that system `sys' keeps its partial sortedness. 00114 if (i != num_lines_or_equalities) { 00115 std::swap(sys[i], sys[num_lines_or_equalities]); 00116 std::swap(sat[i], sat[num_lines_or_equalities]); 00117 std::swap(num_saturators[i], num_saturators[num_lines_or_equalities]); 00118 } 00119 ++num_lines_or_equalities; 00120 // `sys' is no longer sorted. 00121 sys.set_sorted(false); 00122 } 00123 else 00124 // There exists a generator which does not saturate `sys[i]', 00125 // so that `sys[i]' is indeed an inequality. 00126 // We store the number of its saturators. 00127 num_saturators[i] = num_cols_sat - sat[i].count_ones(); 00128 } 00129 00130 // At this point, all the equalities of `sys' (included those 00131 // inequalities that we just transformed to equalities) have 00132 // indexes between 0 and `num_lines_or_equalities' - 1, 00133 // which is the property needed by method gauss(). 00134 // We can simplify the system of equalities, obtaining the rank 00135 // of `sys' as result. 00136 const dimension_type rank = sys.gauss(num_lines_or_equalities); 00137 00138 // Now the irredundant equalities of `sys' have indexes from 0 00139 // to `rank' - 1, whereas the equalities having indexes from `rank' 00140 // to `num_lines_or_equalities' - 1 are all redundant. 00141 // (The inequalities in `sys' have been left untouched.) 00142 // The rows containing equalities are not sorted. 00143 00144 if (rank < num_lines_or_equalities) { 00145 // We identified some redundant equalities. 00146 // Moving them at the bottom of `sys': 00147 // - index `redundant' runs through the redundant equalities 00148 // - index `erasing' identifies the first row that should 00149 // be erased after this loop. 00150 // Note that we exit the loop either because we have moved all 00151 // redundant equalities or because we have moved all the 00152 // inequalities. 00153 for (dimension_type redundant = rank, 00154 erasing = num_rows; 00155 redundant < num_lines_or_equalities 00156 && erasing > num_lines_or_equalities; 00157 ) { 00158 --erasing; 00159 std::swap(sys[redundant], sys[erasing]); 00160 std::swap(sat[redundant], sat[erasing]); 00161 std::swap(num_saturators[redundant], num_saturators[erasing]); 00162 sys.set_sorted(false); 00163 ++redundant; 00164 } 00165 // Adjusting the value of `num_rows' to the number of meaningful 00166 // rows of `sys': `num_lines_or_equalities' - `rank' is the number of 00167 // redundant equalities moved to the bottom of `sys', which are 00168 // no longer meaningful. 00169 num_rows -= num_lines_or_equalities - rank; 00170 // Adjusting the value of `num_lines_or_equalities'. 00171 num_lines_or_equalities = rank; 00172 } 00173 00174 // Now we use the definition of redundancy (given in the Introduction) 00175 // to remove redundant inequalities. 00176 00177 // First we check the saturation rule, which provides a necessary 00178 // condition for an inequality to be irredundant (i.e., it provides 00179 // a sufficient condition for identifying redundant inequalities). 00180 // Let 00181 // num_saturators[i] = num_sat_lines[i] + num_sat_rays_or_points[i]; 00182 // dim_lin_space = num_irred_lines; 00183 // dim_ray_space 00184 // = dim_vector_space - num_irred_equalities - dim_lin_space 00185 // = num_columns - 1 - num_lines_or_equalities - dim_lin_space; 00186 // min_sat_rays_or_points = dim_ray_space. 00187 // 00188 // An inequality saturated by less than `dim_ray_space' _rays/points_ 00189 // is redundant. Thus we have the implication 00190 // 00191 // (num_saturators[i] - num_sat_lines[i] < dim_ray_space) 00192 // ==> 00193 // redundant(sys[i]). 00194 // 00195 // Moreover, since every line saturates all inequalities, we also have 00196 // dim_lin_space = num_sat_lines[i] 00197 // so that we can rewrite the condition above as follows: 00198 // 00199 // (num_saturators[i] < num_columns - num_lines_or_equalities - 1) 00200 // ==> 00201 // redundant(sys[i]). 00202 // 00203 const dimension_type min_saturators 00204 = num_columns - num_lines_or_equalities - 1; 00205 for (dimension_type i = num_lines_or_equalities; i < num_rows; ) { 00206 if (num_saturators[i] < min_saturators) { 00207 // The inequality `sys[i]' is redundant. 00208 --num_rows; 00209 std::swap(sys[i], sys[num_rows]); 00210 std::swap(sat[i], sat[num_rows]); 00211 std::swap(num_saturators[i], num_saturators[num_rows]); 00212 sys.set_sorted(false); 00213 } 00214 else 00215 ++i; 00216 } 00217 00218 // Now we check the independence rule. 00219 for (dimension_type i = num_lines_or_equalities; i < num_rows; ) { 00220 bool redundant = false; 00221 // NOTE: in the inner loop, index `j' runs through _all_ the 00222 // inequalities and we do not test if `sat[i]' is strictly 00223 // contained into `sat[j]'. Experimentation has shown that this 00224 // is faster than having `j' only run through the indexes greater 00225 // than `i' and also doing the test `strict_subset(sat[i], 00226 // sat[k])'. 00227 for (dimension_type j = num_lines_or_equalities; j < num_rows; ) { 00228 if (i == j) 00229 // We want to compare different rows of `sys'. 00230 ++j; 00231 else { 00232 // Let us recall that each generator lies on a facet of the 00233 // polyhedron (see the Introduction). 00234 // Given two constraints `c_1' and `c_2', if there are `m' 00235 // generators lying on the hyper-plane corresponding to `c_1', 00236 // the same `m' generators lie on the hyper-plane 00237 // corresponding to `c_2', too, and there is another one lying 00238 // on the latter but not on the former, then `c_2' is more 00239 // restrictive than `c_1', i.e., `c_1' is redundant. 00240 bool strict_subset; 00241 if (subset_or_equal(sat[j], sat[i], strict_subset)) 00242 if (strict_subset) { 00243 // All the saturators of the inequality `sys[i]' are 00244 // saturators of the inequality `sys[j]' too, 00245 // and there exists at least one saturator of `sys[j]' 00246 // which is not a saturator of `sys[i]'. 00247 // It follows that inequality `sys[i]' is redundant. 00248 redundant = true; 00249 break; 00250 } 00251 else { 00252 // We have `sat[j] == sat[i]'. Hence inequalities 00253 // `sys[i]' and `sys[j]' are saturated by the same set of 00254 // generators. Then we can remove either one of the two 00255 // inequalities: we remove `sys[j]'. 00256 --num_rows; 00257 std::swap(sys[j], sys[num_rows]); 00258 std::swap(sat[j], sat[num_rows]); 00259 std::swap(num_saturators[j], num_saturators[num_rows]); 00260 sys.set_sorted(false); 00261 } 00262 else 00263 // If we reach this point then we know that `sat[i]' does 00264 // not contain (and is different from) `sat[j]', so that 00265 // `sys[i]' is not made redundant by inequality `sys[j]'. 00266 ++j; 00267 } 00268 } 00269 if (redundant) { 00270 // The inequality `sys[i]' is redundant. 00271 --num_rows; 00272 std::swap(sys[i], sys[num_rows]); 00273 std::swap(sat[i], sat[num_rows]); 00274 std::swap(num_saturators[i], num_saturators[num_rows]); 00275 sys.set_sorted(false); 00276 } 00277 else 00278 // The inequality `sys[i]' is not redundant. 00279 ++i; 00280 } 00281 00282 // Here we physically remove the redundant inequalities previously 00283 // moved to the bottom of `sys' and the corresponding `sat' rows. 00284 sys.erase_to_end(num_rows); 00285 sys.unset_pending_rows(); 00286 sat.rows_erase_to_end(num_rows); 00287 // At this point the first `num_lines_or_equalities' rows of 'sys' 00288 // represent the irredundant equalities, while the remaining rows 00289 // (i.e., those having indexes from `num_lines_or_equalities' to 00290 // `num_rows' - 1) represent the irredundant inequalities. 00291 #ifndef NDEBUG 00292 // Check if the flag is set (that of the equalities is already set). 00293 for (dimension_type i = num_lines_or_equalities; i < num_rows; ++i) 00294 assert(sys[i].is_ray_or_point_or_inequality()); 00295 #endif 00296 00297 // Finally, since now the sub-system (of `sys') of the irredundant 00298 // equalities is in triangular form, we back substitute each 00299 // variables with the expression obtained considering the equalities 00300 // starting from the last one. 00301 sys.back_substitute(num_lines_or_equalities); 00302 00303 // The returned value is the number of irredundant equalities i.e., 00304 // the rank of the sub-system of `sys' containing only equalities. 00305 // (See the Introduction for definition of lineality space dimension.) 00306 return num_lines_or_equalities; 00307 }
void Parma_Polyhedra_Library::Polyhedron::throw_runtime_error | ( | const char * | method | ) | const [protected] |
Definition at line 1336 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed().
Referenced by add_generator().
01336 { 01337 std::ostringstream s; 01338 s << "PPL::"; 01339 if (is_necessarily_closed()) 01340 s << "C_"; 01341 else 01342 s << "NNC_"; 01343 s << "Polyhedron::" << method << "." << std::endl; 01344 throw std::runtime_error(s.str()); 01345 }
void Parma_Polyhedra_Library::Polyhedron::throw_invalid_argument | ( | const char * | method, | |
const char * | reason | |||
) | const [protected] |
Definition at line 1348 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed().
Referenced by affine_image(), affine_preimage(), bounded_affine_image(), bounded_affine_preimage(), fold_space_dimensions(), generalized_affine_image(), generalized_affine_preimage(), map_space_dimensions(), and Polyhedron().
01349 { 01350 std::ostringstream s; 01351 s << "PPL::"; 01352 if (is_necessarily_closed()) 01353 s << "C_"; 01354 else 01355 s << "NNC_"; 01356 s << "Polyhedron::" << method << ":" << std::endl 01357 << reason << "."; 01358 throw std::invalid_argument(s.str()); 01359 }
void Parma_Polyhedra_Library::Polyhedron::throw_topology_incompatible | ( | const char * | method, | |
const char * | ph_name, | |||
const Polyhedron & | ph | |||
) | const [protected] |
Definition at line 1362 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed().
Referenced by add_constraint(), add_generator(), add_recycled_constraints(), add_recycled_constraints_and_minimize(), add_recycled_generators(), add_recycled_generators_and_minimize(), BHRZ03_widening_assign(), concatenate_assign(), contains(), H79_widening_assign(), intersection_assign(), intersection_assign_and_minimize(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), poly_difference_assign(), poly_hull_assign(), poly_hull_assign_and_minimize(), Polyhedron(), swap(), and time_elapse_assign().
01364 { 01365 std::ostringstream s; 01366 s << "PPL::"; 01367 if (is_necessarily_closed()) 01368 s << "C_"; 01369 else 01370 s << "NNC_"; 01371 s << "Polyhedron::" << method << ":" << std::endl 01372 << ph_name << " is a "; 01373 if (ph.is_necessarily_closed()) 01374 s << "C_"; 01375 else 01376 s << "NNC_"; 01377 s << "Polyhedron." << std::endl; 01378 throw std::invalid_argument(s.str()); 01379 }
void Parma_Polyhedra_Library::Polyhedron::throw_topology_incompatible | ( | const char * | method, | |
const char * | c_name, | |||
const Constraint & | c | |||
) | const [protected] |
Definition at line 1382 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed().
01384 { 01385 assert(is_necessarily_closed()); 01386 std::ostringstream s; 01387 s << "PPL::C_Polyhedron::" << method << ":" << std::endl 01388 << c_name << " is a strict inequality."; 01389 throw std::invalid_argument(s.str()); 01390 }
void Parma_Polyhedra_Library::Polyhedron::throw_topology_incompatible | ( | const char * | method, | |
const char * | g_name, | |||
const Generator & | g | |||
) | const [protected] |
Definition at line 1393 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed().
01395 { 01396 assert(is_necessarily_closed()); 01397 std::ostringstream s; 01398 s << "PPL::C_Polyhedron::" << method << ":" << std::endl 01399 << g_name << " is a closure point."; 01400 throw std::invalid_argument(s.str()); 01401 }
void Parma_Polyhedra_Library::Polyhedron::throw_topology_incompatible | ( | const char * | method, | |
const char * | cs_name, | |||
const Constraint_System & | cs | |||
) | const [protected] |
Definition at line 1404 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed().
01406 { 01407 assert(is_necessarily_closed()); 01408 std::ostringstream s; 01409 s << "PPL::C_Polyhedron::" << method << ":" << std::endl 01410 << cs_name << " contains strict inequalities."; 01411 throw std::invalid_argument(s.str()); 01412 }
void Parma_Polyhedra_Library::Polyhedron::throw_topology_incompatible | ( | const char * | method, | |
const char * | gs_name, | |||
const Generator_System & | gs | |||
) | const [protected] |
Definition at line 1415 of file Polyhedron_nonpublic.cc.
01417 { 01418 std::ostringstream s; 01419 s << "PPL::C_Polyhedron::" << method << ":" << std::endl 01420 << gs_name << " contains closure points."; 01421 throw std::invalid_argument(s.str()); 01422 }
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
const char * | other_name, | |||
dimension_type | other_dim | |||
) | const [protected] |
Definition at line 1425 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_constraints_and_minimize(), add_recycled_generators(), add_recycled_generators_and_minimize(), affine_image(), affine_preimage(), BHRZ03_widening_assign(), bounded_affine_image(), bounded_affine_preimage(), bounds(), contains(), expand_space_dimension(), fold_space_dimensions(), generalized_affine_image(), generalized_affine_preimage(), H79_widening_assign(), intersection_assign(), intersection_assign_and_minimize(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), max_min(), poly_difference_assign(), poly_hull_assign(), poly_hull_assign_and_minimize(), relation_with(), remove_higher_space_dimensions(), remove_space_dimensions(), throw_dimension_incompatible(), and time_elapse_assign().
01427 { 01428 std::ostringstream s; 01429 s << "PPL::" 01430 << (is_necessarily_closed() ? "C_" : "NNC_") 01431 << "Polyhedron::" << method << ":\n" 01432 << "this->space_dimension() == " << space_dimension() << ", " 01433 << other_name << ".space_dimension() == " << other_dim << "."; 01434 throw std::invalid_argument(s.str()); 01435 }
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
const char * | ph_name, | |||
const Polyhedron & | ph | |||
) | const [protected] |
Definition at line 1438 of file Polyhedron_nonpublic.cc.
References space_dimension(), and throw_dimension_incompatible().
01440 { 01441 throw_dimension_incompatible(method, ph_name, ph.space_dimension()); 01442 }
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
const char * | e_name, | |||
const Linear_Expression & | e | |||
) | const [protected] |
Definition at line 1445 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Linear_Expression::space_dimension(), and throw_dimension_incompatible().
01447 { 01448 throw_dimension_incompatible(method, e_name, e.space_dimension()); 01449 }
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
const char * | c_name, | |||
const Constraint & | c | |||
) | const [protected] |
Definition at line 1452 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Constraint::space_dimension(), and throw_dimension_incompatible().
01454 { 01455 throw_dimension_incompatible(method, c_name, c.space_dimension()); 01456 }
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
const char * | g_name, | |||
const Generator & | g | |||
) | const [protected] |
Definition at line 1459 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Generator::space_dimension(), and throw_dimension_incompatible().
01461 { 01462 throw_dimension_incompatible(method, g_name, g.space_dimension()); 01463 }
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
const char * | cg_name, | |||
const Congruence & | cg | |||
) | const [protected] |
Definition at line 1466 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Congruence::space_dimension(), and throw_dimension_incompatible().
01468 { 01469 throw_dimension_incompatible(method, cg_name, cg.space_dimension()); 01470 }
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
const char * | cs_name, | |||
const Constraint_System & | cs | |||
) | const [protected] |
Definition at line 1473 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Constraint_System::space_dimension(), and throw_dimension_incompatible().
01475 { 01476 throw_dimension_incompatible(method, cs_name, cs.space_dimension()); 01477 }
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
const char * | gs_name, | |||
const Generator_System & | gs | |||
) | const [protected] |
Definition at line 1480 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Generator_System::space_dimension(), and throw_dimension_incompatible().
01482 { 01483 throw_dimension_incompatible(method, gs_name, gs.space_dimension()); 01484 }
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
const char * | cgs_name, | |||
const Congruence_System & | cgs | |||
) | const [protected] |
Definition at line 1487 of file Polyhedron_nonpublic.cc.
References Parma_Polyhedra_Library::Congruence_System::space_dimension(), and throw_dimension_incompatible().
01489 { 01490 throw_dimension_incompatible(method, cgs_name, cgs.space_dimension()); 01491 }
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
const char * | var_name, | |||
const Variable | var | |||
) | const [protected] |
Definition at line 1494 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed(), Parma_Polyhedra_Library::Variable::space_dimension(), and space_dimension().
01496 { 01497 std::ostringstream s; 01498 s << "PPL::"; 01499 if (is_necessarily_closed()) 01500 s << "C_"; 01501 else 01502 s << "NNC_"; 01503 s << "Polyhedron::" << method << ":" << std::endl 01504 << "this->space_dimension() == " << space_dimension() << ", " 01505 << var_name << ".space_dimension() == " << var.space_dimension() << "."; 01506 throw std::invalid_argument(s.str()); 01507 }
void Parma_Polyhedra_Library::Polyhedron::throw_dimension_incompatible | ( | const char * | method, | |
dimension_type | required_space_dim | |||
) | const [protected] |
Definition at line 1511 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed(), and space_dimension().
01512 { 01513 std::ostringstream s; 01514 s << "PPL::"; 01515 if (is_necessarily_closed()) 01516 s << "C_"; 01517 else 01518 s << "NNC_"; 01519 s << "Polyhedron::" << method << ":" << std::endl 01520 << "this->space_dimension() == " << space_dimension() 01521 << ", required space dimension == " << required_space_dim << "."; 01522 throw std::invalid_argument(s.str()); 01523 }
void Parma_Polyhedra_Library::Polyhedron::throw_space_dimension_overflow | ( | Topology | topol, | |
const char * | method, | |||
const char * | reason | |||
) | [static, protected] |
Definition at line 1526 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().
01528 { 01529 std::ostringstream s; 01530 s << "PPL::"; 01531 if (topol == NECESSARILY_CLOSED) 01532 s << "C_"; 01533 else 01534 s << "NNC_"; 01535 s << "Polyhedron::" << method << ":" << std::endl 01536 << reason << "."; 01537 throw std::length_error(s.str()); 01538 }
void Parma_Polyhedra_Library::Polyhedron::throw_invalid_generator | ( | const char * | method, | |
const char * | g_name | |||
) | const [protected] |
Definition at line 1541 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed().
Referenced by add_generator().
01542 { 01543 std::ostringstream s; 01544 s << "PPL::"; 01545 if (is_necessarily_closed()) 01546 s << "C_"; 01547 else 01548 s << "NNC_"; 01549 s << "Polyhedron::" << method << ":" << std::endl 01550 << "*this is an empty polyhedron and " 01551 << g_name << " is not a point."; 01552 throw std::invalid_argument(s.str()); 01553 }
void Parma_Polyhedra_Library::Polyhedron::throw_invalid_generators | ( | const char * | method, | |
const char * | gs_name | |||
) | const [protected] |
Definition at line 1556 of file Polyhedron_nonpublic.cc.
References is_necessarily_closed().
Referenced by add_recycled_generators(), add_recycled_generators_and_minimize(), and Polyhedron().
01557 { 01558 std::ostringstream s; 01559 s << "PPL::"; 01560 if (is_necessarily_closed()) 01561 s << "C_"; 01562 else 01563 s << "NNC_"; 01564 s << "Polyhedron::" << method << ":" << std::endl 01565 << "*this is an empty polyhedron and" << std::endl 01566 << "the non-empty generator system " << gs_name << " contains no points."; 01567 throw std::invalid_argument(s.str()); 01568 }
friend class Parma_Polyhedra_Library::BD_Shape [friend] |
Definition at line 2568 of file Polyhedron.defs.hh.
friend class Parma_Polyhedra_Library::BHRZ03_Certificate [friend] |
Definition at line 2569 of file Polyhedron.defs.hh.
friend class Parma_Polyhedra_Library::H79_Certificate [friend] |
Definition at line 2570 of file Polyhedron.defs.hh.
bool operator== | ( | const Polyhedron & | x, | |
const Polyhedron & | y | |||
) | [friend] |
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 2959 of file Polyhedron_public.cc.
References is_empty(), and minimized_constraints().
02959 { 02960 if (ph.is_empty()) 02961 s << "false"; 02962 else 02963 s << ph.minimized_constraints(); 02964 return s; 02965 }
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 332 of file Polyhedron.inlines.hh.
void swap | ( | Parma_Polyhedra_Library::Polyhedron & | x, | |
Parma_Polyhedra_Library::Polyhedron & | y | |||
) | [related] |
Specializes std::swap
.
Definition at line 100 of file Polyhedron.inlines.hh.
References swap().
00101 { 00102 x.swap(y); 00103 }
bool poly_hull_assign_if_exact | ( | PH & | p, | |
const PH & | q | |||
) | [related] |
If the poly-hull of p
and q
is exact it is assigned to p
and true
is returned, otherwise false
is returned.
Definition at line 51 of file algorithms.hh.
References Parma_Polyhedra_Library::Powerset< Parma_Polyhedra_Library::Determinate< PH > >::begin(), contains(), and Parma_Polyhedra_Library::Powerset< Parma_Polyhedra_Library::Determinate< PH > >::end().
00051 { 00052 PH phull = p; 00053 NNC_Polyhedron nnc_p(p); 00054 phull.poly_hull_assign(q); 00055 std::pair<PH, Polyhedra_Powerset<NNC_Polyhedron> > 00056 partition = linear_partition(q, phull); 00057 const Polyhedra_Powerset<NNC_Polyhedron>& s = partition.second; 00058 typedef Polyhedra_Powerset<NNC_Polyhedron>::const_iterator iter; 00059 for (iter i = s.begin(), s_end = s.end(); i != s_end; ++i) 00060 // The polyhedral hull is exact if and only if all the elements 00061 // of the partition of the polyhedral hull of `p' and `q' with 00062 // respect to `q' are included in `p' 00063 if (!nnc_p.contains(i->element())) 00064 return false; 00065 p = phull; 00066 return true; 00067 }
The system of constraints.
Definition at line 1843 of file Polyhedron.defs.hh.
Referenced by add_constraint(), add_recycled_constraints(), add_recycled_constraints_and_minimize(), add_recycled_generators_and_minimize(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_image(), affine_preimage(), ascii_dump(), ascii_load(), Parma_Polyhedra_Library::BD_Shape< T >::BD_Shape(), BHRZ03_combining_constraints(), bounded_affine_preimage(), concatenate_assign(), constraints(), external_memory_in_bytes(), H79_widening_assign(), intersection_assign(), intersection_assign_and_minimize(), is_included_in(), is_necessarily_closed(), is_topologically_closed(), is_universe(), map_space_dimensions(), obtain_sorted_constraints(), obtain_sorted_constraints_with_sat_c(), OK(), operator=(), poly_hull_assign_and_minimize(), Polyhedron(), process_pending_constraints(), process_pending_generators(), quick_equivalence_test(), relation_with(), remove_higher_space_dimensions(), remove_pending_to_obtain_constraints(), remove_space_dimensions(), select_CH78_constraints(), select_H79_constraints(), set_empty(), set_zero_dim_univ(), shrink_bounding_box(), 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 1846 of file Polyhedron.defs.hh.
Referenced by add_generator(), add_recycled_constraints_and_minimize(), add_recycled_generators(), add_recycled_generators_and_minimize(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_image(), affine_preimage(), ascii_dump(), ascii_load(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), bounded_affine_preimage(), bounds(), concatenate_assign(), external_memory_in_bytes(), generalized_affine_image(), generators(), intersection_assign_and_minimize(), is_bounded(), is_topologically_closed(), is_universe(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), map_space_dimensions(), max_min(), obtain_sorted_generators(), obtain_sorted_generators_with_sat_g(), OK(), operator=(), poly_hull_assign(), poly_hull_assign_and_minimize(), Polyhedron(), process_pending_constraints(), process_pending_generators(), quick_equivalence_test(), relation_with(), remove_higher_space_dimensions(), remove_pending_to_obtain_generators(), remove_space_dimensions(), select_CH78_constraints(), select_H79_constraints(), set_empty(), set_zero_dim_univ(), shrink_bounding_box(), strongly_minimize_constraints(), strongly_minimize_generators(), swap(), time_elapse_assign(), topological_closure_assign(), update_constraints(), update_generators(), update_sat_c(), and update_sat_g().
The saturation matrix having constraints on its columns.
Definition at line 1849 of file Polyhedron.defs.hh.
Referenced by add_recycled_constraints_and_minimize(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), ascii_dump(), ascii_load(), concatenate_assign(), external_memory_in_bytes(), intersection_assign_and_minimize(), obtain_sorted_constraints(), obtain_sorted_constraints_with_sat_c(), obtain_sorted_generators(), obtain_sorted_generators_with_sat_g(), OK(), operator=(), Polyhedron(), process_pending_constraints(), process_pending_generators(), set_empty(), strongly_minimize_constraints(), strongly_minimize_generators(), swap(), update_constraints(), and update_sat_c().
The saturation matrix having generators on its columns.
Definition at line 1852 of file Polyhedron.defs.hh.
Referenced by add_recycled_generators_and_minimize(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), ascii_dump(), ascii_load(), concatenate_assign(), external_memory_in_bytes(), obtain_sorted_constraints(), obtain_sorted_constraints_with_sat_c(), obtain_sorted_generators(), obtain_sorted_generators_with_sat_g(), OK(), operator=(), poly_hull_assign_and_minimize(), Polyhedron(), process_pending_constraints(), process_pending_generators(), select_H79_constraints(), set_empty(), strongly_minimize_constraints(), strongly_minimize_generators(), swap(), update_generators(), and update_sat_g().
The status flags to keep track of the polyhedron's internal state.
Definition at line 2040 of file Polyhedron.defs.hh.
Referenced by add_generator(), add_recycled_constraints(), add_recycled_constraints_and_minimize(), add_recycled_generators(), add_recycled_generators_and_minimize(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), ascii_dump(), ascii_load(), clear_constraints_minimized(), clear_constraints_up_to_date(), clear_empty(), clear_generators_minimized(), clear_generators_up_to_date(), clear_pending_constraints(), clear_pending_generators(), clear_sat_c_up_to_date(), clear_sat_g_up_to_date(), constraints_are_minimized(), constraints_are_up_to_date(), generators_are_minimized(), generators_are_up_to_date(), has_pending_constraints(), has_pending_generators(), has_something_pending(), marked_empty(), OK(), operator=(), Polyhedron(), 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(), strongly_minimize_constraints(), and swap().
The number of dimensions of the enclosing vector space.
Definition at line 2043 of file Polyhedron.defs.hh.
Referenced by add_congruence(), add_congruences(), add_constraint(), add_generator(), add_recycled_constraints(), add_recycled_constraints_and_minimize(), add_recycled_generators(), add_recycled_generators_and_minimize(), add_space_dimensions_and_embed(), add_space_dimensions_and_project(), affine_dimension(), affine_image(), affine_preimage(), ascii_dump(), ascii_load(), BHRZ03_combining_constraints(), BHRZ03_evolving_points(), BHRZ03_evolving_rays(), BHRZ03_widening_assign(), bounded_affine_image(), bounded_affine_preimage(), bounded_BHRZ03_extrapolation_assign(), bounded_H79_extrapolation_assign(), bounds(), Parma_Polyhedra_Library::BHRZ03_Certificate::compare(), concatenate_assign(), constraints(), contains(), expand_space_dimension(), fold_space_dimensions(), generalized_affine_image(), generalized_affine_preimage(), generators(), H79_widening_assign(), intersection_assign(), intersection_assign_and_minimize(), is_bounded(), is_included_in(), is_topologically_closed(), is_universe(), limited_BHRZ03_extrapolation_assign(), limited_H79_extrapolation_assign(), map_space_dimensions(), max_min(), minimize(), OK(), operator=(), poly_difference_assign(), poly_hull_assign(), poly_hull_assign_and_minimize(), Polyhedron(), process_pending(), process_pending_constraints(), process_pending_generators(), quick_equivalence_test(), relation_with(), remove_higher_space_dimensions(), remove_space_dimensions(), select_CH78_constraints(), select_H79_constraints(), set_zero_dim_univ(), shrink_bounding_box(), space_dimension(), strongly_minimize_constraints(), strongly_minimize_generators(), swap(), time_elapse_assign(), topological_closure_assign(), update_constraints(), and update_generators().