ULSAlgorithms 1.1.0-g3e5595996d
High-performance exact and heuristic algorithms for uncapacitated lot sizing
Loading...
Searching...
No Matches
SolverSelectionService.cs
Go to the documentation of this file.
2
3/// <summary>
4/// Selects a usable optimization solver by capability, machine availability,
5/// and deterministic priority.
6/// </summary>
7public sealed class SolverSelectionService
8{
9 /// <summary>
10 /// Selects an optimization-solver adapter.
11 /// </summary>
12 public async ValueTask<SolverSelectionResult> SelectAsync(
13 SolverKind requestedSolver,
14 SolverAdapterRegistry registry,
15 SolverSelectionOptions? options = null,
16 CancellationToken cancellationToken = default)
17 {
18 ArgumentNullException.ThrowIfNull(registry);
19
20 if (requestedSolver == SolverKind.Unknown)
21 {
22 return new SolverSelectionResult(
23 requestedSolver,
24 null,
25 null,
26 ["The requested solver cannot be Unknown."]);
27 }
28
29 options ??= new SolverSelectionOptions();
30 options.EnsureValid();
31
32 var diagnostics = new List<string>();
33 IReadOnlyList<SolverKind> order =
34 BuildSolverOrder(requestedSolver, options);
35
36 foreach (SolverKind solverKind in order)
37 {
38 cancellationToken.ThrowIfCancellationRequested();
39
40 IReadOnlyList<IOptimizationSolverAdapter> adapters =
41 registry.FindBySolverKind(solverKind);
42
43 if (adapters.Count == 0)
44 {
45 diagnostics.Add(
46 $"No registered adapter targets solver '{solverKind}'.");
47
48 if (requestedSolver != SolverKind.Automatic &&
49 options.RequireExactSolverKind)
50 {
51 break;
52 }
53
54 continue;
55 }
56
57 foreach (IOptimizationSolverAdapter adapter in adapters)
58 {
59 cancellationToken.ThrowIfCancellationRequested();
60
61 if (!SupportsRequiredCapabilities(
62 adapter,
63 options.RequiredCapabilities))
64 {
65 diagnostics.Add(
66 $"Adapter '{adapter.AdapterName}' does not support " +
67 "all required capabilities.");
68 continue;
69 }
70
71 SolverAvailabilityInfo availability =
72 await adapter.CheckAvailabilityAsync(cancellationToken);
73
74 if (availability.SolverKind != adapter.SolverKind)
75 {
76 diagnostics.Add(
77 $"Adapter '{adapter.AdapterName}' returned availability " +
78 $"for '{availability.SolverKind}' instead of " +
79 $"'{adapter.SolverKind}'.");
80 continue;
81 }
82
83 if (!IsAvailabilityAccepted(availability, options))
84 {
85 diagnostics.Add(
86 $"Adapter '{adapter.AdapterName}' is not usable. " +
87 $"Availability: {availability.Status}.");
88
89 foreach (string diagnostic in availability.Diagnostics)
90 {
91 diagnostics.Add(
92 $"{adapter.AdapterName}: {diagnostic}");
93 }
94
95 continue;
96 }
97
98 diagnostics.Add(
99 $"Adapter '{adapter.AdapterName}' was selected for " +
100 $"'{solverKind}'.");
101
102 return new SolverSelectionResult(
103 requestedSolver,
104 adapter,
105 availability,
106 diagnostics);
107 }
108
109 if (requestedSolver != SolverKind.Automatic &&
110 options.RequireExactSolverKind)
111 {
112 break;
113 }
114 }
115
116 diagnostics.Add("No suitable optimization solver could be selected.");
117
118 return new SolverSelectionResult(
119 requestedSolver,
120 null,
121 null,
122 diagnostics);
123 }
124
125 private static IReadOnlyList<SolverKind> BuildSolverOrder(
126 SolverKind requestedSolver,
128 {
129 if (requestedSolver == SolverKind.Automatic)
130 {
131 return options.SolverPriority.ToArray();
132 }
133
134 if (options.RequireExactSolverKind)
135 {
136 return [requestedSolver];
137 }
138
139 var order = new List<SolverKind> { requestedSolver };
140
141 foreach (SolverKind solverKind in options.SolverPriority)
142 {
143 if (!order.Contains(solverKind))
144 {
145 order.Add(solverKind);
146 }
147 }
148
149 return order;
150 }
151
152 private static bool SupportsRequiredCapabilities(
153 IOptimizationSolverAdapter adapter,
154 IEnumerable<SolverCapability> requiredCapabilities)
155 {
156 foreach (SolverCapability capability in requiredCapabilities)
157 {
158 if (!adapter.SupportsCapability(capability))
159 {
160 return false;
161 }
162 }
163
164 return true;
165 }
166
167 private static bool IsAvailabilityAccepted(
168 SolverAvailabilityInfo availability,
169 SolverSelectionOptions options)
170 {
171 if (availability.Status == SolverAvailabilityStatus.Available)
172 {
173 return true;
174 }
175
176 return options.AllowLimitedAvailability &&
177 availability.Status ==
178 SolverAvailabilityStatus.AvailableWithLimitations;
179 }
180}
Stores optimization-solver adapters and provides deterministic lookup by adapter identifier and solve...
Describes solver availability and the installation selected by an adapter.
SolverKind SolverKind
Gets the concrete solver kind.
IReadOnlyList< string > Diagnostics
Gets diagnostics produced during availability detection.
Configures automatic or explicit optimization-solver selection.
bool RequireExactSolverKind
Gets or sets whether an explicitly requested solver forbids fallback.
List< SolverKind > SolverPriority
Gets the priority used for SolverKind.Automatic. Earlier entries have higher priority.
Describes the outcome of optimization-solver selection.
Selects a usable optimization solver by capability, machine availability, and deterministic priority.
async ValueTask< SolverSelectionResult > SelectAsync(SolverKind requestedSolver, SolverAdapterRegistry registry, SolverSelectionOptions? options=null, CancellationToken cancellationToken=default)
Selects an optimization-solver adapter.
Defines the common metadata and availability contract implemented by every optimization-solver adapte...
SolverKind SolverKind
Gets the concrete solver targeted by this adapter.
ValueTask< SolverAvailabilityInfo > CheckAvailabilityAsync(CancellationToken cancellationToken=default)
Performs the adapter-specific machine discovery / load / license check.
SolverAvailabilityStatus
Describes whether a solver can currently be used on the current computer.
SolverCapability
Identifies an optional capability exposed by an optimization-solver adapter.
SolverKind
Identifies a mathematical optimization solver that can be used by solver-backed ULS algorithms.
Definition SolverKind.cs:15