1.1 --- a/lemon/Makefile.am Mon Jan 12 12:25:55 2009 +0000
1.2 +++ b/lemon/Makefile.am Mon Jan 12 12:26:01 2009 +0000
1.3 @@ -28,19 +28,19 @@
1.4 $(CLP_LIBS)
1.5
1.6 if HAVE_GLPK
1.7 -lemon_libemon_la_SOURCES += lemon/lp_glpk.cc
1.8 +lemon_libemon_la_SOURCES += lemon/glpk.cc
1.9 endif
1.10
1.11 if HAVE_CPLEX
1.12 -lemon_libemon_la_SOURCES += lemon/lp_cplex.cc
1.13 +lemon_libemon_la_SOURCES += lemon/cplex.cc
1.14 endif
1.15
1.16 if HAVE_SOPLEX
1.17 -lemon_libemon_la_SOURCES += lemon/lp_soplex.cc
1.18 +lemon_libemon_la_SOURCES += lemon/soplex.cc
1.19 endif
1.20
1.21 if HAVE_CLP
1.22 -lemon_libemon_la_SOURCES += lemon/lp_clp.cc
1.23 +lemon_libemon_la_SOURCES += lemon/clp.cc
1.24 endif
1.25
1.26 lemon_HEADERS += \
1.27 @@ -50,10 +50,12 @@
1.28 lemon/bfs.h \
1.29 lemon/bin_heap.h \
1.30 lemon/circulation.h \
1.31 + lemon/clp.h \
1.32 lemon/color.h \
1.33 lemon/concept_check.h \
1.34 lemon/counter.h \
1.35 lemon/core.h \
1.36 + lemon/cplex.h \
1.37 lemon/dfs.h \
1.38 lemon/dijkstra.h \
1.39 lemon/dim2.h \
1.40 @@ -61,6 +63,7 @@
1.41 lemon/elevator.h \
1.42 lemon/error.h \
1.43 lemon/full_graph.h \
1.44 + lemon/glpk.h \
1.45 lemon/graph_to_eps.h \
1.46 lemon/grid_graph.h \
1.47 lemon/hypercube_graph.h \
1.48 @@ -71,11 +74,7 @@
1.49 lemon/list_graph.h \
1.50 lemon/lp.h \
1.51 lemon/lp_base.h \
1.52 - lemon/lp_clp.h \
1.53 - lemon/lp_cplex.h \
1.54 - lemon/lp_glpk.h \
1.55 lemon/lp_skeleton.h \
1.56 - lemon/lp_soplex.h \
1.57 lemon/list_graph.h \
1.58 lemon/maps.h \
1.59 lemon/math.h \
1.60 @@ -86,6 +85,7 @@
1.61 lemon/radix_sort.h \
1.62 lemon/random.h \
1.63 lemon/smart_graph.h \
1.64 + lemon/soplex.h \
1.65 lemon/suurballe.h \
1.66 lemon/time_measure.h \
1.67 lemon/tolerance.h \
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/lemon/clp.cc Mon Jan 12 12:26:01 2009 +0000
2.3 @@ -0,0 +1,437 @@
2.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
2.5 + *
2.6 + * This file is a part of LEMON, a generic C++ optimization library.
2.7 + *
2.8 + * Copyright (C) 2003-2008
2.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
2.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
2.11 + *
2.12 + * Permission to use, modify and distribute this software is granted
2.13 + * provided that this copyright notice appears in all copies. For
2.14 + * precise terms see the accompanying LICENSE file.
2.15 + *
2.16 + * This software is provided "AS IS" with no warranty of any kind,
2.17 + * express or implied, and with no claim as to its suitability for any
2.18 + * purpose.
2.19 + *
2.20 + */
2.21 +
2.22 +#include <lemon/clp.h>
2.23 +#include <coin/ClpSimplex.hpp>
2.24 +
2.25 +namespace lemon {
2.26 +
2.27 + LpClp::LpClp() {
2.28 + _prob = new ClpSimplex();
2.29 + _init_temporals();
2.30 + messageLevel(MESSAGE_NO_OUTPUT);
2.31 + }
2.32 +
2.33 + LpClp::LpClp(const LpClp& other) {
2.34 + _prob = new ClpSimplex(*other._prob);
2.35 + rows = other.rows;
2.36 + cols = other.cols;
2.37 + _init_temporals();
2.38 + messageLevel(MESSAGE_NO_OUTPUT);
2.39 + }
2.40 +
2.41 + LpClp::~LpClp() {
2.42 + delete _prob;
2.43 + _clear_temporals();
2.44 + }
2.45 +
2.46 + void LpClp::_init_temporals() {
2.47 + _primal_ray = 0;
2.48 + _dual_ray = 0;
2.49 + }
2.50 +
2.51 + void LpClp::_clear_temporals() {
2.52 + if (_primal_ray) {
2.53 + delete[] _primal_ray;
2.54 + _primal_ray = 0;
2.55 + }
2.56 + if (_dual_ray) {
2.57 + delete[] _dual_ray;
2.58 + _dual_ray = 0;
2.59 + }
2.60 + }
2.61 +
2.62 + LpClp* LpClp::_newSolver() const {
2.63 + LpClp* newlp = new LpClp;
2.64 + return newlp;
2.65 + }
2.66 +
2.67 + LpClp* LpClp::_cloneSolver() const {
2.68 + LpClp* copylp = new LpClp(*this);
2.69 + return copylp;
2.70 + }
2.71 +
2.72 + const char* LpClp::_solverName() const { return "LpClp"; }
2.73 +
2.74 + int LpClp::_addCol() {
2.75 + _prob->addColumn(0, 0, 0, -COIN_DBL_MAX, COIN_DBL_MAX, 0.0);
2.76 + return _prob->numberColumns() - 1;
2.77 + }
2.78 +
2.79 + int LpClp::_addRow() {
2.80 + _prob->addRow(0, 0, 0, -COIN_DBL_MAX, COIN_DBL_MAX);
2.81 + return _prob->numberRows() - 1;
2.82 + }
2.83 +
2.84 +
2.85 + void LpClp::_eraseCol(int c) {
2.86 + _col_names_ref.erase(_prob->getColumnName(c));
2.87 + _prob->deleteColumns(1, &c);
2.88 + }
2.89 +
2.90 + void LpClp::_eraseRow(int r) {
2.91 + _row_names_ref.erase(_prob->getRowName(r));
2.92 + _prob->deleteRows(1, &r);
2.93 + }
2.94 +
2.95 + void LpClp::_eraseColId(int i) {
2.96 + cols.eraseIndex(i);
2.97 + cols.shiftIndices(i);
2.98 + }
2.99 +
2.100 + void LpClp::_eraseRowId(int i) {
2.101 + rows.eraseIndex(i);
2.102 + rows.shiftIndices(i);
2.103 + }
2.104 +
2.105 + void LpClp::_getColName(int c, std::string& name) const {
2.106 + name = _prob->getColumnName(c);
2.107 + }
2.108 +
2.109 + void LpClp::_setColName(int c, const std::string& name) {
2.110 + _prob->setColumnName(c, const_cast<std::string&>(name));
2.111 + _col_names_ref[name] = c;
2.112 + }
2.113 +
2.114 + int LpClp::_colByName(const std::string& name) const {
2.115 + std::map<std::string, int>::const_iterator it = _col_names_ref.find(name);
2.116 + return it != _col_names_ref.end() ? it->second : -1;
2.117 + }
2.118 +
2.119 + void LpClp::_getRowName(int r, std::string& name) const {
2.120 + name = _prob->getRowName(r);
2.121 + }
2.122 +
2.123 + void LpClp::_setRowName(int r, const std::string& name) {
2.124 + _prob->setRowName(r, const_cast<std::string&>(name));
2.125 + _row_names_ref[name] = r;
2.126 + }
2.127 +
2.128 + int LpClp::_rowByName(const std::string& name) const {
2.129 + std::map<std::string, int>::const_iterator it = _row_names_ref.find(name);
2.130 + return it != _row_names_ref.end() ? it->second : -1;
2.131 + }
2.132 +
2.133 +
2.134 + void LpClp::_setRowCoeffs(int ix, ExprIterator b, ExprIterator e) {
2.135 + std::map<int, Value> coeffs;
2.136 +
2.137 + int n = _prob->clpMatrix()->getNumCols();
2.138 +
2.139 + const int* indices = _prob->clpMatrix()->getIndices();
2.140 + const double* elements = _prob->clpMatrix()->getElements();
2.141 +
2.142 + for (int i = 0; i < n; ++i) {
2.143 + CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[i];
2.144 + CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[i];
2.145 +
2.146 + const int* it = std::lower_bound(indices + begin, indices + end, ix);
2.147 + if (it != indices + end && *it == ix && elements[it - indices] != 0.0) {
2.148 + coeffs[i] = 0.0;
2.149 + }
2.150 + }
2.151 +
2.152 + for (ExprIterator it = b; it != e; ++it) {
2.153 + coeffs[it->first] = it->second;
2.154 + }
2.155 +
2.156 + for (std::map<int, Value>::iterator it = coeffs.begin();
2.157 + it != coeffs.end(); ++it) {
2.158 + _prob->modifyCoefficient(ix, it->first, it->second);
2.159 + }
2.160 + }
2.161 +
2.162 + void LpClp::_getRowCoeffs(int ix, InsertIterator b) const {
2.163 + int n = _prob->clpMatrix()->getNumCols();
2.164 +
2.165 + const int* indices = _prob->clpMatrix()->getIndices();
2.166 + const double* elements = _prob->clpMatrix()->getElements();
2.167 +
2.168 + for (int i = 0; i < n; ++i) {
2.169 + CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[i];
2.170 + CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[i];
2.171 +
2.172 + const int* it = std::lower_bound(indices + begin, indices + end, ix);
2.173 + if (it != indices + end && *it == ix) {
2.174 + *b = std::make_pair(i, elements[it - indices]);
2.175 + }
2.176 + }
2.177 + }
2.178 +
2.179 + void LpClp::_setColCoeffs(int ix, ExprIterator b, ExprIterator e) {
2.180 + std::map<int, Value> coeffs;
2.181 +
2.182 + CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[ix];
2.183 + CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[ix];
2.184 +
2.185 + const int* indices = _prob->clpMatrix()->getIndices();
2.186 + const double* elements = _prob->clpMatrix()->getElements();
2.187 +
2.188 + for (CoinBigIndex i = begin; i != end; ++i) {
2.189 + if (elements[i] != 0.0) {
2.190 + coeffs[indices[i]] = 0.0;
2.191 + }
2.192 + }
2.193 + for (ExprIterator it = b; it != e; ++it) {
2.194 + coeffs[it->first] = it->second;
2.195 + }
2.196 + for (std::map<int, Value>::iterator it = coeffs.begin();
2.197 + it != coeffs.end(); ++it) {
2.198 + _prob->modifyCoefficient(it->first, ix, it->second);
2.199 + }
2.200 + }
2.201 +
2.202 + void LpClp::_getColCoeffs(int ix, InsertIterator b) const {
2.203 + CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[ix];
2.204 + CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[ix];
2.205 +
2.206 + const int* indices = _prob->clpMatrix()->getIndices();
2.207 + const double* elements = _prob->clpMatrix()->getElements();
2.208 +
2.209 + for (CoinBigIndex i = begin; i != end; ++i) {
2.210 + *b = std::make_pair(indices[i], elements[i]);
2.211 + ++b;
2.212 + }
2.213 + }
2.214 +
2.215 + void LpClp::_setCoeff(int ix, int jx, Value value) {
2.216 + _prob->modifyCoefficient(ix, jx, value);
2.217 + }
2.218 +
2.219 + LpClp::Value LpClp::_getCoeff(int ix, int jx) const {
2.220 + CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[ix];
2.221 + CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[ix];
2.222 +
2.223 + const int* indices = _prob->clpMatrix()->getIndices();
2.224 + const double* elements = _prob->clpMatrix()->getElements();
2.225 +
2.226 + const int* it = std::lower_bound(indices + begin, indices + end, jx);
2.227 + if (it != indices + end && *it == jx) {
2.228 + return elements[it - indices];
2.229 + } else {
2.230 + return 0.0;
2.231 + }
2.232 + }
2.233 +
2.234 + void LpClp::_setColLowerBound(int i, Value lo) {
2.235 + _prob->setColumnLower(i, lo == - INF ? - COIN_DBL_MAX : lo);
2.236 + }
2.237 +
2.238 + LpClp::Value LpClp::_getColLowerBound(int i) const {
2.239 + double val = _prob->getColLower()[i];
2.240 + return val == - COIN_DBL_MAX ? - INF : val;
2.241 + }
2.242 +
2.243 + void LpClp::_setColUpperBound(int i, Value up) {
2.244 + _prob->setColumnUpper(i, up == INF ? COIN_DBL_MAX : up);
2.245 + }
2.246 +
2.247 + LpClp::Value LpClp::_getColUpperBound(int i) const {
2.248 + double val = _prob->getColUpper()[i];
2.249 + return val == COIN_DBL_MAX ? INF : val;
2.250 + }
2.251 +
2.252 + void LpClp::_setRowLowerBound(int i, Value lo) {
2.253 + _prob->setRowLower(i, lo == - INF ? - COIN_DBL_MAX : lo);
2.254 + }
2.255 +
2.256 + LpClp::Value LpClp::_getRowLowerBound(int i) const {
2.257 + double val = _prob->getRowLower()[i];
2.258 + return val == - COIN_DBL_MAX ? - INF : val;
2.259 + }
2.260 +
2.261 + void LpClp::_setRowUpperBound(int i, Value up) {
2.262 + _prob->setRowUpper(i, up == INF ? COIN_DBL_MAX : up);
2.263 + }
2.264 +
2.265 + LpClp::Value LpClp::_getRowUpperBound(int i) const {
2.266 + double val = _prob->getRowUpper()[i];
2.267 + return val == COIN_DBL_MAX ? INF : val;
2.268 + }
2.269 +
2.270 + void LpClp::_setObjCoeffs(ExprIterator b, ExprIterator e) {
2.271 + int num = _prob->clpMatrix()->getNumCols();
2.272 + for (int i = 0; i < num; ++i) {
2.273 + _prob->setObjectiveCoefficient(i, 0.0);
2.274 + }
2.275 + for (ExprIterator it = b; it != e; ++it) {
2.276 + _prob->setObjectiveCoefficient(it->first, it->second);
2.277 + }
2.278 + }
2.279 +
2.280 + void LpClp::_getObjCoeffs(InsertIterator b) const {
2.281 + int num = _prob->clpMatrix()->getNumCols();
2.282 + for (int i = 0; i < num; ++i) {
2.283 + Value coef = _prob->getObjCoefficients()[i];
2.284 + if (coef != 0.0) {
2.285 + *b = std::make_pair(i, coef);
2.286 + ++b;
2.287 + }
2.288 + }
2.289 + }
2.290 +
2.291 + void LpClp::_setObjCoeff(int i, Value obj_coef) {
2.292 + _prob->setObjectiveCoefficient(i, obj_coef);
2.293 + }
2.294 +
2.295 + LpClp::Value LpClp::_getObjCoeff(int i) const {
2.296 + return _prob->getObjCoefficients()[i];
2.297 + }
2.298 +
2.299 + LpClp::SolveExitStatus LpClp::_solve() {
2.300 + return _prob->primal() >= 0 ? SOLVED : UNSOLVED;
2.301 + }
2.302 +
2.303 + LpClp::SolveExitStatus LpClp::solvePrimal() {
2.304 + return _prob->primal() >= 0 ? SOLVED : UNSOLVED;
2.305 + }
2.306 +
2.307 + LpClp::SolveExitStatus LpClp::solveDual() {
2.308 + return _prob->dual() >= 0 ? SOLVED : UNSOLVED;
2.309 + }
2.310 +
2.311 + LpClp::SolveExitStatus LpClp::solveBarrier() {
2.312 + return _prob->barrier() >= 0 ? SOLVED : UNSOLVED;
2.313 + }
2.314 +
2.315 + LpClp::Value LpClp::_getPrimal(int i) const {
2.316 + return _prob->primalColumnSolution()[i];
2.317 + }
2.318 + LpClp::Value LpClp::_getPrimalValue() const {
2.319 + return _prob->objectiveValue();
2.320 + }
2.321 +
2.322 + LpClp::Value LpClp::_getDual(int i) const {
2.323 + return _prob->dualRowSolution()[i];
2.324 + }
2.325 +
2.326 + LpClp::Value LpClp::_getPrimalRay(int i) const {
2.327 + if (!_primal_ray) {
2.328 + _primal_ray = _prob->unboundedRay();
2.329 + LEMON_ASSERT(_primal_ray != 0, "Primal ray is not provided");
2.330 + }
2.331 + return _primal_ray[i];
2.332 + }
2.333 +
2.334 + LpClp::Value LpClp::_getDualRay(int i) const {
2.335 + if (!_dual_ray) {
2.336 + _dual_ray = _prob->infeasibilityRay();
2.337 + LEMON_ASSERT(_dual_ray != 0, "Dual ray is not provided");
2.338 + }
2.339 + return _dual_ray[i];
2.340 + }
2.341 +
2.342 + LpClp::VarStatus LpClp::_getColStatus(int i) const {
2.343 + switch (_prob->getColumnStatus(i)) {
2.344 + case ClpSimplex::basic:
2.345 + return BASIC;
2.346 + case ClpSimplex::isFree:
2.347 + return FREE;
2.348 + case ClpSimplex::atUpperBound:
2.349 + return UPPER;
2.350 + case ClpSimplex::atLowerBound:
2.351 + return LOWER;
2.352 + case ClpSimplex::isFixed:
2.353 + return FIXED;
2.354 + case ClpSimplex::superBasic:
2.355 + return FREE;
2.356 + default:
2.357 + LEMON_ASSERT(false, "Wrong column status");
2.358 + return VarStatus();
2.359 + }
2.360 + }
2.361 +
2.362 + LpClp::VarStatus LpClp::_getRowStatus(int i) const {
2.363 + switch (_prob->getColumnStatus(i)) {
2.364 + case ClpSimplex::basic:
2.365 + return BASIC;
2.366 + case ClpSimplex::isFree:
2.367 + return FREE;
2.368 + case ClpSimplex::atUpperBound:
2.369 + return UPPER;
2.370 + case ClpSimplex::atLowerBound:
2.371 + return LOWER;
2.372 + case ClpSimplex::isFixed:
2.373 + return FIXED;
2.374 + case ClpSimplex::superBasic:
2.375 + return FREE;
2.376 + default:
2.377 + LEMON_ASSERT(false, "Wrong row status");
2.378 + return VarStatus();
2.379 + }
2.380 + }
2.381 +
2.382 +
2.383 + LpClp::ProblemType LpClp::_getPrimalType() const {
2.384 + if (_prob->isProvenOptimal()) {
2.385 + return OPTIMAL;
2.386 + } else if (_prob->isProvenPrimalInfeasible()) {
2.387 + return INFEASIBLE;
2.388 + } else if (_prob->isProvenDualInfeasible()) {
2.389 + return UNBOUNDED;
2.390 + } else {
2.391 + return UNDEFINED;
2.392 + }
2.393 + }
2.394 +
2.395 + LpClp::ProblemType LpClp::_getDualType() const {
2.396 + if (_prob->isProvenOptimal()) {
2.397 + return OPTIMAL;
2.398 + } else if (_prob->isProvenDualInfeasible()) {
2.399 + return INFEASIBLE;
2.400 + } else if (_prob->isProvenPrimalInfeasible()) {
2.401 + return INFEASIBLE;
2.402 + } else {
2.403 + return UNDEFINED;
2.404 + }
2.405 + }
2.406 +
2.407 + void LpClp::_setSense(LpClp::Sense sense) {
2.408 + switch (sense) {
2.409 + case MIN:
2.410 + _prob->setOptimizationDirection(1);
2.411 + break;
2.412 + case MAX:
2.413 + _prob->setOptimizationDirection(-1);
2.414 + break;
2.415 + }
2.416 + }
2.417 +
2.418 + LpClp::Sense LpClp::_getSense() const {
2.419 + double dir = _prob->optimizationDirection();
2.420 + if (dir > 0.0) {
2.421 + return MIN;
2.422 + } else {
2.423 + return MAX;
2.424 + }
2.425 + }
2.426 +
2.427 + void LpClp::_clear() {
2.428 + delete _prob;
2.429 + _prob = new ClpSimplex();
2.430 + rows.clear();
2.431 + cols.clear();
2.432 + _col_names_ref.clear();
2.433 + _clear_temporals();
2.434 + }
2.435 +
2.436 + void LpClp::messageLevel(MessageLevel m) {
2.437 + _prob->setLogLevel(static_cast<int>(m));
2.438 + }
2.439 +
2.440 +} //END OF NAMESPACE LEMON
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/lemon/clp.h Mon Jan 12 12:26:01 2009 +0000
3.3 @@ -0,0 +1,179 @@
3.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
3.5 + *
3.6 + * This file is a part of LEMON, a generic C++ optimization library.
3.7 + *
3.8 + * Copyright (C) 2003-2008
3.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
3.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
3.11 + *
3.12 + * Permission to use, modify and distribute this software is granted
3.13 + * provided that this copyright notice appears in all copies. For
3.14 + * precise terms see the accompanying LICENSE file.
3.15 + *
3.16 + * This software is provided "AS IS" with no warranty of any kind,
3.17 + * express or implied, and with no claim as to its suitability for any
3.18 + * purpose.
3.19 + *
3.20 + */
3.21 +
3.22 +#ifndef LEMON_CLP_H
3.23 +#define LEMON_CLP_H
3.24 +
3.25 +///\file
3.26 +///\brief Header of the LEMON-CLP lp solver interface.
3.27 +
3.28 +#include <vector>
3.29 +#include <string>
3.30 +
3.31 +#include <lemon/lp_base.h>
3.32 +
3.33 +class ClpSimplex;
3.34 +
3.35 +namespace lemon {
3.36 +
3.37 + /// \ingroup lp_group
3.38 + ///
3.39 + /// \brief Interface for the CLP solver
3.40 + ///
3.41 + /// This class implements an interface for the Clp LP solver. The
3.42 + /// Clp library is an object oriented lp solver library developed at
3.43 + /// the IBM. The CLP is part of the COIN-OR package and it can be
3.44 + /// used with Common Public License.
3.45 + class LpClp : public LpSolver {
3.46 + protected:
3.47 +
3.48 + ClpSimplex* _prob;
3.49 +
3.50 + std::map<std::string, int> _col_names_ref;
3.51 + std::map<std::string, int> _row_names_ref;
3.52 +
3.53 + public:
3.54 +
3.55 + /// \e
3.56 + LpClp();
3.57 + /// \e
3.58 + LpClp(const LpClp&);
3.59 + /// \e
3.60 + ~LpClp();
3.61 +
3.62 + protected:
3.63 +
3.64 + mutable double* _primal_ray;
3.65 + mutable double* _dual_ray;
3.66 +
3.67 + void _init_temporals();
3.68 + void _clear_temporals();
3.69 +
3.70 + protected:
3.71 +
3.72 + virtual LpClp* _newSolver() const;
3.73 + virtual LpClp* _cloneSolver() const;
3.74 +
3.75 + virtual const char* _solverName() const;
3.76 +
3.77 + virtual int _addCol();
3.78 + virtual int _addRow();
3.79 +
3.80 + virtual void _eraseCol(int i);
3.81 + virtual void _eraseRow(int i);
3.82 +
3.83 + virtual void _eraseColId(int i);
3.84 + virtual void _eraseRowId(int i);
3.85 +
3.86 + virtual void _getColName(int col, std::string& name) const;
3.87 + virtual void _setColName(int col, const std::string& name);
3.88 + virtual int _colByName(const std::string& name) const;
3.89 +
3.90 + virtual void _getRowName(int row, std::string& name) const;
3.91 + virtual void _setRowName(int row, const std::string& name);
3.92 + virtual int _rowByName(const std::string& name) const;
3.93 +
3.94 + virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
3.95 + virtual void _getRowCoeffs(int i, InsertIterator b) const;
3.96 +
3.97 + virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
3.98 + virtual void _getColCoeffs(int i, InsertIterator b) const;
3.99 +
3.100 + virtual void _setCoeff(int row, int col, Value value);
3.101 + virtual Value _getCoeff(int row, int col) const;
3.102 +
3.103 + virtual void _setColLowerBound(int i, Value value);
3.104 + virtual Value _getColLowerBound(int i) const;
3.105 + virtual void _setColUpperBound(int i, Value value);
3.106 + virtual Value _getColUpperBound(int i) const;
3.107 +
3.108 + virtual void _setRowLowerBound(int i, Value value);
3.109 + virtual Value _getRowLowerBound(int i) const;
3.110 + virtual void _setRowUpperBound(int i, Value value);
3.111 + virtual Value _getRowUpperBound(int i) const;
3.112 +
3.113 + virtual void _setObjCoeffs(ExprIterator, ExprIterator);
3.114 + virtual void _getObjCoeffs(InsertIterator) const;
3.115 +
3.116 + virtual void _setObjCoeff(int i, Value obj_coef);
3.117 + virtual Value _getObjCoeff(int i) const;
3.118 +
3.119 + virtual void _setSense(Sense sense);
3.120 + virtual Sense _getSense() const;
3.121 +
3.122 + virtual SolveExitStatus _solve();
3.123 +
3.124 + virtual Value _getPrimal(int i) const;
3.125 + virtual Value _getDual(int i) const;
3.126 +
3.127 + virtual Value _getPrimalValue() const;
3.128 +
3.129 + virtual Value _getPrimalRay(int i) const;
3.130 + virtual Value _getDualRay(int i) const;
3.131 +
3.132 + virtual VarStatus _getColStatus(int i) const;
3.133 + virtual VarStatus _getRowStatus(int i) const;
3.134 +
3.135 + virtual ProblemType _getPrimalType() const;
3.136 + virtual ProblemType _getDualType() const;
3.137 +
3.138 + virtual void _clear();
3.139 +
3.140 + public:
3.141 +
3.142 + ///Solves LP with primal simplex method.
3.143 + SolveExitStatus solvePrimal();
3.144 +
3.145 + ///Solves LP with dual simplex method.
3.146 + SolveExitStatus solveDual();
3.147 +
3.148 + ///Solves LP with barrier method.
3.149 + SolveExitStatus solveBarrier();
3.150 +
3.151 + ///Returns the constraint identifier understood by CLP.
3.152 + int clpRow(Row r) const { return rows(id(r)); }
3.153 +
3.154 + ///Returns the variable identifier understood by CLP.
3.155 + int clpCol(Col c) const { return cols(id(c)); }
3.156 +
3.157 + ///Enum for \c messageLevel() parameter
3.158 + enum MessageLevel {
3.159 + /// no output (default value)
3.160 + MESSAGE_NO_OUTPUT = 0,
3.161 + /// print final solution
3.162 + MESSAGE_FINAL_SOLUTION = 1,
3.163 + /// print factorization
3.164 + MESSAGE_FACTORIZATION = 2,
3.165 + /// normal output
3.166 + MESSAGE_NORMAL_OUTPUT = 3,
3.167 + /// verbose output
3.168 + MESSAGE_VERBOSE_OUTPUT = 4
3.169 + };
3.170 + ///Set the verbosity of the messages
3.171 +
3.172 + ///Set the verbosity of the messages
3.173 + ///
3.174 + ///\param m is the level of the messages output by the solver routines.
3.175 + void messageLevel(MessageLevel m);
3.176 +
3.177 + };
3.178 +
3.179 +} //END OF NAMESPACE LEMON
3.180 +
3.181 +#endif //LEMON_CLP_H
3.182 +
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/lemon/cplex.cc Mon Jan 12 12:26:01 2009 +0000
4.3 @@ -0,0 +1,925 @@
4.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
4.5 + *
4.6 + * This file is a part of LEMON, a generic C++ optimization library.
4.7 + *
4.8 + * Copyright (C) 2003-2008
4.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
4.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
4.11 + *
4.12 + * Permission to use, modify and distribute this software is granted
4.13 + * provided that this copyright notice appears in all copies. For
4.14 + * precise terms see the accompanying LICENSE file.
4.15 + *
4.16 + * This software is provided "AS IS" with no warranty of any kind,
4.17 + * express or implied, and with no claim as to its suitability for any
4.18 + * purpose.
4.19 + *
4.20 + */
4.21 +
4.22 +#include <iostream>
4.23 +#include <vector>
4.24 +#include <cstring>
4.25 +
4.26 +#include <lemon/cplex.h>
4.27 +
4.28 +extern "C" {
4.29 +#include <ilcplex/cplex.h>
4.30 +}
4.31 +
4.32 +
4.33 +///\file
4.34 +///\brief Implementation of the LEMON-CPLEX lp solver interface.
4.35 +namespace lemon {
4.36 +
4.37 + CplexEnv::LicenseError::LicenseError(int status) {
4.38 + if (!CPXgeterrorstring(0, status, _message)) {
4.39 + std::strcpy(_message, "Cplex unknown error");
4.40 + }
4.41 + }
4.42 +
4.43 + CplexEnv::CplexEnv() {
4.44 + int status;
4.45 + _cnt = new int;
4.46 + _env = CPXopenCPLEX(&status);
4.47 + if (_env == 0) {
4.48 + delete _cnt;
4.49 + _cnt = 0;
4.50 + throw LicenseError(status);
4.51 + }
4.52 + }
4.53 +
4.54 + CplexEnv::CplexEnv(const CplexEnv& other) {
4.55 + _env = other._env;
4.56 + _cnt = other._cnt;
4.57 + ++(*_cnt);
4.58 + }
4.59 +
4.60 + CplexEnv& CplexEnv::operator=(const CplexEnv& other) {
4.61 + _env = other._env;
4.62 + _cnt = other._cnt;
4.63 + ++(*_cnt);
4.64 + return *this;
4.65 + }
4.66 +
4.67 + CplexEnv::~CplexEnv() {
4.68 + --(*_cnt);
4.69 + if (*_cnt == 0) {
4.70 + delete _cnt;
4.71 + CPXcloseCPLEX(&_env);
4.72 + }
4.73 + }
4.74 +
4.75 + CplexBase::CplexBase() : LpBase() {
4.76 + int status;
4.77 + _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
4.78 + }
4.79 +
4.80 + CplexBase::CplexBase(const CplexEnv& env)
4.81 + : LpBase(), _env(env) {
4.82 + int status;
4.83 + _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
4.84 + }
4.85 +
4.86 + CplexBase::CplexBase(const CplexBase& cplex)
4.87 + : LpBase() {
4.88 + int status;
4.89 + _prob = CPXcloneprob(cplexEnv(), cplex._prob, &status);
4.90 + rows = cplex.rows;
4.91 + cols = cplex.cols;
4.92 + }
4.93 +
4.94 + CplexBase::~CplexBase() {
4.95 + CPXfreeprob(cplexEnv(),&_prob);
4.96 + }
4.97 +
4.98 + int CplexBase::_addCol() {
4.99 + int i = CPXgetnumcols(cplexEnv(), _prob);
4.100 + double lb = -INF, ub = INF;
4.101 + CPXnewcols(cplexEnv(), _prob, 1, 0, &lb, &ub, 0, 0);
4.102 + return i;
4.103 + }
4.104 +
4.105 +
4.106 + int CplexBase::_addRow() {
4.107 + int i = CPXgetnumrows(cplexEnv(), _prob);
4.108 + const double ub = INF;
4.109 + const char s = 'L';
4.110 + CPXnewrows(cplexEnv(), _prob, 1, &ub, &s, 0, 0);
4.111 + return i;
4.112 + }
4.113 +
4.114 +
4.115 + void CplexBase::_eraseCol(int i) {
4.116 + CPXdelcols(cplexEnv(), _prob, i, i);
4.117 + }
4.118 +
4.119 + void CplexBase::_eraseRow(int i) {
4.120 + CPXdelrows(cplexEnv(), _prob, i, i);
4.121 + }
4.122 +
4.123 + void CplexBase::_eraseColId(int i) {
4.124 + cols.eraseIndex(i);
4.125 + cols.shiftIndices(i);
4.126 + }
4.127 + void CplexBase::_eraseRowId(int i) {
4.128 + rows.eraseIndex(i);
4.129 + rows.shiftIndices(i);
4.130 + }
4.131 +
4.132 + void CplexBase::_getColName(int col, std::string &name) const {
4.133 + int size;
4.134 + CPXgetcolname(cplexEnv(), _prob, 0, 0, 0, &size, col, col);
4.135 + if (size == 0) {
4.136 + name.clear();
4.137 + return;
4.138 + }
4.139 +
4.140 + size *= -1;
4.141 + std::vector<char> buf(size);
4.142 + char *cname;
4.143 + int tmp;
4.144 + CPXgetcolname(cplexEnv(), _prob, &cname, &buf.front(), size,
4.145 + &tmp, col, col);
4.146 + name = cname;
4.147 + }
4.148 +
4.149 + void CplexBase::_setColName(int col, const std::string &name) {
4.150 + char *cname;
4.151 + cname = const_cast<char*>(name.c_str());
4.152 + CPXchgcolname(cplexEnv(), _prob, 1, &col, &cname);
4.153 + }
4.154 +
4.155 + int CplexBase::_colByName(const std::string& name) const {
4.156 + int index;
4.157 + if (CPXgetcolindex(cplexEnv(), _prob,
4.158 + const_cast<char*>(name.c_str()), &index) == 0) {
4.159 + return index;
4.160 + }
4.161 + return -1;
4.162 + }
4.163 +
4.164 + void CplexBase::_getRowName(int row, std::string &name) const {
4.165 + int size;
4.166 + CPXgetrowname(cplexEnv(), _prob, 0, 0, 0, &size, row, row);
4.167 + if (size == 0) {
4.168 + name.clear();
4.169 + return;
4.170 + }
4.171 +
4.172 + size *= -1;
4.173 + std::vector<char> buf(size);
4.174 + char *cname;
4.175 + int tmp;
4.176 + CPXgetrowname(cplexEnv(), _prob, &cname, &buf.front(), size,
4.177 + &tmp, row, row);
4.178 + name = cname;
4.179 + }
4.180 +
4.181 + void CplexBase::_setRowName(int row, const std::string &name) {
4.182 + char *cname;
4.183 + cname = const_cast<char*>(name.c_str());
4.184 + CPXchgrowname(cplexEnv(), _prob, 1, &row, &cname);
4.185 + }
4.186 +
4.187 + int CplexBase::_rowByName(const std::string& name) const {
4.188 + int index;
4.189 + if (CPXgetrowindex(cplexEnv(), _prob,
4.190 + const_cast<char*>(name.c_str()), &index) == 0) {
4.191 + return index;
4.192 + }
4.193 + return -1;
4.194 + }
4.195 +
4.196 + void CplexBase::_setRowCoeffs(int i, ExprIterator b,
4.197 + ExprIterator e)
4.198 + {
4.199 + std::vector<int> indices;
4.200 + std::vector<int> rowlist;
4.201 + std::vector<Value> values;
4.202 +
4.203 + for(ExprIterator it=b; it!=e; ++it) {
4.204 + indices.push_back(it->first);
4.205 + values.push_back(it->second);
4.206 + rowlist.push_back(i);
4.207 + }
4.208 +
4.209 + CPXchgcoeflist(cplexEnv(), _prob, values.size(),
4.210 + &rowlist.front(), &indices.front(), &values.front());
4.211 + }
4.212 +
4.213 + void CplexBase::_getRowCoeffs(int i, InsertIterator b) const {
4.214 + int tmp1, tmp2, tmp3, length;
4.215 + CPXgetrows(cplexEnv(), _prob, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
4.216 +
4.217 + length = -length;
4.218 + std::vector<int> indices(length);
4.219 + std::vector<double> values(length);
4.220 +
4.221 + CPXgetrows(cplexEnv(), _prob, &tmp1, &tmp2,
4.222 + &indices.front(), &values.front(),
4.223 + length, &tmp3, i, i);
4.224 +
4.225 + for (int i = 0; i < length; ++i) {
4.226 + *b = std::make_pair(indices[i], values[i]);
4.227 + ++b;
4.228 + }
4.229 + }
4.230 +
4.231 + void CplexBase::_setColCoeffs(int i, ExprIterator b, ExprIterator e) {
4.232 + std::vector<int> indices;
4.233 + std::vector<int> collist;
4.234 + std::vector<Value> values;
4.235 +
4.236 + for(ExprIterator it=b; it!=e; ++it) {
4.237 + indices.push_back(it->first);
4.238 + values.push_back(it->second);
4.239 + collist.push_back(i);
4.240 + }
4.241 +
4.242 + CPXchgcoeflist(cplexEnv(), _prob, values.size(),
4.243 + &indices.front(), &collist.front(), &values.front());
4.244 + }
4.245 +
4.246 + void CplexBase::_getColCoeffs(int i, InsertIterator b) const {
4.247 +
4.248 + int tmp1, tmp2, tmp3, length;
4.249 + CPXgetcols(cplexEnv(), _prob, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
4.250 +
4.251 + length = -length;
4.252 + std::vector<int> indices(length);
4.253 + std::vector<double> values(length);
4.254 +
4.255 + CPXgetcols(cplexEnv(), _prob, &tmp1, &tmp2,
4.256 + &indices.front(), &values.front(),
4.257 + length, &tmp3, i, i);
4.258 +
4.259 + for (int i = 0; i < length; ++i) {
4.260 + *b = std::make_pair(indices[i], values[i]);
4.261 + ++b;
4.262 + }
4.263 +
4.264 + }
4.265 +
4.266 + void CplexBase::_setCoeff(int row, int col, Value value) {
4.267 + CPXchgcoef(cplexEnv(), _prob, row, col, value);
4.268 + }
4.269 +
4.270 + CplexBase::Value CplexBase::_getCoeff(int row, int col) const {
4.271 + CplexBase::Value value;
4.272 + CPXgetcoef(cplexEnv(), _prob, row, col, &value);
4.273 + return value;
4.274 + }
4.275 +
4.276 + void CplexBase::_setColLowerBound(int i, Value value) {
4.277 + const char s = 'L';
4.278 + CPXchgbds(cplexEnv(), _prob, 1, &i, &s, &value);
4.279 + }
4.280 +
4.281 + CplexBase::Value CplexBase::_getColLowerBound(int i) const {
4.282 + CplexBase::Value res;
4.283 + CPXgetlb(cplexEnv(), _prob, &res, i, i);
4.284 + return res <= -CPX_INFBOUND ? -INF : res;
4.285 + }
4.286 +
4.287 + void CplexBase::_setColUpperBound(int i, Value value)
4.288 + {
4.289 + const char s = 'U';
4.290 + CPXchgbds(cplexEnv(), _prob, 1, &i, &s, &value);
4.291 + }
4.292 +
4.293 + CplexBase::Value CplexBase::_getColUpperBound(int i) const {
4.294 + CplexBase::Value res;
4.295 + CPXgetub(cplexEnv(), _prob, &res, i, i);
4.296 + return res >= CPX_INFBOUND ? INF : res;
4.297 + }
4.298 +
4.299 + CplexBase::Value CplexBase::_getRowLowerBound(int i) const {
4.300 + char s;
4.301 + CPXgetsense(cplexEnv(), _prob, &s, i, i);
4.302 + CplexBase::Value res;
4.303 +
4.304 + switch (s) {
4.305 + case 'G':
4.306 + case 'R':
4.307 + case 'E':
4.308 + CPXgetrhs(cplexEnv(), _prob, &res, i, i);
4.309 + return res <= -CPX_INFBOUND ? -INF : res;
4.310 + default:
4.311 + return -INF;
4.312 + }
4.313 + }
4.314 +
4.315 + CplexBase::Value CplexBase::_getRowUpperBound(int i) const {
4.316 + char s;
4.317 + CPXgetsense(cplexEnv(), _prob, &s, i, i);
4.318 + CplexBase::Value res;
4.319 +
4.320 + switch (s) {
4.321 + case 'L':
4.322 + case 'E':
4.323 + CPXgetrhs(cplexEnv(), _prob, &res, i, i);
4.324 + return res >= CPX_INFBOUND ? INF : res;
4.325 + case 'R':
4.326 + CPXgetrhs(cplexEnv(), _prob, &res, i, i);
4.327 + {
4.328 + double rng;
4.329 + CPXgetrngval(cplexEnv(), _prob, &rng, i, i);
4.330 + res += rng;
4.331 + }
4.332 + return res >= CPX_INFBOUND ? INF : res;
4.333 + default:
4.334 + return INF;
4.335 + }
4.336 + }
4.337 +
4.338 + //This is easier to implement
4.339 + void CplexBase::_set_row_bounds(int i, Value lb, Value ub) {
4.340 + if (lb == -INF) {
4.341 + const char s = 'L';
4.342 + CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
4.343 + CPXchgrhs(cplexEnv(), _prob, 1, &i, &ub);
4.344 + } else if (ub == INF) {
4.345 + const char s = 'G';
4.346 + CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
4.347 + CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
4.348 + } else if (lb == ub){
4.349 + const char s = 'E';
4.350 + CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
4.351 + CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
4.352 + } else {
4.353 + const char s = 'R';
4.354 + CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
4.355 + CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
4.356 + double len = ub - lb;
4.357 + CPXchgrngval(cplexEnv(), _prob, 1, &i, &len);
4.358 + }
4.359 + }
4.360 +
4.361 + void CplexBase::_setRowLowerBound(int i, Value lb)
4.362 + {
4.363 + LEMON_ASSERT(lb != INF, "Invalid bound");
4.364 + _set_row_bounds(i, lb, CplexBase::_getRowUpperBound(i));
4.365 + }
4.366 +
4.367 + void CplexBase::_setRowUpperBound(int i, Value ub)
4.368 + {
4.369 +
4.370 + LEMON_ASSERT(ub != -INF, "Invalid bound");
4.371 + _set_row_bounds(i, CplexBase::_getRowLowerBound(i), ub);
4.372 + }
4.373 +
4.374 + void CplexBase::_setObjCoeffs(ExprIterator b, ExprIterator e)
4.375 + {
4.376 + std::vector<int> indices;
4.377 + std::vector<Value> values;
4.378 + for(ExprIterator it=b; it!=e; ++it) {
4.379 + indices.push_back(it->first);
4.380 + values.push_back(it->second);
4.381 + }
4.382 + CPXchgobj(cplexEnv(), _prob, values.size(),
4.383 + &indices.front(), &values.front());
4.384 +
4.385 + }
4.386 +
4.387 + void CplexBase::_getObjCoeffs(InsertIterator b) const
4.388 + {
4.389 + int num = CPXgetnumcols(cplexEnv(), _prob);
4.390 + std::vector<Value> x(num);
4.391 +
4.392 + CPXgetobj(cplexEnv(), _prob, &x.front(), 0, num - 1);
4.393 + for (int i = 0; i < num; ++i) {
4.394 + if (x[i] != 0.0) {
4.395 + *b = std::make_pair(i, x[i]);
4.396 + ++b;
4.397 + }
4.398 + }
4.399 + }
4.400 +
4.401 + void CplexBase::_setObjCoeff(int i, Value obj_coef)
4.402 + {
4.403 + CPXchgobj(cplexEnv(), _prob, 1, &i, &obj_coef);
4.404 + }
4.405 +
4.406 + CplexBase::Value CplexBase::_getObjCoeff(int i) const
4.407 + {
4.408 + Value x;
4.409 + CPXgetobj(cplexEnv(), _prob, &x, i, i);
4.410 + return x;
4.411 + }
4.412 +
4.413 + void CplexBase::_setSense(CplexBase::Sense sense) {
4.414 + switch (sense) {
4.415 + case MIN:
4.416 + CPXchgobjsen(cplexEnv(), _prob, CPX_MIN);
4.417 + break;
4.418 + case MAX:
4.419 + CPXchgobjsen(cplexEnv(), _prob, CPX_MAX);
4.420 + break;
4.421 + }
4.422 + }
4.423 +
4.424 + CplexBase::Sense CplexBase::_getSense() const {
4.425 + switch (CPXgetobjsen(cplexEnv(), _prob)) {
4.426 + case CPX_MIN:
4.427 + return MIN;
4.428 + case CPX_MAX:
4.429 + return MAX;
4.430 + default:
4.431 + LEMON_ASSERT(false, "Invalid sense");
4.432 + return CplexBase::Sense();
4.433 + }
4.434 + }
4.435 +
4.436 + void CplexBase::_clear() {
4.437 + CPXfreeprob(cplexEnv(),&_prob);
4.438 + int status;
4.439 + _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
4.440 + rows.clear();
4.441 + cols.clear();
4.442 + }
4.443 +
4.444 + // LpCplex members
4.445 +
4.446 + LpCplex::LpCplex()
4.447 + : LpBase(), CplexBase(), LpSolver() {}
4.448 +
4.449 + LpCplex::LpCplex(const CplexEnv& env)
4.450 + : LpBase(), CplexBase(env), LpSolver() {}
4.451 +
4.452 + LpCplex::LpCplex(const LpCplex& other)
4.453 + : LpBase(), CplexBase(other), LpSolver() {}
4.454 +
4.455 + LpCplex::~LpCplex() {}
4.456 +
4.457 + LpCplex* LpCplex::_newSolver() const { return new LpCplex; }
4.458 + LpCplex* LpCplex::_cloneSolver() const {return new LpCplex(*this); }
4.459 +
4.460 + const char* LpCplex::_solverName() const { return "LpCplex"; }
4.461 +
4.462 + void LpCplex::_clear_temporals() {
4.463 + _col_status.clear();
4.464 + _row_status.clear();
4.465 + _primal_ray.clear();
4.466 + _dual_ray.clear();
4.467 + }
4.468 +
4.469 + // The routine returns zero unless an error occurred during the
4.470 + // optimization. Examples of errors include exhausting available
4.471 + // memory (CPXERR_NO_MEMORY) or encountering invalid data in the
4.472 + // CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a
4.473 + // user-specified CPLEX limit, or proving the model infeasible or
4.474 + // unbounded, are not considered errors. Note that a zero return
4.475 + // value does not necessarily mean that a solution exists. Use query
4.476 + // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
4.477 + // further information about the status of the optimization.
4.478 + LpCplex::SolveExitStatus LpCplex::convertStatus(int status) {
4.479 +#if CPX_VERSION >= 800
4.480 + if (status == 0) {
4.481 + switch (CPXgetstat(cplexEnv(), _prob)) {
4.482 + case CPX_STAT_OPTIMAL:
4.483 + case CPX_STAT_INFEASIBLE:
4.484 + case CPX_STAT_UNBOUNDED:
4.485 + return SOLVED;
4.486 + default:
4.487 + return UNSOLVED;
4.488 + }
4.489 + } else {
4.490 + return UNSOLVED;
4.491 + }
4.492 +#else
4.493 + if (status == 0) {
4.494 + //We want to exclude some cases
4.495 + switch (CPXgetstat(cplexEnv(), _prob)) {
4.496 + case CPX_OBJ_LIM:
4.497 + case CPX_IT_LIM_FEAS:
4.498 + case CPX_IT_LIM_INFEAS:
4.499 + case CPX_TIME_LIM_FEAS:
4.500 + case CPX_TIME_LIM_INFEAS:
4.501 + return UNSOLVED;
4.502 + default:
4.503 + return SOLVED;
4.504 + }
4.505 + } else {
4.506 + return UNSOLVED;
4.507 + }
4.508 +#endif
4.509 + }
4.510 +
4.511 + LpCplex::SolveExitStatus LpCplex::_solve() {
4.512 + _clear_temporals();
4.513 + return convertStatus(CPXlpopt(cplexEnv(), _prob));
4.514 + }
4.515 +
4.516 + LpCplex::SolveExitStatus LpCplex::solvePrimal() {
4.517 + _clear_temporals();
4.518 + return convertStatus(CPXprimopt(cplexEnv(), _prob));
4.519 + }
4.520 +
4.521 + LpCplex::SolveExitStatus LpCplex::solveDual() {
4.522 + _clear_temporals();
4.523 + return convertStatus(CPXdualopt(cplexEnv(), _prob));
4.524 + }
4.525 +
4.526 + LpCplex::SolveExitStatus LpCplex::solveBarrier() {
4.527 + _clear_temporals();
4.528 + return convertStatus(CPXbaropt(cplexEnv(), _prob));
4.529 + }
4.530 +
4.531 + LpCplex::Value LpCplex::_getPrimal(int i) const {
4.532 + Value x;
4.533 + CPXgetx(cplexEnv(), _prob, &x, i, i);
4.534 + return x;
4.535 + }
4.536 +
4.537 + LpCplex::Value LpCplex::_getDual(int i) const {
4.538 + Value y;
4.539 + CPXgetpi(cplexEnv(), _prob, &y, i, i);
4.540 + return y;
4.541 + }
4.542 +
4.543 + LpCplex::Value LpCplex::_getPrimalValue() const {
4.544 + Value objval;
4.545 + CPXgetobjval(cplexEnv(), _prob, &objval);
4.546 + return objval;
4.547 + }
4.548 +
4.549 + LpCplex::VarStatus LpCplex::_getColStatus(int i) const {
4.550 + if (_col_status.empty()) {
4.551 + _col_status.resize(CPXgetnumcols(cplexEnv(), _prob));
4.552 + CPXgetbase(cplexEnv(), _prob, &_col_status.front(), 0);
4.553 + }
4.554 + switch (_col_status[i]) {
4.555 + case CPX_BASIC:
4.556 + return BASIC;
4.557 + case CPX_FREE_SUPER:
4.558 + return FREE;
4.559 + case CPX_AT_LOWER:
4.560 + return LOWER;
4.561 + case CPX_AT_UPPER:
4.562 + return UPPER;
4.563 + default:
4.564 + LEMON_ASSERT(false, "Wrong column status");
4.565 + return LpCplex::VarStatus();
4.566 + }
4.567 + }
4.568 +
4.569 + LpCplex::VarStatus LpCplex::_getRowStatus(int i) const {
4.570 + if (_row_status.empty()) {
4.571 + _row_status.resize(CPXgetnumrows(cplexEnv(), _prob));
4.572 + CPXgetbase(cplexEnv(), _prob, 0, &_row_status.front());
4.573 + }
4.574 + switch (_row_status[i]) {
4.575 + case CPX_BASIC:
4.576 + return BASIC;
4.577 + case CPX_AT_LOWER:
4.578 + {
4.579 + char s;
4.580 + CPXgetsense(cplexEnv(), _prob, &s, i, i);
4.581 + return s != 'L' ? LOWER : UPPER;
4.582 + }
4.583 + case CPX_AT_UPPER:
4.584 + return UPPER;
4.585 + default:
4.586 + LEMON_ASSERT(false, "Wrong row status");
4.587 + return LpCplex::VarStatus();
4.588 + }
4.589 + }
4.590 +
4.591 + LpCplex::Value LpCplex::_getPrimalRay(int i) const {
4.592 + if (_primal_ray.empty()) {
4.593 + _primal_ray.resize(CPXgetnumcols(cplexEnv(), _prob));
4.594 + CPXgetray(cplexEnv(), _prob, &_primal_ray.front());
4.595 + }
4.596 + return _primal_ray[i];
4.597 + }
4.598 +
4.599 + LpCplex::Value LpCplex::_getDualRay(int i) const {
4.600 + if (_dual_ray.empty()) {
4.601 +
4.602 + }
4.603 + return _dual_ray[i];
4.604 + }
4.605 +
4.606 + //7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
4.607 + // This table lists the statuses, returned by the CPXgetstat()
4.608 + // routine, for solutions to LP problems or mixed integer problems. If
4.609 + // no solution exists, the return value is zero.
4.610 +
4.611 + // For Simplex, Barrier
4.612 + // 1 CPX_OPTIMAL
4.613 + // Optimal solution found
4.614 + // 2 CPX_INFEASIBLE
4.615 + // Problem infeasible
4.616 + // 3 CPX_UNBOUNDED
4.617 + // Problem unbounded
4.618 + // 4 CPX_OBJ_LIM
4.619 + // Objective limit exceeded in Phase II
4.620 + // 5 CPX_IT_LIM_FEAS
4.621 + // Iteration limit exceeded in Phase II
4.622 + // 6 CPX_IT_LIM_INFEAS
4.623 + // Iteration limit exceeded in Phase I
4.624 + // 7 CPX_TIME_LIM_FEAS
4.625 + // Time limit exceeded in Phase II
4.626 + // 8 CPX_TIME_LIM_INFEAS
4.627 + // Time limit exceeded in Phase I
4.628 + // 9 CPX_NUM_BEST_FEAS
4.629 + // Problem non-optimal, singularities in Phase II
4.630 + // 10 CPX_NUM_BEST_INFEAS
4.631 + // Problem non-optimal, singularities in Phase I
4.632 + // 11 CPX_OPTIMAL_INFEAS
4.633 + // Optimal solution found, unscaled infeasibilities
4.634 + // 12 CPX_ABORT_FEAS
4.635 + // Aborted in Phase II
4.636 + // 13 CPX_ABORT_INFEAS
4.637 + // Aborted in Phase I
4.638 + // 14 CPX_ABORT_DUAL_INFEAS
4.639 + // Aborted in barrier, dual infeasible
4.640 + // 15 CPX_ABORT_PRIM_INFEAS
4.641 + // Aborted in barrier, primal infeasible
4.642 + // 16 CPX_ABORT_PRIM_DUAL_INFEAS
4.643 + // Aborted in barrier, primal and dual infeasible
4.644 + // 17 CPX_ABORT_PRIM_DUAL_FEAS
4.645 + // Aborted in barrier, primal and dual feasible
4.646 + // 18 CPX_ABORT_CROSSOVER
4.647 + // Aborted in crossover
4.648 + // 19 CPX_INForUNBD
4.649 + // Infeasible or unbounded
4.650 + // 20 CPX_PIVOT
4.651 + // User pivot used
4.652 + //
4.653 + // Ezeket hova tegyem:
4.654 + // ??case CPX_ABORT_DUAL_INFEAS
4.655 + // ??case CPX_ABORT_CROSSOVER
4.656 + // ??case CPX_INForUNBD
4.657 + // ??case CPX_PIVOT
4.658 +
4.659 + //Some more interesting stuff:
4.660 +
4.661 + // CPX_PARAM_PROBMETHOD 1062 int LPMETHOD
4.662 + // 0 Automatic
4.663 + // 1 Primal Simplex
4.664 + // 2 Dual Simplex
4.665 + // 3 Network Simplex
4.666 + // 4 Standard Barrier
4.667 + // Default: 0
4.668 + // Description: Method for linear optimization.
4.669 + // Determines which algorithm is used when CPXlpopt() (or "optimize"
4.670 + // in the Interactive Optimizer) is called. Currently the behavior of
4.671 + // the "Automatic" setting is that CPLEX simply invokes the dual
4.672 + // simplex method, but this capability may be expanded in the future
4.673 + // so that CPLEX chooses the method based on problem characteristics
4.674 +#if CPX_VERSION < 900
4.675 + void statusSwitch(CPXENVptr cplexEnv(),int& stat){
4.676 + int lpmethod;
4.677 + CPXgetintparam (cplexEnv(),CPX_PARAM_PROBMETHOD,&lpmethod);
4.678 + if (lpmethod==2){
4.679 + if (stat==CPX_UNBOUNDED){
4.680 + stat=CPX_INFEASIBLE;
4.681 + }
4.682 + else{
4.683 + if (stat==CPX_INFEASIBLE)
4.684 + stat=CPX_UNBOUNDED;
4.685 + }
4.686 + }
4.687 + }
4.688 +#else
4.689 + void statusSwitch(CPXENVptr,int&){}
4.690 +#endif
4.691 +
4.692 + LpCplex::ProblemType LpCplex::_getPrimalType() const {
4.693 + // Unboundedness not treated well: the following is from cplex 9.0 doc
4.694 + // About Unboundedness
4.695 +
4.696 + // The treatment of models that are unbounded involves a few
4.697 + // subtleties. Specifically, a declaration of unboundedness means that
4.698 + // ILOG CPLEX has determined that the model has an unbounded
4.699 + // ray. Given any feasible solution x with objective z, a multiple of
4.700 + // the unbounded ray can be added to x to give a feasible solution
4.701 + // with objective z-1 (or z+1 for maximization models). Thus, if a
4.702 + // feasible solution exists, then the optimal objective is
4.703 + // unbounded. Note that ILOG CPLEX has not necessarily concluded that
4.704 + // a feasible solution exists. Users can call the routine CPXsolninfo
4.705 + // to determine whether ILOG CPLEX has also concluded that the model
4.706 + // has a feasible solution.
4.707 +
4.708 + int stat = CPXgetstat(cplexEnv(), _prob);
4.709 +#if CPX_VERSION >= 800
4.710 + switch (stat)
4.711 + {
4.712 + case CPX_STAT_OPTIMAL:
4.713 + return OPTIMAL;
4.714 + case CPX_STAT_UNBOUNDED:
4.715 + return UNBOUNDED;
4.716 + case CPX_STAT_INFEASIBLE:
4.717 + return INFEASIBLE;
4.718 + default:
4.719 + return UNDEFINED;
4.720 + }
4.721 +#else
4.722 + statusSwitch(cplexEnv(),stat);
4.723 + //CPXgetstat(cplexEnv(), _prob);
4.724 + //printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL);
4.725 + switch (stat) {
4.726 + case 0:
4.727 + return UNDEFINED; //Undefined
4.728 + case CPX_OPTIMAL://Optimal
4.729 + return OPTIMAL;
4.730 + case CPX_UNBOUNDED://Unbounded
4.731 + return INFEASIBLE;//In case of dual simplex
4.732 + //return UNBOUNDED;
4.733 + case CPX_INFEASIBLE://Infeasible
4.734 + // case CPX_IT_LIM_INFEAS:
4.735 + // case CPX_TIME_LIM_INFEAS:
4.736 + // case CPX_NUM_BEST_INFEAS:
4.737 + // case CPX_OPTIMAL_INFEAS:
4.738 + // case CPX_ABORT_INFEAS:
4.739 + // case CPX_ABORT_PRIM_INFEAS:
4.740 + // case CPX_ABORT_PRIM_DUAL_INFEAS:
4.741 + return UNBOUNDED;//In case of dual simplex
4.742 + //return INFEASIBLE;
4.743 + // case CPX_OBJ_LIM:
4.744 + // case CPX_IT_LIM_FEAS:
4.745 + // case CPX_TIME_LIM_FEAS:
4.746 + // case CPX_NUM_BEST_FEAS:
4.747 + // case CPX_ABORT_FEAS:
4.748 + // case CPX_ABORT_PRIM_DUAL_FEAS:
4.749 + // return FEASIBLE;
4.750 + default:
4.751 + return UNDEFINED; //Everything else comes here
4.752 + //FIXME error
4.753 + }
4.754 +#endif
4.755 + }
4.756 +
4.757 + //9.0-as cplex verzio statusai
4.758 + // CPX_STAT_ABORT_DUAL_OBJ_LIM
4.759 + // CPX_STAT_ABORT_IT_LIM
4.760 + // CPX_STAT_ABORT_OBJ_LIM
4.761 + // CPX_STAT_ABORT_PRIM_OBJ_LIM
4.762 + // CPX_STAT_ABORT_TIME_LIM
4.763 + // CPX_STAT_ABORT_USER
4.764 + // CPX_STAT_FEASIBLE_RELAXED
4.765 + // CPX_STAT_INFEASIBLE
4.766 + // CPX_STAT_INForUNBD
4.767 + // CPX_STAT_NUM_BEST
4.768 + // CPX_STAT_OPTIMAL
4.769 + // CPX_STAT_OPTIMAL_FACE_UNBOUNDED
4.770 + // CPX_STAT_OPTIMAL_INFEAS
4.771 + // CPX_STAT_OPTIMAL_RELAXED
4.772 + // CPX_STAT_UNBOUNDED
4.773 +
4.774 + LpCplex::ProblemType LpCplex::_getDualType() const {
4.775 + int stat = CPXgetstat(cplexEnv(), _prob);
4.776 +#if CPX_VERSION >= 800
4.777 + switch (stat) {
4.778 + case CPX_STAT_OPTIMAL:
4.779 + return OPTIMAL;
4.780 + case CPX_STAT_UNBOUNDED:
4.781 + return INFEASIBLE;
4.782 + default:
4.783 + return UNDEFINED;
4.784 + }
4.785 +#else
4.786 + statusSwitch(cplexEnv(),stat);
4.787 + switch (stat) {
4.788 + case 0:
4.789 + return UNDEFINED; //Undefined
4.790 + case CPX_OPTIMAL://Optimal
4.791 + return OPTIMAL;
4.792 + case CPX_UNBOUNDED:
4.793 + return INFEASIBLE;
4.794 + default:
4.795 + return UNDEFINED; //Everything else comes here
4.796 + //FIXME error
4.797 + }
4.798 +#endif
4.799 + }
4.800 +
4.801 + // MipCplex members
4.802 +
4.803 + MipCplex::MipCplex()
4.804 + : LpBase(), CplexBase(), MipSolver() {
4.805 +
4.806 +#if CPX_VERSION < 800
4.807 + CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MIP);
4.808 +#else
4.809 + CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MILP);
4.810 +#endif
4.811 + }
4.812 +
4.813 + MipCplex::MipCplex(const CplexEnv& env)
4.814 + : LpBase(), CplexBase(env), MipSolver() {
4.815 +
4.816 +#if CPX_VERSION < 800
4.817 + CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MIP);
4.818 +#else
4.819 + CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MILP);
4.820 +#endif
4.821 +
4.822 + }
4.823 +
4.824 + MipCplex::MipCplex(const MipCplex& other)
4.825 + : LpBase(), CplexBase(other), MipSolver() {}
4.826 +
4.827 + MipCplex::~MipCplex() {}
4.828 +
4.829 + MipCplex* MipCplex::_newSolver() const { return new MipCplex; }
4.830 + MipCplex* MipCplex::_cloneSolver() const {return new MipCplex(*this); }
4.831 +
4.832 + const char* MipCplex::_solverName() const { return "MipCplex"; }
4.833 +
4.834 + void MipCplex::_setColType(int i, MipCplex::ColTypes col_type) {
4.835 +
4.836 + // Note If a variable is to be changed to binary, a call to CPXchgbds
4.837 + // should also be made to change the bounds to 0 and 1.
4.838 +
4.839 + switch (col_type){
4.840 + case INTEGER: {
4.841 + const char t = 'I';
4.842 + CPXchgctype (cplexEnv(), _prob, 1, &i, &t);
4.843 + } break;
4.844 + case REAL: {
4.845 + const char t = 'C';
4.846 + CPXchgctype (cplexEnv(), _prob, 1, &i, &t);
4.847 + } break;
4.848 + default:
4.849 + break;
4.850 + }
4.851 + }
4.852 +
4.853 + MipCplex::ColTypes MipCplex::_getColType(int i) const {
4.854 + char t;
4.855 + CPXgetctype (cplexEnv(), _prob, &t, i, i);
4.856 + switch (t) {
4.857 + case 'I':
4.858 + return INTEGER;
4.859 + case 'C':
4.860 + return REAL;
4.861 + default:
4.862 + LEMON_ASSERT(false, "Invalid column type");
4.863 + return ColTypes();
4.864 + }
4.865 +
4.866 + }
4.867 +
4.868 + MipCplex::SolveExitStatus MipCplex::_solve() {
4.869 + int status;
4.870 + status = CPXmipopt (cplexEnv(), _prob);
4.871 + if (status==0)
4.872 + return SOLVED;
4.873 + else
4.874 + return UNSOLVED;
4.875 +
4.876 + }
4.877 +
4.878 +
4.879 + MipCplex::ProblemType MipCplex::_getType() const {
4.880 +
4.881 + int stat = CPXgetstat(cplexEnv(), _prob);
4.882 +
4.883 + //Fortunately, MIP statuses did not change for cplex 8.0
4.884 + switch (stat) {
4.885 + case CPXMIP_OPTIMAL:
4.886 + // Optimal integer solution has been found.
4.887 + case CPXMIP_OPTIMAL_TOL:
4.888 + // Optimal soluton with the tolerance defined by epgap or epagap has
4.889 + // been found.
4.890 + return OPTIMAL;
4.891 + //This also exists in later issues
4.892 + // case CPXMIP_UNBOUNDED:
4.893 + //return UNBOUNDED;
4.894 + case CPXMIP_INFEASIBLE:
4.895 + return INFEASIBLE;
4.896 + default:
4.897 + return UNDEFINED;
4.898 + }
4.899 + //Unboundedness not treated well: the following is from cplex 9.0 doc
4.900 + // About Unboundedness
4.901 +
4.902 + // The treatment of models that are unbounded involves a few
4.903 + // subtleties. Specifically, a declaration of unboundedness means that
4.904 + // ILOG CPLEX has determined that the model has an unbounded
4.905 + // ray. Given any feasible solution x with objective z, a multiple of
4.906 + // the unbounded ray can be added to x to give a feasible solution
4.907 + // with objective z-1 (or z+1 for maximization models). Thus, if a
4.908 + // feasible solution exists, then the optimal objective is
4.909 + // unbounded. Note that ILOG CPLEX has not necessarily concluded that
4.910 + // a feasible solution exists. Users can call the routine CPXsolninfo
4.911 + // to determine whether ILOG CPLEX has also concluded that the model
4.912 + // has a feasible solution.
4.913 + }
4.914 +
4.915 + MipCplex::Value MipCplex::_getSol(int i) const {
4.916 + Value x;
4.917 + CPXgetmipx(cplexEnv(), _prob, &x, i, i);
4.918 + return x;
4.919 + }
4.920 +
4.921 + MipCplex::Value MipCplex::_getSolValue() const {
4.922 + Value objval;
4.923 + CPXgetmipobjval(cplexEnv(), _prob, &objval);
4.924 + return objval;
4.925 + }
4.926 +
4.927 +} //namespace lemon
4.928 +
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/lemon/cplex.h Mon Jan 12 12:26:01 2009 +0000
5.3 @@ -0,0 +1,256 @@
5.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
5.5 + *
5.6 + * This file is a part of LEMON, a generic C++ optimization library.
5.7 + *
5.8 + * Copyright (C) 2003-2008
5.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
5.11 + *
5.12 + * Permission to use, modify and distribute this software is granted
5.13 + * provided that this copyright notice appears in all copies. For
5.14 + * precise terms see the accompanying LICENSE file.
5.15 + *
5.16 + * This software is provided "AS IS" with no warranty of any kind,
5.17 + * express or implied, and with no claim as to its suitability for any
5.18 + * purpose.
5.19 + *
5.20 + */
5.21 +
5.22 +#ifndef LEMON_CPLEX_H
5.23 +#define LEMON_CPLEX_H
5.24 +
5.25 +///\file
5.26 +///\brief Header of the LEMON-CPLEX lp solver interface.
5.27 +
5.28 +#include <lemon/lp_base.h>
5.29 +
5.30 +struct cpxenv;
5.31 +struct cpxlp;
5.32 +
5.33 +namespace lemon {
5.34 +
5.35 + /// \brief Reference counted wrapper around cpxenv pointer
5.36 + ///
5.37 + /// The cplex uses environment object which is responsible for
5.38 + /// checking the proper license usage. This class provides a simple
5.39 + /// interface for share the environment object between different
5.40 + /// problems.
5.41 + class CplexEnv {
5.42 + friend class CplexBase;
5.43 + private:
5.44 + cpxenv* _env;
5.45 + mutable int* _cnt;
5.46 +
5.47 + public:
5.48 +
5.49 + /// \brief This exception is thrown when the license check is not
5.50 + /// sufficient
5.51 + class LicenseError : public Exception {
5.52 + friend class CplexEnv;
5.53 + private:
5.54 +
5.55 + LicenseError(int status);
5.56 + char _message[510];
5.57 +
5.58 + public:
5.59 +
5.60 + /// The short error message
5.61 + virtual const char* what() const throw() {
5.62 + return _message;
5.63 + }
5.64 + };
5.65 +
5.66 + /// Constructor
5.67 + CplexEnv();
5.68 + /// Shallow copy constructor
5.69 + CplexEnv(const CplexEnv&);
5.70 + /// Shallow assignement
5.71 + CplexEnv& operator=(const CplexEnv&);
5.72 + /// Destructor
5.73 + virtual ~CplexEnv();
5.74 +
5.75 + protected:
5.76 +
5.77 + cpxenv* cplexEnv() { return _env; }
5.78 + const cpxenv* cplexEnv() const { return _env; }
5.79 + };
5.80 +
5.81 + /// \brief Base interface for the CPLEX LP and MIP solver
5.82 + ///
5.83 + /// This class implements the common interface of the CPLEX LP and
5.84 + /// MIP solvers.
5.85 + /// \ingroup lp_group
5.86 + class CplexBase : virtual public LpBase {
5.87 + protected:
5.88 +
5.89 + CplexEnv _env;
5.90 + cpxlp* _prob;
5.91 +
5.92 + CplexBase();
5.93 + CplexBase(const CplexEnv&);
5.94 + CplexBase(const CplexBase &);
5.95 + virtual ~CplexBase();
5.96 +
5.97 + virtual int _addCol();
5.98 + virtual int _addRow();
5.99 +
5.100 + virtual void _eraseCol(int i);
5.101 + virtual void _eraseRow(int i);
5.102 +
5.103 + virtual void _eraseColId(int i);
5.104 + virtual void _eraseRowId(int i);
5.105 +
5.106 + virtual void _getColName(int col, std::string& name) const;
5.107 + virtual void _setColName(int col, const std::string& name);
5.108 + virtual int _colByName(const std::string& name) const;
5.109 +
5.110 + virtual void _getRowName(int row, std::string& name) const;
5.111 + virtual void _setRowName(int row, const std::string& name);
5.112 + virtual int _rowByName(const std::string& name) const;
5.113 +
5.114 + virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
5.115 + virtual void _getRowCoeffs(int i, InsertIterator b) const;
5.116 +
5.117 + virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
5.118 + virtual void _getColCoeffs(int i, InsertIterator b) const;
5.119 +
5.120 + virtual void _setCoeff(int row, int col, Value value);
5.121 + virtual Value _getCoeff(int row, int col) const;
5.122 +
5.123 + virtual void _setColLowerBound(int i, Value value);
5.124 + virtual Value _getColLowerBound(int i) const;
5.125 +
5.126 + virtual void _setColUpperBound(int i, Value value);
5.127 + virtual Value _getColUpperBound(int i) const;
5.128 +
5.129 + private:
5.130 + void _set_row_bounds(int i, Value lb, Value ub);
5.131 + protected:
5.132 +
5.133 + virtual void _setRowLowerBound(int i, Value value);
5.134 + virtual Value _getRowLowerBound(int i) const;
5.135 +
5.136 + virtual void _setRowUpperBound(int i, Value value);
5.137 + virtual Value _getRowUpperBound(int i) const;
5.138 +
5.139 + virtual void _setObjCoeffs(ExprIterator b, ExprIterator e);
5.140 + virtual void _getObjCoeffs(InsertIterator b) const;
5.141 +
5.142 + virtual void _setObjCoeff(int i, Value obj_coef);
5.143 + virtual Value _getObjCoeff(int i) const;
5.144 +
5.145 + virtual void _setSense(Sense sense);
5.146 + virtual Sense _getSense() const;
5.147 +
5.148 + virtual void _clear();
5.149 +
5.150 + public:
5.151 +
5.152 + /// Returns the used \c CplexEnv instance
5.153 + const CplexEnv& env() const { return _env; }
5.154 + ///
5.155 + const cpxenv* cplexEnv() const { return _env.cplexEnv(); }
5.156 +
5.157 + cpxlp* cplexLp() { return _prob; }
5.158 + const cpxlp* cplexLp() const { return _prob; }
5.159 +
5.160 + };
5.161 +
5.162 + /// \brief Interface for the CPLEX LP solver
5.163 + ///
5.164 + /// This class implements an interface for the CPLEX LP solver.
5.165 + ///\ingroup lp_group
5.166 + class LpCplex : public CplexBase, public LpSolver {
5.167 + public:
5.168 + /// \e
5.169 + LpCplex();
5.170 + /// \e
5.171 + LpCplex(const CplexEnv&);
5.172 + /// \e
5.173 + LpCplex(const LpCplex&);
5.174 + /// \e
5.175 + virtual ~LpCplex();
5.176 +
5.177 + private:
5.178 +
5.179 + // these values cannot retrieved element by element
5.180 + mutable std::vector<int> _col_status;
5.181 + mutable std::vector<int> _row_status;
5.182 +
5.183 + mutable std::vector<Value> _primal_ray;
5.184 + mutable std::vector<Value> _dual_ray;
5.185 +
5.186 + void _clear_temporals();
5.187 +
5.188 + SolveExitStatus convertStatus(int status);
5.189 +
5.190 + protected:
5.191 +
5.192 + virtual LpCplex* _cloneSolver() const;
5.193 + virtual LpCplex* _newSolver() const;
5.194 +
5.195 + virtual const char* _solverName() const;
5.196 +
5.197 + virtual SolveExitStatus _solve();
5.198 + virtual Value _getPrimal(int i) const;
5.199 + virtual Value _getDual(int i) const;
5.200 + virtual Value _getPrimalValue() const;
5.201 +
5.202 + virtual VarStatus _getColStatus(int i) const;
5.203 + virtual VarStatus _getRowStatus(int i) const;
5.204 +
5.205 + virtual Value _getPrimalRay(int i) const;
5.206 + virtual Value _getDualRay(int i) const;
5.207 +
5.208 + virtual ProblemType _getPrimalType() const;
5.209 + virtual ProblemType _getDualType() const;
5.210 +
5.211 + public:
5.212 +
5.213 + /// Solve with primal simplex method
5.214 + SolveExitStatus solvePrimal();
5.215 +
5.216 + /// Solve with dual simplex method
5.217 + SolveExitStatus solveDual();
5.218 +
5.219 + /// Solve with barrier method
5.220 + SolveExitStatus solveBarrier();
5.221 +
5.222 + };
5.223 +
5.224 + /// \brief Interface for the CPLEX MIP solver
5.225 + ///
5.226 + /// This class implements an interface for the CPLEX MIP solver.
5.227 + ///\ingroup lp_group
5.228 + class MipCplex : public CplexBase, public MipSolver {
5.229 + public:
5.230 + /// \e
5.231 + MipCplex();
5.232 + /// \e
5.233 + MipCplex(const CplexEnv&);
5.234 + /// \e
5.235 + MipCplex(const MipCplex&);
5.236 + /// \e
5.237 + virtual ~MipCplex();
5.238 +
5.239 + protected:
5.240 +
5.241 + virtual MipCplex* _cloneSolver() const;
5.242 + virtual MipCplex* _newSolver() const;
5.243 +
5.244 + virtual const char* _solverName() const;
5.245 +
5.246 + virtual ColTypes _getColType(int col) const;
5.247 + virtual void _setColType(int col, ColTypes col_type);
5.248 +
5.249 + virtual SolveExitStatus _solve();
5.250 + virtual ProblemType _getType() const;
5.251 + virtual Value _getSol(int i) const;
5.252 + virtual Value _getSolValue() const;
5.253 +
5.254 + };
5.255 +
5.256 +} //END OF NAMESPACE LEMON
5.257 +
5.258 +#endif //LEMON_CPLEX_H
5.259 +
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/lemon/glpk.cc Mon Jan 12 12:26:01 2009 +0000
6.3 @@ -0,0 +1,952 @@
6.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
6.5 + *
6.6 + * This file is a part of LEMON, a generic C++ optimization library.
6.7 + *
6.8 + * Copyright (C) 2003-2008
6.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
6.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
6.11 + *
6.12 + * Permission to use, modify and distribute this software is granted
6.13 + * provided that this copyright notice appears in all copies. For
6.14 + * precise terms see the accompanying LICENSE file.
6.15 + *
6.16 + * This software is provided "AS IS" with no warranty of any kind,
6.17 + * express or implied, and with no claim as to its suitability for any
6.18 + * purpose.
6.19 + *
6.20 + */
6.21 +
6.22 +///\file
6.23 +///\brief Implementation of the LEMON GLPK LP and MIP solver interface.
6.24 +
6.25 +#include <lemon/glpk.h>
6.26 +#include <glpk.h>
6.27 +
6.28 +#include <lemon/assert.h>
6.29 +
6.30 +namespace lemon {
6.31 +
6.32 + // GlpkBase members
6.33 +
6.34 + GlpkBase::GlpkBase() : LpBase() {
6.35 + lp = glp_create_prob();
6.36 + glp_create_index(lp);
6.37 + }
6.38 +
6.39 + GlpkBase::GlpkBase(const GlpkBase &other) : LpBase() {
6.40 + lp = glp_create_prob();
6.41 + glp_copy_prob(lp, other.lp, GLP_ON);
6.42 + glp_create_index(lp);
6.43 + rows = other.rows;
6.44 + cols = other.cols;
6.45 + }
6.46 +
6.47 + GlpkBase::~GlpkBase() {
6.48 + glp_delete_prob(lp);
6.49 + }
6.50 +
6.51 + int GlpkBase::_addCol() {
6.52 + int i = glp_add_cols(lp, 1);
6.53 + glp_set_col_bnds(lp, i, GLP_FR, 0.0, 0.0);
6.54 + return i;
6.55 + }
6.56 +
6.57 + int GlpkBase::_addRow() {
6.58 + int i = glp_add_rows(lp, 1);
6.59 + glp_set_row_bnds(lp, i, GLP_FR, 0.0, 0.0);
6.60 + return i;
6.61 + }
6.62 +
6.63 + void GlpkBase::_eraseCol(int i) {
6.64 + int ca[2];
6.65 + ca[1] = i;
6.66 + glp_del_cols(lp, 1, ca);
6.67 + }
6.68 +
6.69 + void GlpkBase::_eraseRow(int i) {
6.70 + int ra[2];
6.71 + ra[1] = i;
6.72 + glp_del_rows(lp, 1, ra);
6.73 + }
6.74 +
6.75 + void GlpkBase::_eraseColId(int i) {
6.76 + cols.eraseIndex(i);
6.77 + cols.shiftIndices(i);
6.78 + }
6.79 +
6.80 + void GlpkBase::_eraseRowId(int i) {
6.81 + rows.eraseIndex(i);
6.82 + rows.shiftIndices(i);
6.83 + }
6.84 +
6.85 + void GlpkBase::_getColName(int c, std::string& name) const {
6.86 + const char *str = glp_get_col_name(lp, c);
6.87 + if (str) name = str;
6.88 + else name.clear();
6.89 + }
6.90 +
6.91 + void GlpkBase::_setColName(int c, const std::string & name) {
6.92 + glp_set_col_name(lp, c, const_cast<char*>(name.c_str()));
6.93 +
6.94 + }
6.95 +
6.96 + int GlpkBase::_colByName(const std::string& name) const {
6.97 + int k = glp_find_col(lp, const_cast<char*>(name.c_str()));
6.98 + return k > 0 ? k : -1;
6.99 + }
6.100 +
6.101 + void GlpkBase::_getRowName(int r, std::string& name) const {
6.102 + const char *str = glp_get_row_name(lp, r);
6.103 + if (str) name = str;
6.104 + else name.clear();
6.105 + }
6.106 +
6.107 + void GlpkBase::_setRowName(int r, const std::string & name) {
6.108 + glp_set_row_name(lp, r, const_cast<char*>(name.c_str()));
6.109 +
6.110 + }
6.111 +
6.112 + int GlpkBase::_rowByName(const std::string& name) const {
6.113 + int k = glp_find_row(lp, const_cast<char*>(name.c_str()));
6.114 + return k > 0 ? k : -1;
6.115 + }
6.116 +
6.117 + void GlpkBase::_setRowCoeffs(int i, ExprIterator b, ExprIterator e) {
6.118 + std::vector<int> indexes;
6.119 + std::vector<Value> values;
6.120 +
6.121 + indexes.push_back(0);
6.122 + values.push_back(0);
6.123 +
6.124 + for(ExprIterator it = b; it != e; ++it) {
6.125 + indexes.push_back(it->first);
6.126 + values.push_back(it->second);
6.127 + }
6.128 +
6.129 + glp_set_mat_row(lp, i, values.size() - 1,
6.130 + &indexes.front(), &values.front());
6.131 + }
6.132 +
6.133 + void GlpkBase::_getRowCoeffs(int ix, InsertIterator b) const {
6.134 + int length = glp_get_mat_row(lp, ix, 0, 0);
6.135 +
6.136 + std::vector<int> indexes(length + 1);
6.137 + std::vector<Value> values(length + 1);
6.138 +
6.139 + glp_get_mat_row(lp, ix, &indexes.front(), &values.front());
6.140 +
6.141 + for (int i = 1; i <= length; ++i) {
6.142 + *b = std::make_pair(indexes[i], values[i]);
6.143 + ++b;
6.144 + }
6.145 + }
6.146 +
6.147 + void GlpkBase::_setColCoeffs(int ix, ExprIterator b,
6.148 + ExprIterator e) {
6.149 +
6.150 + std::vector<int> indexes;
6.151 + std::vector<Value> values;
6.152 +
6.153 + indexes.push_back(0);
6.154 + values.push_back(0);
6.155 +
6.156 + for(ExprIterator it = b; it != e; ++it) {
6.157 + indexes.push_back(it->first);
6.158 + values.push_back(it->second);
6.159 + }
6.160 +
6.161 + glp_set_mat_col(lp, ix, values.size() - 1,
6.162 + &indexes.front(), &values.front());
6.163 + }
6.164 +
6.165 + void GlpkBase::_getColCoeffs(int ix, InsertIterator b) const {
6.166 + int length = glp_get_mat_col(lp, ix, 0, 0);
6.167 +
6.168 + std::vector<int> indexes(length + 1);
6.169 + std::vector<Value> values(length + 1);
6.170 +
6.171 + glp_get_mat_col(lp, ix, &indexes.front(), &values.front());
6.172 +
6.173 + for (int i = 1; i <= length; ++i) {
6.174 + *b = std::make_pair(indexes[i], values[i]);
6.175 + ++b;
6.176 + }
6.177 + }
6.178 +
6.179 + void GlpkBase::_setCoeff(int ix, int jx, Value value) {
6.180 +
6.181 + if (glp_get_num_cols(lp) < glp_get_num_rows(lp)) {
6.182 +
6.183 + int length = glp_get_mat_row(lp, ix, 0, 0);
6.184 +
6.185 + std::vector<int> indexes(length + 2);
6.186 + std::vector<Value> values(length + 2);
6.187 +
6.188 + glp_get_mat_row(lp, ix, &indexes.front(), &values.front());
6.189 +
6.190 + //The following code does not suppose that the elements of the
6.191 + //array indexes are sorted
6.192 + bool found = false;
6.193 + for (int i = 1; i <= length; ++i) {
6.194 + if (indexes[i] == jx) {
6.195 + found = true;
6.196 + values[i] = value;
6.197 + break;
6.198 + }
6.199 + }
6.200 + if (!found) {
6.201 + ++length;
6.202 + indexes[length] = jx;
6.203 + values[length] = value;
6.204 + }
6.205 +
6.206 + glp_set_mat_row(lp, ix, length, &indexes.front(), &values.front());
6.207 +
6.208 + } else {
6.209 +
6.210 + int length = glp_get_mat_col(lp, jx, 0, 0);
6.211 +
6.212 + std::vector<int> indexes(length + 2);
6.213 + std::vector<Value> values(length + 2);
6.214 +
6.215 + glp_get_mat_col(lp, jx, &indexes.front(), &values.front());
6.216 +
6.217 + //The following code does not suppose that the elements of the
6.218 + //array indexes are sorted
6.219 + bool found = false;
6.220 + for (int i = 1; i <= length; ++i) {
6.221 + if (indexes[i] == ix) {
6.222 + found = true;
6.223 + values[i] = value;
6.224 + break;
6.225 + }
6.226 + }
6.227 + if (!found) {
6.228 + ++length;
6.229 + indexes[length] = ix;
6.230 + values[length] = value;
6.231 + }
6.232 +
6.233 + glp_set_mat_col(lp, jx, length, &indexes.front(), &values.front());
6.234 + }
6.235 +
6.236 + }
6.237 +
6.238 + GlpkBase::Value GlpkBase::_getCoeff(int ix, int jx) const {
6.239 +
6.240 + int length = glp_get_mat_row(lp, ix, 0, 0);
6.241 +
6.242 + std::vector<int> indexes(length + 1);
6.243 + std::vector<Value> values(length + 1);
6.244 +
6.245 + glp_get_mat_row(lp, ix, &indexes.front(), &values.front());
6.246 +
6.247 + for (int i = 1; i <= length; ++i) {
6.248 + if (indexes[i] == jx) {
6.249 + return values[i];
6.250 + }
6.251 + }
6.252 +
6.253 + return 0;
6.254 + }
6.255 +
6.256 + void GlpkBase::_setColLowerBound(int i, Value lo) {
6.257 + LEMON_ASSERT(lo != INF, "Invalid bound");
6.258 +
6.259 + int b = glp_get_col_type(lp, i);
6.260 + double up = glp_get_col_ub(lp, i);
6.261 + if (lo == -INF) {
6.262 + switch (b) {
6.263 + case GLP_FR:
6.264 + case GLP_LO:
6.265 + glp_set_col_bnds(lp, i, GLP_FR, lo, up);
6.266 + break;
6.267 + case GLP_UP:
6.268 + break;
6.269 + case GLP_DB:
6.270 + case GLP_FX:
6.271 + glp_set_col_bnds(lp, i, GLP_UP, lo, up);
6.272 + break;
6.273 + default:
6.274 + break;
6.275 + }
6.276 + } else {
6.277 + switch (b) {
6.278 + case GLP_FR:
6.279 + case GLP_LO:
6.280 + glp_set_col_bnds(lp, i, GLP_LO, lo, up);
6.281 + break;
6.282 + case GLP_UP:
6.283 + case GLP_DB:
6.284 + case GLP_FX:
6.285 + if (lo == up)
6.286 + glp_set_col_bnds(lp, i, GLP_FX, lo, up);
6.287 + else
6.288 + glp_set_col_bnds(lp, i, GLP_DB, lo, up);
6.289 + break;
6.290 + default:
6.291 + break;
6.292 + }
6.293 + }
6.294 + }
6.295 +
6.296 + GlpkBase::Value GlpkBase::_getColLowerBound(int i) const {
6.297 + int b = glp_get_col_type(lp, i);
6.298 + switch (b) {
6.299 + case GLP_LO:
6.300 + case GLP_DB:
6.301 + case GLP_FX:
6.302 + return glp_get_col_lb(lp, i);
6.303 + default:
6.304 + return -INF;
6.305 + }
6.306 + }
6.307 +
6.308 + void GlpkBase::_setColUpperBound(int i, Value up) {
6.309 + LEMON_ASSERT(up != -INF, "Invalid bound");
6.310 +
6.311 + int b = glp_get_col_type(lp, i);
6.312 + double lo = glp_get_col_lb(lp, i);
6.313 + if (up == INF) {
6.314 + switch (b) {
6.315 + case GLP_FR:
6.316 + case GLP_LO:
6.317 + break;
6.318 + case GLP_UP:
6.319 + glp_set_col_bnds(lp, i, GLP_FR, lo, up);
6.320 + break;
6.321 + case GLP_DB:
6.322 + case GLP_FX:
6.323 + glp_set_col_bnds(lp, i, GLP_LO, lo, up);
6.324 + break;
6.325 + default:
6.326 + break;
6.327 + }
6.328 + } else {
6.329 + switch (b) {
6.330 + case GLP_FR:
6.331 + glp_set_col_bnds(lp, i, GLP_UP, lo, up);
6.332 + break;
6.333 + case GLP_UP:
6.334 + glp_set_col_bnds(lp, i, GLP_UP, lo, up);
6.335 + break;
6.336 + case GLP_LO:
6.337 + case GLP_DB:
6.338 + case GLP_FX:
6.339 + if (lo == up)
6.340 + glp_set_col_bnds(lp, i, GLP_FX, lo, up);
6.341 + else
6.342 + glp_set_col_bnds(lp, i, GLP_DB, lo, up);
6.343 + break;
6.344 + default:
6.345 + break;
6.346 + }
6.347 + }
6.348 +
6.349 + }
6.350 +
6.351 + GlpkBase::Value GlpkBase::_getColUpperBound(int i) const {
6.352 + int b = glp_get_col_type(lp, i);
6.353 + switch (b) {
6.354 + case GLP_UP:
6.355 + case GLP_DB:
6.356 + case GLP_FX:
6.357 + return glp_get_col_ub(lp, i);
6.358 + default:
6.359 + return INF;
6.360 + }
6.361 + }
6.362 +
6.363 + void GlpkBase::_setRowLowerBound(int i, Value lo) {
6.364 + LEMON_ASSERT(lo != INF, "Invalid bound");
6.365 +
6.366 + int b = glp_get_row_type(lp, i);
6.367 + double up = glp_get_row_ub(lp, i);
6.368 + if (lo == -INF) {
6.369 + switch (b) {
6.370 + case GLP_FR:
6.371 + case GLP_LO:
6.372 + glp_set_row_bnds(lp, i, GLP_FR, lo, up);
6.373 + break;
6.374 + case GLP_UP:
6.375 + break;
6.376 + case GLP_DB:
6.377 + case GLP_FX:
6.378 + glp_set_row_bnds(lp, i, GLP_UP, lo, up);
6.379 + break;
6.380 + default:
6.381 + break;
6.382 + }
6.383 + } else {
6.384 + switch (b) {
6.385 + case GLP_FR:
6.386 + case GLP_LO:
6.387 + glp_set_row_bnds(lp, i, GLP_LO, lo, up);
6.388 + break;
6.389 + case GLP_UP:
6.390 + case GLP_DB:
6.391 + case GLP_FX:
6.392 + if (lo == up)
6.393 + glp_set_row_bnds(lp, i, GLP_FX, lo, up);
6.394 + else
6.395 + glp_set_row_bnds(lp, i, GLP_DB, lo, up);
6.396 + break;
6.397 + default:
6.398 + break;
6.399 + }
6.400 + }
6.401 +
6.402 + }
6.403 +
6.404 + GlpkBase::Value GlpkBase::_getRowLowerBound(int i) const {
6.405 + int b = glp_get_row_type(lp, i);
6.406 + switch (b) {
6.407 + case GLP_LO:
6.408 + case GLP_DB:
6.409 + case GLP_FX:
6.410 + return glp_get_row_lb(lp, i);
6.411 + default:
6.412 + return -INF;
6.413 + }
6.414 + }
6.415 +
6.416 + void GlpkBase::_setRowUpperBound(int i, Value up) {
6.417 + LEMON_ASSERT(up != -INF, "Invalid bound");
6.418 +
6.419 + int b = glp_get_row_type(lp, i);
6.420 + double lo = glp_get_row_lb(lp, i);
6.421 + if (up == INF) {
6.422 + switch (b) {
6.423 + case GLP_FR:
6.424 + case GLP_LO:
6.425 + break;
6.426 + case GLP_UP:
6.427 + glp_set_row_bnds(lp, i, GLP_FR, lo, up);
6.428 + break;
6.429 + case GLP_DB:
6.430 + case GLP_FX:
6.431 + glp_set_row_bnds(lp, i, GLP_LO, lo, up);
6.432 + break;
6.433 + default:
6.434 + break;
6.435 + }
6.436 + } else {
6.437 + switch (b) {
6.438 + case GLP_FR:
6.439 + glp_set_row_bnds(lp, i, GLP_UP, lo, up);
6.440 + break;
6.441 + case GLP_UP:
6.442 + glp_set_row_bnds(lp, i, GLP_UP, lo, up);
6.443 + break;
6.444 + case GLP_LO:
6.445 + case GLP_DB:
6.446 + case GLP_FX:
6.447 + if (lo == up)
6.448 + glp_set_row_bnds(lp, i, GLP_FX, lo, up);
6.449 + else
6.450 + glp_set_row_bnds(lp, i, GLP_DB, lo, up);
6.451 + break;
6.452 + default:
6.453 + break;
6.454 + }
6.455 + }
6.456 + }
6.457 +
6.458 + GlpkBase::Value GlpkBase::_getRowUpperBound(int i) const {
6.459 + int b = glp_get_row_type(lp, i);
6.460 + switch (b) {
6.461 + case GLP_UP:
6.462 + case GLP_DB:
6.463 + case GLP_FX:
6.464 + return glp_get_row_ub(lp, i);
6.465 + default:
6.466 + return INF;
6.467 + }
6.468 + }
6.469 +
6.470 + void GlpkBase::_setObjCoeffs(ExprIterator b, ExprIterator e) {
6.471 + for (int i = 1; i <= glp_get_num_cols(lp); ++i) {
6.472 + glp_set_obj_coef(lp, i, 0.0);
6.473 + }
6.474 + for (ExprIterator it = b; it != e; ++it) {
6.475 + glp_set_obj_coef(lp, it->first, it->second);
6.476 + }
6.477 + }
6.478 +
6.479 + void GlpkBase::_getObjCoeffs(InsertIterator b) const {
6.480 + for (int i = 1; i <= glp_get_num_cols(lp); ++i) {
6.481 + Value val = glp_get_obj_coef(lp, i);
6.482 + if (val != 0.0) {
6.483 + *b = std::make_pair(i, val);
6.484 + ++b;
6.485 + }
6.486 + }
6.487 + }
6.488 +
6.489 + void GlpkBase::_setObjCoeff(int i, Value obj_coef) {
6.490 + //i = 0 means the constant term (shift)
6.491 + glp_set_obj_coef(lp, i, obj_coef);
6.492 + }
6.493 +
6.494 + GlpkBase::Value GlpkBase::_getObjCoeff(int i) const {
6.495 + //i = 0 means the constant term (shift)
6.496 + return glp_get_obj_coef(lp, i);
6.497 + }
6.498 +
6.499 + void GlpkBase::_setSense(GlpkBase::Sense sense) {
6.500 + switch (sense) {
6.501 + case MIN:
6.502 + glp_set_obj_dir(lp, GLP_MIN);
6.503 + break;
6.504 + case MAX:
6.505 + glp_set_obj_dir(lp, GLP_MAX);
6.506 + break;
6.507 + }
6.508 + }
6.509 +
6.510 + GlpkBase::Sense GlpkBase::_getSense() const {
6.511 + switch(glp_get_obj_dir(lp)) {
6.512 + case GLP_MIN:
6.513 + return MIN;
6.514 + case GLP_MAX:
6.515 + return MAX;
6.516 + default:
6.517 + LEMON_ASSERT(false, "Wrong sense");
6.518 + return GlpkBase::Sense();
6.519 + }
6.520 + }
6.521 +
6.522 + void GlpkBase::_clear() {
6.523 + glp_erase_prob(lp);
6.524 + rows.clear();
6.525 + cols.clear();
6.526 + }
6.527 +
6.528 + // LpGlpk members
6.529 +
6.530 + LpGlpk::LpGlpk()
6.531 + : LpBase(), GlpkBase(), LpSolver() {
6.532 + messageLevel(MESSAGE_NO_OUTPUT);
6.533 + }
6.534 +
6.535 + LpGlpk::LpGlpk(const LpGlpk& other)
6.536 + : LpBase(other), GlpkBase(other), LpSolver(other) {
6.537 + messageLevel(MESSAGE_NO_OUTPUT);
6.538 + }
6.539 +
6.540 + LpGlpk* LpGlpk::_newSolver() const { return new LpGlpk; }
6.541 + LpGlpk* LpGlpk::_cloneSolver() const { return new LpGlpk(*this); }
6.542 +
6.543 + const char* LpGlpk::_solverName() const { return "LpGlpk"; }
6.544 +
6.545 + void LpGlpk::_clear_temporals() {
6.546 + _primal_ray.clear();
6.547 + _dual_ray.clear();
6.548 + }
6.549 +
6.550 + LpGlpk::SolveExitStatus LpGlpk::_solve() {
6.551 + return solvePrimal();
6.552 + }
6.553 +
6.554 + LpGlpk::SolveExitStatus LpGlpk::solvePrimal() {
6.555 + _clear_temporals();
6.556 +
6.557 + glp_smcp smcp;
6.558 + glp_init_smcp(&smcp);
6.559 +
6.560 + switch (_message_level) {
6.561 + case MESSAGE_NO_OUTPUT:
6.562 + smcp.msg_lev = GLP_MSG_OFF;
6.563 + break;
6.564 + case MESSAGE_ERROR_MESSAGE:
6.565 + smcp.msg_lev = GLP_MSG_ERR;
6.566 + break;
6.567 + case MESSAGE_NORMAL_OUTPUT:
6.568 + smcp.msg_lev = GLP_MSG_ON;
6.569 + break;
6.570 + case MESSAGE_FULL_OUTPUT:
6.571 + smcp.msg_lev = GLP_MSG_ALL;
6.572 + break;
6.573 + }
6.574 +
6.575 + if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
6.576 + return SOLVED;
6.577 + }
6.578 +
6.579 + LpGlpk::SolveExitStatus LpGlpk::solveDual() {
6.580 + _clear_temporals();
6.581 +
6.582 + glp_smcp smcp;
6.583 + glp_init_smcp(&smcp);
6.584 +
6.585 + switch (_message_level) {
6.586 + case MESSAGE_NO_OUTPUT:
6.587 + smcp.msg_lev = GLP_MSG_OFF;
6.588 + break;
6.589 + case MESSAGE_ERROR_MESSAGE:
6.590 + smcp.msg_lev = GLP_MSG_ERR;
6.591 + break;
6.592 + case MESSAGE_NORMAL_OUTPUT:
6.593 + smcp.msg_lev = GLP_MSG_ON;
6.594 + break;
6.595 + case MESSAGE_FULL_OUTPUT:
6.596 + smcp.msg_lev = GLP_MSG_ALL;
6.597 + break;
6.598 + }
6.599 + smcp.meth = GLP_DUAL;
6.600 +
6.601 + if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
6.602 + return SOLVED;
6.603 + }
6.604 +
6.605 + LpGlpk::Value LpGlpk::_getPrimal(int i) const {
6.606 + return glp_get_col_prim(lp, i);
6.607 + }
6.608 +
6.609 + LpGlpk::Value LpGlpk::_getDual(int i) const {
6.610 + return glp_get_row_dual(lp, i);
6.611 + }
6.612 +
6.613 + LpGlpk::Value LpGlpk::_getPrimalValue() const {
6.614 + return glp_get_obj_val(lp);
6.615 + }
6.616 +
6.617 + LpGlpk::VarStatus LpGlpk::_getColStatus(int i) const {
6.618 + switch (glp_get_col_stat(lp, i)) {
6.619 + case GLP_BS:
6.620 + return BASIC;
6.621 + case GLP_UP:
6.622 + return UPPER;
6.623 + case GLP_LO:
6.624 + return LOWER;
6.625 + case GLP_NF:
6.626 + return FREE;
6.627 + case GLP_NS:
6.628 + return FIXED;
6.629 + default:
6.630 + LEMON_ASSERT(false, "Wrong column status");
6.631 + return LpGlpk::VarStatus();
6.632 + }
6.633 + }
6.634 +
6.635 + LpGlpk::VarStatus LpGlpk::_getRowStatus(int i) const {
6.636 + switch (glp_get_row_stat(lp, i)) {
6.637 + case GLP_BS:
6.638 + return BASIC;
6.639 + case GLP_UP:
6.640 + return UPPER;
6.641 + case GLP_LO:
6.642 + return LOWER;
6.643 + case GLP_NF:
6.644 + return FREE;
6.645 + case GLP_NS:
6.646 + return FIXED;
6.647 + default:
6.648 + LEMON_ASSERT(false, "Wrong row status");
6.649 + return LpGlpk::VarStatus();
6.650 + }
6.651 + }
6.652 +
6.653 + LpGlpk::Value LpGlpk::_getPrimalRay(int i) const {
6.654 + if (_primal_ray.empty()) {
6.655 + int row_num = glp_get_num_rows(lp);
6.656 + int col_num = glp_get_num_cols(lp);
6.657 +
6.658 + _primal_ray.resize(col_num + 1, 0.0);
6.659 +
6.660 + int index = glp_get_unbnd_ray(lp);
6.661 + if (index != 0) {
6.662 + // The primal ray is found in primal simplex second phase
6.663 + LEMON_ASSERT((index <= row_num ? glp_get_row_stat(lp, index) :
6.664 + glp_get_col_stat(lp, index - row_num)) != GLP_BS,
6.665 + "Wrong primal ray");
6.666 +
6.667 + bool negate = glp_get_obj_dir(lp) == GLP_MAX;
6.668 +
6.669 + if (index > row_num) {
6.670 + _primal_ray[index - row_num] = 1.0;
6.671 + if (glp_get_col_dual(lp, index - row_num) > 0) {
6.672 + negate = !negate;
6.673 + }
6.674 + } else {
6.675 + if (glp_get_row_dual(lp, index) > 0) {
6.676 + negate = !negate;
6.677 + }
6.678 + }
6.679 +
6.680 + std::vector<int> ray_indexes(row_num + 1);
6.681 + std::vector<Value> ray_values(row_num + 1);
6.682 + int ray_length = glp_eval_tab_col(lp, index, &ray_indexes.front(),
6.683 + &ray_values.front());
6.684 +
6.685 + for (int i = 1; i <= ray_length; ++i) {
6.686 + if (ray_indexes[i] > row_num) {
6.687 + _primal_ray[ray_indexes[i] - row_num] = ray_values[i];
6.688 + }
6.689 + }
6.690 +
6.691 + if (negate) {
6.692 + for (int i = 1; i <= col_num; ++i) {
6.693 + _primal_ray[i] = - _primal_ray[i];
6.694 + }
6.695 + }
6.696 + } else {
6.697 + for (int i = 1; i <= col_num; ++i) {
6.698 + _primal_ray[i] = glp_get_col_prim(lp, i);
6.699 + }
6.700 + }
6.701 + }
6.702 + return _primal_ray[i];
6.703 + }
6.704 +
6.705 + LpGlpk::Value LpGlpk::_getDualRay(int i) const {
6.706 + if (_dual_ray.empty()) {
6.707 + int row_num = glp_get_num_rows(lp);
6.708 +
6.709 + _dual_ray.resize(row_num + 1, 0.0);
6.710 +
6.711 + int index = glp_get_unbnd_ray(lp);
6.712 + if (index != 0) {
6.713 + // The dual ray is found in dual simplex second phase
6.714 + LEMON_ASSERT((index <= row_num ? glp_get_row_stat(lp, index) :
6.715 + glp_get_col_stat(lp, index - row_num)) == GLP_BS,
6.716 +
6.717 + "Wrong dual ray");
6.718 +
6.719 + int idx;
6.720 + bool negate = false;
6.721 +
6.722 + if (index > row_num) {
6.723 + idx = glp_get_col_bind(lp, index - row_num);
6.724 + if (glp_get_col_prim(lp, index - row_num) >
6.725 + glp_get_col_ub(lp, index - row_num)) {
6.726 + negate = true;
6.727 + }
6.728 + } else {
6.729 + idx = glp_get_row_bind(lp, index);
6.730 + if (glp_get_row_prim(lp, index) > glp_get_row_ub(lp, index)) {
6.731 + negate = true;
6.732 + }
6.733 + }
6.734 +
6.735 + _dual_ray[idx] = negate ? - 1.0 : 1.0;
6.736 +
6.737 + glp_btran(lp, &_dual_ray.front());
6.738 + } else {
6.739 + double eps = 1e-7;
6.740 + // The dual ray is found in primal simplex first phase
6.741 + // We assume that the glpk minimizes the slack to get feasible solution
6.742 + for (int i = 1; i <= row_num; ++i) {
6.743 + int index = glp_get_bhead(lp, i);
6.744 + if (index <= row_num) {
6.745 + double res = glp_get_row_prim(lp, index);
6.746 + if (res > glp_get_row_ub(lp, index) + eps) {
6.747 + _dual_ray[i] = -1;
6.748 + } else if (res < glp_get_row_lb(lp, index) - eps) {
6.749 + _dual_ray[i] = 1;
6.750 + } else {
6.751 + _dual_ray[i] = 0;
6.752 + }
6.753 + _dual_ray[i] *= glp_get_rii(lp, index);
6.754 + } else {
6.755 + double res = glp_get_col_prim(lp, index - row_num);
6.756 + if (res > glp_get_col_ub(lp, index - row_num) + eps) {
6.757 + _dual_ray[i] = -1;
6.758 + } else if (res < glp_get_col_lb(lp, index - row_num) - eps) {
6.759 + _dual_ray[i] = 1;
6.760 + } else {
6.761 + _dual_ray[i] = 0;
6.762 + }
6.763 + _dual_ray[i] /= glp_get_sjj(lp, index - row_num);
6.764 + }
6.765 + }
6.766 +
6.767 + glp_btran(lp, &_dual_ray.front());
6.768 +
6.769 + for (int i = 1; i <= row_num; ++i) {
6.770 + _dual_ray[i] /= glp_get_rii(lp, i);
6.771 + }
6.772 + }
6.773 + }
6.774 + return _dual_ray[i];
6.775 + }
6.776 +
6.777 + LpGlpk::ProblemType LpGlpk::_getPrimalType() const {
6.778 + if (glp_get_status(lp) == GLP_OPT)
6.779 + return OPTIMAL;
6.780 + switch (glp_get_prim_stat(lp)) {
6.781 + case GLP_UNDEF:
6.782 + return UNDEFINED;
6.783 + case GLP_FEAS:
6.784 + case GLP_INFEAS:
6.785 + if (glp_get_dual_stat(lp) == GLP_NOFEAS) {
6.786 + return UNBOUNDED;
6.787 + } else {
6.788 + return UNDEFINED;
6.789 + }
6.790 + case GLP_NOFEAS:
6.791 + return INFEASIBLE;
6.792 + default:
6.793 + LEMON_ASSERT(false, "Wrong primal type");
6.794 + return LpGlpk::ProblemType();
6.795 + }
6.796 + }
6.797 +
6.798 + LpGlpk::ProblemType LpGlpk::_getDualType() const {
6.799 + if (glp_get_status(lp) == GLP_OPT)
6.800 + return OPTIMAL;
6.801 + switch (glp_get_dual_stat(lp)) {
6.802 + case GLP_UNDEF:
6.803 + return UNDEFINED;
6.804 + case GLP_FEAS:
6.805 + case GLP_INFEAS:
6.806 + if (glp_get_prim_stat(lp) == GLP_NOFEAS) {
6.807 + return UNBOUNDED;
6.808 + } else {
6.809 + return UNDEFINED;
6.810 + }
6.811 + case GLP_NOFEAS:
6.812 + return INFEASIBLE;
6.813 + default:
6.814 + LEMON_ASSERT(false, "Wrong primal type");
6.815 + return LpGlpk::ProblemType();
6.816 + }
6.817 + }
6.818 +
6.819 + void LpGlpk::presolver(bool b) {
6.820 + lpx_set_int_parm(lp, LPX_K_PRESOL, b ? 1 : 0);
6.821 + }
6.822 +
6.823 + void LpGlpk::messageLevel(MessageLevel m) {
6.824 + _message_level = m;
6.825 + }
6.826 +
6.827 + // MipGlpk members
6.828 +
6.829 + MipGlpk::MipGlpk()
6.830 + : LpBase(), GlpkBase(), MipSolver() {
6.831 + messageLevel(MESSAGE_NO_OUTPUT);
6.832 + }
6.833 +
6.834 + MipGlpk::MipGlpk(const MipGlpk& other)
6.835 + : LpBase(), GlpkBase(other), MipSolver() {
6.836 + messageLevel(MESSAGE_NO_OUTPUT);
6.837 + }
6.838 +
6.839 + void MipGlpk::_setColType(int i, MipGlpk::ColTypes col_type) {
6.840 + switch (col_type) {
6.841 + case INTEGER:
6.842 + glp_set_col_kind(lp, i, GLP_IV);
6.843 + break;
6.844 + case REAL:
6.845 + glp_set_col_kind(lp, i, GLP_CV);
6.846 + break;
6.847 + }
6.848 + }
6.849 +
6.850 + MipGlpk::ColTypes MipGlpk::_getColType(int i) const {
6.851 + switch (glp_get_col_kind(lp, i)) {
6.852 + case GLP_IV:
6.853 + case GLP_BV:
6.854 + return INTEGER;
6.855 + default:
6.856 + return REAL;
6.857 + }
6.858 +
6.859 + }
6.860 +
6.861 + MipGlpk::SolveExitStatus MipGlpk::_solve() {
6.862 + glp_smcp smcp;
6.863 + glp_init_smcp(&smcp);
6.864 +
6.865 + switch (_message_level) {
6.866 + case MESSAGE_NO_OUTPUT:
6.867 + smcp.msg_lev = GLP_MSG_OFF;
6.868 + break;
6.869 + case MESSAGE_ERROR_MESSAGE:
6.870 + smcp.msg_lev = GLP_MSG_ERR;
6.871 + break;
6.872 + case MESSAGE_NORMAL_OUTPUT:
6.873 + smcp.msg_lev = GLP_MSG_ON;
6.874 + break;
6.875 + case MESSAGE_FULL_OUTPUT:
6.876 + smcp.msg_lev = GLP_MSG_ALL;
6.877 + break;
6.878 + }
6.879 + smcp.meth = GLP_DUAL;
6.880 +
6.881 + if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
6.882 + if (glp_get_status(lp) != GLP_OPT) return SOLVED;
6.883 +
6.884 + glp_iocp iocp;
6.885 + glp_init_iocp(&iocp);
6.886 +
6.887 + switch (_message_level) {
6.888 + case MESSAGE_NO_OUTPUT:
6.889 + iocp.msg_lev = GLP_MSG_OFF;
6.890 + break;
6.891 + case MESSAGE_ERROR_MESSAGE:
6.892 + iocp.msg_lev = GLP_MSG_ERR;
6.893 + break;
6.894 + case MESSAGE_NORMAL_OUTPUT:
6.895 + iocp.msg_lev = GLP_MSG_ON;
6.896 + break;
6.897 + case MESSAGE_FULL_OUTPUT:
6.898 + iocp.msg_lev = GLP_MSG_ALL;
6.899 + break;
6.900 + }
6.901 +
6.902 + if (glp_intopt(lp, &iocp) != 0) return UNSOLVED;
6.903 + return SOLVED;
6.904 + }
6.905 +
6.906 +
6.907 + MipGlpk::ProblemType MipGlpk::_getType() const {
6.908 + switch (glp_get_status(lp)) {
6.909 + case GLP_OPT:
6.910 + switch (glp_mip_status(lp)) {
6.911 + case GLP_UNDEF:
6.912 + return UNDEFINED;
6.913 + case GLP_NOFEAS:
6.914 + return INFEASIBLE;
6.915 + case GLP_FEAS:
6.916 + return FEASIBLE;
6.917 + case GLP_OPT:
6.918 + return OPTIMAL;
6.919 + default:
6.920 + LEMON_ASSERT(false, "Wrong problem type.");
6.921 + return MipGlpk::ProblemType();
6.922 + }
6.923 + case GLP_NOFEAS:
6.924 + return INFEASIBLE;
6.925 + case GLP_INFEAS:
6.926 + case GLP_FEAS:
6.927 + if (glp_get_dual_stat(lp) == GLP_NOFEAS) {
6.928 + return UNBOUNDED;
6.929 + } else {
6.930 + return UNDEFINED;
6.931 + }
6.932 + default:
6.933 + LEMON_ASSERT(false, "Wrong problem type.");
6.934 + return MipGlpk::ProblemType();
6.935 + }
6.936 + }
6.937 +
6.938 + MipGlpk::Value MipGlpk::_getSol(int i) const {
6.939 + return glp_mip_col_val(lp, i);
6.940 + }
6.941 +
6.942 + MipGlpk::Value MipGlpk::_getSolValue() const {
6.943 + return glp_mip_obj_val(lp);
6.944 + }
6.945 +
6.946 + MipGlpk* MipGlpk::_newSolver() const { return new MipGlpk; }
6.947 + MipGlpk* MipGlpk::_cloneSolver() const {return new MipGlpk(*this); }
6.948 +
6.949 + const char* MipGlpk::_solverName() const { return "MipGlpk"; }
6.950 +
6.951 + void MipGlpk::messageLevel(MessageLevel m) {
6.952 + _message_level = m;
6.953 + }
6.954 +
6.955 +} //END OF NAMESPACE LEMON
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/lemon/glpk.h Mon Jan 12 12:26:01 2009 +0000
7.3 @@ -0,0 +1,259 @@
7.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
7.5 + *
7.6 + * This file is a part of LEMON, a generic C++ optimization library.
7.7 + *
7.8 + * Copyright (C) 2003-2008
7.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
7.11 + *
7.12 + * Permission to use, modify and distribute this software is granted
7.13 + * provided that this copyright notice appears in all copies. For
7.14 + * precise terms see the accompanying LICENSE file.
7.15 + *
7.16 + * This software is provided "AS IS" with no warranty of any kind,
7.17 + * express or implied, and with no claim as to its suitability for any
7.18 + * purpose.
7.19 + *
7.20 + */
7.21 +
7.22 +#ifndef LEMON_GLPK_H
7.23 +#define LEMON_GLPK_H
7.24 +
7.25 +///\file
7.26 +///\brief Header of the LEMON-GLPK lp solver interface.
7.27 +///\ingroup lp_group
7.28 +
7.29 +#include <lemon/lp_base.h>
7.30 +
7.31 +// forward declaration
7.32 +#ifndef _GLP_PROB
7.33 +#define _GLP_PROB
7.34 +typedef struct { double _prob; } glp_prob;
7.35 +/* LP/MIP problem object */
7.36 +#endif
7.37 +
7.38 +namespace lemon {
7.39 +
7.40 +
7.41 + /// \brief Base interface for the GLPK LP and MIP solver
7.42 + ///
7.43 + /// This class implements the common interface of the GLPK LP and MIP solver.
7.44 + /// \ingroup lp_group
7.45 + class GlpkBase : virtual public LpBase {
7.46 + protected:
7.47 +
7.48 + typedef glp_prob LPX;
7.49 + glp_prob* lp;
7.50 +
7.51 + GlpkBase();
7.52 + GlpkBase(const GlpkBase&);
7.53 + virtual ~GlpkBase();
7.54 +
7.55 + protected:
7.56 +
7.57 + virtual int _addCol();
7.58 + virtual int _addRow();
7.59 +
7.60 + virtual void _eraseCol(int i);
7.61 + virtual void _eraseRow(int i);
7.62 +
7.63 + virtual void _eraseColId(int i);
7.64 + virtual void _eraseRowId(int i);
7.65 +
7.66 + virtual void _getColName(int col, std::string& name) const;
7.67 + virtual void _setColName(int col, const std::string& name);
7.68 + virtual int _colByName(const std::string& name) const;
7.69 +
7.70 + virtual void _getRowName(int row, std::string& name) const;
7.71 + virtual void _setRowName(int row, const std::string& name);
7.72 + virtual int _rowByName(const std::string& name) const;
7.73 +
7.74 + virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
7.75 + virtual void _getRowCoeffs(int i, InsertIterator b) const;
7.76 +
7.77 + virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
7.78 + virtual void _getColCoeffs(int i, InsertIterator b) const;
7.79 +
7.80 + virtual void _setCoeff(int row, int col, Value value);
7.81 + virtual Value _getCoeff(int row, int col) const;
7.82 +
7.83 + virtual void _setColLowerBound(int i, Value value);
7.84 + virtual Value _getColLowerBound(int i) const;
7.85 +
7.86 + virtual void _setColUpperBound(int i, Value value);
7.87 + virtual Value _getColUpperBound(int i) const;
7.88 +
7.89 + virtual void _setRowLowerBound(int i, Value value);
7.90 + virtual Value _getRowLowerBound(int i) const;
7.91 +
7.92 + virtual void _setRowUpperBound(int i, Value value);
7.93 + virtual Value _getRowUpperBound(int i) const;
7.94 +
7.95 + virtual void _setObjCoeffs(ExprIterator b, ExprIterator e);
7.96 + virtual void _getObjCoeffs(InsertIterator b) const;
7.97 +
7.98 + virtual void _setObjCoeff(int i, Value obj_coef);
7.99 + virtual Value _getObjCoeff(int i) const;
7.100 +
7.101 + virtual void _setSense(Sense);
7.102 + virtual Sense _getSense() const;
7.103 +
7.104 + virtual void _clear();
7.105 +
7.106 + public:
7.107 +
7.108 + ///Pointer to the underlying GLPK data structure.
7.109 + LPX *lpx() {return lp;}
7.110 + ///Const pointer to the underlying GLPK data structure.
7.111 + const LPX *lpx() const {return lp;}
7.112 +
7.113 + ///Returns the constraint identifier understood by GLPK.
7.114 + int lpxRow(Row r) const { return rows(id(r)); }
7.115 +
7.116 + ///Returns the variable identifier understood by GLPK.
7.117 + int lpxCol(Col c) const { return cols(id(c)); }
7.118 +
7.119 + };
7.120 +
7.121 + /// \brief Interface for the GLPK LP solver
7.122 + ///
7.123 + /// This class implements an interface for the GLPK LP solver.
7.124 + ///\ingroup lp_group
7.125 + class LpGlpk : public GlpkBase, public LpSolver {
7.126 + public:
7.127 +
7.128 + ///\e
7.129 + LpGlpk();
7.130 + ///\e
7.131 + LpGlpk(const LpGlpk&);
7.132 +
7.133 + private:
7.134 +
7.135 + mutable std::vector<double> _primal_ray;
7.136 + mutable std::vector<double> _dual_ray;
7.137 +
7.138 + void _clear_temporals();
7.139 +
7.140 + protected:
7.141 +
7.142 + virtual LpGlpk* _cloneSolver() const;
7.143 + virtual LpGlpk* _newSolver() const;
7.144 +
7.145 + virtual const char* _solverName() const;
7.146 +
7.147 + virtual SolveExitStatus _solve();
7.148 + virtual Value _getPrimal(int i) const;
7.149 + virtual Value _getDual(int i) const;
7.150 +
7.151 + virtual Value _getPrimalValue() const;
7.152 +
7.153 + virtual VarStatus _getColStatus(int i) const;
7.154 + virtual VarStatus _getRowStatus(int i) const;
7.155 +
7.156 + virtual Value _getPrimalRay(int i) const;
7.157 + virtual Value _getDualRay(int i) const;
7.158 +
7.159 + ///\todo It should be clarified
7.160 + ///
7.161 + virtual ProblemType _getPrimalType() const;
7.162 + virtual ProblemType _getDualType() const;
7.163 +
7.164 + public:
7.165 +
7.166 + ///Solve with primal simplex
7.167 + SolveExitStatus solvePrimal();
7.168 +
7.169 + ///Solve with dual simplex
7.170 + SolveExitStatus solveDual();
7.171 +
7.172 + ///Turns on or off the presolver
7.173 +
7.174 + ///Turns on (\c b is \c true) or off (\c b is \c false) the presolver
7.175 + ///
7.176 + ///The presolver is off by default.
7.177 + void presolver(bool b);
7.178 +
7.179 + ///Enum for \c messageLevel() parameter
7.180 + enum MessageLevel {
7.181 + /// no output (default value)
7.182 + MESSAGE_NO_OUTPUT = 0,
7.183 + /// error messages only
7.184 + MESSAGE_ERROR_MESSAGE = 1,
7.185 + /// normal output
7.186 + MESSAGE_NORMAL_OUTPUT = 2,
7.187 + /// full output (includes informational messages)
7.188 + MESSAGE_FULL_OUTPUT = 3
7.189 + };
7.190 +
7.191 + private:
7.192 +
7.193 + MessageLevel _message_level;
7.194 +
7.195 + public:
7.196 +
7.197 + ///Set the verbosity of the messages
7.198 +
7.199 + ///Set the verbosity of the messages
7.200 + ///
7.201 + ///\param m is the level of the messages output by the solver routines.
7.202 + void messageLevel(MessageLevel m);
7.203 + };
7.204 +
7.205 + /// \brief Interface for the GLPK MIP solver
7.206 + ///
7.207 + /// This class implements an interface for the GLPK MIP solver.
7.208 + ///\ingroup lp_group
7.209 + class MipGlpk : public GlpkBase, public MipSolver {
7.210 + public:
7.211 +
7.212 + ///\e
7.213 + MipGlpk();
7.214 + ///\e
7.215 + MipGlpk(const MipGlpk&);
7.216 +
7.217 + protected:
7.218 +
7.219 + virtual MipGlpk* _cloneSolver() const;
7.220 + virtual MipGlpk* _newSolver() const;
7.221 +
7.222 + virtual const char* _solverName() const;
7.223 +
7.224 + virtual ColTypes _getColType(int col) const;
7.225 + virtual void _setColType(int col, ColTypes col_type);
7.226 +
7.227 + virtual SolveExitStatus _solve();
7.228 + virtual ProblemType _getType() const;
7.229 + virtual Value _getSol(int i) const;
7.230 + virtual Value _getSolValue() const;
7.231 +
7.232 + ///Enum for \c messageLevel() parameter
7.233 + enum MessageLevel {
7.234 + /// no output (default value)
7.235 + MESSAGE_NO_OUTPUT = 0,
7.236 + /// error messages only
7.237 + MESSAGE_ERROR_MESSAGE = 1,
7.238 + /// normal output
7.239 + MESSAGE_NORMAL_OUTPUT = 2,
7.240 + /// full output (includes informational messages)
7.241 + MESSAGE_FULL_OUTPUT = 3
7.242 + };
7.243 +
7.244 + private:
7.245 +
7.246 + MessageLevel _message_level;
7.247 +
7.248 + public:
7.249 +
7.250 + ///Set the verbosity of the messages
7.251 +
7.252 + ///Set the verbosity of the messages
7.253 + ///
7.254 + ///\param m is the level of the messages output by the solver routines.
7.255 + void messageLevel(MessageLevel m);
7.256 + };
7.257 +
7.258 +
7.259 +} //END OF NAMESPACE LEMON
7.260 +
7.261 +#endif //LEMON_GLPK_H
7.262 +
8.1 --- a/lemon/lp.h Mon Jan 12 12:25:55 2009 +0000
8.2 +++ b/lemon/lp.h Mon Jan 12 12:26:01 2009 +0000
8.3 @@ -23,13 +23,13 @@
8.4
8.5
8.6 #ifdef HAVE_GLPK
8.7 -#include <lemon/lp_glpk.h>
8.8 +#include <lemon/glpk.h>
8.9 #elif HAVE_CPLEX
8.10 -#include <lemon/lp_cplex.h>
8.11 +#include <lemon/cplex.h>
8.12 #elif HAVE_SOPLEX
8.13 -#include <lemon/lp_soplex.h>
8.14 +#include <lemon/soplex.h>
8.15 #elif HAVE_CLP
8.16 -#include <lemon/lp_clp.h>
8.17 +#include <lemon/clp.h>
8.18 #endif
8.19
8.20 ///\file
8.21 @@ -43,8 +43,8 @@
8.22 ///The default LP solver identifier.
8.23 ///\ingroup lp_group
8.24 ///
8.25 - ///Currently, the possible values are \c LP_GLPK, \c LP_CPLEX, \c
8.26 - ///LP_SOPLEX or \c LP_CLP
8.27 + ///Currently, the possible values are \c GLPK, \c CPLEX,
8.28 + ///\c SOPLEX or \c CLP
8.29 #define LEMON_DEFAULT_LP SOLVER
8.30 ///The default LP solver
8.31
8.32 @@ -59,7 +59,7 @@
8.33 ///The default MIP solver identifier.
8.34 ///\ingroup lp_group
8.35 ///
8.36 - ///Currently, the possible values are \c MIP_GLPK or \c MIP_CPLEX
8.37 + ///Currently, the possible values are \c GLPK or \c CPLEX
8.38 #define LEMON_DEFAULT_MIP SOLVER
8.39 ///The default MIP solver.
8.40
8.41 @@ -70,20 +70,20 @@
8.42 typedef MipGlpk Mip;
8.43 #else
8.44 #ifdef HAVE_GLPK
8.45 -# define LEMON_DEFAULT_LP LP_GLPK
8.46 +# define LEMON_DEFAULT_LP GLPK
8.47 typedef LpGlpk Lp;
8.48 -# define LEMON_DEFAULT_MIP MIP_GLPK
8.49 +# define LEMON_DEFAULT_MIP GLPK
8.50 typedef MipGlpk Mip;
8.51 #elif HAVE_CPLEX
8.52 -# define LEMON_DEFAULT_LP LP_CPLEX
8.53 +# define LEMON_DEFAULT_LP CPLEX
8.54 typedef LpCplex Lp;
8.55 -# define LEMON_DEFAULT_MIP MIP_CPLEX
8.56 +# define LEMON_DEFAULT_MIP CPLEX
8.57 typedef MipCplex Mip;
8.58 #elif HAVE_SOPLEX
8.59 -# define DEFAULT_LP LP_SOPLEX
8.60 +# define DEFAULT_LP SOPLEX
8.61 typedef LpSoplex Lp;
8.62 #elif HAVE_CLP
8.63 -# define DEFAULT_LP LP_CLP
8.64 +# define DEFAULT_LP CLP
8.65 typedef LpClp Lp;
8.66 #endif
8.67 #endif
9.1 --- a/lemon/lp_clp.cc Mon Jan 12 12:25:55 2009 +0000
9.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
9.3 @@ -1,437 +0,0 @@
9.4 -/* -*- mode: C++; indent-tabs-mode: nil; -*-
9.5 - *
9.6 - * This file is a part of LEMON, a generic C++ optimization library.
9.7 - *
9.8 - * Copyright (C) 2003-2008
9.9 - * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
9.10 - * (Egervary Research Group on Combinatorial Optimization, EGRES).
9.11 - *
9.12 - * Permission to use, modify and distribute this software is granted
9.13 - * provided that this copyright notice appears in all copies. For
9.14 - * precise terms see the accompanying LICENSE file.
9.15 - *
9.16 - * This software is provided "AS IS" with no warranty of any kind,
9.17 - * express or implied, and with no claim as to its suitability for any
9.18 - * purpose.
9.19 - *
9.20 - */
9.21 -
9.22 -#include <lemon/lp_clp.h>
9.23 -#include <coin/ClpSimplex.hpp>
9.24 -
9.25 -namespace lemon {
9.26 -
9.27 - LpClp::LpClp() {
9.28 - _prob = new ClpSimplex();
9.29 - _init_temporals();
9.30 - messageLevel(MESSAGE_NO_OUTPUT);
9.31 - }
9.32 -
9.33 - LpClp::LpClp(const LpClp& other) {
9.34 - _prob = new ClpSimplex(*other._prob);
9.35 - rows = other.rows;
9.36 - cols = other.cols;
9.37 - _init_temporals();
9.38 - messageLevel(MESSAGE_NO_OUTPUT);
9.39 - }
9.40 -
9.41 - LpClp::~LpClp() {
9.42 - delete _prob;
9.43 - _clear_temporals();
9.44 - }
9.45 -
9.46 - void LpClp::_init_temporals() {
9.47 - _primal_ray = 0;
9.48 - _dual_ray = 0;
9.49 - }
9.50 -
9.51 - void LpClp::_clear_temporals() {
9.52 - if (_primal_ray) {
9.53 - delete[] _primal_ray;
9.54 - _primal_ray = 0;
9.55 - }
9.56 - if (_dual_ray) {
9.57 - delete[] _dual_ray;
9.58 - _dual_ray = 0;
9.59 - }
9.60 - }
9.61 -
9.62 - LpClp* LpClp::_newSolver() const {
9.63 - LpClp* newlp = new LpClp;
9.64 - return newlp;
9.65 - }
9.66 -
9.67 - LpClp* LpClp::_cloneSolver() const {
9.68 - LpClp* copylp = new LpClp(*this);
9.69 - return copylp;
9.70 - }
9.71 -
9.72 - const char* LpClp::_solverName() const { return "LpClp"; }
9.73 -
9.74 - int LpClp::_addCol() {
9.75 - _prob->addColumn(0, 0, 0, -COIN_DBL_MAX, COIN_DBL_MAX, 0.0);
9.76 - return _prob->numberColumns() - 1;
9.77 - }
9.78 -
9.79 - int LpClp::_addRow() {
9.80 - _prob->addRow(0, 0, 0, -COIN_DBL_MAX, COIN_DBL_MAX);
9.81 - return _prob->numberRows() - 1;
9.82 - }
9.83 -
9.84 -
9.85 - void LpClp::_eraseCol(int c) {
9.86 - _col_names_ref.erase(_prob->getColumnName(c));
9.87 - _prob->deleteColumns(1, &c);
9.88 - }
9.89 -
9.90 - void LpClp::_eraseRow(int r) {
9.91 - _row_names_ref.erase(_prob->getRowName(r));
9.92 - _prob->deleteRows(1, &r);
9.93 - }
9.94 -
9.95 - void LpClp::_eraseColId(int i) {
9.96 - cols.eraseIndex(i);
9.97 - cols.shiftIndices(i);
9.98 - }
9.99 -
9.100 - void LpClp::_eraseRowId(int i) {
9.101 - rows.eraseIndex(i);
9.102 - rows.shiftIndices(i);
9.103 - }
9.104 -
9.105 - void LpClp::_getColName(int c, std::string& name) const {
9.106 - name = _prob->getColumnName(c);
9.107 - }
9.108 -
9.109 - void LpClp::_setColName(int c, const std::string& name) {
9.110 - _prob->setColumnName(c, const_cast<std::string&>(name));
9.111 - _col_names_ref[name] = c;
9.112 - }
9.113 -
9.114 - int LpClp::_colByName(const std::string& name) const {
9.115 - std::map<std::string, int>::const_iterator it = _col_names_ref.find(name);
9.116 - return it != _col_names_ref.end() ? it->second : -1;
9.117 - }
9.118 -
9.119 - void LpClp::_getRowName(int r, std::string& name) const {
9.120 - name = _prob->getRowName(r);
9.121 - }
9.122 -
9.123 - void LpClp::_setRowName(int r, const std::string& name) {
9.124 - _prob->setRowName(r, const_cast<std::string&>(name));
9.125 - _row_names_ref[name] = r;
9.126 - }
9.127 -
9.128 - int LpClp::_rowByName(const std::string& name) const {
9.129 - std::map<std::string, int>::const_iterator it = _row_names_ref.find(name);
9.130 - return it != _row_names_ref.end() ? it->second : -1;
9.131 - }
9.132 -
9.133 -
9.134 - void LpClp::_setRowCoeffs(int ix, ExprIterator b, ExprIterator e) {
9.135 - std::map<int, Value> coeffs;
9.136 -
9.137 - int n = _prob->clpMatrix()->getNumCols();
9.138 -
9.139 - const int* indices = _prob->clpMatrix()->getIndices();
9.140 - const double* elements = _prob->clpMatrix()->getElements();
9.141 -
9.142 - for (int i = 0; i < n; ++i) {
9.143 - CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[i];
9.144 - CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[i];
9.145 -
9.146 - const int* it = std::lower_bound(indices + begin, indices + end, ix);
9.147 - if (it != indices + end && *it == ix && elements[it - indices] != 0.0) {
9.148 - coeffs[i] = 0.0;
9.149 - }
9.150 - }
9.151 -
9.152 - for (ExprIterator it = b; it != e; ++it) {
9.153 - coeffs[it->first] = it->second;
9.154 - }
9.155 -
9.156 - for (std::map<int, Value>::iterator it = coeffs.begin();
9.157 - it != coeffs.end(); ++it) {
9.158 - _prob->modifyCoefficient(ix, it->first, it->second);
9.159 - }
9.160 - }
9.161 -
9.162 - void LpClp::_getRowCoeffs(int ix, InsertIterator b) const {
9.163 - int n = _prob->clpMatrix()->getNumCols();
9.164 -
9.165 - const int* indices = _prob->clpMatrix()->getIndices();
9.166 - const double* elements = _prob->clpMatrix()->getElements();
9.167 -
9.168 - for (int i = 0; i < n; ++i) {
9.169 - CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[i];
9.170 - CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[i];
9.171 -
9.172 - const int* it = std::lower_bound(indices + begin, indices + end, ix);
9.173 - if (it != indices + end && *it == ix) {
9.174 - *b = std::make_pair(i, elements[it - indices]);
9.175 - }
9.176 - }
9.177 - }
9.178 -
9.179 - void LpClp::_setColCoeffs(int ix, ExprIterator b, ExprIterator e) {
9.180 - std::map<int, Value> coeffs;
9.181 -
9.182 - CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[ix];
9.183 - CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[ix];
9.184 -
9.185 - const int* indices = _prob->clpMatrix()->getIndices();
9.186 - const double* elements = _prob->clpMatrix()->getElements();
9.187 -
9.188 - for (CoinBigIndex i = begin; i != end; ++i) {
9.189 - if (elements[i] != 0.0) {
9.190 - coeffs[indices[i]] = 0.0;
9.191 - }
9.192 - }
9.193 - for (ExprIterator it = b; it != e; ++it) {
9.194 - coeffs[it->first] = it->second;
9.195 - }
9.196 - for (std::map<int, Value>::iterator it = coeffs.begin();
9.197 - it != coeffs.end(); ++it) {
9.198 - _prob->modifyCoefficient(it->first, ix, it->second);
9.199 - }
9.200 - }
9.201 -
9.202 - void LpClp::_getColCoeffs(int ix, InsertIterator b) const {
9.203 - CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[ix];
9.204 - CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[ix];
9.205 -
9.206 - const int* indices = _prob->clpMatrix()->getIndices();
9.207 - const double* elements = _prob->clpMatrix()->getElements();
9.208 -
9.209 - for (CoinBigIndex i = begin; i != end; ++i) {
9.210 - *b = std::make_pair(indices[i], elements[i]);
9.211 - ++b;
9.212 - }
9.213 - }
9.214 -
9.215 - void LpClp::_setCoeff(int ix, int jx, Value value) {
9.216 - _prob->modifyCoefficient(ix, jx, value);
9.217 - }
9.218 -
9.219 - LpClp::Value LpClp::_getCoeff(int ix, int jx) const {
9.220 - CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[ix];
9.221 - CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[ix];
9.222 -
9.223 - const int* indices = _prob->clpMatrix()->getIndices();
9.224 - const double* elements = _prob->clpMatrix()->getElements();
9.225 -
9.226 - const int* it = std::lower_bound(indices + begin, indices + end, jx);
9.227 - if (it != indices + end && *it == jx) {
9.228 - return elements[it - indices];
9.229 - } else {
9.230 - return 0.0;
9.231 - }
9.232 - }
9.233 -
9.234 - void LpClp::_setColLowerBound(int i, Value lo) {
9.235 - _prob->setColumnLower(i, lo == - INF ? - COIN_DBL_MAX : lo);
9.236 - }
9.237 -
9.238 - LpClp::Value LpClp::_getColLowerBound(int i) const {
9.239 - double val = _prob->getColLower()[i];
9.240 - return val == - COIN_DBL_MAX ? - INF : val;
9.241 - }
9.242 -
9.243 - void LpClp::_setColUpperBound(int i, Value up) {
9.244 - _prob->setColumnUpper(i, up == INF ? COIN_DBL_MAX : up);
9.245 - }
9.246 -
9.247 - LpClp::Value LpClp::_getColUpperBound(int i) const {
9.248 - double val = _prob->getColUpper()[i];
9.249 - return val == COIN_DBL_MAX ? INF : val;
9.250 - }
9.251 -
9.252 - void LpClp::_setRowLowerBound(int i, Value lo) {
9.253 - _prob->setRowLower(i, lo == - INF ? - COIN_DBL_MAX : lo);
9.254 - }
9.255 -
9.256 - LpClp::Value LpClp::_getRowLowerBound(int i) const {
9.257 - double val = _prob->getRowLower()[i];
9.258 - return val == - COIN_DBL_MAX ? - INF : val;
9.259 - }
9.260 -
9.261 - void LpClp::_setRowUpperBound(int i, Value up) {
9.262 - _prob->setRowUpper(i, up == INF ? COIN_DBL_MAX : up);
9.263 - }
9.264 -
9.265 - LpClp::Value LpClp::_getRowUpperBound(int i) const {
9.266 - double val = _prob->getRowUpper()[i];
9.267 - return val == COIN_DBL_MAX ? INF : val;
9.268 - }
9.269 -
9.270 - void LpClp::_setObjCoeffs(ExprIterator b, ExprIterator e) {
9.271 - int num = _prob->clpMatrix()->getNumCols();
9.272 - for (int i = 0; i < num; ++i) {
9.273 - _prob->setObjectiveCoefficient(i, 0.0);
9.274 - }
9.275 - for (ExprIterator it = b; it != e; ++it) {
9.276 - _prob->setObjectiveCoefficient(it->first, it->second);
9.277 - }
9.278 - }
9.279 -
9.280 - void LpClp::_getObjCoeffs(InsertIterator b) const {
9.281 - int num = _prob->clpMatrix()->getNumCols();
9.282 - for (int i = 0; i < num; ++i) {
9.283 - Value coef = _prob->getObjCoefficients()[i];
9.284 - if (coef != 0.0) {
9.285 - *b = std::make_pair(i, coef);
9.286 - ++b;
9.287 - }
9.288 - }
9.289 - }
9.290 -
9.291 - void LpClp::_setObjCoeff(int i, Value obj_coef) {
9.292 - _prob->setObjectiveCoefficient(i, obj_coef);
9.293 - }
9.294 -
9.295 - LpClp::Value LpClp::_getObjCoeff(int i) const {
9.296 - return _prob->getObjCoefficients()[i];
9.297 - }
9.298 -
9.299 - LpClp::SolveExitStatus LpClp::_solve() {
9.300 - return _prob->primal() >= 0 ? SOLVED : UNSOLVED;
9.301 - }
9.302 -
9.303 - LpClp::SolveExitStatus LpClp::solvePrimal() {
9.304 - return _prob->primal() >= 0 ? SOLVED : UNSOLVED;
9.305 - }
9.306 -
9.307 - LpClp::SolveExitStatus LpClp::solveDual() {
9.308 - return _prob->dual() >= 0 ? SOLVED : UNSOLVED;
9.309 - }
9.310 -
9.311 - LpClp::SolveExitStatus LpClp::solveBarrier() {
9.312 - return _prob->barrier() >= 0 ? SOLVED : UNSOLVED;
9.313 - }
9.314 -
9.315 - LpClp::Value LpClp::_getPrimal(int i) const {
9.316 - return _prob->primalColumnSolution()[i];
9.317 - }
9.318 - LpClp::Value LpClp::_getPrimalValue() const {
9.319 - return _prob->objectiveValue();
9.320 - }
9.321 -
9.322 - LpClp::Value LpClp::_getDual(int i) const {
9.323 - return _prob->dualRowSolution()[i];
9.324 - }
9.325 -
9.326 - LpClp::Value LpClp::_getPrimalRay(int i) const {
9.327 - if (!_primal_ray) {
9.328 - _primal_ray = _prob->unboundedRay();
9.329 - LEMON_ASSERT(_primal_ray != 0, "Primal ray is not provided");
9.330 - }
9.331 - return _primal_ray[i];
9.332 - }
9.333 -
9.334 - LpClp::Value LpClp::_getDualRay(int i) const {
9.335 - if (!_dual_ray) {
9.336 - _dual_ray = _prob->infeasibilityRay();
9.337 - LEMON_ASSERT(_dual_ray != 0, "Dual ray is not provided");
9.338 - }
9.339 - return _dual_ray[i];
9.340 - }
9.341 -
9.342 - LpClp::VarStatus LpClp::_getColStatus(int i) const {
9.343 - switch (_prob->getColumnStatus(i)) {
9.344 - case ClpSimplex::basic:
9.345 - return BASIC;
9.346 - case ClpSimplex::isFree:
9.347 - return FREE;
9.348 - case ClpSimplex::atUpperBound:
9.349 - return UPPER;
9.350 - case ClpSimplex::atLowerBound:
9.351 - return LOWER;
9.352 - case ClpSimplex::isFixed:
9.353 - return FIXED;
9.354 - case ClpSimplex::superBasic:
9.355 - return FREE;
9.356 - default:
9.357 - LEMON_ASSERT(false, "Wrong column status");
9.358 - return VarStatus();
9.359 - }
9.360 - }
9.361 -
9.362 - LpClp::VarStatus LpClp::_getRowStatus(int i) const {
9.363 - switch (_prob->getColumnStatus(i)) {
9.364 - case ClpSimplex::basic:
9.365 - return BASIC;
9.366 - case ClpSimplex::isFree:
9.367 - return FREE;
9.368 - case ClpSimplex::atUpperBound:
9.369 - return UPPER;
9.370 - case ClpSimplex::atLowerBound:
9.371 - return LOWER;
9.372 - case ClpSimplex::isFixed:
9.373 - return FIXED;
9.374 - case ClpSimplex::superBasic:
9.375 - return FREE;
9.376 - default:
9.377 - LEMON_ASSERT(false, "Wrong row status");
9.378 - return VarStatus();
9.379 - }
9.380 - }
9.381 -
9.382 -
9.383 - LpClp::ProblemType LpClp::_getPrimalType() const {
9.384 - if (_prob->isProvenOptimal()) {
9.385 - return OPTIMAL;
9.386 - } else if (_prob->isProvenPrimalInfeasible()) {
9.387 - return INFEASIBLE;
9.388 - } else if (_prob->isProvenDualInfeasible()) {
9.389 - return UNBOUNDED;
9.390 - } else {
9.391 - return UNDEFINED;
9.392 - }
9.393 - }
9.394 -
9.395 - LpClp::ProblemType LpClp::_getDualType() const {
9.396 - if (_prob->isProvenOptimal()) {
9.397 - return OPTIMAL;
9.398 - } else if (_prob->isProvenDualInfeasible()) {
9.399 - return INFEASIBLE;
9.400 - } else if (_prob->isProvenPrimalInfeasible()) {
9.401 - return INFEASIBLE;
9.402 - } else {
9.403 - return UNDEFINED;
9.404 - }
9.405 - }
9.406 -
9.407 - void LpClp::_setSense(LpClp::Sense sense) {
9.408 - switch (sense) {
9.409 - case MIN:
9.410 - _prob->setOptimizationDirection(1);
9.411 - break;
9.412 - case MAX:
9.413 - _prob->setOptimizationDirection(-1);
9.414 - break;
9.415 - }
9.416 - }
9.417 -
9.418 - LpClp::Sense LpClp::_getSense() const {
9.419 - double dir = _prob->optimizationDirection();
9.420 - if (dir > 0.0) {
9.421 - return MIN;
9.422 - } else {
9.423 - return MAX;
9.424 - }
9.425 - }
9.426 -
9.427 - void LpClp::_clear() {
9.428 - delete _prob;
9.429 - _prob = new ClpSimplex();
9.430 - rows.clear();
9.431 - cols.clear();
9.432 - _col_names_ref.clear();
9.433 - _clear_temporals();
9.434 - }
9.435 -
9.436 - void LpClp::messageLevel(MessageLevel m) {
9.437 - _prob->setLogLevel(static_cast<int>(m));
9.438 - }
9.439 -
9.440 -} //END OF NAMESPACE LEMON
10.1 --- a/lemon/lp_clp.h Mon Jan 12 12:25:55 2009 +0000
10.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
10.3 @@ -1,179 +0,0 @@
10.4 -/* -*- mode: C++; indent-tabs-mode: nil; -*-
10.5 - *
10.6 - * This file is a part of LEMON, a generic C++ optimization library.
10.7 - *
10.8 - * Copyright (C) 2003-2008
10.9 - * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
10.10 - * (Egervary Research Group on Combinatorial Optimization, EGRES).
10.11 - *
10.12 - * Permission to use, modify and distribute this software is granted
10.13 - * provided that this copyright notice appears in all copies. For
10.14 - * precise terms see the accompanying LICENSE file.
10.15 - *
10.16 - * This software is provided "AS IS" with no warranty of any kind,
10.17 - * express or implied, and with no claim as to its suitability for any
10.18 - * purpose.
10.19 - *
10.20 - */
10.21 -
10.22 -#ifndef LEMON_LP_CLP_H
10.23 -#define LEMON_LP_CLP_H
10.24 -
10.25 -///\file
10.26 -///\brief Header of the LEMON-CLP lp solver interface.
10.27 -
10.28 -#include <vector>
10.29 -#include <string>
10.30 -
10.31 -#include <lemon/lp_base.h>
10.32 -
10.33 -class ClpSimplex;
10.34 -
10.35 -namespace lemon {
10.36 -
10.37 - /// \ingroup lp_group
10.38 - ///
10.39 - /// \brief Interface for the CLP solver
10.40 - ///
10.41 - /// This class implements an interface for the Clp LP solver. The
10.42 - /// Clp library is an object oriented lp solver library developed at
10.43 - /// the IBM. The CLP is part of the COIN-OR package and it can be
10.44 - /// used with Common Public License.
10.45 - class LpClp : public LpSolver {
10.46 - protected:
10.47 -
10.48 - ClpSimplex* _prob;
10.49 -
10.50 - std::map<std::string, int> _col_names_ref;
10.51 - std::map<std::string, int> _row_names_ref;
10.52 -
10.53 - public:
10.54 -
10.55 - /// \e
10.56 - LpClp();
10.57 - /// \e
10.58 - LpClp(const LpClp&);
10.59 - /// \e
10.60 - ~LpClp();
10.61 -
10.62 - protected:
10.63 -
10.64 - mutable double* _primal_ray;
10.65 - mutable double* _dual_ray;
10.66 -
10.67 - void _init_temporals();
10.68 - void _clear_temporals();
10.69 -
10.70 - protected:
10.71 -
10.72 - virtual LpClp* _newSolver() const;
10.73 - virtual LpClp* _cloneSolver() const;
10.74 -
10.75 - virtual const char* _solverName() const;
10.76 -
10.77 - virtual int _addCol();
10.78 - virtual int _addRow();
10.79 -
10.80 - virtual void _eraseCol(int i);
10.81 - virtual void _eraseRow(int i);
10.82 -
10.83 - virtual void _eraseColId(int i);
10.84 - virtual void _eraseRowId(int i);
10.85 -
10.86 - virtual void _getColName(int col, std::string& name) const;
10.87 - virtual void _setColName(int col, const std::string& name);
10.88 - virtual int _colByName(const std::string& name) const;
10.89 -
10.90 - virtual void _getRowName(int row, std::string& name) const;
10.91 - virtual void _setRowName(int row, const std::string& name);
10.92 - virtual int _rowByName(const std::string& name) const;
10.93 -
10.94 - virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
10.95 - virtual void _getRowCoeffs(int i, InsertIterator b) const;
10.96 -
10.97 - virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
10.98 - virtual void _getColCoeffs(int i, InsertIterator b) const;
10.99 -
10.100 - virtual void _setCoeff(int row, int col, Value value);
10.101 - virtual Value _getCoeff(int row, int col) const;
10.102 -
10.103 - virtual void _setColLowerBound(int i, Value value);
10.104 - virtual Value _getColLowerBound(int i) const;
10.105 - virtual void _setColUpperBound(int i, Value value);
10.106 - virtual Value _getColUpperBound(int i) const;
10.107 -
10.108 - virtual void _setRowLowerBound(int i, Value value);
10.109 - virtual Value _getRowLowerBound(int i) const;
10.110 - virtual void _setRowUpperBound(int i, Value value);
10.111 - virtual Value _getRowUpperBound(int i) const;
10.112 -
10.113 - virtual void _setObjCoeffs(ExprIterator, ExprIterator);
10.114 - virtual void _getObjCoeffs(InsertIterator) const;
10.115 -
10.116 - virtual void _setObjCoeff(int i, Value obj_coef);
10.117 - virtual Value _getObjCoeff(int i) const;
10.118 -
10.119 - virtual void _setSense(Sense sense);
10.120 - virtual Sense _getSense() const;
10.121 -
10.122 - virtual SolveExitStatus _solve();
10.123 -
10.124 - virtual Value _getPrimal(int i) const;
10.125 - virtual Value _getDual(int i) const;
10.126 -
10.127 - virtual Value _getPrimalValue() const;
10.128 -
10.129 - virtual Value _getPrimalRay(int i) const;
10.130 - virtual Value _getDualRay(int i) const;
10.131 -
10.132 - virtual VarStatus _getColStatus(int i) const;
10.133 - virtual VarStatus _getRowStatus(int i) const;
10.134 -
10.135 - virtual ProblemType _getPrimalType() const;
10.136 - virtual ProblemType _getDualType() const;
10.137 -
10.138 - virtual void _clear();
10.139 -
10.140 - public:
10.141 -
10.142 - ///Solves LP with primal simplex method.
10.143 - SolveExitStatus solvePrimal();
10.144 -
10.145 - ///Solves LP with dual simplex method.
10.146 - SolveExitStatus solveDual();
10.147 -
10.148 - ///Solves LP with barrier method.
10.149 - SolveExitStatus solveBarrier();
10.150 -
10.151 - ///Returns the constraint identifier understood by CLP.
10.152 - int clpRow(Row r) const { return rows(id(r)); }
10.153 -
10.154 - ///Returns the variable identifier understood by CLP.
10.155 - int clpCol(Col c) const { return cols(id(c)); }
10.156 -
10.157 - ///Enum for \c messageLevel() parameter
10.158 - enum MessageLevel {
10.159 - /// no output (default value)
10.160 - MESSAGE_NO_OUTPUT = 0,
10.161 - /// print final solution
10.162 - MESSAGE_FINAL_SOLUTION = 1,
10.163 - /// print factorization
10.164 - MESSAGE_FACTORIZATION = 2,
10.165 - /// normal output
10.166 - MESSAGE_NORMAL_OUTPUT = 3,
10.167 - /// verbose output
10.168 - MESSAGE_VERBOSE_OUTPUT = 4
10.169 - };
10.170 - ///Set the verbosity of the messages
10.171 -
10.172 - ///Set the verbosity of the messages
10.173 - ///
10.174 - ///\param m is the level of the messages output by the solver routines.
10.175 - void messageLevel(MessageLevel m);
10.176 -
10.177 - };
10.178 -
10.179 -} //END OF NAMESPACE LEMON
10.180 -
10.181 -#endif //LEMON_LP_CLP_H
10.182 -
11.1 --- a/lemon/lp_cplex.cc Mon Jan 12 12:25:55 2009 +0000
11.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
11.3 @@ -1,925 +0,0 @@
11.4 -/* -*- mode: C++; indent-tabs-mode: nil; -*-
11.5 - *
11.6 - * This file is a part of LEMON, a generic C++ optimization library.
11.7 - *
11.8 - * Copyright (C) 2003-2008
11.9 - * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
11.10 - * (Egervary Research Group on Combinatorial Optimization, EGRES).
11.11 - *
11.12 - * Permission to use, modify and distribute this software is granted
11.13 - * provided that this copyright notice appears in all copies. For
11.14 - * precise terms see the accompanying LICENSE file.
11.15 - *
11.16 - * This software is provided "AS IS" with no warranty of any kind,
11.17 - * express or implied, and with no claim as to its suitability for any
11.18 - * purpose.
11.19 - *
11.20 - */
11.21 -
11.22 -#include <iostream>
11.23 -#include <vector>
11.24 -#include <cstring>
11.25 -
11.26 -#include <lemon/lp_cplex.h>
11.27 -
11.28 -extern "C" {
11.29 -#include <ilcplex/cplex.h>
11.30 -}
11.31 -
11.32 -
11.33 -///\file
11.34 -///\brief Implementation of the LEMON-CPLEX lp solver interface.
11.35 -namespace lemon {
11.36 -
11.37 - CplexEnv::LicenseError::LicenseError(int status) {
11.38 - if (!CPXgeterrorstring(0, status, _message)) {
11.39 - std::strcpy(_message, "Cplex unknown error");
11.40 - }
11.41 - }
11.42 -
11.43 - CplexEnv::CplexEnv() {
11.44 - int status;
11.45 - _cnt = new int;
11.46 - _env = CPXopenCPLEX(&status);
11.47 - if (_env == 0) {
11.48 - delete _cnt;
11.49 - _cnt = 0;
11.50 - throw LicenseError(status);
11.51 - }
11.52 - }
11.53 -
11.54 - CplexEnv::CplexEnv(const CplexEnv& other) {
11.55 - _env = other._env;
11.56 - _cnt = other._cnt;
11.57 - ++(*_cnt);
11.58 - }
11.59 -
11.60 - CplexEnv& CplexEnv::operator=(const CplexEnv& other) {
11.61 - _env = other._env;
11.62 - _cnt = other._cnt;
11.63 - ++(*_cnt);
11.64 - return *this;
11.65 - }
11.66 -
11.67 - CplexEnv::~CplexEnv() {
11.68 - --(*_cnt);
11.69 - if (*_cnt == 0) {
11.70 - delete _cnt;
11.71 - CPXcloseCPLEX(&_env);
11.72 - }
11.73 - }
11.74 -
11.75 - CplexBase::CplexBase() : LpBase() {
11.76 - int status;
11.77 - _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
11.78 - }
11.79 -
11.80 - CplexBase::CplexBase(const CplexEnv& env)
11.81 - : LpBase(), _env(env) {
11.82 - int status;
11.83 - _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
11.84 - }
11.85 -
11.86 - CplexBase::CplexBase(const CplexBase& cplex)
11.87 - : LpBase() {
11.88 - int status;
11.89 - _prob = CPXcloneprob(cplexEnv(), cplex._prob, &status);
11.90 - rows = cplex.rows;
11.91 - cols = cplex.cols;
11.92 - }
11.93 -
11.94 - CplexBase::~CplexBase() {
11.95 - CPXfreeprob(cplexEnv(),&_prob);
11.96 - }
11.97 -
11.98 - int CplexBase::_addCol() {
11.99 - int i = CPXgetnumcols(cplexEnv(), _prob);
11.100 - double lb = -INF, ub = INF;
11.101 - CPXnewcols(cplexEnv(), _prob, 1, 0, &lb, &ub, 0, 0);
11.102 - return i;
11.103 - }
11.104 -
11.105 -
11.106 - int CplexBase::_addRow() {
11.107 - int i = CPXgetnumrows(cplexEnv(), _prob);
11.108 - const double ub = INF;
11.109 - const char s = 'L';
11.110 - CPXnewrows(cplexEnv(), _prob, 1, &ub, &s, 0, 0);
11.111 - return i;
11.112 - }
11.113 -
11.114 -
11.115 - void CplexBase::_eraseCol(int i) {
11.116 - CPXdelcols(cplexEnv(), _prob, i, i);
11.117 - }
11.118 -
11.119 - void CplexBase::_eraseRow(int i) {
11.120 - CPXdelrows(cplexEnv(), _prob, i, i);
11.121 - }
11.122 -
11.123 - void CplexBase::_eraseColId(int i) {
11.124 - cols.eraseIndex(i);
11.125 - cols.shiftIndices(i);
11.126 - }
11.127 - void CplexBase::_eraseRowId(int i) {
11.128 - rows.eraseIndex(i);
11.129 - rows.shiftIndices(i);
11.130 - }
11.131 -
11.132 - void CplexBase::_getColName(int col, std::string &name) const {
11.133 - int size;
11.134 - CPXgetcolname(cplexEnv(), _prob, 0, 0, 0, &size, col, col);
11.135 - if (size == 0) {
11.136 - name.clear();
11.137 - return;
11.138 - }
11.139 -
11.140 - size *= -1;
11.141 - std::vector<char> buf(size);
11.142 - char *cname;
11.143 - int tmp;
11.144 - CPXgetcolname(cplexEnv(), _prob, &cname, &buf.front(), size,
11.145 - &tmp, col, col);
11.146 - name = cname;
11.147 - }
11.148 -
11.149 - void CplexBase::_setColName(int col, const std::string &name) {
11.150 - char *cname;
11.151 - cname = const_cast<char*>(name.c_str());
11.152 - CPXchgcolname(cplexEnv(), _prob, 1, &col, &cname);
11.153 - }
11.154 -
11.155 - int CplexBase::_colByName(const std::string& name) const {
11.156 - int index;
11.157 - if (CPXgetcolindex(cplexEnv(), _prob,
11.158 - const_cast<char*>(name.c_str()), &index) == 0) {
11.159 - return index;
11.160 - }
11.161 - return -1;
11.162 - }
11.163 -
11.164 - void CplexBase::_getRowName(int row, std::string &name) const {
11.165 - int size;
11.166 - CPXgetrowname(cplexEnv(), _prob, 0, 0, 0, &size, row, row);
11.167 - if (size == 0) {
11.168 - name.clear();
11.169 - return;
11.170 - }
11.171 -
11.172 - size *= -1;
11.173 - std::vector<char> buf(size);
11.174 - char *cname;
11.175 - int tmp;
11.176 - CPXgetrowname(cplexEnv(), _prob, &cname, &buf.front(), size,
11.177 - &tmp, row, row);
11.178 - name = cname;
11.179 - }
11.180 -
11.181 - void CplexBase::_setRowName(int row, const std::string &name) {
11.182 - char *cname;
11.183 - cname = const_cast<char*>(name.c_str());
11.184 - CPXchgrowname(cplexEnv(), _prob, 1, &row, &cname);
11.185 - }
11.186 -
11.187 - int CplexBase::_rowByName(const std::string& name) const {
11.188 - int index;
11.189 - if (CPXgetrowindex(cplexEnv(), _prob,
11.190 - const_cast<char*>(name.c_str()), &index) == 0) {
11.191 - return index;
11.192 - }
11.193 - return -1;
11.194 - }
11.195 -
11.196 - void CplexBase::_setRowCoeffs(int i, ExprIterator b,
11.197 - ExprIterator e)
11.198 - {
11.199 - std::vector<int> indices;
11.200 - std::vector<int> rowlist;
11.201 - std::vector<Value> values;
11.202 -
11.203 - for(ExprIterator it=b; it!=e; ++it) {
11.204 - indices.push_back(it->first);
11.205 - values.push_back(it->second);
11.206 - rowlist.push_back(i);
11.207 - }
11.208 -
11.209 - CPXchgcoeflist(cplexEnv(), _prob, values.size(),
11.210 - &rowlist.front(), &indices.front(), &values.front());
11.211 - }
11.212 -
11.213 - void CplexBase::_getRowCoeffs(int i, InsertIterator b) const {
11.214 - int tmp1, tmp2, tmp3, length;
11.215 - CPXgetrows(cplexEnv(), _prob, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
11.216 -
11.217 - length = -length;
11.218 - std::vector<int> indices(length);
11.219 - std::vector<double> values(length);
11.220 -
11.221 - CPXgetrows(cplexEnv(), _prob, &tmp1, &tmp2,
11.222 - &indices.front(), &values.front(),
11.223 - length, &tmp3, i, i);
11.224 -
11.225 - for (int i = 0; i < length; ++i) {
11.226 - *b = std::make_pair(indices[i], values[i]);
11.227 - ++b;
11.228 - }
11.229 - }
11.230 -
11.231 - void CplexBase::_setColCoeffs(int i, ExprIterator b, ExprIterator e) {
11.232 - std::vector<int> indices;
11.233 - std::vector<int> collist;
11.234 - std::vector<Value> values;
11.235 -
11.236 - for(ExprIterator it=b; it!=e; ++it) {
11.237 - indices.push_back(it->first);
11.238 - values.push_back(it->second);
11.239 - collist.push_back(i);
11.240 - }
11.241 -
11.242 - CPXchgcoeflist(cplexEnv(), _prob, values.size(),
11.243 - &indices.front(), &collist.front(), &values.front());
11.244 - }
11.245 -
11.246 - void CplexBase::_getColCoeffs(int i, InsertIterator b) const {
11.247 -
11.248 - int tmp1, tmp2, tmp3, length;
11.249 - CPXgetcols(cplexEnv(), _prob, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
11.250 -
11.251 - length = -length;
11.252 - std::vector<int> indices(length);
11.253 - std::vector<double> values(length);
11.254 -
11.255 - CPXgetcols(cplexEnv(), _prob, &tmp1, &tmp2,
11.256 - &indices.front(), &values.front(),
11.257 - length, &tmp3, i, i);
11.258 -
11.259 - for (int i = 0; i < length; ++i) {
11.260 - *b = std::make_pair(indices[i], values[i]);
11.261 - ++b;
11.262 - }
11.263 -
11.264 - }
11.265 -
11.266 - void CplexBase::_setCoeff(int row, int col, Value value) {
11.267 - CPXchgcoef(cplexEnv(), _prob, row, col, value);
11.268 - }
11.269 -
11.270 - CplexBase::Value CplexBase::_getCoeff(int row, int col) const {
11.271 - CplexBase::Value value;
11.272 - CPXgetcoef(cplexEnv(), _prob, row, col, &value);
11.273 - return value;
11.274 - }
11.275 -
11.276 - void CplexBase::_setColLowerBound(int i, Value value) {
11.277 - const char s = 'L';
11.278 - CPXchgbds(cplexEnv(), _prob, 1, &i, &s, &value);
11.279 - }
11.280 -
11.281 - CplexBase::Value CplexBase::_getColLowerBound(int i) const {
11.282 - CplexBase::Value res;
11.283 - CPXgetlb(cplexEnv(), _prob, &res, i, i);
11.284 - return res <= -CPX_INFBOUND ? -INF : res;
11.285 - }
11.286 -
11.287 - void CplexBase::_setColUpperBound(int i, Value value)
11.288 - {
11.289 - const char s = 'U';
11.290 - CPXchgbds(cplexEnv(), _prob, 1, &i, &s, &value);
11.291 - }
11.292 -
11.293 - CplexBase::Value CplexBase::_getColUpperBound(int i) const {
11.294 - CplexBase::Value res;
11.295 - CPXgetub(cplexEnv(), _prob, &res, i, i);
11.296 - return res >= CPX_INFBOUND ? INF : res;
11.297 - }
11.298 -
11.299 - CplexBase::Value CplexBase::_getRowLowerBound(int i) const {
11.300 - char s;
11.301 - CPXgetsense(cplexEnv(), _prob, &s, i, i);
11.302 - CplexBase::Value res;
11.303 -
11.304 - switch (s) {
11.305 - case 'G':
11.306 - case 'R':
11.307 - case 'E':
11.308 - CPXgetrhs(cplexEnv(), _prob, &res, i, i);
11.309 - return res <= -CPX_INFBOUND ? -INF : res;
11.310 - default:
11.311 - return -INF;
11.312 - }
11.313 - }
11.314 -
11.315 - CplexBase::Value CplexBase::_getRowUpperBound(int i) const {
11.316 - char s;
11.317 - CPXgetsense(cplexEnv(), _prob, &s, i, i);
11.318 - CplexBase::Value res;
11.319 -
11.320 - switch (s) {
11.321 - case 'L':
11.322 - case 'E':
11.323 - CPXgetrhs(cplexEnv(), _prob, &res, i, i);
11.324 - return res >= CPX_INFBOUND ? INF : res;
11.325 - case 'R':
11.326 - CPXgetrhs(cplexEnv(), _prob, &res, i, i);
11.327 - {
11.328 - double rng;
11.329 - CPXgetrngval(cplexEnv(), _prob, &rng, i, i);
11.330 - res += rng;
11.331 - }
11.332 - return res >= CPX_INFBOUND ? INF : res;
11.333 - default:
11.334 - return INF;
11.335 - }
11.336 - }
11.337 -
11.338 - //This is easier to implement
11.339 - void CplexBase::_set_row_bounds(int i, Value lb, Value ub) {
11.340 - if (lb == -INF) {
11.341 - const char s = 'L';
11.342 - CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
11.343 - CPXchgrhs(cplexEnv(), _prob, 1, &i, &ub);
11.344 - } else if (ub == INF) {
11.345 - const char s = 'G';
11.346 - CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
11.347 - CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
11.348 - } else if (lb == ub){
11.349 - const char s = 'E';
11.350 - CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
11.351 - CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
11.352 - } else {
11.353 - const char s = 'R';
11.354 - CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
11.355 - CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
11.356 - double len = ub - lb;
11.357 - CPXchgrngval(cplexEnv(), _prob, 1, &i, &len);
11.358 - }
11.359 - }
11.360 -
11.361 - void CplexBase::_setRowLowerBound(int i, Value lb)
11.362 - {
11.363 - LEMON_ASSERT(lb != INF, "Invalid bound");
11.364 - _set_row_bounds(i, lb, CplexBase::_getRowUpperBound(i));
11.365 - }
11.366 -
11.367 - void CplexBase::_setRowUpperBound(int i, Value ub)
11.368 - {
11.369 -
11.370 - LEMON_ASSERT(ub != -INF, "Invalid bound");
11.371 - _set_row_bounds(i, CplexBase::_getRowLowerBound(i), ub);
11.372 - }
11.373 -
11.374 - void CplexBase::_setObjCoeffs(ExprIterator b, ExprIterator e)
11.375 - {
11.376 - std::vector<int> indices;
11.377 - std::vector<Value> values;
11.378 - for(ExprIterator it=b; it!=e; ++it) {
11.379 - indices.push_back(it->first);
11.380 - values.push_back(it->second);
11.381 - }
11.382 - CPXchgobj(cplexEnv(), _prob, values.size(),
11.383 - &indices.front(), &values.front());
11.384 -
11.385 - }
11.386 -
11.387 - void CplexBase::_getObjCoeffs(InsertIterator b) const
11.388 - {
11.389 - int num = CPXgetnumcols(cplexEnv(), _prob);
11.390 - std::vector<Value> x(num);
11.391 -
11.392 - CPXgetobj(cplexEnv(), _prob, &x.front(), 0, num - 1);
11.393 - for (int i = 0; i < num; ++i) {
11.394 - if (x[i] != 0.0) {
11.395 - *b = std::make_pair(i, x[i]);
11.396 - ++b;
11.397 - }
11.398 - }
11.399 - }
11.400 -
11.401 - void CplexBase::_setObjCoeff(int i, Value obj_coef)
11.402 - {
11.403 - CPXchgobj(cplexEnv(), _prob, 1, &i, &obj_coef);
11.404 - }
11.405 -
11.406 - CplexBase::Value CplexBase::_getObjCoeff(int i) const
11.407 - {
11.408 - Value x;
11.409 - CPXgetobj(cplexEnv(), _prob, &x, i, i);
11.410 - return x;
11.411 - }
11.412 -
11.413 - void CplexBase::_setSense(CplexBase::Sense sense) {
11.414 - switch (sense) {
11.415 - case MIN:
11.416 - CPXchgobjsen(cplexEnv(), _prob, CPX_MIN);
11.417 - break;
11.418 - case MAX:
11.419 - CPXchgobjsen(cplexEnv(), _prob, CPX_MAX);
11.420 - break;
11.421 - }
11.422 - }
11.423 -
11.424 - CplexBase::Sense CplexBase::_getSense() const {
11.425 - switch (CPXgetobjsen(cplexEnv(), _prob)) {
11.426 - case CPX_MIN:
11.427 - return MIN;
11.428 - case CPX_MAX:
11.429 - return MAX;
11.430 - default:
11.431 - LEMON_ASSERT(false, "Invalid sense");
11.432 - return CplexBase::Sense();
11.433 - }
11.434 - }
11.435 -
11.436 - void CplexBase::_clear() {
11.437 - CPXfreeprob(cplexEnv(),&_prob);
11.438 - int status;
11.439 - _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
11.440 - rows.clear();
11.441 - cols.clear();
11.442 - }
11.443 -
11.444 - // LpCplex members
11.445 -
11.446 - LpCplex::LpCplex()
11.447 - : LpBase(), CplexBase(), LpSolver() {}
11.448 -
11.449 - LpCplex::LpCplex(const CplexEnv& env)
11.450 - : LpBase(), CplexBase(env), LpSolver() {}
11.451 -
11.452 - LpCplex::LpCplex(const LpCplex& other)
11.453 - : LpBase(), CplexBase(other), LpSolver() {}
11.454 -
11.455 - LpCplex::~LpCplex() {}
11.456 -
11.457 - LpCplex* LpCplex::_newSolver() const { return new LpCplex; }
11.458 - LpCplex* LpCplex::_cloneSolver() const {return new LpCplex(*this); }
11.459 -
11.460 - const char* LpCplex::_solverName() const { return "LpCplex"; }
11.461 -
11.462 - void LpCplex::_clear_temporals() {
11.463 - _col_status.clear();
11.464 - _row_status.clear();
11.465 - _primal_ray.clear();
11.466 - _dual_ray.clear();
11.467 - }
11.468 -
11.469 - // The routine returns zero unless an error occurred during the
11.470 - // optimization. Examples of errors include exhausting available
11.471 - // memory (CPXERR_NO_MEMORY) or encountering invalid data in the
11.472 - // CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a
11.473 - // user-specified CPLEX limit, or proving the model infeasible or
11.474 - // unbounded, are not considered errors. Note that a zero return
11.475 - // value does not necessarily mean that a solution exists. Use query
11.476 - // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
11.477 - // further information about the status of the optimization.
11.478 - LpCplex::SolveExitStatus LpCplex::convertStatus(int status) {
11.479 -#if CPX_VERSION >= 800
11.480 - if (status == 0) {
11.481 - switch (CPXgetstat(cplexEnv(), _prob)) {
11.482 - case CPX_STAT_OPTIMAL:
11.483 - case CPX_STAT_INFEASIBLE:
11.484 - case CPX_STAT_UNBOUNDED:
11.485 - return SOLVED;
11.486 - default:
11.487 - return UNSOLVED;
11.488 - }
11.489 - } else {
11.490 - return UNSOLVED;
11.491 - }
11.492 -#else
11.493 - if (status == 0) {
11.494 - //We want to exclude some cases
11.495 - switch (CPXgetstat(cplexEnv(), _prob)) {
11.496 - case CPX_OBJ_LIM:
11.497 - case CPX_IT_LIM_FEAS:
11.498 - case CPX_IT_LIM_INFEAS:
11.499 - case CPX_TIME_LIM_FEAS:
11.500 - case CPX_TIME_LIM_INFEAS:
11.501 - return UNSOLVED;
11.502 - default:
11.503 - return SOLVED;
11.504 - }
11.505 - } else {
11.506 - return UNSOLVED;
11.507 - }
11.508 -#endif
11.509 - }
11.510 -
11.511 - LpCplex::SolveExitStatus LpCplex::_solve() {
11.512 - _clear_temporals();
11.513 - return convertStatus(CPXlpopt(cplexEnv(), _prob));
11.514 - }
11.515 -
11.516 - LpCplex::SolveExitStatus LpCplex::solvePrimal() {
11.517 - _clear_temporals();
11.518 - return convertStatus(CPXprimopt(cplexEnv(), _prob));
11.519 - }
11.520 -
11.521 - LpCplex::SolveExitStatus LpCplex::solveDual() {
11.522 - _clear_temporals();
11.523 - return convertStatus(CPXdualopt(cplexEnv(), _prob));
11.524 - }
11.525 -
11.526 - LpCplex::SolveExitStatus LpCplex::solveBarrier() {
11.527 - _clear_temporals();
11.528 - return convertStatus(CPXbaropt(cplexEnv(), _prob));
11.529 - }
11.530 -
11.531 - LpCplex::Value LpCplex::_getPrimal(int i) const {
11.532 - Value x;
11.533 - CPXgetx(cplexEnv(), _prob, &x, i, i);
11.534 - return x;
11.535 - }
11.536 -
11.537 - LpCplex::Value LpCplex::_getDual(int i) const {
11.538 - Value y;
11.539 - CPXgetpi(cplexEnv(), _prob, &y, i, i);
11.540 - return y;
11.541 - }
11.542 -
11.543 - LpCplex::Value LpCplex::_getPrimalValue() const {
11.544 - Value objval;
11.545 - CPXgetobjval(cplexEnv(), _prob, &objval);
11.546 - return objval;
11.547 - }
11.548 -
11.549 - LpCplex::VarStatus LpCplex::_getColStatus(int i) const {
11.550 - if (_col_status.empty()) {
11.551 - _col_status.resize(CPXgetnumcols(cplexEnv(), _prob));
11.552 - CPXgetbase(cplexEnv(), _prob, &_col_status.front(), 0);
11.553 - }
11.554 - switch (_col_status[i]) {
11.555 - case CPX_BASIC:
11.556 - return BASIC;
11.557 - case CPX_FREE_SUPER:
11.558 - return FREE;
11.559 - case CPX_AT_LOWER:
11.560 - return LOWER;
11.561 - case CPX_AT_UPPER:
11.562 - return UPPER;
11.563 - default:
11.564 - LEMON_ASSERT(false, "Wrong column status");
11.565 - return LpCplex::VarStatus();
11.566 - }
11.567 - }
11.568 -
11.569 - LpCplex::VarStatus LpCplex::_getRowStatus(int i) const {
11.570 - if (_row_status.empty()) {
11.571 - _row_status.resize(CPXgetnumrows(cplexEnv(), _prob));
11.572 - CPXgetbase(cplexEnv(), _prob, 0, &_row_status.front());
11.573 - }
11.574 - switch (_row_status[i]) {
11.575 - case CPX_BASIC:
11.576 - return BASIC;
11.577 - case CPX_AT_LOWER:
11.578 - {
11.579 - char s;
11.580 - CPXgetsense(cplexEnv(), _prob, &s, i, i);
11.581 - return s != 'L' ? LOWER : UPPER;
11.582 - }
11.583 - case CPX_AT_UPPER:
11.584 - return UPPER;
11.585 - default:
11.586 - LEMON_ASSERT(false, "Wrong row status");
11.587 - return LpCplex::VarStatus();
11.588 - }
11.589 - }
11.590 -
11.591 - LpCplex::Value LpCplex::_getPrimalRay(int i) const {
11.592 - if (_primal_ray.empty()) {
11.593 - _primal_ray.resize(CPXgetnumcols(cplexEnv(), _prob));
11.594 - CPXgetray(cplexEnv(), _prob, &_primal_ray.front());
11.595 - }
11.596 - return _primal_ray[i];
11.597 - }
11.598 -
11.599 - LpCplex::Value LpCplex::_getDualRay(int i) const {
11.600 - if (_dual_ray.empty()) {
11.601 -
11.602 - }
11.603 - return _dual_ray[i];
11.604 - }
11.605 -
11.606 - //7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
11.607 - // This table lists the statuses, returned by the CPXgetstat()
11.608 - // routine, for solutions to LP problems or mixed integer problems. If
11.609 - // no solution exists, the return value is zero.
11.610 -
11.611 - // For Simplex, Barrier
11.612 - // 1 CPX_OPTIMAL
11.613 - // Optimal solution found
11.614 - // 2 CPX_INFEASIBLE
11.615 - // Problem infeasible
11.616 - // 3 CPX_UNBOUNDED
11.617 - // Problem unbounded
11.618 - // 4 CPX_OBJ_LIM
11.619 - // Objective limit exceeded in Phase II
11.620 - // 5 CPX_IT_LIM_FEAS
11.621 - // Iteration limit exceeded in Phase II
11.622 - // 6 CPX_IT_LIM_INFEAS
11.623 - // Iteration limit exceeded in Phase I
11.624 - // 7 CPX_TIME_LIM_FEAS
11.625 - // Time limit exceeded in Phase II
11.626 - // 8 CPX_TIME_LIM_INFEAS
11.627 - // Time limit exceeded in Phase I
11.628 - // 9 CPX_NUM_BEST_FEAS
11.629 - // Problem non-optimal, singularities in Phase II
11.630 - // 10 CPX_NUM_BEST_INFEAS
11.631 - // Problem non-optimal, singularities in Phase I
11.632 - // 11 CPX_OPTIMAL_INFEAS
11.633 - // Optimal solution found, unscaled infeasibilities
11.634 - // 12 CPX_ABORT_FEAS
11.635 - // Aborted in Phase II
11.636 - // 13 CPX_ABORT_INFEAS
11.637 - // Aborted in Phase I
11.638 - // 14 CPX_ABORT_DUAL_INFEAS
11.639 - // Aborted in barrier, dual infeasible
11.640 - // 15 CPX_ABORT_PRIM_INFEAS
11.641 - // Aborted in barrier, primal infeasible
11.642 - // 16 CPX_ABORT_PRIM_DUAL_INFEAS
11.643 - // Aborted in barrier, primal and dual infeasible
11.644 - // 17 CPX_ABORT_PRIM_DUAL_FEAS
11.645 - // Aborted in barrier, primal and dual feasible
11.646 - // 18 CPX_ABORT_CROSSOVER
11.647 - // Aborted in crossover
11.648 - // 19 CPX_INForUNBD
11.649 - // Infeasible or unbounded
11.650 - // 20 CPX_PIVOT
11.651 - // User pivot used
11.652 - //
11.653 - // Ezeket hova tegyem:
11.654 - // ??case CPX_ABORT_DUAL_INFEAS
11.655 - // ??case CPX_ABORT_CROSSOVER
11.656 - // ??case CPX_INForUNBD
11.657 - // ??case CPX_PIVOT
11.658 -
11.659 - //Some more interesting stuff:
11.660 -
11.661 - // CPX_PARAM_PROBMETHOD 1062 int LPMETHOD
11.662 - // 0 Automatic
11.663 - // 1 Primal Simplex
11.664 - // 2 Dual Simplex
11.665 - // 3 Network Simplex
11.666 - // 4 Standard Barrier
11.667 - // Default: 0
11.668 - // Description: Method for linear optimization.
11.669 - // Determines which algorithm is used when CPXlpopt() (or "optimize"
11.670 - // in the Interactive Optimizer) is called. Currently the behavior of
11.671 - // the "Automatic" setting is that CPLEX simply invokes the dual
11.672 - // simplex method, but this capability may be expanded in the future
11.673 - // so that CPLEX chooses the method based on problem characteristics
11.674 -#if CPX_VERSION < 900
11.675 - void statusSwitch(CPXENVptr cplexEnv(),int& stat){
11.676 - int lpmethod;
11.677 - CPXgetintparam (cplexEnv(),CPX_PARAM_PROBMETHOD,&lpmethod);
11.678 - if (lpmethod==2){
11.679 - if (stat==CPX_UNBOUNDED){
11.680 - stat=CPX_INFEASIBLE;
11.681 - }
11.682 - else{
11.683 - if (stat==CPX_INFEASIBLE)
11.684 - stat=CPX_UNBOUNDED;
11.685 - }
11.686 - }
11.687 - }
11.688 -#else
11.689 - void statusSwitch(CPXENVptr,int&){}
11.690 -#endif
11.691 -
11.692 - LpCplex::ProblemType LpCplex::_getPrimalType() const {
11.693 - // Unboundedness not treated well: the following is from cplex 9.0 doc
11.694 - // About Unboundedness
11.695 -
11.696 - // The treatment of models that are unbounded involves a few
11.697 - // subtleties. Specifically, a declaration of unboundedness means that
11.698 - // ILOG CPLEX has determined that the model has an unbounded
11.699 - // ray. Given any feasible solution x with objective z, a multiple of
11.700 - // the unbounded ray can be added to x to give a feasible solution
11.701 - // with objective z-1 (or z+1 for maximization models). Thus, if a
11.702 - // feasible solution exists, then the optimal objective is
11.703 - // unbounded. Note that ILOG CPLEX has not necessarily concluded that
11.704 - // a feasible solution exists. Users can call the routine CPXsolninfo
11.705 - // to determine whether ILOG CPLEX has also concluded that the model
11.706 - // has a feasible solution.
11.707 -
11.708 - int stat = CPXgetstat(cplexEnv(), _prob);
11.709 -#if CPX_VERSION >= 800
11.710 - switch (stat)
11.711 - {
11.712 - case CPX_STAT_OPTIMAL:
11.713 - return OPTIMAL;
11.714 - case CPX_STAT_UNBOUNDED:
11.715 - return UNBOUNDED;
11.716 - case CPX_STAT_INFEASIBLE:
11.717 - return INFEASIBLE;
11.718 - default:
11.719 - return UNDEFINED;
11.720 - }
11.721 -#else
11.722 - statusSwitch(cplexEnv(),stat);
11.723 - //CPXgetstat(cplexEnv(), _prob);
11.724 - //printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL);
11.725 - switch (stat) {
11.726 - case 0:
11.727 - return UNDEFINED; //Undefined
11.728 - case CPX_OPTIMAL://Optimal
11.729 - return OPTIMAL;
11.730 - case CPX_UNBOUNDED://Unbounded
11.731 - return INFEASIBLE;//In case of dual simplex
11.732 - //return UNBOUNDED;
11.733 - case CPX_INFEASIBLE://Infeasible
11.734 - // case CPX_IT_LIM_INFEAS:
11.735 - // case CPX_TIME_LIM_INFEAS:
11.736 - // case CPX_NUM_BEST_INFEAS:
11.737 - // case CPX_OPTIMAL_INFEAS:
11.738 - // case CPX_ABORT_INFEAS:
11.739 - // case CPX_ABORT_PRIM_INFEAS:
11.740 - // case CPX_ABORT_PRIM_DUAL_INFEAS:
11.741 - return UNBOUNDED;//In case of dual simplex
11.742 - //return INFEASIBLE;
11.743 - // case CPX_OBJ_LIM:
11.744 - // case CPX_IT_LIM_FEAS:
11.745 - // case CPX_TIME_LIM_FEAS:
11.746 - // case CPX_NUM_BEST_FEAS:
11.747 - // case CPX_ABORT_FEAS:
11.748 - // case CPX_ABORT_PRIM_DUAL_FEAS:
11.749 - // return FEASIBLE;
11.750 - default:
11.751 - return UNDEFINED; //Everything else comes here
11.752 - //FIXME error
11.753 - }
11.754 -#endif
11.755 - }
11.756 -
11.757 - //9.0-as cplex verzio statusai
11.758 - // CPX_STAT_ABORT_DUAL_OBJ_LIM
11.759 - // CPX_STAT_ABORT_IT_LIM
11.760 - // CPX_STAT_ABORT_OBJ_LIM
11.761 - // CPX_STAT_ABORT_PRIM_OBJ_LIM
11.762 - // CPX_STAT_ABORT_TIME_LIM
11.763 - // CPX_STAT_ABORT_USER
11.764 - // CPX_STAT_FEASIBLE_RELAXED
11.765 - // CPX_STAT_INFEASIBLE
11.766 - // CPX_STAT_INForUNBD
11.767 - // CPX_STAT_NUM_BEST
11.768 - // CPX_STAT_OPTIMAL
11.769 - // CPX_STAT_OPTIMAL_FACE_UNBOUNDED
11.770 - // CPX_STAT_OPTIMAL_INFEAS
11.771 - // CPX_STAT_OPTIMAL_RELAXED
11.772 - // CPX_STAT_UNBOUNDED
11.773 -
11.774 - LpCplex::ProblemType LpCplex::_getDualType() const {
11.775 - int stat = CPXgetstat(cplexEnv(), _prob);
11.776 -#if CPX_VERSION >= 800
11.777 - switch (stat) {
11.778 - case CPX_STAT_OPTIMAL:
11.779 - return OPTIMAL;
11.780 - case CPX_STAT_UNBOUNDED:
11.781 - return INFEASIBLE;
11.782 - default:
11.783 - return UNDEFINED;
11.784 - }
11.785 -#else
11.786 - statusSwitch(cplexEnv(),stat);
11.787 - switch (stat) {
11.788 - case 0:
11.789 - return UNDEFINED; //Undefined
11.790 - case CPX_OPTIMAL://Optimal
11.791 - return OPTIMAL;
11.792 - case CPX_UNBOUNDED:
11.793 - return INFEASIBLE;
11.794 - default:
11.795 - return UNDEFINED; //Everything else comes here
11.796 - //FIXME error
11.797 - }
11.798 -#endif
11.799 - }
11.800 -
11.801 - // MipCplex members
11.802 -
11.803 - MipCplex::MipCplex()
11.804 - : LpBase(), CplexBase(), MipSolver() {
11.805 -
11.806 -#if CPX_VERSION < 800
11.807 - CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MIP);
11.808 -#else
11.809 - CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MILP);
11.810 -#endif
11.811 - }
11.812 -
11.813 - MipCplex::MipCplex(const CplexEnv& env)
11.814 - : LpBase(), CplexBase(env), MipSolver() {
11.815 -
11.816 -#if CPX_VERSION < 800
11.817 - CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MIP);
11.818 -#else
11.819 - CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MILP);
11.820 -#endif
11.821 -
11.822 - }
11.823 -
11.824 - MipCplex::MipCplex(const MipCplex& other)
11.825 - : LpBase(), CplexBase(other), MipSolver() {}
11.826 -
11.827 - MipCplex::~MipCplex() {}
11.828 -
11.829 - MipCplex* MipCplex::_newSolver() const { return new MipCplex; }
11.830 - MipCplex* MipCplex::_cloneSolver() const {return new MipCplex(*this); }
11.831 -
11.832 - const char* MipCplex::_solverName() const { return "MipCplex"; }
11.833 -
11.834 - void MipCplex::_setColType(int i, MipCplex::ColTypes col_type) {
11.835 -
11.836 - // Note If a variable is to be changed to binary, a call to CPXchgbds
11.837 - // should also be made to change the bounds to 0 and 1.
11.838 -
11.839 - switch (col_type){
11.840 - case INTEGER: {
11.841 - const char t = 'I';
11.842 - CPXchgctype (cplexEnv(), _prob, 1, &i, &t);
11.843 - } break;
11.844 - case REAL: {
11.845 - const char t = 'C';
11.846 - CPXchgctype (cplexEnv(), _prob, 1, &i, &t);
11.847 - } break;
11.848 - default:
11.849 - break;
11.850 - }
11.851 - }
11.852 -
11.853 - MipCplex::ColTypes MipCplex::_getColType(int i) const {
11.854 - char t;
11.855 - CPXgetctype (cplexEnv(), _prob, &t, i, i);
11.856 - switch (t) {
11.857 - case 'I':
11.858 - return INTEGER;
11.859 - case 'C':
11.860 - return REAL;
11.861 - default:
11.862 - LEMON_ASSERT(false, "Invalid column type");
11.863 - return ColTypes();
11.864 - }
11.865 -
11.866 - }
11.867 -
11.868 - MipCplex::SolveExitStatus MipCplex::_solve() {
11.869 - int status;
11.870 - status = CPXmipopt (cplexEnv(), _prob);
11.871 - if (status==0)
11.872 - return SOLVED;
11.873 - else
11.874 - return UNSOLVED;
11.875 -
11.876 - }
11.877 -
11.878 -
11.879 - MipCplex::ProblemType MipCplex::_getType() const {
11.880 -
11.881 - int stat = CPXgetstat(cplexEnv(), _prob);
11.882 -
11.883 - //Fortunately, MIP statuses did not change for cplex 8.0
11.884 - switch (stat) {
11.885 - case CPXMIP_OPTIMAL:
11.886 - // Optimal integer solution has been found.
11.887 - case CPXMIP_OPTIMAL_TOL:
11.888 - // Optimal soluton with the tolerance defined by epgap or epagap has
11.889 - // been found.
11.890 - return OPTIMAL;
11.891 - //This also exists in later issues
11.892 - // case CPXMIP_UNBOUNDED:
11.893 - //return UNBOUNDED;
11.894 - case CPXMIP_INFEASIBLE:
11.895 - return INFEASIBLE;
11.896 - default:
11.897 - return UNDEFINED;
11.898 - }
11.899 - //Unboundedness not treated well: the following is from cplex 9.0 doc
11.900 - // About Unboundedness
11.901 -
11.902 - // The treatment of models that are unbounded involves a few
11.903 - // subtleties. Specifically, a declaration of unboundedness means that
11.904 - // ILOG CPLEX has determined that the model has an unbounded
11.905 - // ray. Given any feasible solution x with objective z, a multiple of
11.906 - // the unbounded ray can be added to x to give a feasible solution
11.907 - // with objective z-1 (or z+1 for maximization models). Thus, if a
11.908 - // feasible solution exists, then the optimal objective is
11.909 - // unbounded. Note that ILOG CPLEX has not necessarily concluded that
11.910 - // a feasible solution exists. Users can call the routine CPXsolninfo
11.911 - // to determine whether ILOG CPLEX has also concluded that the model
11.912 - // has a feasible solution.
11.913 - }
11.914 -
11.915 - MipCplex::Value MipCplex::_getSol(int i) const {
11.916 - Value x;
11.917 - CPXgetmipx(cplexEnv(), _prob, &x, i, i);
11.918 - return x;
11.919 - }
11.920 -
11.921 - MipCplex::Value MipCplex::_getSolValue() const {
11.922 - Value objval;
11.923 - CPXgetmipobjval(cplexEnv(), _prob, &objval);
11.924 - return objval;
11.925 - }
11.926 -
11.927 -} //namespace lemon
11.928 -
12.1 --- a/lemon/lp_cplex.h Mon Jan 12 12:25:55 2009 +0000
12.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
12.3 @@ -1,256 +0,0 @@
12.4 -/* -*- mode: C++; indent-tabs-mode: nil; -*-
12.5 - *
12.6 - * This file is a part of LEMON, a generic C++ optimization library.
12.7 - *
12.8 - * Copyright (C) 2003-2008
12.9 - * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
12.10 - * (Egervary Research Group on Combinatorial Optimization, EGRES).
12.11 - *
12.12 - * Permission to use, modify and distribute this software is granted
12.13 - * provided that this copyright notice appears in all copies. For
12.14 - * precise terms see the accompanying LICENSE file.
12.15 - *
12.16 - * This software is provided "AS IS" with no warranty of any kind,
12.17 - * express or implied, and with no claim as to its suitability for any
12.18 - * purpose.
12.19 - *
12.20 - */
12.21 -
12.22 -#ifndef LEMON_LP_CPLEX_H
12.23 -#define LEMON_LP_CPLEX_H
12.24 -
12.25 -///\file
12.26 -///\brief Header of the LEMON-CPLEX lp solver interface.
12.27 -
12.28 -#include <lemon/lp_base.h>
12.29 -
12.30 -struct cpxenv;
12.31 -struct cpxlp;
12.32 -
12.33 -namespace lemon {
12.34 -
12.35 - /// \brief Reference counted wrapper around cpxenv pointer
12.36 - ///
12.37 - /// The cplex uses environment object which is responsible for
12.38 - /// checking the proper license usage. This class provides a simple
12.39 - /// interface for share the environment object between different
12.40 - /// problems.
12.41 - class CplexEnv {
12.42 - friend class CplexBase;
12.43 - private:
12.44 - cpxenv* _env;
12.45 - mutable int* _cnt;
12.46 -
12.47 - public:
12.48 -
12.49 - /// \brief This exception is thrown when the license check is not
12.50 - /// sufficient
12.51 - class LicenseError : public Exception {
12.52 - friend class CplexEnv;
12.53 - private:
12.54 -
12.55 - LicenseError(int status);
12.56 - char _message[510];
12.57 -
12.58 - public:
12.59 -
12.60 - /// The short error message
12.61 - virtual const char* what() const throw() {
12.62 - return _message;
12.63 - }
12.64 - };
12.65 -
12.66 - /// Constructor
12.67 - CplexEnv();
12.68 - /// Shallow copy constructor
12.69 - CplexEnv(const CplexEnv&);
12.70 - /// Shallow assignement
12.71 - CplexEnv& operator=(const CplexEnv&);
12.72 - /// Destructor
12.73 - virtual ~CplexEnv();
12.74 -
12.75 - protected:
12.76 -
12.77 - cpxenv* cplexEnv() { return _env; }
12.78 - const cpxenv* cplexEnv() const { return _env; }
12.79 - };
12.80 -
12.81 - /// \brief Base interface for the CPLEX LP and MIP solver
12.82 - ///
12.83 - /// This class implements the common interface of the CPLEX LP and
12.84 - /// MIP solvers.
12.85 - /// \ingroup lp_group
12.86 - class CplexBase : virtual public LpBase {
12.87 - protected:
12.88 -
12.89 - CplexEnv _env;
12.90 - cpxlp* _prob;
12.91 -
12.92 - CplexBase();
12.93 - CplexBase(const CplexEnv&);
12.94 - CplexBase(const CplexBase &);
12.95 - virtual ~CplexBase();
12.96 -
12.97 - virtual int _addCol();
12.98 - virtual int _addRow();
12.99 -
12.100 - virtual void _eraseCol(int i);
12.101 - virtual void _eraseRow(int i);
12.102 -
12.103 - virtual void _eraseColId(int i);
12.104 - virtual void _eraseRowId(int i);
12.105 -
12.106 - virtual void _getColName(int col, std::string& name) const;
12.107 - virtual void _setColName(int col, const std::string& name);
12.108 - virtual int _colByName(const std::string& name) const;
12.109 -
12.110 - virtual void _getRowName(int row, std::string& name) const;
12.111 - virtual void _setRowName(int row, const std::string& name);
12.112 - virtual int _rowByName(const std::string& name) const;
12.113 -
12.114 - virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
12.115 - virtual void _getRowCoeffs(int i, InsertIterator b) const;
12.116 -
12.117 - virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
12.118 - virtual void _getColCoeffs(int i, InsertIterator b) const;
12.119 -
12.120 - virtual void _setCoeff(int row, int col, Value value);
12.121 - virtual Value _getCoeff(int row, int col) const;
12.122 -
12.123 - virtual void _setColLowerBound(int i, Value value);
12.124 - virtual Value _getColLowerBound(int i) const;
12.125 -
12.126 - virtual void _setColUpperBound(int i, Value value);
12.127 - virtual Value _getColUpperBound(int i) const;
12.128 -
12.129 - private:
12.130 - void _set_row_bounds(int i, Value lb, Value ub);
12.131 - protected:
12.132 -
12.133 - virtual void _setRowLowerBound(int i, Value value);
12.134 - virtual Value _getRowLowerBound(int i) const;
12.135 -
12.136 - virtual void _setRowUpperBound(int i, Value value);
12.137 - virtual Value _getRowUpperBound(int i) const;
12.138 -
12.139 - virtual void _setObjCoeffs(ExprIterator b, ExprIterator e);
12.140 - virtual void _getObjCoeffs(InsertIterator b) const;
12.141 -
12.142 - virtual void _setObjCoeff(int i, Value obj_coef);
12.143 - virtual Value _getObjCoeff(int i) const;
12.144 -
12.145 - virtual void _setSense(Sense sense);
12.146 - virtual Sense _getSense() const;
12.147 -
12.148 - virtual void _clear();
12.149 -
12.150 - public:
12.151 -
12.152 - /// Returns the used \c CplexEnv instance
12.153 - const CplexEnv& env() const { return _env; }
12.154 - ///
12.155 - const cpxenv* cplexEnv() const { return _env.cplexEnv(); }
12.156 -
12.157 - cpxlp* cplexLp() { return _prob; }
12.158 - const cpxlp* cplexLp() const { return _prob; }
12.159 -
12.160 - };
12.161 -
12.162 - /// \brief Interface for the CPLEX LP solver
12.163 - ///
12.164 - /// This class implements an interface for the CPLEX LP solver.
12.165 - ///\ingroup lp_group
12.166 - class LpCplex : public CplexBase, public LpSolver {
12.167 - public:
12.168 - /// \e
12.169 - LpCplex();
12.170 - /// \e
12.171 - LpCplex(const CplexEnv&);
12.172 - /// \e
12.173 - LpCplex(const LpCplex&);
12.174 - /// \e
12.175 - virtual ~LpCplex();
12.176 -
12.177 - private:
12.178 -
12.179 - // these values cannot retrieved element by element
12.180 - mutable std::vector<int> _col_status;
12.181 - mutable std::vector<int> _row_status;
12.182 -
12.183 - mutable std::vector<Value> _primal_ray;
12.184 - mutable std::vector<Value> _dual_ray;
12.185 -
12.186 - void _clear_temporals();
12.187 -
12.188 - SolveExitStatus convertStatus(int status);
12.189 -
12.190 - protected:
12.191 -
12.192 - virtual LpCplex* _cloneSolver() const;
12.193 - virtual LpCplex* _newSolver() const;
12.194 -
12.195 - virtual const char* _solverName() const;
12.196 -
12.197 - virtual SolveExitStatus _solve();
12.198 - virtual Value _getPrimal(int i) const;
12.199 - virtual Value _getDual(int i) const;
12.200 - virtual Value _getPrimalValue() const;
12.201 -
12.202 - virtual VarStatus _getColStatus(int i) const;
12.203 - virtual VarStatus _getRowStatus(int i) const;
12.204 -
12.205 - virtual Value _getPrimalRay(int i) const;
12.206 - virtual Value _getDualRay(int i) const;
12.207 -
12.208 - virtual ProblemType _getPrimalType() const;
12.209 - virtual ProblemType _getDualType() const;
12.210 -
12.211 - public:
12.212 -
12.213 - /// Solve with primal simplex method
12.214 - SolveExitStatus solvePrimal();
12.215 -
12.216 - /// Solve with dual simplex method
12.217 - SolveExitStatus solveDual();
12.218 -
12.219 - /// Solve with barrier method
12.220 - SolveExitStatus solveBarrier();
12.221 -
12.222 - };
12.223 -
12.224 - /// \brief Interface for the CPLEX MIP solver
12.225 - ///
12.226 - /// This class implements an interface for the CPLEX MIP solver.
12.227 - ///\ingroup lp_group
12.228 - class MipCplex : public CplexBase, public MipSolver {
12.229 - public:
12.230 - /// \e
12.231 - MipCplex();
12.232 - /// \e
12.233 - MipCplex(const CplexEnv&);
12.234 - /// \e
12.235 - MipCplex(const MipCplex&);
12.236 - /// \e
12.237 - virtual ~MipCplex();
12.238 -
12.239 - protected:
12.240 -
12.241 - virtual MipCplex* _cloneSolver() const;
12.242 - virtual MipCplex* _newSolver() const;
12.243 -
12.244 - virtual const char* _solverName() const;
12.245 -
12.246 - virtual ColTypes _getColType(int col) const;
12.247 - virtual void _setColType(int col, ColTypes col_type);
12.248 -
12.249 - virtual SolveExitStatus _solve();
12.250 - virtual ProblemType _getType() const;
12.251 - virtual Value _getSol(int i) const;
12.252 - virtual Value _getSolValue() const;
12.253 -
12.254 - };
12.255 -
12.256 -} //END OF NAMESPACE LEMON
12.257 -
12.258 -#endif //LEMON_LP_CPLEX_H
12.259 -
13.1 --- a/lemon/lp_glpk.cc Mon Jan 12 12:25:55 2009 +0000
13.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
13.3 @@ -1,952 +0,0 @@
13.4 -/* -*- mode: C++; indent-tabs-mode: nil; -*-
13.5 - *
13.6 - * This file is a part of LEMON, a generic C++ optimization library.
13.7 - *
13.8 - * Copyright (C) 2003-2008
13.9 - * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
13.10 - * (Egervary Research Group on Combinatorial Optimization, EGRES).
13.11 - *
13.12 - * Permission to use, modify and distribute this software is granted
13.13 - * provided that this copyright notice appears in all copies. For
13.14 - * precise terms see the accompanying LICENSE file.
13.15 - *
13.16 - * This software is provided "AS IS" with no warranty of any kind,
13.17 - * express or implied, and with no claim as to its suitability for any
13.18 - * purpose.
13.19 - *
13.20 - */
13.21 -
13.22 -///\file
13.23 -///\brief Implementation of the LEMON GLPK LP and MIP solver interface.
13.24 -
13.25 -#include <lemon/lp_glpk.h>
13.26 -#include <glpk.h>
13.27 -
13.28 -#include <lemon/assert.h>
13.29 -
13.30 -namespace lemon {
13.31 -
13.32 - // GlpkBase members
13.33 -
13.34 - GlpkBase::GlpkBase() : LpBase() {
13.35 - lp = glp_create_prob();
13.36 - glp_create_index(lp);
13.37 - }
13.38 -
13.39 - GlpkBase::GlpkBase(const GlpkBase &other) : LpBase() {
13.40 - lp = glp_create_prob();
13.41 - glp_copy_prob(lp, other.lp, GLP_ON);
13.42 - glp_create_index(lp);
13.43 - rows = other.rows;
13.44 - cols = other.cols;
13.45 - }
13.46 -
13.47 - GlpkBase::~GlpkBase() {
13.48 - glp_delete_prob(lp);
13.49 - }
13.50 -
13.51 - int GlpkBase::_addCol() {
13.52 - int i = glp_add_cols(lp, 1);
13.53 - glp_set_col_bnds(lp, i, GLP_FR, 0.0, 0.0);
13.54 - return i;
13.55 - }
13.56 -
13.57 - int GlpkBase::_addRow() {
13.58 - int i = glp_add_rows(lp, 1);
13.59 - glp_set_row_bnds(lp, i, GLP_FR, 0.0, 0.0);
13.60 - return i;
13.61 - }
13.62 -
13.63 - void GlpkBase::_eraseCol(int i) {
13.64 - int ca[2];
13.65 - ca[1] = i;
13.66 - glp_del_cols(lp, 1, ca);
13.67 - }
13.68 -
13.69 - void GlpkBase::_eraseRow(int i) {
13.70 - int ra[2];
13.71 - ra[1] = i;
13.72 - glp_del_rows(lp, 1, ra);
13.73 - }
13.74 -
13.75 - void GlpkBase::_eraseColId(int i) {
13.76 - cols.eraseIndex(i);
13.77 - cols.shiftIndices(i);
13.78 - }
13.79 -
13.80 - void GlpkBase::_eraseRowId(int i) {
13.81 - rows.eraseIndex(i);
13.82 - rows.shiftIndices(i);
13.83 - }
13.84 -
13.85 - void GlpkBase::_getColName(int c, std::string& name) const {
13.86 - const char *str = glp_get_col_name(lp, c);
13.87 - if (str) name = str;
13.88 - else name.clear();
13.89 - }
13.90 -
13.91 - void GlpkBase::_setColName(int c, const std::string & name) {
13.92 - glp_set_col_name(lp, c, const_cast<char*>(name.c_str()));
13.93 -
13.94 - }
13.95 -
13.96 - int GlpkBase::_colByName(const std::string& name) const {
13.97 - int k = glp_find_col(lp, const_cast<char*>(name.c_str()));
13.98 - return k > 0 ? k : -1;
13.99 - }
13.100 -
13.101 - void GlpkBase::_getRowName(int r, std::string& name) const {
13.102 - const char *str = glp_get_row_name(lp, r);
13.103 - if (str) name = str;
13.104 - else name.clear();
13.105 - }
13.106 -
13.107 - void GlpkBase::_setRowName(int r, const std::string & name) {
13.108 - glp_set_row_name(lp, r, const_cast<char*>(name.c_str()));
13.109 -
13.110 - }
13.111 -
13.112 - int GlpkBase::_rowByName(const std::string& name) const {
13.113 - int k = glp_find_row(lp, const_cast<char*>(name.c_str()));
13.114 - return k > 0 ? k : -1;
13.115 - }
13.116 -
13.117 - void GlpkBase::_setRowCoeffs(int i, ExprIterator b, ExprIterator e) {
13.118 - std::vector<int> indexes;
13.119 - std::vector<Value> values;
13.120 -
13.121 - indexes.push_back(0);
13.122 - values.push_back(0);
13.123 -
13.124 - for(ExprIterator it = b; it != e; ++it) {
13.125 - indexes.push_back(it->first);
13.126 - values.push_back(it->second);
13.127 - }
13.128 -
13.129 - glp_set_mat_row(lp, i, values.size() - 1,
13.130 - &indexes.front(), &values.front());
13.131 - }
13.132 -
13.133 - void GlpkBase::_getRowCoeffs(int ix, InsertIterator b) const {
13.134 - int length = glp_get_mat_row(lp, ix, 0, 0);
13.135 -
13.136 - std::vector<int> indexes(length + 1);
13.137 - std::vector<Value> values(length + 1);
13.138 -
13.139 - glp_get_mat_row(lp, ix, &indexes.front(), &values.front());
13.140 -
13.141 - for (int i = 1; i <= length; ++i) {
13.142 - *b = std::make_pair(indexes[i], values[i]);
13.143 - ++b;
13.144 - }
13.145 - }
13.146 -
13.147 - void GlpkBase::_setColCoeffs(int ix, ExprIterator b,
13.148 - ExprIterator e) {
13.149 -
13.150 - std::vector<int> indexes;
13.151 - std::vector<Value> values;
13.152 -
13.153 - indexes.push_back(0);
13.154 - values.push_back(0);
13.155 -
13.156 - for(ExprIterator it = b; it != e; ++it) {
13.157 - indexes.push_back(it->first);
13.158 - values.push_back(it->second);
13.159 - }
13.160 -
13.161 - glp_set_mat_col(lp, ix, values.size() - 1,
13.162 - &indexes.front(), &values.front());
13.163 - }
13.164 -
13.165 - void GlpkBase::_getColCoeffs(int ix, InsertIterator b) const {
13.166 - int length = glp_get_mat_col(lp, ix, 0, 0);
13.167 -
13.168 - std::vector<int> indexes(length + 1);
13.169 - std::vector<Value> values(length + 1);
13.170 -
13.171 - glp_get_mat_col(lp, ix, &indexes.front(), &values.front());
13.172 -
13.173 - for (int i = 1; i <= length; ++i) {
13.174 - *b = std::make_pair(indexes[i], values[i]);
13.175 - ++b;
13.176 - }
13.177 - }
13.178 -
13.179 - void GlpkBase::_setCoeff(int ix, int jx, Value value) {
13.180 -
13.181 - if (glp_get_num_cols(lp) < glp_get_num_rows(lp)) {
13.182 -
13.183 - int length = glp_get_mat_row(lp, ix, 0, 0);
13.184 -
13.185 - std::vector<int> indexes(length + 2);
13.186 - std::vector<Value> values(length + 2);
13.187 -
13.188 - glp_get_mat_row(lp, ix, &indexes.front(), &values.front());
13.189 -
13.190 - //The following code does not suppose that the elements of the
13.191 - //array indexes are sorted
13.192 - bool found = false;
13.193 - for (int i = 1; i <= length; ++i) {
13.194 - if (indexes[i] == jx) {
13.195 - found = true;
13.196 - values[i] = value;
13.197 - break;
13.198 - }
13.199 - }
13.200 - if (!found) {
13.201 - ++length;
13.202 - indexes[length] = jx;
13.203 - values[length] = value;
13.204 - }
13.205 -
13.206 - glp_set_mat_row(lp, ix, length, &indexes.front(), &values.front());
13.207 -
13.208 - } else {
13.209 -
13.210 - int length = glp_get_mat_col(lp, jx, 0, 0);
13.211 -
13.212 - std::vector<int> indexes(length + 2);
13.213 - std::vector<Value> values(length + 2);
13.214 -
13.215 - glp_get_mat_col(lp, jx, &indexes.front(), &values.front());
13.216 -
13.217 - //The following code does not suppose that the elements of the
13.218 - //array indexes are sorted
13.219 - bool found = false;
13.220 - for (int i = 1; i <= length; ++i) {
13.221 - if (indexes[i] == ix) {
13.222 - found = true;
13.223 - values[i] = value;
13.224 - break;
13.225 - }
13.226 - }
13.227 - if (!found) {
13.228 - ++length;
13.229 - indexes[length] = ix;
13.230 - values[length] = value;
13.231 - }
13.232 -
13.233 - glp_set_mat_col(lp, jx, length, &indexes.front(), &values.front());
13.234 - }
13.235 -
13.236 - }
13.237 -
13.238 - GlpkBase::Value GlpkBase::_getCoeff(int ix, int jx) const {
13.239 -
13.240 - int length = glp_get_mat_row(lp, ix, 0, 0);
13.241 -
13.242 - std::vector<int> indexes(length + 1);
13.243 - std::vector<Value> values(length + 1);
13.244 -
13.245 - glp_get_mat_row(lp, ix, &indexes.front(), &values.front());
13.246 -
13.247 - for (int i = 1; i <= length; ++i) {
13.248 - if (indexes[i] == jx) {
13.249 - return values[i];
13.250 - }
13.251 - }
13.252 -
13.253 - return 0;
13.254 - }
13.255 -
13.256 - void GlpkBase::_setColLowerBound(int i, Value lo) {
13.257 - LEMON_ASSERT(lo != INF, "Invalid bound");
13.258 -
13.259 - int b = glp_get_col_type(lp, i);
13.260 - double up = glp_get_col_ub(lp, i);
13.261 - if (lo == -INF) {
13.262 - switch (b) {
13.263 - case GLP_FR:
13.264 - case GLP_LO:
13.265 - glp_set_col_bnds(lp, i, GLP_FR, lo, up);
13.266 - break;
13.267 - case GLP_UP:
13.268 - break;
13.269 - case GLP_DB:
13.270 - case GLP_FX:
13.271 - glp_set_col_bnds(lp, i, GLP_UP, lo, up);
13.272 - break;
13.273 - default:
13.274 - break;
13.275 - }
13.276 - } else {
13.277 - switch (b) {
13.278 - case GLP_FR:
13.279 - case GLP_LO:
13.280 - glp_set_col_bnds(lp, i, GLP_LO, lo, up);
13.281 - break;
13.282 - case GLP_UP:
13.283 - case GLP_DB:
13.284 - case GLP_FX:
13.285 - if (lo == up)
13.286 - glp_set_col_bnds(lp, i, GLP_FX, lo, up);
13.287 - else
13.288 - glp_set_col_bnds(lp, i, GLP_DB, lo, up);
13.289 - break;
13.290 - default:
13.291 - break;
13.292 - }
13.293 - }
13.294 - }
13.295 -
13.296 - GlpkBase::Value GlpkBase::_getColLowerBound(int i) const {
13.297 - int b = glp_get_col_type(lp, i);
13.298 - switch (b) {
13.299 - case GLP_LO:
13.300 - case GLP_DB:
13.301 - case GLP_FX:
13.302 - return glp_get_col_lb(lp, i);
13.303 - default:
13.304 - return -INF;
13.305 - }
13.306 - }
13.307 -
13.308 - void GlpkBase::_setColUpperBound(int i, Value up) {
13.309 - LEMON_ASSERT(up != -INF, "Invalid bound");
13.310 -
13.311 - int b = glp_get_col_type(lp, i);
13.312 - double lo = glp_get_col_lb(lp, i);
13.313 - if (up == INF) {
13.314 - switch (b) {
13.315 - case GLP_FR:
13.316 - case GLP_LO:
13.317 - break;
13.318 - case GLP_UP:
13.319 - glp_set_col_bnds(lp, i, GLP_FR, lo, up);
13.320 - break;
13.321 - case GLP_DB:
13.322 - case GLP_FX:
13.323 - glp_set_col_bnds(lp, i, GLP_LO, lo, up);
13.324 - break;
13.325 - default:
13.326 - break;
13.327 - }
13.328 - } else {
13.329 - switch (b) {
13.330 - case GLP_FR:
13.331 - glp_set_col_bnds(lp, i, GLP_UP, lo, up);
13.332 - break;
13.333 - case GLP_UP:
13.334 - glp_set_col_bnds(lp, i, GLP_UP, lo, up);
13.335 - break;
13.336 - case GLP_LO:
13.337 - case GLP_DB:
13.338 - case GLP_FX:
13.339 - if (lo == up)
13.340 - glp_set_col_bnds(lp, i, GLP_FX, lo, up);
13.341 - else
13.342 - glp_set_col_bnds(lp, i, GLP_DB, lo, up);
13.343 - break;
13.344 - default:
13.345 - break;
13.346 - }
13.347 - }
13.348 -
13.349 - }
13.350 -
13.351 - GlpkBase::Value GlpkBase::_getColUpperBound(int i) const {
13.352 - int b = glp_get_col_type(lp, i);
13.353 - switch (b) {
13.354 - case GLP_UP:
13.355 - case GLP_DB:
13.356 - case GLP_FX:
13.357 - return glp_get_col_ub(lp, i);
13.358 - default:
13.359 - return INF;
13.360 - }
13.361 - }
13.362 -
13.363 - void GlpkBase::_setRowLowerBound(int i, Value lo) {
13.364 - LEMON_ASSERT(lo != INF, "Invalid bound");
13.365 -
13.366 - int b = glp_get_row_type(lp, i);
13.367 - double up = glp_get_row_ub(lp, i);
13.368 - if (lo == -INF) {
13.369 - switch (b) {
13.370 - case GLP_FR:
13.371 - case GLP_LO:
13.372 - glp_set_row_bnds(lp, i, GLP_FR, lo, up);
13.373 - break;
13.374 - case GLP_UP:
13.375 - break;
13.376 - case GLP_DB:
13.377 - case GLP_FX:
13.378 - glp_set_row_bnds(lp, i, GLP_UP, lo, up);
13.379 - break;
13.380 - default:
13.381 - break;
13.382 - }
13.383 - } else {
13.384 - switch (b) {
13.385 - case GLP_FR:
13.386 - case GLP_LO:
13.387 - glp_set_row_bnds(lp, i, GLP_LO, lo, up);
13.388 - break;
13.389 - case GLP_UP:
13.390 - case GLP_DB:
13.391 - case GLP_FX:
13.392 - if (lo == up)
13.393 - glp_set_row_bnds(lp, i, GLP_FX, lo, up);
13.394 - else
13.395 - glp_set_row_bnds(lp, i, GLP_DB, lo, up);
13.396 - break;
13.397 - default:
13.398 - break;
13.399 - }
13.400 - }
13.401 -
13.402 - }
13.403 -
13.404 - GlpkBase::Value GlpkBase::_getRowLowerBound(int i) const {
13.405 - int b = glp_get_row_type(lp, i);
13.406 - switch (b) {
13.407 - case GLP_LO:
13.408 - case GLP_DB:
13.409 - case GLP_FX:
13.410 - return glp_get_row_lb(lp, i);
13.411 - default:
13.412 - return -INF;
13.413 - }
13.414 - }
13.415 -
13.416 - void GlpkBase::_setRowUpperBound(int i, Value up) {
13.417 - LEMON_ASSERT(up != -INF, "Invalid bound");
13.418 -
13.419 - int b = glp_get_row_type(lp, i);
13.420 - double lo = glp_get_row_lb(lp, i);
13.421 - if (up == INF) {
13.422 - switch (b) {
13.423 - case GLP_FR:
13.424 - case GLP_LO:
13.425 - break;
13.426 - case GLP_UP:
13.427 - glp_set_row_bnds(lp, i, GLP_FR, lo, up);
13.428 - break;
13.429 - case GLP_DB:
13.430 - case GLP_FX:
13.431 - glp_set_row_bnds(lp, i, GLP_LO, lo, up);
13.432 - break;
13.433 - default:
13.434 - break;
13.435 - }
13.436 - } else {
13.437 - switch (b) {
13.438 - case GLP_FR:
13.439 - glp_set_row_bnds(lp, i, GLP_UP, lo, up);
13.440 - break;
13.441 - case GLP_UP:
13.442 - glp_set_row_bnds(lp, i, GLP_UP, lo, up);
13.443 - break;
13.444 - case GLP_LO:
13.445 - case GLP_DB:
13.446 - case GLP_FX:
13.447 - if (lo == up)
13.448 - glp_set_row_bnds(lp, i, GLP_FX, lo, up);
13.449 - else
13.450 - glp_set_row_bnds(lp, i, GLP_DB, lo, up);
13.451 - break;
13.452 - default:
13.453 - break;
13.454 - }
13.455 - }
13.456 - }
13.457 -
13.458 - GlpkBase::Value GlpkBase::_getRowUpperBound(int i) const {
13.459 - int b = glp_get_row_type(lp, i);
13.460 - switch (b) {
13.461 - case GLP_UP:
13.462 - case GLP_DB:
13.463 - case GLP_FX:
13.464 - return glp_get_row_ub(lp, i);
13.465 - default:
13.466 - return INF;
13.467 - }
13.468 - }
13.469 -
13.470 - void GlpkBase::_setObjCoeffs(ExprIterator b, ExprIterator e) {
13.471 - for (int i = 1; i <= glp_get_num_cols(lp); ++i) {
13.472 - glp_set_obj_coef(lp, i, 0.0);
13.473 - }
13.474 - for (ExprIterator it = b; it != e; ++it) {
13.475 - glp_set_obj_coef(lp, it->first, it->second);
13.476 - }
13.477 - }
13.478 -
13.479 - void GlpkBase::_getObjCoeffs(InsertIterator b) const {
13.480 - for (int i = 1; i <= glp_get_num_cols(lp); ++i) {
13.481 - Value val = glp_get_obj_coef(lp, i);
13.482 - if (val != 0.0) {
13.483 - *b = std::make_pair(i, val);
13.484 - ++b;
13.485 - }
13.486 - }
13.487 - }
13.488 -
13.489 - void GlpkBase::_setObjCoeff(int i, Value obj_coef) {
13.490 - //i = 0 means the constant term (shift)
13.491 - glp_set_obj_coef(lp, i, obj_coef);
13.492 - }
13.493 -
13.494 - GlpkBase::Value GlpkBase::_getObjCoeff(int i) const {
13.495 - //i = 0 means the constant term (shift)
13.496 - return glp_get_obj_coef(lp, i);
13.497 - }
13.498 -
13.499 - void GlpkBase::_setSense(GlpkBase::Sense sense) {
13.500 - switch (sense) {
13.501 - case MIN:
13.502 - glp_set_obj_dir(lp, GLP_MIN);
13.503 - break;
13.504 - case MAX:
13.505 - glp_set_obj_dir(lp, GLP_MAX);
13.506 - break;
13.507 - }
13.508 - }
13.509 -
13.510 - GlpkBase::Sense GlpkBase::_getSense() const {
13.511 - switch(glp_get_obj_dir(lp)) {
13.512 - case GLP_MIN:
13.513 - return MIN;
13.514 - case GLP_MAX:
13.515 - return MAX;
13.516 - default:
13.517 - LEMON_ASSERT(false, "Wrong sense");
13.518 - return GlpkBase::Sense();
13.519 - }
13.520 - }
13.521 -
13.522 - void GlpkBase::_clear() {
13.523 - glp_erase_prob(lp);
13.524 - rows.clear();
13.525 - cols.clear();
13.526 - }
13.527 -
13.528 - // LpGlpk members
13.529 -
13.530 - LpGlpk::LpGlpk()
13.531 - : LpBase(), GlpkBase(), LpSolver() {
13.532 - messageLevel(MESSAGE_NO_OUTPUT);
13.533 - }
13.534 -
13.535 - LpGlpk::LpGlpk(const LpGlpk& other)
13.536 - : LpBase(other), GlpkBase(other), LpSolver(other) {
13.537 - messageLevel(MESSAGE_NO_OUTPUT);
13.538 - }
13.539 -
13.540 - LpGlpk* LpGlpk::_newSolver() const { return new LpGlpk; }
13.541 - LpGlpk* LpGlpk::_cloneSolver() const { return new LpGlpk(*this); }
13.542 -
13.543 - const char* LpGlpk::_solverName() const { return "LpGlpk"; }
13.544 -
13.545 - void LpGlpk::_clear_temporals() {
13.546 - _primal_ray.clear();
13.547 - _dual_ray.clear();
13.548 - }
13.549 -
13.550 - LpGlpk::SolveExitStatus LpGlpk::_solve() {
13.551 - return solvePrimal();
13.552 - }
13.553 -
13.554 - LpGlpk::SolveExitStatus LpGlpk::solvePrimal() {
13.555 - _clear_temporals();
13.556 -
13.557 - glp_smcp smcp;
13.558 - glp_init_smcp(&smcp);
13.559 -
13.560 - switch (_message_level) {
13.561 - case MESSAGE_NO_OUTPUT:
13.562 - smcp.msg_lev = GLP_MSG_OFF;
13.563 - break;
13.564 - case MESSAGE_ERROR_MESSAGE:
13.565 - smcp.msg_lev = GLP_MSG_ERR;
13.566 - break;
13.567 - case MESSAGE_NORMAL_OUTPUT:
13.568 - smcp.msg_lev = GLP_MSG_ON;
13.569 - break;
13.570 - case MESSAGE_FULL_OUTPUT:
13.571 - smcp.msg_lev = GLP_MSG_ALL;
13.572 - break;
13.573 - }
13.574 -
13.575 - if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
13.576 - return SOLVED;
13.577 - }
13.578 -
13.579 - LpGlpk::SolveExitStatus LpGlpk::solveDual() {
13.580 - _clear_temporals();
13.581 -
13.582 - glp_smcp smcp;
13.583 - glp_init_smcp(&smcp);
13.584 -
13.585 - switch (_message_level) {
13.586 - case MESSAGE_NO_OUTPUT:
13.587 - smcp.msg_lev = GLP_MSG_OFF;
13.588 - break;
13.589 - case MESSAGE_ERROR_MESSAGE:
13.590 - smcp.msg_lev = GLP_MSG_ERR;
13.591 - break;
13.592 - case MESSAGE_NORMAL_OUTPUT:
13.593 - smcp.msg_lev = GLP_MSG_ON;
13.594 - break;
13.595 - case MESSAGE_FULL_OUTPUT:
13.596 - smcp.msg_lev = GLP_MSG_ALL;
13.597 - break;
13.598 - }
13.599 - smcp.meth = GLP_DUAL;
13.600 -
13.601 - if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
13.602 - return SOLVED;
13.603 - }
13.604 -
13.605 - LpGlpk::Value LpGlpk::_getPrimal(int i) const {
13.606 - return glp_get_col_prim(lp, i);
13.607 - }
13.608 -
13.609 - LpGlpk::Value LpGlpk::_getDual(int i) const {
13.610 - return glp_get_row_dual(lp, i);
13.611 - }
13.612 -
13.613 - LpGlpk::Value LpGlpk::_getPrimalValue() const {
13.614 - return glp_get_obj_val(lp);
13.615 - }
13.616 -
13.617 - LpGlpk::VarStatus LpGlpk::_getColStatus(int i) const {
13.618 - switch (glp_get_col_stat(lp, i)) {
13.619 - case GLP_BS:
13.620 - return BASIC;
13.621 - case GLP_UP:
13.622 - return UPPER;
13.623 - case GLP_LO:
13.624 - return LOWER;
13.625 - case GLP_NF:
13.626 - return FREE;
13.627 - case GLP_NS:
13.628 - return FIXED;
13.629 - default:
13.630 - LEMON_ASSERT(false, "Wrong column status");
13.631 - return LpGlpk::VarStatus();
13.632 - }
13.633 - }
13.634 -
13.635 - LpGlpk::VarStatus LpGlpk::_getRowStatus(int i) const {
13.636 - switch (glp_get_row_stat(lp, i)) {
13.637 - case GLP_BS:
13.638 - return BASIC;
13.639 - case GLP_UP:
13.640 - return UPPER;
13.641 - case GLP_LO:
13.642 - return LOWER;
13.643 - case GLP_NF:
13.644 - return FREE;
13.645 - case GLP_NS:
13.646 - return FIXED;
13.647 - default:
13.648 - LEMON_ASSERT(false, "Wrong row status");
13.649 - return LpGlpk::VarStatus();
13.650 - }
13.651 - }
13.652 -
13.653 - LpGlpk::Value LpGlpk::_getPrimalRay(int i) const {
13.654 - if (_primal_ray.empty()) {
13.655 - int row_num = glp_get_num_rows(lp);
13.656 - int col_num = glp_get_num_cols(lp);
13.657 -
13.658 - _primal_ray.resize(col_num + 1, 0.0);
13.659 -
13.660 - int index = glp_get_unbnd_ray(lp);
13.661 - if (index != 0) {
13.662 - // The primal ray is found in primal simplex second phase
13.663 - LEMON_ASSERT((index <= row_num ? glp_get_row_stat(lp, index) :
13.664 - glp_get_col_stat(lp, index - row_num)) != GLP_BS,
13.665 - "Wrong primal ray");
13.666 -
13.667 - bool negate = glp_get_obj_dir(lp) == GLP_MAX;
13.668 -
13.669 - if (index > row_num) {
13.670 - _primal_ray[index - row_num] = 1.0;
13.671 - if (glp_get_col_dual(lp, index - row_num) > 0) {
13.672 - negate = !negate;
13.673 - }
13.674 - } else {
13.675 - if (glp_get_row_dual(lp, index) > 0) {
13.676 - negate = !negate;
13.677 - }
13.678 - }
13.679 -
13.680 - std::vector<int> ray_indexes(row_num + 1);
13.681 - std::vector<Value> ray_values(row_num + 1);
13.682 - int ray_length = glp_eval_tab_col(lp, index, &ray_indexes.front(),
13.683 - &ray_values.front());
13.684 -
13.685 - for (int i = 1; i <= ray_length; ++i) {
13.686 - if (ray_indexes[i] > row_num) {
13.687 - _primal_ray[ray_indexes[i] - row_num] = ray_values[i];
13.688 - }
13.689 - }
13.690 -
13.691 - if (negate) {
13.692 - for (int i = 1; i <= col_num; ++i) {
13.693 - _primal_ray[i] = - _primal_ray[i];
13.694 - }
13.695 - }
13.696 - } else {
13.697 - for (int i = 1; i <= col_num; ++i) {
13.698 - _primal_ray[i] = glp_get_col_prim(lp, i);
13.699 - }
13.700 - }
13.701 - }
13.702 - return _primal_ray[i];
13.703 - }
13.704 -
13.705 - LpGlpk::Value LpGlpk::_getDualRay(int i) const {
13.706 - if (_dual_ray.empty()) {
13.707 - int row_num = glp_get_num_rows(lp);
13.708 -
13.709 - _dual_ray.resize(row_num + 1, 0.0);
13.710 -
13.711 - int index = glp_get_unbnd_ray(lp);
13.712 - if (index != 0) {
13.713 - // The dual ray is found in dual simplex second phase
13.714 - LEMON_ASSERT((index <= row_num ? glp_get_row_stat(lp, index) :
13.715 - glp_get_col_stat(lp, index - row_num)) == GLP_BS,
13.716 -
13.717 - "Wrong dual ray");
13.718 -
13.719 - int idx;
13.720 - bool negate = false;
13.721 -
13.722 - if (index > row_num) {
13.723 - idx = glp_get_col_bind(lp, index - row_num);
13.724 - if (glp_get_col_prim(lp, index - row_num) >
13.725 - glp_get_col_ub(lp, index - row_num)) {
13.726 - negate = true;
13.727 - }
13.728 - } else {
13.729 - idx = glp_get_row_bind(lp, index);
13.730 - if (glp_get_row_prim(lp, index) > glp_get_row_ub(lp, index)) {
13.731 - negate = true;
13.732 - }
13.733 - }
13.734 -
13.735 - _dual_ray[idx] = negate ? - 1.0 : 1.0;
13.736 -
13.737 - glp_btran(lp, &_dual_ray.front());
13.738 - } else {
13.739 - double eps = 1e-7;
13.740 - // The dual ray is found in primal simplex first phase
13.741 - // We assume that the glpk minimizes the slack to get feasible solution
13.742 - for (int i = 1; i <= row_num; ++i) {
13.743 - int index = glp_get_bhead(lp, i);
13.744 - if (index <= row_num) {
13.745 - double res = glp_get_row_prim(lp, index);
13.746 - if (res > glp_get_row_ub(lp, index) + eps) {
13.747 - _dual_ray[i] = -1;
13.748 - } else if (res < glp_get_row_lb(lp, index) - eps) {
13.749 - _dual_ray[i] = 1;
13.750 - } else {
13.751 - _dual_ray[i] = 0;
13.752 - }
13.753 - _dual_ray[i] *= glp_get_rii(lp, index);
13.754 - } else {
13.755 - double res = glp_get_col_prim(lp, index - row_num);
13.756 - if (res > glp_get_col_ub(lp, index - row_num) + eps) {
13.757 - _dual_ray[i] = -1;
13.758 - } else if (res < glp_get_col_lb(lp, index - row_num) - eps) {
13.759 - _dual_ray[i] = 1;
13.760 - } else {
13.761 - _dual_ray[i] = 0;
13.762 - }
13.763 - _dual_ray[i] /= glp_get_sjj(lp, index - row_num);
13.764 - }
13.765 - }
13.766 -
13.767 - glp_btran(lp, &_dual_ray.front());
13.768 -
13.769 - for (int i = 1; i <= row_num; ++i) {
13.770 - _dual_ray[i] /= glp_get_rii(lp, i);
13.771 - }
13.772 - }
13.773 - }
13.774 - return _dual_ray[i];
13.775 - }
13.776 -
13.777 - LpGlpk::ProblemType LpGlpk::_getPrimalType() const {
13.778 - if (glp_get_status(lp) == GLP_OPT)
13.779 - return OPTIMAL;
13.780 - switch (glp_get_prim_stat(lp)) {
13.781 - case GLP_UNDEF:
13.782 - return UNDEFINED;
13.783 - case GLP_FEAS:
13.784 - case GLP_INFEAS:
13.785 - if (glp_get_dual_stat(lp) == GLP_NOFEAS) {
13.786 - return UNBOUNDED;
13.787 - } else {
13.788 - return UNDEFINED;
13.789 - }
13.790 - case GLP_NOFEAS:
13.791 - return INFEASIBLE;
13.792 - default:
13.793 - LEMON_ASSERT(false, "Wrong primal type");
13.794 - return LpGlpk::ProblemType();
13.795 - }
13.796 - }
13.797 -
13.798 - LpGlpk::ProblemType LpGlpk::_getDualType() const {
13.799 - if (glp_get_status(lp) == GLP_OPT)
13.800 - return OPTIMAL;
13.801 - switch (glp_get_dual_stat(lp)) {
13.802 - case GLP_UNDEF:
13.803 - return UNDEFINED;
13.804 - case GLP_FEAS:
13.805 - case GLP_INFEAS:
13.806 - if (glp_get_prim_stat(lp) == GLP_NOFEAS) {
13.807 - return UNBOUNDED;
13.808 - } else {
13.809 - return UNDEFINED;
13.810 - }
13.811 - case GLP_NOFEAS:
13.812 - return INFEASIBLE;
13.813 - default:
13.814 - LEMON_ASSERT(false, "Wrong primal type");
13.815 - return LpGlpk::ProblemType();
13.816 - }
13.817 - }
13.818 -
13.819 - void LpGlpk::presolver(bool b) {
13.820 - lpx_set_int_parm(lp, LPX_K_PRESOL, b ? 1 : 0);
13.821 - }
13.822 -
13.823 - void LpGlpk::messageLevel(MessageLevel m) {
13.824 - _message_level = m;
13.825 - }
13.826 -
13.827 - // MipGlpk members
13.828 -
13.829 - MipGlpk::MipGlpk()
13.830 - : LpBase(), GlpkBase(), MipSolver() {
13.831 - messageLevel(MESSAGE_NO_OUTPUT);
13.832 - }
13.833 -
13.834 - MipGlpk::MipGlpk(const MipGlpk& other)
13.835 - : LpBase(), GlpkBase(other), MipSolver() {
13.836 - messageLevel(MESSAGE_NO_OUTPUT);
13.837 - }
13.838 -
13.839 - void MipGlpk::_setColType(int i, MipGlpk::ColTypes col_type) {
13.840 - switch (col_type) {
13.841 - case INTEGER:
13.842 - glp_set_col_kind(lp, i, GLP_IV);
13.843 - break;
13.844 - case REAL:
13.845 - glp_set_col_kind(lp, i, GLP_CV);
13.846 - break;
13.847 - }
13.848 - }
13.849 -
13.850 - MipGlpk::ColTypes MipGlpk::_getColType(int i) const {
13.851 - switch (glp_get_col_kind(lp, i)) {
13.852 - case GLP_IV:
13.853 - case GLP_BV:
13.854 - return INTEGER;
13.855 - default:
13.856 - return REAL;
13.857 - }
13.858 -
13.859 - }
13.860 -
13.861 - MipGlpk::SolveExitStatus MipGlpk::_solve() {
13.862 - glp_smcp smcp;
13.863 - glp_init_smcp(&smcp);
13.864 -
13.865 - switch (_message_level) {
13.866 - case MESSAGE_NO_OUTPUT:
13.867 - smcp.msg_lev = GLP_MSG_OFF;
13.868 - break;
13.869 - case MESSAGE_ERROR_MESSAGE:
13.870 - smcp.msg_lev = GLP_MSG_ERR;
13.871 - break;
13.872 - case MESSAGE_NORMAL_OUTPUT:
13.873 - smcp.msg_lev = GLP_MSG_ON;
13.874 - break;
13.875 - case MESSAGE_FULL_OUTPUT:
13.876 - smcp.msg_lev = GLP_MSG_ALL;
13.877 - break;
13.878 - }
13.879 - smcp.meth = GLP_DUAL;
13.880 -
13.881 - if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
13.882 - if (glp_get_status(lp) != GLP_OPT) return SOLVED;
13.883 -
13.884 - glp_iocp iocp;
13.885 - glp_init_iocp(&iocp);
13.886 -
13.887 - switch (_message_level) {
13.888 - case MESSAGE_NO_OUTPUT:
13.889 - iocp.msg_lev = GLP_MSG_OFF;
13.890 - break;
13.891 - case MESSAGE_ERROR_MESSAGE:
13.892 - iocp.msg_lev = GLP_MSG_ERR;
13.893 - break;
13.894 - case MESSAGE_NORMAL_OUTPUT:
13.895 - iocp.msg_lev = GLP_MSG_ON;
13.896 - break;
13.897 - case MESSAGE_FULL_OUTPUT:
13.898 - iocp.msg_lev = GLP_MSG_ALL;
13.899 - break;
13.900 - }
13.901 -
13.902 - if (glp_intopt(lp, &iocp) != 0) return UNSOLVED;
13.903 - return SOLVED;
13.904 - }
13.905 -
13.906 -
13.907 - MipGlpk::ProblemType MipGlpk::_getType() const {
13.908 - switch (glp_get_status(lp)) {
13.909 - case GLP_OPT:
13.910 - switch (glp_mip_status(lp)) {
13.911 - case GLP_UNDEF:
13.912 - return UNDEFINED;
13.913 - case GLP_NOFEAS:
13.914 - return INFEASIBLE;
13.915 - case GLP_FEAS:
13.916 - return FEASIBLE;
13.917 - case GLP_OPT:
13.918 - return OPTIMAL;
13.919 - default:
13.920 - LEMON_ASSERT(false, "Wrong problem type.");
13.921 - return MipGlpk::ProblemType();
13.922 - }
13.923 - case GLP_NOFEAS:
13.924 - return INFEASIBLE;
13.925 - case GLP_INFEAS:
13.926 - case GLP_FEAS:
13.927 - if (glp_get_dual_stat(lp) == GLP_NOFEAS) {
13.928 - return UNBOUNDED;
13.929 - } else {
13.930 - return UNDEFINED;
13.931 - }
13.932 - default:
13.933 - LEMON_ASSERT(false, "Wrong problem type.");
13.934 - return MipGlpk::ProblemType();
13.935 - }
13.936 - }
13.937 -
13.938 - MipGlpk::Value MipGlpk::_getSol(int i) const {
13.939 - return glp_mip_col_val(lp, i);
13.940 - }
13.941 -
13.942 - MipGlpk::Value MipGlpk::_getSolValue() const {
13.943 - return glp_mip_obj_val(lp);
13.944 - }
13.945 -
13.946 - MipGlpk* MipGlpk::_newSolver() const { return new MipGlpk; }
13.947 - MipGlpk* MipGlpk::_cloneSolver() const {return new MipGlpk(*this); }
13.948 -
13.949 - const char* MipGlpk::_solverName() const { return "MipGlpk"; }
13.950 -
13.951 - void MipGlpk::messageLevel(MessageLevel m) {
13.952 - _message_level = m;
13.953 - }
13.954 -
13.955 -} //END OF NAMESPACE LEMON
14.1 --- a/lemon/lp_glpk.h Mon Jan 12 12:25:55 2009 +0000
14.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
14.3 @@ -1,259 +0,0 @@
14.4 -/* -*- mode: C++; indent-tabs-mode: nil; -*-
14.5 - *
14.6 - * This file is a part of LEMON, a generic C++ optimization library.
14.7 - *
14.8 - * Copyright (C) 2003-2008
14.9 - * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
14.10 - * (Egervary Research Group on Combinatorial Optimization, EGRES).
14.11 - *
14.12 - * Permission to use, modify and distribute this software is granted
14.13 - * provided that this copyright notice appears in all copies. For
14.14 - * precise terms see the accompanying LICENSE file.
14.15 - *
14.16 - * This software is provided "AS IS" with no warranty of any kind,
14.17 - * express or implied, and with no claim as to its suitability for any
14.18 - * purpose.
14.19 - *
14.20 - */
14.21 -
14.22 -#ifndef LEMON_LP_GLPK_H
14.23 -#define LEMON_LP_GLPK_H
14.24 -
14.25 -///\file
14.26 -///\brief Header of the LEMON-GLPK lp solver interface.
14.27 -///\ingroup lp_group
14.28 -
14.29 -#include <lemon/lp_base.h>
14.30 -
14.31 -// forward declaration
14.32 -#ifndef _GLP_PROB
14.33 -#define _GLP_PROB
14.34 -typedef struct { double _prob; } glp_prob;
14.35 -/* LP/MIP problem object */
14.36 -#endif
14.37 -
14.38 -namespace lemon {
14.39 -
14.40 -
14.41 - /// \brief Base interface for the GLPK LP and MIP solver
14.42 - ///
14.43 - /// This class implements the common interface of the GLPK LP and MIP solver.
14.44 - /// \ingroup lp_group
14.45 - class GlpkBase : virtual public LpBase {
14.46 - protected:
14.47 -
14.48 - typedef glp_prob LPX;
14.49 - glp_prob* lp;
14.50 -
14.51 - GlpkBase();
14.52 - GlpkBase(const GlpkBase&);
14.53 - virtual ~GlpkBase();
14.54 -
14.55 - protected:
14.56 -
14.57 - virtual int _addCol();
14.58 - virtual int _addRow();
14.59 -
14.60 - virtual void _eraseCol(int i);
14.61 - virtual void _eraseRow(int i);
14.62 -
14.63 - virtual void _eraseColId(int i);
14.64 - virtual void _eraseRowId(int i);
14.65 -
14.66 - virtual void _getColName(int col, std::string& name) const;
14.67 - virtual void _setColName(int col, const std::string& name);
14.68 - virtual int _colByName(const std::string& name) const;
14.69 -
14.70 - virtual void _getRowName(int row, std::string& name) const;
14.71 - virtual void _setRowName(int row, const std::string& name);
14.72 - virtual int _rowByName(const std::string& name) const;
14.73 -
14.74 - virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
14.75 - virtual void _getRowCoeffs(int i, InsertIterator b) const;
14.76 -
14.77 - virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
14.78 - virtual void _getColCoeffs(int i, InsertIterator b) const;
14.79 -
14.80 - virtual void _setCoeff(int row, int col, Value value);
14.81 - virtual Value _getCoeff(int row, int col) const;
14.82 -
14.83 - virtual void _setColLowerBound(int i, Value value);
14.84 - virtual Value _getColLowerBound(int i) const;
14.85 -
14.86 - virtual void _setColUpperBound(int i, Value value);
14.87 - virtual Value _getColUpperBound(int i) const;
14.88 -
14.89 - virtual void _setRowLowerBound(int i, Value value);
14.90 - virtual Value _getRowLowerBound(int i) const;
14.91 -
14.92 - virtual void _setRowUpperBound(int i, Value value);
14.93 - virtual Value _getRowUpperBound(int i) const;
14.94 -
14.95 - virtual void _setObjCoeffs(ExprIterator b, ExprIterator e);
14.96 - virtual void _getObjCoeffs(InsertIterator b) const;
14.97 -
14.98 - virtual void _setObjCoeff(int i, Value obj_coef);
14.99 - virtual Value _getObjCoeff(int i) const;
14.100 -
14.101 - virtual void _setSense(Sense);
14.102 - virtual Sense _getSense() const;
14.103 -
14.104 - virtual void _clear();
14.105 -
14.106 - public:
14.107 -
14.108 - ///Pointer to the underlying GLPK data structure.
14.109 - LPX *lpx() {return lp;}
14.110 - ///Const pointer to the underlying GLPK data structure.
14.111 - const LPX *lpx() const {return lp;}
14.112 -
14.113 - ///Returns the constraint identifier understood by GLPK.
14.114 - int lpxRow(Row r) const { return rows(id(r)); }
14.115 -
14.116 - ///Returns the variable identifier understood by GLPK.
14.117 - int lpxCol(Col c) const { return cols(id(c)); }
14.118 -
14.119 - };
14.120 -
14.121 - /// \brief Interface for the GLPK LP solver
14.122 - ///
14.123 - /// This class implements an interface for the GLPK LP solver.
14.124 - ///\ingroup lp_group
14.125 - class LpGlpk : public GlpkBase, public LpSolver {
14.126 - public:
14.127 -
14.128 - ///\e
14.129 - LpGlpk();
14.130 - ///\e
14.131 - LpGlpk(const LpGlpk&);
14.132 -
14.133 - private:
14.134 -
14.135 - mutable std::vector<double> _primal_ray;
14.136 - mutable std::vector<double> _dual_ray;
14.137 -
14.138 - void _clear_temporals();
14.139 -
14.140 - protected:
14.141 -
14.142 - virtual LpGlpk* _cloneSolver() const;
14.143 - virtual LpGlpk* _newSolver() const;
14.144 -
14.145 - virtual const char* _solverName() const;
14.146 -
14.147 - virtual SolveExitStatus _solve();
14.148 - virtual Value _getPrimal(int i) const;
14.149 - virtual Value _getDual(int i) const;
14.150 -
14.151 - virtual Value _getPrimalValue() const;
14.152 -
14.153 - virtual VarStatus _getColStatus(int i) const;
14.154 - virtual VarStatus _getRowStatus(int i) const;
14.155 -
14.156 - virtual Value _getPrimalRay(int i) const;
14.157 - virtual Value _getDualRay(int i) const;
14.158 -
14.159 - ///\todo It should be clarified
14.160 - ///
14.161 - virtual ProblemType _getPrimalType() const;
14.162 - virtual ProblemType _getDualType() const;
14.163 -
14.164 - public:
14.165 -
14.166 - ///Solve with primal simplex
14.167 - SolveExitStatus solvePrimal();
14.168 -
14.169 - ///Solve with dual simplex
14.170 - SolveExitStatus solveDual();
14.171 -
14.172 - ///Turns on or off the presolver
14.173 -
14.174 - ///Turns on (\c b is \c true) or off (\c b is \c false) the presolver
14.175 - ///
14.176 - ///The presolver is off by default.
14.177 - void presolver(bool b);
14.178 -
14.179 - ///Enum for \c messageLevel() parameter
14.180 - enum MessageLevel {
14.181 - /// no output (default value)
14.182 - MESSAGE_NO_OUTPUT = 0,
14.183 - /// error messages only
14.184 - MESSAGE_ERROR_MESSAGE = 1,
14.185 - /// normal output
14.186 - MESSAGE_NORMAL_OUTPUT = 2,
14.187 - /// full output (includes informational messages)
14.188 - MESSAGE_FULL_OUTPUT = 3
14.189 - };
14.190 -
14.191 - private:
14.192 -
14.193 - MessageLevel _message_level;
14.194 -
14.195 - public:
14.196 -
14.197 - ///Set the verbosity of the messages
14.198 -
14.199 - ///Set the verbosity of the messages
14.200 - ///
14.201 - ///\param m is the level of the messages output by the solver routines.
14.202 - void messageLevel(MessageLevel m);
14.203 - };
14.204 -
14.205 - /// \brief Interface for the GLPK MIP solver
14.206 - ///
14.207 - /// This class implements an interface for the GLPK MIP solver.
14.208 - ///\ingroup lp_group
14.209 - class MipGlpk : public GlpkBase, public MipSolver {
14.210 - public:
14.211 -
14.212 - ///\e
14.213 - MipGlpk();
14.214 - ///\e
14.215 - MipGlpk(const MipGlpk&);
14.216 -
14.217 - protected:
14.218 -
14.219 - virtual MipGlpk* _cloneSolver() const;
14.220 - virtual MipGlpk* _newSolver() const;
14.221 -
14.222 - virtual const char* _solverName() const;
14.223 -
14.224 - virtual ColTypes _getColType(int col) const;
14.225 - virtual void _setColType(int col, ColTypes col_type);
14.226 -
14.227 - virtual SolveExitStatus _solve();
14.228 - virtual ProblemType _getType() const;
14.229 - virtual Value _getSol(int i) const;
14.230 - virtual Value _getSolValue() const;
14.231 -
14.232 - ///Enum for \c messageLevel() parameter
14.233 - enum MessageLevel {
14.234 - /// no output (default value)
14.235 - MESSAGE_NO_OUTPUT = 0,
14.236 - /// error messages only
14.237 - MESSAGE_ERROR_MESSAGE = 1,
14.238 - /// normal output
14.239 - MESSAGE_NORMAL_OUTPUT = 2,
14.240 - /// full output (includes informational messages)
14.241 - MESSAGE_FULL_OUTPUT = 3
14.242 - };
14.243 -
14.244 - private:
14.245 -
14.246 - MessageLevel _message_level;
14.247 -
14.248 - public:
14.249 -
14.250 - ///Set the verbosity of the messages
14.251 -
14.252 - ///Set the verbosity of the messages
14.253 - ///
14.254 - ///\param m is the level of the messages output by the solver routines.
14.255 - void messageLevel(MessageLevel m);
14.256 - };
14.257 -
14.258 -
14.259 -} //END OF NAMESPACE LEMON
14.260 -
14.261 -#endif //LEMON_LP_GLPK_H
14.262 -
15.1 --- a/lemon/lp_soplex.cc Mon Jan 12 12:25:55 2009 +0000
15.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
15.3 @@ -1,423 +0,0 @@
15.4 -/* -*- mode: C++; indent-tabs-mode: nil; -*-
15.5 - *
15.6 - * This file is a part of LEMON, a generic C++ optimization library.
15.7 - *
15.8 - * Copyright (C) 2003-2008
15.9 - * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
15.10 - * (Egervary Research Group on Combinatorial Optimization, EGRES).
15.11 - *
15.12 - * Permission to use, modify and distribute this software is granted
15.13 - * provided that this copyright notice appears in all copies. For
15.14 - * precise terms see the accompanying LICENSE file.
15.15 - *
15.16 - * This software is provided "AS IS" with no warranty of any kind,
15.17 - * express or implied, and with no claim as to its suitability for any
15.18 - * purpose.
15.19 - *
15.20 - */
15.21 -
15.22 -#include <iostream>
15.23 -#include <lemon/lp_soplex.h>
15.24 -
15.25 -#include <soplex/soplex.h>
15.26 -
15.27 -
15.28 -///\file
15.29 -///\brief Implementation of the LEMON-SOPLEX lp solver interface.
15.30 -namespace lemon {
15.31 -
15.32 - LpSoplex::LpSoplex() {
15.33 - soplex = new soplex::SoPlex;
15.34 - }
15.35 -
15.36 - LpSoplex::~LpSoplex() {
15.37 - delete soplex;
15.38 - }
15.39 -
15.40 - LpSoplex::LpSoplex(const LpSoplex& lp) {
15.41 - rows = lp.rows;
15.42 - cols = lp.cols;
15.43 -
15.44 - soplex = new soplex::SoPlex;
15.45 - (*static_cast<soplex::SPxLP*>(soplex)) = *(lp.soplex);
15.46 -
15.47 - _col_names = lp._col_names;
15.48 - _col_names_ref = lp._col_names_ref;
15.49 -
15.50 - _row_names = lp._row_names;
15.51 - _row_names_ref = lp._row_names_ref;
15.52 -
15.53 - }
15.54 -
15.55 - void LpSoplex::_clear_temporals() {
15.56 - _primal_values.clear();
15.57 - _dual_values.clear();
15.58 - }
15.59 -
15.60 - LpSoplex* LpSoplex::_newSolver() const {
15.61 - LpSoplex* newlp = new LpSoplex();
15.62 - return newlp;
15.63 - }
15.64 -
15.65 - LpSoplex* LpSoplex::_cloneSolver() const {
15.66 - LpSoplex* newlp = new LpSoplex(*this);
15.67 - return newlp;
15.68 - }
15.69 -
15.70 - const char* LpSoplex::_solverName() const { return "LpSoplex"; }
15.71 -
15.72 - int LpSoplex::_addCol() {
15.73 - soplex::LPCol c;
15.74 - c.setLower(-soplex::infinity);
15.75 - c.setUpper(soplex::infinity);
15.76 - soplex->addCol(c);
15.77 -
15.78 - _col_names.push_back(std::string());
15.79 -
15.80 - return soplex->nCols() - 1;
15.81 - }
15.82 -
15.83 - int LpSoplex::_addRow() {
15.84 - soplex::LPRow r;
15.85 - r.setLhs(-soplex::infinity);
15.86 - r.setRhs(soplex::infinity);
15.87 - soplex->addRow(r);
15.88 -
15.89 - _row_names.push_back(std::string());
15.90 -
15.91 - return soplex->nRows() - 1;
15.92 - }
15.93 -
15.94 -
15.95 - void LpSoplex::_eraseCol(int i) {
15.96 - soplex->removeCol(i);
15.97 - _col_names_ref.erase(_col_names[i]);
15.98 - _col_names[i] = _col_names.back();
15.99 - _col_names_ref[_col_names.back()] = i;
15.100 - _col_names.pop_back();
15.101 - }
15.102 -
15.103 - void LpSoplex::_eraseRow(int i) {
15.104 - soplex->removeRow(i);
15.105 - _row_names_ref.erase(_row_names[i]);
15.106 - _row_names[i] = _row_names.back();
15.107 - _row_names_ref[_row_names.back()] = i;
15.108 - _row_names.pop_back();
15.109 - }
15.110 -
15.111 - void LpSoplex::_eraseColId(int i) {
15.112 - cols.eraseIndex(i);
15.113 - cols.relocateIndex(i, cols.maxIndex());
15.114 - }
15.115 - void LpSoplex::_eraseRowId(int i) {
15.116 - rows.eraseIndex(i);
15.117 - rows.relocateIndex(i, rows.maxIndex());
15.118 - }
15.119 -
15.120 - void LpSoplex::_getColName(int c, std::string &name) const {
15.121 - name = _col_names[c];
15.122 - }
15.123 -
15.124 - void LpSoplex::_setColName(int c, const std::string &name) {
15.125 - _col_names_ref.erase(_col_names[c]);
15.126 - _col_names[c] = name;
15.127 - if (!name.empty()) {
15.128 - _col_names_ref.insert(std::make_pair(name, c));
15.129 - }
15.130 - }
15.131 -
15.132 - int LpSoplex::_colByName(const std::string& name) const {
15.133 - std::map<std::string, int>::const_iterator it =
15.134 - _col_names_ref.find(name);
15.135 - if (it != _col_names_ref.end()) {
15.136 - return it->second;
15.137 - } else {
15.138 - return -1;
15.139 - }
15.140 - }
15.141 -
15.142 - void LpSoplex::_getRowName(int r, std::string &name) const {
15.143 - name = _row_names[r];
15.144 - }
15.145 -
15.146 - void LpSoplex::_setRowName(int r, const std::string &name) {
15.147 - _row_names_ref.erase(_row_names[r]);
15.148 - _row_names[r] = name;
15.149 - if (!name.empty()) {
15.150 - _row_names_ref.insert(std::make_pair(name, r));
15.151 - }
15.152 - }
15.153 -
15.154 - int LpSoplex::_rowByName(const std::string& name) const {
15.155 - std::map<std::string, int>::const_iterator it =
15.156 - _row_names_ref.find(name);
15.157 - if (it != _row_names_ref.end()) {
15.158 - return it->second;
15.159 - } else {
15.160 - return -1;
15.161 - }
15.162 - }
15.163 -
15.164 -
15.165 - void LpSoplex::_setRowCoeffs(int i, ExprIterator b, ExprIterator e) {
15.166 - for (int j = 0; j < soplex->nCols(); ++j) {
15.167 - soplex->changeElement(i, j, 0.0);
15.168 - }
15.169 - for(ExprIterator it = b; it != e; ++it) {
15.170 - soplex->changeElement(i, it->first, it->second);
15.171 - }
15.172 - }
15.173 -
15.174 - void LpSoplex::_getRowCoeffs(int i, InsertIterator b) const {
15.175 - const soplex::SVector& vec = soplex->rowVector(i);
15.176 - for (int k = 0; k < vec.size(); ++k) {
15.177 - *b = std::make_pair(vec.index(k), vec.value(k));
15.178 - ++b;
15.179 - }
15.180 - }
15.181 -
15.182 - void LpSoplex::_setColCoeffs(int j, ExprIterator b, ExprIterator e) {
15.183 - for (int i = 0; i < soplex->nRows(); ++i) {
15.184 - soplex->changeElement(i, j, 0.0);
15.185 - }
15.186 - for(ExprIterator it = b; it != e; ++it) {
15.187 - soplex->changeElement(it->first, j, it->second);
15.188 - }
15.189 - }
15.190 -
15.191 - void LpSoplex::_getColCoeffs(int i, InsertIterator b) const {
15.192 - const soplex::SVector& vec = soplex->colVector(i);
15.193 - for (int k = 0; k < vec.size(); ++k) {
15.194 - *b = std::make_pair(vec.index(k), vec.value(k));
15.195 - ++b;
15.196 - }
15.197 - }
15.198 -
15.199 - void LpSoplex::_setCoeff(int i, int j, Value value) {
15.200 - soplex->changeElement(i, j, value);
15.201 - }
15.202 -
15.203 - LpSoplex::Value LpSoplex::_getCoeff(int i, int j) const {
15.204 - return soplex->rowVector(i)[j];
15.205 - }
15.206 -
15.207 - void LpSoplex::_setColLowerBound(int i, Value value) {
15.208 - LEMON_ASSERT(value != INF, "Invalid bound");
15.209 - soplex->changeLower(i, value != -INF ? value : -soplex::infinity);
15.210 - }
15.211 -
15.212 - LpSoplex::Value LpSoplex::_getColLowerBound(int i) const {
15.213 - double value = soplex->lower(i);
15.214 - return value != -soplex::infinity ? value : -INF;
15.215 - }
15.216 -
15.217 - void LpSoplex::_setColUpperBound(int i, Value value) {
15.218 - LEMON_ASSERT(value != -INF, "Invalid bound");
15.219 - soplex->changeUpper(i, value != INF ? value : soplex::infinity);
15.220 - }
15.221 -
15.222 - LpSoplex::Value LpSoplex::_getColUpperBound(int i) const {
15.223 - double value = soplex->upper(i);
15.224 - return value != soplex::infinity ? value : INF;
15.225 - }
15.226 -
15.227 - void LpSoplex::_setRowLowerBound(int i, Value lb) {
15.228 - LEMON_ASSERT(lb != INF, "Invalid bound");
15.229 - soplex->changeRange(i, lb != -INF ? lb : -soplex::infinity, soplex->rhs(i));
15.230 - }
15.231 -
15.232 - LpSoplex::Value LpSoplex::_getRowLowerBound(int i) const {
15.233 - double res = soplex->lhs(i);
15.234 - return res == -soplex::infinity ? -INF : res;
15.235 - }
15.236 -
15.237 - void LpSoplex::_setRowUpperBound(int i, Value ub) {
15.238 - LEMON_ASSERT(ub != -INF, "Invalid bound");
15.239 - soplex->changeRange(i, soplex->lhs(i), ub != INF ? ub : soplex::infinity);
15.240 - }
15.241 -
15.242 - LpSoplex::Value LpSoplex::_getRowUpperBound(int i) const {
15.243 - double res = soplex->rhs(i);
15.244 - return res == soplex::infinity ? INF : res;
15.245 - }
15.246 -
15.247 - void LpSoplex::_setObjCoeffs(ExprIterator b, ExprIterator e) {
15.248 - for (int j = 0; j < soplex->nCols(); ++j) {
15.249 - soplex->changeObj(j, 0.0);
15.250 - }
15.251 - for (ExprIterator it = b; it != e; ++it) {
15.252 - soplex->changeObj(it->first, it->second);
15.253 - }
15.254 - }
15.255 -
15.256 - void LpSoplex::_getObjCoeffs(InsertIterator b) const {
15.257 - for (int j = 0; j < soplex->nCols(); ++j) {
15.258 - Value coef = soplex->obj(j);
15.259 - if (coef != 0.0) {
15.260 - *b = std::make_pair(j, coef);
15.261 - ++b;
15.262 - }
15.263 - }
15.264 - }
15.265 -
15.266 - void LpSoplex::_setObjCoeff(int i, Value obj_coef) {
15.267 - soplex->changeObj(i, obj_coef);
15.268 - }
15.269 -
15.270 - LpSoplex::Value LpSoplex::_getObjCoeff(int i) const {
15.271 - return soplex->obj(i);
15.272 - }
15.273 -
15.274 - LpSoplex::SolveExitStatus LpSoplex::_solve() {
15.275 -
15.276 - _clear_temporals();
15.277 -
15.278 - soplex::SPxSolver::Status status = soplex->solve();
15.279 -
15.280 - switch (status) {
15.281 - case soplex::SPxSolver::OPTIMAL:
15.282 - case soplex::SPxSolver::INFEASIBLE:
15.283 - case soplex::SPxSolver::UNBOUNDED:
15.284 - return SOLVED;
15.285 - default:
15.286 - return UNSOLVED;
15.287 - }
15.288 - }
15.289 -
15.290 - LpSoplex::Value LpSoplex::_getPrimal(int i) const {
15.291 - if (_primal_values.empty()) {
15.292 - _primal_values.resize(soplex->nCols());
15.293 - soplex::Vector pv(_primal_values.size(), &_primal_values.front());
15.294 - soplex->getPrimal(pv);
15.295 - }
15.296 - return _primal_values[i];
15.297 - }
15.298 -
15.299 - LpSoplex::Value LpSoplex::_getDual(int i) const {
15.300 - if (_dual_values.empty()) {
15.301 - _dual_values.resize(soplex->nRows());
15.302 - soplex::Vector dv(_dual_values.size(), &_dual_values.front());
15.303 - soplex->getDual(dv);
15.304 - }
15.305 - return _dual_values[i];
15.306 - }
15.307 -
15.308 - LpSoplex::Value LpSoplex::_getPrimalValue() const {
15.309 - return soplex->objValue();
15.310 - }
15.311 -
15.312 - LpSoplex::VarStatus LpSoplex::_getColStatus(int i) const {
15.313 - switch (soplex->getBasisColStatus(i)) {
15.314 - case soplex::SPxSolver::BASIC:
15.315 - return BASIC;
15.316 - case soplex::SPxSolver::ON_UPPER:
15.317 - return UPPER;
15.318 - case soplex::SPxSolver::ON_LOWER:
15.319 - return LOWER;
15.320 - case soplex::SPxSolver::FIXED:
15.321 - return FIXED;
15.322 - case soplex::SPxSolver::ZERO:
15.323 - return FREE;
15.324 - default:
15.325 - LEMON_ASSERT(false, "Wrong column status");
15.326 - return VarStatus();
15.327 - }
15.328 - }
15.329 -
15.330 - LpSoplex::VarStatus LpSoplex::_getRowStatus(int i) const {
15.331 - switch (soplex->getBasisRowStatus(i)) {
15.332 - case soplex::SPxSolver::BASIC:
15.333 - return BASIC;
15.334 - case soplex::SPxSolver::ON_UPPER:
15.335 - return UPPER;
15.336 - case soplex::SPxSolver::ON_LOWER:
15.337 - return LOWER;
15.338 - case soplex::SPxSolver::FIXED:
15.339 - return FIXED;
15.340 - case soplex::SPxSolver::ZERO:
15.341 - return FREE;
15.342 - default:
15.343 - LEMON_ASSERT(false, "Wrong row status");
15.344 - return VarStatus();
15.345 - }
15.346 - }
15.347 -
15.348 - LpSoplex::Value LpSoplex::_getPrimalRay(int i) const {
15.349 - if (_primal_ray.empty()) {
15.350 - _primal_ray.resize(soplex->nCols());
15.351 - soplex::Vector pv(_primal_ray.size(), &_primal_ray.front());
15.352 - soplex->getDualfarkas(pv);
15.353 - }
15.354 - return _primal_ray[i];
15.355 - }
15.356 -
15.357 - LpSoplex::Value LpSoplex::_getDualRay(int i) const {
15.358 - if (_dual_ray.empty()) {
15.359 - _dual_ray.resize(soplex->nRows());
15.360 - soplex::Vector dv(_dual_ray.size(), &_dual_ray.front());
15.361 - soplex->getDualfarkas(dv);
15.362 - }
15.363 - return _dual_ray[i];
15.364 - }
15.365 -
15.366 - LpSoplex::ProblemType LpSoplex::_getPrimalType() const {
15.367 - switch (soplex->status()) {
15.368 - case soplex::SPxSolver::OPTIMAL:
15.369 - return OPTIMAL;
15.370 - case soplex::SPxSolver::UNBOUNDED:
15.371 - return UNBOUNDED;
15.372 - case soplex::SPxSolver::INFEASIBLE:
15.373 - return INFEASIBLE;
15.374 - default:
15.375 - return UNDEFINED;
15.376 - }
15.377 - }
15.378 -
15.379 - LpSoplex::ProblemType LpSoplex::_getDualType() const {
15.380 - switch (soplex->status()) {
15.381 - case soplex::SPxSolver::OPTIMAL:
15.382 - return OPTIMAL;
15.383 - case soplex::SPxSolver::UNBOUNDED:
15.384 - return UNBOUNDED;
15.385 - case soplex::SPxSolver::INFEASIBLE:
15.386 - return INFEASIBLE;
15.387 - default:
15.388 - return UNDEFINED;
15.389 - }
15.390 - }
15.391 -
15.392 - void LpSoplex::_setSense(Sense sense) {
15.393 - switch (sense) {
15.394 - case MIN:
15.395 - soplex->changeSense(soplex::SPxSolver::MINIMIZE);
15.396 - break;
15.397 - case MAX:
15.398 - soplex->changeSense(soplex::SPxSolver::MAXIMIZE);
15.399 - }
15.400 - }
15.401 -
15.402 - LpSoplex::Sense LpSoplex::_getSense() const {
15.403 - switch (soplex->spxSense()) {
15.404 - case soplex::SPxSolver::MAXIMIZE:
15.405 - return MAX;
15.406 - case soplex::SPxSolver::MINIMIZE:
15.407 - return MIN;
15.408 - default:
15.409 - LEMON_ASSERT(false, "Wrong sense.");
15.410 - return LpSoplex::Sense();
15.411 - }
15.412 - }
15.413 -
15.414 - void LpSoplex::_clear() {
15.415 - soplex->clear();
15.416 - _col_names.clear();
15.417 - _col_names_ref.clear();
15.418 - _row_names.clear();
15.419 - _row_names_ref.clear();
15.420 - cols.clear();
15.421 - rows.clear();
15.422 - _clear_temporals();
15.423 - }
15.424 -
15.425 -} //namespace lemon
15.426 -
16.1 --- a/lemon/lp_soplex.h Mon Jan 12 12:25:55 2009 +0000
16.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
16.3 @@ -1,151 +0,0 @@
16.4 -/* -*- mode: C++; indent-tabs-mode: nil; -*-
16.5 - *
16.6 - * This file is a part of LEMON, a generic C++ optimization library.
16.7 - *
16.8 - * Copyright (C) 2003-2008
16.9 - * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
16.10 - * (Egervary Research Group on Combinatorial Optimization, EGRES).
16.11 - *
16.12 - * Permission to use, modify and distribute this software is granted
16.13 - * provided that this copyright notice appears in all copies. For
16.14 - * precise terms see the accompanying LICENSE file.
16.15 - *
16.16 - * This software is provided "AS IS" with no warranty of any kind,
16.17 - * express or implied, and with no claim as to its suitability for any
16.18 - * purpose.
16.19 - *
16.20 - */
16.21 -
16.22 -#ifndef LEMON_LP_SOPLEX_H
16.23 -#define LEMON_LP_SOPLEX_H
16.24 -
16.25 -///\file
16.26 -///\brief Header of the LEMON-SOPLEX lp solver interface.
16.27 -
16.28 -#include <vector>
16.29 -#include <string>
16.30 -
16.31 -#include <lemon/lp_base.h>
16.32 -
16.33 -// Forward declaration
16.34 -namespace soplex {
16.35 - class SoPlex;
16.36 -}
16.37 -
16.38 -namespace lemon {
16.39 -
16.40 - /// \ingroup lp_group
16.41 - ///
16.42 - /// \brief Interface for the SOPLEX solver
16.43 - ///
16.44 - /// This class implements an interface for the SoPlex LP solver.
16.45 - /// The SoPlex library is an object oriented lp solver library
16.46 - /// developed at the Konrad-Zuse-Zentrum für Informationstechnik
16.47 - /// Berlin (ZIB). You can find detailed information about it at the
16.48 - /// <tt>http://soplex.zib.de</tt> address.
16.49 - class LpSoplex : public LpSolver {
16.50 - private:
16.51 -
16.52 - soplex::SoPlex* soplex;
16.53 -
16.54 - std::vector<std::string> _col_names;
16.55 - std::map<std::string, int> _col_names_ref;
16.56 -
16.57 - std::vector<std::string> _row_names;
16.58 - std::map<std::string, int> _row_names_ref;
16.59 -
16.60 - private:
16.61 -
16.62 - // these values cannot be retrieved element by element
16.63 - mutable std::vector<Value> _primal_values;
16.64 - mutable std::vector<Value> _dual_values;
16.65 -
16.66 - mutable std::vector<Value> _primal_ray;
16.67 - mutable std::vector<Value> _dual_ray;
16.68 -
16.69 - void _clear_temporals();
16.70 -
16.71 - public:
16.72 -
16.73 - /// \e
16.74 - LpSoplex();
16.75 - /// \e
16.76 - LpSoplex(const LpSoplex&);
16.77 - /// \e
16.78 - ~LpSoplex();
16.79 -
16.80 - protected:
16.81 -
16.82 - virtual LpSoplex* _newSolver() const;
16.83 - virtual LpSoplex* _cloneSolver() const;
16.84 -
16.85 - virtual const char* _solverName() const;
16.86 -
16.87 - virtual int _addCol();
16.88 - virtual int _addRow();
16.89 -
16.90 - virtual void _eraseCol(int i);
16.91 - virtual void _eraseRow(int i);
16.92 -
16.93 - virtual void _eraseColId(int i);
16.94 - virtual void _eraseRowId(int i);
16.95 -
16.96 - virtual void _getColName(int col, std::string& name) const;
16.97 - virtual void _setColName(int col, const std::string& name);
16.98 - virtual int _colByName(const std::string& name) const;
16.99 -
16.100 - virtual void _getRowName(int row, std::string& name) const;
16.101 - virtual void _setRowName(int row, const std::string& name);
16.102 - virtual int _rowByName(const std::string& name) const;
16.103 -
16.104 - virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
16.105 - virtual void _getRowCoeffs(int i, InsertIterator b) const;
16.106 -
16.107 - virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
16.108 - virtual void _getColCoeffs(int i, InsertIterator b) const;
16.109 -
16.110 - virtual void _setCoeff(int row, int col, Value value);
16.111 - virtual Value _getCoeff(int row, int col) const;
16.112 -
16.113 - virtual void _setColLowerBound(int i, Value value);
16.114 - virtual Value _getColLowerBound(int i) const;
16.115 - virtual void _setColUpperBound(int i, Value value);
16.116 - virtual Value _getColUpperBound(int i) const;
16.117 -
16.118 - virtual void _setRowLowerBound(int i, Value value);
16.119 - virtual Value _getRowLowerBound(int i) const;
16.120 - virtual void _setRowUpperBound(int i, Value value);
16.121 - virtual Value _getRowUpperBound(int i) const;
16.122 -
16.123 - virtual void _setObjCoeffs(ExprIterator b, ExprIterator e);
16.124 - virtual void _getObjCoeffs(InsertIterator b) const;
16.125 -
16.126 - virtual void _setObjCoeff(int i, Value obj_coef);
16.127 - virtual Value _getObjCoeff(int i) const;
16.128 -
16.129 - virtual void _setSense(Sense sense);
16.130 - virtual Sense _getSense() const;
16.131 -
16.132 - virtual SolveExitStatus _solve();
16.133 - virtual Value _getPrimal(int i) const;
16.134 - virtual Value _getDual(int i) const;
16.135 -
16.136 - virtual Value _getPrimalValue() const;
16.137 -
16.138 - virtual Value _getPrimalRay(int i) const;
16.139 - virtual Value _getDualRay(int i) const;
16.140 -
16.141 - virtual VarStatus _getColStatus(int i) const;
16.142 - virtual VarStatus _getRowStatus(int i) const;
16.143 -
16.144 - virtual ProblemType _getPrimalType() const;
16.145 - virtual ProblemType _getDualType() const;
16.146 -
16.147 - virtual void _clear();
16.148 -
16.149 - };
16.150 -
16.151 -} //END OF NAMESPACE LEMON
16.152 -
16.153 -#endif //LEMON_LP_SOPLEX_H
16.154 -
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/lemon/soplex.cc Mon Jan 12 12:26:01 2009 +0000
17.3 @@ -0,0 +1,423 @@
17.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
17.5 + *
17.6 + * This file is a part of LEMON, a generic C++ optimization library.
17.7 + *
17.8 + * Copyright (C) 2003-2008
17.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
17.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
17.11 + *
17.12 + * Permission to use, modify and distribute this software is granted
17.13 + * provided that this copyright notice appears in all copies. For
17.14 + * precise terms see the accompanying LICENSE file.
17.15 + *
17.16 + * This software is provided "AS IS" with no warranty of any kind,
17.17 + * express or implied, and with no claim as to its suitability for any
17.18 + * purpose.
17.19 + *
17.20 + */
17.21 +
17.22 +#include <iostream>
17.23 +#include <lemon/soplex.h>
17.24 +
17.25 +#include <soplex/soplex.h>
17.26 +
17.27 +
17.28 +///\file
17.29 +///\brief Implementation of the LEMON-SOPLEX lp solver interface.
17.30 +namespace lemon {
17.31 +
17.32 + LpSoplex::LpSoplex() {
17.33 + soplex = new soplex::SoPlex;
17.34 + }
17.35 +
17.36 + LpSoplex::~LpSoplex() {
17.37 + delete soplex;
17.38 + }
17.39 +
17.40 + LpSoplex::LpSoplex(const LpSoplex& lp) {
17.41 + rows = lp.rows;
17.42 + cols = lp.cols;
17.43 +
17.44 + soplex = new soplex::SoPlex;
17.45 + (*static_cast<soplex::SPxLP*>(soplex)) = *(lp.soplex);
17.46 +
17.47 + _col_names = lp._col_names;
17.48 + _col_names_ref = lp._col_names_ref;
17.49 +
17.50 + _row_names = lp._row_names;
17.51 + _row_names_ref = lp._row_names_ref;
17.52 +
17.53 + }
17.54 +
17.55 + void LpSoplex::_clear_temporals() {
17.56 + _primal_values.clear();
17.57 + _dual_values.clear();
17.58 + }
17.59 +
17.60 + LpSoplex* LpSoplex::_newSolver() const {
17.61 + LpSoplex* newlp = new LpSoplex();
17.62 + return newlp;
17.63 + }
17.64 +
17.65 + LpSoplex* LpSoplex::_cloneSolver() const {
17.66 + LpSoplex* newlp = new LpSoplex(*this);
17.67 + return newlp;
17.68 + }
17.69 +
17.70 + const char* LpSoplex::_solverName() const { return "LpSoplex"; }
17.71 +
17.72 + int LpSoplex::_addCol() {
17.73 + soplex::LPCol c;
17.74 + c.setLower(-soplex::infinity);
17.75 + c.setUpper(soplex::infinity);
17.76 + soplex->addCol(c);
17.77 +
17.78 + _col_names.push_back(std::string());
17.79 +
17.80 + return soplex->nCols() - 1;
17.81 + }
17.82 +
17.83 + int LpSoplex::_addRow() {
17.84 + soplex::LPRow r;
17.85 + r.setLhs(-soplex::infinity);
17.86 + r.setRhs(soplex::infinity);
17.87 + soplex->addRow(r);
17.88 +
17.89 + _row_names.push_back(std::string());
17.90 +
17.91 + return soplex->nRows() - 1;
17.92 + }
17.93 +
17.94 +
17.95 + void LpSoplex::_eraseCol(int i) {
17.96 + soplex->removeCol(i);
17.97 + _col_names_ref.erase(_col_names[i]);
17.98 + _col_names[i] = _col_names.back();
17.99 + _col_names_ref[_col_names.back()] = i;
17.100 + _col_names.pop_back();
17.101 + }
17.102 +
17.103 + void LpSoplex::_eraseRow(int i) {
17.104 + soplex->removeRow(i);
17.105 + _row_names_ref.erase(_row_names[i]);
17.106 + _row_names[i] = _row_names.back();
17.107 + _row_names_ref[_row_names.back()] = i;
17.108 + _row_names.pop_back();
17.109 + }
17.110 +
17.111 + void LpSoplex::_eraseColId(int i) {
17.112 + cols.eraseIndex(i);
17.113 + cols.relocateIndex(i, cols.maxIndex());
17.114 + }
17.115 + void LpSoplex::_eraseRowId(int i) {
17.116 + rows.eraseIndex(i);
17.117 + rows.relocateIndex(i, rows.maxIndex());
17.118 + }
17.119 +
17.120 + void LpSoplex::_getColName(int c, std::string &name) const {
17.121 + name = _col_names[c];
17.122 + }
17.123 +
17.124 + void LpSoplex::_setColName(int c, const std::string &name) {
17.125 + _col_names_ref.erase(_col_names[c]);
17.126 + _col_names[c] = name;
17.127 + if (!name.empty()) {
17.128 + _col_names_ref.insert(std::make_pair(name, c));
17.129 + }
17.130 + }
17.131 +
17.132 + int LpSoplex::_colByName(const std::string& name) const {
17.133 + std::map<std::string, int>::const_iterator it =
17.134 + _col_names_ref.find(name);
17.135 + if (it != _col_names_ref.end()) {
17.136 + return it->second;
17.137 + } else {
17.138 + return -1;
17.139 + }
17.140 + }
17.141 +
17.142 + void LpSoplex::_getRowName(int r, std::string &name) const {
17.143 + name = _row_names[r];
17.144 + }
17.145 +
17.146 + void LpSoplex::_setRowName(int r, const std::string &name) {
17.147 + _row_names_ref.erase(_row_names[r]);
17.148 + _row_names[r] = name;
17.149 + if (!name.empty()) {
17.150 + _row_names_ref.insert(std::make_pair(name, r));
17.151 + }
17.152 + }
17.153 +
17.154 + int LpSoplex::_rowByName(const std::string& name) const {
17.155 + std::map<std::string, int>::const_iterator it =
17.156 + _row_names_ref.find(name);
17.157 + if (it != _row_names_ref.end()) {
17.158 + return it->second;
17.159 + } else {
17.160 + return -1;
17.161 + }
17.162 + }
17.163 +
17.164 +
17.165 + void LpSoplex::_setRowCoeffs(int i, ExprIterator b, ExprIterator e) {
17.166 + for (int j = 0; j < soplex->nCols(); ++j) {
17.167 + soplex->changeElement(i, j, 0.0);
17.168 + }
17.169 + for(ExprIterator it = b; it != e; ++it) {
17.170 + soplex->changeElement(i, it->first, it->second);
17.171 + }
17.172 + }
17.173 +
17.174 + void LpSoplex::_getRowCoeffs(int i, InsertIterator b) const {
17.175 + const soplex::SVector& vec = soplex->rowVector(i);
17.176 + for (int k = 0; k < vec.size(); ++k) {
17.177 + *b = std::make_pair(vec.index(k), vec.value(k));
17.178 + ++b;
17.179 + }
17.180 + }
17.181 +
17.182 + void LpSoplex::_setColCoeffs(int j, ExprIterator b, ExprIterator e) {
17.183 + for (int i = 0; i < soplex->nRows(); ++i) {
17.184 + soplex->changeElement(i, j, 0.0);
17.185 + }
17.186 + for(ExprIterator it = b; it != e; ++it) {
17.187 + soplex->changeElement(it->first, j, it->second);
17.188 + }
17.189 + }
17.190 +
17.191 + void LpSoplex::_getColCoeffs(int i, InsertIterator b) const {
17.192 + const soplex::SVector& vec = soplex->colVector(i);
17.193 + for (int k = 0; k < vec.size(); ++k) {
17.194 + *b = std::make_pair(vec.index(k), vec.value(k));
17.195 + ++b;
17.196 + }
17.197 + }
17.198 +
17.199 + void LpSoplex::_setCoeff(int i, int j, Value value) {
17.200 + soplex->changeElement(i, j, value);
17.201 + }
17.202 +
17.203 + LpSoplex::Value LpSoplex::_getCoeff(int i, int j) const {
17.204 + return soplex->rowVector(i)[j];
17.205 + }
17.206 +
17.207 + void LpSoplex::_setColLowerBound(int i, Value value) {
17.208 + LEMON_ASSERT(value != INF, "Invalid bound");
17.209 + soplex->changeLower(i, value != -INF ? value : -soplex::infinity);
17.210 + }
17.211 +
17.212 + LpSoplex::Value LpSoplex::_getColLowerBound(int i) const {
17.213 + double value = soplex->lower(i);
17.214 + return value != -soplex::infinity ? value : -INF;
17.215 + }
17.216 +
17.217 + void LpSoplex::_setColUpperBound(int i, Value value) {
17.218 + LEMON_ASSERT(value != -INF, "Invalid bound");
17.219 + soplex->changeUpper(i, value != INF ? value : soplex::infinity);
17.220 + }
17.221 +
17.222 + LpSoplex::Value LpSoplex::_getColUpperBound(int i) const {
17.223 + double value = soplex->upper(i);
17.224 + return value != soplex::infinity ? value : INF;
17.225 + }
17.226 +
17.227 + void LpSoplex::_setRowLowerBound(int i, Value lb) {
17.228 + LEMON_ASSERT(lb != INF, "Invalid bound");
17.229 + soplex->changeRange(i, lb != -INF ? lb : -soplex::infinity, soplex->rhs(i));
17.230 + }
17.231 +
17.232 + LpSoplex::Value LpSoplex::_getRowLowerBound(int i) const {
17.233 + double res = soplex->lhs(i);
17.234 + return res == -soplex::infinity ? -INF : res;
17.235 + }
17.236 +
17.237 + void LpSoplex::_setRowUpperBound(int i, Value ub) {
17.238 + LEMON_ASSERT(ub != -INF, "Invalid bound");
17.239 + soplex->changeRange(i, soplex->lhs(i), ub != INF ? ub : soplex::infinity);
17.240 + }
17.241 +
17.242 + LpSoplex::Value LpSoplex::_getRowUpperBound(int i) const {
17.243 + double res = soplex->rhs(i);
17.244 + return res == soplex::infinity ? INF : res;
17.245 + }
17.246 +
17.247 + void LpSoplex::_setObjCoeffs(ExprIterator b, ExprIterator e) {
17.248 + for (int j = 0; j < soplex->nCols(); ++j) {
17.249 + soplex->changeObj(j, 0.0);
17.250 + }
17.251 + for (ExprIterator it = b; it != e; ++it) {
17.252 + soplex->changeObj(it->first, it->second);
17.253 + }
17.254 + }
17.255 +
17.256 + void LpSoplex::_getObjCoeffs(InsertIterator b) const {
17.257 + for (int j = 0; j < soplex->nCols(); ++j) {
17.258 + Value coef = soplex->obj(j);
17.259 + if (coef != 0.0) {
17.260 + *b = std::make_pair(j, coef);
17.261 + ++b;
17.262 + }
17.263 + }
17.264 + }
17.265 +
17.266 + void LpSoplex::_setObjCoeff(int i, Value obj_coef) {
17.267 + soplex->changeObj(i, obj_coef);
17.268 + }
17.269 +
17.270 + LpSoplex::Value LpSoplex::_getObjCoeff(int i) const {
17.271 + return soplex->obj(i);
17.272 + }
17.273 +
17.274 + LpSoplex::SolveExitStatus LpSoplex::_solve() {
17.275 +
17.276 + _clear_temporals();
17.277 +
17.278 + soplex::SPxSolver::Status status = soplex->solve();
17.279 +
17.280 + switch (status) {
17.281 + case soplex::SPxSolver::OPTIMAL:
17.282 + case soplex::SPxSolver::INFEASIBLE:
17.283 + case soplex::SPxSolver::UNBOUNDED:
17.284 + return SOLVED;
17.285 + default:
17.286 + return UNSOLVED;
17.287 + }
17.288 + }
17.289 +
17.290 + LpSoplex::Value LpSoplex::_getPrimal(int i) const {
17.291 + if (_primal_values.empty()) {
17.292 + _primal_values.resize(soplex->nCols());
17.293 + soplex::Vector pv(_primal_values.size(), &_primal_values.front());
17.294 + soplex->getPrimal(pv);
17.295 + }
17.296 + return _primal_values[i];
17.297 + }
17.298 +
17.299 + LpSoplex::Value LpSoplex::_getDual(int i) const {
17.300 + if (_dual_values.empty()) {
17.301 + _dual_values.resize(soplex->nRows());
17.302 + soplex::Vector dv(_dual_values.size(), &_dual_values.front());
17.303 + soplex->getDual(dv);
17.304 + }
17.305 + return _dual_values[i];
17.306 + }
17.307 +
17.308 + LpSoplex::Value LpSoplex::_getPrimalValue() const {
17.309 + return soplex->objValue();
17.310 + }
17.311 +
17.312 + LpSoplex::VarStatus LpSoplex::_getColStatus(int i) const {
17.313 + switch (soplex->getBasisColStatus(i)) {
17.314 + case soplex::SPxSolver::BASIC:
17.315 + return BASIC;
17.316 + case soplex::SPxSolver::ON_UPPER:
17.317 + return UPPER;
17.318 + case soplex::SPxSolver::ON_LOWER:
17.319 + return LOWER;
17.320 + case soplex::SPxSolver::FIXED:
17.321 + return FIXED;
17.322 + case soplex::SPxSolver::ZERO:
17.323 + return FREE;
17.324 + default:
17.325 + LEMON_ASSERT(false, "Wrong column status");
17.326 + return VarStatus();
17.327 + }
17.328 + }
17.329 +
17.330 + LpSoplex::VarStatus LpSoplex::_getRowStatus(int i) const {
17.331 + switch (soplex->getBasisRowStatus(i)) {
17.332 + case soplex::SPxSolver::BASIC:
17.333 + return BASIC;
17.334 + case soplex::SPxSolver::ON_UPPER:
17.335 + return UPPER;
17.336 + case soplex::SPxSolver::ON_LOWER:
17.337 + return LOWER;
17.338 + case soplex::SPxSolver::FIXED:
17.339 + return FIXED;
17.340 + case soplex::SPxSolver::ZERO:
17.341 + return FREE;
17.342 + default:
17.343 + LEMON_ASSERT(false, "Wrong row status");
17.344 + return VarStatus();
17.345 + }
17.346 + }
17.347 +
17.348 + LpSoplex::Value LpSoplex::_getPrimalRay(int i) const {
17.349 + if (_primal_ray.empty()) {
17.350 + _primal_ray.resize(soplex->nCols());
17.351 + soplex::Vector pv(_primal_ray.size(), &_primal_ray.front());
17.352 + soplex->getDualfarkas(pv);
17.353 + }
17.354 + return _primal_ray[i];
17.355 + }
17.356 +
17.357 + LpSoplex::Value LpSoplex::_getDualRay(int i) const {
17.358 + if (_dual_ray.empty()) {
17.359 + _dual_ray.resize(soplex->nRows());
17.360 + soplex::Vector dv(_dual_ray.size(), &_dual_ray.front());
17.361 + soplex->getDualfarkas(dv);
17.362 + }
17.363 + return _dual_ray[i];
17.364 + }
17.365 +
17.366 + LpSoplex::ProblemType LpSoplex::_getPrimalType() const {
17.367 + switch (soplex->status()) {
17.368 + case soplex::SPxSolver::OPTIMAL:
17.369 + return OPTIMAL;
17.370 + case soplex::SPxSolver::UNBOUNDED:
17.371 + return UNBOUNDED;
17.372 + case soplex::SPxSolver::INFEASIBLE:
17.373 + return INFEASIBLE;
17.374 + default:
17.375 + return UNDEFINED;
17.376 + }
17.377 + }
17.378 +
17.379 + LpSoplex::ProblemType LpSoplex::_getDualType() const {
17.380 + switch (soplex->status()) {
17.381 + case soplex::SPxSolver::OPTIMAL:
17.382 + return OPTIMAL;
17.383 + case soplex::SPxSolver::UNBOUNDED:
17.384 + return UNBOUNDED;
17.385 + case soplex::SPxSolver::INFEASIBLE:
17.386 + return INFEASIBLE;
17.387 + default:
17.388 + return UNDEFINED;
17.389 + }
17.390 + }
17.391 +
17.392 + void LpSoplex::_setSense(Sense sense) {
17.393 + switch (sense) {
17.394 + case MIN:
17.395 + soplex->changeSense(soplex::SPxSolver::MINIMIZE);
17.396 + break;
17.397 + case MAX:
17.398 + soplex->changeSense(soplex::SPxSolver::MAXIMIZE);
17.399 + }
17.400 + }
17.401 +
17.402 + LpSoplex::Sense LpSoplex::_getSense() const {
17.403 + switch (soplex->spxSense()) {
17.404 + case soplex::SPxSolver::MAXIMIZE:
17.405 + return MAX;
17.406 + case soplex::SPxSolver::MINIMIZE:
17.407 + return MIN;
17.408 + default:
17.409 + LEMON_ASSERT(false, "Wrong sense.");
17.410 + return LpSoplex::Sense();
17.411 + }
17.412 + }
17.413 +
17.414 + void LpSoplex::_clear() {
17.415 + soplex->clear();
17.416 + _col_names.clear();
17.417 + _col_names_ref.clear();
17.418 + _row_names.clear();
17.419 + _row_names_ref.clear();
17.420 + cols.clear();
17.421 + rows.clear();
17.422 + _clear_temporals();
17.423 + }
17.424 +
17.425 +} //namespace lemon
17.426 +
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/lemon/soplex.h Mon Jan 12 12:26:01 2009 +0000
18.3 @@ -0,0 +1,151 @@
18.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
18.5 + *
18.6 + * This file is a part of LEMON, a generic C++ optimization library.
18.7 + *
18.8 + * Copyright (C) 2003-2008
18.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
18.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
18.11 + *
18.12 + * Permission to use, modify and distribute this software is granted
18.13 + * provided that this copyright notice appears in all copies. For
18.14 + * precise terms see the accompanying LICENSE file.
18.15 + *
18.16 + * This software is provided "AS IS" with no warranty of any kind,
18.17 + * express or implied, and with no claim as to its suitability for any
18.18 + * purpose.
18.19 + *
18.20 + */
18.21 +
18.22 +#ifndef LEMON_SOPLEX_H
18.23 +#define LEMON_SOPLEX_H
18.24 +
18.25 +///\file
18.26 +///\brief Header of the LEMON-SOPLEX lp solver interface.
18.27 +
18.28 +#include <vector>
18.29 +#include <string>
18.30 +
18.31 +#include <lemon/lp_base.h>
18.32 +
18.33 +// Forward declaration
18.34 +namespace soplex {
18.35 + class SoPlex;
18.36 +}
18.37 +
18.38 +namespace lemon {
18.39 +
18.40 + /// \ingroup lp_group
18.41 + ///
18.42 + /// \brief Interface for the SOPLEX solver
18.43 + ///
18.44 + /// This class implements an interface for the SoPlex LP solver.
18.45 + /// The SoPlex library is an object oriented lp solver library
18.46 + /// developed at the Konrad-Zuse-Zentrum für Informationstechnik
18.47 + /// Berlin (ZIB). You can find detailed information about it at the
18.48 + /// <tt>http://soplex.zib.de</tt> address.
18.49 + class LpSoplex : public LpSolver {
18.50 + private:
18.51 +
18.52 + soplex::SoPlex* soplex;
18.53 +
18.54 + std::vector<std::string> _col_names;
18.55 + std::map<std::string, int> _col_names_ref;
18.56 +
18.57 + std::vector<std::string> _row_names;
18.58 + std::map<std::string, int> _row_names_ref;
18.59 +
18.60 + private:
18.61 +
18.62 + // these values cannot be retrieved element by element
18.63 + mutable std::vector<Value> _primal_values;
18.64 + mutable std::vector<Value> _dual_values;
18.65 +
18.66 + mutable std::vector<Value> _primal_ray;
18.67 + mutable std::vector<Value> _dual_ray;
18.68 +
18.69 + void _clear_temporals();
18.70 +
18.71 + public:
18.72 +
18.73 + /// \e
18.74 + LpSoplex();
18.75 + /// \e
18.76 + LpSoplex(const LpSoplex&);
18.77 + /// \e
18.78 + ~LpSoplex();
18.79 +
18.80 + protected:
18.81 +
18.82 + virtual LpSoplex* _newSolver() const;
18.83 + virtual LpSoplex* _cloneSolver() const;
18.84 +
18.85 + virtual const char* _solverName() const;
18.86 +
18.87 + virtual int _addCol();
18.88 + virtual int _addRow();
18.89 +
18.90 + virtual void _eraseCol(int i);
18.91 + virtual void _eraseRow(int i);
18.92 +
18.93 + virtual void _eraseColId(int i);
18.94 + virtual void _eraseRowId(int i);
18.95 +
18.96 + virtual void _getColName(int col, std::string& name) const;
18.97 + virtual void _setColName(int col, const std::string& name);
18.98 + virtual int _colByName(const std::string& name) const;
18.99 +
18.100 + virtual void _getRowName(int row, std::string& name) const;
18.101 + virtual void _setRowName(int row, const std::string& name);
18.102 + virtual int _rowByName(const std::string& name) const;
18.103 +
18.104 + virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
18.105 + virtual void _getRowCoeffs(int i, InsertIterator b) const;
18.106 +
18.107 + virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
18.108 + virtual void _getColCoeffs(int i, InsertIterator b) const;
18.109 +
18.110 + virtual void _setCoeff(int row, int col, Value value);
18.111 + virtual Value _getCoeff(int row, int col) const;
18.112 +
18.113 + virtual void _setColLowerBound(int i, Value value);
18.114 + virtual Value _getColLowerBound(int i) const;
18.115 + virtual void _setColUpperBound(int i, Value value);
18.116 + virtual Value _getColUpperBound(int i) const;
18.117 +
18.118 + virtual void _setRowLowerBound(int i, Value value);
18.119 + virtual Value _getRowLowerBound(int i) const;
18.120 + virtual void _setRowUpperBound(int i, Value value);
18.121 + virtual Value _getRowUpperBound(int i) const;
18.122 +
18.123 + virtual void _setObjCoeffs(ExprIterator b, ExprIterator e);
18.124 + virtual void _getObjCoeffs(InsertIterator b) const;
18.125 +
18.126 + virtual void _setObjCoeff(int i, Value obj_coef);
18.127 + virtual Value _getObjCoeff(int i) const;
18.128 +
18.129 + virtual void _setSense(Sense sense);
18.130 + virtual Sense _getSense() const;
18.131 +
18.132 + virtual SolveExitStatus _solve();
18.133 + virtual Value _getPrimal(int i) const;
18.134 + virtual Value _getDual(int i) const;
18.135 +
18.136 + virtual Value _getPrimalValue() const;
18.137 +
18.138 + virtual Value _getPrimalRay(int i) const;
18.139 + virtual Value _getDualRay(int i) const;
18.140 +
18.141 + virtual VarStatus _getColStatus(int i) const;
18.142 + virtual VarStatus _getRowStatus(int i) const;
18.143 +
18.144 + virtual ProblemType _getPrimalType() const;
18.145 + virtual ProblemType _getDualType() const;
18.146 +
18.147 + virtual void _clear();
18.148 +
18.149 + };
18.150 +
18.151 +} //END OF NAMESPACE LEMON
18.152 +
18.153 +#endif //LEMON_SOPLEX_H
18.154 +
19.1 --- a/test/lp_test.cc Mon Jan 12 12:25:55 2009 +0000
19.2 +++ b/test/lp_test.cc Mon Jan 12 12:26:01 2009 +0000
19.3 @@ -26,19 +26,19 @@
19.4 #endif
19.5
19.6 #ifdef HAVE_GLPK
19.7 -#include <lemon/lp_glpk.h>
19.8 +#include <lemon/glpk.h>
19.9 #endif
19.10
19.11 #ifdef HAVE_CPLEX
19.12 -#include <lemon/lp_cplex.h>
19.13 +#include <lemon/cplex.h>
19.14 #endif
19.15
19.16 #ifdef HAVE_SOPLEX
19.17 -#include <lemon/lp_soplex.h>
19.18 +#include <lemon/soplex.h>
19.19 #endif
19.20
19.21 #ifdef HAVE_CLP
19.22 -#include <lemon/lp_clp.h>
19.23 +#include <lemon/clp.h>
19.24 #endif
19.25
19.26 using namespace lemon;
20.1 --- a/test/mip_test.cc Mon Jan 12 12:25:55 2009 +0000
20.2 +++ b/test/mip_test.cc Mon Jan 12 12:26:01 2009 +0000
20.3 @@ -24,11 +24,11 @@
20.4 #endif
20.5
20.6 #ifdef HAVE_CPLEX
20.7 -#include <lemon/lp_cplex.h>
20.8 +#include <lemon/cplex.h>
20.9 #endif
20.10
20.11 #ifdef HAVE_GLPK
20.12 -#include <lemon/lp_glpk.h>
20.13 +#include <lemon/glpk.h>
20.14 #endif
20.15
20.16