summaryrefslogtreecommitdiff
path: root/src/PIP_Tree.defs.hh
blob: 90afc9e8e62cfefbf4b18d2955522a2c0964baba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
/* PIP_Tree_Node class declaration.
   Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
   Copyright (C) 2010-2011 BUGSENG srl (http://bugseng.com)

This file is part of the Parma Polyhedra Library (PPL).

The PPL is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3 of the License, or (at your
option) any later version.

The PPL is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.

For the most up-to-date information see the Parma Polyhedra Library
site: http://www.cs.unipr.it/ppl/ . */

#ifndef PPL_PIP_Tree_defs_hh
#define PPL_PIP_Tree_defs_hh 1

#include "PIP_Tree.types.hh"
#include "Variable.defs.hh"
#include "Linear_Expression.types.hh"
#include "Constraint_System.defs.hh"
#include "Constraint_System.inlines.hh"
#include "Constraint.defs.hh"
#include "Matrix.defs.hh"
#include "Variables_Set.defs.hh"
#include "globals.defs.hh"
#include "PIP_Problem.defs.hh"

namespace Parma_Polyhedra_Library {

//! A node of the PIP solution tree.
/*!
  This is the base class for the nodes of the binary trees representing
  the solutions of PIP problems. From this one, two classes are derived:
    - PIP_Decision_Node, for the internal nodes of the tree;
    - PIP_Solution_Node, for the leaves of the tree.
*/
class PIP_Tree_Node {
protected:
  //! Constructor: builds a node owned by \p *owner.
  explicit PIP_Tree_Node(const PIP_Problem* owner);

  //! Copy constructor.
  PIP_Tree_Node(const PIP_Tree_Node& y);

  //! Returns a pointer to the PIP_Problem owning object.
  const PIP_Problem* get_owner() const;

  //! Sets the pointer to the PIP_Problem owning object.
  virtual void set_owner(const PIP_Problem* owner) = 0;

  /*! \brief
    Returns \c true if and only if all the nodes in the subtree
    rooted in \p *this is owned by \p *pip.
  */
  virtual bool check_ownership(const PIP_Problem* owner) const = 0;

public:
  //! Returns a pointer to a dynamically-allocated copy of \p *this.
  virtual PIP_Tree_Node* clone() const = 0;

  //! Destructor.
  virtual ~PIP_Tree_Node();

  //! Returns \c true if and only if \p *this is well formed.
  virtual bool OK() const;

  //! Returns \p this if \p *this is a solution node, 0 otherwise.
  virtual const PIP_Solution_Node* as_solution() const;

  //! Returns \p this if \p *this is a decision node, 0 otherwise.
  virtual const PIP_Decision_Node* as_decision() const;

  /*! \brief
    Returns the system of parameter constraints controlling \p *this.

    The indices in the constraints are the same as the original variables and
    parameters. Coefficients in indices corresponding to variables always are
    zero.
  */
  const Constraint_System& constraints() const;

  class Artificial_Parameter;

  //! A type alias for a sequence of Artificial_Parameter's.
  typedef std::vector<Artificial_Parameter> Artificial_Parameter_Sequence;

  //! Returns a const_iterator to the beginning of local artificial parameters.
  Artificial_Parameter_Sequence::const_iterator art_parameter_begin() const;

  //! Returns a const_iterator to the end of local artificial parameters.
  Artificial_Parameter_Sequence::const_iterator art_parameter_end() const;

  //! Returns the number of local artificial parameters.
  dimension_type art_parameter_count() const;

  //! Prints on \p s the tree rooted in \p *this.
  /*!
    \param s
    The output stream.

    \param indent
    The amount of indentation.
  */
  void print(std::ostream& s, unsigned indent = 0) const;

  //! Dumps to \p s an ASCII representation of \p *this.
  void ascii_dump(std::ostream& s) const;

  /*! \brief
    Loads from \p s an ASCII representation (as produced by
    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
  */
  bool ascii_load(std::istream& s);

  //! Returns the total size in bytes of the memory occupied by \p *this.
  virtual memory_size_type total_memory_in_bytes() const = 0;
  //! Returns the size in bytes of the memory managed by \p *this.
  virtual memory_size_type external_memory_in_bytes() const = 0;

protected:
  //! A type alias for a sequence of constraints.
  typedef std::vector<Constraint> Constraint_Sequence;

