LotSizingDataModel.Core 2.0.1
Core domain model, shared abstractions and XML-serializable entities.
Loading...
Searching...
No Matches
WorkCenter.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 work center.
15/// </summary>
16public sealed partial class WorkCenter :
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 /// during each planning period.
27 ///
28 /// A null value means that the work center is not subject
29 /// to an explicit capacity constraint.
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 during each planning 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 work center
60 /// 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 /// 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 SchedulingProfile is not null;
123
124 /// <summary>
125 /// Gets a value indicating whether every active parameter
126 /// uses the same planning horizon.
127 /// </summary>
128 [XmlIgnore]
130 {
131 get
132 {
133 int? expectedHorizon = null;
134
135 // Compare each active parameter's horizon against the first.
136 foreach (IPlanningHorizonAware parameter
137 in GetDecisionParameters())
138 {
139 if (expectedHorizon is null)
140 {
141 expectedHorizon =
142 parameter.PlanningHorizon;
143
144 continue;
145 }
146
147 if (parameter.PlanningHorizon !=
148 expectedHorizon.Value)
149 {
150 return false;
151 }
152 }
153
154 return true;
155 }
156 }
157
158 /// <summary>
159 /// Gets a value indicating whether the dependencies between
160 /// capacity-related parameters are respected.
161 /// </summary>
162 [XmlIgnore]
164 (AdditionalCapacity is null ||
165 CapacityConstraint is not null) &&
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.
195 OnPropertyChanged(nameof(PlanningHorizon));
196 OnPropertyChanged(
198 }
199
200 /// <summary>
201 /// Removes all decision-model parameters from
202 /// this work center.
203 /// </summary>
205 {
206 CapacityConstraint = null;
207 AdditionalCapacity = null;
208 FixedUsageCost = null;
210 SchedulingProfile = null;
211 }
212
213 private void SetDecisionParameter<T>(
214 ref T? field,
215 T? value,
216 string propertyName)
218 {
219 if (ReferenceEquals(field, value))
220 {
221 return;
222 }
223
224 // Unsubscribe from old parameter.
225 if (field is not null)
226 {
227 field.PropertyChanged -=
228 OnDecisionParameterPropertyChanged;
229 }
230
231 field = value;
232
233 // Subscribe to new parameter.
234 if (field is not null)
235 {
236 field.PropertyChanged +=
237 OnDecisionParameterPropertyChanged;
238 }
239
240 // Notify the specific property plus all dependent ones.
241 OnPropertyChanged(propertyName);
242 OnPropertyChanged(nameof(PlanningHorizon));
243 OnPropertyChanged(nameof(HasDecisionParameters));
244 OnPropertyChanged(
246 OnPropertyChanged(
248 }
249
250 private IEnumerable<IPlanningHorizonAware>
251 GetDecisionParameters()
252 {
253 if (CapacityConstraint is not null)
254 {
255 yield return CapacityConstraint;
256 }
257
258 if (AdditionalCapacity is not null)
259 {
260 yield return AdditionalCapacity;
261 }
262
263 if (FixedUsageCost is not null)
264 {
265 yield return FixedUsageCost;
266 }
267
268 if (AdditionalCapacityCost is not null)
269 {
270 yield return AdditionalCapacityCost;
271 }
272
273 if (SchedulingProfile is not null)
274 {
275 yield return SchedulingProfile;
276 }
277 }
278
279 private void OnDecisionParameterPropertyChanged(
280 object? sender,
281 PropertyChangedEventArgs e)
282 {
283 // Forward notification for the specific parameter that changed.
284 if (ReferenceEquals(sender, CapacityConstraint))
285 {
286 OnPropertyChanged(nameof(CapacityConstraint));
287 }
288 else if (ReferenceEquals(sender, AdditionalCapacity))
289 {
290 OnPropertyChanged(nameof(AdditionalCapacity));
291 }
292 else if (ReferenceEquals(sender, FixedUsageCost))
293 {
294 OnPropertyChanged(nameof(FixedUsageCost));
295 }
296 else if (ReferenceEquals(
297 sender,
299 {
300 OnPropertyChanged(nameof(AdditionalCapacityCost));
301 }
302 else if (ReferenceEquals(sender, SchedulingProfile))
303 {
304 OnPropertyChanged(nameof(SchedulingProfile));
305 }
306
307 // Update all computed properties that may be affected.
308 OnPropertyChanged(nameof(PlanningHorizon));
309 OnPropertyChanged(
311 OnPropertyChanged(
313 }
314}
Base class for model objects that notify listeners when one of their properties changes.
Represents a production work center belonging to a plant.
Definition WorkCenter.cs:15
bool HasConsistentPlanningHorizon
Gets a value indicating whether every active parameter uses the same planning horizon.
CapacityConstraint? CapacityConstraint
Gets or sets the maximum regular capacity available during each planning period.
bool HasValidCapacityConfiguration
Gets a value indicating whether the dependencies between capacity-related parameters are respected.
FixedUsageCost? FixedUsageCost
Gets or sets the fixed cost incurred when the work center is used during a planning period.
AdditionalCapacity? AdditionalCapacity
Gets or sets the maximum additional capacity that may be allocated during each planning period.
void ResizeTimeSeries(int periodCount)
Resizes every active period-dependent parameter.
AdditionalCapacityCost? AdditionalCapacityCost
Gets or sets the cost of using one unit of additional capacity during each planning period.
int PlanningHorizon
Gets the planning horizon represented by the first active period-dependent parameter.
void ClearDecisionParameters()
Removes all decision-model parameters from this work center.
bool HasDecisionParameters
Gets a value indicating whether at least one decision-model parameter is active.
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.