LotSizingDataModel.Solver 2.0.1
Solver-independent modeling, execution, monitoring and adapter infrastructure.
Loading...
Searching...
No Matches
InventoryBalanceConstraintBuilder.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Generic;
4
6
7/// <summary>
8/// Builds a corrected inventory-balance constraint for one
9/// item, location, and period.
10/// </summary>
11/// <remarks>
12/// The generated balance follows the convention:
13/// <code>
14/// I(t) - B(t) + S(t)
15/// = I(t-1) - B(t-1) + S(t-1)
16/// + inflows - outflows - demand.
17/// </code>
18/// After moving all variable terms to the left-hand side, the
19/// generated constraint is:
20/// <code>
21/// I(t) - B(t) + S(t)
22/// - I(t-1) + B(t-1) - S(t-1)
23/// - inflows + outflows = -demand.
24/// </code>
25/// </remarks>
27{
28 private readonly List<LinearTerm> _inflows =
29 new();
30
31 private readonly List<LinearTerm> _outflows =
32 new();
33
34 private MathematicalVariable? _currentInventory;
35
36 private MathematicalVariable? _currentBacklog;
37
38 private MathematicalVariable? _currentShortage;
39
40 private MathematicalVariable? _previousInventory;
41
42 private MathematicalVariable? _previousBacklog;
43
44 private MathematicalVariable? _previousShortage;
45
46 /// <summary>
47 /// Gets or sets the external demand for the period.
48 /// </summary>
49 public double Demand
50 {
51 get;
52 set;
53 }
54
55 /// <summary>
56 /// Assigns the current-period inventory state variables.
57 /// </summary>
58 /// <param name="inventory">
59 /// Current-period inventory variable.
60 /// </param>
61 /// <param name="backlog">
62 /// Optional current-period backlog variable.
63 /// </param>
64 /// <param name="shortage">
65 /// Optional current-period shortage variable.
66 /// </param>
67 /// <returns>
68 /// Current builder.
69 /// </returns>
70 /// <exception cref="ArgumentNullException">
71 /// Thrown when <paramref name="inventory"/> is
72 /// <see langword="null"/>.
73 /// </exception>
75 MathematicalVariable inventory,
76 MathematicalVariable? backlog = null,
77 MathematicalVariable? shortage = null)
78 {
79 ArgumentNullException.ThrowIfNull(
80 inventory);
81
82 inventory.EnsureValid();
83 backlog?.EnsureValid();
84 shortage?.EnsureValid();
85
86 _currentInventory =
87 inventory;
88
89 _currentBacklog =
90 backlog;
91
92 _currentShortage =
93 shortage;
94
95 return this;
96 }
97
98 /// <summary>
99 /// Assigns the previous-period inventory state variables.
100 /// </summary>
101 /// <param name="inventory">
102 /// Optional previous-period inventory variable.
103 /// </param>
104 /// <param name="backlog">
105 /// Optional previous-period backlog variable.
106 /// </param>
107 /// <param name="shortage">
108 /// Optional previous-period shortage variable.
109 /// </param>
110 /// <returns>
111 /// Current builder.
112 /// </returns>
114 MathematicalVariable? inventory,
115 MathematicalVariable? backlog = null,
116 MathematicalVariable? shortage = null)
117 {
118 inventory?.EnsureValid();
119 backlog?.EnsureValid();
120 shortage?.EnsureValid();
121
122 _previousInventory =
123 inventory;
124
125 _previousBacklog =
126 backlog;
127
128 _previousShortage =
129 shortage;
130
131 return this;
132 }
133
134 /// <summary>
135 /// Adds an inflow variable to the balance.
136 /// </summary>
137 /// <param name="variable">
138 /// Inflow variable.
139 /// </param>
140 /// <param name="coefficient">
141 /// Positive conversion or quantity coefficient.
142 /// </param>
143 /// <returns>
144 /// Current builder.
145 /// </returns>
147 MathematicalVariable variable,
148 double coefficient = 1.0)
149 {
150 AddFlowTerm(
151 _inflows,
152 variable,
153 coefficient,
154 nameof(coefficient));
155
156 return this;
157 }
158
159 /// <summary>
160 /// Adds an outflow variable to the balance.
161 /// </summary>
162 /// <param name="variable">
163 /// Outflow variable.
164 /// </param>
165 /// <param name="coefficient">
166 /// Positive conversion or quantity coefficient.
167 /// </param>
168 /// <returns>
169 /// Current builder.
170 /// </returns>
172 MathematicalVariable variable,
173 double coefficient = 1.0)
174 {
175 AddFlowTerm(
176 _outflows,
177 variable,
178 coefficient,
179 nameof(coefficient));
180
181 return this;
182 }
183
184 /// <summary>
185 /// Builds the corrected inventory-balance expression.
186 /// </summary>
187 /// <returns>
188 /// Left-hand-side expression of the corrected balance.
189 /// </returns>
190 /// <exception cref="InvalidOperationException">
191 /// Thrown when the current inventory variable is missing or
192 /// the demand is invalid.
193 /// </exception>
195 {
196 EnsureValid();
197
198 var expression =
199 new LinearExpression();
200
201 expression.AddTerm(
202 _currentInventory!.Id,
203 1.0);
204
205 if (_currentBacklog is not null)
206 {
207 expression.AddTerm(
208 _currentBacklog.Id,
209 -1.0);
210 }
211
212 if (_currentShortage is not null)
213 {
214 expression.AddTerm(
215 _currentShortage.Id,
216 1.0);
217 }
218
219 if (_previousInventory is not null)
220 {
221 expression.AddTerm(
222 _previousInventory.Id,
223 -1.0);
224 }
225
226 if (_previousBacklog is not null)
227 {
228 expression.AddTerm(
229 _previousBacklog.Id,
230 1.0);
231 }
232
233 if (_previousShortage is not null)
234 {
235 expression.AddTerm(
236 _previousShortage.Id,
237 -1.0);
238 }
239
240 foreach (
241 LinearTerm inflow
242 in _inflows)
243 {
244 expression.AddTerm(
245 inflow.VariableId,
246 -inflow.Coefficient);
247 }
248
249 foreach (
250 LinearTerm outflow
251 in _outflows)
252 {
253 expression.AddTerm(
254 outflow.VariableId,
255 outflow.Coefficient);
256 }
257
258 expression.EnsureValid();
259
260 return expression;
261 }
262
263 /// <summary>
264 /// Adds the corrected inventory-balance constraint to a
265 /// mathematical model.
266 /// </summary>
267 /// <param name="modelBuilder">
268 /// Mathematical model builder.
269 /// </param>
270 /// <param name="name">
271 /// Constraint name.
272 /// </param>
273 /// <param name="domainKey">
274 /// Optional business-domain key.
275 /// </param>
276 /// <param name="description">
277 /// Optional description.
278 /// </param>
279 /// <returns>
280 /// Created inventory-balance constraint.
281 /// </returns>
283 MathematicalModelBuilder modelBuilder,
284 string name,
285 string domainKey = "",
286 string description = "")
287 {
288 ArgumentNullException.ThrowIfNull(
289 modelBuilder);
290
291 return modelBuilder.AddConstraint(
292 name,
295 -Demand,
296 domainKey,
297 description);
298 }
299
300 /// <summary>
301 /// Validates the inventory-balance definition.
302 /// </summary>
303 /// <exception cref="InvalidOperationException">
304 /// Thrown when the definition is incomplete or invalid.
305 /// </exception>
306 public void EnsureValid()
307 {
308 if (_currentInventory is null)
309 {
310 throw new InvalidOperationException(
311 "A current-period inventory variable is " +
312 "required.");
313 }
314
315 if (double.IsNaN(
316 Demand) ||
317 double.IsInfinity(
318 Demand))
319 {
320 throw new InvalidOperationException(
321 "Inventory-balance demand must be finite.");
322 }
323
324 foreach (
325 LinearTerm term
326 in _inflows)
327 {
328 term.EnsureValid();
329 }
330
331 foreach (
332 LinearTerm term
333 in _outflows)
334 {
335 term.EnsureValid();
336 }
337 }
338
339 private static void AddFlowTerm(
340 ICollection<LinearTerm> target,
341 MathematicalVariable variable,
342 double coefficient,
343 string coefficientName)
344 {
345 ArgumentNullException.ThrowIfNull(
346 variable);
347
348 variable.EnsureValid();
349
350 if (double.IsNaN(
351 coefficient) ||
352 double.IsInfinity(
353 coefficient) ||
354 coefficient <= 0.0)
355 {
356 throw new ArgumentOutOfRangeException(
357 coefficientName,
358 coefficient,
359 "A flow coefficient must be finite and " +
360 "strictly positive.");
361 }
362
363 target.Add(
364 new LinearTerm(
365 variable.Id,
366 coefficient));
367 }
368}
Builds a corrected inventory-balance constraint for one item, location, and period.
InventoryBalanceConstraintBuilder AddInflow(MathematicalVariable variable, double coefficient=1.0)
Adds an inflow variable to the balance.
InventoryBalanceConstraintBuilder AddOutflow(MathematicalVariable variable, double coefficient=1.0)
Adds an outflow variable to the balance.
LinearExpression BuildExpression()
Builds the corrected inventory-balance expression.
InventoryBalanceConstraintBuilder SetCurrentState(MathematicalVariable inventory, MathematicalVariable? backlog=null, MathematicalVariable? shortage=null)
Assigns the current-period inventory state variables.
InventoryBalanceConstraintBuilder SetPreviousState(MathematicalVariable? inventory, MathematicalVariable? backlog=null, MathematicalVariable? shortage=null)
Assigns the previous-period inventory state variables.
LinearConstraint AddToModel(MathematicalModelBuilder modelBuilder, string name, string domainKey="", string description="")
Adds the corrected inventory-balance constraint to a mathematical model.
Builds a solver-independent mathematical model while assigning unique variable and constraint identif...
LinearConstraint AddConstraint(string name, LinearExpression leftHandSide, MathematicalConstraintSense sense, double rightHandSide, string domainKey="", string description="")
Creates and adds a linear constraint.
Represents one linear constraint in a mathematical optimization model.
Represents a linear expression composed of variable terms and a constant value.
Represents one coefficient-variable term in a linear expression.
Definition LinearTerm.cs:13
int VariableId
Gets or sets the identifier of the referenced mathematical variable.
Definition LinearTerm.cs:49
double Coefficient
Gets or sets the coefficient multiplying the referenced variable.
Definition LinearTerm.cs:60
void EnsureValid()
Validates the linear term.
Definition LinearTerm.cs:72
Represents one decision variable in a mathematical optimization model.
int Id
Gets or sets the unique variable identifier within the mathematical model.
void EnsureValid()
Validates the mathematical variable.
MathematicalConstraintSense
Identifies the relational sense of a mathematical constraint.