  // Only PIP_Problem and PIP_Decision_Node are allowed to use the
  // constructor and methods.
  friend class PIP_Problem;
  friend class PIP_Decision_Node;
  friend class PIP_Solution_Node;

  //! A pointer to the PIP_Problem object owning this node.
  const PIP_Problem* owner_;

  //! A pointer to the parent of \p *this, null if \p *this is the root.
  const PIP_Decision_Node* parent_;

  //! The local system of parameter constraints.
  Constraint_System constraints_;

  //! The local sequence of expressions for local artificial parameters.
  Artificial_Parameter_Sequence artificial_parameters;

  //! Returns a pointer to this node's parent.
  const PIP_Decision_Node* parent() const;

  //! Set this node's parent to \p *p.
  void set_parent(const PIP_Decision_Node* p);

  /*! \brief
    Populates the parametric simplex tableau using external data.

    \param pip
    The PIP_Problem object containing this node.

    \param external_space_dim
    The number of all problem variables and problem parameters
    (excluding artificial parameters).

    \param first_pending_constraint
    The first element in \p input_cs to be added to the tableau,
    which already contains the previous elements.

    \param input_cs
    All the constraints of the PIP problem.

    \param parameters
    The set of indices of the problem parameters.
  */
  virtual void update_tableau(const PIP_Problem& pip,
                              dimension_type external_space_dim,
                              dimension_type first_pending_constraint,
                              const Constraint_Sequence& input_cs,
                              const Variables_Set& parameters) = 0;

  /*! \brief
    Executes a parametric simplex on the tableau, under specified context.

    \return
    The root of the PIP tree solution, or 0 if unfeasible.

    \param pip
    The PIP_Problem object containing this node.

    \param check_feasible_context
    Whether the resolution process should (re-)check feasibility of
    context (since the initial context may have been modified).

    \param context
    The context, being a set of constraints on the parameters.

    \param params
    The local parameter set, including parent's artificial parameters.

    \param space_dim
    The space dimension of parent, including artificial parameters.

    \param indent_level
    The indentation level (for debugging output only).
  */
  virtual PIP_Tree_Node* solve(const PIP_Problem& pip,
                               bool check_feasible_context,
                               const Matrix& context,
                               const Variables_Set& params,
                               dimension_type space_dim,
                               unsigned indent_level) = 0;

  //! Inserts a new parametric constraint in internal Row format
  void add_constraint(const Row& x, const Variables_Set& parameters);

  //! Merges parent's artificial parameters into \p *this.
  void parent_merge();

  //! Prints on \p s the tree rooted in \p *this.
  /*!
    \param s
    The output stream.

    \param indent
    The amount of indentation.

    \param pip_dim_is_param
    A vector of Boolean flags telling which PIP problem dimensions are
    problem parameters. The size of the vector is equal to the PIP
    problem internal space dimension (i.e., no artificial parameters).

    \param first_art_dim
    The first space dimension corresponding to an artificial parameter
    that was created in this node (if any).
  */
  virtual void print_tree(std::ostream& s,
                          unsigned indent,
                          const std::vector<bool>& pip_dim_is_param,
                          dimension_type first_art_dim) const;

  //! A helper function used when printing PIP trees.
  static void
  indent_and_print(std::ostream& s, unsigned indent, const char* str);

  /*! \brief
    Checks whether a context matrix is satisfiable.

    The satisfiability check is implemented by the revised dual simplex
    algorithm on the context matrix. The algorithm ensures the feasible
    solution is integer by applying a cut generation method when
    intermediate non-integer solutions are found.
  */
  static bool compatibility_check(Matrix& s);

