Quintiq file version 2.0 
 | 
#parent: #root 
 | 
Method InitConstraintsForShelfLifeCumulativeDemand ( 
 | 
  CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program, 
 | 
  const ProductInStockingPointInPeriodPlanning pispip, 
 | 
  DateTime lastpispipstart, 
 | 
  DateTime firstafteractualstart, 
 | 
  const IncomingShelfLifeDay islday, 
 | 
  const LibOpt_Scope scope 
 | 
) const 
 | 
{ 
 | 
  Description: 'Initialize the constraints that are related to shelf life' 
 | 
  TextBody: 
 | 
  [* 
 | 
    cdconstname := typeof( MPCumulativeDemandConstraint ); 
 | 
    scalefactor_mass := this.ScaleConstraintTerm( typeof( MPSalesDemandQtyVariable ), cdconstname ); 
 | 
    scalefactor_rhs_constr := this.ScaleConstraintRHS( cdconstname, 1.0 );  
 | 
     
 | 
    previouspispip := pispip.PreviousPlanningPISPIP(); 
 | 
     
 | 
    constr := program.CumulativeDemandConstraints().New( pispip, islday );  
 | 
    constr.RHSValue( 0.0 );  
 | 
    constr.Sense( '=' );  
 | 
     
 | 
    var := program.CumulativeDemandVariables().Find( previouspispip, islday );  
 | 
    isfirstpispip := isnull( var );       
 | 
     
 | 
    if ( not isfirstpispip ) // once var = null then we are at the 1st period of extra pispip prior to opt horizon (for which we make sure we always have enough via method ShelfLifeExtendHistoricalPeriods 
 | 
    { 
 | 
       constr.NewTerm( 1.0 * scalefactor_mass, 
 | 
                       program.CumulativeDemandVariables().Get( previouspispip, islday ) ); 
 | 
    } 
 | 
     
 | 
    // sales and dependent demand applicable for CP(pispip, *)  
 | 
    pispipstoconsider := pispip.GetNextPISPIPWithinShelfLife( lastpispipstart ); // included pispip - still need to check for precise shelf life condition 
 | 
    product := pispip.ProductInStockingPoint_MP().Product_MP();  
 | 
     
 | 
    traverse( pispip, ProductInStockingPoint_MP.OutgoingShelfLifeDay, oslday )  
 | 
    { 
 | 
      traverse( pispipstoconsider,  
 | 
                Elements,  
 | 
                pispipnext,     
 | 
                CapacityPlanningSuboptimizer::ShelfLifeFilterArrivedForDemand( pispip, pispipnext, islday )   
 | 
                and CapacityPlanningSuboptimizer::GetIsUsableInTargetPeriod( product, pispip.Period_MP(), pispipnext.GetTargetPeriod( oslday ) ) 
 | 
                and ( isfirstpispip or not CapacityPlanningSuboptimizer::GetIsUsableInTargetPeriod( product, pispip.PreviousPlanningPISPIP().Period_MP(), pispipnext.GetTargetPeriod( oslday ) ) )  // only add what is new 
 | 
                and ( pispipnext.Start() >= firstafteractualstart ) )  // exclude sales, dep. demand prior to actual if it exists ) 
 | 
      {  
 | 
        constr.NewTerm( 1.0 * scalefactor_mass, program.DependentDemandInPISPIPShelfLifeVariables().Get( pispipnext, islday, oslday ) );  
 | 
        if ( oslday.ShelfLifeDays() = 0 and not oslday.IsZeroShelfLifeDaysForTrips() ) // the dependent demand var does not include sales demand so add separately (considered as outgoing lead time 0 
 | 
        { 
 | 
          traverse( pispipnext.GetLeafSalesDemandInPeriod(),  
 | 
                    Elements,  
 | 
                    lsdip,  
 | 
                    not lsdip.IsPostponed() ) 
 | 
          { 
 | 
              svar := program.SalesDemandQtyVariables().Find( lsdip ); 
 | 
              if ( not isnull( svar ) )  
 | 
              {  
 | 
                constr.NewTerm( 1.0 * scalefactor_mass, svar );  
 | 
              } 
 | 
              else 
 | 
              { 
 | 
                constr.RHSValue( constr.RHSValue() - scalefactor_rhs_constr * lsdip.FulfilledQuantity() );  
 | 
              } 
 | 
          } 
 | 
           
 | 
          // Postponed demands which are postponed to this period 
 | 
          previouspispip := pispipnext.PreviousPlanningPISPIP(); 
 | 
           
 | 
          maxnumberofpostponement := pispipnext.ProductInStockingPoint_MP().OptimizerMaxPostponementPeriod(); // set in init instance for performance  
 | 
          for( i := 1; 
 | 
               i <= maxnumberofpostponement       // within the maximum number of postponement periods 
 | 
               and not isnull( previouspispip );  // the previous pispip exists 
 | 
               i++ ) 
 | 
          { 
 | 
            traverse( previouspispip.astype( ProductInStockingPointInPeriodPlanningLeaf ), PlanningBaseSalesDemandInPeriodForOptimizationPostponable, sd ) 
 | 
            {                                              
 | 
              delayedvar := sd.GetDelayedSalesDemandShelfLifeQtyVariable( program, pispipnext.Period_MP(), islday );  
 | 
              if ( not isnull( delayedvar ) )  
 | 
              { 
 | 
                constr.NewTerm( 1.0 * scalefactor_mass, delayedvar );  
 | 
              } 
 | 
            } 
 | 
            previouspispip := previouspispip.PreviousPlanningPISPIP();  
 | 
          } 
 | 
        } 
 | 
      } 
 | 
    } 
 | 
    constr.NewTerm( -1.0 * scalefactor_mass, 
 | 
                   program.CumulativeDemandVariables().Get( pispip, islday )); 
 | 
  *] 
 | 
  InterfaceProperties { Accessibility: 'Module' } 
 | 
} 
 |