lpsolver.h
Go to the documentation of this file.
00001 /*************************************************************************** 00002 file : $URL: http://svn.code.sf.net/p/frepple/code/trunk/modules/lp_solver/lpsolver.h $ 00003 version : $LastChangedRevision: 1715 $ $LastChangedBy: jdetaeye $ 00004 date : $LastChangedDate: 2012-07-19 21:37:46 +0200 (Thu, 19 Jul 2012) $ 00005 ***************************************************************************/ 00006 00007 /*************************************************************************** 00008 * * 00009 * Copyright (C) 2007-2012 by Johan De Taeye, frePPLe bvba * 00010 * * 00011 * This library is free software; you can redistribute it and/or modify it * 00012 * under the terms of the GNU Affero General Public License as published * 00013 * by the Free Software Foundation; either version 3 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 * This library is distributed in the hope that it will be useful, * 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00019 * GNU Affero General Public License for more details. * 00020 * * 00021 * You should have received a copy of the GNU Affero General Public * 00022 * License along with this program. * 00023 * If not, see <http://www.gnu.org/licenses/>. * 00024 * * 00025 ***************************************************************************/ 00026 00027 /** @file lpsolver.h 00028 * @brief Header file for the module lp_solver. 00029 * 00030 * @namespace module_lp_solver 00031 * @brief A solver module based on a linear programming algorithm. 00032 * 00033 * The solver is intended primarly for prototyping purposes. Cleaner and 00034 * more performant alternatives are recommended for real production use. 00035 * 00036 * The module uses the "Gnu Linear Programming Kit" library (aka GLPK) to 00037 * solve the LP model.<br> 00038 * The solver works as follows: 00039 * - The solver expects a <b>model file</b> and a <b>data file</b> as input.<br> 00040 * The model file represents the mathematical representation of the 00041 * problem to solve.<br> 00042 * The data file holds the data to be loaded into the problem. If no 00043 * data file is specified, the data section in the model file is used 00044 * instead.<br> 00045 * The user is responsible for creating these files. See the unit test 00046 * lp_solver1 for an example. 00047 * - The solver solves for a number of objectives in sequence.<br> 00048 * After solving an objective's optimal value, the solver freezes the 00049 * value as a constraint and start for the next objective. Subsequent 00050 * objectives can thus never yield a solution that is suboptimal for the 00051 * previous objectives. 00052 * - After solving for all objectives the solution is written to a solution 00053 * file.<br> 00054 * The user is responsible for all processing of this solution file. 00055 * 00056 * The XML schema extension enabled by this module is (see mod_lpsolver.xsd): 00057 * <PRE> 00058 * <xsd:complexType name="solver_lp"> 00059 * <xsd:complexContent> 00060 * <xsd:extension base="solver"> 00061 * <xsd:choice minOccurs="0" maxOccurs="unbounded"> 00062 * <xsd:element name="loglevel" type="loglevel" /> 00063 * <xsd:element name="minimum" type="xsd:boolean" /> 00064 * <xsd:element name="modelfile" type="xsd:normalizedString" /> 00065 * <xsd:element name="datafile" type="xsd:normalizedString" /> 00066 * <xsd:element name="solutionfile" type="xsd:normalizedString" /> 00067 * <xsd:element name="objective" type="xsd:normalizedString" /> 00068 * </xsd:choice> 00069 * <xsd:attribute name="loglevel" type="loglevel" /> 00070 * <xsd:attribute name="minimum" type="xsd:boolean" /> 00071 * <xsd:attribute name="modelfile" type="xsd:normalizedString" /> 00072 * <xsd:attribute name="datafile" type="xsd:normalizedString" /> 00073 * <xsd:attribute name="solutionfile" type="xsd:normalizedString" /> 00074 * <xsd:attribute name="objective" type="xsd:normalizedString" /> 00075 * </xsd:extension> 00076 * </xsd:complexContent> 00077 * </xsd:complexType> 00078 * </PRE> 00079 */ 00080 00081 #include "frepple.h" 00082 using namespace frepple; 00083 00084 extern "C" 00085 { 00086 #if defined HAVE_GLPK_H || !defined HAVE_GLPK_GLPK_H 00087 #include "glpk.h" 00088 #else 00089 #ifdef HAVE_GLPK_GLPK_H 00090 #include "glpk/glpk.h" 00091 #endif 00092 #endif 00093 } 00094 00095 namespace module_lp_solver 00096 { 00097 00098 /** Initialization routine for the library. */ 00099 MODULE_EXPORT const char* initialize(const Environment::ParameterList& z); 00100 00101 /** @brief This class is a prototype of an Linear Programming (LP) Solver for 00102 * the planning problem or a subset of it. 00103 * 00104 * The solver is intended primarly for prototyping purposes. Cleaner and 00105 * more performant alternatives are recommended for real production use. 00106 */ 00107 class LPSolver : public Solver 00108 { 00109 public: 00110 /** This method creates a new column in the model for every demand. It's 00111 * value represents the planned quantity of that demand. 00112 * @exception DataException Generated when no calendar has been specified. 00113 */ 00114 void solve(void* = NULL); 00115 00116 /** Return the name of the GNU MathProg model file. */ 00117 string getModelFile() const {return modelfilename;} 00118 00119 /** Update the name of the GNU MathProg model file. */ 00120 void setModelFile(const string& c) {modelfilename = c;} 00121 00122 /** Return the name of the GNU MathProg data file. */ 00123 string getDataFile() const {return datafilename;} 00124 00125 /** Update the name of the GNU MathProg data file. */ 00126 void setDataFile(const string& c) {datafilename = c;} 00127 00128 /** Return the name of the solution file. */ 00129 string getSolutionFile() const {return solutionfilename;} 00130 00131 /** Update the name of the solution file. <br> 00132 * After running the solver the solution is written to this flat file. 00133 */ 00134 void setSolutionFile(const string& c) {solutionfilename = c;} 00135 00136 /** Returns true when the solver needs to minimize the objective(s).<br> 00137 * Returns false when the solver needs to maximize the objective(s). 00138 */ 00139 bool getMinimum() const {return minimum;} 00140 00141 /** Update the solver direction: minimization or maximization. */ 00142 void setMinimum(bool m) {minimum = m;} 00143 00144 /** Append a new objective to the list. */ 00145 void addObjective(const string& c) {objectives.push_back(c);} 00146 00147 /** Return a reference to the list of objectives. */ 00148 const list<string>& getObjectives() const {return objectives;} 00149 00150 virtual void writeElement(XMLOutput*, const Keyword&, mode=DEFAULT) const; 00151 void endElement(XMLInput& pIn, const Attribute& pAttr, const DataElement& pElement); 00152 virtual PyObject* getattro(const Attribute&); 00153 virtual int setattro(const Attribute&, const PythonObject&); 00154 static int initialize(); 00155 00156 /** Constructor. */ 00157 LPSolver(const string& n) : Solver(n), minimum(true) {initType(metadata);} 00158 00159 /** Destructor. */ 00160 ~LPSolver() {}; 00161 00162 virtual const MetaClass& getType() const {return *metadata;} 00163 static const MetaClass *metadata; 00164 virtual size_t getSize() const {return sizeof(LPSolver);} 00165 00166 private: 00167 /** This is an auxilary function. GLPK requires names to contain only 00168 * "graphic" characters. A space isn't one of those. Since our model 00169 * can contain HasHierarchy names with a space, we call this function to 00170 * replace the spaces with underscores.<br> 00171 * Note however that we can't garantuee that the updated strings are 00172 * all unique after the replacement! 00173 */ 00174 static string replaceSpaces(const string&); 00175 00176 /** This object is the interface with the GLPK structures. */ 00177 LPX* lp; 00178 00179 /** Storing simplex configuration paramters. */ 00180 glp_smcp parameters; 00181 00182 /** A list of model columns to use as objectives. */ 00183 list<string> objectives; 00184 00185 /** Direction of the solver: minimization or maximization. */ 00186 bool minimum; 00187 00188 /** Name of the model file.<br> 00189 * This field is required.*/ 00190 string modelfilename; 00191 00192 /** Name of the data file.<br> 00193 * If the field is left empty, the data section in the model file is 00194 * used instead. 00195 */ 00196 string datafilename; 00197 00198 /** Name of the solution file.<br> 00199 * If the field is left empty, the solution is not exported. 00200 */ 00201 string solutionfilename; 00202 00203 /** A hook to intercept the terminal output of the solver library, and 00204 * redirect it into the frePPLe log file. 00205 */ 00206 static int solveroutputredirect(void* info, const char* msg) 00207 { 00208 logger << msg; 00209 logger.flush(); 00210 return 1; 00211 } 00212 00213 /** Solve for a goal in a hierarchical sequence. */ 00214 void solveObjective(const string&); 00215 }; 00216 00217 } // End namespace