27 "Adaptive exact selection",
29 "Adaptive exact strategy selection",
30 "O(T) in the NSM case; O(T log T) in the general case",
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",
40 static options =>
new global::ULSAlgorithms.Selection.AdaptiveExactUlsSolver(
41 options.AdaptiveGeneralFallback ??
42 global::ULSAlgorithms.Selection.UlsGeneralExactFallback.WagelmansGeneral)),
44 "wagner-whitin-classical",
45 "Wagner–Whitin classical",
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()),
58 "wagner-whitin-evans",
59 "Wagner–Whitin / Evans",
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()),
72 "wagner-whitin-linear",
73 "Wagner–Whitin linear",
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()),
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()),
100 "federgruen-tzur-general",
101 "Federgruen–Tzur general",
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()),
114 "federgruen-tzur-nsm",
115 "Federgruen–Tzur linear (NSM)",
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()),
128 "federgruen-tzur-nondecreasing-setup",
129 "Federgruen–Tzur linear (setup)",
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()),
145 "Monge / geometric DP",
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()),
156 "bahl-taj-planning-horizon",
157 "Bahl–Taj planning horizon",
159 "Planning-horizon DP",
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()),
173 "Planning-horizon DP",
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()),
184 "chowdhury-baki-azab",
185 "Chowdhury–Baki–Azab",
187 "Linear Wagner–Whitin",
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()),
198 "sadjadi-aryanezhad-sadeghi",
199 "Sadjadi–Aryanezhad–Sadeghi",
201 "Planning-horizon DP",
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",
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()),
216 "O(T²) work; O(T²/p) ideal parallel candidate span",
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)),
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",
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()),
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",
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()),
261 "Network / shortest path",
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()),
272 "aggregate-inventory-formulation",
273 "Aggregate inventory formulation",
275 "Solver-backed mathematical formulation",
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(),
286 static options =>
new global::ULSAlgorithms.Exact.Formulations.AggregateInventoryFormulationSolver(
287 options.OptimizationExecution)),
289 "facility-location-formulation",
290 "Facility-location formulation",
292 "Solver-backed mathematical formulation",
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(),
303 static options =>
new global::ULSAlgorithms.Exact.Formulations.FacilityLocationFormulationSolver(
304 options.OptimizationExecution)),
306 "shortest-path-formulation",
307 "Shortest-path formulation",
309 "Solver-backed network formulation",
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(),
320 static options =>
new global::ULSAlgorithms.Exact.Formulations.ShortestPathFormulationSolver(
321 options.OptimizationExecution)),
323 "inventory-eliminated-formulation",
324 "Inventory-eliminated formulation",
326 "Solver-backed mathematical formulation",
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(),
337 static options =>
new global::ULSAlgorithms.Exact.Formulations.InventoryEliminatedFormulationSolver(
338 options.OptimizationExecution)),
340 "general-ls-cutting-plane",
341 "General (l,S) cutting-plane",
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(),
355 static options =>
new global::ULSAlgorithms.Exact.CuttingPlanes.GeneralLsCuttingPlaneSolver(
356 options.OptimizationExecution,
357 options.CuttingPlane)),
359 "wagner-whitin-ls-cutting-plane",
360 "Wagner–Whitin (l,S) cutting-plane",
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)),
385 "Classical MRP lot-for-lot rule",
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()),
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",
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()),
412 "Stationary setup, production and relevant holding costs",
413 "Classical Least Unit Cost (LUC) lot-sizing rule",
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()),
420 "part-period-balancing",
421 "Part-Period Balancing",
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()),
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",
443 "Marginal setup/holding criterion",
444 "src/ULSAlgorithms/Heuristics/GroffSolver.cs",
445 typeof(global::ULSAlgorithms.
Heuristics.GroffSolver),
446 static () =>
new global::ULSAlgorithms.
Heuristics.GroffSolver()),
448 "periodic-order-quantity",
449 "Periodic Order Quantity",
454 "Stationary setup, production and relevant holding costs",
455 "Classical Periodic Order Quantity (POQ) rule",
457 "EOQ-derived replenishment interval",
458 "src/ULSAlgorithms/Heuristics/PeriodicOrderQuantitySolver.cs",
459 typeof(global::ULSAlgorithms.
Heuristics.PeriodicOrderQuantitySolver),
460 static () =>
new global::ULSAlgorithms.
Heuristics.PeriodicOrderQuantitySolver()),
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",
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()),
476 "patterson-laforge-incremental-part-period",
477 "Patterson–LaForge IPPA",
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()),
490 "wemmerlov-modified-ppb",
491 "Wemmerlöv corrected PPB",
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()),
504 "wemmerlov-ppb-lalb",
505 "Wemmerlöv PPB + LALB",
507 "Look-ahead / look-back",
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()),
518 "wemmerlov-modified-ppb-lalb",
519 "Wemmerlöv corrected PPB + LALB",
521 "Look-ahead / look-back",
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()),
532 "part-period-simplified",
533 "Part-Period Simplified",
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)",
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()),
546 "segerstedt-reformulated-silver-meal",
547 "Segerstedt reformulated Silver-Meal",
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()),
560 "chiu-modified-least-unit-cost",
561 "Chiu modified Least Unit Cost",
563 "Average-cost / post-processing",
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()),
574 "chiu-ting-modified-part-period-balancing",
575 "Chiu-Ting modified Part-Period Balancing",
577 "Part-period / post-processing",
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",
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()),
588 "ho-chang-solis-net-least-period-cost",
589 "Ho-Chang-Solis net Least Period Cost",
591 "Average-cost / net period",
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()),
602 "ho-chang-solis-improved-net-least-period-cost",
603 "Ho-Chang-Solis improved nLPC(i)",
605 "Average-cost / net period",
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()),
616 "mclaren-order-moment",
617 "McLaren Order Moment",
619 "Part-period / EOQ hybrid",
622 "Stationary setup, production and relevant holding costs",
623 "McLaren (1977), Order Moment lot-sizing rule; Baciarello et al. (2013), Lot Sizing Heuristics Performance",
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()),
630 "karni-maximum-part-period-gain",
631 "Karni Maximum Part-Period Gain",
633 "Global part-period merge",
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",
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()),
645 private static readonly Dictionary<string, UlsSolverDescriptor> ById =
646 CreateIndex(Descriptors);
648 private static readonly IReadOnlyList<UlsSolverDescriptor> AllView =
649 Array.AsReadOnly(Descriptors);
651 private static readonly IReadOnlyList<UlsSolverDescriptor> ExactView =
657 private static readonly IReadOnlyList<UlsSolverDescriptor> DirectExactView =
664 private static readonly IReadOnlyList<UlsSolverDescriptor> FormulationsView =
668 descriptor.Category ==
672 private static readonly IReadOnlyList<UlsSolverDescriptor> CuttingPlanesView =
679 private static readonly IReadOnlyList<UlsSolverDescriptor> HeuristicsView =
686 private static readonly IReadOnlyList<UlsSolverDescriptor> ConfigurableView =
689 .Where(descriptor => descriptor.SupportsConfiguration)
693 public static IReadOnlyList<UlsSolverDescriptor>
All => AllView;
699 public static IReadOnlyList<UlsSolverDescriptor>
Exact => ExactView;
702 public static IReadOnlyList<UlsSolverDescriptor>
DirectExact => DirectExactView;
705 public static IReadOnlyList<UlsSolverDescriptor>
Formulations => FormulationsView;
708 public static IReadOnlyList<UlsSolverDescriptor>
CuttingPlanes => CuttingPlanesView;
711 public static IReadOnlyList<UlsSolverDescriptor>
Heuristics => HeuristicsView;
724 Get(
"adaptive-exact");
734 ArgumentException.ThrowIfNullOrWhiteSpace(
id);
736 if (ById.TryGetValue(
id, out var descriptor))
741 throw new KeyNotFoundException(
742 $
"Unknown ULS solver identifier '{id}'.");
755 if (
string.IsNullOrWhiteSpace(
id))
761 return ById.TryGetValue(
id, out descriptor);
771 ArgumentNullException.ThrowIfNull(implementationType);
773 foreach (var descriptor
in Descriptors)
775 if (descriptor.ImplementationType == implementationType)
781 throw new KeyNotFoundException(
782 $
"Type '{implementationType.FullName}' is not registered in the ULS solver catalog.");
785 private static Dictionary<string, UlsSolverDescriptor> CreateIndex(
786 IReadOnlyList<UlsSolverDescriptor> descriptors)
788 var index =
new Dictionary<string, UlsSolverDescriptor>(
790 StringComparer.OrdinalIgnoreCase);
792 var types =
new HashSet<Type>();
794 foreach (var descriptor
in descriptors)
796 if (!index.TryAdd(descriptor.Id, descriptor))
798 throw new InvalidOperationException(
799 $
"Duplicate solver catalog identifier '{descriptor.Id}'.");
802 if (!types.Add(descriptor.ImplementationType))
804 throw new InvalidOperationException(
805 $
"Duplicate solver catalog type '{descriptor.ImplementationType.FullName}'.");