| 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' } | 
| } |