| Quintiq file version 2.0 | 
| #parent: #root | 
| MethodOverride Operation ( | 
|   LibOpt_Task task | 
| ) as stream[JSON] | 
| { | 
|   TextBody: | 
|   [* | 
|     debuginfo(  'ITERATION START >>>>>>>>>>>>>>>>>>>>>>. Previous accepted seqnr =', guard( task.Run().LastAcceptedSnapshotMacroPlannerOptimizer().SequenceNr(), -1 ), 'objtype=', this.DefinitionName() );  | 
|     start := OS::PrecisionCounter();  | 
|     out_scope := LibOpt_Scope::Create( task.Run(), task.Scope().ScopeElements() ); // copy because periods are already in there  | 
|     out_scope.EstimatedNrPISPIPs( 0 );  | 
|      | 
|     lanelegsforopt := selectset(  out_scope.GetLaneLegForOptimization(), Elements, ll, true, true );  | 
|      | 
|     periods := selectset(  out_scope.GetPeriodInOptimizerRun(), Elements, p, true, true );  | 
|     SelectorMeta::ResetAllPISPAttributes( this.Optimization().astype( Optimization ).MacroPlan() ); // for estimated counting puzzle size in #of pispips while we build up the puzzle ( takes into account gap filling is still to happen) | 
|     runcontextmeta := this.GetRunContextMeta();  | 
|     runcontextmeta.SelectorAddedFriends( false ); | 
|     iscampaignoptimization :=  this.Optimization().astype( Optimization ).MacroPlan().StrategyMacroPlan().UseCampaignSequenceOptimizer();  | 
|     /* debugging - single level cplex. Example growing constraint weights as follows:  | 
|      | 
|     weightlevels := select(  task, Run.RunContext.astype( RunContextForCapacityPlanning ).WeightLevelNonFinancial, wl, true, true );  | 
|     growthfactor := runcontextmeta.OptionGrowthFactorConstraintWeights();  | 
|      | 
|     if ( not growthfactor = 1 )  | 
|     { | 
|       weightlevels.UnitCapacityWeight( minvalue(  1e6, weightlevels.UnitCapacityWeight() * growthfactor) );  | 
|       weightlevels.StockingPointCapacityWeight( minvalue( 1e6, weightlevels.StockingPointCapacityWeight() * growthfactor ) );  | 
|       weightlevels.SlackWeight( minvalue(  1e6, weightlevels.SlackWeight() * growthfactor ) );  | 
|        | 
|       debuginfo(  ' ################ unit cap wt=', weightlevels.UnitCapacityWeight(), '######' );  | 
|       debuginfo(  ' ################ stpt cap wt=', weightlevels.StockingPointCapacityWeight(), '######' );  | 
|       debuginfo(  ' ################    slack wt=', weightlevels.SlackWeight(), '######' );  | 
|     } | 
|     */ | 
|     if(  runcontextmeta.IsSelectorBeyondFirstIteration() or iscampaignoptimization ) // for campaign optimization we need to run cplex because level 0 score depends on feasbility of combis | 
|     { | 
|       // build up neighborhood until size at limit | 
|       if ( runcontextmeta.OptionDebugCopyDataSetForSaveRollback() )  | 
|       { | 
|         this.DebugCopyDataSet( task );  | 
|       } | 
|       runcontext := this.GetRunContextCapacityPlanning();  | 
|        | 
|       this.AdaptNeighborhoodSize( task, runcontext, runcontextmeta );  | 
|        | 
|       debuginfo( 'Size limit = ', runcontextmeta.OptionMaxNumberOfPISPIPSForNeighborhood() );  | 
|       task.Log( 'Size limit' + [String] runcontextmeta.OptionMaxNumberOfPISPIPSForNeighborhood() );  | 
|       this.DescriptionSelectedAnchor( '' );  | 
|        | 
|       anchorpispips := this.GetAnchorPISPIPs( out_scope, runcontext, runcontextmeta ); // ordinary operation  | 
|        | 
|       task.Log( 'ANCHOR ' + this.DescriptionSelectedAnchor() );  | 
|       debuginfo( 'ANCHOR', this.DescriptionSelectedAnchor() );    | 
|          | 
|       this.IncreaseTriedCount( anchorpispips );  | 
|        | 
|       this.BuildBasicNeighborhood( anchorpispips, task, out_scope, lanelegsforopt, periods, runcontext, runcontextmeta ); // this method build the basic neighborhood, excluded gap fill + nonleaf pispips | 
|        | 
|       this.PISPGapFill( out_scope, runcontext ); | 
|      | 
|       this.ShelfLifeCompleteSimple( out_scope, runcontext );  | 
|          | 
|       this.AddNonLeafPlanning( out_scope ); | 
|        | 
|       // Handle sales demand before the optimization horizon, including those before the planning horizon. | 
|       TransformerSmartPlan::AddSalesDemandsBeforeScope( out_scope, runcontext ); | 
|        | 
|       this.CompleteForSmallPuzzle( task, runcontext, out_scope ); | 
|        | 
|       out_scope.CompleteForPTO_PIT(); // add in unitperiods, units, operations, trips based on pto and pit  | 
|       out_scope.CompleteFor_PISPIP(); // ensure scope contains period, pisp, spip and sales demand objects for pispip in scope | 
|         | 
|       out_scope.CompleteForCampaignSequencingSimple( this, runcontextmeta, runcontext ); // simple completion of neighborhood for campaign sequencing            | 
|        | 
|       this.ActivateUnitShiftPatterns( runcontext, runcontextmeta, out_scope );  | 
|                                                                                                                                                                          | 
|       if ( this.Optimization().astype( Optimization ).DebugMode() )  | 
|       { | 
|         SelectorMeta::ComputeFirstLastPISPIPInScope( out_scope ); // make sure first last relations are set | 
|         SelectorMeta::CheckNoGap( out_scope ); // in debug mode check gap property | 
|       } | 
|        | 
|       analysis := MathematicalProgramAnalysis::Analysis();  | 
|       if ( guard( analysis.Active(), false ) )  | 
|       { | 
|         info(  'Resetting math program analsyis for iteration' );  | 
|         analysis.ResetAnalysis(); // only keep for last iteration so we can run extended nr of iteration until running into trouble | 
|       } | 
|     } | 
|     else | 
|     { | 
|       debuginfo(  'Skipping first iteration ', this.DefinitionName() );  | 
|     } | 
|     runcontextmeta.IsSelectorBeyondFirstIteration( true ); // first iteration we don't optimize | 
|      | 
|     this.StoreKPIForSubOptimizer( task, out_scope );  | 
|     this.CollectDebugInFormation( task );  | 
|     this.IncreaseInScopeCount( out_scope );  | 
|      | 
|     this.ReducePeriodDecay( task, runcontextmeta );  | 
|      | 
|     end := OS::PrecisionCounter();  | 
|     durationselector := (end-start)/ OS::PrecisionCounterFrequency();  | 
|     debuginfo( 'Done =', DateTime::ActualTime(), 'Duration = ', durationselector );  | 
|     task.Log( 'Selector Duration = ' + [String] durationselector + 'estimate pispips = ' + [String] out_scope.GetEstimatedNrPISPIPs( ));  | 
|     return this.Continue( task, out_scope ); | 
|   *] | 
| } |