00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "lpsolver.h"
00029
00030 namespace module_lp_solver
00031 {
00032
00033 const MetaClass *LPSolver::metadata;
00034
00035 const Keyword tag_datafile("datafile");
00036 const Keyword tag_modelfile("modelfile");
00037 const Keyword tag_solutionfile("solutionfile");
00038 const Keyword tag_objective("objective");
00039
00040
00041 MODULE_EXPORT const char* initialize(const CommandLoadLibrary::ParameterList& z)
00042 {
00043
00044 static bool init = false;
00045 static const char* name = "lpsolver";
00046 if (init)
00047 {
00048 logger << "Warning: Initializing module lpsolver more than once." << endl;
00049 return name;
00050 }
00051 init = true;
00052
00053 try
00054 {
00055
00056 PyThreadState *myThreadState = PyGILState_GetThisThreadState();
00057 if (!Py_IsInitialized() || !myThreadState)
00058 throw RuntimeException("Python isn't initialized correctly");
00059 try
00060 {
00061
00062 PyEval_RestoreThread(myThreadState);
00063
00064 if (LPSolver::initialize())
00065 throw RuntimeException("Error registering Python solver_lp extension");
00066 }
00067
00068 catch (...)
00069 {
00070 PyEval_ReleaseLock();
00071 throw;
00072 }
00073 PyEval_ReleaseLock();
00074 }
00075 catch (exception &e)
00076 {
00077
00078 logger << "Error: " << e.what() << endl;
00079 }
00080 catch (...)
00081 {
00082 logger << "Error: unknown exception" << endl;
00083 }
00084
00085
00086 return name;
00087 }
00088
00089
00090 int LPSolver::initialize()
00091 {
00092
00093 metadata = new MetaClass("solver", "solver_lp",
00094 Object::createString<LPSolver>);
00095
00096
00097 return FreppleClass<LPSolver,Solver>::initialize();
00098 }
00099
00100
00101 void LPSolver::solveObjective(const string& colname)
00102 {
00103
00104 if (colname.empty()) throw DataException("Empty objective name");
00105 int col = glp_find_col(lp, colname.c_str());
00106 if (!col)
00107 throw DataException("Unknown objective name '" + string(colname) + "'");
00108 lpx_set_obj_coef(lp, col, 1.0);
00109
00110
00111 if (getLogLevel()>0)
00112 logger << "Solving for " << colname << "..." << endl;
00113
00114
00115 int result = glp_simplex(lp, ¶meters);
00116
00117
00118 double val = lpx_get_obj_val(lp);
00119 if (getLogLevel()>0)
00120 {
00121 if (result)
00122 logger << " Error " << result << endl;
00123 else
00124 logger << " Optimum " << val << " found at " << Date::now() << endl;
00125 }
00126
00127
00128 lpx_set_col_bnds(lp, col, LPX_DB,
00129 val>=ROUNDING_ERROR ? val-ROUNDING_ERROR : 0.0,
00130 val>=-ROUNDING_ERROR ? val+ROUNDING_ERROR : 0.0);
00131
00132
00133 lpx_set_obj_coef(lp, col, 0.0);
00134
00135
00136 if (parameters.presolve) parameters.presolve = 0;
00137 }
00138
00139
00140 void LPSolver::solve(void *v)
00141 {
00142 if (getLogLevel()>0)
00143 logger << "Start running the solver at " << Date::now() << endl;
00144
00145
00146 glp_term_hook(solveroutputredirect,NULL);
00147
00148
00149 glp_init_smcp(¶meters);
00150 if (getLogLevel() == 0)
00151 parameters.msg_lev = GLP_MSG_OFF;
00152 else if (getLogLevel() == 1)
00153 parameters.msg_lev = GLP_MSG_ERR;
00154 else if (getLogLevel() == 2)
00155 parameters.msg_lev = GLP_MSG_ON;
00156 else
00157 parameters.msg_lev = GLP_MSG_ALL;
00158
00159
00160 if (modelfilename.empty())
00161 throw DataException("No model file specified");
00162 if (datafilename.empty())
00163 lp = lpx_read_model(modelfilename.c_str(), NULL, NULL);
00164 else
00165 lp = lpx_read_model(modelfilename.c_str(), datafilename.c_str(), NULL);
00166 if (lp == NULL)
00167 throw RuntimeException("Cannot read model file '" + modelfilename + "'");
00168
00169
00170
00171 if (getLogLevel()>2)
00172 {
00173 string c = modelfilename + ".mps";
00174 lpx_write_mps(lp,c.c_str());
00175 }
00176
00177
00178 lpx_scale_prob(lp);
00179
00180
00181
00182 parameters.presolve = 1;
00183
00184
00185 glp_set_obj_dir(lp, minimum ? GLP_MIN : GLP_MAX);
00186
00187
00188 glp_create_index(lp);
00189
00190 if (getLogLevel()>0)
00191 logger << "Finished solver initialisation at " << Date::now() << endl;
00192
00193
00194 if (objectives.empty())
00195 throw DataException("No solver objectives are specified");
00196 for (list<string>::const_iterator i = objectives.begin();
00197 i != objectives.end(); ++i)
00198 solveObjective(*i);
00199
00200
00201 if (!solutionfilename.empty())
00202 lpx_print_sol(lp,solutionfilename.c_str());
00203
00204
00205 lpx_delete_prob(lp);
00206 glp_term_hook(NULL,NULL);
00207
00208 if (getLogLevel()>0)
00209 logger << "Finished running the solver at " << Date::now() << endl;
00210 }
00211
00212
00213 string LPSolver::replaceSpaces(const string& input)
00214 {
00215 string x = input;
00216 for (string::iterator i = x.begin(); i != x.end(); ++i)
00217 if (*i == ' ') *i = '_';
00218 return x;
00219 }
00220
00221
00222 void LPSolver::writeElement(XMLOutput *o, const Keyword& tag, mode m) const
00223 {
00224
00225 if (m == REFERENCE)
00226 {
00227 o->writeElement(tag, Tags::tag_name, getName());
00228 return;
00229 }
00230
00231
00232 if (m != NOHEADER) o->BeginObject
00233 (tag, Tags::tag_name, getName(), Tags::tag_type, getType().type);
00234
00235
00236 if (getMinimum())
00237 o->writeElement(Tags::tag_minimum, true);
00238 else
00239 o->writeElement(Tags::tag_maximum, true);
00240 o->writeElement(tag_modelfile, getModelFile());
00241 o->writeElement(tag_datafile, getDataFile());
00242 o->writeElement(tag_solutionfile, getSolutionFile());
00243 for (list<string>::const_iterator i = objectives.begin();
00244 i != objectives.end(); ++i)
00245 o->writeElement(tag_objective, *i);
00246 Solver::writeElement(o, tag, NOHEADER);
00247 }
00248
00249
00250 void LPSolver::endElement(XMLInput& pIn, const Attribute& pAttr, const DataElement& pElement)
00251 {
00252 if (pAttr.isA(Tags::tag_minimum))
00253 setMinimum(pElement.getBool());
00254 else if (pAttr.isA(Tags::tag_maximum))
00255 setMinimum(!pElement.getBool());
00256 else if (pAttr.isA(tag_datafile))
00257 setDataFile(pElement.getString());
00258 else if (pAttr.isA(tag_modelfile))
00259 setModelFile(pElement.getString());
00260 else if (pAttr.isA(tag_solutionfile))
00261 setSolutionFile(pElement.getString());
00262 else if (pAttr.isA(tag_objective))
00263 addObjective(pElement.getString());
00264 else
00265
00266 Solver::endElement(pIn, pAttr, pElement);
00267 }
00268
00269
00270 PyObject* LPSolver::getattro(const Attribute& attr)
00271 {
00272 if (attr.isA(Tags::tag_minimum))
00273 return PythonObject(getMinimum());
00274 else if (attr.isA(Tags::tag_maximum))
00275 return PythonObject(!(getMinimum()));
00276 else if (attr.isA(tag_datafile))
00277 return PythonObject(getDataFile());
00278 else if (attr.isA(tag_modelfile))
00279 return PythonObject(getModelFile());
00280 else if (attr.isA(tag_solutionfile))
00281 return PythonObject(getSolutionFile());
00282 else if (attr.isA(tag_objective))
00283 {
00284
00285 PyObject* result = PyList_New(getObjectives().size());
00286 int count = 0;
00287 for (list<string>::const_iterator i = getObjectives().begin();
00288 i != getObjectives().end(); ++i)
00289 PyList_SetItem(result, count++, PythonObject(*i));
00290 return result;
00291 }
00292 return Solver::getattro(attr);
00293 }
00294
00295
00296 int LPSolver::setattro(const Attribute& attr, const PythonObject& field)
00297 {
00298 if (attr.isA(Tags::tag_minimum))
00299 setMinimum(field.getBool());
00300 else if (attr.isA(Tags::tag_maximum))
00301 setMinimum(!field.getBool());
00302 else if (attr.isA(tag_datafile))
00303 setDataFile(field.getString());
00304 else if (attr.isA(tag_modelfile))
00305 setModelFile(field.getString());
00306 else if (attr.isA(tag_solutionfile))
00307 setSolutionFile(field.getString());
00308 else if (attr.isA(tag_objective))
00309 {
00310
00311 PyObject* seq = PySequence_Fast(static_cast<PyObject*>(field), "expected a list");
00312 if (!PyList_Check(seq))
00313 {
00314 PyErr_SetString(PythonDataException, "expected a list");
00315 return -1;
00316 }
00317 int len = PySequence_Size(static_cast<PyObject*>(field));
00318 PythonObject item;
00319 for (int i = 0; i < len; i++)
00320 {
00321 item = PyList_GET_ITEM(seq, i);
00322 addObjective(item.getString());
00323 }
00324 }
00325 else
00326 return Solver::setattro(attr, field);
00327 return 0;
00328 }
00329
00330 }