COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lp_glpk.cc @ 2366:bfbdded3763a

Last change on this file since 2366:bfbdded3763a was 2366:bfbdded3763a, checked in by Balazs Dezso, 17 years ago

Using const in lp interface
colByName functionality

File size: 12.8 KB
RevLine 
[1261]1/* -*- C++ -*-
2 *
[1956]3 * This file is a part of LEMON, a generic C++ optimization library
4 *
5 * Copyright (C) 2003-2006
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
[1359]7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
[1261]8 *
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
12 *
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
15 * purpose.
16 *
17 */
18
19///\file
20///\brief Implementation of the LEMON-GLPK lp solver interface.
21
[1305]22#include <lemon/lp_glpk.h>
[1473]23//#include <iostream>
[1261]24namespace lemon {
25
[1364]26
[2363]27  LpGlpk::LpGlpk() : Parent() {
28    rows = _lp_bits::LpId(1);
29    cols = _lp_bits::LpId(1);
30    lp = lpx_create_prob();
31    ///\todo control function for this:
[1321]32    lpx_set_int_parm(lp, LPX_K_DUAL, 1);
33    messageLevel(0);
34  }
35 
[2363]36  LpGlpk::LpGlpk(const LpGlpk &glp) : Parent() {
37    rows = _lp_bits::LpId(1);
38    cols = _lp_bits::LpId(1);
39    lp = lpx_create_prob();
[2366]40    lpx_create_index(lp);
[2363]41    ///\todo control function for this:
[2321]42    lpx_set_int_parm(lp, LPX_K_DUAL, 1);
43    messageLevel(0);
44    //Coefficient matrix, row bounds
45    lpx_add_rows(lp, lpx_get_num_rows(glp.lp));
46    lpx_add_cols(lp, lpx_get_num_cols(glp.lp));
47    int len;
48    int ind[1+lpx_get_num_cols(glp.lp)];
49    Value val[1+lpx_get_num_cols(glp.lp)];
50    for (int i=1;i<=lpx_get_num_rows(glp.lp);++i)
51      {
52        len=lpx_get_mat_row(glp.lp,i,ind,val);
53        lpx_set_mat_row(lp, i,len,ind,val);
54        lpx_set_row_bnds(lp,i,lpx_get_row_type(glp.lp,i),
55                         lpx_get_row_lb(glp.lp,i),lpx_get_row_ub(glp.lp,i));
56      }
57
58    //Objective function, coloumn bounds
59    lpx_set_obj_dir(lp, lpx_get_obj_dir(glp.lp));
60    //Objectif function's constant term treated separately
61    lpx_set_obj_coef(lp,0,lpx_get_obj_coef(glp.lp,0));
62    for (int i=1;i<=lpx_get_num_cols(glp.lp);++i)
63      {
64        lpx_set_obj_coef(lp,i,lpx_get_obj_coef(glp.lp,i));
65        lpx_set_col_bnds(lp,i,lpx_get_col_type(glp.lp,i),
66                         lpx_get_col_lb(glp.lp,i),lpx_get_col_ub(glp.lp,i));
67      }
68  }
69 
[1321]70  LpGlpk::~LpGlpk() {
71    lpx_delete_prob(lp);
72  }
73 
74  int LpGlpk::_addCol() {
75    int i=lpx_add_cols(lp, 1);
76    _setColLowerBound(i, -INF);
77    _setColUpperBound(i, INF);
78    return i;
79  }
80
[1436]81  ///\e
82
83
84  LpSolverBase &LpGlpk::_newLp()
85  {
[2321]86    LpGlpk* newlp=new LpGlpk;
[1436]87    return *newlp;
88  }
89 
90  ///\e
91
92  LpSolverBase &LpGlpk::_copyLp()
93  {
[2321]94    LpGlpk* newlp=new LpGlpk(*this);
[1436]95    return *newlp;
96  }
97
[1321]98  int LpGlpk::_addRow() {
99    int i=lpx_add_rows(lp, 1);
100    return i;
101  }
102
103 
[1432]104  void LpGlpk::_eraseCol(int i) {
105    int cols[2];
106    cols[1]=i;
107    lpx_del_cols(lp, 1, cols);
108  }
109 
110  void LpGlpk::_eraseRow(int i) {
111    int rows[2];
112    rows[1]=i;
113    lpx_del_rows(lp, 1, rows);
114  }
115
[2366]116  void LpGlpk::_getColName(int col, std::string & name) const
[1895]117  {
118   
119    char *n = lpx_get_col_name(lp,col);
120    name = n?n:"";
121  }
122 
123 
124  void LpGlpk::_setColName(int col, const std::string & name)
125  {
126    lpx_set_col_name(lp,col,const_cast<char*>(name.c_str()));
[2349]127
[1895]128  }
[2366]129
130  int LpGlpk::_colByName(const std::string& name) const
131  {
132    int k = lpx_find_col(lp, const_cast<char*>(name.c_str()));
133    return k > 0 ? k : -1;
134  }
135
[1895]136 
[2364]137  void LpGlpk::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e)
[1321]138  {
[2312]139    std::vector<int> indices;
140    std::vector<Value> values;
141
142    indices.push_back(0);
143    values.push_back(0);
144
[2364]145    for(ConstRowIterator it=b; it!=e; ++it) {
[2312]146      indices.push_back(it->first);
147      values.push_back(it->second);
148    }
149
150    lpx_set_mat_row(lp, i, values.size() - 1, &indices[0], &values[0]);
[1321]151  }
[2364]152
[2366]153  void LpGlpk::_getRowCoeffs(int i, RowIterator b) const
[2364]154  {
155    int length = lpx_get_mat_row(lp, i, 0, 0);
156   
157    std::vector<int> indices(length + 1);
158    std::vector<Value> values(length + 1);
159   
160    lpx_get_mat_row(lp, i, &indices[0], &values[0]);
161   
162    for (int i = 1; i <= length; ++i) {
163      *b = std::make_pair(indices[i], values[i]);
164      ++b;
165    }
166  }
[1321]167 
[2364]168  void LpGlpk::_setColCoeffs(int i, ConstColIterator b, ConstColIterator e) {
[2312]169
170    std::vector<int> indices;
171    std::vector<Value> values;
172
173    indices.push_back(0);
174    values.push_back(0);
175
[2364]176    for(ConstColIterator it=b; it!=e; ++it) {
[2312]177      indices.push_back(it->first);
178      values.push_back(it->second);
179    }
180   
181    lpx_set_mat_col(lp, i, values.size() - 1, &indices[0], &values[0]);
[1321]182  }
[1431]183
[2366]184  void LpGlpk::_getColCoeffs(int i, ColIterator b) const
[2364]185  {
186    int length = lpx_get_mat_col(lp, i, 0, 0);
187   
188    std::vector<int> indices(length + 1);
189    std::vector<Value> values(length + 1);
190   
191    lpx_get_mat_col(lp, i, &indices[0], &values[0]);
192   
193    for (int i = 1; i <= length; ++i) {
194      *b = std::make_pair(indices[i], values[i]);
195      ++b;
196    }
197  }
[1431]198
199  void LpGlpk::_setCoeff(int row, int col, Value value)
200  {
[2312]201
202    if (lpx_get_num_cols(lp) < lpx_get_num_rows(lp)) {
203
204      int length=lpx_get_mat_row(lp, row, 0, 0);
205     
206      std::vector<int> indices(length + 2);
207      std::vector<Value> values(length + 2);
208     
209      lpx_get_mat_row(lp, row, &indices[0], &values[0]);
210     
211      //The following code does not suppose that the elements of the
212      //array indices are sorted
213      bool found=false;
214      for (int i = 1; i <= length; ++i) {
215        if (indices[i]==col){
216          found=true;
217          values[i]=value;
218          break;
219        }
220      }
221      if (!found){
222        ++length;
223        indices[length]=col;
224        values[length]=value;
225      }
[1431]226   
[2312]227      lpx_set_mat_row(lp, row, length, &indices[0], &values[0]);
228
229    } else {
230
231      int length=lpx_get_mat_col(lp, col, 0, 0);
232     
233      std::vector<int> indices(length + 2);
234      std::vector<Value> values(length + 2);
235     
236      lpx_get_mat_col(lp, col, &indices[0], &values[0]);
237     
238      //The following code does not suppose that the elements of the
239      //array indices are sorted
240      bool found=false;
241      for (int i = 1; i <= length; ++i) {
242        if (indices[i]==col){
243          found=true;
244          values[i]=value;
245          break;
246        }
247      }
248      if (!found){
249        ++length;
250        indices[length]=row;
251        values[length]=value;
252      }
[1431]253   
[2312]254      lpx_set_mat_col(lp, col, length, &indices[0], &values[0]);
[1431]255    }
256  }
257
[2366]258  LpGlpk::Value LpGlpk::_getCoeff(int row, int col) const
[2324]259  {
[2328]260
261    int length=lpx_get_mat_row(lp, row, 0, 0);
262   
[2364]263    std::vector<int> indices(length + 1);
264    std::vector<Value> values(length + 1);
[2328]265   
266    lpx_get_mat_row(lp, row, &indices[0], &values[0]);
267   
268    //The following code does not suppose that the elements of the
269    //array indices are sorted
270    for (int i = 1; i <= length; ++i) {
271      if (indices[i]==col){
272        return values[i];
273      }
274    }
[2324]275    return 0;
[2328]276
[2324]277  }
278
279
[1321]280  void LpGlpk::_setColLowerBound(int i, Value lo)
281  {
282    if (lo==INF) {
283      //FIXME error
284    }
285    int b=lpx_get_col_type(lp, i);
286    double up=lpx_get_col_ub(lp, i);   
287    if (lo==-INF) {
288      switch (b) {
289      case LPX_FR:
290      case LPX_LO:
291        lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
292        break;
293      case LPX_UP:
294        break;
295      case LPX_DB:
296      case LPX_FX:
297        lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
298        break;
299      default: ;
300        //FIXME error
301      }
302    } else {
303      switch (b) {
304      case LPX_FR:
305      case LPX_LO:
306        lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
307        break;
308      case LPX_UP:       
309      case LPX_DB:
310      case LPX_FX:
311        if (lo==up)
312          lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
313        else
314          lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
315        break;
316      default: ;
317        //FIXME error
318      }
[1261]319    }
320
[1321]321  }
[2328]322
[2366]323  LpGlpk::Value LpGlpk::_getColLowerBound(int i) const
[2328]324  {
325    int b=lpx_get_col_type(lp, i);
326      switch (b) {
327      case LPX_LO:
328      case LPX_DB:
329      case LPX_FX:
330        return lpx_get_col_lb(lp, i);   
331      default: ;
332        return -INF;
333      }
334  }
[1321]335 
336  void LpGlpk::_setColUpperBound(int i, Value up)
337  {
338    if (up==-INF) {
339      //FIXME error
[1261]340    }
[1321]341    int b=lpx_get_col_type(lp, i);
342    double lo=lpx_get_col_lb(lp, i);
343    if (up==INF) {
344      switch (b) {
345      case LPX_FR:
346      case LPX_LO:
347        break;
348      case LPX_UP:
349        lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
350        break;
351      case LPX_DB:
352      case LPX_FX:
353        lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
354        break;
355      default: ;
[1261]356        //FIXME error
357      }
[1321]358    } else {
359      switch (b) {
360      case LPX_FR:
361        lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
362        break;
363      case LPX_UP:
364        lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
365        break;
366      case LPX_LO:
367      case LPX_DB:
368      case LPX_FX:
369        if (lo==up)
370          lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
371        else
372          lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
373        break;
374      default: ;
[1261]375        //FIXME error
376      }
[1321]377    }
378  }
[2328]379
[2366]380  LpGlpk::Value LpGlpk::_getColUpperBound(int i) const
[2328]381  {
382    int b=lpx_get_col_type(lp, i);
383      switch (b) {
384      case LPX_UP:
385      case LPX_DB:
386      case LPX_FX:
387        return lpx_get_col_ub(lp, i);   
388      default: ;
389        return INF;
390      }
391  }
[1321]392 
[1379]393  void LpGlpk::_setRowBounds(int i, Value lb, Value ub)
394  {
395    //Bad parameter
396    if (lb==INF || ub==-INF) {
397      //FIXME error
398    }
399
400    if (lb == -INF){
401      if (ub == INF){
402        lpx_set_row_bnds(lp, i, LPX_FR, lb, ub);
403      }
404      else{
405        lpx_set_row_bnds(lp, i, LPX_UP, lb, ub);
406      }
407    }
408    else{
409      if (ub==INF){
410        lpx_set_row_bnds(lp, i, LPX_LO, lb, ub);
411
412      }
413      else{
414        if (lb == ub){
415          lpx_set_row_bnds(lp, i, LPX_FX, lb, ub);
416        }
417        else{
418          lpx_set_row_bnds(lp, i, LPX_DB, lb, ub);
419        }
420      }
421    }
422
423  }
[2328]424
[2366]425  void LpGlpk::_getRowBounds(int i, Value &lb, Value &ub) const
[2328]426  {
427
428    int b=lpx_get_row_type(lp, i);
429    switch (b) {
430    case LPX_FR:
431    case LPX_UP:
432      lb = -INF;
433        break;
434    default:
435      lb=lpx_get_row_lb(lp, i);
436    }
437
438    switch (b) {
439    case LPX_FR:
440    case LPX_LO:
441      ub = INF;
442        break;
443    default:
444      ub=lpx_get_row_ub(lp, i);
445    }
446   
447  }
[1261]448 
[1298]449  void LpGlpk::_setObjCoeff(int i, Value obj_coef)
450  {
[1376]451    //i=0 means the constant term (shift)
[1298]452    lpx_set_obj_coef(lp, i, obj_coef);
453  }
[1261]454
[2366]455  LpGlpk::Value LpGlpk::_getObjCoeff(int i) const {
[2324]456    //i=0 means the constant term (shift)
457    return lpx_get_obj_coef(lp, i);
458  }
459
[1377]460  void LpGlpk::_clearObj()
[1376]461  {
[1377]462    for (int i=0;i<=lpx_get_num_cols(lp);++i){
463      lpx_set_obj_coef(lp, i, 0);
[1376]464    }
465  }
[1263]466
[1303]467  LpGlpk::SolveExitStatus LpGlpk::_solve()
[1263]468  {
[2345]469    // A way to check the problem to be solved
470    //lpx_write_cpxlp(lp,"naittvan.cpx");   
471
[2363]472    lpx_std_basis(lp);
[1458]473    int i =  lpx_simplex(lp);
[2363]474   
[1298]475    switch (i) {
476    case LPX_E_OK:
477      return SOLVED;
478    default:
479      return UNSOLVED;
480    }
[1263]481  }
482
[2366]483  LpGlpk::Value LpGlpk::_getPrimal(int i) const
[1263]484  {
[1298]485    return lpx_get_col_prim(lp,i);
[1263]486  }
[1787]487
[2366]488  LpGlpk::Value LpGlpk::_getDual(int i) const
[1787]489  {
490    return lpx_get_row_dual(lp,i);
491  }
[1263]492 
[2366]493  LpGlpk::Value LpGlpk::_getPrimalValue() const
[1312]494  {
[1314]495    return lpx_get_obj_val(lp);
[1312]496  }
[2366]497  bool LpGlpk::_isBasicCol(int i) const
498  {
[1840]499    return (lpx_get_col_stat(lp, i)==LPX_BS);
500  }
[1312]501 
[1298]502 
[2366]503  LpGlpk::SolutionStatus LpGlpk::_getPrimalStatus() const
[1294]504  {
[1298]505    int stat=  lpx_get_status(lp);
506    switch (stat) {
507    case LPX_UNDEF://Undefined (no solve has been run yet)
508      return UNDEFINED;
[1458]509    case LPX_NOFEAS://There is no feasible solution (primal, I guess)
510    case LPX_INFEAS://Infeasible
511      return INFEASIBLE;
512    case LPX_UNBND://Unbounded
513      return INFINITE;
514    case LPX_FEAS://Feasible
515      return FEASIBLE;
516    case LPX_OPT://Feasible
517      return OPTIMAL;
518    default:
519      return UNDEFINED; //to avoid gcc warning
520      //FIXME error
521    }
522  }
523
[2366]524  LpGlpk::SolutionStatus LpGlpk::_getDualStatus() const
[1458]525  {
[1466]526    switch (lpx_get_dual_stat(lp)) {
[1458]527    case LPX_D_UNDEF://Undefined (no solve has been run yet)
528      return UNDEFINED;
[1540]529    case LPX_D_NOFEAS://There is no dual feasible solution
[1460]530//    case LPX_D_INFEAS://Infeasible
[1458]531      return INFEASIBLE;
[1473]532    case LPX_D_FEAS://Feasible   
533      switch (lpx_get_status(lp)) {
534      case LPX_NOFEAS:
[1458]535        return INFINITE;
536      case LPX_OPT:
537        return OPTIMAL;
538      default:
539        return FEASIBLE;
540      }
541    default:
542      return UNDEFINED; //to avoid gcc warning
543      //FIXME error
544    }
545  }
546
[2366]547  LpGlpk::ProblemTypes LpGlpk::_getProblemType() const
[1458]548  {
[1460]549      //int stat=  lpx_get_status(lp);
[1458]550    int statp=  lpx_get_prim_stat(lp);
551    int statd=  lpx_get_dual_stat(lp);
[1464]552    if (statp==LPX_P_FEAS && statd==LPX_D_FEAS)
[1460]553        return PRIMAL_DUAL_FEASIBLE;
[1464]554    if (statp==LPX_P_FEAS && statd==LPX_D_NOFEAS)
[1460]555        return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
[1464]556    if (statp==LPX_P_NOFEAS && statd==LPX_D_FEAS)
[1460]557        return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
[1464]558    if (statp==LPX_P_NOFEAS && statd==LPX_D_NOFEAS)
[1460]559        return PRIMAL_DUAL_INFEASIBLE;
560    //In all other cases
561    return UNKNOWN;
[1294]562  }
[1263]563
[1312]564  void LpGlpk::_setMax()
565  {
[1321]566    lpx_set_obj_dir(lp, LPX_MAX);
567  }
568
[1312]569  void LpGlpk::_setMin()
570  {
[1321]571    lpx_set_obj_dir(lp, LPX_MIN);
572  }
573
[2366]574  bool LpGlpk::_isMax() const
[2324]575  {
576    return (lpx_get_obj_dir(lp)==LPX_MAX);
577  }
578
[1321]579 
[2324]580
[1321]581  void LpGlpk::messageLevel(int m)
582  {
583    lpx_set_int_parm(lp, LPX_K_MSGLEV, m);
584  }
[1312]585
[1326]586  void LpGlpk::presolver(bool b)
587  {
588    lpx_set_int_parm(lp, LPX_K_PRESOL, b);
589  }
590
[1312]591 
[1261]592} //END OF NAMESPACE LEMON
Note: See TracBrowser for help on using the repository browser.