LotSizingDataModel.Solver 2.0.1
Solver-independent modeling, execution, monitoring and adapter infrastructure.
Loading...
Searching...
No Matches
LotSizingExactRepairMatheuristicDomain.cs
Go to the documentation of this file.
3using MetaheuristicsPlatform.Core;
4using MetaheuristicsPlatform.Matheuristics;
5using MetaheuristicsPlatform.Random;
6
8
10 IExactRepairMatheuristicDomain
11{
12 private readonly MathematicalModel _sourceModel;
13 private readonly MathematicalVariable[] _variables;
14 private readonly MathematicalModelCandidateEvaluator _evaluator;
16 private readonly MatheuristicModelSolveDelegate _exactSolver;
17 private readonly MatheuristicModelSolveDelegate _relaxationSolver;
18 private readonly MatheuristicPoint _initialPoint;
19 private readonly MatheuristicVariableKind[] _variableKinds;
20 private readonly double _feasibilityTolerance;
21
23 MathematicalModel sourceModel,
24 IReadOnlyDictionary<int, double> initialValuesByVariableId,
26 MatheuristicModelSolveDelegate relaxationSolver,
27 double feasibilityTolerance = 1.0e-6)
28 {
29 ArgumentNullException.ThrowIfNull(
30 sourceModel);
31
32 ArgumentNullException.ThrowIfNull(
33 initialValuesByVariableId);
34
35 _exactSolver =
36 exactSolver ??
37 throw new ArgumentNullException(
38 nameof(exactSolver));
39
40 _relaxationSolver =
41 relaxationSolver ??
42 throw new ArgumentNullException(
43 nameof(relaxationSolver));
44
45 if (!double.IsFinite(
46 feasibilityTolerance) ||
47 feasibilityTolerance < 0.0)
48 {
49 throw new ArgumentOutOfRangeException(
50 nameof(feasibilityTolerance));
51 }
52
53 sourceModel.EnsureValid();
54
55 _sourceModel =
56 sourceModel;
57
58 _variables =
59 sourceModel.Variables
60 .OrderBy(
61 variable =>
62 variable.Id)
63 .ToArray();
64
65 _variableKinds =
66 _variables
67 .Select(
68 GetVariableKind)
69 .ToArray();
70
71 _evaluator =
73 sourceModel);
74
75 _builder =
77
78 _feasibilityTolerance =
79 feasibilityTolerance;
80
81 double[] initialValues =
82 CreateCompleteValues(
83 initialValuesByVariableId);
84
85 if (!_evaluator.IsFeasible(
86 initialValues,
87 feasibilityTolerance))
88 {
89 throw new InvalidOperationException(
90 "The exact-repair initial point must be feasible for the source mathematical model.");
91 }
92
93 _initialPoint =
94 new MatheuristicPoint(
95 initialValues,
96 _evaluator.EvaluateObjective(
97 initialValues),
98 isIntegerFeasible:
99 true);
100 }
101
102 public OptimizationSense Sense =>
103 _sourceModel.Objective.Sense switch
104 {
106 OptimizationSense.Minimize,
107
109 OptimizationSense.Maximize,
110
111 _ =>
112 throw new NotSupportedException(
113 $"Objective sense '{_sourceModel.Objective.Sense}' is not supported by the exact-repair bridge.")
114 };
115
116 public IReadOnlyList<MatheuristicVariableKind>
118 _variableKinds;
119
120 public MatheuristicPoint CreateInitial(
121 IRandomSource random)
122 {
123 ArgumentNullException.ThrowIfNull(
124 random);
125
126 return new MatheuristicPoint(
127 _initialPoint.Values,
128 _initialPoint.Objective,
129 _initialPoint.IsIntegerFeasible,
130 _initialPoint.ReducedCosts);
131 }
132
133 public double Evaluate(
134 IReadOnlyList<double> values)
135 {
136 return _evaluator.EvaluateObjective(
137 values);
138 }
139
140 public bool IsIntegerFeasible(
141 IReadOnlyList<double> values)
142 {
143 return _evaluator.IsIntegerFeasible(
144 values,
145 _feasibilityTolerance);
146 }
147
148 public MatheuristicSolveResult SolveRelaxation(
149 ExactRepairRequest request,
150 CancellationToken cancellationToken)
151 {
152 MathematicalModel subproblem =
153 _builder.BuildRelaxation(
154 _sourceModel,
155 request);
156
157 return SolveSubproblem(
158 subproblem,
159 request.NodeLimit,
160 _relaxationSolver,
161 requireIntegerFeasible:
162 false,
163 cancellationToken);
164 }
165
166 public MatheuristicSolveResult SolveExact(
167 ExactRepairRequest request,
168 CancellationToken cancellationToken)
169 {
170 MathematicalModel subproblem =
171 _builder.BuildExact(
172 _sourceModel,
173 request);
174
175 return SolveSubproblem(
176 subproblem,
177 request.NodeLimit,
178 _exactSolver,
179 requireIntegerFeasible:
180 true,
181 cancellationToken);
182 }
183
184 private MatheuristicSolveResult SolveSubproblem(
185 MathematicalModel subproblem,
186 int nodeLimit,
188 bool requireIntegerFeasible,
189 CancellationToken cancellationToken)
190 {
191 MathematicalModelSolveResult solveResult =
192 solver(
193 subproblem,
194 nodeLimit,
195 cancellationToken);
196
197 ArgumentNullException.ThrowIfNull(
198 solveResult);
199
200 if (!solveResult.HasFeasibleSolution)
201 {
202 return MatheuristicSolveResult.NoSolution(
203 exploredNodes:
204 ConvertExploredNodes(
205 solveResult.ExploredNodeCount));
206 }
207
208 var subproblemEvaluator =
209 new MathematicalModelCandidateEvaluator(
210 subproblem);
211
212 double[] values =
213 subproblemEvaluator.ExtractCompleteValues(
214 solveResult);
215
216 if (!subproblemEvaluator.IsConstraintFeasible(
217 values,
218 _feasibilityTolerance))
219 {
220 throw new InvalidOperationException(
221 "Exact-repair solve delegate returned a point infeasible for its generated subproblem.");
222 }
223
224 bool integerFeasible =
225 _evaluator.IsIntegerFeasible(
226 values,
227 _feasibilityTolerance);
228
229 if (requireIntegerFeasible &&
230 !integerFeasible)
231 {
232 throw new InvalidOperationException(
233 "Exact-repair solve delegate returned a non-integral exact point.");
234 }
235
236 var point =
237 new MatheuristicPoint(
238 values,
239 _evaluator.EvaluateObjective(
240 values),
241 integerFeasible);
242
243 return MatheuristicSolveResult.FromPoint(
244 point,
245 exploredNodes:
246 ConvertExploredNodes(
247 solveResult.ExploredNodeCount));
248 }
249
250 private double[] CreateCompleteValues(
251 IReadOnlyDictionary<int, double> valuesByVariableId)
252 {
253 var values =
254 new double[_variables.Length];
255
256 for (int index = 0;
257 index < _variables.Length;
258 index++)
259 {
260 MathematicalVariable variable =
261 _variables[index];
262
263 if (!valuesByVariableId.TryGetValue(
264 variable.Id,
265 out double value))
266 {
267 throw new InvalidOperationException(
268 $"Initial point is missing variable identifier '{variable.Id}'.");
269 }
270
271 if (!double.IsFinite(
272 value))
273 {
274 throw new InvalidOperationException(
275 $"Initial value for variable '{variable.Name}' is not finite.");
276 }
277
278 values[index] =
279 value;
280 }
281
282 return values;
283 }
284
285 private static MatheuristicVariableKind
286 GetVariableKind(
287 MathematicalVariable variable)
288 {
289 return variable.VariableType switch
290 {
291 MathematicalVariableType.Continuous =>
292 MatheuristicVariableKind.Continuous,
293
294 MathematicalVariableType.Integer =>
295 MatheuristicVariableKind.Integer,
296
297 MathematicalVariableType.Binary =>
298 MatheuristicVariableKind.Binary,
299
300 _ =>
301 throw new NotSupportedException(
302 $"Variable type '{variable.VariableType}' is outside the alpha.37 exact-repair bridge.")
303 };
304 }
305
306 private static int ConvertExploredNodes(
307 long? exploredNodes)
308 {
309 if (!exploredNodes.HasValue)
310 {
311 return 0;
312 }
313
314 if (exploredNodes.Value <
315 0 ||
316 exploredNodes.Value >
317 int.MaxValue)
318 {
319 throw new InvalidOperationException(
320 "Exact-repair explored-node count is outside the supported range.");
321 }
322
323 return (int)exploredNodes.Value;
324 }
325}
MatheuristicSolveResult SolveExact(ExactRepairRequest request, CancellationToken cancellationToken)
LotSizingExactRepairMatheuristicDomain(MathematicalModel sourceModel, IReadOnlyDictionary< int, double > initialValuesByVariableId, MatheuristicModelSolveDelegate exactSolver, MatheuristicModelSolveDelegate relaxationSolver, double feasibilityTolerance=1.0e-6)
MatheuristicSolveResult SolveRelaxation(ExactRepairRequest request, CancellationToken cancellationToken)
Stores the solver result for a solver-independent mathematical model.
long? ExploredNodeCount
Gets or sets the number of explored branch-and-bound nodes, when available.
bool HasFeasibleSolution
Gets or sets a value indicating whether the solver produced at least one feasible solution.
Represents a solver-independent mathematical optimization model.
void EnsureValid()
Validates the complete mathematical model.
Represents one decision variable in a mathematical optimization model.
int Id
Gets or sets the unique variable identifier within the mathematical model.
delegate MathematicalModelSolveResult MatheuristicModelSolveDelegate(MathematicalModel model, int nodeLimit, CancellationToken cancellationToken)
@ Maximize
The objective value must be maximized.
@ Minimize
The objective value must be minimized.