2using System.Collections.Generic;
3using System.Globalization;
5using System.Xml.Serialization;
6using LotSizingDataModel.Core.Common;
8using LotSizingDataModel.Solution.Common;
57[XmlType(TypeName =
"solutionMethodRecommendation")]
60 private string _methodCode =
63 private string _methodName =
66 private string _methodVersion =
69 private SolutionMethodKind _methodKind =
78 private string _scopeDescription =
81 private double _score;
85 private DateTime? _evaluatedAtUtc;
87 private string _advisorVersion =
90 private string _methodCatalogName =
93 private string _methodCatalogVersion =
96 private string _supplyChainFingerprint =
99 private string _summary =
102 private string _comment =
134 SolutionMethodKind methodKind)
136 if (
string.IsNullOrWhiteSpace(methodCode))
138 throw new ArgumentException(
139 "A solution-method code is required.",
143 if (
string.IsNullOrWhiteSpace(methodName))
145 throw new ArgumentException(
146 "A solution-method name is required.",
173 ArgumentNullException.ThrowIfNull(
180 methodDefinition.
Name;
193 [XmlAttribute(
"methodCode")]
201 NormalizeCode(value)))
216 [XmlAttribute(
"methodName")]
224 value?.Trim() ??
string.Empty))
239 [XmlAttribute(
"methodVersion")]
242 get => _methodVersion;
247 value?.Trim() ??
string.Empty))
259 [XmlAttribute(
"methodKind")]
271 [XmlAttribute(
"compatibilityLevel")]
274 get => _compatibilityLevel;
278 ref _compatibilityLevel,
281 NotifyCompatibilityProperties();
294 [XmlAttribute(
"scope")]
304 NotifyScopeProperties();
335 [XmlElement(
"scopeDescription")]
338 get => _scopeDescription;
342 ref _scopeDescription,
343 value?.Trim() ??
string.Empty))
378 [XmlAttribute(
"score")]
384 if (!
double.IsFinite(value) ||
388 throw new ArgumentOutOfRangeException(
391 "The compatibility score must be finite " +
392 "and lie between zero and one.");
415 [XmlElement(
"rank", IsNullable =
true)]
421 if (value.HasValue &&
424 throw new ArgumentOutOfRangeException(
427 "A recommendation rank must be strictly " +
445 [XmlElement(
"evaluatedAtUtc", IsNullable =
true)]
448 get => _evaluatedAtUtc;
451 DateTime? normalizedValue =
453 ? ConvertToUtc(value.Value)
470 [XmlAttribute(
"advisorVersion")]
473 get => _advisorVersion;
478 value?.Trim() ??
string.Empty))
490 [XmlAttribute(
"methodCatalogName")]
493 get => _methodCatalogName;
497 ref _methodCatalogName,
498 value?.Trim() ??
string.Empty))
510 [XmlAttribute(
"methodCatalogVersion")]
513 get => _methodCatalogVersion;
517 ref _methodCatalogVersion,
518 value?.Trim() ??
string.Empty))
530 [XmlAttribute(
"supplyChainFingerprint")]
533 get => _supplyChainFingerprint;
537 ref _supplyChainFingerprint,
538 value?.Trim() ??
string.Empty))
573 [XmlElement(
"summary")]
581 value?.Trim() ??
string.Empty))
593 [XmlArray(
"evidence")]
594 [XmlArrayItem(
"criterion")]
629 [XmlArray(
"requiredAdaptations")]
630 [XmlArrayItem(
"adaptation")]
638 [XmlArray(
"warnings")]
639 [XmlArrayItem(
"warning")]
646 [XmlElement(
"comment")]
654 value?.Trim() ??
string.Empty))
668 !
string.IsNullOrWhiteSpace(
677 !
string.IsNullOrWhiteSpace(
686 !
string.IsNullOrWhiteSpace(
722 !
string.IsNullOrWhiteSpace(
747 !
string.IsNullOrWhiteSpace(
756 !
string.IsNullOrWhiteSpace(
758 !
string.IsNullOrWhiteSpace(
767 !
string.IsNullOrWhiteSpace(
776 !
string.IsNullOrWhiteSpace(
801 criterion is not
null &&
802 criterion.IsSatisfied);
811 criterion is not
null &&
812 criterion.IsMismatch);
821 criterion is not
null &&
822 criterion.IsBlockingMismatch);
831 criterion is not
null &&
832 criterion.IsRequiredMismatch);
841 criterion is not
null &&
842 criterion.IsOptionalMismatch);
874 RequiredAdaptations.Count > 0;
890 !
string.IsNullOrWhiteSpace(
961 double.IsFinite(
Score) &&
985 ArgumentNullException.ThrowIfNull(
990 throw new ArgumentException(
991 "The compatibility evidence is invalid.",
998 NotifyEvidenceProperties();
1016 IEnumerable<MethodCompatibilityEvidence> evidence)
1018 ArgumentNullException.ThrowIfNull(
1021 var normalizedEvidence =
1022 new List<MethodCompatibilityEvidence>();
1027 if (criterion is
null)
1029 throw new ArgumentException(
1030 "The evidence collection cannot contain " +
1037 throw new ArgumentException(
1038 $
"Compatibility evidence " +
1039 $
"'{criterion.CriterionCode}' is invalid.",
1043 normalizedEvidence.Add(
1050 normalizedEvidence);
1052 NotifyEvidenceProperties();
1062 NotifyEvidenceProperties();
1073 IEnumerable<string> adaptations)
1075 ReplaceNormalizedStrings(
1078 nameof(adaptations));
1098 IEnumerable<string> warnings)
1100 ReplaceNormalizedStrings(
1134 criterion is not
null &&
1139 double totalWeight =
1140 weightedEvidence.Sum(
1144 if (totalWeight <= 0.0)
1149 double satisfiedWeight =
1158 double calculatedScore =
1176 double calculatedScore =
1182 return calculatedScore;
1207 double recommendedScoreThreshold = 0.85,
1208 bool updateEvaluationDate =
true)
1210 if (!
double.IsFinite(
1211 recommendedScoreThreshold) ||
1212 recommendedScoreThreshold < 0.0 ||
1213 recommendedScoreThreshold > 1.0)
1215 throw new ArgumentOutOfRangeException(
1216 nameof(recommendedScoreThreshold),
1217 recommendedScoreThreshold,
1218 "The recommended-score threshold must be " +
1219 "finite and lie between zero and one.");
1244 .PartiallyCompatible;
1247 recommendedScoreThreshold)
1261 if (updateEvaluationDate &&
1284 string currentFingerprint)
1287 string.IsNullOrWhiteSpace(
1288 currentFingerprint))
1293 return string.Equals(
1295 currentFingerprint.Trim(),
1296 StringComparison.Ordinal);
1330 NotifyEvidenceProperties();
1348 string scoreDescription =
1351 CultureInfo.InvariantCulture);
1353 string rankDescription =
1359 $
"{MethodCode} — {MethodName}; " +
1360 $
"{CompatibilityLevel}; " +
1361 $
"score {scoreDescription}" +
1365 private static string NormalizeCode(
1368 return string.IsNullOrWhiteSpace(value)
1370 : value.Trim().ToUpperInvariant();
1373 private static DateTime ConvertToUtc(
1376 return value.Kind
switch
1381 DateTimeKind.Local =>
1382 value.ToUniversalTime(),
1385 DateTime.SpecifyKind(
1391 private static void ReplaceNormalizedStrings(
1392 ICollection<string> destination,
1393 IEnumerable<string> source,
1394 string parameterName)
1396 ArgumentNullException.ThrowIfNull(
1400 string[] normalizedValues =
1404 !
string.IsNullOrWhiteSpace(
1410 StringComparer.OrdinalIgnoreCase)
1414 StringComparer.OrdinalIgnoreCase)
1417 destination.Clear();
1419 foreach (
string value
in normalizedValues)
1426 private void NotifyCompatibilityProperties()
1453 private void NotifyScopeProperties()
1471 private void NotifyEvidenceProperties()
Represents one piece of evidence used to evaluate the compatibility between a solution method and a l...
bool IsSatisfied
Gets or sets a value indicating whether the compatibility criterion is satisfied.
double Weight
Gets or sets the non-negative importance assigned to the criterion.
bool IsValidEvidence
Gets a value indicating whether this evidence contains the minimum information required for use by th...
Describes the applicability, capabilities and limitations of a solution method for lot-sizing problem...
string MethodCode
Gets or sets the stable code identifying the solution method.
SolutionMethodKind MethodKind
Gets or sets the general category of the solution method.
string Name
Gets or sets the human-readable name of the method.
string MethodVersion
Gets or sets the version of the method definition.
string ScopeDescription
Gets or sets a human-readable explanation of the applicable problem scope.
bool HasOptionalMismatches
Gets a value indicating whether at least one optional criterion is not satisfied.
string SupplyChainFingerprint
Gets or sets the fingerprint of the supply-chain data evaluated by the method advisor.
void ClearEvidence()
Removes all compatibility evidence.
List< MethodCompatibilityEvidence > Evidence
Gets the evidence used to evaluate the compatibility of the method.
List< string > RequiredAdaptations
Gets the adaptations required before the method can be applied.
bool HasMethodCode
Gets a value indicating whether a stable method code has been recorded.
bool HasRank
Gets a value indicating whether the recommendation has been ranked.
int OptionalMismatchCount
Gets the number of unsatisfied optional criteria.
bool HasScope
Gets a value indicating whether an applicable problem scope has been recorded.
string MethodVersion
Gets or sets the version of the evaluated method definition.
bool AppliesToCompleteProblem
Gets a value indicating whether the recommendation applies to the complete problem.
void ReplaceRequiredAdaptations(IEnumerable< string > adaptations)
Replaces the adaptations required before applying the method.
int SatisfiedEvidenceCount
Gets the number of satisfied compatibility criteria.
bool HasEvaluationDate
Gets a value indicating whether an evaluation date has been recorded.
int EvidenceCount
Gets the number of compatibility-evidence records.
SolutionMethodRecommendation(string methodCode, string methodName, SolutionMethodKind methodKind)
Initializes a recommendation for a solution method.
bool HasComment
Gets a value indicating whether an explanatory comment has been recorded.
int MismatchCount
Gets the number of unsatisfied compatibility criteria.
bool HasMethodName
Gets a value indicating whether a human-readable method name has been recorded.
bool RequiresAdaptation
Gets a value indicating whether decomposition, relaxation or another adaptation is necessary.
SolutionMethodKind MethodKind
Gets or sets the general category of the evaluated solution method.
string Summary
Gets or sets a concise human-readable summary of the recommendation.
bool IsValidRecommendation
Gets a value indicating whether the recommendation contains the minimum coherent information required...
MethodCompatibilityLevel UpdateCompatibilityFromEvidence(double recommendedScoreThreshold=0.85, bool updateEvaluationDate=true)
Determines the compatibility level from the current evidence, scope and score.
double Score
Gets or sets the normalized compatibility score.
string AdvisorVersion
Gets or sets the version of the method advisor used to produce the recommendation.
bool HasSummary
Gets a value indicating whether a human-readable summary has been recorded.
bool HasMethodVersion
Gets a value indicating whether a method version has been recorded.
void ReplaceWarnings(IEnumerable< string > warnings)
Replaces the warnings associated with this recommendation.
List< string > Warnings
Gets the non-fatal warnings produced during method evaluation.
bool HasEvidence
Gets a value indicating whether compatibility evidence has been recorded.
string MethodCatalogVersion
Gets or sets the version of the method catalog used during evaluation.
MethodCompatibilityLevel CompatibilityLevel
Gets or sets the evaluated compatibility level.
int? Rank
Gets or sets the rank assigned to the recommendation.
void ClearEvaluation()
Clears the evaluated compatibility while preserving the identity of the solution method.
bool HasMethodCatalogInformation
Gets a value indicating whether method-catalog information has been recorded.
double CalculateScore()
Calculates a normalized score from the current compatibility evidence.
void ReplaceEvidence(IEnumerable< MethodCompatibilityEvidence > evidence)
Replaces all compatibility-evidence records.
bool HasBlockingMismatches
Gets a value indicating whether at least one blocking incompatibility has been found.
string MethodCatalogName
Gets or sets the name of the method catalog used during evaluation.
string Comment
Gets or sets an optional explanatory comment.
bool HasAdvisorVersion
Gets a value indicating whether an advisor version has been recorded.
bool HasSupplyChainFingerprint
Gets a value indicating whether a supply-chain fingerprint has been recorded.
bool MatchesSupplyChainFingerprint(string currentFingerprint)
Determines whether the recommendation was produced for the supplied supply-chain fingerprint.
void AddEvidence(MethodCompatibilityEvidence evidence)
Adds one compatibility-evidence record.
bool IsIncompatible
Gets a value indicating whether the method is incompatible with the complete problem.
string MethodCode
Gets or sets the stable code identifying the evaluated solution method.
bool IsCompatible
Gets a value indicating whether the method is directly compatible.
bool IsRecommended
Gets a value indicating whether the method is recommended.
double UpdateScore()
Recalculates and stores the compatibility score.
bool CanSolveCompleteProblemDirectly
Gets a value indicating whether the method may be applied directly to the complete problem.
override string ToString()
bool HasScopeDescription
Gets a value indicating whether a human-readable scope description has been recorded.
DateTime? EvaluatedAtUtc
Gets or sets the UTC date and time at which the recommendation was evaluated.
SolutionMethodRecommendation(SolutionMethodDefinition methodDefinition)
Initializes a recommendation from a method definition.
bool HasBeenEvaluated
Gets a value indicating whether the method has been evaluated.
bool HasRequiredMismatches
Gets a value indicating whether at least one required compatibility criterion is not satisfied.
int RequiredMismatchCount
Gets the number of unsatisfied required criteria.
int BlockingMismatchCount
Gets the number of blocking incompatibilities.
bool HasWarnings
Gets a value indicating whether at least one warning has been recorded.
bool IsPartiallyCompatible
Gets a value indicating whether the method is only partially compatible.
SolutionMethodRecommendation()
Initializes an empty solution-method recommendation.
string MethodName
Gets or sets the human-readable name of the evaluated solution method.
ProblemClassificationScope Scope
Gets or sets the problem scope to which the method can be applied.
bool HasRequiredAdaptations
Gets a value indicating whether at least one adaptation is required before applying the method.
ProblemClassificationScope
Identifies the part of a lot-sizing instance to which a known-problem-family match applies.
MethodCompatibilityLevel
Indicates the compatibility level between a solution method and a lot-sizing problem instance.
@ Compatible
The method supports the complete problem instance and none of its hard assumptions are violated.