  /*! \brief
    Helper method: checks for satisfiability of the restricted context
    obtained by adding \p row to \p context.
  */
  static bool compatibility_check(const Matrix& context, const Row& row);

}; // class PIP_Tree_Node


/*! \brief
  Artificial parameters in PIP solution trees.

  These parameters are built from a linear expression combining other
  parameters (constant term included) divided by a positive integer
  denominator. Coefficients at variables indices corresponding to
  PIP problem variables are always zero.
*/
class PIP_Tree_Node::Artificial_Parameter
  : public Linear_Expression {
public:
  //! Default constructor: builds a zero artificial parameter.
  Artificial_Parameter();

  //! Constructor.
  /*!
    Builds artificial parameter \f$\frac{\mathit{expr}}{\mathit{den}}\f$.

    \param expr
    The expression that, after normalization, will form the numerator of
    the artificial parameter.

    \param den
    The integer constant thatm after normalization, will form the
    denominator of the artificial parameter.

    \exception std::invalid_argument
    Thrown if \p den is zero.

    Normalization will ensure that the denominator is positive.
  */
  Artificial_Parameter(const Linear_Expression& expr,
                       Coefficient_traits::const_reference den);

  //! Copy constructor.
  Artificial_Parameter(const Artificial_Parameter& y);

  //! Returns the normalized (i.e., positive) denominator.
  Coefficient_traits::const_reference denominator() const;

  //! Swaps \p *this with \p y.
  void swap(Artificial_Parameter& y);

  //! Returns \c true if and only if \p *this and \p y are equal.
  /*!
    Note that two artificial parameters having different space dimensions
    are considered to be different.
  */
  bool operator==(const Artificial_Parameter& y) const;
  //! Returns \c true if and only if \p *this and \p y are different.
  bool operator!=(const Artificial_Parameter& y) const;

  PPL_OUTPUT_DECLARATIONS

  /*! \brief
    Loads from \p s an ASCII representation (as produced by
    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
  */
  bool ascii_load(std::istream& s);

  //! Returns the total size in bytes of the memory occupied by \p *this.
  memory_size_type total_memory_in_bytes() const;
  //! Returns the size in bytes of the memory managed by \p *this.
  memory_size_type external_memory_in_bytes() const;

  //! Returns \c true if and only if the parameter is well-formed.
  bool OK() const;

private:
  //! The normalized (i.e., positive) denominator.
  Coefficient denom;
}; // class PIP_Tree_Node::Artificial_Parameter


//! A tree node representing part of the space of solutions.
class PIP_Solution_Node : public PIP_Tree_Node {
public:
  //! Constructor: builds a solution node owned by \p *owner.
  explicit PIP_Solution_Node(const PIP_Problem* owner);

  //! Returns a pointer to a dynamically-allocated copy of \p *this.
  virtual PIP_Tree_Node* clone() const;

  //! Destructor.
  virtual ~PIP_Solution_Node();

  //! Returns \c true if and only if \p *this is well formed.
  virtual bool OK() const;

  //! Returns \p this.
  virtual const PIP_Solution_Node* as_solution() const;

  /*! \brief
    Returns a parametric expression for the values of problem variable \p var.

    The returned linear expression may involve problem parameters
    as well as artificial parameters.

    \param var
    The problem variable which is queried about.

    \exception std::invalid_argument
    Thrown if \p var is dimension-incompatible with the PIP_Problem
    owning this solution node, or if \p var is a problem parameter.
  */
  const Linear_Expression& parametric_values(Variable var) const;

  //! Dumps to \p s an ASCII representation of \p *this.
  void ascii_dump(std::ostream& s) const;

  /*! \brief
    Loads from \p s an ASCII representation (as produced by
    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
  */
  bool ascii_load(std::istream& s);

  //! Returns the total size in bytes of the memory occupied by \p *this.
  virtual memory_size_type total_memory_in_bytes() const;
  //! Returns the size in bytes of the memory managed by \p *this.
  virtual memory_size_type external_memory_in_bytes() const;

private:
  //! The type for parametric simplex tableau.
  struct Tableau {
    //! The matrix of simplex coefficients.
    Matrix s;
    //! The matrix of parameter coefficients.
    Matrix t;
    //! A common denominator for all matrix elements
    Coefficient denom;

    //! Default constructor.
    Tableau();
    //! Copy constructor.
    Tableau(const Tableau& y);
    //! Destructor.
    ~Tableau();

    //! Tests whether the matrix is integer, i.e., the denominator is 1.
    bool is_integer() const;

    //! Multiplies all coefficients and denominator with ratio.
    void scale(Coefficient_traits::const_reference ratio);

    //! Normalizes the modulo of coefficients so that they are mutually prime.
    /*!
      Computes the Greatest Common Divisor (GCD) among the elements of
      the matrices and normalizes them and the denominator by the GCD itself.
    */
    void normalize();

