lemon/lp_cplex.cc
author athos
Thu, 26 May 2005 15:33:16 +0000
changeset 1438 826bdac3525a
parent 1435 8e85e6bbefdf
child 1458 7a483c1d38b5
permissions -rw-r--r--
Some documentation got revised.
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");
athos@1436
    28
    //CPXmsg (cpxresults, "Hello-bello\n");
alpar@1381
    29
  }
alpar@1381
    30
  
alpar@1381
    31
  LpCplex::~LpCplex() {
athos@1436
    32
    CPXfreeprob(env,&lp); 
athos@1436
    33
    CPXcloseCPLEX(&env); 
alpar@1381
    34
  }
alpar@1381
    35
  
athos@1405
    36
  LpSolverBase &LpCplex::_newLp() 
athos@1405
    37
  {
athos@1436
    38
    //The first approach opens a new environment
athos@1436
    39
    LpCplex* newlp=new LpCplex();
athos@1436
    40
    return *newlp;
athos@1405
    41
  }
athos@1436
    42
athos@1405
    43
  LpSolverBase &LpCplex::_copyLp() {
athos@1436
    44
    //The first approach opens a new environment
athos@1436
    45
    LpCplex* newlp=new LpCplex();
athos@1436
    46
    //The routine CPXcloneprob can be used to create a new CPLEX problem 
athos@1436
    47
    //object and copy all the problem data from an existing problem 
athos@1436
    48
    //object to it. Solution and starting information is not copied.
athos@1436
    49
    newlp->lp = CPXcloneprob (env, lp, &status);
athos@1436
    50
    return *newlp;
athos@1405
    51
  }
alpar@1381
    52
alpar@1381
    53
  int LpCplex::_addCol()
alpar@1381
    54
  {
alpar@1381
    55
    int i = CPXgetnumcols (env, lp);
alpar@1381
    56
    Value lb[1],ub[1];
alpar@1381
    57
    lb[0]=-INF;//-CPX_INFBOUND;
alpar@1381
    58
    ub[0]=INF;//CPX_INFBOUND;
alpar@1381
    59
    status = CPXnewcols (env, lp, 1, NULL, lb, ub, NULL, NULL);
alpar@1381
    60
    return i;
alpar@1381
    61
  }
athos@1436
    62
alpar@1381
    63
  
alpar@1381
    64
  int LpCplex::_addRow() 
alpar@1381
    65
  {
alpar@1381
    66
    //We want a row that is not constrained
alpar@1381
    67
    char sense[1];
alpar@1381
    68
    sense[0]='L';//<= constraint
alpar@1381
    69
    Value rhs[1];
alpar@1381
    70
    rhs[0]=INF;
alpar@1381
    71
    int i = CPXgetnumrows (env, lp);
alpar@1381
    72
    status = CPXnewrows (env, lp, 1, rhs, sense, NULL, NULL);
alpar@1381
    73
    return i;
alpar@1381
    74
  }
athos@1432
    75
athos@1432
    76
athos@1432
    77
  void LpCplex::_eraseCol(int i) {
athos@1436
    78
    CPXdelcols (env, lp, i, i);
athos@1432
    79
  }
athos@1432
    80
  
athos@1432
    81
  void LpCplex::_eraseRow(int i) {
athos@1436
    82
    CPXdelrows (env, lp, i, i);
athos@1432
    83
  }
athos@1432
    84
alpar@1381
    85
  
alpar@1381
    86
  ///\warning Data at index 0 is ignored in the arrays.
alpar@1381
    87
  void LpCplex::_setRowCoeffs(int i, 
alpar@1381
    88
			      int length,
alpar@1381
    89
			      int  const * indices, 
alpar@1381
    90
			      Value  const * values )
