source: branches/HeuristicLab.Problems.BioBoost/HeuristicLab.Problems.BioBoost/3.3/Evaluators/ConcludingEvaluator.cs @ 13069

Last change on this file since 13069 was 13069, checked in by gkronber, 7 years ago

#2499: imported source code for HeuristicLab.BioBoost from private repository with some changes

File size: 18.7 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Diagnostics;
4using System.Text.RegularExpressions;
5using HeuristicLab.Common;
6using HeuristicLab.Core;
7using HeuristicLab.Data;
8using HeuristicLab.Parameters;
9using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
10using System.Linq;
11using HeuristicLab.BioBoost.Representation;
12using HeuristicLab.BioBoost.Utils;
13
14namespace HeuristicLab.BioBoost.Evaluators {
15  [StorableClass]
16  public class ConcludingEvaluator : BioBoostEvaluator {
17
18    #region Parameter
19    public LookupParameter<DoubleValue> TotalCostParameter {
20      get { return (LookupParameter<DoubleValue>) Parameters["TotalCost"]; }
21    }
22    public LookupParameter<BoolValue> RemoveIntermediateResultsParameter {
23      get { return (LookupParameter<BoolValue>) Parameters["RemoveIntermediateResults"]; }
24    }
25    public ILookupParameter<DoubleArray> QualityCriteriaParameter {
26      get { return (ILookupParameter<DoubleArray>) Parameters["QualityCriteria"]; }
27    }
28    #endregion
29
30    #region Parameter Values
31    public double TotalCost {
32      get { return TotalCostParameter.ActualValue.Value; }
33      set { TotalCostParameter.ActualValue = new DoubleValue(value); }
34    }
35    public bool RemoveIntermediateResults {
36      get { return RemoveIntermediateResultsParameter.ActualValue.Value; }
37      set { RemoveIntermediateResultsParameter.ActualValue = new BoolValue(value); }
38    }
39    public DoubleArray QualityCriteria {
40      get { return QualityCriteriaParameter.ActualValue; }
41      set { QualityCriteriaParameter.ActualValue = value; }
42    }
43    #endregion
44
45    #region Construction & Cloning
46    [StorableConstructor]
47    protected ConcludingEvaluator(bool isDeserializing) : base(isDeserializing) {}
48    public ConcludingEvaluator() {
49      Parameters.Add(new LookupParameter<BoolValue>("RemoveIntermediateResults", "Whether to remove intermediate results created during evaluation."));
50      Parameters.Add(new LookupParameter<DoubleValue>("TotalCost", "Overall cost of the whole scenario."));
51      Parameters.Add(new LookupParameter<DoubleArray>("QualityCriteria", "The list of qualities to consider."));
52    }
53    public ConcludingEvaluator(ConcludingEvaluator original, Cloner cloner) : base(original, cloner) { }
54    public override IDeepCloneable Clone(Cloner cloner) {
55      return new ConcludingEvaluator(this, cloner);
56    }
57    [StorableHook(HookType.AfterDeserialization)]
58    void AfterDeserialization() {
59      if (!Parameters.ContainsKey("QualityCriteria"))
60        Parameters.Add(new LookupParameter<DoubleArray>("QualityCriteria", "The list of qualities to consider."));
61    }
62    #endregion
63
64    private readonly Regex penaltyRegex = new Regex("[Pp]enalt(y|ies)$");
65
66    public override IOperation Apply() {
67      CreateAggregationLayers();
68      var expenses = 0d;
69      var revenues = 0d;
70      var penalties = 0d;
71      foreach (var cost in Costs) {
72        var value = cost.Value as DoubleValue;
73        if (value == null) continue;
74        if (penaltyRegex.IsMatch(cost.Name)) {
75          penalties += value.Value;
76        } else if (value.Value > 0) {
77          expenses += value.Value;
78        } else {
79          revenues -= value.Value;
80        }
81      }
82      var roi = Math.Abs(expenses) < 1 ? revenues : (revenues - expenses)/expenses;
83      TotalCost = roi - penalties;
84      var qualities = new List<double> {TotalCost};
85      if (RemoveIntermediateResults) {
86        foreach (var r in IntermediateResults) {
87          RemoveFromScope(r.Name);
88        }
89        RemoveFromScope(IntermediateResultsParameter.ActualName);
90        RemoveFromScope(CostsParameter.ActualName);
91      }
92      foreach (var p in ProblemData.Products) {
93        var amounts = GetFromScope<DoubleArray>(LayerDescriptor.AmountsAtSource.NameWithPrefix(p.Label));
94        if (amounts != null) {
95          qualities.Add(amounts.Sum());
96        }
97      }
98      QualityCriteria = new DoubleArray(qualities.ToArray());
99      return base.Apply();
100    }
101
102    private void CreateAggregationLayers() {
103      // for transport targets (straw, biosyncrude)
104      // aggregate sources (recursively)
105      // straw -> straw targets
106      // straw -> straw targets -> biosyncrude targets
107      // biosyncrude -> biosyncrude targets
108      var scope = ExecutionContext.Scope;
109
110      // straw sources, biosyncrude sources
111      var sources = scope.Variables
112        .Where(v => LayerDescriptor.Sources.IsSuffixOf(v.Name))
113        .Where(v => v.Value is ItemArray<ItemList<IntValue>>)
114        .ToDictionary(
115          v => LayerDescriptor.Sources.RemoveSuffixFrom(v.Name),
116          v => (ItemArray<ItemList<IntValue>>)v.Value);
117
118      // determine straw 1, biosyncrude 2 ???
119      // -> find utilizations
120      var feedstocks = scope.Variables
121        .Where(v => LayerDescriptor.Utilizations.IsSuffixOf(v.Name))
122        .Select(v => LayerDescriptor.Utilizations.RemoveSuffixFrom(v.Name))
123        .ToHashSet();
124      if (feedstocks.Count > 1) throw new InvalidOperationException("Currently only one feedstock is allowed.");
125      if (feedstocks.Count == 0) return;
126      var feedstock = feedstocks.First();
127      var carriers = sources.Keys.Where(k => k != feedstock);
128      if (carriers.Count() > 1) throw new InvalidOperationException("Currently only one carrier is allowed");
129      var carrier = carriers.Count() == 0 ? null : carriers.First();
130
131      var feedstockSources = sources[feedstock];
132      var carrierSources = carrier == null ? null : sources[carrier];
133      var finalProductName = GetFinalProductName(carrier ?? feedstock);
134      if (finalProductName == null) finalProductName = "TransportFuel";
135
136
137      if (carrier == null) {
138        AnalyzeSingleEchelon(feedstock, finalProductName, feedstockSources);
139      } else {
140        AnalyzeBinaryEchelon(feedstock, carrier, finalProductName, feedstockSources, carrierSources);
141      }
142    }
143
144    private void AnalyzeBinaryEchelon(string feedstock, string carrier, string finalProductName, ItemArray<ItemList<IntValue>> feedstockSources, ItemArray<ItemList<IntValue>> carrierSources) {
145      var length = feedstockSources.Length;
146
147      var feedstockCosts = GetFromScope<DoubleArray>(LayerDescriptor.TotalCostsAtSource.NameWithPrefix(feedstock));
148      //var feedstockAmounts = GetFromScope<DoubleArray>(LayerDescriptor.AmountsTransportedFromSource.NameWithPrefix(feedstock));
149      var feedstockLogisticCosts = GetFromScope<DoubleArray>(LayerDescriptor.TotalLogisticCosts.NameWithPrefix(feedstock));
150      var carrierLogisticCosts = GetFromScope<DoubleArray>(LayerDescriptor.TotalLogisticCosts.NameWithPrefix(carrier));
151      var decentralConversionCosts = GetFromScope<DoubleArray>(LayerDescriptor.TotalAmortizedConversionCosts.NameWithPrefix(feedstock));
152      var finalProductAmounts = GetFromScope<DoubleArray>(LayerDescriptor.AmountsAtSource.NameWithPrefix(finalProductName));
153      var carrierProductAmounts = GetFromScope<DoubleArray>(LayerDescriptor.AmountsTransportedFromSource.NameWithPrefix(carrier));
154      var finalProductCosts = GetFromScope<DoubleArray>(LayerDescriptor.TotalCostsAtSource.NameWithPrefix(finalProductName));
155      var carrierProductCosts = GetFromScope<DoubleArray>(LayerDescriptor.TotalCostsAtSource.NameWithPrefix(carrier));
156      var centralConversionCosts = GetFromScope<DoubleArray>(LayerDescriptor.TotalAmortizedConversionCosts.NameWithPrefix(carrier));
157      var finalProductPrice = ProblemData.Products.FirstOrDefault(p => p.Label == finalProductName).PriceAtSource;
158      var carrierProductPrice = ProblemData.Products.FirstOrDefault(p => p.Label == carrier).PriceAtSource;
159
160      var centralPlantsFeedstockCosts = new DoubleArray(length);
161      var centralPlantsFeedstockCostsRelative = new DoubleArray(length);
162      var centralPlantsDecentralLogisticCosts = new DoubleArray(length);
163      var centralPlantsDecentralLogisticCostsRelative = new DoubleArray(length);
164      var centralPlantsDecentralConversionCosts = new DoubleArray(length);
165      var centralPlantsDecentralConversionCostsRelative = new DoubleArray(length);
166      var centralPlantsCentralLogisticCosts = new DoubleArray(length);
167      var centralPlantsCentralLogisticCostsRelative = new DoubleArray(length);
168      // var plantsCentralConversionCosts = new DoubleArray(length);  already there
169      var centralPlantsCentralConversionCostsRelative = new DoubleArray(length);
170      var centralPlantsRoiFollowed = new DoubleArray(length);
171      var centralPlantsRoiAggregated = new DoubleArray(length);
172
173      var decentralPlantsFeedstockCosts = new DoubleArray(length);
174      var decentralPlantsFeedstockCostsRelative = new DoubleArray(length);
175      var decentralPlantsDecentralLogisticCosts = new DoubleArray(length);
176      var decentralPlantsDecentralLogisticCostsRelative = new DoubleArray(length);
177      //var decentralPlantsDecentralConversionCosts = new DoubleArray(length);
178      var decentralPlantsDecentralConversionCostsRelative = new DoubleArray(length);
179      var decentralPlantsRoiFollowed = new DoubleArray(length);
180      var decentralPlantsRoiAggregated = new DoubleArray(length);
181
182      for (int i = 0; i < carrierSources.Length; i++) {
183        if (carrierSources[i] != null) { // central plant
184          var plantsFeedstockSources = carrierSources[i]
185            .Select(j => feedstockSources[j.Value].Select(s => s.Value))
186            .Aggregate((e1, e2) => e1.Concat(e2))
187            .ToHashSet();
188          var plantsCarrierSources = carrierSources[i].Select(j => j.Value).ToHashSet();
189          var finalProductAmount = finalProductAmounts[i];
190
191          centralPlantsFeedstockCosts[i] = feedstockCosts.FuncOverIndices(plantsFeedstockSources, Sum);
192          centralPlantsFeedstockCostsRelative[i] = centralPlantsFeedstockCosts[i]/finalProductAmount;
193
194          centralPlantsDecentralLogisticCosts[i] = feedstockLogisticCosts.FuncOverIndices(plantsFeedstockSources, Sum);
195          centralPlantsDecentralLogisticCostsRelative[i] = centralPlantsDecentralLogisticCosts[i]/finalProductAmount;
196
197          centralPlantsDecentralConversionCosts[i] = decentralConversionCosts.FuncOverIndices(plantsCarrierSources, Sum);
198          centralPlantsDecentralConversionCostsRelative[i] = centralPlantsDecentralConversionCosts[i]/finalProductAmount;
199
200          centralPlantsCentralLogisticCosts[i] = carrierLogisticCosts.FuncOverIndices(plantsCarrierSources, Sum);
201          centralPlantsCentralLogisticCostsRelative[i] = centralPlantsCentralLogisticCosts[i]/finalProductAmount;
202
203          centralPlantsCentralConversionCostsRelative[i] = centralConversionCosts[i]/finalProductAmount;
204
205          var revenue = finalProductAmounts[i]*finalProductPrice;
206          var profit = revenue - finalProductCosts[i];
207          centralPlantsRoiFollowed[i] = finalProductCosts[i] == 0 ? profit : profit/finalProductCosts[i];
208
209          var totalCost = centralPlantsFeedstockCosts[i] + centralPlantsDecentralLogisticCosts[i] +
210                          centralPlantsDecentralConversionCosts[i] +
211                          centralPlantsCentralLogisticCosts[i] +
212                          centralConversionCosts[i];
213          centralPlantsRoiAggregated[i] = (revenue - totalCost)/totalCost;
214        }
215        if (feedstockSources[i] != null) { // decentral plant
216          var plantsFeedstockSources = feedstockSources[i].Select(j => j.Value).ToHashSet();
217          var carrierProductAmount = carrierProductAmounts[i];
218
219          decentralPlantsFeedstockCosts[i] = feedstockCosts.FuncOverIndices(plantsFeedstockSources, Sum);
220          decentralPlantsFeedstockCostsRelative[i] = decentralPlantsFeedstockCosts[i]/carrierProductAmount;
221
222          decentralPlantsDecentralLogisticCosts[i] = feedstockLogisticCosts.FuncOverIndices(plantsFeedstockSources, Sum);
223          decentralPlantsDecentralLogisticCostsRelative[i] = decentralPlantsDecentralLogisticCosts[i]/carrierProductAmount;
224
225          decentralPlantsDecentralConversionCostsRelative[i] = decentralConversionCosts[i]/carrierProductAmount;
226
227          var revenue = carrierProductAmounts[i]*carrierProductPrice;
228          var profit = revenue - carrierProductCosts[i];
229          decentralPlantsRoiFollowed[i] = carrierProductCosts[i] == 0 ? profit : profit/carrierProductCosts[i];
230
231          var totalCost = decentralPlantsFeedstockCosts[i] + decentralPlantsDecentralLogisticCosts[i] + decentralConversionCosts[i];
232          decentralPlantsRoiAggregated[i] = (revenue - totalCost)/totalCost;
233        }
234      }
235
236      PutInScope(LayerDescriptor.FeedstockCosts.NameWithPrefix(finalProductName), centralPlantsFeedstockCosts, false);
237      PutInScope(LayerDescriptor.FeedstockCostsRelative.NameWithPrefix(finalProductName), centralPlantsFeedstockCostsRelative, false);
238      PutInScope(LayerDescriptor.DecentralLogisticCosts.NameWithPrefix(finalProductName), centralPlantsDecentralLogisticCosts, false);
239      PutInScope(LayerDescriptor.DecentralLogisticCostsRelative.NameWithPrefix(finalProductName), centralPlantsDecentralLogisticCostsRelative, false);
240      PutInScope(LayerDescriptor.DecentralConversionCosts.NameWithPrefix(finalProductName), centralPlantsDecentralConversionCosts, false);
241      PutInScope(LayerDescriptor.DecentralConversionCostsRelative.NameWithPrefix(finalProductName), centralPlantsDecentralConversionCostsRelative, false);
242      PutInScope(LayerDescriptor.CentralLogisticCosts.NameWithPrefix(finalProductName), centralPlantsCentralLogisticCosts, false);
243      PutInScope(LayerDescriptor.CentralLogisticCostsRelative.NameWithPrefix(finalProductName), centralPlantsCentralLogisticCostsRelative, false);
244      PutInScope(LayerDescriptor.CentralConversionCostsRelative.NameWithPrefix(finalProductName), centralPlantsCentralConversionCostsRelative, false);
245      PutInScope(LayerDescriptor.RoiFollowed.NameWithPrefix(finalProductName), centralPlantsRoiFollowed, false);
246      PutInScope(LayerDescriptor.RoiAggregated.NameWithPrefix(finalProductName), centralPlantsRoiAggregated, false);
247
248      PutInScope(LayerDescriptor.FeedstockCosts.NameWithPrefix(carrier), decentralPlantsFeedstockCosts, false);
249      PutInScope(LayerDescriptor.FeedstockCostsRelative.NameWithPrefix(carrier), decentralPlantsFeedstockCostsRelative, false);
250      PutInScope(LayerDescriptor.DecentralLogisticCosts.NameWithPrefix(carrier), decentralPlantsDecentralLogisticCosts, false);
251      PutInScope(LayerDescriptor.DecentralLogisticCostsRelative.NameWithPrefix(carrier), decentralPlantsDecentralLogisticCostsRelative, false);
252      PutInScope(LayerDescriptor.DecentralConversionCostsRelative.NameWithPrefix(carrier), decentralPlantsDecentralConversionCostsRelative, false);
253      PutInScope(LayerDescriptor.RoiFollowed.NameWithPrefix(carrier), decentralPlantsRoiFollowed, false);
254      PutInScope(LayerDescriptor.RoiAggregated.NameWithPrefix(carrier), decentralPlantsRoiAggregated, false);
255    }
256
257    private void AnalyzeSingleEchelon(string feedstock, string finalProductName, ItemArray<ItemList<IntValue>> feedstockSources) {
258      var length = feedstockSources.Length;
259
260      var feedstockCosts = GetFromScope<DoubleArray>(LayerDescriptor.TotalCostsAtSource.NameWithPrefix(feedstock));
261      var feedstockLogisticCosts = GetFromScope<DoubleArray>(LayerDescriptor.TotalLogisticCosts.NameWithPrefix(feedstock));
262      var centralConversionCosts = GetFromScope<DoubleArray>(LayerDescriptor.TotalAmortizedConversionCosts.NameWithPrefix(feedstock));
263      var finalProductAmounts = GetFromScope<DoubleArray>(LayerDescriptor.AmountsAtSource.NameWithPrefix(finalProductName));
264      var finalProductCosts = GetFromScope<DoubleArray>(LayerDescriptor.TotalCostsAtSource.NameWithPrefix(finalProductName));
265      var finalProductPrice = ProblemData.Products.FirstOrDefault(p => p.Label == finalProductName).PriceAtSource;
266
267      var centralPlantsFeedstockCosts = new DoubleArray(length);
268      var centralPlantsFeedstockCostsRelative = new DoubleArray(length);
269      var centralPlantsCentralLogisticCosts = new DoubleArray(length);
270      var centralPlantsCentralLogisticCostsRelative = new DoubleArray(length);
271      var centralPlantsCentralConversionCostsRelative = new DoubleArray(length);
272      var centralPlantsRoiFollowed = new DoubleArray(length);
273      var centralPlantsRoiAggregated = new DoubleArray(length);
274
275      for (int i = 0; i < feedstockSources.Length; i++) {
276        if (feedstockSources[i] != null) {
277          var plantsFeedstockSources = feedstockSources[i].Select(j => j.Value).ToHashSet();
278          var finalProductAmount = finalProductAmounts[i];
279
280          centralPlantsFeedstockCosts[i] = feedstockCosts.FuncOverIndices(plantsFeedstockSources, Sum);
281          centralPlantsFeedstockCostsRelative[i] = centralPlantsFeedstockCosts[i]/finalProductAmount;
282
283          centralPlantsCentralLogisticCosts[i] = feedstockLogisticCosts.FuncOverIndices(plantsFeedstockSources, Sum);
284          centralPlantsCentralLogisticCostsRelative[i] = centralPlantsCentralLogisticCosts[i]/finalProductAmount;
285
286          centralPlantsCentralConversionCostsRelative[i] = centralConversionCosts[i]/finalProductAmount;
287
288          var revenue = finalProductAmounts[i]*finalProductPrice;
289          var profit = revenue - finalProductCosts[i];
290          centralPlantsRoiFollowed[i] = finalProductCosts[i] == 0 ? profit : profit/finalProductCosts[i];
291
292          var totalCost = centralPlantsFeedstockCosts[i] + centralPlantsCentralLogisticCosts[i] + centralConversionCosts[i];
293          centralPlantsRoiAggregated[i] = (revenue - totalCost)/totalCost;
294        }
295      }
296
297      PutInScope(LayerDescriptor.FeedstockCosts.NameWithPrefix(finalProductName), centralPlantsFeedstockCosts, false);
298      PutInScope(LayerDescriptor.FeedstockCostsRelative.NameWithPrefix(finalProductName), centralPlantsFeedstockCostsRelative, false);
299      PutInScope(LayerDescriptor.CentralLogisticCosts.NameWithPrefix(finalProductName), centralPlantsCentralLogisticCosts, false);
300      PutInScope(LayerDescriptor.CentralLogisticCostsRelative.NameWithPrefix(finalProductName), centralPlantsCentralLogisticCostsRelative, false);
301      PutInScope(LayerDescriptor.CentralConversionCostsRelative.NameWithPrefix(finalProductName), centralPlantsCentralConversionCostsRelative, false);
302      PutInScope(LayerDescriptor.RoiFollowed.NameWithPrefix(finalProductName), centralPlantsRoiFollowed, false);
303      PutInScope(LayerDescriptor.RoiAggregated.NameWithPrefix(finalProductName), centralPlantsRoiAggregated, false);
304
305    }
306
307    private static double Sum(IEnumerable<double> values) { return values.Sum(); }
308
309    private string GetFinalProductName(string feedstock) {
310      var productLinks = ProblemData.ProductLinks;
311      for (int i = 0; i < productLinks.Rows; i++) {
312        if (productLinks[i, 0] == feedstock)
313          return productLinks[i, 1];
314      }
315      return null;
316    }
317  }
318}
Note: See TracBrowser for help on using the repository browser.