    /*! \brief
      Compares two pivot row and column pairs before pivoting.

      The algorithm searches the first (ie, leftmost) column \f$k\f$ in
      parameter matrix for which the \f$c=s_{*j}\frac{t_{ik}}{s_{ij}}\f$
      and \f$c'=s_{*j'}\frac{t_{i'k}}{s_{i'j'}}\f$ columns are different,
      where \f$s_{*j}\f$ denotes the \f$j\f$<sup>th</sup> column from the
      \f$s\f$ matrix and \f$s_{*j'}\f$ is the \f$j'\f$<sup>th</sup> column
      of \f$s\f$.

      \f$c\f$ is the computed column that would be subtracted to column
      \f$k\f$ in parameter matrix if pivoting is done using the \f$(i,j)\f$
      row and column pair.
      \f$c'\f$ is the computed column that would be subtracted to column
      \f$k\f$ in parameter matrix if pivoting is done using the
      \f$(i',j')\f$ row and column pair.

      The test is true if the computed \f$-c\f$ column is lexicographically
      bigger than the \f$-c'\f$ column. Due to the column ordering in the
      parameter matrix of the tableau, leftmost search will enforce solution
      increase with respect to the following priority order:
       - the constant term
       - the coefficients for the original parameters
       - the coefficients for the oldest artificial parameters.

      \return
      \c true if pivot row and column pair \f$(i,j)\f$ is more
      suitable for pivoting than the \f$(i',j')\f$ pair

      \param mapping
      the PIP_Solution_Node::mapping vector for the tableau

      \param basis
      the PIP_Solution_Node::basis vector for the tableau

      \param i
      the row number for the first pivot row and column pair to be compared

      \param j
      the column number for the first pivot row and column pair to be
      compared

      \param i_
      the row number for the second pivot row and column pair to be compared

      \param j_
      the column number for the second pivot row and column pair to be
      compared
    */
    bool is_better_pivot(const std::vector<dimension_type>& mapping,
                         const std::vector<bool>& basis,
                         const dimension_type i,
                         const dimension_type j,
                         const dimension_type i_,
                         const dimension_type j_) const;

    //! Returns the value of the denominator.
    Coefficient_traits::const_reference denominator() const;

    //! Dumps to \p s an ASCII representation of \p *this.
    void ascii_dump(std::ostream& s) const;

    /*! \brief
      Loads from \p s an ASCII representation (as produced by
      ascii_dump(std::ostream&) const) and sets \p *this accordingly.
      Returns \c true if successful, \c false otherwise.
    */
    bool ascii_load(std::istream& s);

    //! Returns the size in bytes of the memory managed by \p *this.
    /*!
      \note
      No need for a \c total_memory_in_bytes() method, since
      class Tableau is a private inner class of PIP_Solution_Node.
    */
    memory_size_type external_memory_in_bytes() const;

    //! Returns \c true if and only if \p *this is well formed.
    bool OK() const;
  }; // struct Tableau

  //! The parametric simplex tableau.
  Tableau tableau;

  /*! \brief
    A boolean vector for identifying the basic variables.

    Variable identifiers are numbered from 0 to <tt>n+m-1</tt>, where \p n
    is the number of columns in the simplex tableau corresponding to variables,
    and \p m is the number of rows.

    Indices from 0 to <tt>n-1</tt> correspond to the original variables.

    Indices from \p n to <tt>n+m-1</tt> correspond to the slack variables
    associated to the internal constraints, which do not strictly correspond
    to original constraints, since these may have been transformed to fit the
    standard form of the dual simplex.

    The value for <tt>basis[i]</tt> is:
     - \b true if variable \p i is basic,
     - \b false if variable \p i is nonbasic.
  */
  std::vector<bool> basis;

  /*! \brief
    A mapping between the tableau rows/columns and the original variables.

    The value of <tt>mapping[i]</tt> depends of the value of <tt>basis[i]</tt>.

     - If <tt>basis[i]</tt> is \b true, <tt>mapping[i]</tt> encodes the column
       index of variable \p i in the \p s matrix of the tableau.
     - If <tt>basis[i]</tt> is \b false, <tt>mapping[i]</tt> encodes the row
       index of variable \p i in the tableau.
  */
  std::vector<dimension_type> mapping;

  /*! \brief
    The variable identifiers associated to the rows of the simplex tableau.
  */
  std::vector<dimension_type> var_row;

  /*! \brief
    The variable identifiers associated to the columns of the simplex tableau.
  */
  std::vector<dimension_type> var_column;

