chenqinghong
2024-05-07 3ec06a830367465068963156dcc1d8e522571c13
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
Quintiq file version 2.0
#parent: #root
Method InitConstraintsForInventorySpecificationHighLevel (
  CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program,
  const LibOpt_Scope scope,
  const RunContextForCapacityPlanning runcontext,
  const constcontent ProductInStockingPointInPeriodPlannings pispipsinrun
) const
{
  Description: 'adds constraints for inventory target and minimum inventory, for high level products that are aggregates over lower level products'
  TextBody:
  [*
    // These are high level constraints, so leaf pisps should not be considered
    
    targetconstname := typeof( MPTargetInventoryLevelConstraint );
    minconstname := typeof( MPMinInventoryLevelConstraint );
    maxconstname := typeof( MPMaxInventoryLevelConstraint );
     
    scalefactor_invqtyundertarget_targetconst := this.ScaleConstraintTerm( typeof( MPInvQtyUnderTargetVariable ), targetconstname );
    scalefactor_mininvqtyunder_minconst := this.ScaleConstraintTerm( typeof( MPMinInvQtyUnderVariable ), minconstname );
    scalefactor_maxinvqtyover_maxconst := this.ScaleConstraintTerm( typeof( MPMaxInvQtyOverVariable ), maxconstname );
    
    scalefactor_rhs_targetconst := this.ScaleConstraintRHS( targetconstname, 1.0 );
    scalefactor_rhs_minconst := this.ScaleConstraintRHS( minconstname, 1.0 );
    scalefactor_rhs_maxconst := this.ScaleConstraintRHS( maxconstname, 1.0 );
    
    demandfulfillmentinpispip_varname := typeof( MPDemandFulfillmentInPISPIPVariable );
    demandfulfillmentinpispip_constrname := typeof( MPDemandFulfillmentInPISPIPConstraint );
    // Get scaling factors. For performance we dont want to recompute this for each pispip 
    scalefactor_demandfulfillmentinpispip_constr := this.ScaleConstraintTerm( demandfulfillmentinpispip_varname, demandfulfillmentinpispip_constrname );
    scalefactor_rhs_constr := this.ScaleConstraintRHS( demandfulfillmentinpispip_constrname, 1.0 );
    
    scalefactor_invqty_constr_targetconst := this.ScaleConstraintTerm( typeof( MPInvQtyVariable ), targetconstname );
    scalefactor_rhs_constr_targetconst := this.ScaleConstraintRHS( targetconstname, 1.0 );
    
    scalefactor_invqty_constr_minconst := this.ScaleConstraintTerm( typeof( MPInvQtyVariable ), minconstname );
    scalefactor_rhs_constr_minconst := this.ScaleConstraintRHS( minconstname, 1.0 );
    
    scalefactor_invqty_constr_maxconst := this.ScaleConstraintTerm( typeof( MPInvQtyVariable ), maxconstname );
    scalefactor_rhs_constr_maxconst := this.ScaleConstraintRHS( maxconstname, 1.0 );
    
    leafpispips := null( ProductInStockingPointInPeriodPlannings, constcontent, owning );
    pispips := this.GetPISPIPsForInventorySpecifications( scope, false, &leafpispips  )
    traverse( pispips, Elements.astype( ProductInStockingPointInPeriodPlanningNonLeaf ), pispip, not pispip.IsLeafPlanning() )
    {
      // Penalty of not fulfilling the target
      if( pispip.GetHasTargetInventory() 
          and (pispip.GetHasTargetInDays() or scope.Contains( pispip.PISPIPInOptimizerRun() ) ) )
      {
        rhs := ifexpr( not pispip.GetHasTargetInDays(), pispip.TargetInQuantity(), 0.0 );  // If specified in days, the target inventory is calculated based on next period demand fulfillment
        // targetconst constraint UoM: target PISP
        targetconst := program.TargetInventoryLevelConstraints().New( pispip );
        // RHS UoM: target PISP
        targetconst.RHSValue( rhs * scalefactor_rhs_targetconst );
        targetconst.Sense( '>=' );
         // Term UoM: SP
        targetconst.NewTerm( 1.0 * scalefactor_invqtyundertarget_targetconst, program.InvQtyUnderTargetVariables().Get( pispip ) );
        // sum of inventory quantity of active pispips
        this.AddTermsToInventorySpecificationHighLevelConstraint( program, targetconst, pispip, scope, scalefactor_invqty_constr_targetconst, scalefactor_rhs_constr_targetconst );
      }
    
      // Penalty of not reaching the minimum inventory level
      if( pispip.GetHasMinLevel()
          and ( pispip.InventorySpecification().HasMinLevelInDays() or scope.Contains( pispip.PISPIPInOptimizerRun()  ) ) )
      {
        rhs := ifexpr( not pispip.GetHasMinLevelInDays(), pispip.MinLevelInQuantity(), 0.0 );  // If specified in days, the target inventory is calculated based on next period demand fulfillment
        // minconst constraint UoM: target PISP
        minconst := program.MinInventoryLevelConstraints().New( pispip );
        minconst.Sense( '>=' );
        // RHS UoM: target PISP
        minconst.RHSValue( rhs * scalefactor_rhs_minconst );
        // Term UoM: target PISP
        minconst.NewTerm( 1.0 * scalefactor_mininvqtyunder_minconst, program.MinInvQtyUnderVariables().Get( pispip ) );
        // sum of inventory quantity of active pispips
        this.AddTermsToInventorySpecificationHighLevelConstraint( program, minconst, pispip, scope, scalefactor_invqty_constr_minconst, scalefactor_rhs_constr_minconst );
      }
      
      // Penalty of exceeding the maximum inventory level
      if( pispip.GetHasMaxLevel() 
          and ( pispip.InventorySpecification().HasMaxLevelInDays() or scope.Contains( pispip.PISPIPInOptimizerRun() ) ) )
      {
        rhs := ifexpr( not pispip.GetHasMaxLevelInDays(), pispip.MaxLevelInQuantity(), 0.0 );  // If specified in days, the target inventory is calculated based on next period demand fulfillment
        // maxconst constraint UoM: target PISP
        maxconst := program.MaxInventoryLevelConstraints().New( pispip );
        maxconst.Sense( '<=' );
        // RHS UoM: target PISP
        maxconst.RHSValue( rhs * scalefactor_rhs_maxconst );
        // Term UoM: target PISP
        maxconst.NewTerm( -1.0 * scalefactor_maxinvqtyover_maxconst, program.MaxInvQtyOverVariables().Get( pispip ) );
        // sum of inventory quantity of active pispips
        this.AddTermsToInventorySpecificationHighLevelConstraint( program, maxconst, pispip, scope, scalefactor_invqty_constr_maxconst, scalefactor_rhs_constr_maxconst );
      }
      
      // For inventory specifications in days, add terms for the target / min / max inventory level
      // based on the fulfilled sales demands and dependent demands on next periods
      this.AddTermsToInventorySpecificationConstraints( program, pispip, scope, scalefactor_demandfulfillmentinpispip_constr, scalefactor_rhs_constr );
    }
  *]
  InterfaceProperties { Accessibility: 'Module' }
}