Quintiq file version 2.0
|
#parent: #root
|
Method NextRe (
|
Number periodNumber,
|
ProductInStockingPoint_MP pisp
|
) as owning ProbabilityDistribution
|
{
|
TextBody:
|
[*
|
/*
|
nextre
|
calculates the new supply distribution
|
####################################
|
this will check how much the target changes from previous and calculate how much we would need to fulfill the change in target and the expected demand (including dependent demand from childs)
|
then it will calculate how much we have in upstream location as a total supply (based on nexts and nextre of upstream stockingpoint at period-leadtime)
|
taking minimum of what we want and what we can have will give us the distribution of the new supply
|
*/
|
|
dsum := 0.0;
|
prev_target := 0.0;
|
value := MEIO_Engine::GetZeroDistribution();
|
|
// if we do not set previous target, use the earlier (or manually set) value from mp
|
if( periodNumber-1 > 0
|
and periodNumber-1 <= pisp.MEIO_Leadtime() )
|
|
{
|
prev_target := pisp.GetPISPIPFromPeriodNumber( periodNumber - 1 ).TargetInQuantity();
|
}
|
//# if we cannot affect the new supply of this period, we use the value from mp
|
if( periodNumber <= pisp.MEIO_Leadtime() )
|
{
|
value := DiscreteDistribution::Construct( pisp.GetPISPIPFromPeriodNumber( periodNumber ).NewSupplyQuantity() );
|
}
|
// in other cases we need to calculate how much the siblings need and how much of the parent supply is used for this stocking point
|
// we calculate factor based on expected demands
|
// we assume infinite supply from root, so this is only needed in a case when parent is not root
|
else
|
{
|
factor := 1.0;
|
if( isnull( pisp.MEIO_ParentRoot() ) ) // if dummy supplier node is not the parent.
|
{
|
siblingDemand := this.ReDistOfWealth( pisp.MEIO_Parent(), periodNumber - pisp.MEIO_Leadtime() );
|
thisDemand := this.ReDistOfWealth(pisp, periodNumber )+ MEIO_Engine::GetDemandExpectedValue( pisp, periodNumber );
|
|
if( siblingDemand > 0 )
|
{
|
factor := thisDemand / siblingDemand;
|
}
|
// we force the factor to 1 due to bug that was previously in the redist_of_wealth, analysis of the effect of the factor should be done again
|
// without this forcing to 1, the effect from the upstream is far too big compared to evaluation
|
}
|
// collect the expected and variance from the childnodes of the periods based on the leadtime to childs
|
listofnodes := MEIO_Engine::GetTreePISP( pisp );
|
traverse( listofnodes, Elements, leaf )
|
{
|
future_period := periodNumber + this.GetLeadTime( leaf, pisp );
|
if( future_period <= this.LastPeriodNumber() )
|
{
|
dsum := dsum + MEIO_Engine::GetDemandExpectedValue( leaf, future_period );
|
}
|
// if the demand of childs would go over the planning horizon we use demand of the last period (that is, extrapolation of demands as constant)
|
else
|
{
|
dsum := dsum + MEIO_Engine::GetDemandExpectedValue( leaf, this.LastPeriodNumber() )
|
}
|
}
|
//# if previous period is set by us, then we use target from it
|
if( periodNumber > (pisp.MEIO_Leadtime() + 1 ) )
|
{
|
prev_target := pisp.GetPISPIPFromPeriodNumber( periodNumber - 1 ).MEIO_Target();
|
}
|
// we only take minimum of "what we want and what we have" if upstream is not root
|
if( isnull( pisp.MEIO_ParentRoot() ) ) // if dummy supplier node is not the parent.
|
{
|
parentResupply := null( ProbabilityDistribution );
|
// parentResupply is the the what we can have from parent
|
// if period-leadtime points to period where we cannot control the supply in upstream location, we simply assume sufficient supply in upstream
|
if ( periodNumber-pisp.MEIO_Leadtime() <= pisp.MEIO_Parent().MEIO_Leadtime() )
|
{
|
parentResupply := MEIO_Engine::GetDiracDistribution( this.MEIO_Parameters().InitialLargeValueParentResupply() ); //#huge number, assume we have enough supply if we cannot control upstream
|
}
|
// if we can control upstream supply, we will assume that we only have what the target in upstream allows us to have as calculated by nexts and nextre at upstream location
|
else
|
{
|
// this is where we make a recursive call - for efficientcy we want to replace it by stored distributions
|
|
dis1 := this.NextRe( periodNumber - pisp.MEIO_Leadtime(), pisp.MEIO_Parent() );
|
dis2 := this.NextS( periodNumber - pisp.MEIO_Leadtime(), pisp.MEIO_Parent() );
|
parentResupply := ProbabilityDistribution::Sum( dis1, dis2, this.MEIO_Parameters().SampleSizeForDistributions() );
|
}
|
// take minimum of what we can have and what we would want, and make sure it's positive (also don't use in place of "what we can have" a distribution that has negative values)
|
|
expr1 := ProbabilityDistribution::Sum( parentResupply, MEIO_Engine::GetDemandDistributionTimesMinusOne( pisp.MEIO_Parent(), periodNumber - pisp.MEIO_Leadtime() ));
|
expr2 := ProbabilityDistribution::Max ( expr1, MEIO_Engine::GetZeroDistribution(), this.MEIO_Parameters().SampleSizeForDistributions() );
|
factordistr := DiscreteDistribution::Construct( factor );
|
expr3 := ProbabilityDistribution::Multiply( expr2, factordistr, this.MEIO_Parameters().SampleSizeForDistributions() );
|
current_target := pisp.GetPISPIPFromPeriodNumber( periodNumber ).MEIO_Target();
|
valuefordirac := dsum + current_target - prev_target;
|
|
diracdistr := MEIO_Engine::GetDiracDistribution( valuefordirac );
|
expr4 := ProbabilityDistribution::Min( diracdistr, expr3, this.MEIO_Parameters().SampleSizeForDistributions() );
|
value := ProbabilityDistribution::Max( expr4, MEIO_Engine::GetZeroDistribution(), this.MEIO_Parameters().SampleSizeForDistributions() );
|
|
/* In R lingo the above computes the following for value:
|
value = Maximum(
|
Minimum(
|
diracDist( dsum + stockingpoint$targets[period] - prev_target),
|
factor*(
|
Maximum( parentResupply - stockingpoint$parent$demands[[period-stockingpoint$leadtime]],
|
zeroDist() ) )
|
),
|
zeroDist()
|
)
|
*/
|
}
|
//if upstream is root, we get what we want
|
else
|
{
|
current_target := pisp.GetPISPIPFromPeriodNumber( periodNumber ).MEIO_Target();
|
valuefordiscretedistr := maxvalue( dsum + current_target - prev_target, 0 )
|
value := MEIO_Engine::GetDiracDistribution( valuefordiscretedistr );
|
}
|
}
|
return &value;
|
*]
|
}
|