lemon/lp_cplex.cc
author Balazs Dezso <deba@inf.elte.hu>
Tue, 02 Dec 2008 22:48:28 +0100
changeset 459 ed54c0d13df0
parent 458 7afc121e0689
permissions -rw-r--r--
Thorough redesign of the LP/MIP interface (#44)

- Redesigned class structure
- Redesigned iterators
- Some functions in the basic interface redesigned
- More complete setting functions
- Ray retrieving functions
- Lot of improvements
- Cplex common env
- CLP macro definition to config.h.in
- Update lp.h to also use soplex and clp
- Remove default_solver_name
- New solverName() function in solvers
- Handle exceptions for MipCplex test
- Rename tolerance parameter to epsilon
- Rename MapIt to CoeffIt
- Lot of documentation improvements
- Various bugfixes
deba@458
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
deba@458
     2
 *
deba@458
     3
 * This file is a part of LEMON, a generic C++ optimization library.
deba@458
     4
 *
deba@458
     5
 * Copyright (C) 2003-2008
deba@458
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@458
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@458
     8
 *
deba@458
     9
 * Permission to use, modify and distribute this software is granted
deba@458
    10
 * provided that this copyright notice appears in all copies. For
deba@458
    11
 * precise terms see the accompanying LICENSE file.
deba@458
    12
 *
deba@458
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@458
    14
 * express or implied, and with no claim as to its suitability for any
deba@458
    15
 * purpose.
deba@458
    16
 *
deba@458
    17
 */
deba@458
    18
deba@458
    19
#include <iostream>
deba@458
    20
#include <vector>
deba@459
    21
#include <cstring>
deba@459
    22
deba@458
    23
#include <lemon/lp_cplex.h>
deba@458
    24
deba@458
    25
extern "C" {
deba@458
    26
#include <ilcplex/cplex.h>
deba@458
    27
}
deba@458
    28
deba@458
    29
deba@458
    30
///\file
deba@458
    31
///\brief Implementation of the LEMON-CPLEX lp solver interface.
deba@458
    32
namespace lemon {
deba@458
    33
deba@459
    34
  CplexEnv::LicenseError::LicenseError(int status) {
deba@459
    35
    if (!CPXgeterrorstring(0, status, _message)) {
deba@459
    36
      std::strcpy(_message, "Cplex unknown error");
deba@459
    37
    }
deba@458
    38
  }
deba@458
    39
deba@459
    40
  CplexEnv::CplexEnv() {
deba@459
    41
    int status;
deba@459
    42
    _cnt = new int;
deba@459
    43
    _env = CPXopenCPLEX(&status);
deba@459
    44
    if (_env == 0) {
deba@459
    45
      delete _cnt;
deba@459
    46
      _cnt = 0;
deba@459
    47
      throw LicenseError(status);
deba@459
    48
    }
deba@459
    49
  }
deba@459
    50
deba@459
    51
  CplexEnv::CplexEnv(const CplexEnv& other) {
deba@459
    52
    _env = other._env;
deba@459
    53
    _cnt = other._cnt;
deba@459
    54
    ++(*_cnt);
deba@459
    55
  }
deba@459
    56
deba@459
    57
  CplexEnv& CplexEnv::operator=(const CplexEnv& other) {
deba@459
    58
    _env = other._env;
deba@459
    59
    _cnt = other._cnt;
deba@459
    60
    ++(*_cnt);
deba@459
    61
    return *this;
deba@459
    62
  }
deba@459
    63
deba@459
    64
  CplexEnv::~CplexEnv() {
deba@459
    65
    --(*_cnt);
deba@459
    66
    if (*_cnt == 0) {
deba@459
    67
      delete _cnt;
deba@459
    68
      CPXcloseCPLEX(&_env);
deba@459
    69
    }
deba@459
    70
  }
deba@459
    71
deba@459
    72
  CplexBase::CplexBase() : LpBase() {
deba@459
    73
    int status;
deba@459
    74
    _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
deba@459
    75
  }
deba@459
    76
deba@459
    77
  CplexBase::CplexBase(const CplexEnv& env)
deba@459
    78
    : LpBase(), _env(env) {
deba@459
    79
    int status;
deba@459
    80
    _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
deba@459
    81
  }
deba@459
    82
deba@459
    83
  CplexBase::CplexBase(const CplexBase& cplex)
deba@459
    84
    : LpBase() {
deba@459
    85
    int status;
deba@459
    86
    _prob = CPXcloneprob(cplexEnv(), cplex._prob, &status);
deba@458
    87
    rows = cplex.rows;
deba@458
    88
    cols = cplex.cols;
deba@458
    89
  }
deba@458
    90
deba@459
    91
  CplexBase::~CplexBase() {
deba@459
    92
    CPXfreeprob(cplexEnv(),&_prob);
deba@458
    93
  }
deba@458
    94
deba@459
    95
  int CplexBase::_addCol() {
deba@459
    96
    int i = CPXgetnumcols(cplexEnv(), _prob);
deba@459
    97
    double lb = -INF, ub = INF;
deba@459
    98
    CPXnewcols(cplexEnv(), _prob, 1, 0, &lb, &ub, 0, 0);
deba@458
    99
    return i;
deba@458
   100
  }
deba@458
   101
deba@458
   102
deba@459
   103
  int CplexBase::_addRow() {
deba@459
   104
    int i = CPXgetnumrows(cplexEnv(), _prob);
deba@459
   105
    const double ub = INF;
deba@459
   106
    const char s = 'L';
deba@459
   107
    CPXnewrows(cplexEnv(), _prob, 1, &ub, &s, 0, 0);
deba@458
   108
    return i;
deba@458
   109
  }
deba@458
   110
deba@458
   111
deba@459
   112
  void CplexBase::_eraseCol(int i) {
deba@459
   113
    CPXdelcols(cplexEnv(), _prob, i, i);
deba@458
   114
  }
deba@458
   115
deba@459
   116
  void CplexBase::_eraseRow(int i) {
deba@459
   117
    CPXdelrows(cplexEnv(), _prob, i, i);
deba@458
   118
  }
deba@458
   119
deba@459
   120
  void CplexBase::_eraseColId(int i) {
deba@459
   121
    cols.eraseIndex(i);
deba@459
   122
    cols.shiftIndices(i);
deba@459
   123
  }
deba@459
   124
  void CplexBase::_eraseRowId(int i) {
deba@459
   125
    rows.eraseIndex(i);
deba@459
   126
    rows.shiftIndices(i);
deba@459
   127
  }
deba@459
   128
deba@459
   129
  void CplexBase::_getColName(int col, std::string &name) const {
deba@459
   130
    int size;
deba@459
   131
    CPXgetcolname(cplexEnv(), _prob, 0, 0, 0, &size, col, col);
deba@459
   132
    if (size == 0) {
deba@458
   133
      name.clear();
deba@458
   134
      return;
deba@458
   135
    }
deba@458
   136
deba@459
   137
    size *= -1;
deba@459
   138
    std::vector<char> buf(size);
deba@459
   139
    char *cname;
deba@459
   140
    int tmp;
deba@459
   141
    CPXgetcolname(cplexEnv(), _prob, &cname, &buf.front(), size,
deba@459
   142
                  &tmp, col, col);
deba@459
   143
    name = cname;
deba@458
   144
  }
deba@458
   145
deba@459
   146
  void CplexBase::_setColName(int col, const std::string &name) {
deba@459
   147
    char *cname;
deba@459
   148
    cname = const_cast<char*>(name.c_str());
deba@459
   149
    CPXchgcolname(cplexEnv(), _prob, 1, &col, &cname);
deba@458
   150
  }
deba@458
   151
deba@459
   152
  int CplexBase::_colByName(const std::string& name) const {
deba@458
   153
    int index;
deba@459
   154
    if (CPXgetcolindex(cplexEnv(), _prob,
deba@458
   155
                       const_cast<char*>(name.c_str()), &index) == 0) {
deba@458
   156
      return index;
deba@458
   157
    }
deba@458
   158
    return -1;
deba@458
   159
  }
deba@458
   160
deba@459
   161
  void CplexBase::_getRowName(int row, std::string &name) const {
deba@459
   162
    int size;
deba@459
   163
    CPXgetrowname(cplexEnv(), _prob, 0, 0, 0, &size, row, row);
deba@459
   164
    if (size == 0) {
deba@459
   165
      name.clear();
deba@459
   166
      return;
deba@459
   167
    }
deba@459
   168
deba@459
   169
    size *= -1;
deba@459
   170
    std::vector<char> buf(size);
deba@459
   171
    char *cname;
deba@459
   172
    int tmp;
deba@459
   173
    CPXgetrowname(cplexEnv(), _prob, &cname, &buf.front(), size,
deba@459
   174
                  &tmp, row, row);
deba@459
   175
    name = cname;
deba@459
   176
  }
deba@459
   177
deba@459
   178
  void CplexBase::_setRowName(int row, const std::string &name) {
deba@459
   179
    char *cname;
deba@459
   180
    cname = const_cast<char*>(name.c_str());
deba@459
   181
    CPXchgrowname(cplexEnv(), _prob, 1, &row, &cname);
deba@459
   182
  }
deba@459
   183
deba@459
   184
  int CplexBase::_rowByName(const std::string& name) const {
deba@459
   185
    int index;
deba@459
   186
    if (CPXgetrowindex(cplexEnv(), _prob,
deba@459
   187
                       const_cast<char*>(name.c_str()), &index) == 0) {
deba@459
   188
      return index;
deba@459
   189
    }
deba@459
   190
    return -1;
deba@459
   191
  }
deba@459
   192
deba@459
   193
  void CplexBase::_setRowCoeffs(int i, ExprIterator b,
deba@459
   194
                                      ExprIterator e)
deba@458
   195
  {
deba@458
   196
    std::vector<int> indices;
deba@458
   197
    std::vector<int> rowlist;
deba@458
   198
    std::vector<Value> values;
deba@458
   199
deba@459
   200
    for(ExprIterator it=b; it!=e; ++it) {
deba@458
   201
      indices.push_back(it->first);
deba@458
   202
      values.push_back(it->second);
deba@458
   203
      rowlist.push_back(i);
deba@458
   204
    }
deba@458
   205
deba@459
   206
    CPXchgcoeflist(cplexEnv(), _prob, values.size(),
deba@459
   207
                   &rowlist.front(), &indices.front(), &values.front());
deba@458
   208
  }
deba@458
   209
deba@459
   210
  void CplexBase::_getRowCoeffs(int i, InsertIterator b) const {
deba@458
   211
    int tmp1, tmp2, tmp3, length;
deba@459
   212
    CPXgetrows(cplexEnv(), _prob, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
deba@458
   213
deba@458
   214
    length = -length;
deba@458
   215
    std::vector<int> indices(length);
deba@458
   216
    std::vector<double> values(length);
deba@458
   217
deba@459
   218
    CPXgetrows(cplexEnv(), _prob, &tmp1, &tmp2,
deba@459
   219
               &indices.front(), &values.front(),
deba@458
   220
               length, &tmp3, i, i);
deba@458
   221
deba@458
   222
    for (int i = 0; i < length; ++i) {
deba@458
   223
      *b = std::make_pair(indices[i], values[i]);
deba@458
   224
      ++b;
deba@458
   225
    }
deba@458
   226
  }
deba@458
   227
deba@459
   228
  void CplexBase::_setColCoeffs(int i, ExprIterator b, ExprIterator e) {
deba@458
   229
    std::vector<int> indices;
deba@458
   230
    std::vector<int> collist;
deba@458
   231
    std::vector<Value> values;
deba@458
   232
deba@459
   233
    for(ExprIterator it=b; it!=e; ++it) {
deba@458
   234
      indices.push_back(it->first);
deba@458
   235
      values.push_back(it->second);
deba@458
   236
      collist.push_back(i);
deba@458
   237
    }
deba@458
   238
deba@459
   239
    CPXchgcoeflist(cplexEnv(), _prob, values.size(),
deba@459
   240
                   &indices.front(), &collist.front(), &values.front());
deba@458
   241
  }
deba@458
   242
deba@459
   243
  void CplexBase::_getColCoeffs(int i, InsertIterator b) const {
deba@458
   244
deba@458
   245
    int tmp1, tmp2, tmp3, length;
deba@459
   246
    CPXgetcols(cplexEnv(), _prob, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
deba@458
   247
deba@458
   248
    length = -length;
deba@458
   249
    std::vector<int> indices(length);
deba@458
   250
    std::vector<double> values(length);
deba@458
   251
deba@459
   252
    CPXgetcols(cplexEnv(), _prob, &tmp1, &tmp2,
deba@459
   253
               &indices.front(), &values.front(),
deba@458
   254
               length, &tmp3, i, i);
deba@458
   255
deba@458
   256
    for (int i = 0; i < length; ++i) {
deba@458
   257
      *b = std::make_pair(indices[i], values[i]);
deba@458
   258
      ++b;
deba@458
   259
    }
deba@458
   260
deba@458
   261
  }
deba@458
   262
deba@459
   263
  void CplexBase::_setCoeff(int row, int col, Value value) {
deba@459
   264
    CPXchgcoef(cplexEnv(), _prob, row, col, value);
deba@458
   265
  }
deba@458
   266
deba@459
   267
  CplexBase::Value CplexBase::_getCoeff(int row, int col) const {
deba@459
   268
    CplexBase::Value value;
deba@459
   269
    CPXgetcoef(cplexEnv(), _prob, row, col, &value);
deba@458
   270
    return value;
deba@458
   271
  }
deba@458
   272
deba@459
   273
  void CplexBase::_setColLowerBound(int i, Value value) {
deba@459
   274
    const char s = 'L';
deba@459
   275
    CPXchgbds(cplexEnv(), _prob, 1, &i, &s, &value);
deba@459
   276
  }
deba@459
   277
deba@459
   278
  CplexBase::Value CplexBase::_getColLowerBound(int i) const {
deba@459
   279
    CplexBase::Value res;
deba@459
   280
    CPXgetlb(cplexEnv(), _prob, &res, i, i);
deba@459
   281
    return res <= -CPX_INFBOUND ? -INF : res;
deba@459
   282
  }
deba@459
   283
deba@459
   284
  void CplexBase::_setColUpperBound(int i, Value value)
deba@458
   285
  {
deba@459
   286
    const char s = 'U';
deba@459
   287
    CPXchgbds(cplexEnv(), _prob, 1, &i, &s, &value);
deba@459
   288
  }
deba@459
   289
deba@459
   290
  CplexBase::Value CplexBase::_getColUpperBound(int i) const {
deba@459
   291
    CplexBase::Value res;
deba@459
   292
    CPXgetub(cplexEnv(), _prob, &res, i, i);
deba@459
   293
    return res >= CPX_INFBOUND ? INF : res;
deba@459
   294
  }
deba@459
   295
deba@459
   296
  CplexBase::Value CplexBase::_getRowLowerBound(int i) const {
deba@459
   297
    char s;
deba@459
   298
    CPXgetsense(cplexEnv(), _prob, &s, i, i);
deba@459
   299
    CplexBase::Value res;
deba@459
   300
deba@459
   301
    switch (s) {
deba@459
   302
    case 'G':
deba@459
   303
    case 'R':
deba@459
   304
    case 'E':
deba@459
   305
      CPXgetrhs(cplexEnv(), _prob, &res, i, i);
deba@459
   306
      return res <= -CPX_INFBOUND ? -INF : res;
deba@459
   307
    default:
deba@459
   308
      return -INF;
deba@459
   309
    }
deba@459
   310
  }
deba@459
   311
deba@459
   312
  CplexBase::Value CplexBase::_getRowUpperBound(int i) const {
deba@459
   313
    char s;
deba@459
   314
    CPXgetsense(cplexEnv(), _prob, &s, i, i);
deba@459
   315
    CplexBase::Value res;
deba@459
   316
deba@459
   317
    switch (s) {
deba@459
   318
    case 'L':
deba@459
   319
    case 'E':
deba@459
   320
      CPXgetrhs(cplexEnv(), _prob, &res, i, i);
deba@459
   321
      return res >= CPX_INFBOUND ? INF : res;
deba@459
   322
    case 'R':
deba@459
   323
      CPXgetrhs(cplexEnv(), _prob, &res, i, i);
deba@459
   324
      {
deba@459
   325
        double rng;
deba@459
   326
        CPXgetrngval(cplexEnv(), _prob, &rng, i, i);
deba@459
   327
        res += rng;
deba@459
   328
      }
deba@459
   329
      return res >= CPX_INFBOUND ? INF : res;
deba@459
   330
    default:
deba@459
   331
      return INF;
deba@459
   332
    }
deba@459
   333
  }
deba@459
   334
deba@459
   335
  //This is easier to implement
deba@459
   336
  void CplexBase::_set_row_bounds(int i, Value lb, Value ub) {
deba@459
   337
    if (lb == -INF) {
deba@459
   338
      const char s = 'L';
deba@459
   339
      CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
deba@459
   340
      CPXchgrhs(cplexEnv(), _prob, 1, &i, &ub);
deba@459
   341
    } else if (ub == INF) {
deba@459
   342
      const char s = 'G';
deba@459
   343
      CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
deba@459
   344
      CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
deba@459
   345
    } else if (lb == ub){
deba@459
   346
      const char s = 'E';
deba@459
   347
      CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
deba@459
   348
      CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
deba@459
   349
    } else {
deba@459
   350
      const char s = 'R';
deba@459
   351
      CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
deba@459
   352
      CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
deba@459
   353
      double len = ub - lb;
deba@459
   354
      CPXchgrngval(cplexEnv(), _prob, 1, &i, &len);
deba@459
   355
    }
deba@459
   356
  }
deba@459
   357
deba@459
   358
  void CplexBase::_setRowLowerBound(int i, Value lb)
deba@459
   359
  {
deba@459
   360
    LEMON_ASSERT(lb != INF, "Invalid bound");
deba@459
   361
    _set_row_bounds(i, lb, CplexBase::_getRowUpperBound(i));
deba@459
   362
  }
deba@459
   363
deba@459
   364
  void CplexBase::_setRowUpperBound(int i, Value ub)
deba@459
   365
  {
deba@459
   366
deba@459
   367
    LEMON_ASSERT(ub != -INF, "Invalid bound");
deba@459
   368
    _set_row_bounds(i, CplexBase::_getRowLowerBound(i), ub);
deba@459
   369
  }
deba@459
   370
deba@459
   371
  void CplexBase::_setObjCoeffs(ExprIterator b, ExprIterator e)
deba@459
   372
  {
deba@459
   373
    std::vector<int> indices;
deba@459
   374
    std::vector<Value> values;
deba@459
   375
    for(ExprIterator it=b; it!=e; ++it) {
deba@459
   376
      indices.push_back(it->first);
deba@459
   377
      values.push_back(it->second);
deba@459
   378
    }
deba@459
   379
    CPXchgobj(cplexEnv(), _prob, values.size(),
deba@459
   380
              &indices.front(), &values.front());
deba@458
   381
deba@458
   382
  }
deba@458
   383
deba@459
   384
  void CplexBase::_getObjCoeffs(InsertIterator b) const
deba@458
   385
  {
deba@459
   386
    int num = CPXgetnumcols(cplexEnv(), _prob);
deba@459
   387
    std::vector<Value> x(num);
deba@458
   388
deba@459
   389
    CPXgetobj(cplexEnv(), _prob, &x.front(), 0, num - 1);
deba@459
   390
    for (int i = 0; i < num; ++i) {
deba@459
   391
      if (x[i] != 0.0) {
deba@459
   392
        *b = std::make_pair(i, x[i]);
deba@459
   393
        ++b;
deba@458
   394
      }
deba@458
   395
    }
deba@458
   396
  }
deba@458
   397
deba@459
   398
  void CplexBase::_setObjCoeff(int i, Value obj_coef)
deba@458
   399
  {
deba@459
   400
    CPXchgobj(cplexEnv(), _prob, 1, &i, &obj_coef);
deba@458
   401
  }
deba@458
   402
deba@459
   403
  CplexBase::Value CplexBase::_getObjCoeff(int i) const
deba@458
   404
  {
deba@458
   405
    Value x;
deba@459
   406
    CPXgetobj(cplexEnv(), _prob, &x, i, i);
deba@458
   407
    return x;
deba@458
   408
  }
deba@458
   409
deba@459
   410
  void CplexBase::_setSense(CplexBase::Sense sense) {
deba@459
   411
    switch (sense) {
deba@459
   412
    case MIN:
deba@459
   413
      CPXchgobjsen(cplexEnv(), _prob, CPX_MIN);
deba@459
   414
      break;
deba@459
   415
    case MAX:
deba@459
   416
      CPXchgobjsen(cplexEnv(), _prob, CPX_MAX);
deba@459
   417
      break;
deba@458
   418
    }
deba@459
   419
  }
deba@458
   420
deba@459
   421
  CplexBase::Sense CplexBase::_getSense() const {
deba@459
   422
    switch (CPXgetobjsen(cplexEnv(), _prob)) {
deba@459
   423
    case CPX_MIN:
deba@459
   424
      return MIN;
deba@459
   425
    case CPX_MAX:
deba@459
   426
      return MAX;
deba@459
   427
    default:
deba@459
   428
      LEMON_ASSERT(false, "Invalid sense");
deba@459
   429
      return CplexBase::Sense();
deba@459
   430
    }
deba@458
   431
  }
deba@459
   432
deba@459
   433
  void CplexBase::_clear() {
deba@459
   434
    CPXfreeprob(cplexEnv(),&_prob);
deba@459
   435
    int status;
deba@459
   436
    _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
deba@459
   437
    rows.clear();
deba@459
   438
    cols.clear();
deba@459
   439
  }
deba@459
   440
deba@459
   441
  // LpCplex members
deba@459
   442
deba@459
   443
  LpCplex::LpCplex()
deba@459
   444
    : LpBase(), CplexBase(), LpSolver() {}
deba@459
   445
deba@459
   446
  LpCplex::LpCplex(const CplexEnv& env)
deba@459
   447
    : LpBase(), CplexBase(env), LpSolver() {}
deba@459
   448
deba@459
   449
  LpCplex::LpCplex(const LpCplex& other)
deba@459
   450
    : LpBase(), CplexBase(other), LpSolver() {}
deba@459
   451
deba@459
   452
  LpCplex::~LpCplex() {}
deba@459
   453
deba@459
   454
  LpCplex* LpCplex::_newSolver() const { return new LpCplex; }
deba@459
   455
  LpCplex* LpCplex::_cloneSolver() const {return new LpCplex(*this); }
deba@459
   456
deba@459
   457
  const char* LpCplex::_solverName() const { return "LpCplex"; }
deba@459
   458
deba@459
   459
  void LpCplex::_clear_temporals() {
deba@459
   460
    _col_status.clear();
deba@459
   461
    _row_status.clear();
deba@459
   462
    _primal_ray.clear();
deba@459
   463
    _dual_ray.clear();
deba@459
   464
  }
deba@459
   465
deba@458
   466
  // The routine returns zero unless an error occurred during the
deba@458
   467
  // optimization. Examples of errors include exhausting available
deba@458
   468
  // memory (CPXERR_NO_MEMORY) or encountering invalid data in the
deba@458
   469
  // CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a
deba@458
   470
  // user-specified CPLEX limit, or proving the model infeasible or
deba@458
   471
  // unbounded, are not considered errors. Note that a zero return
deba@458
   472
  // value does not necessarily mean that a solution exists. Use query
deba@458
   473
  // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
deba@458
   474
  // further information about the status of the optimization.
deba@459
   475
  LpCplex::SolveExitStatus LpCplex::convertStatus(int status) {
deba@458
   476
#if CPX_VERSION >= 800
deba@459
   477
    if (status == 0) {
deba@459
   478
      switch (CPXgetstat(cplexEnv(), _prob)) {
deba@459
   479
      case CPX_STAT_OPTIMAL:
deba@459
   480
      case CPX_STAT_INFEASIBLE:
deba@459
   481
      case CPX_STAT_UNBOUNDED:
deba@459
   482
        return SOLVED;
deba@459
   483
      default:
deba@459
   484
        return UNSOLVED;
deba@459
   485
      }
deba@459
   486
    } else {
deba@458
   487
      return UNSOLVED;
deba@458
   488
    }
deba@458
   489
#else
deba@459
   490
    if (status == 0) {
deba@458
   491
      //We want to exclude some cases
deba@459
   492
      switch (CPXgetstat(cplexEnv(), _prob)) {
deba@458
   493
      case CPX_OBJ_LIM:
deba@458
   494
      case CPX_IT_LIM_FEAS:
deba@458
   495
      case CPX_IT_LIM_INFEAS:
deba@458
   496
      case CPX_TIME_LIM_FEAS:
deba@458
   497
      case CPX_TIME_LIM_INFEAS:
deba@458
   498
        return UNSOLVED;
deba@458
   499
      default:
deba@458
   500
        return SOLVED;
deba@458
   501
      }
deba@459
   502
    } else {
deba@458
   503
      return UNSOLVED;
deba@458
   504
    }
deba@458
   505
#endif
deba@458
   506
  }
deba@458
   507
deba@459
   508
  LpCplex::SolveExitStatus LpCplex::_solve() {
deba@459
   509
    _clear_temporals();
deba@459
   510
    return convertStatus(CPXlpopt(cplexEnv(), _prob));
deba@459
   511
  }
deba@459
   512
deba@459
   513
  LpCplex::SolveExitStatus LpCplex::solvePrimal() {
deba@459
   514
    _clear_temporals();
deba@459
   515
    return convertStatus(CPXprimopt(cplexEnv(), _prob));
deba@459
   516
  }
deba@459
   517
deba@459
   518
  LpCplex::SolveExitStatus LpCplex::solveDual() {
deba@459
   519
    _clear_temporals();
deba@459
   520
    return convertStatus(CPXdualopt(cplexEnv(), _prob));
deba@459
   521
  }
deba@459
   522
deba@459
   523
  LpCplex::SolveExitStatus LpCplex::solveBarrier() {
deba@459
   524
    _clear_temporals();
deba@459
   525
    return convertStatus(CPXbaropt(cplexEnv(), _prob));
deba@459
   526
  }
deba@459
   527
deba@459
   528
  LpCplex::Value LpCplex::_getPrimal(int i) const {
deba@458
   529
    Value x;
deba@459
   530
    CPXgetx(cplexEnv(), _prob, &x, i, i);
deba@458
   531
    return x;
deba@458
   532
  }
deba@458
   533
deba@459
   534
  LpCplex::Value LpCplex::_getDual(int i) const {
deba@458
   535
    Value y;
deba@459
   536
    CPXgetpi(cplexEnv(), _prob, &y, i, i);
deba@458
   537
    return y;
deba@458
   538
  }
deba@458
   539
deba@459
   540
  LpCplex::Value LpCplex::_getPrimalValue() const {
deba@458
   541
    Value objval;
deba@459
   542
    CPXgetobjval(cplexEnv(), _prob, &objval);
deba@458
   543
    return objval;
deba@458
   544
  }
deba@459
   545
deba@459
   546
  LpCplex::VarStatus LpCplex::_getColStatus(int i) const {
deba@459
   547
    if (_col_status.empty()) {
deba@459
   548
      _col_status.resize(CPXgetnumcols(cplexEnv(), _prob));
deba@459
   549
      CPXgetbase(cplexEnv(), _prob, &_col_status.front(), 0);
deba@459
   550
    }
deba@459
   551
    switch (_col_status[i]) {
deba@459
   552
    case CPX_BASIC:
deba@459
   553
      return BASIC;
deba@459
   554
    case CPX_FREE_SUPER:
deba@459
   555
      return FREE;
deba@459
   556
    case CPX_AT_LOWER:
deba@459
   557
      return LOWER;
deba@459
   558
    case CPX_AT_UPPER:
deba@459
   559
      return UPPER;
deba@459
   560
    default:
deba@459
   561
      LEMON_ASSERT(false, "Wrong column status");
deba@459
   562
      return LpCplex::VarStatus();
deba@459
   563
    }
deba@458
   564
  }
deba@458
   565
deba@459
   566
  LpCplex::VarStatus LpCplex::_getRowStatus(int i) const {
deba@459
   567
    if (_row_status.empty()) {
deba@459
   568
      _row_status.resize(CPXgetnumrows(cplexEnv(), _prob));
deba@459
   569
      CPXgetbase(cplexEnv(), _prob, 0, &_row_status.front());
deba@459
   570
    }
deba@459
   571
    switch (_row_status[i]) {
deba@459
   572
    case CPX_BASIC:
deba@459
   573
      return BASIC;
deba@459
   574
    case CPX_AT_LOWER:
deba@459
   575
      {
deba@459
   576
        char s;
deba@459
   577
        CPXgetsense(cplexEnv(), _prob, &s, i, i);
deba@459
   578
        return s != 'L' ? LOWER : UPPER;
deba@459
   579
      }
deba@459
   580
    case CPX_AT_UPPER:
deba@459
   581
      return UPPER;
deba@459
   582
    default:
deba@459
   583
      LEMON_ASSERT(false, "Wrong row status");
deba@459
   584
      return LpCplex::VarStatus();
deba@459
   585
    }
deba@459
   586
  }
deba@458
   587
deba@459
   588
  LpCplex::Value LpCplex::_getPrimalRay(int i) const {
deba@459
   589
    if (_primal_ray.empty()) {
deba@459
   590
      _primal_ray.resize(CPXgetnumcols(cplexEnv(), _prob));
deba@459
   591
      CPXgetray(cplexEnv(), _prob, &_primal_ray.front());
deba@459
   592
    }
deba@459
   593
    return _primal_ray[i];
deba@459
   594
  }
deba@458
   595
deba@459
   596
  LpCplex::Value LpCplex::_getDualRay(int i) const {
deba@459
   597
    if (_dual_ray.empty()) {
deba@458
   598
deba@459
   599
    }
deba@459
   600
    return _dual_ray[i];
deba@459
   601
  }
deba@459
   602
deba@459
   603
  //7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
deba@459
   604
  // This table lists the statuses, returned by the CPXgetstat()
deba@459
   605
  // routine, for solutions to LP problems or mixed integer problems. If
deba@459
   606
  // no solution exists, the return value is zero.
deba@459
   607
deba@459
   608
  // For Simplex, Barrier
deba@459
   609
  // 1          CPX_OPTIMAL
deba@459
   610
  //          Optimal solution found
deba@459
   611
  // 2          CPX_INFEASIBLE
deba@459
   612
  //          Problem infeasible
deba@459
   613
  // 3    CPX_UNBOUNDED
deba@459
   614
  //          Problem unbounded
deba@459
   615
  // 4          CPX_OBJ_LIM
deba@459
   616
  //          Objective limit exceeded in Phase II
deba@459
   617
  // 5          CPX_IT_LIM_FEAS
deba@459
   618
  //          Iteration limit exceeded in Phase II
deba@459
   619
  // 6          CPX_IT_LIM_INFEAS
deba@459
   620
  //          Iteration limit exceeded in Phase I
deba@459
   621
  // 7          CPX_TIME_LIM_FEAS
deba@459
   622
  //          Time limit exceeded in Phase II
deba@459
   623
  // 8          CPX_TIME_LIM_INFEAS
deba@459
   624
  //          Time limit exceeded in Phase I
deba@459
   625
  // 9          CPX_NUM_BEST_FEAS
deba@459
   626
  //          Problem non-optimal, singularities in Phase II
deba@459
   627
  // 10         CPX_NUM_BEST_INFEAS
deba@459
   628
  //          Problem non-optimal, singularities in Phase I
deba@459
   629
  // 11         CPX_OPTIMAL_INFEAS
deba@459
   630
  //          Optimal solution found, unscaled infeasibilities
deba@459
   631
  // 12         CPX_ABORT_FEAS
deba@459
   632
  //          Aborted in Phase II
deba@459
   633
  // 13         CPX_ABORT_INFEAS
deba@459
   634
  //          Aborted in Phase I
deba@459
   635
  // 14          CPX_ABORT_DUAL_INFEAS
deba@459
   636
  //          Aborted in barrier, dual infeasible
deba@459
   637
  // 15          CPX_ABORT_PRIM_INFEAS
deba@459
   638
  //          Aborted in barrier, primal infeasible
deba@459
   639
  // 16          CPX_ABORT_PRIM_DUAL_INFEAS
deba@459
   640
  //          Aborted in barrier, primal and dual infeasible
deba@459
   641
  // 17          CPX_ABORT_PRIM_DUAL_FEAS
deba@459
   642
  //          Aborted in barrier, primal and dual feasible
deba@459
   643
  // 18          CPX_ABORT_CROSSOVER
deba@459
   644
  //          Aborted in crossover
deba@459
   645
  // 19          CPX_INForUNBD
deba@459
   646
  //          Infeasible or unbounded
deba@459
   647
  // 20   CPX_PIVOT
deba@459
   648
  //       User pivot used
deba@459
   649
  //
deba@459
   650
  //     Ezeket hova tegyem:
deba@459
   651
  // ??case CPX_ABORT_DUAL_INFEAS
deba@459
   652
  // ??case CPX_ABORT_CROSSOVER
deba@459
   653
  // ??case CPX_INForUNBD
deba@459
   654
  // ??case CPX_PIVOT
deba@459
   655
deba@459
   656
  //Some more interesting stuff:
deba@459
   657
deba@459
   658
  // CPX_PARAM_PROBMETHOD  1062  int  LPMETHOD
deba@459
   659
  // 0 Automatic
deba@459
   660
  // 1 Primal Simplex
deba@459
   661
  // 2 Dual Simplex
deba@459
   662
  // 3 Network Simplex
deba@459
   663
  // 4 Standard Barrier
deba@459
   664
  // Default: 0
deba@459
   665
  // Description: Method for linear optimization.
deba@459
   666
  // Determines which algorithm is used when CPXlpopt() (or "optimize"
deba@459
   667
  // in the Interactive Optimizer) is called. Currently the behavior of
deba@459
   668
  // the "Automatic" setting is that CPLEX simply invokes the dual
deba@459
   669
  // simplex method, but this capability may be expanded in the future
deba@459
   670
  // so that CPLEX chooses the method based on problem characteristics
deba@458
   671
#if CPX_VERSION < 900
deba@459
   672
  void statusSwitch(CPXENVptr cplexEnv(),int& stat){
deba@458
   673
    int lpmethod;
deba@459
   674
    CPXgetintparam (cplexEnv(),CPX_PARAM_PROBMETHOD,&lpmethod);
deba@458
   675
    if (lpmethod==2){
deba@458
   676
      if (stat==CPX_UNBOUNDED){
deba@458
   677
        stat=CPX_INFEASIBLE;
deba@458
   678
      }
deba@458
   679
      else{
deba@458
   680
        if (stat==CPX_INFEASIBLE)
deba@458
   681
          stat=CPX_UNBOUNDED;
deba@458
   682
      }
deba@458
   683
    }
deba@458
   684
  }
deba@458
   685
#else
deba@458
   686
  void statusSwitch(CPXENVptr,int&){}
deba@458
   687
#endif
deba@458
   688
deba@459
   689
  LpCplex::ProblemType LpCplex::_getPrimalType() const {
deba@459
   690
    // Unboundedness not treated well: the following is from cplex 9.0 doc
deba@459
   691
    // About Unboundedness
deba@459
   692
deba@459
   693
    // The treatment of models that are unbounded involves a few
deba@459
   694
    // subtleties. Specifically, a declaration of unboundedness means that
deba@459
   695
    // ILOG CPLEX has determined that the model has an unbounded
deba@459
   696
    // ray. Given any feasible solution x with objective z, a multiple of
deba@459
   697
    // the unbounded ray can be added to x to give a feasible solution
deba@459
   698
    // with objective z-1 (or z+1 for maximization models). Thus, if a
deba@459
   699
    // feasible solution exists, then the optimal objective is
deba@459
   700
    // unbounded. Note that ILOG CPLEX has not necessarily concluded that
deba@459
   701
    // a feasible solution exists. Users can call the routine CPXsolninfo
deba@459
   702
    // to determine whether ILOG CPLEX has also concluded that the model
deba@459
   703
    // has a feasible solution.
deba@459
   704
deba@459
   705
    int stat = CPXgetstat(cplexEnv(), _prob);
deba@459
   706
#if CPX_VERSION >= 800
deba@459
   707
    switch (stat)
deba@459
   708
      {
deba@459
   709
      case CPX_STAT_OPTIMAL:
deba@459
   710
        return OPTIMAL;
deba@459
   711
      case CPX_STAT_UNBOUNDED:
deba@459
   712
        return UNBOUNDED;
deba@459
   713
      case CPX_STAT_INFEASIBLE:
deba@459
   714
        return INFEASIBLE;
deba@459
   715
      default:
deba@459
   716
        return UNDEFINED;
deba@459
   717
      }
deba@459
   718
#else
deba@459
   719
    statusSwitch(cplexEnv(),stat);
deba@459
   720
    //CPXgetstat(cplexEnv(), _prob);
deba@459
   721
    //printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL);
deba@459
   722
    switch (stat) {
deba@459
   723
    case 0:
deba@459
   724
      return UNDEFINED; //Undefined
deba@459
   725
    case CPX_OPTIMAL://Optimal
deba@459
   726
      return OPTIMAL;
deba@459
   727
    case CPX_UNBOUNDED://Unbounded
deba@459
   728
      return INFEASIBLE;//In case of dual simplex
deba@459
   729
      //return UNBOUNDED;
deba@459
   730
    case CPX_INFEASIBLE://Infeasible
deba@459
   731
      //    case CPX_IT_LIM_INFEAS:
deba@459
   732
      //     case CPX_TIME_LIM_INFEAS:
deba@459
   733
      //     case CPX_NUM_BEST_INFEAS:
deba@459
   734
      //     case CPX_OPTIMAL_INFEAS:
deba@459
   735
      //     case CPX_ABORT_INFEAS:
deba@459
   736
      //     case CPX_ABORT_PRIM_INFEAS:
deba@459
   737
      //     case CPX_ABORT_PRIM_DUAL_INFEAS:
deba@459
   738
      return UNBOUNDED;//In case of dual simplex
deba@459
   739
      //return INFEASIBLE;
deba@459
   740
      //     case CPX_OBJ_LIM:
deba@459
   741
      //     case CPX_IT_LIM_FEAS:
deba@459
   742
      //     case CPX_TIME_LIM_FEAS:
deba@459
   743
      //     case CPX_NUM_BEST_FEAS:
deba@459
   744
      //     case CPX_ABORT_FEAS:
deba@459
   745
      //     case CPX_ABORT_PRIM_DUAL_FEAS:
deba@459
   746
      //       return FEASIBLE;
deba@459
   747
    default:
deba@459
   748
      return UNDEFINED; //Everything else comes here
deba@459
   749
      //FIXME error
deba@459
   750
    }
deba@459
   751
#endif
deba@459
   752
  }
deba@459
   753
deba@459
   754
  //9.0-as cplex verzio statusai
deba@459
   755
  // CPX_STAT_ABORT_DUAL_OBJ_LIM
deba@459
   756
  // CPX_STAT_ABORT_IT_LIM
deba@459
   757
  // CPX_STAT_ABORT_OBJ_LIM
deba@459
   758
  // CPX_STAT_ABORT_PRIM_OBJ_LIM
deba@459
   759
  // CPX_STAT_ABORT_TIME_LIM
deba@459
   760
  // CPX_STAT_ABORT_USER
deba@459
   761
  // CPX_STAT_FEASIBLE_RELAXED
deba@459
   762
  // CPX_STAT_INFEASIBLE
deba@459
   763
  // CPX_STAT_INForUNBD
deba@459
   764
  // CPX_STAT_NUM_BEST
deba@459
   765
  // CPX_STAT_OPTIMAL
deba@459
   766
  // CPX_STAT_OPTIMAL_FACE_UNBOUNDED
deba@459
   767
  // CPX_STAT_OPTIMAL_INFEAS
deba@459
   768
  // CPX_STAT_OPTIMAL_RELAXED
deba@459
   769
  // CPX_STAT_UNBOUNDED
deba@459
   770
deba@459
   771
  LpCplex::ProblemType LpCplex::_getDualType() const {
deba@459
   772
    int stat = CPXgetstat(cplexEnv(), _prob);
deba@459
   773
#if CPX_VERSION >= 800
deba@459
   774
    switch (stat) {
deba@459
   775
    case CPX_STAT_OPTIMAL:
deba@459
   776
      return OPTIMAL;
deba@459
   777
    case CPX_STAT_UNBOUNDED:
deba@459
   778
      return INFEASIBLE;
deba@459
   779
    default:
deba@459
   780
      return UNDEFINED;
deba@459
   781
    }
deba@459
   782
#else
deba@459
   783
    statusSwitch(cplexEnv(),stat);
deba@459
   784
    switch (stat) {
deba@459
   785
    case 0:
deba@459
   786
      return UNDEFINED; //Undefined
deba@459
   787
    case CPX_OPTIMAL://Optimal
deba@459
   788
      return OPTIMAL;
deba@459
   789
    case CPX_UNBOUNDED:
deba@459
   790
      return INFEASIBLE;
deba@459
   791
    default:
deba@459
   792
      return UNDEFINED; //Everything else comes here
deba@459
   793
      //FIXME error
deba@459
   794
    }
deba@459
   795
#endif
deba@459
   796
  }
deba@459
   797
deba@459
   798
  // MipCplex members
deba@459
   799
deba@459
   800
  MipCplex::MipCplex()
deba@459
   801
    : LpBase(), CplexBase(), MipSolver() {
deba@459
   802
deba@459
   803
#if CPX_VERSION < 800
deba@459
   804
    CPXchgprobtype(cplexEnv(),  _prob, CPXPROB_MIP);
deba@459
   805
#else
deba@459
   806
    CPXchgprobtype(cplexEnv(),  _prob, CPXPROB_MILP);
deba@459
   807
#endif
deba@459
   808
  }
deba@459
   809
deba@459
   810
  MipCplex::MipCplex(const CplexEnv& env)
deba@459
   811
    : LpBase(), CplexBase(env), MipSolver() {
deba@459
   812
deba@459
   813
#if CPX_VERSION < 800
deba@459
   814
    CPXchgprobtype(cplexEnv(),  _prob, CPXPROB_MIP);
deba@459
   815
#else
deba@459
   816
    CPXchgprobtype(cplexEnv(),  _prob, CPXPROB_MILP);
deba@459
   817
#endif
deba@459
   818
deba@459
   819
  }
deba@459
   820
deba@459
   821
  MipCplex::MipCplex(const MipCplex& other)
deba@459
   822
    : LpBase(), CplexBase(other), MipSolver() {}
deba@459
   823
deba@459
   824
  MipCplex::~MipCplex() {}
deba@459
   825
deba@459
   826
  MipCplex* MipCplex::_newSolver() const { return new MipCplex; }
deba@459
   827
  MipCplex* MipCplex::_cloneSolver() const {return new MipCplex(*this); }
deba@459
   828
deba@459
   829
  const char* MipCplex::_solverName() const { return "MipCplex"; }
deba@459
   830
deba@459
   831
  void MipCplex::_setColType(int i, MipCplex::ColTypes col_type) {
deba@459
   832
deba@459
   833
    // Note If a variable is to be changed to binary, a call to CPXchgbds
deba@459
   834
    // should also be made to change the bounds to 0 and 1.
deba@459
   835
deba@459
   836
    switch (col_type){
deba@459
   837
    case INTEGER: {
deba@459
   838
      const char t = 'I';
deba@459
   839
      CPXchgctype (cplexEnv(), _prob, 1, &i, &t);
deba@459
   840
    } break;
deba@459
   841
    case REAL: {
deba@459
   842
      const char t = 'C';
deba@459
   843
      CPXchgctype (cplexEnv(), _prob, 1, &i, &t);
deba@459
   844
    } break;
deba@459
   845
    default:
deba@459
   846
      break;
deba@459
   847
    }
deba@459
   848
  }
deba@459
   849
deba@459
   850
  MipCplex::ColTypes MipCplex::_getColType(int i) const {
deba@459
   851
    char t;
deba@459
   852
    CPXgetctype (cplexEnv(), _prob, &t, i, i);
deba@459
   853
    switch (t) {
deba@459
   854
    case 'I':
deba@459
   855
      return INTEGER;
deba@459
   856
    case 'C':
deba@459
   857
      return REAL;
deba@459
   858
    default:
deba@459
   859
      LEMON_ASSERT(false, "Invalid column type");
deba@459
   860
      return ColTypes();
deba@459
   861
    }
deba@459
   862
deba@459
   863
  }
deba@459
   864
deba@459
   865
  MipCplex::SolveExitStatus MipCplex::_solve() {
deba@459
   866
    int status;
deba@459
   867
    status = CPXmipopt (cplexEnv(), _prob);
deba@459
   868
    if (status==0)
deba@459
   869
      return SOLVED;
deba@459
   870
    else
deba@459
   871
      return UNSOLVED;
deba@459
   872
deba@459
   873
  }
deba@459
   874
deba@459
   875
deba@459
   876
  MipCplex::ProblemType MipCplex::_getType() const {
deba@459
   877
deba@459
   878
    int stat = CPXgetstat(cplexEnv(), _prob);
deba@459
   879
deba@459
   880
    //Fortunately, MIP statuses did not change for cplex 8.0
deba@459
   881
    switch (stat) {
deba@459
   882
    case CPXMIP_OPTIMAL:
deba@459
   883
      // Optimal integer solution has been found.
deba@459
   884
    case CPXMIP_OPTIMAL_TOL:
deba@459
   885
      // Optimal soluton with the tolerance defined by epgap or epagap has
deba@459
   886
      // been found.
deba@459
   887
      return OPTIMAL;
deba@459
   888
      //This also exists in later issues
deba@459
   889
      //    case CPXMIP_UNBOUNDED:
deba@459
   890
      //return UNBOUNDED;
deba@459
   891
      case CPXMIP_INFEASIBLE:
deba@459
   892
        return INFEASIBLE;
deba@459
   893
    default:
deba@459
   894
      return UNDEFINED;
deba@459
   895
    }
deba@458
   896
    //Unboundedness not treated well: the following is from cplex 9.0 doc
deba@458
   897
    // About Unboundedness
deba@458
   898
deba@458
   899
    // The treatment of models that are unbounded involves a few
deba@458
   900
    // subtleties. Specifically, a declaration of unboundedness means that
deba@458
   901
    // ILOG CPLEX has determined that the model has an unbounded
deba@458
   902
    // ray. Given any feasible solution x with objective z, a multiple of
deba@458
   903
    // the unbounded ray can be added to x to give a feasible solution
deba@458
   904
    // with objective z-1 (or z+1 for maximization models). Thus, if a
deba@458
   905
    // feasible solution exists, then the optimal objective is
deba@458
   906
    // unbounded. Note that ILOG CPLEX has not necessarily concluded that
deba@458
   907
    // a feasible solution exists. Users can call the routine CPXsolninfo
deba@458
   908
    // to determine whether ILOG CPLEX has also concluded that the model
deba@458
   909
    // has a feasible solution.
deba@458
   910
  }
deba@458
   911
deba@459
   912
  MipCplex::Value MipCplex::_getSol(int i) const {
deba@459
   913
    Value x;
deba@459
   914
    CPXgetmipx(cplexEnv(), _prob, &x, i, i);
deba@459
   915
    return x;
deba@458
   916
  }
deba@458
   917
deba@459
   918
  MipCplex::Value MipCplex::_getSolValue() const {
deba@459
   919
    Value objval;
deba@459
   920
    CPXgetmipobjval(cplexEnv(), _prob, &objval);
deba@459
   921
    return objval;
deba@458
   922
  }
deba@458
   923
deba@458
   924
} //namespace lemon
deba@458
   925