14 * express or implied, and with no claim as to its suitability for any |
14 * express or implied, and with no claim as to its suitability for any |
15 * purpose. |
15 * purpose. |
16 * |
16 * |
17 */ |
17 */ |
18 |
18 |
19 #include<iostream> |
19 #include <iostream> |
20 #include<lemon/lp_soplex.h> |
20 #include <lemon/lp_soplex.h> |
21 |
21 |
22 #include <soplex/soplex.h> |
22 #include <soplex/soplex.h> |
23 |
23 |
24 |
24 |
25 ///\file |
25 ///\file |
26 ///\brief Implementation of the LEMON-SOPLEX lp solver interface. |
26 ///\brief Implementation of the LEMON-SOPLEX lp solver interface. |
27 namespace lemon { |
27 namespace lemon { |
28 |
28 |
29 LpSoplex::LpSoplex() : LpSolverBase() { |
29 LpSoplex::LpSoplex() { |
30 rows.setIdHandler(relocateIdHandler); |
|
31 cols.setIdHandler(relocateIdHandler); |
|
32 soplex = new soplex::SoPlex; |
30 soplex = new soplex::SoPlex; |
33 solved = false; |
|
34 } |
31 } |
35 |
32 |
36 LpSoplex::~LpSoplex() { |
33 LpSoplex::~LpSoplex() { |
37 delete soplex; |
34 delete soplex; |
38 } |
35 } |
39 |
36 |
40 LpSoplex::LpSoplex(const LpSoplex& lp) : LpSolverBase() { |
37 LpSoplex::LpSoplex(const LpSoplex& lp) { |
41 rows = lp.rows; |
38 rows = lp.rows; |
42 rows.setIdHandler(relocateIdHandler); |
|
43 |
|
44 cols = lp.cols; |
39 cols = lp.cols; |
45 cols.setIdHandler(relocateIdHandler); |
|
46 |
40 |
47 soplex = new soplex::SoPlex; |
41 soplex = new soplex::SoPlex; |
48 (*static_cast<soplex::SPxLP*>(soplex)) = *(lp.soplex); |
42 (*static_cast<soplex::SPxLP*>(soplex)) = *(lp.soplex); |
49 |
43 |
50 colNames = lp.colNames; |
44 _col_names = lp._col_names; |
51 invColNames = lp.invColNames; |
45 _col_names_ref = lp._col_names_ref; |
52 |
46 |
53 primal_value = lp.primal_value; |
47 _row_names = lp._row_names; |
54 dual_value = lp.dual_value; |
48 _row_names_ref = lp._row_names_ref; |
55 |
49 |
56 } |
50 } |
57 |
51 |
58 LpSolverBase* LpSoplex::_newLp() { |
52 void LpSoplex::_clear_temporals() { |
|
53 _primal_values.clear(); |
|
54 _dual_values.clear(); |
|
55 } |
|
56 |
|
57 LpSoplex* LpSoplex::_newSolver() const { |
59 LpSoplex* newlp = new LpSoplex(); |
58 LpSoplex* newlp = new LpSoplex(); |
60 return newlp; |
59 return newlp; |
61 } |
60 } |
62 |
61 |
63 LpSolverBase* LpSoplex::_copyLp() { |
62 LpSoplex* LpSoplex::_cloneSolver() const { |
64 LpSoplex* newlp = new LpSoplex(*this); |
63 LpSoplex* newlp = new LpSoplex(*this); |
65 return newlp; |
64 return newlp; |
66 } |
65 } |
|
66 |
|
67 const char* LpSoplex::_solverName() const { return "LpSoplex"; } |
67 |
68 |
68 int LpSoplex::_addCol() { |
69 int LpSoplex::_addCol() { |
69 soplex::LPCol c; |
70 soplex::LPCol c; |
70 c.setLower(-soplex::infinity); |
71 c.setLower(-soplex::infinity); |
71 c.setUpper(soplex::infinity); |
72 c.setUpper(soplex::infinity); |
72 soplex->addCol(c); |
73 soplex->addCol(c); |
73 |
74 |
74 colNames.push_back(std::string()); |
75 _col_names.push_back(std::string()); |
75 primal_value.push_back(0.0); |
|
76 solved = false; |
|
77 |
76 |
78 return soplex->nCols() - 1; |
77 return soplex->nCols() - 1; |
79 } |
78 } |
80 |
79 |
81 int LpSoplex::_addRow() { |
80 int LpSoplex::_addRow() { |
82 soplex::LPRow r; |
81 soplex::LPRow r; |
83 r.setLhs(-soplex::infinity); |
82 r.setLhs(-soplex::infinity); |
84 r.setRhs(soplex::infinity); |
83 r.setRhs(soplex::infinity); |
85 soplex->addRow(r); |
84 soplex->addRow(r); |
86 |
85 |
87 dual_value.push_back(0.0); |
86 _row_names.push_back(std::string()); |
88 solved = false; |
|
89 |
87 |
90 return soplex->nRows() - 1; |
88 return soplex->nRows() - 1; |
91 } |
89 } |
92 |
90 |
93 |
91 |
94 void LpSoplex::_eraseCol(int i) { |
92 void LpSoplex::_eraseCol(int i) { |
95 soplex->removeCol(i); |
93 soplex->removeCol(i); |
96 invColNames.erase(colNames[i]); |
94 _col_names_ref.erase(_col_names[i]); |
97 colNames[i] = colNames.back(); |
95 _col_names[i] = _col_names.back(); |
98 invColNames[colNames.back()] = i; |
96 _col_names_ref[_col_names.back()] = i; |
99 colNames.pop_back(); |
97 _col_names.pop_back(); |
100 primal_value[i] = primal_value.back(); |
|
101 primal_value.pop_back(); |
|
102 solved = false; |
|
103 } |
98 } |
104 |
99 |
105 void LpSoplex::_eraseRow(int i) { |
100 void LpSoplex::_eraseRow(int i) { |
106 soplex->removeRow(i); |
101 soplex->removeRow(i); |
107 dual_value[i] = dual_value.back(); |
102 _row_names_ref.erase(_row_names[i]); |
108 dual_value.pop_back(); |
103 _row_names[i] = _row_names.back(); |
109 solved = false; |
104 _row_names_ref[_row_names.back()] = i; |
|
105 _row_names.pop_back(); |
|
106 } |
|
107 |
|
108 void LpSoplex::_eraseColId(int i) { |
|
109 cols.eraseIndex(i); |
|
110 cols.relocateIndex(i, cols.maxIndex()); |
|
111 } |
|
112 void LpSoplex::_eraseRowId(int i) { |
|
113 rows.eraseIndex(i); |
|
114 rows.relocateIndex(i, rows.maxIndex()); |
110 } |
115 } |
111 |
116 |
112 void LpSoplex::_getColName(int c, std::string &name) const { |
117 void LpSoplex::_getColName(int c, std::string &name) const { |
113 name = colNames[c]; |
118 name = _col_names[c]; |
114 } |
119 } |
115 |
120 |
116 void LpSoplex::_setColName(int c, const std::string &name) { |
121 void LpSoplex::_setColName(int c, const std::string &name) { |
117 invColNames.erase(colNames[c]); |
122 _col_names_ref.erase(_col_names[c]); |
118 colNames[c] = name; |
123 _col_names[c] = name; |
119 if (!name.empty()) { |
124 if (!name.empty()) { |
120 invColNames.insert(std::make_pair(name, c)); |
125 _col_names_ref.insert(std::make_pair(name, c)); |
121 } |
126 } |
122 } |
127 } |
123 |
128 |
124 int LpSoplex::_colByName(const std::string& name) const { |
129 int LpSoplex::_colByName(const std::string& name) const { |
125 std::map<std::string, int>::const_iterator it = |
130 std::map<std::string, int>::const_iterator it = |
126 invColNames.find(name); |
131 _col_names_ref.find(name); |
127 if (it != invColNames.end()) { |
132 if (it != _col_names_ref.end()) { |
128 return it->second; |
133 return it->second; |
129 } else { |
134 } else { |
130 return -1; |
135 return -1; |
131 } |
136 } |
132 } |
137 } |
133 |
138 |
134 |
139 void LpSoplex::_getRowName(int r, std::string &name) const { |
135 void LpSoplex::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e) { |
140 name = _row_names[r]; |
|
141 } |
|
142 |
|
143 void LpSoplex::_setRowName(int r, const std::string &name) { |
|
144 _row_names_ref.erase(_row_names[r]); |
|
145 _row_names[r] = name; |
|
146 if (!name.empty()) { |
|
147 _row_names_ref.insert(std::make_pair(name, r)); |
|
148 } |
|
149 } |
|
150 |
|
151 int LpSoplex::_rowByName(const std::string& name) const { |
|
152 std::map<std::string, int>::const_iterator it = |
|
153 _row_names_ref.find(name); |
|
154 if (it != _row_names_ref.end()) { |
|
155 return it->second; |
|
156 } else { |
|
157 return -1; |
|
158 } |
|
159 } |
|
160 |
|
161 |
|
162 void LpSoplex::_setRowCoeffs(int i, ExprIterator b, ExprIterator e) { |
136 for (int j = 0; j < soplex->nCols(); ++j) { |
163 for (int j = 0; j < soplex->nCols(); ++j) { |
137 soplex->changeElement(i, j, 0.0); |
164 soplex->changeElement(i, j, 0.0); |
138 } |
165 } |
139 for(ConstRowIterator it = b; it != e; ++it) { |
166 for(ExprIterator it = b; it != e; ++it) { |
140 soplex->changeElement(i, it->first, it->second); |
167 soplex->changeElement(i, it->first, it->second); |
141 } |
168 } |
142 solved = false; |
169 } |
143 } |
170 |
144 |
171 void LpSoplex::_getRowCoeffs(int i, InsertIterator b) const { |
145 void LpSoplex::_getRowCoeffs(int i, RowIterator b) const { |
|
146 const soplex::SVector& vec = soplex->rowVector(i); |
172 const soplex::SVector& vec = soplex->rowVector(i); |
147 for (int k = 0; k < vec.size(); ++k) { |
173 for (int k = 0; k < vec.size(); ++k) { |
148 *b = std::make_pair(vec.index(k), vec.value(k)); |
174 *b = std::make_pair(vec.index(k), vec.value(k)); |
149 ++b; |
175 ++b; |
150 } |
176 } |
151 } |
177 } |
152 |
178 |
153 void LpSoplex::_setColCoeffs(int j, ConstColIterator b, ConstColIterator e) { |
179 void LpSoplex::_setColCoeffs(int j, ExprIterator b, ExprIterator e) { |
154 for (int i = 0; i < soplex->nRows(); ++i) { |
180 for (int i = 0; i < soplex->nRows(); ++i) { |
155 soplex->changeElement(i, j, 0.0); |
181 soplex->changeElement(i, j, 0.0); |
156 } |
182 } |
157 for(ConstColIterator it = b; it != e; ++it) { |
183 for(ExprIterator it = b; it != e; ++it) { |
158 soplex->changeElement(it->first, j, it->second); |
184 soplex->changeElement(it->first, j, it->second); |
159 } |
185 } |
160 solved = false; |
186 } |
161 } |
187 |
162 |
188 void LpSoplex::_getColCoeffs(int i, InsertIterator b) const { |
163 void LpSoplex::_getColCoeffs(int i, ColIterator b) const { |
|
164 const soplex::SVector& vec = soplex->colVector(i); |
189 const soplex::SVector& vec = soplex->colVector(i); |
165 for (int k = 0; k < vec.size(); ++k) { |
190 for (int k = 0; k < vec.size(); ++k) { |
166 *b = std::make_pair(vec.index(k), vec.value(k)); |
191 *b = std::make_pair(vec.index(k), vec.value(k)); |
167 ++b; |
192 ++b; |
168 } |
193 } |
169 } |
194 } |
170 |
195 |
171 void LpSoplex::_setCoeff(int i, int j, Value value) { |
196 void LpSoplex::_setCoeff(int i, int j, Value value) { |
172 soplex->changeElement(i, j, value); |
197 soplex->changeElement(i, j, value); |
173 solved = false; |
|
174 } |
198 } |
175 |
199 |
176 LpSoplex::Value LpSoplex::_getCoeff(int i, int j) const { |
200 LpSoplex::Value LpSoplex::_getCoeff(int i, int j) const { |
177 return soplex->rowVector(i)[j]; |
201 return soplex->rowVector(i)[j]; |
178 } |
202 } |
179 |
203 |
180 void LpSoplex::_setColLowerBound(int i, Value value) { |
204 void LpSoplex::_setColLowerBound(int i, Value value) { |
|
205 LEMON_ASSERT(value != INF, "Invalid bound"); |
181 soplex->changeLower(i, value != -INF ? value : -soplex::infinity); |
206 soplex->changeLower(i, value != -INF ? value : -soplex::infinity); |
182 solved = false; |
|
183 } |
207 } |
184 |
208 |
185 LpSoplex::Value LpSoplex::_getColLowerBound(int i) const { |
209 LpSoplex::Value LpSoplex::_getColLowerBound(int i) const { |
186 double value = soplex->lower(i); |
210 double value = soplex->lower(i); |
187 return value != -soplex::infinity ? value : -INF; |
211 return value != -soplex::infinity ? value : -INF; |
188 } |
212 } |
189 |
213 |
190 void LpSoplex::_setColUpperBound(int i, Value value) { |
214 void LpSoplex::_setColUpperBound(int i, Value value) { |
|
215 LEMON_ASSERT(value != -INF, "Invalid bound"); |
191 soplex->changeUpper(i, value != INF ? value : soplex::infinity); |
216 soplex->changeUpper(i, value != INF ? value : soplex::infinity); |
192 solved = false; |
|
193 } |
217 } |
194 |
218 |
195 LpSoplex::Value LpSoplex::_getColUpperBound(int i) const { |
219 LpSoplex::Value LpSoplex::_getColUpperBound(int i) const { |
196 double value = soplex->upper(i); |
220 double value = soplex->upper(i); |
197 return value != soplex::infinity ? value : INF; |
221 return value != soplex::infinity ? value : INF; |
198 } |
222 } |
199 |
223 |
200 void LpSoplex::_setRowBounds(int i, Value lb, Value ub) { |
224 void LpSoplex::_setRowLowerBound(int i, Value lb) { |
201 soplex->changeRange(i, lb != -INF ? lb : -soplex::infinity, |
225 LEMON_ASSERT(lb != INF, "Invalid bound"); |
202 ub != INF ? ub : soplex::infinity); |
226 soplex->changeRange(i, lb != -INF ? lb : -soplex::infinity, soplex->rhs(i)); |
203 solved = false; |
227 } |
204 } |
228 |
205 void LpSoplex::_getRowBounds(int i, Value &lower, Value &upper) const { |
229 LpSoplex::Value LpSoplex::_getRowLowerBound(int i) const { |
206 lower = soplex->lhs(i); |
230 double res = soplex->lhs(i); |
207 if (lower == -soplex::infinity) lower = -INF; |
231 return res == -soplex::infinity ? -INF : res; |
208 upper = soplex->rhs(i); |
232 } |
209 if (upper == -soplex::infinity) upper = INF; |
233 |
|
234 void LpSoplex::_setRowUpperBound(int i, Value ub) { |
|
235 LEMON_ASSERT(ub != -INF, "Invalid bound"); |
|
236 soplex->changeRange(i, soplex->lhs(i), ub != INF ? ub : soplex::infinity); |
|
237 } |
|
238 |
|
239 LpSoplex::Value LpSoplex::_getRowUpperBound(int i) const { |
|
240 double res = soplex->rhs(i); |
|
241 return res == soplex::infinity ? INF : res; |
|
242 } |
|
243 |
|
244 void LpSoplex::_setObjCoeffs(ExprIterator b, ExprIterator e) { |
|
245 for (int j = 0; j < soplex->nCols(); ++j) { |
|
246 soplex->changeObj(j, 0.0); |
|
247 } |
|
248 for (ExprIterator it = b; it != e; ++it) { |
|
249 soplex->changeObj(it->first, it->second); |
|
250 } |
|
251 } |
|
252 |
|
253 void LpSoplex::_getObjCoeffs(InsertIterator b) const { |
|
254 for (int j = 0; j < soplex->nCols(); ++j) { |
|
255 Value coef = soplex->obj(j); |
|
256 if (coef != 0.0) { |
|
257 *b = std::make_pair(j, coef); |
|
258 ++b; |
|
259 } |
|
260 } |
210 } |
261 } |
211 |
262 |
212 void LpSoplex::_setObjCoeff(int i, Value obj_coef) { |
263 void LpSoplex::_setObjCoeff(int i, Value obj_coef) { |
213 soplex->changeObj(i, obj_coef); |
264 soplex->changeObj(i, obj_coef); |
214 solved = false; |
|
215 } |
265 } |
216 |
266 |
217 LpSoplex::Value LpSoplex::_getObjCoeff(int i) const { |
267 LpSoplex::Value LpSoplex::_getObjCoeff(int i) const { |
218 return soplex->obj(i); |
268 return soplex->obj(i); |
219 } |
269 } |
220 |
270 |
221 void LpSoplex::_clearObj() { |
|
222 for (int i = 0; i < soplex->nCols(); ++i) { |
|
223 soplex->changeObj(i, 0.0); |
|
224 } |
|
225 solved = false; |
|
226 } |
|
227 |
|
228 LpSoplex::SolveExitStatus LpSoplex::_solve() { |
271 LpSoplex::SolveExitStatus LpSoplex::_solve() { |
|
272 |
|
273 _clear_temporals(); |
|
274 |
229 soplex::SPxSolver::Status status = soplex->solve(); |
275 soplex::SPxSolver::Status status = soplex->solve(); |
230 |
|
231 soplex::Vector pv(primal_value.size(), &primal_value[0]); |
|
232 soplex->getPrimal(pv); |
|
233 |
|
234 soplex::Vector dv(dual_value.size(), &dual_value[0]); |
|
235 soplex->getDual(dv); |
|
236 |
276 |
237 switch (status) { |
277 switch (status) { |
238 case soplex::SPxSolver::OPTIMAL: |
278 case soplex::SPxSolver::OPTIMAL: |
239 case soplex::SPxSolver::INFEASIBLE: |
279 case soplex::SPxSolver::INFEASIBLE: |
240 case soplex::SPxSolver::UNBOUNDED: |
280 case soplex::SPxSolver::UNBOUNDED: |
241 solved = true; |
|
242 return SOLVED; |
281 return SOLVED; |
243 default: |
282 default: |
244 return UNSOLVED; |
283 return UNSOLVED; |
245 } |
284 } |
246 } |
285 } |
247 |
286 |
248 LpSoplex::Value LpSoplex::_getPrimal(int i) const { |
287 LpSoplex::Value LpSoplex::_getPrimal(int i) const { |
249 return primal_value[i]; |
288 if (_primal_values.empty()) { |
|
289 _primal_values.resize(soplex->nCols()); |
|
290 soplex::Vector pv(_primal_values.size(), &_primal_values.front()); |
|
291 soplex->getPrimal(pv); |
|
292 } |
|
293 return _primal_values[i]; |
250 } |
294 } |
251 |
295 |
252 LpSoplex::Value LpSoplex::_getDual(int i) const { |
296 LpSoplex::Value LpSoplex::_getDual(int i) const { |
253 return dual_value[i]; |
297 if (_dual_values.empty()) { |
|
298 _dual_values.resize(soplex->nRows()); |
|
299 soplex::Vector dv(_dual_values.size(), &_dual_values.front()); |
|
300 soplex->getDual(dv); |
|
301 } |
|
302 return _dual_values[i]; |
254 } |
303 } |
255 |
304 |
256 LpSoplex::Value LpSoplex::_getPrimalValue() const { |
305 LpSoplex::Value LpSoplex::_getPrimalValue() const { |
257 return soplex->objValue(); |
306 return soplex->objValue(); |
258 } |
307 } |
259 |
308 |
260 bool LpSoplex::_isBasicCol(int i) const { |
309 LpSoplex::VarStatus LpSoplex::_getColStatus(int i) const { |
261 return soplex->getBasisColStatus(i) == soplex::SPxSolver::BASIC; |
310 switch (soplex->getBasisColStatus(i)) { |
262 } |
311 case soplex::SPxSolver::BASIC: |
263 |
312 return BASIC; |
264 LpSoplex::SolutionStatus LpSoplex::_getPrimalStatus() const { |
313 case soplex::SPxSolver::ON_UPPER: |
265 if (!solved) return UNDEFINED; |
314 return UPPER; |
|
315 case soplex::SPxSolver::ON_LOWER: |
|
316 return LOWER; |
|
317 case soplex::SPxSolver::FIXED: |
|
318 return FIXED; |
|
319 case soplex::SPxSolver::ZERO: |
|
320 return FREE; |
|
321 default: |
|
322 LEMON_ASSERT(false, "Wrong column status"); |
|
323 return VarStatus(); |
|
324 } |
|
325 } |
|
326 |
|
327 LpSoplex::VarStatus LpSoplex::_getRowStatus(int i) const { |
|
328 switch (soplex->getBasisRowStatus(i)) { |
|
329 case soplex::SPxSolver::BASIC: |
|
330 return BASIC; |
|
331 case soplex::SPxSolver::ON_UPPER: |
|
332 return UPPER; |
|
333 case soplex::SPxSolver::ON_LOWER: |
|
334 return LOWER; |
|
335 case soplex::SPxSolver::FIXED: |
|
336 return FIXED; |
|
337 case soplex::SPxSolver::ZERO: |
|
338 return FREE; |
|
339 default: |
|
340 LEMON_ASSERT(false, "Wrong row status"); |
|
341 return VarStatus(); |
|
342 } |
|
343 } |
|
344 |
|
345 LpSoplex::Value LpSoplex::_getPrimalRay(int i) const { |
|
346 if (_primal_ray.empty()) { |
|
347 _primal_ray.resize(soplex->nCols()); |
|
348 soplex::Vector pv(_primal_ray.size(), &_primal_ray.front()); |
|
349 soplex->getDualfarkas(pv); |
|
350 } |
|
351 return _primal_ray[i]; |
|
352 } |
|
353 |
|
354 LpSoplex::Value LpSoplex::_getDualRay(int i) const { |
|
355 if (_dual_ray.empty()) { |
|
356 _dual_ray.resize(soplex->nRows()); |
|
357 soplex::Vector dv(_dual_ray.size(), &_dual_ray.front()); |
|
358 soplex->getDualfarkas(dv); |
|
359 } |
|
360 return _dual_ray[i]; |
|
361 } |
|
362 |
|
363 LpSoplex::ProblemType LpSoplex::_getPrimalType() const { |
266 switch (soplex->status()) { |
364 switch (soplex->status()) { |
267 case soplex::SPxSolver::OPTIMAL: |
365 case soplex::SPxSolver::OPTIMAL: |
268 return OPTIMAL; |
366 return OPTIMAL; |
269 case soplex::SPxSolver::UNBOUNDED: |
367 case soplex::SPxSolver::UNBOUNDED: |
270 return INFINITE; |
368 return UNBOUNDED; |
271 case soplex::SPxSolver::INFEASIBLE: |
369 case soplex::SPxSolver::INFEASIBLE: |
272 return INFEASIBLE; |
370 return INFEASIBLE; |
273 default: |
371 default: |
274 return UNDEFINED; |
372 return UNDEFINED; |
275 } |
373 } |
276 } |
374 } |
277 |
375 |
278 LpSoplex::SolutionStatus LpSoplex::_getDualStatus() const { |
376 LpSoplex::ProblemType LpSoplex::_getDualType() const { |
279 if (!solved) return UNDEFINED; |
|
280 switch (soplex->status()) { |
377 switch (soplex->status()) { |
281 case soplex::SPxSolver::OPTIMAL: |
378 case soplex::SPxSolver::OPTIMAL: |
282 return OPTIMAL; |
379 return OPTIMAL; |
283 case soplex::SPxSolver::UNBOUNDED: |
380 case soplex::SPxSolver::UNBOUNDED: |
|
381 return UNBOUNDED; |
|
382 case soplex::SPxSolver::INFEASIBLE: |
284 return INFEASIBLE; |
383 return INFEASIBLE; |
285 default: |
384 default: |
286 return UNDEFINED; |
385 return UNDEFINED; |
287 } |
386 } |
288 } |
387 } |
289 |
388 |
290 LpSoplex::ProblemTypes LpSoplex::_getProblemType() const { |
389 void LpSoplex::_setSense(Sense sense) { |
291 if (!solved) return UNKNOWN; |
390 switch (sense) { |
292 switch (soplex->status()) { |
391 case MIN: |
293 case soplex::SPxSolver::OPTIMAL: |
392 soplex->changeSense(soplex::SPxSolver::MINIMIZE); |
294 return PRIMAL_DUAL_FEASIBLE; |
393 break; |
295 case soplex::SPxSolver::UNBOUNDED: |
394 case MAX: |
296 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE; |
395 soplex->changeSense(soplex::SPxSolver::MAXIMIZE); |
297 default: |
396 } |
298 return UNKNOWN; |
397 } |
299 } |
398 |
300 } |
399 LpSoplex::Sense LpSoplex::_getSense() const { |
301 |
400 switch (soplex->spxSense()) { |
302 void LpSoplex::_setMax() { |
401 case soplex::SPxSolver::MAXIMIZE: |
303 soplex->changeSense(soplex::SPxSolver::MAXIMIZE); |
402 return MAX; |
304 solved = false; |
403 case soplex::SPxSolver::MINIMIZE: |
305 } |
404 return MIN; |
306 void LpSoplex::_setMin() { |
405 default: |
307 soplex->changeSense(soplex::SPxSolver::MINIMIZE); |
406 LEMON_ASSERT(false, "Wrong sense."); |
308 solved = false; |
407 return LpSoplex::Sense(); |
309 } |
408 } |
310 bool LpSoplex::_isMax() const { |
409 } |
311 return soplex->spxSense() == soplex::SPxSolver::MAXIMIZE; |
410 |
312 } |
411 void LpSoplex::_clear() { |
313 |
412 soplex->clear(); |
|
413 _col_names.clear(); |
|
414 _col_names_ref.clear(); |
|
415 _row_names.clear(); |
|
416 _row_names_ref.clear(); |
|
417 cols.clear(); |
|
418 rows.clear(); |
|
419 _clear_temporals(); |
|
420 } |
314 |
421 |
315 } //namespace lemon |
422 } //namespace lemon |
316 |
423 |