LotSizingDataModel.Solver 2.0.1
Solver-independent modeling, execution, monitoring and adapter infrastructure.
Loading...
Searching...
No Matches
ScientificFormulationSelectionService.cs
Go to the documentation of this file.
1using LotSizingDataModel.Instance;
2using LotSizingDataModel.Instance.Scientific;
3
5
6/// <summary>
7/// Scientifically filters registered mathematical formulations before
8/// technical build selection.
9/// </summary>
10/// <remarks>
11/// Automatic selection requires verified scientific compatibility.
12/// Undetermined profiles/extensions are never auto-selected.
13///
14/// The LotSizingInstance overload additionally evaluates CanBuild(instance).
15/// </remarks>
17{
18 private readonly ScientificClassificationEngine _classificationEngine;
20 _compatibilityService;
21
23 : this(
24 new ScientificClassificationEngine(),
26 {
27 }
28
30 ScientificClassificationEngine classificationEngine,
32 {
33 _classificationEngine =
34 classificationEngine ??
35 throw new ArgumentNullException(nameof(classificationEngine));
36
37 _compatibilityService =
38 compatibilityService ??
39 throw new ArgumentNullException(nameof(compatibilityService));
40 }
41
43 ScientificClassificationResult classification,
45 string requestedFormulationId = "",
46 bool allowFallback = true)
47 {
48 ArgumentNullException.ThrowIfNull(classification);
49 ArgumentNullException.ThrowIfNull(registry);
50
51 return SelectCore(
52 classification,
53 registry,
54 requestedFormulationId,
55 allowFallback,
56 instance: null);
57 }
58
60 LotSizingInstance instance,
62 string requestedFormulationId = "",
63 bool allowFallback = true,
64 ScientificClassificationRequest? classificationRequest = null)
65 {
66 ArgumentNullException.ThrowIfNull(instance);
67 ArgumentNullException.ThrowIfNull(registry);
68
69 ScientificClassificationResult classification =
70 _classificationEngine.Analyze(
71 instance,
72 classificationRequest);
73
74 return SelectCore(
75 classification,
76 registry,
77 requestedFormulationId,
78 allowFallback,
79 instance);
80 }
81
82 private ScientificFormulationSelectionResult SelectCore(
83 ScientificClassificationResult classification,
85 string requestedFormulationId,
86 bool allowFallback,
87 LotSizingInstance? instance)
88 {
89 string requested =
90 requestedFormulationId?.Trim() ?? string.Empty;
91
92 var diagnostics =
93 new List<ScientificFormulationDiagnostic>();
94
95 var candidates =
96 registry.GetAll()
97 .Select(
98 formulation =>
99 {
101 _compatibilityService.Assess(
102 classification,
103 formulation.FormulationId);
104
105 bool? canBuild =
106 instance is null
107 ? null
108 : formulation.CanBuild(instance);
109
110 if (canBuild == false)
111 {
112 diagnostics.Add(
114 "LSDM-FORM-030",
116 $"formulation.{formulation.FormulationId}",
117 "Scientific compatibility may be satisfied, " +
118 "but the formulation's technical CanBuild " +
119 "contract rejected the instance."));
120 }
121
122 return new ScientificFormulationSelectionCandidate(
123 formulation,
124 compatibility,
125 canBuild);
126 })
127 .OrderBy(
128 candidate =>
129 candidate.Formulation.FormulationId,
130 StringComparer.OrdinalIgnoreCase)
131 .ToArray();
132
133 ScientificFormulationSelectionCandidate? selected = null;
134 bool usedFallback = false;
135
136 if (!string.IsNullOrWhiteSpace(requested))
137 {
138 ScientificFormulationSelectionCandidate? requestedCandidate =
139 candidates.FirstOrDefault(
140 candidate =>
141 candidate.Formulation.FormulationId.Equals(
142 requested,
143 StringComparison.OrdinalIgnoreCase));
144
145 if (requestedCandidate is null)
146 {
147 diagnostics.Add(
148 new ScientificFormulationDiagnostic(
149 "LSDM-FORM-031",
151 "selection.requestedFormulation",
152 $"Requested formulation '{requested}' is not registered."));
153 }
154 else if (requestedCandidate.IsSelectable)
155 {
156 selected = requestedCandidate;
157 }
158 else
159 {
160 diagnostics.Add(
161 new ScientificFormulationDiagnostic(
162 "LSDM-FORM-032",
164 "selection.requestedFormulation",
165 $"Requested formulation '{requested}' is not " +
166 "scientifically and technically selectable."));
167 }
168
169 if (selected is null && !allowFallback)
170 {
171 return new ScientificFormulationSelectionResult(
172 classification,
173 requested,
174 selectedCandidate: null,
175 usedFallback: false,
176 candidates,
177 diagnostics);
178 }
179 }
180
181 if (selected is null)
182 {
183 selected =
184 candidates.FirstOrDefault(
185 candidate =>
186 candidate.IsSelectable);
187
188 usedFallback =
189 selected is not null &&
190 !string.IsNullOrWhiteSpace(requested);
191 }
192
193 if (selected is null)
194 {
195 diagnostics.Add(
196 new ScientificFormulationDiagnostic(
197 "LSDM-FORM-033",
199 "selection",
200 "No registered formulation has verified scientific " +
201 "compatibility and an acceptable technical build status."));
202 }
203 else
204 {
205 diagnostics.Add(
206 new ScientificFormulationDiagnostic(
207 "LSDM-FORM-034",
209 "selection",
210 $"Selected formulation '{selected.Formulation.FormulationId}'."));
211 }
212
213 return new ScientificFormulationSelectionResult(
214 classification,
215 requested,
216 selected,
217 usedFallback,
218 candidates,
219 diagnostics);
220 }
221}
IReadOnlyList< IMathematicalModelFormulation > GetAll()
Returns all registered formulations ordered by name and identifier.
Evaluates whether one mathematical formulation has verified scientific coverage for a classified lot-...
ScientificFormulationSelectionService(ScientificClassificationEngine classificationEngine, ScientificFormulationCompatibilityService compatibilityService)
ScientificFormulationSelectionResult Select(LotSizingInstance instance, MathematicalModelFormulationRegistry registry, string requestedFormulationId="", bool allowFallback=true, ScientificClassificationRequest? classificationRequest=null)
ScientificFormulationSelectionResult Select(ScientificClassificationResult classification, MathematicalModelFormulationRegistry registry, string requestedFormulationId="", bool allowFallback=true)