Quintiq file version 2.0 
 | 
#parent: #root 
 | 
Method ReExecuteOptimizerSlidingWindows ( 
 | 
  CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program, 
 | 
  const RunContextForCapacityPlanning runcontext, 
 | 
  LibOpt_Task task 
 | 
) 
 | 
{ 
 | 
  TextBody: 
 | 
  [* 
 | 
    // Unfreeze the slack variables 
 | 
    // Since we will change some variables from continuous to integer, it could be that the slacks from the previous run are insufficient 
 | 
    isunfreeze := true; 
 | 
    scope := task.Scope();  
 | 
    this.FreezeZeroSlack( program, isunfreeze, runcontext, scope  ); 
 | 
     
 | 
    periodslastwindow := selectset( scope.GetPeriodInSlidingWindow(), Elements, period, true ); 
 | 
     
 | 
    // Select the first period in the next window 
 | 
    // From the first period in the previous window we move NumberOfPeriodsPerSlide forward 
 | 
    // Each period that we move forward is added to the set of newly frozen periods 
 | 
    firstperiod := minselect( periodslastwindow, Elements, period, true, period.Start() ); 
 | 
     
 | 
    newfrozenperiods := construct( Period_MPs ); 
 | 
    for( i:= 1; 
 | 
         i <= runcontext.NumberOfPeriodsPerSlide() 
 | 
         and not isnull( firstperiod.NextPlanningPeriod() ); 
 | 
         i++ ) 
 | 
    { 
 | 
      newfrozenperiods.Add( firstperiod ); 
 | 
      firstperiod := firstperiod.NextPlanningPeriod(); 
 | 
    } 
 | 
     
 | 
    // Remove from scope the periods that are no longer in the active window 
 | 
    traverse( newfrozenperiods, Elements, period, period.GetIsInSlidingWindow( scope ) ) 
 | 
    { 
 | 
      period.PeriodInSlidingWindow().Delete();  
 | 
    } 
 | 
     
 | 
    // Add periods in the new window to the scope and select them 
 | 
    this.SetSlidingWindowPeriods( firstperiod, runcontext, scope ); 
 | 
    periodsnextwindow := selectset( scope.GetPeriodInSlidingWindow(), Elements, period, true ); 
 | 
     
 | 
    // Freeze the binary/integer variables that are in the newly frozen periods 
 | 
    // First freeze the semicontinous PTQty variable 
 | 
    if( runcontext.UseProcessMinimumQuantity() or runcontext.UseLotSize() ) 
 | 
    { 
 | 
      traverse( newfrozenperiods, Elements, period, 
 | 
                period.IsWithinLotSizeHorizon() ) 
 | 
      { 
 | 
        traverse( period, UnitPeriod, unitperiod, 
 | 
                 scope.Contains( unitperiod.UnitPeriodInOptimizerRun() ) ) 
 | 
        { 
 | 
          operations := this.GetOperationsForUnitPeriod( scope, unitperiod ); 
 | 
          traverse( operations, Elements, operation ) 
 | 
          { 
 | 
            // Freeze the period task operation minimum process quantity variables 
 | 
            if( runcontext.UseProcessMinimumQuantity() 
 | 
                and operation.HasMinimumQuantity() ) 
 | 
            { 
 | 
              ptvar := program.PTQtyVariables().Get( operation, period );  
 | 
              optimalvalue := this.GetOptimalValue( ptvar ); 
 | 
              this.FreezeVariableWithSlack( ptvar, optimalvalue ); 
 | 
            } 
 | 
             
 | 
            // Freeze the period task operation lotsize variables 
 | 
            if( runcontext.UseLotSize() 
 | 
                and operation.HasLotSize() ) 
 | 
            { 
 | 
              ptnroflotsvar := program.PTNrOfLotsVariables().Get( operation, period ); 
 | 
              optimalvalue := this.GetOptimalValue( ptnroflotsvar ); 
 | 
              this.FreezeVariableWithSlack( ptnroflotsvar, optimalvalue ); 
 | 
            } 
 | 
             
 | 
            // Freeze the operation input lot size variables 
 | 
            if( runcontext.UseLotSize() 
 | 
                and operation.HasInputLotSize() ) 
 | 
            { 
 | 
              periodsfordd := construct( Period_MPs, constcontent ); // periods for dependent demand 
 | 
             
 | 
              // Consider all relevant periods for the dependent demand 
 | 
              CapacityPlanningSuboptimizer::GetOperationDependentDemandPeriods( period, operation, &periodsfordd, this.GetPeriodsFromPeriodTaskOperation() ); // period itself may be included twice  
 | 
              periodsfordd := periodsfordd.Unique(); 
 | 
               
 | 
              traverse( periodsfordd, Elements, ddperiod, 
 | 
                        period.IsWithinLotSizeHorizon() ) 
 | 
              {  
 | 
                // Freeze the operation input lot size variables 
 | 
                traverse( operation,  
 | 
                          OperationInput,  
 | 
                          input, 
 | 
                          input.ProductInStockingPoint_MP().HasInputLotSize()  
 | 
                          and ( input.HasRegularProductforOptimizer() or input.GetIsProductInOptimizerRun( runcontext.IsPostProcessing() ) ) )  
 | 
                { 
 | 
                  operationinputnroflotsvar := program.OperationInputNrOfLotsVariables().Get( input, ddperiod ); 
 | 
                  optimalvalue := this.GetOptimalValue( operationinputnroflotsvar ); 
 | 
                  this.FreezeVariableWithSlack( operationinputnroflotsvar, optimalvalue ); 
 | 
                } 
 | 
              } 
 | 
            } 
 | 
          } 
 | 
        } 
 | 
        // Freeze the trip lotsize variables 
 | 
        if( runcontext.UseLotSize() ) 
 | 
        { 
 | 
          traverse( period, UnitPeriod.astype( UnitPeriodTransportBase ), unitperiod, 
 | 
                    unitperiod.HasLotSize() ) 
 | 
          { 
 | 
            traverse( unitperiod, AsDepartureUnitPeriod, trip, 
 | 
                      scope.Contains(  trip.TripInOptimizerRun() ) ) 
 | 
            { 
 | 
              // TripNrOfLots variable UoM: Number 
 | 
              tripnroflotsvar := program.TripNrOfLotsVariables().Get( trip ); 
 | 
              optimalvalue := this.GetOptimalValue( tripnroflotsvar ); 
 | 
              this.FreezeVariableWithSlack( tripnroflotsvar, optimalvalue ); 
 | 
            } 
 | 
          } 
 | 
        } 
 | 
      } 
 | 
    } 
 | 
     
 | 
    remainingwindowperiods := periodsnextwindow.Intersect( periodslastwindow ); 
 | 
    newwindowperiods := periodsnextwindow.Difference( remainingwindowperiods ); 
 | 
     
 | 
    // Make set variables in the periods that are new in the sliding window to integer 
 | 
    if( runcontext.UseProcessMinimumQuantity() or runcontext.UseLotSize() ) 
 | 
    { 
 | 
      traverse( newwindowperiods, Elements, period, 
 | 
                period.IsWithinLotSizeHorizon() ) 
 | 
      { 
 | 
        traverse( period, UnitPeriod, unitperiod, 
 | 
                 scope.Contains(  unitperiod.UnitPeriodInOptimizerRun() ) ) 
 | 
        { 
 | 
          operations := this.GetOperationsForUnitPeriod( scope, unitperiod ); 
 | 
          traverse( operations, Elements, operation ) 
 | 
          { 
 | 
            // Set the period task operation minimum process quantity variables that are new to the sliding window to semicontinous 
 | 
            if( runcontext.UseProcessMinimumQuantity() 
 | 
                and operation.HasMinimumQuantity() ) 
 | 
            { 
 | 
              ptvar := program.PTQtyVariables().Get( operation, period ); 
 | 
              ptvar.VariableType( 'SemiContinuous' ); 
 | 
              lowerbound := operation.MinimumQuantity() / operation.QuantityToProcessFactor();    
 | 
              if ( lowerbound > 0 )  
 | 
              { 
 | 
                this.FreezeVariableLowerBound( ptvar, lowerbound ); 
 | 
              } 
 | 
            } 
 | 
            // Set the period task operation lotsize variables that are new to the sliding window to integer 
 | 
            if( runcontext.UseLotSize() 
 | 
                and operation.HasLotSize() ) 
 | 
            { 
 | 
              ptnroflotsvar := program.PTNrOfLotsVariables().Get( operation, period ); 
 | 
              ptnroflotsvar.VariableType( 'Integer' ); 
 | 
            } 
 | 
             
 | 
            // Set the operation input lot size variables that are new to the sliding window to integer 
 | 
            if( runcontext.UseLotSize() 
 | 
                and operation.HasInputLotSize() ) 
 | 
            { 
 | 
              periodsfordd := construct( Period_MPs, constcontent ); // periods for dependent demand 
 | 
             
 | 
              // Consider all relevant periods for the dependent demand 
 | 
              CapacityPlanningSuboptimizer::GetOperationDependentDemandPeriods( period, operation, &periodsfordd, this.GetPeriodsFromPeriodTaskOperation() ); // period may be added twice 
 | 
              periodsfordd := periodsfordd.Unique();  
 | 
                     
 | 
              traverse( periodsfordd, Elements, ddperiod, 
 | 
                        period.IsWithinLotSizeHorizon() ) 
 | 
              { 
 | 
                traverse( operation, OperationInput, input, 
 | 
                          input.GetIsProductInOptimizerRun( runcontext.IsPostProcessing() ) 
 | 
                          and input.ProductInStockingPoint_MP().HasInputLotSize() ) 
 | 
                { 
 | 
                  operationinputnroflotsvar := program.OperationInputNrOfLotsVariables().Get( input, ddperiod ); 
 | 
                  operationinputnroflotsvar.VariableType( 'Integer' ); 
 | 
                } 
 | 
              } 
 | 
            } 
 | 
          } 
 | 
        } 
 | 
         
 | 
        // Set the trip lotsize variables that are new to the sliding window to integer 
 | 
        if( runcontext.UseLotSize() ) 
 | 
        { 
 | 
          traverse( period, UnitPeriod.astype( UnitPeriodTransportBase ), unitperiod, 
 | 
                    unitperiod.HasLotSize() ) 
 | 
          { 
 | 
            traverse( unitperiod, AsDepartureUnitPeriod, trip, 
 | 
                      scope.Contains(  trip.TripInOptimizerRun() ) ) 
 | 
            { 
 | 
              // TripNrOfLots variable UoM: Number 
 | 
              tripnroflotsvar := program.TripNrOfLotsVariables().Get( trip ); 
 | 
              tripnroflotsvar.VariableType( 'Integer' ); 
 | 
            } 
 | 
          } 
 | 
        } 
 | 
      } 
 | 
    } 
 | 
     
 | 
    // Add the new window periods to the algorithmrun 
 | 
    traverse( newwindowperiods, Elements, period ) 
 | 
    { 
 | 
      scope.Add( period.PeriodInSlidingWindow( relnew ) );   
 | 
    } 
 | 
     
 | 
    // reset lower bounds on goal variables for the next window 
 | 
    traverse( this, MacroPlan.StrategyMacroPlan.StrategyLevelMacroPlan, level )  
 | 
    { 
 | 
      var := program.GoalForLevelVariables().Get( level );  
 | 
      var.LowerBound( Real::MinReal() );  
 | 
    } 
 | 
    // Remove the active goals 
 | 
    traverse( program.Goal().Terms(), Elements, term ) 
 | 
    { 
 | 
      term.Coefficient( 0.0 ); 
 | 
    } 
 | 
     
 | 
     
 | 
     
 | 
    // Reexecute the algorithm and start from the first level and reactivate the level 1 goals 
 | 
    this.ReExecute( program ); 
 | 
    this.CreateSubOptimizerLevels( runcontext, task );  
 | 
    this.ActivateGoals( program, runcontext, scope ); 
 | 
     
 | 
    info( "----------- Sliding the lotsize window -----------" ); 
 | 
    info( "-------- New window starts at ", minselect( periodsnextwindow, Elements, period, true, period.Start() ).Start() ); 
 | 
    info( "------------- Reexecuting algorithm --------------" ); 
 | 
  *] 
 | 
  InterfaceProperties { Accessibility: 'Module' } 
 | 
} 
 |