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