Parma_Polyhedra_Library::PIP_Problem Class Reference
[C++ Language Interface]

A Parametric Integer (linear) Programming problem. More...

#include <PIP_Problem.defs.hh>

Collaboration diagram for Parma_Polyhedra_Library::PIP_Problem:
Collaboration graph
[legend]

List of all members.

Public Types

enum  Control_Parameter_Name { CUTTING_STRATEGY, PIVOT_ROW_STRATEGY, CONTROL_PARAMETER_NAME_SIZE }
 

Possible names for PIP_Problem control parameters.

More...
enum  Control_Parameter_Value {
  CUTTING_STRATEGY_FIRST, CUTTING_STRATEGY_DEEPEST, CUTTING_STRATEGY_ALL, PIVOT_ROW_STRATEGY_FIRST,
  PIVOT_ROW_STRATEGY_MAX_COLUMN, CONTROL_PARAMETER_VALUE_SIZE
}
 

Possible values for PIP_Problem control parameters.

More...
typedef
Constraint_Sequence::const_iterator 
const_iterator
 A type alias for the read-only iterator on the constraints defining the feasible region.

Public Member Functions

 PIP_Problem (dimension_type dim=0)
 Builds a trivial PIP problem.
template<typename In >
 PIP_Problem (dimension_type dim, In first, In last, const Variables_Set &p_vars)
 Builds a PIP problem having space dimension dim from the sequence of constraints in the range $[\mathrm{first}, \mathrm{last})$; those dimensions whose indices occur in p_vars are interpreted as parameters.
 PIP_Problem (const PIP_Problem &y)
 Ordinary copy-constructor.
 ~PIP_Problem ()
 Destructor.
PIP_Problemoperator= (const PIP_Problem &y)
 Assignment operator.
dimension_type space_dimension () const
 Returns the space dimension of the PIP problem.
const Variables_Setparameter_space_dimensions () const
 Returns a set containing all the variables' indexes representing the parameters of the PIP problem.
const_iterator constraints_begin () const
 Returns a read-only iterator to the first constraint defining the feasible region.
const_iterator constraints_end () const
 Returns a past-the-end read-only iterator to the sequence of constraints defining the feasible region.
void clear ()
 Resets *this to be equal to the trivial PIP problem.
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 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.
void add_constraint (const Constraint &c)
 Adds a copy of constraint c to the PIP problem.
void add_constraints (const Constraint_System &cs)
 Adds a copy of the constraints in cs to the PIP problem.
bool is_satisfiable () const
 Checks satisfiability of *this.
PIP_Problem_Status solve () const
 Optimizes the PIP problem.
PIP_Tree solution () const
 Returns a feasible solution for *this, if it exists.
PIP_Tree optimizing_solution () const
 Returns an optimizing solution for *this, if it exists.
bool OK () const
 Checks if all the invariants are satisfied.
void print_solution (std::ostream &s, unsigned indent=0) const
 Prints on s the solution computed for *this.
void ascii_dump () const
 Writes to std::cerr an ASCII representation of *this.
void ascii_dump (std::ostream &s) const
 Writes to s an ASCII representation of *this.
void print () const
 Prints *this to std::cerr using operator<<.
bool ascii_load (std::istream &s)
 Loads from s an ASCII representation (as produced by ascii_dump(std::ostream&) const) and sets *this accordingly. Returns true if successful, false otherwise.
memory_size_type total_memory_in_bytes () const
 Returns the total size in bytes of the memory occupied by *this.
memory_size_type external_memory_in_bytes () const
 Returns the size in bytes of the memory managed by *this.
void swap (PIP_Problem &y)
 Swaps *this with y.
Control_Parameter_Value get_control_parameter (Control_Parameter_Name name) const
 Returns the value of control parameter name.
void set_control_parameter (Control_Parameter_Value value)
 Sets control parameter value.
void set_big_parameter_dimension (dimension_type big_dim)
 Sets the dimension for the big parameter to big_dim.
dimension_type get_big_parameter_dimension () const
 Returns the space dimension for the big parameter.

Static Public Member Functions

static dimension_type max_space_dimension ()
 Returns the maximum space dimension a PIP_Problem can handle.

Private Types

enum  Status { UNSATISFIABLE, OPTIMIZED, PARTIALLY_SATISFIABLE }
 

An enumerated type describing the internal status of the PIP problem.

More...
typedef std::vector< ConstraintConstraint_Sequence
 A type alias for a sequence of constraints.

Private Member Functions

void control_parameters_init ()
 Initializes the control parameters with default values.
void control_parameters_copy (const PIP_Problem &y)
 Copies the control parameters from problem object y.

Private Attributes

dimension_type external_space_dim
 The dimension of the vector space.
dimension_type internal_space_dim
 The space dimension of the current (partial) solution of the PIP problem; it may be smaller than external_space_dim.
Status status
 The internal state of the MIP problem.
PIP_Tree_Nodecurrent_solution
 The current solution decision tree.
Constraint_Sequence input_cs
 The sequence of constraints describing the feasible region.
