COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lp_cplex.cc @ 1473:876c7b7f4dae

Last change on this file since 1473:876c7b7f4dae was 1473:876c7b7f4dae, checked in by athos, 14 years ago

Some tests have been developed, bugs got fixed.

File size: 10.8 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    if (status == 0){
246      //We want to exclude some cases
247      switch (CPXgetstat (env, lp)){
248      case CPX_OBJ_LIM:
249      case CPX_IT_LIM_FEAS:
250      case CPX_IT_LIM_INFEAS:               
251      case CPX_TIME_LIM_FEAS:
252      case CPX_TIME_LIM_INFEAS:
253        return UNSOLVED;
254      default:
255        return SOLVED;
256      }
257    }
258    else{
259      return UNSOLVED;
260    }
261  }
262
263  LpCplex::Value LpCplex::_getPrimal(int i)
264  {
265    Value x;
266    CPXgetx (env, lp, &x, i, i);
267    return x;
268  }
269 
270  LpCplex::Value LpCplex::_getPrimalValue()
271  {
272    Value objval;
273    //method = CPXgetmethod (env, lp);
274    status = CPXgetobjval (env, lp, &objval);
275    return objval;
276  }
277 
278
279//7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
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.
281
282// For Simplex, Barrier 
283// 1    CPX_OPTIMAL 
284//       Optimal solution found 
285// 2    CPX_INFEASIBLE 
286//       Problem infeasible 
287// 3    CPX_UNBOUNDED 
288//       Problem unbounded 
289// 4    CPX_OBJ_LIM 
290//       Objective limit exceeded in Phase II 
291// 5    CPX_IT_LIM_FEAS 
292//       Iteration limit exceeded in Phase II 
293// 6    CPX_IT_LIM_INFEAS 
294//       Iteration limit exceeded in Phase I 
295// 7    CPX_TIME_LIM_FEAS 
296//       Time limit exceeded in Phase II 
297// 8    CPX_TIME_LIM_INFEAS 
298//       Time limit exceeded in Phase I 
299// 9    CPX_NUM_BEST_FEAS 
300//       Problem non-optimal, singularities in Phase II 
301// 10   CPX_NUM_BEST_INFEAS 
302//       Problem non-optimal, singularities in Phase I 
303// 11   CPX_OPTIMAL_INFEAS 
304//       Optimal solution found, unscaled infeasibilities 
305// 12   CPX_ABORT_FEAS 
306//       Aborted in Phase II 
307// 13   CPX_ABORT_INFEAS 
308//       Aborted in Phase I 
309// 14   CPX_ABORT_DUAL_INFEAS 
310//       Aborted in barrier, dual infeasible 
311// 15   CPX_ABORT_PRIM_INFEAS 
312//       Aborted in barrier, primal infeasible 
313// 16   CPX_ABORT_PRIM_DUAL_INFEAS 
314//       Aborted in barrier, primal and dual infeasible 
315// 17   CPX_ABORT_PRIM_DUAL_FEAS 
316//       Aborted in barrier, primal and dual feasible 
317// 18   CPX_ABORT_CROSSOVER 
318//       Aborted in crossover 
319// 19   CPX_INForUNBD 
320//       Infeasible or unbounded 
321// 20   CPX_PIVOT
322//       User pivot used
323//
324//     Ezeket hova tegyem:
325// ??case CPX_ABORT_DUAL_INFEAS           
326// ??case CPX_ABORT_CROSSOVER             
327// ??case CPX_INForUNBD                   
328// ??case CPX_PIVOT                       
329
330  LpCplex::SolutionStatus LpCplex::_getPrimalStatus()
331  {
332    int stat = CPXgetstat (env, lp);
333    switch (stat) {
334    case 0:
335      return UNDEFINED; //Undefined
336    case CPX_OPTIMAL://Optimal
337      return OPTIMAL;
338    case CPX_UNBOUNDED://Unbounded
339      return INFINITE;
340    case CPX_INFEASIBLE://Infeasible
341 //    case CPX_IT_LIM_INFEAS:
342//     case CPX_TIME_LIM_INFEAS:
343//     case CPX_NUM_BEST_INFEAS:             
344//     case CPX_OPTIMAL_INFEAS:             
345//     case CPX_ABORT_INFEAS:               
346//     case CPX_ABORT_PRIM_INFEAS:           
347//     case CPX_ABORT_PRIM_DUAL_INFEAS:     
348      return INFEASIBLE;
349//     case CPX_OBJ_LIM:                   
350//     case CPX_IT_LIM_FEAS:             
351//     case CPX_TIME_LIM_FEAS:               
352//     case CPX_NUM_BEST_FEAS:               
353//     case CPX_ABORT_FEAS:                 
354//     case CPX_ABORT_PRIM_DUAL_FEAS:       
355//       return FEASIBLE;
356    default:
357      return UNDEFINED; //Everything else comes here
358      //FIXME error
359    }
360
361  }
362
363//9.0-as cplex verzio statusai
364// CPX_STAT_ABORT_DUAL_OBJ_LIM
365// CPX_STAT_ABORT_IT_LIM
366// CPX_STAT_ABORT_OBJ_LIM
367// CPX_STAT_ABORT_PRIM_OBJ_LIM
368// CPX_STAT_ABORT_TIME_LIM
369// CPX_STAT_ABORT_USER
370// CPX_STAT_FEASIBLE_RELAXED
371// CPX_STAT_INFEASIBLE
372// CPX_STAT_INForUNBD
373// CPX_STAT_NUM_BEST
374// CPX_STAT_OPTIMAL
375// CPX_STAT_OPTIMAL_FACE_UNBOUNDED
376// CPX_STAT_OPTIMAL_INFEAS
377// CPX_STAT_OPTIMAL_RELAXED
378// CPX_STAT_UNBOUNDED
379
380  LpCplex::SolutionStatus LpCplex::_getDualStatus()
381  {
382    int stat = CPXgetstat (env, lp);
383    switch (stat) {
384    case 0:
385      return UNDEFINED; //Undefined
386    case CPX_OPTIMAL://Optimal
387      return OPTIMAL;
388    case CPX_UNBOUNDED:
389     return INFEASIBLE;
390    default:
391      return UNDEFINED; //Everything else comes here
392      //FIXME error
393    }
394  }
395
396  LpCplex::ProblemTypes LpCplex::_getProblemType()
397  {
398    int stat = CPXgetstat (env, lp);
399    switch (stat) {
400    case CPX_OPTIMAL://Optimal
401        return PRIMAL_DUAL_FEASIBLE;
402    case CPX_UNBOUNDED:
403        return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
404//      return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
405//      return PRIMAL_DUAL_INFEASIBLE;
406
407//Seems to be that this is all we can say for sure
408    default:
409        //In all other cases
410        return UNKNOWN;
411      //FIXME error
412    }
413  }
414
415  void LpCplex::_setMax()
416  {
417    CPXchgobjsen (env, lp, CPX_MAX);
418   }
419  void LpCplex::_setMin()
420  {
421    CPXchgobjsen (env, lp, CPX_MIN);
422   }
423 
424} //namespace lemon
425
Note: See TracBrowser for help on using the repository browser.