lemon/lp_cplex.cc
author alpar
Thu, 02 Feb 2006 15:53:01 +0000
changeset 1944 89d5cf6e6abb
parent 1875 98698b69a902
child 1950 a1a6f5b788bd
permissions -rw-r--r--
Use short icpc paths
alpar@1381
     1
/* -*- C++ -*-
ladanyi@1435
     2
 * lemon/lp_cplex.cc - Part of LEMON, a generic C++ optimization library
alpar@1381
     3
 *
alpar@1875
     4
 * Copyright (C) 2006 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@1381
     5
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@1381
     6
 *
alpar@1381
     7
 * Permission to use, modify and distribute this software is granted
alpar@1381
     8
 * provided that this copyright notice appears in all copies. For
alpar@1381
     9
 * precise terms see the accompanying LICENSE file.
alpar@1381
    10
 *
alpar@1381
    11
 * This software is provided "AS IS" with no warranty of any kind,
alpar@1381
    12
 * express or implied, and with no claim as to its suitability for any
alpar@1381
    13
 * purpose.
alpar@1381
    14
 *
alpar@1381
    15
 */
athos@1405
    16
#include <iostream>
athos@1405
    17
#include<lemon/lp_cplex.h>
alpar@1381
    18
alpar@1381
    19
///\file
alpar@1381
    20
///\brief Implementation of the LEMON-CPLEX lp solver interface.
alpar@1381
    21
