29 _historicalCapabilityAnalyzer;
49 historicalCapabilityAnalyzer)
53 throw new ArgumentNullException(nameof(modelChecker));
57 throw new ArgumentNullException(nameof(notationGenerator));
61 throw new ArgumentNullException(nameof(notationParser));
65 throw new ArgumentNullException(nameof(notationMatcher));
67 _problemClassDetector =
68 problemClassDetector ??
69 throw new ArgumentNullException(nameof(problemClassDetector));
71 _historicalCapabilityAnalyzer =
72 historicalCapabilityAnalyzer ??
73 throw new ArgumentNullException(
74 nameof(historicalCapabilityAnalyzer));
81 ArgumentNullException.ThrowIfNull(descriptor);
83 return AnalyzeDescriptorCore(
86 instanceValidation:
null,
95 ArgumentNullException.ThrowIfNull(features);
104 SupplyChain supplyChain,
107 ArgumentNullException.ThrowIfNull(supplyChain);
122 ArgumentNullException.ThrowIfNull(instance);
129 _modelChecker.Check(instance);
133 return CreateBlockedResult(
134 instanceValidation: validation,
139 code:
"LSDM-SCI-001",
145 "Scientific classification is blocked by " +
146 "instance-model validation.")
152 return AnalyzeSupplyChain(
159 SupplyChain supplyChain,
170 productStructureAnalysis,
179 new List<ScientificClassificationDiagnostic>();
181 diagnostics.AddRange(
182 productStructureAnalysis.
Warnings.Select(
185 code:
"LSDM-SCI-002",
189 path:
"descriptor.structure",
192 diagnostics.AddRange(
193 productStructureAnalysis.
Errors.Select(
196 code:
"LSDM-SCI-003",
200 path:
"descriptor.structure",
203 if (productStructureAnalysis.
Errors.Count > 0)
205 return CreateBlockedResult(
212 return AnalyzeDescriptorCore(
219 private ScientificClassificationResult AnalyzeDescriptorCore(
221 ScientificClassificationRequest request,
223 IEnumerable<ScientificClassificationDiagnostic>
227 new List<ScientificClassificationDiagnostic>(
231 _notationGenerator.Generate(
233 request.DerivedSemantics);
235 IReadOnlyList<LotSizingProblemClassMatchResult>
237 _problemClassDetector.Detect(
241 problemClasses.Count == 1
245 if (problemClasses.Count == 0)
248 new ScientificClassificationDiagnostic(
249 code:
"LSDM-SCI-020",
253 path:
"classification.problemClasses",
255 "No currently detectable canonical lot-sizing " +
256 "problem class matches this descriptor."));
258 else if (problemClasses.Count > 1)
261 new ScientificClassificationDiagnostic(
262 code:
"LSDM-SCI-021",
266 path:
"classification.problemClasses",
268 "More than one canonical problem class is " +
269 "compatible; no primary class was selected."));
272 ScientificNotationComparison notationComparison =
273 CompareDeclaredNotation(
278 IReadOnlyList<HistoricalClassificationCapability>
279 historicalCapabilities =
280 _historicalCapabilityAnalyzer.Analyze(
283 return new ScientificClassificationResult(
290 historicalCapabilities,
295 private ScientificNotationComparison CompareDeclaredNotation(
296 LotSizingProblemDescriptor descriptor,
297 ScientificClassificationRequest request,
298 ICollection<ScientificClassificationDiagnostic> diagnostics)
300 if (!request.HasDeclaredNotation)
302 return new ScientificNotationComparison(
307 UniversalProblemSpecification declaredSpecification;
311 UniversalLotSizingNotation parsed =
312 _notationParser.Parse(
313 request.DeclaredNotation);
315 declaredSpecification =
316 new UniversalProblemSpecification(
319 catch (Exception exception)
321 exception is FormatException or
322 NotSupportedException or
326 new ScientificClassificationDiagnostic(
327 code:
"LSDM-SCI-010",
331 path:
"classification.declaredNotation",
333 "Declared notation is invalid: " +
336 return new ScientificNotationComparison(
337 request.DeclaredNotation,
339 .InvalidDeclaredNotation);
342 UniversalNotationMatchResult match =
343 _notationMatcher.Match(
345 declaredSpecification,
346 request.DerivedSemantics);
351 UniversalNotationMatchKind.Exact =>
354 UniversalNotationMatchKind.Compatible =>
357 UniversalNotationMatchKind.Incomplete =>
360 UniversalNotationMatchKind.Contradiction =>
363 _ =>
throw new ArgumentOutOfRangeException()
366 AppendDeclaredNotationDiagnostic(
370 return new ScientificNotationComparison(
371 request.DeclaredNotation,
373 declaredSpecification,
377 private static void AppendDeclaredNotationDiagnostic(
379 ICollection<ScientificClassificationDiagnostic> diagnostics)
389 new ScientificClassificationDiagnostic(
390 code:
"LSDM-SCI-011",
394 path:
"classification.declaredNotation",
396 "Declared notation is compatible but less " +
397 "specific than detected instance semantics."));
402 new ScientificClassificationDiagnostic(
403 code:
"LSDM-SCI-012",
407 path:
"classification.declaredNotation",
409 "Declared notation requires semantic " +
410 "information that has not been analyzed."));
415 new ScientificClassificationDiagnostic(
416 code:
"LSDM-SCI-013",
420 path:
"classification.declaredNotation",
422 "Declared notation contradicts detected " +
423 "instance semantics."));
430 throw new ArgumentOutOfRangeException(
433 "Unknown notation-comparison kind.");
437 private static ScientificClassificationResult CreateBlockedResult(
438 InstanceModelCheckResult? instanceValidation,
439 IEnumerable<ScientificClassificationDiagnostic> diagnostics,
440 string declaredNotation,
441 LotSizingProblemDescriptor? descriptor =
null)
443 ScientificNotationComparison notationComparison =
444 string.IsNullOrWhiteSpace(declaredNotation)
445 ?
new ScientificNotationComparison(
448 : new ScientificNotationComparison(
453 return new ScientificClassificationResult(
456 detectedNotation:
null,
459 Array.Empty<LotSizingProblemClassMatchResult>(),
460 primaryProblemClass:
null,
461 historicalCapabilities:
462 Array.Empty<HistoricalClassificationCapability>(),