13 ReadOnlySpan<int> predecessor,
15 CancellationToken cancellationToken)
17 ArgumentNullException.ThrowIfNull(problem);
20 if (predecessor.Length != horizon + 1)
22 throw new ArgumentException(
23 $
"Predecessor vector must contain {horizon + 1} entries.",
27 var production =
new double[horizon];
28 var inventory =
new double[horizon];
29 var setup =
new bool[horizon];
36 cancellationToken.ThrowIfCancellationRequested();
38 var start = predecessor[end];
39 if (start < 0 || start >= end)
41 throw new InvalidOperationException(
42 "The shortest-path predecessor chain is inconsistent.");
46 for (var period = start; period < end; period++)
48 quantity = AddFinite(quantity, demands[period],
"reconstructed production quantity");
53 production[start] = quantity;
60 var runningInventory = 0.0;
62 var productionCost = 0.0;
63 var holdingCost = 0.0;
69 for (var period = 0; period < horizon; period++)
71 cancellationToken.ThrowIfCancellationRequested();
75 setupCost = AddFinite(
78 "solution setup cost");
81 productionCost = AddFinite(
84 productionCosts[period],
86 "solution production cost"),
87 "solution production cost");
89 runningInventory = AddFinite(
94 runningInventory -= demands[period];
96 var tolerance = 1e-10 * Math.Max(
98 Math.Max(Math.Abs(runningInventory), Math.Abs(demands[period])));
100 if (runningInventory < -tolerance)
102 throw new InvalidOperationException(
103 $
"Reconstructed solution has negative inventory at period {period}.");
106 if (runningInventory < 0.0)
108 runningInventory = 0.0;
111 inventory[period] = runningInventory;
113 holdingCost = AddFinite(
116 holdingCosts[period],
118 "solution holding cost"),
119 "solution holding cost");