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
Quintiq file version 2.0
#parent: #root
Method InitVariablesForShiftPatterns (
  CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program,
  const RunContextForCapacityPlanning runcontext,
  const LibOpt_Scope scope
) const
{
  Description: 'Initialize all variables related to shift pattern optimization.'
  TextBody:
  [*
    nrshiftbinaries := 0; 
    if( runcontext.UseShiftOptimization() )
    {
      // Find every unit period that be planned by the optimizer.
      traverse( scope.GetUnitInOptimizerRunConst(), Elements, parentunit, parentunit.GetUseShiftOptimization() )
      {
        traverse( parentunit.GetUnitForShiftOptimization(), Elements, unit )
        {
          nractive := counter( unit, UnitShiftPatternAllowed, usa, usa.IsActive() ); 
          singletonactive := ifexpr( nractive = 1, select( unit, UnitShiftPatternAllowed, usa, true, usa.IsActive() ).ShiftPattern(), null( ShiftPattern ) ); 
          // Get the shift patterns allowed on this unit.
          traverse( unit, UnitShiftPatternAllowed, usa ) 
          {
            sp := usa.ShiftPattern();
            traverse( unit, UnitPeriod.astype(UnitPeriodTime), up )
            {
              if( up.IsInScopeForShiftOptimization( scope ) )
              {
                // Create the variables indicating which shift pattern is used on which unit period.
                isusedvar := program.ShiftPatternIsUsedVariables().New( sp, up );
                nrshiftbinaries++; 
                startvalue := ifexpr( up.ShiftPattern() = sp, 1.0, 0.0 ); 
                isusedvar.StartValue( startvalue ); 
                if ( runcontext.IsMetaIteration() 
                     and ( nractive = 0 // for units not selected to be included, we can just fix to current value
                           or ( not usa.IsActive() and startvalue = 0.0 ) )
                           or ( up.ShiftPattern() = singletonactive ) ) // if only 1 active and equal to assigned shiftpattern, then fix to that one because there is no other option
                {
                  isusedvar.LowerBound( startvalue ); 
                  isusedvar.UpperBound( startvalue );    
                  isusedvar.VariableType( MPVariableType::Continuous().AsString() ); // so in solver log we don't see them as binaries
                  nrshiftbinaries--; 
                }
              
                // Create the variables indicating whether a shift pattern is the first one is a sequence of assignments.
                program.ShiftPatternIsFirstVariables().New( sp, up );
                
                // Create variables for unit periods not in scope that directly follow a unit period in scope.
                nextup := guard ( up.NextPlanningUnitPeriod().astype( UnitPeriodTime ), null( UnitPeriodTime ) );
                if( not isnull( nextup ) and not nextup.IsInScopeForShiftOptimization( scope ) )
                {
                  program.ShiftPatternIsFirstVariables().New( sp, nextup );
                }
              }
              
              // Create slack variables for the minimum shift pattern duration constraint.
              // Variables are created even for unit periods not in scope, because some of them might still be used in the constraint.
              program.ShiftPatternDurationSlackVariables().New( sp, up );
            }
          }   
        }
        
        // Create the variables representing the number of shift pattern changes.
        program.NrShiftPatternChangesVariables().New( parentunit );
      }
    }
    program.StoreReal( 'NrShiftBinaries', [Real]nrshiftbinaries );
  *]
  InterfaceProperties { Accessibility: 'Module' }
}