| Quintiq file version 2.0 | 
| #parent: #root | 
| Method CapacityPlanningAlgorithmHandleFeasible ( | 
|   CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program, | 
|   const RunContextForCapacityPlanning runcontext, | 
|   LibOpt_Task task | 
| ) as CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm | 
| { | 
|   Description: 'The method called in "Handle feasible" tab' | 
|   TextBody: | 
|   [* | 
|     scope := task.Scope();  | 
|     // Program goal value is affected by goal scaling factor. It is intended to show the CPLEX value with scaling applied | 
|     goalvalue := program.GoalValue(); | 
|     isinventoryoptimization := runcontext.IsInventoryOptimizationRun(); | 
|     // We only want to report the progress of the algorithm runs if this is not an autotune copy and this is not an inventory optimization | 
|     isdisplay := not isinventoryoptimization | 
|                  and not runcontext.IsMetaIteration(); | 
|      | 
|     // Do not report the current level if this is an inventory optimization run | 
|     if( isdisplay ) | 
|     { | 
|       info( Translations::Algorithm_MP_InfoCurrentLevel( [String]this.CurrentSubOptimizerLevel().LevelNumber() ) ); | 
|       info( Translations::Algorithm_MP_InfoFeasibleCapacityPlanning( [String]DateTime::ActualTime(), [String]goalvalue ) ); | 
|     } | 
|      | 
|     dofinalize := this.CurrentSubOptimizerLevel().IsLast() or ( this.UseHierarchicalCPLEXGoals() );  | 
|     justoptimizerhiddenslacklevel := this.CurrentSubOptimizerLevel().IsFirst();  | 
|     algorithmrun := this.MacroPlan().GetLastAlgorithmRun();  | 
|     iscampainoptimization := runcontext.UseCampaignSequenceOptimizer();  | 
|      | 
|     if ( not runcontext.IsMetaIteration() )  | 
|     { | 
|       this.DebugWriteForAutoTestInstances( program, runcontext, scope );  | 
|       this.AppendLastRunResultToLogFile( program );  // Update the log file with the latest results | 
|     } | 
|      | 
|     // Update postprocessing start | 
|     algorithmrun.UpdatePostprocessingTime( DateTime::ActualTime(), algorithmrun.PostprocessingEnd() ); | 
|      | 
|     if( isdisplay ) | 
|     { | 
|       this.DisplayGoalValue( program, runcontext );   // Display scores | 
|     } | 
|     if( not task.IsAborted() | 
|         and dofinalize | 
|         and ( not runcontext.IsMetaIteration() or ( this.IsBeyondFirstIteration() or iscampainoptimization)  or this.IsFullPlanMetaPriorFocus() ) ) // first iteration for meta optimizer we don't plan, unless campaign optimization | 
|     {                                                                                                                                               // as we need to know feasbility of campaign combis, for level 0 score | 
|       pispipsinrun := scope.GetPISPIPInOptimizerRun();  | 
|       // Handle feasible methods to assign optimizer optimal value to attributes | 
|       this.ResetPeriodTaskCampaign( runcontext, scope );  | 
|       this.CapacityPlanningAlgorithmHandleFeasibleCampaignSequencing( program, runcontext, task ); | 
|       this.CapacityPlanningAlgorithmHandleFeasibleOperationPeriodTask( program, runcontext, task ); | 
|       this.CapacityPlanningAlgorithmHandleFeasibleTrip( program, scope ); | 
|       this.CapacityPlanningAlgorithmHandleFeasibleSalesDemand( program, runcontext, scope, pispipsinrun ); | 
|       this.CapacityPlanningAlgorithmHandleFeasibleProductInStockingPointInPeriod( program, runcontext, scope, this.Setting_KeepTotAlavailableSupplyOverride(), pispipsinrun ); | 
|       this.CapacityPlanningAlgorithmHandleFeasibleShiftPattern( program, runcontext, scope ); | 
|       this.SetOptimizerFulfilledTargetInventoryQuantityPastHorizon( runcontext, scope ); | 
|       Transaction::Transaction().Propagate();  | 
|       this.DebugWriteVariables( program, scope, pispipsinrun );  | 
|       if ( runcontext.IsSlidingWindowsRun() )  | 
|       { | 
|         this.CurrentSubOptimizerLevel( relset, this.FirstSubOptimizerLevel() );  | 
|       } | 
|       else | 
|       { | 
|         this.CurrentSubOptimizerLevel( relflush ); // signal for post handle results, so we only obtain KPIs all the way at the end (is expensive) | 
|       } | 
|       if ( this.Optimization().astype( Optimization ).DebugMode() )  | 
|       { | 
|         this.Optimization().astype( Optimization ).CheckOptimizerPuzzle( task );    | 
|       } | 
|     } | 
|      | 
|     // Update postprocessing end | 
|     algorithmrun.UpdatePostprocessingTime( algorithmrun.PostprocessingStart(), DateTime::ActualTime() ); | 
|      | 
|     isunfreeze := false; | 
|     if ( justoptimizerhiddenslacklevel  | 
|          and not dofinalize )  | 
|     { | 
|       this.FreezeZeroSlack( program, isunfreeze, runcontext, scope ); | 
|     } | 
|      | 
|     if( ( not runcontext.IsMetaIteration() or ( this.IsBeyondFirstIteration() or iscampainoptimization ) or this.IsFullPlanMetaPriorFocus() ) // first iteration of level for meta optimizer we do plan, just record KPI to check skip to next focuslevel  | 
|         and not task.IsAborted() | 
|         and not dofinalize ) | 
|     { | 
|       this.SetNextSubOptimizerLevelAsCurrent();  | 
|       this.ActivateGoals( program, runcontext, scope );          //activate terms for next level | 
|      | 
|       if( isdisplay ) | 
|       { | 
|         info( Translations::Algorithm_MP_InfoReExecuteLevel( [String]DateTime::ActualTime(), [String]( this.CurrentSubOptimizerLevel().LevelNumber() ), [String]goalvalue ) ); | 
|         this.AddLogFileMarking( program ); | 
|       } | 
|        | 
|       // Re-execute cplex | 
|       program.MIPStartSolution( true ); | 
|       this.ReExecute( program ); | 
|          | 
|       // Add extension to program file name such that it is postfix with level | 
|       filename := program.ProblemFileName(); | 
|       if( filename <> Util::Const_EmptyString() ) | 
|       { | 
|         nextlevel := this.CurrentSubOptimizerLevel().LevelNumber();  | 
|         strings := filename.Tokenize( Util::Const_Dot() ); | 
|         extension := ifexpr( this.IsLPFileExported(), Translations::Algorithm_MP_FileExtensionSav(), guard( strings.Element( strings.Size() - 1 ), Translations::Algorithm_MP_FileExtensionSav() ) ); | 
|         program.ProblemFileName( Translations::Algorithm_MP_ProblemFileName( nextlevel.AsQUILL(), extension ) ); | 
|         debuginfo( 'Problem file name=', program.ProblemFileName() ); | 
|       } | 
|     } | 
|      | 
|     // Run the autoscaling | 
|     if( this.IsAutoScalingEnabled() and dofinalize ) | 
|     { | 
|       // Update the rest of the statistics and run the autoscaling after the last level | 
|       this.RunAutoScaling( program, task, runcontext.IsMetaIteration() ); | 
|     } | 
|      | 
|     if ( not runcontext.IsMetaIteration() )  | 
|     { | 
|       algorithmrun.CalcRunUIFeedback(); // AlgorithmRunLevel IsFeasible attribute is set above and this method should be called for propagating | 
|     } | 
|      | 
|     if( dofinalize   | 
|         and not runcontext.IsMetaIteration() ) | 
|     { | 
|       // If this is a sliding windows run and the last period in the active window is not the last period in the optimizer run | 
|       // then slide the window and reexecute the algorithm | 
|       lastperiodinwindow := maxselect( scope.GetPeriodInSlidingWindow(), Elements, period, true, period.Start() ); | 
|       if( runcontext.IsSlidingWindowsRun() | 
|           and lastperiodinwindow <> runcontext.LastPeriod_MP() ) | 
|       { | 
|         this.ReExecuteOptimizerSlidingWindows( program, runcontext, task ); | 
|       } | 
|       else | 
|       {     | 
|         if( runcontext.IsInventoryOptimizationRun() ) | 
|         { | 
|           runcontext_nonconst := select( task, Run.RunContext.astype( RunContextForCapacityPlanning ), rctxt, true, true ); // workaround because we don't want avoid the cascase of const argument down this path | 
|           this.CapacityPlanningAlgorithmHandleFeasibleInventoryOptimization( runcontext_nonconst, scope ); | 
|         } | 
|      | 
|         if( algorithmrun.IsBenchmark() ) | 
|         { | 
|           Transaction::Transaction().Propagate(); | 
|           algorithmrun.NumberOfSanityCheckErrors( this.MacroPlan().SanityCheckHighestSeverityMsgCount() ); | 
|           if(  algorithmrun.NumberOfSanityCheckErrors() > 0 ) | 
|           { | 
|             algorithmrun.SanityCheckHighestSeverityToolTip( Translations::MP_SanityCheck_Failed( this.MacroPlan().MostSevereSanityCheckCategoryLevel() ) ); | 
|           } | 
|         } | 
|       } | 
|     } | 
|      | 
|     return program; | 
|   *] | 
|   InterfaceProperties { Accessibility: 'Module' } | 
| } |