1// Copyright (C) 2000, International Business Machines
2// Corporation and others. All Rights Reserved.
3// This code is licensed under the terms of the Eclipse Public License (EPL).
4
5#ifndef OsiRowCutDebugger_H
6#define OsiRowCutDebugger_H
7
8/*! \file OsiRowCutDebugger.hpp
9
10 \brief Provides a facility to validate cut constraints to ensure that they
11 do not cut off a given solution.
12*/
13
14#include <string>
15
16#include "OsiCuts.hpp"
17#include "OsiSolverInterface.hpp"
18
19/*! \brief Validate cuts against a known solution
20
21 OsiRowCutDebugger provides a facility for validating cuts against a known
22 solution for a problem. The debugger knows an optimal solution for many of
23 the miplib3 problems. Check the source for
24 #activate(const OsiSolverInterface&,const char*)
25 in OsiRowCutDebugger.cpp for the full set of known problems.
26
27 A full solution vector can be supplied as a parameter with
28 (#activate(const OsiSolverInterface&,const double*,bool)).
29 Only the integer values need to be valid.
30 The default behaviour is to solve an lp relaxation with the integer
31 variables fixed to the specified values and use the optimal solution to fill
32 in the continuous variables in the solution.
33 The debugger can be instructed to preserve the continuous variables (useful
34 when debugging solvers where the linear relaxation doesn't capture all the
35 constraints).
36
37 Note that the solution must match the problem held in the solver interface.
38 If you want to use the row cut debugger on a problem after applying presolve
39 transformations, your solution must match the presolved problem. (But see
40 #redoSolution().)
41*/
42class OsiRowCutDebugger {
43 friend void OsiRowCutDebuggerUnitTest(const OsiSolverInterface * siP,
44 const std::string & mpsDir);
45
46public:
47
48 /*! @name Validate Row Cuts
49
50 Check that the specified cuts do not cut off the known solution.
51 */
52 //@{
53 /*! \brief Check that the set of cuts does not cut off the solution known
54 to the debugger.
55
56 Check if any generated cuts cut off the solution known to the debugger!
57 If so then print offending cuts. Return the number of invalid cuts.
58 */
59 virtual int validateCuts(const OsiCuts & cs, int first, int last) const;
60
61 /*! \brief Check that the cut does not cut off the solution known to the
62 debugger.
63
64 Return true if cut is invalid
65 */
66 virtual bool invalidCut(const OsiRowCut & rowcut) const;
67
68 /*! \brief Returns true if the solution held in the solver is compatible
69 with the known solution.
70
71 More specifically, returns true if the known solution satisfies the column
72 bounds held in the solver.
73 */
74 bool onOptimalPath(const OsiSolverInterface &si) const;
75 //@}
76
77 /*! @name Activate the Debugger
78
79 The debugger is considered to be active when it holds a known solution.
80 */
81 //@{
82 /*! \brief Activate a debugger using the name of a problem.
83
84 The debugger knows an optimal solution for most of miplib3. Check the
85 source code for the full list. Returns true if the debugger is
86 successfully activated.
87 */
88 bool activate(const OsiSolverInterface &si, const char *model) ;
89
90 /*! \brief Activate a debugger using a full solution array.
91
92 The solution must have one entry for every variable, but only the entries
93 for integer values are used. By default the debugger will solve an lp
94 relaxation with the integer variables fixed and fill in values for the
95 continuous variables from this solution. If the debugger should preserve
96 the given values for the continuous variables, set \p keepContinuous to
97 \c true.
98
99 Returns true if debugger activates successfully.
100 */
101 bool activate(const OsiSolverInterface &si, const double* solution,
102 bool keepContinuous = false) ;
103
104 /// Returns true if the debugger is active
105 bool active() const;
106 //@}
107
108 /*! @name Query or Manipulate the Known Solution */
109 //@{
110 /// Return the known solution
111 inline const double * optimalSolution() const
112 { return knownSolution_;}
113
114 /// Return the number of columns in the known solution
115 inline int numberColumns() const { return (numberColumns_) ; }
116
117 /// Return the value of the objective for the known solution
118 inline double optimalValue() const { return knownValue_;}
119
120 /*! \brief Edit the known solution to reflect column changes
121
122 Given a translation array \p originalColumns[numberColumns] which can
123 translate current column indices to original column indices, this method
124 will edit the solution held in the debugger so that it matches the current
125 set of columns.
126
127 Useful when the original problem is preprocessed prior to cut generation.
128 The debugger does keep a record of the changes.
129 */
130 void redoSolution(int numberColumns, const int *originalColumns);
131
132 /// Print optimal solution (returns -1 bad debug, 0 on optimal, 1 not)
133 int printOptimalSolution(const OsiSolverInterface & si) const;
134 //@}
135
136 /**@name Constructors and Destructors */
137 //@{
138 /// Default constructor - no checking
139 OsiRowCutDebugger ();
140
141 /*! \brief Constructor with name of model.
142
143 See #activate(const OsiSolverInterface&,const char*).
144 */
145 OsiRowCutDebugger(const OsiSolverInterface &si, const char *model) ;
146
147 /*! \brief Constructor with full solution.
148
149 See #activate(const OsiSolverInterface&,const double*,bool).
150 */
151 OsiRowCutDebugger(const OsiSolverInterface &si, const double *solution,
152 bool enforceOptimality = false) ;
153
154 /// Copy constructor
155 OsiRowCutDebugger(const OsiRowCutDebugger &);
156
157 /// Assignment operator
158 OsiRowCutDebugger& operator=(const OsiRowCutDebugger& rhs);
159
160 /// Destructor
161 virtual ~OsiRowCutDebugger ();
162 //@}
163
164private:
165
166 // Private member data
167
168 /**@name Private member data */
169 //@{
170 /// Value of known solution
171 double knownValue_;
172
173 /*! \brief Number of columns in known solution
174
175 This must match the number of columns reported by the solver.
176 */
177 int numberColumns_;
178
179 /// array specifying integer variables
180 bool * integerVariable_;
181
182 /// array specifying known solution
183 double * knownSolution_;
184 //@}
185};
186
187#endif
188