lemon/lp_cplex.cc
author hegyi
Mon, 13 Jun 2005 19:49:33 +0000
changeset 1478 bc7ae573d77d
parent 1460 7c58aabb9eea
child 1508 389a94a1d9eb
permissions -rw-r--r--
Known bugs are eliminated from gui, and new ones are created by changing tool selectors to special radiobuttons, and by adding edgecreation-canceller function (right-click on any group element).
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@1436
    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
  {
alpar@1381
    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;
alpar@1381
    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;
alpar@1381
    70
    int i = CPXgetnumrows (env, lp);
alpar@1381
    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@1436
    77
    CPXdelcols (env, lp, i, i);
athos@1432
    78
  }
athos@1432
    79
  
athos@1432
    80
  void LpCplex::_eraseRow(int i) {
athos@1436
    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@1431
   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;
alpar@1381
   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;
alpar@1381
   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';
alpar@1381
   163
      CPXchgsense (env, lp, cnt, indices, sense);
alpar@1381
   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';
alpar@1381
   170
	CPXchgsense (env, lp, cnt, indices, sense);
alpar@1381
   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';
alpar@1381
   176
	  CPXchgsense (env, lp, cnt, indices, sense);
alpar@1381
   177
	  CPXchgcoef (env, lp, i, -1, lb);
alpar@1381
   178
	}