alpar@1381
    91
  {
alpar@1381
    92
    int rowlist[length+1];
alpar@1381
    93
    int* p=rowlist;
alpar@1381
    94
    for (int k=1;k<=length;++k){
alpar@1381
    95
      rowlist[k]=i;
alpar@1381
    96
    }
alpar@1381
    97
    status = CPXchgcoeflist(env, lp, 
alpar@1381
    98
			    length, 
alpar@1381
    99
			    p+1, 
alpar@1381
   100
			    const_cast<int * >(indices+1), 
alpar@1381
   101
			    const_cast<Value * >(values+1));
alpar@1381
   102
  }
alpar@1381
   103
  
alpar@1381
   104
  void LpCplex::_setColCoeffs(int i, 
alpar@1381
   105
			      int length,
alpar@1381
   106
			      int  const * indices, 
alpar@1381
   107
			      Value  const * values)
alpar@1381
   108
  {
alpar@1381
   109
    int collist[length+1];
alpar@1381
   110
    int* p=collist;
alpar@1381
   111
    for (int k=1;k<=length;++k){
alpar@1381
   112
      collist[k]=i;
alpar@1381
   113
    }
alpar@1381
   114
    status = CPXchgcoeflist(env, lp, 
alpar@1381
   115
			    length, 
alpar@1381
   116
			    const_cast<int * >(indices+1), 
alpar@1381
   117
			    p+1, 
alpar@1381
   118
			    const_cast<Value * >(values+1));
alpar@1381
   119
  }
alpar@1381
   120
  
athos@1431
   121
  void LpCplex::_setCoeff(int row, int col, Value value) 
athos@1431
   122
  {
athos@1431
   123
    CPXchgcoef (env, lp, row, col, value);
athos@1431
   124
  }
athos@1431
   125
alpar@1381
   126
  void LpCplex::_setColLowerBound(int i, Value value)
alpar@1381
   127
  {
alpar@1381
   128
    int indices[1];
alpar@1381
   129
    indices[0]=i;
alpar@1381
   130
    char lu[1];
alpar@1381
   131
    lu[0]='L';
alpar@1381
   132
    Value bd[1];
alpar@1381
   133
    bd[0]=value;
alpar@1381
   134
    status = CPXchgbds (env, lp, 1, indices, lu, bd);
alpar@1381
   135
 
alpar@1381
   136
  }
alpar@1381
   137
  
alpar@1381
   138
  void LpCplex::_setColUpperBound(int i, Value value)
alpar@1381
   139
  {
alpar@1381
   140
    int indices[1];
alpar@1381
   141
    indices[0]=i;
alpar@1381
   142
    char lu[1];
alpar@1381
   143
    lu[0]='U';
alpar@1381
   144
    Value bd[1];
alpar@1381
   145
    bd[0]=value;
alpar@1381
   146
    status = CPXchgbds (env, lp, 1, indices, lu, bd);
alpar@1381
   147
  }
alpar@1381
   148
alpar@1381
   149
  //This will be easier to implement
alpar@1381
   150
  void LpCplex::_setRowBounds(int i, Value lb, Value ub)
alpar@1381
   151
  {
alpar@1381
   152
    //Bad parameter
alpar@1381
   153
    if (lb==INF || ub==-INF) {
alpar@1381
   154
      //FIXME error
alpar@1381
   155
    }
athos@1405
   156
    
alpar@1381
   157
    int cnt=1;
alpar@1381
   158
    int indices[1];
alpar@1381
   159
    indices[0]=i;
alpar@1381
   160
    char sense[1];
alpar@1381
   161
alpar@1381
   162
    if (lb==-INF){
alpar@1381
   163
      sense[0]='L';
alpar@1381
   164
      CPXchgsense (env, lp, cnt, indices, sense);
alpar@1381
   165
      CPXchgcoef (env, lp, i, -1, ub);
athos@1405
   166
      
alpar@1381
   167
    }
alpar@1381
   168
    else{
alpar@1381
   169
      if (ub==INF){
alpar@1381
   170
	sense[0]='G';
alpar@1381
   171
	CPXchgsense (env, lp, cnt, indices, sense);
alpar@1381
   172
	CPXchgcoef (env, lp, i, -1, lb);
alpar@1381
   173
      }
alpar@1381
   174
      else{
alpar@1381
   175
	if (lb == ub){
alpar@1381
   176
	  sense[0]='E';
alpar@1381
   177
	  CPXchgsense (env, lp, cnt, indices, sense);
alpar@1381
   178
	  CPXchgcoef (env, lp, i, -1, lb);
alpar@1381
   179
	}
alpar@1381
   180
	else{
alpar@1381
   181
	  sense[0]='R';
alpar@1381
   182
	  CPXchgsense (env, lp, cnt, indices, sense);
alpar@1381
   183
	  CPXchgcoef (env, lp, i, -1, lb);
alpar@1381
   184
	  CPXchgcoef (env, lp, i, -2, ub-lb);	  
alpar@1381
   185
	}
alpar@1381
   186
      }
alpar@1381
   187
    }
alpar@1381
   188
  }
