lemon/lp_cplex.cc
author Balazs Dezso <deba@inf.elte.hu>
Tue, 02 Dec 2008 21:40:33 +0100
changeset 481 7afc121e0689
child 482 ed54c0d13df0
permissions -rw-r--r--
Port LP and MIP solvers from SVN -r3509 (#44)
deba@481
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
deba@481
     2
 *
deba@481
     3
 * This file is a part of LEMON, a generic C++ optimization library.
deba@481
     4
 *
deba@481
     5
 * Copyright (C) 2003-2008
deba@481
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@481
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@481
     8
 *
deba@481
     9
 * Permission to use, modify and distribute this software is granted
deba@481
    10
 * provided that this copyright notice appears in all copies. For
deba@481
    11
 * precise terms see the accompanying LICENSE file.
deba@481
    12
 *
deba@481
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@481
    14
 * express or implied, and with no claim as to its suitability for any
deba@481
    15
 * purpose.
deba@481
    16
 *
deba@481
    17
 */
deba@481
    18
deba@481
    19
#include <iostream>
deba@481
    20
#include <vector>
deba@481
    21
#include <lemon/lp_cplex.h>
deba@481
    22
deba@481
    23
extern "C" {
deba@481
    24
#include <ilcplex/cplex.h>
deba@481
    25
}
deba@481
    26
deba@481
    27
deba@481
    28
///\file
deba@481
    29
///\brief Implementation of the LEMON-CPLEX lp solver interface.
deba@481
    30
namespace lemon {
deba@481
    31
deba@481
    32
  LpCplex::LpCplex() {
deba@481
    33
    //    env = CPXopenCPLEXdevelop(&status);
deba@481
    34
    env = CPXopenCPLEX(&status);
deba@481
    35
    lp = CPXcreateprob(env, &status, "LP problem");
deba@481
    36
  }
deba@481
    37
deba@481
    38
  LpCplex::LpCplex(const LpCplex& cplex) : LpSolverBase() {
deba@481
    39
    env = CPXopenCPLEX(&status);
deba@481
    40
    lp = CPXcloneprob(env, cplex.lp, &status);
deba@481
    41
    rows = cplex.rows;
deba@481
    42
    cols = cplex.cols;
deba@481
    43
  }
deba@481
    44
deba@481
    45
  LpCplex::~LpCplex() {
deba@481
    46
    CPXfreeprob(env,&lp);
deba@481
    47
    CPXcloseCPLEX(&env);
deba@481
    48
  }
deba@481
    49
deba@481
    50
  LpSolverBase* LpCplex::_newLp()
deba@481
    51
  {
deba@481
    52
    //The first approach opens a new environment
deba@481
    53
    return new LpCplex();
deba@481
    54
  }
deba@481
    55
deba@481
    56
  LpSolverBase* LpCplex::_copyLp() {
deba@481
    57
    return new LpCplex(*this);
deba@481
    58
  }
deba@481
    59
deba@481
    60
  int LpCplex::_addCol()
deba@481
    61
  {
deba@481
    62
    int i = CPXgetnumcols(env, lp);
deba@481
    63
    Value lb[1],ub[1];
deba@481
    64
    lb[0]=-INF;
deba@481
    65
    ub[0]=INF;
deba@481
    66
    status = CPXnewcols(env, lp, 1, NULL, lb, ub, NULL, NULL);
deba@481
    67
    return i;
deba@481
    68
  }
deba@481
    69
deba@481
    70
deba@481
    71
  int LpCplex::_addRow()
deba@481
    72
  {
deba@481
    73
    //We want a row that is not constrained
deba@481
    74
    char sense[1];
deba@481
    75
    sense[0]='L';//<= constraint
deba@481
    76
    Value rhs[1];
deba@481
    77
    rhs[0]=INF;
deba@481
    78
    int i = CPXgetnumrows(env, lp);
deba@481
    79
    status = CPXnewrows(env, lp, 1, rhs, sense, NULL, NULL);
deba@481
    80
    return i;
deba@481
    81
  }
deba@481
    82
deba@481
    83
deba@481
    84
  void LpCplex::_eraseCol(int i) {
deba@481
    85
    CPXdelcols(env, lp, i, i);
deba@481
    86
  }
deba@481
    87
deba@481
    88
  void LpCplex::_eraseRow(int i) {
deba@481
    89
    CPXdelrows(env, lp, i, i);
deba@481
    90
  }
deba@481
    91
deba@481
    92
  void LpCplex::_getColName(int col, std::string &name) const
deba@481
    93
  {
deba@481
    94
    ///\bug Untested
deba@481
    95
    int storespace;
deba@481
    96
    CPXgetcolname(env, lp, 0, 0, 0, &storespace, col, col);
deba@481
    97
    if (storespace == 0) {
deba@481
    98
      name.clear();
deba@481
    99
      return;
deba@481
   100
    }
deba@481
   101
deba@481
   102
    storespace *= -1;
deba@481
   103
    std::vector<char> buf(storespace);
deba@481
   104
    char *names[1];
deba@481
   105
    int dontcare;
deba@481
   106
    ///\bug return code unchecked for error
deba@481
   107
    CPXgetcolname(env, lp, names, &*buf.begin(), storespace,
deba@481
   108
                  &dontcare, col, col);
deba@481
   109
    name = names[0];
deba@481
   110
  }
deba@481
   111
deba@481
   112
  void LpCplex::_setColName(int col, const std::string &name)
deba@481
   113
  {
deba@481
   114
    ///\bug Untested
deba@481
   115
    char *names[1];
deba@481
   116
    names[0] = const_cast<char*>(name.c_str());
deba@481
   117
    ///\bug return code unchecked for error
deba@481
   118
    CPXchgcolname(env, lp, 1, &col, names);
deba@481
   119
  }
deba@481
   120
deba@481
   121
  int LpCplex::_colByName(const std::string& name) const
deba@481
   122
  {
deba@481
   123
    int index;
deba@481
   124
    if (CPXgetcolindex(env, lp,
deba@481
   125
                       const_cast<char*>(name.c_str()), &index) == 0) {
deba@481
   126
      return index;
deba@481
   127
    }
deba@481
   128
    return -1;
deba@481
   129
  }
deba@481
   130
deba@481
   131
  ///\warning Data at index 0 is ignored in the arrays.
deba@481
   132
  void LpCplex::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e)
deba@481
   133
  {
deba@481
   134
    std::vector<int> indices;
deba@481
   135
    std::vector<int> rowlist;
deba@481
   136
    std::vector<Value> values;
deba@481
   137
deba@481
   138
    for(ConstRowIterator it=b; it!=e; ++it) {
deba@481
   139
      indices.push_back(it->first);
deba@481
   140
      values.push_back(it->second);
deba@481
   141
      rowlist.push_back(i);
deba@481
   142
    }
deba@481
   143
deba@481
   144
    status = CPXchgcoeflist(env, lp, values.size(),
deba@481
   145
                            &rowlist[0], &indices[0], &values[0]);
deba@481
   146
  }
deba@481
   147
deba@481
   148
  void LpCplex::_getRowCoeffs(int i, RowIterator b) const {
deba@481
   149
    int tmp1, tmp2, tmp3, length;
deba@481
   150
    CPXgetrows(env, lp, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
deba@481
   151
deba@481
   152
    length = -length;
deba@481
   153
    std::vector<int> indices(length);
deba@481
   154
    std::vector<double> values(length);
deba@481
   155
deba@481
   156
    CPXgetrows(env, lp, &tmp1, &tmp2, &indices[0], &values[0],
deba@481
   157
               length, &tmp3, i, i);
deba@481
   158
deba@481
   159
    for (int i = 0; i < length; ++i) {
deba@481
   160
      *b = std::make_pair(indices[i], values[i]);
deba@481
   161
      ++b;
deba@481
   162
    }
deba@481
   163
deba@481
   164
    /// \todo implement
deba@481
   165
  }
deba@481
   166
deba@481
   167
  void LpCplex::_setColCoeffs(int i, ConstColIterator b, ConstColIterator e)
deba@481
   168
  {
deba@481
   169
    std::vector<int> indices;
deba@481
   170
    std::vector<int> collist;
deba@481
   171
    std::vector<Value> values;
deba@481
   172
deba@481
   173
    for(ConstColIterator it=b; it!=e; ++it) {
deba@481
   174
      indices.push_back(it->first);
deba@481
   175
      values.push_back(it->second);
deba@481
   176
      collist.push_back(i);
deba@481
   177
    }
deba@481
   178
deba@481
   179
    status = CPXchgcoeflist(env, lp, values.size(),
deba@481
   180
                            &indices[0], &collist[0], &values[0]);
deba@481
   181
  }
deba@481
   182
deba@481
   183
  void LpCplex::_getColCoeffs(int i, ColIterator b) const {
deba@481
   184
deba@481
   185
    int tmp1, tmp2, tmp3, length;
deba@481
   186
    CPXgetcols(env, lp, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
deba@481
   187
deba@481
   188
    length = -length;
deba@481
   189
    std::vector<int> indices(length);
deba@481
   190
    std::vector<double> values(length);
deba@481
   191
deba@481
   192
    CPXgetcols(env, lp, &tmp1, &tmp2, &indices[0], &values[0],
deba@481
   193
               length, &tmp3, i, i);
deba@481
   194
deba@481
   195
    for (int i = 0; i < length; ++i) {
deba@481
   196
      *b = std::make_pair(indices[i], values[i]);
deba@481
   197
      ++b;
deba@481
   198
    }
deba@481
   199
deba@481
   200
  }
deba@481
   201
deba@481
   202
  void LpCplex::_setCoeff(int row, int col, Value value)
deba@481
   203
  {
deba@481
   204
    CPXchgcoef(env, lp, row, col, value);
deba@481
   205
  }
deba@481
   206
deba@481
   207
  LpCplex::Value LpCplex::_getCoeff(int row, int col) const
deba@481
   208
  {
deba@481
   209
    LpCplex::Value value;
deba@481
   210
    CPXgetcoef(env, lp, row, col, &value);
deba@481
   211
    return value;
deba@481
   212
  }
deba@481
   213
deba@481
   214
  void LpCplex::_setColLowerBound(int i, Value value)
deba@481
   215
  {
deba@481
   216
    int indices[1];
deba@481
   217
    indices[0]=i;
deba@481
   218
    char lu[1];
deba@481
   219
    lu[0]='L';
deba@481
   220
    Value bd[1];
deba@481
   221
    bd[0]=value;
deba@481
   222
    status = CPXchgbds(env, lp, 1, indices, lu, bd);
deba@481
   223
deba@481
   224
  }
deba@481
   225
deba@481
   226
  LpCplex::Value LpCplex::_getColLowerBound(int i) const
deba@481
   227
  {
deba@481
   228
    LpCplex::Value x;
deba@481
   229
    CPXgetlb (env, lp, &x, i, i);
deba@481
   230
    if (x <= -CPX_INFBOUND) x = -INF;
deba@481
   231
    return x;
deba@481
   232
  }
deba@481
   233
deba@481
   234
  void LpCplex::_setColUpperBound(int i, Value value)
deba@481
   235
  {
deba@481
   236
    int indices[1];
deba@481
   237
    indices[0]=i;
deba@481
   238
    char lu[1];
deba@481
   239
    lu[0]='U';
deba@481
   240
    Value bd[1];
deba@481
   241
    bd[0]=value;
deba@481
   242
    status = CPXchgbds(env, lp, 1, indices, lu, bd);
deba@481
   243
  }
deba@481
   244
deba@481
   245
  LpCplex::Value LpCplex::_getColUpperBound(int i) const
deba@481
   246
  {
deba@481
   247
    LpCplex::Value x;
deba@481
   248
    CPXgetub (env, lp, &x, i, i);
deba@481
   249
    if (x >= CPX_INFBOUND) x = INF;
deba@481
   250
    return x;
deba@481
   251
  }
deba@481
   252
deba@481
   253
  //This will be easier to implement
deba@481
   254
  void LpCplex::_setRowBounds(int i, Value lb, Value ub)
deba@481
   255
  {
deba@481
   256
    //Bad parameter
deba@481
   257
    if (lb==INF || ub==-INF) {
deba@481
   258
      //FIXME error
deba@481
   259
    }
deba@481
   260
deba@481
   261
    int cnt=1;
deba@481
   262
    int indices[1];
deba@481
   263
    indices[0]=i;
deba@481
   264
    char sense[1];
deba@481
   265
deba@481
   266
    if (lb==-INF){
deba@481
   267
      sense[0]='L';
deba@481
   268
      CPXchgsense(env, lp, cnt, indices, sense);
deba@481
   269
      CPXchgcoef(env, lp, i, -1, ub);
deba@481
   270
deba@481
   271
    }
deba@481
   272
    else{
deba@481
   273
      if (ub==INF){
deba@481
   274
        sense[0]='G';
deba@481
   275
        CPXchgsense(env, lp, cnt, indices, sense);
deba@481
   276
        CPXchgcoef(env, lp, i, -1, lb);
deba@481
   277
      }
deba@481
   278
      else{
deba@481
   279
        if (lb == ub){
deba@481
   280
          sense[0]='E';
deba@481
   281
          CPXchgsense(env, lp, cnt, indices, sense);
deba@481
   282
          CPXchgcoef(env, lp, i, -1, lb);
deba@481
   283
        }
deba@481
   284
        else{
deba@481
   285
          sense[0]='R';
deba@481
   286
          CPXchgsense(env, lp, cnt, indices, sense);
deba@481
   287
          CPXchgcoef(env, lp, i, -1, lb);
deba@481
   288
          CPXchgcoef(env, lp, i, -2, ub-lb);
deba@481
   289
        }
deba@481
   290
      }
deba@481
   291
    }
deba@481
   292
  }
deba@481
   293
deba@481
   294
//   void LpCplex::_setRowLowerBound(int i, Value value)
deba@481
   295
//   {
deba@481
   296
//     //Not implemented, obsolete
deba@481
   297
//   }
deba@481
   298
deba@481
   299
//   void LpCplex::_setRowUpperBound(int i, Value value)
deba@481
   300
//   {
deba@481
   301
//     //Not implemented, obsolete
deba@481
   302
// //     //TODO Ezt kell meg megirni
deba@481
   303
// //     //type of the problem
deba@481
   304
// //     char sense[1];
deba@481
   305
// //     status = CPXgetsense(env, lp, sense, i, i);
deba@481
   306
// //     Value rhs[1];
deba@481
   307
// //     status = CPXgetrhs(env, lp, rhs, i, i);
deba@481
   308
deba@481
   309
// //     switch (sense[0]) {
deba@481
   310
// //     case 'L'://<= constraint
deba@481
   311
// //       break;
deba@481
   312
// //     case 'E'://= constraint
deba@481
   313
// //       break;
deba@481
   314
// //     case 'G'://>= constraint
deba@481
   315
// //       break;
deba@481
   316
// //     case 'R'://ranged constraint
deba@481
   317
// //       break;
deba@481
   318
// //     default: ;
deba@481
   319
// //       //FIXME error
deba@481
   320
// //     }
deba@481
   321
deba@481
   322
// //     status = CPXchgcoef(env, lp, i, -2, value_rng);
deba@481
   323
//   }
deba@481
   324
deba@481
   325
  void LpCplex::_getRowBounds(int i, Value &lb, Value &ub) const
deba@481
   326
  {
deba@481
   327
    char sense;
deba@481
   328
    CPXgetsense(env, lp, &sense,i,i);
deba@481
   329
    lb=-INF;
deba@481
   330
    ub=INF;
deba@481
   331
    switch (sense)
deba@481
   332
      {
deba@481
   333
      case 'L':
deba@481
   334
        CPXgetcoef(env, lp, i, -1, &ub);
deba@481
   335
        break;
deba@481
   336
      case 'G':
deba@481
   337
        CPXgetcoef(env, lp, i, -1, &lb);
deba@481
   338
        break;
deba@481
   339
      case 'E':
deba@481
   340
        CPXgetcoef(env, lp, i, -1, &lb);
deba@481
   341
        ub=lb;
deba@481
   342
        break;
deba@481
   343
      case 'R':
deba@481
   344
        CPXgetcoef(env, lp, i, -1, &lb);
deba@481
   345
        Value x;
deba@481
   346
        CPXgetcoef(env, lp, i, -2, &x);
deba@481
   347
        ub=lb+x;
deba@481
   348
        break;
deba@481
   349
      }
deba@481
   350
  }
deba@481
   351
deba@481
   352
  void LpCplex::_setObjCoeff(int i, Value obj_coef)
deba@481
   353
  {
deba@481
   354
    CPXchgcoef(env, lp, -1, i, obj_coef);
deba@481
   355
  }
deba@481
   356
deba@481
   357
  LpCplex::Value LpCplex::_getObjCoeff(int i) const
deba@481
   358
  {
deba@481
   359
    Value x;
deba@481
   360
    CPXgetcoef(env, lp, -1, i, &x);
deba@481
   361
    return x;
deba@481
   362
  }
deba@481
   363
deba@481
   364
  void LpCplex::_clearObj()
deba@481
   365
  {
deba@481
   366
    for (int i=0;i< CPXgetnumcols(env, lp);++i){
deba@481
   367
      CPXchgcoef(env, lp, -1, i, 0);
deba@481
   368
    }
deba@481
   369
deba@481
   370
  }
deba@481
   371
  // The routine returns zero unless an error occurred during the
deba@481
   372
  // optimization. Examples of errors include exhausting available
deba@481
   373
  // memory (CPXERR_NO_MEMORY) or encountering invalid data in the
deba@481
   374
  // CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a
deba@481
   375
  // user-specified CPLEX limit, or proving the model infeasible or
deba@481
   376
  // unbounded, are not considered errors. Note that a zero return
deba@481
   377
  // value does not necessarily mean that a solution exists. Use query
deba@481
   378
  // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
deba@481
   379
  // further information about the status of the optimization.
deba@481
   380
  LpCplex::SolveExitStatus LpCplex::_solve()
deba@481
   381
  {
deba@481
   382
    //CPX_PARAM_LPMETHOD
deba@481
   383
    status = CPXlpopt(env, lp);
deba@481
   384
    //status = CPXprimopt(env, lp);
deba@481
   385
#if CPX_VERSION >= 800
deba@481
   386
    if (status)
deba@481
   387
    {
deba@481
   388
      return UNSOLVED;
deba@481
   389
    }
deba@481
   390
    else
deba@481
   391
    {
deba@481
   392
      switch (CPXgetstat(env, lp))
deba@481
   393
      {
deba@481
   394
        case CPX_STAT_OPTIMAL:
deba@481
   395
        case CPX_STAT_INFEASIBLE:
deba@481
   396
        case CPX_STAT_UNBOUNDED:
deba@481
   397
          return SOLVED;
deba@481
   398
        default:
deba@481
   399
          return UNSOLVED;
deba@481
   400
      }
deba@481
   401
    }
deba@481
   402
#else
deba@481
   403
    if (status == 0){
deba@481
   404
      //We want to exclude some cases
deba@481
   405
      switch (CPXgetstat(env, lp)){
deba@481
   406
      case CPX_OBJ_LIM:
deba@481
   407
      case CPX_IT_LIM_FEAS:
deba@481
   408
      case CPX_IT_LIM_INFEAS:
deba@481
   409
      case CPX_TIME_LIM_FEAS:
deba@481
   410
      case CPX_TIME_LIM_INFEAS:
deba@481
   411
        return UNSOLVED;
deba@481
   412
      default:
deba@481
   413
        return SOLVED;
deba@481
   414
      }
deba@481
   415
    }
deba@481
   416
    else{
deba@481
   417
      return UNSOLVED;
deba@481
   418
    }
deba@481
   419
#endif
deba@481
   420
  }
deba@481
   421
deba@481
   422
  LpCplex::Value LpCplex::_getPrimal(int i) const
deba@481
   423
  {
deba@481
   424
    Value x;
deba@481
   425
    CPXgetx(env, lp, &x, i, i);
deba@481
   426
    return x;
deba@481
   427
  }
deba@481
   428
deba@481
   429
  LpCplex::Value LpCplex::_getDual(int i) const
deba@481
   430
  {
deba@481
   431
    Value y;
deba@481
   432
    CPXgetpi(env, lp, &y, i, i);
deba@481
   433
    return y;
deba@481
   434
  }
deba@481
   435
deba@481
   436
  LpCplex::Value LpCplex::_getPrimalValue() const
deba@481
   437
  {
deba@481
   438
    Value objval;
deba@481
   439
    //method = CPXgetmethod (env, lp);
deba@481
   440
    //printf("CPXgetprobtype %d \n",CPXgetprobtype(env,lp));
deba@481
   441
    CPXgetobjval(env, lp, &objval);
deba@481
   442
    //printf("Objective value: %g \n",objval);
deba@481
   443
    return objval;
deba@481
   444
  }
deba@481
   445
  bool LpCplex::_isBasicCol(int i) const
deba@481
   446
  {
deba@481
   447
    std::vector<int> cstat(CPXgetnumcols(env, lp));
deba@481
   448
    CPXgetbase(env, lp, &*cstat.begin(), NULL);
deba@481
   449
    return (cstat[i]==CPX_BASIC);
deba@481
   450
  }
deba@481
   451
deba@481
   452
//7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
deba@481
   453
// This table lists the statuses, returned by the CPXgetstat()
deba@481
   454
// routine, for solutions to LP problems or mixed integer problems. If
deba@481
   455
// no solution exists, the return value is zero.
deba@481
   456
deba@481
   457
// For Simplex, Barrier
deba@481
   458
// 1          CPX_OPTIMAL
deba@481
   459
//          Optimal solution found
deba@481
   460
// 2          CPX_INFEASIBLE
deba@481
   461
//          Problem infeasible
deba@481
   462
// 3    CPX_UNBOUNDED
deba@481
   463
//          Problem unbounded
deba@481
   464
// 4          CPX_OBJ_LIM
deba@481
   465
//          Objective limit exceeded in Phase II
deba@481
   466
// 5          CPX_IT_LIM_FEAS
deba@481
   467
//          Iteration limit exceeded in Phase II
deba@481
   468
// 6          CPX_IT_LIM_INFEAS
deba@481
   469
//          Iteration limit exceeded in Phase I
deba@481
   470
// 7          CPX_TIME_LIM_FEAS
deba@481
   471
//          Time limit exceeded in Phase II
deba@481
   472
// 8          CPX_TIME_LIM_INFEAS
deba@481
   473
//          Time limit exceeded in Phase I
deba@481
   474
// 9          CPX_NUM_BEST_FEAS
deba@481
   475
//          Problem non-optimal, singularities in Phase II
deba@481
   476
// 10         CPX_NUM_BEST_INFEAS
deba@481
   477
//          Problem non-optimal, singularities in Phase I
deba@481
   478
// 11         CPX_OPTIMAL_INFEAS
deba@481
   479
//          Optimal solution found, unscaled infeasibilities
deba@481
   480
// 12         CPX_ABORT_FEAS
deba@481
   481
//          Aborted in Phase II
deba@481
   482
// 13         CPX_ABORT_INFEAS
deba@481
   483
//          Aborted in Phase I
deba@481
   484
// 14          CPX_ABORT_DUAL_INFEAS
deba@481
   485
//          Aborted in barrier, dual infeasible
deba@481
   486
// 15          CPX_ABORT_PRIM_INFEAS
deba@481
   487
//          Aborted in barrier, primal infeasible
deba@481
   488
// 16          CPX_ABORT_PRIM_DUAL_INFEAS
deba@481
   489
//          Aborted in barrier, primal and dual infeasible
deba@481
   490
// 17          CPX_ABORT_PRIM_DUAL_FEAS
deba@481
   491
//          Aborted in barrier, primal and dual feasible
deba@481
   492
// 18          CPX_ABORT_CROSSOVER
deba@481
   493
//          Aborted in crossover
deba@481
   494
// 19          CPX_INForUNBD
deba@481
   495
//          Infeasible or unbounded
deba@481
   496
// 20   CPX_PIVOT
deba@481
   497
//       User pivot used
deba@481
   498
//
deba@481
   499
//     Ezeket hova tegyem:
deba@481
   500
// ??case CPX_ABORT_DUAL_INFEAS
deba@481
   501
// ??case CPX_ABORT_CROSSOVER
deba@481
   502
// ??case CPX_INForUNBD
deba@481
   503
// ??case CPX_PIVOT
deba@481
   504
deba@481
   505
//Some more interesting stuff:
deba@481
   506
deba@481
   507
// CPX_PARAM_LPMETHOD  1062  int  LPMETHOD
deba@481
   508
// 0 Automatic
deba@481
   509
// 1 Primal Simplex
deba@481
   510
// 2 Dual Simplex
deba@481
   511
// 3 Network Simplex
deba@481
   512
// 4 Standard Barrier
deba@481
   513
// Default: 0
deba@481
   514
// Description: Method for linear optimization.
deba@481
   515
// Determines which algorithm is used when CPXlpopt() (or "optimize"
deba@481
   516
// in the Interactive Optimizer) is called. Currently the behavior of
deba@481
   517
// the "Automatic" setting is that CPLEX simply invokes the dual
deba@481
   518
// simplex method, but this capability may be expanded in the future
deba@481
   519
// so that CPLEX chooses the method based on problem characteristics
deba@481
   520
#if CPX_VERSION < 900
deba@481
   521
  void statusSwitch(CPXENVptr env,int& stat){
deba@481
   522
    int lpmethod;
deba@481
   523
    CPXgetintparam (env,CPX_PARAM_LPMETHOD,&lpmethod);
deba@481
   524
    if (lpmethod==2){
deba@481
   525
      if (stat==CPX_UNBOUNDED){
deba@481
   526
        stat=CPX_INFEASIBLE;
deba@481
   527
      }
deba@481
   528
      else{
deba@481
   529
        if (stat==CPX_INFEASIBLE)
deba@481
   530
          stat=CPX_UNBOUNDED;
deba@481
   531
      }
deba@481
   532
    }
deba@481
   533
  }
deba@481
   534
#else
deba@481
   535
  void statusSwitch(CPXENVptr,int&){}
deba@481
   536
#endif
deba@481
   537
deba@481
   538
  LpCplex::SolutionStatus LpCplex::_getPrimalStatus() const
deba@481
   539
  {
deba@481
   540
    //Unboundedness not treated well: the following is from cplex 9.0 doc
deba@481
   541
    // About Unboundedness
deba@481
   542
deba@481
   543
    // The treatment of models that are unbounded involves a few
deba@481
   544
    // subtleties. Specifically, a declaration of unboundedness means that
deba@481
   545
    // ILOG CPLEX has determined that the model has an unbounded
deba@481
   546
    // ray. Given any feasible solution x with objective z, a multiple of
deba@481
   547
    // the unbounded ray can be added to x to give a feasible solution
deba@481
   548
    // with objective z-1 (or z+1 for maximization models). Thus, if a
deba@481
   549
    // feasible solution exists, then the optimal objective is
deba@481
   550
    // unbounded. Note that ILOG CPLEX has not necessarily concluded that
deba@481
   551
    // a feasible solution exists. Users can call the routine CPXsolninfo
deba@481
   552
    // to determine whether ILOG CPLEX has also concluded that the model
deba@481
   553
    // has a feasible solution.
deba@481
   554
deba@481
   555
    int stat = CPXgetstat(env, lp);
deba@481
   556
#if CPX_VERSION >= 800
deba@481
   557
    switch (stat)
deba@481
   558
    {
deba@481
   559
      case CPX_STAT_OPTIMAL:
deba@481
   560
        return OPTIMAL;
deba@481
   561
      case CPX_STAT_UNBOUNDED:
deba@481
   562
        return INFINITE;
deba@481
   563
      case CPX_STAT_INFEASIBLE:
deba@481
   564
        return INFEASIBLE;
deba@481
   565
      default:
deba@481
   566
        return UNDEFINED;
deba@481
   567
    }
deba@481
   568
#else
deba@481
   569
    statusSwitch(env,stat);
deba@481
   570
    //CPXgetstat(env, lp);
deba@481
   571
    //printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL);
deba@481
   572
    switch (stat) {
deba@481
   573
    case 0:
deba@481
   574
      return UNDEFINED; //Undefined
deba@481
   575
    case CPX_OPTIMAL://Optimal
deba@481
   576
      return OPTIMAL;
deba@481
   577
    case CPX_UNBOUNDED://Unbounded
deba@481
   578
      return INFEASIBLE;//In case of dual simplex
deba@481
   579
      //return INFINITE;
deba@481
   580
    case CPX_INFEASIBLE://Infeasible
deba@481
   581
 //    case CPX_IT_LIM_INFEAS:
deba@481
   582
//     case CPX_TIME_LIM_INFEAS:
deba@481
   583
//     case CPX_NUM_BEST_INFEAS:
deba@481
   584
//     case CPX_OPTIMAL_INFEAS:
deba@481
   585
//     case CPX_ABORT_INFEAS:
deba@481
   586
//     case CPX_ABORT_PRIM_INFEAS:
deba@481
   587
//     case CPX_ABORT_PRIM_DUAL_INFEAS:
deba@481
   588
      return INFINITE;//In case of dual simplex
deba@481
   589
      //return INFEASIBLE;
deba@481
   590
//     case CPX_OBJ_LIM:
deba@481
   591
//     case CPX_IT_LIM_FEAS:
deba@481
   592
//     case CPX_TIME_LIM_FEAS:
deba@481
   593
//     case CPX_NUM_BEST_FEAS:
deba@481
   594
//     case CPX_ABORT_FEAS:
deba@481
   595
//     case CPX_ABORT_PRIM_DUAL_FEAS:
deba@481
   596
//       return FEASIBLE;
deba@481
   597
    default:
deba@481
   598
      return UNDEFINED; //Everything else comes here
deba@481
   599
      //FIXME error
deba@481
   600
    }
deba@481
   601
#endif
deba@481
   602
  }
deba@481
   603
deba@481
   604
//9.0-as cplex verzio statusai
deba@481
   605
// CPX_STAT_ABORT_DUAL_OBJ_LIM
deba@481
   606
// CPX_STAT_ABORT_IT_LIM
deba@481
   607
// CPX_STAT_ABORT_OBJ_LIM
deba@481
   608
// CPX_STAT_ABORT_PRIM_OBJ_LIM
deba@481
   609
// CPX_STAT_ABORT_TIME_LIM
deba@481
   610
// CPX_STAT_ABORT_USER
deba@481
   611
// CPX_STAT_FEASIBLE_RELAXED
deba@481
   612
// CPX_STAT_INFEASIBLE
deba@481
   613
// CPX_STAT_INForUNBD
deba@481
   614
// CPX_STAT_NUM_BEST
deba@481
   615
// CPX_STAT_OPTIMAL
deba@481
   616
// CPX_STAT_OPTIMAL_FACE_UNBOUNDED
deba@481
   617
// CPX_STAT_OPTIMAL_INFEAS
deba@481
   618
// CPX_STAT_OPTIMAL_RELAXED
deba@481
   619
// CPX_STAT_UNBOUNDED
deba@481
   620
deba@481
   621
  LpCplex::SolutionStatus LpCplex::_getDualStatus() const
deba@481
   622
  {
deba@481
   623
    int stat = CPXgetstat(env, lp);
deba@481
   624
#if CPX_VERSION >= 800
deba@481
   625
    switch (stat)
deba@481
   626
    {
deba@481
   627
      case CPX_STAT_OPTIMAL:
deba@481
   628
        return OPTIMAL;
deba@481
   629
      case CPX_STAT_UNBOUNDED:
deba@481
   630
        return INFEASIBLE;
deba@481
   631
      default:
deba@481
   632
        return UNDEFINED;
deba@481
   633
    }
deba@481
   634
#else
deba@481
   635
    statusSwitch(env,stat);
deba@481
   636
    switch (stat) {
deba@481
   637
    case 0:
deba@481
   638
      return UNDEFINED; //Undefined
deba@481
   639
    case CPX_OPTIMAL://Optimal
deba@481
   640
      return OPTIMAL;
deba@481
   641
    case CPX_UNBOUNDED:
deba@481
   642
     return INFEASIBLE;
deba@481
   643
    default:
deba@481
   644
      return UNDEFINED; //Everything else comes here
deba@481
   645
      //FIXME error
deba@481
   646
    }
deba@481
   647
#endif
deba@481
   648
  }
deba@481
   649
deba@481
   650
  LpCplex::ProblemTypes LpCplex::_getProblemType() const
deba@481
   651
  {
deba@481
   652
    int stat = CPXgetstat(env, lp);
deba@481
   653
#if CPX_VERSION >= 800
deba@481
   654
    switch (stat)
deba@481
   655
    {
deba@481
   656
      case CPX_STAT_OPTIMAL:
deba@481
   657
        return PRIMAL_DUAL_FEASIBLE;
deba@481
   658
      case CPX_STAT_UNBOUNDED:
deba@481
   659
         return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
deba@481
   660
      default:
deba@481
   661
        return UNKNOWN;
deba@481
   662
    }
deba@481
   663
#else
deba@481
   664
    switch (stat) {
deba@481
   665
    case CPX_OPTIMAL://Optimal
deba@481
   666
        return PRIMAL_DUAL_FEASIBLE;
deba@481
   667
    case CPX_UNBOUNDED:
deba@481
   668
         return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
deba@481
   669
//         return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
deba@481
   670
//         return PRIMAL_DUAL_INFEASIBLE;
deba@481
   671
deba@481
   672
//Seems to be that this is all we can say for sure
deba@481
   673
    default:
deba@481
   674
        //In all other cases
deba@481
   675
        return UNKNOWN;
deba@481
   676
      //FIXME error
deba@481
   677
    }
deba@481
   678
#endif
deba@481
   679
  }
deba@481
   680
deba@481
   681
  void LpCplex::_setMax()
deba@481
   682
  {
deba@481
   683
    CPXchgobjsen(env, lp, CPX_MAX);
deba@481
   684
   }
deba@481
   685
  void LpCplex::_setMin()
deba@481
   686
  {
deba@481
   687
    CPXchgobjsen(env, lp, CPX_MIN);
deba@481
   688
   }
deba@481
   689
deba@481
   690
  bool LpCplex::_isMax() const
deba@481
   691
  {
deba@481
   692
    if (CPXgetobjsen(env, lp)==CPX_MAX)
deba@481
   693
      return true;
deba@481
   694
    else
deba@481
   695
      return false;
deba@481
   696
  }
deba@481
   697
deba@481
   698
} //namespace lemon
deba@481
   699