deba@458: /* -*- mode: C++; indent-tabs-mode: nil; -*- deba@458: * deba@458: * This file is a part of LEMON, a generic C++ optimization library. deba@458: * deba@458: * Copyright (C) 2003-2008 deba@458: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport deba@458: * (Egervary Research Group on Combinatorial Optimization, EGRES). deba@458: * deba@458: * Permission to use, modify and distribute this software is granted deba@458: * provided that this copyright notice appears in all copies. For deba@458: * precise terms see the accompanying LICENSE file. deba@458: * deba@458: * This software is provided "AS IS" with no warranty of any kind, deba@458: * express or implied, and with no claim as to its suitability for any deba@458: * purpose. deba@458: * deba@458: */ deba@458: deba@458: ///\file deba@458: ///\brief Implementation of the LEMON-GLPK mip solver interface. deba@458: deba@458: #include deba@458: deba@458: extern "C" { deba@458: #include deba@458: } deba@458: deba@458: #if GLP_MAJOR_VERSION > 4 || (GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION > 15) deba@458: #define LEMON_glp(func) (glp_##func) deba@458: #define LEMON_lpx(func) (lpx_##func) deba@458: deba@458: #define LEMON_GLP(def) (GLP_##def) deba@458: #define LEMON_LPX(def) (LPX_##def) deba@458: deba@458: #else deba@458: deba@458: #define LEMON_glp(func) (lpx_##func) deba@458: #define LEMON_lpx(func) (lpx_##func) deba@458: deba@458: #define LEMON_GLP(def) (LPX_##def) deba@458: #define LEMON_LPX(def) (LPX_##def) deba@458: deba@458: #endif deba@458: deba@458: namespace lemon { deba@458: deba@458: MipGlpk::MipGlpk() { deba@458: #if !(GLP_MAJOR_VERSION > 4 || \ deba@458: (GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION > 15)) deba@458: LEMON_lpx(set_class)(lp,LEMON_GLP(MIP)); deba@458: #endif deba@458: } deba@458: deba@458: void MipGlpk::_colType(int i, MipGlpk::ColTypes col_type){ deba@458: switch (col_type){ deba@458: case INT: deba@458: LEMON_glp(set_col_kind)(lp,i,LEMON_GLP(IV)); deba@458: break; deba@458: case REAL: deba@458: LEMON_glp(set_col_kind)(lp,i,LEMON_GLP(CV)); deba@458: break; deba@458: default:; deba@458: //FIXME problem deba@458: } deba@458: } deba@458: deba@458: MipGlpk::ColTypes MipGlpk::_colType(int i) const { deba@458: switch (LEMON_glp(get_col_kind)(lp,i)){ deba@458: case LEMON_GLP(IV): deba@458: return INT;//Or binary deba@458: case LEMON_GLP(CV): deba@458: return REAL; deba@458: default: deba@458: return REAL;//Error! deba@458: } deba@458: deba@458: } deba@458: deba@458: LpGlpk::SolveExitStatus MipGlpk::_solve() { deba@458: int result = LEMON_lpx(simplex)(lp); deba@458: deba@458: // hack: mip does not contain integer variable deba@458: #if GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION == 16 deba@458: int tmp = -1; deba@458: if (LEMON_glp(get_num_int(lp)) == 0) { deba@458: tmp = LEMON_lpx(add_cols)(lp, 1); deba@458: LEMON_glp(set_col_bnds)(lp, tmp, LEMON_GLP(FX), 0.0, 0.0); deba@458: LEMON_glp(set_col_kind)(lp, tmp, LEMON_GLP(IV)); deba@458: } deba@458: #endif deba@458: deba@458: if (LEMON_lpx(get_status)(lp)==LEMON_LPX(OPT)) { deba@458: //Maybe we could try the routine lpx_intopt(lp), a revised deba@458: //version of lpx_integer deba@458: deba@458: result = LEMON_lpx(integer)(lp); deba@458: switch (result){ deba@458: case LEMON_LPX(E_OK): deba@458: solved = true; deba@458: break; deba@458: default: deba@458: solved = false; deba@458: } deba@458: } else { deba@458: solved = false; deba@458: } deba@458: #if GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION == 16 deba@458: if (tmp != -1) { deba@458: int tmpa[2]; deba@458: tmpa[1] = tmp; deba@458: LEMON_lpx(del_cols)(lp, 1, tmpa); deba@458: } deba@458: #endif deba@458: return solved ? SOLVED : UNSOLVED; deba@458: } deba@458: deba@458: deba@458: LpGlpk::SolutionStatus MipGlpk::_getMipStatus() const { deba@458: deba@458: if (LEMON_lpx(get_status)(lp)==LEMON_LPX(OPT)){ deba@458: //Meg kell nezni: ha az LP is infinite, akkor ez is, ha az is deba@458: //infeasible, akkor ez is, de ez lehet maskepp is infeasible. deba@458: int stat= LEMON_lpx(mip_status)(lp); deba@458: deba@458: switch (stat) { deba@458: case LEMON_LPX(I_UNDEF)://Undefined (no solve has been run yet) deba@458: return UNDEFINED; deba@458: case LEMON_LPX(I_NOFEAS)://There is no feasible integral solution deba@458: return INFEASIBLE; deba@458: // case LEMON_LPX(UNBND)://Unbounded deba@458: // return INFINITE; deba@458: case LEMON_LPX(I_FEAS)://Feasible deba@458: return FEASIBLE; deba@458: case LEMON_LPX(I_OPT)://Feasible deba@458: return OPTIMAL; deba@458: default: deba@458: return UNDEFINED; //to avoid gcc warning deba@458: //FIXME error deba@458: } deba@458: } deba@458: else deba@458: return UNDEFINED; //Maybe we could refine this: what does the LP deba@458: //relaxation look like deba@458: deba@458: } deba@458: deba@458: MipGlpk::Value MipGlpk::_getPrimal(int i) const { deba@458: return LEMON_glp(mip_col_val)(lp,i); deba@458: } deba@458: deba@458: MipGlpk::Value MipGlpk::_getPrimalValue() const { deba@458: return LEMON_glp(mip_obj_val)(lp); deba@458: } deba@458: } //END OF NAMESPACE LEMON