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