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