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