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