1 | using System;
|
---|
2 | using System.Collections.Generic;
|
---|
3 | using HeuristicLab.Common;
|
---|
4 | using HeuristicLab.Core;
|
---|
5 | using HeuristicLab.Data;
|
---|
6 | using HeuristicLab.Parameters;
|
---|
7 | using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
|
---|
8 | using YamlDotNet.RepresentationModel;
|
---|
9 |
|
---|
10 | namespace HeuristicLab.BioBoost.Data {
|
---|
11 | [StorableClass]
|
---|
12 | [Item("Conversion", "Describes a conversion process including storage.")]
|
---|
13 | public class Conversion : DataItem {
|
---|
14 |
|
---|
15 | #region Parameters
|
---|
16 | public IValueParameter<StringValue> LabelParameter { get { return (IValueParameter<StringValue>)Parameters["Label"]; } }
|
---|
17 | public IValueParameter<StringValue> FeedstockParameter { get { return (IValueParameter<StringValue>)Parameters["Feedstock"]; } }
|
---|
18 | public IValueParameter<DoubleValue> CostParameter { get { return (IValueParameter<DoubleValue>)Parameters["Cost"]; } }
|
---|
19 | public IValueParameter<DoubleValue> DesignCapacityParameter { get { return (IValueParameter<DoubleValue>)Parameters["DesignCapacity"]; } }
|
---|
20 | public IValueParameter<DoubleValue> ConstructionParameter { get { return (IValueParameter<DoubleValue>)Parameters["Construction"]; } }
|
---|
21 | public IValueParameter<DoubleValue> MinConstructionParameter { get { return (IValueParameter<DoubleValue>)Parameters["MinConstruction"]; } }
|
---|
22 | public IValueParameter<DoubleValue> MaintenanceParameter { get { return (IValueParameter<DoubleValue>)Parameters["Maintenance"]; } }
|
---|
23 | public IValueParameter<DoubleValue> MinMaintenanceParameter { get { return (IValueParameter<DoubleValue>)Parameters["MinMaintenance"]; } }
|
---|
24 | public IValueParameter<DoubleValue> ConstructionScalingExponentParameter { get { return (IValueParameter<DoubleValue>)Parameters["ConstructionScalingExponent"]; } }
|
---|
25 | public IValueParameter<DoubleValue> MaintenanceScalingExponentParameter { get { return (IValueParameter<DoubleValue>)Parameters["MaintenanceScalingExponent"]; } }
|
---|
26 | public IValueParameter<DoubleValue> SafetyStockParameter { get { return (IValueParameter<DoubleValue>)Parameters["SafetyStock"]; } }
|
---|
27 | public IValueParameter<DoubleValue> DryMatterLossParameter { get { return (IValueParameter<DoubleValue>)Parameters["DryMatterLoss"]; } }
|
---|
28 | public IValueParameter<LogisticAction> StorageParameter { get { return (IValueParameter<LogisticAction>)Parameters["Storage"]; } }
|
---|
29 | public IValueParameter<DoubleValue> UtilizationFactorParameter { get { return (IValueParameter<DoubleValue>)Parameters["UtilizationFactor"]; } }
|
---|
30 | public IValueParameter<ValueParameterCollection> ProductsParameter { get { return (IValueParameter<ValueParameterCollection>)Parameters["Products"]; } }
|
---|
31 | public IValueParameter<ValueParameterCollection> ConstructionEmissionsParameter { get { return (IValueParameter<ValueParameterCollection>)Parameters["ConstructionEmissions"]; } }
|
---|
32 | public IValueParameter<ValueParameterCollection> AvailableCapacitiesParameter { get { return (IValueParameter<ValueParameterCollection>)Parameters["AvailableCapacities"]; } }
|
---|
33 | public IValueParameter<ValueParameterCollection> MaxCapacitiesParameter { get { return (IValueParameter<ValueParameterCollection>)Parameters["MaxCapacities"]; } }
|
---|
34 | public IValueParameter<DoubleValue> AvailableMaintenanceFactorParameter { get { return (IValueParameter<DoubleValue>)Parameters["AvailableMaintenanceFactor"]; } }
|
---|
35 | public IValueParameter<DoubleValue> MinCapacityParameter { get { return (IValueParameter<DoubleValue>) Parameters["MinCapacity"]; } }
|
---|
36 | public IValueParameter<StringValue> MainProductParameter { get { return (IValueParameter<StringValue>)Parameters["MainProduct"]; } }
|
---|
37 | public IValueParameter<DoubleValue> MainProductConversionRateParameter { get { return (IValueParameter<DoubleValue>)Parameters["MainProductConversionRate"]; } }
|
---|
38 | #endregion
|
---|
39 |
|
---|
40 | #region Parameter Values
|
---|
41 | public string Label { get { return LabelParameter.Value.Value; } }
|
---|
42 | public string Feedstock { get { return FeedstockParameter.Value.Value; } }
|
---|
43 | public string MainProduct { get { return MainProductParameter.Value.Value; } set { MainProductParameter.Value.Value = value; }
|
---|
44 | }
|
---|
45 |
|
---|
46 | public double Cost { get { return CostParameter.Value.Value; } set { CostParameter.Value.Value = value; } }
|
---|
47 |
|
---|
48 | public double DesignCapacity { get { return DesignCapacityParameter.Value.Value; } }
|
---|
49 | public double Construction { get { return ConstructionParameter.Value.Value; } }
|
---|
50 | public double MinConstruction { get { return MinConstructionParameter.Value.Value; } }
|
---|
51 | public double Maintenance { get { return MaintenanceParameter.Value.Value; } }
|
---|
52 | public double MinMaintenance { get { return MinMaintenanceParameter.Value.Value; } }
|
---|
53 | public double ConstructionScalingExponent { get { return ConstructionScalingExponentParameter.Value.Value; } }
|
---|
54 | public double MaintenanceScalingExponent { get { return MaintenanceScalingExponentParameter.Value.Value; } }
|
---|
55 | public double SafetyStock { get { return SafetyStockParameter.Value.Value; } }
|
---|
56 | public double DryMatterLoss { get { return DryMatterLossParameter.Value.Value; } }
|
---|
57 | public double UtilizationFactor { get { return UtilizationFactorParameter.Value.Value; } }
|
---|
58 | public LogisticAction Storage { get { return StorageParameter.Value; } }
|
---|
59 | public ValueParameterCollection Products { get { return ProductsParameter.Value; } }
|
---|
60 | public ValueParameterCollection ConstructionEmissions { get { return ConstructionEmissionsParameter.Value; } }
|
---|
61 | public ValueParameterCollection MaxCapacities { get { return MaxCapacitiesParameter.Value; } }
|
---|
62 | public ValueParameterCollection AvailableCapacities { get { return AvailableCapacitiesParameter.Value; } }
|
---|
63 | public double AvailableMaintenanceFactor { get { return AvailableMaintenanceFactorParameter.Value.Value; } }
|
---|
64 | public double MainProductConversionRate {
|
---|
65 | get { return MainProductConversionRateParameter.Value.Value; }
|
---|
66 | set { MainProductConversionRateParameter.Value = new DoubleValue(value); }
|
---|
67 | }
|
---|
68 |
|
---|
69 | public double MinCapacity {
|
---|
70 | get {
|
---|
71 | double minCapacity = MinCapacityParameter.Value.Value;
|
---|
72 | if (minCapacity == 0d)
|
---|
73 | minCapacity = MinCapacityParameter.Value.Value = GetInferredMinCapacity();
|
---|
74 | return minCapacity;
|
---|
75 | }
|
---|
76 | }
|
---|
77 |
|
---|
78 | private double GetInferredMinCapacity() {
|
---|
79 | if (MinConstructionParameter.Value != null && // reconstruct from MinConstruction
|
---|
80 | ConstructionParameter.Value != null &&
|
---|
81 | DesignCapacityParameter.Value != null &&
|
---|
82 | ConstructionScalingExponentParameter.Value != null)
|
---|
83 | return Math.Pow(MinConstruction / Construction, 1 / ConstructionScalingExponent) * DesignCapacity;
|
---|
84 | if (MinMaintenanceParameter.Value != null && // reconstruct from MinMaintenance
|
---|
85 | MaintenanceParameter.Value != null &&
|
---|
86 | MaintenanceScalingExponentParameter.Value != null &&
|
---|
87 | DesignCapacityParameter.Value != null)
|
---|
88 | return Math.Pow(MinMaintenance / Maintenance, 1 / MaintenanceScalingExponent) * DesignCapacity;
|
---|
89 | throw new IndexOutOfRangeException("MinCapacity is not available and could be reconstructed from other parameters.");
|
---|
90 | }
|
---|
91 |
|
---|
92 | #endregion
|
---|
93 |
|
---|
94 | #region Construction & Cloning
|
---|
95 | public Conversion() {
|
---|
96 | Parameters.Add(new ValueParameter<StringValue>("Label", "The label/name of this conversion."));
|
---|
97 | Parameters.Add(new ValueParameter<StringValue>("Feedstock", "The product used as feedstock (@target)."));
|
---|
98 | Parameters.Add(new ValueParameter<DoubleValue>("Cost", "The conversion cost [EUR/t]."));
|
---|
99 | Parameters.Add(new ValueParameter<DoubleValue>("Construction", "The amortized construction costs [EUR/a]"));
|
---|
100 | Parameters.Add(new ValueParameter<DoubleValue>("Maintenance", "The amortized operation and maintenance costs [EUR/a]"));
|
---|
101 | Parameters.Add(new ValueParameter<DoubleValue>("DesignCapacity", "The yearly turnover of feedstock [t/a]."));
|
---|
102 | Parameters.Add(new ValueParameter<DoubleValue>("MinConstruction", "The minimum construction costs [EUR/a]"));
|
---|
103 | Parameters.Add(new ValueParameter<DoubleValue>("MinMaintenance", "The minimum maintenance costs [EUR/a]"));
|
---|
104 | Parameters.Add(new ValueParameter<DoubleValue>("ConstructionScalingExponent", "The exponent used for up- and downsising construction costs.", new DoubleValue(0.86)));
|
---|
105 | Parameters.Add(new ValueParameter<DoubleValue>("MaintenanceScalingExponent", "The exponent used for up- and downscaling maintenance costs.", new DoubleValue(0.91)));
|
---|
106 | Parameters.Add(new ValueParameter<DoubleValue>("SafetyStock", "The number of days feedstock needs to be stored on average."));
|
---|
107 | Parameters.Add(new ValueParameter<DoubleValue>("DryMatterLoss", "The percentage of feedstock that is lost due to shrinkage.", new DoubleValue(0.0)));
|
---|
108 | Parameters.Add(new ValueParameter<DoubleValue>("UtilizationFactor", "Assumed utilization of a plant.", new DoubleValue(0.7)));
|
---|
109 | Parameters.Add(new ValueParameter<LogisticAction>("Storage", "Description of storage cost components [EUR/t/a]"));
|
---|
110 | Parameters.Add(new ValueParameter<ValueParameterCollection>("Products", "The list and amounts of products created by the conversion."));
|
---|
111 | Parameters.Add(new ValueParameter<ValueParameterCollection>("ConstructionEmissions", "The set of amortized emissions and amounts [t/a]"));
|
---|
112 | Parameters.Add(new ValueParameter<ValueParameterCollection>("AvailableCapacities", "Dictionary of regions with their free capacities of this conversion type."));
|
---|
113 | Parameters.Add(new ValueParameter<ValueParameterCollection>("MaxCapacities", "Dictionary of regions (or 'Default') with their maximum allows capapcity for this conversion type."));
|
---|
114 | Parameters.Add(new ValueParameter<DoubleValue>("AvailableMaintenanceFactor", "Scaling factor for maintenance costs when using free capacities."));
|
---|
115 | Parameters.Add(new ValueParameter<DoubleValue>("MinCapacity", "Minimum capacity to be reasonably build."));
|
---|
116 | Parameters.Add(new ValueParameter<StringValue>("MainProduct", "The main output product created during this conversion process."));
|
---|
117 | Parameters.Add(new ValueParameter<DoubleValue>("MainProductConversionRate", "The conversion rate of the main output product. (This value is automatically calculated)"));
|
---|
118 | RegisterEventHandlers();
|
---|
119 | }
|
---|
120 |
|
---|
121 | [StorableConstructor]
|
---|
122 | protected Conversion(bool isDeserializing) : base(isDeserializing) { }
|
---|
123 |
|
---|
124 | [StorableHook(HookType.AfterDeserialization)]
|
---|
125 | private void AfterDeserialization() {
|
---|
126 | if (!Parameters.ContainsKey("AvailableCapacities"))
|
---|
127 | Parameters.Add(new ValueParameter<ValueParameterCollection>("AvailableCapacities", "Dictionary of regions with their free capacities of this conversion type."));
|
---|
128 | if (!Parameters.ContainsKey("MaxCapacities"))
|
---|
129 | Parameters.Add(new ValueParameter<ValueParameterCollection>("MaxCapacities", "Dictionary of regions (or 'Default') with their maximum allows capapcity for this conversion type."));
|
---|
130 | if (!Parameters.ContainsKey("AvailableMaintenanceFactor"))
|
---|
131 | Parameters.Add(new ValueParameter<DoubleValue>("AvailableMaintenanceFactor", "Scaling factor for maintenance costs when using free capacities."));
|
---|
132 | if (!Parameters.ContainsKey("DryMatterLoss"))
|
---|
133 | Parameters.Add(new ValueParameter<DoubleValue>("DryMatterLoss", "The percentage of feedstock that is lost due to shrinkage.", new DoubleValue(0.0)));
|
---|
134 | if (!Parameters.ContainsKey("MinCapacity"))
|
---|
135 | Parameters.Add(new ValueParameter<DoubleValue>("MinCapacity", "Minimum capacity to be reasonably build.", new DoubleValue(GetInferredMinCapacity())));
|
---|
136 | if (!Parameters.ContainsKey("MainProduct"))
|
---|
137 | Parameters.Add(new ValueParameter<StringValue>("MainProduct", "The main output product created during this conversion process."));
|
---|
138 | if (!Parameters.ContainsKey("MainProductConversionRate"))
|
---|
139 | Parameters.Add(new ValueParameter<DoubleValue>("MainProductConversionRate", "The conversion rate of the main output product. (This value is automatically calculated)"));
|
---|
140 | RegisterEventHandlers();
|
---|
141 | }
|
---|
142 |
|
---|
143 | protected Conversion(Conversion orig, Cloner cloner)
|
---|
144 | : base(orig, cloner) {
|
---|
145 | RegisterEventHandlers();
|
---|
146 | }
|
---|
147 | public override IDeepCloneable Clone(Cloner cloner) {
|
---|
148 | return new Conversion(this, cloner);
|
---|
149 | }
|
---|
150 | #endregion
|
---|
151 |
|
---|
152 | protected override void Parse(YamlMappingNode node) {
|
---|
153 | base.Parse(node);
|
---|
154 | MaybeDetermineMainProductConversionRate();
|
---|
155 | }
|
---|
156 |
|
---|
157 | private void MaybeDetermineMainProductConversionRate() {
|
---|
158 | if (MainProductParameter.Value != null &&
|
---|
159 | (MainProductConversionRateParameter.Value == null || MainProductConversionRate == 0))
|
---|
160 | MainProductConversionRate = ((DoubleValue) Products[MainProduct].Value).Value;
|
---|
161 | }
|
---|
162 |
|
---|
163 | public override void CollectParameterValues(System.Collections.Generic.IDictionary<string, IItem> values) {
|
---|
164 | var tmpDict = new Dictionary<string, IItem>();
|
---|
165 | base.CollectParameterValues(tmpDict);
|
---|
166 | foreach (var entry in tmpDict) {
|
---|
167 | if (entry.Key == "Label") continue;
|
---|
168 | if (entry.Key == "Feedstock") continue;
|
---|
169 | values.Add("Conversion " + Label + "." + Feedstock + "." + entry.Key, entry.Value);
|
---|
170 | }
|
---|
171 | }
|
---|
172 |
|
---|
173 | private void RegisterEventHandlers() {
|
---|
174 | // when the HL value is changed
|
---|
175 | LabelParameter.ValueChanged += (sender, args) => {
|
---|
176 | UpdateName();
|
---|
177 | LabelParameter.Value.ValueChanged += (s, a) => { UpdateName(); };
|
---|
178 | };
|
---|
179 | // when the HL value's value is changed
|
---|
180 | LabelParameter.Value.ValueChanged += (sender, args) => { UpdateName(); };
|
---|
181 | }
|
---|
182 |
|
---|
183 | private void UpdateName() {
|
---|
184 | this.Name = ItemName + ": " + Label;
|
---|
185 | }
|
---|
186 |
|
---|
187 | public override bool IsEquivalentTo(DataItem other) {
|
---|
188 | var c = other as Conversion;
|
---|
189 | if (c == null) return false;
|
---|
190 | return c.Label == Label;
|
---|
191 | }
|
---|
192 |
|
---|
193 | public void MaybeInferMainProduct(Dictionary<string, double> prices) {
|
---|
194 | if (MainProductParameter.Value != null) { return; }
|
---|
195 | string mainProductName = null;
|
---|
196 | double mainProductRevenue = 0;
|
---|
197 | foreach (var product in Products) {
|
---|
198 | double price = 0;
|
---|
199 | if (prices.TryGetValue(product.Name, out price) && product.Value is ValueParameter<DoubleValue>) {
|
---|
200 | var doubleValue = (IValueParameter<DoubleValue>)product;
|
---|
201 | var revenue = price*doubleValue.Value.Value;
|
---|
202 | if (mainProductName == null && revenue > 0 || revenue > mainProductRevenue) {
|
---|
203 | mainProductName = product.Name;
|
---|
204 | mainProductRevenue = revenue;
|
---|
205 | }
|
---|
206 | }
|
---|
207 | }
|
---|
208 | if (mainProductName != null) {
|
---|
209 | MainProduct = MainProduct;
|
---|
210 | MaybeDetermineMainProductConversionRate();
|
---|
211 | }
|
---|
212 | }
|
---|
213 | }
|
---|
214 | }
|
---|