LotSizingDataModel.Solver 2.0.1
Solver-independent modeling, execution, monitoring and adapter infrastructure.
Loading...
Searching...
No Matches
InventoryCapacityConstraintFamilyBuilder.cs
Go to the documentation of this file.
1using System;
2using System.Threading;
3using System.Threading.Tasks;
4using LotSizingDataModel.Core.Relationships;
5using LotSizingDataModel.Instance;
9
11
12/// <summary>
13/// Builds item-specific inventory capacity constraints.
14/// </summary>
15/// <remarks>
16/// For each inventory relation with an item-specific capacity,
17/// the generated load is:
18/// <code>
19/// unitCapacityConsumption * inventory
20/// + setupTime * inventorySetup
21/// &lt;= regularCapacity + additionalCapacityUsed.
22/// </code>
23/// </remarks>
26{
27 /// <summary>
28 /// Gets the unique constraint-family identifier.
29 /// </summary>
30 public override string ConstraintFamilyId =>
31 "inventoryCapacity";
32
33 /// <summary>
34 /// Determines whether item-specific inventory capacities
35 /// exist.
36 /// </summary>
37 public override bool IsEnabled(
38 LotSizingInstance instance,
40 {
41 ArgumentNullException.ThrowIfNull(instance);
42 ArgumentNullException.ThrowIfNull(options);
43
44 foreach (Inventory inventory in instance.SupplyChain.Inventories)
45 {
46 if (inventory.CapacityConstraint is not null)
47 {
48 return true;
49 }
50 }
51
52 return false;
53 }
54
55 /// <summary>
56 /// Builds item-specific inventory capacity constraints.
57 /// </summary>
58 protected override ValueTask BuildConstraintsAsync(
59 LotSizingInstance instance,
62 CancellationToken cancellationToken)
63 {
64 foreach (Inventory inventory in instance.SupplyChain.Inventories)
65 {
66 if (inventory.CapacityConstraint is null)
67 {
68 continue;
69 }
70
71 for (int period = 1;
72 period <= instance.PlanningHorizon;
73 period++)
74 {
75 cancellationToken.ThrowIfCancellationRequested();
76
77 MathematicalVariable inventoryVariable =
78 GetInventoryVariable(
79 context,
80 inventory,
81 period);
82
83 var expression =
85 .Add(
86 inventoryVariable,
87 inventory.UnitCapacityConsumption?[period] ??
88 1.0);
89
90 AddOptionalSetupLoad(
91 context,
92 expression,
93 inventory,
94 period);
95
96 AddOptionalAdditionalCapacity(
97 context,
98 expression,
99 inventory,
100 period);
101
103 context,
104 $"inventoryCapacity_i{inventory.ItemId}" +
105 $"_w{inventory.Warehouse.ReferenceId}_t{period}",
106 expression.Build(),
107 MathematicalConstraintSense.LessThanOrEqual,
108 inventory.CapacityConstraint[period],
109 description:
110 "Item-specific inventory capacity " +
111 "constraint.");
112 }
113 }
114
115 return ValueTask.CompletedTask;
116 }
117
118 private static MathematicalVariable GetInventoryVariable(
120 Inventory inventory,
121 int period)
122 {
123 var keyBuilder =
126 .Add(
128 inventory.ItemId);
129
131 keyBuilder,
132 inventory.Warehouse);
133
134 return context.GetVariable(
135 keyBuilder
136 .Add(
138 period)
139 .Build());
140 }
141
142 private static void AddOptionalSetupLoad(
144 LinearExpressionBuilder expression,
145 Inventory inventory,
146 int period)
147 {
148 double setupTime =
149 inventory.SetupTime?[period] ??
150 0.0;
151
152 if (setupTime == 0.0)
153 {
154 return;
155 }
156
157 var keyBuilder =
160 .Add(
162 inventory.ItemId);
163
164 StandardFormulationDomainKeyFactory.AddWarehouse(
165 keyBuilder,
166 inventory.Warehouse);
167
168 string key =
169 keyBuilder
170 .Add(
172 period)
173 .Build();
174
175 if (context.VariableRegistry.TryGet(
176 key,
177 out MathematicalVariable? setupVariable) &&
178 setupVariable is not null)
179 {
180 expression.Add(
181 setupVariable,
182 setupTime);
183 }
184 }
185
186 private static void AddOptionalAdditionalCapacity(
187 MathematicalModelBuildContext context,
188 LinearExpressionBuilder expression,
189 Inventory inventory,
190 int period)
191 {
192 var keyBuilder =
193 new MathematicalDomainKeyBuilder(
194 MathematicalDecisionCategory
195 .InventoryAdditionalCapacity)
196 .Add(
197 MathematicalDomainKeySegment.Item,
198 inventory.ItemId);
199
200 StandardFormulationDomainKeyFactory.AddWarehouse(
201 keyBuilder,
202 inventory.Warehouse);
203
204 string key =
205 keyBuilder
206 .Add(
207 MathematicalDomainKeySegment.Period,
208 period)
209 .Build();
210
211 if (context.VariableRegistry.TryGet(
212 key,
213 out MathematicalVariable? additionalVariable) &&
214 additionalVariable is not null)
215 {
216 expression.Subtract(
217 additionalVariable);
218 }
219 }
220}
Provides a fluent builder for linear expressions.
LinearExpressionBuilder Subtract(MathematicalVariable variable, double coefficient=1.0)
Subtracts a variable term from the expression.
LinearExpressionBuilder Add(MathematicalVariable variable, double coefficient=1.0)
Adds a variable term to the expression.
Builds stable business-domain keys for mathematical variables and constraints.
MathematicalDomainKeyBuilder Add(string name, string value)
Adds a text segment.
Provides the shared state required while constructing a solver-independent mathematical model.
MathematicalVariable GetVariable(string domainKey)
Gets a required mathematical variable from its business-domain key.
MathematicalVariableRegistry VariableRegistry
Gets the registry that maps business-domain keys to mathematical variables.
bool TryGet(string domainKey, out MathematicalVariable? variable)
Attempts to get the variable registered for a domain key.
override ValueTask BuildConstraintsAsync(LotSizingInstance instance, MathematicalModelBuildContext context, StandardLotSizingFormulationOptions options, CancellationToken cancellationToken)
Builds item-specific inventory capacity constraints.
override bool IsEnabled(LotSizingInstance instance, StandardLotSizingFormulationOptions options)
Determines whether item-specific inventory capacities exist.
Creates canonical domain-key fragments shared by standard formulation builders and provides warehouse...
static MathematicalDomainKeyBuilder AddWarehouse(MathematicalDomainKeyBuilder builder, WarehouseReference warehouse)
Adds a warehouse reference using the generic warehouse or plant segment.
Provides common validation and helper methods for one constraint family of the standard lot-sizing fo...
static void AddConstraint(MathematicalModelBuildContext context, string name, LinearExpression expression, MathematicalConstraintSense sense, double rightHandSide, string domainKey="", string description="")
Adds one linear constraint to the mathematical model.
Configures the standard solver-independent mixed-integer lot-sizing formulation.
Provides the canonical mathematical domain-key categories used to identify lot-sizing decision famili...
const string Inventory
Identifies inventory-level decision variables.
const string InventorySetup
Identifies inventory setup decision variables.
Provides the canonical mathematical domain-key segment names used by lot-sizing variables and constra...
Represents one decision variable in a mathematical optimization model.
MathematicalConstraintSense
Identifies the relational sense of a mathematical constraint.