dimension_type first_pending_constraint
 The first index of `input_cs' containing a pending constraint.
Variables_Set parameters
 A set containing all the indices of space dimensions that are interpreted as problem parameters.
Matrix initial_context
 The initial context.
Control_Parameter_Value control_parameters [CONTROL_PARAMETER_NAME_SIZE]
 The control parameters for the problem object.
dimension_type big_parameter_dimension
 The dimension for the big parameter, or not_a_dimension() if not set.

Friends

class PIP_Solution_Node

Related Functions

(Note that these are not member functions.)



std::ostream & operator<< (std::ostream &s, const PIP_Problem &p)
 Output operator.
void swap (Parma_Polyhedra_Library::PIP_Problem &x, Parma_Polyhedra_Library::PIP_Problem &y)
 Specializes std::swap.

Detailed Description

A Parametric Integer (linear) Programming problem.

An object of this class encodes a parametric integer (linear) programming problem. The PIP problem is specified by providing:

Note that all problem variables and problem parameters are assumed to take non-negative integer values, so that there is no need to specify non-negativity constraints.

The class provides support for the (incremental) solution of the PIP problem based on variations of the revised simplex method and on Gomory cut generation techniques.

The solution for a PIP problem is the lexicographic minimum of the integer points of the feasible region, expressed in terms of the parameters. As the problem to be solved only involves non-negative variables and parameters, the problem will always be either unfeasible or optimizable.

As the feasibility and the solution value of a PIP problem depend on the values of the parameters, the solution is a binary decision tree, dividing the context parameter set into subsets. The tree nodes are of two kinds:

It may happen that a decision node has no false child. This means that there is no solution if at least one of the corresponding constraints is not satisfied. Decision nodes having two or more linear tests on the parameters cannot have a false child. Decision nodes always have a true child.

Both kinds of tree nodes may also contain the definition of extra parameters which are artificially introduced by the solver to enforce an integral solution. Such artificial parameters are defined by the integer division of a linear expression on the parameters by an integer coefficient.

By exploiting the incremental nature of the solver, it is possible to reuse part of the computational work already done when solving variants of a given PIP_Problem: currently, incremental resolution supports the addition of space dimensions, the addition of parameters and the addition of constraints.

Example problem
An example PIP problem can be defined the following:
  3*j >= -2*i+8
  j <= 4*i - 4
  i <= n
  j <= m
where i and j are the problem variables and n and m are the problem parameters. This problem can be optimized; the resulting solution tree may be represented as follows:
  if 7*n >= 10 then
    if 7*m >= 12 then
      {i = 2 ; j = 2}
    else
      Parameter P = (m) div 2
      if 2*n + 3*m >= 8 then
        {i = -m - P + 4 ; j = m}
      else
        _|_
  else
    _|_
  
The solution tree starts with a decision node depending on the context constraint 7*n >= 10. If this constraint is satisfied by the values assigned to the problem parameters, then the (textually first) then branch is taken, reaching the true child of the root node (which in this case is another decision node); otherwise, the (textually last) else branch is taken, for which there is no corresponding false child.
The $\perp$ notation, also called bottom, denotes the lexicographic minimum of an empty set of solutions, here meaning the corresponding subproblem is unfeasible.
Notice that a tree node may introduce new (non-problem) parameters, as is the case for parameter P in the (textually first) else branch above. These artificial parameters are only meaningful inside the subtree where they are defined and are used to define the parametric values of the problem variables in solution nodes (e.g., the {i,j} vector in the textually third then branch).
Context restriction
The above solution is correct in an unrestricted initial context, meaning all possible values are allowed for the parameters. If we restrict the context with the following parameter inequalities:
  m >= n
  n >= 5
then the resulting optimizing tree will be a simple solution node:
  {i = 2 ; j = 2}
  
Creating the PIP_Problem object
The PIP_Problem object corresponding to the above example can be created as follows:
  Variable i(0);
  Variable j(1);
  Variable n(2);
  Variable m(3);
  Variables_Set params(n, m);
  Constraint_System cs;
  cs.insert(3*j >= -2*i+8);
  cs.insert(j <= 4*i - 4);
  cs.insert(j <= m);
  cs.insert(i <= n);
  PIP_Problem pip(cs.space_dimension(), cs.begin(), cs.end(), params);
If you want to restrict the initial context, simply add the parameter constraints the same way as for normal constraints.
  cs.insert(m >= n);
  cs.insert(n >= 5);
Solving the problem
Once the PIP_Problem object has been created, you can start the resolution of the problem by calling the solve() method:
  PIP_Problem_Status status = pip.solve();
where the returned status indicates if the problem has been optimized or if it is unfeasible for any possible configuration of the parameter values. The resolution process is also started if an attempt is made to get its solution, as follows:
  const PIP_Tree_Node* node = pip.solution();
In this case, an unfeasible problem will result in an empty solution tree, i.e., assigning a null pointer to node.
Printing the solution tree
A previously computed solution tree may be printed as follows:
  pip.print_solution(std::cout);
This will produce the following output (note: variables and parameters are printed according to the default output function; see Variable::set_output_function):
  if 7*C >= 10 then
    if 7*D >= 12 then
      {2 ; 2}
    else
      Parameter E = (D) div 2
      if 2*C + 3*D >= 8 then
        {-D - E + 4 ; D}
      else
        _|_
  else
    _|_
  
Spanning the solution tree
A parameter assignment for a PIP problem binds each of the problem parameters to a non-negative integer value. After fixing a parameter assignment, the ``spanning'' of the PIP problem solution tree refers to the process whereby the solution tree is navigated, starting from the root node: the value of artificial parameters is computed according to the parameter assignment and the node's contraints are evaluated, thereby descending in either the true or the false subtree of decision nodes and eventually reaching a solution node or a bottom node. If a solution node is found, each of the problem variables is provided with a parametric expression, which can be evaluated to a fixed value using the given parameter assignment and the computed values for artificial parameters.
The coding of the spanning process can be done as follows. First, the root of the PIP solution tree is retrieved:
  const PIP_Tree_Node* node = pip.solution();
If node represents an unfeasible solution (i.e., $\perp$), its value will be 0. For a non-null tree node, the virtual methods PIP_Tree_Node::as_decision() and PIP_Tree_Node::as_solution() can be used to check whether the node is a decision or a solution node:
  const PIP_Solution_Node* sol = node->as_solution();
  if (sol != 0) {
    // The node is a solution node
    ...
  }
  else {
    // The node is a decision node
    const PIP_Decision_Node* dec = node->as_decision();
    ...
  }
The true (resp., false) child node of a Decision Node may be accessed by using method PIP_Decision_Node::child_node(bool), passing true (resp., false) as the input argument.
Artificial parameters
A PIP_Tree_Node::Artificial_Parameter object represents the result of the integer division of a Linear_Expression (on the other parameters, including the previously-defined artificials) by an integer denominator (a Coefficient object). The dimensions of the artificial parameters (if any) in a tree node have consecutive indices starting from dim+1, where the value of dim is computed as follows:
  • for the tree root node, dim is the space dimension of the PIP_Problem;
  • for any other node of the tree, it is recusrively obtained by adding the value of dim computed for the parent node to the number of artificial parameters defined in the parent node.
Since the numbering of dimensions for artificial parameters follows the rule above, the addition of new problem variables and/or new problem parameters to an already solved PIP_Problem object (as done when incrementally solving a problem) will result in the systematic renumbering of all the existing artificial parameters.
Node constraints
All kind of tree nodes can contain context constraints. Decision nodes always contain at least one of them. The node's local constraint system can be obtained using method PIP_Tree_Node::constraints. These constraints only involve parameters, including both the problem parameters and the artificial parameters that have been defined in nodes occurring on the path from the root node to the current node. The meaning of these constraints is as follows:
  • On a decision node, if all tests in the constraints are true, then the solution is the true child; otherwise it is the false child.
  • On a solution node, if the (possibly empty) system of constraints evaluates to true for a given parameter assignment, then the solution is described by the node; otherwise the solution is $\perp$ (i.e., the problem is unfeasible for that parameter assignment).
Getting the optimal values for the variables
After spanning the solution tree using the given parameter assignment, if a solution node has been reached, then it is possible to retrieve the parametric expression for each of the problem variables using method PIP_Solution_Node::parametric_values. The retrieved expression will be defined in terms of all the parameters (problem parameters and artificial parameters defined along the path).
Solving maximization problems
You can solve a lexicographic maximization problem by reformulating its constraints using variable substitution. Proceed the following steps:
  • Create a big parameter (see PIP_Problem::set_big_parameter_dimension), which we will call $M$.
  • Reformulate each of the maximization problem constraints by substituting each $x_i$ variable with an expression of the form $M-x'_i$, where the $x'_i$ variables are positive variables to be minimized.
  • Solve the lexicographic minimum for the $x'$ variable vector.
  • In the solution expressions, the values of the $x'$ variables will be expressed in the form: $x'_i = M-x_i$. To get back the value of the expression of each $x_i$ variable, just apply the formula: $x_i = M-x'_i$.
Note that if the resulting expression of one of the $x'_i$ variables is not in the $x'_i = M-x_i$ form, this means that the sign-unrestricted problem is unbounded.
You can choose to maximize only a subset of the variables while minimizing the other variables. In that case, just apply the variable substitution method on the variables you want to be maximized. The variable optimization priority will still be in lexicographic order.
Example: consider you want to find the lexicographic maximum of the $(x,y)$ vector, under the constraints:

\[\left\{\begin{array}{l} y \geq 2x - 4\\ y \leq -x + p \end{array}\right.\]

where $p$ is a parameter.
After variable substitution, the constraints become:

\[\left\{\begin{array}{l} M - y \geq 2M - 2x - 4\\ M - y \leq -M + x + p \end{array}\right.\]

The code for creating the corresponding problem object is the following:
  Variable x(0);
  Variable y(1);
  Variable p(2);
  Variable M(3);
  Variables_Set params(p, M);
  Constraint_System cs;
  cs.insert(M - y >= 2*M - 2*x - 4);
  cs.insert(M - y <= -M + x + p);
  PIP_Problem pip(cs.space_dimension(), cs.begin(), cs.end(), params);
  pip.set_big_parameter_dimension(3);     // M is the big parameter
Solving the problem provides the following solution:
  Parameter E = (C + 1) div 3
  {D - E - 1 ; -C + D + E + 1}
  
Under the notations above, the solution is:

\[ \left\{\begin{array}{l} x'=M-\left\lfloor\frac{p+1}{3}\right\rfloor-1\\ y'=M-p+\left\lfloor\frac{p+1}{3}\right\rfloor+1 \end{array}\right. \]

Performing substitution again provides us with the values of the original variables:

\[ \left\{\begin{array}{l} x=\left\lfloor\frac{p+1}{3}\right\rfloor+1\\ y=p-\left\lfloor\frac{p+1}{3}\right\rfloor-1 \end{array}\right. \]

Allowing variables to be arbitrarily signed
You can deal with arbitrarily signed variables by reformulating the constraints using variable substitution. Proceed the following steps:
  • Create a big parameter (see PIP_Problem::set_big_parameter_dimension), which we will call $M$.
  • Reformulate each of the maximization problem constraints by substituting each $x_i$ variable with an expression of the form $x'_i-M$, where the $x'_i$ variables are positive.
  • Solve the lexicographic minimum for the $x'$ variable vector.
  • The solution expression can be read in the form:
  • In the solution expressions, the values of the $x'$ variables will be expressed in the form: $x'_i = x_i+M$. To get back the value of the expression of each signed $x_i$ variable, just apply the formula: $x_i = x'_i-M$.
Note that if the resulting expression of one of the $x'_i$ variables is not in the $x'_i = x_i+M$ form, this means that the sign-unrestricted problem is unbounded.
You can choose to define only a subset of the variables to be sign-unrestricted. In that case, just apply the variable substitution method on the variables you want to be sign-unrestricted.
Example: consider you want to find the lexicographic minimum of the $(x,y)$ vector, where the $x$ and $y$ variables are sign-unrestricted, under the constraints:

\[\left\{\begin{array}{l} y \geq -2x - 4\\ 2y \leq x + 2p \end{array}\right.\]

where $p$ is a parameter.
After variable substitution, the constraints become:

\[\left\{\begin{array}{l} y' - M \geq -2x' + 2M - 4\\ 2y' - 2M \leq x' - M + 2p \end{array}\right.\]

The code for creating the corresponding problem object is the following:
  Variable x(0);
  Variable y(1);
  Variable p(2);
  Variable M(3);
  Variables_Set params(p, M);
  Constraint_System cs;
  cs.insert(y - M >= -2*x + 2*M - 4);
  cs.insert(2*y - 2*M <= x - M + 2*p);
  PIP_Problem pip(cs.space_dimension(), cs.begin(), cs.end(), params);
  pip.set_big_parameter_dimension(3);     // M is the big parameter
Solving the problem provides the following solution:
  Parameter E = (2*C + 3) div 5
  {D - E - 1 ; D + 2*E - 2}
  
Under the notations above, the solution is:

\[ \left\{\begin{array}{l} x'=M-\left\lfloor\frac{2p+3}{5}\right\rfloor-1\\ y'=M+2\left\lfloor\frac{2p+3}{5}\right\rfloor-2 \end{array}\right. \]

Performing substitution again provides us with the values of the original variables:

\[ \left\{\begin{array}{l} x=-\left\lfloor\frac{2p+3}{5}\right\rfloor-1\\ y=2\left\lfloor\frac{2p+3}{5}\right\rfloor-2 \end{array}\right. \]

Allowing parameters to be arbitrarily signed
You can consider a parameter $p$ arbitrarily signed by replacing $p$ with $p^+-p^-$, where both $p^+$ and $p^-$ are positive parameters. To represent a set of arbitrarily signed parameters, replace each parameter $p_i$ with $p^+_i-p^-$, where $-p^-$ is the minimum negative value of all parameters.
Minimizing a linear cost function
Lexicographic solving can be used to find the parametric minimum of a linear cost function.
Suppose the variables are named $x_1, x_2, \dots, x_n$, and the parameters $p_1, p_2, \dots, p_m$. You can minimize a linear cost function $f(x_2, \dots, x_n, p_1, \dots, p_m)$ by simply adding the constraint $x_1 \geq f(x_2, \dots, x_n, p_1, \dots, p_m)$ to the constraint system. As lexicographic minimization ensures $x_1$ is minimized in priority, and because $x_1$ is forced by a constraint to be superior or equal to the cost function, optimal solutions of the problem necessarily ensure that the solution value of $x_1$ is the optimal value of the cost function.

Definition at line 488 of file PIP_Problem.defs.hh.


Member Typedef Documentation

typedef Constraint_Sequence::const_iterator Parma_Polyhedra_Library::PIP_Problem::const_iterator

A type alias for the read-only iterator on the constraints defining the feasible region.

Definition at line 567 of file PIP_Problem.defs.hh.

A type alias for a sequence of constraints.

Definition at line 560 of file PIP_Problem.defs.hh.


Member Enumeration Documentation

Possible names for PIP_Problem control parameters.

Enumerator:
CUTTING_STRATEGY 

Cutting strategy.

PIVOT_ROW_STRATEGY 

Pivot row strategy.

CONTROL_PARAMETER_NAME_SIZE 

Number of different enumeration values.

Definition at line 703 of file PIP_Problem.defs.hh.

00703                               {
00705     CUTTING_STRATEGY,
00707     PIVOT_ROW_STRATEGY,
00708 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
00709 
00710 #endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
00711     CONTROL_PARAMETER_NAME_SIZE
00712   };

Possible values for PIP_Problem control parameters.

Enumerator:
CUTTING_STRATEGY_FIRST 

Choose the first non-integer row.

CUTTING_STRATEGY_DEEPEST 

Choose row which generates the deepest cut.

CUTTING_STRATEGY_ALL 

Always generate all possible cuts.

PIVOT_ROW_STRATEGY_FIRST 

Choose the first row with negative parameter sign.

PIVOT_ROW_STRATEGY_MAX_COLUMN 

Choose the row which generates the lexico-maximal pivot column.

CONTROL_PARAMETER_VALUE_SIZE 

Number of different enumeration values.

Definition at line 715 of file PIP_Problem.defs.hh.

00715                                {
00717     CUTTING_STRATEGY_FIRST,
00719     CUTTING_STRATEGY_DEEPEST,
00721     CUTTING_STRATEGY_ALL,
00722 
00724     PIVOT_ROW_STRATEGY_FIRST,
00726     PIVOT_ROW_STRATEGY_MAX_COLUMN,
00727 
00728 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
00729 
00730 #endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
00731     CONTROL_PARAMETER_VALUE_SIZE
00732   };

An enumerated type describing the internal status of the PIP problem.

Enumerator:
UNSATISFIABLE 

The PIP problem is unsatisfiable.

OPTIMIZED 

The PIP problem is optimized; the solution tree has been computed.

PARTIALLY_SATISFIABLE 

The feasible region of the PIP problem has been changed by adding new variables, parameters or constraints; a feasible solution for the old feasible region is still available.

Definition at line 768 of file PIP_Problem.defs.hh.

00768               {
00770     UNSATISFIABLE,
00772     OPTIMIZED,
00778     PARTIALLY_SATISFIABLE
00779   };


Constructor & Destructor Documentation

Parma_Polyhedra_Library::PIP_Problem::PIP_Problem ( dimension_type  dim = 0  )  [explicit]

Builds a trivial PIP problem.

A trivial PIP problem requires to compute the lexicographic minimum on a vector space under no constraints and with no parameters: due to the implicit non-negativity constraints, the origin of the vector space is an optimal solution.

Parameters:
dim The dimension of the vector space enclosing *this (optional argument with default value $0$).
Exceptions:
std::length_error Thrown if dim exceeds max_space_dimension().

Definition at line 47 of file PIP_Problem.cc.

References control_parameters_init(), max_space_dimension(), and OK().

00048   : external_space_dim(dim),
00049     internal_space_dim(0),
00050     status(PARTIALLY_SATISFIABLE),
00051     current_solution(0),
00052     input_cs(),
00053     first_pending_constraint(0),
00054     parameters(),
00055     initial_context(),
00056     big_parameter_dimension(not_a_dimension()) {
00057   // Check for space dimension overflow.
00058   if (dim > max_space_dimension())
00059     throw std::length_error("PPL::PIP_Problem::PIP_Problem(dim):\n"
00060                             "dim exceeds the maximum allowed "
00061                             "space dimension.");
00062   control_parameters_init();
00063   PPL_ASSERT(OK());
00064 }

template<typename In >
Parma_Polyhedra_Library::PIP_Problem::PIP_Problem ( dimension_type  dim,
In  first,
In  last,
const Variables_Set p_vars 
) [inline]

Builds a PIP problem having space dimension dim from the sequence of constraints in the range $[\mathrm{first}, \mathrm{last})$; those dimensions whose indices occur in p_vars are interpreted as parameters.

Parameters:
dim The dimension of the vector space (variables and parameters) enclosing *this.
first An input iterator to the start of the sequence of constraints.
last A past-the-end input iterator to the sequence of constraints.
p_vars The set of variables' indexes that are interpreted as parameters.
Exceptions:
std::length_error Thrown if dim exceeds max_space_dimension().
std::invalid_argument Thrown if the space dimension of a constraint in the sequence (resp., the parameter variables) is strictly greater than dim.

Definition at line 32 of file PIP_Problem.templates.hh.

References control_parameters_init(), external_space_dim, input_cs, max_space_dimension(), OK(), and Parma_Polyhedra_Library::Variables_Set::space_dimension().

00036   : external_space_dim(dim),
00037     internal_space_dim(0),
00038     status(PARTIALLY_SATISFIABLE),
00039     current_solution(0),
00040     input_cs(),
00041     first_pending_constraint(0),
00042     parameters(p_vars),
00043     initial_context(),
00044     big_parameter_dimension(not_a_dimension()) {
00045   // Check that integer Variables_Set does not exceed the space dimension
00046   // of the problem.
00047   if (p_vars.space_dimension() > external_space_dim) {
00048     std::ostringstream s;
00049     s << "PPL::PIP_Problem::PIP_Problem(dim, first, last, p_vars):\n"
00050       << "dim == " << external_space_dim
00051       << " and p_vars.space_dimension() == "
00052       << p_vars.space_dimension()
00053       << " are dimension incompatible.";
00054     throw std::invalid_argument(s.str());
00055   }
00056 
00057   // Check for space dimension overflow.
00058   if (dim > max_space_dimension())
00059     throw std::length_error("PPL::PIP_Problem::"
00060                             "PIP_Problem(dim, first, last, p_vars):\n"
00061                             "dim exceeds the maximum allowed "
00062                             "space dimension.");
00063   // Check the constraints.
00064   for (In i = first; i != last; ++i) {
00065     if (i->space_dimension() > dim) {
00066       std::ostringstream s;
00067       s << "PPL::PIP_Problem::"
00068         << "PIP_Problem(dim, first, last, p_vars):\n"
00069         << "range [first, last) contains a constraint having space "
00070         << "dimension == " << i->space_dimension()
00071         << " that exceeds this->space_dimension == " << dim << ".";
00072       throw std::invalid_argument(s.str());
00073     }
00074     input_cs.push_back(*i);
00075   }
00076   control_parameters_init();
00077   PPL_ASSERT(OK());
00078 }

Parma_Polyhedra_Library::PIP_Problem::PIP_Problem ( const PIP_Problem y  ) 

Ordinary copy-constructor.

Definition at line 66 of file PIP_Problem.cc.

References Parma_Polyhedra_Library::PIP_Tree_Node::clone(), control_parameters_copy(), current_solution, OK(), and Parma_Polyhedra_Library::PIP_Tree_Node::set_owner().

00067   : external_space_dim(y.external_space_dim),
00068     internal_space_dim(y.internal_space_dim),
00069     status(y.status),
00070     current_solution(0),
00071     input_cs(y.input_cs),
00072     first_pending_constraint(y.first_pending_constraint),
00073     parameters(y.parameters),
00074     initial_context(y.initial_context),
00075     big_parameter_dimension(y.big_parameter_dimension) {
00076   if (y.current_solution != 0) {
00077     current_solution = y.current_solution->clone();
00078     current_solution->set_owner(this);
00079   }
00080   control_parameters_copy(y);
00081   PPL_ASSERT(OK());
00082 }

Parma_Polyhedra_Library::PIP_Problem::~PIP_Problem (  ) 

Destructor.

Definition at line 84 of file PIP_Problem.cc.

References current_solution.

00084                              {
00085   delete current_solution;
00086 }


Member Function Documentation

void Parma_Polyhedra_Library::PIP_Problem::add_constraint ( const Constraint c  ) 

Adds a copy of constraint c to the PIP problem.

Exceptions:
std::invalid_argument Thrown if the space dimension of c is strictly greater than the space dimension of *this.

Definition at line 625 of file PIP_Problem.cc.

References external_space_dim, input_cs, PARTIALLY_SATISFIABLE, Parma_Polyhedra_Library::Constraint::space_dimension(), status, and UNSATISFIABLE.

Referenced by add_constraints().

00625                                                   {
00626   if (c.space_dimension() > external_space_dim) {
00627     std::ostringstream s;
00628     s << "PPL::PIP_Problem::add_constraint(c):\n"
00629       << "dim == "<< external_space_dim << " and c.space_dimension() == "
00630       << c.space_dimension() << " are dimension incompatible.";
00631     throw std::invalid_argument(s.str());
00632   }
00633   input_cs.push_back(c);
00634   // Update problem status.
00635   if (status != UNSATISFIABLE)
00636     status = PARTIALLY_SATISFIABLE;
00637 }

void Parma_Polyhedra_Library::PIP_Problem::add_constraints ( const Constraint_System cs  ) 

Adds a copy of the constraints in cs to the PIP problem.

Exceptions:
std::invalid_argument Thrown if the space dimension of constraint system cs is strictly greater than the space dimension of *this.

Definition at line 640 of file PIP_Problem.cc.

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

00640                                                            {
00641   for (Constraint_System::const_iterator ci = cs.begin(),
00642          ci_end = cs.end(); ci != ci_end; ++ci)
00643     add_constraint(*ci);
00644 }

void Parma_Polyhedra_Library::PIP_Problem::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.

Parameters:
m_vars The number of space dimensions to add that are interpreted as PIP problem variables (i.e., non parameters). These are added before adding the m_params parameters.
m_params The number of space dimensions to add that are interpreted as PIP problem parameters. These are added after having added the m_vars problem variables.
Exceptions:
std::length_error Thrown if adding m_vars + m_params new space dimensions would cause the vector space to exceed dimension max_space_dimension().

The new space dimensions will be those having the highest indexes in the new PIP problem; they are initially unconstrained.

Definition at line 565 of file PIP_Problem.cc.

References external_space_dim, Parma_Polyhedra_Library::Variables_Set::insert(), max_space_dimension(), OK(), parameters, PARTIALLY_SATISFIABLE, space_dimension(), status, and UNSATISFIABLE.

00566                                                                 {
00567   // Adding no space dims at all is a no-op:
00568   // this avoids invalidating problem status (if it was optimized).
00569   if (m_vars == 0 && m_params == 0)
00570     return;
00571 
00572   // The space dimension of the resulting PIP problem should not
00573   // overflow the maximum allowed space dimension.
00574   dimension_type available = max_space_dimension() - space_dimension();
00575   bool should_throw = (m_vars > available);
00576   if (!should_throw) {
00577     available -= m_vars;
00578     should_throw = (m_params > available);
00579   }
00580   if (should_throw)
00581     throw std::length_error("PPL::PIP_Problem::"
00582                             "add_space_dimensions_and_embed(m_v, m_p):\n"
00583                             "adding m_v+m_p new space dimensions exceeds "
00584                             "the maximum allowed space dimension.");
00585   // First add PIP variables ...
00586   external_space_dim += m_vars;
00587   // ... then add PIP parameters.
00588   for (dimension_type i = m_params; i-- > 0; ) {
00589     parameters.insert(Variable(external_space_dim));
00590     ++external_space_dim;
00591   }
00592   // Update problem status.
00593   if (status != UNSATISFIABLE)
00594     status = PARTIALLY_SATISFIABLE;
00595   PPL_ASSERT(OK());
00596 }

void Parma_Polyhedra_Library::PIP_Problem::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.

Exceptions:
std::invalid_argument Thrown if some index in p_vars does not correspond to a space dimension in *this.

Definition at line 600 of file PIP_Problem.cc.

References external_space_dim, Parma_Polyhedra_Library::Variables_Set::insert(), internal_space_dim, parameters, PARTIALLY_SATISFIABLE, Parma_Polyhedra_Library::Variables_Set::space_dimension(), status, and UNSATISFIABLE.

00600                                                                {
00601   if (p_vars.space_dimension() > external_space_dim)
00602     throw std::invalid_argument("PPL::PIP_Problem::"
00603                                 "add_to_parameter_space_dimension(p_vars):\n"
00604                                 "*this and p_vars are dimension "
00605                                 "incompatible.");
00606   const dimension_type original_size = parameters.size();
00607   parameters.insert(p_vars.begin(), p_vars.end());
00608   // Do not allow to turn variables into parameters.
00609   for (Variables_Set::const_iterator p = p_vars.begin(),
00610          end = p_vars.end(); p != end; ++p) {
00611     if (*p < internal_space_dim) {
00612       throw std::invalid_argument("PPL::PIP_Problem::"
00613                                   "add_to_parameter_space_dimension(p_vars):"
00614                                   "p_vars contain variable indices.");
00615     }
00616   }
00617 
00618   // If a new parameter was inserted, set the internal status to
00619   // PARTIALLY_SATISFIABLE.
00620   if (parameters.size() != original_size && status != UNSATISFIABLE)
00621     status = PARTIALLY_SATISFIABLE;
00622 }

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

Writes to s an ASCII representation of *this.

Definition at line 344 of file PIP_Problem.cc.

References Parma_Polyhedra_Library::PIP_Tree_Node::as_decision(), Parma_Polyhedra_Library::PIP_Tree_Node::as_solution(), Parma_Polyhedra_Library::PIP_Solution_Node::ascii_dump(), Parma_Polyhedra_Library::Matrix::ascii_dump(), Parma_Polyhedra_Library::Variables_Set::ascii_dump(), ascii_dump(), big_parameter_dimension, CONTROL_PARAMETER_NAME_SIZE, control_parameters, current_solution, CUTTING_STRATEGY_ALL, CUTTING_STRATEGY_DEEPEST, CUTTING_STRATEGY_FIRST, external_space_dim, first_pending_constraint, initial_context, input_cs, internal_space_dim, OPTIMIZED, parameters, PARTIALLY_SATISFIABLE, PIVOT_ROW_STRATEGY_FIRST, PIVOT_ROW_STRATEGY_MAX_COLUMN, status, and UNSATISFIABLE.

00344                                               {
00345   using namespace IO_Operators;
00346   s << "\nexternal_space_dim: " << external_space_dim << "\n";
00347   s << "\ninternal_space_dim: " << internal_space_dim << "\n";
00348 
00349   const dimension_type input_cs_size = input_cs.size();
00350 
00351   s << "\ninput_cs( " << input_cs_size << " )\n";
00352   for (dimension_type i = 0; i < input_cs_size; ++i)
00353     input_cs[i].ascii_dump(s);
00354 
00355   s << "\nfirst_pending_constraint: " <<  first_pending_constraint << "\n";
00356 
00357   s << "\nstatus: ";
00358   switch (status) {
00359   case UNSATISFIABLE:
00360     s << "UNSATISFIABLE";
00361     break;
00362   case OPTIMIZED:
00363     s << "OPTIMIZED";
00364     break;
00365   case PARTIALLY_SATISFIABLE:
00366     s << "PARTIALLY_SATISFIABLE";
00367     break;
00368   }
00369   s << "\n";
00370 
00371   s << "\nparameters";
00372   parameters.ascii_dump(s);
00373 
00374   s << "\ninitial_context\n";
00375   initial_context.ascii_dump(s);
00376 
00377   s << "\ncontrol_parameters\n";
00378   for (dimension_type i = 0; i < CONTROL_PARAMETER_NAME_SIZE; ++i) {
00379     Control_Parameter_Value value = control_parameters[i];
00380     switch (value) {
00381     case CUTTING_STRATEGY_FIRST:
00382       s << "CUTTING_STRATEGY_FIRST";
00383       break;
00384     case CUTTING_STRATEGY_DEEPEST:
00385       s << "CUTTING_STRATEGY_DEEPEST";
00386       break;
00387     case CUTTING_STRATEGY_ALL:
00388       s << "CUTTING_STRATEGY_ALL";
00389       break;
00390     case PIVOT_ROW_STRATEGY_FIRST:
00391       s << "PIVOT_ROW_STRATEGY_FIRST";
00392       break;
00393     case PIVOT_ROW_STRATEGY_MAX_COLUMN:
00394       s << "PIVOT_ROW_STRATEGY_MAX_COLUMN";
00395       break;
00396     default:
00397       s << "Invalid control parameter value";
00398     }
00399     s << "\n";
00400   }
00401 
00402   s << "\nbig_parameter_dimension: " << big_parameter_dimension << "\n";
00403 
00404   s << "\ncurrent_solution: ";
00405   if (current_solution == 0)
00406     s << "BOTTOM\n";
00407   else if (const PIP_Decision_Node* dec = current_solution->as_decision()) {
00408     s << "DECISION\n";
00409     dec->ascii_dump(s);
00410   }
00411   else {
00412     const PIP_Solution_Node* sol = current_solution->as_solution();
00413     PPL_ASSERT(sol != 0);
00414     s << "SOLUTION\n";
00415     sol->ascii_dump(s);
00416   }
00417 }

void Parma_Polyhedra_Library::PIP_Problem::ascii_dump (  )  const

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

Referenced by ascii_dump(), and OK().

bool Parma_Polyhedra_Library::PIP_Problem::ascii_load ( std::istream &  s  ) 

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

Definition at line 422 of file PIP_Problem.cc.

References Parma_Polyhedra_Library::PIP_Solution_Node::ascii_load(), Parma_Polyhedra_Library::PIP_Decision_Node::ascii_load(), Parma_Polyhedra_Library::Constraint::ascii_load(), Parma_Polyhedra_Library::PIP_Solution_Node::set_owner(), Parma_Polyhedra_Library::PIP_Decision_Node::set_owner(), and Parma_Polyhedra_Library::Constraint::zero_dim_positivity().

00422                                         {
00423   std::string str;
00424   if (!(s >> str) || str != "external_space_dim:")
00425     return false;
00426 
00427   if (!(s >> external_space_dim))
00428     return false;
00429 
00430   if (!(s >> str) || str != "internal_space_dim:")
00431     return false;
00432 
00433   if (!(s >> internal_space_dim))
00434     return false;
00435 
00436   if (!(s >> str) || str != "input_cs(")
00437     return false;
00438 
00439   dimension_type input_cs_size;
00440 
00441   if (!(s >> input_cs_size))
00442     return false;
00443 
00444   if (!(s >> str) || str != ")")
00445     return false;
00446 
00447   Constraint c(Constraint::zero_dim_positivity());
00448   for (dimension_type i = 0; i < input_cs_size; ++i) {
00449     if (!c.ascii_load(s))
00450       return false;
00451     input_cs.push_back(c);
00452   }
00453 
00454   if (!(s >> str) || str != "first_pending_constraint:")
00455     return false;
00456 
00457   if (!(s >> first_pending_constraint))
00458     return false;
00459 
00460   if (!(s >> str) || str != "status:")
00461     return false;
00462 
00463   if (!(s >> str))
00464     return false;
00465 
00466   if (str == "UNSATISFIABLE")
00467     status = UNSATISFIABLE;
00468   else if (str == "OPTIMIZED")
00469     status = OPTIMIZED;
00470   else if (str == "PARTIALLY_SATISFIABLE")
00471     status = PARTIALLY_SATISFIABLE;
00472   else
00473     return false;
00474 
00475   if (!(s >> str) || str != "parameters")
00476     return false;
00477 
00478   if (!parameters.ascii_load(s))
00479     return false;
00480 
00481   if (!(s >> str) || str != "initial_context")
00482     return false;
00483 
00484   if (!initial_context.ascii_load(s))
00485     return false;
00486 
00487   if (!(s >> str) || str != "control_parameters")
00488     return false;
00489 
00490   for (dimension_type i = 0; i < CONTROL_PARAMETER_NAME_SIZE; ++i) {
00491     if (!(s >> str))
00492       return false;
00493     Control_Parameter_Value value;
00494     if (str == "CUTTING_STRATEGY_FIRST")
00495       value = CUTTING_STRATEGY_FIRST;
00496     else if (str == "CUTTING_STRATEGY_DEEPEST")
00497       value = CUTTING_STRATEGY_DEEPEST;
00498     else if (str == "CUTTING_STRATEGY_ALL")
00499       value = CUTTING_STRATEGY_ALL;
00500     else if (str == "PIVOT_ROW_STRATEGY_FIRST")
00501       value = PIVOT_ROW_STRATEGY_FIRST;
00502     else if (str == "PIVOT_ROW_STRATEGY_MAX_COLUMN")
00503       value = PIVOT_ROW_STRATEGY_MAX_COLUMN;
00504     else
00505       return false;
00506     control_parameters[i] = value;
00507   }
00508 
00509   if (!(s >> str) || str != "big_parameter_dimension:")
00510     return false;
00511   if (!(s >> big_parameter_dimension))
00512     return false;
00513 
00514   // Release current_solution tree (if any).
00515   delete current_solution;
00516   current_solution = 0;
00517   // Load current_solution (if any).
00518   if (!(s >> str) || str != "current_solution:")
00519     return false;
00520   if (!(s >> str))
00521     return false;
00522   if (str == "BOTTOM")
00523     current_solution = 0;
00524   else if (str == "DECISION") {
00525     PIP_Decision_Node* dec = new PIP_Decision_Node(0, 0, 0);
00526     current_solution = dec;
00527     if (!dec->ascii_load(s))
00528       return false;
00529     dec->set_owner(this);
00530   }
00531   else if (str == "SOLUTION") {
00532     PIP_Solution_Node* sol = new PIP_Solution_Node(0);
00533     current_solution = sol;
00534     if (!sol->ascii_load(s))
00535       return false;
00536     sol->set_owner(this);
00537   }
00538   else
00539     // Unknown node kind.
00540     return false;
00541 
00542   PPL_ASSERT(OK());
00543   return true;
00544 }

void Parma_Polyhedra_Library::PIP_Problem::clear (  ) 

Resets *this to be equal to the trivial PIP problem.

The space dimension is reset to $0$.

Definition at line 547 of file PIP_Problem.cc.

References big_parameter_dimension, Parma_Polyhedra_Library::Matrix::clear(), control_parameters_init(), current_solution, external_space_dim, first_pending_constraint, initial_context, input_cs, internal_space_dim, Parma_Polyhedra_Library::not_a_dimension(), parameters, PARTIALLY_SATISFIABLE, and status.

00547                       {
00548   external_space_dim = 0;
00549   internal_space_dim = 0;
00550   status = PARTIALLY_SATISFIABLE;
00551   if (current_solution != 0) {
00552     delete current_solution;
00553     current_solution = 0;
00554   }
00555   input_cs.clear();
00556   first_pending_constraint = 0;
00557   parameters.clear();
00558   initial_context.clear();
00559   control_parameters_init();
00560   big_parameter_dimension = not_a_dimension();
00561 }

PIP_Problem::const_iterator Parma_Polyhedra_Library::PIP_Problem::constraints_begin (  )  const [inline]

Returns a read-only iterator to the first constraint defining the feasible region.

Definition at line 40 of file PIP_Problem.inlines.hh.

References input_cs.

Referenced by operator<<().

00040                                      {
00041   return input_cs.begin();
00042 }

PIP_Problem::const_iterator Parma_Polyhedra_Library::PIP_Problem::constraints_end (  )  const [inline]

Returns a past-the-end read-only iterator to the sequence of constraints defining the feasible region.

Definition at line 45 of file PIP_Problem.inlines.hh.

References input_cs.

Referenced by operator<<().

00045                                    {
00046   return input_cs.end();
00047 }

void Parma_Polyhedra_Library::PIP_Problem::control_parameters_copy ( const PIP_Problem y  )  [private]

Copies the control parameters from problem object y.

Definition at line 95 of file PIP_Problem.cc.

References CONTROL_PARAMETER_NAME_SIZE, and control_parameters.

Referenced by PIP_Problem().

00095                                                             {
00096   for (dimension_type i = CONTROL_PARAMETER_NAME_SIZE; i-- > 0; )
00097     control_parameters[i] = y.control_parameters[i];
00098 }

void Parma_Polyhedra_Library::PIP_Problem::control_parameters_init (  )  [private]

Initializes the control parameters with default values.

Definition at line 89 of file PIP_Problem.cc.

References control_parameters, CUTTING_STRATEGY, CUTTING_STRATEGY_FIRST, PIVOT_ROW_STRATEGY, and PIVOT_ROW_STRATEGY_FIRST.

Referenced by clear(), and PIP_Problem().

PPL::memory_size_type Parma_Polyhedra_Library::PIP_Problem::external_memory_in_bytes (  )  const

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

Definition at line 689 of file PIP_Problem.cc.

References current_solution, Parma_Polyhedra_Library::Matrix::external_memory_in_bytes(), initial_context, input_cs, parameters, and Parma_Polyhedra_Library::PIP_Tree_Node::total_memory_in_bytes().

Referenced by total_memory_in_bytes().

00689                                                {
00690   memory_size_type n = initial_context.external_memory_in_bytes();
00691   // Adding the external memory for `current_solution'.
00692   if (current_solution)
00693     n += current_solution->total_memory_in_bytes();
00694   // Adding the external memory for `input_cs'.
00695   n += input_cs.capacity() * sizeof(Constraint);
00696   for (const_iterator i = input_cs.begin(),
00697          i_end = input_cs.end(); i != i_end; ++i)
00698     n += (i->external_memory_in_bytes());
00699   // FIXME: Adding the external memory for `parameters'.
00700   n += parameters.size() * sizeof(dimension_type);
00701 
00702   return n;
00703 }

