ULSAlgorithms 1.1.0-g3e5595996d
High-performance exact and heuristic algorithms for uncapacitated lot sizing
Loading...
Searching...
No Matches
CplexSolverAdapter.cs
Go to the documentation of this file.
1using System.Reflection;
2using System.Runtime.Loader;
3
5
6/// <summary>
7/// Detects and validates an optional IBM ILOG CPLEX installation.
8/// </summary>
9/// <remarks>
10/// The managed CPLEX assemblies are loaded dynamically so ULSAlgorithms keeps
11/// no compile-time dependency on IBM binaries.
12/// </remarks>
13public sealed class CplexSolverAdapter :
15{
16 private static readonly object RuntimeGate = new();
17
18 /// <summary>Initializes the CPLEX adapter.</summary>
30
31 /// <inheritdoc />
32 public override string AdapterId =>
33 "ULSAlgorithms.Solver.Cplex";
34
35 /// <inheritdoc />
36 public override string AdapterName =>
37 "ULSAlgorithms CPLEX Adapter";
38
39 /// <inheritdoc />
40 public override SolverKind SolverKind =>
41 SolverKind.Cplex;
42
43 /// <inheritdoc />
44 public override ValueTask<SolverAvailabilityInfo>
46 CancellationToken cancellationToken = default)
47 {
48 cancellationToken.ThrowIfCancellationRequested();
49
52
53 if (discovery.Installation is null)
54 {
55 return ValueTask.FromResult(
57 SolverKind.Cplex,
58 SolverAvailabilityStatus.NotInstalled,
59 solverName: "IBM ILOG CPLEX",
60 diagnostics: discovery.Diagnostics));
61 }
62
63 lock (RuntimeGate)
64 {
65 cancellationToken.ThrowIfCancellationRequested();
66
67 CplexInstallationInfo installation =
68 discovery.Installation;
69
70 string oldPath =
71 Environment.GetEnvironmentVariable("PATH") ??
72 string.Empty;
73
74 try
75 {
76 PrependPath(
77 installation.RuntimeDirectory,
78 oldPath);
79
80 LoadAssemblyIfNeeded(
81 "ILOG.Concert",
82 installation.ConcertAssemblyPath);
83
84 Assembly cplexAssembly =
85 LoadAssemblyIfNeeded(
86 "ILOG.CPLEX",
87 installation.CplexAssemblyPath);
88
89 Type cplexType =
90 cplexAssembly.GetType(
91 "ILOG.CPLEX.Cplex",
92 throwOnError: true,
93 ignoreCase: false)!;
94
95 object? cplex =
96 Activator.CreateInstance(cplexType);
97
98 if (cplex is null)
99 {
100 throw new InvalidOperationException(
101 "ILOG.CPLEX.Cplex could not be instantiated.");
102 }
103
104 try
105 {
106 string version =
107 cplexType
108 .GetProperty(
109 "Version",
110 BindingFlags.Instance |
111 BindingFlags.Public)?
112 .GetValue(cplex)?
113 .ToString() ??
114 string.Empty;
115
116 var diagnostics =
117 discovery.Diagnostics
118 .Concat(
119 [
120 "The ILOG.Concert and ILOG.CPLEX managed " +
121 "assemblies were loaded successfully.",
122 "ILOG.CPLEX.Cplex was instantiated successfully."
123 ])
124 .ToArray();
125
126 return ValueTask.FromResult(
128 SolverKind.Cplex,
129 SolverAvailabilityStatus.Available,
130 solverName: "IBM ILOG CPLEX",
131 solverVersion: version,
132 installationPath:
133 installation.RootDirectory,
134 managedAssemblyPath:
135 installation.CplexAssemblyPath,
136 nativeLibraryPath:
137 installation.RuntimeDirectory,
138 licenseInformation:
139 "CPLEX environment creation succeeded.",
140 diagnostics: diagnostics));
141 }
142 finally
143 {
144 cplexType
145 .GetMethod(
146 "End",
147 BindingFlags.Instance |
148 BindingFlags.Public,
149 binder: null,
150 types: Type.EmptyTypes,
151 modifiers: null)?
152 .Invoke(
153 cplex,
154 null);
155 }
156 }
157 catch (Exception exception)
158 {
159 Exception effective =
160 Unwrap(exception);
161
162 return ValueTask.FromResult(
164 SolverKind.Cplex,
165 ClassifyFailure(effective),
166 solverName: "IBM ILOG CPLEX",
167 installationPath:
168 discovery.Installation.RootDirectory,
169 managedAssemblyPath:
170 discovery.Installation.CplexAssemblyPath,
171 nativeLibraryPath:
172 discovery.Installation.RuntimeDirectory,
173 diagnostics:
174 discovery.Diagnostics.Concat(
175 [
176 effective.Message
177 ])));
178 }
179 finally
180 {
181 Environment.SetEnvironmentVariable(
182 "PATH",
183 oldPath);
184 }
185 }
186 }
187
188 private static Assembly LoadAssemblyIfNeeded(
189 string simpleName,
190 string path)
191 {
192 Assembly? loaded =
193 AppDomain.CurrentDomain
194 .GetAssemblies()
195 .FirstOrDefault(
196 assembly =>
197 string.Equals(
198 assembly.GetName().Name,
199 simpleName,
200 StringComparison.OrdinalIgnoreCase));
201
202 return loaded ??
203 AssemblyLoadContext.Default.LoadFromAssemblyPath(
204 Path.GetFullPath(path));
205 }
206
207 private static void PrependPath(
208 string directory,
209 string currentPath)
210 {
211 string updated =
212 string.IsNullOrWhiteSpace(currentPath)
213 ? directory
214 : directory +
215 Path.PathSeparator +
216 currentPath;
217
218 Environment.SetEnvironmentVariable(
219 "PATH",
220 updated);
221 }
222}
CplexInstallationInfo? Installation
Gets the selected compatible installation.
Locates compatible IBM ILOG CPLEX installations without a compile-time reference to ILOG....
static CplexInstallationDiscoveryResult Discover()
Finds the newest compatible CPLEX installation visible to the process.
override string AdapterId
Gets the stable adapter identifier.
override ValueTask< SolverAvailabilityInfo > CheckAvailabilityAsync(CancellationToken cancellationToken=default)
Performs the adapter-specific machine discovery / load / license check.
override SolverKind SolverKind
Gets the concrete solver targeted by this adapter.
override string AdapterName
Gets the adapter display name.
static Exception Unwrap(Exception exception)
Unwraps reflection invocation exceptions.
static SolverAvailabilityStatus ClassifyFailure(Exception exception)
Maps an exception to a stable availability state.
OptimizationSolverAdapterBase(params SolverCapability[] capabilities)
Initializes an adapter with its supported capabilities.
Describes solver availability and the installation selected by an adapter.
record CplexInstallationInfo(string VersionFamily, string RootDirectory, string RuntimeDirectory, string ConcertAssemblyPath, string CplexAssemblyPath, string DiscoverySource)
Describes one compatible IBM ILOG CPLEX installation.
SolverAvailabilityStatus
Describes whether a solver can currently be used on the current computer.
SolverCapability
Identifies an optional capability exposed by an optimization-solver adapter.
@ LinearProgramming
Continuous linear programming.
@ OptimalityGapReporting
Best-bound and optimality-gap reporting.
@ MixedIntegerLinearProgramming
Mixed-integer linear programming.
@ SearchStatistics
Search-node and iteration statistics.