  /*! \brief
    The variable number of the special inequality used for modelling
    equality constraints.

    The subset of equality constraints in a specific problem can be expressed
    as: \f$f_i(x,p) = 0 ; 1 \leq i \leq n\f$. As the dual simplex standard form
    requires constraints to be inequalities, the following constraints can be
    modelized the following way:

     - \f$f_i(x,p) \geq 0 ; 1 \leq i \leq n\f$

     - \f$\sum\limits_{i=1}^n f_i(x,p) \leq 0\f$

    The \p special_equality_row value stores the variable number of the
    specific constraint which is used to modelize the latter sum of
    constraints. If no such constraint exists, the value is set to \p 0.
  */
  dimension_type special_equality_row;

  /*! \brief
    The column index in the parametric part of the simplex tableau
    corresponding to the big parameter; \c not_a_dimension() if not set.
  */
  dimension_type big_dimension;

  //! The possible values for the sign of a parametric linear expression.
  enum Row_Sign {
    //! Not computed yet (default).
    UNKNOWN,
    //! All row coefficients are zero.
    ZERO,
    //! All nonzero row coefficients are positive.
    POSITIVE,
    //! All nonzero row coefficients are negative.
    NEGATIVE,
    //! The row contains both positive and negative coefficients.
    MIXED
  };

  //! A cache for computed sign values of constraint parametric RHS.
  std::vector<Row_Sign> sign;

  //! Parametric values for the solution.
  std::vector<Linear_Expression> solution;

  //! An indicator for solution validity.
  bool solution_valid;

  //! Returns the sign of row \p x.
  static Row_Sign row_sign(const Row& x, dimension_type big_dimension);

protected:
  //! Copy constructor.
  PIP_Solution_Node(const PIP_Solution_Node& y);

  //! A tag type to select the alternative copy constructor.
  struct No_Constraints {};

  //! Alternative copy constructor.
  /*!
    This constructor differs from the default copy constructor in that
    it will not copy the constraint system, nor the artificial parameters.
  */
  PIP_Solution_Node(const PIP_Solution_Node& y, No_Constraints);

  // PIP_Problem::ascii load() method needs access set_owner().
  friend bool PIP_Problem::ascii_load(std::istream& s);

  //! Sets the pointer to the PIP_Problem owning object.
  virtual void set_owner(const PIP_Problem* owner);

  /*! \brief
    Returns \c true if and only if all the nodes in the subtree
    rooted in \p *this is owned by \p *pip.
  */
  virtual bool check_ownership(const PIP_Problem* owner) const;

  //! Implements pure virtual method PIP_Tree_Node::update_tableau.
  virtual void update_tableau(const PIP_Problem& pip,
                              dimension_type external_space_dim,
                              dimension_type first_pending_constraint,
                              const Constraint_Sequence& input_cs,
                              const Variables_Set& parameters);

  /*! \brief
    Update the solution values.

    \param pip_dim_is_param
    A vector of Boolean flags telling which PIP problem dimensions are
    problem parameters. The size of the vector is equal to the PIP
    problem internal space dimension (i.e., no artificial parameters).
  */
  void update_solution(const std::vector<bool>& pip_dim_is_param) const;

  //! Helper method.
  void update_solution() const;

  //! Implements pure virtual method PIP_Tree_Node::solve.
  virtual PIP_Tree_Node* solve(const PIP_Problem& pip,
                               bool check_feasible_context,
                               const Matrix& context,
                               const Variables_Set& params,
                               dimension_type space_dim,
                               unsigned indent_level);

  /*! \brief
    Generate a Gomory cut using non-integer tableau row \p i.

    \param i
    Row index in simplex tableau from which the cut is generated

    \param parameters
    A std::set of the current parameter dimensions (including artificials);
    to be updated if a new artificial parameter is to be created

    \param context
    A set of linear inequalities on the parameters, in matrix form; to be
    updated if a new artificial parameter is to be created

    \param space_dimension
    The current space dimension, including variables and all parameters; to
    be updated if an extra parameter is to be created

    \param indent_level
    The indentation level (for debugging output only).
  */
  void generate_cut(dimension_type i,
                    Variables_Set& parameters,
                    Matrix& context,
                    dimension_type& space_dimension,
                    unsigned indent_level);

  //! Prints on \p s the tree rooted in \p *this.
  virtual void print_tree(std::ostream& s,
                          unsigned indent,
                          const std::vector<bool>& pip_dim_is_param,
                          dimension_type first_art_dim) const;

}; // class PIP_Solution_Node


//! A tree node representing a decision in the space of solutions.
class PIP_Decision_Node : public PIP_Tree_Node {
public:
  //! Returns a pointer to a dynamically-allocated copy of \p *this.
  virtual PIP_Tree_Node* clone() const;