dimension_type Parma_Polyhedra_Library::PIP_Problem::get_big_parameter_dimension (  )  const [inline]

Returns the space dimension for the big parameter.

If a big parameter was not set, returns not_a_dimension().

Definition at line 83 of file PIP_Problem.inlines.hh.

References big_parameter_dimension.

Referenced by operator<<().

00083                                                {
00084   return big_parameter_dimension;
00085 }

PIP_Problem::Control_Parameter_Value Parma_Polyhedra_Library::PIP_Problem::get_control_parameter ( Control_Parameter_Name  name  )  const [inline]

Returns the value of control parameter name.

Definition at line 77 of file PIP_Problem.inlines.hh.

References CONTROL_PARAMETER_NAME_SIZE, and control_parameters.

00077                                                                  {
00078   PPL_ASSERT(n >= 0 && n < CONTROL_PARAMETER_NAME_SIZE);
00079   return control_parameters[n];
00080 }

bool Parma_Polyhedra_Library::PIP_Problem::is_satisfiable (  )  const

Checks satisfiability of *this.

Returns:
true if and only if the PIP problem is satisfiable.

Definition at line 647 of file PIP_Problem.cc.

References OPTIMIZED, PARTIALLY_SATISFIABLE, solve(), and status.

00647                                      {
00648   if (status == PARTIALLY_SATISFIABLE)
00649     solve();
00650   return status == OPTIMIZED;
00651 }

