ULSAlgorithms 1.1.0-g3e5595996d
High-performance exact and heuristic algorithms for uncapacitated lot sizing
Loading...
Searching...
No Matches
PeriodicOrderQuantitySolver.cs
Go to the documentation of this file.
1using System.Buffers;
6
8
9/// <summary>
10/// Implements the classical Periodic Order Quantity (POQ) rule.
11/// </summary>
12/// <remarks>
13/// POQ converts the EOQ quantity into an integer order interval using the
14/// average per-period demand:
15/// <c>P = round(sqrt(2A / (h * dBar)))</c>, with a minimum of one period.
16/// Each replenishment then covers the demands in the next <c>P</c> calendar
17/// periods.
18/// </remarks>
20{
21 public string Name => "Periodic Order Quantity";
22
23 public UlsSolverKind Kind => UlsSolverKind.Heuristic;
24
25 public static bool IsApplicable(UlsProblem problem) =>
27
28 public static int GetOrderInterval(UlsProblem problem)
29 {
30 ArgumentNullException.ThrowIfNull(problem);
32 problem,
33 "Periodic Order Quantity");
34
35 if (problem.TotalDemand == 0.0)
36 {
37 return 1;
38 }
39
40 var averageDemand =
41 problem.TotalDemand / problem.Horizon;
42
43 var setupCost = problem.SetupCosts[0];
44
45 var holdingCost =
46 problem.Horizon > 1 ? problem.HoldingCosts[0] : 0.0;
47
48 if (holdingCost == 0.0)
49 {
50 return problem.Horizon;
51 }
52
53 if (setupCost == 0.0)
54 {
55 return 1;
56 }
57
58 var continuousInterval =
59 Math.Sqrt(
60 (2.0 * setupCost) /
61 (holdingCost * averageDemand));
62
63 var interval = (int)Math.Round(
64 continuousInterval,
65 MidpointRounding.AwayFromZero);
66
67 return Math.Clamp(interval, 1, problem.Horizon);
68 }
69
71 UlsProblem problem,
72 CancellationToken cancellationToken = default)
73 {
74 ArgumentNullException.ThrowIfNull(problem);
75 cancellationToken.ThrowIfCancellationRequested();
77
78 var horizon = problem.Horizon;
79 var buffer = ArrayPool<int>.Shared.Rent(horizon);
80
81 try
82 {
83 var cycleEnds = buffer.AsSpan(0, horizon);
84 cycleEnds.Fill(-1);
85
86 var demands = problem.Demands;
87 var interval = GetOrderInterval(problem);
88
89 var start =
91
92 while (start < horizon)
93 {
94 cancellationToken.ThrowIfCancellationRequested();
95
96 var end =
97 Math.Min(
98 horizon - 1,
99 start + interval - 1);
100
101 cycleEnds[start] = end;
102
104 demands,
105 end + 1);
106 }
107
109 problem,
110 cycleEnds,
111 Name,
112 cancellationToken);
113 }
114 finally
115 {
116 ArrayPool<int>.Shared.Return(buffer, clearArray: false);
117 }
118 }
119}
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 classical Periodic Order Quantity (POQ) rule.
string Name
Gets the stable human-readable name of the solver.
UlsSolverKind Kind
Gets the broad family of the solver.
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
double TotalDemand
Gets the total demand over the complete planning horizon.
Definition UlsProblem.cs:87
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.