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>
25 #if GLP_MAJOR_VERSION > 4 || (GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION > 15)
26 #define LEMON_glp(func) (glp_##func)
27 #define LEMON_lpx(func) (lpx_##func)
29 #define LEMON_GLP(def) (GLP_##def)
30 #define LEMON_LPX(def) (LPX_##def)
34 #define LEMON_glp(func) (lpx_##func)
35 #define LEMON_lpx(func) (lpx_##func)
37 #define LEMON_GLP(def) (LPX_##def)
38 #define LEMON_LPX(def) (LPX_##def)
44 LpGlpk::LpGlpk() : Parent() {
46 rows = _lp_bits::LpId(1);
47 cols = _lp_bits::LpId(1);
48 lp = LEMON_glp(create_prob)();
49 LEMON_glp(create_index)(lp);
50 LEMON_lpx(set_int_parm)(lp, LEMON_LPX(K_DUAL), 1);
54 LpGlpk::LpGlpk(const LpGlpk &glp) : Parent() {
56 rows = _lp_bits::LpId(1);
57 cols = _lp_bits::LpId(1);
58 lp = LEMON_glp(create_prob)();
59 LEMON_glp(create_index)(lp);
60 ///\todo control function for this:
61 LEMON_lpx(set_int_parm)(lp, LEMON_LPX(K_DUAL), 1);
63 //Coefficient matrix, row bounds
64 LEMON_glp(add_rows)(lp, LEMON_glp(get_num_rows)(glp.lp));
65 LEMON_glp(add_cols)(lp, LEMON_glp(get_num_cols)(glp.lp));
67 std::vector<int> ind(1+LEMON_glp(get_num_cols)(glp.lp));
68 std::vector<Value> val(1+LEMON_glp(get_num_cols)(glp.lp));
69 for (int i=1;i<=LEMON_glp(get_num_rows)(glp.lp);++i)
71 len=LEMON_glp(get_mat_row)(glp.lp,i,&*ind.begin(),&*val.begin());
72 LEMON_glp(set_mat_row)(lp, i,len,&*ind.begin(),&*val.begin());
73 LEMON_glp(set_row_bnds)(lp,i,
74 LEMON_glp(get_row_type)(glp.lp,i),
75 LEMON_glp(get_row_lb)(glp.lp,i),
76 LEMON_glp(get_row_ub)(glp.lp,i));
79 //Objective function, coloumn bounds
80 LEMON_glp(set_obj_dir)(lp, LEMON_glp(get_obj_dir)(glp.lp));
81 //Objectif function's constant term treated separately
82 LEMON_glp(set_obj_coef)(lp,0,LEMON_glp(get_obj_coef)(glp.lp,0));
83 for (int i=1;i<=LEMON_glp(get_num_cols)(glp.lp);++i)
85 LEMON_glp(set_obj_coef)(lp,i,
86 LEMON_glp(get_obj_coef)(glp.lp,i));
87 LEMON_glp(set_col_bnds)(lp,i,
88 LEMON_glp(get_col_type)(glp.lp,i),
89 LEMON_glp(get_col_lb)(glp.lp,i),
90 LEMON_glp(get_col_ub)(glp.lp,i));
97 LEMON_glp(delete_prob)(lp);
100 int LpGlpk::_addCol() {
101 int i=LEMON_glp(add_cols)(lp, 1);
102 LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FR), 0.0, 0.0);
110 LpSolverBase* LpGlpk::_newLp()
112 LpGlpk* newlp = new LpGlpk;
118 LpSolverBase* LpGlpk::_copyLp()
120 LpGlpk *newlp = new LpGlpk(*this);
124 int LpGlpk::_addRow() {
125 int i=LEMON_glp(add_rows)(lp, 1);
131 void LpGlpk::_eraseCol(int i) {
134 LEMON_glp(del_cols)(lp, 1, ca);
138 void LpGlpk::_eraseRow(int i) {
141 LEMON_glp(del_rows)(lp, 1, ra);
145 void LpGlpk::_getColName(int c, std::string & name) const
148 const char *n = LEMON_glp(get_col_name)(lp,c);
153 void LpGlpk::_setColName(int c, const std::string & name)
155 LEMON_glp(set_col_name)(lp,c,const_cast<char*>(name.c_str()));
159 int LpGlpk::_colByName(const std::string& name) const
161 int k = LEMON_glp(find_col)(lp, const_cast<char*>(name.c_str()));
162 return k > 0 ? k : -1;
166 void LpGlpk::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e)
168 std::vector<int> indices;
169 std::vector<Value> values;
171 indices.push_back(0);
174 for(ConstRowIterator it=b; it!=e; ++it) {
175 indices.push_back(it->first);
176 values.push_back(it->second);
179 LEMON_glp(set_mat_row)(lp, i, values.size() - 1,
180 &indices[0], &values[0]);
185 void LpGlpk::_getRowCoeffs(int ix, RowIterator b) const
187 int length = LEMON_glp(get_mat_row)(lp, ix, 0, 0);
189 std::vector<int> indices(length + 1);
190 std::vector<Value> values(length + 1);
192 LEMON_glp(get_mat_row)(lp, ix, &indices[0], &values[0]);
194 for (int i = 1; i <= length; ++i) {
195 *b = std::make_pair(indices[i], values[i]);
200 void LpGlpk::_setColCoeffs(int ix, ConstColIterator b, ConstColIterator e) {
202 std::vector<int> indices;
203 std::vector<Value> values;
205 indices.push_back(0);
208 for(ConstColIterator it=b; it!=e; ++it) {
209 indices.push_back(it->first);
210 values.push_back(it->second);
213 LEMON_glp(set_mat_col)(lp, ix, values.size() - 1,
214 &indices[0], &values[0]);
219 void LpGlpk::_getColCoeffs(int ix, ColIterator b) const
221 int length = LEMON_glp(get_mat_col)(lp, ix, 0, 0);
223 std::vector<int> indices(length + 1);
224 std::vector<Value> values(length + 1);
226 LEMON_glp(get_mat_col)(lp, ix, &indices[0], &values[0]);
228 for (int i = 1; i <= length; ++i) {
229 *b = std::make_pair(indices[i], values[i]);
234 void LpGlpk::_setCoeff(int ix, int jx, Value value)
237 if (LEMON_glp(get_num_cols)(lp) < LEMON_glp(get_num_rows)(lp)) {
239 int length=LEMON_glp(get_mat_row)(lp, ix, 0, 0);
241 std::vector<int> indices(length + 2);
242 std::vector<Value> values(length + 2);
244 LEMON_glp(get_mat_row)(lp, ix, &indices[0], &values[0]);
246 //The following code does not suppose that the elements of the
247 //array indices are sorted
249 for (int i = 1; i <= length; ++i) {
259 values[length]=value;
262 LEMON_glp(set_mat_row)(lp, ix, length, &indices[0], &values[0]);
266 int length=LEMON_glp(get_mat_col)(lp, jx, 0, 0);
268 std::vector<int> indices(length + 2);
269 std::vector<Value> values(length + 2);
271 LEMON_glp(get_mat_col)(lp, jx, &indices[0], &values[0]);
273 //The following code does not suppose that the elements of the
274 //array indices are sorted
276 for (int i = 1; i <= length; ++i) {
286 values[length]=value;
289 LEMON_glp(set_mat_col)(lp, jx, length, &indices[0], &values[0]);
295 LpGlpk::Value LpGlpk::_getCoeff(int ix, int jx) const
298 int length=LEMON_glp(get_mat_row)(lp, ix, 0, 0);
300 std::vector<int> indices(length + 1);
301 std::vector<Value> values(length + 1);
303 LEMON_glp(get_mat_row)(lp, ix, &indices[0], &values[0]);
305 //The following code does not suppose that the elements of the
306 //array indices are sorted
307 for (int i = 1; i <= length; ++i) {
317 void LpGlpk::_setColLowerBound(int i, Value lo)
322 int b=LEMON_glp(get_col_type)(lp, i);
323 double up=LEMON_glp(get_col_ub)(lp, i);
328 LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FR), lo, up);
334 LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(UP), lo, up);
343 LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(LO), lo, up);
349 LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FX), lo, up);
351 LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(DB), lo, up);
361 LpGlpk::Value LpGlpk::_getColLowerBound(int i) const
363 int b=LEMON_glp(get_col_type)(lp, i);
368 return LEMON_glp(get_col_lb)(lp, i);
374 void LpGlpk::_setColUpperBound(int i, Value up)
379 int b=LEMON_glp(get_col_type)(lp, i);
380 double lo=LEMON_glp(get_col_lb)(lp, i);
387 LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FR), lo, up);
391 LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(LO), lo, up);
399 LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(UP), lo, up);
402 LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(UP), lo, up);
408 LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FX), lo, up);
410 LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(DB), lo, up);
420 LpGlpk::Value LpGlpk::_getColUpperBound(int i) const
422 int b=LEMON_glp(get_col_type)(lp, i);
427 return LEMON_glp(get_col_ub)(lp, i);
433 void LpGlpk::_setRowBounds(int i, Value lb, Value ub)
436 if (lb==INF || ub==-INF) {
442 LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(FR), lb, ub);
445 LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(UP), lb, ub);
450 LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(LO), lb, ub);
455 LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(FX), lb, ub);
458 LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(DB), lb, ub);
466 void LpGlpk::_getRowBounds(int i, Value &lb, Value &ub) const
469 int b=LEMON_glp(get_row_type)(lp, i);
476 lb=LEMON_glp(get_row_lb)(lp, i);
485 ub=LEMON_glp(get_row_ub)(lp, i);
490 void LpGlpk::_setObjCoeff(int i, Value obj_coef)
492 //i=0 means the constant term (shift)
493 LEMON_glp(set_obj_coef)(lp, i, obj_coef);
498 LpGlpk::Value LpGlpk::_getObjCoeff(int i) const {
499 //i=0 means the constant term (shift)
500 return LEMON_glp(get_obj_coef)(lp, i);
503 void LpGlpk::_clearObj()
505 for (int i=0;i<=LEMON_glp(get_num_cols)(lp);++i){
506 LEMON_glp(set_obj_coef)(lp, i, 0);
512 LpGlpk::SolveExitStatus LpGlpk::_solve()
514 // A way to check the problem to be solved
515 //LEMON_glp(write_cpxlp(lp,"naittvan.cpx");
517 LEMON_lpx(std_basis)(lp);
518 int i = LEMON_lpx(simplex)(lp);
521 case LEMON_LPX(E_OK):
529 LpGlpk::Value LpGlpk::_getPrimal(int i) const
531 return LEMON_glp(get_col_prim)(lp,i);
534 LpGlpk::Value LpGlpk::_getDual(int i) const
536 return LEMON_glp(get_row_dual)(lp,i);
539 LpGlpk::Value LpGlpk::_getPrimalValue() const
541 return LEMON_glp(get_obj_val)(lp);
543 bool LpGlpk::_isBasicCol(int i) const
545 return (LEMON_glp(get_col_stat)(lp, i)==LEMON_GLP(BS));
549 LpGlpk::SolutionStatus LpGlpk::_getPrimalStatus() const
551 if (!solved) return UNDEFINED;
552 int stat= LEMON_lpx(get_status)(lp);
554 case LEMON_LPX(UNDEF)://Undefined (no solve has been run yet)
556 case LEMON_LPX(NOFEAS)://There is no feasible solution (primal, I guess)
557 case LEMON_LPX(INFEAS)://Infeasible
559 case LEMON_LPX(UNBND)://Unbounded
561 case LEMON_LPX(FEAS)://Feasible
563 case LEMON_LPX(OPT)://Feasible
566 return UNDEFINED; //to avoid gcc warning
571 LpGlpk::SolutionStatus LpGlpk::_getDualStatus() const
573 if (!solved) return UNDEFINED;
574 switch (LEMON_lpx(get_dual_stat)(lp)) {
575 case LEMON_LPX(D_UNDEF)://Undefined (no solve has been run yet)
577 case LEMON_LPX(D_NOFEAS)://There is no dual feasible solution
578 // case LEMON_LPX(D_INFEAS://Infeasible
580 case LEMON_LPX(D_FEAS)://Feasible
581 switch (LEMON_lpx(get_status)(lp)) {
582 case LEMON_LPX(NOFEAS):
590 return UNDEFINED; //to avoid gcc warning
595 LpGlpk::ProblemTypes LpGlpk::_getProblemType() const
597 if (!solved) return UNKNOWN;
598 //int stat= LEMON_glp(get_status(lp);
599 int statp= LEMON_lpx(get_prim_stat)(lp);
600 int statd= LEMON_lpx(get_dual_stat)(lp);
601 if (statp==LEMON_LPX(P_FEAS) && statd==LEMON_LPX(D_FEAS))
602 return PRIMAL_DUAL_FEASIBLE;
603 if (statp==LEMON_LPX(P_FEAS) && statd==LEMON_LPX(D_NOFEAS))
604 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
605 if (statp==LEMON_LPX(P_NOFEAS) && statd==LEMON_LPX(D_FEAS))
606 return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
607 if (statp==LEMON_LPX(P_NOFEAS) && statd==LEMON_LPX(D_NOFEAS))
608 return PRIMAL_DUAL_INFEASIBLE;
613 void LpGlpk::_setMax()
616 LEMON_glp(set_obj_dir)(lp, LEMON_GLP(MAX));
619 void LpGlpk::_setMin()
622 LEMON_glp(set_obj_dir)(lp, LEMON_GLP(MIN));
625 bool LpGlpk::_isMax() const
627 return (LEMON_glp(get_obj_dir)(lp)==LEMON_GLP(MAX));
632 void LpGlpk::messageLevel(int m)
634 LEMON_lpx(set_int_parm)(lp, LEMON_LPX(K_MSGLEV), m);
637 void LpGlpk::presolver(bool b)
639 LEMON_lpx(set_int_parm)(lp, LEMON_LPX(K_PRESOL), b);
643 } //END OF NAMESPACE LEMON