Quintiq file version 2.0
|
#parent: #root
|
Method SetOptimizerInput (
|
LibOpt_Scope scope,
|
RunContextForCapacityPlanning runcontext
|
)
|
{
|
Description: 'Creates scope for run'
|
TextBody:
|
[*
|
// We need to do some partial propegation to ensure the relations used in this method exist.
|
Transaction::Transaction().Propagate( relation( Trip, ArrivalUnitPeriod ) );
|
Transaction::Transaction().Propagate( relation( Trip, DepartureUnitPeriod ) );
|
Transaction::Transaction().Propagate( relation( ProductInTrip, ArrivalPISPIP ) );
|
Transaction::Transaction().Propagate( relation( ProductInTrip, DeparturePISPIP ) );
|
|
periodstart := runcontext.FirstPeriod_MP();
|
periodend := runcontext.LastPeriod_MP();
|
macroplan := periodstart.MacroPlan();
|
|
optpuzzle := scope.GetOptimizerPuzzleInOptimizerRun();
|
|
units := null( Units );
|
pisps := null( ProductInStockingPoint_MPs );
|
sps := construct( StockingPoint_MPs );
|
|
if ( not isnull( optpuzzle ) )
|
{
|
units := optpuzzle.GetIncludedUnits();
|
sps := optpuzzle.GetIncludedStockingPoints( units );
|
pisps := selectset( sps, Elements.ProductInStockingPoint_MP, pisp, pisp.IsLeaf() and pisp.IsInOptimizerPuzzle() );
|
}
|
else
|
{
|
units := selectset( macroplan, Unit, unit, true, true );
|
sps := selectset( macroplan, StockingPoint_MP, sp, true, true );
|
pisps := selectset( macroplan, Product_MP.ProductInStockingPoint_MP, pisp, pisp.IsLeaf() )
|
}
|
|
traverse( units, Elements, unit )
|
{
|
scope.Add( unit );
|
}
|
|
// Set the relation from all pisps
|
traverse( pisps, Elements, pisp )
|
{
|
scope.Add( pisp );
|
}
|
|
// Traverse over all periods that should be included in the optimization
|
scopeperiods := construct( Period_MPs );
|
traverse( macroplan, PlanningPeriod, period,
|
period.IsAvailableForOptimization( periodstart, periodend ) )
|
{
|
// Set a relation to this algorithm run for all periods within the optimization horizon
|
scope.Add( period );
|
scopeperiods.Add( period );
|
|
// Set a relation from all SPinPeriod related to the selected periods to this algorithm run
|
traverse( period, StockingPointInPeriod, spip, spip.StockingPoint_MP().isInOptimizerPuzzle() )
|
{
|
scope.Add( spip );
|
|
// Set a relation from all PISPIP related to the selected spip to this algorithm run
|
// Only include those pispips that belong to a pisp that is part of this algorithm run
|
// Only include those pispips where the product is included.
|
traverse( spip, LeafPlanningPISPIPs, pispip,
|
scope.Contains( pispip.ProductInStockingPoint_MP().PISPInOptimizerRun() ) and
|
( pispip.HasRegularProductForOptimizer() or pispip.GetProductIsIncludedInOptimizerRun( runcontext.IsPostProcessing() ) ) )
|
{
|
scope.Add( pispip );
|
scope.SetLeafAggregateSDIPRelation( pispip );
|
}
|
}
|
|
// Set a relation from all UnitPeriods related to the selected period to this algorithmrun
|
// Only set that relation if the UnitPeriod belongs to a unit that is part of this algorithm run
|
traverse( period, UnitPeriod, up, not up.IsPeriodFrozen() and scope.Contains( up.Unit().UnitInOptimizerRun() ) )
|
{
|
if ( not up.Unit().Operation( relsize ) = 0
|
or exists( up, PeriodTask_MP.astype( PeriodTaskLaneLeg ).Trip, trip, trip.GetIsValidNonFrozenTrip() )
|
or exists( up, astype( UnitPeriodTransportBase ).AsArrivalUnitPeriod, trip, trip.GetIsValidNonFrozenTrip() )
|
or exists( up, astype( UnitPeriodTransportBase ).AsDepartureUnitPeriod, trip, trip.GetIsValidNonFrozenTrip() ) )
|
{
|
scope.Add( up );
|
}
|
// put existing period task operations into scope
|
traverse( up,
|
PeriodTaskOperation,
|
periodtaskoperation,
|
periodtaskoperation.Operation().GetIsAvailableForOptimization()
|
and forall( periodtaskoperation.Operation(), OperationInput.AsInputInProductInStockingPoint_MP, pisp, scope.Contains( pisp.PISPInOptimizerRun() ) )
|
and forall( periodtaskoperation.Operation(), OperationOutput.AsOutputInProductInStockingPoint_MP, pisp, scope.Contains( pisp.PISPInOptimizerRun() ) ) )
|
{
|
scope.Add( periodtaskoperation );
|
}
|
}
|
}
|
|
// Set the relation from the operations related to the selected units to this algorithmrun
|
operationsaddedtoscope := construct( Operations );
|
traverse( units, Elements, unit )
|
{
|
traverse( unit, Operation, operation,
|
operation.GetIsAvailableForOptimization()
|
and forall( operation, OperationInput.AsInputInProductInStockingPoint_MP, pisp, scope.Contains( pisp.PISPInOptimizerRun() ) )
|
and forall ( operation, OperationOutput.AsOutputInProductInStockingPoint_MP, pisp, scope.Contains( pisp.PISPInOptimizerRun() ) ) )
|
//)
|
{
|
scope.Add( operation );
|
operationsaddedtoscope.Add( operation );
|
unit.OptimizerFullRunAddedOperationOrTrip( true );
|
}
|
}
|
|
// Set the relation from the trips that are part of the selected units and the selected unit periods to this algorithmrun
|
traverse( units, Elements, unit )
|
{
|
traverse( unit, Lane.LaneLeg, laneleg,
|
laneleg.GetIsAvailableForOptimization() )
|
{
|
traverse( laneleg,
|
Trip,
|
trip,
|
trip.HasValidArrival()
|
and trip.HasValidDeparture()
|
and guard( scope.Contains( trip.DepartureUnitPeriod().UnitPeriodInOptimizerRun() ), false )
|
and guard( scope.Contains( trip.ArrivalUnitPeriod().UnitPeriodInOptimizerRun() ), false )
|
and trip.LaneLeg().AsOriginStockingPointLeg().StockingPoint_MP().isInOptimizerPuzzle()
|
and trip.LaneLeg().AsDestinationStockingPointLeg().StockingPoint_MP().isInOptimizerPuzzle() )
|
{
|
scope.Add( trip );
|
unit.OptimizerFullRunAddedOperationOrTrip( true );
|
|
// Set the relation from all products in this trip to this algorithmrun
|
// Both the arrival and departure PISPIP must be part of this algorithm run
|
// Only include those productintrips where the product is included.
|
traverse( trip, ProductInTrip, productintrip,
|
guard( scope.Contains( productintrip.ArrivalPISPIP().PISPIPInOptimizerRun() ), false )
|
and guard( scope.Contains( productintrip.DeparturePISPIP().PISPIPInOptimizerRun() ), false )
|
and guard( productintrip.HasRegularProductForOptimizer() or productintrip.Product_MP().GetIsInOptimizerRun( runcontext.IsPostProcessing() ), false )
|
)
|
{
|
scope.Add( productintrip );
|
}
|
}
|
}
|
}
|
|
// Remove the units that have no operations or trips for optimization
|
traverse( units, Elements, unit, // full run uses all units - added above - no need to check scope again
|
not unit.OptimizerFullRunAddedOperationOrTrip() )
|
{
|
unit.UnitInOptimizerRun().Delete();
|
traverse( unit, UnitPeriod.UnitPeriodInOptimizerRun, unitperiodinrun, scope.Contains( unitperiodinrun ) )
|
{
|
unitperiodinrun.Delete();
|
}
|
}
|
|
// The PISPIPs that contain the dependent demand of a valid operation-period combination should also be considered
|
traverse( operationsaddedtoscope, Elements, operation )
|
{
|
ddperiodstotal := construct( Period_MPs, constcontent );
|
periods := this.GetPeriodsForOperation( scopeperiods, operation );
|
|
traverse( periods, Elements, period )
|
{
|
ddperiods := construct( Period_MPs, constcontent );
|
CapacityPlanningSuboptimizer::GetOperationDependentDemandPeriods( period, operation, &ddperiods, false );
|
ddperiodstotal := ddperiodstotal.Add( ddperiods );
|
}
|
ddperiodstotal := ddperiodstotal.Unique();
|
|
if ( ddperiodstotal.Size() > 0 )
|
{
|
pispiptoadd := selectset( operation,
|
OperationInput.ProductInStockingPoint_MP.ProductInStockingPointInPeriodPlanning,
|
pispip,
|
ddperiodstotal.Find( pispip.Period_MP() ) > 0
|
and ( pispip.HasRegularProductForOptimizer() or pispip.GetProductIsIncludedInOptimizerRun( runcontext.IsPostProcessing() ) )
|
and not scope.Contains( pispip.PISPIPInOptimizerRun() ) )
|
|
traverse( pispiptoadd, Elements, pispip )
|
{
|
scope.Add( pispip );
|
scope.Add( pispip.StockingPointInPeriod() );
|
scope.Add( pispip.ProductInStockingPoint_MP() );
|
}
|
}
|
}
|
|
// Handle sales demand before the optimization horizon, including those before the planning horizon.
|
if( macroplan.FirstPlanningPeriod().Start() < periodstart.Start() ) // If there exists planning periods before the optimization horizon.
|
{
|
traverse( macroplan, SalesSegment_MP.PostponementSpecification, postponementspec,
|
postponementspec.IsValidData()
|
)
|
{
|
traverse( postponementspec, SalesDemandInPeriod.astype( SalesDemandInPeriod ), sdip,
|
not sdip.IsPostponed()
|
and sdip.CanOptimizeWhenPostponed( periodstart )
|
and sdip.NeedsToBePlanned()
|
and sdip.IsWithinThresholdQuantity()
|
and sdip.GetIsPISPAndProductInOptimizerRun( scope, runcontext.IsPostProcessing() )
|
)
|
{
|
scope.AddSDIPBeforeScope( sdip );
|
sdip.SDIPBeforeScopeInRun().OptMinPostponementPeriod( periodstart.SequenceNrInPeriodSpecification()
|
- sdip.AsSalesDemandInPeriodBase().Period_MP().SequenceNrInPeriodSpecification()
|
);
|
}
|
}
|
}
|
|
if ( runcontext.IsSlidingWindowsRun() )
|
{
|
this.SetSlidingWindowPeriods( scope, runcontext, periodstart ); // method requires periods already added
|
}
|
*]
|
InterfaceProperties { Accessibility: 'Module' }
|
}
|