LotSizingDataModel.Core 2.0.1
Core domain model, shared abstractions and XML-serializable entities.
Loading...
Searching...
No Matches
TransportResource.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 optional decision-model parameters associated
14/// with a transport resource.
15/// </summary>
16public sealed partial class TransportResource :
17 IPlanningHorizonAware
18{
19 private CapacityConstraint? _capacityConstraint;
20 private AdditionalCapacity? _additionalCapacity;
21 private FixedUsageCost? _fixedUsageCost;
22 private AdditionalCapacityCost? _additionalCapacityCost;
23
24 /// <summary>
25 /// Gets or sets the maximum regular capacity available
26 /// for the transport resource during each planning period.
27 ///
28 /// A null value means that no global capacity constraint
29 /// is active for this transport resource.
30 /// </summary>
31 [XmlElement("capacityConstraint")]
33 {
34 get => _capacityConstraint;
35 set => SetDecisionParameter(
36 ref _capacityConstraint,
37 value,
38 nameof(CapacityConstraint));
39 }
40
41 /// <summary>
42 /// Gets or sets the maximum additional capacity that may
43 /// be allocated to the transport resource during each period.
44 ///
45 /// This parameter should only be defined when a regular
46 /// capacity constraint is also defined.
47 /// </summary>
48 [XmlElement("additionalCapacity")]
50 {
51 get => _additionalCapacity;
52 set => SetDecisionParameter(
53 ref _additionalCapacity,
54 value,
55 nameof(AdditionalCapacity));
56 }
57
58 /// <summary>
59 /// Gets or sets the fixed cost incurred when the transport
60 /// resource is used during a planning period.
61 /// </summary>
62 [XmlElement("fixedUsageCost")]
64 {
65 get => _fixedUsageCost;
66 set => SetDecisionParameter(
67 ref _fixedUsageCost,
68 value,
69 nameof(FixedUsageCost));
70 }
71
72 /// <summary>
73 /// Gets or sets the cost of using one unit of additional
74 /// transport capacity during each planning period.
75 ///
76 /// This parameter should only be defined when additional
77 /// capacity is authorized.
78 /// </summary>
79 [XmlElement("additionalCapacityCost")]
81 {
82 get => _additionalCapacityCost;
83 set => SetDecisionParameter(
84 ref _additionalCapacityCost,
85 value,
87 }
88
89 /// <summary>
90 /// Gets the planning horizon represented by the first
91 /// active period-dependent parameter.
92 ///
93 /// Returns zero when no decision parameter is active.
94 /// </summary>
95 [XmlIgnore]
96 public int PlanningHorizon
97 {
98 get
99 {
100 // Return the first active parameter's horizon.
101 foreach (IPlanningHorizonAware parameter
102 in GetDecisionParameters())
103 {
104 return parameter.PlanningHorizon;
105 }
106
107 // No active parameter → horizon is zero.
108 return 0;
109 }
110 }
111
112 /// <summary>
113 /// Gets a value indicating whether at least one
114 /// decision-model parameter is active.
115 /// </summary>
116 [XmlIgnore]
118 CapacityConstraint is not null ||
119 AdditionalCapacity is not null ||
120 FixedUsageCost is not null ||
121 AdditionalCapacityCost is not null;
122
123 /// <summary>
124 /// Gets a value indicating whether all active parameters
125 /// use the same planning horizon.
126 /// </summary>
127 [XmlIgnore]
129 {
130 get
131 {
132 int? expectedHorizon = null;
133
134 // Compare each active parameter's horizon against the first.
135 foreach (IPlanningHorizonAware parameter
136 in GetDecisionParameters())
137 {
138 if (expectedHorizon is null)
139 {
140 expectedHorizon =
141 parameter.PlanningHorizon;
142
143 continue;
144 }
145
146 if (parameter.PlanningHorizon !=
147 expectedHorizon.Value)
148 {
149 return false;
150 }
151 }
152
153 return true;
154 }
155 }
156
157 /// <summary>
158 /// Gets a value indicating whether the dependencies between
159 /// the capacity-related parameters are respected.
160 /// </summary>
161 [XmlIgnore]
163 (AdditionalCapacity is null ||
164 CapacityConstraint is not null) &&
165
166 (AdditionalCapacityCost is null ||
167 AdditionalCapacity is not null);
168
169 /// <summary>
170 /// Resizes every active period-dependent parameter.
171 ///
172 /// Existing values are preserved.
173 /// </summary>
174 /// <param name="periodCount">
175 /// New number of planning periods.
176 /// </param>
177 public void ResizeTimeSeries(int periodCount)
178 {
179 if (periodCount < 0)
180 {
181 throw new ArgumentOutOfRangeException(
182 nameof(periodCount),
183 periodCount,
184 "The planning horizon cannot be negative.");
185 }
186
187 // Resize every active decision parameter.
188 foreach (IPlanningHorizonAware parameter
189 in GetDecisionParameters())
190 {
191 parameter.ResizeTimeSeries(periodCount);
192 }
193
194 // Notify dependent computed properties.
198 }
199
200 /// <summary>
201 /// Removes all decision-model parameters from
202 /// this transport resource.
203 ///
204 /// The transport lanes are preserved.
205 /// </summary>
207 {
208 CapacityConstraint = null;
209 AdditionalCapacity = null;
210 FixedUsageCost = null;
212 }
213
214 private void SetDecisionParameter<T>(
215 ref T? field,
216 T? value,
217 string propertyName)
219 {
220 if (ReferenceEquals(field, value))
221 {
222 return;
223 }
224
225 // Unsubscribe from old parameter.
226 if (field is not null)
227 {
228 field.PropertyChanged -=
229 OnDecisionParameterPropertyChanged;
230 }
231
232 field = value;
233
234 // Subscribe to new parameter.
235 if (field is not null)
236 {
237 field.PropertyChanged +=
238 OnDecisionParameterPropertyChanged;
239 }
240
241 // Notify the specific property plus all dependent ones.
242 OnPropertyChanged(propertyName);
249 }
250
251 private IEnumerable<IPlanningHorizonAware>
252 GetDecisionParameters()
253 {
254 if (CapacityConstraint is not null)
255 {
256 yield return CapacityConstraint;
257 }
258
259 if (AdditionalCapacity is not null)
260 {
261 yield return AdditionalCapacity;
262 }
263
264 if (FixedUsageCost is not null)
265 {
266 yield return FixedUsageCost;
267 }
268
269 if (AdditionalCapacityCost is not null)
270 {
271 yield return AdditionalCapacityCost;
272 }
273 }
274
275 private void OnDecisionParameterPropertyChanged(
276 object? sender,
277 PropertyChangedEventArgs e)
278 {
279 // Forward notification for the specific parameter that changed.
280 if (ReferenceEquals(sender, CapacityConstraint))
281 {
283 }
284 else if (ReferenceEquals(sender, AdditionalCapacity))
285 {
287 }
288 else if (ReferenceEquals(sender, FixedUsageCost))
289 {
291 }
292 else if (ReferenceEquals(
293 sender,
295 {
297 nameof(AdditionalCapacityCost));
298 }
299
300 // Update all computed properties that may be affected.
306 }
307}
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.
A transport resource with its own shared capacities and costs.
void ClearDecisionParameters()
Removes all decision-model parameters from this transport resource.
AdditionalCapacityCost? AdditionalCapacityCost
Gets or sets the cost of using one unit of additional transport capacity during each planning period.
void ResizeTimeSeries(int periodCount)
Resizes every active period-dependent parameter.
int PlanningHorizon
Gets the planning horizon represented by the first active period-dependent parameter.
AdditionalCapacity? AdditionalCapacity
Gets or sets the maximum additional capacity that may be allocated to the transport resource during e...
FixedUsageCost? FixedUsageCost
Gets or sets the fixed cost incurred when the transport resource is used during a planning period.
bool HasConsistentPlanningHorizon
Gets a value indicating whether all active parameters use the same planning horizon.
bool HasValidCapacityConfiguration
Gets a value indicating whether the dependencies between the capacity-related parameters are respecte...
bool HasDecisionParameters
Gets a value indicating whether at least one decision-model parameter is active.
CapacityConstraint? CapacityConstraint
Gets or sets the maximum regular capacity available for the transport resource during each planning p...
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.