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