1 /* PIP_Problem class declaration.
2    Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
3    Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
4 
5 This file is part of the Parma Polyhedra Library (PPL).
6 
7 The PPL is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 The PPL is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
20 
21 For the most up-to-date information see the Parma Polyhedra Library
22 site: http://bugseng.com/products/ppl/ . */
23 
24 #ifndef PPL_PIP_Problem_defs_hh
25 #define PPL_PIP_Problem_defs_hh 1
26 
27 #include "PIP_Problem_types.hh"
28 #include "PIP_Tree_types.hh"
29 #include "globals_types.hh"
30 #include "Linear_Expression_defs.hh"
31 #include "Matrix_defs.hh"
32 #include "Constraint_defs.hh"
33 #include "Constraint_System_types.hh"
34 #include "Generator_defs.hh"
35 #include "Variables_Set_defs.hh"
36 #include <vector>
37 #include <deque>
38 #include <iosfwd>
39 
40 namespace Parma_Polyhedra_Library {
41 
42 namespace IO_Operators {
43 
44 //! Output operator.
45 /*! \relates Parma_Polyhedra_Library::PIP_Problem */
46 std::ostream&
47 operator<<(std::ostream& s, const PIP_Problem& pip);
48 
49 } // namespace IO_Operators
50 
51 //! Swaps \p x with \p y.
52 /*! \relates PIP_Problem */
53 void swap(PIP_Problem& x, PIP_Problem& y);
54 
55 } // namespace Parma_Polyhedra_Library
56 
57 //! A Parametric Integer (linear) Programming problem.
58 /*! \ingroup PPL_CXX_interface
59   An object of this class encodes a parametric integer (linear)
60   programming problem. The PIP problem is specified by providing:
61    - the dimension of the vector space;
62    - the subset of those dimensions of the vector space that are
63      interpreted as integer parameters (the other space dimensions
64      are interpreted as non-parameter integer variables);
65    - a finite set of linear equality and (strict or non-strict)
66      inequality constraints involving variables and/or parameters;
67      these constraints are used to define:
68        - the <EM>feasible region</EM>, if they involve one or more
69          problem variable (and maybe some parameters);
70        - the <EM>initial context</EM>, if they only involve the
71          parameters;
72    - optionally, the so-called <EM>big parameter</EM>,
73      i.e., a problem parameter to be considered arbitrarily big.
74 
75   Note that all problem variables and problem parameters are assumed
76   to take non-negative integer values, so that there is no need
77   to specify non-negativity constraints.
78 
79   The class provides support for the (incremental) solution of the
80   PIP problem based on variations of the revised simplex method and
81   on Gomory cut generation techniques.
82 
83   The solution for a PIP problem is the lexicographic minimum of the
84   integer points of the feasible region, expressed in terms of the
85   parameters. As the problem to be solved only involves non-negative
86   variables and parameters, the problem will always be either unfeasible
87   or optimizable.
88 
89   As the feasibility and the solution value of a PIP problem depend on the
90   values of the parameters, the solution is a binary decision tree,
91   dividing the context parameter set into subsets.
92   The tree nodes are of two kinds:
93    - \e Decision nodes.
94      These are internal tree nodes encoding one or more linear tests
95      on the parameters; if all the tests are satisfied, then the solution
96      is the node's \e true child; otherwise, the solution is the node's
97      \e false child;
98    - \e Solution nodes.
99      These are leaf nodes in the tree, encoding the solution of the problem
100      in the current context subset, where each variable is defined in terms
101      of a linear expression of the parameters.
102      Solution nodes also optionally embed a set of parameter constraints:
103      if all these constraints are satisfied, the solution is described by
104      the node, otherwise the problem has no solution.
105 
106   It may happen that a decision node has no \e false child. This means
107   that there is no solution if at least one of the corresponding
108   constraints is not satisfied. Decision nodes having two or more linear
109   tests on the parameters cannot have a \e false child. Decision nodes
110   always have a \e true child.
111 
112   Both kinds of tree nodes may also contain the definition of extra
113   parameters which are artificially introduced by the solver to enforce
114   an integral solution. Such artificial parameters are defined by
115   the integer division of a linear expression on the parameters
116   by an integer coefficient.
117 
118   By exploiting the incremental nature of the solver, it is possible
119   to reuse part of the computational work already done when solving
120   variants of a given PIP_Problem: currently, incremental resolution
121   supports the addition of space dimensions, the addition of parameters
122   and the addition of constraints.
123 
124   \par Example problem
125   An example PIP problem can be defined the following:
126   \code
127   3*j >= -2*i+8
128   j <= 4*i - 4
129   i <= n
130   j <= m
131   \endcode
132   where \c i and \c j are the problem variables
133   and \c n and \c m are the problem parameters.
134   This problem can be optimized; the resulting solution tree may be
135   represented as follows:
136   \verbatim
137   if 7*n >= 10 then
138     if 7*m >= 12 then
139       {i = 2 ; j = 2}
140     else
141       Parameter P = (m) div 2
142       if 2*n + 3*m >= 8 then
143         {i = -m - P + 4 ; j = m}
144       else
145         _|_
146   else
147     _|_
148   \endverbatim
149   The solution tree starts with a decision node depending on the
150   context constraint <code>7*n >= 10</code>.
151   If this constraint is satisfied by the values assigned to the
152   problem parameters, then the (textually first) \c then branch is taken,
153   reaching the \e true child of the root node (which in this case
154   is another decision node); otherwise, the (textually last) \c else
155   branch is taken, for which there is no corresponding \e false child.
156   \par
157   The \f$\perp\f$ notation, also called \e bottom, denotes the
158   lexicographic minimum of an empty set of solutions,
159   here meaning the corresponding subproblem is unfeasible.
160   \par
161   Notice that a tree node may introduce new (non-problem) parameters,
162   as is the case for parameter \c P in the (textually first) \c else
163   branch above. These \e artificial parameters are only meaningful
164   inside the subtree where they are defined and are used to define
165   the parametric values of the problem variables in solution nodes
166   (e.g., the <CODE>{i,j}</CODE> vector in the textually third \c then branch).
167 
168   \par Context restriction
169   The above solution is correct in an unrestricted initial context,
170   meaning all possible values are allowed for the parameters. If we
171   restrict the context with the following parameter inequalities:
172   \code
173   m >= n
174   n >= 5
175   \endcode
176   then the resulting optimizing tree will be a simple solution node:
177   \verbatim
178   {i = 2 ; j = 2}
179   \endverbatim
180 
181   \par Creating the PIP_Problem object
182   The PIP_Problem object corresponding to the above example can be
183   created as follows:
184   \code
185   Variable i(0);
186   Variable j(1);
187   Variable n(2);
188   Variable m(3);
189   Variables_Set params(n, m);
190   Constraint_System cs;
191   cs.insert(3*j >= -2*i+8);
192   cs.insert(j <= 4*i - 4);
193   cs.insert(j <= m);
194   cs.insert(i <= n);
195   PIP_Problem pip(cs.space_dimension(), cs.begin(), cs.end(), params);
196   \endcode
197   If you want to restrict the initial context, simply add the parameter
198   constraints the same way as for normal constraints.
199   \code
200   cs.insert(m >= n);
201   cs.insert(n >= 5);
202   \endcode
203 
204   \par Solving the problem
205   Once the PIP_Problem object has been created, you can start the
206   resolution of the problem by calling the solve() method:
207   \code
208   PIP_Problem_Status status = pip.solve();
209   \endcode
210   where the returned \c status indicates if the problem has been optimized
211   or if it is unfeasible for any possible configuration of the parameter
212   values. The resolution process is also started if an attempt is made
213   to get its solution, as follows:
214   \code
215   const PIP_Tree_Node* node = pip.solution();
216   \endcode
217   In this case, an unfeasible problem will result in an empty solution
218   tree, i.e., assigning a null pointer to \c node.
219 
220   \par Printing the solution tree
221   A previously computed solution tree may be printed as follows:
222   \code
223   pip.print_solution(std::cout);
224   \endcode
225   This will produce the following output (note: variables and parameters
226   are printed according to the default output function; see
227   <code>Variable::set_output_function</code>):
228   \verbatim
229   if 7*C >= 10 then
230     if 7*D >= 12 then
231       {2 ; 2}
232     else
233       Parameter E = (D) div 2
234       if 2*C + 3*D >= 8 then
235         {-D - E + 4 ; D}
236       else
237         _|_
238   else
239     _|_
240   \endverbatim
241 
242   \par Spanning the solution tree
243   A parameter assignment for a PIP problem binds each of the problem
244   parameters to a non-negative integer value. After fixing a parameter
245   assignment, the ``spanning'' of the PIP problem solution tree refers
246   to the process whereby the solution tree is navigated, starting from
247   the root node: the value of artificial parameters is computed according
248   to the parameter assignment and the node's constraints are evaluated,
249   thereby descending in either the true or the false subtree of decision
250   nodes and eventually reaching a solution node or a bottom node.
251   If a solution node is found, each of the problem variables is provided
252   with a parametric expression, which can be evaluated to a fixed value
253   using the given parameter assignment and the computed values for
254   artificial parameters.
255   \par
256   The coding of the spanning process can be done as follows.
257   First, the root of the PIP solution tree is retrieved:
258   \code
259   const PIP_Tree_Node* node = pip.solution();
260   \endcode
261   If \c node represents an unfeasible solution (i.e., \f$\perp\f$),
262   its value will be \c 0. For a non-null tree node, the virtual methods
263   \c PIP_Tree_Node::as_decision() and \c PIP_Tree_Node::as_solution()
264   can be used to check whether the node is a decision or a solution node:
265   \code
266   const PIP_Solution_Node* sol = node->as_solution();
267   if (sol != 0) {
268     // The node is a solution node
269     ...
270   }
271   else {
272     // The node is a decision node
273     const PIP_Decision_Node* dec = node->as_decision();
274     ...
275   }
276   \endcode
277   \par
278   The true (resp., false) child node of a Decision Node may be accessed by
279   using method \c PIP_Decision_Node::child_node(bool), passing \c true
280   (resp., \c false) as the input argument.
281 
282   \par Artificial parameters
283   A PIP_Tree_Node::Artificial_Parameter object represents the result
284   of the integer division of a Linear_Expression (on the other
285   parameters, including the previously-defined artificials)
286   by an integer denominator (a Coefficient object).
287   The dimensions of the artificial parameters (if any) in a tree node
288   have consecutive indices starting from <code>dim+1</code>, where the value
289   of \c dim is computed as follows:
290    - for the tree root node, \c dim is the space dimension of the PIP_Problem;
291    - for any other node of the tree, it is recursively obtained by adding
292      the value of \c dim computed for the parent node to the number of
293      artificial parameters defined in the parent node.
294   \par
295   Since the numbering of dimensions for artificial parameters follows
296   the rule above, the addition of new problem variables and/or new problem
297   parameters to an already solved PIP_Problem object (as done when
298   incrementally solving a problem) will result in the systematic
299   renumbering of all the existing artificial parameters.
300 
301   \par Node constraints
302   All kind of tree nodes can contain context constraints.
303   Decision nodes always contain at least one of them.
304   The node's local constraint system can be obtained using method
305   PIP_Tree_Node::constraints.
306   These constraints only involve parameters, including both the problem
307   parameters and the artificial parameters that have been defined
308   in nodes occurring on the path from the root node to the current node.
309   The meaning of these constraints is as follows:
310    - On a decision node, if all tests in the constraints are true, then the
311      solution is the \e true child; otherwise it is the \e false child.
312    - On a solution node, if the (possibly empty) system of constraints
313      evaluates to true for a given parameter assignment, then the solution
314      is described by the node; otherwise the solution is \f$\perp\f$
315      (i.e., the problem is unfeasible for that parameter assignment).
316 
317   \par Getting the optimal values for the variables
318   After spanning the solution tree using the given parameter assignment,
319   if a solution node has been reached, then it is possible to retrieve
320   the parametric expression for each of the problem variables using
321   method PIP_Solution_Node::parametric_values. The retrieved expression
322   will be defined in terms of all the parameters (problem parameters
323   and artificial parameters defined along the path).
324 
325   \par Solving maximization problems
326   You can solve a lexicographic maximization problem by reformulating its
327   constraints using variable substitution. Proceed the following steps:
328    - Create a big parameter (see PIP_Problem::set_big_parameter_dimension),
329      which we will call \f$M\f$.
330    - Reformulate each of the maximization problem constraints by
331      substituting each \f$x_i\f$ variable with an expression of the form
332      \f$M-x'_i\f$, where the \f$x'_i\f$ variables are positive variables to
333      be minimized.
334    - Solve the lexicographic minimum for the \f$x'\f$ variable vector.
335    - In the solution expressions, the values of the \f$x'\f$ variables will
336      be expressed in the form: \f$x'_i = M-x_i\f$. To get back the value of
337      the expression of each \f$x_i\f$ variable, just apply the
338      formula: \f$x_i = M-x'_i\f$.
339   \par
340   Note that if the resulting expression of one of the \f$x'_i\f$ variables
341   is not in the \f$x'_i = M-x_i\f$ form, this means that the
342   sign-unrestricted problem is unbounded.
343   \par
344   You can choose to maximize only a subset of the variables while minimizing
345   the other variables. In that case, just apply the variable substitution
346   method on the variables you want to be maximized. The variable
347   optimization priority will still be in lexicographic order.
348 
349   \par
350   \b Example: consider you want to find the lexicographic maximum of the
351   \f$(x,y)\f$ vector, under the constraints:
352     \f[\left\{\begin{array}{l}
353       y \geq 2x - 4\\
354       y \leq -x + p
355     \end{array}\right.\f]
356   \par
357   where \f$p\f$ is a parameter.
358   \par
359   After variable substitution, the constraints become:
360     \f[\left\{\begin{array}{l}
361       M - y \geq 2M - 2x - 4\\
362       M - y \leq -M + x + p
363     \end{array}\right.\f]
364   \par
365   The code for creating the corresponding problem object is the following:
366   \code
367   Variable x(0);
368   Variable y(1);
369   Variable p(2);
370   Variable M(3);
371   Variables_Set params(p, M);
372   Constraint_System cs;
373   cs.insert(M - y >= 2*M - 2*x - 4);
374   cs.insert(M - y <= -M + x + p);
375   PIP_Problem pip(cs.space_dimension(), cs.begin(), cs.end(), params);
376   pip.set_big_parameter_dimension(3);     // M is the big parameter
377   \endcode
378   Solving the problem provides the following solution:
379   \verbatim
380   Parameter E = (C + 1) div 3
381   {D - E - 1 ; -C + D + E + 1}
382   \endverbatim
383   Under the notations above, the solution is:
384   \f[ \left\{\begin{array}{l}
385     x' = M - \left\lfloor\frac{p+1}{3}\right\rfloor - 1 \\
386     y' = M - p + \left\lfloor\frac{p+1}{3}\right\rfloor + 1
387   \end{array}\right.
388   \f]
389   \par
390   Performing substitution again provides us with the values of the original
391   variables:
392   \f[ \left\{\begin{array}{l}
393     x = \left\lfloor\frac{p+1}{3}\right\rfloor + 1 \\
394     y = p - \left\lfloor\frac{p+1}{3}\right\rfloor - 1
395   \end{array}\right.
396   \f]
397 
398   \par Allowing variables to be arbitrarily signed
399   You can deal with arbitrarily signed variables by reformulating the
400   constraints using variable substitution. Proceed the following steps:
401    - Create a big parameter (see PIP_Problem::set_big_parameter_dimension),
402      which we will call \f$M\f$.
403    - Reformulate each of the maximization problem constraints by
404      substituting each \f$x_i\f$ variable with an expression of the form
405      \f$x'_i-M\f$, where the \f$x'_i\f$ variables are positive.
406    - Solve the lexicographic minimum for the \f$x'\f$ variable vector.
407    - The solution expression can be read in the form:
408    - In the solution expressions, the values of the \f$x'\f$ variables will
409      be expressed in the form: \f$x'_i = x_i+M\f$. To get back the value of
410      the expression of each signed \f$x_i\f$ variable, just apply the
411      formula: \f$x_i = x'_i-M\f$.
412   \par
413   Note that if the resulting expression of one of the \f$x'_i\f$ variables
414   is not in the \f$x'_i = x_i+M\f$ form, this means that the
415   sign-unrestricted problem is unbounded.
416   \par
417   You can choose to define only a subset of the variables to be
418   sign-unrestricted. In that case, just apply the variable substitution
419   method on the variables you want to be sign-unrestricted.
420 
421   \par
422   \b Example: consider you want to find the lexicographic minimum of the
423   \f$(x,y)\f$ vector, where the \f$x\f$ and \f$y\f$ variables are
424   sign-unrestricted, under the constraints:
425     \f[\left\{\begin{array}{l}
426       y \geq -2x - 4\\
427       2y \leq x + 2p
428     \end{array}\right.\f]
429   \par
430   where \f$p\f$ is a parameter.
431   \par
432   After variable substitution, the constraints become:
433     \f[\left\{\begin{array}{l}
434       y' - M \geq -2x' + 2M - 4\\
435       2y' - 2M \leq x' - M + 2p
436     \end{array}\right.\f]
437   \par
438   The code for creating the corresponding problem object is the following:
439   \code
440   Variable x(0);
441   Variable y(1);
442   Variable p(2);
443   Variable M(3);
444   Variables_Set params(p, M);
445   Constraint_System cs;
446   cs.insert(y - M >= -2*x + 2*M - 4);
447   cs.insert(2*y - 2*M <= x - M + 2*p);
448   PIP_Problem pip(cs.space_dimension(), cs.begin(), cs.end(), params);
449   pip.set_big_parameter_dimension(3);     // M is the big parameter
450   \endcode
451   \par
452   Solving the problem provides the following solution:
453   \verbatim
454   Parameter E = (2*C + 3) div 5
455   {D - E - 1 ; D + 2*E - 2}
456   \endverbatim
457   Under the notations above, the solution is:
458   \f[ \left\{\begin{array}{l}
459     x' = M - \left\lfloor\frac{2p+3}{5}\right\rfloor - 1 \\
460     y' = M + 2\left\lfloor\frac{2p+3}{5}\right\rfloor - 2
461   \end{array}\right.
462   \f]
463   \par
464   Performing substitution again provides us with the values of the original
465   variables:
466   \f[ \left\{\begin{array}{l}
467     x = -\left\lfloor\frac{2p+3}{5}\right\rfloor - 1 \\
468     y = 2\left\lfloor\frac{2p+3}{5}\right\rfloor - 2
469   \end{array}\right.
470   \f]
471 
472   \par Allowing parameters to be arbitrarily signed
473   You can consider a parameter \f$p\f$ arbitrarily signed by replacing
474   \f$p\f$ with \f$p^+-p^-\f$, where both \f$p^+\f$ and \f$p^-\f$ are
475   positive parameters. To represent a set of arbitrarily signed parameters,
476   replace each parameter \f$p_i\f$ with \f$p^+_i-p^-\f$, where \f$-p^-\f$ is
477   the minimum negative value of all parameters.
478 
479   \par Minimizing a linear cost function
480   Lexicographic solving can be used to find the parametric minimum of a
481   linear cost function.
482   \par
483   Suppose the variables are named \f$x_1, x_2, \dots, x_n\f$, and the
484   parameters \f$p_1, p_2, \dots, p_m\f$. You can minimize a linear cost
485   function \f$f(x_2, \dots, x_n, p_1, \dots, p_m)\f$ by simply adding the
486   constraint \f$x_1 \geq f(x_2, \dots, x_n, p_1, \dots, p_m)\f$ to the
487   constraint system. As lexicographic minimization ensures \f$x_1\f$ is
488   minimized in priority, and because \f$x_1\f$ is forced by a constraint to
489   be superior or equal to the cost function, optimal solutions of the
490   problem necessarily ensure that the solution value of \f$x_1\f$ is the
491   optimal value of the cost function.
492 */
493 class Parma_Polyhedra_Library::PIP_Problem {
494 public:
495   //! Builds a trivial PIP problem.
496   /*!
497     A trivial PIP problem requires to compute the lexicographic minimum
498     on a vector space under no constraints and with no parameters:
499     due to the implicit non-negativity constraints, the origin of the
500     vector space is an optimal solution.
501 
502     \param dim
503     The dimension of the vector space enclosing \p *this
504     (optional argument with default value \f$0\f$).
505 
506     \exception std::length_error
507     Thrown if \p dim exceeds <CODE>max_space_dimension()</CODE>.
508   */
509   explicit PIP_Problem(dimension_type dim = 0);
510 
511   /*! \brief
512     Builds a PIP problem having space dimension \p dim
513     from the sequence of constraints in the range
514     \f$[\mathrm{first}, \mathrm{last})\f$;
515     those dimensions whose indices occur in \p p_vars are
516     interpreted as parameters.
517 
518     \param dim
519     The dimension of the vector space (variables and parameters) enclosing
520     \p *this.
521 
522     \param first
523     An input iterator to the start of the sequence of constraints.
524 
525     \param last
526     A past-the-end input iterator to the sequence of constraints.
527 
528     \param p_vars
529     The set of variables' indexes that are interpreted as parameters.
530 
531     \exception std::length_error
532     Thrown if \p dim exceeds <CODE>max_space_dimension()</CODE>.
533 
534     \exception std::invalid_argument
535     Thrown if the space dimension of a constraint in the sequence
536     (resp., the parameter variables) is strictly greater than \p dim.
537   */
538   template <typename In>
539   PIP_Problem(dimension_type dim, In first, In last,
540               const Variables_Set& p_vars);
541 
542   //! Ordinary copy-constructor.
543   PIP_Problem(const PIP_Problem& y);
544 
545   //! Destructor.
546   ~PIP_Problem();
547 
548   //! Assignment operator.
549   PIP_Problem& operator=(const PIP_Problem& y);
550 
551   //! Returns the maximum space dimension a PIP_Problem can handle.
552   static dimension_type max_space_dimension();
553 
554   //! Returns the space dimension of the PIP problem.
555   dimension_type space_dimension() const;
556 
557   /*! \brief
558     Returns a set containing all the variables' indexes representing
559     the parameters of the PIP problem.
560   */
561   const Variables_Set& parameter_space_dimensions() const;
562 
563 private:
564   //! A type alias for a sequence of constraints.
565   typedef std::vector<Constraint> Constraint_Sequence;
566 
567 public:
568   /*! \brief
569     A type alias for the read-only iterator on the constraints
570     defining the feasible region.
571   */
572   typedef Constraint_Sequence::const_iterator const_iterator;
573 
574   /*! \brief
575     Returns a read-only iterator to the first constraint defining
576     the feasible region.
577   */
578   const_iterator constraints_begin() const;
579 
580   /*! \brief
581     Returns a past-the-end read-only iterator to the sequence of
582     constraints defining the feasible region.
583   */
584   const_iterator constraints_end() const;
585 
586   //! Resets \p *this to be equal to the trivial PIP problem.
587   /*!
588     The space dimension is reset to \f$0\f$.
589   */
590   void clear();
591 
592   /*! \brief
593     Adds <CODE>m_vars + m_params</CODE> new space dimensions
594     and embeds the old PIP problem in the new vector space.
595 
596     \param m_vars
597     The number of space dimensions to add that are interpreted as
598     PIP problem variables (i.e., non parameters). These are added
599     \e before adding the \p m_params parameters.
600 
601     \param m_params
602     The number of space dimensions to add that are interpreted as
603     PIP problem parameters. These are added \e after having added the
604     \p m_vars problem variables.
605 
606     \exception std::length_error
607     Thrown if adding <CODE>m_vars + m_params</CODE> new space
608     dimensions would cause the vector space to exceed dimension
609     <CODE>max_space_dimension()</CODE>.
610 
611     The new space dimensions will be those having the highest indexes
612     in the new PIP problem; they are initially unconstrained.
613   */
614   void add_space_dimensions_and_embed(dimension_type m_vars,
615                                       dimension_type m_params);
616 
617   /*! \brief
618     Sets the space dimensions whose indexes which are in set \p p_vars
619     to be parameter space dimensions.
620 
621     \exception std::invalid_argument
622     Thrown if some index in \p p_vars does not correspond to
623     a space dimension in \p *this.
624   */
625   void add_to_parameter_space_dimensions(const Variables_Set& p_vars);
626 
627   /*! \brief
628     Adds a copy of constraint \p c to the PIP problem.
629 
630     \exception std::invalid_argument
631     Thrown if the space dimension of \p c is strictly greater than
632     the space dimension of \p *this.
633   */
634   void add_constraint(const Constraint& c);
635 
636   /*! \brief
637     Adds a copy of the constraints in \p cs to the PIP problem.
638 
639     \exception std::invalid_argument
640     Thrown if the space dimension of constraint system \p cs is strictly
641     greater than the space dimension of \p *this.
642   */
643   void add_constraints(const Constraint_System& cs);
644 
645   //! Checks satisfiability of \p *this.
646   /*!
647     \return
648     \c true if and only if the PIP problem is satisfiable.
649   */
650   bool is_satisfiable() const;
651 
652   //! Optimizes the PIP problem.
653   /*!
654     \return
655     A PIP_Problem_Status flag indicating the outcome of the optimization
656     attempt (unfeasible or optimized problem).
657   */
658   PIP_Problem_Status solve() const;
659 
660   //! Returns a feasible solution for \p *this, if it exists.
661   /*!
662     A null pointer is returned for an unfeasible PIP problem.
663   */
664   PIP_Tree solution() const;
665 
666   //! Returns an optimizing solution for \p *this, if it exists.
667   /*!
668     A null pointer is returned for an unfeasible PIP problem.
669   */
670   PIP_Tree optimizing_solution() const;
671 
672   //! Checks if all the invariants are satisfied.
673   bool OK() const;
674 
675   //! Prints on \p s the solution computed for \p *this.
676   /*!
677     \param s
678     The output stream.
679 
680     \param indent
681     An indentation parameter (default value 0).
682 
683     \exception std::logic_error
684     Thrown if trying to print the solution when the PIP problem
685     still has to be solved.
686   */
687   void print_solution(std::ostream& s, int indent = 0) const;
688 
689   PPL_OUTPUT_DECLARATIONS
690 
691   /*! \brief
692     Loads from \p s an ASCII representation (as produced by
693     ascii_dump(std::ostream&) const) and sets \p *this accordingly.
694     Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
695   */
696   bool ascii_load(std::istream& s);
697 
698   //! Returns the total size in bytes of the memory occupied by \p *this.
699   memory_size_type total_memory_in_bytes() const;
700 
701   //! Returns the size in bytes of the memory managed by \p *this.
702   memory_size_type external_memory_in_bytes() const;
703 
704   //! Swaps \p *this with \p y.
705   void m_swap(PIP_Problem& y);
706 
707   //! Possible names for PIP_Problem control parameters.
708   enum Control_Parameter_Name {
709     //! Cutting strategy
710     CUTTING_STRATEGY,
711     //! Pivot row strategy
712     PIVOT_ROW_STRATEGY,
713 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
714     //! Number of different enumeration values.
715 #endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
716     CONTROL_PARAMETER_NAME_SIZE
717   };
718 
719   //! Possible values for PIP_Problem control parameters.
720   enum Control_Parameter_Value {
721     //! Choose the first non-integer row.
722     CUTTING_STRATEGY_FIRST,
723     //! Choose row which generates the deepest cut.
724     CUTTING_STRATEGY_DEEPEST,
725     //! Always generate all possible cuts.
726     CUTTING_STRATEGY_ALL,
727 
728     //! Choose the first row with negative parameter sign.
729     PIVOT_ROW_STRATEGY_FIRST,
730     //! Choose a row that generates a lexicographically maximal pivot column.
731     PIVOT_ROW_STRATEGY_MAX_COLUMN,
732 
733 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
734     //! Number of different enumeration values.
735 #endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
736     CONTROL_PARAMETER_VALUE_SIZE
737   };
738 
739   //! Returns the value of control parameter \p name.
740   Control_Parameter_Value
741   get_control_parameter(Control_Parameter_Name name) const;
742 
743   //! Sets control parameter \p value.
744   void set_control_parameter(Control_Parameter_Value value);
745 
746   //! Sets the dimension for the big parameter to \p big_dim.
747   void set_big_parameter_dimension(dimension_type big_dim);
748 
749   /*! \brief
750     Returns the space dimension for the big parameter.
751 
752     If a big parameter was not set, returns \c not_a_dimension().
753   */
754   dimension_type get_big_parameter_dimension() const;
755 
756 private:
757   //! Initializes the control parameters with default values.
758   void control_parameters_init();
759 
760   //! Copies the control parameters from problem object \p y.
761   void control_parameters_copy(const PIP_Problem& y);
762 
763   //! The dimension of the vector space.
764   dimension_type external_space_dim;
765 
766   /*! \brief
767     The space dimension of the current (partial) solution of the
768     PIP problem; it may be smaller than \p external_space_dim.
769   */
770   dimension_type internal_space_dim;
771 
772   //! An enumerated type describing the internal status of the PIP problem.
773   enum Status {
774     //! The PIP problem is unsatisfiable.
775     UNSATISFIABLE,
776     //! The PIP problem is optimized; the solution tree has been computed.
777     OPTIMIZED,
778     /*! \brief
779       The feasible region of the PIP problem has been changed by adding
780       new variables, parameters or constraints; a feasible solution for
781       the old feasible region is still available.
782     */
783     PARTIALLY_SATISFIABLE
784   };
785 
786   //! The internal state of the MIP problem.
787   Status status;
788 
789   //! The current solution decision tree
790   PIP_Tree_Node* current_solution;
791 
792   //! The sequence of constraints describing the feasible region.
793   Constraint_Sequence input_cs;
794 
795   //! The first index of `input_cs' containing a pending constraint.
796   dimension_type first_pending_constraint;
797 
798   /*! \brief
799     A set containing all the indices of space dimensions that are
800     interpreted as problem parameters.
801   */
802   Variables_Set parameters;
803 
804 #if PPL_USE_SPARSE_MATRIX
805   typedef Sparse_Row Row;
806 #else
807   typedef Dense_Row Row;
808 #endif
809 
810   /*! \brief
811     The initial context
812 
813     Contains problem constraints on parameters only
814   */
815   Matrix<Row> initial_context;
816 
817   //! The control parameters for the problem object.
818   Control_Parameter_Value
819   control_parameters[CONTROL_PARAMETER_NAME_SIZE];
820 
821   /*! \brief
822     The dimension for the big parameter, or \c not_a_dimension()
823     if not set.
824   */
825   dimension_type big_parameter_dimension;
826 
827   friend class PIP_Solution_Node;
828 };
829 
830 #include "PIP_Problem_inlines.hh"
831 #include "PIP_Problem_templates.hh"
832 
833 #endif // !defined(PPL_PIP_Problem_defs_hh)
834