ULSAlgorithms 1.1.0-g3e5595996d
High-performance exact and heuristic algorithms for uncapacitated lot sizing
Loading...
Searching...
No Matches
GroffSolver.cs
Go to the documentation of this file.
1using System.Buffers;
6
8
9/// <summary>
10/// Implements Groff's marginal-cost lot-sizing rule.
11/// </summary>
12/// <remarks>
13/// A demand in offset <c>n</c> from the current replenishment period is added
14/// while
15/// <c>d[t+n] * n * (n+1) &lt;= 2A/h</c>.
16/// <para>
17/// Reference: G. K. Groff,
18/// "A Lot-Sizing Rule for Time-Phased Component Demand",
19/// Production and Inventory Management 20(1), 47-53, 1979.
20/// </para>
21/// </remarks>
22public sealed class GroffSolver : IUlsSolver
23{
24 public string Name => "Groff";
25
26 public UlsSolverKind Kind => UlsSolverKind.Heuristic;
27
28 public static bool IsApplicable(UlsProblem problem) =>
30
32 UlsProblem problem,
33 CancellationToken cancellationToken = default)
34 {
35 ArgumentNullException.ThrowIfNull(problem);
36 cancellationToken.ThrowIfCancellationRequested();
38
39 var horizon = problem.Horizon;
40 var buffer = ArrayPool<int>.Shared.Rent(horizon);
41
42 try
43 {
44 var cycleEnds = buffer.AsSpan(0, horizon);
45 cycleEnds.Fill(-1);
46
47 var demands = problem.Demands;
48 var setupCost = problem.SetupCosts[0];
49 var holdingCost =
50 horizon > 1 ? problem.HoldingCosts[0] : 0.0;
51
52 var threshold = holdingCost == 0.0
53 ? double.PositiveInfinity
54 : (2.0 * setupCost) / holdingCost;
55
56 var start =
58
59 while (start < horizon)
60 {
61 cancellationToken.ThrowIfCancellationRequested();
62
63 var bestEnd = start;
64
65 for (var end = start + 1; end < horizon; end++)
66 {
67 var offset = end - start;
68
69 var marginalCriterion =
70 demands[end] *
71 offset *
72 (offset + 1.0);
73
74 if (marginalCriterion > threshold)
75 {
76 break;
77 }
78
79 bestEnd = end;
80 }
81
82 cycleEnds[start] = bestEnd;
83
85 demands,
86 bestEnd + 1);
87 }
88
90 problem,
91 cycleEnds,
92 Name,
93 cancellationToken);
94 }
95 finally
96 {
97 ArrayPool<int>.Shared.Return(buffer, clearArray: false);
98 }
99 }
100}
Implements Groff's marginal-cost lot-sizing rule.
UlsSolveResult Solve(UlsProblem problem, CancellationToken cancellationToken=default)
Solves an uncapacitated lot-sizing problem.
string Name
Gets the stable human-readable name of the solver.
static bool IsApplicable(UlsProblem problem)
UlsSolverKind Kind
Gets the broad family of the solver.
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)
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.