dimension_type Parma_Polyhedra_Library::PIP_Problem::max_space_dimension (  )  [inline, static]

Returns the maximum space dimension a PIP_Problem can handle.

Definition at line 35 of file PIP_Problem.inlines.hh.

Referenced by add_space_dimensions_and_embed(), and PIP_Problem().

00035                                  {
00036   return Constraint::max_space_dimension();
00037 }

bool Parma_Polyhedra_Library::PIP_Problem::OK (  )  const

Checks if all the invariants are satisfied.

Definition at line 246 of file PIP_Problem.cc.

References ascii_dump(), big_parameter_dimension, Parma_Polyhedra_Library::PIP_Tree_Node::check_ownership(), control_parameters, current_solution, CUTTING_STRATEGY, CUTTING_STRATEGY_ALL, CUTTING_STRATEGY_DEEPEST, CUTTING_STRATEGY_FIRST, external_space_dim, initial_context, input_cs, internal_space_dim, Parma_Polyhedra_Library::not_a_dimension(), Parma_Polyhedra_Library::PIP_Tree_Node::OK(), Parma_Polyhedra_Library::Matrix::OK(), Parma_Polyhedra_Library::Variables_Set::OK(), parameters, PIVOT_ROW_STRATEGY, PIVOT_ROW_STRATEGY_FIRST, PIVOT_ROW_STRATEGY_MAX_COLUMN, and space_dimension().

