14 ReadOnlySpan<int> cycleEnds,
16 CancellationToken cancellationToken)
18 ArgumentNullException.ThrowIfNull(problem);
22 if (cycleEnds.Length < horizon)
24 throw new ArgumentException(
25 "The cycle-end vector is shorter than the problem horizon.",
29 var production =
new double[horizon];
30 var inventory =
new double[horizon];
31 var setup =
new bool[horizon];
35 for (var start = 0; start < horizon; start++)
37 if ((start & 255) == 0)
39 cancellationToken.ThrowIfCancellationRequested();
42 var end = cycleEnds[start];
49 if (end < start || end >= horizon)
51 throw new InvalidOperationException(
52 $
"Invalid replenishment cycle [{start}, {end}].");
57 for (var period = start; period <= end; period++)
59 quantity += demands[period];
61 if (!
double.IsFinite(quantity))
63 throw new ArithmeticException(
64 "Numerical overflow while accumulating a heuristic lot.");
73 if (production[start] != 0.0)
75 throw new InvalidOperationException(
76 $
"More than one replenishment cycle starts in period {start}.");
79 production[start] = quantity;
84 var productionCost = 0.0;
85 var holdingCost = 0.0;
95 for (var period = 0; period < horizon; period++)
97 if ((period & 255) == 0)
99 cancellationToken.ThrowIfCancellationRequested();
102 stock += production[period] - demands[period];
104 if (stock < -tolerance)
106 throw new InvalidOperationException(
107 $
"The heuristic plan backlogs demand in period {period}.");
110 if (Math.Abs(stock) <= tolerance)
115 inventory[period] = stock;
119 setupCost = AddFinite(
122 "heuristic setup cost");
125 productionCost = AddFinite(
129 productionCosts[period],
130 "heuristic production cost"),
131 "heuristic production cost");
133 holdingCost = AddFinite(
137 holdingCosts[period],
138 "heuristic holding cost"),
139 "heuristic holding cost");
142 if (Math.Abs(stock) > tolerance)
144 throw new InvalidOperationException(
145 "The heuristic plan does not end with zero inventory.");
160 "Heuristic solution; no optimality proof is claimed.");