Quintiq file version 2.0 
 | 
#parent: #root 
 | 
Method InitConstraintsForBalanceNoShelfLife ( 
 | 
  CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program, 
 | 
  const constcontent ProductInStockingPointInPeriods smartplanpispips, 
 | 
  constcontent ProductInStockingPoint_MPs intermediatepisps, 
 | 
  const ProductInStockingPointInPeriodPlanningLeaf pispip, 
 | 
  const RunContextForCapacityPlanning runcontext, 
 | 
  const LibOpt_Scope scope, 
 | 
  Real scalefactor_demandslack_const, 
 | 
  Real scalefactor_tripnewsupply_const, 
 | 
  Real scalefactor_invqty_const, 
 | 
  Real scalefactor_salesdemandqty_const, 
 | 
  Real scalefactor_dependentdemandinpispip_const, 
 | 
  Real scalefactor_delayedsalesdemandqty_const, 
 | 
  Real scalefactor_periodtaskqty_const, 
 | 
  Real scalefactor_expired_const, 
 | 
  Real scalefactor_rhs_constr 
 | 
) const 
 | 
{ 
 | 
  Description: 
 | 
  [* 
 | 
    To balance the demands and supply in pispip 
 | 
    Dependent demands must be fulfilled in full quantity. Sales demands can be fulfilled halfly. 
 | 
  *] 
 | 
  TextBody: 
 | 
  [* 
 | 
    //   SUM( factor * relativeduration * PTQty ( operationoutput.operation, ptperiod ) 
 | 
    // + SUM( TripNewSupply ( newsupply.productintrip )  
 | 
    // + InvQty ( Previous )  
 | 
    // - SUM( SalesDemandQty ( leaf sales demand ) ) 
 | 
    // - SUM( DelayedSalesDemandQty ( delayed leaf sales demand ) ) 
 | 
    // - SUM( DisaggregatedSalesDemandQty ( disaggregated sales demand ) ) 
 | 
    // - SUM( DelayedDisaggregatedSalesDemandQty( delayed disaggregated sales demand ) ) 
 | 
    // - DependentDemandInPISPIP 
 | 
    // - TargetInvQty 
 | 
    // - UnallocQty  
 | 
    // - Expiry (pispip)  
 | 
    // = - InventorySupplyQuantity âˆ€ pispip where operationoutput, newsupply, sales demands   âˆˆ pispip 
 | 
     
 | 
     
 | 
     
 | 
                                  
 | 
    // unallocated supply = new supply + inventory supply + inventory carried forward - demands (sales demands ( Leaf sales demands and Disaggregated sales demands), dependent demand, inventory demand ) 
 | 
    // constr constraint UoM: PISP 
 | 
     
 | 
     
 | 
     
 | 
    constr := program.BalanceConstraints().New( pispip ); 
 | 
    constr.Sense( '=' ); 
 | 
     
 | 
    // RHS UoM: PISP 
 | 
    rhs := this.GetInventoryRHSForBalanceConstraint( pispip, runcontext, scope ); 
 | 
    rhs_scaled := rhs * scalefactor_rhs_constr 
 | 
    constr.RHSValue( rhs_scaled ); 
 | 
     
 | 
    // Inventory end for pispip 
 | 
    // Term UoM: PISP 
 | 
    constr.NewTerm( -1.0 * scalefactor_invqty_const, program.InvQtyVariables().Get( pispip ) ); 
 | 
     
 | 
    // Penalty for decreasing demand quantity in a pispip for balancing the constraint 
 | 
    // (A positive DemandSlack represents a supply that is "magically" created to even out the balance constraint) 
 | 
    // Term UoM: PISP 
 | 
    // Remove the slack in case we only plan 1 step upstream and it is an intermediary product.       
 | 
    if( this.GetIsBalanceSlackAllowed( pispip, smartplanpispips, intermediatepisps, runcontext ) ) 
 | 
    {   
 | 
      constr.NewTerm( 1.0 * scalefactor_demandslack_const, 
 | 
                     program.DemandSlackVariables().Get( pispip ) );                   
 | 
    } 
 | 
     
 | 
    // New supplies from operations 
 | 
    ispostprocessing := runcontext.IsPostProcessing();  
 | 
    traverse( pispip,  
 | 
              ProductInStockingPoint_MP.OperationOutputAvailableForOptimization,  
 | 
              output,  
 | 
              output.HasRegularProductforOptimizer() or  
 | 
              output.GetIsProductInOptimizerRun( ispostprocessing ) ) 
 | 
    {              
 | 
      // Term UoM: Output PISP 
 | 
      this.AddConstraintForOperationNewSupplies( output, pispip.Period_MP(), null( Period_MP ), 
 | 
                                                 program, 1.0, constr, scalefactor_periodtaskqty_const, scope ); 
 | 
    } 
 | 
     
 | 
    // New supplies from trips, for those productintrip that are part of the optimizer run 
 | 
    traverse( pispip, NewSupplyTrip.ProductInTrip, productintrip ) 
 | 
    { 
 | 
      // Term UoM: Output PISP 
 | 
      pitnsvar := program.TripNewSupplyVariables().Find( productintrip ); 
 | 
      if ( not isnull( pitnsvar ) ) // if not isnull means in scope and vice-versa 
 | 
      {  
 | 
        constr.NewTerm( scalefactor_tripnewsupply_const, pitnsvar ); 
 | 
      } 
 | 
    } 
 | 
     
 | 
    // Inventory carried forward, if the previous pispip exists and is part of the optimizer run 
 | 
    previouspispip := pispip.PreviousPlanningPISPIP(); 
 | 
    if( not isnull( previouspispip ) 
 | 
        and previouspispip.Start() >= pispip.ProductInStockingPoint_MP().EarliestPISPIPInScope().Start() )  
 | 
    { 
 | 
         // Term UoM: PISP 
 | 
        constr.NewTerm( scalefactor_invqty_const, 
 | 
                       program.InvQtyVariables().Get( previouspispip ) ); 
 | 
    } 
 | 
     
 | 
    // Sales demands added to balance constraint pispip salesdemands 
 | 
    traverse( pispip.GetLeafSalesDemandInPeriod(), Elements, lsdip, not lsdip.IsPostponed() or lsdip.IsManuallyPostponed() ) // note GetLeafSalesDemandInPeriod can include postponed sd, but non manual postponed  
 | 
    {                                                                                                      // sd is never added to scope (only the original) (*) 
 | 
      // Leaf sales demands added to balance constraint 
 | 
      constr.NewTerm( -1.0 * scalefactor_salesdemandqty_const, 
 | 
                     program.SalesDemandQtyVariables().Get( lsdip ) ); 
 | 
    } 
 | 
     
 | 
    traverse( pispip.GetDisaggregatedSalesDemandInPeriod(),  
 | 
              Elements,  
 | 
              dsdip,  
 | 
              not dsdip.IsPostponed() ) // similar remark as (*) above. Note disaggregates sales demand cannot be manually postponed 
 | 
    { 
 | 
      // Disaggregated sales demands added to balance constraint 
 | 
      constr.NewTerm( -1.0 * scalefactor_salesdemandqty_const, 
 | 
                     program.DisaggregatedSalesDemandQtyVariables().Get( dsdip ) ); 
 | 
    } 
 | 
     
 | 
    // Dependent demands, with slack to prevent infeasibility 
 | 
    // Term UoM: PISP 
 | 
    constr.NewTerm( -1.0 * scalefactor_dependentdemandinpispip_const, 
 | 
                   program.DependentDemandInPISPIPVariables().Get( pispip ) ); 
 | 
     
 | 
     
 | 
    if ( pispip.ProductInStockingPoint_MP().IsOptShelfLife() ) // note we always include the unsplit balance constraint defined in the current method  
 | 
    {                                                          // so pispip can still have shelf life defined 
 | 
      constr.NewTerm( -1.0 * scalefactor_expired_const, program.ExpiredVariables().Get( pispip ) ); 
 | 
    } 
 | 
     
 | 
    // PISPs with allowed negative inventory 
 | 
    // Define positive inventory to allow inventory cost calculation 
 | 
    if( pispip.ProductInStockingPoint_MP().IsNegativeInventoryAllowed() ) 
 | 
    { 
 | 
      posinvconst := program.PositiveInventoryConstraints().New( pispip ); 
 | 
      posinvconst.Sense( '>=' ); 
 | 
      posinvconst.RHSValue( 0.0 ); 
 | 
       
 | 
      posinvconst.NewTerm( scalefactor_invqty_const, program.PosInvQtyVariables().Get( pispip ) );   
 | 
      posinvconst.NewTerm( -1.0 * scalefactor_invqty_const,program.InvQtyVariables().Get( pispip ) ); 
 | 
    } 
 | 
     
 | 
    previouspispip := pispip.PreviousPlanningPISPIP(); 
 | 
     
 | 
    maxnumberofpostponement := pispip.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 ) 
 | 
      { 
 | 
        var := null( MPVariable ); 
 | 
         
 | 
        var := sd.GetDelayedSalesDemandQtyVariable( program, pispip.Period_MP() ); 
 | 
         
 | 
        if( not isnull( var ) ) 
 | 
        { 
 | 
          // Term UoM: PISP 
 | 
          constr.NewTerm( -1.0 * scalefactor_delayedsalesdemandqty_const, var ); 
 | 
        } 
 | 
      } 
 | 
      previouspispip := previouspispip.PreviousPlanningPISPIP(); 
 | 
    } 
 | 
  *] 
 | 
  InterfaceProperties { Accessibility: 'Module' } 
 | 
} 
 |