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
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
Quintiq file version 2.0
#parent: #root
Method GetNonFinancialKPI (
  Number level,
  Boolean includeintbased,
  Boolean intbasedonly,
  output String msg_o,
  const WeightLevelNonFinancial weightlevels,
  output Real minweightused,
  output Real maxweightused
) as Real
{
  TextBody:
  [*
    // Storing of goal value to instances
    
    msg := ''; 
    dummy1 := 0.0; 
    dummy2 := 0.0; 
    dummy3 := 0.0; 
    value := 0.0; 
    subopt := this.Suboptimizer().astype( CapacityPlanningSuboptimizer ); 
    mp := subopt.Run().Optimization().astype( Optimization ).MacroPlan(); 
    if ( not isnull( weightlevels ) ) 
    {
      eis := mp.OptimizerMetaEIS(); 
      if ( not eis.IsNeedEstimatedImprovementScores()  ) // used so we can also write scores to snapshot in smartplan , full optimizer
      {
        eis.TemporaryForScoreWriting( true ); 
        Transaction::Transaction().Propagate( attribute( OptimizerMetaEIS, KPIBalanceViolation ) ); 
        Transaction::Transaction().Propagate( attribute( OptimizerMetaEIS, KPILotSizeTotal ) ); 
        Transaction::Transaction().Propagate( attribute( OptimizerMetaEIS, KPIMaximumInventory ) ); 
        Transaction::Transaction().Propagate( attribute( OptimizerMetaEIS, KPIMinimumInventory ) ); 
        Transaction::Transaction().Propagate( attribute( OptimizerMetaEIS, KPITargetInventory ) ); 
        Transaction::Transaction().Propagate( attribute( OptimizerMetaEIS, KPISalesDemandPriority ) );                                                                                                                      
        eis.TemporaryForScoreWriting( false ); 
      }
      
      if ( intbasedonly ) 
      {
        valuelotsize :=  ifexpr( level = weightlevels.LotSizeLevel(), -eis.KPILotSizeTotal() * this.AdjustMinMax( minweightused, maxweightused, weightlevels.LotSizeWeight() ), 0.0  )
        msg := msg + 'KPILotSize=' + [String]valuelotsize + String::NewLine();
        valueprocessminqty :=  ifexpr( level = weightlevels.SlackLevel(), // note process min qty is implemented with BIGM. It should be score on the hidden slack level 
                                       -mp.GetKPIProcessMinimumQuantity(this.CutOffProcessMinQtyKPI() ) * this.AdjustMinMax( minweightused, maxweightused, weightlevels.ProcessMinimumQuantityWeight() ),  0.0 ) 
        msg := msg + 'KPIProcessMinQty=' + [String] valueprocessminqty + String::NewLine();
        value := valuelotsize + valueprocessminqty; 
      }
      else
      { 
        valuelotsize :=  ifexpr( includeintbased and level = weightlevels.LotSizeLevel(), -eis.KPILotSizeTotal() * this.AdjustMinMax( minweightused, maxweightused, weightlevels.LotSizeWeight() ), 0.0  )
        msg := msg + 'KPILotSize=' + [String]valuelotsize + String::NewLine();
        valueprocessminqty :=  ifexpr( includeintbased and level =weightlevels.SlackLevel(), // note process min qty is implemented with BIGM. It should be score on the hidden slack level 
                                       -mp.GetKPIProcessMinimumQuantity( this.CutOffProcessMinQtyKPI()) * this.AdjustMinMax( minweightused, maxweightused, weightlevels.ProcessMinimumQuantityWeight() ),  0.0 ) 
        msg := msg + 'KPIProcessMinQty=' + [String] valueprocessminqty + String::NewLine();
        
        valuecampaign := ifexpr( level = weightlevels.CampaignLevel(), 
                                 -RollbackKPIMeta::GetCampaignScore( weightlevels.RunContextForCapacityPlanning(), mp, dummy1, dummy2, dummy3 ) * this.AdjustMinMax( minweightused, maxweightused, weightlevels.CampaignWeight() ),  0.0 ); 
        msg := msg + 'KPICampagin=' + [String]valuecampaign + String::NewLine(); 
        valuefulfillment :=  ifexpr( level = weightlevels.FulfillmentLevel(), mp.GetKPIFulfillment() * this.AdjustMinMax( minweightused, maxweightused, weightlevels.FulfillmentWeight() ), 0.0 ); 
        msg := msg + 'KPIfulfillment=' + [String]valuefulfillment + String::NewLine();
        valueinventorymix :=  ifexpr( level = weightlevels.InventoryMixBalancingLevel(), -mp.GetKPIInventoryMixBalancing() * this.AdjustMinMax( minweightused, maxweightused, weightlevels.InventoryMixBalancingWeight() ), 0.0  )  
        msg := msg + 'KPIInventoryMixBalancing=' + [String]valueinventorymix + String::NewLine();
        valuemaxinventory :=  ifexpr( level = weightlevels.MaximumInventoryLevel(),  -eis.KPIMaximumInventory() * this.AdjustMinMax( minweightused, maxweightused, weightlevels.MaximumInventoryLevelWeight() ), 0.0  ) 
        msg := msg + 'KPIMaxInventoryLevel=' + [String] valuemaxinventory + String::NewLine();
        valuemininventory := ifexpr( level = weightlevels.MinimumInventoryLevel(), -eis.KPIMinimumInventory() * this.AdjustMinMax( minweightused, maxweightused, weightlevels.MinimumInventoryLevelWeight() ), 0.0  )
        msg := msg + 'KPIMinInventoryLevel=' + [String] valuemininventory + String::NewLine();
        valuesupplytarget :=  ifexpr( level = weightlevels.SupplyTargetLevel(), -mp.GetKPISupplyTarget() * this.AdjustMinMax( minweightused, maxweightused, weightlevels.SupplyTargetWeight() ),  0.0 )
        msg := msg + 'KPISupplyTarget=' + [String]valuesupplytarget + String::NewLine();
        valueminsupply :=  ifexpr( level = weightlevels.MinimumSupplyLevel(),  -mp.GetKPIMinimumSupply() * this.AdjustMinMax( minweightused, maxweightused, weightlevels.MinimumSupplyWeight() ), 0.0  ) 
        msg := msg + 'KPIMinSupply=' + [String] valueminsupply + String::NewLine();
        valuemaxsupply :=  ifexpr( level = weightlevels.MaximumSupplyLevel(),  -mp.GetKPIMaximumSupply() * this.AdjustMinMax( minweightused, maxweightused, weightlevels.MaximumSupplyWeight() ), 0.0  ) 
        msg := msg + 'KPIMaxSupply=' + [String] valuemaxsupply + String::NewLine();
        valueminunitcap :=  ifexpr( level = weightlevels.MinimumUnitCapacityLevel(), -mp.GetKPIUnitCapacityNotMet() * this.AdjustMinMax( minweightused, maxweightused, weightlevels.MinimumUnitCapacityWeight() ), 0.0 ) 
        msg := msg + 'KPIMinUnitCapacity=' + [String] valueminunitcap + String::NewLine();
        valuepostpone :=  ifexpr( level = weightlevels.PostponementPenaltyLevel(),  -mp.GetKPIPostponementPenalty() * this.AdjustMinMax( minweightused, maxweightused, weightlevels.PostponementPenaltyWeight() ), 0.0  ) 
        msg := msg + 'KPIPostponementPenalty=' + [String] valuepostpone + String::NewLine();
        valueprocessmaxqty :=  ifexpr( level = weightlevels.ProcessMaximumQuantityLevel(),  -mp.GetKPIProcessMaximumQuantity() * this.AdjustMinMax( minweightused, maxweightused, weightlevels.ProcessMaximumQuantityWeight() ), 0.0  ) 
        msg := msg + 'KPIProcessMaxQty=' + [String] valueprocessmaxqty + String::NewLine();
      
        valuesalesdemandprio :=  ifexpr( level = weightlevels.SalesDemandPriorityLevel(), eis.KPISalesDemandPriority() * this.AdjustMinMax( minweightused, maxweightused, weightlevels.SalesDemandPriorityWeight() ), 0.0   ) // use attribute to avoid expensive kpi method
        msg := msg + 'KPISalesDemandPrio=' + [String] valuesalesdemandprio + String::NewLine();
        valuefftarget :=  ifexpr( level = weightlevels.FulfillmentTargetLevel(), mp.GetKPIFulfillmentTargetOpt() * this.AdjustMinMax( minweightused, maxweightused, weightlevels.FulfillmentTargetWeight() ),   0.0  ) 
        msg := msg + 'KPIFulfillmentTarget=' + [String] valuefftarget + String::NewLine(); // note KPIFulfillmentTarget is a poor KPI to gauge convergence for 
        valueservice :=  ifexpr( level = weightlevels.ServiceLevelLevel(), mp.GetKPIServiceLevel() * this.AdjustMinMax( minweightused, maxweightused, weightlevels.ServiceLevelWeight() ), 0.0  )
        msg := msg + 'KPIServiceLevel' + [String] valueservice + String::NewLine();
        valuespcap :=  ifexpr( level = weightlevels.StockingPointCapacityLevel(), -mp.GetKPIStockingPointCapacity() * this.AdjustMinMax( minweightused, maxweightused, weightlevels.StockingPointCapacityWeight() ), 0.0 ) 
        msg := msg + 'KPISPCapacity=' + [String] valuespcap + String::NewLine();
        valuetinvlevel :=  ifexpr( level = weightlevels.TargetInventoryLevel(), -eis.KPITargetInventory() * this.AdjustMinMax( minweightused, maxweightused, weightlevels.TargetInventoryLevelWeight() ), 0.0 ) 
        msg := msg + 'KPITargetInvLevel=' + [String] valuetinvlevel + String::NewLine();
        valueunitcap :=  ifexpr( level = weightlevels.UnitCapacityLevel(), -mp.GetKPIUnitCapacity() * this.AdjustMinMax( minweightused, maxweightused, weightlevels.UnitCapacityWeight() ), 0.0 )
        msg := msg + 'KPIUnitCap=' + [String] valueunitcap + String::NewLine();
        valuebalance := ifexpr ( level = weightlevels.SlackLevel(), -eis.KPIBalanceViolation() * this.AdjustMinMax( minweightused, maxweightused, weightlevels.SlackWeight() ), 0.0 ); // hidden balance KPI in level 1
        msg := msg + 'KPIBalanceViolation=' + [String] valuebalance + String::NewLine(); 
        valuecampaigncombislack := ifexpr( level = weightlevels.SlackLevel(), -RollbackKPIMeta::GetCampaignCombiSlackScore( mp, dummy1, dummy2, weightlevels.RunContextForCapacityPlanning().UseCampaignSequenceOptimizer() ), 0.0 ); 
        msg := msg + 'CampaignCombiSlack=' + [String] valuecampaigncombislack + String::NewLine(); 
        valueshiftmindurqationslack := ifexpr( level = weightlevels.SlackLevel(), -RollbackKPIMeta::GetShiftOptimizerMinDurationSlackScore( mp, subopt ), 0.0 ); 
        msg := msg + 'ShiftOptimizerMinDurationSlack=' + [String] valueshiftmindurqationslack + String::NewLine(); 
        valueblending := ifexpr(  level = weightlevels.BlendingLevel(), -mp.GetKPIBlending( this.AccuracyBlendingKPI() ) * this.AdjustMinMax( minweightused, maxweightused, weightlevels.BlendingWeight() ), 0.0 ); 
        msg := msg + 'KPIblending=' + [String] valueblending + String::NewLine(); 
        valuetotalexpired := ifexpr(  level = weightlevels.ExpiredQtyLevel(), -mp.GetKPITotalExpiredQuantity() * this.AdjustMinMax( minweightused, maxweightused, weightlevels.ExpiredQtyWeight() ), 0.0 ); 
        msg := msg + 'KPITotalExpiredQuantity=' + [String] valuetotalexpired + String::NewLine(); 
        valueco2emission := ifexpr( level = weightlevels.CO2EmissionLevel(), -mp.GetKPICO2Emission() * this.AdjustMinMax( minweightused, maxweightused, weightlevels.CO2EmissionWeight() ), 0.0 );
        msg := msg + 'KPICO2Emission=' + [String] valueco2emission + String::NewLine();
        
        value := valuecampaign 
                 + valuefulfillment 
                 + valueinventorymix 
                 + valuelotsize 
                 + valuemaxinventory 
                 + valuemininventory 
                 + valuesupplytarget 
                 + valueminsupply 
                 + valuemaxsupply 
                 + valueminunitcap 
                 + valuepostpone 
                 + valueprocessmaxqty 
                 + valueprocessminqty 
                 + valuesalesdemandprio 
                 + valuefftarget 
                 + valueservice 
                 + valuespcap 
                 + valuetinvlevel 
                 + valueunitcap 
                 + valuebalance 
                 + valuecampaigncombislack
                 + valueshiftmindurqationslack
                 + valueblending 
                 + valuetotalexpired
                 + valueco2emission; 
        
        msg_o := msg;          
      }
    }
    value := ifexpr( this.RoundPuzzleScoreDecimal() >= 0, value.Round( this.RoundPuzzleScoreDecimal() ), value ); // negative means no round
    
    return value;
  *]
  InterfaceProperties { Accessibility: 'Module' }
}