32 LotSizingSolution solution,
35 ArgumentNullException.ThrowIfNull(solution);
36 ArgumentNullException.ThrowIfNull(options);
47 AreVariableDomainsValid =
51 IsObjectiveConsistent =
57 CheckProductionDecisions(
62 CheckInventoryDecisions(
67 CheckTransportDecisions(
72 CheckPurchaseDecisions(
77 CheckDistributionDecisions(
82 CheckWorkCenterCapacityDecisions(
87 CheckWarehouseCapacityDecisions(
92 CheckTransportResourceCapacityDecisions(
97 catch (Exception exception)
107 "Variable-domain checking failed: " +
112 result.AreVariableDomainsValid =
121 private static void CheckProductionDecisions(
122 LotSizingSolution solution,
127 ProductionDecision decision
128 in solution.ProductionDecisions)
131 $
"production|routing={decision.RoutingId}";
133 CheckNonNegativeFiniteSeries(
146 CheckNonNegativeIntegerSeries(
147 decision.LotMultipleCounts,
154 private static void CheckInventoryDecisions(
155 LotSizingSolution solution,
160 InventoryDecision decision
161 in solution.InventoryDecisions)
164 $
"inventory|item={decision.ItemId}";
166 CheckNonNegativeFiniteSeries(
173 CheckNonNegativeFiniteSeries(
174 decision.SafetyStockViolations,
176 "safetyStockViolations",
186 CheckNonNegativeFiniteSeries(
187 decision.AdditionalCapacityUsed,
189 "additionalCapacityUsed",
195 private static void CheckTransportDecisions(
196 LotSizingSolution solution,
197 SolutionCheckOptions options,
198 SolutionCheckResult result)
201 TransportDecision decision
202 in solution.TransportDecisions)
205 $
"transport|item={decision.ItemId}" +
206 $
"|resource={decision.TransportResourceId}";
208 CheckNonNegativeFiniteSeries(
209 decision.TransportedQuantities,
211 "transportedQuantities",
221 CheckNonNegativeFiniteSeries(
222 decision.AdditionalCapacityUsed,
224 "additionalCapacityUsed",
230 private static void CheckPurchaseDecisions(
231 LotSizingSolution solution,
232 SolutionCheckOptions options,
233 SolutionCheckResult result)
236 PurchaseDecision decision
237 in solution.PurchaseDecisions)
240 $
"purchase|supplier={decision.SupplierId}" +
241 $
"|item={decision.ItemId}";
243 CheckNonNegativeFiniteSeries(
244 decision.PurchasedQuantities,
246 "purchasedQuantities",
252 private static void CheckDistributionDecisions(
253 LotSizingSolution solution,
254 SolutionCheckOptions options,
255 SolutionCheckResult result)
258 DistributionDecision decision
259 in solution.DistributionDecisions)
262 $
"distribution|center={decision.DistributionCenterId}" +
263 $
"|item={decision.ItemId}";
265 CheckNonNegativeFiniteSeries(
266 decision.DeliveredQuantities,
268 "deliveredQuantities",
272 CheckNonNegativeFiniteSeries(
273 decision.BacklogLevels,
279 CheckNonNegativeFiniteSeries(
280 decision.ShortageQuantities,
282 "shortageQuantities",
288 private static void CheckWorkCenterCapacityDecisions(
289 LotSizingSolution solution,
290 SolutionCheckOptions options,
291 SolutionCheckResult result)
294 WorkCenterCapacityDecision decision
295 in solution.WorkCenterCapacityDecisions)
298 $
"workCenterCapacity" +
299 $
"|plant={decision.WorkCenter.PlantId}" +
300 $
"|workCenter={decision.WorkCenter.WorkCenterId}";
303 decision.Activations,
308 CheckNonNegativeFiniteSeries(
309 decision.AdditionalCapacityUsed,
311 "additionalCapacityUsed",
317 private static void CheckWarehouseCapacityDecisions(
318 LotSizingSolution solution,
319 SolutionCheckOptions options,
320 SolutionCheckResult result)
323 WarehouseCapacityDecision decision
324 in solution.WarehouseCapacityDecisions)
330 decision.Activations,
335 CheckNonNegativeFiniteSeries(
336 decision.AdditionalCapacityUsed,
338 "additionalCapacityUsed",
344 private static void CheckTransportResourceCapacityDecisions(
345 LotSizingSolution solution,
346 SolutionCheckOptions options,
347 SolutionCheckResult result)
350 TransportResourceCapacityDecision decision
351 in solution.TransportResourceCapacityDecisions)
354 $
"transportResourceCapacity" +
355 $
"|resource={decision.TransportResourceId}";
358 decision.Activations,
363 CheckNonNegativeFiniteSeries(
364 decision.AdditionalCapacityUsed,
366 "additionalCapacityUsed",
372 private static void CheckNonNegativeFiniteSeries(
373 DoubleTimeSeries series,
376 SolutionCheckOptions options,
377 SolutionCheckResult result)
379 ArgumentNullException.ThrowIfNull(series);
382 period <= series.PeriodCount;
388 if (!
double.IsFinite(value))
395 "Value must be finite.",
408 "Value must be non-negative.",
414 private static void CheckBinarySeries(
415 IntegerTimeSeries series,
418 SolutionCheckResult result)
420 ArgumentNullException.ThrowIfNull(series);
423 period <= series.PeriodCount;
429 if (value is not 0 and not 1)
436 "Binary value must be 0 or 1.",
442 private static void CheckNonNegativeIntegerSeries(
443 IntegerTimeSeries series,
446 SolutionCheckResult result)
448 ArgumentNullException.ThrowIfNull(series);
451 period <= series.PeriodCount;
464 "Integer value must be non-negative.",
470 private static void AddDomainError(
476 SolutionCheckResult result)
479 new SolutionCheckIssue
488 $
"{domainKey}|period={period}",
494 $
"{seriesName}[{period}] = " +
495 $
"{actualValue:G17}. {explanation}"