24 #include "ppl-config.h"
34 s <<
"\nConstraints:";
41 s <<
"\nNo big-parameter set.\n";
51 : external_space_dim(dim),
52 internal_space_dim(0),
53 status(PARTIALLY_SATISFIABLE),
56 first_pending_constraint(0),
62 throw std::length_error(
"PPL::PIP_Problem::PIP_Problem(dim):\n"
63 "dim exceeds the maximum allowed "
71 : external_space_dim(y.external_space_dim),
72 internal_space_dim(y.internal_space_dim),
76 first_pending_constraint(y.first_pending_constraint),
77 parameters(y.parameters),
78 initial_context(y.initial_context),
79 big_parameter_dimension(y.big_parameter_dimension) {
89 delete current_solution;
94 control_parameters[CUTTING_STRATEGY] = CUTTING_STRATEGY_FIRST;
95 control_parameters[PIVOT_ROW_STRATEGY] = PIVOT_ROW_STRATEGY_FIRST;
117 case PARTIALLY_SATISFIABLE:
121 if (current_solution == 0) {
127 const dimension_type old_num_cols = initial_context.num_columns();
128 if (old_num_cols < new_num_cols) {
133 const Variables_Set::const_iterator param_begin = parameters.begin();
134 const Variables_Set::const_iterator param_end = parameters.end();
138 bool check_feasible_context =
false;
141 for (Constraint_Sequence::const_iterator
142 cs_i =
nth_iter(input_cs, first_pending_constraint),
143 cs_end = input_cs.end(); cs_i != cs_end; ++cs_i) {
146 PPL_ASSERT(external_space_dim >= c_space_dim);
154 check_feasible_context =
true;
183 for (Variables_Set::const_iterator
184 pi = param_begin; pi != param_end; ++pi, ++i) {
185 if (*pi < c_space_dim) {
186 Coefficient_traits::const_reference coeff_pi
189 itr = row.
insert(itr, i, coeff_pi);
209 i_end = last_row.
end(); i != i_end; ++i) {
215 if (check_feasible_context) {
231 first_pending_constraint,
239 check_feasible_context,
262 if (status == PARTIALLY_SATISFIABLE) {
265 return current_solution;
270 if (status == PARTIALLY_SATISFIABLE) {
273 return current_solution;
283 if (external_space_dim < internal_space_dim) {
285 cerr <<
"The internal space dimension of the PIP_Problem is "
286 <<
"greater than its external space dimension."
296 if (input_cs[i].space_dimension() > external_space_dim) {
298 cerr <<
"The space dimension of the PIP_Problem is smaller than "
299 <<
"the space dimension of one of its constraints."
309 if (strategy != CUTTING_STRATEGY_FIRST
310 && strategy != CUTTING_STRATEGY_DEEPEST
311 && strategy != CUTTING_STRATEGY_ALL) {
313 cerr <<
"Invalid value for the CUTTING_STRATEGY control parameter."
320 strategy = control_parameters[PIVOT_ROW_STRATEGY];
321 if (strategy < PIVOT_ROW_STRATEGY_FIRST
322 || strategy > PIVOT_ROW_STRATEGY_MAX_COLUMN) {
324 cerr <<
"Invalid value for the PIVOT_ROW_STRATEGY control parameter."
332 && parameters.count(big_parameter_dimension) == 0) {
334 cerr <<
"The big parameter is set, but it is not a parameter." << endl;
340 if (!parameters.OK()) {
343 if (!initial_context.OK()) {
347 if (current_solution != 0) {
349 if (!current_solution->OK()) {
351 cerr <<
"The computed solution tree is broken.\n";
357 if (!current_solution->check_ownership(
this)) {
359 cerr <<
"There are nodes in the solution tree "
360 <<
"that are not owned by *this.\n";
373 using namespace IO_Operators;
374 s <<
"\nexternal_space_dim: " << external_space_dim <<
"\n";
375 s <<
"\ninternal_space_dim: " << internal_space_dim <<
"\n";
379 s <<
"\ninput_cs( " << input_cs_size <<
" )\n";
381 input_cs[i].ascii_dump(s);
384 s <<
"\nfirst_pending_constraint: " << first_pending_constraint <<
"\n";
389 s <<
"UNSATISFIABLE";
394 case PARTIALLY_SATISFIABLE:
395 s <<
"PARTIALLY_SATISFIABLE";
401 parameters.ascii_dump(s);
403 s <<
"\ninitial_context\n";
404 initial_context.ascii_dump(s);
406 s <<
"\ncontrol_parameters\n";
407 for (
dimension_type i = 0; i < CONTROL_PARAMETER_NAME_SIZE; ++i) {
410 case CUTTING_STRATEGY_FIRST:
411 s <<
"CUTTING_STRATEGY_FIRST";
413 case CUTTING_STRATEGY_DEEPEST:
414 s <<
"CUTTING_STRATEGY_DEEPEST";
416 case CUTTING_STRATEGY_ALL:
417 s <<
"CUTTING_STRATEGY_ALL";
419 case PIVOT_ROW_STRATEGY_FIRST:
420 s <<
"PIVOT_ROW_STRATEGY_FIRST";
422 case PIVOT_ROW_STRATEGY_MAX_COLUMN:
423 s <<
"PIVOT_ROW_STRATEGY_MAX_COLUMN";
426 s <<
"Invalid control parameter value";
431 s <<
"\nbig_parameter_dimension: " << big_parameter_dimension <<
"\n";
433 s <<
"\ncurrent_solution: ";
434 if (current_solution == 0) {
444 PPL_ASSERT(sol != 0);
455 if (!(s >> str) || str !=
"external_space_dim:") {
459 if (!(s >> external_space_dim)) {
463 if (!(s >> str) || str !=
"internal_space_dim:") {
467 if (!(s >> internal_space_dim)) {
471 if (!(s >> str) || str !=
"input_cs(") {
477 if (!(s >> input_cs_size)) {
481 if (!(s >> str) || str !=
")") {
490 input_cs.push_back(c);
493 if (!(s >> str) || str !=
"first_pending_constraint:") {
497 if (!(s >> first_pending_constraint)) {
501 if (!(s >> str) || str !=
"status:") {
509 if (str ==
"UNSATISFIABLE") {
510 status = UNSATISFIABLE;
512 else if (str ==
"OPTIMIZED") {
515 else if (str ==
"PARTIALLY_SATISFIABLE") {
516 status = PARTIALLY_SATISFIABLE;
522 if (!(s >> str) || str !=
"parameters") {
526 if (!parameters.ascii_load(s)) {
530 if (!(s >> str) || str !=
"initial_context") {
534 if (!initial_context.ascii_load(s)) {
538 if (!(s >> str) || str !=
"control_parameters") {
542 for (
dimension_type i = 0; i < CONTROL_PARAMETER_NAME_SIZE; ++i) {
547 if (str ==
"CUTTING_STRATEGY_FIRST") {
548 value = CUTTING_STRATEGY_FIRST;
550 else if (str ==
"CUTTING_STRATEGY_DEEPEST") {
551 value = CUTTING_STRATEGY_DEEPEST;
553 else if (str ==
"CUTTING_STRATEGY_ALL") {
554 value = CUTTING_STRATEGY_ALL;
556 else if (str ==
"PIVOT_ROW_STRATEGY_FIRST") {
557 value = PIVOT_ROW_STRATEGY_FIRST;
559 else if (str ==
"PIVOT_ROW_STRATEGY_MAX_COLUMN") {
560 value = PIVOT_ROW_STRATEGY_MAX_COLUMN;
565 control_parameters[i] =
value;
568 if (!(s >> str) || str !=
"big_parameter_dimension:") {
571 if (!(s >> big_parameter_dimension)) {
576 delete current_solution;
577 current_solution = 0;
579 if (!(s >> str) || str !=
"current_solution:") {
585 if (str ==
"BOTTOM") {
586 current_solution = 0;
588 else if (str ==
"DECISION") {
590 current_solution = dec;
596 else if (str ==
"SOLUTION") {
598 current_solution = sol;
615 external_space_dim = 0;
616 internal_space_dim = 0;
617 status = PARTIALLY_SATISFIABLE;
618 if (current_solution != 0) {
619 delete current_solution;
620 current_solution = 0;
623 first_pending_constraint = 0;
625 initial_context.clear();
626 control_parameters_init();
636 if (m_vars == 0 && m_params == 0) {
643 bool should_throw = (m_vars > available);
646 should_throw = (m_params > available);
649 throw std::length_error(
"PPL::PIP_Problem::"
650 "add_space_dimensions_and_embed(m_v, m_p):\n"
651 "adding m_v+m_p new space dimensions exceeds "
652 "the maximum allowed space dimension.");
655 external_space_dim += m_vars;
658 parameters.insert(
Variable(external_space_dim));
659 ++external_space_dim;
662 if (status != UNSATISFIABLE) {
663 status = PARTIALLY_SATISFIABLE;
672 throw std::invalid_argument(
"PPL::PIP_Problem::"
673 "add_to_parameter_space_dimension(p_vars):\n"
674 "*this and p_vars are dimension "
678 parameters.insert(p_vars.begin(), p_vars.end());
680 for (Variables_Set::const_iterator p = p_vars.begin(),
681 end = p_vars.end(); p != end; ++p) {
682 if (*p < internal_space_dim) {
683 throw std::invalid_argument(
"PPL::PIP_Problem::"
684 "add_to_parameter_space_dimension(p_vars):"
685 "p_vars contain variable indices.");
691 if (parameters.size() != original_size && status != UNSATISFIABLE) {
692 status = PARTIALLY_SATISFIABLE;
699 std::ostringstream s;
700 s <<
"PPL::PIP_Problem::add_constraint(c):\n"
701 <<
"dim == "<< external_space_dim <<
" and c.space_dimension() == "
703 throw std::invalid_argument(s.str());
705 input_cs.push_back(c);
707 if (status != UNSATISFIABLE) {
708 status = PARTIALLY_SATISFIABLE;
715 ci_end = cs.
end(); ci != ci_end; ++ci) {
722 if (status == PARTIALLY_SATISFIABLE) {
725 return status == OPTIMIZED;
731 case CUTTING_STRATEGY_FIRST:
733 case CUTTING_STRATEGY_DEEPEST:
735 case CUTTING_STRATEGY_ALL:
736 control_parameters[CUTTING_STRATEGY] =
value;
738 case PIVOT_ROW_STRATEGY_FIRST:
740 case PIVOT_ROW_STRATEGY_MAX_COLUMN:
741 control_parameters[PIVOT_ROW_STRATEGY] =
value;
744 throw std::invalid_argument(
"PPL::PIP_Problem::set_control_parameter(v)"
745 ":\ninvalid value.");
751 if (parameters.count(big_dim) == 0) {
752 throw std::invalid_argument(
"PPL::PIP_Problem::"
753 "set_big_parameter_dimension(big_dim):\n"
754 "dimension 'big_dim' is not a parameter.");
756 if (big_dim < internal_space_dim) {
757 throw std::invalid_argument(
"PPL::PIP_Problem::"
758 "set_big_parameter_dimension(big_dim):\n"
759 "only newly-added parameters can be"
760 "converted into the big parameter.");
762 big_parameter_dimension = big_dim;
769 if (current_solution != 0) {
770 n += current_solution->total_memory_in_bytes();
773 n += input_cs.capacity() *
sizeof(
Constraint);
775 i_end = input_cs.end(); i != i_end; ++i) {
776 n += (i->external_memory_in_bytes());
794 PPL_ASSERT(current_solution == 0);
799 PPL_ASSERT(current_solution != 0);
800 current_solution->print(s, indent);
803 case PARTIALLY_SATISFIABLE:
804 throw std::logic_error(
"PIP_Problem::print_solution():\n"
805 "the PIP problem has not been solved.");
An iterator over a system of constraints.
dimension_type space_dimension() const
Returns the dimension of the smallest vector space enclosing all the variables whose indexes are in t...
dimension_type internal_space_dim
The space dimension of the current (partial) solution of the PIP problem; it may be smaller than exte...
dimension_type max_space_dimension()
Returns the maximum space dimension this library can handle.
static bool compatibility_check(Matrix< Row > &s)
Checks whether a context matrix is satisfiable.
const_iterator constraints_end() const
Returns a past-the-end read-only iterator to the sequence of constraints defining the feasible region...
A linear equality or inequality.
virtual void set_owner(const PIP_Problem *owner)
Sets the pointer to the PIP_Problem owning object.
static dimension_type max_space_dimension()
Returns the maximum space dimension a PIP_Problem can handle.
bool is_equality() const
Returns true if and only if *this is an equality constraint.
void add_constraint(const Constraint &c)
Adds a copy of constraint c to the PIP problem.
void set_control_parameter(Control_Parameter_Value value)
Sets control parameter value.
virtual void set_owner(const PIP_Problem *owner)
Sets the pointer to the PIP_Problem owning object.
size_t dimension_type
An unsigned integral type for representing space dimensions.
PIP_Problem(dimension_type dim=0)
Builds a trivial PIP problem.
An std::set of variables' indexes.
bool ascii_load(std::istream &s)
Loads from s an ASCII representation (as produced by ascii_dump(std::ostream&) const) and sets *this ...
void add_constraints(const Constraint_System &cs)
Adds a copy of the constraints in cs to the PIP problem.
Enable_If< Is_Native_Or_Checked< T >::value, void >::type ascii_dump(std::ostream &s, const T &t)
virtual void set_owner(const PIP_Problem *owner)=0
Sets the pointer to the PIP_Problem owning object.
dimension_type not_a_dimension()
Returns a value that does not designate a valid dimension.
PIP_Tree_Node * current_solution
The current solution decision tree.
std::ostream & operator<<(std::ostream &s, const Ask_Tell< D > &x)
bool OK() const
Checks if all the invariants are satisfied.
A sparse matrix of Coefficient.
bool ascii_load(std::istream &is)
Loads from is an ASCII representation (as produced by ascii_dump(std::ostream&) const) and sets *this...
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
A finite sparse sequence of coefficients.
The standard C++ namespace.
Constraint_Sequence::const_iterator const_iterator
A type alias for the read-only iterator on the constraints defining the feasible region.
dimension_type space_dimension() const
Returns the space dimension of the PIP problem.
An iterator on the tree elements, ordered by key.
const iterator & end()
Returns an iterator that points after the last stored element.
void set_big_parameter_dimension(dimension_type big_dim)
Sets the dimension for the big parameter to big_dim.
memory_size_type total_memory_in_bytes() const
Returns the total size in bytes of the memory occupied by *this.
const_iterator begin() const
Returns the const_iterator pointing to the first constraint, if *this is not empty; otherwise...
bool all_zeroes_except(const Variables_Set &vars, dimension_type start, dimension_type end) const
Returns true if all coefficients in [start,end), except those corresponding to variables in vars...
memory_size_type external_memory_in_bytes() const
Returns the size in bytes of the memory managed by *this.
A Parametric Integer (linear) Programming problem.
virtual PIP_Tree_Node * clone() const =0
Returns a pointer to a dynamically-allocated copy of *this.
Coefficient_traits::const_reference coefficient(Variable v) const
Returns the coefficient of v in *this.
The problem has an optimal solution.
virtual void update_tableau(const PIP_Problem &pip, dimension_type external_space_dim, dimension_type first_pending_constraint, const Constraint_Sequence &input_cs, const Variables_Set ¶meters)=0
Populates the parametric simplex tableau using external data.
RA_Container::iterator nth_iter(RA_Container &cont, dimension_type n)
A tree node representing a decision in the space of solutions.
A dimension of the vector space.
void ascii_dump() const
Writes to std::cerr an ASCII representation of *this.
void control_parameters_init()
Initializes the control parameters with default values.
bool is_strict_inequality() const
Returns true if and only if *this is a strict inequality constraint.
Control_Parameter_Value control_parameters[CONTROL_PARAMETER_NAME_SIZE]
The control parameters for the problem object.
Control_Parameter_Value
Possible values for PIP_Problem control parameters.
const Variables_Set & parameter_space_dimensions() const
Returns a set containing all the variables' indexes representing the parameters of the PIP problem...
dimension_type first_pending_constraint
The first index of `input_cs' containing a pending constraint.
void ascii_dump(std::ostream &os) const
Dumps to os an ASCII representation of *this.
void control_parameters_copy(const PIP_Problem &y)
Copies the control parameters from problem object y.
virtual const PIP_Solution_Node * as_solution() const
Returns this.
Enable_If< Is_Native< T >::value, memory_size_type >::type external_memory_in_bytes(const T &)
For native types, returns the size in bytes of the memory managed by the type of the (unused) paramet...
const_iterator end() const
Returns the past-the-end const_iterator.
Status status
The internal state of the MIP problem.
virtual const PIP_Decision_Node * as_decision() const
Returns this.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type ascii_load(std::istream &s, T &t)
bool is_satisfiable() const
Checks satisfiability of *this.
iterator insert(dimension_type i, Coefficient_traits::const_reference x)
Equivalent to (*this)[i] = x; find(i), but faster.
PIP_Problem_Status
Possible outcomes of the PIP_Problem solver.
void neg_assign(GMP_Integer &x)
#define PPL_OUTPUT_DEFINITIONS(class_name)
The entire library is confined to this namespace.
PIP_Problem_Status solve() const
Optimizes the PIP problem.
The problem is unfeasible.
Matrix< Row > initial_context
The initial context.
void clear()
Resets *this to be equal to the trivial PIP problem.
PIP_Tree solution() const
Returns a feasible solution for *this, if it exists.
static const Constraint & zero_dim_positivity()
The true (zero-dimension space) constraint , also known as positivity constraint. ...
iterator begin()
Returns an iterator that points at the first stored element.
A tree node representing part of the space of solutions.
size_t memory_size_type
An unsigned integral type for representing memory size in bytes.
~PIP_Problem()
Destructor.
dimension_type get_big_parameter_dimension() const
Returns the space dimension for the big parameter.
Coefficient_traits::const_reference inhomogeneous_term() const
Returns the inhomogeneous term of *this.
void add_to_parameter_space_dimensions(const Variables_Set &p_vars)
Sets the space dimensions whose indexes which are in set p_vars to be parameter space dimensions...
expr_type expression() const
Partial read access to the (adapted) internal expression.
const_iterator constraints_begin() const
Returns a read-only iterator to the first constraint defining the feasible region.
virtual PIP_Tree_Node * solve(const PIP_Problem &pip, bool check_feasible_context, const Matrix< Row > &context, const Variables_Set ¶ms, dimension_type space_dim, int indent_level)=0
Executes a parametric simplex on the tableau, under specified context.
A node of the PIP solution tree.
void add_space_dimensions_and_embed(dimension_type m_vars, dimension_type m_params)
Adds m_vars + m_params new space dimensions and embeds the old PIP problem in the new vector space...
void print_solution(std::ostream &s, int indent=0) const
Prints on s the solution computed for *this.
bool ascii_load(std::istream &s)
Loads from s an ASCII representation (as produced by ascii_dump(std::ostream&) const) and sets *this ...
PIP_Tree optimizing_solution() const
Returns an optimizing solution for *this, if it exists.
static void indent_and_print(std::ostream &s, int indent, const char *str)
A helper function used when printing PIP trees.