ULSAlgorithms 1.1.0-g3e5595996d
High-performance exact and heuristic algorithms for uncapacitated lot sizing
Loading...
Searching...
No Matches
UlsSolutionValidator.cs
Go to the documentation of this file.
3
5
6/// <summary>
7/// Independently verifies a ULS production plan against the original
8/// <see cref="UlsProblem"/>.
9/// </summary>
10public static class UlsSolutionValidator
11{
12 /// <summary>
13 /// Validates inventory balance, nonnegativity, setup linking, final
14 /// inventory and all objective components.
15 /// </summary>
17 UlsProblem problem,
18 UlsSolution solution,
19 double tolerance = 1.0e-7)
20 {
21 ArgumentNullException.ThrowIfNull(problem);
22 ArgumentNullException.ThrowIfNull(solution);
23
24 if (!double.IsFinite(tolerance) ||
25 tolerance <= 0.0)
26 {
27 throw new ArgumentOutOfRangeException(
28 nameof(tolerance));
29 }
30
31 if (solution.Horizon != problem.Horizon)
32 {
34 false,
35 double.PositiveInfinity,
36 double.PositiveInfinity,
37 0,
38 double.NaN,
39 double.NaN,
40 double.NaN,
41 double.PositiveInfinity,
42 [
43 $"Solution horizon {solution.Horizon} differs from " +
44 $"problem horizon {problem.Horizon}."
45 ]);
46 }
47
48 ReadOnlySpan<double> production =
49 solution.ProductionQuantities;
50
51 ReadOnlySpan<double> inventory =
52 solution.EndingInventories;
53
54 ReadOnlySpan<bool> setup =
55 solution.SetupDecisions;
56
57 double maximumBalanceResidual = 0.0;
58 double maximumScaledBalanceResidual = 0.0;
59 int setupLinkViolations = 0;
60
61 double previousInventory = 0.0;
62
63 double setupCost = 0.0;
64 double productionCost = 0.0;
65 double holdingCost = 0.0;
66
67 var diagnostics =
68 new List<string>();
69
70 for (int period = 0;
71 period < problem.Horizon;
72 period++)
73 {
74 double balanceResidual =
75 previousInventory +
76 production[period] -
77 problem.Demands[period] -
78 inventory[period];
79
80 double absoluteBalanceResidual =
81 Math.Abs(
82 balanceResidual);
83
84 maximumBalanceResidual =
85 Math.Max(
86 maximumBalanceResidual,
87 absoluteBalanceResidual);
88
89 double scale =
90 Math.Max(
91 1.0,
92 Math.Max(
93 Math.Abs(previousInventory),
94 Math.Max(
95 Math.Abs(production[period]),
96 Math.Max(
97 Math.Abs(problem.Demands[period]),
98 Math.Abs(inventory[period])))));
99
100 maximumScaledBalanceResidual =
101 Math.Max(
102 maximumScaledBalanceResidual,
103 absoluteBalanceResidual / scale);
104
105 if (production[period] >
106 tolerance *
107 Math.Max(
108 1.0,
109 Math.Abs(production[period])) &&
110 !setup[period])
111 {
112 setupLinkViolations++;
113 }
114
115 if (setup[period])
116 {
117 setupCost +=
118 problem.SetupCosts[period];
119 }
120
121 productionCost +=
122 production[period] *
123 problem.UnitProductionCosts[period];
124
125 holdingCost +=
126 inventory[period] *
127 problem.HoldingCosts[period];
128
129 previousInventory =
130 inventory[period];
131 }
132
133 double finalInventoryResidual =
134 Math.Abs(
135 inventory[^1]);
136
137 double inventoryTolerance =
138 tolerance *
139 Math.Max(
140 1.0,
141 problem.TotalDemand);
142
143 double setupDifference =
144 Math.Abs(
145 solution.SetupCost -
146 setupCost);
147
148 double productionDifference =
149 Math.Abs(
150 solution.ProductionCost -
151 productionCost);
152
153 double holdingDifference =
154 Math.Abs(
155 solution.HoldingCost -
156 holdingCost);
157
158 double totalDifference =
159 Math.Abs(
160 solution.TotalCost -
161 (setupCost +
162 productionCost +
163 holdingCost));
164
165 double maximumCostDifference =
166 Math.Max(
167 Math.Max(
168 setupDifference,
169 productionDifference),
170 Math.Max(
171 holdingDifference,
172 totalDifference));
173
174 double costScale =
175 Math.Max(
176 1.0,
177 Math.Max(
178 Math.Abs(solution.TotalCost),
179 Math.Abs(
180 setupCost +
181 productionCost +
182 holdingCost)));
183
184 bool feasible =
185 maximumScaledBalanceResidual <= tolerance &&
186 finalInventoryResidual <= inventoryTolerance &&
187 setupLinkViolations == 0 &&
188 maximumCostDifference <=
189 tolerance * costScale;
190
191 if (maximumScaledBalanceResidual > tolerance)
192 {
193 diagnostics.Add(
194 $"Maximum scaled inventory-balance residual is " +
195 $"{maximumScaledBalanceResidual:R}.");
196 }
197
198 if (finalInventoryResidual > inventoryTolerance)
199 {
200 diagnostics.Add(
201 $"Final inventory residual is " +
202 $"{finalInventoryResidual:R}.");
203 }
204
205 if (setupLinkViolations > 0)
206 {
207 diagnostics.Add(
208 $"{setupLinkViolations} period(s) contain positive " +
209 "production without an active setup.");
210 }
211
212 if (maximumCostDifference >
213 tolerance * costScale)
214 {
215 diagnostics.Add(
216 $"Maximum objective-component discrepancy is " +
217 $"{maximumCostDifference:R}.");
218 }
219
221 feasible,
222 maximumBalanceResidual,
223 finalInventoryResidual,
224 setupLinkViolations,
225 setupCost,
226 productionCost,
227 holdingCost,
228 maximumCostDifference,
229 diagnostics);
230 }
231}
Represents a validated classical uncapacitated lot-sizing problem.
Definition UlsProblem.cs:23
double TotalDemand
Gets the total demand over the complete planning horizon.
Definition UlsProblem.cs:87
ReadOnlySpan< double > UnitProductionCosts
Gets unit production costs by period.
int Horizon
Gets the number of planning periods.
Definition UlsProblem.cs:82
ReadOnlySpan< double > HoldingCosts
Gets end-of-period unit holding costs by period.
ReadOnlySpan< double > Demands
Gets demand by period.
Definition UlsProblem.cs:92
ReadOnlySpan< double > SetupCosts
Gets fixed setup costs by period.
Definition UlsProblem.cs:97
Represents a feasible production plan for a ULS problem.
Definition UlsSolution.cs:7
double SetupCost
Gets the total fixed setup cost.
ReadOnlySpan< bool > SetupDecisions
Gets setup decisions by period.
double TotalCost
Gets the complete objective value.
ReadOnlySpan< double > EndingInventories
Gets end-of-period inventories by period.
int Horizon
Gets the number of periods represented by the solution.
ReadOnlySpan< double > ProductionQuantities
Gets production quantities by period.
double ProductionCost
Gets the total variable production cost.
double HoldingCost
Gets the total holding cost.
Independent ULS-domain validation report for one production plan.
Independently verifies a ULS production plan against the original UlsProblem.
static UlsSolutionValidationResult Validate(UlsProblem problem, UlsSolution solution, double tolerance=1.0e-7)
Validates inventory balance, nonnegativity, setup linking, final inventory and all objective componen...