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 #define FREPPLE_CORE
00029 #include "frepple/solver.h"
00030 namespace frepple
00031 {
00032
00033 DECLARE_EXPORT const MetaClass* SolverMRP::metadata;
00034
00035
00036 void LibrarySolver::initialize()
00037 {
00038
00039 static bool init = false;
00040 if (init)
00041 {
00042 logger << "Warning: Calling frepple::LibrarySolver::initialize() more "
00043 << "than once." << endl;
00044 return;
00045 }
00046 init = true;
00047
00048
00049 if (SolverMRP::initialize())
00050 throw RuntimeException("Error registering solver_mrp Python type");
00051 }
00052
00053
00054 int SolverMRP::initialize()
00055 {
00056
00057 metadata = new MetaClass
00058 ("solver","solver_mrp",Object::createString<SolverMRP>,true);
00059
00060
00061 FreppleClass<SolverMRP,Solver>::getType().addMethod("solve", solve, METH_VARARGS, "run the solver");
00062 FreppleClass<SolverMRP,Solver>::getType().addMethod("commit", commit, METH_NOARGS, "commit the plan changes");
00063 FreppleClass<SolverMRP,Solver>::getType().addMethod("undo", undo, METH_NOARGS, "undo the plan changes");
00064 return FreppleClass<SolverMRP,Solver>::initialize();
00065 }
00066
00067
00068 DECLARE_EXPORT bool SolverMRP::demand_comparison(const Demand* l1, const Demand* l2)
00069 {
00070 if (l1->getPriority() != l2->getPriority())
00071 return l1->getPriority() < l2->getPriority();
00072 else if (l1->getDue() != l2->getDue())
00073 return l1->getDue() < l2->getDue();
00074 else
00075 return l1->getQuantity() < l2->getQuantity();
00076 }
00077
00078
00079 DECLARE_EXPORT void SolverMRP::SolverMRPdata::execute()
00080 {
00081
00082 if (!demands || !getSolver())
00083 throw LogicException("Missing demands or solver.");
00084
00085
00086 SolverMRP* Solver = getSolver();
00087 if (Solver->getLogLevel()>0)
00088 logger << "Start solving cluster " << cluster << " at " << Date::now() << endl;
00089
00090
00091 try
00092 {
00093
00094
00095
00096 stable_sort(demands->begin(), demands->end(), demand_comparison);
00097
00098
00099 constrainedPlanning = (Solver->getPlanType() == 1);
00100 for (deque<Demand*>::const_iterator i = demands->begin();
00101 i != demands->end(); ++i)
00102 {
00103 Command* topcommand = getLastCommand();
00104
00105 try
00106 {
00107 State* mystate = state;
00108 push();
00109 try {(*i)->solve(*Solver,this);}
00110 catch (...)
00111 {
00112 while (state > mystate) pop();
00113 throw;
00114 }
00115 while (state > mystate) pop();
00116 }
00117 catch (...)
00118 {
00119
00120 logger << "Error: Caught an exception while solving demand '"
00121 << (*i)->getName() << "':" << endl;
00122 try {throw;}
00123 catch (bad_exception&) {logger << " bad exception" << endl;}
00124 catch (exception& e) {logger << " " << e.what() << endl;}
00125 catch (...) {logger << " Unknown type" << endl;}
00126
00127
00128 undo(topcommand);
00129 }
00130 }
00131
00132
00133 demands->clear();
00134 }
00135 catch (...)
00136 {
00137
00138
00139
00140
00141
00142
00143 logger << "Error: Caught an exception while solving cluster "
00144 << cluster << ":" << endl;
00145 try {throw;}
00146 catch (bad_exception&){logger << " bad exception" << endl;}
00147 catch (exception& e) {logger << " " << e.what() << endl;}
00148 catch (...) {logger << " Unknown type" << endl;}
00149
00150
00151 for (Operation::iterator f=Operation::begin(); f!=Operation::end(); ++f)
00152 if (f->getCluster() == cluster)
00153 f->deleteOperationPlans();
00154
00155
00156 demands->clear();
00157 }
00158
00159
00160 if (Solver->getLogLevel()>0)
00161 logger << "End solving cluster " << cluster << " at " << Date::now() << endl;
00162 }
00163
00164
00165 DECLARE_EXPORT void SolverMRP::solve(void *v)
00166 {
00167
00168 for (Demand::iterator i = Demand::begin(); i != Demand::end(); ++i)
00169 demands_per_cluster[i->getCluster()].push_back(&*i);
00170
00171
00172
00173
00174
00175
00176
00177 if (getLogLevel()>0) logger << "Deleting previous plan" << endl;
00178 for (Operation::iterator e=Operation::begin(); e!=Operation::end(); ++e)
00179
00180 if (demands_per_cluster.find(e->getCluster())!=demands_per_cluster.end())
00181 e->deleteOperationPlans();
00182
00183
00184 int cl = demands_per_cluster.size();
00185 if (cl<1) return;
00186
00187
00188 CommandList threads;
00189
00190
00191
00192
00193 if (getLogLevel()>0 || !getAutocommit())
00194 threads.setMaxParallel(1);
00195 else
00196 threads.setMaxParallel( cl > getMaxParallel() ? getMaxParallel() : cl);
00197
00198
00199 threads.setAbortOnError(false);
00200 for (classified_demand::iterator j = demands_per_cluster.begin();
00201 j != demands_per_cluster.end(); ++j)
00202 threads.add(new SolverMRPdata(this, j->first, &(j->second)));
00203
00204
00205 threads.execute();
00206
00207
00208 for (Resource::iterator gres = Resource::begin(); gres != Resource::end(); ++gres)
00209 {
00210 if (gres->getSetupMatrix()) gres->updateSetups();
00211 }
00212 }
00213
00214
00215 DECLARE_EXPORT void SolverMRP::writeElement(XMLOutput *o, const Keyword& tag, mode m) const
00216 {
00217
00218 if (m == REFERENCE)
00219 {
00220 o->writeElement
00221 (tag, Tags::tag_name, getName(), Tags::tag_type, getType().type);
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 (constrts) o->writeElement(Tags::tag_constraints, constrts);
00231 if (plantype != 1) o->writeElement(Tags::tag_plantype, plantype);
00232 if (maxparallel) o->writeElement(Tags::tag_maxparallel, maxparallel);
00233 if (!autocommit) o->writeElement(Tags::tag_autocommit, autocommit);
00234 if (userexit_flow)
00235 o->writeElement(Tags::tag_userexit_flow, static_cast<string>(userexit_flow));
00236 if (userexit_demand)
00237 o->writeElement(Tags::tag_userexit_demand, static_cast<string>(userexit_demand));
00238 if (userexit_buffer)
00239 o->writeElement(Tags::tag_userexit_buffer, static_cast<string>(userexit_buffer));
00240 if (userexit_resource)
00241 o->writeElement(Tags::tag_userexit_resource, static_cast<string>(userexit_resource));
00242 if (userexit_operation)
00243 o->writeElement(Tags::tag_userexit_operation, static_cast<string>(userexit_operation));
00244
00245
00246 Solver::writeElement(o, tag, NOHEADER);
00247 }
00248
00249
00250 DECLARE_EXPORT void SolverMRP::endElement(XMLInput& pIn, const Attribute& pAttr, const DataElement& pElement)
00251 {
00252 if (pAttr.isA(Tags::tag_constraints))
00253 setConstraints(pElement.getInt());
00254 else if (pAttr.isA(Tags::tag_maxparallel))
00255 setMaxParallel(pElement.getInt());
00256 else if (pAttr.isA(Tags::tag_autocommit))
00257 setAutocommit(pElement.getBool());
00258 else if (pAttr.isA(Tags::tag_userexit_flow))
00259 setUserExitFlow(pElement.getString());
00260 else if (pAttr.isA(Tags::tag_userexit_demand))
00261 setUserExitDemand(pElement.getString());
00262 else if (pAttr.isA(Tags::tag_userexit_buffer))
00263 setUserExitBuffer(pElement.getString());
00264 else if (pAttr.isA(Tags::tag_userexit_resource))
00265 setUserExitResource(pElement.getString());
00266 else if (pAttr.isA(Tags::tag_userexit_operation))
00267 setUserExitOperation(pElement.getString());
00268 else if (pAttr.isA(Tags::tag_plantype))
00269 setPlanType(pElement.getInt());
00270 else
00271 Solver::endElement(pIn, pAttr, pElement);
00272 }
00273
00274
00275 DECLARE_EXPORT PyObject* SolverMRP::getattro(const Attribute& attr)
00276 {
00277 if (attr.isA(Tags::tag_constraints))
00278 return PythonObject(getConstraints());
00279 if (attr.isA(Tags::tag_maxparallel))
00280 return PythonObject(getMaxParallel());
00281 if (attr.isA(Tags::tag_autocommit))
00282 return PythonObject(getAutocommit());
00283 if (attr.isA(Tags::tag_userexit_flow))
00284 return getUserExitFlow();
00285 if (attr.isA(Tags::tag_userexit_demand))
00286 return getUserExitDemand();
00287 if (attr.isA(Tags::tag_userexit_buffer))
00288 return getUserExitBuffer();
00289 if (attr.isA(Tags::tag_userexit_resource))
00290 return getUserExitResource();
00291 if (attr.isA(Tags::tag_userexit_operation))
00292 return getUserExitOperation();
00293 if (attr.isA(Tags::tag_plantype))
00294 return PythonObject(getPlanType());
00295 return Solver::getattro(attr);
00296 }
00297
00298
00299 DECLARE_EXPORT int SolverMRP::setattro(const Attribute& attr, const PythonObject& field)
00300 {
00301 if (attr.isA(Tags::tag_constraints))
00302 setConstraints(field.getInt());
00303 else if (attr.isA(Tags::tag_maxparallel))
00304 setMaxParallel(field.getInt());
00305 else if (attr.isA(Tags::tag_autocommit))
00306 setAutocommit(field.getBool());
00307 else if (attr.isA(Tags::tag_userexit_flow))
00308 setUserExitFlow(field);
00309 else if (attr.isA(Tags::tag_userexit_demand))
00310 setUserExitDemand(field);
00311 else if (attr.isA(Tags::tag_userexit_buffer))
00312 setUserExitBuffer(field);
00313 else if (attr.isA(Tags::tag_userexit_resource))
00314 setUserExitResource(field);
00315 else if (attr.isA(Tags::tag_userexit_operation))
00316 setUserExitOperation(field);
00317 else if (attr.isA(Tags::tag_plantype))
00318 setPlanType(field.getInt());
00319 else
00320 return Solver::setattro(attr, field);
00321 return 0;
00322 }
00323
00324
00325 DECLARE_EXPORT PyObject* SolverMRP::solve(PyObject *self, PyObject *args)
00326 {
00327
00328 PyObject *dem = NULL;
00329 if (args && !PyArg_ParseTuple(args, "|O:solve", &dem)) return NULL;
00330 if (dem && !PyObject_TypeCheck(dem, Demand::metadata->pythonClass))
00331 throw DataException("solver argument must be a demand");
00332
00333 Py_BEGIN_ALLOW_THREADS
00334 try
00335 {
00336 SolverMRP* sol = static_cast<SolverMRP*>(self);
00337 if (!dem)
00338 {
00339
00340 sol->setAutocommit(true);
00341 sol->solve();
00342 }
00343 else
00344 {
00345
00346 sol->setAutocommit(false);
00347 sol->commands.sol = sol;
00348 static_cast<Demand*>(dem)->solve(*sol, &(sol->commands));
00349 }
00350 }
00351 catch(...)
00352 {
00353 Py_BLOCK_THREADS;
00354 PythonType::evalException();
00355 return NULL;
00356 }
00357 Py_END_ALLOW_THREADS
00358 return Py_BuildValue("");
00359 }
00360
00361
00362 DECLARE_EXPORT PyObject* SolverMRP::commit(PyObject *self, PyObject *args)
00363 {
00364 Py_BEGIN_ALLOW_THREADS
00365 try
00366 {
00367 static_cast<SolverMRP*>(self)->commands.CommandList::execute();
00368 }
00369 catch(...)
00370 {
00371 Py_BLOCK_THREADS;
00372 PythonType::evalException();
00373 return NULL;
00374 }
00375 Py_END_ALLOW_THREADS
00376 return Py_BuildValue("");
00377 }
00378
00379
00380 DECLARE_EXPORT PyObject* SolverMRP::undo(PyObject *self, PyObject *args)
00381 {
00382 Py_BEGIN_ALLOW_THREADS
00383 try
00384 {
00385 static_cast<SolverMRP*>(self)->commands.undo();
00386 }
00387 catch(...)
00388 {
00389 Py_BLOCK_THREADS;
00390 PythonType::evalException();
00391 return NULL;
00392 }
00393 Py_END_ALLOW_THREADS
00394 return Py_BuildValue("");
00395 }
00396
00397 }