COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lp_cplex.cc @ 1611:bb51e4a510c5

Last change on this file since 1611:bb51e4a510c5 was 1542:0219ee65ffcc, checked in by athos, 19 years ago

Some testing of the LP interface: bugs got fixed.

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