Quintiq file version 2.0 
 | 
#parent: #root 
 | 
Method InitConstraintsForShelfLifeSumConstraints ( 
 | 
  CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program, 
 | 
  const constcontent ProductInStockingPointInPeriods smartplanpispips, 
 | 
  constcontent ProductInStockingPoint_MPs intermediatepisps, 
 | 
  const ProductInStockingPointInPeriodPlanning pispip, 
 | 
  DateTime firstpispipstart, 
 | 
  DateTime lastpispipstart, 
 | 
  const LibOpt_Scope scope, 
 | 
  Real scalefactor_mass, 
 | 
  Real scalefactor_rhs_constr 
 | 
) const 
 | 
{ 
 | 
  Description: 'sum constraints split variables' 
 | 
  TextBody: 
 | 
  [* 
 | 
    // >> sum of split InvQty = InvQty  
 | 
    { 
 | 
      constr := program.InvQtyShelfLifeSumConstraints().New( pispip );  
 | 
      if ( scope.Contains( pispip.PISPIPInOptimizerRun() ) )  
 | 
      { 
 | 
        constr.NewTerm( -1.0 * scalefactor_mass, program.InvQtyVariables().Get( pispip ) );  
 | 
      } 
 | 
      else 
 | 
      { 
 | 
        constr.RHSValue( pispip.InventoryLevelEnd() * scalefactor_rhs_constr ); // optimizer itself figure out what has expired - so just sum to the total inventory quantity.  
 | 
      } 
 | 
      traverse( pispip, ProductInStockingPoint_MP.IncomingShelfLifeDay, islday )   
 | 
      { 
 | 
        constr.NewTerm( 1.0 * scalefactor_mass, program.InvQtyShelfLifeVariables().Get( pispip, islday ) );  
 | 
      } 
 | 
    } 
 | 
     
 | 
    // sum of split dependent demand = dependent demand  
 | 
    { 
 | 
      constr := program.DependentDemandInPISPIPShelfLifeSumConstraints().New( pispip ); 
 | 
      if ( scope.Contains( pispip.PISPIPInOptimizerRun() ) )  
 | 
      { 
 | 
        constr.NewTerm( -1.0 * scalefactor_mass, program.DependentDemandInPISPIPVariables().Get( pispip ) );  
 | 
      } 
 | 
      else 
 | 
      { 
 | 
        constr.RHSValue( scalefactor_rhs_constr * pispip.DependentDemandQuantity() );  
 | 
      } 
 | 
      traverse( pispip, ProductInStockingPoint_MP.IncomingShelfLifeDay, islday )   
 | 
      { 
 | 
        traverse( pispip, ProductInStockingPoint_MP.OutgoingShelfLifeDay, oslday )  
 | 
        { 
 | 
          constr.NewTerm( 1.0 * scalefactor_mass, program.DependentDemandInPISPIPShelfLifeVariables().Get( pispip, islday, oslday ) );  
 | 
        } 
 | 
      } 
 | 
    } 
 | 
    // sum of split expired = expired on pispip 
 | 
    { 
 | 
      constr := program.ExpiredConstraints().New( pispip );  
 | 
      constr.NewTerm( -1.0 * scalefactor_mass, program.ExpiredVariables().Get( pispip ) );  
 | 
      traverse( pispip, ProductInStockingPoint_MP.IncomingShelfLifeDay, islday )  
 | 
      { 
 | 
        constr.NewTerm( 1.0 * scalefactor_mass, program.ExpiredForAgeVariables().Get( pispip, islday ) );  
 | 
      } 
 | 
    } 
 | 
     
 | 
     
 | 
    traverse( pispip.GetLeafSalesDemandInPeriod(), Elements, lsdip, not lsdip.IsPostponed() ) 
 | 
    { 
 | 
      constr := program.SalesDemandQtyShelfLifeSumConstraints().New( lsdip );  
 | 
      if( scope.Contains( pispip.PISPIPInOptimizerRun() ) )   
 | 
      { 
 | 
        constr.NewTerm( -1.0 * scalefactor_mass, program.SalesDemandQtyVariables().Get( lsdip ) );  
 | 
      } 
 | 
      else 
 | 
      { 
 | 
        constr.RHSValue( lsdip.FulfilledQuantity() * scalefactor_rhs_constr );  
 | 
      } 
 | 
      traverse( lsdip, ProductInStockingPoint_MP.IncomingShelfLifeDay, islday )  
 | 
      { 
 | 
        constr.NewTerm( 1.0 * scalefactor_mass, program.SalesDemandShelfLifeQtyVariables().Get( lsdip, islday ) );  
 | 
      } 
 | 
       
 | 
      if( lsdip.CanBePostponed() and lsdip.NeedsToBePlanned() ) 
 | 
      { 
 | 
        nextpispip := lsdip.AsPlanningBaseSalesDemandInPeriod().NextPlanningPISPIP(); 
 | 
        minpostponement := guard( lsdip.SDIPBeforeScopeInRun().OptMinPostponementPeriod(), 1 ); // if object null, then no min postponement  
 | 
        for( i := 2; i <= minpostponement and not isnull( nextpispip ); i++ ) 
 | 
        { 
 | 
          nextpispip := nextpispip.NextPlanningPISPIP(); 
 | 
        } 
 | 
         
 | 
        for( i := minpostponement; 
 | 
             i <= lsdip.MaxPostponementPeriod()                                           // within the maximum number of postponement periods 
 | 
             and not isnull( nextpispip );                                          // the next pispip exists 
 | 
             i++ ) 
 | 
        { 
 | 
          constrsum := program.DelayedSalesDemandQtyShelfLifeSumConstraints().New( lsdip, nextpispip.Period_MP() ); 
 | 
          if ( scope.Contains(  nextpispip.PISPIPInOptimizerRun() ) )  
 | 
          // can avoid scope.Contains(  nextpispip.PISPIPInOptimizerRun() ) ) because we are in the same transaction 
 | 
          { 
 | 
            constrsum.NewTerm( -1.0 * scalefactor_mass, program.DelayedSalesDemandQtyVariables().Get( lsdip, nextpispip.Period_MP() ) ); 
 | 
          } 
 | 
          else 
 | 
          { 
 | 
            postponedty := sum( lsdip, PostponedSalesDemand, psd, psd.ProductInStockingPointInPeriodPlanning() = nextpispip, psd.QuantityToPlan() );  
 | 
            constrsum.RHSValue( postponedty * scalefactor_rhs_constr );  
 | 
          } 
 | 
          traverse( lsdip, ProductInStockingPoint_MP.IncomingShelfLifeDay, islday )  
 | 
          { 
 | 
            splitvar := program.DelayedSalesDemandShelfLifeQtyVariables().Get( lsdip, nextpispip.Period_MP(), islday ); 
 | 
            constrsum.NewTerm( 1.0 * scalefactor_mass, splitvar );  
 | 
          } 
 | 
          nextpispip := nextpispip.NextPlanningPISPIP(); 
 | 
        } 
 | 
      }  
 | 
    } 
 | 
     
 | 
    traverse( pispip.GetDisaggregatedSalesDemandInPeriod(), Elements, dsdip ) 
 | 
    { 
 | 
      constr := program.DisAggregatedSalesDemandQtyShelfLifeSumConstraints().New( dsdip );  
 | 
      if ( scope.Contains( pispip.PISPIPInOptimizerRun() ) )  
 | 
      // can avoid scope.Contains( pispip.PISPIPInOptimizerRun() ) ) because we are in the same transaction 
 | 
      { 
 | 
        constr.NewTerm( -1.0 *scalefactor_mass, program.DisaggregatedSalesDemandQtyVariables().Get( dsdip ) );  
 | 
      } 
 | 
      else 
 | 
      { 
 | 
        constr.RHSValue( dsdip.FulfilledQuantity() * scalefactor_rhs_constr );  
 | 
      } 
 | 
      traverse( dsdip, ProductInStockingPoint_MP.IncomingShelfLifeDay, islday )  
 | 
      { 
 | 
        program.DisaggregatedSalesDemandShelfLifeQtyVariables().Get( dsdip, islday ); 
 | 
      } 
 | 
       
 | 
      if ( dsdip.CanBePostponed() and dsdip.NeedsToBePlanned() )  
 | 
      { 
 | 
     
 | 
        nextperiod := dsdip.AsSalesDemandInPeriodBase().Period_MP().NextPlanningPeriod();  // It is not possible to traverse PISPIP from disaggregated but not from Aggregated. 
 | 
        minpostponement := guard( dsdip.AggregatedSalesDemandInPeriod().SDIPBeforeScopeInRun().OptMinPostponementPeriod(), 1 ); // if object null, then no min postponement  
 | 
        for( i := 2; i <= minpostponement and not isnull( nextperiod ); i++ ) 
 | 
        { 
 | 
          nextperiod := nextperiod.NextPlanningPeriod(); 
 | 
        } 
 | 
         
 | 
        for( i := minpostponement; 
 | 
             i <= dsdip.MaxPostponementPeriod()                                           // within the maximum number of postponement periods 
 | 
             and not isnull( nextperiod );                                          // the next pispip exists 
 | 
             i++ ) 
 | 
        { 
 | 
          constrsum := program.DelayedDisaggregatedSalesDemandQtyShelfLifeSumConstraints().New( dsdip, nextperiod );  
 | 
          var := program.DelayedDisaggregatedSalesDemandQtyVariables().Get( dsdip, nextperiod );  
 | 
          if ( not isnull( var ) ) // if we are in the optimizer scope we need to use te var other obtain from model  
 | 
          { 
 | 
            constrsum.NewTerm( -1.0 * scalefactor_mass, var );  
 | 
          } 
 | 
          else 
 | 
          { 
 | 
            postponedqty := sum( dsdip, PostponedSalesDemand, psd, psd.ProductInStockingPointInPeriodPlanning().Period_MP() = nextperiod, psd.QuantityToPlan() );   
 | 
            constrsum.RHSValue( postponedqty * scalefactor_rhs_constr );  
 | 
          } 
 | 
          traverse( dsdip, ProductInStockingPoint_MP.IncomingShelfLifeDay, islday )  
 | 
          { 
 | 
            constrsum.NewTerm( 1.0 * scalefactor_mass, program.DelayedDisaggregatedSalesDemandShelfLifeQtyVariables().Get( dsdip, nextperiod, islday ) );  
 | 
          } 
 | 
          nextperiod := nextperiod.NextPlanningPeriod(); 
 | 
        } 
 | 
      } 
 | 
    } 
 | 
  *] 
 | 
  InterfaceProperties { Accessibility: 'Module' } 
 | 
} 
 |