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: 713 $  $LastChangedBy: jdetaeye $
00004   date : $LastChangedDate: 2008-03-28 15:26:21 +0100 (Fri, 28 Mar 2008) $
00005  ***************************************************************************/
00006 
00007 /***************************************************************************
00008  *                                                                         *
00009  * Copyright (C) 2007 by Johan De Taeye                                    *
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA *
00024  *                                                                         *
00025  ***************************************************************************/
00026 
00027 #define FREPPLE_CORE
00028 #include "frepple/model.h"
00029 
00030 namespace frepple
00031 {
00032 
00033 
00034 DECLARE_EXPORT PeggingIterator::PeggingIterator(const Demand* d) : downstream(false)
00035 {
00036   // Loop through all delivery operationplans
00037   first = false;  // ... because the stack is still empty
00038   for (Demand::OperationPlan_list::const_iterator opplaniter = d->getDelivery().begin();
00039     opplaniter != d->getDelivery().end(); ++opplaniter)
00040     followPegging(*opplaniter, 0, (*opplaniter)->getQuantity(), 1.0);
00041 }
00042 
00043 
00044 DECLARE_EXPORT void PeggingIterator::updateStack
00045   (short l, double q, double f, const FlowPlan* fc, const FlowPlan* fp, bool p)
00046 {
00047   // Avoid very small pegging quantities
00048   if (q < ROUNDING_ERROR) return;
00049 
00050   if (first)
00051   {
00052     // We can update the current top element of the stack
00053     state& t = stack.top();
00054     t.cons_flowplan = fc;
00055     t.prod_flowplan = fp;
00056     t.qty = q;
00057     t.factor = f;
00058     t.level = l;
00059     t.pegged = p;
00060     first = false;
00061   }
00062   else
00063     // We need to create a new element on the stack
00064     stack.push(state(l, q, f, fc, fp, p));
00065 }
00066 
00067 
00068 DECLARE_EXPORT PeggingIterator& PeggingIterator::operator++()
00069 {
00070   // Validate
00071   if (stack.empty())
00072     throw LogicException("Incrementing the iterator beyond it's end");
00073   if (!downstream)
00074     throw LogicException("Incrementing a downstream iterator");
00075   state& st = stack.top();
00076 
00077   // Handle unconsumed material entries on the stack
00078   if (!st.pegged)
00079   {
00080     stack.pop();
00081     return *this;
00082   }
00083 
00084   // Mark the top entry in the stack as invalid, so it can be reused
00085   first = true;
00086 
00087   // Take the consuming flowplan and follow the pegging
00088   if (st.cons_flowplan)
00089     followPegging(st.cons_flowplan->getOperationPlan()->getTopOwner(),
00090       st.level-1, st.qty, st.factor);
00091 
00092   // Pop invalid entries from the stack
00093   if (first) stack.pop();
00094 
00095   return *this;
00096 }
00097 
00098 
00099 DECLARE_EXPORT PeggingIterator& PeggingIterator::operator--()
00100 {
00101   // Validate
00102   if (stack.empty())
00103     throw LogicException("Incrementing the iterator beyond it's end");
00104   if (downstream)
00105     throw LogicException("Decrementing an upstream iterator");
00106   state& st = stack.top();
00107 
00108   // Handle unconsumed material entries on the stack
00109   if (!st.pegged)
00110   {
00111     stack.pop();
00112     return *this;
00113   }
00114 
00115   // Mark the top entry in the stack as invalid, so it can be reused
00116   first = true;
00117 
00118   // Take the producing flowplan and follow the pegging
00119   if (st.prod_flowplan)
00120     followPegging(st.prod_flowplan->getOperationPlan()->getTopOwner(),
00121       st.level+1, st.qty, st.factor);
00122 
00123   // Pop invalid entries from the stack
00124   if (first) stack.pop();
00125 
00126   return *this;
00127 }
00128 
00129 
00130 DECLARE_EXPORT void PeggingIterator::followPegging
00131   (const OperationPlan* op, short nextlevel, double qty, double factor)
00132 {
00133   // For each flowplan (producing or consuming depending on whether we go
00134   // upstream or downstream) ask the buffer to give us the pegged flowplans.
00135   if (downstream)
00136     for (OperationPlan::FlowPlanIterator i = op->beginFlowPlans();
00137         i != op->endFlowPlans(); ++i)
00138     {
00139       // We're interested in consuming flowplans of an operationplan when
00140       // walking upstream.
00141       if (i->getQuantity()>ROUNDING_ERROR)
00142         i->getFlow()->getBuffer()->followPegging(*this, &*i, nextlevel, qty, factor);
00143     }
00144   else
00145     for (OperationPlan::FlowPlanIterator i = op->beginFlowPlans();
00146         i != op->endFlowPlans(); ++i)
00147     {
00148       // We're interested in consuming flowplans of an operationplan when
00149       // walking upstream.
00150       if (i->getQuantity()<-ROUNDING_ERROR)
00151         i->getFlow()->getBuffer()->followPegging(*this, &*i, nextlevel, qty, factor);
00152     }
00153 
00154   // Recursively call this function for all sub-operationplans.
00155   if (op->getSubOperationPlan())
00156     // There is only a single suboperationplan
00157     followPegging(op->getSubOperationPlan(), nextlevel, qty, factor);
00158   for (OperationPlan::OperationPlanList::const_iterator
00159       j = op->getSubOperationPlans().begin();
00160       j != op->getSubOperationPlans().end(); ++j)
00161     // There is a linked list of suboperationplans
00162     followPegging(*j, nextlevel, qty, factor);
00163 }
00164 
00165 } // End namespace

Documentation generated by  doxygen