3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2008
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
20 #include<lemon/lp_soplex.h>
22 #include <soplex/soplex.h>
26 ///\brief Implementation of the LEMON-SOPLEX lp solver interface.
29 LpSoplex::LpSoplex() : LpSolverBase() {
30 rows.setIdHandler(relocateIdHandler);
31 cols.setIdHandler(relocateIdHandler);
32 soplex = new soplex::SoPlex;
36 LpSoplex::~LpSoplex() {
40 LpSoplex::LpSoplex(const LpSoplex& lp) : LpSolverBase() {
42 rows.setIdHandler(relocateIdHandler);
45 cols.setIdHandler(relocateIdHandler);
47 soplex = new soplex::SoPlex;
48 (*static_cast<soplex::SPxLP*>(soplex)) = *(lp.soplex);
50 colNames = lp.colNames;
51 invColNames = lp.invColNames;
53 primal_value = lp.primal_value;
54 dual_value = lp.dual_value;
58 LpSolverBase* LpSoplex::_newLp() {
59 LpSoplex* newlp = new LpSoplex();
63 LpSolverBase* LpSoplex::_copyLp() {
64 LpSoplex* newlp = new LpSoplex(*this);
68 int LpSoplex::_addCol() {
70 c.setLower(-soplex::infinity);
71 c.setUpper(soplex::infinity);
74 colNames.push_back(std::string());
75 primal_value.push_back(0.0);
78 return soplex->nCols() - 1;
81 int LpSoplex::_addRow() {
83 r.setLhs(-soplex::infinity);
84 r.setRhs(soplex::infinity);
87 dual_value.push_back(0.0);
90 return soplex->nRows() - 1;
94 void LpSoplex::_eraseCol(int i) {
96 invColNames.erase(colNames[i]);
97 colNames[i] = colNames.back();
98 invColNames[colNames.back()] = i;
100 primal_value[i] = primal_value.back();
101 primal_value.pop_back();
105 void LpSoplex::_eraseRow(int i) {
106 soplex->removeRow(i);
107 dual_value[i] = dual_value.back();
108 dual_value.pop_back();
112 void LpSoplex::_getColName(int c, std::string &name) const {
116 void LpSoplex::_setColName(int c, const std::string &name) {
117 invColNames.erase(colNames[c]);
120 invColNames.insert(std::make_pair(name, c));
124 int LpSoplex::_colByName(const std::string& name) const {
125 std::map<std::string, int>::const_iterator it =
126 invColNames.find(name);
127 if (it != invColNames.end()) {
135 void LpSoplex::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e) {
136 for (int j = 0; j < soplex->nCols(); ++j) {
137 soplex->changeElement(i, j, 0.0);
139 for(ConstRowIterator it = b; it != e; ++it) {
140 soplex->changeElement(i, it->first, it->second);
145 void LpSoplex::_getRowCoeffs(int i, RowIterator b) const {
146 const soplex::SVector& vec = soplex->rowVector(i);
147 for (int k = 0; k < vec.size(); ++k) {
148 *b = std::make_pair(vec.index(k), vec.value(k));
153 void LpSoplex::_setColCoeffs(int j, ConstColIterator b, ConstColIterator e) {
154 for (int i = 0; i < soplex->nRows(); ++i) {
155 soplex->changeElement(i, j, 0.0);
157 for(ConstColIterator it = b; it != e; ++it) {
158 soplex->changeElement(it->first, j, it->second);
163 void LpSoplex::_getColCoeffs(int i, ColIterator b) const {
164 const soplex::SVector& vec = soplex->colVector(i);
165 for (int k = 0; k < vec.size(); ++k) {
166 *b = std::make_pair(vec.index(k), vec.value(k));
171 void LpSoplex::_setCoeff(int i, int j, Value value) {
172 soplex->changeElement(i, j, value);
176 LpSoplex::Value LpSoplex::_getCoeff(int i, int j) const {
177 return soplex->rowVector(i)[j];
180 void LpSoplex::_setColLowerBound(int i, Value value) {
181 soplex->changeLower(i, value != -INF ? value : -soplex::infinity);
185 LpSoplex::Value LpSoplex::_getColLowerBound(int i) const {
186 double value = soplex->lower(i);
187 return value != -soplex::infinity ? value : -INF;
190 void LpSoplex::_setColUpperBound(int i, Value value) {
191 soplex->changeUpper(i, value != INF ? value : soplex::infinity);
195 LpSoplex::Value LpSoplex::_getColUpperBound(int i) const {
196 double value = soplex->upper(i);
197 return value != soplex::infinity ? value : INF;
200 void LpSoplex::_setRowBounds(int i, Value lb, Value ub) {
201 soplex->changeRange(i, lb != -INF ? lb : -soplex::infinity,
202 ub != INF ? ub : soplex::infinity);
205 void LpSoplex::_getRowBounds(int i, Value &lower, Value &upper) const {
206 lower = soplex->lhs(i);
207 if (lower == -soplex::infinity) lower = -INF;
208 upper = soplex->rhs(i);
209 if (upper == -soplex::infinity) upper = INF;
212 void LpSoplex::_setObjCoeff(int i, Value obj_coef) {
213 soplex->changeObj(i, obj_coef);
217 LpSoplex::Value LpSoplex::_getObjCoeff(int i) const {
218 return soplex->obj(i);
221 void LpSoplex::_clearObj() {
222 for (int i = 0; i < soplex->nCols(); ++i) {
223 soplex->changeObj(i, 0.0);
228 LpSoplex::SolveExitStatus LpSoplex::_solve() {
229 soplex::SPxSolver::Status status = soplex->solve();
231 soplex::Vector pv(primal_value.size(), &primal_value[0]);
232 soplex->getPrimal(pv);
234 soplex::Vector dv(dual_value.size(), &dual_value[0]);
238 case soplex::SPxSolver::OPTIMAL:
239 case soplex::SPxSolver::INFEASIBLE:
240 case soplex::SPxSolver::UNBOUNDED:
248 LpSoplex::Value LpSoplex::_getPrimal(int i) const {
249 return primal_value[i];
252 LpSoplex::Value LpSoplex::_getDual(int i) const {
253 return dual_value[i];
256 LpSoplex::Value LpSoplex::_getPrimalValue() const {
257 return soplex->objValue();
260 bool LpSoplex::_isBasicCol(int i) const {
261 return soplex->getBasisColStatus(i) == soplex::SPxSolver::BASIC;
264 LpSoplex::SolutionStatus LpSoplex::_getPrimalStatus() const {
265 if (!solved) return UNDEFINED;
266 switch (soplex->status()) {
267 case soplex::SPxSolver::OPTIMAL:
269 case soplex::SPxSolver::UNBOUNDED:
271 case soplex::SPxSolver::INFEASIBLE:
278 LpSoplex::SolutionStatus LpSoplex::_getDualStatus() const {
279 if (!solved) return UNDEFINED;
280 switch (soplex->status()) {
281 case soplex::SPxSolver::OPTIMAL:
283 case soplex::SPxSolver::UNBOUNDED:
290 LpSoplex::ProblemTypes LpSoplex::_getProblemType() const {
291 if (!solved) return UNKNOWN;
292 switch (soplex->status()) {
293 case soplex::SPxSolver::OPTIMAL:
294 return PRIMAL_DUAL_FEASIBLE;
295 case soplex::SPxSolver::UNBOUNDED:
296 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
302 void LpSoplex::_setMax() {
303 soplex->changeSense(soplex::SPxSolver::MAXIMIZE);
306 void LpSoplex::_setMin() {
307 soplex->changeSense(soplex::SPxSolver::MINIMIZE);
310 bool LpSoplex::_isMax() const {
311 return soplex->spxSense() == soplex::SPxSolver::MAXIMIZE;