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