  //! Destructor.
  virtual ~PIP_Decision_Node();

  //! Returns \c true if and only if \p *this is well formed.
  virtual bool OK() const;

  //! Returns \p this.
  virtual const PIP_Decision_Node* as_decision() const;

  //! Returns a const pointer to the \p b (true or false) branch of \p *this.
  const PIP_Tree_Node* child_node(bool b) const;

  //! Returns a pointer to the \p b (true or false) branch of \p *this.
  PIP_Tree_Node* child_node(bool b);

  //! Dumps to \p s an ASCII representation of \p *this.
  void ascii_dump(std::ostream& s) const;

  /*! \brief
    Loads from \p s an ASCII representation (as produced by
    ascii_dump(std::ostream&) const) and sets \p *this accordingly.
    Returns <CODE>true</CODE> if successful, <CODE>false</CODE> otherwise.
  */
  bool ascii_load(std::istream& s);

  //! Returns the total size in bytes of the memory occupied by \p *this.
  virtual memory_size_type total_memory_in_bytes() const;
  //! Returns the size in bytes of the memory managed by \p *this.
  virtual memory_size_type external_memory_in_bytes() const;

private:
  // PIP_Solution_Node is allowed to use the constructor and methods.
  friend class PIP_Solution_Node;

  // PIP_Problem ascii load method needs access to private constructors.
  friend bool PIP_Problem::ascii_load(std::istream& s);

  //! Pointer to the "false" child of \p *this.
  PIP_Tree_Node* false_child;

  //! Pointer to the "true" child of \p *this.
  PIP_Tree_Node* true_child;

  /*! \brief
    Builds a decision node having \p fcp and \p tcp as child.

    The decision node will encode the structure
    "if \c cs then \p tcp else \p fcp",
    where the system of constraints \c cs is initially empty.

    \param owner
    Pointer to the owning PIP_Problem object; it may be null if and
    only if both children are null.

    \param fcp
    Pointer to "false" child; it may be null.

    \param tcp
    Pointer to "true" child; it may be null.

    \note
    If any of \p fcp or \p tcp is not null, then \p owner is required
    to be not null and equal to the owner of its non-null children;
    otherwise the behavior is undefined.
  */
  explicit PIP_Decision_Node(const PIP_Problem* owner,
                             PIP_Tree_Node* fcp,
                             PIP_Tree_Node* tcp);

  //! Sets the pointer to the PIP_Problem owning object.
  virtual void set_owner(const PIP_Problem* owner);

  /*! \brief
    Returns \c true if and only if all the nodes in the subtree
    rooted in \p *this is owned by \p *pip.
  */
  virtual bool check_ownership(const PIP_Problem* owner) const;

protected:
  //! Copy constructor.
  PIP_Decision_Node(const PIP_Decision_Node& y);

  //! Implements pure virtual method PIP_Tree_Node::update_tableau.
  virtual void update_tableau(const PIP_Problem& pip,
                              dimension_type external_space_dim,
                              dimension_type first_pending_constraint,
                              const Constraint_Sequence& input_cs,
                              const Variables_Set& parameters);

  //! Implements pure virtual method PIP_Tree_Node::solve.
  virtual PIP_Tree_Node* solve(const PIP_Problem& pip,
                               bool check_feasible_context,
                               const Matrix& context,
                               const Variables_Set& params,
                               dimension_type space_dim,
                               unsigned indent_level);

  //! Prints on \p s the tree rooted in \p *this.
  virtual void print_tree(std::ostream& s,
                          unsigned indent,
                          const std::vector<bool>& pip_dim_is_param,
                          dimension_type first_art_dim) const;

}; // class PIP_Decision_Node

namespace IO_Operators {

//! Output operator: prints the solution tree rooted in \p x.
/*! \relates Parma_Polyhedra_Library::PIP_Tree_Node */
std::ostream& operator<<(std::ostream& os, const PIP_Tree_Node& x);

//! Output operator.
/*! \relates Parma_Polyhedra_Library::PIP_Tree_Node::Artificial_Parameter */
std::ostream& operator<<(std::ostream& os,
                         const PIP_Tree_Node::Artificial_Parameter& x);

} // namespace IO_Operators

} // namespace Parma_Polyhedra_Library

#include "PIP_Tree.inlines.hh"

#endif // !defined(PPL_PIP_Tree_defs_hh)