1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
3 * This file is a part of LEMON, a generic C++ optimization library.
5 * Copyright (C) 2003-2008
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>
29 #if GLP_MAJOR_VERSION > 4 || (GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION > 15)
30 #define LEMON_glp(func) (glp_##func)
31 #define LEMON_lpx(func) (lpx_##func)
33 #define LEMON_GLP(def) (GLP_##def)
34 #define LEMON_LPX(def) (LPX_##def)
38 #define LEMON_glp(func) (lpx_##func)
39 #define LEMON_lpx(func) (lpx_##func)
41 #define LEMON_GLP(def) (LPX_##def)
42 #define LEMON_LPX(def) (LPX_##def)
48 LpGlpk::LpGlpk() : Parent() {
50 rows = _lp_bits::LpId(1);
51 cols = _lp_bits::LpId(1);
52 lp = LEMON_glp(create_prob)();
53 LEMON_glp(create_index)(lp);
57 LpGlpk::LpGlpk(const LpGlpk &glp) : Parent() {
59 rows = _lp_bits::LpId(1);
60 cols = _lp_bits::LpId(1);
61 lp = LEMON_glp(create_prob)();
62 LEMON_glp(create_index)(lp);
64 //Coefficient matrix, row bounds
65 LEMON_glp(add_rows)(lp, LEMON_glp(get_num_rows)(glp.lp));
66 LEMON_glp(add_cols)(lp, LEMON_glp(get_num_cols)(glp.lp));
68 std::vector<int> ind(1+LEMON_glp(get_num_cols)(glp.lp));
69 std::vector<Value> val(1+LEMON_glp(get_num_cols)(glp.lp));
70 for (int i=1;i<=LEMON_glp(get_num_rows)(glp.lp);++i)
72 len=LEMON_glp(get_mat_row)(glp.lp,i,&*ind.begin(),&*val.begin());
73 LEMON_glp(set_mat_row)(lp, i,len,&*ind.begin(),&*val.begin());
74 LEMON_glp(set_row_bnds)(lp,i,
75 LEMON_glp(get_row_type)(glp.lp,i),
76 LEMON_glp(get_row_lb)(glp.lp,i),
77 LEMON_glp(get_row_ub)(glp.lp,i));
80 //Objective function, coloumn bounds
81 LEMON_glp(set_obj_dir)(lp, LEMON_glp(get_obj_dir)(glp.lp));
82 //Objectif function's constant term treated separately
83 LEMON_glp(set_obj_coef)(lp,0,LEMON_glp(get_obj_coef)(glp.lp,0));
84 for (int i=1;i<=LEMON_glp(get_num_cols)(glp.lp);++i)
86 LEMON_glp(set_obj_coef)(lp,i,
87 LEMON_glp(get_obj_coef)(glp.lp,i));
88 LEMON_glp(set_col_bnds)(lp,i,
89 LEMON_glp(get_col_type)(glp.lp,i),
90 LEMON_glp(get_col_lb)(glp.lp,i),
91 LEMON_glp(get_col_ub)(glp.lp,i));
98 LEMON_glp(delete_prob)(lp);
101 int LpGlpk::_addCol() {
102 int i=LEMON_glp(add_cols)(lp, 1);
103 LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FR), 0.0, 0.0);
111 LpSolverBase* LpGlpk::_newLp()
113 LpGlpk* newlp = new LpGlpk;
119 LpSolverBase* LpGlpk::_copyLp()
121 LpGlpk *newlp = new LpGlpk(*this);
125 int LpGlpk::_addRow() {
126 int i=LEMON_glp(add_rows)(lp, 1);
132 void LpGlpk::_eraseCol(int i) {
135 LEMON_glp(del_cols)(lp, 1, ca);
139 void LpGlpk::_eraseRow(int i) {
142 LEMON_glp(del_rows)(lp, 1, ra);
146 void LpGlpk::_getColName(int c, std::string & name) const
149 const char *n = LEMON_glp(get_col_name)(lp,c);
154 void LpGlpk::_setColName(int c, const std::string & name)
156 LEMON_glp(set_col_name)(lp,c,const_cast<char*>(name.c_str()));
160 int LpGlpk::_colByName(const std::string& name) const
162 int k = LEMON_glp(find_col)(lp, const_cast<char*>(name.c_str()));
163 return k > 0 ? k : -1;
167 void LpGlpk::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e)
169 std::vector<int> indices;
170 std::vector<Value> values;
172 indices.push_back(0);
175 for(ConstRowIterator it=b; it!=e; ++it) {
176 indices.push_back(it->first);
177 values.push_back(it->second);
180 LEMON_glp(set_mat_row)(lp, i, values.size() - 1,
181 &indices[0], &values[0]);
186 void LpGlpk::_getRowCoeffs(int ix, RowIterator b) const
188 int length = LEMON_glp(get_mat_row)(lp, ix, 0, 0);
190 std::vector<int> indices(length + 1);
191 std::vector<Value> values(length + 1);
193 LEMON_glp(get_mat_row)(lp, ix, &indices[0], &values[0]);
195 for (int i = 1; i <= length; ++i) {
196 *b = std::make_pair(indices[i], values[i]);
201 void LpGlpk::_setColCoeffs(int ix, ConstColIterator b, ConstColIterator e) {
203 std::vector<int> indices;
204 std::vector<Value> values;
206 indices.push_back(0);
209 for(ConstColIterator it=b; it!=e; ++it) {
210 indices.push_back(it->first);
211 values.push_back(it->second);
214 LEMON_glp(set_mat_col)(lp, ix, values.size() - 1,
215 &indices[0], &values[0]);
220 void LpGlpk::_getColCoeffs(int ix, ColIterator b) const
222 int length = LEMON_glp(get_mat_col)(lp, ix, 0, 0);
224 std::vector<int> indices(length + 1);
225 std::vector<Value> values(length + 1);
227 LEMON_glp(get_mat_col)(lp, ix, &indices[0], &values[0]);
229 for (int i = 1; i <= length; ++i) {
230 *b = std::make_pair(indices[i], values[i]);
235 void LpGlpk::_setCoeff(int ix, int jx, Value value)
238 if (LEMON_glp(get_num_cols)(lp) < LEMON_glp(get_num_rows)(lp)) {
240 int length=LEMON_glp(get_mat_row)(lp, ix, 0, 0);
242 std::vector<int> indices(length + 2);
243 std::vector<Value> values(length + 2);
245 LEMON_glp(get_mat_row)(lp, ix, &indices[0], &values[0]);
247 //The following code does not suppose that the elements of the
248 //array indices are sorted
250 for (int i = 1; i <= length; ++i) {
260 values[length]=value;
263 LEMON_glp(set_mat_row)(lp, ix, length, &indices[0], &values[0]);
267 int length=LEMON_glp(get_mat_col)(lp, jx, 0, 0);
269 std::vector<int> indices(length + 2);
270 std::vector<Value> values(length + 2);
272 LEMON_glp(get_mat_col)(lp, jx, &indices[0], &values[0]);
274 //The following code does not suppose that the elements of the
275 //array indices are sorted
277 for (int i = 1; i <= length; ++i) {
287 values[length]=value;
290 LEMON_glp(set_mat_col)(lp, jx, length, &indices[0], &values[0]);
296 LpGlpk::Value LpGlpk::_getCoeff(int ix, int jx) const
299 int length=LEMON_glp(get_mat_row)(lp, ix, 0, 0);
301 std::vector<int> indices(length + 1);
302 std::vector<Value> values(length + 1);
304 LEMON_glp(get_mat_row)(lp, ix, &indices[0], &values[0]);
306 //The following code does not suppose that the elements of the
307 //array indices are sorted
308 for (int i = 1; i <= length; ++i) {
318 void LpGlpk::_setColLowerBound(int i, Value lo)
323 int b=LEMON_glp(get_col_type)(lp, i);
324 double up=LEMON_glp(get_col_ub)(lp, i);
329 LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FR), lo, up);
335 LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(UP), lo, up);
344 LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(LO), lo, up);
350 LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FX), lo, up);
352 LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(DB), lo, up);
362 LpGlpk::Value LpGlpk::_getColLowerBound(int i) const
364 int b=LEMON_glp(get_col_type)(lp, i);
369 return LEMON_glp(get_col_lb)(lp, i);
375 void LpGlpk::_setColUpperBound(int i, Value up)
380 int b=LEMON_glp(get_col_type)(lp, i);
381 double lo=LEMON_glp(get_col_lb)(lp, i);
388 LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FR), lo, up);
392 LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(LO), lo, up);
400 LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(UP), lo, up);
403 LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(UP), lo, up);
409 LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FX), lo, up);
411 LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(DB), lo, up);
421 LpGlpk::Value LpGlpk::_getColUpperBound(int i) const
423 int b=LEMON_glp(get_col_type)(lp, i);
428 return LEMON_glp(get_col_ub)(lp, i);
434 void LpGlpk::_setRowBounds(int i, Value lb, Value ub)
437 if (lb==INF || ub==-INF) {
443 LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(FR), lb, ub);
446 LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(UP), lb, ub);
451 LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(LO), lb, ub);
456 LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(FX), lb, ub);
459 LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(DB), lb, ub);
467 void LpGlpk::_getRowBounds(int i, Value &lb, Value &ub) const
470 int b=LEMON_glp(get_row_type)(lp, i);
477 lb=LEMON_glp(get_row_lb)(lp, i);
486 ub=LEMON_glp(get_row_ub)(lp, i);
491 void LpGlpk::_setObjCoeff(int i, Value obj_coef)
493 //i=0 means the constant term (shift)
494 LEMON_glp(set_obj_coef)(lp, i, obj_coef);
499 LpGlpk::Value LpGlpk::_getObjCoeff(int i) const {
500 //i=0 means the constant term (shift)
501 return LEMON_glp(get_obj_coef)(lp, i);
504 void LpGlpk::_clearObj()
506 for (int i=0;i<=LEMON_glp(get_num_cols)(lp);++i){
507 LEMON_glp(set_obj_coef)(lp, i, 0);
513 LpGlpk::SolveExitStatus LpGlpk::_solve()
515 // A way to check the problem to be solved
516 //LEMON_glp(write_cpxlp(lp,"naittvan.cpx");
518 LEMON_lpx(std_basis)(lp);
519 int i = LEMON_lpx(simplex)(lp);
522 case LEMON_LPX(E_OK):
530 LpGlpk::Value LpGlpk::_getPrimal(int i) const
532 return LEMON_glp(get_col_prim)(lp,i);
535 LpGlpk::Value LpGlpk::_getDual(int i) const
537 return LEMON_glp(get_row_dual)(lp,i);
540 LpGlpk::Value LpGlpk::_getPrimalValue() const
542 return LEMON_glp(get_obj_val)(lp);
544 bool LpGlpk::_isBasicCol(int i) const
546 return (LEMON_glp(get_col_stat)(lp, i)==LEMON_GLP(BS));
550 LpGlpk::SolutionStatus LpGlpk::_getPrimalStatus() const
552 if (!solved) return UNDEFINED;
553 int stat= LEMON_lpx(get_status)(lp);
555 case LEMON_LPX(UNDEF)://Undefined (no solve has been run yet)
557 case LEMON_LPX(NOFEAS)://There is no feasible solution (primal, I guess)
558 case LEMON_LPX(INFEAS)://Infeasible
560 case LEMON_LPX(UNBND)://Unbounded
562 case LEMON_LPX(FEAS)://Feasible
564 case LEMON_LPX(OPT)://Feasible
567 return UNDEFINED; //to avoid gcc warning
572 LpGlpk::SolutionStatus LpGlpk::_getDualStatus() const
574 if (!solved) return UNDEFINED;
575 switch (LEMON_lpx(get_dual_stat)(lp)) {
576 case LEMON_LPX(D_UNDEF)://Undefined (no solve has been run yet)
578 case LEMON_LPX(D_NOFEAS)://There is no dual feasible solution
579 // case LEMON_LPX(D_INFEAS://Infeasible
581 case LEMON_LPX(D_FEAS)://Feasible
582 switch (LEMON_lpx(get_status)(lp)) {
583 case LEMON_LPX(NOFEAS):
591 return UNDEFINED; //to avoid gcc warning
596 LpGlpk::ProblemTypes LpGlpk::_getProblemType() const
598 if (!solved) return UNKNOWN;
599 //int stat= LEMON_glp(get_status(lp);
600 int statp= LEMON_lpx(get_prim_stat)(lp);
601 int statd= LEMON_lpx(get_dual_stat)(lp);
602 if (statp==LEMON_LPX(P_FEAS) && statd==LEMON_LPX(D_FEAS))
603 return PRIMAL_DUAL_FEASIBLE;
604 if (statp==LEMON_LPX(P_FEAS) && statd==LEMON_LPX(D_NOFEAS))
605 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
606 if (statp==LEMON_LPX(P_NOFEAS) && statd==LEMON_LPX(D_FEAS))
607 return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
608 if (statp==LEMON_LPX(P_NOFEAS) && statd==LEMON_LPX(D_NOFEAS))
609 return PRIMAL_DUAL_INFEASIBLE;
614 void LpGlpk::_setMax()
617 LEMON_glp(set_obj_dir)(lp, LEMON_GLP(MAX));
620 void LpGlpk::_setMin()
623 LEMON_glp(set_obj_dir)(lp, LEMON_GLP(MIN));
626 bool LpGlpk::_isMax() const
628 return (LEMON_glp(get_obj_dir)(lp)==LEMON_GLP(MAX));
633 void LpGlpk::messageLevel(int m)
635 LEMON_lpx(set_int_parm)(lp, LEMON_LPX(K_MSGLEV), m);
638 void LpGlpk::presolver(bool b)
640 LEMON_lpx(set_int_parm)(lp, LEMON_LPX(K_PRESOL), b);
644 } //END OF NAMESPACE LEMON