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