[13069] | 1 | using System;
|
---|
| 2 | using System.Collections;
|
---|
| 3 | using System.Threading;
|
---|
| 4 | using GeoAPI.CoordinateSystems;
|
---|
| 5 | using HeuristicLab.BioBoost.ProblemDescription;
|
---|
| 6 | using HeuristicLab.Common;
|
---|
| 7 | using HeuristicLab.Core;
|
---|
| 8 | using HeuristicLab.Data;
|
---|
| 9 | using HeuristicLab.Operators;
|
---|
| 10 | using HeuristicLab.Optimization;
|
---|
| 11 | using HeuristicLab.Parameters;
|
---|
| 12 | using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
|
---|
| 13 | using System.Collections.Generic;
|
---|
| 14 | using System.Diagnostics;
|
---|
| 15 | using System.Globalization;
|
---|
| 16 | using System.Linq;
|
---|
| 17 | using System.Security.Permissions;
|
---|
| 18 | using HeuristicLab.Analysis;
|
---|
| 19 | using HeuristicLab.BioBoost.Data;
|
---|
| 20 | using HeuristicLab.BioBoost.Operators;
|
---|
| 21 | using HeuristicLab.BioBoost.Representation;
|
---|
| 22 | using HeuristicLab.BioBoost.Utils;
|
---|
| 23 | using HeuristicLab.Encodings.IntegerVectorEncoding;
|
---|
| 24 | using HeuristicLab.Encodings.RealVectorEncoding;
|
---|
| 25 | using HeuristicLab.PluginInfrastructure;
|
---|
| 26 |
|
---|
| 27 | namespace HeuristicLab.BioBoost.Evaluators {
|
---|
| 28 | [StorableClass]
|
---|
| 29 | public class MonolithicEvaluator : AggregateEvaluator {
|
---|
| 30 |
|
---|
| 31 | #region ISingleObjectiveEvaluator Members
|
---|
| 32 | public double Quality {
|
---|
| 33 | get { return QualityParameter.ActualValue.Value; }
|
---|
| 34 | set { QualityParameter.ActualValue = new DoubleValue(value);}
|
---|
| 35 | }
|
---|
| 36 | #endregion
|
---|
| 37 |
|
---|
| 38 | #region IMultiObjectEvaluator Members
|
---|
| 39 | private DoubleArray Qualities {
|
---|
| 40 | get { return QualitiesParameter.ActualValue; }
|
---|
| 41 | set { QualitiesParameter.ActualValue = value;} }
|
---|
| 42 |
|
---|
| 43 | #endregion
|
---|
| 44 |
|
---|
| 45 | public IValueParameter<IntArray> QualityRoundingParameter { get { return (IValueParameter<IntArray>) Parameters["QualityRounding"]; } }
|
---|
| 46 | public OptionalConstrainedValueParameter<IDiscreteDoubleValueModifier> AlphaValueModifierParameter { get { return (OptionalConstrainedValueParameter<IDiscreteDoubleValueModifier>) Parameters["AlphaValueModifier"]; } }
|
---|
| 47 | public IValueLookupParameter<DoubleValue> AlphaParameter { get { return (IValueLookupParameter<DoubleValue>) Parameters["Alpha"]; } }
|
---|
| 48 |
|
---|
| 49 | public IntArray QualityRounding { get { return QualityRoundingParameter.Value; } }
|
---|
| 50 | public IDiscreteDoubleValueModifier AlphaValueModifier { get { return AlphaValueModifierParameter.Value; } }
|
---|
| 51 | public double Alpha { get { return AlphaParameter.ActualValue.Value; } }
|
---|
| 52 |
|
---|
| 53 | private static object simplificationLock = new object();
|
---|
| 54 |
|
---|
| 55 | #region Construction & Cloning
|
---|
| 56 | [StorableConstructor]
|
---|
| 57 | protected MonolithicEvaluator(bool isDeserializing) : base(isDeserializing) { }
|
---|
| 58 | protected MonolithicEvaluator(MonolithicEvaluator orig, Cloner cloner) : base(orig, cloner) { }
|
---|
| 59 | public MonolithicEvaluator() {
|
---|
| 60 | Parameters.Add(new ValueParameter<IntArray>("QualityRounding", "The rounding cut-off for the quality (used e.g. for multi-object optimizaiton)."));
|
---|
| 61 | Parameters.Add(new ValueLookupParameter<DoubleValue>("Alpha", "The weight of the first quality parameter", new DoubleValue(0.5)));
|
---|
| 62 | Parameters.Add(new OptionalConstrainedValueParameter<IDiscreteDoubleValueModifier>("AlphaValueModifier", "An operator to modify the value of alpha over time",
|
---|
| 63 | new ItemSet<IDiscreteDoubleValueModifier>( ApplicationManager.Manager.GetInstances<IDiscreteDoubleValueModifier>())));
|
---|
| 64 | foreach (var modifier in AlphaValueModifierParameter.ValidValues) {
|
---|
| 65 | modifier.StartIndexParameter.Value = new IntValue(0);
|
---|
| 66 | modifier.EndIndexParameter.ActualName = "MaximumGenerations";
|
---|
| 67 | modifier.ValueParameter.ActualName = AlphaParameter.ActualName;
|
---|
| 68 | modifier.IndexParameter.ActualName = "Generations";
|
---|
| 69 | modifier.StartValueParameter.Value = new DoubleValue(1);
|
---|
| 70 | modifier.EndValueParameter.Value = new DoubleValue(0.8);
|
---|
| 71 | }
|
---|
| 72 | // disable AggregateEvaluator heritage
|
---|
| 73 | InitializeCostsAndIntermediateResults = false;
|
---|
| 74 | OperatorGraph.InitialOperator = null;
|
---|
| 75 | OperatorGraph.Operators.Clear();
|
---|
| 76 | }
|
---|
| 77 | public override IDeepCloneable Clone(Cloner cloner) {
|
---|
| 78 | return new MonolithicEvaluator(this, cloner);
|
---|
| 79 | }
|
---|
| 80 |
|
---|
| 81 | [StorableHook(HookType.AfterDeserialization)]
|
---|
| 82 | private void AfterDeserialization() {
|
---|
| 83 | if (!Parameters.ContainsKey("QualityRounding"))
|
---|
| 84 | Parameters.Add(new ValueParameter<IntArray>("QualityRounding", "The rounding cut-off for the quality (used e.g. for multi-object optimizaiton)."));
|
---|
| 85 | if (!Parameters.ContainsKey("Alpha"))
|
---|
| 86 | Parameters.Add(new ValueLookupParameter<DoubleValue>("Alpha", "The weight of the first quality parameter", new DoubleValue(0.5)));
|
---|
| 87 | if (!Parameters.ContainsKey("AlphaValueModifier")) {
|
---|
| 88 | Parameters.Add(new OptionalConstrainedValueParameter<IDiscreteDoubleValueModifier>("AlphaValueModifier",
|
---|
| 89 | "An operator to modify the value of alpha over time",
|
---|
| 90 | new ItemSet<IDiscreteDoubleValueModifier>(
|
---|
| 91 | ApplicationManager.Manager.GetInstances<IDiscreteDoubleValueModifier>())));
|
---|
| 92 | foreach (var modifier in AlphaValueModifierParameter.ValidValues) {
|
---|
| 93 | modifier.StartIndexParameter.Value = new IntValue(0);
|
---|
| 94 | modifier.EndIndexParameter.ActualName = "MaximumGenerations";
|
---|
| 95 | modifier.ValueParameter.ActualName = AlphaParameter.ActualName;
|
---|
| 96 | modifier.IndexParameter.ActualName = "Generations";
|
---|
| 97 | modifier.StartValueParameter.Value = new DoubleValue(1);
|
---|
| 98 | modifier.EndValueParameter.Value = new DoubleValue(0.8);
|
---|
| 99 | }
|
---|
| 100 | }
|
---|
| 101 | }
|
---|
| 102 | #endregion
|
---|
| 103 |
|
---|
| 104 | public override IOperation Apply() {
|
---|
| 105 | var data = LoadOrCreateSimpleDataInScope();
|
---|
| 106 | RealVector utilizations =
|
---|
| 107 | GetFromScope<RealVector>(LayerDescriptor.Utilizations.NameWithPrefix(data.Echelons[0].FeedstockName));
|
---|
| 108 | var temp = new Temp(data.N);
|
---|
| 109 | temp.Amounts = CalculateFeedstockCosts(data, utilizations, temp);
|
---|
| 110 | for (int i = 0; i < data.Echelons.Count - 1; i++) {
|
---|
| 111 | IntegerVector transportTargets =
|
---|
| 112 | GetFromScope<IntegerVector>(LayerDescriptor.TransportTargets.NameWithPrefix(data.Echelons[i].FeedstockName));
|
---|
| 113 | temp.Amounts = CalculateLogisticCosts(data, i, temp, transportTargets);
|
---|
| 114 | CalculateConversionCosts(data, i, temp);
|
---|
| 115 | }
|
---|
| 116 | var totalAmount = temp.Amounts.Sum();
|
---|
| 117 | var maxPossibleAmount = data.Potentials.Sum();
|
---|
| 118 | for (int i = 0; i < data.Echelons.Count - 1; i++)
|
---|
| 119 | maxPossibleAmount *= data.Echelons[i].Conversion.MainProductConversionRate;
|
---|
| 120 | //var nrOfPlants = temp.Amounts.Count(a => a > 0);
|
---|
| 121 | var revenue = totalAmount*data.FinalProudctPrice;
|
---|
| 122 | var roi = temp.TotalCost == 0 ? revenue : (revenue-temp.TotalCost)/temp.TotalCost;
|
---|
| 123 | Quality = Alpha*(roi - temp.TotalPenalty) + (1-Alpha)*totalAmount/maxPossibleAmount;
|
---|
| 124 | Qualities = new DoubleArray(new[] {Quality, totalAmount});
|
---|
| 125 | //Qualities = new DoubleArray(new[] {Quality, Math.Log(nrOfPlants)/Math.Log(2)});
|
---|
| 126 | if (QualityRoundingParameter.Value != null) {
|
---|
| 127 | if (QualityRounding.Length > 0) {
|
---|
| 128 | Quality = Math.Round(Quality, QualityRounding[0]);
|
---|
| 129 | if (QualityRounding.Length >= Qualities.Length) {
|
---|
| 130 | for (int i = 0; i < Qualities.Length; i++) {
|
---|
| 131 | int precision = QualityRounding[i];
|
---|
| 132 | if (precision >= 0) {
|
---|
| 133 | Qualities[i] = Math.Round(Qualities[i], QualityRounding[i]);
|
---|
| 134 | } else {
|
---|
| 135 | var multiplier = Math.Pow(10, Math.Abs(precision));
|
---|
| 136 | Qualities[i] = Math.Round(Qualities[i]/multiplier)*multiplier;
|
---|
| 137 | }
|
---|
| 138 | }
|
---|
| 139 | }
|
---|
| 140 | }
|
---|
| 141 | }
|
---|
| 142 | var ops = new OperationCollection();
|
---|
| 143 | if (AlphaValueModifierParameter.ActualValue != null)
|
---|
| 144 | ops.Add(ExecutionContext.CreateChildOperation(AlphaValueModifier));
|
---|
| 145 | ops.Add(base.Apply());
|
---|
| 146 | return ops;
|
---|
| 147 | }
|
---|
| 148 |
|
---|
| 149 | private SimpleProblemData LoadOrCreateSimpleDataInScope() {
|
---|
| 150 | var globalScope = ExecutionContext.Scope;
|
---|
| 151 | while (globalScope.Parent != null)
|
---|
| 152 | globalScope = globalScope.Parent;
|
---|
| 153 | SimpleProblemData data;
|
---|
| 154 | lock (simplificationLock) {
|
---|
| 155 | IVariable dataVariable;
|
---|
| 156 | if (!globalScope.Variables.TryGetValue("SimpleProblemData", out dataVariable) ||
|
---|
| 157 | !(dataVariable.Value is SimpleProblemData) ||
|
---|
| 158 | ((SimpleProblemData)dataVariable.Value).Echelons == null) {
|
---|
| 159 | data = new SimpleProblemData(ProblemData);
|
---|
| 160 | globalScope.Variables.Remove("SimpleProblemData");
|
---|
| 161 | globalScope.Variables.Add(new Variable("SimpleProblemData", data));
|
---|
| 162 | } else {
|
---|
| 163 | data = dataVariable.Value as SimpleProblemData;
|
---|
| 164 | }
|
---|
| 165 | }
|
---|
| 166 | return data;
|
---|
| 167 | }
|
---|
| 168 |
|
---|
| 169 | private double[] CalculateFeedstockCosts(SimpleProblemData data, RealVector utilizations, Temp temp) {
|
---|
| 170 | double cost = 0;
|
---|
| 171 | var amountsAtSource = new double[data.N];
|
---|
| 172 | for (int i = 0; i < data.N; i++) {
|
---|
| 173 | var amount = data.Potentials[i]*utilizations[i];
|
---|
| 174 | if (amount < 100) amount = 0; // TODO: make this configurable
|
---|
| 175 | amountsAtSource[i] = amount;
|
---|
| 176 | cost += FeedstockCostEvaluator.GetScaledCost(data.FeedstockBasePrices[i], data.FeedstockMaxPrices[i], amount, utilizations[i]);
|
---|
| 177 | }
|
---|
| 178 | temp.TotalCost += cost;
|
---|
| 179 | return amountsAtSource;
|
---|
| 180 | }
|
---|
| 181 |
|
---|
| 182 | private double[] CalculateLogisticCosts(SimpleProblemData data, int echelonNr, Temp temp, IntegerVector transportTargets) {
|
---|
| 183 | var echelon = data.Echelons[echelonNr];
|
---|
| 184 | var distanceMatrix = echelon.DistanceMatrix;
|
---|
| 185 | var logistic = echelon.Logistic;
|
---|
| 186 | double cost = 0;
|
---|
| 187 | double penalty = 0;
|
---|
| 188 | double[] amountsAtTarget = new double[data.N];
|
---|
| 189 | for (int i = 0; i < data.N; i++) {
|
---|
| 190 | if (temp.Amounts[i] <= 0) continue;
|
---|
| 191 | var amount = Brace(temp.Amounts[i], logistic.MinAmount, logistic.MaxAmount);
|
---|
| 192 | var target = transportTargets[i];
|
---|
| 193 | amountsAtTarget[target] += Math.Min(temp.Amounts[i], amount); // cannot have more than before
|
---|
| 194 | var distance = distanceMatrix[i, target];
|
---|
| 195 | if (distance > logistic.MaxDistance)
|
---|
| 196 | penalty += LogisticCostEvaluator.Penalty(distance, logistic.MaxDistance, distanceMatrix.Max);
|
---|
| 197 | cost += data.GetLogisticActionCost(logistic.Transport, amount*distance*(1-logistic.WaterContent), i, target);
|
---|
| 198 | cost += data.GetLogisticActionCost(logistic.Handling, amount*(1-logistic.WaterContent), i, target);
|
---|
| 199 | }
|
---|
| 200 | temp.TotalCost += cost;
|
---|
| 201 | temp.TotalPenalty += penalty;
|
---|
| 202 | return amountsAtTarget;
|
---|
| 203 | }
|
---|
| 204 |
|
---|
| 205 | private static double Brace(double value, double min, double max) { return Math.Min(max, Math.Max(min, value)); }
|
---|
| 206 |
|
---|
| 207 |
|
---|
| 208 | private void CalculateConversionCosts(SimpleProblemData data, int echelonNr, Temp temp) {
|
---|
| 209 | var echelon = data.Echelons[echelonNr];
|
---|
| 210 | var conversion = echelon.Conversion;
|
---|
| 211 | double cost = 0;
|
---|
| 212 | double penalty = 0;
|
---|
| 213 | for (int i = 0; i < data.N; i++) {
|
---|
| 214 | var amount = temp.Amounts[i];
|
---|
| 215 | if (amount <= 0) continue;
|
---|
| 216 | var maxCapacity = echelon.MaxConversionCapacities[i];
|
---|
| 217 | amount = amount * (1-conversion.DryMatterLoss);
|
---|
| 218 | var capacity = amount/conversion.UtilizationFactor;
|
---|
| 219 | // NOTE: available capacities are ignored (unused anyway)
|
---|
| 220 | var scale = capacity/conversion.DesignCapacity;
|
---|
| 221 | var minScale = conversion.MinCapacity/conversion.DesignCapacity;
|
---|
| 222 | var maxScale = maxCapacity/conversion.DesignCapacity;
|
---|
| 223 | penalty += ConversionCostEvaluator.ScalingPenalty(scale, minScale, maxScale);
|
---|
| 224 | penalty += ConversionCostEvaluator.CapacityPenalty(capacity, maxCapacity);
|
---|
| 225 | cost += ConversionCostEvaluator.ScaledCost(scale, maxScale, conversion.Construction, conversion.ConstructionScalingExponent);
|
---|
| 226 | cost += ConversionCostEvaluator.ScaledCost(scale, maxScale, conversion.Maintenance, conversion.MaintenanceScalingExponent);
|
---|
| 227 | cost += conversion.Cost*amount; // side product costs and revenues have been factored in before
|
---|
| 228 | var storageCapacity = capacity/365*conversion.SafetyStock;
|
---|
| 229 | cost += data.GetLogisticActionCost(conversion.Storage, storageCapacity, i);
|
---|
| 230 | temp.Amounts[i] = amount*conversion.MainProductConversionRate;
|
---|
| 231 | }
|
---|
| 232 | temp.TotalCost += cost;
|
---|
| 233 | temp.TotalPenalty += penalty;
|
---|
| 234 | }
|
---|
| 235 |
|
---|
| 236 | private T GetFromScope<T>(string variableName) where T: class{
|
---|
| 237 | var variables = ExecutionContext.Scope.Variables;
|
---|
| 238 | return variables[variableName].Value as T;
|
---|
| 239 | }
|
---|
| 240 | }
|
---|
| 241 |
|
---|
| 242 | public sealed class Temp {
|
---|
| 243 | public double[] Amounts;
|
---|
| 244 | public double TotalCost;
|
---|
| 245 | public double TotalPenalty;
|
---|
| 246 | public Temp(int n) { Amounts = new double[n]; }
|
---|
| 247 | }
|
---|
| 248 |
|
---|
| 249 | [StorableClass(StorableClassType.AllFieldsAndAllProperties)]
|
---|
| 250 | public sealed class SimpleProblemData : Item {
|
---|
| 251 |
|
---|
| 252 | [StorableConstructor]
|
---|
| 253 | private SimpleProblemData(bool isDeserializing) : base(isDeserializing) { }
|
---|
| 254 |
|
---|
| 255 | private SimpleProblemData(SimpleProblemData orig, Cloner cloner) : base(orig, cloner) {
|
---|
| 256 | FinalProudctPrice = orig.FinalProudctPrice;
|
---|
| 257 | N = orig.N;
|
---|
| 258 | Potentials = Util.Clone(orig.Potentials);
|
---|
| 259 | FeedstockBasePrices = Util.Clone(orig.FeedstockBasePrices);
|
---|
| 260 | FeedstockMaxPrices = Util.Clone(orig.FeedstockMaxPrices);
|
---|
| 261 | invest = Util.Clone(orig.invest);
|
---|
| 262 | fuel = Util.Clone(orig.fuel);
|
---|
| 263 | other = Util.Clone(orig.other);
|
---|
| 264 | Echelons = orig.Echelons.Select(cloner.Clone).ToList();
|
---|
| 265 | }
|
---|
| 266 |
|
---|
| 267 | public SimpleProblemData(BioBoostProblemData data) {
|
---|
| 268 | N = data.LocationNames.Length;
|
---|
| 269 | var feedstockName = data.Utilizations.CheckedItems.First().Value.Value;
|
---|
| 270 | Potentials = ((IValueParameter<DoubleArray>) data.FeedstockPotentials[LayerDescriptor.PotentialsFromProblemData.NameWithPrefix(feedstockName)]).Value.ToArray();
|
---|
| 271 | var feedstock = data.Products.First(p => p.Label == feedstockName);
|
---|
| 272 | FeedstockBasePrices = data.LocationNames.Select(loc => feedstock.GetRegionalBasePrice(loc)).ToArray();
|
---|
| 273 | FeedstockMaxPrices = data.LocationNames.Select(loc => feedstock.GetRegionalMaxPrice(loc)).ToArray();
|
---|
| 274 | invest = data.InvestmentCostFactors.ToArray();
|
---|
| 275 | maint = data.MaintenanceCostFactors.ToArray();
|
---|
| 276 | fuel = data.FuelCostFactors.ToArray();
|
---|
| 277 | labor = data.LaborCostFactors.ToArray();
|
---|
| 278 | other = data.OtherCostFactors.ToArray();
|
---|
| 279 | var transportedProducts = data.TransportTargets.CheckedItems.Select(i => i.Value.Value).ToArray();
|
---|
| 280 | var prices = data.Products.ToDictionary(p => p.Label, p => p.Price);
|
---|
| 281 | // different prices (@source/@target) are not considered (unused anyway)
|
---|
| 282 | Echelons = new List<Echelon>(3);
|
---|
| 283 | for (int i = 0; i < transportedProducts.Length; i++) {
|
---|
| 284 | var echelon = new Echelon();
|
---|
| 285 | var productName = echelon.FeedstockName = transportedProducts[i];
|
---|
| 286 | var logistic = echelon.Logistic = (Logistic) data.Logistics[productName].First().Clone(); // TODO: make better choice
|
---|
| 287 | logistic.Transport.Other += logistic.Transport.Emissions.TotalCost(prices, null);
|
---|
| 288 | logistic.Handling.Other += logistic.Handling.Emissions.TotalCost(prices, null);
|
---|
| 289 | echelon.DistanceMatrix = GetFromProblemData<DistanceMatrix>(data, logistic.Distances + "DistanceMatrix");
|
---|
| 290 | var conversion = echelon.Conversion = (Conversion) data.Conversions[productName].First().Clone(); // TODO: make better choice?
|
---|
| 291 | echelon.MaxConversionCapacities =
|
---|
| 292 | data.LocationNames.Select(loc => ConversionCostEvaluator.GetMaxCapacity(conversion, loc)).ToArray();
|
---|
| 293 | conversion.MaybeInferMainProduct(prices);
|
---|
| 294 | conversion.Cost += conversion.Products.TotalCost(prices, conversion.MainProduct);
|
---|
| 295 | Echelons.Add(echelon);
|
---|
| 296 | }
|
---|
| 297 | var finalEchelon = new Echelon();
|
---|
| 298 | var finalProductName = finalEchelon.FeedstockName = data.FinalProducts.CheckedItems.First().Value.Value;
|
---|
| 299 | Echelons.Add(finalEchelon);
|
---|
| 300 | FinalProudctPrice = prices[finalProductName];
|
---|
| 301 | }
|
---|
| 302 |
|
---|
| 303 | private static V GetValue<K,V>(IDictionary<K,V> d, K key, V defaultValue) {
|
---|
| 304 | V value;
|
---|
| 305 | if (d.TryGetValue(key, out value))
|
---|
| 306 | return value;
|
---|
| 307 | return defaultValue;
|
---|
| 308 | }
|
---|
| 309 |
|
---|
| 310 | private static double GetValue(ValueParameterCollection parameters, string name, double defaultValue) {
|
---|
| 311 | IValueParameter param = null;
|
---|
| 312 | if (!parameters.TryGetValue(name, out param)) return defaultValue;
|
---|
| 313 | var doubleValueParam = param as IValueLookupParameter<DoubleValue>;
|
---|
| 314 | if (doubleValueParam == null) return defaultValue;
|
---|
| 315 | return doubleValueParam.Value.Value;
|
---|
| 316 | }
|
---|
| 317 |
|
---|
| 318 | [StorableClass(StorableClassType.AllFieldsAndAllProperties)]
|
---|
| 319 | public sealed class Echelon : Item {
|
---|
| 320 |
|
---|
| 321 | public Logistic Logistic;
|
---|
| 322 | public DistanceMatrix DistanceMatrix;
|
---|
| 323 | public double[] MaxConversionCapacities;
|
---|
| 324 | public Conversion Conversion;
|
---|
| 325 | public string FeedstockName;
|
---|
| 326 |
|
---|
| 327 | [StorableConstructor]
|
---|
| 328 | private Echelon(bool isDeserializing) : base(isDeserializing) { }
|
---|
| 329 |
|
---|
| 330 | public Echelon() { }
|
---|
| 331 |
|
---|
| 332 | private Echelon(Echelon orig, Cloner cloner) {
|
---|
| 333 | Logistic = cloner.Clone(orig.Logistic);
|
---|
| 334 | DistanceMatrix = cloner.Clone(orig.DistanceMatrix);
|
---|
| 335 | MaxConversionCapacities = Util.Clone(orig.MaxConversionCapacities);
|
---|
| 336 | Conversion = cloner.Clone(orig.Conversion);
|
---|
| 337 | FeedstockName = Util.Clone(orig.FeedstockName);
|
---|
| 338 | }
|
---|
| 339 |
|
---|
| 340 | public override IDeepCloneable Clone(Cloner cloner) {
|
---|
| 341 | return new Echelon(this, cloner);
|
---|
| 342 | }
|
---|
| 343 | }
|
---|
| 344 |
|
---|
| 345 | public double FinalProudctPrice;
|
---|
| 346 | public int N;
|
---|
| 347 | public double[] Potentials;
|
---|
| 348 | public double[] FeedstockBasePrices;
|
---|
| 349 | public double[] FeedstockMaxPrices;
|
---|
| 350 | public double[] invest, maint, fuel, labor, other;
|
---|
| 351 | public List<Echelon> Echelons; // nr of echelons + 1 for final product
|
---|
| 352 |
|
---|
| 353 | public double GetLogisticActionCost(LogisticAction a, double amount, int i, int j) {
|
---|
| 354 | return
|
---|
| 355 | amount * (
|
---|
| 356 | a.Investment *(invest[i] + invest[j]) +
|
---|
| 357 | a.Maintenance *( maint[i] + maint[j]) +
|
---|
| 358 | a.Fuel *( fuel[i] + fuel[j]) +
|
---|
| 359 | a.Labor *( labor[i] + labor[j]) +
|
---|
| 360 | a.Other *( other[i] + other[j]))/2;
|
---|
| 361 | }
|
---|
| 362 |
|
---|
| 363 | public double GetLogisticActionCost(LogisticAction a, double amount, int i) {
|
---|
| 364 | return
|
---|
| 365 | amount * (
|
---|
| 366 | a.Investment * invest[i] +
|
---|
| 367 | a.Maintenance * maint[i] +
|
---|
| 368 | a.Fuel * fuel[i] +
|
---|
| 369 | a.Labor * labor[i] +
|
---|
| 370 | a.Other * other[i]);
|
---|
| 371 | }
|
---|
| 372 |
|
---|
| 373 | public override IDeepCloneable Clone(Cloner cloner) {
|
---|
| 374 | return new SimpleProblemData(this, cloner);
|
---|
| 375 | }
|
---|
| 376 |
|
---|
| 377 | public static T GetFromProblemData<T>(BioBoostProblemData data, string label) where T : class, IItem {
|
---|
| 378 | IParameter param;
|
---|
| 379 | data.Parameters.TryGetValue(label, out param);
|
---|
| 380 | var valueParam = param as IValueParameter;
|
---|
| 381 | if (valueParam != null) return valueParam.Value as T;
|
---|
| 382 | if (param != null) return param.ActualValue as T;
|
---|
| 383 | return null;
|
---|
| 384 | }
|
---|
| 385 |
|
---|
| 386 | }
|
---|
| 387 | }
|
---|