ULSAlgorithms 1.1.0-g3e5595996d
High-performance exact and heuristic algorithms for uncapacitated lot sizing
Loading...
Searching...
No Matches
LinearVariableValueNormalizer.cs
Go to the documentation of this file.
2
4
5/// <summary>
6/// Normalizes raw mathematical-variable values returned by optimization
7/// solvers before independent validation, objective reconstruction and ULS
8/// solution mapping.
9/// </summary>
10/// <remarks>
11/// <para>
12/// Solver values are floating-point values and can contain harmless numerical
13/// residuals such as -5E-9 or 180.00000000000006.
14/// </para>
15/// <para>
16/// This class deliberately follows the same numerical-cleanup policy and
17/// default tolerances as LotSizingDataModel's
18/// MathematicalVariableValueNormalizer.
19/// </para>
20/// <para>
21/// Materially fractional or materially negative values are never silently
22/// repaired.
23/// </para>
24/// </remarks>
26{
27 /// <summary>
28 /// Default absolute tolerance used to identify numerical zero.
29 /// </summary>
30 public const double DefaultZeroTolerance =
31 1.0e-8;
32 /// <summary>
33 /// Historical public default absolute tolerance used for integer-domain
34 /// variables.
35 /// </summary>
36 /// <remarks>
37 /// This value is retained for 1.x public-API compatibility.
38 /// Solver-backed execution uses
39 /// <see cref="SolverIntegralityTolerance"/> by default.
40 /// </remarks>
41 public const double DefaultIntegralityTolerance =
42 1.0e-7;
43
44 /// <summary>
45 /// Default integrality tolerance used when normalizing values returned by
46 /// external mathematical-programming solvers.
47 /// </summary>
48 /// <remarks>
49 /// The wider tolerance accommodates harmless solver residuals while the
50 /// normalized solution remains subject to independent model-feasibility
51 /// validation.
52 /// </remarks>
53 public const double SolverIntegralityTolerance =
54 1.0e-5;
55
56 /// <summary>
57 /// Default absolute tolerance used to clean continuous values that are
58 /// numerically indistinguishable from an integer.
59 /// </summary>
60 public const double DefaultNearIntegerTolerance =
61 1.0e-8;
62
63 /// <summary>Initializes the normalizer with repository defaults.</summary>
71
72 /// <summary>Initializes the normalizer with explicit tolerances.</summary>
74 double zeroTolerance,
75 double integralityTolerance,
76 double nearIntegerTolerance)
77 {
78 ValidateTolerance(
79 zeroTolerance,
80 nameof(zeroTolerance));
81
82 ValidateTolerance(
83 integralityTolerance,
84 nameof(integralityTolerance));
85
86 ValidateTolerance(
87 nearIntegerTolerance,
88 nameof(nearIntegerTolerance));
89
91 zeroTolerance;
92
94 integralityTolerance;
95
97 nearIntegerTolerance;
98 }
99
100 /// <summary>Gets the zero tolerance.</summary>
101 public double ZeroTolerance { get; }
102
103 /// <summary>Gets the integrality tolerance.</summary>
104 public double IntegralityTolerance { get; }
105
106 /// <summary>Gets the near-integer tolerance for continuous values.</summary>
107 public double NearIntegerTolerance { get; }
108
109 /// <summary>
110 /// Normalizes one raw solver value according to the variable domain.
111 /// </summary>
112 public double Normalize(
113 LinearVariable variable,
114 double rawValue)
115 {
116 ArgumentNullException.ThrowIfNull(
117 variable);
118
119 if (!double.IsFinite(rawValue))
120 {
121 throw new ArgumentOutOfRangeException(
122 nameof(rawValue),
123 rawValue,
124 "A solver variable value must be finite.");
125 }
126
127 if (Math.Abs(rawValue) <=
129 {
130 return 0.0;
131 }
132
133 return variable.Type switch
134 {
136 NormalizeBinary(
137 rawValue),
138
140 NormalizeInteger(
141 rawValue),
142
144 NormalizeContinuous(
145 rawValue),
146
147 _ =>
148 NormalizeContinuous(
149 rawValue)
150 };
151 }
152
153 private double NormalizeBinary(
154 double rawValue)
155 {
156 // A binary value is solver-reported floating-point data. Normalize
157 // symmetrically around both admissible integer values using the
158 // configured integrality tolerance. The normalized solution is then
159 // independently checked against every model constraint.
160 if (Math.Abs(rawValue) <=
162 {
163 return 0.0;
164 }
165
166 if (Math.Abs(
167 rawValue - 1.0) <=
169 {
170 return 1.0;
171 }
172
173 throw new InvalidOperationException(
174 $"Binary solver value '{rawValue:G17}' is not within " +
175 $"the configured integrality tolerance " +
176 $"'{IntegralityTolerance:G17}' of 0 or 1.");
177 }
178 private double NormalizeInteger(
179 double rawValue)
180 {
181 double nearestInteger =
182 Math.Round(
183 rawValue,
184 MidpointRounding.AwayFromZero);
185
186 return Math.Abs(
187 rawValue -
188 nearestInteger) <=
190 ? nearestInteger
191 : rawValue;
192 }
193
194 private double NormalizeContinuous(
195 double rawValue)
196 {
197 double nearestInteger =
198 Math.Round(
199 rawValue,
200 MidpointRounding.AwayFromZero);
201
202 return Math.Abs(
203 rawValue -
204 nearestInteger) <=
206 ? nearestInteger
207 : rawValue;
208 }
209
210 private static void ValidateTolerance(
211 double tolerance,
212 string parameterName)
213 {
214 if (!double.IsFinite(tolerance) ||
215 tolerance < 0.0)
216 {
217 throw new ArgumentOutOfRangeException(
218 parameterName,
219 tolerance,
220 "A numerical tolerance must be finite and non-negative.");
221 }
222 }
223}
224
225
226
LinearVariableValueNormalizer()
Initializes the normalizer with repository defaults.
double NearIntegerTolerance
Gets the near-integer tolerance for continuous values.
const double DefaultIntegralityTolerance
Historical public default absolute tolerance used for integer-domain variables.
const double DefaultNearIntegerTolerance
Default absolute tolerance used to clean continuous values that are numerically indistinguishable fro...
LinearVariableValueNormalizer(double zeroTolerance, double integralityTolerance, double nearIntegerTolerance)
Initializes the normalizer with explicit tolerances.
const double DefaultZeroTolerance
Default absolute tolerance used to identify numerical zero.
const double SolverIntegralityTolerance
Default integrality tolerance used when normalizing values returned by external mathematical-programm...
double Normalize(LinearVariable variable, double rawValue)
Normalizes one raw solver value according to the variable domain.
Describes one variable in a portable linear mathematical model.
@ Binary
A binary variable restricted to zero or one.