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/model.h"
00030
00031 namespace frepple
00032 {
00033
00034 DECLARE_EXPORT bool Plannable::anyChange = false;
00035 DECLARE_EXPORT bool Plannable::computationBusy = false;
00036 DECLARE_EXPORT const MetaCategory* Problem::metadata;
00037 DECLARE_EXPORT const MetaClass* ProblemMaterialExcess::metadata,
00038 *ProblemMaterialShortage::metadata,
00039 *ProblemExcess::metadata,
00040 *ProblemShort::metadata,
00041 *ProblemEarly::metadata,
00042 *ProblemLate::metadata,
00043 *ProblemDemandNotPlanned::metadata,
00044 *ProblemPrecedence::metadata,
00045 *ProblemBeforeFence::metadata,
00046 *ProblemBeforeCurrent::metadata,
00047 *ProblemCapacityUnderload::metadata,
00048 *ProblemCapacityOverload::metadata;
00049
00050
00051 int Problem::initialize()
00052 {
00053
00054 Problem::metadata = new MetaCategory
00055 ("problem", "problems", NULL, Problem::writer);
00056 ProblemMaterialExcess::metadata = new MetaClass
00057 ("problem","material excess");
00058 ProblemMaterialShortage::metadata = new MetaClass
00059 ("problem","material shortage");
00060 ProblemExcess::metadata = new MetaClass
00061 ("problem","excess");
00062 ProblemShort::metadata = new MetaClass
00063 ("problem","short");
00064 ProblemEarly::metadata = new MetaClass
00065 ("problem","early");
00066 ProblemLate::metadata = new MetaClass
00067 ("problem","late");
00068 ProblemDemandNotPlanned::metadata = new MetaClass
00069 ("problem","unplanned");
00070 ProblemPrecedence::metadata = new MetaClass
00071 ("problem","precedence");
00072 ProblemBeforeFence::metadata = new MetaClass
00073 ("problem","before fence");
00074 ProblemBeforeCurrent::metadata = new MetaClass
00075 ("problem","before current");
00076 ProblemCapacityUnderload::metadata = new MetaClass
00077 ("problem","underload");
00078 ProblemCapacityOverload::metadata = new MetaClass
00079 ("problem","overload");
00080
00081
00082 PythonType& x = PythonExtension<Problem>::getType();
00083 x.setName("problem");
00084 x.setDoc("frePPLe problem");
00085 x.supportgetattro();
00086 x.supportstr();
00087 x.addMethod("toXML", toXML, METH_VARARGS, "return a XML representation");
00088 const_cast<MetaCategory*>(metadata)->pythonClass = x.type_object();
00089 return x.typeReady();
00090 }
00091
00092
00093 DECLARE_EXPORT bool Problem::operator < (const Problem& a) const
00094 {
00095
00096 assert(owner == a.owner);
00097
00098
00099 if (getType() != a.getType()) return getType() < a.getType();
00100
00101
00102 return getDateRange().getStart() < a.getDateRange().getStart();
00103 }
00104
00105
00106 DECLARE_EXPORT void Problem::addProblem()
00107 {
00108 assert(owner);
00109 if ((owner->firstProblem && *this < *(owner->firstProblem))
00110 || !owner->firstProblem)
00111 {
00112
00113 nextProblem = owner->firstProblem;
00114 owner->firstProblem = this;
00115 }
00116 else
00117 {
00118
00119 Problem* curProblem = owner->firstProblem->nextProblem;
00120 Problem* prevProblem = owner->firstProblem;
00121 while (curProblem && !(*this < *curProblem))
00122 {
00123 prevProblem = curProblem;
00124 curProblem = curProblem->nextProblem;
00125 }
00126 nextProblem = curProblem;
00127 prevProblem->nextProblem = this;
00128 }
00129 }
00130
00131
00132 DECLARE_EXPORT void Problem::removeProblem()
00133 {
00134
00135
00136 if (!owner) return;
00137
00138 if (owner->firstProblem == this)
00139
00140 owner->firstProblem = nextProblem;
00141 else
00142 {
00143
00144 Problem *prev = owner->firstProblem;
00145 for (Problem* cur = owner->firstProblem; cur; cur=cur->nextProblem)
00146 {
00147 if (cur == this)
00148 {
00149
00150 prev->nextProblem = nextProblem;
00151 return;
00152 }
00153 prev = cur;
00154 }
00155
00156 throw LogicException("Corrupted problem list");
00157 }
00158 }
00159
00160
00161 DECLARE_EXPORT void Plannable::setDetectProblems(bool b)
00162 {
00163 if (useProblemDetection && !b)
00164
00165 Problem::clearProblems(*this);
00166 else if (!useProblemDetection && b)
00167
00168
00169 setChanged();
00170
00171 useProblemDetection=b;
00172 }
00173
00174
00175 DECLARE_EXPORT void Plannable::computeProblems()
00176 {
00177
00178 if (!anyChange && !computationBusy) return;
00179
00180 computationBusy = true;
00181
00182 static Mutex computationbusy;
00183 {
00184 ScopeMutexLock l(computationbusy);
00185
00186
00187
00188 while (anyChange)
00189 {
00190
00191
00192 anyChange = false;
00193
00194
00195 for (HasProblems::EntityIterator i; i!=HasProblems::endEntity(); ++i)
00196 {
00197 Plannable *e = i->getEntity();
00198 if (e->getChanged() && e->getDetectProblems()) i->updateProblems();
00199 }
00200
00201
00202 for (HasProblems::EntityIterator j; j!=HasProblems::endEntity(); ++j)
00203 {
00204 Plannable *e = j->getEntity();
00205 if (e->getChanged() && e->getDetectProblems()) e->setChanged(false);
00206 }
00207 }
00208
00209
00210 computationBusy = false;
00211 }
00212 }
00213
00214
00215 DECLARE_EXPORT void Plannable::writeElement (XMLOutput* o, const Keyword& tag, mode m) const
00216 {
00217
00218
00219
00220
00221 if (!getDetectProblems()) o->writeElement(Tags::tag_detectproblems, false);
00222 }
00223
00224
00225 DECLARE_EXPORT void Plannable::endElement(XMLInput& pIn, const Attribute& pAttr, const DataElement& pElement)
00226 {
00227 if (pAttr.isA (Tags::tag_detectproblems))
00228 {
00229 bool b = pElement.getBool();
00230 setDetectProblems(b);
00231 }
00232 }
00233
00234
00235 DECLARE_EXPORT void Problem::clearProblems()
00236 {
00237
00238 for (HasProblems::EntityIterator i = HasProblems::beginEntity();
00239 i != HasProblems::endEntity(); ++i)
00240 {
00241 clearProblems(*i);
00242 i->getEntity()->setChanged(true);
00243 }
00244 }
00245
00246
00247 DECLARE_EXPORT void Problem::clearProblems(HasProblems& p, bool setchanged)
00248 {
00249
00250 if (!p.firstProblem) return;
00251
00252
00253 for (Problem *cur=p.firstProblem; cur; )
00254 {
00255 Problem *del = cur;
00256 cur = cur->nextProblem;
00257 del->owner = NULL;
00258 delete del;
00259 }
00260 p.firstProblem = NULL;
00261
00262
00263 if (setchanged) p.getEntity()->setChanged();
00264 }
00265
00266
00267 DECLARE_EXPORT void Problem::writer(const MetaCategory* c, XMLOutput* o)
00268 {
00269 const_iterator piter = begin();
00270 if (piter != end())
00271 {
00272 o->BeginObject(*c->grouptag);
00273 for (; piter!=end(); ++piter)
00274
00275
00276
00277 piter->writeElement(o, *c->typetag);
00278 o->EndObject(*c->grouptag);
00279 }
00280 }
00281
00282
00283 DECLARE_EXPORT void Problem::writeElement(XMLOutput *o, const Keyword& tag, mode m) const
00284 {
00285
00286 o->BeginObject(tag);
00287 o->writeElement(Tags::tag_name, getType().type);
00288 o->writeElement(Tags::tag_description, getDescription());
00289 o->writeElement(Tags::tag_start, getDateRange().getStart());
00290 o->writeElement(Tags::tag_end, getDateRange().getEnd());
00291 o->writeElement(Tags::tag_weight, getWeight());
00292 o->EndObject(tag);
00293 }
00294
00295
00296 DECLARE_EXPORT HasProblems::EntityIterator::EntityIterator() : type(0)
00297 {
00298
00299 bufIter = new Buffer::iterator(Buffer::begin());
00300 if (*bufIter != Buffer::end()) return;
00301
00302
00303 delete bufIter;
00304 type = 1;
00305 resIter = new Resource::iterator(Resource::begin());
00306 if (*resIter != Resource::end()) return;
00307
00308
00309 delete resIter;
00310 type = 2;
00311 operIter = new OperationPlan::iterator(OperationPlan::begin());
00312 if (*operIter != OperationPlan::end()) return;
00313
00314
00315 delete operIter;
00316 type = 3;
00317 demIter = new Demand::iterator(Demand::begin());
00318 if (*demIter == Demand::end())
00319 {
00320
00321 delete demIter;
00322 type = 4;
00323 }
00324 }
00325
00326
00327 DECLARE_EXPORT HasProblems::EntityIterator& HasProblems::EntityIterator::operator++()
00328 {
00329 switch (type)
00330 {
00331 case 0:
00332
00333 if (*bufIter != Buffer::end())
00334 if (++(*bufIter) != Buffer::end()) return *this;
00335 ++type;
00336 delete bufIter;
00337 resIter = new Resource::iterator(Resource::begin());
00338 if (*resIter != Resource::end()) return *this;
00339
00340 case 1:
00341
00342 if (*resIter != Resource::end())
00343 if (++(*resIter) != Resource::end()) return *this;
00344 ++type;
00345 delete resIter;
00346 operIter = new OperationPlan::iterator(OperationPlan::begin());
00347 if (*operIter != OperationPlan::end()) return *this;
00348
00349 case 2:
00350
00351 if (*operIter != OperationPlan::end())
00352 if (++(*operIter) != OperationPlan::end()) return *this;
00353 ++type;
00354 delete operIter;
00355 demIter = new Demand::iterator(Demand::begin());
00356 if (*demIter != Demand::end()) return *this;
00357
00358 case 3:
00359
00360 if (*demIter != Demand::end())
00361 if (++(*demIter) != Demand::end()) return *this;
00362
00363 ++type;
00364 delete demIter;
00365 demIter = NULL;
00366 return *this;
00367 }
00368 throw LogicException("Unreachable code reached");
00369 }
00370
00371
00372 DECLARE_EXPORT HasProblems::EntityIterator::~EntityIterator()
00373 {
00374 switch (type)
00375 {
00376
00377 case 0: delete bufIter; return;
00378
00379 case 1: delete resIter; return;
00380
00381 case 2: delete operIter; return;
00382
00383 case 3: delete demIter; return;
00384 }
00385 }
00386
00387
00388 DECLARE_EXPORT HasProblems::EntityIterator::EntityIterator(const EntityIterator& o)
00389 {
00390
00391 this->~EntityIterator();
00392
00393 type = o.type;
00394 if (type==0) bufIter = new Buffer::iterator(*(o.bufIter));
00395 else if (type==1) resIter = new Resource::iterator(*(o.resIter));
00396 else if (type==2) operIter = new OperationPlan::iterator(*(o.operIter));
00397 else if (type==3) demIter = new Demand::iterator(*(o.demIter));
00398 }
00399
00400
00401 DECLARE_EXPORT HasProblems::EntityIterator&
00402 HasProblems::EntityIterator::operator=(const EntityIterator& o)
00403 {
00404
00405 if (this == &o) return *this;
00406
00407 this->~EntityIterator();
00408
00409 type = o.type;
00410 if (type==0) bufIter = new Buffer::iterator(*(o.bufIter));
00411 else if (type==1) resIter = new Resource::iterator(*(o.resIter));
00412 else if (type==2) operIter = new OperationPlan::iterator(*(o.operIter));
00413 else if (type==3) demIter = new Demand::iterator(*(o.demIter));
00414 return *this;
00415 }
00416
00417
00418 DECLARE_EXPORT bool
00419 HasProblems::EntityIterator::operator != (const EntityIterator& t) const
00420 {
00421
00422 if (type != t.type) return true;
00423
00424
00425 switch (type)
00426 {
00427
00428 case 0: return *bufIter != *(t.bufIter);
00429
00430 case 1: return *resIter != *(t.resIter);
00431
00432 case 2: return *operIter != *(t.operIter);
00433
00434 case 3: return *demIter != *(t.demIter);
00435
00436
00437 default: return false;
00438 }
00439 }
00440
00441
00442 DECLARE_EXPORT HasProblems& HasProblems::EntityIterator::operator*() const
00443 {
00444 switch (type)
00445 {
00446
00447 case 0: return **bufIter;
00448
00449 case 1: return **resIter;
00450
00451 case 2: return **operIter;
00452
00453 case 3: return **demIter;
00454 default: throw LogicException("Unreachable code reached");
00455 }
00456 }
00457
00458
00459 DECLARE_EXPORT HasProblems* HasProblems::EntityIterator::operator->() const
00460 {
00461 switch (type)
00462 {
00463
00464 case 0: return &**bufIter;
00465
00466 case 1: return &**resIter;
00467
00468 case 2: return &**operIter;
00469
00470 case 3: return &**demIter;
00471 default: throw LogicException("Unreachable code reached");
00472 }
00473 }
00474
00475
00476 DECLARE_EXPORT HasProblems::EntityIterator HasProblems::beginEntity()
00477 {
00478 return EntityIterator();
00479 }
00480
00481
00482 DECLARE_EXPORT HasProblems::EntityIterator HasProblems::endEntity()
00483 {
00484
00485
00486 return EntityIterator(4);
00487 }
00488
00489
00490 DECLARE_EXPORT Problem::const_iterator& Problem::const_iterator::operator++()
00491 {
00492
00493 if (!iter) return *this;
00494
00495
00496 iter = iter->nextProblem;
00497
00498
00499
00500 while (!iter && !owner && eiter!=HasProblems::endEntity())
00501 {
00502 ++eiter;
00503 if (eiter!=HasProblems::endEntity()) iter = eiter->firstProblem;
00504 }
00505 return *this;
00506 }
00507
00508
00509 DECLARE_EXPORT Problem::const_iterator Problem::begin()
00510 {
00511 Plannable::computeProblems();
00512 return const_iterator();
00513 }
00514
00515
00516 DECLARE_EXPORT Problem::const_iterator Problem::begin(HasProblems* i, bool refresh)
00517 {
00518
00519 if (!i) return begin();
00520
00521
00522 if (refresh) i->updateProblems();
00523 return const_iterator(i);
00524 }
00525
00526
00527 DECLARE_EXPORT const Problem::const_iterator Problem::end()
00528 {
00529 return const_iterator(NULL);
00530 }
00531
00532
00533 PyObject* Problem::getattro(const Attribute& attr)
00534 {
00535 if (attr.isA(Tags::tag_name))
00536 return PythonObject(getType().type);
00537 if (attr.isA(Tags::tag_description))
00538 return PythonObject(getDescription());
00539 if (attr.isA(Tags::tag_entity))
00540 return PythonObject(getEntity());
00541 if (attr.isA(Tags::tag_start))
00542 return PythonObject(getDateRange().getStart());
00543 if (attr.isA(Tags::tag_end))
00544 return PythonObject(getDateRange().getEnd());
00545 if (attr.isA(Tags::tag_weight))
00546 return PythonObject(getWeight());
00547 if (attr.isA(Tags::tag_owner))
00548 return PythonObject(getOwner());
00549 return NULL;
00550 }
00551
00552 }