Closed mlubin closed 7 years ago
My objections to option 2 could be alleviated by following a convention of putting
using JuMP, Clp
solver = ClpSolver()
at the top of each file so that it's easier to run the examples with a new solver.
I don't see the problem with Option 2. It's the most straightforward and transparent. Different solvers may have slightly different behaviors and I feel users should be aware of and actively make a decision about which solver to use. It's more verbose perhaps, but IMO less "ugly" than the other options.
The suggestion you just posted, Miles, is pretty much exactly what I was about to suggest.
Should we even allow not specifying a solver then?
I think it creates headaches (as we have seen with Pajarito a little). Keep things simple, always specify a solver.
I also vote for Option 2.
Disallowing a non-solver model creation could potentially affect JuMP extensions. In my Complementarity.jl
package, I create a JuMP Model()
without actually solving it. Can we do solver=nothing
?
@chkwon, good point. We can make it an error at solve time instead of when calling Model()
.
Personally I think the INFO message in option 1 will help obviate a lot of the potential confusion. Option 2 would be fine as well, but there's an elegance to Option 1 for teaching/workshops that I would miss.
Nobody besides me and @joehuchette seems to favor the magical option of picking a default solver based on which packages are loaded, so seems like option 2 is the winner.
What about
using JuMP, Clp
JuMP.adddefaultsolver!(ClpSolver())
# or
# JuMP.setdefaultsolvers!(ClpSolver())
m = Model()
@variable(m, x2)
@constraint(m, x == 1)
solve(m) # defaults to Clp
m2 = Model()
@variable(m2, x)
@nlconstraint(m2, exp(x) == 1)
solve(m2) # errors "No Non-Linear solver loaded as default"
using JuMP, Clp, Ipopt
JuMP.adddefaultsolver!(ClpSolver())
JuMP.adddefaultsolver!(IpoptSolver())
# or
# JuMP.setdefaultsolvers!(ClpSolver(), IpoptSolver())
m = Model()
@variable(m, x2)
@constraint(m, x == 1)
solve(m) # defaults to Clp
m2 = Model()
@variable(m2, x)
@nlconstraint(m2, exp(x) == 1)
solve(m2) # defaults to Ipopt
@odow, that's problematic because we don't have a great way to query the capabilities of a solver given a solver object.
We could have a global default but that doesn't seem much better than putting solver = ...
at the top of your file and using Model(solver=solver)
everywhere.
Well why not have a way to query solver capability? Ref https://github.com/JuliaOpt/JuMP.jl/issues/83
MathProgBase.supports(solver::AbstractMathProgBaseSolver)
# returns a subset of [:linear, :integer, :quadratic, :conic, :smooth, :nonconvex, :callbacks]
If you'd like to lead that effort, I'd support it :)
Implementation at https://github.com/JuliaOpt/JuMP.jl/pull/970
Ok, time to figure out the user-facing side of default solvers. As of https://github.com/JuliaOpt/JuMP.jl/pull/959, we have the following significant changes:
The question is, how do we present example code now?
will no longer work. Some options are:
Option 1:
Option 2:
This is the most similar to "production" code but feels a bit ugly to me. It's potentially annoying that you'd have to install Clp or modify the code (digging through it to find all uses of
ClpSolver()
) to run examples.Option 3:
Should we even have a
loaddefaultsolvers
method?Relevant prior discussion at https://github.com/JuliaOpt/MathProgBase.jl/pull/150.
CC @odow @chriscoey @blegat @chkwon