LotSizingDataModel.Core 2.0.1
Core domain model, shared abstractions and XML-serializable entities.
Loading...
Searching...
No Matches
Warehouse.DecisionModel.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Generic;
3using System.ComponentModel;
4using System.Xml.Serialization;
9
11
12/// <summary>
13/// Adds the global decision-model parameters associated
14/// with a warehouse.
15///
16/// These parameters concern the warehouse as a whole,
17/// independently of the items stored in it.
18/// </summary>
19public abstract partial class Warehouse :
20 IPlanningHorizonAware
21{
22 private CapacityConstraint? _capacityConstraint;
23 private AdditionalCapacity? _additionalCapacity;
24 private FixedUsageCost? _fixedUsageCost;
25 private AdditionalCapacityCost? _additionalCapacityCost;
26
27 /// <summary>
28 /// Gets or sets the maximum global storage capacity
29 /// of the warehouse during each planning period.
30 ///
31 /// Corresponds to CMax[v,t].
32 /// </summary>
33 [XmlElement("capacityConstraint")]
35 {
36 get => _capacityConstraint;
37 set => SetDecisionParameter(
38 ref _capacityConstraint,
39 value,
40 nameof(CapacityConstraint));
41 }
42
43 /// <summary>
44 /// Gets or sets the maximum additional storage capacity
45 /// that may be allocated to the warehouse.
46 ///
47 /// Corresponds to CSuppl[v,t].
48 /// </summary>
49 [XmlElement("additionalCapacity")]
51 {
52 get => _additionalCapacity;
53 set => SetDecisionParameter(
54 ref _additionalCapacity,
55 value,
56 nameof(AdditionalCapacity));
57 }
58
59 /// <summary>
60 /// Gets or sets the fixed cost incurred when the warehouse
61 /// is used during a planning period.
62 ///
63 /// Corresponds to CFU[v,t].
64 /// </summary>
65 [XmlElement("fixedUsageCost")]
67 {
68 get => _fixedUsageCost;
69 set => SetDecisionParameter(
70 ref _fixedUsageCost,
71 value,
72 nameof(FixedUsageCost));
73 }
74
75 /// <summary>
76 /// Gets or sets the cost of using one unit of global
77 /// additional warehouse capacity.
78 ///
79 /// Corresponds to COV[v,t].
80 /// </summary>
81 [XmlElement("additionalCapacityCost")]
83 {
84 get => _additionalCapacityCost;
85 set => SetDecisionParameter(
86 ref _additionalCapacityCost,
87 value,
89 }
90
91 /// <summary>
92 /// Gets the planning horizon represented by the first
93 /// active period-dependent parameter.
94 ///
95 /// Returns zero when no decision parameter is active.
96 /// </summary>
97 [XmlIgnore]
98 public int PlanningHorizon
99 {
100 get
101 {
102 // Return the first active parameter's horizon.
103 foreach (IPlanningHorizonAware parameter
104 in GetDecisionParameters())
105 {
106 return parameter.PlanningHorizon;
107 }
108
109 // No active parameter → horizon is zero.
110 return 0;
111 }
112 }
113
114 /// <summary>
115 /// Gets a value indicating whether the warehouse contains
116 /// at least one global decision-model parameter.
117 /// </summary>
118 [XmlIgnore]
120 CapacityConstraint is not null ||
121 AdditionalCapacity is not null ||
122 FixedUsageCost is not null ||
123 AdditionalCapacityCost is not null;
124
125 /// <summary>
126 /// Gets a value indicating whether all active parameters
127 /// use the same planning horizon.
128 /// </summary>
129 [XmlIgnore]
131 {
132 get
133 {
134 int? expectedHorizon = null;
135
136 // Compare each active parameter's horizon against the first.
137 foreach (IPlanningHorizonAware parameter
138 in GetDecisionParameters())
139 {
140 if (expectedHorizon is null)
141 {
142 expectedHorizon =
143 parameter.PlanningHorizon;
144
145 continue;
146 }
147
148 if (parameter.PlanningHorizon !=
149 expectedHorizon.Value)
150 {
151 return false;
152 }
153 }
154
155 return true;
156 }
157 }
158
159 /// <summary>
160 /// Gets a value indicating whether the dependencies between
161 /// the warehouse-capacity parameters are respected.
162 /// </summary>
163 [XmlIgnore]
165 (AdditionalCapacity is null ||
166 CapacityConstraint is not null) &&
167
168 (AdditionalCapacityCost is null ||
169 AdditionalCapacity is not null);
170
171 /// <summary>
172 /// Resizes every active period-dependent warehouse parameter.
173 ///
174 /// Existing values are preserved.
175 /// </summary>
176 /// <param name="periodCount">
177 /// New number of planning periods.
178 /// </param>
179 public void ResizeTimeSeries(int periodCount)
180 {
181 if (periodCount < 0)
182 {
183 throw new ArgumentOutOfRangeException(
184 nameof(periodCount),
185 periodCount,
186 "The planning horizon cannot be negative.");
187 }
188
189 // Resize every active decision parameter.
190 foreach (IPlanningHorizonAware parameter
191 in GetDecisionParameters())
192 {
193 parameter.ResizeTimeSeries(periodCount);
194 }
195
196 // Notify dependent computed properties.
200 }
201
202 /// <summary>
203 /// Removes all global decision-model parameters
204 /// from the warehouse.
205 ///
206 /// Item-specific inventory parameters are not affected.
207 /// </summary>
209 {
210 CapacityConstraint = null;
211 AdditionalCapacity = null;
212 FixedUsageCost = null;
214 }
215
216 private void SetDecisionParameter<T>(
217 ref T? field,
218 T? value,
219 string propertyName)
221 {
222 if (ReferenceEquals(field, value))
223 {
224 return;
225 }
226
227 // Unsubscribe from old parameter.
228 if (field is not null)
229 {
230 field.PropertyChanged -=
231 OnDecisionParameterPropertyChanged;
232 }
233
234 field = value;
235
236 // Subscribe to new parameter.
237 if (field is not null)
238 {
239 field.PropertyChanged +=
240 OnDecisionParameterPropertyChanged;
241 }
242
243 // Notify the specific property plus all dependent ones.
244 OnPropertyChanged(propertyName);
251 }
252
253 private IEnumerable<IPlanningHorizonAware>
254 GetDecisionParameters()
255 {
256 if (CapacityConstraint is not null)
257 {
258 yield return CapacityConstraint;
259 }
260
261 if (AdditionalCapacity is not null)
262 {
263 yield return AdditionalCapacity;
264 }
265
266 if (FixedUsageCost is not null)
267 {
268 yield return FixedUsageCost;
269 }
270
271 if (AdditionalCapacityCost is not null)
272 {
273 yield return AdditionalCapacityCost;
274 }
275 }
276
277 private void OnDecisionParameterPropertyChanged(
278 object? sender,
279 PropertyChangedEventArgs e)
280 {
281 // Forward notification for the specific parameter that changed.
282 if (ReferenceEquals(sender, CapacityConstraint))
283 {
285 }
286 else if (ReferenceEquals(sender, AdditionalCapacity))
287 {
289 }
290 else if (ReferenceEquals(sender, FixedUsageCost))
291 {
293 }
294 else if (ReferenceEquals(
295 sender,
297 {
299 nameof(AdditionalCapacityCost));
300 }
301
302 // Update all computed properties that may be affected.
308 }
309}
Base class for model objects that notify listeners when one of their properties changes.
virtual void OnPropertyChanged([CallerMemberName] string? propertyName=null)
Raises the PropertyChanged event.
Represents a warehouse in the supply chain.
Definition Warehouse.cs:19
AdditionalCapacity? AdditionalCapacity
Gets or sets the maximum additional storage capacity that may be allocated to the warehouse.
bool HasValidCapacityConfiguration
Gets a value indicating whether the dependencies between the warehouse-capacity parameters are respec...
FixedUsageCost? FixedUsageCost
Gets or sets the fixed cost incurred when the warehouse is used during a planning period.
int PlanningHorizon
Gets the planning horizon represented by the first active period-dependent parameter.
bool HasDecisionParameters
Gets a value indicating whether the warehouse contains at least one global decision-model parameter.
CapacityConstraint? CapacityConstraint
Gets or sets the maximum global storage capacity of the warehouse during each planning period.
void ClearDecisionParameters()
Removes all global decision-model parameters from the warehouse.
AdditionalCapacityCost? AdditionalCapacityCost
Gets or sets the cost of using one unit of global additional warehouse capacity.
void ResizeTimeSeries(int periodCount)
Resizes every active period-dependent warehouse parameter.
bool HasConsistentPlanningHorizon
Gets a value indicating whether all active parameters use the same planning horizon.
Defines a model object containing data indexed by planning period.
int PlanningHorizon
Gets the number of planning periods currently represented by the object's time-dependent data.
void ResizeTimeSeries(int periodCount)
Resizes every time-dependent series contained in the object.