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