1 | // Copyright (C) 2003, 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 OsiPresolve_H |
6 | #define OsiPresolve_H |
7 | #include "OsiSolverInterface.hpp" |
8 | |
9 | class CoinPresolveAction; |
10 | #include "CoinPresolveMatrix.hpp" |
11 | |
12 | |
13 | /*! \class OsiPresolve |
14 | \brief OSI interface to COIN problem simplification capabilities |
15 | |
16 | COIN provides a number of classes which implement problem simplification |
17 | algorithms (CoinPresolveAction, CoinPrePostsolveMatrix, and derived |
18 | classes). The model of operation is as follows: |
19 | <ul> |
20 | <li> |
21 | Create a copy of the original problem. |
22 | </li> |
23 | <li> |
24 | Subject the copy to a series of transformations (the <i>presolve</i> |
25 | methods) to produce a presolved model. Each transformation is also |
26 | expected to provide a method to reverse the transformation (the |
27 | <i>postsolve</i> method). The postsolve methods are collected in a |
28 | linked list; the postsolve method for the final presolve transformation |
29 | is at the head of the list. |
30 | </li> |
31 | <li> |
32 | Hand the presolved problem to the solver for optimization. |
33 | </li> |
34 | <li> |
35 | Apply the collected postsolve methods to the presolved problem |
36 | and solution, restating the solution in terms of the original problem. |
37 | </li> |
38 | </ul> |
39 | |
40 | The COIN presolve algorithms are unaware of OSI. The OsiPresolve class takes |
41 | care of the interface. Given an OsiSolverInterface \c origModel, it will take |
42 | care of creating a clone properly loaded with the presolved problem and ready |
43 | for optimization. After optimization, it will apply postsolve |
44 | transformations and load the result back into \c origModel. |
45 | |
46 | Assuming a problem has been loaded into an |
47 | \c OsiSolverInterface \c origModel, a bare-bones application looks like this: |
48 | \code |
49 | OsiPresolve pinfo ; |
50 | OsiSolverInterface *presolvedModel ; |
51 | // Return an OsiSolverInterface loaded with the presolved problem. |
52 | presolvedModel = pinfo.presolvedModel(*origModel,1.0e-8,false,numberPasses) ; |
53 | presolvedModel->initialSolve() ; |
54 | // Restate the solution and load it back into origModel. |
55 | pinfo.postsolve(true) ; |
56 | delete presolvedModel ; |
57 | \endcode |
58 | */ |
59 | |
60 | |
61 | |
62 | class OsiPresolve { |
63 | public: |
64 | /// Default constructor (empty object) |
65 | OsiPresolve(); |
66 | |
67 | /// Virtual destructor |
68 | virtual ~OsiPresolve(); |
69 | |
70 | /*! \brief Create a new OsiSolverInterface loaded with the presolved problem. |
71 | |
72 | This method implements the first two steps described in the class |
73 | documentation. It clones \c origModel and applies presolve |
74 | transformations, storing the resulting list of postsolve |
75 | transformations. It returns a pointer to a new OsiSolverInterface loaded |
76 | with the presolved problem, or NULL if the problem is infeasible or |
77 | unbounded. If \c keepIntegers is true then bounds may be tightened in |
78 | the original. Bounds will be moved by up to \c feasibilityTolerance to |
79 | try and stay feasible. When \c doStatus is true, the current solution will |
80 | be transformed to match the presolved model. |
81 | |
82 | This should be paired with postsolve(). It is up to the client to |
83 | destroy the returned OsiSolverInterface, <i>after</i> calling postsolve(). |
84 | |
85 | This method is virtual. Override this method if you need to customize |
86 | the steps of creating a model to apply presolve transformations. |
87 | |
88 | In some sense, a wrapper for presolve(CoinPresolveMatrix*). |
89 | */ |
90 | virtual OsiSolverInterface *presolvedModel(OsiSolverInterface & origModel, |
91 | double feasibilityTolerance=0.0, |
92 | bool keepIntegers=true, |
93 | int numberPasses=5, |
94 | const char * prohibited=nullptr, |
95 | bool doStatus=true, |
96 | const char * rowProhibited=nullptr); |
97 | |
98 | /*! \brief Restate the solution to the presolved problem in terms of the |
99 | original problem and load it into the original model. |
100 | |
101 | postsolve() restates the solution in terms of the original problem and |
102 | updates the original OsiSolverInterface supplied to presolvedModel(). If |
103 | the problem has not been solved to optimality, there are no guarantees. |
104 | If you are using an algorithm like simplex that has a concept of a basic |
105 | solution, then set updateStatus |
106 | |
107 | The advantage of going back to the original problem is that it |
108 | will be exactly as it was, <i>i.e.</i>, 0.0 will not become 1.0e-19. |
109 | |
110 | Note that if you modified the original problem after presolving, then you |
111 | must ``undo'' these modifications before calling postsolve(). |
112 | |
113 | In some sense, a wrapper for postsolve(CoinPostsolveMatrix&). |
114 | */ |
115 | virtual void postsolve(bool updateStatus=true); |
116 | |
117 | /*! \brief Return a pointer to the presolved model. */ |
118 | OsiSolverInterface * model() const; |
119 | |
120 | /// Return a pointer to the original model |
121 | OsiSolverInterface * originalModel() const; |
122 | |
123 | /// Set the pointer to the original model |
124 | void setOriginalModel(OsiSolverInterface *model); |
125 | |
126 | /// Return a pointer to the original columns |
127 | const int * originalColumns() const; |
128 | |
129 | /// Return a pointer to the original rows |
130 | const int * originalRows() const; |
131 | |
132 | /// Return number of rows in original model |
133 | inline int getNumRows() const |
134 | { return nrows_;} |
135 | |
136 | /// Return number of columns in original model |
137 | inline int getNumCols() const |
138 | { return ncols_;} |
139 | |
140 | /** "Magic" number. If this is non-zero then any elements with this value |
141 | may change and so presolve is very limited in what can be done |
142 | to the row and column. This is for non-linear problems. |
143 | */ |
144 | inline void setNonLinearValue(double value) |
145 | { nonLinearValue_ = value;} |
146 | inline double nonLinearValue() const |
147 | { return nonLinearValue_;} |
148 | /** Whether we want to skip dual part of presolve etc. |
149 | 1 bit allows duplicate column processing on integer columns |
150 | and dual stuff on integers |
151 | 2 bit set switches off actions which can change +1 to something else |
152 | 4 bit set transfers costs to integer variables |
153 | 8 bit set stops x+y+z=1 transform |
154 | 16 bit set allows doing presolve things which don't easily unroll |
155 | 32 bit set allows dubious gub element reduction |
156 | */ |
157 | inline void setPresolveActions(int action) |
158 | { presolveActions_ = (presolveActions_&0xffff0000)|(action&0xffff);} |
159 | |
160 | private: |
161 | /*! Original model (solver interface loaded with the original problem). |
162 | |
163 | Must not be destroyed until after postsolve(). |
164 | */ |
165 | OsiSolverInterface * originalModel_; |
166 | |
167 | /*! Presolved model (solver interface loaded with the presolved problem) |
168 | |
169 | Must be destroyed by the client (using delete) after postsolve(). |
170 | */ |
171 | OsiSolverInterface * presolvedModel_; |
172 | |
173 | /*! "Magic" number. If this is non-zero then any elements with this value |
174 | may change and so presolve is very limited in what can be done |
175 | to the row and column. This is for non-linear problems. |
176 | One could also allow for cases where sign of coefficient is known. |
177 | */ |
178 | double nonLinearValue_; |
179 | |
180 | /// Original column numbers |
181 | int * originalColumn_; |
182 | |
183 | /// Original row numbers |
184 | int * originalRow_; |
185 | |
186 | /// The list of transformations applied. |
187 | const CoinPresolveAction *paction_; |
188 | |
189 | /*! \brief Number of columns in original model. |
190 | |
191 | The problem will expand back to its former size as postsolve |
192 | transformations are applied. It is efficient to allocate data structures |
193 | for the final size of the problem rather than expand them as needed. |
194 | */ |
195 | int ncols_; |
196 | |
197 | /*! \brief Number of rows in original model. */ |
198 | int nrows_; |
199 | |
200 | /*! \brief Number of nonzero matrix coefficients in the original model. */ |
201 | CoinBigIndex nelems_; |
202 | |
203 | /** Whether we want to skip dual part of presolve etc. |
204 | 1 bit allows duplicate column processing on integer columns |
205 | and dual stuff on integers |
206 | 4 transfers costs to integer variables |
207 | */ |
208 | int presolveActions_; |
209 | /// Number of major passes |
210 | int numberPasses_; |
211 | |
212 | protected: |
213 | /*! \brief Apply presolve transformations to the problem. |
214 | |
215 | Handles the core activity of applying presolve transformations. |
216 | |
217 | If you want to apply the individual presolve routines differently, or |
218 | perhaps add your own to the mix, define a derived class and override |
219 | this method |
220 | */ |
221 | virtual const CoinPresolveAction *presolve(CoinPresolveMatrix *prob); |
222 | |
223 | /*! \brief Reverse presolve transformations to recover the solution |
224 | to the original problem. |
225 | |
226 | Handles the core activity of applying postsolve transformations. |
227 | |
228 | Postsolving is pretty generic; just apply the transformations in reverse |
229 | order. You will probably only be interested in overriding this method if |
230 | you want to add code to test for consistency while debugging new presolve |
231 | techniques. |
232 | */ |
233 | virtual void postsolve(CoinPostsolveMatrix &prob); |
234 | |
235 | /*! \brief Destroys queued postsolve actions. |
236 | |
237 | <i>E.g.</i>, when presolve() determines the problem is infeasible, so that |
238 | it will not be necessary to actually solve the presolved problem and |
239 | convert the result back to the original problem. |
240 | */ |
241 | void gutsOfDestroy(); |
242 | }; |
243 | #endif |
244 | |