46 CancellationToken cancellationToken =
default)
48 ArgumentNullException.ThrowIfNull(problem);
49 cancellationToken.ThrowIfCancellationRequested();
53 var valueBuffer = ArrayPool<double>.Shared.Rent(horizon + 1);
54 var predecessorBuffer = ArrayPool<int>.Shared.Rent(horizon + 1);
55 var intervalCostBuffer = ArrayPool<double>.Shared.Rent(horizon);
56 var deliveredCostBuffer = ArrayPool<double>.Shared.Rent(horizon);
57 var cumulativeDemandBuffer = ArrayPool<double>.Shared.Rent(horizon);
61 var value = valueBuffer.AsSpan(0, horizon + 1);
62 var predecessor = predecessorBuffer.AsSpan(0, horizon + 1);
63 var intervalCost = intervalCostBuffer.AsSpan(0, horizon);
64 var deliveredCost = deliveredCostBuffer.AsSpan(0, horizon);
65 var cumulativeDemand = cumulativeDemandBuffer.AsSpan(0, horizon);
67 value.Fill(
double.PositiveInfinity);
70 deliveredCost.Clear();
71 cumulativeDemand.Clear();
80 for (var end = 0; end < horizon; end++)
82 cancellationToken.ThrowIfCancellationRequested();
84 deliveredCost[end] = productionCosts[end];
85 intervalCost[end] = 0.0;
86 cumulativeDemand[end] = 0.0;
88 var best =
double.PositiveInfinity;
91 for (var start = 0; start <= end; start++)
93 cumulativeDemand[start] += demands[end];
94 intervalCost[start] += demands[end] * deliveredCost[start];
96 if (!
double.IsFinite(intervalCost[start]))
98 throw new ArithmeticException(
99 "Numerical overflow while updating an Evans regeneration interval.");
102 var regenerationCost =
103 cumulativeDemand[start] > 0.0
104 ? setupCosts[start] + intervalCost[start]
107 var candidate = value[start] + regenerationCost;
109 if (candidate < best)
116 if (!
double.IsFinite(best) || bestStart < 0)
118 throw new ArithmeticException(
119 $
"No finite Evans dynamic-programming value was obtained for period {end}.");
122 value[end + 1] = best;
123 predecessor[end + 1] = bestStart;
125 if (end < horizon - 1)
127 for (var start = 0; start <= end; start++)
129 deliveredCost[start] += holdingCosts[end];
131 if (!
double.IsFinite(deliveredCost[start]))
133 throw new ArithmeticException(
134 "Numerical overflow while updating Evans delivered unit costs.");
148 ArrayPool<double>.Shared.Return(valueBuffer, clearArray:
false);
149 ArrayPool<int>.Shared.Return(predecessorBuffer, clearArray:
false);
150 ArrayPool<double>.Shared.Return(intervalCostBuffer, clearArray:
false);
151 ArrayPool<double>.Shared.Return(deliveredCostBuffer, clearArray:
false);
152 ArrayPool<double>.Shared.Return(cumulativeDemandBuffer, clearArray:
false);