3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2006
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 LpSolverBase &LpSoplex::_newLp() {
41 LpSoplex* newlp = new LpSoplex();
45 LpSolverBase &LpSoplex::_copyLp() {
46 LpSoplex* newlp = new LpSoplex();
47 ((soplex::SPxLP&)*(newlp->soplex)) = *soplex;
51 int LpSoplex::_addCol() {
53 col.setLower(-soplex::infinity);
54 col.setUpper(soplex::infinity);
57 colNames.push_back(std::string());
58 primal_value.push_back(0.0);
61 return soplex->nCols() - 1;
64 int LpSoplex::_addRow() {
66 row.setLhs(-soplex::infinity);
67 row.setRhs(soplex::infinity);
70 dual_value.push_back(0.0);
73 return soplex->nRows() - 1;
77 void LpSoplex::_eraseCol(int i) {
79 colNames[i] = colNames.back();
81 primal_value[i] = primal_value.back();
82 primal_value.pop_back();
86 void LpSoplex::_eraseRow(int i) {
88 dual_value[i] = dual_value.back();
89 dual_value.pop_back();
93 void LpSoplex::_getColName(int col, std::string &name) {
97 void LpSoplex::_setColName(int col, const std::string &name) {
102 void LpSoplex::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e) {
103 for (int j = 0; j < soplex->nCols(); ++j) {
104 soplex->changeElement(i, j, 0.0);
106 for(ConstRowIterator it = b; it != e; ++it) {
107 soplex->changeElement(i, it->first, it->second);
112 void LpSoplex::_getRowCoeffs(int i, RowIterator b) {
113 const soplex::SVector& vec = soplex->rowVector(i);
114 for (int k = 0; k < vec.size(); ++k) {
115 *b = std::make_pair(vec.index(k), vec.value(k));
120 void LpSoplex::_setColCoeffs(int j, ConstColIterator b, ConstColIterator e) {
121 for (int i = 0; i < soplex->nRows(); ++i) {
122 soplex->changeElement(i, j, 0.0);
124 for(ConstColIterator it = b; it != e; ++it) {
125 soplex->changeElement(it->first, j, it->second);
130 void LpSoplex::_getColCoeffs(int i, ColIterator b) {
131 const soplex::SVector& vec = soplex->colVector(i);
132 for (int k = 0; k < vec.size(); ++k) {
133 *b = std::make_pair(vec.index(k), vec.value(k));
138 void LpSoplex::_setCoeff(int i, int j, Value value) {
139 soplex->changeElement(i, j, value);
143 LpSoplex::Value LpSoplex::_getCoeff(int i, int j) {
144 return soplex->rowVector(i)[j];
147 void LpSoplex::_setColLowerBound(int i, Value value) {
148 soplex->changeLower(i, value != -INF ? value : -soplex::infinity);
152 LpSoplex::Value LpSoplex::_getColLowerBound(int i) {
153 double value = soplex->lower(i);
154 return value != -soplex::infinity ? value : -INF;
157 void LpSoplex::_setColUpperBound(int i, Value value) {
158 soplex->changeUpper(i, value != INF ? value : soplex::infinity);
162 LpSoplex::Value LpSoplex::_getColUpperBound(int i) {
163 double value = soplex->upper(i);
164 return value != soplex::infinity ? value : INF;
167 void LpSoplex::_setRowBounds(int i, Value lb, Value ub) {
168 soplex->changeRange(i, lb != -INF ? lb : -soplex::infinity,
169 ub != INF ? ub : soplex::infinity);
172 void LpSoplex::_getRowBounds(int i, Value &lower, Value &upper) {
173 lower = soplex->lhs(i);
174 if (lower == -soplex::infinity) lower = -INF;
175 upper = soplex->rhs(i);
176 if (upper == -soplex::infinity) upper = INF;
179 void LpSoplex::_setObjCoeff(int i, Value obj_coef) {
180 soplex->changeObj(i, obj_coef);
184 LpSoplex::Value LpSoplex::_getObjCoeff(int i) {
185 return soplex->obj(i);
188 void LpSoplex::_clearObj() {
189 for (int i = 0; i < soplex->nCols(); ++i) {
190 soplex->changeObj(i, 0.0);
195 LpSoplex::SolveExitStatus LpSoplex::_solve() {
196 soplex::SPxSolver::Status status = soplex->solve();
198 soplex::Vector pv(primal_value.size(), &primal_value[0]);
199 soplex->getPrimal(pv);
201 soplex::Vector dv(dual_value.size(), &dual_value[0]);
205 case soplex::SPxSolver::OPTIMAL:
206 case soplex::SPxSolver::INFEASIBLE:
207 case soplex::SPxSolver::UNBOUNDED:
215 LpSoplex::Value LpSoplex::_getPrimal(int i) {
216 return primal_value[i];
219 LpSoplex::Value LpSoplex::_getDual(int i) {
220 return dual_value[i];
223 LpSoplex::Value LpSoplex::_getPrimalValue() {
224 return soplex->objValue();
227 bool LpSoplex::_isBasicCol(int i) {
228 return soplex->getBasisColStatus(i) == soplex::SPxSolver::BASIC;
231 LpSoplex::SolutionStatus LpSoplex::_getPrimalStatus() {
232 if (!solved) return UNDEFINED;
233 switch (soplex->status()) {
234 case soplex::SPxSolver::OPTIMAL:
236 case soplex::SPxSolver::UNBOUNDED:
238 case soplex::SPxSolver::INFEASIBLE:
245 LpSoplex::SolutionStatus LpSoplex::_getDualStatus() {
246 if (!solved) return UNDEFINED;
247 switch (soplex->status()) {
248 case soplex::SPxSolver::OPTIMAL:
250 case soplex::SPxSolver::UNBOUNDED:
257 LpSoplex::ProblemTypes LpSoplex::_getProblemType() {
258 if (!solved) return UNKNOWN;
259 switch (soplex->status()) {
260 case soplex::SPxSolver::OPTIMAL:
261 return PRIMAL_DUAL_FEASIBLE;
262 case soplex::SPxSolver::UNBOUNDED:
263 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
269 void LpSoplex::_setMax() {
270 soplex->changeSense(soplex::SPxSolver::MAXIMIZE);
273 void LpSoplex::_setMin() {
274 soplex->changeSense(soplex::SPxSolver::MINIMIZE);
277 bool LpSoplex::_isMax() {
278 return soplex->spxSense() == soplex::SPxSolver::MAXIMIZE;