ULSAlgorithms 1.1.0-g3e5595996d
High-performance exact and heuristic algorithms for uncapacitated lot sizing
Loading...
Searching...
No Matches
LastReplenishmentMergeImprover.cs
Go to the documentation of this file.
2
4
5/// <summary>
6/// Applies the published final-lot merge test used by the modified LUC and
7/// modified PPB heuristics.
8/// </summary>
9internal static class LastReplenishmentMergeImprover
10{
11 /// <summary>
12 /// Eliminates the final replenishment lot when moving its complete demand
13 /// to the preceding replenishment period strictly reduces setup plus
14 /// holding cost.
15 /// </summary>
16 public static bool TryMergeLastLot(
17 UlsProblem problem,
18 Span<int> cycleEnds)
19 {
20 ArgumentNullException.ThrowIfNull(problem);
21
22 if (cycleEnds.Length < problem.Horizon)
23 {
24 throw new ArgumentException(
25 "The cycle-end buffer is shorter than the problem horizon.",
26 nameof(cycleEnds));
27 }
28
29 var previousStart = -1;
30 var lastStart = -1;
31
32 for (var period = 0; period < problem.Horizon; period++)
33 {
34 if (cycleEnds[period] < period)
35 {
36 continue;
37 }
38
39 previousStart = lastStart;
40 lastStart = period;
41 }
42
43 if (previousStart < 0 || lastStart < 0)
44 {
45 return false;
46 }
47
48 var lastEnd = cycleEnds[lastStart];
49
50 if (lastEnd < lastStart ||
51 lastEnd >= problem.Horizon)
52 {
53 throw new InvalidOperationException(
54 $"Invalid final replenishment cycle [{lastStart}, {lastEnd}].");
55 }
56
57 var lastQuantity = 0.0;
58 var demands = problem.Demands;
59
60 for (var period = lastStart; period <= lastEnd; period++)
61 {
62 lastQuantity += demands[period];
63
64 if (!double.IsFinite(lastQuantity))
65 {
66 throw new ArithmeticException(
67 "Numerical overflow while evaluating the final-lot merge.");
68 }
69 }
70
71 if (lastQuantity <= 0.0)
72 {
73 return false;
74 }
75
76 var holdingCost =
77 problem.Horizon > 1
78 ? problem.HoldingCosts[0]
79 : 0.0;
80
81 var extraHoldingCost =
82 holdingCost *
83 (lastStart - previousStart) *
84 lastQuantity;
85
86 if (!double.IsFinite(extraHoldingCost))
87 {
88 throw new ArithmeticException(
89 "Numerical overflow while evaluating final-lot holding cost.");
90 }
91
92 var setupSaving = problem.SetupCosts[0];
93
94 var scale =
95 Math.Max(
96 1.0,
97 Math.Max(
98 Math.Abs(extraHoldingCost),
99 Math.Abs(setupSaving)));
100
101 var tolerance = 1.0e-12 * scale;
102
103 if (extraHoldingCost + tolerance >= setupSaving)
104 {
105 return false;
106 }
107
108 cycleEnds[previousStart] = lastEnd;
109 cycleEnds[lastStart] = -1;
110
111 return true;
112 }
113}
Applies the published final-lot merge test used by the modified LUC and modified PPB heuristics.
static bool TryMergeLastLot(UlsProblem problem, Span< int > cycleEnds)
Eliminates the final replenishment lot when moving its complete demand to the preceding replenishment...
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