ULSAlgorithms 1.1.0-g3e5595996d
High-performance exact and heuristic algorithms for uncapacitated lot sizing
Loading...
Searching...
No Matches
UlsSolverCatalog.cs
Go to the documentation of this file.
1using System.Diagnostics.CodeAnalysis;
3
5
6/// <summary>
7/// Canonical runtime inventory of every public <see cref="IUlsSolver"/> strategy.
8/// </summary>
9/// <remarks>
10/// <para>
11/// This catalog is the source of truth for stable strategy identifiers,
12/// categories and public metadata. The repository documentation JSON is a
13/// generated projection of this runtime catalog and is validated by CI.
14/// </para>
15/// <para>
16/// The catalog stores default and, where supported, configured factories rather
17/// than singleton solver instances. Each construction call returns a fresh
18/// strategy instance.
19/// </para>
20/// </remarks>
21public static class UlsSolverCatalog
22{
23 private static readonly UlsSolverDescriptor[] Descriptors =
24 [
25 new(
26 "adaptive-exact",
27 "Adaptive exact selection",
28 UlsSolverCategory.DirectExact,
29 "Adaptive exact strategy selection",
30 "O(T) in the NSM case; O(T log T) in the general case",
31 "O(T)",
32 "All validated classical ULS instances; dispatches from the no-speculative-motive condition",
33 "Wagelmans, Van Hoesel & Kolen (1992), Economic Lot Sizing: An O(n log n) Algorithm That Runs in Linear Time in the Wagner-Whitin Case, Operations Research 40(S1), S145-S156; Federgruen & Tzur (1991), A Simple Forward Algorithm to Solve General Dynamic Lot Sizing Models with n Periods in O(n log n) or O(n) Time, Management Science 37(8), 909-925",
34 "10.1287/opre.40.1.S145",
35 "Selects the linear Wagner-Whitin specialization when applicable; otherwise uses a configurable O(T log T) general exact fallback",
36 "src/ULSAlgorithms/Selection/AdaptiveExactUlsSolver.cs",
37 typeof(global::ULSAlgorithms.Selection.AdaptiveExactUlsSolver),
38 static () => new global::ULSAlgorithms.Selection.AdaptiveExactUlsSolver(),
39 UlsSolverConfigurationCapabilities.AdaptiveGeneralFallback,
40 static options => new global::ULSAlgorithms.Selection.AdaptiveExactUlsSolver(
41 options.AdaptiveGeneralFallback ??
42 global::ULSAlgorithms.Selection.UlsGeneralExactFallback.WagelmansGeneral)),
43 new(
44 "wagner-whitin-classical",
45 "Wagner–Whitin classical",
46 UlsSolverCategory.DirectExact,
47 "Wagner–Whitin DP",
48 "O(T²)",
49 "O(T²)",
50 "Classical ULS / Wagner–Whitin model",
51 "Wagner & Whitin (1958), Dynamic Version of the Economic Lot Size Model, Management Science 5(1), 89-96",
52 "10.1287/mnsc.5.1.89",
53 "Classical dynamic program",
54 "src/ULSAlgorithms/Exact/WagnerWhitin/WagnerWhitinClassicalSolver.cs",
55 typeof(global::ULSAlgorithms.Exact.WagnerWhitin.WagnerWhitinClassicalSolver),
56 static () => new global::ULSAlgorithms.Exact.WagnerWhitin.WagnerWhitinClassicalSolver()),
57 new(
58 "wagner-whitin-evans",
59 "Wagner–Whitin / Evans",
60 UlsSolverCategory.DirectExact,
61 "Wagner–Whitin DP",
62 "O(T²)",
63 "O(T)",
64 "Classical ULS / Wagner–Whitin model",
65 "Evans (1985), An Efficient Implementation of the Wagner-Whitin Algorithm for Dynamic Lot-Sizing, Journal of Operations Management 5(2), 229-235",
66 "10.1016/0272-6963(85)90009-9",
67 "Low-storage forward DP",
68 "src/ULSAlgorithms/Exact/WagnerWhitin/WagnerWhitinEvansSolver.cs",
69 typeof(global::ULSAlgorithms.Exact.WagnerWhitin.WagnerWhitinEvansSolver),
70 static () => new global::ULSAlgorithms.Exact.WagnerWhitin.WagnerWhitinEvansSolver()),
71 new(
72 "wagner-whitin-linear",
73 "Wagner–Whitin linear",
74 UlsSolverCategory.DirectExact,
75 "Geometric DP",
76 "O(T)",
77 "O(T)",
78 "No speculative motive / Wagner–Whitin costs",
79 "Wagelmans, Van Hoesel & Kolen (1992), Economic Lot Sizing: An O(n log n) Algorithm That Runs in Linear Time in the Wagner-Whitin Case, Operations Research 40(S1), S145-S156",
80 "10.1287/opre.40.1.S145",
81 "Linear convex-hull specialization",
82 "src/ULSAlgorithms/Exact/WagnerWhitin/WagnerWhitinSolver.cs",
83 typeof(global::ULSAlgorithms.Exact.WagnerWhitin.WagnerWhitinSolver),
84 static () => new global::ULSAlgorithms.Exact.WagnerWhitin.WagnerWhitinSolver()),
85 new(
86 "wagelmans-general",
87 "Wagelmans general",
88 UlsSolverCategory.DirectExact,
89 "Geometric DP",
90 "O(T log T)",
91 "O(T)",
92 "General time-varying ULS costs",
93 "Wagelmans, Van Hoesel & Kolen (1992), Economic Lot Sizing: An O(n log n) Algorithm That Runs in Linear Time in the Wagner-Whitin Case, Operations Research 40(S1), S145-S156",
94 "10.1287/opre.40.1.S145",
95 "General geometric dynamic program",
96 "src/ULSAlgorithms/Exact/Wagelmans/WagelmansGeneralSolver.cs",
97 typeof(global::ULSAlgorithms.Exact.Wagelmans.WagelmansGeneralSolver),
98 static () => new global::ULSAlgorithms.Exact.Wagelmans.WagelmansGeneralSolver()),
99 new(
100 "federgruen-tzur-general",
101 "Federgruen–Tzur general",
102 UlsSolverCategory.DirectExact,
103 "Geometric DP",
104 "O(T log T)",
105 "O(T)",
106 "General time-varying ULS costs",
107 "Federgruen & Tzur (1991), A Simple Forward Algorithm to Solve General Dynamic Lot Sizing Models with n Periods in O(n log n) or O(n) Time, Management Science 37(8), 909-925",
108 "10.1287/mnsc.37.8.909",
109 "Forward tree-accelerated DP",
110 "src/ULSAlgorithms/Exact/FedergruenTzur/FedergruenTzurSolver.cs",
111 typeof(global::ULSAlgorithms.Exact.FedergruenTzur.FedergruenTzurSolver),
112 static () => new global::ULSAlgorithms.Exact.FedergruenTzur.FedergruenTzurSolver()),
113 new(
114 "federgruen-tzur-nsm",
115 "Federgruen–Tzur linear (NSM)",
116 UlsSolverCategory.DirectExact,
117 "Geometric DP",
118 "O(T)",
119 "O(T)",
120 "No speculative motive",
121 "Federgruen & Tzur (1991), A Simple Forward Algorithm to Solve General Dynamic Lot Sizing Models with n Periods in O(n log n) or O(n) Time, Management Science 37(8), 909-925",
122 "10.1287/mnsc.37.8.909",
123 "Linear specialization",
124 "src/ULSAlgorithms/Exact/FedergruenTzur/FedergruenTzurNoSpeculativeMotiveSolver.cs",
125 typeof(global::ULSAlgorithms.Exact.FedergruenTzur.FedergruenTzurNoSpeculativeMotiveSolver),
126 static () => new global::ULSAlgorithms.Exact.FedergruenTzur.FedergruenTzurNoSpeculativeMotiveSolver()),
127 new(
128 "federgruen-tzur-nondecreasing-setup",
129 "Federgruen–Tzur linear (setup)",
130 UlsSolverCategory.DirectExact,
131 "Geometric DP",
132 "O(T)",
133 "O(T)",
134 "Published restricted nondecreasing-setup case",
135 "Federgruen & Tzur (1991), A Simple Forward Algorithm to Solve General Dynamic Lot Sizing Models with n Periods in O(n log n) or O(n) Time, Management Science 37(8), 909-925",
136 "10.1287/mnsc.37.8.909",
137 "Linear restricted specialization",
138 "src/ULSAlgorithms/Exact/FedergruenTzur/FedergruenTzurNondecreasingSetupSolver.cs",
139 typeof(global::ULSAlgorithms.Exact.FedergruenTzur.FedergruenTzurNondecreasingSetupSolver),
140 static () => new global::ULSAlgorithms.Exact.FedergruenTzur.FedergruenTzurNondecreasingSetupSolver()),
141 new(
142 "aggarwal-park",
143 "Aggarwal–Park",
144 UlsSolverCategory.DirectExact,
145 "Monge / geometric DP",
146 "O(T log T)",
147 "O(T)",
148 "General ULS costs represented by the library",
149 "Aggarwal & Park (1993), Improved Algorithms for Economic Lot Size Problems, Operations Research 41(3), 549-571",
150 "10.1287/opre.41.3.549",
151 "CDQ + implicit Monge/SMAWK architecture",
152 "src/ULSAlgorithms/Exact/AggarwalPark/AggarwalParkSolver.cs",
153 typeof(global::ULSAlgorithms.Exact.AggarwalPark.AggarwalParkSolver),
154 static () => new global::ULSAlgorithms.Exact.AggarwalPark.AggarwalParkSolver()),
155 new(
156 "bahl-taj-planning-horizon",
157 "Bahl–Taj planning horizon",
158 UlsSolverCategory.DirectExact,
159 "Planning-horizon DP",
160 "O(T²) worst case",
161 "O(T)",
162 "No speculative motive",
163 "Bahl & Taj (1991), A data-dependent efficient implementation of the Wagner-Whitin algorithm for lot-sizing, Computers & Industrial Engineering 20(2), 289-291",
164 "10.1016/0360-8352(91)90033-3",
165 "Data-dependent planning-horizon pruning",
166 "src/ULSAlgorithms/Exact/WagnerWhitin/BahlTajPlanningHorizonSolver.cs",
167 typeof(global::ULSAlgorithms.Exact.WagnerWhitin.BahlTajPlanningHorizonSolver),
168 static () => new global::ULSAlgorithms.Exact.WagnerWhitin.BahlTajPlanningHorizonSolver()),
169 new(
170 "heady-zhu",
171 "Heady–Zhu",
172 UlsSolverCategory.DirectExact,
173 "Planning-horizon DP",
174 "O(T²) worst case",
175 "O(T)",
176 "Constant setup, production and relevant holding costs",
177 "Heady & Zhu (1994), An Improved Implementation of the Wagner-Whitin Algorithm, Production and Operations Management 3(1), 55-63",
178 "10.1111/j.1937-5956.1994.tb00109.x",
179 "Planning horizon + economic-part-period pruning",
180 "src/ULSAlgorithms/Exact/WagnerWhitin/HeadyZhuEconomicPartPeriodSolver.cs",
181 typeof(global::ULSAlgorithms.Exact.WagnerWhitin.HeadyZhuEconomicPartPeriodSolver),
182 static () => new global::ULSAlgorithms.Exact.WagnerWhitin.HeadyZhuEconomicPartPeriodSolver()),
183 new(
184 "chowdhury-baki-azab",
185 "Chowdhury–Baki–Azab",
186 UlsSolverCategory.DirectExact,
187 "Linear Wagner–Whitin",
188 "O(T)",
189 "O(T)",
190 "Strictly positive demand; stationary relevant holding; constant unit production cost",
191 "Chowdhury, Baki & Azab (2018), Dynamic Economic Lot-Sizing Problem: A new O(T) Algorithm for the Wagner-Whitin Model, Computers & Industrial Engineering 117, 6-18",
192 "10.1016/j.cie.2018.01.010",
193 "Published O(T) active-diagonal algorithm",
194 "src/ULSAlgorithms/Exact/ChowdhuryBakiAzab/ChowdhuryBakiAzabSolver.cs",
195 typeof(global::ULSAlgorithms.Exact.ChowdhuryBakiAzab.ChowdhuryBakiAzabSolver),
196 static () => new global::ULSAlgorithms.Exact.ChowdhuryBakiAzab.ChowdhuryBakiAzabSolver()),
197 new(
198 "sadjadi-aryanezhad-sadeghi",
199 "Sadjadi–Aryanezhad–Sadeghi",
200 UlsSolverCategory.DirectExact,
201 "Planning-horizon DP",
202 "O(T²) worst case",
203 "O(T)",
204 "Constant setup, production and relevant holding costs",
205 "Sadjadi, Aryanezhad & Sadeghi (2009), An Improved Wagner-Whitin Algorithm, International Journal of Industrial Engineering & Production Research 20, 117-123",
206 "",
207 "Incremental pruning + planning horizon",
208 "src/ULSAlgorithms/Exact/WagnerWhitin/SadjadiAryanezhadSadeghiSolver.cs",
209 typeof(global::ULSAlgorithms.Exact.WagnerWhitin.SadjadiAryanezhadSadeghiSolver),
210 static () => new global::ULSAlgorithms.Exact.WagnerWhitin.SadjadiAryanezhadSadeghiSolver()),
211 new(
212 "lyu-lee-parallel",
213 "Lyu–Lee parallel",
214 UlsSolverCategory.DirectExact,
215 "Parallel DP",
216 "O(T²) work; O(T²/p) ideal parallel candidate span",
217 "O(T)",
218 "General ULS costs",
219 "Lyu & Lee (2001), A Parallel Algorithm for the Dynamic Lot-Sizing Problem",
220 "10.1016/S0360-8352(01)00047-X",
221 "Modern shared-memory reconstruction",
222 "src/ULSAlgorithms/Exact/Parallel/LyuLeeParallelSolver.cs",
223 typeof(global::ULSAlgorithms.Exact.Parallel.LyuLeeParallelSolver),
224 static () => new global::ULSAlgorithms.Exact.Parallel.LyuLeeParallelSolver(),
226 static options => new global::ULSAlgorithms.Exact.Parallel.LyuLeeParallelSolver(
227 options.MaxDegreeOfParallelism ?? -1,
228 options.ParallelThreshold ?? 128)),
229 new(
230 "saydam-mcknew",
231 "Saydam–McKnew",
232 UlsSolverCategory.DirectExact,
233 "Wagner–Whitin DP",
234 "O(T²)",
235 "O(T²)",
236 "General ULS costs represented by the library",
237 "Saydam & McKnew (1987), A Fast Microcomputer Program for Ordering Using the Wagner-Whitin Algorithm, Production and Inventory Management 28(4), 15-19",
238 "",
239 "Modern contiguous triangular-cost reconstruction",
240 "src/ULSAlgorithms/Exact/SaydamMcKnew/SaydamMcKnewFastWagnerWhitinSolver.cs",
241 typeof(global::ULSAlgorithms.Exact.SaydamMcKnew.SaydamMcKnewFastWagnerWhitinSolver),
242 static () => new global::ULSAlgorithms.Exact.SaydamMcKnew.SaydamMcKnewFastWagnerWhitinSolver()),
243 new(
244 "jacobs-khumawala",
245 "Jacobs–Khumawala",
246 UlsSolverCategory.DirectExact,
247 "Branch and bound",
248 "O(T²)",
249 "O(T)",
250 "General ULS costs represented by the library",
251 "Jacobs & Khumawala (1987), A Simplified Procedure for Optimal Single-Level Lot Sizing, Production and Inventory Management 28(3), 39-43",
252 "",
253 "Modern branch/subproblem reconstruction",
254 "src/ULSAlgorithms/Exact/JacobsKhumawala/JacobsKhumawalaBranchAndBoundSolver.cs",
255 typeof(global::ULSAlgorithms.Exact.JacobsKhumawala.JacobsKhumawalaBranchAndBoundSolver),
256 static () => new global::ULSAlgorithms.Exact.JacobsKhumawala.JacobsKhumawalaBranchAndBoundSolver()),
257 new(
258 "zangwill-network",
259 "Zangwill network",
260 UlsSolverCategory.DirectExact,
261 "Network / shortest path",
262 "O(T²)",
263 "O(T)",
264 "Single-echelon no-backlogging ULS represented by the library",
265 "Zangwill (1969), A Backlogging Model and a Multi-Echelon Model of a Dynamic Economic Lot Size Production System, Management Science 15(9), 506-527",
266 "10.1287/mnsc.15.9.506",
267 "Backward DAG shortest path",
268 "src/ULSAlgorithms/Exact/Zangwill/ZangwillNetworkSolver.cs",
269 typeof(global::ULSAlgorithms.Exact.Zangwill.ZangwillNetworkSolver),
270 static () => new global::ULSAlgorithms.Exact.Zangwill.ZangwillNetworkSolver()),
271 new(
272 "aggregate-inventory-formulation",
273 "Aggregate inventory formulation",
274 UlsSolverCategory.OptimizationFormulation,
275 "Solver-backed mathematical formulation",
276 "Solver-dependent",
277 "O(T) model + solver",
278 "General classical ULS",
279 "Wagner & Whitin (1958), Dynamic Version of the Economic Lot Size Model, Management Science 5(1), 89-96; Brahimi, Dauzere-Peres, Najid & Nordli (2006), Single Item Lot Sizing Problems, European Journal of Operational Research 168(1), 1-16",
280 "10.1287/mnsc.5.1.89",
281 "Aggregate x/y/I MILP with automatic solver selection",
282 "src/ULSAlgorithms/Exact/Formulations/AggregateInventoryFormulationSolver.cs",
283 typeof(global::ULSAlgorithms.Exact.Formulations.AggregateInventoryFormulationSolver),
284 static () => new global::ULSAlgorithms.Exact.Formulations.AggregateInventoryFormulationSolver(),
285 UlsSolverConfigurationCapabilities.OptimizationExecution,
286 static options => new global::ULSAlgorithms.Exact.Formulations.AggregateInventoryFormulationSolver(
287 options.OptimizationExecution)),
288 new(
289 "facility-location-formulation",
290 "Facility-location formulation",
291 UlsSolverCategory.OptimizationFormulation,
292 "Solver-backed mathematical formulation",
293 "Solver-dependent",
294 "O(T²) model + solver",
295 "General classical ULS",
296 "Krarup & Bilde (1977), Plant Location, Set Covering and Economic Lot Size: An O(nm)-Algorithm for Structured Problems; Brahimi, Dauzere-Peres, Najid & Nordli (2006), Single Item Lot Sizing Problems, European Journal of Operational Research 168(1), 1-16",
297 "10.1007/978-3-0348-5936-3_10",
298 "Disaggregated q[t,k]/y formulation",
299 "src/ULSAlgorithms/Exact/Formulations/FacilityLocationFormulationSolver.cs",
300 typeof(global::ULSAlgorithms.Exact.Formulations.FacilityLocationFormulationSolver),
301 static () => new global::ULSAlgorithms.Exact.Formulations.FacilityLocationFormulationSolver(),
302 UlsSolverConfigurationCapabilities.OptimizationExecution,
303 static options => new global::ULSAlgorithms.Exact.Formulations.FacilityLocationFormulationSolver(
304 options.OptimizationExecution)),
305 new(
306 "shortest-path-formulation",
307 "Shortest-path formulation",
308 UlsSolverCategory.OptimizationFormulation,
309 "Solver-backed network formulation",
310 "Solver-dependent",
311 "O(T²) model + solver",
312 "No speculative motive / Wagner–Whitin costs",
313 "Zangwill (1969), A Backlogging Model and a Multi-Echelon Model of a Dynamic Economic Lot Size Production System, Management Science 15(9), 506-527; Brahimi, Dauzere-Peres, Najid & Nordli (2006), Single Item Lot Sizing Problems, European Journal of Operational Research 168(1), 1-16",
314 "10.1287/mnsc.15.9.506",
315 "Continuous network-flow formulation with path reconstruction",
316 "src/ULSAlgorithms/Exact/Formulations/ShortestPathFormulationSolver.cs",
317 typeof(global::ULSAlgorithms.Exact.Formulations.ShortestPathFormulationSolver),
318 static () => new global::ULSAlgorithms.Exact.Formulations.ShortestPathFormulationSolver(),
319 UlsSolverConfigurationCapabilities.OptimizationExecution,
320 static options => new global::ULSAlgorithms.Exact.Formulations.ShortestPathFormulationSolver(
321 options.OptimizationExecution)),
322 new(
323 "inventory-eliminated-formulation",
324 "Inventory-eliminated formulation",
325 UlsSolverCategory.OptimizationFormulation,
326 "Solver-backed mathematical formulation",
327 "Solver-dependent",
328 "O(T) variables + O(T²) coefficients/constraints",
329 "General classical ULS",
330 "Brahimi, Dauzere-Peres, Najid & Nordli (2006), Single Item Lot Sizing Problems, European Journal of Operational Research 168(1), 1-16",
331 "10.1016/j.ejor.2004.01.054",
332 "Aggregate x/y formulation with inventory algebraically eliminated",
333 "src/ULSAlgorithms/Exact/Formulations/InventoryEliminatedFormulationSolver.cs",
334 typeof(global::ULSAlgorithms.Exact.Formulations.InventoryEliminatedFormulationSolver),
335 static () => new global::ULSAlgorithms.Exact.Formulations.InventoryEliminatedFormulationSolver(),
336 UlsSolverConfigurationCapabilities.OptimizationExecution,
337 static options => new global::ULSAlgorithms.Exact.Formulations.InventoryEliminatedFormulationSolver(
338 options.OptimizationExecution)),
339 new(
340 "general-ls-cutting-plane",
341 "General (l,S) cutting-plane",
342 UlsSolverCategory.CuttingPlane,
343 "Cutting planes / convex hull",
344 "O(T²) separation per root iteration + solver",
345 "O(T) separator + model/cuts",
346 "General classical ULS",
347 "Barany, Van Roy & Wolsey (1984), Uncapacitated Lot-Sizing: The Convex Hull of Solutions",
348 "10.1007/BFb0121006",
349 "Exact general (l,S) separation + strengthened final MILP",
350 "src/ULSAlgorithms/Exact/CuttingPlanes/GeneralLsCuttingPlaneSolver.cs",
351 typeof(global::ULSAlgorithms.Exact.CuttingPlanes.GeneralLsCuttingPlaneSolver),
352 static () => new global::ULSAlgorithms.Exact.CuttingPlanes.GeneralLsCuttingPlaneSolver(),
353 UlsSolverConfigurationCapabilities.OptimizationExecution |
355 static options => new global::ULSAlgorithms.Exact.CuttingPlanes.GeneralLsCuttingPlaneSolver(
356 options.OptimizationExecution,
357 options.CuttingPlane)),
358 new(
359 "wagner-whitin-ls-cutting-plane",
360 "Wagner–Whitin (l,S) cutting-plane",
361 UlsSolverCategory.CuttingPlane,
362 "Cutting planes / Wagner–Whitin",
363 "O(T²) separation per root iteration + solver",
364 "O(T) separator + model/cuts",
365 "No speculative motive / Wagner–Whitin costs",
366 "Pochet & Wolsey (1994), Polyhedra for Lot-Sizing with Wagner-Whitin Costs",
367 "10.1007/BF01582225",
368 "O(T²) prefix-S Wagner–Whitin separation + strengthened final MILP",
369 "src/ULSAlgorithms/Exact/CuttingPlanes/WagnerWhitinLsCuttingPlaneSolver.cs",
370 typeof(global::ULSAlgorithms.Exact.CuttingPlanes.WagnerWhitinLsCuttingPlaneSolver),
371 static () => new global::ULSAlgorithms.Exact.CuttingPlanes.WagnerWhitinLsCuttingPlaneSolver(),
374 static options => new global::ULSAlgorithms.Exact.CuttingPlanes.WagnerWhitinLsCuttingPlaneSolver(
375 options.OptimizationExecution,
376 options.CuttingPlane)),
377 new(
378 "lot-for-lot",
379 "Lot-for-Lot",
380 UlsSolverCategory.Heuristic,
381 "Baseline",
382 "O(T)",
383 "O(T)",
384 "General ULS costs",
385 "Classical MRP lot-for-lot rule",
386 "",
387 "One replenishment per positive-demand period",
388 "src/ULSAlgorithms/Heuristics/LotForLotSolver.cs",
389 typeof(global::ULSAlgorithms.Heuristics.LotForLotSolver),
390 static () => new global::ULSAlgorithms.Heuristics.LotForLotSolver()),
391 new(
392 "silver-meal",
393 "Silver–Meal",
394 UlsSolverCategory.Heuristic,
395 "Average-cost",
396 "O(T)",
397 "O(T)",
398 "Stationary setup, production and relevant holding costs",
399 "Silver & Meal (1973), A Heuristic for Selecting Lot Size Quantities for the Case of a Deterministic Time-Varying Demand Rate and Discrete Opportunities for Replenishment, Production and Inventory Management 14(2), 64-74",
400 "",
401 "Least cost per covered period",
402 "src/ULSAlgorithms/Heuristics/SilverMealSolver.cs",
403 typeof(global::ULSAlgorithms.Heuristics.SilverMealSolver),
404 static () => new global::ULSAlgorithms.Heuristics.SilverMealSolver()),
405 new(
406 "least-unit-cost",
407 "Least Unit Cost",
408 UlsSolverCategory.Heuristic,
409 "Average-cost",
410 "O(T)",
411 "O(T)",
412 "Stationary setup, production and relevant holding costs",
413 "Classical Least Unit Cost (LUC) lot-sizing rule",
414 "",
415 "Least relevant cost per unit",
416 "src/ULSAlgorithms/Heuristics/LeastUnitCostSolver.cs",
417 typeof(global::ULSAlgorithms.Heuristics.LeastUnitCostSolver),
418 static () => new global::ULSAlgorithms.Heuristics.LeastUnitCostSolver()),
419 new(
420 "part-period-balancing",
421 "Part-Period Balancing",
422 UlsSolverCategory.Heuristic,
423 "Part-period",
424 "O(T)",
425 "O(T)",
426 "Stationary setup, production and relevant holding costs",
427 "DeMatteis (1968), An Economic Lot-Sizing Technique I: The Part-Period Algorithm, IBM Systems Journal 7(1), 30-38",
428 "10.1147/sj.71.0030",
429 "Closest balance to economic part period",
430 "src/ULSAlgorithms/Heuristics/PartPeriodBalancingSolver.cs",
431 typeof(global::ULSAlgorithms.Heuristics.PartPeriodBalancingSolver),
432 static () => new global::ULSAlgorithms.Heuristics.PartPeriodBalancingSolver()),
433 new(
434 "groff",
435 "Groff",
436 UlsSolverCategory.Heuristic,
437 "Marginal-cost",
438 "O(T)",
439 "O(T)",
440 "Stationary setup, production and relevant holding costs",
441 "Groff (1979), A Lot Sizing Rule for Time-Phased Component Demand, Production and Inventory Management 20(4), 66-74",
442 "",
443 "Marginal setup/holding criterion",
444 "src/ULSAlgorithms/Heuristics/GroffSolver.cs",
445 typeof(global::ULSAlgorithms.Heuristics.GroffSolver),
446 static () => new global::ULSAlgorithms.Heuristics.GroffSolver()),
447 new(
448 "periodic-order-quantity",
449 "Periodic Order Quantity",
450 UlsSolverCategory.Heuristic,
451 "Fixed-cycle",
452 "O(T)",
453 "O(T)",
454 "Stationary setup, production and relevant holding costs",
455 "Classical Periodic Order Quantity (POQ) rule",
456 "",
457 "EOQ-derived replenishment interval",
458 "src/ULSAlgorithms/Heuristics/PeriodicOrderQuantitySolver.cs",
459 typeof(global::ULSAlgorithms.Heuristics.PeriodicOrderQuantitySolver),
460 static () => new global::ULSAlgorithms.Heuristics.PeriodicOrderQuantitySolver()),
461 new(
462 "freeland-colley",
463 "Freeland–Colley",
464 UlsSolverCategory.Heuristic,
465 "Marginal-cost",
466 "O(T)",
467 "O(T)",
468 "Stationary setup, production and relevant holding costs",
469 "Freeland & Colley (1982), A Simple Heuristic Method for Lot Sizing in a Time-Phased Reorder System, Production and Inventory Management 23(1), 15-21",
470 "",
471 "Local incremental carrying-cost criterion",
472 "src/ULSAlgorithms/Heuristics/FreelandColleySolver.cs",
473 typeof(global::ULSAlgorithms.Heuristics.FreelandColleySolver),
474 static () => new global::ULSAlgorithms.Heuristics.FreelandColleySolver()),
475 new(
476 "patterson-laforge-incremental-part-period",
477 "Patterson–LaForge IPPA",
478 UlsSolverCategory.Heuristic,
479 "Part-period",
480 "O(T)",
481 "O(T)",
482 "Stationary setup, production and relevant holding costs",
483 "Patterson & LaForge (1985), The Incremental Part-Period Algorithm: An Alternative to EOQ, Journal of Purchasing and Materials Management 21(2), 28-33",
484 "10.1111/j.1745-493X.1985.tb00132.x",
485 "Incremental part-period stopping rule",
486 "src/ULSAlgorithms/Heuristics/PattersonLaForgeIncrementalPartPeriodSolver.cs",
487 typeof(global::ULSAlgorithms.Heuristics.PattersonLaForgeIncrementalPartPeriodSolver),
488 static () => new global::ULSAlgorithms.Heuristics.PattersonLaForgeIncrementalPartPeriodSolver()),
489 new(
490 "wemmerlov-modified-ppb",
491 "Wemmerlöv corrected PPB",
492 UlsSolverCategory.Heuristic,
493 "Part-period",
494 "O(T)",
495 "O(T)",
496 "Stationary setup, production and relevant holding costs",
497 "Wemmerlöv (1983), The Part-Period Balancing Algorithm and Its Look Ahead-Look Back Feature: A Theoretical and Experimental Analysis of a Single Stage Lot-Sizing Procedure, Journal of Operations Management 4(1), 23-39",
498 "10.1016/0272-6963(83)90023-2",
499 "Corrected PPB with ν = 0.5",
500 "src/ULSAlgorithms/Heuristics/WemmerlovModifiedPartPeriodBalancingSolver.cs",
501 typeof(global::ULSAlgorithms.Heuristics.WemmerlovModifiedPartPeriodBalancingSolver),
502 static () => new global::ULSAlgorithms.Heuristics.WemmerlovModifiedPartPeriodBalancingSolver()),
503 new(
504 "wemmerlov-ppb-lalb",
505 "Wemmerlöv PPB + LALB",
506 UlsSolverCategory.Heuristic,
507 "Look-ahead / look-back",
508 "O(T)",
509 "O(T)",
510 "Stationary costs; strictly positive demand",
511 "Wemmerlöv (1983), The Part-Period Balancing Algorithm and Its Look Ahead-Look Back Feature: A Theoretical and Experimental Analysis of a Single Stage Lot-Sizing Procedure, Journal of Operations Management 4(1), 23-39",
512 "10.1016/0272-6963(83)90023-2",
513 "PPB with local LALB adjustment",
514 "src/ULSAlgorithms/Heuristics/WemmerlovPpbLookAheadLookBackSolver.cs",
515 typeof(global::ULSAlgorithms.Heuristics.WemmerlovPpbLookAheadLookBackSolver),
516 static () => new global::ULSAlgorithms.Heuristics.WemmerlovPpbLookAheadLookBackSolver()),
517 new(
518 "wemmerlov-modified-ppb-lalb",
519 "Wemmerlöv corrected PPB + LALB",
520 UlsSolverCategory.Heuristic,
521 "Look-ahead / look-back",
522 "O(T)",
523 "O(T)",
524 "Stationary costs; strictly positive demand",
525 "Wemmerlöv (1983), The Part-Period Balancing Algorithm and Its Look Ahead-Look Back Feature: A Theoretical and Experimental Analysis of a Single Stage Lot-Sizing Procedure, Journal of Operations Management 4(1), 23-39",
526 "10.1016/0272-6963(83)90023-2",
527 "Corrected PPB + LALB",
528 "src/ULSAlgorithms/Heuristics/WemmerlovModifiedPpbLookAheadLookBackSolver.cs",
529 typeof(global::ULSAlgorithms.Heuristics.WemmerlovModifiedPpbLookAheadLookBackSolver),
530 static () => new global::ULSAlgorithms.Heuristics.WemmerlovModifiedPpbLookAheadLookBackSolver()),
531 new(
532 "part-period-simplified",
533 "Part-Period Simplified",
534 UlsSolverCategory.Heuristic,
535 "Part-period",
536 "O(T)",
537 "O(T)",
538 "Stationary setup, production and relevant holding costs",
539 "DeMatteis (1968), An Economic Lot-Sizing Technique I: The Part-Period Algorithm, IBM Systems Journal 7(1), 30-38; Baciarello et al. (2013)",
540 "10.5772/56004",
541 "No-overshoot EPP / Part-Period Simplified rule",
542 "src/ULSAlgorithms/Heuristics/PartPeriodSimplifiedSolver.cs",
543 typeof(global::ULSAlgorithms.Heuristics.PartPeriodSimplifiedSolver),
544 static () => new global::ULSAlgorithms.Heuristics.PartPeriodSimplifiedSolver()),
545 new(
546 "segerstedt-reformulated-silver-meal",
547 "Segerstedt reformulated Silver-Meal",
548 UlsSolverCategory.Heuristic,
549 "Average-cost",
550 "O(T)",
551 "O(T)",
552 "Stationary setup, production and relevant holding costs",
553 "Segerstedt, Abdul-Jalbar & Samuelsson (2023), Reformulated Silver-Meal and Similar Lot Sizing Techniques, Axioms 12(7), 661",
554 "10.3390/axioms12070661",
555 "Reformulated Silver-Meal over non-zero demand events",
556 "src/ULSAlgorithms/Heuristics/SegerstedtReformulatedSilverMealSolver.cs",
557 typeof(global::ULSAlgorithms.Heuristics.SegerstedtReformulatedSilverMealSolver),
558 static () => new global::ULSAlgorithms.Heuristics.SegerstedtReformulatedSilverMealSolver()),
559 new(
560 "chiu-modified-least-unit-cost",
561 "Chiu modified Least Unit Cost",
562 UlsSolverCategory.Heuristic,
563 "Average-cost / post-processing",
564 "O(T)",
565 "O(T)",
566 "Stationary setup, production and relevant holding costs",
567 "Chiu (2004), A modification of the least unit cost lot-sizing heuristic, Journal of Statistics and Management Systems 7(1), 197-207",
568 "10.1080/09720510.2004.10701115",
569 "Classical LUC plus cost-beneficial final-lot merge",
570 "src/ULSAlgorithms/Heuristics/ChiuModifiedLeastUnitCostSolver.cs",
571 typeof(global::ULSAlgorithms.Heuristics.ChiuModifiedLeastUnitCostSolver),
572 static () => new global::ULSAlgorithms.Heuristics.ChiuModifiedLeastUnitCostSolver()),
573 new(
574 "chiu-ting-modified-part-period-balancing",
575 "Chiu-Ting modified Part-Period Balancing",
576 UlsSolverCategory.Heuristic,
577 "Part-period / post-processing",
578 "O(T)",
579 "O(T)",
580 "Stationary setup, production and relevant holding costs",
581 "Chiu, Ting & Chiu (2005), A Modified Version of the Part Period Lot-Sizing Heuristic, International Journal for Engineering Modelling 18(1-2), 59-64",
582 "",
583 "Nearest-EPP PPB plus cost-beneficial final-lot merge",
584 "src/ULSAlgorithms/Heuristics/ChiuTingModifiedPartPeriodBalancingSolver.cs",
585 typeof(global::ULSAlgorithms.Heuristics.ChiuTingModifiedPartPeriodBalancingSolver),
586 static () => new global::ULSAlgorithms.Heuristics.ChiuTingModifiedPartPeriodBalancingSolver()),
587 new(
588 "ho-chang-solis-net-least-period-cost",
589 "Ho-Chang-Solis net Least Period Cost",
590 UlsSolverCategory.Heuristic,
591 "Average-cost / net period",
592 "O(T)",
593 "O(T)",
594 "Stationary setup, production and relevant holding costs",
595 "Ho, Chang & Solis (2006), Two modifications of the least cost per period heuristic for dynamic lot-sizing, Journal of the Operational Research Society 57(8), 1005-1013",
596 "10.1057/palgrave.jors.2602076",
597 "Incremental O(T) evaluation of the published nAPC stopping rule; zero-demand periods are excluded from the average denominator",
598 "src/ULSAlgorithms/Heuristics/HoChangSolisNetLeastPeriodCostSolver.cs",
599 typeof(global::ULSAlgorithms.Heuristics.HoChangSolisNetLeastPeriodCostSolver),
600 static () => new global::ULSAlgorithms.Heuristics.HoChangSolisNetLeastPeriodCostSolver()),
601 new(
602 "ho-chang-solis-improved-net-least-period-cost",
603 "Ho-Chang-Solis improved nLPC(i)",
604 UlsSolverCategory.Heuristic,
605 "Average-cost / net period",
606 "O(T)",
607 "O(T)",
608 "Stationary setup, production and relevant holding costs",
609 "Ho, Chang & Solis (2006), Two modifications of the least cost per period heuristic for dynamic lot-sizing, Journal of the Operational Research Society 57(8), 1005-1013",
610 "10.1057/palgrave.jors.2602076",
611 "Incremental nAPC rule with the published improved tie-breaking stop condition",
612 "src/ULSAlgorithms/Heuristics/HoChangSolisImprovedNetLeastPeriodCostSolver.cs",
613 typeof(global::ULSAlgorithms.Heuristics.HoChangSolisImprovedNetLeastPeriodCostSolver),
614 static () => new global::ULSAlgorithms.Heuristics.HoChangSolisImprovedNetLeastPeriodCostSolver()),
615 new(
616 "mclaren-order-moment",
617 "McLaren Order Moment",
618 UlsSolverCategory.Heuristic,
619 "Part-period / EOQ hybrid",
620 "O(T)",
621 "O(T)",
622 "Stationary setup, production and relevant holding costs",
623 "McLaren (1977), Order Moment lot-sizing rule; Baciarello et al. (2013), Lot Sizing Heuristics Performance",
624 "10.5772/56004",
625 "EOQ-derived Order Moment Target with part-period accumulation and a final marginal holding/setup test",
626 "src/ULSAlgorithms/Heuristics/McLarenOrderMomentSolver.cs",
627 typeof(global::ULSAlgorithms.Heuristics.McLarenOrderMomentSolver),
628 static () => new global::ULSAlgorithms.Heuristics.McLarenOrderMomentSolver()),
629 new(
630 "karni-maximum-part-period-gain",
631 "Karni Maximum Part-Period Gain",
632 UlsSolverCategory.Heuristic,
633 "Global part-period merge",
634 "O(T log T)",
635 "O(T)",
636 "Stationary setup, production and relevant holding costs",
637 "Karni (1981), Maximum Part-Period Gain lot-sizing rule; Baciarello et al. (2013), Lot Sizing Heuristics Performance",
638 "10.5772/56004",
639 "Priority-queue acceleration of the published non-forward global smallest-part-period merge rule",
640 "src/ULSAlgorithms/Heuristics/KarniMaximumPartPeriodGainSolver.cs",
641 typeof(global::ULSAlgorithms.Heuristics.KarniMaximumPartPeriodGainSolver),
642 static () => new global::ULSAlgorithms.Heuristics.KarniMaximumPartPeriodGainSolver()),
643 ];
644
645 private static readonly Dictionary<string, UlsSolverDescriptor> ById =
646 CreateIndex(Descriptors);
647
648 private static readonly IReadOnlyList<UlsSolverDescriptor> AllView =
649 Array.AsReadOnly(Descriptors);
650
651 private static readonly IReadOnlyList<UlsSolverDescriptor> ExactView =
652 Array.AsReadOnly(
653 Descriptors
654 .Where(descriptor => descriptor.Kind == UlsSolverKind.Exact)
655 .ToArray());
656
657 private static readonly IReadOnlyList<UlsSolverDescriptor> DirectExactView =
658 Array.AsReadOnly(
659 Descriptors
660 .Where(descriptor =>
661 descriptor.Category == UlsSolverCategory.DirectExact)
662 .ToArray());
663
664 private static readonly IReadOnlyList<UlsSolverDescriptor> FormulationsView =
665 Array.AsReadOnly(
666 Descriptors
667 .Where(descriptor =>
668 descriptor.Category ==
669 UlsSolverCategory.OptimizationFormulation)
670 .ToArray());
671
672 private static readonly IReadOnlyList<UlsSolverDescriptor> CuttingPlanesView =
673 Array.AsReadOnly(
674 Descriptors
675 .Where(descriptor =>
676 descriptor.Category == UlsSolverCategory.CuttingPlane)
677 .ToArray());
678
679 private static readonly IReadOnlyList<UlsSolverDescriptor> HeuristicsView =
680 Array.AsReadOnly(
681 Descriptors
682 .Where(descriptor =>
683 descriptor.Category == UlsSolverCategory.Heuristic)
684 .ToArray());
685
686 private static readonly IReadOnlyList<UlsSolverDescriptor> ConfigurableView =
687 Array.AsReadOnly(
688 Descriptors
689 .Where(descriptor => descriptor.SupportsConfiguration)
690 .ToArray());
691
692 /// <summary>Gets all public strategies in stable catalog order.</summary>
693 public static IReadOnlyList<UlsSolverDescriptor> All => AllView;
694
695 /// <summary>
696 /// Gets all exact strategies, including direct algorithms, formulations and
697 /// cutting-plane methods.
698 /// </summary>
699 public static IReadOnlyList<UlsSolverDescriptor> Exact => ExactView;
700
701 /// <summary>Gets direct exact algorithms that need no external optimizer.</summary>
702 public static IReadOnlyList<UlsSolverDescriptor> DirectExact => DirectExactView;
703
704 /// <summary>Gets exact solver-backed mathematical formulations.</summary>
705 public static IReadOnlyList<UlsSolverDescriptor> Formulations => FormulationsView;
706
707 /// <summary>Gets exact solver-backed cutting-plane strategies.</summary>
708 public static IReadOnlyList<UlsSolverDescriptor> CuttingPlanes => CuttingPlanesView;
709
710 /// <summary>Gets all heuristic strategies.</summary>
711 public static IReadOnlyList<UlsSolverDescriptor> Heuristics => HeuristicsView;
712
713 /// <summary>
714 /// Gets strategies exposing at least one constructor-level configurable
715 /// factory setting.
716 /// </summary>
717 public static IReadOnlyList<UlsSolverDescriptor> Configurable =>
718 ConfigurableView;
719
720 /// <summary>
721 /// Gets the recommended automatic exact entry point.
722 /// </summary>
724 Get("adaptive-exact");
725
726 /// <summary>
727 /// Gets one descriptor by stable identifier.
728 /// </summary>
729 /// <param name="id">Stable lower-kebab-case strategy identifier.</param>
730 /// <returns>The matching descriptor.</returns>
731 /// <exception cref="KeyNotFoundException">No strategy uses the identifier.</exception>
732 public static UlsSolverDescriptor Get(string id)
733 {
734 ArgumentException.ThrowIfNullOrWhiteSpace(id);
735
736 if (ById.TryGetValue(id, out var descriptor))
737 {
738 return descriptor;
739 }
740
741 throw new KeyNotFoundException(
742 $"Unknown ULS solver identifier '{id}'.");
743 }
744
745 /// <summary>
746 /// Attempts to resolve one descriptor by stable identifier.
747 /// </summary>
748 /// <param name="id">Stable identifier.</param>
749 /// <param name="descriptor">Resolved descriptor, or null when not found.</param>
750 /// <returns>True when a matching descriptor exists.</returns>
751 public static bool TryGet(
752 string? id,
753 [NotNullWhen(true)] out UlsSolverDescriptor? descriptor)
754 {
755 if (string.IsNullOrWhiteSpace(id))
756 {
757 descriptor = null;
758 return false;
759 }
760
761 return ById.TryGetValue(id, out descriptor);
762 }
763
764 /// <summary>
765 /// Gets the descriptor associated with a concrete solver type.
766 /// </summary>
767 /// <param name="implementationType">Public solver implementation type.</param>
768 /// <returns>The matching descriptor.</returns>
769 public static UlsSolverDescriptor GetByType(Type implementationType)
770 {
771 ArgumentNullException.ThrowIfNull(implementationType);
772
773 foreach (var descriptor in Descriptors)
774 {
775 if (descriptor.ImplementationType == implementationType)
776 {
777 return descriptor;
778 }
779 }
780
781 throw new KeyNotFoundException(
782 $"Type '{implementationType.FullName}' is not registered in the ULS solver catalog.");
783 }
784
785 private static Dictionary<string, UlsSolverDescriptor> CreateIndex(
786 IReadOnlyList<UlsSolverDescriptor> descriptors)
787 {
788 var index = new Dictionary<string, UlsSolverDescriptor>(
789 descriptors.Count,
790 StringComparer.OrdinalIgnoreCase);
791
792 var types = new HashSet<Type>();
793
794 foreach (var descriptor in descriptors)
795 {
796 if (!index.TryAdd(descriptor.Id, descriptor))
797 {
798 throw new InvalidOperationException(
799 $"Duplicate solver catalog identifier '{descriptor.Id}'.");
800 }
801
802 if (!types.Add(descriptor.ImplementationType))
803 {
804 throw new InvalidOperationException(
805 $"Duplicate solver catalog type '{descriptor.ImplementationType.FullName}'.");
806 }
807 }
808
809 return index;
810 }
811}
812
Canonical runtime inventory of every public IUlsSolver strategy.
static IReadOnlyList< UlsSolverDescriptor > CuttingPlanes
Gets exact solver-backed cutting-plane strategies.
static IReadOnlyList< UlsSolverDescriptor > Heuristics
Gets all heuristic strategies.
static UlsSolverDescriptor RecommendedExact
Gets the recommended automatic exact entry point.
static bool TryGet(string? id, [NotNullWhen(true)] out UlsSolverDescriptor? descriptor)
Attempts to resolve one descriptor by stable identifier.
static IReadOnlyList< UlsSolverDescriptor > All
Gets all public strategies in stable catalog order.
static IReadOnlyList< UlsSolverDescriptor > Configurable
Gets strategies exposing at least one constructor-level configurable factory setting.
static IReadOnlyList< UlsSolverDescriptor > Formulations
Gets exact solver-backed mathematical formulations.
static UlsSolverDescriptor Get(string id)
Gets one descriptor by stable identifier.
static IReadOnlyList< UlsSolverDescriptor > DirectExact
Gets direct exact algorithms that need no external optimizer.
static UlsSolverDescriptor GetByType(Type implementationType)
Gets the descriptor associated with a concrete solver type.
static IReadOnlyList< UlsSolverDescriptor > Exact
Gets all exact strategies, including direct algorithms, formulations and cutting-plane methods.
Immutable metadata and construction entry for one public ULS strategy.
Selects and executes an efficient exact ULS algorithm from problem characteristics while preserving t...
UlsSolverKind
Identifies the broad family of a ULS solution strategy.
UlsSolverConfigurationCapabilities
Identifies the constructor-level settings that can be supplied through the configurable solver factor...
@ OptimizationExecution
The strategy accepts portable mathematical-optimization execution options, including explicit solver ...
UlsSolverCategory
Identifies the operational category of a public ULS strategy.