LotSizingDataModel.Solver 2.0.1
Solver-independent modeling, execution, monitoring and adapter infrastructure.
Loading...
Searching...
No Matches
MathematicalModelSolverAdapterBase.cs
Go to the documentation of this file.
1using System;
2using System.Threading;
3using System.Threading.Tasks;
7
9
10/// <summary>
11/// Provides common execution-state and cancellation handling for
12/// solver adapters that solve solver-independent mathematical
13/// models.
14/// </summary>
17{
18 private readonly object _syncRoot =
19 new();
20
21 private CancellationTokenSource? _activeSolveCancellationSource;
22
23 private bool _isRunning;
24
25 /// <summary>
26 /// Gets the solver kind.
27 /// </summary>
28 public abstract SolverKind SolverKind
29 {
30 get;
31 }
32
33 /// <summary>
34 /// Gets the solver name.
35 /// </summary>
36 public abstract string SolverName
37 {
38 get;
39 }
40
41 /// <summary>
42 /// Gets the solver version when available.
43 /// </summary>
44 public abstract string SolverVersion
45 {
46 get;
47 }
48
49 /// <summary>
50 /// Gets a value indicating whether a solve operation is
51 /// currently running.
52 /// </summary>
53 public bool IsRunning
54 {
55 get
56 {
57 lock (_syncRoot)
58 {
59 return _isRunning;
60 }
61 }
62 }
63
64 /// <summary>
65 /// Solves a solver-independent mathematical model.
66 /// </summary>
67 /// <param name="request">
68 /// Mathematical-model solve request.
69 /// </param>
70 /// <param name="cancellationToken">
71 /// Token used to cancel the solve operation.
72 /// </param>
73 /// <returns>
74 /// Task returning the generic mathematical-model solve
75 /// result.
76 /// </returns>
77 /// <exception cref="ArgumentNullException">
78 /// Thrown when <paramref name="request"/> is
79 /// <see langword="null"/>.
80 /// </exception>
81 /// <exception cref="InvalidOperationException">
82 /// Thrown when another solve operation is already running.
83 /// </exception>
84 public async ValueTask<MathematicalModelSolveResult> SolveAsync(
86 CancellationToken cancellationToken = default)
87 {
88 ArgumentNullException.ThrowIfNull(
89 request);
90
91 request.EnsureValid();
92
93 CancellationTokenSource linkedCancellationSource =
94 BeginSolve(
95 cancellationToken);
96
97 try
98 {
100 await SolveCoreAsync(
101 request,
102 linkedCancellationSource.Token);
103
104 ArgumentNullException.ThrowIfNull(
105 result);
106
108 request,
109 result);
110
111 result.EnsureValid();
112
113 return result;
114 }
115 finally
116 {
117 EndSolve(
118 linkedCancellationSource);
119 }
120 }
121
122 /// <summary>
123 /// Requests interruption of the currently running solve
124 /// operation.
125 /// </summary>
126 public void RequestStop()
127 {
128 CancellationTokenSource? cancellationSource;
129
130 lock (_syncRoot)
131 {
132 cancellationSource =
133 _activeSolveCancellationSource;
134 }
135
136 if (cancellationSource is null)
137 {
138 return;
139 }
140
141 try
142 {
143 cancellationSource.Cancel();
144 }
145 catch (ObjectDisposedException)
146 {
147 // The solve operation completed concurrently.
148 }
149
151 }
152
153 /// <summary>
154 /// Performs the solver-specific translation and solve.
155 /// </summary>
156 /// <param name="request">
157 /// Validated mathematical-model solve request.
158 /// </param>
159 /// <param name="cancellationToken">
160 /// Token used to cancel the native solve operation.
161 /// </param>
162 /// <returns>
163 /// Task returning the solver result.
164 /// </returns>
165 protected abstract ValueTask<MathematicalModelSolveResult>
168 CancellationToken cancellationToken);
169
170 /// <summary>
171 /// Requests interruption through the native solver API.
172 /// </summary>
173 /// <remarks>
174 /// Derived adapters should override this method when the
175 /// native solver exposes an explicit interruption mechanism.
176 /// </remarks>
177 protected virtual void RequestNativeStop()
178 {
179 }
180
181 /// <summary>
182 /// Completes generic result metadata when it was not supplied
183 /// by the native adapter.
184 /// </summary>
185 /// <param name="request">
186 /// Source solve request.
187 /// </param>
188 /// <param name="result">
189 /// Solver result to complete.
190 /// </param>
191 protected virtual void CompleteResultMetadata(
194 {
195 if (string.IsNullOrWhiteSpace(
196 result.RunName))
197 {
198 result.RunName =
199 request.RunName;
200 }
201
202 if (string.IsNullOrWhiteSpace(
203 result.FormulationId))
204 {
205 result.FormulationId =
206 request.FormulationId;
207 }
208
209 if (result.SolverKind ==
210 SolverKind.Unknown)
211 {
212 result.SolverKind =
214 }
215
216 if (string.IsNullOrWhiteSpace(
217 result.SolverName))
218 {
219 result.SolverName =
221 }
222
223 if (string.IsNullOrWhiteSpace(
224 result.SolverVersion))
225 {
226 result.SolverVersion =
228 }
229 }
230
231 private CancellationTokenSource BeginSolve(
232 CancellationToken cancellationToken)
233 {
234 lock (_syncRoot)
235 {
236 if (_isRunning)
237 {
238 throw new InvalidOperationException(
239 $"Solver '{SolverName}' is already running.");
240 }
241
242 var linkedCancellationSource =
243 CancellationTokenSource.CreateLinkedTokenSource(
244 cancellationToken);
245
246 _activeSolveCancellationSource =
247 linkedCancellationSource;
248
249 _isRunning =
250 true;
251
252 return linkedCancellationSource;
253 }
254 }
255
256 private void EndSolve(
257 CancellationTokenSource cancellationSource)
258 {
259 lock (_syncRoot)
260 {
261 if (ReferenceEquals(
262 _activeSolveCancellationSource,
263 cancellationSource))
264 {
265 _activeSolveCancellationSource =
266 null;
267
268 _isRunning =
269 false;
270 }
271 }
272
273 cancellationSource.Dispose();
274 }
275}
Provides common execution-state and cancellation handling for solver adapters that solve solver-indep...
bool IsRunning
Gets a value indicating whether a solve operation is currently running.
virtual void CompleteResultMetadata(MathematicalModelSolveRequest request, MathematicalModelSolveResult result)
Completes generic result metadata when it was not supplied by the native adapter.
void RequestStop()
Requests interruption of the currently running solve operation.
virtual void RequestNativeStop()
Requests interruption through the native solver API.
ValueTask< MathematicalModelSolveResult > SolveCoreAsync(MathematicalModelSolveRequest request, CancellationToken cancellationToken)
Performs the solver-specific translation and solve.
async ValueTask< MathematicalModelSolveResult > SolveAsync(MathematicalModelSolveRequest request, CancellationToken cancellationToken=default)
Solves a solver-independent mathematical model.
Describes a request to solve an already built, solver-independent mathematical model.
string FormulationId
Gets or sets the identifier of the formulation that generated the mathematical model.
void EnsureValid()
Validates the mathematical-model solve request.
Stores the solver result for a solver-independent mathematical model.
void EnsureValid()
Validates the mathematical-model solve result.
string FormulationId
Gets or sets the identifier of the formulation that generated the mathematical model.
Defines a solver adapter capable of solving an already built, solver-independent mathematical model.