Hi all,
I’d like to be able to verify / list available linear solvers on any given machine before running a model. My stack is JuMP
and Ipopt
, which means I can do something like this:
import Ipopt;
import JuMP;
optimizer = JuMP.with_optimizer(Ipopt.Optimizer, linear_solver="ma97");
model = JuMP.Model(optimizer)
Here, optimizer
is of type JuMP.OptimizerFactory
, and seems to be lazily evaluated since at this point in time model
has no issues even if one types garbage into the linear_solver
string.
From my understanding, JuMP sends this factory info to Ipopt.jl, which uses MOI to then do a bunch of ccall
s to run everything once JuMP.optimize!(model)
is called, and not before.
By default Ipopt.jl packages the MUMPS linear solver, although there are more efficient ones out there: HSL MA97 as an example (as set in optimizer
above).
In my specific case, I want to be able to prioritize certain linear solvers over others, depending on solvers available on a users system. By default, Ipopt will use MA27 if it’s compiled with HSL, but I’m needing MA97 if available and would fall back to MUMPS if not.
The only ways I can find to check if MA97 is extant at the moment is to run JuMP.optimize!(model)
and wait for it to fail via the MOI ccall
attempt via addOption
at the JuMP level.
Which ultimately could be simplified to invoking something at the Ipopt.jl level by building some dummy IpoptProblem
and capture the error:
prob = Ipopt.createProblem(1,[1.],[1.],1,[1.],[1.],1,1,sum,sum,sum,sum);
try
Ipopt.addOption(prob, "linear_solver", "ma97")
println("HSL installed")
catch
println("Use MUMPS")
end
Is there a cleaner way to do this at all that I’ve just overlooked? This of course gets pretty messy if I want a list of installed solvers rather than just one check and a fallback.
Update: as a followup - I’ve realized this solution isn’t even enough. The addOption
call will pass so long as it is possible to be accepted in Ipopt’s settings here. For example, I don’t have “pardiso” installed, but I won’t receive an error at this point if I try to test with it. Thus I need to actually call Ipopt.solveProblem(prob)
as well and capture on that output instead.