陈清红
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
126
127
128
129
130
131
132
Quintiq file version 2.0
#parent: #root
MethodOverride CreateComponents (
  LibOpt_Run run
)
{
  TextBody:
  [*
    rcm := RunContextMeta::GetRunContextMeta( run ); 
    
    runcontext := RunContextForCapacityPlanning::GetRunContextCapacityPlanning( run ); 
    
    mp := this.Optimization().astype( Optimization ).MacroPlan(); 
    maxlevel := max( mp, StrategyMacroPlan.StrategyLevelMacroPlan, slm, true, slm.Level() ); 
    
    prepostcomp := run.Component( relnew, OptimizerPrePostProcessing, Name := 'PrePostProcessing_Meta' ); 
    
    iteratormeta := this.Iterator( run, 'IteratorLevels' ); // default start component 
    iteratormeta.SetMaxIterations( this.GetNumberOfIterationForRoundRobin( maxlevel, rcm ) );
    
    prepostcomp.To( iteratormeta ); 
                                    
    roundrobin := this.SwitchRoundRobin( run, 'RoundRobinProcessAllLevels' ); 
    iteratormeta.To( roundrobin ); 
    if ( this.GetRunFullPuzzlePriorToMeta( rcm ) )
    {
      selectorfullpuzzle := run.Component( relnew, SelectorFullPuzzle, Name := 'SelectorFullPuzzle' ); 
      transformerforuserperiodtasks := run.Component( relnew, TransformerFullRun, Name := 'TransformerFullRun'  ); 
      roundrobin.Branch( transformerforuserperiodtasks );  
    
      suboptimizer := CapacityPlanningSuboptimizer::Create( rcm.OptionMinimumMetaLevel() - 1,                                                    // focuslevel
                                                            false,                                                // ispriorlevelsfixed
                                                            runcontext.IsAutoScalingEnabled() and rcm.OptionAllowScalingRecompute(),                    // isupdatescaling
                                                            false,                                                // runpastfocuslevel
                                                            run, 
                                                            'CapacityPlanningSubOptimizerForFullRunPriorMetaLevel',  // name
                                                            false,   // user supply correction carried fwd inventory
                                                            false,   // keep total available supply
                                                            false,   // do not get periods by traversal over periodtaskoperation
                                                            false,   // only plan demand smart plan pispips
                                                            rcm.OptionMinimizePTQty(),  // extra level to minimize ptqty
                                                            rcm.OptionMinimizePTQtyDoInventoryBased(), 
                                                            rcm.OptionMinimizePTQTYLevelRelativeGoalSlack(), 
                                                            true,    // apply noise threshold
                                                            rcm.OptionUseHierarchicalCPLEXGoals(), 
                                                            runcontext.SmallestIntegralityTolerance(),
                                                            runcontext.SmallestFeasibilityTolerance(), 
                                                            true,    // full plan for meta  
                                                            false, 0.0 ); // collapse level and weight
    
        transformerforuserperiodtasks.To( selectorfullpuzzle ); 
        selectorfullpuzzle.To( suboptimizer );
        
        RollbackKPIMeta::Create( suboptimizer, 
                               RunContextForCapacityPlanning::GetRunContextCapacityPlanning( run ), 
                               rcm.OptionPrecisionForRollback(), 
                               rcm.OptionToleranceRollback(),
                               rcm.OptionCutOffProcessMinQtyKPI(), 
                               runcontext.SmallestFeasibilityTolerance(), // blending KPI precision 
                               rcm.OptionUseRollBack(), 
                               suboptimizer.FocusLevel(), 
                               true ); // always accept 
        
    }
    for ( focuslevel := rcm.OptionMinimumMetaLevel(); focuslevel <= maxlevel; focuslevel++ ) 
    {
      maxdurationforlevel := Duration::Seconds( rcm.GetTotalDurationSecondsForLevel( focuslevel ) ); 
      stopmeta := construct( StopCriterionMeta, 
                             FocusLevel := focuslevel, 
                             MaxDurationLocal := maxdurationforlevel, 
                             MaxDurationGlobal := Duration::Seconds( rcm.OptionMaxNumberOfSecondsRun() ), 
                             ConvergenceWindowSize := rcm.OptionConvergenceWindowSize(), 
                             ConvergenceThreshold := rcm.OptionConvergenceThreshold(), 
                             CutOffForOptimal := rcm.OptionCutOffForOptimal(), 
                             MaxError := rcm.OptionMaximumError(), 
                             MaxLevel := maxlevel, 
                             IsEnabledAutoScaling := runcontext.IsAutoScalingEnabled() and rcm.OptionAllowScalingRecompute() ); 
    
      stopmeta.SetStopScoreForBenchmarking( run.Optimization().astype( Optimization ).MacroPlan(), runcontext.IsForBenchmarking(), rcm.OptionBenchmarkStopThreshold() ); // note for OTS we need to set it in select scope as workaround (LibOpt_BT_TrackingTableRow::SelectScope )                          
      iteratorconv := this.Iterator(  run,  'IteratorConvergence' + [String] focuslevel, &stopmeta);
      
      roundrobin.Branch( iteratorconv ); 
      // create sub tree for level 'focuslevel'
      
      suboptimizerforlevel := CapacityPlanningSuboptimizer::Create( focuslevel, 
                                                                    rcm.OptionFixDecisionVariablesPriorToFocusLevel(), 
                                                                    runcontext.IsAutoScalingEnabled() and rcm.OptionAllowScalingRecompute(), // isupdatescaling, 
                                                                    rcm.OptionRunPastFocusLevel(), 
                                                                    run, 
                                                                    'SubOptimizerLevel'+[String]focuslevel, 
                                                                    false,   // apply user correction carried fwd inventory 
                                                                    false,   // keep total avail supply override 
                                                                    true,    // period for operations from periodtaskoperation like smart plan
                                                                    false,   // only plan demand smart plan pispips
                                                                    rcm.OptionMinimizePTQty(),  // extra level to minimize ptqty
                                                                    rcm.OptionMinimizePTQtyDoInventoryBased(), 
                                                                    rcm.OptionMinimizePTQTYLevelRelativeGoalSlack(), 
                                                                    false,   // do not apply noise treshold during meta iterations
                                                                    rcm.OptionUseHierarchicalCPLEXGoals(), 
                                                                    runcontext.SmallestIntegralityTolerance(),
                                                                    runcontext.SmallestFeasibilityTolerance(), 
                                                                    false,   // full plan for meta  
                                                                    rcm.OptionCollapseLevels(), // collapse level
                                                                    rcm.OptionCollapseLevelWeight() ); // collapse level weight
      RollbackKPIMeta::Create( suboptimizerforlevel, 
                               RunContextForCapacityPlanning::GetRunContextCapacityPlanning( run ), 
                               rcm.OptionPrecisionForRollback(), 
                               rcm.OptionToleranceRollback(),
                               rcm.OptionCutOffProcessMinQtyKPI(), 
                               runcontext.SmallestFeasibilityTolerance(), // blending KPI precision 
                               rcm.OptionUseRollBack(), 
                               focuslevel, 
                               rcm.OptionRollbackAlwaysAccept() ); 
        
      startcomponentsubtree := this.CreateComponentTreeForLevel( run, suboptimizerforlevel, focuslevel );
      iteratorconv.To( startcomponentsubtree );  
    }
    
    startexcludedproducts := Optimization::GetStartComponentForExcludedProductsOptimization( run ); 
    if ( not isnull( startexcludedproducts ) ) 
    {
      // add to diagram by inserting an iteration up to
      iteratortwotimes := this.Iterator(  run, 'IteratorTwoTimesForExcludedProducts'  ); 
      iteratortwotimes.SetMaxIterations( 2 ); 
      roundrobinforexcludedproducts := this.SwitchRoundRobin( run, 'RoundRobinForExcludedProducts' ); 
      prepostcomp.To( iteratortwotimes ); // redirect from iteratormeta in this case 
      iteratortwotimes.To( roundrobinforexcludedproducts ); 
      roundrobinforexcludedproducts.Branch( iteratormeta ); 
      roundrobinforexcludedproducts.Branch( startexcludedproducts ); 
    }
  *]
}