ULSAlgorithms 1.1.0-g3e5595996d
High-performance exact and heuristic algorithms for uncapacitated lot sizing
Loading...
Searching...
No Matches
UlsRegenerationCost.cs
Go to the documentation of this file.
2
4
5/// <summary>
6/// O(1) regeneration-interval cost evaluator for the uncapacitated
7/// zero-inventory-ordering structure.
8/// </summary>
9internal sealed class UlsRegenerationCost
10{
11 private readonly UlsProblem _problem;
12 private readonly double[] _demandPrefix;
13 private readonly double[] _holdingPrefix;
14 private readonly double[] _weightedDemandPrefix;
15
17 {
18 ArgumentNullException.ThrowIfNull(problem);
19
20 _problem = problem;
21
22 var horizon = problem.Horizon;
23
24 _demandPrefix = new double[horizon + 1];
25 _holdingPrefix = new double[horizon + 1];
26 _weightedDemandPrefix = new double[horizon + 1];
27
28 var demands = problem.Demands;
29 var holdingCosts = problem.HoldingCosts;
30
31 for (var period = 0; period < horizon; period++)
32 {
33 _demandPrefix[period + 1] = AddFinite(
34 _demandPrefix[period],
35 demands[period],
36 "cumulative demand");
37
38 _weightedDemandPrefix[period + 1] = AddFinite(
39 _weightedDemandPrefix[period],
40 MultiplyFinite(
41 demands[period],
42 _holdingPrefix[period],
43 "demand-weighted holding prefix"),
44 "demand-weighted holding prefix");
45
46 _holdingPrefix[period + 1] = AddFinite(
47 _holdingPrefix[period],
48 holdingCosts[period],
49 "cumulative holding cost");
50 }
51 }
52
53 /// <summary>
54 /// Gets the cost of one replenishment in <paramref name="start"/>
55 /// satisfying demand through <paramref name="endInclusive"/>.
56 /// </summary>
57 public double GetCost(
58 int start,
59 int endInclusive)
60 {
61 if ((uint)start >= (uint)_problem.Horizon ||
62 endInclusive < start ||
63 endInclusive >= _problem.Horizon)
64 {
65 throw new ArgumentOutOfRangeException();
66 }
67
68 var endExclusive = endInclusive + 1;
69
70 var segmentDemand =
71 _demandPrefix[endExclusive] -
72 _demandPrefix[start];
73
74 if (segmentDemand == 0.0)
75 {
76 return 0.0;
77 }
78
79 var transformedUnitCost =
80 _problem.UnitProductionCosts[start] -
81 _holdingPrefix[start];
82
83 var variableCost = AddFinite(
84 MultiplyFinite(
85 transformedUnitCost,
86 segmentDemand,
87 "regeneration variable cost"),
88 _weightedDemandPrefix[endExclusive] -
89 _weightedDemandPrefix[start],
90 "regeneration variable cost");
91
92 return AddFinite(
93 _problem.SetupCosts[start],
94 variableCost,
95 "regeneration interval cost");
96 }
97
98 public double GetDemand(
99 int start,
100 int endInclusive)
101 {
102 if ((uint)start >= (uint)_problem.Horizon ||
103 endInclusive < start ||
104 endInclusive >= _problem.Horizon)
105 {
106 throw new ArgumentOutOfRangeException();
107 }
108
109 return
110 _demandPrefix[endInclusive + 1] -
111 _demandPrefix[start];
112 }
113
114 private static double AddFinite(
115 double left,
116 double right,
117 string operation)
118 {
119 var value = left + right;
120
121 if (!double.IsFinite(value))
122 {
123 throw new ArithmeticException(
124 $"Numerical overflow while computing {operation}.");
125 }
126
127 return value;
128 }
129
130 private static double MultiplyFinite(
131 double left,
132 double right,
133 string operation)
134 {
135 var value = left * right;
136
137 if (!double.IsFinite(value))
138 {
139 throw new ArithmeticException(
140 $"Numerical overflow while computing {operation}.");
141 }
142
143 return value;
144 }
145}
double GetDemand(int start, int endInclusive)
double GetCost(int start, int endInclusive)
Gets the cost of one replenishment in start satisfying demand through endInclusive .
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