alpar@1381
   189
athos@1405
   190
//   void LpCplex::_setRowLowerBound(int i, Value value)
athos@1405
   191
//   {
athos@1405
   192
//     //Not implemented, obsolete
athos@1405
   193
//   }
alpar@1381
   194
  
athos@1405
   195
//   void LpCplex::_setRowUpperBound(int i, Value value)
athos@1405
   196
//   {
athos@1405
   197
//     //Not implemented, obsolete
athos@1405
   198
// //     //TODO Ezt kell meg megirni
athos@1405
   199
// //     //type of the problem
athos@1405
   200
// //     char sense[1];
athos@1405
   201
// //     status = CPXgetsense (env, lp, sense, i, i);
athos@1405
   202
// //     Value rhs[1];
athos@1405
   203
// //     status = CPXgetrhs (env, lp, rhs, i, i);
alpar@1381
   204
athos@1405
   205
// //     switch (sense[0]) {
athos@1405
   206
// //     case 'L'://<= constraint
athos@1405
   207
// //       break;
athos@1405
   208
// //     case 'E'://= constraint
athos@1405
   209
// //       break;
athos@1405
   210
// //     case 'G'://>= constraint
athos@1405
   211
// //       break;
athos@1405
   212
// //     case 'R'://ranged constraint
athos@1405
   213
// //       break;
athos@1405
   214
// //     default: ;
athos@1405
   215
// //       //FIXME error
athos@1405
   216
// //     }
alpar@1381
   217
athos@1405
   218
// //     status = CPXchgcoef (env, lp, i, -2, value_rng);
athos@1405
   219
//   }
alpar@1381
   220
  
alpar@1381
   221
  void LpCplex::_setObjCoeff(int i, Value obj_coef)
alpar@1381
   222
  {
alpar@1381
   223
    CPXchgcoef (env, lp, -1, i, obj_coef);
alpar@1381
   224
  }
alpar@1381
   225
alpar@1381
   226
  void LpCplex::_clearObj()
alpar@1381
   227
  {
alpar@1381
   228
    for (int i=0;i< CPXgetnumcols (env, lp);++i){
alpar@1381
   229
      CPXchgcoef (env, lp, -1, i, 0);
alpar@1381
   230
    }
alpar@1381
   231
    
alpar@1381
   232
  }
alpar@1381
   233
alpar@1381
   234
  LpCplex::SolveExitStatus LpCplex::_solve()
alpar@1381
   235
  {
alpar@1381
   236
    
alpar@1381
   237
    status = CPXlpopt (env, lp);
alpar@1381
   238
    if (status == 0){
alpar@1381
   239
      return SOLVED;
alpar@1381
   240
    }
alpar@1381
   241
    else{
alpar@1381
   242
      return UNSOLVED;
alpar@1381
   243
    }
alpar@1381
   244
//     int i=  lpx_simplex(lp);
alpar@1381
   245
//     switch (i) {
alpar@1381
   246
//     case LPX_E_OK: 
alpar@1381
   247
//       return SOLVED;
alpar@1381
   248
//       break;
alpar@1381
   249
//     default:
alpar@1381
   250
//       return UNSOLVED;
alpar@1381
   251
//     }
alpar@1381
   252
  }
