1.1 --- a/lemon/lp_cplex.cc Mon Jan 12 12:25:55 2009 +0000
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,925 +0,0 @@
1.4 -/* -*- mode: C++; indent-tabs-mode: nil; -*-
1.5 - *
1.6 - * This file is a part of LEMON, a generic C++ optimization library.
1.7 - *
1.8 - * Copyright (C) 2003-2008
1.9 - * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
1.10 - * (Egervary Research Group on Combinatorial Optimization, EGRES).
1.11 - *
1.12 - * Permission to use, modify and distribute this software is granted
1.13 - * provided that this copyright notice appears in all copies. For
1.14 - * precise terms see the accompanying LICENSE file.
1.15 - *
1.16 - * This software is provided "AS IS" with no warranty of any kind,
1.17 - * express or implied, and with no claim as to its suitability for any
1.18 - * purpose.
1.19 - *
1.20 - */
1.21 -
1.22 -#include <iostream>
1.23 -#include <vector>
1.24 -#include <cstring>
1.25 -
1.26 -#include <lemon/lp_cplex.h>
1.27 -
1.28 -extern "C" {
1.29 -#include <ilcplex/cplex.h>
1.30 -}
1.31 -
1.32 -
1.33 -///\file
1.34 -///\brief Implementation of the LEMON-CPLEX lp solver interface.
1.35 -namespace lemon {
1.36 -
1.37 - CplexEnv::LicenseError::LicenseError(int status) {
1.38 - if (!CPXgeterrorstring(0, status, _message)) {
1.39 - std::strcpy(_message, "Cplex unknown error");
1.40 - }
1.41 - }
1.42 -
1.43 - CplexEnv::CplexEnv() {
1.44 - int status;
1.45 - _cnt = new int;
1.46 - _env = CPXopenCPLEX(&status);
1.47 - if (_env == 0) {
1.48 - delete _cnt;
1.49 - _cnt = 0;
1.50 - throw LicenseError(status);
1.51 - }
1.52 - }
1.53 -
1.54 - CplexEnv::CplexEnv(const CplexEnv& other) {
1.55 - _env = other._env;
1.56 - _cnt = other._cnt;
1.57 - ++(*_cnt);
1.58 - }
1.59 -
1.60 - CplexEnv& CplexEnv::operator=(const CplexEnv& other) {
1.61 - _env = other._env;
1.62 - _cnt = other._cnt;
1.63 - ++(*_cnt);
1.64 - return *this;
1.65 - }
1.66 -
1.67 - CplexEnv::~CplexEnv() {
1.68 - --(*_cnt);
1.69 - if (*_cnt == 0) {
1.70 - delete _cnt;
1.71 - CPXcloseCPLEX(&_env);
1.72 - }
1.73 - }
1.74 -
1.75 - CplexBase::CplexBase() : LpBase() {
1.76 - int status;
1.77 - _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
1.78 - }
1.79 -
1.80 - CplexBase::CplexBase(const CplexEnv& env)
1.81 - : LpBase(), _env(env) {
1.82 - int status;
1.83 - _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
1.84 - }
1.85 -
1.86 - CplexBase::CplexBase(const CplexBase& cplex)
1.87 - : LpBase() {
1.88 - int status;
1.89 - _prob = CPXcloneprob(cplexEnv(), cplex._prob, &status);
1.90 - rows = cplex.rows;
1.91 - cols = cplex.cols;
1.92 - }
1.93 -
1.94 - CplexBase::~CplexBase() {
1.95 - CPXfreeprob(cplexEnv(),&_prob);
1.96 - }
1.97 -
1.98 - int CplexBase::_addCol() {
1.99 - int i = CPXgetnumcols(cplexEnv(), _prob);
1.100 - double lb = -INF, ub = INF;
1.101 - CPXnewcols(cplexEnv(), _prob, 1, 0, &lb, &ub, 0, 0);
1.102 - return i;
1.103 - }
1.104 -
1.105 -
1.106 - int CplexBase::_addRow() {
1.107 - int i = CPXgetnumrows(cplexEnv(), _prob);
1.108 - const double ub = INF;
1.109 - const char s = 'L';
1.110 - CPXnewrows(cplexEnv(), _prob, 1, &ub, &s, 0, 0);
1.111 - return i;
1.112 - }
1.113 -
1.114 -
1.115 - void CplexBase::_eraseCol(int i) {
1.116 - CPXdelcols(cplexEnv(), _prob, i, i);
1.117 - }
1.118 -
1.119 - void CplexBase::_eraseRow(int i) {
1.120 - CPXdelrows(cplexEnv(), _prob, i, i);
1.121 - }
1.122 -
1.123 - void CplexBase::_eraseColId(int i) {
1.124 - cols.eraseIndex(i);
1.125 - cols.shiftIndices(i);
1.126 - }
1.127 - void CplexBase::_eraseRowId(int i) {
1.128 - rows.eraseIndex(i);
1.129 - rows.shiftIndices(i);
1.130 - }
1.131 -
1.132 - void CplexBase::_getColName(int col, std::string &name) const {
1.133 - int size;
1.134 - CPXgetcolname(cplexEnv(), _prob, 0, 0, 0, &size, col, col);
1.135 - if (size == 0) {
1.136 - name.clear();
1.137 - return;
1.138 - }
1.139 -
1.140 - size *= -1;
1.141 - std::vector<char> buf(size);
1.142 - char *cname;
1.143 - int tmp;
1.144 - CPXgetcolname(cplexEnv(), _prob, &cname, &buf.front(), size,
1.145 - &tmp, col, col);
1.146 - name = cname;
1.147 - }
1.148 -
1.149 - void CplexBase::_setColName(int col, const std::string &name) {
1.150 - char *cname;
1.151 - cname = const_cast<char*>(name.c_str());
1.152 - CPXchgcolname(cplexEnv(), _prob, 1, &col, &cname);
1.153 - }
1.154 -
1.155 - int CplexBase::_colByName(const std::string& name) const {
1.156 - int index;
1.157 - if (CPXgetcolindex(cplexEnv(), _prob,
1.158 - const_cast<char*>(name.c_str()), &index) == 0) {
1.159 - return index;
1.160 - }
1.161 - return -1;
1.162 - }
1.163 -
1.164 - void CplexBase::_getRowName(int row, std::string &name) const {
1.165 - int size;
1.166 - CPXgetrowname(cplexEnv(), _prob, 0, 0, 0, &size, row, row);
1.167 - if (size == 0) {
1.168 - name.clear();
1.169 - return;
1.170 - }
1.171 -
1.172 - size *= -1;
1.173 - std::vector<char> buf(size);
1.174 - char *cname;
1.175 - int tmp;
1.176 - CPXgetrowname(cplexEnv(), _prob, &cname, &buf.front(), size,
1.177 - &tmp, row, row);
1.178 - name = cname;
1.179 - }
1.180 -
1.181 - void CplexBase::_setRowName(int row, const std::string &name) {
1.182 - char *cname;
1.183 - cname = const_cast<char*>(name.c_str());
1.184 - CPXchgrowname(cplexEnv(), _prob, 1, &row, &cname);
1.185 - }
1.186 -
1.187 - int CplexBase::_rowByName(const std::string& name) const {
1.188 - int index;
1.189 - if (CPXgetrowindex(cplexEnv(), _prob,
1.190 - const_cast<char*>(name.c_str()), &index) == 0) {
1.191 - return index;
1.192 - }
1.193 - return -1;
1.194 - }
1.195 -
1.196 - void CplexBase::_setRowCoeffs(int i, ExprIterator b,
1.197 - ExprIterator e)
1.198 - {
1.199 - std::vector<int> indices;
1.200 - std::vector<int> rowlist;
1.201 - std::vector<Value> values;
1.202 -
1.203 - for(ExprIterator it=b; it!=e; ++it) {
1.204 - indices.push_back(it->first);
1.205 - values.push_back(it->second);
1.206 - rowlist.push_back(i);
1.207 - }
1.208 -
1.209 - CPXchgcoeflist(cplexEnv(), _prob, values.size(),
1.210 - &rowlist.front(), &indices.front(), &values.front());
1.211 - }
1.212 -
1.213 - void CplexBase::_getRowCoeffs(int i, InsertIterator b) const {
1.214 - int tmp1, tmp2, tmp3, length;
1.215 - CPXgetrows(cplexEnv(), _prob, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
1.216 -
1.217 - length = -length;
1.218 - std::vector<int> indices(length);
1.219 - std::vector<double> values(length);
1.220 -
1.221 - CPXgetrows(cplexEnv(), _prob, &tmp1, &tmp2,
1.222 - &indices.front(), &values.front(),
1.223 - length, &tmp3, i, i);
1.224 -
1.225 - for (int i = 0; i < length; ++i) {
1.226 - *b = std::make_pair(indices[i], values[i]);
1.227 - ++b;
1.228 - }
1.229 - }
1.230 -
1.231 - void CplexBase::_setColCoeffs(int i, ExprIterator b, ExprIterator e) {
1.232 - std::vector<int> indices;
1.233 - std::vector<int> collist;
1.234 - std::vector<Value> values;
1.235 -
1.236 - for(ExprIterator it=b; it!=e; ++it) {
1.237 - indices.push_back(it->first);
1.238 - values.push_back(it->second);
1.239 - collist.push_back(i);
1.240 - }
1.241 -
1.242 - CPXchgcoeflist(cplexEnv(), _prob, values.size(),
1.243 - &indices.front(), &collist.front(), &values.front());
1.244 - }
1.245 -
1.246 - void CplexBase::_getColCoeffs(int i, InsertIterator b) const {
1.247 -
1.248 - int tmp1, tmp2, tmp3, length;
1.249 - CPXgetcols(cplexEnv(), _prob, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
1.250 -
1.251 - length = -length;
1.252 - std::vector<int> indices(length);
1.253 - std::vector<double> values(length);
1.254 -
1.255 - CPXgetcols(cplexEnv(), _prob, &tmp1, &tmp2,
1.256 - &indices.front(), &values.front(),
1.257 - length, &tmp3, i, i);
1.258 -
1.259 - for (int i = 0; i < length; ++i) {
1.260 - *b = std::make_pair(indices[i], values[i]);
1.261 - ++b;
1.262 - }
1.263 -
1.264 - }
1.265 -
1.266 - void CplexBase::_setCoeff(int row, int col, Value value) {
1.267 - CPXchgcoef(cplexEnv(), _prob, row, col, value);
1.268 - }
1.269 -
1.270 - CplexBase::Value CplexBase::_getCoeff(int row, int col) const {
1.271 - CplexBase::Value value;
1.272 - CPXgetcoef(cplexEnv(), _prob, row, col, &value);
1.273 - return value;
1.274 - }
1.275 -
1.276 - void CplexBase::_setColLowerBound(int i, Value value) {
1.277 - const char s = 'L';
1.278 - CPXchgbds(cplexEnv(), _prob, 1, &i, &s, &value);
1.279 - }
1.280 -
1.281 - CplexBase::Value CplexBase::_getColLowerBound(int i) const {
1.282 - CplexBase::Value res;
1.283 - CPXgetlb(cplexEnv(), _prob, &res, i, i);
1.284 - return res <= -CPX_INFBOUND ? -INF : res;
1.285 - }
1.286 -
1.287 - void CplexBase::_setColUpperBound(int i, Value value)
1.288 - {
1.289 - const char s = 'U';
1.290 - CPXchgbds(cplexEnv(), _prob, 1, &i, &s, &value);
1.291 - }
1.292 -
1.293 - CplexBase::Value CplexBase::_getColUpperBound(int i) const {
1.294 - CplexBase::Value res;
1.295 - CPXgetub(cplexEnv(), _prob, &res, i, i);
1.296 - return res >= CPX_INFBOUND ? INF : res;
1.297 - }
1.298 -
1.299 - CplexBase::Value CplexBase::_getRowLowerBound(int i) const {
1.300 - char s;
1.301 - CPXgetsense(cplexEnv(), _prob, &s, i, i);
1.302 - CplexBase::Value res;
1.303 -
1.304 - switch (s) {
1.305 - case 'G':
1.306 - case 'R':
1.307 - case 'E':
1.308 - CPXgetrhs(cplexEnv(), _prob, &res, i, i);
1.309 - return res <= -CPX_INFBOUND ? -INF : res;
1.310 - default:
1.311 - return -INF;
1.312 - }
1.313 - }
1.314 -
1.315 - CplexBase::Value CplexBase::_getRowUpperBound(int i) const {
1.316 - char s;
1.317 - CPXgetsense(cplexEnv(), _prob, &s, i, i);
1.318 - CplexBase::Value res;
1.319 -
1.320 - switch (s) {
1.321 - case 'L':
1.322 - case 'E':
1.323 - CPXgetrhs(cplexEnv(), _prob, &res, i, i);
1.324 - return res >= CPX_INFBOUND ? INF : res;
1.325 - case 'R':
1.326 - CPXgetrhs(cplexEnv(), _prob, &res, i, i);
1.327 - {
1.328 - double rng;
1.329 - CPXgetrngval(cplexEnv(), _prob, &rng, i, i);
1.330 - res += rng;
1.331 - }
1.332 - return res >= CPX_INFBOUND ? INF : res;
1.333 - default:
1.334 - return INF;
1.335 - }
1.336 - }
1.337 -
1.338 - //This is easier to implement
1.339 - void CplexBase::_set_row_bounds(int i, Value lb, Value ub) {
1.340 - if (lb == -INF) {
1.341 - const char s = 'L';
1.342 - CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
1.343 - CPXchgrhs(cplexEnv(), _prob, 1, &i, &ub);
1.344 - } else if (ub == INF) {
1.345 - const char s = 'G';
1.346 - CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
1.347 - CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
1.348 - } else if (lb == ub){
1.349 - const char s = 'E';
1.350 - CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
1.351 - CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
1.352 - } else {
1.353 - const char s = 'R';
1.354 - CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
1.355 - CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
1.356 - double len = ub - lb;
1.357 - CPXchgrngval(cplexEnv(), _prob, 1, &i, &len);
1.358 - }
1.359 - }
1.360 -
1.361 - void CplexBase::_setRowLowerBound(int i, Value lb)
1.362 - {
1.363 - LEMON_ASSERT(lb != INF, "Invalid bound");
1.364 - _set_row_bounds(i, lb, CplexBase::_getRowUpperBound(i));
1.365 - }
1.366 -
1.367 - void CplexBase::_setRowUpperBound(int i, Value ub)
1.368 - {
1.369 -
1.370 - LEMON_ASSERT(ub != -INF, "Invalid bound");
1.371 - _set_row_bounds(i, CplexBase::_getRowLowerBound(i), ub);
1.372 - }
1.373 -
1.374 - void CplexBase::_setObjCoeffs(ExprIterator b, ExprIterator e)
1.375 - {
1.376 - std::vector<int> indices;
1.377 - std::vector<Value> values;
1.378 - for(ExprIterator it=b; it!=e; ++it) {
1.379 - indices.push_back(it->first);
1.380 - values.push_back(it->second);
1.381 - }
1.382 - CPXchgobj(cplexEnv(), _prob, values.size(),
1.383 - &indices.front(), &values.front());
1.384 -
1.385 - }
1.386 -
1.387 - void CplexBase::_getObjCoeffs(InsertIterator b) const
1.388 - {
1.389 - int num = CPXgetnumcols(cplexEnv(), _prob);
1.390 - std::vector<Value> x(num);
1.391 -
1.392 - CPXgetobj(cplexEnv(), _prob, &x.front(), 0, num - 1);
1.393 - for (int i = 0; i < num; ++i) {
1.394 - if (x[i] != 0.0) {
1.395 - *b = std::make_pair(i, x[i]);
1.396 - ++b;
1.397 - }
1.398 - }
1.399 - }
1.400 -
1.401 - void CplexBase::_setObjCoeff(int i, Value obj_coef)
1.402 - {
1.403 - CPXchgobj(cplexEnv(), _prob, 1, &i, &obj_coef);
1.404 - }
1.405 -
1.406 - CplexBase::Value CplexBase::_getObjCoeff(int i) const
1.407 - {
1.408 - Value x;
1.409 - CPXgetobj(cplexEnv(), _prob, &x, i, i);
1.410 - return x;
1.411 - }
1.412 -
1.413 - void CplexBase::_setSense(CplexBase::Sense sense) {
1.414 - switch (sense) {
1.415 - case MIN:
1.416 - CPXchgobjsen(cplexEnv(), _prob, CPX_MIN);
1.417 - break;
1.418 - case MAX:
1.419 - CPXchgobjsen(cplexEnv(), _prob, CPX_MAX);
1.420 - break;
1.421 - }
1.422 - }
1.423 -
1.424 - CplexBase::Sense CplexBase::_getSense() const {
1.425 - switch (CPXgetobjsen(cplexEnv(), _prob)) {
1.426 - case CPX_MIN:
1.427 - return MIN;
1.428 - case CPX_MAX:
1.429 - return MAX;
1.430 - default:
1.431 - LEMON_ASSERT(false, "Invalid sense");
1.432 - return CplexBase::Sense();
1.433 - }
1.434 - }
1.435 -
1.436 - void CplexBase::_clear() {
1.437 - CPXfreeprob(cplexEnv(),&_prob);
1.438 - int status;
1.439 - _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
1.440 - rows.clear();
1.441 - cols.clear();
1.442 - }
1.443 -
1.444 - // LpCplex members
1.445 -
1.446 - LpCplex::LpCplex()
1.447 - : LpBase(), CplexBase(), LpSolver() {}
1.448 -
1.449 - LpCplex::LpCplex(const CplexEnv& env)
1.450 - : LpBase(), CplexBase(env), LpSolver() {}
1.451 -
1.452 - LpCplex::LpCplex(const LpCplex& other)
1.453 - : LpBase(), CplexBase(other), LpSolver() {}
1.454 -
1.455 - LpCplex::~LpCplex() {}
1.456 -
1.457 - LpCplex* LpCplex::_newSolver() const { return new LpCplex; }
1.458 - LpCplex* LpCplex::_cloneSolver() const {return new LpCplex(*this); }
1.459 -
1.460 - const char* LpCplex::_solverName() const { return "LpCplex"; }
1.461 -
1.462 - void LpCplex::_clear_temporals() {
1.463 - _col_status.clear();
1.464 - _row_status.clear();
1.465 - _primal_ray.clear();
1.466 - _dual_ray.clear();
1.467 - }
1.468 -
1.469 - // The routine returns zero unless an error occurred during the
1.470 - // optimization. Examples of errors include exhausting available
1.471 - // memory (CPXERR_NO_MEMORY) or encountering invalid data in the
1.472 - // CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a
1.473 - // user-specified CPLEX limit, or proving the model infeasible or
1.474 - // unbounded, are not considered errors. Note that a zero return
1.475 - // value does not necessarily mean that a solution exists. Use query
1.476 - // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
1.477 - // further information about the status of the optimization.
1.478 - LpCplex::SolveExitStatus LpCplex::convertStatus(int status) {
1.479 -#if CPX_VERSION >= 800
1.480 - if (status == 0) {
1.481 - switch (CPXgetstat(cplexEnv(), _prob)) {
1.482 - case CPX_STAT_OPTIMAL:
1.483 - case CPX_STAT_INFEASIBLE:
1.484 - case CPX_STAT_UNBOUNDED:
1.485 - return SOLVED;
1.486 - default:
1.487 - return UNSOLVED;
1.488 - }
1.489 - } else {
1.490 - return UNSOLVED;
1.491 - }
1.492 -#else
1.493 - if (status == 0) {
1.494 - //We want to exclude some cases
1.495 - switch (CPXgetstat(cplexEnv(), _prob)) {
1.496 - case CPX_OBJ_LIM:
1.497 - case CPX_IT_LIM_FEAS:
1.498 - case CPX_IT_LIM_INFEAS:
1.499 - case CPX_TIME_LIM_FEAS:
1.500 - case CPX_TIME_LIM_INFEAS:
1.501 - return UNSOLVED;
1.502 - default:
1.503 - return SOLVED;
1.504 - }
1.505 - } else {
1.506 - return UNSOLVED;
1.507 - }
1.508 -#endif
1.509 - }
1.510 -
1.511 - LpCplex::SolveExitStatus LpCplex::_solve() {
1.512 - _clear_temporals();
1.513 - return convertStatus(CPXlpopt(cplexEnv(), _prob));
1.514 - }
1.515 -
1.516 - LpCplex::SolveExitStatus LpCplex::solvePrimal() {
1.517 - _clear_temporals();
1.518 - return convertStatus(CPXprimopt(cplexEnv(), _prob));
1.519 - }
1.520 -
1.521 - LpCplex::SolveExitStatus LpCplex::solveDual() {
1.522 - _clear_temporals();
1.523 - return convertStatus(CPXdualopt(cplexEnv(), _prob));
1.524 - }
1.525 -
1.526 - LpCplex::SolveExitStatus LpCplex::solveBarrier() {
1.527 - _clear_temporals();
1.528 - return convertStatus(CPXbaropt(cplexEnv(), _prob));
1.529 - }
1.530 -
1.531 - LpCplex::Value LpCplex::_getPrimal(int i) const {
1.532 - Value x;
1.533 - CPXgetx(cplexEnv(), _prob, &x, i, i);
1.534 - return x;
1.535 - }
1.536 -
1.537 - LpCplex::Value LpCplex::_getDual(int i) const {
1.538 - Value y;
1.539 - CPXgetpi(cplexEnv(), _prob, &y, i, i);
1.540 - return y;
1.541 - }
1.542 -
1.543 - LpCplex::Value LpCplex::_getPrimalValue() const {
1.544 - Value objval;
1.545 - CPXgetobjval(cplexEnv(), _prob, &objval);
1.546 - return objval;
1.547 - }
1.548 -
1.549 - LpCplex::VarStatus LpCplex::_getColStatus(int i) const {
1.550 - if (_col_status.empty()) {
1.551 - _col_status.resize(CPXgetnumcols(cplexEnv(), _prob));
1.552 - CPXgetbase(cplexEnv(), _prob, &_col_status.front(), 0);
1.553 - }
1.554 - switch (_col_status[i]) {
1.555 - case CPX_BASIC:
1.556 - return BASIC;
1.557 - case CPX_FREE_SUPER:
1.558 - return FREE;
1.559 - case CPX_AT_LOWER:
1.560 - return LOWER;
1.561 - case CPX_AT_UPPER:
1.562 - return UPPER;
1.563 - default:
1.564 - LEMON_ASSERT(false, "Wrong column status");
1.565 - return LpCplex::VarStatus();
1.566 - }
1.567 - }
1.568 -
1.569 - LpCplex::VarStatus LpCplex::_getRowStatus(int i) const {
1.570 - if (_row_status.empty()) {
1.571 - _row_status.resize(CPXgetnumrows(cplexEnv(), _prob));
1.572 - CPXgetbase(cplexEnv(), _prob, 0, &_row_status.front());
1.573 - }
1.574 - switch (_row_status[i]) {
1.575 - case CPX_BASIC:
1.576 - return BASIC;
1.577 - case CPX_AT_LOWER:
1.578 - {
1.579 - char s;
1.580 - CPXgetsense(cplexEnv(), _prob, &s, i, i);
1.581 - return s != 'L' ? LOWER : UPPER;
1.582 - }
1.583 - case CPX_AT_UPPER:
1.584 - return UPPER;
1.585 - default:
1.586 - LEMON_ASSERT(false, "Wrong row status");
1.587 - return LpCplex::VarStatus();
1.588 - }
1.589 - }
1.590 -
1.591 - LpCplex::Value LpCplex::_getPrimalRay(int i) const {
1.592 - if (_primal_ray.empty()) {
1.593 - _primal_ray.resize(CPXgetnumcols(cplexEnv(), _prob));
1.594 - CPXgetray(cplexEnv(), _prob, &_primal_ray.front());
1.595 - }
1.596 - return _primal_ray[i];
1.597 - }
1.598 -
1.599 - LpCplex::Value LpCplex::_getDualRay(int i) const {
1.600 - if (_dual_ray.empty()) {
1.601 -
1.602 - }
1.603 - return _dual_ray[i];
1.604 - }
1.605 -
1.606 - //7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
1.607 - // This table lists the statuses, returned by the CPXgetstat()
1.608 - // routine, for solutions to LP problems or mixed integer problems. If
1.609 - // no solution exists, the return value is zero.
1.610 -
1.611 - // For Simplex, Barrier
1.612 - // 1 CPX_OPTIMAL
1.613 - // Optimal solution found
1.614 - // 2 CPX_INFEASIBLE
1.615 - // Problem infeasible
1.616 - // 3 CPX_UNBOUNDED
1.617 - // Problem unbounded
1.618 - // 4 CPX_OBJ_LIM
1.619 - // Objective limit exceeded in Phase II
1.620 - // 5 CPX_IT_LIM_FEAS
1.621 - // Iteration limit exceeded in Phase II
1.622 - // 6 CPX_IT_LIM_INFEAS
1.623 - // Iteration limit exceeded in Phase I
1.624 - // 7 CPX_TIME_LIM_FEAS
1.625 - // Time limit exceeded in Phase II
1.626 - // 8 CPX_TIME_LIM_INFEAS
1.627 - // Time limit exceeded in Phase I
1.628 - // 9 CPX_NUM_BEST_FEAS
1.629 - // Problem non-optimal, singularities in Phase II
1.630 - // 10 CPX_NUM_BEST_INFEAS
1.631 - // Problem non-optimal, singularities in Phase I
1.632 - // 11 CPX_OPTIMAL_INFEAS
1.633 - // Optimal solution found, unscaled infeasibilities
1.634 - // 12 CPX_ABORT_FEAS
1.635 - // Aborted in Phase II
1.636 - // 13 CPX_ABORT_INFEAS
1.637 - // Aborted in Phase I
1.638 - // 14 CPX_ABORT_DUAL_INFEAS
1.639 - // Aborted in barrier, dual infeasible
1.640 - // 15 CPX_ABORT_PRIM_INFEAS
1.641 - // Aborted in barrier, primal infeasible
1.642 - // 16 CPX_ABORT_PRIM_DUAL_INFEAS
1.643 - // Aborted in barrier, primal and dual infeasible
1.644 - // 17 CPX_ABORT_PRIM_DUAL_FEAS
1.645 - // Aborted in barrier, primal and dual feasible
1.646 - // 18 CPX_ABORT_CROSSOVER
1.647 - // Aborted in crossover
1.648 - // 19 CPX_INForUNBD
1.649 - // Infeasible or unbounded
1.650 - // 20 CPX_PIVOT
1.651 - // User pivot used
1.652 - //
1.653 - // Ezeket hova tegyem:
1.654 - // ??case CPX_ABORT_DUAL_INFEAS
1.655 - // ??case CPX_ABORT_CROSSOVER
1.656 - // ??case CPX_INForUNBD
1.657 - // ??case CPX_PIVOT
1.658 -
1.659 - //Some more interesting stuff:
1.660 -
1.661 - // CPX_PARAM_PROBMETHOD 1062 int LPMETHOD
1.662 - // 0 Automatic
1.663 - // 1 Primal Simplex
1.664 - // 2 Dual Simplex
1.665 - // 3 Network Simplex
1.666 - // 4 Standard Barrier
1.667 - // Default: 0
1.668 - // Description: Method for linear optimization.
1.669 - // Determines which algorithm is used when CPXlpopt() (or "optimize"
1.670 - // in the Interactive Optimizer) is called. Currently the behavior of
1.671 - // the "Automatic" setting is that CPLEX simply invokes the dual
1.672 - // simplex method, but this capability may be expanded in the future
1.673 - // so that CPLEX chooses the method based on problem characteristics
1.674 -#if CPX_VERSION < 900
1.675 - void statusSwitch(CPXENVptr cplexEnv(),int& stat){
1.676 - int lpmethod;
1.677 - CPXgetintparam (cplexEnv(),CPX_PARAM_PROBMETHOD,&lpmethod);
1.678 - if (lpmethod==2){
1.679 - if (stat==CPX_UNBOUNDED){
1.680 - stat=CPX_INFEASIBLE;
1.681 - }
1.682 - else{
1.683 - if (stat==CPX_INFEASIBLE)
1.684 - stat=CPX_UNBOUNDED;
1.685 - }
1.686 - }
1.687 - }
1.688 -#else
1.689 - void statusSwitch(CPXENVptr,int&){}
1.690 -#endif
1.691 -
1.692 - LpCplex::ProblemType LpCplex::_getPrimalType() const {
1.693 - // Unboundedness not treated well: the following is from cplex 9.0 doc
1.694 - // About Unboundedness
1.695 -
1.696 - // The treatment of models that are unbounded involves a few
1.697 - // subtleties. Specifically, a declaration of unboundedness means that
1.698 - // ILOG CPLEX has determined that the model has an unbounded
1.699 - // ray. Given any feasible solution x with objective z, a multiple of
1.700 - // the unbounded ray can be added to x to give a feasible solution
1.701 - // with objective z-1 (or z+1 for maximization models). Thus, if a
1.702 - // feasible solution exists, then the optimal objective is
1.703 - // unbounded. Note that ILOG CPLEX has not necessarily concluded that
1.704 - // a feasible solution exists. Users can call the routine CPXsolninfo
1.705 - // to determine whether ILOG CPLEX has also concluded that the model
1.706 - // has a feasible solution.
1.707 -
1.708 - int stat = CPXgetstat(cplexEnv(), _prob);
1.709 -#if CPX_VERSION >= 800
1.710 - switch (stat)
1.711 - {
1.712 - case CPX_STAT_OPTIMAL:
1.713 - return OPTIMAL;
1.714 - case CPX_STAT_UNBOUNDED:
1.715 - return UNBOUNDED;
1.716 - case CPX_STAT_INFEASIBLE:
1.717 - return INFEASIBLE;
1.718 - default:
1.719 - return UNDEFINED;
1.720 - }
1.721 -#else
1.722 - statusSwitch(cplexEnv(),stat);
1.723 - //CPXgetstat(cplexEnv(), _prob);
1.724 - //printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL);
1.725 - switch (stat) {
1.726 - case 0:
1.727 - return UNDEFINED; //Undefined
1.728 - case CPX_OPTIMAL://Optimal
1.729 - return OPTIMAL;
1.730 - case CPX_UNBOUNDED://Unbounded
1.731 - return INFEASIBLE;//In case of dual simplex
1.732 - //return UNBOUNDED;
1.733 - case CPX_INFEASIBLE://Infeasible
1.734 - // case CPX_IT_LIM_INFEAS:
1.735 - // case CPX_TIME_LIM_INFEAS:
1.736 - // case CPX_NUM_BEST_INFEAS:
1.737 - // case CPX_OPTIMAL_INFEAS:
1.738 - // case CPX_ABORT_INFEAS:
1.739 - // case CPX_ABORT_PRIM_INFEAS:
1.740 - // case CPX_ABORT_PRIM_DUAL_INFEAS:
1.741 - return UNBOUNDED;//In case of dual simplex
1.742 - //return INFEASIBLE;
1.743 - // case CPX_OBJ_LIM:
1.744 - // case CPX_IT_LIM_FEAS:
1.745 - // case CPX_TIME_LIM_FEAS:
1.746 - // case CPX_NUM_BEST_FEAS:
1.747 - // case CPX_ABORT_FEAS:
1.748 - // case CPX_ABORT_PRIM_DUAL_FEAS:
1.749 - // return FEASIBLE;
1.750 - default:
1.751 - return UNDEFINED; //Everything else comes here
1.752 - //FIXME error
1.753 - }
1.754 -#endif
1.755 - }
1.756 -
1.757 - //9.0-as cplex verzio statusai
1.758 - // CPX_STAT_ABORT_DUAL_OBJ_LIM
1.759 - // CPX_STAT_ABORT_IT_LIM
1.760 - // CPX_STAT_ABORT_OBJ_LIM
1.761 - // CPX_STAT_ABORT_PRIM_OBJ_LIM
1.762 - // CPX_STAT_ABORT_TIME_LIM
1.763 - // CPX_STAT_ABORT_USER
1.764 - // CPX_STAT_FEASIBLE_RELAXED
1.765 - // CPX_STAT_INFEASIBLE
1.766 - // CPX_STAT_INForUNBD
1.767 - // CPX_STAT_NUM_BEST
1.768 - // CPX_STAT_OPTIMAL
1.769 - // CPX_STAT_OPTIMAL_FACE_UNBOUNDED
1.770 - // CPX_STAT_OPTIMAL_INFEAS
1.771 - // CPX_STAT_OPTIMAL_RELAXED
1.772 - // CPX_STAT_UNBOUNDED
1.773 -
1.774 - LpCplex::ProblemType LpCplex::_getDualType() const {
1.775 - int stat = CPXgetstat(cplexEnv(), _prob);
1.776 -#if CPX_VERSION >= 800
1.777 - switch (stat) {
1.778 - case CPX_STAT_OPTIMAL:
1.779 - return OPTIMAL;
1.780 - case CPX_STAT_UNBOUNDED:
1.781 - return INFEASIBLE;
1.782 - default:
1.783 - return UNDEFINED;
1.784 - }
1.785 -#else
1.786 - statusSwitch(cplexEnv(),stat);
1.787 - switch (stat) {
1.788 - case 0:
1.789 - return UNDEFINED; //Undefined
1.790 - case CPX_OPTIMAL://Optimal
1.791 - return OPTIMAL;
1.792 - case CPX_UNBOUNDED:
1.793 - return INFEASIBLE;
1.794 - default:
1.795 - return UNDEFINED; //Everything else comes here
1.796 - //FIXME error
1.797 - }
1.798 -#endif
1.799 - }
1.800 -
1.801 - // MipCplex members
1.802 -
1.803 - MipCplex::MipCplex()
1.804 - : LpBase(), CplexBase(), MipSolver() {
1.805 -
1.806 -#if CPX_VERSION < 800
1.807 - CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MIP);
1.808 -#else
1.809 - CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MILP);
1.810 -#endif
1.811 - }
1.812 -
1.813 - MipCplex::MipCplex(const CplexEnv& env)
1.814 - : LpBase(), CplexBase(env), MipSolver() {
1.815 -
1.816 -#if CPX_VERSION < 800
1.817 - CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MIP);
1.818 -#else
1.819 - CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MILP);
1.820 -#endif
1.821 -
1.822 - }
1.823 -
1.824 - MipCplex::MipCplex(const MipCplex& other)
1.825 - : LpBase(), CplexBase(other), MipSolver() {}
1.826 -
1.827 - MipCplex::~MipCplex() {}
1.828 -
1.829 - MipCplex* MipCplex::_newSolver() const { return new MipCplex; }
1.830 - MipCplex* MipCplex::_cloneSolver() const {return new MipCplex(*this); }
1.831 -
1.832 - const char* MipCplex::_solverName() const { return "MipCplex"; }
1.833 -
1.834 - void MipCplex::_setColType(int i, MipCplex::ColTypes col_type) {
1.835 -
1.836 - // Note If a variable is to be changed to binary, a call to CPXchgbds
1.837 - // should also be made to change the bounds to 0 and 1.
1.838 -
1.839 - switch (col_type){
1.840 - case INTEGER: {
1.841 - const char t = 'I';
1.842 - CPXchgctype (cplexEnv(), _prob, 1, &i, &t);
1.843 - } break;
1.844 - case REAL: {
1.845 - const char t = 'C';
1.846 - CPXchgctype (cplexEnv(), _prob, 1, &i, &t);
1.847 - } break;
1.848 - default:
1.849 - break;
1.850 - }
1.851 - }
1.852 -
1.853 - MipCplex::ColTypes MipCplex::_getColType(int i) const {
1.854 - char t;
1.855 - CPXgetctype (cplexEnv(), _prob, &t, i, i);
1.856 - switch (t) {
1.857 - case 'I':
1.858 - return INTEGER;
1.859 - case 'C':
1.860 - return REAL;
1.861 - default:
1.862 - LEMON_ASSERT(false, "Invalid column type");
1.863 - return ColTypes();
1.864 - }
1.865 -
1.866 - }
1.867 -
1.868 - MipCplex::SolveExitStatus MipCplex::_solve() {
1.869 - int status;
1.870 - status = CPXmipopt (cplexEnv(), _prob);
1.871 - if (status==0)
1.872 - return SOLVED;
1.873 - else
1.874 - return UNSOLVED;
1.875 -
1.876 - }
1.877 -
1.878 -
1.879 - MipCplex::ProblemType MipCplex::_getType() const {
1.880 -
1.881 - int stat = CPXgetstat(cplexEnv(), _prob);
1.882 -
1.883 - //Fortunately, MIP statuses did not change for cplex 8.0
1.884 - switch (stat) {
1.885 - case CPXMIP_OPTIMAL:
1.886 - // Optimal integer solution has been found.
1.887 - case CPXMIP_OPTIMAL_TOL:
1.888 - // Optimal soluton with the tolerance defined by epgap or epagap has
1.889 - // been found.
1.890 - return OPTIMAL;
1.891 - //This also exists in later issues
1.892 - // case CPXMIP_UNBOUNDED:
1.893 - //return UNBOUNDED;
1.894 - case CPXMIP_INFEASIBLE:
1.895 - return INFEASIBLE;
1.896 - default:
1.897 - return UNDEFINED;
1.898 - }
1.899 - //Unboundedness not treated well: the following is from cplex 9.0 doc
1.900 - // About Unboundedness
1.901 -
1.902 - // The treatment of models that are unbounded involves a few
1.903 - // subtleties. Specifically, a declaration of unboundedness means that
1.904 - // ILOG CPLEX has determined that the model has an unbounded
1.905 - // ray. Given any feasible solution x with objective z, a multiple of
1.906 - // the unbounded ray can be added to x to give a feasible solution
1.907 - // with objective z-1 (or z+1 for maximization models). Thus, if a
1.908 - // feasible solution exists, then the optimal objective is
1.909 - // unbounded. Note that ILOG CPLEX has not necessarily concluded that
1.910 - // a feasible solution exists. Users can call the routine CPXsolninfo
1.911 - // to determine whether ILOG CPLEX has also concluded that the model
1.912 - // has a feasible solution.
1.913 - }
1.914 -
1.915 - MipCplex::Value MipCplex::_getSol(int i) const {
1.916 - Value x;
1.917 - CPXgetmipx(cplexEnv(), _prob, &x, i, i);
1.918 - return x;
1.919 - }
1.920 -
1.921 - MipCplex::Value MipCplex::_getSolValue() const {
1.922 - Value objval;
1.923 - CPXgetmipobjval(cplexEnv(), _prob, &objval);
1.924 - return objval;
1.925 - }
1.926 -
1.927 -} //namespace lemon
1.928 -