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