Referenced by add_space_dimensions_and_embed(), PIP_Problem(), and solve().

00246                          {
00247 #ifndef NDEBUG
00248   using std::endl;
00249   using std::cerr;
00250 #endif
00251 
00252   if (external_space_dim < internal_space_dim) {
00253 #ifndef NDEBUG
00254       cerr << "The internal space dimension of the PIP_Problem is "
00255            << "greater than its external space dimension."
00256            << endl;
00257       ascii_dump(cerr);
00258 #endif
00259       return false;
00260     }
00261 
00262   // Constraint system should be OK.
00263   const dimension_type input_cs_num_rows = input_cs.size();
00264   for (dimension_type i = input_cs_num_rows; i-- > 0; )
00265     if (!input_cs[i].OK())
00266       return false;
00267 
00268   // Constraint system should be space dimension compatible.
00269   for (dimension_type i = input_cs_num_rows; i-- > 0; ) {
00270     if (input_cs[i].space_dimension() > external_space_dim) {
00271 #ifndef NDEBUG
00272       cerr << "The space dimension of the PIP_Problem is smaller than "
00273            << "the space dimension of one of its constraints."
00274            << endl;
00275       ascii_dump(cerr);
00276 #endif
00277       return false;
00278     }
00279   }
00280 
00281   // Test validity of control parameter values.
00282   Control_Parameter_Value strategy = control_parameters[CUTTING_STRATEGY];
00283   if (strategy != CUTTING_STRATEGY_FIRST
00284       && strategy != CUTTING_STRATEGY_DEEPEST
00285       && strategy != CUTTING_STRATEGY_ALL) {
00286 #ifndef NDEBUG
00287     cerr << "Invalid value for the CUTTING_STRATEGY control parameter."
00288          << endl;
00289     ascii_dump(cerr);
00290 #endif
00291     return false;
00292   }
00293 
00294   strategy = control_parameters[PIVOT_ROW_STRATEGY];
00295   if (strategy < PIVOT_ROW_STRATEGY_FIRST
00296       || strategy > PIVOT_ROW_STRATEGY_MAX_COLUMN) {
00297 #ifndef NDEBUG
00298     cerr << "Invalid value for the PIVOT_ROW_STRATEGY control parameter."
00299         << endl;
00300     ascii_dump(cerr);
00301 #endif
00302     return false;
00303   }
00304 
00305   if (big_parameter_dimension != not_a_dimension()
00306       && parameters.count(big_parameter_dimension) == 0) {
00307 #ifndef NDEBUG
00308     cerr << "The big parameter is set, but it is not a parameter." << endl;
00309     ascii_dump(cerr);
00310 #endif
00311     return false;
00312   }
00313 
00314   if (!parameters.OK())
00315     return false;
00316   if (!initial_context.OK())
00317     return false;
00318 
00319   if (current_solution) {
00320     // Check well formedness of the solution tree.
00321     if (!current_solution->OK()) {
00322 #ifndef NDEBUG
00323       cerr << "The computed solution tree is broken.\n";
00324       ascii_dump(cerr);
00325 #endif
00326       return false;
00327     }
00328     // Check that all nodes in the solution tree belong to *this.
00329     if (!current_solution->check_ownership(this)) {
00330 #ifndef NDEBUG
00331       cerr << "There are nodes in the solution tree "
00332            << "that are not owned by *this.\n";
00333       ascii_dump(cerr);
00334 #endif
00335       return false;
00336     }
00337   }
00338 
00339   // All checks passed.
00340   return true;
00341 }

