陈清红
2025-04-14 880f3c0257eeb8c37761d484258fdd102a369a19
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
Quintiq file version 2.0
#parent: #root
Method InitVariablesForSalesDemands (
  CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program,
  const LibOpt_Scope scope
) const
{
  Description: 'Initialize all sales demand quantity variables for AggregatedSalesDemandInPeriod, DisaggregatedSalesDemandInPeriod and LeafSalesDemandInPeriod'
  TextBody:
  [*
    // edz1 Oct-20-2016 (created)
    
    // Leaf sales demands 
    traverse( scope.GetLeafSalesDemandInPeriodInRunConst(), Elements, lsdip ) 
    {
      // Type    : LeafSalesDemandInPeriod
      // Variable: 'SalesDemandQty' UoM: PISP
      var := program.SalesDemandQtyVariables().New( lsdip );
      upperbound := maxvalue( 0.0, lsdip.GetQuantityForOptimizer( scope ) );
      this.FreezeVariableUpperBound( var, upperbound );
    
      if ( lsdip.ProductInStockingPoint_MP().IsOptShelfLife() ) 
      {
        traverse( lsdip, ProductInStockingPoint_MP.IncomingShelfLifeDay, islday ) 
        {
           // Leaf sales demands added to balance constraint
           program.SalesDemandShelfLifeQtyVariables().New( lsdip, islday );
        }
      }
          
      // Postponed sales demand variable
      if( lsdip.CanBePostponed() )
      {
        // Type    : LeafSalesDemandInPeriod
        // Variable: 'DelayedSalesDemandQty' UoM: PISP 
        lsdip.InitVariablesForPostponedSalesDemands(  this, program, scope, 1, false /* shelf life var only false */ ); 
      }
    }
    
    // Aggregated sales demands for higher product level
    traverse( scope.GetAggregatedSalesDemandInPeriodInRunConst(), Elements, asdip ) 
    {
      // There is no decision variable for AggregatedSalesDemandInPeriod
      // Traverse the children ( Disaggregated Sales demands )
      traverse ( asdip, 
                 DisaggregatedSalesDemandInPeriod, 
                 dasdip,
                 not dasdip.IsPostponed() // note that postponed dasdip is still owned by the original asdip and that we do not unplan the postponed asdip object until handle feasible
                 and scope.Contains( dasdip.AsPlanningBaseSalesDemandInPeriod().PISPIPInOptimizerRun() ) ) // so un aggregated variables need to be taken care of like this
      {
        // Type    : DisaggregatedSalesDemandInPeriod
        // Variable: 'DisaggregatedSalesDemandQty' UoM: PISP
        var := program.DisaggregatedSalesDemandQtyVariables().New( dasdip );
        lowerbound := 0.0;
        upperbound := maxvalue( 0.0, asdip.GetQuantityForOptimizer( scope ) );
        this.FreezeVariableLowerUpperBound( var, lowerbound, upperbound );
    
        if ( dasdip.ProductInStockingPoint_MP().IsOptShelfLife() ) 
        {
          traverse( dasdip, ProductInStockingPoint_MP.IncomingShelfLifeDay, islday ) 
          {
            program.DisaggregatedSalesDemandShelfLifeQtyVariables().New( dasdip, islday );
          }
        }
        // Postponed or delayed sales demand variable
        if( asdip.CanBePostponed() )
        {
          // Type    : DelayedDisaggregatedSalesDemandInPeriod
          // Variable: 'DelayedDisaggregatedSalesDemandQty' UoM: PISP
          dasdip.InitVariablesForPostponedSalesDemands( this, program, scope, 1, false /* shelf life var only false */ ); 
        }
      }
    }
    
    // Sales demand before the optimization horizon, including those before the planning horizon.
    this.InitVariablesForSalesDemandsInScopeWhenPostponed( program, scope );
    
    
    // extra for extended collection of periods for shelf life prior to scope
    traverse( scope.GetProductInStockingPointInOptimizerRunConst(), Elements, pisp, pisp.IsOptShelfLife() ) 
    {
      initpispips := pisp.PISPInOptimizerRun().GetPISPIPForShelfLifeOptimizer( scope ); 
      traverse( initpispips, Elements, pispip, not scope.Contains( pispip.PISPIPInOptimizerRun() ) )
      {
        traverse( pispip.GetLeafSalesDemandInPeriod(), Elements, lsdip ) 
        {
          traverse( lsdip, ProductInStockingPoint_MP.IncomingShelfLifeDay, islday ) 
          {
            // Leaf sales demands added to balance constraint
            program.SalesDemandShelfLifeQtyVariables().New( lsdip, islday );
          }
          
          // Postponed sales demand variable
          if( lsdip.CanBePostponed() )
          {
            // Type    : LeafSalesDemandInPeriod
            // Variable: 'DelayedSalesDemandQty' UoM: PISP 
            lsdip.InitVariablesForPostponedSalesDemands(  this, program, scope, 1, true /* shelf life var only true */ ); 
          }
        }
        
        traverse( pispip.GetDisaggregatedSalesDemandInPeriod(), 
                  Elements, 
                  dasdip,
                  not dasdip.IsPostponed() ) // note that postponed dasdip is still owned by the original asdip and that we do not unplan the postponed asdip object until handle feasible
        {
          asdip := dasdip.AggregatedSalesDemandInPeriod(); 
    
          traverse( dasdip, ProductInStockingPoint_MP.IncomingShelfLifeDay, islday ) 
          {
            program.DisaggregatedSalesDemandShelfLifeQtyVariables().New( dasdip, islday );
          }
          // Postponed or delayed sales demand variable
          if( asdip.CanBePostponed() )
          {
            // Type    : DelayedDisaggregatedSalesDemandInPeriod
            // Variable: 'DelayedDisaggregatedSalesDemandQty' UoM: PISP
            dasdip.InitVariablesForPostponedSalesDemands( this, program, scope, 1, true /* shelf life var only false */ ); 
          }
        }
      }
    }
  *]
  InterfaceProperties { Accessibility: 'Module' }
}