COIN-OR::LEMON - Graph Library

source: lemon/lemon/lp_soplex.cc @ 481:7afc121e0689

Last change on this file since 481:7afc121e0689 was 481:7afc121e0689, checked in by Balazs Dezso <deba@…>, 15 years ago

Port LP and MIP solvers from SVN -r3509 (#44)

File size: 7.9 KB
Line 
1/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 *
3 * This file is a part of LEMON, a generic C++ optimization library.
4 *
5 * Copyright (C) 2003-2008
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 *
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.
12 *
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
15 * purpose.
16 *
17 */
18
19#include<iostream>
20#include<lemon/lp_soplex.h>
21
22#include <soplex/soplex.h>
23
24
25///\file
26///\brief Implementation of the LEMON-SOPLEX lp solver interface.
27namespace lemon {
28
29  LpSoplex::LpSoplex() : LpSolverBase() {
30    rows.setIdHandler(relocateIdHandler);
31    cols.setIdHandler(relocateIdHandler);
32    soplex = new soplex::SoPlex;
33    solved = false;
34  }
35
36  LpSoplex::~LpSoplex() {
37    delete soplex;
38  }
39
40  LpSoplex::LpSoplex(const LpSoplex& lp) : LpSolverBase() {
41    rows = lp.rows;
42    rows.setIdHandler(relocateIdHandler);
43
44    cols = lp.cols;
45    cols.setIdHandler(relocateIdHandler);
46
47    soplex = new soplex::SoPlex;
48    (*static_cast<soplex::SPxLP*>(soplex)) = *(lp.soplex);
49
50    colNames = lp.colNames;
51    invColNames = lp.invColNames;
52
53    primal_value = lp.primal_value;
54    dual_value = lp.dual_value;
55
56  }
57
58  LpSolverBase* LpSoplex::_newLp() {
59    LpSoplex* newlp = new LpSoplex();
60    return newlp;
61  }
62
63  LpSolverBase* LpSoplex::_copyLp() {
64    LpSoplex* newlp = new LpSoplex(*this);
65    return newlp;
66  }
67
68  int LpSoplex::_addCol() {
69    soplex::LPCol c;
70    c.setLower(-soplex::infinity);
71    c.setUpper(soplex::infinity);
72    soplex->addCol(c);
73
74    colNames.push_back(std::string());
75    primal_value.push_back(0.0);
76    solved = false;
77
78    return soplex->nCols() - 1;
79  }
80
81  int LpSoplex::_addRow() {
82    soplex::LPRow r;
83    r.setLhs(-soplex::infinity);
84    r.setRhs(soplex::infinity);
85    soplex->addRow(r);
86
87    dual_value.push_back(0.0);
88    solved = false;
89
90    return soplex->nRows() - 1;
91  }
92
93
94  void LpSoplex::_eraseCol(int i) {
95    soplex->removeCol(i);
96    invColNames.erase(colNames[i]);
97    colNames[i] = colNames.back();
98    invColNames[colNames.back()] = i;
99    colNames.pop_back();
100    primal_value[i] = primal_value.back();
101    primal_value.pop_back();
102    solved = false;
103  }
104
105  void LpSoplex::_eraseRow(int i) {
106    soplex->removeRow(i);
107    dual_value[i] = dual_value.back();
108    dual_value.pop_back();
109    solved = false;
110  }
111
112  void LpSoplex::_getColName(int c, std::string &name) const {
113    name = colNames[c];
114  }
115
116  void LpSoplex::_setColName(int c, const std::string &name) {
117    invColNames.erase(colNames[c]);
118    colNames[c] = name;
119    if (!name.empty()) {
120      invColNames.insert(std::make_pair(name, c));
121    }
122  }
123
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()) {
128      return it->second;
129    } else {
130      return -1;
131    }
132  }
133
134
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);
138    }
139    for(ConstRowIterator it = b; it != e; ++it) {
140      soplex->changeElement(i, it->first, it->second);
141    }
142    solved = false;
143  }
144
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));
149      ++b;
150    }
151  }
152
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);
156    }
157    for(ConstColIterator it = b; it != e; ++it) {
158      soplex->changeElement(it->first, j, it->second);
159    }
160    solved = false;
161  }
162
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));
167      ++b;
168    }
169  }
170
171  void LpSoplex::_setCoeff(int i, int j, Value value) {
172    soplex->changeElement(i, j, value);
173    solved = false;
174  }
175
176  LpSoplex::Value LpSoplex::_getCoeff(int i, int j) const {
177    return soplex->rowVector(i)[j];
178  }
179
180  void LpSoplex::_setColLowerBound(int i, Value value) {
181    soplex->changeLower(i, value != -INF ? value : -soplex::infinity);
182    solved = false;
183  }
184
185  LpSoplex::Value LpSoplex::_getColLowerBound(int i) const {
186    double value = soplex->lower(i);
187    return value != -soplex::infinity ? value : -INF;
188  }
189
190  void LpSoplex::_setColUpperBound(int i, Value value) {
191    soplex->changeUpper(i, value != INF ? value : soplex::infinity);
192    solved = false;
193  }
194
195  LpSoplex::Value LpSoplex::_getColUpperBound(int i) const {
196    double value = soplex->upper(i);
197    return value != soplex::infinity ? value : INF;
198  }
199
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);
203    solved = false;
204  }
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;
210  }
211
212  void LpSoplex::_setObjCoeff(int i, Value obj_coef) {
213    soplex->changeObj(i, obj_coef);
214    solved = false;
215  }
216
217  LpSoplex::Value LpSoplex::_getObjCoeff(int i) const {
218    return soplex->obj(i);
219  }
220
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() {
229    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
237    switch (status) {
238    case soplex::SPxSolver::OPTIMAL:
239    case soplex::SPxSolver::INFEASIBLE:
240    case soplex::SPxSolver::UNBOUNDED:
241      solved = true;
242      return SOLVED;
243    default:
244      return UNSOLVED;
245    }
246  }
247
248  LpSoplex::Value LpSoplex::_getPrimal(int i) const {
249    return primal_value[i];
250  }
251
252  LpSoplex::Value LpSoplex::_getDual(int i) const {
253    return dual_value[i];
254  }
255
256  LpSoplex::Value LpSoplex::_getPrimalValue() const {
257    return soplex->objValue();
258  }
259
260  bool LpSoplex::_isBasicCol(int i) const {
261    return soplex->getBasisColStatus(i) == soplex::SPxSolver::BASIC;
262  }
263
264  LpSoplex::SolutionStatus LpSoplex::_getPrimalStatus() const {
265    if (!solved) return UNDEFINED;
266    switch (soplex->status()) {
267    case soplex::SPxSolver::OPTIMAL:
268      return OPTIMAL;
269    case soplex::SPxSolver::UNBOUNDED:
270      return INFINITE;
271    case soplex::SPxSolver::INFEASIBLE:
272      return INFEASIBLE;
273    default:
274      return UNDEFINED;
275    }
276  }
277
278  LpSoplex::SolutionStatus LpSoplex::_getDualStatus() const {
279    if (!solved) return UNDEFINED;
280    switch (soplex->status()) {
281    case soplex::SPxSolver::OPTIMAL:
282      return OPTIMAL;
283    case soplex::SPxSolver::UNBOUNDED:
284      return INFEASIBLE;
285    default:
286      return UNDEFINED;
287    }
288  }
289
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;
297    default:
298      return UNKNOWN;
299    }
300  }
301
302  void LpSoplex::_setMax() {
303    soplex->changeSense(soplex::SPxSolver::MAXIMIZE);
304    solved = false;
305  }
306  void LpSoplex::_setMin() {
307    soplex->changeSense(soplex::SPxSolver::MINIMIZE);
308    solved = false;
309  }
310  bool LpSoplex::_isMax() const {
311    return soplex->spxSense() == soplex::SPxSolver::MAXIMIZE;
312  }
313
314
315} //namespace lemon
316
Note: See TracBrowser for help on using the repository browser.