55 ArgumentNullException.ThrowIfNull(problem);
62 var setupCost = setupCosts[0];
63 var productionCost = productionCosts[0];
65 for (var period = 1; period < horizon; period++)
67 if (setupCosts[period] != setupCost ||
68 productionCosts[period] != productionCost)
76 var holdingCost = holdingCosts[0];
78 for (var period = 1; period < horizon - 1; period++)
80 if (holdingCosts[period] != holdingCost)
117 CancellationToken cancellationToken =
default)
119 ArgumentNullException.ThrowIfNull(problem);
120 cancellationToken.ThrowIfCancellationRequested();
124 throw new NotSupportedException(
125 "SadjadiAryanezhadSadeghiSolver requires constant setup, " +
126 "unit production and relevant holding costs.");
130 var valueBuffer = ArrayPool<double>.Shared.Rent(horizon + 1);
131 var predecessorBuffer = ArrayPool<int>.Shared.Rent(horizon + 1);
135 var value = valueBuffer.AsSpan(0, horizon + 1);
136 var predecessor = predecessorBuffer.AsSpan(0, horizon + 1);
138 value.Fill(
double.PositiveInfinity);
139 predecessor.Fill(-1);
151 var planningHorizonStart = 0;
152 var cancellationCounter = 0;
154 for (var end = 0; end < horizon; end++)
156 if ((cancellationCounter++ & CancellationCheckMask) == 0)
158 cancellationToken.ThrowIfCancellationRequested();
161 if (demands[end] == 0.0)
163 value[end + 1] = value[end];
164 predecessor[end + 1] = end;
168 var best =
double.PositiveInfinity;
170 var futureDemand = 0.0;
171 var intervalHoldingCost = 0.0;
173 for (var start = end;
174 start >= planningHorizonStart;
177 if ((cancellationCounter++ & CancellationCheckMask) == 0)
179 cancellationToken.ThrowIfCancellationRequested();
184 var incrementalHoldingCost =
188 "DPP incremental holding cost");
192 if (incrementalHoldingCost > setupCost)
197 intervalHoldingCost = AddFinite(
199 incrementalHoldingCost,
200 "candidate holding cost");
203 futureDemand = AddFinite(
208 var candidate = AddFinite(
213 candidate = AddFinite(
218 "candidate production cost"),
221 candidate = AddFinite(
228 if (candidate < best)
235 if (!
double.IsFinite(best) ||
236 bestStart < planningHorizonStart)
238 throw new ArithmeticException(
239 $
"No finite Sadjadi value was obtained for period {end}.");
242 value[end + 1] = best;
243 predecessor[end + 1] = bestStart;
244 planningHorizonStart = bestStart;
255 ArrayPool<double>.Shared.Return(valueBuffer, clearArray:
false);
256 ArrayPool<int>.Shared.Return(predecessorBuffer, clearArray:
false);