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
20 ///\brief Implementation of the LEMON-GLPK lp solver interface.
22 #include <lemon/lp_glpk.h>
27 LpGlpk::LpGlpk() : Parent(),
28 lp(lpx_create_prob()) {
29 ///\todo constrol function for this:
30 lpx_set_int_parm(lp, LPX_K_DUAL, 1);
38 int LpGlpk::_addCol() {
39 int i=lpx_add_cols(lp, 1);
40 _setColLowerBound(i, -INF);
41 _setColUpperBound(i, INF);
48 LpSolverBase &LpGlpk::_newLp()
50 LpGlpk* newlp=new LpGlpk();
56 LpSolverBase &LpGlpk::_copyLp()
58 LpGlpk* newlp=new LpGlpk();
60 //Coefficient matrix, row bounds
61 lpx_add_rows(newlp->lp, lpx_get_num_rows(lp));
62 lpx_add_cols(newlp->lp, lpx_get_num_cols(lp));
64 int ind[1+lpx_get_num_cols(lp)];
65 Value val[1+lpx_get_num_cols(lp)];
66 for (int i=1;i<=lpx_get_num_rows(lp);++i){
67 len=lpx_get_mat_row(lp,i,ind,val);
68 lpx_set_mat_row(newlp->lp, i,len,ind,val);
69 lpx_set_row_bnds(newlp->lp,i,lpx_get_row_type(lp,i),
70 lpx_get_row_lb(lp,i),lpx_get_row_ub(lp,i));
73 //Objective function, coloumn bounds
74 lpx_set_obj_dir(newlp->lp, lpx_get_obj_dir(lp));
75 //Objectif function's constant term treated separately
76 lpx_set_obj_coef(newlp->lp,0,lpx_get_obj_coef(lp,0));
77 for (int i=1;i<=lpx_get_num_cols(lp);++i){
78 lpx_set_obj_coef(newlp->lp,i,lpx_get_obj_coef(lp,i));
79 lpx_set_col_bnds(newlp->lp,i,lpx_get_col_type(lp,i),
80 lpx_get_col_lb(lp,i),lpx_get_col_ub(lp,i));
88 int LpGlpk::_addRow() {
89 int i=lpx_add_rows(lp, 1);
94 void LpGlpk::_eraseCol(int i) {
97 lpx_del_cols(lp, 1, cols);
100 void LpGlpk::_eraseRow(int i) {
103 lpx_del_rows(lp, 1, rows);
106 void LpGlpk::_getColName(int col, std::string & name)
109 char *n = lpx_get_col_name(lp,col);
114 void LpGlpk::_setColName(int col, const std::string & name)
116 lpx_set_col_name(lp,col,const_cast<char*>(name.c_str()));
119 void LpGlpk::_setRowCoeffs(int i, LpRowIterator b, LpRowIterator e)
121 std::vector<int> indices;
122 std::vector<Value> values;
124 indices.push_back(0);
127 for(LpRowIterator it=b; it!=e; ++it) {
128 indices.push_back(it->first);
129 values.push_back(it->second);
132 lpx_set_mat_row(lp, i, values.size() - 1, &indices[0], &values[0]);
135 void LpGlpk::_setColCoeffs(int i, LpColIterator b, LpColIterator e) {
137 std::vector<int> indices;
138 std::vector<Value> values;
140 indices.push_back(0);
143 for(LpColIterator it=b; it!=e; ++it) {
144 indices.push_back(it->first);
145 values.push_back(it->second);
148 lpx_set_mat_col(lp, i, values.size() - 1, &indices[0], &values[0]);
152 void LpGlpk::_setCoeff(int row, int col, Value value)
155 if (lpx_get_num_cols(lp) < lpx_get_num_rows(lp)) {
157 int length=lpx_get_mat_row(lp, row, 0, 0);
159 std::vector<int> indices(length + 2);
160 std::vector<Value> values(length + 2);
162 lpx_get_mat_row(lp, row, &indices[0], &values[0]);
164 //The following code does not suppose that the elements of the
165 //array indices are sorted
167 for (int i = 1; i <= length; ++i) {
168 if (indices[i]==col){
177 values[length]=value;
180 lpx_set_mat_row(lp, row, length, &indices[0], &values[0]);
184 int length=lpx_get_mat_col(lp, col, 0, 0);
186 std::vector<int> indices(length + 2);
187 std::vector<Value> values(length + 2);
189 lpx_get_mat_col(lp, col, &indices[0], &values[0]);
191 //The following code does not suppose that the elements of the
192 //array indices are sorted
194 for (int i = 1; i <= length; ++i) {
195 if (indices[i]==col){
204 values[length]=value;
207 lpx_set_mat_col(lp, col, length, &indices[0], &values[0]);
211 void LpGlpk::_setColLowerBound(int i, Value lo)
216 int b=lpx_get_col_type(lp, i);
217 double up=lpx_get_col_ub(lp, i);
222 lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
228 lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
237 lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
243 lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
245 lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
254 void LpGlpk::_setColUpperBound(int i, Value up)
259 int b=lpx_get_col_type(lp, i);
260 double lo=lpx_get_col_lb(lp, i);
267 lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
271 lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
279 lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
282 lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
288 lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
290 lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
298 // void LpGlpk::_setRowLowerBound(int i, Value lo)
303 // int b=lpx_get_row_type(lp, i);
304 // double up=lpx_get_row_ub(lp, i);
309 // lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
315 // lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
324 // lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
330 // lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
332 // lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
340 // void LpGlpk::_setRowUpperBound(int i, Value up)
345 // int b=lpx_get_row_type(lp, i);
346 // double lo=lpx_get_row_lb(lp, i);
353 // lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
357 // lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
365 // lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
368 // lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
374 // lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
376 // lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
384 void LpGlpk::_setRowBounds(int i, Value lb, Value ub)
387 if (lb==INF || ub==-INF) {
393 lpx_set_row_bnds(lp, i, LPX_FR, lb, ub);
396 lpx_set_row_bnds(lp, i, LPX_UP, lb, ub);
401 lpx_set_row_bnds(lp, i, LPX_LO, lb, ub);
406 lpx_set_row_bnds(lp, i, LPX_FX, lb, ub);
409 lpx_set_row_bnds(lp, i, LPX_DB, lb, ub);
416 void LpGlpk::_setObjCoeff(int i, Value obj_coef)
418 //i=0 means the constant term (shift)
419 lpx_set_obj_coef(lp, i, obj_coef);
422 void LpGlpk::_clearObj()
424 for (int i=0;i<=lpx_get_num_cols(lp);++i){
425 lpx_set_obj_coef(lp, i, 0);
428 // void LpGlpk::_setObj(int length,
429 // int const * indices,
430 // Value const * values )
432 // Value new_values[1+lpx_num_cols()];
433 // for (i=0;i<=lpx_num_cols();++i){
436 // for (i=1;i<=length;++i){
437 // new_values[indices[i]]=values[i];
440 // for (i=0;i<=lpx_num_cols();++i){
441 // lpx_set_obj_coef(lp, i, new_values[i]);
445 LpGlpk::SolveExitStatus LpGlpk::_solve()
447 int i = lpx_simplex(lp);
456 LpGlpk::Value LpGlpk::_getPrimal(int i)
458 return lpx_get_col_prim(lp,i);
461 LpGlpk::Value LpGlpk::_getDual(int i)
463 return lpx_get_row_dual(lp,i);
466 LpGlpk::Value LpGlpk::_getPrimalValue()
468 return lpx_get_obj_val(lp);
470 bool LpGlpk::_isBasicCol(int i) {
471 return (lpx_get_col_stat(lp, i)==LPX_BS);
475 LpGlpk::SolutionStatus LpGlpk::_getPrimalStatus()
477 int stat= lpx_get_status(lp);
479 case LPX_UNDEF://Undefined (no solve has been run yet)
481 case LPX_NOFEAS://There is no feasible solution (primal, I guess)
482 case LPX_INFEAS://Infeasible
484 case LPX_UNBND://Unbounded
486 case LPX_FEAS://Feasible
488 case LPX_OPT://Feasible
491 return UNDEFINED; //to avoid gcc warning
496 LpGlpk::SolutionStatus LpGlpk::_getDualStatus()
498 // std::cout<<"Itt megy: "<<lpx_get_dual_stat(lp)<<std::endl;
499 // std::cout<<"Itt a primal: "<<lpx_get_prim_stat(lp)<<std::endl;
501 switch (lpx_get_dual_stat(lp)) {
502 case LPX_D_UNDEF://Undefined (no solve has been run yet)
504 case LPX_D_NOFEAS://There is no dual feasible solution
505 // case LPX_D_INFEAS://Infeasible
507 case LPX_D_FEAS://Feasible
508 switch (lpx_get_status(lp)) {
517 return UNDEFINED; //to avoid gcc warning
522 LpGlpk::ProblemTypes LpGlpk::_getProblemType()
524 //int stat= lpx_get_status(lp);
525 int statp= lpx_get_prim_stat(lp);
526 int statd= lpx_get_dual_stat(lp);
527 if (statp==LPX_P_FEAS && statd==LPX_D_FEAS)
528 return PRIMAL_DUAL_FEASIBLE;
529 if (statp==LPX_P_FEAS && statd==LPX_D_NOFEAS)
530 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
531 if (statp==LPX_P_NOFEAS && statd==LPX_D_FEAS)
532 return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
533 if (statp==LPX_P_NOFEAS && statd==LPX_D_NOFEAS)
534 return PRIMAL_DUAL_INFEASIBLE;
539 void LpGlpk::_setMax()
541 lpx_set_obj_dir(lp, LPX_MAX);
544 void LpGlpk::_setMin()
546 lpx_set_obj_dir(lp, LPX_MIN);
550 void LpGlpk::messageLevel(int m)
552 lpx_set_int_parm(lp, LPX_K_MSGLEV, m);
555 void LpGlpk::presolver(bool b)
557 lpx_set_int_parm(lp, LPX_K_PRESOL, b);
561 } //END OF NAMESPACE LEMON