2 * lemon/lp_glpk.cc - Part of LEMON, a generic C++ optimization library
4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Research Group on Combinatorial Optimization, EGRES).
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.
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
17 #ifndef LEMON_LP_GLPK_CC
18 #define LEMON_LP_GLPK_CC
21 ///\brief Implementation of the LEMON-GLPK lp solver interface.
23 #include <lemon/lp_glpk.h>
28 LpGlpk::LpGlpk() : Parent(),
29 lp(lpx_create_prob()) {
30 ///\todo constrol function for this:
31 lpx_set_int_parm(lp, LPX_K_DUAL, 1);
39 int LpGlpk::_addCol() {
40 int i=lpx_add_cols(lp, 1);
41 _setColLowerBound(i, -INF);
42 _setColUpperBound(i, INF);
49 LpSolverBase &LpGlpk::_newLp()
51 LpGlpk* newlp=new LpGlpk();
57 LpSolverBase &LpGlpk::_copyLp()
59 LpGlpk* newlp=new LpGlpk();
61 //Coefficient matrix, row bounds
62 lpx_add_rows(newlp->lp, lpx_get_num_rows(lp));
63 lpx_add_cols(newlp->lp, lpx_get_num_cols(lp));
65 int ind[1+lpx_get_num_cols(lp)];
66 Value val[1+lpx_get_num_cols(lp)];
67 for (int i=1;i<=lpx_get_num_rows(lp);++i){
68 len=lpx_get_mat_row(lp,i,ind,val);
69 lpx_set_mat_row(newlp->lp, i,len,ind,val);
70 lpx_set_row_bnds(newlp->lp,i,lpx_get_row_type(lp,i),
71 lpx_get_row_lb(lp,i),lpx_get_row_ub(lp,i));
74 //Objective function, coloumn bounds
75 lpx_set_obj_dir(newlp->lp, lpx_get_obj_dir(lp));
76 //Objectif function's constant term treated separately
77 lpx_set_obj_coef(newlp->lp,0,lpx_get_obj_coef(lp,0));
78 for (int i=1;i<=lpx_get_num_cols(lp);++i){
79 lpx_set_obj_coef(newlp->lp,i,lpx_get_obj_coef(lp,i));
80 lpx_set_col_bnds(newlp->lp,i,lpx_get_col_type(lp,i),
81 lpx_get_col_lb(lp,i),lpx_get_col_ub(lp,i));
89 int LpGlpk::_addRow() {
90 int i=lpx_add_rows(lp, 1);
95 void LpGlpk::_eraseCol(int i) {
98 lpx_del_cols(lp, 1, cols);
101 void LpGlpk::_eraseRow(int i) {
104 lpx_del_rows(lp, 1, rows);
107 void LpGlpk::_setRowCoeffs(int i,
110 const Value * values )
112 lpx_set_mat_row(lp, i, length,
113 const_cast<int * >(indices) ,
114 const_cast<Value * >(values));
117 void LpGlpk::_setColCoeffs(int i,
120 const Value * values)
122 lpx_set_mat_col(lp, i, length,
123 const_cast<int * >(indices),
124 const_cast<Value * >(values));
128 void LpGlpk::_setCoeff(int row, int col, Value value)
130 ///FIXME Of course this is not efficient at all, but GLPK knows not more.
131 // First approach: get one row, apply changes and set it again
132 //(one idea to improve this: maybe it is better to do this with 1 coloumn)
134 int mem_length=2+lpx_get_num_cols(lp);
135 int* indices = new int[mem_length];
136 Value* values = new Value[mem_length];
139 int length=lpx_get_mat_row(lp, row, indices, values);
141 //The following code does not suppose that the elements of the array indices are sorted
144 while (i <= length && !found){
145 if (indices[i]==col){
154 values[length]=value;
157 lpx_set_mat_row(lp, row, length, indices, values);
163 void LpGlpk::_setColLowerBound(int i, Value lo)
168 int b=lpx_get_col_type(lp, i);
169 double up=lpx_get_col_ub(lp, i);
174 lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
180 lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
189 lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
195 lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
197 lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
206 void LpGlpk::_setColUpperBound(int i, Value up)
211 int b=lpx_get_col_type(lp, i);
212 double lo=lpx_get_col_lb(lp, i);
219 lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
223 lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
231 lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
234 lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
240 lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
242 lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
250 // void LpGlpk::_setRowLowerBound(int i, Value lo)
255 // int b=lpx_get_row_type(lp, i);
256 // double up=lpx_get_row_ub(lp, i);
261 // lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
267 // lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
276 // lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
282 // lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
284 // lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
292 // void LpGlpk::_setRowUpperBound(int i, Value up)
297 // int b=lpx_get_row_type(lp, i);
298 // double lo=lpx_get_row_lb(lp, i);
305 // lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
309 // lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
317 // lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
320 // lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
326 // lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
328 // lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
336 void LpGlpk::_setRowBounds(int i, Value lb, Value ub)
339 if (lb==INF || ub==-INF) {
345 lpx_set_row_bnds(lp, i, LPX_FR, lb, ub);
348 lpx_set_row_bnds(lp, i, LPX_UP, lb, ub);
353 lpx_set_row_bnds(lp, i, LPX_LO, lb, ub);
358 lpx_set_row_bnds(lp, i, LPX_FX, lb, ub);
361 lpx_set_row_bnds(lp, i, LPX_DB, lb, ub);
368 void LpGlpk::_setObjCoeff(int i, Value obj_coef)
370 //i=0 means the constant term (shift)
371 lpx_set_obj_coef(lp, i, obj_coef);
374 void LpGlpk::_clearObj()
376 for (int i=0;i<=lpx_get_num_cols(lp);++i){
377 lpx_set_obj_coef(lp, i, 0);
380 // void LpGlpk::_setObj(int length,
381 // int const * indices,
382 // Value const * values )
384 // Value new_values[1+lpx_num_cols()];
385 // for (i=0;i<=lpx_num_cols();++i){
388 // for (i=1;i<=length;++i){
389 // new_values[indices[i]]=values[i];
392 // for (i=0;i<=lpx_num_cols();++i){
393 // lpx_set_obj_coef(lp, i, new_values[i]);
397 LpGlpk::SolveExitStatus LpGlpk::_solve()
399 int i = lpx_simplex(lp);
408 LpGlpk::Value LpGlpk::_getPrimal(int i)
410 return lpx_get_col_prim(lp,i);
413 LpGlpk::Value LpGlpk::_getPrimalValue()
415 return lpx_get_obj_val(lp);
419 LpGlpk::SolutionStatus LpGlpk::_getPrimalStatus()
421 int stat= lpx_get_status(lp);
423 case LPX_UNDEF://Undefined (no solve has been run yet)
425 case LPX_NOFEAS://There is no feasible solution (primal, I guess)
426 case LPX_INFEAS://Infeasible
428 case LPX_UNBND://Unbounded
430 case LPX_FEAS://Feasible
432 case LPX_OPT://Feasible
435 return UNDEFINED; //to avoid gcc warning
440 LpGlpk::SolutionStatus LpGlpk::_getDualStatus()
442 // std::cout<<"Itt megy: "<<lpx_get_dual_stat(lp)<<std::endl;
443 // std::cout<<"Itt a primal: "<<lpx_get_prim_stat(lp)<<std::endl;
445 switch (lpx_get_dual_stat(lp)) {
446 case LPX_D_UNDEF://Undefined (no solve has been run yet)
448 case LPX_D_NOFEAS://There is no dual feasible solution
449 // case LPX_D_INFEAS://Infeasible
451 case LPX_D_FEAS://Feasible
452 switch (lpx_get_status(lp)) {
461 return UNDEFINED; //to avoid gcc warning
466 LpGlpk::ProblemTypes LpGlpk::_getProblemType()
468 //int stat= lpx_get_status(lp);
469 int statp= lpx_get_prim_stat(lp);
470 int statd= lpx_get_dual_stat(lp);
471 if (statp==LPX_P_FEAS && statd==LPX_D_FEAS)
472 return PRIMAL_DUAL_FEASIBLE;
473 if (statp==LPX_P_FEAS && statd==LPX_D_NOFEAS)
474 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
475 if (statp==LPX_P_NOFEAS && statd==LPX_D_FEAS)
476 return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
477 if (statp==LPX_P_NOFEAS && statd==LPX_D_NOFEAS)
478 return PRIMAL_DUAL_INFEASIBLE;
483 void LpGlpk::_setMax()
485 lpx_set_obj_dir(lp, LPX_MAX);
488 void LpGlpk::_setMin()
490 lpx_set_obj_dir(lp, LPX_MIN);
494 void LpGlpk::messageLevel(int m)
496 lpx_set_int_parm(lp, LPX_K_MSGLEV, m);
499 void LpGlpk::presolver(bool b)
501 lpx_set_int_parm(lp, LPX_K_PRESOL, b);
505 } //END OF NAMESPACE LEMON
507 #endif //LEMON_LP_GLPK_CC