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 );
|
*]
|
}
|