namespace lemon {
alpar@1381
    22
  
alpar@1381
    23
  LpCplex::LpCplex() : LpSolverBase() {
athos@1436
    24
athos@1436
    25
    //    env = CPXopenCPLEXdevelop(&status);     
athos@1436
    26
    env = CPXopenCPLEX(&status);     
alpar@1381
    27
    lp = CPXcreateprob(env, &status, "LP problem");
alpar@1381
    28
  }
alpar@1381
    29
  
alpar@1381
    30
  LpCplex::~LpCplex() {
athos@1436
    31
    CPXfreeprob(env,&lp); 
athos@1436
    32
    CPXcloseCPLEX(&env); 
alpar@1381
    33
  }
alpar@1381
    34
  
athos@1405
    35
  LpSolverBase &LpCplex::_newLp() 
athos@1405
    36
  {
athos@1436
    37
    //The first approach opens a new environment
athos@1436
    38
    LpCplex* newlp=new LpCplex();
athos@1436
    39
    return *newlp;
athos@1405
    40
  }
athos@1436
    41
athos@1405
    42
  LpSolverBase &LpCplex::_copyLp() {
athos@1436
    43
    //The first approach opens a new environment
athos@1436
    44
    LpCplex* newlp=new LpCplex();
athos@1436
    45
    //The routine CPXcloneprob can be used to create a new CPLEX problem 
athos@1436
    46
    //object and copy all the problem data from an existing problem 
athos@1436
    47
    //object to it. Solution and starting information is not copied.
athos@1508
    48
    newlp->lp = CPXcloneprob(env, lp, &status);
athos@1436
    49
    return *newlp;
athos@1405
    50
  }
alpar@1381
    51
alpar@1381
    52
  int LpCplex::_addCol()
alpar@1381
    53
  {
athos@1508
    54
    int i = CPXgetnumcols(env, lp);
alpar@1381
    55
    Value lb[1],ub[1];
alpar@1381
    56
    lb[0]=-INF;//-CPX_INFBOUND;
alpar@1381
    57
    ub[0]=INF;//CPX_INFBOUND;
athos@1508
    58
    status = CPXnewcols(env, lp, 1, NULL, lb, ub, NULL, NULL);
alpar@1381
    59
    return i;
alpar@1381
    60
  }
athos@1436
    61
alpar@1381
    62
  
alpar@1381
    63
  int LpCplex::_addRow() 
alpar@1381
    64
  {
alpar@1381
    65
    //We want a row that is not constrained
alpar@1381
    66
    char sense[1];
alpar@1381
    67
    sense[0]='L';//<= constraint
alpar@1381
    68
    Value rhs[1];
alpar@1381
    69
    rhs[0]=INF;
athos@1508
    70
    int i = CPXgetnumrows(env, lp);
athos@1508
    71
    status = CPXnewrows(env, lp, 1, rhs, sense, NULL, NULL);
alpar@1381
    72
    return i;
alpar@1381
    73
  }
athos@1432
    74
athos@1432
    75
athos@1432
    76
  void LpCplex::_eraseCol(int i) {
athos@1508
    77
    CPXdelcols(env, lp, i, i);
athos@1432
    78
  }
athos@1432
    79
  
athos@1432
    80
  void LpCplex::_eraseRow(int i) {
athos@1508
    81
    CPXdelrows(env, lp, i, i);
athos@1432
    82
  }
alpar@1895
    83
  
alpar@1895
    84
  void LpCplex::_getColName(int col, std::string &name)
alpar@1895
    85
  {
alpar@1895
    86
    ///\bug Unimplemented
alpar@1895
    87
  }
alpar@1895
    88
  
alpar@1895
    89
  void LpCplex::_setColName(int col, const std::string &name)
alpar@1895
    90
  {
alpar@1895
    91
    ///\bug Untested
alpar@1895
    92
    CPXchgcolname(env, lp, 1, &col, const_cast<char*>(name.c_str()));
alpar@1895
    93
  }
alpar@1381
    94
  
alpar@1381
    95
  ///\warning Data at index 0 is ignored in the arrays.
alpar@1381
    96
  void LpCplex::_setRowCoeffs(int i, 
alpar@1381
    97
			      int length,
alpar@1381
    98
			      int  const * indices, 
alpar@1381
    99
			      Value  const * values )
alpar@1381
   100
  {
alpar@1381
   101
    int rowlist[length+1];
alpar@1381
   102
    int* p=rowlist;
alpar@1381
   103
    for (int k=1;k<=length;++k){
alpar@1381
   104
      rowlist[k]=i;
alpar@1381
   105
    }
alpar@1381
   106
    status = CPXchgcoeflist(env, lp, 
alpar@1381
   107
			    length, 
alpar@1381
   108
			    p+1, 
alpar@1381
   109
			    const_cast<int * >(indices+1), 
alpar@1381
   110
			    const_cast<Value * >(values+1));
alpar@1381
   111
  }
alpar@1381
   112
  
alpar@1381
   113
  void LpCplex::_setColCoeffs(int i, 
alpar@1381
   114
			      int length,
alpar@1381
   115
			      int  const * indices, 
alpar@1381
   116
			      Value  const * values)
alpar@1381
   117
  {
alpar@1381
   118
    int collist[length+1];
alpar@1381
   119
    int* p=collist;
alpar@1381
   120
    for (int k=1;k<=length;++k){
alpar@1381
   121
      collist[k]=i;
alpar@1381
   122
    }
alpar@1381
   123
    status = CPXchgcoeflist(env, lp, 
alpar@1381
   124
			    length, 
alpar@1381
   125
			    const_cast<int * >(indices+1), 
alpar@1381
   126
			    p+1, 
alpar@1381
   127
			    const_cast<Value * >(values+1));
alpar@1381
   128
  }
alpar@1381
   129
  
athos@1431
   130
  void LpCplex::_setCoeff(int row, int col, Value value) 
athos@1431
   131
  {
athos@1508
   132
    CPXchgcoef(env, lp, row, col, value);
athos@1431
   133
  }
athos@1431
   134
alpar@1381
   135
  void LpCplex::_setColLowerBound(int i, Value value)
alpar@1381
   136
  {
alpar@1381
   137
    int indices[1];
alpar@1381
   138
    indices[0]=i;
alpar@1381
   139
    char lu[1];
alpar@1381
   140
    lu[0]='L';
alpar@1381
   141
    Value bd[1];
alpar@1381
   142
    bd[0]=value;
athos@1508
   143
    status = CPXchgbds(env, lp, 1, indices, lu, bd);
alpar@1381
   144
 
alpar@1381
   145
  }
alpar@1381
   146
  
alpar@1381
   147
  void LpCplex::_setColUpperBound(int i, Value value)
alpar@1381
   148
  {
alpar@1381
   149
    int indices[1];
alpar@1381
   150
    indices[0]=i;
alpar@1381
   151
    char lu[1];
alpar@1381
   152
    lu[0]='U';
alpar@1381
   153
    Value bd[1];
alpar@1381
   154
    bd[0]=value;
athos@1508
   155
    status = CPXchgbds(env, lp, 1, indices, lu, bd);
alpar@1381
   156
  }
alpar@1381
   157
alpar@1381
   158
  //This will be easier to implement
alpar@1381
   159
  void LpCplex::_setRowBounds(int i, Value lb, Value ub)
alpar@1381
   160
  {
alpar@1381
   161
    //Bad parameter
alpar@1381
   162
    if (lb==INF || ub==-INF) {
alpar@1381
   163
      //FIXME error
alpar@1381
   164
    }
athos@1405
   165
    
alpar@1381
   166
    int cnt=1;
alpar@1381
   167
    int indices[1];
alpar@1381
   168
    indices[0]=i;
alpar@1381
   169
    char sense[1];
alpar@1381
   170
alpar@1381
   171
    if (lb==-INF){
alpar@1381
   172
      sense[0]='L';
athos@1508
   173
      CPXchgsense(env, lp, cnt, indices, sense);
athos@1508
   174
      CPXchgcoef(env, lp, i, -1, ub);
athos@1405
   175
      
alpar@1381
   176
    }
alpar@1381
   177
    else{
alpar@1381
   178
      if (ub==INF){
alpar@1381
   179
	sense[0]='G';
athos@1508
   180
	CPXchgsense(env, lp, cnt, indices, sense);
athos@1508
   181
	CPXchgcoef(env, lp, i, -1, lb);
alpar@1381
   182
      }
alpar@1381
   183
      else{
alpar@1381
   184
	if (lb == ub){
alpar@1381
   185
	  sense[0]='E';
athos@1508
   186
	  CPXchgsense(env, lp, cnt, indices, sense);
athos@1508
   187
	  CPXchgcoef(env, lp, i, -1, lb);
alpar@1381
   188
	}
alpar@1381
   189
	else{
alpar@1381
   190
	  sense[0]='R';
athos@1508
   191
	  CPXchgsense(env, lp, cnt, indices, sense);
athos@1508
   192
	  CPXchgcoef(env, lp, i, -1, lb);
athos@1508
   193
	  CPXchgcoef(env, lp, i, -2, ub-lb);	  
alpar@1381
   194
	}
alpar@1381
   195
      }
alpar@1381
   196
    }
alpar@1381
   197
  }
alpar@1381
   198
athos@1405
   199
//   void LpCplex::_setRowLowerBound(int i, Value value)
athos@1405
   200
//   {
athos@1405
   201
//     //Not implemented, obsolete
athos@1405
   202
//   }
alpar@1381
   203
  
athos@1405
   204
//   void LpCplex::_setRowUpperBound(int i, Value value)
athos@1405
   205
//   {
athos@1405
   206
//     //Not implemented, obsolete
athos@1405
   207
// //     //TODO Ezt kell meg megirni
athos@1405
   208
// //     //type of the problem
athos@1405
   209
// //     char sense[1];
athos@1508
   210
// //     status = CPXgetsense(env, lp, sense, i, i);
athos@1405
   211
// //     Value rhs[1];
athos@1508
   212
// //     status = CPXgetrhs(env, lp, rhs, i, i);
alpar@1381
   213
athos@1405
   214
// //     switch (sense[0]) {
athos@1405
   215
// //     case 'L'://<= constraint
athos@1405
   216
// //       break;
athos@1405
   217
// //     case 'E'://= constraint
athos@1405
   218
// //       break;
athos@1405
   219
// //     case 'G'://>= constraint
athos@1405
   220
// //       break;
athos@1405
   221
// //     case 'R'://ranged constraint
athos@1405
   222
// //       break;
athos@1405
   223
// //     default: ;
athos@1405
   224
// //       //FIXME error
athos@1405
   225
// //     }
alpar@1381
   226
athos@1508
   227
// //     status = CPXchgcoef(env, lp, i, -2, value_rng);
athos@1405
   228
//   }
alpar@1381
   229
  
alpar@1381
   230
  void LpCplex::_setObjCoeff(int i, Value obj_coef)
alpar@1381
   231
  {
athos@1508
   232
    CPXchgcoef(env, lp, -1, i, obj_coef);
alpar@1381
   233
  }
alpar@1381
   234
alpar@1381
   235
  void LpCplex::_clearObj()
alpar@1381
   236
  {
athos@1508
   237
    for (int i=0;i< CPXgetnumcols(env, lp);++i){
athos@1508
   238
      CPXchgcoef(env, lp, -1, i, 0);
alpar@1381
   239
    }
alpar@1381
   240
    
alpar@1381
   241
  }
athos@1458
   242
  // The routine returns zero unless an error occurred during the
athos@1458
   243
  // optimization. Examples of errors include exhausting available
athos@1458
   244
  // memory (CPXERR_NO_MEMORY) or encountering invalid data in the
athos@1458
   245
  // CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a
athos@1458
   246
  // user-specified CPLEX limit, or proving the model infeasible or
athos@1458
   247
  // unbounded, are not considered errors. Note that a zero return
athos@1458
   248
  // value does not necessarily mean that a solution exists. Use query
athos@1458
   249
  // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
athos@1458
   250
  // further information about the status of the optimization.
alpar@1381
   251
  LpCplex::SolveExitStatus LpCplex::_solve()
alpar@1381
   252
  {
athos@1458
   253
    //CPX_PARAM_LPMETHOD 
athos@1508
   254
    status = CPXlpopt(env, lp);
athos@1542
   255
    //status = CPXprimopt(env, lp);
alpar@1381
   256
    if (status == 0){
athos@1458
   257
      //We want to exclude some cases
athos@1508
   258
      switch (CPXgetstat(env, lp)){
athos@1458
   259
      case CPX_OBJ_LIM:
athos@1458
   260
      case CPX_IT_LIM_FEAS:
athos@1458
   261
      case CPX_IT_LIM_INFEAS:               
athos@1458
   262
      case CPX_TIME_LIM_FEAS:
athos@1458
   263
      case CPX_TIME_LIM_INFEAS:
athos@1458
   264
	return UNSOLVED;
athos@1458
   265
      default:
athos@1458
   266
	return SOLVED; 
athos@1458
   267
      }
alpar@1381
   268
    }
alpar@1381
   269
    else{
alpar@1381
   270
      return UNSOLVED;
alpar@1381
   271
    }
alpar@1381
   272
  }
alpar@1381
   273
athos@1460
   274
  LpCplex::Value LpCplex::_getPrimal(int i)
athos@1460
   275
  {
athos@1460
   276
    Value x;
athos@1508
   277
    CPXgetx(env, lp, &x, i, i);
athos@1460
   278
    return x;
athos@1460
   279
  }
marci@1787
   280
marci@1787
   281
  LpCplex::Value LpCplex::_getDual(int i)
marci@1787
   282
  {
marci@1787
   283
    Value y;
klao@1798
   284
    CPXgetpi(env, lp, &y, i, i);
marci@1787
   285
    return y;
marci@1787
   286
  }
athos@1460
   287
  
athos@1460
   288
  LpCplex::Value LpCplex::_getPrimalValue()
athos@1460
   289
  {
athos@1460
   290
    Value objval;
athos@1460
   291
    //method = CPXgetmethod (env, lp);
athos@1508
   292
    //printf("CPXgetprobtype %d \n",CPXgetprobtype(env,lp));
athos@1508
   293
    status = CPXgetobjval(env, lp, &objval);
athos@1508
   294
    //printf("Objective value: %g \n",objval);
athos@1460
   295
    return objval;
athos@1460
   296
  }
marci@1840
   297
  bool LpCplex::_isBasicCol(int i) {
marci@1841
   298
    int cstat[CPXgetnumcols(env, lp)];
marci@1841
   299
    CPXgetbase(env, lp, cstat, NULL);
marci@1841
   300
    return (cstat[i]==CPX_BASIC);
marci@1840
   301
  }  
athos@1407
   302
athos@1458
   303
//7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
athos@1458
   304
// 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
   305
athos@1458
   306
// For Simplex, Barrier  
athos@1458
   307
// 1  	CPX_OPTIMAL  
athos@1458
   308
// 	 Optimal solution found  
athos@1458
   309
// 2  	CPX_INFEASIBLE  
athos@1458
   310
// 	 Problem infeasible  
athos@1458
   311
// 3    CPX_UNBOUNDED  
athos@1458
   312
// 	 Problem unbounded  
athos@1458
   313
// 4  	CPX_OBJ_LIM  
athos@1458
   314
// 	 Objective limit exceeded in Phase II  
athos@1458
   315
// 5  	CPX_IT_LIM_FEAS  
athos@1458
   316
// 	 Iteration limit exceeded in Phase II  
athos@1458
   317
// 6  	CPX_IT_LIM_INFEAS  
athos@1458
   318
// 	 Iteration limit exceeded in Phase I  
athos@1458
   319
// 7  	CPX_TIME_LIM_FEAS  
athos@1458
   320
// 	 Time limit exceeded in Phase II  
athos@1458
   321
// 8  	CPX_TIME_LIM_INFEAS  
athos@1458
   322
// 	 Time limit exceeded in Phase I  
athos@1458
   323
// 9  	CPX_NUM_BEST_FEAS  
athos@1458
   324
// 	 Problem non-optimal, singularities in Phase II  
athos@1458
   325
// 10 	CPX_NUM_BEST_INFEAS  
athos@1458
   326
// 	 Problem non-optimal, singularities in Phase I  
athos@1458
   327
// 11 	CPX_OPTIMAL_INFEAS  
athos@1458
   328
// 	 Optimal solution found, unscaled infeasibilities  
athos@1458
   329
// 12 	CPX_ABORT_FEAS  
athos@1458
   330
// 	 Aborted in Phase II  
athos@1458
   331
// 13 	CPX_ABORT_INFEAS  
athos@1458
   332
// 	 Aborted in Phase I  
athos@1458
   333
// 14  	CPX_ABORT_DUAL_INFEAS  
athos@1458
   334
// 	 Aborted in barrier, dual infeasible  
athos@1458
   335
// 15  	CPX_ABORT_PRIM_INFEAS  
athos@1458
   336
// 	 Aborted in barrier, primal infeasible  
athos@1458
   337
// 16  	CPX_ABORT_PRIM_DUAL_INFEAS  
athos@1458
   338
// 	 Aborted in barrier, primal and dual infeasible  
athos@1458
   339
// 17  	CPX_ABORT_PRIM_DUAL_FEAS  
athos@1458
   340
// 	 Aborted in barrier, primal and dual feasible  
athos@1458
   341
// 18  	CPX_ABORT_CROSSOVER  
athos@1458
   342
// 	 Aborted in crossover  
athos@1458
   343
// 19  	CPX_INForUNBD  
athos@1458
   344
// 	 Infeasible or unbounded  
athos@1458
   345
// 20   CPX_PIVOT
athos@1458
   346
//       User pivot used
athos@1458
   347
//
athos@1407
   348
//     Ezeket hova tegyem:
athos@1407
   349
// ??case CPX_ABORT_DUAL_INFEAS           
athos@1407
   350
// ??case CPX_ABORT_CROSSOVER             
athos@1407
   351
// ??case CPX_INForUNBD                   
athos@1542
   352
// ??case CPX_PIVOT              
athos@1542
   353
         
athos@1542
   354
//Some more interesting stuff:
athos@1542
   355
athos@1542
   356
// CPX_PARAM_LPMETHOD  1062  int  LPMETHOD
athos@1542
   357
// 0 Automatic 
athos@1542
   358
// 1 Primal Simplex 
athos@1542
   359
// 2 Dual Simplex 
athos@1542
   360
// 3 Network Simplex 
athos@1542
   361
// 4 Standard Barrier 
athos@1542
   362
// Default: 0 
athos@1542
   363
// Description: Method for linear optimization. 
athos@1542
   364
// 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
   365
  //Hulye cplex
athos@1542
   366
  void statusSwitch(CPXENVptr env,int& stat){
athos@1542
   367
    int lpmethod;
athos@1542
   368
    CPXgetintparam (env,CPX_PARAM_LPMETHOD,&lpmethod);
athos@1542
   369
    if (lpmethod==2){
athos@1542
   370
      if (stat==CPX_UNBOUNDED){
athos@1542
   371
	stat=CPX_INFEASIBLE;
athos@1542
   372
      }
athos@1542
   373
      else{
athos@1542
   374
	if (stat==CPX_INFEASIBLE)
athos@1542
   375
	  stat=CPX_UNBOUNDED;
athos@1542
   376
      }
athos@1542
   377
    }
athos@1542
   378
  }
athos@1407
   379
athos@1458
   380
  LpCplex::SolutionStatus LpCplex::_getPrimalStatus()
athos@1458
   381
  {
athos@1542
   382
    
athos@1508
   383
    int stat = CPXgetstat(env, lp);
athos@1542
   384
    statusSwitch(env,stat);
athos@1542
   385
    //CPXgetstat(env, lp);
athos@1508
   386
    //printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL);
athos@1407
   387
    switch (stat) {
athos@1407
   388
    case 0:
athos@1407
   389
      return UNDEFINED; //Undefined
athos@1407
   390
    case CPX_OPTIMAL://Optimal
athos@1407
   391
      return OPTIMAL;
athos@1407
   392
    case CPX_UNBOUNDED://Unbounded
athos@1542
   393
      return INFEASIBLE;//In case of dual simplex
athos@1542
   394
      //return INFINITE;
athos@1407
   395
    case CPX_INFEASIBLE://Infeasible 
athos@1458
   396
 //    case CPX_IT_LIM_INFEAS:
athos@1458
   397
//     case CPX_TIME_LIM_INFEAS:
athos@1458
   398
//     case CPX_NUM_BEST_INFEAS:             
athos@1458
   399
//     case CPX_OPTIMAL_INFEAS:              
athos@1458
   400
//     case CPX_ABORT_INFEAS:                
athos@1458
   401
//     case CPX_ABORT_PRIM_INFEAS:           
athos@1458
   402
//     case CPX_ABORT_PRIM_DUAL_INFEAS:      
athos@1542
   403
      return INFINITE;//In case of dual simplex
athos@1542
   404
      //return INFEASIBLE;
athos@1458
   405
//     case CPX_OBJ_LIM:                    
athos@1458
   406
//     case CPX_IT_LIM_FEAS:             
athos@1458
   407
//     case CPX_TIME_LIM_FEAS:                
athos@1458
   408
//     case CPX_NUM_BEST_FEAS:                
athos@1458
   409
//     case CPX_ABORT_FEAS:                  
athos@1458
   410
//     case CPX_ABORT_PRIM_DUAL_FEAS:        
athos@1458
   411
//       return FEASIBLE;
athos@1407
   412
    default:
athos@1407
   413
      return UNDEFINED; //Everything else comes here
athos@1407
   414
      //FIXME error
athos@1407
   415
    }
athos@1407
   416
athos@1458
   417
  }
athos@1407
   418
athos@1458
   419
//9.0-as cplex verzio statusai
athos@1405
   420
// CPX_STAT_ABORT_DUAL_OBJ_LIM
athos@1405
   421
// CPX_STAT_ABORT_IT_LIM
athos@1405
   422
// CPX_STAT_ABORT_OBJ_LIM
athos@1405
   423
// CPX_STAT_ABORT_PRIM_OBJ_LIM
athos@1405
   424
// CPX_STAT_ABORT_TIME_LIM
athos@1405
   425
// CPX_STAT_ABORT_USER
athos@1405
   426
// CPX_STAT_FEASIBLE_RELAXED
athos@1405
   427
// CPX_STAT_INFEASIBLE
athos@1405
   428
// CPX_STAT_INForUNBD
athos@1405
   429
// CPX_STAT_NUM_BEST
athos@1405
   430
// CPX_STAT_OPTIMAL
athos@1405
   431
// CPX_STAT_OPTIMAL_FACE_UNBOUNDED
athos@1405
   432
// CPX_STAT_OPTIMAL_INFEAS
athos@1405
   433
// CPX_STAT_OPTIMAL_RELAXED
athos@1405
   434
// CPX_STAT_UNBOUNDED
athos@1405
   435
athos@1458
   436
  LpCplex::SolutionStatus LpCplex::_getDualStatus()
athos@1458
   437
  {
athos@1508
   438
    int stat = CPXgetstat(env, lp);
athos@1542
   439
    statusSwitch(env,stat);
athos@1458
   440
    switch (stat) {
athos@1458
   441
    case 0:
athos@1458
   442
      return UNDEFINED; //Undefined
athos@1458
   443
    case CPX_OPTIMAL://Optimal
athos@1458
   444
      return OPTIMAL;
athos@1458
   445
    case CPX_UNBOUNDED:
athos@1458
   446
     return INFEASIBLE;
athos@1458
   447
    default:
athos@1458
   448
      return UNDEFINED; //Everything else comes here
athos@1458
   449
      //FIXME error
athos@1458
   450
    }
athos@1473
   451
  }
alpar@1381
   452
athos@1460
   453
  LpCplex::ProblemTypes LpCplex::_getProblemType()
alpar@1381
   454
  {
athos@1508
   455
    int stat = CPXgetstat(env, lp);
athos@1460
   456
    switch (stat) {
athos@1460
   457
    case CPX_OPTIMAL://Optimal
athos@1460
   458
	return PRIMAL_DUAL_FEASIBLE;
athos@1460
   459
    case CPX_UNBOUNDED:
athos@1460
   460
 	return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
athos@1460
   461
// 	return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
athos@1460
   462
// 	return PRIMAL_DUAL_INFEASIBLE;
athos@1460
   463
athos@1460
   464
//Seems to be that this is all we can say for sure
athos@1460
   465
    default:
athos@1460
   466
	//In all other cases
athos@1460
   467
	return UNKNOWN;
athos@1460
   468
      //FIXME error
athos@1460
   469
    }
athos@1473
   470
  }
alpar@1381
   471
alpar@1381
   472
  void LpCplex::_setMax()
alpar@1381
   473
  {
athos@1508
   474
    CPXchgobjsen(env, lp, CPX_MAX);
alpar@1381
   475
   }
alpar@1381
   476
  void LpCplex::_setMin()
alpar@1381
   477
  {
athos@1508
   478
    CPXchgobjsen(env, lp, CPX_MIN);
alpar@1381
   479
   }
alpar@1381
   480
  
alpar@1381
   481
} //namespace lemon
alpar@1381
   482