yanweiyuan3
2023-08-09 588bc7829387dfc761cc25f06f77d4c81818bd10
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
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' }
}