LotSizingDataModel.Solver 2.0.1
Solver-independent modeling, execution, monitoring and adapter infrastructure.
Loading...
Searching...
No Matches
TransportDecisionMapper.cs
Go to the documentation of this file.
1using System;
2using System.Linq;
3using LotSizingDataModel.Core.PhysicalModel;
4using LotSizingDataModel.Solution;
5using LotSizingDataModel.Solution.Decisions;
7
9
10/// <summary>
11/// Maps mathematical transport-variable values to transport
12/// decisions in a lot-sizing solution.
13/// </summary>
14/// <remarks>
15/// Expected canonical domain-key format:
16/// <code>
17/// transport|item=&lt;id&gt;|transportResource=&lt;id&gt;|originWarehouse=&lt;id&gt;|destinationWarehouse=&lt;id&gt;|period=&lt;index&gt;
18/// </code>
19/// Origin and destination may alternatively be identified by
20/// <c>originPlant</c> and <c>destinationPlant</c> when the
21/// corresponding warehouses are attached to plants.
22/// </remarks>
23public sealed class TransportDecisionMapper :
25{
26 /// <summary>
27 /// Gets the mathematical domain-key category handled by this
28 /// mapper.
29 /// </summary>
30 public override string Category =>
32
33 /// <summary>
34 /// Maps one non-zero transport quantity.
35 /// </summary>
36 /// <param name="context">
37 /// Mathematical-solution mapping context.
38 /// </param>
39 /// <param name="solution">
40 /// Target lot-sizing solution.
41 /// </param>
42 /// <param name="domainKey">
43 /// Parsed transport domain key.
44 /// </param>
45 /// <param name="variableValue">
46 /// Transport quantity returned by the solver.
47 /// </param>
48 protected override void MapValue(
50 LotSizingSolution solution,
51 MathematicalDomainKey domainKey,
52 MathematicalVariableValue variableValue)
53 {
54 ArgumentNullException.ThrowIfNull(
55 context);
56
57 ArgumentNullException.ThrowIfNull(
58 solution);
59
60 ArgumentNullException.ThrowIfNull(
61 domainKey);
62
63 ArgumentNullException.ThrowIfNull(
64 variableValue);
65
66 int itemId =
67 domainKey.GetRequiredInt32(
69
70 int transportResourceId =
71 domainKey.GetRequiredInt32(
73
74 int period =
75 domainKey.GetRequiredInt32(
77
78 WarehouseReference origin =
79 ResolveWarehouse(
80 domainKey,
83 "origin");
84
85 WarehouseReference destination =
86 ResolveWarehouse(
87 domainKey,
90 "destination");
91
92 TransportDecision? decision =
93 solution.TransportDecisions
94 .FirstOrDefault(
95 existing =>
96 existing.ItemId ==
97 itemId &&
98 existing.TransportResourceId ==
99 transportResourceId &&
100 existing.Origin.Kind ==
101 origin.Kind &&
102 existing.Origin.ReferenceId ==
103 origin.ReferenceId &&
104 existing.Destination.Kind ==
105 destination.Kind &&
106 existing.Destination.ReferenceId ==
107 destination.ReferenceId);
108
109 if (decision is null)
110 {
111 if (solution.PlanningHorizon <= 0)
112 {
113 throw new InvalidOperationException(
114 "The target lot-sizing solution must have a " +
115 "strictly positive planning horizon before " +
116 "transport decisions are mapped.");
117 }
118
119 decision =
120 new TransportDecision(
121 itemId,
122 transportResourceId,
123 origin,
124 destination,
125 solution.PlanningHorizon);
126
127 solution.AddTransportDecision(
128 decision);
129 }
130
131 decision.SetTransportedQuantity(
132 period,
133 variableValue.Value);
134 }
135
136 private static WarehouseReference ResolveWarehouse(
137 MathematicalDomainKey domainKey,
138 string warehouseSegment,
139 string plantSegment,
140 string role)
141 {
142 bool hasStandaloneWarehouse =
143 domainKey.TryGetInt32(
144 warehouseSegment,
145 out int warehouseId);
146
147 bool hasPlantWarehouse =
148 domainKey.TryGetInt32(
149 plantSegment,
150 out int plantId);
151
152 if (hasStandaloneWarehouse ==
153 hasPlantWarehouse)
154 {
155 throw new InvalidOperationException(
156 $"A transport domain key must identify exactly " +
157 $"one {role} warehouse using either " +
158 $"'{warehouseSegment}' or '{plantSegment}'.");
159 }
160
161 if (hasStandaloneWarehouse)
162 {
163 return WarehouseReference
164 .ForStandaloneWarehouse(
165 warehouseId);
166 }
167
168 return WarehouseReference
169 .ForPlantWarehouse(
170 plantId);
171 }
172}
Stores the value returned by a solver for one mathematical decision variable.
double Value
Gets or sets the value returned by the solver.
Provides the canonical mathematical domain-key categories used to identify lot-sizing decision famili...
const string Transport
Identifies transported-quantity decision variables.
Provides a reusable base implementation for mathematical decision mappers handling one domain-key cat...
Represents a parsed mathematical-model business-domain key.
int GetRequiredInt32(string name)
Gets a required integer segment.
bool TryGetInt32(string name, out int value)
Attempts to get an integer segment.
Provides the canonical mathematical domain-key segment names used by lot-sizing variables and constra...
const string TransportResource
Transport-resource identifier segment.
const string DestinationWarehouse
Standalone destination-warehouse identifier segment.
const string DestinationPlant
Destination-plant identifier segment.
const string OriginWarehouse
Standalone origin-warehouse identifier segment.
Provides the shared state and lookup services required while mapping a mathematical solver result bac...
Maps mathematical transport-variable values to transport decisions in a lot-sizing solution.
override void MapValue(MathematicalSolutionMappingContext context, LotSizingSolution solution, MathematicalDomainKey domainKey, MathematicalVariableValue variableValue)
Maps one non-zero transport quantity.
override string Category
Gets the mathematical domain-key category handled by this mapper.