Querying optimizer to set for another JuMP model

I have a question (probably very naive though) on how to query an optimizer used for a particular model, so that I can use it in another JuMP model. For example, suppose user decides to use GLPK for the first model as shown here:

using JuMP

model = Model(GLPK.Optimizer)
@variable(...)
...
optimize!(model)

Now, I want to run another model that needs to use the exact same solver as above and run my new_model as:

using JuMP

new_model = Model(query_solver(model)) #Madeup function query_solver(...)
@variable(...)
...
optimize!(new_model)

As far as I could look into the JuMP documentation, I could not find a function to retrieve the solver object. Is there something in MOI that I can probably use here? Or is there some other method I can use?
One possible way I can think is let user store the solver as solver = GLPK.Optimizer before the first model is run, and then simply use solver in my second model. However, I don’t want this solution. You can think of first model as an input to a package and second model as part of a package that solves a modification of model, i.e., new_model.

I believe there is some very standard way to do so in packages with dependency on JuMP; however, I am new to understanding the machinery behind it, so any help is appreciated. Thanks!

One possible way I can think is let user store the solver as solver = GLPK.Optimizer before the first model is run, and then simply use solver in my second model.

This is the recommended way, just ask the user for an optimizer.

OK. The reason I was looking for a different solution was because I thought the JuMP extension packages do it in a different (possibly a more programmatically right) way.

Can you give me an example (or even better refer to one) of how to query for the solver. I tried looking through packages such as StochasticPrograms.jl/SDDP.jl but could not find the exact location in the code where packages query the solver from the user.

Thanks a lot!

You can recover the name of the optimizer as a string using JuMP.solver_name(model).

Gets passed here:
https://github.com/odow/SDDP.jl/blob/26690765450df69d1b1f95886530ddbb8d37e43c/src/user_interface.jl#L620
Used here:
https://github.com/odow/SDDP.jl/blob/26690765450df69d1b1f95886530ddbb8d37e43c/src/user_interface.jl#L653
https://github.com/odow/SDDP.jl/blob/26690765450df69d1b1f95886530ddbb8d37e43c/src/user_interface.jl#L505-L524
Stored here:
https://github.com/odow/SDDP.jl/blob/26690765450df69d1b1f95886530ddbb8d37e43c/src/user_interface.jl#L409-L410

In general, you should write your extension to be agnostic of the solver. Allow the user to choose, don’t force them into something.

What type of extension are you trying to write?

This is amazing. Thank you so much for this.

That totally makes sense. I will keep this in mind.

I am trying to write a small solver that can possibly solve a two-stage stochastic program using decomposition techniques like Benders and/or column generation (I know packages like SDDP.jl already exist for this purpose). I am not aiming at writing a full extension right now, but mostly trying to automate my stuff and learn how these packages are build so that I can hopefully help write full fledged extensions (or contribute to the existing ones) in the future.

I am relatively new to Julia and building packages in particular and I sincerely appreciate the quick help and solution you guys provide here and on Julia slack. Surely want to leverage your experience. Thanks again!

solve a two-stage stochastic program using decomposition techniques like Benders and/or column generation

See also GitHub - atoptima/Coluna.jl: Branch-and-Price-and-Cut in Julia and related packages.

Another reference is
https://github.com/odow/StochOptFormat/blob/master/examples/lang-julia/TwoStageBenders.jl

I was not aware of this one. I will have a look at it. Thank you!

Is there a way I can directly convert this string object to the object I can feed to set_optimizer(model, solver), where for example, solver = GLPK.Optimizer.

I assume there are ways but probably it is not recommended to convert string to other data types? Correct me if I am wrong.

Is there a way I can directly convert this string object to the object I can feed to

No. Please don’t use the String approach. It’s led to problems when it has been tried before: Alpine checks solver name - Why? · Issue #178 · lanl-ansi/Alpine.jl · GitHub.

Yes, don’t rely on strings to match actual types or objects.

Makes sense. :+1:

Thanks for confirming :+1: