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