alpar@1381
   253
alpar@1381
   254
  LpCplex::SolutionStatus LpCplex::_getPrimalStatus()
alpar@1381
   255
  {
athos@1407
   256
//7.5-os cplex statusai
athos@1407
   257
// #define CPX_OPTIMAL                      1
athos@1407
   258
// #define CPX_INFEASIBLE                   2
athos@1407
   259
// #define CPX_UNBOUNDED                    3
athos@1407
   260
// #define CPX_OBJ_LIM                      4
athos@1407
   261
// #define CPX_IT_LIM_FEAS                  5
athos@1407
   262
// #define CPX_IT_LIM_INFEAS                6
athos@1407
   263
// #define CPX_TIME_LIM_FEAS                7
athos@1407
   264
// #define CPX_TIME_LIM_INFEAS              8
athos@1407
   265
// #define CPX_NUM_BEST_FEAS                9
athos@1407
   266
// #define CPX_NUM_BEST_INFEAS             10
athos@1407
   267
// #define CPX_OPTIMAL_INFEAS              11
athos@1407
   268
// #define CPX_ABORT_FEAS                  12
athos@1407
   269
// #define CPX_ABORT_INFEAS                13
athos@1407
   270
// #define CPX_ABORT_DUAL_INFEAS           14
athos@1407
   271
// #define CPX_ABORT_PRIM_INFEAS           15
athos@1407
   272
// #define CPX_ABORT_PRIM_DUAL_INFEAS      16
athos@1407
   273
// #define CPX_ABORT_PRIM_DUAL_FEAS        17
athos@1407
   274
// #define CPX_ABORT_CROSSOVER             18
athos@1407
   275
// #define CPX_INForUNBD                   19
athos@1407
   276
// #define CPX_PIVOT                       20
athos@1407
   277
athos@1407
   278
//     Ezeket hova tegyem:
athos@1407
   279
// ??case CPX_ABORT_DUAL_INFEAS           
athos@1407
   280
// ??case CPX_ABORT_CROSSOVER             
athos@1407
   281
// ??case CPX_INForUNBD                   
athos@1407
   282
// ??case CPX_PIVOT                       
athos@1407
   283
athos@1407
   284
    int stat = CPXgetstat (env, lp);
athos@1407
   285
    switch (stat) {
athos@1407
   286
    case 0:
athos@1407
   287
      return UNDEFINED; //Undefined
athos@1407
   288
      break;      
athos@1407
   289
    case CPX_OPTIMAL://Optimal
athos@1407
   290
      return OPTIMAL;
athos@1407
   291
      break;
athos@1407
   292
    case CPX_UNBOUNDED://Unbounded
athos@1407
   293
      return INFINITE;
athos@1407
   294
      break;
athos@1407
   295
    case CPX_INFEASIBLE://Infeasible 
athos@1407
   296
    case CPX_IT_LIM_INFEAS:
athos@1407
   297
    case CPX_TIME_LIM_INFEAS:
athos@1407
   298
    case CPX_NUM_BEST_INFEAS:             
athos@1407
   299
    case CPX_OPTIMAL_INFEAS:              
athos@1407
   300
    case CPX_ABORT_INFEAS:                
athos@1407
   301
    case CPX_ABORT_PRIM_INFEAS:           
athos@1407
   302
    case CPX_ABORT_PRIM_DUAL_INFEAS:      
athos@1407
   303
      return INFEASIBLE;
athos@1407
   304
      break;
athos@1407
   305
    case CPX_OBJ_LIM:                    
athos@1407
   306
    case CPX_IT_LIM_FEAS:             
athos@1407
   307
    case CPX_TIME_LIM_FEAS:                
athos@1407
   308
    case CPX_NUM_BEST_FEAS:                
athos@1407
   309
    case CPX_ABORT_FEAS:                  
athos@1407
   310
    case CPX_ABORT_PRIM_DUAL_FEAS:        
athos@1407
   311
      return FEASIBLE;
athos@1407
   312
      break;
athos@1407
   313
    default:
athos@1407
   314
      return UNDEFINED; //Everything else comes here
athos@1407
   315
      //FIXME error
athos@1407
   316
    }
athos@1407
   317
athos@1407
   318
athos@1407
   319
    //Nem tudom, hanyas cplex verzio statusai
athos@1405
   320
// CPX_STAT_ABORT_DUAL_OBJ_LIM
athos@1405
   321
// CPX_STAT_ABORT_IT_LIM
athos@1405
   322
// CPX_STAT_ABORT_OBJ_LIM
athos@1405
   323
// CPX_STAT_ABORT_PRIM_OBJ_LIM
athos@1405
   324
// CPX_STAT_ABORT_TIME_LIM
athos@1405
   325
// CPX_STAT_ABORT_USER
athos@1405
   326
// CPX_STAT_FEASIBLE_RELAXED
athos@1405
   327
// CPX_STAT_INFEASIBLE
athos@1405
   328
// CPX_STAT_INForUNBD
athos@1405
   329
// CPX_STAT_NUM_BEST
athos@1405
   330
// CPX_STAT_OPTIMAL
athos@1405
   331
// CPX_STAT_OPTIMAL_FACE_UNBOUNDED
athos@1405
   332
// CPX_STAT_OPTIMAL_INFEAS
athos@1405
   333
// CPX_STAT_OPTIMAL_RELAXED
athos@1405
   334
// CPX_STAT_UNBOUNDED
athos@1405
   335
athos@1407
   336
//     int stat = CPXgetstat (env, lp);
athos@1407
   337
//     switch (stat) {
athos@1407
   338
//     case CPX_STAT_OPTIMAL://Optimal
athos@1407
   339
//       return OPTIMAL;
athos@1407
   340
//       break;
athos@1407
   341
//     case CPX_STAT_INFEASIBLE://Infeasible 
athos@1407
   342
//       return INFEASIBLE;
athos@1407
   343
//       break;
athos@1407
   344
//     case CPX_STAT_UNBOUNDED://Unbounded
athos@1407
   345
//       return INFINITE;
athos@1407
   346
//       break;
athos@1407
   347
//     case CPX_STAT_NUM_BEST://Feasible
athos@1407
   348
//       return FEASIBLE;
athos@1407
   349
//       break;
athos@1407
   350
//     default:
athos@1407
   351
//       return UNDEFINED; //Everything else comes here
athos@1407
   352
//       //FIXME error
athos@1407
   353
//     }
athos@1407
   354
alpar@1381
   355
  }
