haorenhui
2023-10-30 6d6cc10d9e8e242661da7fd655dec155a09d676c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
Quintiq file version 2.0
#parent: #root
Method InitConstraintsForUserTotalSupply (
  CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program,
  const RunContextForCapacityPlanning runcontext,
  const LibOpt_Scope scope,
  const constcontent ProductInStockingPointInPeriodPlannings pispipsinrun
) const
{
  Description:
  [*
    Initialize the constraint related to the total (user) supply in a base PISPIP
    This constraint is used in the Smart plan functionality.
  *]
  TextBody:
  [*
    // For each PISPIP, if it has a total user supply and it should be considered in this run
    // Then the sum of all supply into this pispip ( Inventory Supply, TripNewSupply, OperationNewSupply and InvQty of the previous period)
    // should be equal to the total supply user
    
    if( runcontext.GetConsiderTotalUserSupply( scope ) )
    {
      pispipsforconstraint := runcontext.GetPISPISPForUserSupplyConstraint( scope, pispipsinrun ); 
      
      constrname := typeof( MPUserTotalSupplyConstraint );
      
      scalefactor_invqty_constr := this.ScaleConstraintTerm( typeof( MPInvQtyVariable ), constrname );
      scalefactor_tripnewsupply_constr := this.ScaleConstraintTerm( typeof( MPTripNewSupplyVariable ), constrname );
      scalefactor_usertotalsupplyover_constr := this.ScaleConstraintTerm( typeof( MPUserTotalSupplyOverVariable ), constrname );
      scalefactor_usertotalsupplyunder_constr := this.ScaleConstraintTerm( typeof( MPUserTotalSupplyUnderVariable ), constrname );
      scalefactor_periodtaskqty_constr := this.ScaleConstraintTerm( typeof( MPPTQtyVariable ), constrname );
      
      scalefactor_rhs_constr := this.ScaleConstraintRHS( constrname, 1.0 );
      
      traverse( pispipsforconstraint, Elements, pispip ) 
      {
        // constr constraint UoM: PISP
        constr := program.UserTotalSupplyConstraints().New( pispip );
        constr.Sense( '=' );
      
        rhs := pispip.TotalSupplyUser() - pispip.InventorySupplyQuantity();
        // RHS UoM: PISP
        constr.RHSValue( rhs * scalefactor_rhs_constr );
      
        previouspispip := pispip.PreviousPlanningPISPIP();
      
        // Inventory end of the previous period
        if( not isnull( previouspispip ) )
          {
          // If the previous pipsip is part of the optimizer run, add the inventory quantity variable to the constraint
          if( scope.Contains( previouspispip.PISPIPInOptimizerRun() ) )
          {
            // Term UoM: PISP
            constr.NewTerm( scalefactor_invqty_constr,
                            program.InvQtyVariables().Get( previouspispip ) );
            if ( pispip.ProductInStockingPoint_MP().IsOptShelfLife() ) 
            {
              constr.NewTerm( -scalefactor_invqty_constr, program.ExpiredVariables().Get( pispip ) ); 
            }                        
          }
          // Otherwise update the RHS to include the frozen inventory end
          else
          {
            newrhs := this.GetConstraintRHS( constr, scalefactor_rhs_constr ) - previouspispip.InventoryLevelEnd();
            constr.RHSValue( newrhs * scalefactor_rhs_constr );
          }
        }
      
        // New supplies from trips
        traverse( pispip, astype(ProductInStockingPointInPeriodPlanningLeaf ).NewSupply.ProductInTrip, productintrip )
        {
          // If the productintrip is part of the optimizer run, add its tripnewsupply quantity variable to the constraint
          if( scope.Contains( productintrip.ProductInTripInOptimizerRun() ) ) 
          {
            // Term UoM: Output PISP
            constr.NewTerm( scalefactor_tripnewsupply_constr, program.TripNewSupplyVariables().Get( productintrip ) );
          }
          // Otherwise update the RHS with the frozen productintrip supply quantity
          else
          {
            newrhs := this.GetConstraintRHS( constr, scalefactor_rhs_constr ) - productintrip.Quantity();
            constr.RHSValue( newrhs * scalefactor_rhs_constr );
          }
        }
      
        // New supplies from operations
        traverse( pispip, ProductInStockingPoint_MP.OperationOutputAvailableForOptimization, output )
        {
          // Term UoM: Output PISP
          this.AddConstraintForOperationNewSupplies( output, pispip.Period_MP(), null( Period_MP ),
                                                     program, 1.0, constr, scalefactor_periodtaskqty_constr, scope );
      
          // If there is a new supply of this output in this pispips that is not part of the optimization run, then this new supply should be subtracted from the RHS
          // Comment from MvE: this should follow the summing of RHS new supply in GetInventoryRHSForBalanceConstraint
          traverse( output, NewSupply, newsupply,
                    newsupply.PeriodTask_MP().UnitPeriod().Period_MP() = pispip.Period_MP()                
                    and( not scope.Contains(  newsupply.PeriodTaskOperation().PeriodTaskOperationInOptimizerRun() )
                         and not scope.Contains( newsupply.PeriodTask_MP().UnitPeriod().UnitPeriodInOptimizerRun() ) ) // If this is a regular optimizer run, the PTOperations are not added to the algorithm run
                    or ( ifexpr( runcontext.IsSmartPlanForPeriodTask(), not newsupply.GetHasAllDDInOptimizerScope( runcontext, scope ), false ) ) // Only check this for period task smart plan
                    )  
          {
            newrhs := this.GetConstraintRHS( constr, scalefactor_rhs_constr ) - newsupply.Quantity();
            constr.RHSValue( newrhs * scalefactor_rhs_constr );
          }
        }
      
        // Add slack variables
        // Term UoM: Output PISP
        constr.NewTerm( -1.0 * scalefactor_usertotalsupplyover_constr, program.UserTotalSupplyOverVariables().Get( pispip ) );
        constr.NewTerm( scalefactor_usertotalsupplyunder_constr, program.UserTotalSupplyUnderVariables().Get( pispip ) );
      }
    }
  *]
  InterfaceProperties { Accessibility: 'Module' }
}