yanweiyuan3
2023-08-09 588bc7829387dfc761cc25f06f77d4c81818bd10
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
Quintiq file version 2.0
#parent: #root
Method InitConstraintsForServiceLevel (
  CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program,
  const RunContextForCapacityPlanning runcontext,
  const LibOpt_Scope scope,
  const constcontent ProductInStockingPointInPeriodPlanningLeafs leafpispipsinrun
) const
{
  Description: 'Initialize constraints forservice level'
  TextBody:
  [*
    eis := this.MacroPlan().OptimizerMetaEIS();  
    if ( ( runcontext.IsMetaIteration() 
         and ( eis.ServiceLevelWeight() > 0 or eis.FulfillmentTargetWeight() > 0  ) ) 
         or not runcontext.IsMetaIteration() 
         or this.IsFullPlanMetaPriorFocus() ) // for performance don't define if we don't have the kpi's in the strategy
    {
      constfromtargetname := typeof( MPServiceLevelFromTargetConstraint );
      constfromsddetname := typeof( MPFulfillmentTargetFromSDQtyConstraint );
      constfromsdstoname := typeof( MPServiceLevelFromSDQtyConstraint );
      
      scalefactor_servicelevelqty_constfromtarget := this.ScaleConstraintTerm( typeof( MPFulfillmentTargetVariable ), constfromtargetname );
      scalefactor_servicelevelqty_constfromsd_det := this.ScaleConstraintTerm( typeof( MPFulfillmentTargetVariable ), constfromsddetname );
      scalefactor_servicelevelqty_constfromsd_sto := this.ScaleConstraintTerm( typeof( MPServiceLevelQtyVariable ), constfromsdstoname );
      scalefactor_salesdemandqty_constfromsd_det := this.ScaleConstraintTerm( typeof( MPSalesDemandQtyVariable ), constfromsddetname );
      scalefactor_salesdemandqty_constfromsd_sto := this.ScaleConstraintTerm( typeof( MPSalesDemandQtyVariable ), constfromsdstoname );
      
      scalefactor_rhs_constfromtarget := this.ScaleConstraintRHS( constfromtargetname, 1.0 );
      scalefactor_rhs_constfromsddet := this.ScaleConstraintRHS( constfromsddetname, 1.0 ); 
      scalefactor_rhs_constfromsdsto := this.ScaleConstraintRHS( constfromsdstoname, 1.0 ); 
      
      //
      // step 1: created constraints
      //
      slbases := selectset(  this, 
                             MacroPlan.AllServiceLevelBase, 
                             sl, 
                             sl.GetIsInOptimizerRun( scope ) ); 
      traverse( slbases, Elements, sl )
      {
        vardummy := program.NewVariable( 'OptimizerConstantTerm', sl ); // workaround for const - cant use attribute
        vardummy.Enabled( false );  
        this.StoreValueInVariable( vardummy, 0.0 ); 
    
        // If this is a fulfillment goal related service level then add the related constraints
        if( sl.IsUsedForPlanningFulfillmentSystem() )
        {
          // two constraints are added: 
          //
          // constfromtarget, which specifies the fulfilled quantity(sl) is <= target% * total demand qty (sl)              (*)
          //
          // constfromsd, which specifies fulfilled quantity (sl) <= total demand qty ( sl)
      
          // constraints to calculate fulfilled part of the fulfillmentgoal
          // plannedservicelevel <= target% * sum of sd.Quantity
          // const constraint UoM: Default
          constfromtarget := program.ServiceLevelFromTargetConstraints().New( sl ); 
          constfromtarget.Sense( '<=' );
      
          // Term UoM: Default
          constfromtarget.NewTerm( 1.0 * scalefactor_servicelevelqty_constfromtarget, program.FulfillmentTargetVariables().Get( sl ) );
      
          // ServiceLevel <= sum of SalesDemandQty
          // const constraint UoM: Default
          constfromsd := program.FulfillmentTargetFromSDQtyConstraints().New( sl );
          constfromsd.Sense( '<=' );
          constfromsd.RHSValue( 0.0 );
          
          // Term UoM: Default
          constfromsd.NewTerm( 1.0 * scalefactor_servicelevelqty_constfromsd_det, program.FulfillmentTargetVariables().Get( sl ) );
          constfromsd.Enabled( false ); // enable once we add a term
        }
        // Else, if this is a inventory optimization related service level, add the related constraints
        else if( sl.IsUsedForSafetyStockCalculation() )
        {
          // ServiceLevel <= SUM( SalesDemandQty ) + SUM ( DisaggregatedSalesDemandQty )
          // const constraint UoM: Default
          constr := program.ServiceLevelFromSDQtyConstraints().New( sl );
          constr.Sense( '<=' );
          constr.RHSValue( 0.0 );
          
          // Term UoM: Default
          constr.NewTerm( 1.0 * scalefactor_servicelevelqty_constfromsd_sto , program.ServiceLevelQtyVariables().Get( sl ) );
          constr.Enabled( false ); // enable once we add a term
        }
      }
      
      // 
      // step 2: add terms to constraint
      //
      //bsdips := selectset(  this, MacroPlan.SalesDemand.AsMasterSalesDemand, bsdip, true, true ); 
      bsdips := selectset(  leafpispipsinrun, 
                            Elements.PlanningBaseSalesDemandInPeriodForOptimization,
                            bsdip, 
                            true, 
                            not bsdip.MasterSalesDemand().IsExcludedFromFulfillmentKPI() );  
      this.AddTermsToServiceLevelConstraints( program,
                                              bsdips,
                                              scalefactor_salesdemandqty_constfromsd_det,
                                              scalefactor_salesdemandqty_constfromsd_sto,
                                              scope );
      // step 3: set computed rhs for constraint
      traverse( slbases, Elements, sl ) 
      {
        opt_constant_term := program.Variable( 'OptimizerConstantTerm', sl ).UpperBound(); // workaround because cannot write to attribute 
        outofscopequantity := sl.TotalFulfilledQuantity() - opt_constant_term; // latter term set in AddTermsToServiceLevelConstraint
        if( sl.IsUsedForPlanningFulfillmentSystem() )
        {
          constfromtarget := program.ServiceLevelFromTargetConstraints().Get( sl ); 
          desiredservicelevelpercentage := sl.TargetPercentage();
          rhsfromtarget := maxvalue( 0.0, sl.TotalDemandQuantity() * ( desiredservicelevelpercentage / 100.0 ) );   //prevent negative goal
          // RHS UoM: Default
          constfromtarget.RHSValue( rhsfromtarget * scalefactor_rhs_constfromtarget ); // poses the upper bound mentioned in (*) 
          
          constrfromsd := program.FulfillmentTargetFromSDQtyConstraints().Get( sl ); 
    
          newrhs := this.GetConstraintRHS( constrfromsd, scalefactor_rhs_constfromsddet ) + outofscopequantity; // variable is added on the right, so we *add* constantterm to the RHS
          constrfromsd.RHSValue( newrhs * scalefactor_rhs_constfromsddet );
        }
        else
        {
          constr := program.ServiceLevelFromSDQtyConstraints().Get( sl ); 
          newrhs := this.GetConstraintRHS( constr, scalefactor_rhs_constfromsdsto ) + outofscopequantity; // variable is added on the right, so we *add* constantterm to the RHS
          constr.RHSValue( newrhs * scalefactor_rhs_constfromsdsto );
        }
      }
    }
  *]
  InterfaceProperties { Accessibility: 'Module' }
}