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