COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lp_cplex.cc @ 1787:932b8490caf0

Last change on this file since 1787:932b8490caf0 was 1787:932b8490caf0, checked in by marci, 18 years ago

bugfix in setCol, getting dual values

File size: 12.1 KB
Line 
1/* -*- C++ -*-
2 * lemon/lp_cplex.cc - Part of LEMON, a generic C++ optimization library
3 *
4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Research Group on Combinatorial Optimization, EGRES).
6 *
7 * Permission to use, modify and distribute this software is granted
8 * provided that this copyright notice appears in all copies. For
9 * precise terms see the accompanying LICENSE file.
10 *
11 * This software is provided "AS IS" with no warranty of any kind,
12 * express or implied, and with no claim as to its suitability for any
13 * purpose.
14 *
15 */
16#include <iostream>
17#include<lemon/lp_cplex.h>
18
19///\file
20///\brief Implementation of the LEMON-CPLEX lp solver interface.
21namespace lemon {
22 
23  LpCplex::LpCplex() : LpSolverBase() {
24
25    //    env = CPXopenCPLEXdevelop(&status);     
26    env = CPXopenCPLEX(&status);     
27    lp = CPXcreateprob(env, &status, "LP problem");
28  }
29 
30  LpCplex::~LpCplex() {
31    CPXfreeprob(env,&lp);
32    CPXcloseCPLEX(&env);
33  }
34 
35  LpSolverBase &LpCplex::_newLp()
36  {
37    //The first approach opens a new environment
38    LpCplex* newlp=new LpCplex();
39    return *newlp;
40  }
41
42  LpSolverBase &LpCplex::_copyLp() {
43    //The first approach opens a new environment
44    LpCplex* newlp=new LpCplex();
45    //The routine CPXcloneprob can be used to create a new CPLEX problem
46    //object and copy all the problem data from an existing problem
47    //object to it. Solution and starting information is not copied.
48    newlp->lp = CPXcloneprob(env, lp, &status);
49    return *newlp;
50  }
51
52  int LpCplex::_addCol()
53  {
54    int i = CPXgetnumcols(env, lp);
55    Value lb[1],ub[1];
56    lb[0]=-INF;//-CPX_INFBOUND;
57    ub[0]=INF;//CPX_INFBOUND;
58    status = CPXnewcols(env, lp, 1, NULL, lb, ub, NULL, NULL);
59    return i;
60  }
61
62 
63  int LpCplex::_addRow()
64  {
65    //We want a row that is not constrained
66    char sense[1];
67    sense[0]='L';//<= constraint
68    Value rhs[1];
69    rhs[0]=INF;
70    int i = CPXgetnumrows(env, lp);
71    status = CPXnewrows(env, lp, 1, rhs, sense, NULL, NULL);
72    return i;
73  }
74
75
76  void LpCplex::_eraseCol(int i) {
77    CPXdelcols(env, lp, i, i);
78  }
79 
80  void LpCplex::_eraseRow(int i) {
81    CPXdelrows(env, lp, i, i);
82  }
83
84 
85  ///\warning Data at index 0 is ignored in the arrays.
86  void LpCplex::_setRowCoeffs(int i,
87                              int length,
88                              int  const * indices,
89                              Value  const * values )
90  {
91    int rowlist[length+1];
92    int* p=rowlist;
93    for (int k=1;k<=length;++k){
94      rowlist[k]=i;
95    }
96    status = CPXchgcoeflist(env, lp,
97                            length,
98                            p+1,
99                            const_cast<int * >(indices+1),
100                            const_cast<Value * >(values+1));
101  }
102 
103  void LpCplex::_setColCoeffs(int i,
104                              int length,
105                              int  const * indices,
106                              Value  const * values)
107  {
108    int collist[length+1];
109    int* p=collist;
110    for (int k=1;k<=length;++k){
111      collist[k]=i;
112    }
113    status = CPXchgcoeflist(env, lp,
114                            length,
115                            const_cast<int * >(indices+1),
116                            p+1,
117                            const_cast<Value * >(values+1));
118  }
119 
120  void LpCplex::_setCoeff(int row, int col, Value value)
121  {
122    CPXchgcoef(env, lp, row, col, value);
123  }
124
125  void LpCplex::_setColLowerBound(int i, Value value)
126  {
127    int indices[1];
128    indices[0]=i;
129    char lu[1];
130    lu[0]='L';
131    Value bd[1];
132    bd[0]=value;
133    status = CPXchgbds(env, lp, 1, indices, lu, bd);
134 
135  }
136 
137  void LpCplex::_setColUpperBound(int i, Value value)
138  {
139    int indices[1];
140    indices[0]=i;
141    char lu[1];
142    lu[0]='U';
143    Value bd[1];
144    bd[0]=value;
145    status = CPXchgbds(env, lp, 1, indices, lu, bd);
146  }
147
148  //This will be easier to implement
149  void LpCplex::_setRowBounds(int i, Value lb, Value ub)
150  {
151    //Bad parameter
152    if (lb==INF || ub==-INF) {
153      //FIXME error
154    }
155   
156    int cnt=1;
157    int indices[1];
158    indices[0]=i;
159    char sense[1];
160
161    if (lb==-INF){
162      sense[0]='L';
163      CPXchgsense(env, lp, cnt, indices, sense);
164      CPXchgcoef(env, lp, i, -1, ub);
165     
166    }
167    else{
168      if (ub==INF){
169        sense[0]='G';
170        CPXchgsense(env, lp, cnt, indices, sense);
171        CPXchgcoef(env, lp, i, -1, lb);
172      }
173      else{
174        if (lb == ub){
175          sense[0]='E';
176          CPXchgsense(env, lp, cnt, indices, sense);
177          CPXchgcoef(env, lp, i, -1, lb);
178        }
179        else{
180          sense[0]='R';
181          CPXchgsense(env, lp, cnt, indices, sense);
182          CPXchgcoef(env, lp, i, -1, lb);
183          CPXchgcoef(env, lp, i, -2, ub-lb);     
184        }
185      }
186    }
187  }
188
189//   void LpCplex::_setRowLowerBound(int i, Value value)
190//   {
191//     //Not implemented, obsolete
192//   }
193 
194//   void LpCplex::_setRowUpperBound(int i, Value value)
195//   {
196//     //Not implemented, obsolete
197// //     //TODO Ezt kell meg megirni
198// //     //type of the problem
199// //     char sense[1];
200// //     status = CPXgetsense(env, lp, sense, i, i);
201// //     Value rhs[1];
202// //     status = CPXgetrhs(env, lp, rhs, i, i);
203
204// //     switch (sense[0]) {
205// //     case 'L'://<= constraint
206// //       break;
207// //     case 'E'://= constraint
208// //       break;
209// //     case 'G'://>= constraint
210// //       break;
211// //     case 'R'://ranged constraint
212// //       break;
213// //     default: ;
214// //       //FIXME error
215// //     }
216
217// //     status = CPXchgcoef(env, lp, i, -2, value_rng);
218//   }
219 
220  void LpCplex::_setObjCoeff(int i, Value obj_coef)
221  {
222    CPXchgcoef(env, lp, -1, i, obj_coef);
223  }
224
225  void LpCplex::_clearObj()
226  {
227    for (int i=0;i< CPXgetnumcols(env, lp);++i){
228      CPXchgcoef(env, lp, -1, i, 0);
229    }
230   
231  }
232  // The routine returns zero unless an error occurred during the
233  // optimization. Examples of errors include exhausting available
234  // memory (CPXERR_NO_MEMORY) or encountering invalid data in the
235  // CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a
236  // user-specified CPLEX limit, or proving the model infeasible or
237  // unbounded, are not considered errors. Note that a zero return
238  // value does not necessarily mean that a solution exists. Use query
239  // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
240  // further information about the status of the optimization.
241  LpCplex::SolveExitStatus LpCplex::_solve()
242  {
243    //CPX_PARAM_LPMETHOD
244    status = CPXlpopt(env, lp);
245    //status = CPXprimopt(env, lp);
246    if (status == 0){
247      //We want to exclude some cases
248      switch (CPXgetstat(env, lp)){
249      case CPX_OBJ_LIM:
250      case CPX_IT_LIM_FEAS:
251      case CPX_IT_LIM_INFEAS:               
252      case CPX_TIME_LIM_FEAS:
253      case CPX_TIME_LIM_INFEAS:
254        return UNSOLVED;
255      default:
256        return SOLVED;
257      }
258    }
259    else{
260      return UNSOLVED;
261    }
262  }
263
264  LpCplex::Value LpCplex::_getPrimal(int i)
265  {
266    Value x;
267    CPXgetx(env, lp, &x, i, i);
268    return x;
269  }
270
271  LpCplex::Value LpCplex::_getDual(int i)
272  {
273    Value y;
274    CPXgety(env, lp, &y, i, i);
275    return y;
276  }
277 
278  LpCplex::Value LpCplex::_getPrimalValue()
279  {
280    Value objval;
281    //method = CPXgetmethod (env, lp);
282    //printf("CPXgetprobtype %d \n",CPXgetprobtype(env,lp));
283    status = CPXgetobjval(env, lp, &objval);
284    //printf("Objective value: %g \n",objval);
285    return objval;
286  }
287 
288
289//7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
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.
291
292// For Simplex, Barrier 
293// 1    CPX_OPTIMAL 
294//       Optimal solution found 
295// 2    CPX_INFEASIBLE 
296//       Problem infeasible 
297// 3    CPX_UNBOUNDED 
298//       Problem unbounded 
299// 4    CPX_OBJ_LIM 
300//       Objective limit exceeded in Phase II 
301// 5    CPX_IT_LIM_FEAS 
302//       Iteration limit exceeded in Phase II 
303// 6    CPX_IT_LIM_INFEAS 
304//       Iteration limit exceeded in Phase I 
305// 7    CPX_TIME_LIM_FEAS 
306//       Time limit exceeded in Phase II 
307// 8    CPX_TIME_LIM_INFEAS 
308//       Time limit exceeded in Phase I 
309// 9    CPX_NUM_BEST_FEAS 
310//       Problem non-optimal, singularities in Phase II 
311// 10   CPX_NUM_BEST_INFEAS 
312//       Problem non-optimal, singularities in Phase I 
313// 11   CPX_OPTIMAL_INFEAS 
314//       Optimal solution found, unscaled infeasibilities 
315// 12   CPX_ABORT_FEAS 
316//       Aborted in Phase II 
317// 13   CPX_ABORT_INFEAS 
318//       Aborted in Phase I 
319// 14   CPX_ABORT_DUAL_INFEAS 
320//       Aborted in barrier, dual infeasible 
321// 15   CPX_ABORT_PRIM_INFEAS 
322//       Aborted in barrier, primal infeasible 
323// 16   CPX_ABORT_PRIM_DUAL_INFEAS 
324//       Aborted in barrier, primal and dual infeasible 
325// 17   CPX_ABORT_PRIM_DUAL_FEAS 
326//       Aborted in barrier, primal and dual feasible 
327// 18   CPX_ABORT_CROSSOVER 
328//       Aborted in crossover 
329// 19   CPX_INForUNBD 
330//       Infeasible or unbounded 
331// 20   CPX_PIVOT
332//       User pivot used
333//
334//     Ezeket hova tegyem:
335// ??case CPX_ABORT_DUAL_INFEAS           
336// ??case CPX_ABORT_CROSSOVER             
337// ??case CPX_INForUNBD                   
338// ??case CPX_PIVOT             
339         
340//Some more interesting stuff:
341
342// CPX_PARAM_LPMETHOD  1062  int  LPMETHOD
343// 0 Automatic
344// 1 Primal Simplex
345// 2 Dual Simplex
346// 3 Network Simplex
347// 4 Standard Barrier
348// Default: 0
349// Description: Method for linear optimization.
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
351  //Hulye cplex
352  void statusSwitch(CPXENVptr env,int& stat){
353    int lpmethod;
354    CPXgetintparam (env,CPX_PARAM_LPMETHOD,&lpmethod);
355    if (lpmethod==2){
356      if (stat==CPX_UNBOUNDED){
357        stat=CPX_INFEASIBLE;
358      }
359      else{
360        if (stat==CPX_INFEASIBLE)
361          stat=CPX_UNBOUNDED;
362      }
363    }
364  }
365
366  LpCplex::SolutionStatus LpCplex::_getPrimalStatus()
367  {
368   
369    int stat = CPXgetstat(env, lp);
370    statusSwitch(env,stat);
371    //CPXgetstat(env, lp);
372    //printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL);
373    switch (stat) {
374    case 0:
375      return UNDEFINED; //Undefined
376    case CPX_OPTIMAL://Optimal
377      return OPTIMAL;
378    case CPX_UNBOUNDED://Unbounded
379      return INFEASIBLE;//In case of dual simplex
380      //return INFINITE;
381    case CPX_INFEASIBLE://Infeasible
382 //    case CPX_IT_LIM_INFEAS:
383//     case CPX_TIME_LIM_INFEAS:
384//     case CPX_NUM_BEST_INFEAS:             
385//     case CPX_OPTIMAL_INFEAS:             
386//     case CPX_ABORT_INFEAS:               
387//     case CPX_ABORT_PRIM_INFEAS:           
388//     case CPX_ABORT_PRIM_DUAL_INFEAS:     
389      return INFINITE;//In case of dual simplex
390      //return INFEASIBLE;
391//     case CPX_OBJ_LIM:                   
392//     case CPX_IT_LIM_FEAS:             
393//     case CPX_TIME_LIM_FEAS:               
394//     case CPX_NUM_BEST_FEAS:               
395//     case CPX_ABORT_FEAS:                 
396//     case CPX_ABORT_PRIM_DUAL_FEAS:       
397//       return FEASIBLE;
398    default:
399      return UNDEFINED; //Everything else comes here
400      //FIXME error
401    }
402
403  }
404
405//9.0-as cplex verzio statusai
406// CPX_STAT_ABORT_DUAL_OBJ_LIM
407// CPX_STAT_ABORT_IT_LIM
408// CPX_STAT_ABORT_OBJ_LIM
409// CPX_STAT_ABORT_PRIM_OBJ_LIM
410// CPX_STAT_ABORT_TIME_LIM
411// CPX_STAT_ABORT_USER
412// CPX_STAT_FEASIBLE_RELAXED
413// CPX_STAT_INFEASIBLE
414// CPX_STAT_INForUNBD
415// CPX_STAT_NUM_BEST
416// CPX_STAT_OPTIMAL
417// CPX_STAT_OPTIMAL_FACE_UNBOUNDED
418// CPX_STAT_OPTIMAL_INFEAS
419// CPX_STAT_OPTIMAL_RELAXED
420// CPX_STAT_UNBOUNDED
421
422  LpCplex::SolutionStatus LpCplex::_getDualStatus()
423  {
424    int stat = CPXgetstat(env, lp);
425    statusSwitch(env,stat);
426    switch (stat) {
427    case 0:
428      return UNDEFINED; //Undefined
429    case CPX_OPTIMAL://Optimal
430      return OPTIMAL;
431    case CPX_UNBOUNDED:
432     return INFEASIBLE;
433    default:
434      return UNDEFINED; //Everything else comes here
435      //FIXME error
436    }
437  }
438
439  LpCplex::ProblemTypes LpCplex::_getProblemType()
440  {
441    int stat = CPXgetstat(env, lp);
442    switch (stat) {
443    case CPX_OPTIMAL://Optimal
444        return PRIMAL_DUAL_FEASIBLE;
445    case CPX_UNBOUNDED:
446        return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
447//      return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
448//      return PRIMAL_DUAL_INFEASIBLE;
449
450//Seems to be that this is all we can say for sure
451    default:
452        //In all other cases
453        return UNKNOWN;
454      //FIXME error
455    }
456  }
457
458  void LpCplex::_setMax()
459  {
460    CPXchgobjsen(env, lp, CPX_MAX);
461   }
462  void LpCplex::_setMin()
463  {
464    CPXchgobjsen(env, lp, CPX_MIN);
465   }
466 
467} //namespace lemon
468
Note: See TracBrowser for help on using the repository browser.