lemon/lp_cplex.cc
author hegyi
Thu, 20 Oct 2005 15:50:23 +0000
changeset 1731 616bc933c2bc
parent 1508 389a94a1d9eb
child 1787 932b8490caf0
permissions -rw-r--r--
Mapselector widget reached its first release, but there are still work to do on it, I know...
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
  }
athos@1460
   270
  
athos@1460
   271
  LpCplex::Value LpCplex::_getPrimalValue()
athos@1460
   272
  {
athos@1460
   273
    Value objval;
athos@1460
   274
    //method = CPXgetmethod (env, lp);
athos@1508
   275
    //printf("CPXgetprobtype %d \n",CPXgetprobtype(env,lp));
athos@1508
   276
    status = CPXgetobjval(env, lp, &objval);
athos@1508
   277
    //printf("Objective value: %g \n",objval);
athos@1460
   278
    return objval;
athos@1460
   279
  }
athos@1460
   280
  
athos@1407
   281
athos@1458
   282
//7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
athos@1458
   283
// 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
   284
athos@1458
   285
// For Simplex, Barrier  
athos@1458
   286
// 1  	CPX_OPTIMAL  
athos@1458
   287
// 	 Optimal solution found  
athos@1458
   288
// 2  	CPX_INFEASIBLE  
athos@1458
   289
// 	 Problem infeasible  
athos@1458
   290
// 3    CPX_UNBOUNDED  
athos@1458
   291
// 	 Problem unbounded  
athos@1458
   292
// 4  	CPX_OBJ_LIM  
athos@1458
   293
// 	 Objective limit exceeded in Phase II  
athos@1458
   294
// 5  	CPX_IT_LIM_FEAS  
athos@1458
   295
// 	 Iteration limit exceeded in Phase II  
athos@1458
   296
// 6  	CPX_IT_LIM_INFEAS  
athos@1458
   297
// 	 Iteration limit exceeded in Phase I  
athos@1458
   298
// 7  	CPX_TIME_LIM_FEAS  
athos@1458
   299
// 	 Time limit exceeded in Phase II  
athos@1458
   300
// 8  	CPX_TIME_LIM_INFEAS  
athos@1458
   301
// 	 Time limit exceeded in Phase I  
athos@1458
   302
// 9  	CPX_NUM_BEST_FEAS  
athos@1458
   303
// 	 Problem non-optimal, singularities in Phase II  
athos@1458
   304
// 10 	CPX_NUM_BEST_INFEAS  
athos@1458
   305
// 	 Problem non-optimal, singularities in Phase I  
athos@1458
   306
// 11 	CPX_OPTIMAL_INFEAS  
athos@1458
   307
// 	 Optimal solution found, unscaled infeasibilities  
athos@1458
   308
// 12 	CPX_ABORT_FEAS  
athos@1458
   309
// 	 Aborted in Phase II  
athos@1458
   310
// 13 	CPX_ABORT_INFEAS  
athos@1458
   311
// 	 Aborted in Phase I  
athos@1458
   312
// 14  	CPX_ABORT_DUAL_INFEAS  
athos@1458
   313
// 	 Aborted in barrier, dual infeasible  
athos@1458
   314
// 15  	CPX_ABORT_PRIM_INFEAS  
athos@1458
   315
// 	 Aborted in barrier, primal infeasible  
athos@1458
   316
// 16  	CPX_ABORT_PRIM_DUAL_INFEAS  
athos@1458
   317
// 	 Aborted in barrier, primal and dual infeasible  
athos@1458
   318
// 17  	CPX_ABORT_PRIM_DUAL_FEAS  
athos@1458
   319
// 	 Aborted in barrier, primal and dual feasible  
athos@1458
   320
// 18  	CPX_ABORT_CROSSOVER  
athos@1458
   321
// 	 Aborted in crossover  
athos@1458
   322
// 19  	CPX_INForUNBD  
athos@1458
   323
// 	 Infeasible or unbounded  
athos@1458
   324
