1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /*                                                                           */
3 /*        This file is part of the program PolySCIP                          */
4 /*                                                                           */
5 /*    Copyright (C) 2012-2021 Konrad-Zuse-Zentrum                            */
6 /*                            fuer Informationstechnik Berlin                */
7 /*                                                                           */
8 /*  PolySCIP is distributed under the terms of the ZIB Academic License.     */
9 /*                                                                           */
10 /*  You should have received a copy of the ZIB Academic License              */
11 /*  along with PolySCIP; see the file LICENCE.                               */
12 /*                                                                           */
13 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
14 
15 /**
16  * @file polyscip.h
17  * @brief PolySCIP solver class
18  * @author Sebastian Schenker
19  *
20  */
21 
22 #ifndef POLYSCIP_SRC_POLYSCIP_H_INCLUDED
23 #define POLYSCIP_SRC_POLYSCIP_H_INCLUDED
24 
25 #include <cstdlib>
26 #include <functional>
27 #include <iostream>
28 #include <iterator>
29 #include <ostream>
30 #include <map>
31 #include <memory>
32 #include <string>
33 #include <utility>
34 #include <vector>
35 
36 #include "cmd_line_args.h"
37 #include "objscip/objscip.h"
38 #include "polyscip_types.h"
39 #include "weight_space_polyhedron.h"
40 
41 namespace polyscip {
42 
43     /**
44      * @class TwoDProj
45      * @brief Class representing a two-dimensional projection of an outcome
46      */
47     class TwoDProj {
48     public:
49 
50         /**
51          * Default constructor
52          * @param outcome Corresponding outcome to take two-dimensional projection of
53          * @param first First (objective) index of outcome to consider for projection
54          * @param second Second (objective) index of outcome to consider for projection
55          */
56         explicit TwoDProj(const OutcomeType& outcome,
57                           std::size_t first,
58                           std::size_t second);
59 
60         /**
61          * Get first projection value
62          * @return First value of projection
63          */
getFirst()64         ValueType getFirst() const {return proj_.first;}
65 
66         /**
67          * Get second projection value
68          * @return Second value of projection
69          */
getSecond()70         ValueType getSecond() const {return proj_.second;}
71 
72         /**
73          * Ostream operator
74          * @param os Output stream
75          * @param proj Projection to write to stream
76          * @return Output stream
77          */
78         friend std::ostream &operator<<(std::ostream& os, const TwoDProj& proj);
79 
80     private:
81         std::pair<ValueType, ValueType> proj_; ///< Pair of projection values
82 
83     };
84 
85     /**
86      * @class NondomProjections
87      * @brief Class representing non-dominated projections
88      */
89     class NondomProjections {
90     public:
91         using ProjMap = std::map<TwoDProj, ResultContainer, std::function<bool(const TwoDProj&, const TwoDProj&)>>; ///< Container for non-dominated projections
92 
93         /**
94          * Default constructor
95          * @param epsilon Error value for comparisons
96          * @param supported Results to take non-dominated projections
97          * @param first First (objective) index to consider for projection
98          * @param second Second (objective) index to consider for projection
99          */
100         explicit NondomProjections(double epsilon,
101                                    const ResultContainer& supported,
102                                    std::size_t first,
103                                    std::size_t second);
104 
105         /**
106          * Ostream operator
107          * @param os Output stream
108          * @param nd_proj Non-dominated projections to write to stream
109          * @return Output stream
110          */
111         friend std::ostream &operator<<(std::ostream& os, const NondomProjections& nd_proj);
112 
113         /**
114          * lhs-Projection epsilonDominates rhs-Projection if lhs.first - epsilon < rhs.first && lhs.second - epsilon < rhs.second
115          * @param lhs lhs-Projection
116          * @param rhs rhs-Projection
117          * @return true if lhs-Projection epsilon-dominated rhs-Projection; false otherwise
118          */
119         bool epsilonDominates(const TwoDProj& lhs,
120                               const TwoDProj& rhs) const;
121 
122         /**
123          * Indicates that all stored projections are investigated
124          * @return true if all stored projections have been investigated; false otherwise
125          */
126         bool finished() const;
127 
128         /**
129          * Advances current_ iterator
130          */
131         void update();
132 
133         /**
134          * Incorporates a new projection and corresponding result into non-dominated projections
135          * @param proj Projection to incorporated
136          * @param res Corresponding result of projection
137          */
138         void update(TwoDProj proj, Result res);
139 
140         /**
141          * Get outcomes corresponding to non-dominated projections
142          * @return Vector of outcomes corresponding to non-dominated projections
143          */
144         std::vector<OutcomeType> getNondomProjOutcomes() const;
145 
146         /**
147          * Get projection to be investigated
148          * @return Two-dimensional projection
149          */
getLeftProj()150         TwoDProj getLeftProj() const {return current_->first;};
151 
152         /**
153          * Get right neighbour of projection to be investigated
154          * @return Two-dimensional projection
155          */
getRightProj()156         TwoDProj getRightProj() const {return std::next(current_)->first;};
157 
158         /**
159          * Get projection with maximal value for second index
160          * @return Two-dimensional projection
161          */
getLastProj()162         TwoDProj getLastProj() const {return std::prev(end(nondom_projections_))->first;};
163 
164 
165     private:
166         /**
167          * Add projection and corresponding result to non-dominated projections
168          * @param proj Projection to add
169          * @param res Corresponding result of projections
170          * @return Iterator pointing to proj
171          */
172         ProjMap::iterator add(TwoDProj proj,
173                               Result res);
174 
175         double epsilon_; ///< Epsilon value used in fct 'epsilonDominates'
176         ProjMap nondom_projections_; ///< Container for non-dominated projections
177         ProjMap::iterator current_; ///< Currently investigated projection
178     };
179 
180     /**
181      * @class RectangularBox
182      * @brief A rectangular box R = [a_1,e_1) x ... x [a_k,e_k) is a k-ary Cartesian product of half-open intervals
183      */
184     class RectangularBox {
185     public:
186         using Interval = std::pair<ValueType, ValueType>; ///< Interval I = [a,b)
187 
188         /**
189          * Copy constructor
190          * @param box RectangularBox to copy
191          */
192         explicit RectangularBox(const std::vector<Interval>& box);
193 
194         /**
195          * Move constructor
196          * @param box RectangularBox to copy
197          */
198         explicit RectangularBox(std::vector<Interval>&& box);
199 
200         /**
201          * Ostream operator
202          * @param os Output stream to write to
203          * @param box Box to write to stream
204          * @return Output stream
205          */
206         friend std::ostream &operator<<(std::ostream& os, const RectangularBox& box);
207 
208         /**
209          * Indicates whether given box is subset
210          * @param other Box to compare
211          * @return true if 'other' is subset; false otherwise
212          */
213         bool isSupersetOf(const RectangularBox &other) const;
214 
215         /**
216          * Indicates whether given box is superset
217          * @param other Box to compare
218          * @return true if 'other' is superset; false otherwise
219          */
220         bool isSubsetOf(const RectangularBox &other) const;
221 
222         /**
223          * Indicates whether given box is disjoint
224          * @param other Box to compare
225          * @return true if 'other' is disjoint; false otherwise
226          */
227         bool isDisjointFrom(const RectangularBox &other) const;
228 
229         /**
230          * Indicates whether a_i + epsilon > e_i for all i
231          * @param epsilon Value to add to left interval limit
232          * @return true if a_i + epsilon <= e_i for all i; false otherwise
233          */
234         bool isFeasible(double epsilon) const;
235 
236         /**
237          * Makes disjoint rectangular boxes with respect to given box
238          * @param delta Feasibility threshold
239          * @param other Box to compare to
240          * @return Container of disjoint boxes
241          */
242         std::vector<RectangularBox> getDisjointPartsFrom(double delta, const RectangularBox &other) const;
243 
244         /**
245          * Get get number of intervals
246          * @return Dimension of rectangular box
247          */
248         std::size_t size() const;
249 
250         /**
251          * Get interval of box
252          * @param index Corresponding interval index
253          * @return Interval corresponding to index
254          */
255         Interval getInterval(std::size_t index) const;
256 
257         /**
258          * Indicates whether outcome dominates entire box
259          * @param outcome Outcome to compare to
260          * @return true if given outcome dominates entire box; false otherwise
261          */
262         bool isDominated(const OutcomeType& outcome) const;
263 
264     private:
265         /**
266          * Get interval intersection with respect to given dimension and given box
267          * @param index Interval index to take intersection
268          * @param other Box to consider intersection
269          * @return Interval intersection
270          */
271         Interval getIntervalIntersection(std::size_t index,
272                                          const RectangularBox& other) const;
273 
274         /**
275          * Constructor: constructs box first_beg x ... x (first_end-1) x second x third_bex x ... x (third_end-1)
276          * @param first_beg Iterator referring to interval
277          * @param first_end Iterator referring to past-the-end interval
278          * @param second Middle interval
279          * @param third_beg Iterator referring to interval
280          * @param third_end Iterator referring to past-the-end interval
281          */
282         RectangularBox(std::vector<Interval>::const_iterator first_beg,
283                        std::vector<Interval>::const_iterator first_end,
284                        Interval second,
285                        std::vector<Interval>::const_iterator third_beg,
286                        std::vector<Interval>::const_iterator third_end);
287 
288         std::vector<Interval> box_; ///< Container storing interval of rectangular box
289     };
290 
291     /**
292      * @class Polyscip
293      * @brief Class for PolySCIP solver functions
294      */
295     class Polyscip {
296     public:
297 
298         /**
299          * Different statuses of PolySCIP solver
300          */
301         enum class PolyscipStatus {
302             Unsolved, ///< Initial status after calling public constructor
303             ProblemRead, ///< Status after problem instance was read successfully
304             LexOptPhase, ///< Status after lexicographic optimal results were computed
305             WeightSpacePhase, ///< Status while results of weight space polyhedron are computed
306             TwoProjPhase, ///< Status while computing 2-dimensional non-dominated projection results
307             Finished, ///< Status if problem was solved successfully
308             TimeLimitReached, ///< Status if given time limit was reached
309             Error ///< Status if an error occured
310         };
311 
312         using ObjPair = std::pair<std::size_t, std::size_t>; ///< Pair of objectives indices
313 
314         /**
315          * Default constructor
316          * @param argc Argument count
317          * @param argv Argument vector
318          */
319         explicit Polyscip(int argc,
320                           const char *const *argv);
321 
322         /**
323          * Destructor
324          */
325         ~Polyscip();
326 
327         /**
328          * Read multi-objective problem file
329          * @return SCIP_OKAY if everything worked; otherwise a suitable error code is passed
330          */
331         SCIP_RETCODE readProblem();
332 
333         /**
334          * Compute non-dominated points of given problem
335          * @attention readProblem() needs to be called before
336          * @return SCIP_OKAY if everything worked; otherwise a suitable error code is passed
337          */
338         SCIP_RETCODE computeNondomPoints();
339 
340         /**
341          * Indicates whether results shold be written to a file
342          * @return true if results should be written to a file; otherwise false
343          */
writeResults()344         bool writeResults() const {return cmd_line_args_.writeResults();};
345 
346         /**
347          * Write results to file named 'solutions_name-of-problem-file.txt'
348          */
349         void writeResultsToFile() const;
350 
351         /**
352          * Print results
353          * @param os Output stream to print to
354          */
355         void printResults(std::ostream &os = std::cout) const;
356 
357         /**
358          * Print PolySCIP status
359          * @param os Output stream to print to
360          */
361         void printStatus(std::ostream& os = std::cout) const;
362 
363         /**
364          * Get PolySCIP status
365          * @return Current PolySCIP status
366          */
367         PolyscipStatus getStatus() const;
368 
369         /**
370          * Get number of bounded results
371          * @return Number of computed bounded results
372          */
373         std::size_t numberOfBoundedResults() const;
374 
375         /**
376          * Get number of unbounded results
377          * @return Number of computed unbounded results
378          */
379         std::size_t numberofUnboundedResults() const;
380 
381         /**
382          * Indicates whether dominated results were computed
383          * @return true if dominated bounded results were computed
384          */
385         bool dominatedPointsFound() const;
386 
387         /**
388          * Get iterator to beginning of bounded results
389          * @return Const_iterator to beginning of bounded results
390          */
boundedCBegin()391         ResultContainer::const_iterator boundedCBegin() {return bounded_.cbegin();};
392 
393         /**
394          * Get iterator to past-the-end of bounded results
395          * @return Const_iterator to past-the-end of bounded results
396          */
boundedCEnd()397         ResultContainer::const_iterator boundedCEnd() {return bounded_.cend();};
398 
399     private:
400 
401         /**
402          * Check whether file can be opened
403          * @param filename Name of file to open
404          * @return true if corresponding file can be opened; false otherwise
405          */
406         bool filenameIsOkay(const std::string &filename);
407 
408         /**
409          * Compute lexicographic optimal results
410          * @param orig_vars Container storing original problem variables with non-zero coefficients for each objective
411          * @param orig_vals Container storing original non-zero objective coefficients for each objective
412          * @return SCIP_OKAY if everything worked; otherwise a suitable error code is passed
413          */
414         SCIP_RETCODE computeLexicographicOptResults(std::vector<std::vector<SCIP_VAR*>>& orig_vars,
415                                                     std::vector<std::vector<ValueType>>& orig_vals);
416 
417         /**
418          * Compute lexicographic optimal result with given objective having highest preference
419          * @param obj Objective with highest preference
420          * @param orig_vars Container storing original problem variables with non-zero coefficients for each objective
421          * @param orig_vals Container storing original non-zero objective coefficients for each objective
422          * @return SCIP_OKAY if everything worked; otherwise a suitable error code is passed
423          */
424         SCIP_RETCODE computeLexicographicOptResult(std::size_t obj,
425                                               std::vector<std::vector<SCIP_VAR*>>& orig_vars,
426                                               std::vector<std::vector<ValueType>>& orig_vals);
427 
428 
429         /**
430          * Checks whether results corresponding to given iterator is dominated or equal to other given elements
431          * @param it Const_iterator corresponding to result
432          * @param beg_it Const_iterator to beginning of result container
433          * @param end_it Const_iterator to past-the-end of result container
434          * @return true if result given by it is dominated or equal to other given results; false otherwise
435          */
436         bool isDominatedOrEqual(ResultContainer::const_iterator it,
437                                 ResultContainer::const_iterator beg_it,
438                                 ResultContainer::const_iterator end_it) const;
439 
440         /**
441          * Set weighted objective: weight * (c_1,...,c_k) \\cdot x
442          * @param weight Weight
443          * @return SCIP_OKAY if everything worked; otherwise a suitable error code is passed
444          */
445         SCIP_RETCODE setWeightedObjective(const WeightType& weight);
446 
447         /**
448          * Solves currently considered SCIP instance
449          * @return SCIP_OKAY if everything worked; otherwise a suitable error code is passed
450          */
451         SCIP_RETCODE solve();
452 
453         /**
454          * Resolve INFORUNBD SCIP status to either infeasible or unbounded
455          * @param weight Weight yielding INFORUNBD status
456          * @param with_presolving Indicates whether presolving should be used or not
457          * @return SCIP_OKAY if everything worked; otherwise a suitable error code is passed
458          */
459         SCIP_STATUS separateINFORUNBD(const WeightType& weight,
460                                       bool with_presolving = true);
461 
462         /**
463          * Handle SCIP status that is neither optimal nor unbounded
464          * @param status Current SCIP status
465          * @return SCIP_OKAY if everything worked; otherwise a suitable error code is passed
466          */
467         SCIP_RETCODE handleNonOptNonUnbdStatus(SCIP_STATUS status);
468 
469         /**
470          * Handle unbounded SCIP status
471          * @param check_if_new_result Indicates whether to check if computed results is already known
472          * @return SCIP_OKAY if everything worked; otherwise a suitable error code is passed
473          */
474         SCIP_RETCODE handleUnboundedStatus(bool check_if_new_result=false);
475 
476         /**
477          * Indicates whether given outcomes coincide within some epsilon error
478          * @param a First outcome to compare
479          * @param b Second outcome to compare
480          * @param epsilon Allowed error
481          * @return true if outcomes coincides; false otherwise
482          */
483         static bool outcomesCoincide(const OutcomeType& a,
484                                      const OutcomeType& b,
485                                      double epsilon);
486 
487         /**
488          * Indicates whether given outcome was not computed before
489          * @param outcome Outcome to check
490          * @param outcome_is_bounded Indicates whether given outcome is bounded or unbounded
491          * @return true if given outcome was not computed before; false otherwise
492          */
493         bool outcomeIsNew(const OutcomeType& outcome,
494                           bool outcome_is_bounded) const;
495 
496         /**
497          * Indicates whether given outcome is new with respect to other given results
498          * @param outcome Outcome to check
499          * @param beg Const_iterator to beginning of result container
500          * @param last Const_iterator to past-the-end of result container
501          * @return true if given outcome does not coincide with outcomes; false otherwise
502          */
503         bool outcomeIsNew(const OutcomeType& outcome,
504                           ResultContainer::const_iterator beg,
505                           ResultContainer::const_iterator last) const;
506 
507         /**
508          * Get computed result
509          * @param outcome_is_bounded Indicates whether previous computation yielded unbounded status
510          * @param primal_sol Corresponding SCIP primal solution pointer if previous computation yielded optimal status
511          * @return Result type
512          */
513         Result getResult(bool outcome_is_bounded = false,
514                          SCIP_SOL* primal_sol = nullptr);
515 
516         /**
517          * Get bounded optimal result
518          * @return Result type
519          */
520         Result getOptimalResult();
521 
522         /**
523          * Print objective
524          * @param obj_no Corresponding index of objective
525          * @param nonzero_indices Indices of variables with non-zero coefficients
526          * @param nonzero_vals Corresponding non-zero coefficient variable values
527          * @param os Output stream to write to
528          */
529         void printObjective(std::size_t obj_no,
530                             const std::vector<int>& nonzero_indices,
531                             const std::vector<SCIP_Real>& nonzero_vals,
532                             std::ostream& os = std::cout) const;
533 
534         /**
535          * Indicates whether objective given by index is redundant
536          * @param begin_nonzeros begin_nonzeros[i+1] = begin_nonzeros[i] + obj_probdata->getNumberNonzeroCoeffs(i)
537          * @param obj_to_nonzero_indices indices of non-zero variables for each objective
538          * @param obj_to_nonzero_values non-zero variables for each objective
539          * @param index index of objective to check
540          * @return true if checked objective is redundant; false otherwise
541          */
542         bool objIsRedundant(const std::vector<int>& begin_nonzeros,
543                             const std::vector<std::vector<int>>& obj_to_nonzero_indices,
544                             const std::vector<std::vector<SCIP_Real>>& obj_to_nonzero_values,
545                             std::size_t index) const;
546 
547         /**
548          * Compute non-dominated extreme point results
549          * @return SCIP_OKAY if everything worked; otherwise a suitable error code is passed
550          */
551         SCIP_RETCODE computeWeightSpaceResults();
552 
553         /**
554          * Compute bounded non-dominated extreme points for objective for which unbounded ray exits
555          * @return SCIP_OKAY if everything worked; otherwise a suitable error code is passed
556          */
557         SCIP_RETCODE computeBoundedNondomResultsForUnbdObjs();
558 
559         /**
560          * Compute non-dominated points which are not lexicographically optimal
561          * @param orig_vars Container storing original problem variables with non-zero coefficients for each objective
562          * @param orig_vals Container storing original non-zero objective coefficients for each objective
563          * @return SCIP_OKAY if everything worked; otherwise a suitable error code is passed
564          */
565         SCIP_RETCODE computeNonLexicographicNondomResults(const std::vector<std::vector<SCIP_VAR*>>& orig_vars,
566                                                           const std::vector<std::vector<ValueType>>& orig_vals);
567 
568         /**
569          * Compute non-dominated points via subproblems with weighted Tchebycheff norm
570          * @param orig_vars Container storing original problem variables with non-zero coefficients for each objective
571          * @param orig_vals Container storing original non-zero objective coefficients for each objective
572          * @param obj_1 Index of first considered objective
573          * @param obj_2 Index of second considered objective
574          * @return Container of non-dominated outcomes which are also non-dominated for projection onto obj_1 and obj_2
575          */
576         std::vector<OutcomeType> solveWeightedTchebycheff(const std::vector<std::vector<SCIP_VAR*>>& orig_vars,
577                                                           const std::vector<std::vector<ValueType>>& orig_vals,
578                                                           std::size_t obj_1,
579                                                           std::size_t obj_2);
580 
581         /**
582          * Compute disjoint rectangular boxes from given feasible rectangular boxes
583          * @param feasible_boxes List of feasible boxes
584          * @return Vector of disjoint feasible rectangular boxes
585          */
586         std::vector<RectangularBox> computeDisjointBoxes(std::list<RectangularBox>&& feasible_boxes) const;
587 
588         /**
589          * Compute feasible rectangular boxes
590          * @param proj_nondom_outcomes Non-dominated outcomes which are non-dominated for objective pair
591          * @param orig_vars Container storing original problem variables with non-zero coefficients for each objective
592          * @param orig_vals Container storing original non-zero objective coefficients for each objective
593          * @return List of feasible rectangular boxes
594          */
595         std::list<RectangularBox> computeFeasibleBoxes(
596                 const std::map<ObjPair, std::vector<OutcomeType>> &proj_nondom_outcomes,
597                 const std::vector<std::vector<SCIP_VAR *>> &orig_vars,
598                 const std::vector<std::vector<ValueType>> &orig_vals);
599 
600         /**
601          * Compute locally non-dominated results in given rectangular box
602          * @param box Rectangular box
603          * @param orig_vars Container storing original problem variables with non-zero coefficients for each objective
604          * @param orig_vals Container storing original non-zero objective coefficients for each objective
605          * @return Container with locally non-dominated results
606          */
607         ResultContainer computeNondomPointsInBox(const RectangularBox& box,
608                                                  const std::vector<std::vector<SCIP_VAR *>>& orig_vars,
609                                                  const std::vector<std::vector<ValueType>>& orig_vals);
610 
611         /**
612          * Indicates whether given outcome is globally dominated
613          * @param outcome Outcome to check for dominance
614          * @param orig_vars Container storing original problem variables with non-zero coefficients for each objective
615          * @param orig_vals Container storing original non-zero objective coefficients for each objective
616          * @return true if given outcome is dominated; false otherwise
617          */
618         bool boxResultIsDominated(const OutcomeType& outcome,
619                                   const std::vector<std::vector<SCIP_VAR*>>& orig_vars,
620                                   const std::vector<std::vector<ValueType>>& orig_vals);
621 
622 
623         /**
624          * Create constraint: new_var - beta_i * orig_vals \\cdot orig_vars >= - beta_i * rhs
625          * @param new_var Non-original variable
626          * @param orig_vars Container storing original problem variables with non-zero coefficients for each objective
627          * @param orig_vals Container storing original non-zero objective coefficients for each objective
628          * @param rhs rhs value
629          * @param beta_i coefficient
630          * @return Pointer to corresponding SCIP constraint
631          */
632         SCIP_CONS* createNewVarTransformCons(SCIP_VAR *new_var,
633                                              const std::vector<SCIP_VAR *> &orig_vars,
634                                              const std::vector<ValueType> &orig_vals,
635                                              const ValueType &rhs,
636                                              const ValueType &beta_i);
637 
638         /**
639          * Create constraint: lhs <= vals \\cdot vars <= rhs
640          * @param vars Considered variables
641          * @param vals Considered coefficient values
642          * @param lhs lhs value
643          * @param rhs rhs value
644          * @return Pointer to corresponding SCIP constraint
645          */
646         SCIP_CONS* createObjValCons(const std::vector<SCIP_VAR *>& vars,
647                                     const std::vector<ValueType>& vals,
648                                     const ValueType& lhs,
649                                     const ValueType& rhs);
650 
651         /**
652          * Computes non-dominated point which fulfills: obj_val_cons1 = obj_val_cons1_rhs and obj_val_cons2 = obj_val_cons2_rhs
653          * @param obj_val_cons1 First constraint to consider
654          * @param obj_val_cons2 Second constraint to consider
655          * @param obj_val_cons1_rhs Corresponding rhs of first constraint
656          * @param obj_val_cons2_rhs Corresponding rhs of second constraint
657          * @param obj_1 Considered objective index corresponding to first constraint
658          * @param obj_2 Considered objective index corresponding to second constraint
659          * @param results Container to store computed non-dominated result
660          * @return SCIP_OKAY if everything worked; otherwise a suitable error code is passed
661          */
662         SCIP_RETCODE computeNondomProjResult(SCIP_CONS* obj_val_cons1,
663                                              SCIP_CONS* obj_val_cons2,
664                                              ValueType obj_val_cons1_rhs,
665                                              ValueType obj_val_cons2_rhs,
666                                              std::size_t obj_1,
667                                              std::size_t obj_2,
668                                              ResultContainer &results);
669 
670         /**
671          * Indicates whether unbounded results were computed
672          * @return true if unbounded results were computed; false otherwise
673          */
unboundedResultsExist()674         bool unboundedResultsExist() const {return !unbounded_.empty();};
675 
676         /**
677          * Print solution
678          * @param sol Solution to print
679          * @param os Output stream to write to
680          */
681         void printSol(const SolType& sol,
682                       std::ostream& os) const;
683 
684         /**
685          * Print outcome
686          * @param outcome Outcome to print
687          * @param os Output stream to write to
688          * @param desc Description to print before given outcome
689          */
690         void outputOutcome(const OutcomeType &outcome,
691                            std::ostream& os,
692                            const std::string desc ="") const;
693 
694         /**
695          * Constructor
696          * @param cmd_line_args Command line parameter object
697          * @param scip SCIP pointer
698          * @param no_objs Number of considered objective
699          * @param clock_total Clock measuring total computation time
700          */
701         explicit Polyscip(const CmdLineArgs& cmd_line_args,
702                           SCIP* scip,
703                           std::size_t no_objs,
704                           SCIP_CLOCK *clock_total);
705 
706         CmdLineArgs cmd_line_args_; ///< Object containing command line parameter information
707         PolyscipStatus polyscip_status_; ///< Current PolySCIP status
708         SCIP* scip_; ///< SCIP pointer
709         SCIP_Objsense obj_sense_; ///< Objective sense of given problem
710         std::size_t no_objs_; ///< Considered number of objectives
711         SCIP_CLOCK* clock_total_; ///< Clock measuring the time needed for the entire computation
712         bool only_weight_space_phase_; ///< Indicates whether only non-dominated extreme points should be computed
713         bool is_sub_prob_; ///< Indicates whether PolySCIP instance belongs to subproblem
714         std::unique_ptr<WeightSpacePolyhedron> weight_space_poly_; ///< Pointer holding weight space polyhedron object
715         ResultContainer bounded_; ///< Container storing bounded non-dominated results
716         ResultContainer unbounded_; ///< Container storing unbounded non-dominated results
717         std::vector<std::size_t> unbd_orig_objs_; ///< Container storing objectives indices for which unbounded rays were found
718     };
719 
720 }
721 
722 #endif //POLYSCIP_SRC_POLYSCIP_H_INCLUDED
723