haorenhui
2023-10-30 6d6cc10d9e8e242661da7fd655dec155a09d676c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
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' }
}