3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2006
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
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.
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
19 #ifndef LEMON_LP_GLPK_CC
20 #define LEMON_LP_GLPK_CC
23 ///\brief Implementation of the LEMON-GLPK lp solver interface.
25 #include <lemon/lp_glpk.h>
30 LpGlpk::LpGlpk() : Parent(),
31 lp(lpx_create_prob()) {
32 ///\todo constrol function for this:
33 lpx_set_int_parm(lp, LPX_K_DUAL, 1);
41 int LpGlpk::_addCol() {
42 int i=lpx_add_cols(lp, 1);
43 _setColLowerBound(i, -INF);
44 _setColUpperBound(i, INF);
51 LpSolverBase &LpGlpk::_newLp()
53 LpGlpk* newlp=new LpGlpk();
59 LpSolverBase &LpGlpk::_copyLp()
61 LpGlpk* newlp=new LpGlpk();
63 //Coefficient matrix, row bounds
64 lpx_add_rows(newlp->lp, lpx_get_num_rows(lp));
65 lpx_add_cols(newlp->lp, lpx_get_num_cols(lp));
67 int ind[1+lpx_get_num_cols(lp)];
68 Value val[1+lpx_get_num_cols(lp)];
69 for (int i=1;i<=lpx_get_num_rows(lp);++i){
70 len=lpx_get_mat_row(lp,i,ind,val);
71 lpx_set_mat_row(newlp->lp, i,len,ind,val);
72 lpx_set_row_bnds(newlp->lp,i,lpx_get_row_type(lp,i),
73 lpx_get_row_lb(lp,i),lpx_get_row_ub(lp,i));
76 //Objective function, coloumn bounds
77 lpx_set_obj_dir(newlp->lp, lpx_get_obj_dir(lp));
78 //Objectif function's constant term treated separately
79 lpx_set_obj_coef(newlp->lp,0,lpx_get_obj_coef(lp,0));
80 for (int i=1;i<=lpx_get_num_cols(lp);++i){
81 lpx_set_obj_coef(newlp->lp,i,lpx_get_obj_coef(lp,i));
82 lpx_set_col_bnds(newlp->lp,i,lpx_get_col_type(lp,i),
83 lpx_get_col_lb(lp,i),lpx_get_col_ub(lp,i));
91 int LpGlpk::_addRow() {
92 int i=lpx_add_rows(lp, 1);
97 void LpGlpk::_eraseCol(int i) {
100 lpx_del_cols(lp, 1, cols);
103 void LpGlpk::_eraseRow(int i) {
106 lpx_del_rows(lp, 1, rows);
109 void LpGlpk::_getColName(int col, std::string & name)
112 char *n = lpx_get_col_name(lp,col);
117 void LpGlpk::_setColName(int col, const std::string & name)
119 lpx_set_col_name(lp,col,const_cast<char*>(name.c_str()));
122 void LpGlpk::_setRowCoeffs(int i,
125 const Value * values )
127 lpx_set_mat_row(lp, i, length,
128 const_cast<int * >(indices) ,
129 const_cast<Value * >(values));
132 void LpGlpk::_setColCoeffs(int i,
135 const Value * values)
137 lpx_set_mat_col(lp, i, length,
138 const_cast<int * >(indices),
139 const_cast<Value * >(values));
143 void LpGlpk::_setCoeff(int row, int col, Value value)
145 ///FIXME Of course this is not efficient at all, but GLPK knows not more.
146 // First approach: get one row, apply changes and set it again
147 //(one idea to improve this: maybe it is better to do this with 1 coloumn)
149 int mem_length=2+lpx_get_num_cols(lp);
150 int* indices = new int[mem_length];
151 Value* values = new Value[mem_length];
154 int length=lpx_get_mat_row(lp, row, indices, values);
156 //The following code does not suppose that the elements of the array indices are sorted
159 while (i <= length && !found){
160 if (indices[i]==col){
169 values[length]=value;
172 lpx_set_mat_row(lp, row, length, indices, values);
178 void LpGlpk::_setColLowerBound(int i, Value lo)
183 int b=lpx_get_col_type(lp, i);
184 double up=lpx_get_col_ub(lp, i);
189 lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
195 lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
204 lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
210 lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
212 lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
221 void LpGlpk::_setColUpperBound(int i, Value up)
226 int b=lpx_get_col_type(lp, i);
227 double lo=lpx_get_col_lb(lp, i);
234 lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
238 lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
246 lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
249 lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
255 lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
257 lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
265 // void LpGlpk::_setRowLowerBound(int i, Value lo)
270 // int b=lpx_get_row_type(lp, i);
271 // double up=lpx_get_row_ub(lp, i);
276 // lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
282 // lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
291 // lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
297 // lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
299 // lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
307 // void LpGlpk::_setRowUpperBound(int i, Value up)
312 // int b=lpx_get_row_type(lp, i);
313 // double lo=lpx_get_row_lb(lp, i);
320 // lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
324 // lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
332 // lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
335 // lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
341 // lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
343 // lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
351 void LpGlpk::_setRowBounds(int i, Value lb, Value ub)
354 if (lb==INF || ub==-INF) {
360 lpx_set_row_bnds(lp, i, LPX_FR, lb, ub);
363 lpx_set_row_bnds(lp, i, LPX_UP, lb, ub);
368 lpx_set_row_bnds(lp, i, LPX_LO, lb, ub);
373 lpx_set_row_bnds(lp, i, LPX_FX, lb, ub);
376 lpx_set_row_bnds(lp, i, LPX_DB, lb, ub);
383 void LpGlpk::_setObjCoeff(int i, Value obj_coef)
385 //i=0 means the constant term (shift)
386 lpx_set_obj_coef(lp, i, obj_coef);
389 void LpGlpk::_clearObj()
391 for (int i=0;i<=lpx_get_num_cols(lp);++i){
392 lpx_set_obj_coef(lp, i, 0);
395 // void LpGlpk::_setObj(int length,
396 // int const * indices,
397 // Value const * values )
399 // Value new_values[1+lpx_num_cols()];
400 // for (i=0;i<=lpx_num_cols();++i){
403 // for (i=1;i<=length;++i){
404 // new_values[indices[i]]=values[i];
407 // for (i=0;i<=lpx_num_cols();++i){
408 // lpx_set_obj_coef(lp, i, new_values[i]);
412 LpGlpk::SolveExitStatus LpGlpk::_solve()
414 int i = lpx_simplex(lp);
423 LpGlpk::Value LpGlpk::_getPrimal(int i)
425 return lpx_get_col_prim(lp,i);
428 LpGlpk::Value LpGlpk::_getDual(int i)
430 return lpx_get_row_dual(lp,i);
433 LpGlpk::Value LpGlpk::_getPrimalValue()
435 return lpx_get_obj_val(lp);
437 bool LpGlpk::_isBasicCol(int i) {
438 return (lpx_get_col_stat(lp, i)==LPX_BS);
442 LpGlpk::SolutionStatus LpGlpk::_getPrimalStatus()
444 int stat= lpx_get_status(lp);
446 case LPX_UNDEF://Undefined (no solve has been run yet)
448 case LPX_NOFEAS://There is no feasible solution (primal, I guess)
449 case LPX_INFEAS://Infeasible
451 case LPX_UNBND://Unbounded
453 case LPX_FEAS://Feasible
455 case LPX_OPT://Feasible
458 return UNDEFINED; //to avoid gcc warning
463 LpGlpk::SolutionStatus LpGlpk::_getDualStatus()
465 // std::cout<<"Itt megy: "<<lpx_get_dual_stat(lp)<<std::endl;
466 // std::cout<<"Itt a primal: "<<lpx_get_prim_stat(lp)<<std::endl;
468 switch (lpx_get_dual_stat(lp)) {
469 case LPX_D_UNDEF://Undefined (no solve has been run yet)
471 case LPX_D_NOFEAS://There is no dual feasible solution
472 // case LPX_D_INFEAS://Infeasible
474 case LPX_D_FEAS://Feasible
475 switch (lpx_get_status(lp)) {
484 return UNDEFINED; //to avoid gcc warning
489 LpGlpk::ProblemTypes LpGlpk::_getProblemType()
491 //int stat= lpx_get_status(lp);
492 int statp= lpx_get_prim_stat(lp);
493 int statd= lpx_get_dual_stat(lp);
494 if (statp==LPX_P_FEAS && statd==LPX_D_FEAS)
495 return PRIMAL_DUAL_FEASIBLE;
496 if (statp==LPX_P_FEAS && statd==LPX_D_NOFEAS)
497 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
498 if (statp==LPX_P_NOFEAS && statd==LPX_D_FEAS)
499 return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
500 if (statp==LPX_P_NOFEAS && statd==LPX_D_NOFEAS)
501 return PRIMAL_DUAL_INFEASIBLE;
506 void LpGlpk::_setMax()
508 lpx_set_obj_dir(lp, LPX_MAX);
511 void LpGlpk::_setMin()
513 lpx_set_obj_dir(lp, LPX_MIN);
517 void LpGlpk::messageLevel(int m)
519 lpx_set_int_parm(lp, LPX_K_MSGLEV, m);
522 void LpGlpk::presolver(bool b)
524 lpx_set_int_parm(lp, LPX_K_PRESOL, b);
528 } //END OF NAMESPACE LEMON
530 #endif //LEMON_LP_GLPK_CC