陈清红
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
Quintiq file version 2.0
#parent: #root
Method ActivateUnitShiftPatterns (
  RunContextForCapacityPlanning runcontext,
  RunContextMeta rcm,
  LibOpt_Scope scope
)
{
  TextBody:
  [*
    if ( runcontext.UseShiftOptimization() ) 
    {
      isoptimizeshiftchanges := runcontext.WeightLevelNonFinancial().ShiftPatternChangesPenaltyLevel() <= this.FocusLevel() and runcontext.WeightLevelNonFinancial().ShiftPatternChangesPenaltyWeight() > 0.0; 
      isoptimizershiftcost := exists( scope.GetAccountsInOptimizerRun(), Elements, account, account.HasStaffingAssignment(), account.Level() <= this.FocusLevel() and account.Weight() > 0.0 ); 
      isneedoptimizershift := isoptimizeshiftchanges or isoptimizershiftcost or this.FocusLevel() = 0;  // also include level 0 in case of fixing min shift durations. 
      
      maxnrunits := rcm.OptionShiftPatternMaxUnits(); 
      maxshiftpatternsperunit := rcm.OptionShiftPatternMaxActive(); 
      
      // first set all to not active  
      traverse( scope.GetUnitInOptimizerRun(), Elements, unit ) 
      {
        traverse( unit, UnitShiftPatternAllowed, usa ) 
        {
          usa.IsActive( false ); 
        }
        
        traverse( unit.GetAllChildren(), Elements.UnitShiftPatternAllowed, usa ) 
        {
          usa.IsActive( false ); 
        }
      }  
    
      // activate all for 'max nr units' problem units   
      problemups := selectset(  scope.GetUnitInOptimizerRun(), Elements.UnitPeriod.astype( UnitPeriodTime ), up, true, not up.IsFulfilledMinimumShiftPatternDuration() ); 
      problemunits := selectset(  problemups, Elements.Unit, u, true, true ).SelectFirst( maxnrunits );
      traverse( problemunits, Elements.UnitShiftPatternAllowed, usa ) 
      {
        usa.IsActive( true ); 
      }
      
      // activate all for 'max nr units' problem units of time aggregation type
      problemupagg := selectset(  scope.GetUnitInOptimizerRun(), 
                                  Elements.UnitPeriod.astype( UnitPeriodTimeAggregation ), 
                                  up, 
                                  true, 
                                  not up.GetAllChildrenOfUnitDimensionMinShiftPatternDurationFulfilled() ); 
                                  
    
      traverse( problemupagg, Elements, up ) { debuginfo(  up.UnitID(), up.Start() ) } ; 
      problemunitsagg := selectset(  problemupagg, Elements.Unit, u, true, true ).SelectFirst( maxnrunits ); 
      traverse( problemunitsagg, Elements, unit ) 
      {
        traverse( unit.GetAllChildren(), Elements.UnitShiftPatternAllowed, usa ) 
        {
          usa.IsActive( true ); 
        }
      }  
    
      // active for units without problem, make some random selection 
      unitsactive := selectsortedset(  scope.GetUnitInOptimizerRun(), 
                                       Elements, 
                                       unit, 
                                       unit.UnitShiftPatternAllowed( relsize ) > 1
                                       or exists(  unit.GetAllChildren(), Elements, child, true, child.UnitShiftPatternAllowed( relsize ) > 1 ), 
                                       Real::Random() ).SelectFirst( maxnrunits ); 
    
        
      // activate 'maxshiftpatternperunit' shift patterns for 'max nr unit' many units 
      counterchild := 0; // avoid selecting uncontrolled neighborhood size for puzzles with large number of child units
      traverse( unitsactive, Elements, unit ) 
      {
        spactive := null( UnitShiftPatterns ); 
        if ( isneedoptimizershift ) 
        {
          spactive := selectsortedset( unit, UnitShiftPatternAllowed, activeusa,  true, Real::Random() ).SelectFirst( maxshiftpatternsperunit ); 
        }
        else
        {
          spactive := selectsortedset( unit, UnitShiftPatternAllowed, activeusa,  true, -activeusa.ShiftPattern().TotalCapacity() ).SelectFirst( 1 ); 
        }
        traverse( spactive, Elements, sp ) 
        {
          sp.IsActive( true ); 
        }
        
        traverse( unit.GetAllChildren(), Elements, child, counterchild <= maxnrunits ) 
        {
          counterchild++; 
          
          spactivechild := null( UnitShiftPatterns ); 
          if ( isneedoptimizershift ) 
          {
            spactivechild := selectsortedset(  child, UnitShiftPatternAllowed, usa, true, Real::Random() ).SelectFirst( maxshiftpatternsperunit ); 
          }
          else
          {
            spactivechild := selectsortedset(  child, UnitShiftPatternAllowed, usa, true, -usa.ShiftPattern().TotalCapacity() ).SelectFirst( 1 ); 
          }
          traverse( spactivechild, Elements, sp ) 
          {
            sp.IsActive( true ); 
          }
        }
      }
      
      totalallowedcombinations := counter( this.Optimization().astype( Optimization ).MacroPlan(), Unit.UnitShiftPatternAllowed, usa, true, usa.Unit().IsInOptimizerPuzzle() ); 
      totalactive := counter( this.Optimization().astype( Optimization ).MacroPlan(), Unit.UnitShiftPatternAllowed, usa, true, usa.IsActive() and usa.Unit().IsInOptimizerPuzzle() ); 
      nolimit := guard( totalactive / totalallowedcombinations > 0.95, true ) // just complete to unrestricted if some extraneous not activated
      
      if ( nolimit ) 
      {
        // first set all to not active  
        traverse( this.Optimization().astype( Optimization ).MacroPlan(), Unit, unit ) 
        {
          traverse( unit, UnitShiftPatternAllowed, usa ) 
          {
            usa.IsActive( true ); 
          }
          
          traverse( unit.GetAllChildren(), Elements.UnitShiftPatternAllowed, usa ) 
          {
            usa.IsActive( true ); 
          }
        }  
      }
    }
  *]
  InterfaceProperties { Accessibility: 'Module' }
}