| 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' } | 
| } |