PIP_Problem & Parma_Polyhedra_Library::PIP_Problem::operator= ( const PIP_Problem y  )  [inline]

Assignment operator.

Definition at line 70 of file PIP_Problem.inlines.hh.

References swap().

00070                                            {
00071   PIP_Problem tmp(y);
00072   swap(tmp);
00073   return *this;
00074 }

PPL::PIP_Tree Parma_Polyhedra_Library::PIP_Problem::optimizing_solution (  )  const

Returns an optimizing solution for *this, if it exists.

A null pointer is returned for an unfeasible PIP problem.

Definition at line 239 of file PIP_Problem.cc.

References current_solution, PARTIALLY_SATISFIABLE, solve(), and status.

00239                                           {
00240   if (status == PARTIALLY_SATISFIABLE)
00241     solve();
00242   return current_solution;
00243 }

const Variables_Set & Parma_Polyhedra_Library::PIP_Problem::parameter_space_dimensions (  )  const [inline]

Returns a set containing all the variables' indexes representing the parameters of the PIP problem.

Definition at line 50 of file PIP_Problem.inlines.hh.

References parameters.

Referenced by operator<<(), Parma_Polyhedra_Library::PIP_Solution_Node::parametric_values(), Parma_Polyhedra_Library::PIP_Tree_Node::print(), and Parma_Polyhedra_Library::PIP_Solution_Node::update_solution().

