90 ArgumentNullException.ThrowIfNull(problem);
97 var setupCost = setupCosts[0];
98 var productionCost = productionCosts[0];
100 for (var period = 1; period < horizon; period++)
102 if (setupCosts[period] != setupCost ||
103 productionCosts[period] != productionCost)
113 var holdingCost = holdingCosts[0];
115 for (var period = 1; period < horizon - 1; period++)
117 if (holdingCosts[period] != holdingCost)
161 CancellationToken cancellationToken =
default)
163 ArgumentNullException.ThrowIfNull(problem);
164 cancellationToken.ThrowIfCancellationRequested();
168 throw new NotSupportedException(
169 "HeadyZhuEconomicPartPeriodSolver requires constant setup " +
170 "costs, constant unit production costs and constant relevant " +
177 ArrayPool<double>.Shared.Rent(horizon + 1);
179 var predecessorBuffer =
180 ArrayPool<int>.Shared.Rent(horizon + 1);
185 valueBuffer.AsSpan(0, horizon + 1);
188 predecessorBuffer.AsSpan(0, horizon + 1);
190 value.Fill(
double.PositiveInfinity);
191 predecessor.Fill(-1);
204 var planningHorizonStart = 0;
206 for (var end = 0; end < horizon; end++)
208 if ((end & CancellationCheckMask) == 0)
210 cancellationToken.ThrowIfCancellationRequested();
213 if (demands[end] == 0.0)
218 value[end + 1] = value[end];
219 predecessor[end + 1] = end;
223 var best =
double.PositiveInfinity;
228 var segmentDemand = 0.0;
231 var intervalHoldingCost = 0.0;
233 for (var start = end;
234 start >= planningHorizonStart;
237 if (((end - start) & CancellationCheckMask) == 0)
239 cancellationToken.ThrowIfCancellationRequested();
247 var incrementalHoldingCost = MultiplyFinite(
250 "economic part-period incremental holding cost");
258 if (incrementalHoldingCost > setupCost)
263 intervalHoldingCost = AddFinite(
265 incrementalHoldingCost,
266 "candidate interval holding cost");
269 segmentDemand = AddFinite(
272 "candidate interval demand");
274 var variableProductionCost = MultiplyFinite(
277 "candidate production cost");
279 var candidate = AddFinite(
282 "forward dynamic-programming candidate");
284 candidate = AddFinite(
286 variableProductionCost,
287 "forward dynamic-programming candidate");
289 candidate = AddFinite(
292 "forward dynamic-programming candidate");
297 if (candidate < best)
304 if (!
double.IsFinite(best) ||
305 bestStart < planningHorizonStart ||
308 throw new ArithmeticException(
309 $
"No finite Heady-Zhu value was obtained for period {end}.");
312 value[end + 1] = best;
313 predecessor[end + 1] = bestStart;
316 planningHorizonStart = bestStart;
319 cancellationToken.ThrowIfCancellationRequested();
329 ArrayPool<double>.Shared.Return(
333 ArrayPool<int>.Shared.Return(