19 double tolerance = 1.0e-7)
21 ArgumentNullException.ThrowIfNull(problem);
22 ArgumentNullException.ThrowIfNull(solution);
24 if (!
double.IsFinite(tolerance) ||
27 throw new ArgumentOutOfRangeException(
35 double.PositiveInfinity,
36 double.PositiveInfinity,
41 double.PositiveInfinity,
43 $
"Solution horizon {solution.Horizon} differs from " +
44 $
"problem horizon {problem.Horizon}."
48 ReadOnlySpan<double> production =
51 ReadOnlySpan<double> inventory =
54 ReadOnlySpan<bool> setup =
57 double maximumBalanceResidual = 0.0;
58 double maximumScaledBalanceResidual = 0.0;
59 int setupLinkViolations = 0;
61 double previousInventory = 0.0;
63 double setupCost = 0.0;
64 double productionCost = 0.0;
65 double holdingCost = 0.0;
74 double balanceResidual =
80 double absoluteBalanceResidual =
84 maximumBalanceResidual =
86 maximumBalanceResidual,
87 absoluteBalanceResidual);
93 Math.Abs(previousInventory),
95 Math.Abs(production[period]),
97 Math.Abs(problem.
Demands[period]),
98 Math.Abs(inventory[period])))));
100 maximumScaledBalanceResidual =
102 maximumScaledBalanceResidual,
103 absoluteBalanceResidual / scale);
105 if (production[period] >
109 Math.Abs(production[period])) &&
112 setupLinkViolations++;
133 double finalInventoryResidual =
137 double inventoryTolerance =
143 double setupDifference =
148 double productionDifference =
153 double holdingDifference =
158 double totalDifference =
165 double maximumCostDifference =
169 productionDifference),
185 maximumScaledBalanceResidual <= tolerance &&
186 finalInventoryResidual <= inventoryTolerance &&
187 setupLinkViolations == 0 &&
188 maximumCostDifference <=
189 tolerance * costScale;
191 if (maximumScaledBalanceResidual > tolerance)
194 $
"Maximum scaled inventory-balance residual is " +
195 $
"{maximumScaledBalanceResidual:R}.");
198 if (finalInventoryResidual > inventoryTolerance)
201 $
"Final inventory residual is " +
202 $
"{finalInventoryResidual:R}.");
205 if (setupLinkViolations > 0)
208 $
"{setupLinkViolations} period(s) contain positive " +
209 "production without an active setup.");
212 if (maximumCostDifference >
213 tolerance * costScale)
216 $
"Maximum objective-component discrepancy is " +
217 $
"{maximumCostDifference:R}.");
222 maximumBalanceResidual,
223 finalInventoryResidual,
228 maximumCostDifference,