Free cookie consent management tool by TermsFeed Policy Generator

source: addons/HeuristicLab.Problems.BioBoost/HeuristicLab.Problems.BioBoost/3.3/Evaluators/ConcludingEvaluator.cs @ 17777

Last change on this file since 17777 was 16575, checked in by gkronber, 5 years ago

#2520: changed HeuristicLab.BioBoost addon to compile with new HL.Persistence

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