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 #define FREPPLE_CORE
00028 #include "frepple/model.h"
00029
00030 namespace frepple
00031 {
00032
00033 template<class Solver> DECLARE_EXPORT Tree utils::HasName<Solver>::st;
00034
00035
00036
00037
00038
00039
00040 DECLARE_EXPORT void CommandSolve::execute()
00041 {
00042
00043 if (!sol) throw RuntimeException("Solve command with unspecified solver");
00044
00045
00046 if (getVerbose())
00047 logger << "Started running the solver '" << sol->getName()
00048 << "' at " << Date::now() << endl;
00049 Timer t;
00050
00051
00052 sol->solve();
00053
00054
00055 if (getVerbose())
00056 logger << "Finished running the solver '" << sol->getName()
00057 << "' at " << Date::now() << " : " << t << endl;
00058 }
00059
00060
00061 DECLARE_EXPORT void Solver::writeElement
00062 (XMLOutput *o, const Keyword &tag, mode m) const
00063 {
00064
00065 assert(m == NOHEADER);
00066
00067
00068 if (loglevel) o->writeElement(Tags::tag_loglevel, loglevel);
00069
00070
00071 o->EndObject(tag);
00072 }
00073
00074
00075 DECLARE_EXPORT void Solver::endElement(XMLInput& pIn, const Attribute& pAttr, const DataElement& pElement)
00076 {
00077 if (pAttr.isA(Tags::tag_loglevel))
00078 {
00079 int i = pElement.getInt();
00080 if (i<0 || i>USHRT_MAX)
00081 throw DataException("Invalid log level" + pElement.getString());
00082 setLogLevel(i);
00083 }
00084 }
00085
00086
00087 DECLARE_EXPORT PyObject* PythonSolver::getattro(const Attribute& attr)
00088 {
00089 if (!obj) return Py_BuildValue("");
00090 if (attr.isA(Tags::tag_name))
00091 return PythonObject(obj->getName());
00092 if (attr.isA(Tags::tag_loglevel))
00093 return PythonObject(obj->getLogLevel());
00094 return NULL;
00095 }
00096
00097
00098 DECLARE_EXPORT int PythonSolver::setattro(const Attribute& attr, const PythonObject& field)
00099 {
00100 if (attr.isA(Tags::tag_name))
00101 obj->setName(field.getString());
00102 else if (attr.isA(Tags::tag_loglevel))
00103 obj->setLogLevel(field.getInt());
00104 else
00105 return -1;
00106 return 0;
00107 }
00108
00109
00110 DECLARE_EXPORT PyObject *PythonSolver::solve(PyObject *self, PyObject *args)
00111 {
00112 Py_BEGIN_ALLOW_THREADS
00113 try
00114 {
00115 Solver *sol = static_cast<PythonSolver*>(self)->obj;
00116 if (!sol) throw LogicException("Can't run NULL solver");
00117 sol->solve();
00118 }
00119 catch(...)
00120 {
00121 Py_BLOCK_THREADS;
00122 PythonType::evalException();
00123 return NULL;
00124 }
00125 Py_END_ALLOW_THREADS
00126 return Py_BuildValue("");
00127 }
00128
00129
00130
00131
00132
00133
00134 DECLARE_EXPORT void CommandReadXMLFile::execute()
00135 {
00136
00137 if (getVerbose())
00138 logger << "Started reading model from file '" << filename
00139 << "' at " << Date::now() << endl;
00140 Timer t;
00141
00142
00143 if (filename.empty())
00144 {
00145
00146 xercesc::StdInInputSource in;
00147 if (validate_only)
00148
00149 XMLInput().parse(in, NULL, true);
00150 else
00151 XMLInput().parse(in, &Plan::instance(), validate);
00152 }
00153 else if (validate_only)
00154
00155 XMLInputFile(filename).parse(NULL, true);
00156 else
00157
00158 XMLInputFile(filename).parse(&Plan::instance(),validate);
00159
00160
00161 if (getVerbose())
00162 logger << "Finished reading model at " << Date::now() << " : " << t << endl;
00163 }
00164
00165
00166 DECLARE_EXPORT PyObject* CommandReadXMLFile::executePython(PyObject* self, PyObject* args)
00167 {
00168
00169 char *data;
00170 int i1(1), i2(0);
00171 int ok = PyArg_ParseTuple(args, "s|ii", &data, &i1, &i2);
00172 if (!ok) return NULL;
00173
00174
00175 Py_BEGIN_ALLOW_THREADS
00176 try {
00177 CommandReadXMLFile(data, i1!=0, i2!=0).execute();
00178 }
00179 catch (...)
00180 {
00181 Py_BLOCK_THREADS;
00182 PythonType::evalException();
00183 return NULL;
00184 }
00185 Py_END_ALLOW_THREADS
00186 return Py_BuildValue("");
00187 }
00188
00189
00190
00191
00192
00193
00194 DECLARE_EXPORT void CommandReadXMLString::execute()
00195 {
00196
00197 if (getVerbose())
00198 logger << "Started reading model from string at " << Date::now() << endl;
00199 Timer t;
00200
00201
00202 if (validate_only)
00203 XMLInputString(data).parse(NULL, true);
00204 else
00205
00206 XMLInputString(data).parse(&Plan::instance(), validate);
00207
00208
00209 if (getVerbose())
00210 logger << "Finished reading model at " << Date::now() << " : " << t << endl;
00211 }
00212
00213
00214 PyObject* CommandReadXMLString::executePython(PyObject *self, PyObject *args)
00215 {
00216
00217 char *data;
00218 int i1(1), i2(0);
00219 int ok = PyArg_ParseTuple(args, "s|ii", &data, &i1, &i2);
00220 if (!ok) return NULL;
00221
00222
00223 Py_BEGIN_ALLOW_THREADS
00224 try {
00225 if (data) CommandReadXMLString(string(data), i1!=0, i2!=0).execute();
00226 }
00227 catch (...)
00228 {
00229 Py_BLOCK_THREADS;
00230 PythonType::evalException();
00231 return NULL;
00232 }
00233 Py_END_ALLOW_THREADS
00234 return Py_BuildValue("");
00235
00236 }
00237
00238
00239
00240
00241
00242
00243 DECLARE_EXPORT void CommandSave::execute()
00244 {
00245
00246 if (getVerbose())
00247 logger << "Start saving model to file '" << filename
00248 << "' at " << Date::now() << endl;
00249 Timer t;
00250
00251
00252 XMLOutputFile o(filename);
00253 if (!headerstart.empty()) o.setHeaderStart(headerstart);
00254 if (!headeratts.empty()) o.setHeaderAtts(headeratts);
00255 o.setContentType(content);
00256 o.writeElementWithHeader(Tags::tag_plan, &Plan::instance());
00257
00258
00259 if (getVerbose())
00260 logger << "Finished saving " << o.countObjects()
00261 << " objects at " << Date::now() << " : " << t << endl;
00262 }
00263
00264
00265 PyObject* CommandSave::executePython(PyObject* self, PyObject* args)
00266 {
00267
00268 char *data;
00269 char *content = NULL;
00270 int ok = PyArg_ParseTuple(args, "s|s", &data, &content);
00271 if (!ok) return NULL;
00272
00273
00274 Py_BEGIN_ALLOW_THREADS
00275 try {
00276 CommandSave cmd(data);
00277 if (content)
00278 {
00279 if (!strcmp(content,"STANDARD"))
00280 cmd.setContent(XMLOutput::STANDARD);
00281 else if (!strcmp(content,"PLAN"))
00282 cmd.setContent(XMLOutput::PLAN);
00283 else if (!strcmp(content,"PLANDETAIL"))
00284 cmd.setContent(XMLOutput::PLANDETAIL);
00285 else
00286 throw DataException("Invalid content type '" + string(content) + "'");
00287 }
00288 cmd.execute();
00289 }
00290 catch (...)
00291 {
00292 Py_BLOCK_THREADS;
00293 PythonType::evalException();
00294 return NULL;
00295 }
00296 Py_END_ALLOW_THREADS
00297 return Py_BuildValue("");
00298 }
00299
00300
00301
00302
00303
00304
00305 DECLARE_EXPORT void CommandSavePlan::execute()
00306 {
00307
00308 if (getVerbose())
00309 logger << "Start saving plan to file '" << getFileName()
00310 << "' at " << Date::now() << endl;
00311 Timer t;
00312
00313
00314 if (getFileName().empty())
00315 throw RuntimeException("No file specified for export");
00316 ofstream textoutput;
00317
00318
00319 try
00320 {
00321
00322 textoutput.open(getFileName().c_str(), ios::out);
00323
00324
00325 for (Buffer::iterator gbuf = Buffer::begin();
00326 gbuf != Buffer::end(); ++gbuf)
00327 {
00328 if (!gbuf->getHidden())
00329 for (Buffer::flowplanlist::const_iterator
00330 oo=gbuf->getFlowPlans().begin();
00331 oo!=gbuf->getFlowPlans().end();
00332 ++oo)
00333 if (oo->getType() == 1 && oo->getQuantity() != 0.0)
00334 {
00335 textoutput << "BUFFER\t" << *gbuf << '\t'
00336 << oo->getDate() << '\t'
00337 << oo->getQuantity() << '\t'
00338 << oo->getOnhand() << endl;
00339 }
00340 }
00341
00342
00343 for (Demand::iterator gdem = Demand::begin();
00344 gdem != Demand::end(); ++gdem)
00345 {
00346 if (!gdem->getHidden())
00347 for (Demand::OperationPlan_list::const_iterator
00348 pp=gdem->getDelivery().begin();
00349 pp!=gdem->getDelivery().end();
00350 ++pp)
00351 {
00352 textoutput << "DEMAND\t" << (*gdem) << '\t'
00353 << (*pp)->getDates().getEnd() << '\t'
00354 << (*pp)->getQuantity() << endl;
00355 }
00356 }
00357
00358
00359 for (Resource::iterator gres = Resource::begin();
00360 gres != Resource::end(); ++gres)
00361 {
00362 if (!gres->getHidden())
00363 for (Resource::loadplanlist::const_iterator
00364 qq=gres->getLoadPlans().begin();
00365 qq!=gres->getLoadPlans().end();
00366 ++qq)
00367 if (qq->getType() == 1 && qq->getQuantity() != 0.0)
00368 {
00369 textoutput << "RESOURCE\t" << *gres << '\t'
00370 << qq->getDate() << '\t'
00371 << qq->getQuantity() << '\t'
00372 << qq->getOnhand() << endl;
00373 }
00374 }
00375
00376
00377 for (OperationPlan::iterator rr = OperationPlan::begin();
00378 rr != OperationPlan::end(); ++rr)
00379 {
00380 if (rr->getOperation()->getHidden()) continue;
00381 textoutput << "OPERATION\t" << rr->getOperation() << '\t'
00382 << rr->getDates().getStart() << '\t'
00383 << rr->getDates().getEnd() << '\t'
00384 << rr->getQuantity() << endl;
00385 }
00386
00387
00388 for (Problem::const_iterator gprob = Problem::begin();
00389 gprob != Problem::end(); ++gprob)
00390 {
00391 textoutput << "PROBLEM\t" << gprob->getType().type << '\t'
00392 << gprob->getDescription() << '\t'
00393 << gprob->getDateRange() << endl;
00394 }
00395
00396
00397 textoutput.close();
00398 }
00399 catch (exception& e)
00400 {
00401 textoutput.close();
00402 throw RuntimeException("Error writing to file '"
00403 + getFileName() + "':\n" + e.what());
00404 }
00405 catch (...)
00406 {
00407 textoutput.close();
00408 throw RuntimeException("Error writing to file '"
00409 + getFileName() + "'");
00410 }
00411
00412
00413 if (getVerbose())
00414 logger << "Finished saving plan at " << Date::now() << " : " << t << endl;
00415 }
00416
00417
00418 PyObject* CommandSavePlan::executePython(PyObject* self, PyObject* args)
00419 {
00420
00421 char *data;
00422 int ok = PyArg_ParseTuple(args, "s", &data);
00423 if (!ok) return NULL;
00424
00425
00426 Py_BEGIN_ALLOW_THREADS
00427 try {
00428 CommandSavePlan(data).execute();
00429 }
00430 catch (...)
00431 {
00432 Py_BLOCK_THREADS;
00433 PythonType::evalException();
00434 return NULL;
00435 }
00436 Py_END_ALLOW_THREADS
00437 return Py_BuildValue("");
00438 }
00439
00440
00441
00442
00443
00444
00445 DECLARE_EXPORT CommandMoveOperationPlan::CommandMoveOperationPlan
00446 (OperationPlan* o, Date newdate, bool pref_end, double newQty)
00447 : opplan(o), prefer_end(pref_end)
00448 {
00449 if (!opplan) return;
00450 originalqty = opplan->getQuantity();
00451 if (newQty == -1.0) newQty = originalqty;
00452 originaldates = opplan->getDates();
00453 if (prefer_end)
00454 opplan->getOperation()->setOperationPlanParameters(
00455 opplan, newQty, Date::infinitePast, newdate, prefer_end
00456 );
00457 else
00458 opplan->getOperation()->setOperationPlanParameters(
00459 opplan, newQty, newdate, Date::infiniteFuture, prefer_end
00460 );
00461 }
00462
00463
00464 DECLARE_EXPORT void CommandMoveOperationPlan::undo()
00465 {
00466 if (!opplan) return;
00467 opplan->getOperation()->setOperationPlanParameters(
00468 opplan, originalqty, originaldates.getStart(), originaldates.getEnd(), prefer_end
00469 );
00470 opplan = NULL;
00471 }
00472
00473
00474 DECLARE_EXPORT void CommandMoveOperationPlan::setDate(Date newdate)
00475 {
00476 if (!opplan) return;
00477 if (prefer_end)
00478 opplan->getOperation()->setOperationPlanParameters(
00479 opplan, opplan->getQuantity(), Date::infinitePast, newdate, prefer_end
00480 );
00481 else
00482 opplan->getOperation()->setOperationPlanParameters(
00483 opplan, opplan->getQuantity(), newdate, Date::infiniteFuture, prefer_end
00484 );
00485 }
00486
00487
00488 DECLARE_EXPORT void CommandMoveOperationPlan::setQuantity(double newqty)
00489 {
00490 if (!opplan) return;
00491 if (prefer_end)
00492 opplan->getOperation()->setOperationPlanParameters(
00493 opplan, newqty, opplan->getDates().getStart(), opplan->getDates().getEnd(), prefer_end
00494 );
00495 else
00496 opplan->getOperation()->setOperationPlanParameters(
00497 opplan, newqty, opplan->getDates().getStart(), opplan->getDates().getEnd(), prefer_end
00498 );
00499 }
00500
00501
00502 DECLARE_EXPORT string CommandMoveOperationPlan::getDescription() const
00503 {
00504 ostringstream ch;
00505 ch << "updating operationplan ";
00506 if (opplan)
00507 ch << "of operation '" << opplan->getOperation()
00508 << "' with identifier " << opplan->getIdentifier();
00509 else
00510 ch << "NULL";
00511 return ch.str();
00512 }
00513
00514
00515
00516
00517
00518
00519 DECLARE_EXPORT CommandDeleteOperationPlan::CommandDeleteOperationPlan
00520 (OperationPlan* o)
00521 {
00522
00523 if (!o)
00524 {
00525 oper = NULL;
00526 return;
00527 }
00528
00529
00530 if (o->getLocked())
00531 throw DataException("Can't delete a locked operationplan");
00532
00533
00534 oper = o->getOperation();
00535 qty = o->getQuantity();
00536 dates = o->getDates();
00537 id = o->getIdentifier();
00538 dmd = o->getDemand();
00539 ow = &*(o->getOwner());
00540
00541
00542 delete o;
00543 }
00544
00545
00546 DECLARE_EXPORT void CommandDeleteOperationPlan::undo()
00547 {
00548
00549 if (!oper) return;
00550
00551
00552
00553
00554
00555 OperationPlan* opplan = oper->createOperationPlan(qty, dates.getStart(),
00556 dates.getEnd(), dmd, const_cast<OperationPlan*>(ow), id);
00557 if (opplan) opplan->initialize();
00558
00559
00560 oper = NULL;
00561 }
00562
00563
00564 DECLARE_EXPORT string CommandDeleteOperationPlan::getDescription() const
00565 {
00566 ostringstream ch;
00567 ch << "deleting operationplan";
00568 if (oper) ch << " for operation '" << oper->getName() << "'";
00569 if (id) ch << " with identifier " << id;
00570 return ch.str();
00571 }
00572
00573
00574
00575
00576
00577
00578
00579 DECLARE_EXPORT void CommandErase::execute()
00580 {
00581
00582 if (getVerbose())
00583 {
00584 if (deleteStaticModel)
00585 logger << "Start model erase command at " << Date::now() << endl;
00586 else
00587 logger << "Start plan erase command at " << Date::now() << endl;
00588 }
00589 Timer t;
00590
00591 if (deleteStaticModel)
00592 {
00593
00594
00595
00596
00597 Demand::clear();
00598 Operation::clear();
00599 Buffer::clear();
00600 Resource::clear();
00601 Location::clear();
00602 Customer::clear();
00603 Calendar::clear();
00604 Solver::clear();
00605 Item::clear();
00606 }
00607 else
00608
00609 for (Operation::iterator gop = Operation::begin();
00610 gop != Operation::end(); ++gop)
00611 gop->deleteOperationPlans();
00612
00613
00614 if (getVerbose())
00615 logger << "Finished erase command at " << Date::now()
00616 << " : " << t << endl;
00617 }
00618
00619
00620 PyObject* CommandErase::executePython(PyObject* self, PyObject* args)
00621 {
00622
00623 PyObject *obj = NULL;
00624 int ok = PyArg_ParseTuple(args, "|O", &obj);
00625 if (!ok) return NULL;
00626
00627
00628 bool staticalso = false;
00629 if (obj) staticalso = PythonObject(obj).getBool();
00630
00631
00632 Py_BEGIN_ALLOW_THREADS
00633 try {
00634 CommandErase(staticalso).execute();
00635 }
00636 catch (...)
00637 {
00638 Py_BLOCK_THREADS;
00639 PythonType::evalException();
00640 return NULL;
00641 }
00642 Py_END_ALLOW_THREADS
00643 return Py_BuildValue("");
00644 }
00645
00646 }