LotSizingDataModel.Solution 2.0.1
Solution objects for production, setup, inventory and related decisions.
Loading...
Searching...
No Matches
SolutionScientificProvenanceCodec.cs
Go to the documentation of this file.
1using System.Globalization;
4
6
7/// <summary>
8/// Stores and reads scientific provenance through the existing serializable
9/// <see cref="SolutionGenerationMetadata.Parameters"/> collection.
10/// </summary>
12{
13 public const string ParameterPrefix =
14 "lsdm.scientific.";
15
16 public const string SchemaVersionParameter =
17 ParameterPrefix + "schemaVersion";
18
19 public const string NotationSchemeIdParameter =
20 ParameterPrefix + "notationSchemeId";
21
22 public const string NotationSchemeVersionParameter =
23 ParameterPrefix + "notationSchemeVersion";
24
25 public const string DetectedNotationParameter =
26 ParameterPrefix + "detectedNotation";
27
28 public const string ProblemClassCodeParameter =
29 ParameterPrefix + "problemClassCode";
30
31 public const string ProblemClassMatchKindParameter =
32 ParameterPrefix + "problemClassMatchKind";
33
34 public const string FormulationIdParameter =
35 ParameterPrefix + "formulationId";
36
37 public const string FormulationFamilyParameter =
38 ParameterPrefix + "formulationFamily";
39
41 ParameterPrefix + "formulationCompatibility";
42
43 public const string SolutionMethodIdParameter =
44 ParameterPrefix + "solutionMethodId";
45
46 public const string SolutionMethodCategoryParameter =
47 ParameterPrefix + "solutionMethodCategory";
48
49 public const string SolverBackendKindParameter =
50 ParameterPrefix + "solverBackendKind";
51
52 public const string CapturedAtUtcParameter =
53 ParameterPrefix + "capturedAtUtc";
54
72
73 public static bool IsReservedParameterName(
74 string name)
75 {
76 if (string.IsNullOrWhiteSpace(name))
77 {
78 return false;
79 }
80
81 return ReservedParameterNames.Contains(
82 name.Trim(),
83 StringComparer.OrdinalIgnoreCase);
84 }
85
86 public static void Write(
89 {
90 ArgumentNullException.ThrowIfNull(metadata);
91 ArgumentNullException.ThrowIfNull(provenance);
92
93 if (!provenance.IsStructurallyComplete)
94 {
95 throw new ArgumentException(
96 "Scientific provenance is structurally incomplete.",
97 nameof(provenance));
98 }
99
100 if (
101 !provenance.SchemaVersion.Equals(
103 StringComparison.Ordinal) &&
104 !provenance.SchemaVersion.Equals(
106 StringComparison.Ordinal))
107 {
108 throw new NotSupportedException(
109 $"Scientific provenance schema " +
110 $"'{provenance.SchemaVersion}' is not supported for writing.");
111 }
112
113 Set(metadata, SchemaVersionParameter, provenance.SchemaVersion);
114 Set(metadata, NotationSchemeIdParameter, provenance.NotationSchemeId);
115 Set(
116 metadata,
118 provenance.NotationSchemeVersion);
119 Set(metadata, DetectedNotationParameter, provenance.DetectedNotation);
120 Set(
121 metadata,
123 provenance.CanonicalProblemClassCode);
124 Set(
125 metadata,
127 provenance.ProblemClassMatchKind);
128 Set(metadata, FormulationIdParameter, provenance.FormulationId);
129 Set(
130 metadata,
132 provenance.FormulationFamily);
133 Set(
134 metadata,
137
138 if (
139 provenance.SchemaVersion.Equals(
141 StringComparison.Ordinal))
142 {
143 Set(
144 metadata,
146 provenance.SolutionMethodId);
147
148 Set(
149 metadata,
151 provenance.SolutionMethodCategory);
152
153 Set(
154 metadata,
156 provenance.SolverBackendKind);
157 }
158 else
159 {
163 }
164
165 Set(
166 metadata,
168 provenance.CapturedAtUtc
169 .ToUniversalTime()
170 .ToString(
171 "O",
172 CultureInfo.InvariantCulture));
173 }
174
177 {
178 ArgumentNullException.ThrowIfNull(metadata);
179
180 bool hasAny =
181 metadata.Parameters.Any(
182 parameter =>
183 parameter.Name.StartsWith(
185 StringComparison.OrdinalIgnoreCase));
186
187 if (!hasAny)
188 {
191 provenance: null,
192 diagnostic:
193 "No LotSizingDataModel scientific provenance is recorded.");
194 }
195
196 string? schema =
197 Get(metadata, SchemaVersionParameter);
198
199 if (string.IsNullOrWhiteSpace(schema))
200 {
201 return Invalid(
202 "Scientific provenance is missing schemaVersion.");
203 }
204
205 if (
206 !schema.Equals(
208 StringComparison.Ordinal) &&
209 !schema.Equals(
211 StringComparison.Ordinal))
212 {
213 return Invalid(
214 $"Unsupported scientific provenance schema '{schema}'.");
215 }
216
217 string? capturedText =
218 Get(metadata, CapturedAtUtcParameter);
219
220 if (
221 string.IsNullOrWhiteSpace(capturedText) ||
222 !DateTime.TryParse(
223 capturedText,
224 CultureInfo.InvariantCulture,
225 DateTimeStyles.RoundtripKind,
226 out DateTime capturedAtUtc))
227 {
228 return Invalid(
229 "Scientific provenance contains an invalid capturedAtUtc.");
230 }
231
232 var provenance =
234 {
235 SchemaVersion = schema,
236 NotationSchemeId =
237 Get(metadata, NotationSchemeIdParameter) ??
238 string.Empty,
239 NotationSchemeVersion =
240 Get(metadata, NotationSchemeVersionParameter) ??
241 string.Empty,
242 DetectedNotation =
243 Get(metadata, DetectedNotationParameter) ??
244 string.Empty,
245 CanonicalProblemClassCode =
246 Get(metadata, ProblemClassCodeParameter) ??
247 string.Empty,
248 ProblemClassMatchKind =
249 Get(metadata, ProblemClassMatchKindParameter) ??
250 string.Empty,
251 FormulationId =
252 Get(metadata, FormulationIdParameter) ??
253 string.Empty,
254 FormulationFamily =
255 Get(metadata, FormulationFamilyParameter) ??
256 string.Empty,
257 FormulationScientificCompatibility =
258 Get(metadata, FormulationCompatibilityParameter) ??
259 string.Empty,
260 SolutionMethodId =
261 Get(metadata, SolutionMethodIdParameter) ??
262 string.Empty,
263 SolutionMethodCategory =
264 Get(metadata, SolutionMethodCategoryParameter) ??
265 string.Empty,
266 SolverBackendKind =
267 Get(metadata, SolverBackendKindParameter) ??
268 string.Empty,
269 CapturedAtUtc =
270 capturedAtUtc.ToUniversalTime()
271 };
272
273 if (!provenance.IsStructurallyComplete)
274 {
275 return Invalid(
276 "Scientific provenance is structurally incomplete.");
277 }
278
281 provenance,
282 diagnostic: string.Empty);
283 }
284
285 public static bool Clear(
287 {
288 ArgumentNullException.ThrowIfNull(metadata);
289
290 bool removedAny = false;
291
292 foreach (
293 string parameterName
295 {
296 removedAny =
297 metadata.RemoveParameter(parameterName) ||
298 removedAny;
299 }
300
301 return removedAny;
302 }
303
304 private static void Set(
306 string name,
307 string value)
308 {
309 metadata.SetParameter(
311 name,
312 value ?? string.Empty,
313 "LotSizingDataModel scientific solution provenance."));
314 }
315
316 private static string? Get(
318 string name) =>
319 metadata.FindParameter(name)?.Value;
320
321 private static SolutionScientificProvenanceReadResult Invalid(
322 string diagnostic) =>
323 new(
325 provenance: null,
326 diagnostic);
327}
Represents one named parameter used by a solution-generation method.
string Value
Gets or sets the serialized parameter value.
static AlgorithmParameter FromString(string name, string value, string description="")
Creates a string algorithm parameter.
Stores and reads scientific provenance through the existing serializable SolutionGenerationMetadata....
static void Write(SolutionGenerationMetadata metadata, SolutionScientificProvenance provenance)
static SolutionScientificProvenanceReadResult Read(SolutionGenerationMetadata metadata)
Dependency-neutral scientific provenance snapshot for one generated lot-sizing solution.
AlgorithmParameter? FindParameter(string name)
Finds an algorithm parameter by name.
bool RemoveParameter(string name)
Removes an algorithm parameter by name.
void SetParameter(AlgorithmParameter parameter)
Adds or replaces an algorithm parameter.
List< AlgorithmParameter > Parameters
Gets the parameters used by the algorithm, solver or solution-generation method.