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; 
 | 
  *] 
 | 
} 
 |