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);
34 LpGlpk::LpGlpk(const LpGlpk &glp) : Parent(glp),
35 lp(lpx_create_prob()) {
36 ///\todo constrol function for this:
37 lpx_set_int_parm(lp, LPX_K_DUAL, 1);
39 //Coefficient matrix, row bounds
40 lpx_add_rows(lp, lpx_get_num_rows(glp.lp));
41 lpx_add_cols(lp, lpx_get_num_cols(glp.lp));
43 int ind[1+lpx_get_num_cols(glp.lp)];
44 Value val[1+lpx_get_num_cols(glp.lp)];
45 for (int i=1;i<=lpx_get_num_rows(glp.lp);++i)
47 len=lpx_get_mat_row(glp.lp,i,ind,val);
48 lpx_set_mat_row(lp, i,len,ind,val);
49 lpx_set_row_bnds(lp,i,lpx_get_row_type(glp.lp,i),
50 lpx_get_row_lb(glp.lp,i),lpx_get_row_ub(glp.lp,i));
53 //Objective function, coloumn bounds
54 lpx_set_obj_dir(lp, lpx_get_obj_dir(glp.lp));
55 //Objectif function's constant term treated separately
56 lpx_set_obj_coef(lp,0,lpx_get_obj_coef(glp.lp,0));
57 for (int i=1;i<=lpx_get_num_cols(glp.lp);++i)
59 lpx_set_obj_coef(lp,i,lpx_get_obj_coef(glp.lp,i));
60 lpx_set_col_bnds(lp,i,lpx_get_col_type(glp.lp,i),
61 lpx_get_col_lb(glp.lp,i),lpx_get_col_ub(glp.lp,i));
69 int LpGlpk::_addCol() {
70 int i=lpx_add_cols(lp, 1);
71 _setColLowerBound(i, -INF);
72 _setColUpperBound(i, INF);
79 LpSolverBase &LpGlpk::_newLp()
81 LpGlpk* newlp=new LpGlpk;
87 LpSolverBase &LpGlpk::_copyLp()
89 LpGlpk* newlp=new LpGlpk(*this);
93 int LpGlpk::_addRow() {
94 int i=lpx_add_rows(lp, 1);
99 void LpGlpk::_eraseCol(int i) {
102 lpx_del_cols(lp, 1, cols);
105 void LpGlpk::_eraseRow(int i) {
108 lpx_del_rows(lp, 1, rows);
111 void LpGlpk::_getColName(int col, std::string & name)
114 char *n = lpx_get_col_name(lp,col);
119 void LpGlpk::_setColName(int col, const std::string & name)
121 lpx_set_col_name(lp,col,const_cast<char*>(name.c_str()));
125 void LpGlpk::_setRowCoeffs(int i, LpRowIterator b, LpRowIterator e)
127 std::vector<int> indices;
128 std::vector<Value> values;
130 indices.push_back(0);
133 for(LpRowIterator it=b; it!=e; ++it) {
134 indices.push_back(it->first);
135 values.push_back(it->second);
138 lpx_set_mat_row(lp, i, values.size() - 1, &indices[0], &values[0]);
141 void LpGlpk::_setColCoeffs(int i, LpColIterator b, LpColIterator e) {
143 std::vector<int> indices;
144 std::vector<Value> values;
146 indices.push_back(0);
149 for(LpColIterator it=b; it!=e; ++it) {
150 indices.push_back(it->first);
151 values.push_back(it->second);
154 lpx_set_mat_col(lp, i, values.size() - 1, &indices[0], &values[0]);
158 void LpGlpk::_setCoeff(int row, int col, Value value)
161 if (lpx_get_num_cols(lp) < lpx_get_num_rows(lp)) {
163 int length=lpx_get_mat_row(lp, row, 0, 0);
165 std::vector<int> indices(length + 2);
166 std::vector<Value> values(length + 2);
168 lpx_get_mat_row(lp, row, &indices[0], &values[0]);
170 //The following code does not suppose that the elements of the
171 //array indices are sorted
173 for (int i = 1; i <= length; ++i) {
174 if (indices[i]==col){
183 values[length]=value;
186 lpx_set_mat_row(lp, row, length, &indices[0], &values[0]);
190 int length=lpx_get_mat_col(lp, col, 0, 0);
192 std::vector<int> indices(length + 2);
193 std::vector<Value> values(length + 2);
195 lpx_get_mat_col(lp, col, &indices[0], &values[0]);
197 //The following code does not suppose that the elements of the
198 //array indices are sorted
200 for (int i = 1; i <= length; ++i) {
201 if (indices[i]==col){
210 values[length]=value;
213 lpx_set_mat_col(lp, col, length, &indices[0], &values[0]);
217 LpGlpk::Value LpGlpk::_getCoeff(int row, int col)
220 int length=lpx_get_mat_row(lp, row, 0, 0);
222 std::vector<int> indices(length + 2);
223 std::vector<Value> values(length + 2);
225 lpx_get_mat_row(lp, row, &indices[0], &values[0]);
227 //The following code does not suppose that the elements of the
228 //array indices are sorted
229 for (int i = 1; i <= length; ++i) {
230 if (indices[i]==col){
239 void LpGlpk::_setColLowerBound(int i, Value lo)
244 int b=lpx_get_col_type(lp, i);
245 double up=lpx_get_col_ub(lp, i);
250 lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
256 lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
265 lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
271 lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
273 lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
282 LpGlpk::Value LpGlpk::_getColLowerBound(int i)
284 int b=lpx_get_col_type(lp, i);
289 return lpx_get_col_lb(lp, i);
295 void LpGlpk::_setColUpperBound(int i, Value up)
300 int b=lpx_get_col_type(lp, i);
301 double lo=lpx_get_col_lb(lp, i);
308 lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
312 lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
320 lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
323 lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
329 lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
331 lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
339 LpGlpk::Value LpGlpk::_getColUpperBound(int i)
341 int b=lpx_get_col_type(lp, i);
346 return lpx_get_col_ub(lp, i);
352 // void LpGlpk::_setRowLowerBound(int i, Value lo)
357 // int b=lpx_get_row_type(lp, i);
358 // double up=lpx_get_row_ub(lp, i);
363 // lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
369 // lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
378 // lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
384 // lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
386 // lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
394 // void LpGlpk::_setRowUpperBound(int i, Value up)
399 // int b=lpx_get_row_type(lp, i);
400 // double lo=lpx_get_row_lb(lp, i);
407 // lpx_set_row_bnds(lp, i, LPX_FR, lo, up);
411 // lpx_set_row_bnds(lp, i, LPX_LO, lo, up);
419 // lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
422 // lpx_set_row_bnds(lp, i, LPX_UP, lo, up);
428 // lpx_set_row_bnds(lp, i, LPX_FX, lo, up);
430 // lpx_set_row_bnds(lp, i, LPX_DB, lo, up);
438 void LpGlpk::_setRowBounds(int i, Value lb, Value ub)
441 if (lb==INF || ub==-INF) {
447 lpx_set_row_bnds(lp, i, LPX_FR, lb, ub);
450 lpx_set_row_bnds(lp, i, LPX_UP, lb, ub);
455 lpx_set_row_bnds(lp, i, LPX_LO, lb, ub);
460 lpx_set_row_bnds(lp, i, LPX_FX, lb, ub);
463 lpx_set_row_bnds(lp, i, LPX_DB, lb, ub);
470 void LpGlpk::_getRowBounds(int i, Value &lb, Value &ub)
473 int b=lpx_get_row_type(lp, i);
480 lb=lpx_get_row_lb(lp, i);
489 ub=lpx_get_row_ub(lp, i);
494 void LpGlpk::_setObjCoeff(int i, Value obj_coef)
496 //i=0 means the constant term (shift)
497 lpx_set_obj_coef(lp, i, obj_coef);
500 LpGlpk::Value LpGlpk::_getObjCoeff(int i){
501 //i=0 means the constant term (shift)
502 return lpx_get_obj_coef(lp, i);
505 void LpGlpk::_clearObj()
507 for (int i=0;i<=lpx_get_num_cols(lp);++i){
508 lpx_set_obj_coef(lp, i, 0);
511 // void LpGlpk::_setObj(int length,
512 // int const * indices,
513 // Value const * values )
515 // Value new_values[1+lpx_num_cols()];
516 // for (i=0;i<=lpx_num_cols();++i){
519 // for (i=1;i<=length;++i){
520 // new_values[indices[i]]=values[i];
523 // for (i=0;i<=lpx_num_cols();++i){
524 // lpx_set_obj_coef(lp, i, new_values[i]);
528 LpGlpk::SolveExitStatus LpGlpk::_solve()
530 // A way to check the problem to be solved
531 //lpx_write_cpxlp(lp,"naittvan.cpx");
533 int i = lpx_simplex(lp);
542 LpGlpk::Value LpGlpk::_getPrimal(int i)
544 return lpx_get_col_prim(lp,i);
547 LpGlpk::Value LpGlpk::_getDual(int i)
549 return lpx_get_row_dual(lp,i);
552 LpGlpk::Value LpGlpk::_getPrimalValue()
554 return lpx_get_obj_val(lp);
556 bool LpGlpk::_isBasicCol(int i) {
557 return (lpx_get_col_stat(lp, i)==LPX_BS);
561 LpGlpk::SolutionStatus LpGlpk::_getPrimalStatus()
563 int stat= lpx_get_status(lp);
565 case LPX_UNDEF://Undefined (no solve has been run yet)
567 case LPX_NOFEAS://There is no feasible solution (primal, I guess)
568 case LPX_INFEAS://Infeasible
570 case LPX_UNBND://Unbounded
572 case LPX_FEAS://Feasible
574 case LPX_OPT://Feasible
577 return UNDEFINED; //to avoid gcc warning
582 LpGlpk::SolutionStatus LpGlpk::_getDualStatus()
584 // std::cout<<"Itt megy: "<<lpx_get_dual_stat(lp)<<std::endl;
585 // std::cout<<"Itt a primal: "<<lpx_get_prim_stat(lp)<<std::endl;
587 switch (lpx_get_dual_stat(lp)) {
588 case LPX_D_UNDEF://Undefined (no solve has been run yet)
590 case LPX_D_NOFEAS://There is no dual feasible solution
591 // case LPX_D_INFEAS://Infeasible
593 case LPX_D_FEAS://Feasible
594 switch (lpx_get_status(lp)) {
603 return UNDEFINED; //to avoid gcc warning
608 LpGlpk::ProblemTypes LpGlpk::_getProblemType()
610 //int stat= lpx_get_status(lp);
611 int statp= lpx_get_prim_stat(lp);
612 int statd= lpx_get_dual_stat(lp);
613 if (statp==LPX_P_FEAS && statd==LPX_D_FEAS)
614 return PRIMAL_DUAL_FEASIBLE;
615 if (statp==LPX_P_FEAS && statd==LPX_D_NOFEAS)
616 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
617 if (statp==LPX_P_NOFEAS && statd==LPX_D_FEAS)
618 return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
619 if (statp==LPX_P_NOFEAS && statd==LPX_D_NOFEAS)
620 return PRIMAL_DUAL_INFEASIBLE;
625 void LpGlpk::_setMax()
627 lpx_set_obj_dir(lp, LPX_MAX);
630 void LpGlpk::_setMin()
632 lpx_set_obj_dir(lp, LPX_MIN);
635 bool LpGlpk::_isMax()
637 return (lpx_get_obj_dir(lp)==LPX_MAX);
642 void LpGlpk::messageLevel(int m)
644 lpx_set_int_parm(lp, LPX_K_MSGLEV, m);
647 void LpGlpk::presolver(bool b)
649 lpx_set_int_parm(lp, LPX_K_PRESOL, b);
653 } //END OF NAMESPACE LEMON