alpar@1381
   179
	else{
alpar@1381
   180
	  sense[0]='R';
alpar@1381
   181
	  CPXchgsense (env, lp, cnt, indices, sense);
alpar@1381
   182
	  CPXchgcoef (env, lp, i, -1, lb);
alpar@1381
   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@1405
   200
// //     status = CPXgetsense (env, lp, sense, i, i);
athos@1405
   201
// //     Value rhs[1];
athos@1405
   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@1405
   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
  {
alpar@1381
   222
    CPXchgcoef (env, lp, -1, i, obj_coef);
alpar@1381
   223
  }
alpar@1381
   224
alpar@1381
   225
  void LpCplex::_clearObj()
alpar@1381
   226
  {
alpar@1381
   227
    for (int i=0;i< CPXgetnumcols (env, lp);++i){
alpar@1381
   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 
alpar@1381
   244
    status = CPXlpopt (env, lp);
alpar@1381
   245
    if (status == 0){
athos@1458
   246
      //We want to exclude some cases
athos@1458
   247
      switch (CPXgetstat (env, lp)){
athos@1458
   248
      case CPX_OBJ_LIM:
athos@1458
   249
      case CPX_IT_LIM_FEAS:
athos@1458
   250
      case CPX_IT_LIM_INFEAS:               
athos@1458
   251
      case CPX_TIME_LIM_FEAS:
athos@1458
   252
      case CPX_TIME_LIM_INFEAS:
athos@1458
   253
	return UNSOLVED;
athos@1458
   254
      default:
athos@1458
   255
	return SOLVED; 
athos@1458
   256
      }
alpar@1381
   257
    }
alpar@1381
   258
    else{
alpar@1381
   259
      return UNSOLVED;
alpar@1381
   260
    }
alpar@1381
   261
  }
alpar@1381
   262
athos@1460
   263
  LpCplex::Value LpCplex::_getPrimal(int i)
athos@1460
   264
  {
athos@1460
   265
    Value x;
athos@1460
   266
    CPXgetx (env, lp, &x, i, i);
athos@1460
   267
    return x;
athos@1460
   268
  }
athos@1460
   269
  
athos@1460
   270
  LpCplex::Value LpCplex::_getPrimalValue()
athos@1460
   271
  {
athos@1460
   272
    Value objval;
athos@1460
   273
    //method = CPXgetmethod (env, lp);
athos@1460
   274
    status = CPXgetobjval (env, lp, &objval);
athos@1460
   275
    return objval;
athos@1460
   276
  }
athos@1460
   277
  
athos@1407
   278
athos@1458
   279
//7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
athos@1458
   280
// 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
   281
athos@1458
   282
// For Simplex, Barrier  
athos@1458
   283
// 1  	CPX_OPTIMAL  
athos@1458
   284
// 	 Optimal solution found  
athos@1458
   285
// 2  	CPX_INFEASIBLE  
athos@1458
   286
// 	 Problem infeasible  
athos@1458
   287
// 3    CPX_UNBOUNDED  
athos@1458
   288
// 	 Problem unbounded  
athos@1458
   289
// 4  	CPX_OBJ_LIM  
athos@1458
   290
// 	 Objective limit exceeded in Phase II  
athos@1458
   291
// 5  	CPX_IT_LIM_FEAS  
athos@1458
   292
// 	 Iteration limit exceeded in Phase II  
athos@1458
   293
// 6  	CPX_IT_LIM_INFEAS  
athos@1458
   294
// 	 Iteration limit exceeded in Phase I  
athos@1458
   295
// 7  	CPX_TIME_LIM_FEAS  
athos@1458
   296
// 	 Time limit exceeded in Phase II  
athos@1458
   297
// 8  	CPX_TIME_LIM_INFEAS  
athos@1458
   298
// 	 Time limit exceeded in Phase I  
athos@1458
   299
// 9  	CPX_NUM_BEST_FEAS  
athos@1458
   300
// 	 Problem non-optimal, singularities in Phase II  
athos@1458
   301
// 10 	CPX_NUM_BEST_INFEAS  
athos@1458
   302
// 	 Problem non-optimal, singularities in Phase I  
athos@1458
   303
// 11 	CPX_OPTIMAL_INFEAS  
athos@1458
   304
// 	 Optimal solution found, unscaled infeasibilities  
athos@1458
   305
// 12 	CPX_ABORT_FEAS  
athos@1458
   306
// 	 Aborted in Phase II  
athos@1458
   307
// 13 	CPX_ABORT_INFEAS  
athos@1458
   308
// 	 Aborted in Phase I  
athos@1458
   309
// 14  	CPX_ABORT_DUAL_INFEAS  
athos@1458
   310
// 	 Aborted in barrier, dual infeasible  
athos@1458
   311
// 15  	CPX_ABORT_PRIM_INFEAS  
athos@1458
   312
// 	 Aborted in barrier, primal infeasible  
athos@1458
   313
// 16  	CPX_ABORT_PRIM_DUAL_INFEAS  
athos@1458
   314
// 	 Aborted in barrier, primal and dual infeasible  
athos@1458
   315
// 17  	CPX_ABORT_PRIM_DUAL_FEAS  
athos@1458
   316
// 	 Aborted in barrier, primal and dual feasible  
athos@1458
   317
// 18  	CPX_ABORT_CROSSOVER  
athos@1458
   318
// 	 Aborted in crossover  
athos@1458
   319
// 19  	CPX_INForUNBD  
athos@1458
   320
// 	 Infeasible or unbounded  
athos@1458
   321
// 20   CPX_PIVOT
athos@1458
   322
//       User pivot used
athos@1458
   323
//
athos@1407
   324
//     Ezeket hova tegyem:
athos@1407
   325
// ??case CPX_ABORT_DUAL_INFEAS           
athos@1407
   326
// ??case CPX_ABORT_CROSSOVER             
athos@1407
   327
// ??case CPX_INForUNBD                   
athos@1407
   328
// ??case CPX_PIVOT                       
athos@1407
   329
athos@1458
   330
  LpCplex::SolutionStatus LpCplex::_getPrimalStatus()
athos@1458
   331
  {
athos@1407
   332
    int stat = CPXgetstat (env, lp);
athos@1407
   333
    switch (stat) {
athos@1407
   334
    case 0:
athos@1407
   335
      return UNDEFINED; //Undefined
athos@1407
   336
    case CPX_OPTIMAL://Optimal
athos@1407
   337
      return OPTIMAL;
athos@1407
   338
    case CPX_UNBOUNDED://Unbounded
athos@1407
   339
      return INFINITE;
athos@1407
   340
    case CPX_INFEASIBLE://Infeasible 
athos@1458
   341
 //    case CPX_IT_LIM_INFEAS:
athos@1458
   342
//     case CPX_TIME_LIM_INFEAS:
athos@1458
   343
//     case CPX_NUM_BEST_INFEAS:             
athos@1458
   344
//     case CPX_OPTIMAL_INFEAS:              
athos@1458
   345
//     case CPX_ABORT_INFEAS:                
athos@1458
   346
//     case CPX_ABORT_PRIM_INFEAS:           
athos@1458
   347
//     case CPX_ABORT_PRIM_DUAL_INFEAS:      
athos@1407
   348
      return INFEASIBLE;
athos@1458
   349
//     case CPX_OBJ_LIM:                    
athos@1458
   350
//     case CPX_IT_LIM_FEAS:             
athos@1458
   351
//     case CPX_TIME_LIM_FEAS:                
athos@1458
   352
//     case CPX_NUM_BEST_FEAS:                
athos@1458
   353
//     case CPX_ABORT_FEAS:                  
athos@1458
   354
//     case CPX_ABORT_PRIM_DUAL_FEAS:        
athos@1458
   355
//       return FEASIBLE;
athos@1407
   356
    default:
athos@1407
   357
      return UNDEFINED; //Everything else comes here
athos@1407
   358
      //FIXME error
athos@1407
   359
    }
athos@1407
   360
athos@1458
   361
  }
athos@1407
   362
athos@1458
   363
//9.0-as cplex verzio statusai
athos@1405
   364
// CPX_STAT_ABORT_DUAL_OBJ_LIM
athos@1405
   365
// CPX_STAT_ABORT_IT_LIM
athos@1405
   366
// CPX_STAT_ABORT_OBJ_LIM
athos@1405
   367
// CPX_STAT_ABORT_PRIM_OBJ_LIM
athos@1405
   368
// CPX_STAT_ABORT_TIME_LIM
athos@1405
   369
// CPX_STAT_ABORT_USER
athos@1405
   370
// CPX_STAT_FEASIBLE_RELAXED
athos@1405
   371
// CPX_STAT_INFEASIBLE
athos@1405
   372
// CPX_STAT_INForUNBD
athos@1405
   373
// CPX_STAT_NUM_BEST
athos@1405
   374
// CPX_STAT_OPTIMAL
athos@1405
   375
// CPX_STAT_OPTIMAL_FACE_UNBOUNDED
athos@1405
   376
// CPX_STAT_OPTIMAL_INFEAS
athos@1405
   377
// CPX_STAT_OPTIMAL_RELAXED
athos@1405
   378
// CPX_STAT_UNBOUNDED
athos@1405
   379
athos@1458
   380
  LpCplex::SolutionStatus LpCplex::_getDualStatus()
athos@1458
   381
  {
athos@1458
   382
    int stat = CPXgetstat (env, lp);
athos@1458
   383
    switch (stat) {
athos@1458
   384
    case 0:
athos@1458
   385
      return UNDEFINED; //Undefined
athos@1458
   386
    case CPX_OPTIMAL://Optimal
athos@1458
   387
      return OPTIMAL;
athos@1458
   388
    case CPX_UNBOUNDED:
athos@1458
   389
     return INFEASIBLE;
athos@1458
   390
    default:
athos@1458
   391
      return UNDEFINED; //Everything else comes here
athos@1458
   392
      //FIXME error
athos@1458
   393
    }
athos@1473
   394
  }
alpar@1381
   395
athos@1460
   396
  LpCplex::ProblemTypes LpCplex::_getProblemType()
alpar@1381
   397
  {
athos@1460
   398
    int stat = CPXgetstat (env, lp);
athos@1460
   399
    switch (stat) {
athos@1460
   400
    case CPX_OPTIMAL://Optimal
athos@1460
   401
	return PRIMAL_DUAL_FEASIBLE;
athos@1460
   402
    case CPX_UNBOUNDED:
athos@1460
   403
 	return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
athos@1460
   404
// 	return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
athos@1460
   405
// 	return PRIMAL_DUAL_INFEASIBLE;
athos@1460
   406
athos@1460
   407
//Seems to be that this is all we can say for sure
athos@1460
   408
    default:
athos@1460
   409
	//In all other cases
athos@1460
   410
	return UNKNOWN;
athos@1460
   411
      //FIXME error
athos@1460
   412
    }
athos@1473
   413
  }
alpar@1381
   414
alpar@1381
   415
  void LpCplex::_setMax()
alpar@1381
   416
  {
alpar@1381
   417
    CPXchgobjsen (env, lp, CPX_MAX);
alpar@1381
   418
   }
alpar@1381
   419
  void LpCplex::_setMin()
alpar@1381
   420
  {
alpar@1381
   421
    CPXchgobjsen (env, lp, CPX_MIN);
alpar@1381
   422
   }
alpar@1381
   423
  
alpar@1381
   424
} //namespace lemon
alpar@1381
   425