00050                                               {
00051   return parameters;
00052 }

void Parma_Polyhedra_Library::PIP_Problem::print (  )  const

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

void Parma_Polyhedra_Library::PIP_Problem::print_solution ( std::ostream &  s,
unsigned  indent = 0 
) const

Prints on s the solution computed for *this.

Parameters:
s The output stream.
indent An indentation parameter (default value 0).
Exceptions:
std::logic_error Thrown if trying to print the solution when the PIP problem still has to be solved.

Definition at line 711 of file PIP_Problem.cc.

References current_solution, Parma_Polyhedra_Library::PIP_Tree_Node::indent_and_print(), OPTIMIZED, PARTIALLY_SATISFIABLE, Parma_Polyhedra_Library::PIP_Tree_Node::print(), status, and UNSATISFIABLE.

00711                                                                    {
00712   switch (status) {
00713 
00714   case UNSATISFIABLE:
00715     PPL_ASSERT(current_solution == 0);
00716     PIP_Tree_Node::indent_and_print(s, indent, "_|_\n");
00717     break;
00718 
00719   case OPTIMIZED:
00720     PPL_ASSERT(current_solution != 0);
00721     current_solution->print(s, indent);
00722     break;
00723 
00724   case PARTIALLY_SATISFIABLE:
00725     throw std::logic_error("PIP_Problem::print_solution():\n"
00726                            "the PIP problem has not been solved.");
00727   }
00728 }

void Parma_Polyhedra_Library::PIP_Problem::set_big_parameter_dimension ( dimension_type  big_dim  ) 

Sets the dimension for the big parameter to big_dim.

Definition at line 675 of file PIP_Problem.cc.

References big_parameter_dimension, internal_space_dim, and parameters.

00675                                                                   {
00676   if (parameters.count(big_dim) == 0)
00677     throw std::invalid_argument("PPL::PIP_Problem::"
00678                                 "set_big_parameter_dimension(big_dim):\n"
00679                                 "dimension 'big_dim' is not a parameter.");
00680   if (big_dim < internal_space_dim)
00681     throw std::invalid_argument("PPL::PIP_Problem::"
00682                                 "set_big_parameter_dimension(big_dim):\n"
00683                                 "only newly-added parameters can be"
00684                                 "converted into the big parameter.");
00685   big_parameter_dimension = big_dim;
00686 }

void Parma_Polyhedra_Library::PIP_Problem::set_control_parameter ( Control_Parameter_Value  value  ) 

Sets control parameter value.

Definition at line 654 of file PIP_Problem.cc.

References control_parameters, CUTTING_STRATEGY, CUTTING_STRATEGY_ALL, CUTTING_STRATEGY_DEEPEST, CUTTING_STRATEGY_FIRST, PIVOT_ROW_STRATEGY, PIVOT_ROW_STRATEGY_FIRST, and PIVOT_ROW_STRATEGY_MAX_COLUMN.

00654                                                                    {
00655   switch (value) {
00656   case CUTTING_STRATEGY_FIRST:
00657     // Intentionally fall through.
00658   case CUTTING_STRATEGY_DEEPEST:
00659     // Intentionally fall through.
00660   case CUTTING_STRATEGY_ALL:
00661     control_parameters[CUTTING_STRATEGY] = value;
00662     break;
00663   case PIVOT_ROW_STRATEGY_FIRST:
00664     // Intentionally fall through.
00665   case PIVOT_ROW_STRATEGY_MAX_COLUMN:
00666     control_parameters[PIVOT_ROW_STRATEGY] = value;
00667     break;
00668   default:
00669     throw std::invalid_argument("PPL::PIP_Problem::set_control_parameter(v)"
00670                                 ":\ninvalid value.");
00671   }
00672 }

PPL::PIP_Tree Parma_Polyhedra_Library::PIP_Problem::solution (  )  const

Returns a feasible solution for *this, if it exists.

A null pointer is returned for an unfeasible PIP problem.

Definition at line 232 of file PIP_Problem.cc.

References current_solution, PARTIALLY_SATISFIABLE, solve(), and status.

00232                                {
00233   if (status == PARTIALLY_SATISFIABLE)
00234     solve();
00235   return current_solution;
00236 }

PPL::PIP_Problem_Status Parma_Polyhedra_Library::PIP_Problem::solve (  )  const

Optimizes the PIP problem.

Returns:
A PIP_Problem_Status flag indicating the outcome of the optimization attempt (unfeasible or optimized problem).

Definition at line 101 of file PIP_Problem.cc.

References Parma_Polyhedra_Library::Matrix::add_row(), Parma_Polyhedra_Library::Matrix::add_zero_columns(), Parma_Polyhedra_Library::Constraint::coefficient(), Parma_Polyhedra_Library::PIP_Tree_Node::compatibility_check(), current_solution, external_space_dim, first_pending_constraint, Parma_Polyhedra_Library::Constraint::inhomogeneous_term(), initial_context, input_cs, internal_space_dim, Parma_Polyhedra_Library::Constraint::is_equality(), Parma_Polyhedra_Library::Constraint::is_strict_inequality(), Parma_Polyhedra_Library::neg_assign(), Parma_Polyhedra_Library::Matrix::num_columns(), OK(), OPTIMIZED, Parma_Polyhedra_Library::OPTIMIZED_PIP_PROBLEM, parameters, PARTIALLY_SATISFIABLE, PIP_Solution_Node, Parma_Polyhedra_Library::PIP_Tree_Node::solve(), Parma_Polyhedra_Library::Constraint::space_dimension(), status, Parma_Polyhedra_Library::UNFEASIBLE_PIP_PROBLEM, UNSATISFIABLE, and Parma_Polyhedra_Library::PIP_Tree_Node::update_tableau().

Referenced by is_satisfiable(), optimizing_solution(), and solution().

