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, LpRowIterator b, LpRowIterator e) {
103 for (int j = 0; j < soplex->nCols(); ++j) {
104 soplex->changeElement(i, j, 0.0);
106 for(LpRowIterator it = b; it != e; ++it) {
107 soplex->changeElement(i, it->first, it->second);
112 void LpSoplex::_setColCoeffs(int j, LpColIterator b, LpColIterator e) {
113 for (int i = 0; i < soplex->nRows(); ++i) {
114 soplex->changeElement(i, j, 0.0);
116 for(LpColIterator it = b; it != e; ++it) {
117 soplex->changeElement(it->first, j, it->second);
122 void LpSoplex::_setCoeff(int i, int j, Value value) {
123 soplex->changeElement(i, j, value);
127 LpSoplex::Value LpSoplex::_getCoeff(int i, int j) {
128 return soplex->rowVector(i)[j];
131 void LpSoplex::_setColLowerBound(int i, Value value) {
132 soplex->changeLower(i, value != -INF ? value : -soplex::infinity);
136 LpSoplex::Value LpSoplex::_getColLowerBound(int i) {
137 double value = soplex->lower(i);
138 return value != -soplex::infinity ? value : -INF;
141 void LpSoplex::_setColUpperBound(int i, Value value) {
142 soplex->changeUpper(i, value != INF ? value : soplex::infinity);
146 LpSoplex::Value LpSoplex::_getColUpperBound(int i) {
147 double value = soplex->upper(i);
148 return value != soplex::infinity ? value : INF;
151 void LpSoplex::_setRowBounds(int i, Value lb, Value ub) {
152 soplex->changeRange(i, lb != -INF ? lb : -soplex::infinity,
153 ub != INF ? ub : soplex::infinity);
156 void LpSoplex::_getRowBounds(int i, Value &lower, Value &upper) {
157 lower = soplex->lhs(i);
158 if (lower == -soplex::infinity) lower = -INF;
159 upper = soplex->rhs(i);
160 if (upper == -soplex::infinity) upper = INF;
163 void LpSoplex::_setObjCoeff(int i, Value obj_coef) {
164 soplex->changeObj(i, obj_coef);
168 LpSoplex::Value LpSoplex::_getObjCoeff(int i) {
169 return soplex->obj(i);
172 void LpSoplex::_clearObj() {
173 for (int i = 0; i < soplex->nCols(); ++i) {
174 soplex->changeObj(i, 0.0);
179 LpSoplex::SolveExitStatus LpSoplex::_solve() {
180 soplex::SPxSolver::Status status = soplex->solve();
182 soplex::Vector pv(primal_value.size(), &primal_value[0]);
183 soplex->getPrimal(pv);
185 soplex::Vector dv(dual_value.size(), &dual_value[0]);
189 case soplex::SPxSolver::OPTIMAL:
190 case soplex::SPxSolver::INFEASIBLE:
191 case soplex::SPxSolver::UNBOUNDED:
199 LpSoplex::Value LpSoplex::_getPrimal(int i) {
200 return primal_value[i];
203 LpSoplex::Value LpSoplex::_getDual(int i) {
204 return dual_value[i];
207 LpSoplex::Value LpSoplex::_getPrimalValue() {
208 return soplex->objValue();
211 bool LpSoplex::_isBasicCol(int i) {
212 return soplex->getBasisColStatus(i) == soplex::SPxSolver::BASIC;
215 LpSoplex::SolutionStatus LpSoplex::_getPrimalStatus() {
216 if (!solved) return UNDEFINED;
217 switch (soplex->status()) {
218 case soplex::SPxSolver::OPTIMAL:
220 case soplex::SPxSolver::UNBOUNDED:
222 case soplex::SPxSolver::INFEASIBLE:
229 LpSoplex::SolutionStatus LpSoplex::_getDualStatus() {
230 if (!solved) return UNDEFINED;
231 switch (soplex->status()) {
232 case soplex::SPxSolver::OPTIMAL:
234 case soplex::SPxSolver::UNBOUNDED:
241 LpSoplex::ProblemTypes LpSoplex::_getProblemType() {
242 if (!solved) return UNKNOWN;
243 switch (soplex->status()) {
244 case soplex::SPxSolver::OPTIMAL:
245 return PRIMAL_DUAL_FEASIBLE;
246 case soplex::SPxSolver::UNBOUNDED:
247 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
253 void LpSoplex::_setMax() {
254 soplex->changeSense(soplex::SPxSolver::MAXIMIZE);
257 void LpSoplex::_setMin() {
258 soplex->changeSense(soplex::SPxSolver::MINIMIZE);
261 bool LpSoplex::_isMax() {
262 return soplex->spxSense() == soplex::SPxSolver::MAXIMIZE;