Remove lp_ prefix from the solver's header name
authorAlpar Juttner <alpar@cs.elte.hu>
Mon, 12 Jan 2009 12:26:01 +0000
changeset 46108d495d48089
parent 460 76ec7bd57026
child 462 9b082b3fb33f
Remove lp_ prefix from the solver's header name
lemon/Makefile.am
lemon/clp.cc
lemon/clp.h
lemon/cplex.cc
lemon/cplex.h
lemon/glpk.cc
lemon/glpk.h
lemon/lp.h
lemon/lp_clp.cc
lemon/lp_clp.h
lemon/lp_cplex.cc
lemon/lp_cplex.h
lemon/lp_glpk.cc
lemon/lp_glpk.h
lemon/lp_soplex.cc
lemon/lp_soplex.h
lemon/soplex.cc
lemon/soplex.h
test/lp_test.cc
test/mip_test.cc
     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