61 CancellationToken cancellationToken =
default)
63 ArgumentNullException.ThrowIfNull(problem);
64 cancellationToken.ThrowIfCancellationRequested();
67 var valueBuffer = ArrayPool<double>.Shared.Rent(horizon + 1);
68 var predecessorBuffer = ArrayPool<int>.Shared.Rent(horizon + 1);
72 var value = valueBuffer.AsSpan(0, horizon + 1);
73 var predecessor = predecessorBuffer.AsSpan(0, horizon + 1);
83 var cumulativeDemand = 0.0;
84 var cumulativeHoldingBefore = 0.0;
85 var firstPeriodHoldingCost = 0.0;
87 using var candidates =
90 for (var period = 0; period < horizon; period++)
92 if ((period & CancellationCheckMask) == 0)
94 cancellationToken.ThrowIfCancellationRequested();
97 var previousCumulativeDemand = cumulativeDemand;
99 cumulativeDemand = AddFinite(
102 "cumulative demand");
104 firstPeriodHoldingCost = AddFinite(
105 firstPeriodHoldingCost,
108 cumulativeHoldingBefore,
109 "first-period-order holding-cost transform"),
110 "first-period-order holding-cost transform");
114 var transformedVariableCost =
115 productionCosts[period] -
116 cumulativeHoldingBefore;
119 transformedVariableCost,
120 "transformed variable production cost");
128 var intercept = value[period];
130 intercept = AddFinite(
133 "candidate intercept");
135 intercept = AddFinite(
137 -firstPeriodHoldingCost,
138 "candidate intercept");
140 intercept = AddFinite(
144 cumulativeHoldingBefore,
145 "candidate intercept"),
146 "candidate intercept");
148 intercept = AddFinite(
151 productionCosts[period],
152 previousCumulativeDemand,
153 "candidate intercept"),
154 "candidate intercept");
158 transformedVariableCost,
162 candidates.GetBestAndDiscardPast(
165 var bestLineValue = AddFinite(
166 candidates.GetIntercept(bestPeriod),
168 candidates.GetSlope(bestPeriod),
170 "candidate line evaluation"),
171 "candidate line evaluation");
173 var orderValue = AddFinite(
174 firstPeriodHoldingCost,
176 "forward dynamic-programming value");
182 if (demands[period] == 0.0 &&
183 value[period] <= orderValue)
185 value[period + 1] = value[period];
186 predecessor[period + 1] = period;
190 value[period + 1] = orderValue;
191 predecessor[period + 1] = bestPeriod;
194 cumulativeHoldingBefore = AddFinite(
195 cumulativeHoldingBefore,
196 holdingCosts[period],
197 "cumulative holding cost");
200 cancellationToken.ThrowIfCancellationRequested();
210 ArrayPool<double>.Shared.Return(
214 ArrayPool<int>.Shared.Return(