pegging.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002   file : $URL: https://frepple.svn.sourceforge.net/svnroot/frepple/trunk/src/model/pegging.cpp $
00003   version : $LastChangedRevision: 1505 $  $LastChangedBy: jdetaeye $
00004   date : $LastChangedDate: 2011-08-26 18:55:08 +0200 (Fri, 26 Aug 2011) $
00005  ***************************************************************************/
00006 
00007 /***************************************************************************
00008  *                                                                         *
00009  * Copyright (C) 2007-2011 by Johan De Taeye, frePPLe bvba                 *
00010  *                                                                         *
00011  * This library is free software; you can redistribute it and/or modify it *
00012  * under the terms of the GNU Lesser General Public License as published   *
00013  * by the Free Software Foundation; either version 2.1 of the License, or  *
00014  * (at your option) any later version.                                     *
00015  *                                                                         *
00016  * This library is distributed in the hope that it will be useful,         *
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser *
00019  * General Public License for more details.                                *
00020  *                                                                         *
00021  * You should have received a copy of the GNU Lesser General Public        *
00022  * License along with this library; if not, write to the Free Software     *
00023  * Foundation Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,*
00024  * USA                                                                     *
00025  *                                                                         *
00026  ***************************************************************************/
00027 
00028 #define FREPPLE_CORE
00029 #include "frepple/model.h"
00030 
00031 namespace frepple
00032 {
00033 
00034 DECLARE_EXPORT const MetaCategory* PeggingIterator::metadata;
00035 
00036 
00037 int PeggingIterator::initialize()
00038 {
00039   // Initialize the pegging metadata
00040   PeggingIterator::metadata = new MetaCategory("pegging","peggings");
00041 
00042   // Initialize the Python type
00043   PythonType& x = PythonExtension<PeggingIterator>::getType();
00044   x.setName("peggingIterator");
00045   x.setDoc("frePPLe iterator for demand pegging");
00046   x.supportgetattro();
00047   x.supportiter();
00048   const_cast<MetaCategory*>(PeggingIterator::metadata)->pythonClass = x.type_object();
00049   return x.typeReady();
00050 }
00051 
00052 
00053 DECLARE_EXPORT PeggingIterator::PeggingIterator(const Demand* d)
00054   : downstream(false), firstIteration(true)
00055 {
00056   // Loop through all delivery operationplans
00057   first = false;  // ... because the stack is still empty
00058   for (Demand::OperationPlan_list::const_iterator opplaniter = d->getDelivery().begin();
00059     opplaniter != d->getDelivery().end(); ++opplaniter)
00060     followPegging(*opplaniter, 0, (*opplaniter)->getQuantity(), 1.0);
00061 
00062   // Initialize Python type information
00063   initType(metadata);
00064 }
00065 
00066 
00067 DECLARE_EXPORT void PeggingIterator::updateStack
00068   (short l, double q, double f, const FlowPlan* fc, const FlowPlan* fp, bool p)
00069 {
00070   // Avoid very small pegging quantities
00071   if (q < 0.1) return;
00072 
00073   if (first)
00074   {
00075     // We can update the current top element of the stack
00076     state& t = states.top();
00077     t.cons_flowplan = fc;
00078     t.prod_flowplan = fp;
00079     t.qty = q;
00080     t.factor = f;
00081     t.level = l;
00082     t.pegged = p;
00083     first = false;
00084   }
00085   else
00086     // We need to create a new element on the stack
00087     states.push(state(l, q, f, fc, fp, p));
00088 }
00089 
00090 
00091 DECLARE_EXPORT PeggingIterator& PeggingIterator::operator++()
00092 {
00093   // Validate
00094   if (states.empty())
00095     throw LogicException("Incrementing the iterator beyond it's end");
00096   if (!downstream)
00097     throw LogicException("Incrementing a downstream iterator");
00098   state& st = states.top();
00099 
00100   // Handle unconsumed material entries on the stack
00101   if (!st.pegged)
00102   {
00103     states.pop();
00104     return *this;
00105   }
00106 
00107   // Mark the top entry in the stack as invalid, so it can be reused
00108   first = true;
00109 
00110   // Take the consuming flowplan and follow the pegging
00111   if (st.cons_flowplan)
00112     followPegging(st.cons_flowplan->getOperationPlan()->getTopOwner(),
00113       st.level-1, st.qty, st.factor);
00114 
00115   // Pop invalid entries from the stack
00116   if (first) states.pop();
00117 
00118   return *this;
00119 }
00120 
00121 
00122 DECLARE_EXPORT PeggingIterator& PeggingIterator::operator--()
00123 {
00124   // Validate
00125   if (states.empty())
00126     throw LogicException("Incrementing the iterator beyond it's end");
00127   if (downstream)
00128     throw LogicException("Decrementing an upstream iterator");
00129   state& st = states.top();
00130 
00131   // Handle unconsumed material entries on the stack
00132   if (!st.pegged)
00133   {
00134     states.pop();
00135     return *this;
00136   }
00137 
00138   // Mark the top entry in the stack as invalid, so it can be reused
00139   first = true;
00140 
00141   // Take the producing flowplan and follow the pegging
00142   if (st.prod_flowplan)
00143     followPegging(st.prod_flowplan->getOperationPlan()->getTopOwner(),
00144       st.level+1, st.qty, st.factor);
00145 
00146   // Pop invalid entries from the stack
00147   if (first) states.pop();
00148 
00149   return *this;
00150 }
00151 
00152 
00153 DECLARE_EXPORT void PeggingIterator::followPegging
00154   (const OperationPlan* op, short nextlevel, double qty, double factor)
00155 {
00156   // For each flowplan (producing or consuming depending on whether we go
00157   // upstream or downstream) ask the buffer to give us the pegged flowplans.
00158   bool noFlowPlans = true;
00159   if (downstream)
00160     for (OperationPlan::FlowPlanIterator i = op->beginFlowPlans();
00161         i != op->endFlowPlans(); ++i)
00162     {
00163       // We're interested in producing flowplans of an operationplan when
00164       // walking downstream.
00165       if (i->getQuantity()>ROUNDING_ERROR)
00166       {
00167         i->getFlow()->getBuffer()->followPegging(*this, &*i, nextlevel, qty, factor);
00168         noFlowPlans = false;
00169       }
00170     }
00171   else
00172     for (OperationPlan::FlowPlanIterator i = op->beginFlowPlans();
00173         i != op->endFlowPlans(); ++i)
00174     {
00175       // We're interested in consuming flowplans of an operationplan when
00176       // walking upstream.
00177       if (i->getQuantity()<-ROUNDING_ERROR)
00178       {
00179         i->getFlow()->getBuffer()->followPegging(*this, &*i, nextlevel, qty, factor);
00180         noFlowPlans = false;
00181       }
00182     }
00183 
00184   // Special case: the operationplan doesn't have flowplans
00185   // @todo if (noFlowPlans) updateStack(nextlevel, qty, factor, NULL, NULL);
00186 
00187   // Recursively call this function for all sub-operationplans.
00188   for (OperationPlan::iterator j(op); j != OperationPlan::end(); ++j)
00189     followPegging(&*j, nextlevel, qty, factor);
00190 }
00191 
00192 
00193 DECLARE_EXPORT PyObject* PeggingIterator::iternext()
00194 {
00195   if (firstIteration)
00196     firstIteration = false;
00197   else
00198     operator--();
00199   if (!operator bool()) return NULL;
00200   Py_INCREF(this);
00201   return static_cast<PyObject*>(this);
00202 }
00203 
00204 
00205 DECLARE_EXPORT PyObject* PeggingIterator::getattro(const Attribute& attr)
00206 {
00207   if (attr.isA(Tags::tag_level))
00208     return PythonObject(getLevel());
00209   if (attr.isA(Tags::tag_consuming))
00210     return PythonObject(getConsumingOperationplan());
00211   if (attr.isA(Tags::tag_producing))
00212     return PythonObject(getProducingOperationplan());
00213   if (attr.isA(Tags::tag_buffer))
00214     return PythonObject(getBuffer());
00215   if (attr.isA(Tags::tag_quantity_demand))
00216     return PythonObject(getQuantityDemand());
00217   if (attr.isA(Tags::tag_quantity_buffer))
00218     return PythonObject(getQuantityBuffer());
00219   if (attr.isA(Tags::tag_pegged))
00220     return PythonObject(getPegged());
00221   if (attr.isA(Tags::tag_consuming_date))
00222     return PythonObject(getConsumingDate());
00223   if (attr.isA(Tags::tag_producing_date))
00224     return PythonObject(getProducingDate());
00225   return NULL;
00226 }
00227 
00228 
00229 } // End namespace

Documentation generated for frePPLe by  doxygen