Quintiq file version 2.0
|
#parent: #root
|
Method Search (
|
ProductInStockingPointInPeriodPlanningLeaf pispip
|
) as Boolean
|
{
|
Description: 'Search procedure to determine safety stock level of a given pispip'
|
TextBody:
|
[*
|
period := pispip.MEIO_PeriodNumber();
|
node := pispip.ProductInStockingPoint_MP();
|
pisp_sl := pispip.GetServiceLevelPercentage() / 100
|
capped_margin := minvalue( this.MEIO_Parameters().InitialGuessMarigin(), pisp_sl );
|
guess := pisp_sl - capped_margin;
|
target := 0.0;
|
|
// Make an initial guess of target level based on the inverse of the cumulative distribution of the demand at the given PISPIP
|
if( pispip.SalesDemandQuantity() = 0 )
|
{
|
if ( this.MEIO_Parameters().OptionMakeInitialGuessForNoSalesDemand() )
|
{
|
leafset := selectset( MEIO_Engine::GetTreePISP( node ), Elements, n, true, n.MEIO_IsLeaf() );
|
avgdemand := average( leafset, Elements, leaf, true, leaf.GetPISPIPFromPeriodNumber( period ).MEIO_DemandExpectedValue() );
|
avgstd := average( leafset, Elements, leaf, true, leaf.GetPISPIPFromPeriodNumber( period ).MEIO_DemandStandardDeviation() );
|
avgdistr := MEIO_Engine::GetRandomDistribution( avgdemand, avgstd );
|
target := maxvalue( avgdistr.Quantile( guess ) -
|
avgdemand,
|
0 );
|
}
|
}
|
else
|
{
|
target := maxvalue( MEIO_Engine::GetDemandDistribution( node, period ).Quantile( guess ) -
|
MEIO_Engine::GetDemandExpectedValue( node, period ),
|
0 );
|
}
|
|
service_level := 0.0;
|
iter := 1;
|
continue := pispip.ProductInStockingPoint_MP().Echelon()>1
|
and (pispip.DependentDemandAndSalesDemandQuantity() > 0 or not pispip.ProductInStockingPoint_MP().IsMostDownstreamPisp() );
|
std := 0.0;
|
reachservicelevel := false;
|
if( continue )
|
{
|
std := this.AggregateStd( pispip.ProductInStockingPoint_MP(), pispip.MEIO_PeriodNumber() ); //get the standard deviation of the sales demand
|
}
|
smallesttarget_formaxservicelevel := target; // keep track of this and fall back on it if we do not manage to reach the required service level
|
maxservicelevelsofar := 0.0;
|
|
while( continue ) // While stopping condition is not reached, continue to predict service level for increasing targets
|
{
|
this.CallForServiceLevel( node, period, target, service_level, iter );
|
|
// Create snapshot
|
snapshot := null( MEIO_Snapshot );
|
if( this.MEIO_Parameters().CreateSnapshots() )
|
{
|
snapshot := MEIO_Snapshot::Create( this,
|
iter,
|
std,
|
target,
|
service_level,
|
pispip.ProductInStockingPoint_MP().Name(),
|
pispip.MEIO_PeriodNumber(),
|
MEIO_Snapshot::SEARCH(),
|
pisp_sl,
|
this.SupplyChain(),
|
-1.0, // max service level so far - supplied below
|
-1.0 ); // min target for max service level -supplied below
|
|
}
|
|
reachservicelevel := service_level >= pisp_sl;
|
continue := not reachservicelevel
|
and iter < this.MEIO_Parameters().NrOfIterations();
|
|
if ( MEIO_Engine::RoundToImprovementTolerance( service_level ) > maxservicelevelsofar )
|
{
|
smallesttarget_formaxservicelevel := target;
|
maxservicelevelsofar := MEIO_Engine::RoundToImprovementTolerance( service_level );
|
}
|
if ( this.MEIO_Parameters().CreateSnapshots() )
|
{
|
snapshot.MaxRoundedServiceLevelSoFar( maxservicelevelsofar );
|
snapshot.MinTargetForMaxRoundedServiceLevel( smallesttarget_formaxservicelevel );
|
}
|
iter := iter + 1;
|
|
// Increase target for next step
|
target := target + this.GetTargetIncrement( service_level, std, pispip );
|
} // while loop
|
|
if ( not reachservicelevel ) // did not manage to reach the service level, pick smallest target reaching max level
|
{
|
pispip.MEIO_Target( smallesttarget_formaxservicelevel );
|
pispip.MEIO_Stockin( maxservicelevelsofar );
|
|
if( this.MEIO_Parameters().CreateSnapshots() )
|
{
|
MEIO_Snapshot::Create( this,
|
iter,
|
std,
|
smallesttarget_formaxservicelevel,
|
maxservicelevelsofar,
|
pispip.ProductInStockingPoint_MP().Name(),
|
pispip.MEIO_PeriodNumber(),
|
MEIO_Snapshot::SEARCH() + MEIO_Engine::ServiceLevelNotReached(),
|
pisp_sl,
|
this.SupplyChain(),
|
maxservicelevelsofar,
|
smallesttarget_formaxservicelevel );
|
}
|
}
|
|
return true;
|
*]
|
}
|