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