Go to the documentation of this file.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 "forecast.h"
00029
00030 namespace module_forecast
00031 {
00032
00033 const MetaClass *ForecastSolver::metadata;
00034
00035 int ForecastSolver::initialize()
00036 {
00037
00038 metadata = new MetaClass("solver", "solver_forecast",
00039 Object::createString<ForecastSolver>);
00040
00041
00042 return FreppleClass<ForecastSolver,Solver>::initialize();
00043 }
00044
00045
00046 bool ForecastSolver::callback(Demand* l, const Signal a)
00047 {
00048
00049 solve(l, NULL);
00050
00051
00052 return true;
00053 }
00054
00055
00056 void ForecastSolver::writeElement(XMLOutput *o, const Keyword& tag, mode m) const
00057 {
00058
00059 if (m == REFERENCE)
00060 {
00061 o->writeElement
00062 (tag, Tags::tag_name, getName(), Tags::tag_type, getType().type);
00063 return;
00064 }
00065
00066
00067 if (m != NOHEADER) o->BeginObject
00068 (tag, Tags::tag_name, getName(), Tags::tag_type, getType().type);
00069
00070
00071 Solver::writeElement(o, tag, NOHEADER);
00072 }
00073
00074
00075 void ForecastSolver::solve(const Demand* l, void* v)
00076 {
00077
00078 if (!l || dynamic_cast<const Forecast*>(l) || l->getHidden()) return;
00079
00080
00081 if (getLogLevel()>0)
00082 logger << " Netting of demand '" << l << "' ('" << l->getCustomer()
00083 << "','" << l->getItem() << "', '" << l->getDeliveryOperation()
00084 << "'): " << l->getDue() << ", " << l->getQuantity() << endl;
00085
00086
00087 Forecast *fcst = matchDemandToForecast(l);
00088
00089 if (!fcst)
00090 {
00091
00092 if (getLogLevel()>0)
00093 logger << " No matching forecast available" << endl;
00094 return;
00095 }
00096 else if (getLogLevel()>0)
00097 logger << " Matching forecast: " << fcst << endl;
00098
00099
00100 netDemandFromForecast(l,fcst);
00101 }
00102
00103
00104 void ForecastSolver::solve(void *v)
00105 {
00106
00107
00108 sortedDemandList l;
00109 for (Demand::iterator i = Demand::begin(); i != Demand::end(); ++i)
00110
00111 if (!dynamic_cast<Forecast*>(&*i)
00112 && !dynamic_cast<ForecastBucket*>(&*i))
00113 l.insert(&*i);
00114
00115
00116 for(sortedDemandList::iterator i = l.begin(); i != l.end(); ++i)
00117 try {solve(*i, NULL);}
00118 catch (...)
00119 {
00120
00121 logger << "Error: Caught an exception while netting demand '"
00122 << (*i)->getName() << "':" << endl;
00123 try {throw;}
00124 catch (bad_exception&) {logger << " bad exception" << endl;}
00125 catch (exception& e) {logger << " " << e.what() << endl;}
00126 catch (...) {logger << " Unknown type" << endl;}
00127 }
00128 }
00129
00130
00131 Forecast* ForecastSolver::matchDemandToForecast(const Demand* l)
00132 {
00133 pair<const Item*, const Customer*> key
00134 = make_pair(&*(l->getItem()), &*(l->getCustomer()));
00135
00136 do
00137 {
00138 do
00139 {
00140 Forecast::MapOfForecasts::iterator x = Forecast::ForecastDictionary.lower_bound(key);
00141
00142
00143 while (x != Forecast::ForecastDictionary.end() && x->first == key)
00144 {
00145 if (!Forecast::getMatchUsingDeliveryOperation()
00146 || x->second->getDeliveryOperation() == l->getDeliveryOperation())
00147
00148 return x->second;
00149 else
00150 ++ x;
00151 }
00152
00153 if (Forecast::Customer_Then_Item_Hierarchy)
00154 {
00155
00156 if (key.second) key.second = key.second->getOwner();
00157 else break;
00158 }
00159 else
00160 {
00161
00162 if (key.first) key.first = key.first->getOwner();
00163 else break;
00164 }
00165 }
00166 while (true);
00167
00168
00169
00170
00171 if (Forecast::Customer_Then_Item_Hierarchy)
00172 {
00173
00174 if (key.first) key.first = key.first->getOwner();
00175 else return NULL;
00176
00177 key.second = &*(l->getCustomer());
00178 }
00179 else
00180 {
00181
00182 if (key.second) key.second = key.second->getOwner();
00183 else return NULL;
00184
00185 key.first = &*(l->getItem());
00186 }
00187 }
00188 while (true);
00189 }
00190
00191
00192 void ForecastSolver::netDemandFromForecast(const Demand* dmd, Forecast* fcst)
00193 {
00194
00195 ForecastBucket* zerobucket = NULL;
00196 for (Forecast::memberIterator i = fcst->beginMember(); i != fcst->endMember(); ++i)
00197 {
00198 zerobucket = dynamic_cast<ForecastBucket*>(&*i);
00199 if (zerobucket && zerobucket->getDueRange().within(dmd->getDue())) break;
00200 }
00201 if (!zerobucket)
00202 throw LogicException("Can't find forecast bucket for "
00203 + string(dmd->getDue()) + " in forecast '" + fcst->getName() + "'");
00204
00205
00206 double remaining = dmd->getQuantity();
00207 ForecastBucket* curbucket = zerobucket;
00208 bool backward = true;
00209 while ( remaining > 0 && curbucket
00210 && (dmd->getDue()-Forecast::getNetEarly() < curbucket->getDueRange().getEnd())
00211 && (dmd->getDue()+Forecast::getNetLate() >= curbucket->getDueRange().getStart())
00212 )
00213 {
00214
00215 double available = curbucket->getQuantity();
00216 if (available > 0)
00217 {
00218 if (available >= remaining)
00219 {
00220
00221 if (getLogLevel()>=2)
00222 logger << " Consuming " << remaining << " from bucket "
00223 << curbucket->getDueRange() << " (" << available
00224 << " available)" << endl;
00225 curbucket->incConsumed(remaining);
00226 remaining = 0;
00227 }
00228 else
00229 {
00230
00231 if (getLogLevel()>=2)
00232 logger << " Consuming " << available << " from bucket "
00233 << curbucket->getDueRange() << " (" << available
00234 << " available)" << endl;
00235 remaining -= available;
00236 curbucket->incConsumed(available);
00237 }
00238 }
00239 else if (getLogLevel()>=2)
00240 logger << " Nothing available in bucket "
00241 << curbucket->getDueRange() << endl;
00242
00243
00244 if (backward)
00245 {
00246
00247 curbucket = curbucket->getPreviousBucket();
00248 if (!curbucket)
00249 {
00250 backward = false;
00251 curbucket = zerobucket->getNextBucket();
00252 }
00253 }
00254 else
00255
00256 curbucket = curbucket->getNextBucket();
00257 }
00258
00259
00260 if (remaining > 0 && getLogLevel()>=2)
00261 logger << " Remains " << remaining << " that can't be netted" << endl;
00262
00263 }
00264
00265 }