Open stumarcus314 opened 1 month ago
Based on the README for Ipopt, it looks like it should be possible as of Julia v1.9. We're still in the process of updating our overall documentation---we'll look into this as well to make sure it works as intended and update accordingly.
How would one set the IPOPT linear solver to SPRAL? Based on the IPOPT subsolver code in EAGO.jl (https://github.com/PSORLab/EAGO.jl/blob/master/src/subsolvers/ipopt.jl), the following attempt does not work.
using IntervalArithmetic; setrounding(Interval, :accurate) using EAGO, COPT eago_factory = () -> EAGO.Optimizer(SubSolvers(; r = COPT.Optimizer())) model = Model(eago_factory) MOI.set(model, MOI.RawOptimizerAttribute("linear_solver"), "spral") # Try to set IPOPT's linear solver to SPRAL. MOI.set(model, MOI.RawOptimizerAttribute("spral_use_gpu"), "yes") # Run SPRAL on the GPU.
$ julia create_model.jl Number of pulses: 256. Cardinal Optimizer v7.1.3. Build date Apr 29 2024 Copyright Cardinal Operations 2024. All Rights Reserved ERROR: LoadError: type Optimizer has no field linear_solver Stacktrace: [1] set(m::Optimizer{EAGO.Incremental{COPT.Optimizer}, EAGO.Incremental{Ipopt.Optimizer}, EAGO.DefaultExt}, p::MathOptInterface.RawOptimizerAttribute, x::String) @ EAGO ~/.julia/packages/EAGO/7BNFB/src/eago_optimizer/moi_wrapper.jl:212 [2] set @ ~/.julia/packages/MathOptInterface/2CULs/src/Bridges/bridge_optimizer.jl:955 [inlined] [3] set(model::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Bridges.LazyBridgeOptimizer{Optimizer{EAGO.Incremental{COPT.Optimizer}, EAGO.Incremental{Ipopt.Optimizer}, EAGO.DefaultExt}}, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}, attr::MathOptInterface.RawOptimizerAttribute, value::String) @ MathOptInterface.Utilities ~/.julia/packages/MathOptInterface/2CULs/src/Utilities/cachingoptimizer.jl:1059 [4] set(m::Model, attr::MathOptInterface.RawOptimizerAttribute, value::String) @ JuMP ~/.julia/packages/JuMP/Gwn88/src/optimizer_interface.jl:794 [5] macro expansion @ ~/julia_code/Gen7_BPM/create_model.jl:156 [inlined] [6] top-level scope @ ./timing.jl:395 in expression starting at /home/stuart/julia_code/Gen7_BPM/create_model.jl:85
EAGO sets subsolver parameters in two ways. The first is by overloading set_default_config!
where the m
field is the subsolver whose properties you are trying to set. The src/subsolvers/ipopt.jl
file is an example of this: when EAGO solves upper problems, the settings in ipopt.jl
are the settings that get passed to IPOPT. If you want to change the default parameters for IPOPT using this method, you would need to overload the set_default_config!
function from ipopt.jl
to reflect the different parameters you want.
The second way EAGO sets subsolver parameters is by setting the EAGOParameter
called "user_solver_config"
to true
, and then setting parameters using MOI.set
with the subsolver as the object. You need to set "user_solver_config" => true
, or else your settings will be overwritten by set_default_config!
when the subsolver is used. For your case, it might look something like this:
using IntervalArithmetic; setrounding(Interval, :accurate)
using JuMP, EAGO # (and COPT, if you want that as the subsolver)
eago_factory = () -> EAGO.Optimizer(SubSolvers())
model = Model(optimizer_with_attributes(eago_factory, "user_solver_config" => true))
upper_optimizer = model.moi_backend.optimizer.model.subsolver_block.upper_optimizer.optimizer.model
MOI.set(upper_optimizer, MOI.RawOptimizerAttribute("linear_solver"), "spral") # Try to set IPOPT's linear solver to SPRAL.
MOI.set(upper_optimizer, MOI.RawOptimizerAttribute("spral_use_gpu"), "yes") # Run SPRAL on the GPU.
#[variables/constraints/objective]
optimize!(model)
Thanks for the advice. I have used the second method. In the second method, are the default parameters (such as "tol" and "constr_viol_tol") set in src/subsolvers/ipopt.jl used by IPOPT, if those parameters are not set in upper_optimizer by MOI.set? That is, are the upper_optimizer parameters set after first calling set_default_config!?
The default parameters in set_default_config!
are only used if "user_solver_config"
is set to false
(which is the default). If you want parameters such as tol
to be set, and you have "user_solver_config" => true
, you'll need to set those yourself as well.
If I modify the file ~/.julia/packages/EAGO/7BNFB/src/subsolvers/ipopt.jl in my Julia installation, will those changes be reflected when I use EAGO.jl to solve a JuMP model? Does the input parameter local_solver to the function set_default_config! equal true?
If you're looking to change the default behavior of EAGO, it's probably a better idea to create your own fork of EAGO and modify/use that. If you're only making changes for solving individual optimization problems, you should use one of the methods I described earlier to change subsolver parameters without changing the default EAGO operation.
The input parameter local_solver
is there to indicate whether the settings are being used for a relaxed optimizer (local_solver=false
) or upper optimizer (local_solver=true
). IPOPT is the default upper optimizer, so the version of set_default_config!
in src/subsolvers/ipopt.jl
will typically be called with local_solver=true
.
There is some advice here for improving the performance of the version of IPOPT used by EAGO by compiling an optimized version of IPOPT. https://psorlab.github.io/EAGO.jl/dev/optimizer/high_performance/#Ipopt-Build
Rather than compiling a new version of IPOPT, is it possible to instead improve the peformance of IPOPT in EAGO, by using set_attribute to select the linear solver, as described here? https://github.com/jump-dev/Ipopt.jl?tab=readme-ov-file#linear-solvers
Is it possible to select MKL instead of OpenBLAS for the BLAS & LAPACK backend library used by IPOPT and the linear solvers in EAGO by using the code below before creating the EAGO model? https://github.com/jump-dev/Ipopt.jl?tab=readme-ov-file#blas-and-lapack using MKL # Replace OpenBLAS by Intel MKL using Ipopt using EAGO model = Model(EAGO.Optimizer)