alpar@1381
   356
alpar@1381
   357
  LpCplex::Value LpCplex::_getPrimal(int i)
alpar@1381
   358
  {
alpar@1381
   359
    Value x;
alpar@1381
   360
    CPXgetx (env, lp, &x, i, i);
alpar@1381
   361
    return x;
alpar@1381
   362
  }
alpar@1381
   363
  
alpar@1381
   364
  LpCplex::Value LpCplex::_getPrimalValue()
alpar@1381
   365
  {
athos@1405
   366
    Value objval;
athos@1405
   367
    //method = CPXgetmethod (env, lp);
athos@1405
   368
    status = CPXgetobjval (env, lp, &objval);
athos@1405
   369
    return objval;
alpar@1381
   370
  }
alpar@1381
   371
  
alpar@1381
   372
 
alpar@1381
   373
alpar@1381
   374
alpar@1381
   375
  void LpCplex::_setMax()
alpar@1381
   376
  {
alpar@1381
   377
    CPXchgobjsen (env, lp, CPX_MAX);
alpar@1381
   378
   }
alpar@1381
   379
  void LpCplex::_setMin()
alpar@1381
   380
  {
alpar@1381
   381
    CPXchgobjsen (env, lp, CPX_MIN);
alpar@1381
   382
   }
alpar@1381
   383
  
alpar@1381
   384
} //namespace lemon
alpar@1381
   385