00101                             {
00102   switch (status) {
00103 
00104   case UNSATISFIABLE:
00105     PPL_ASSERT(OK());
00106     return UNFEASIBLE_PIP_PROBLEM;
00107 
00108   case OPTIMIZED:
00109     PPL_ASSERT(OK());
00110     return OPTIMIZED_PIP_PROBLEM;
00111 
00112   case PARTIALLY_SATISFIABLE:
00113     {
00114       PIP_Problem& x = const_cast<PIP_Problem&>(*this);
00115       // Allocate PIP solution tree root, if needed.
00116       if (current_solution == 0)
00117         x.current_solution = new PIP_Solution_Node(this);
00118 
00119       // Properly resize context matrix.
00120       const dimension_type new_num_cols = parameters.size() + 1;
00121       const dimension_type old_num_cols = initial_context.num_columns();
00122       if (old_num_cols < new_num_cols)
00123         x.initial_context.add_zero_columns(new_num_cols - old_num_cols);
00124 
00125       // Computed once for all (to be used inside loop).
00126       const Variables_Set::const_iterator param_begin = parameters.begin();
00127       const Variables_Set::const_iterator param_end = parameters.end();
00128 
00129       // This flag will be set if we insert a pending constraint
00130       // in the initial context.
00131       bool check_feasible_context = false;
00132 
00133       // Go through all pending constraints.
00134       for (Constraint_Sequence::const_iterator
00135              cs_i = input_cs.begin() + first_pending_constraint,
00136              cs_end = input_cs.end(); cs_i != cs_end; ++cs_i) {
00137         const Constraint& c = *cs_i;
00138         const dimension_type c_space_dim = c.space_dimension();
00139         PPL_ASSERT(external_space_dim >= c_space_dim);
00140 
00141         // Check if constraint has a non-zero variable coefficient.
00142         bool has_nonzero_variable_coefficient = false;
00143         for (dimension_type i = c_space_dim; i-- > 0; ) {
00144           if (c.coefficient(Variable(i)) != 0
00145               && parameters.count(i) == 0) {
00146             has_nonzero_variable_coefficient = true;
00147             break;
00148           }
00149         }
00150         // Constraints having a non-zero variable coefficient
00151         // should not be inserted in context.
00152         if (has_nonzero_variable_coefficient)
00153           continue;
00154 
00155         check_feasible_context = true;
00156 
00157         // Translate constraint into context row.
00158         Row row(new_num_cols, Row::Flags());
00159         row[0] = c.inhomogeneous_term();
00160         {
00161           dimension_type i = 1;
00162           for (Variables_Set::const_iterator
00163                  pi = param_begin; pi != param_end; ++pi, ++i) {
00164             if (*pi < c_space_dim)
00165               row[i] = c.coefficient(Variable(*pi));
00166             else
00167               break;
00168           }
00169         }
00170         // Adjust inhomogenous term if strict.
00171         if (c.is_strict_inequality())
00172           --row[0];
00173 
00174         // Insert new row into initial context.
00175         x.initial_context.add_row(row);
00176 
00177         // If it is an equality, also insert its negation.
00178         if (c.is_equality()) {
00179           for (dimension_type i = new_num_cols; i-- > 0; )
00180             neg_assign(row[i], row[i]);
00181 
00182           // Insert new row into initial context.
00183           x.initial_context.add_row(row);
00184         }
00185       }
00186 
00187       if (check_feasible_context) {
00188         // Check for feasibility of initial context.
00189         Matrix ctx_copy(initial_context);
00190         if (!PIP_Solution_Node::compatibility_check(ctx_copy)) {
00191           // Problem found to be unfeasible.
00192           delete x.current_solution;
00193           x.current_solution = 0;
00194           x.status = UNSATISFIABLE;
00195           PPL_ASSERT(OK());
00196           return UNFEASIBLE_PIP_PROBLEM;
00197         }
00198       }
00199 
00200       // Update tableau and mark constraints as no longer pending.
00201       x.current_solution->update_tableau(*this,
00202                                          external_space_dim,
00203                                          first_pending_constraint,
00204                                          input_cs,
00205                                          parameters);
00206       x.internal_space_dim = external_space_dim;
00207       x.first_pending_constraint = input_cs.size();
00208 
00209       // Actually solve problem.
00210       x.current_solution = x.current_solution->solve(*this,
00211                                                      check_feasible_context,
00212                                                      initial_context,
00213                                                      parameters,
00214                                                      external_space_dim,
00215                                                      /*indent_level=*/ 0);
00216       // Update problem status.
00217       x.status = (x.current_solution) ? OPTIMIZED : UNSATISFIABLE;
00218 
00219       PPL_ASSERT(OK());
00220       return (x.current_solution)
00221         ? OPTIMIZED_PIP_PROBLEM
00222         : UNFEASIBLE_PIP_PROBLEM;
00223     } // End of handler for PARTIALLY_SATISFIABLE case.
00224 
00225   } // End of switch.
00226 
00227   // We should not be here!
00228   throw std::runtime_error("PPL internal error");
00229 }

dimension_type Parma_Polyhedra_Library::PIP_Problem::space_dimension (  )  const [inline]
void Parma_Polyhedra_Library::PIP_Problem::swap ( PIP_Problem y  )  [inline]

Swaps *this with y.

Definition at line 55 of file PIP_Problem.inlines.hh.

References big_parameter_dimension, CONTROL_PARAMETER_NAME_SIZE, control_parameters, current_solution, external_space_dim, first_pending_constraint, initial_context, input_cs, internal_space_dim, parameters, status, and Parma_Polyhedra_Library::swap().

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

00055                                 {
00056   std::swap(external_space_dim, y.external_space_dim);
00057   std::swap(internal_space_dim, y.internal_space_dim);
00058   std::swap(status, y.status);
00059   std::swap(current_solution, y.current_solution);
00060   std::swap(input_cs, y.input_cs);
00061   std::swap(first_pending_constraint, y.first_pending_constraint);
00062   std::swap(parameters, y.parameters);
00063   std::swap(initial_context, y.initial_context);
00064   for (dimension_type i = CONTROL_PARAMETER_NAME_SIZE; i-- > 0; )
00065     std::swap(control_parameters[i], y.control_parameters[i]);
00066   std::swap(big_parameter_dimension, y.big_parameter_dimension);
00067 }

PPL::memory_size_type Parma_Polyhedra_Library::PIP_Problem::total_memory_in_bytes (  )  const

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

Definition at line 706 of file PIP_Problem.cc.

References external_memory_in_bytes().

00706                                             {
00707   return sizeof(*this) + external_memory_in_bytes();
00708 }


Friends And Related Function Documentation

std::ostream & operator<< ( std::ostream &  s,
const PIP_Problem pip 
) [related]

Output operator.

Definition at line 32 of file PIP_Problem.cc.

References constraints_begin(), constraints_end(), get_big_parameter_dimension(), Parma_Polyhedra_Library::not_a_dimension(), parameter_space_dimensions(), and space_dimension().

00032                                                                  {
00033   s << "Space dimension: " << pip.space_dimension();
00034   s << "\nConstraints:";
00035   for (PIP_Problem::const_iterator i = pip.constraints_begin(),
00036          i_end = pip.constraints_end(); i != i_end; ++i)
00037     s << "\n" << *i;
00038   s << "\nProblem parameters: " << pip.parameter_space_dimensions();
00039   if (pip.get_big_parameter_dimension() == not_a_dimension())
00040     s << "\nNo big-parameter set.\n";
00041   else
00042     s << "\nBig-parameter: " << Variable(pip.get_big_parameter_dimension());
00043   s << "\n";
00044   return s;
00045 }

friend class PIP_Solution_Node [friend]

Definition at line 816 of file PIP_Problem.defs.hh.

Referenced by solve().

Specializes std::swap.

Definition at line 93 of file PIP_Problem.inlines.hh.

References swap().

00094                                             {
00095   x.swap(y);
00096 }


Member Data Documentation

The current solution decision tree.

Definition at line 785 of file PIP_Problem.defs.hh.

Referenced by ascii_dump(), clear(), external_memory_in_bytes(), OK(), optimizing_solution(), PIP_Problem(), print_solution(), solution(), solve(), swap(), and ~PIP_Problem().

The first index of `input_cs' containing a pending constraint.

Definition at line 791 of file PIP_Problem.defs.hh.

Referenced by ascii_dump(), clear(), solve(), and swap().

The initial context.

Contains problem constraints on parameters only

Definition at line 804 of file PIP_Problem.defs.hh.

Referenced by ascii_dump(), clear(), external_memory_in_bytes(), OK(), solve(), and swap().

The sequence of constraints describing the feasible region.

Definition at line 788 of file PIP_Problem.defs.hh.

Referenced by add_constraint(), ascii_dump(), clear(), constraints_begin(), constraints_end(), external_memory_in_bytes(), OK(), PIP_Problem(), solve(), and swap().

The space dimension of the current (partial) solution of the PIP problem; it may be smaller than external_space_dim.

Definition at line 765 of file PIP_Problem.defs.hh.

Referenced by add_to_parameter_space_dimensions(), ascii_dump(), clear(), OK(), set_big_parameter_dimension(), solve(), swap(), and Parma_Polyhedra_Library::PIP_Solution_Node::update_tableau().

A set containing all the indices of space dimensions that are interpreted as problem parameters.

Definition at line 797 of file PIP_Problem.defs.hh.

Referenced by add_space_dimensions_and_embed(), add_to_parameter_space_dimensions(), ascii_dump(), clear(), external_memory_in_bytes(), OK(), parameter_space_dimensions(), set_big_parameter_dimension(), solve(), and swap().


The documentation for this class was generated from the following files:
Generated on Sun Feb 27 16:20:31 2011 for PPL by  doxygen 1.6.3