ULSAlgorithms 1.1.0-g3e5595996d
High-performance exact and heuristic algorithms for uncapacitated lot sizing
Loading...
Searching...
No Matches
PattersonLaForgeIncrementalPartPeriodSolver.cs
Go to the documentation of this file.
1using System.Buffers;
6
8
9/// <summary>
10/// Implements the Patterson-LaForge Incremental Part-Period Algorithm (IPPA).
11/// </summary>
12/// <remarks>
13/// <para>
14/// The candidate lot is extended while the cumulative incremental holding cost
15/// remains no greater than the setup cost:
16/// <c>h * sum((t-s) * d[t]) &lt;= A</c>.
17/// </para>
18/// <para>
19/// Reference:
20/// J. W. Patterson and R. L. LaForge,
21/// "The Incremental Part-Period Algorithm: An Alternative to EOQ",
22/// Journal of Purchasing and Materials Management 21(2), 28-33, 1985.
23/// DOI: 10.1111/j.1745-493X.1985.tb00132.x.
24/// </para>
25/// <para>
26/// Worst-case time is O(T); auxiliary working memory is O(T).
27/// </para>
28/// </remarks>
30{
31 public string Name =>
32 "Patterson-LaForge Incremental Part-Period";
33
34 public UlsSolverKind Kind => UlsSolverKind.Heuristic;
35
36 public static bool IsApplicable(UlsProblem problem) =>
38
40 UlsProblem problem,
41 CancellationToken cancellationToken = default)
42 {
43 ArgumentNullException.ThrowIfNull(problem);
44 cancellationToken.ThrowIfCancellationRequested();
45
47 problem,
48 Name);
49
50 var horizon = problem.Horizon;
51 var buffer = ArrayPool<int>.Shared.Rent(horizon);
52
53 try
54 {
55 var cycleEnds = buffer.AsSpan(0, horizon);
56 cycleEnds.Fill(-1);
57
58 var demands = problem.Demands;
59 var setupCost = problem.SetupCosts[0];
60
61 var holdingCost =
62 horizon > 1
63 ? problem.HoldingCosts[0]
64 : 0.0;
65
66 var start =
68 demands,
69 0);
70
71 while (start < horizon)
72 {
73 cancellationToken.ThrowIfCancellationRequested();
74
75 var end = start;
76 var cumulativeHolding = 0.0;
77
78 for (var candidate = start + 1;
79 candidate < horizon;
80 candidate++)
81 {
82 var increment =
83 holdingCost *
84 (candidate - start) *
85 demands[candidate];
86
87 var nextHolding =
88 cumulativeHolding + increment;
89
90 if (!double.IsFinite(nextHolding))
91 {
92 throw new ArithmeticException(
93 "Numerical overflow in the IPPA criterion.");
94 }
95
96 if (nextHolding > setupCost)
97 {
98 break;
99 }
100
101 cumulativeHolding = nextHolding;
102 end = candidate;
103 }
104
105 cycleEnds[start] = end;
106
107 start =
109 demands,
110 end + 1);
111 }
112
114 problem,
115 cycleEnds,
116 Name,
117 cancellationToken);
118 }
119 finally
120 {
121 ArrayPool<int>.Shared.Return(
122 buffer,
123 clearArray: false);
124 }
125 }
126}
Shared applicability checks for classical stationary-cost lot-sizing heuristics.
static void ThrowIfNotStationary(UlsProblem problem, string solverName)
static int FindNextPositiveDemand(ReadOnlySpan< double > demands, int start)
Builds and validates a zero-backlogging heuristic solution from a set of replenishment cycles.
static UlsSolveResult Build(UlsProblem problem, ReadOnlySpan< int > cycleEnds, string solverName, CancellationToken cancellationToken)
Implements the Patterson-LaForge Incremental Part-Period Algorithm (IPPA).
UlsSolveResult Solve(UlsProblem problem, CancellationToken cancellationToken=default)
Solves an uncapacitated lot-sizing problem.
Represents a validated classical uncapacitated lot-sizing problem.
Definition UlsProblem.cs:23
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 the outcome returned by a ULS solution strategy.
Defines the common strategy contract implemented by every ULS solver.
Definition IUlsSolver.cs:14
UlsSolverKind
Identifies the broad family of a ULS solution strategy.