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!

1 Like

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.

2 Likes

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.

1 Like

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.

1 Like

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

1 Like

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.

1 Like

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

2 Likes

Makes sense. :+1:

Thanks for confirming :+1:

1 Like