// 20   CPX_PIVOT
athos@1458
   325
//       User pivot used
athos@1458
   326
//
athos@1407
   327
//     Ezeket hova tegyem:
athos@1407
   328
// ??case CPX_ABORT_DUAL_INFEAS           
athos@1407
   329
// ??case CPX_ABORT_CROSSOVER             
athos@1407
   330
// ??case CPX_INForUNBD                   
athos@1542
   331
// ??case CPX_PIVOT              
athos@1542
   332
         
athos@1542
   333
//Some more interesting stuff:
athos@1542
   334
athos@1542
   335
// CPX_PARAM_LPMETHOD  1062  int  LPMETHOD
athos@1542
   336
// 0 Automatic 
athos@1542
   337
// 1 Primal Simplex 
athos@1542
   338
// 2 Dual Simplex 
athos@1542
   339
// 3 Network Simplex 
athos@1542
   340
// 4 Standard Barrier 
athos@1542
   341
// Default: 0 
athos@1542
   342
// Description: Method for linear optimization. 
athos@1542
   343
// 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
   344
  //Hulye cplex
athos@1542
   345
  void statusSwitch(CPXENVptr env,int& stat){
athos@1542
   346
    int lpmethod;
athos@1542
   347
    CPXgetintparam (env,CPX_PARAM_LPMETHOD,&lpmethod);
athos@1542
   348
    if (lpmethod==2){
athos@1542
   349
      if (stat==CPX_UNBOUNDED){
athos@1542
   350
	stat=CPX_INFEASIBLE;
athos@1542
   351
      }
athos@1542
   352
      else{
athos@1542
   353
	if (stat==CPX_INFEASIBLE)
athos@1542
   354
	  stat=CPX_UNBOUNDED;
athos@1542
   355
      }
athos@1542
   356
    }
athos@1542
   357
  }
athos@1407
   358
athos@1458
   359
  LpCplex::SolutionStatus LpCplex::_getPrimalStatus()
athos@1458
   360
  {
athos@1542
   361
    
athos@1508
   362
    int stat = CPXgetstat(env, lp);
athos@1542
   363
    statusSwitch(env,stat);
athos@1542
   364
    //CPXgetstat(env, lp);
athos@1508
   365
    //printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL);
athos@1407
   366
    switch (stat) {
athos@1407
   367
    case 0:
athos@1407
   368
      return UNDEFINED; //Undefined
athos@1407
   369
    case CPX_OPTIMAL://Optimal
athos@1407
   370
      return OPTIMAL;
athos@1407
   371
    case CPX_UNBOUNDED://Unbounded
athos@1542
   372
      return INFEASIBLE;//In case of dual simplex
athos@1542
   373
      //return INFINITE;
athos@1407
   374
    case CPX_INFEASIBLE://Infeasible 
athos@1458
   375
 //    case CPX_IT_LIM_INFEAS:
athos@1458
   376
//     case CPX_TIME_LIM_INFEAS:
athos@1458
   377
//     case CPX_NUM_BEST_INFEAS:             
athos@1458
   378
//     case CPX_OPTIMAL_INFEAS:              
athos@1458
   379
//     case CPX_ABORT_INFEAS:                
athos@1458
   380
//     case CPX_ABORT_PRIM_INFEAS:           
athos@1458
   381
//     case CPX_ABORT_PRIM_DUAL_INFEAS:      
athos@1542
   382
      return INFINITE;//In case of dual simplex
athos@1542
   383
      //return INFEASIBLE;
athos@1458
   384
//     case CPX_OBJ_LIM:                    
athos@1458
   385
//     case CPX_IT_LIM_FEAS:             
athos@1458
   386
//     case CPX_TIME_LIM_FEAS:                
athos@1458
   387
//     case CPX_NUM_BEST_FEAS:                
athos@1458
   388
//     case CPX_ABORT_FEAS:                  
athos@1458
   389
//     case CPX_ABORT_PRIM_DUAL_FEAS:        
athos@1458
   390
//       return FEASIBLE;
athos@1407
   391
    default:
athos@1407
   392
      return UNDEFINED; //Everything else comes here
athos@1407
   393
      //FIXME error
athos@1407
   394
    }
athos@1407
   395
athos@1458
   396
  }
