| Quintiq file version 2.0 | 
| #parent: #root | 
| Method NextS ( | 
|   Number periodNumber, | 
|   ProductInStockingPoint_MP pisp | 
| ) as owning ProbabilityDistribution | 
| { | 
|   TextBody: | 
|   [* | 
|     // calculates the starting stock distrbution of given period, at given stockingpoint | 
|     // if leadtime to stockingpoint is 2 periods | 
|     // calculation starts at period - 2 | 
|     // start by assuming that at period - 2 there is target left | 
|     // the loop through periods up to period-1, and at every period | 
|     // add expected demand and change in target, substract demand distribution and | 
|     // take maximum with 0, to not allow negative inventory | 
|      | 
|     dsum := MEIO_Engine::GetZeroDistribution(); | 
|     // if period - stockinpoint.leadtime is after start of planning horizon, we have target set a target that we can use | 
|     // based on the simulations, mp hardly ever reached the correct target, and interal service level tries to describe this | 
|      | 
|     if(  periodNumber > pisp.MEIO_Leadtime() )  | 
|     { | 
|       startminleadpispip := pisp.GetPISPIPFromPeriodNumber( periodNumber - pisp.MEIO_Leadtime() ); | 
|       dsum := MEIO_Engine::GetDiracDistribution( MEIO_Engine::GetInternalSeviceLevel() * startminleadpispip.MEIO_Target() );  | 
|     } | 
|     //# in other cases we start with the target of the first period that we have set earlier (or manually in mp) | 
|     else | 
|     { | 
|       pispip := pisp.FirstPlanningPISPIP();  | 
|       dsum := MEIO_Engine::GetDiracDistribution( pispip.TargetInQuantity() ); | 
|     } | 
|     // we only really calculate anything if leaditme is >0, if leadimte =0 we dont need safetystock at all | 
|     if ( pisp.MEIO_Leadtime() > 0) | 
|     { | 
|       // we collect all the children of the stockingpoint (we will aggregate the demand from these)     | 
|       listofnodes := MEIO_Engine::GetTreePISP( pisp ); //Traverse(stockingpoint, c('level')) | 
|       //#start period is leadtime ago or first period,  | 
|       startperiod := maxvalue( periodNumber - pisp.MEIO_Leadtime(), 1 ); //(meio_R_internal_period-pisp.MEIO_Leadtime(), 1) | 
|       //endperiod is previous period or start period | 
|       endperiod := maxvalue(startperiod, periodNumber-1) | 
|        | 
|       //if startperiod is endperiod we would only add the resupply of that and substract the demand | 
|       //in other cases we loop through all startperiod -> endperiod | 
|       | 
|       // we will add the expected demand and substract the demand distribution | 
|       traverse( listofnodes, Elements, nodepisp ) | 
|       { | 
|         standarddev := MEIO_Engine::GetDemandStandardDeviation( nodepisp, startperiod );   | 
|         dsum := ProbabilityDistribution::Sum( dsum,  NormalDistribution::Construct( 0.0, standarddev ), this.MEIO_Parameters().SampleSizeForDistributions() );  | 
|       }  | 
|       //# if there are other periods we do the same as for startperiod | 
|       for ( p:= startperiod + 1; p<= endperiod;  p++ ) | 
|       { | 
|         supply := 0.0;  | 
|          | 
|         // if period is before leadtime of the stockingpoint, we cannot control the supply anymore and thus we use the values from mp | 
|         if ( p <= pisp.MEIO_Leadtime() )   | 
|         { | 
|           supply := maxvalue( pisp.GetPISPIPFromPeriodNumber( p ).NewSupplyQuantity(),  | 
|                               MEIO_Engine::GetDemandExpectedValue(pisp, p ) ) //);  | 
|         } | 
|         //# in other cases we use as a supply the change in targets + expected demand | 
|         else | 
|         { | 
|           supply := maxvalue( MEIO_Engine::GetDemandExpectedValue( pisp, p )  | 
|                               + pisp.GetPISPIPFromPeriodNumber( p ).MEIO_Target() | 
|                               - pisp.GetPISPIPFromPeriodNumber( p - 1 ).MEIO_Target(),  | 
|                               0 );  | 
|         } | 
|         // here we add the supply and substract the demand distribution | 
|          | 
|         minusdemanddistr := MEIO_Engine::GetDemandDistributionTimesMinusOne( pisp, p ); // workaround because ProbabilityDistribution::Subtract gives verify errors | 
|         dsum := ProbabilityDistribution::Sum( dsum, minusdemanddistr, this.MEIO_Parameters().SampleSizeForDistributions() );  | 
|         dsum := ProbabilityDistribution::Sum( dsum, DiscreteDistribution::Construct( supply ), this.MEIO_Parameters().SampleSizeForDistributions() );  | 
|         // for the child nodes we do not add change in targets as supply, only the expected demands | 
|         if(p > pisp.MEIO_Leadtime() )  | 
|         { | 
|           if(listofnodes.Size() > 1 )  | 
|           { | 
|             traverse( listofnodes, Elements, node, not node = pisp )  | 
|             { | 
|               nodeminusdemanddistr := MEIO_Engine::GetDemandDistributionTimesMinusOne( node, p ) | 
|               dsum := ProbabilityDistribution::Sum( dsum, nodeminusdemanddistr, this.MEIO_Parameters().SampleSizeForDistributions() );  | 
|               dsum := ProbabilityDistribution::Sum( dsum, DiscreteDistribution::Construct( MEIO_Engine::GetDemandExpectedValue( node, p ) ), this.MEIO_Parameters().SampleSizeForDistributions() );   | 
|             } // traverse | 
|           } // if  | 
|         } // if  | 
|       } // for loop | 
|     } // if  | 
|      | 
|     // we don't allow negative inventory | 
|     dsum := ProbabilityDistribution::Max( dsum, MEIO_Engine::GetZeroDistribution(), this.MEIO_Parameters().SampleSizeForDistributions() );  | 
|      | 
|     return &dsum; | 
|   *] | 
| } |