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) const {
97 void LpSoplex::_setColName(int col, const std::string &name) {
98 invColNames.erase(colNames[col]);
101 invColNames.insert(std::make_pair(name, col));
105 int LpSoplex::_colByName(const std::string& name) const {
106 std::map<std::string, int>::const_iterator it =
107 invColNames.find(name);
108 if (it != invColNames.end()) {
116 void LpSoplex::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e) {
117 for (int j = 0; j < soplex->nCols(); ++j) {
118 soplex->changeElement(i, j, 0.0);
120 for(ConstRowIterator it = b; it != e; ++it) {
121 soplex->changeElement(i, it->first, it->second);
126 void LpSoplex::_getRowCoeffs(int i, RowIterator b) const {
127 const soplex::SVector& vec = soplex->rowVector(i);
128 for (int k = 0; k < vec.size(); ++k) {
129 *b = std::make_pair(vec.index(k), vec.value(k));
134 void LpSoplex::_setColCoeffs(int j, ConstColIterator b, ConstColIterator e) {
135 for (int i = 0; i < soplex->nRows(); ++i) {
136 soplex->changeElement(i, j, 0.0);
138 for(ConstColIterator it = b; it != e; ++it) {
139 soplex->changeElement(it->first, j, it->second);
144 void LpSoplex::_getColCoeffs(int i, ColIterator b) const {
145 const soplex::SVector& vec = soplex->colVector(i);
146 for (int k = 0; k < vec.size(); ++k) {
147 *b = std::make_pair(vec.index(k), vec.value(k));
152 void LpSoplex::_setCoeff(int i, int j, Value value) {
153 soplex->changeElement(i, j, value);
157 LpSoplex::Value LpSoplex::_getCoeff(int i, int j) const {
158 return soplex->rowVector(i)[j];
161 void LpSoplex::_setColLowerBound(int i, Value value) {
162 soplex->changeLower(i, value != -INF ? value : -soplex::infinity);
166 LpSoplex::Value LpSoplex::_getColLowerBound(int i) const {
167 double value = soplex->lower(i);
168 return value != -soplex::infinity ? value : -INF;
171 void LpSoplex::_setColUpperBound(int i, Value value) {
172 soplex->changeUpper(i, value != INF ? value : soplex::infinity);
176 LpSoplex::Value LpSoplex::_getColUpperBound(int i) const {
177 double value = soplex->upper(i);
178 return value != soplex::infinity ? value : INF;
181 void LpSoplex::_setRowBounds(int i, Value lb, Value ub) {
182 soplex->changeRange(i, lb != -INF ? lb : -soplex::infinity,
183 ub != INF ? ub : soplex::infinity);
186 void LpSoplex::_getRowBounds(int i, Value &lower, Value &upper) const {
187 lower = soplex->lhs(i);
188 if (lower == -soplex::infinity) lower = -INF;
189 upper = soplex->rhs(i);
190 if (upper == -soplex::infinity) upper = INF;
193 void LpSoplex::_setObjCoeff(int i, Value obj_coef) {
194 soplex->changeObj(i, obj_coef);
198 LpSoplex::Value LpSoplex::_getObjCoeff(int i) const {
199 return soplex->obj(i);
202 void LpSoplex::_clearObj() {
203 for (int i = 0; i < soplex->nCols(); ++i) {
204 soplex->changeObj(i, 0.0);
209 LpSoplex::SolveExitStatus LpSoplex::_solve() {
210 soplex::SPxSolver::Status status = soplex->solve();
212 soplex::Vector pv(primal_value.size(), &primal_value[0]);
213 soplex->getPrimal(pv);
215 soplex::Vector dv(dual_value.size(), &dual_value[0]);
219 case soplex::SPxSolver::OPTIMAL:
220 case soplex::SPxSolver::INFEASIBLE:
221 case soplex::SPxSolver::UNBOUNDED:
229 LpSoplex::Value LpSoplex::_getPrimal(int i) const {
230 return primal_value[i];
233 LpSoplex::Value LpSoplex::_getDual(int i) const {
234 return dual_value[i];
237 LpSoplex::Value LpSoplex::_getPrimalValue() const {
238 return soplex->objValue();
241 bool LpSoplex::_isBasicCol(int i) const {
242 return soplex->getBasisColStatus(i) == soplex::SPxSolver::BASIC;
245 LpSoplex::SolutionStatus LpSoplex::_getPrimalStatus() const {
246 if (!solved) return UNDEFINED;
247 switch (soplex->status()) {
248 case soplex::SPxSolver::OPTIMAL:
250 case soplex::SPxSolver::UNBOUNDED:
252 case soplex::SPxSolver::INFEASIBLE:
259 LpSoplex::SolutionStatus LpSoplex::_getDualStatus() const {
260 if (!solved) return UNDEFINED;
261 switch (soplex->status()) {
262 case soplex::SPxSolver::OPTIMAL:
264 case soplex::SPxSolver::UNBOUNDED:
271 LpSoplex::ProblemTypes LpSoplex::_getProblemType() const {
272 if (!solved) return UNKNOWN;
273 switch (soplex->status()) {
274 case soplex::SPxSolver::OPTIMAL:
275 return PRIMAL_DUAL_FEASIBLE;
276 case soplex::SPxSolver::UNBOUNDED:
277 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
283 void LpSoplex::_setMax() {
284 soplex->changeSense(soplex::SPxSolver::MAXIMIZE);
287 void LpSoplex::_setMin() {
288 soplex->changeSense(soplex::SPxSolver::MINIMIZE);
291 bool LpSoplex::_isMax() const {
292 return soplex->spxSense() == soplex::SPxSolver::MAXIMIZE;