athos@1407
   397
athos@1458
   398
//9.0-as cplex verzio statusai
athos@1405
   399
// CPX_STAT_ABORT_DUAL_OBJ_LIM
athos@1405
   400
// CPX_STAT_ABORT_IT_LIM
athos@1405
   401
// CPX_STAT_ABORT_OBJ_LIM
athos@1405
   402
// CPX_STAT_ABORT_PRIM_OBJ_LIM
athos@1405
   403
// CPX_STAT_ABORT_TIME_LIM
athos@1405
   404
// CPX_STAT_ABORT_USER
athos@1405
   405
// CPX_STAT_FEASIBLE_RELAXED
athos@1405
   406
// CPX_STAT_INFEASIBLE
athos@1405
   407
// CPX_STAT_INForUNBD
athos@1405
   408
// CPX_STAT_NUM_BEST
athos@1405
   409
// CPX_STAT_OPTIMAL
athos@1405
   410
// CPX_STAT_OPTIMAL_FACE_UNBOUNDED
athos@1405
   411
// CPX_STAT_OPTIMAL_INFEAS
athos@1405
   412
// CPX_STAT_OPTIMAL_RELAXED
athos@1405
   413
// CPX_STAT_UNBOUNDED
athos@1405
   414
athos@1458
   415
  LpCplex::SolutionStatus LpCplex::_getDualStatus()
athos@1458
   416
  {
athos@1508
   417
    int stat = CPXgetstat(env, lp);
athos@1542
   418
    statusSwitch(env,stat);
athos@1458
   419
    switch (stat) {
athos@1458
   420
    case 0:
athos@1458
   421
      return UNDEFINED; //Undefined
athos@1458
   422
    case CPX_OPTIMAL://Optimal
athos@1458
   423
      return OPTIMAL;
athos@1458
   424
    case CPX_UNBOUNDED:
athos@1458
   425
     return INFEASIBLE;
athos@1458
   426
    default:
athos@1458
   427
      return UNDEFINED; //Everything else comes here
athos@1458
   428
      //FIXME error
athos@1458
   429
    }
athos@1473
   430
  }
alpar@1381
   431
athos@1460
   432
  LpCplex::ProblemTypes LpCplex::_getProblemType()
alpar@1381
   433
  {
athos@1508
   434
    int stat = CPXgetstat(env, lp);
athos@1460
   435
    switch (stat) {
athos@1460
   436
    case CPX_OPTIMAL://Optimal
athos@1460
   437
	return PRIMAL_DUAL_FEASIBLE;
athos@1460
   438
    case CPX_UNBOUNDED:
athos@1460
   439
 	return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
athos@1460
   440
// 	return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
athos@1460
   441
// 	return PRIMAL_DUAL_INFEASIBLE;
athos@1460
   442
athos@1460
   443
//Seems to be that this is all we can say for sure
athos@1460
   444
    default:
athos@1460
   445
	//In all other cases
athos@1460
   446
	return UNKNOWN;
athos@1460
   447
      //FIXME error
athos@1460
   448
    }
athos@1473
   449
  }
alpar@1381
   450
alpar@1381
   451
  void LpCplex::_setMax()
alpar@1381
   452
  {
athos@1508
   453
    CPXchgobjsen(env, lp, CPX_MAX);
alpar@1381
   454
   }
alpar@1381
   455
  void LpCplex::_setMin()
alpar@1381
   456
  {
athos@1508
   457
    CPXchgobjsen(env, lp, CPX_MIN);
alpar@1381
   458
   }
alpar@1381
   459
  
alpar@1381
   460
} //namespace lemon
alpar@1381
   461