LotSizingDataModel.Solver 2.0.1
Solver-independent modeling, execution, monitoring and adapter infrastructure.
Loading...
Searching...
No Matches
NamedSolutionValueParser.cs
Go to the documentation of this file.
1using System.Globalization;
2using System.Text.RegularExpressions;
3
5
6/// <summary>
7/// Parses variable values from solver text files when variables use the
8/// portable <c>v_&lt;id&gt;</c> naming convention.
9/// </summary>
10public static partial class NamedSolutionValueParser
11{
12 /// <summary>
13 /// Parses all recognized variable/value pairs from a solution file.
14 /// </summary>
15 /// <param name="path">Solution-file path.</param>
16 /// <returns>Variable values keyed by mathematical variable identifier.</returns>
17 public static IReadOnlyDictionary<int, double> ParseFile(
18 string path)
19 {
20 if (string.IsNullOrWhiteSpace(path) ||
21 !File.Exists(path))
22 {
23 return new Dictionary<int, double>();
24 }
25
26 return ParseLines(
27 File.ReadLines(path));
28 }
29
30 /// <summary>
31 /// Parses recognized variable/value pairs from text lines.
32 /// </summary>
33 /// <param name="lines">Solution text lines.</param>
34 /// <returns>Variable values keyed by mathematical variable identifier.</returns>
35 public static IReadOnlyDictionary<int, double> ParseLines(
36 IEnumerable<string> lines)
37 {
38 ArgumentNullException.ThrowIfNull(lines);
39
40 var values =
41 new Dictionary<int, double>();
42
43 foreach (string line in lines)
44 {
45 if (string.IsNullOrWhiteSpace(line))
46 {
47 continue;
48 }
49
50 Match match =
51 VariableNameRegex().Match(line);
52
53 if (!match.Success ||
54 !int.TryParse(
55 match.Groups[1].Value,
56 NumberStyles.Integer,
57 CultureInfo.InvariantCulture,
58 out int variableId))
59 {
60 continue;
61 }
62
63 string suffix =
64 line[(match.Index + match.Length)..];
65
66 Match numberMatch =
67 NumberRegex().Match(suffix);
68
69 if (!numberMatch.Success ||
70 !double.TryParse(
71 numberMatch.Value,
72 NumberStyles.Float,
73 CultureInfo.InvariantCulture,
74 out double value) ||
75 !double.IsFinite(value))
76 {
77 continue;
78 }
79
80 values[variableId] =
81 value;
82 }
83
84 return values;
85 }
86
87 /// <summary>
88 /// Tries to parse the first floating-point number captured after a supplied
89 /// regular-expression prefix.
90 /// </summary>
91 /// <param name="text">Text to inspect.</param>
92 /// <param name="prefixPattern">Case-insensitive regular-expression prefix.</param>
93 /// <param name="value">Parsed finite value.</param>
94 /// <returns><see langword="true"/> when a value was found.</returns>
95 public static bool TryParseNumberAfter(
96 string text,
97 string prefixPattern,
98 out double value)
99 {
100 value =
101 default;
102
103 if (string.IsNullOrWhiteSpace(text) ||
104 string.IsNullOrWhiteSpace(prefixPattern))
105 {
106 return false;
107 }
108
109 Match match =
110 Regex.Match(
111 text,
112 prefixPattern +
113 @"\s*(?<value>[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?)",
114 RegexOptions.IgnoreCase |
115 RegexOptions.CultureInvariant);
116
117 return match.Success &&
118 double.TryParse(
119 match.Groups["value"].Value,
120 NumberStyles.Float,
121 CultureInfo.InvariantCulture,
122 out value) &&
123 double.IsFinite(value);
124 }
125
126 [GeneratedRegex(@"\bv_(\d+)\b", RegexOptions.CultureInvariant)]
127 private static partial Regex VariableNameRegex();
128
129 [GeneratedRegex(@"[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?", RegexOptions.CultureInvariant)]
130 private static partial Regex NumberRegex();
131}
Parses variable values from solver text files when variables use the portable v_<id> naming conventio...
static IReadOnlyDictionary< int, double > ParseFile(string path)
Parses all recognized variable/value pairs from a solution file.
static bool TryParseNumberAfter(string text, string prefixPattern, out double value)
Tries to parse the first floating-point number captured after a supplied regular-expression prefix.
static IReadOnlyDictionary< int, double > ParseLines(IEnumerable< string > lines)
Parses recognized variable/value pairs from text lines.