Quintiq file version 2.0
|
#parent: #root
|
Method BuildBasicNeighborhood (
|
ProductInStockingPointInPeriodPlannings anchorpispips,
|
LibOpt_Task task,
|
LibOpt_Scope out_scope,
|
LaneLegs lanelegsforopt,
|
Period_MPs periods,
|
RunContextForCapacityPlanning runcontext,
|
RunContextMeta runcontextmeta
|
)
|
{
|
TextBody:
|
[*
|
// this method builds the neighborhood around the anchor (anchorpispips) given as input
|
//
|
// this consists of
|
// 1 upstream supply chain of anchor
|
// 2 downstream supply chain of anchor
|
// 3 of the neighborhood obtained thus far we search upstream along already selected langelegs ( so side products of step 2 can be properly supplied)
|
// In step 1 we look at unit periods that are bottlenecks, if applicable we add
|
// 4 neighborhood to debottlebeck a random set of those unit periods ( consists of upstream + downstream around the bottlebeck - the latter only search along existing planning)
|
// 5 We then inspect the neighborood obtained so far and for a limited set of pispips where pre production is used ( put stuff in inventory end ) we similarly build
|
// a neigbhoorhood to debottleneck that
|
// Finally ( and if there still is room) we go through the procedure of adding friend pispips to the anchor
|
|
|
transformerup := this.GetUpstreamTransformer( runcontext, runcontextmeta );
|
transformerdown := this.GetDownstreamTransformer( runcontext, runcontextmeta );
|
|
this.AddUpstreamNeighborhood( transformerup, out_scope, runcontext, anchorpispips, true, lanelegsforopt, periods, true /*reset visited*/ );
|
|
task.Log( 'after upstream:' + [String] transformerup.PISPIPVisitedUpstream( relsize ) + 'nr pispips =' + [String] out_scope.GetPISPIPInOptimizerRun().Size() );
|
|
pispips_inputs_to_bottleneck := this.GetPISPIPInputsToUnitPeriodBottleNeck( out_scope, runcontext, 10 ); // 10 max period tasks
|
|
// Add downstream neighborhood
|
pispipsfordownstream := out_scope.GetLeafPISPIPsInOptimizerRun();
|
beforesize := out_scope.GetEstimatedNrPISPIPs();
|
this.AddDownStreamLimitedExplore( transformerdown,
|
out_scope,
|
pispipsfordownstream,
|
runcontext,
|
false, // debug
|
runcontextmeta.OptionCheckSizeLimitDownStreamForAnchor(), // check size limit
|
0.25, // fraction of max neighborhood size to use in case of checking size limit
|
runcontextmeta.MaxFanExploreDownStreamLanes(),
|
false, // limit to nonzero planning
|
runcontextmeta.MaxOperationExploreDownStream(),
|
true ); // reset visited at start - does not matter because first call
|
aftersize := out_scope.GetEstimatedNrPISPIPs();
|
task.Log( 'Selector added for downstream (up(anchor)):' + [String]( aftersize - beforesize ) + ' size before = ' + [String] beforesize );
|
|
if ( runcontextmeta.OptionAdditionalUpstreamClosure() )
|
{
|
startpispips := out_scope.GetPISPIPInOptimizerRun();
|
beforesize := out_scope.GetEstimatedNrPISPIPs();
|
transformerup.LimitToAlreadySelectedLaneLegs( true ); // restrict to lane legs discovered in above steps
|
this.AddUpstreamNeighborhood( transformerup, out_scope, runcontext, startpispips, true, lanelegsforopt, periods, false );
|
transformerup.LimitToAlreadySelectedLaneLegs( false );
|
aftersize := out_scope.GetEstimatedNrPISPIPs();
|
|
task.Log( 'Selector added for EXTRA upstream :' + [String]( aftersize - beforesize ) + ' size before = ' + [String] beforesize );
|
}
|
|
transformerup.PISPIPVisitedUpstream( relflush ); // forget what has been visited upstream in above searches ( because it had some restrictions we don't apply below).
|
transformerdown.PISPIPVisitedDownStream( relflush ); // same remark for downstream search
|
|
// in the following calls we do not reset transformer visited pispips anymore, so we do not repeat searches once we hit pispips already visited
|
|
if ( pispips_inputs_to_bottleneck.Size() > 0 and ( out_scope.GetEstimatedNrPISPIPs() < runcontextmeta.OptionMaxNumberOfPISPIPSForNeighborhood() or not runcontextmeta.OptionCheckSizeLimitDebottleneckNeighborhood() ) )
|
{
|
this.AddDebottleneckNeighborhood( task, transformerup, transformerdown, out_scope, runcontext, runcontextmeta, pispips_inputs_to_bottleneck, lanelegsforopt, periods, '[detection in upstream(anchor)]' );
|
}
|
|
task.Log( 'after debottleneck:' + [String] transformerdown.PISPIPVisitedDownStream(relsize ) + '- ' + [String] transformerup.PISPIPVisitedUpstream( relsize ) );
|
|
if ( out_scope.GetEstimatedNrPISPIPs() < runcontextmeta.OptionMaxNumberOfPISPIPSForNeighborhood() or not runcontextmeta.OptionCheckSizeLimitDebottleneckNeighborhood() )
|
{
|
this.AddPreProductionNeighborhood( task, transformerup, transformerdown, out_scope, runcontext, runcontextmeta, lanelegsforopt, periods, null( ProductInStockingPointInPeriodPlanningLeafs ), 50 ); // max 50 pispips to use
|
}
|
|
task.Log( 'after preprod:' + [String] transformerdown.PISPIPVisitedDownStream( relsize ) + '- ' + [String] transformerup.PISPIPVisitedUpstream( relsize ) );
|
|
|
if ( runcontextmeta.OptionAddFriends() and out_scope.GetEstimatedNrPISPIPs() < runcontextmeta.OptionMaxNumberOfPISPIPSForNeighborhood() )
|
{
|
|
this.AddFriendNeighborhoodForAnchorPISPIP( transformerup, transformerdown, out_scope, task, runcontext, runcontextmeta, anchorpispips, lanelegsforopt, periods, false );
|
}
|
|
task.Log( 'after friends:' + [String] transformerdown.PISPIPVisitedDownStream( relsize ) + '- ' + [String] transformerup.PISPIPVisitedUpstream( relsize ) );
|
*]
|
InterfaceProperties { Accessibility: 'Module' }
|
}
|