Suppress license output from solver in JuMP.Model

using JuMP, Gurobi
m = Model(solver=GurobiSolver(OutputFlag=0))

I have a program where the second line gets called frequently.
Every time it does, this gets printed to stdout:

Academic license - for non-commercial use only

How can I suppress this notice?

In an old version of the JuMP FAQ it is suggested to use

    TT = stdout
    redirect_stdout()
    m = Model(solver=GurobiSolver(OutputFlag = 0))
    redirect_stdout(TT)

But I didn’t find this to work – perhaps it is outdated?

You can try Suppressor.jl. But a better option might be to talk to the package authors and ask them to remove or add an option to remove the message. See this issue for a similar situation, and interesting discussion around it.

This message is coming from Gurobi itself though, not the Julia wrapper. I don’t think Gurobi-the-company is going to be receptive to a request to remove the message, and there might be license issues with having the Julia wrapper suppress the message by default.

1 Like

As others have mentioned, the message comes from Gurobi when getting the Gurobi environment. The solution is to get the environment just once, and then re-use that environment:

julia> gurobi_env = Gurobi.Env()
Academic license - for non-commercial use only
Gurobi.Env(Ptr{Nothing} @0x000000002cd049f0)

julia> m = Model(with_optimizer(Gurobi.Optimizer, gurobi_env))
A JuMP Model
Feasibility problem with:
Variables: 0
Model mode: AUTOMATIC
CachingOptimizer state: EMPTY_OPTIMIZER
Solver name: Gurobi

julia> m = Model(with_optimizer(Gurobi.Optimizer, gurobi_env))
A JuMP Model
Feasibility problem with:
Variables: 0
Model mode: AUTOMATIC
CachingOptimizer state: EMPTY_OPTIMIZER
Solver name: Gurobi

Notice that each model creation doesn’t trigger a printed warning about the academic license.

3 Likes

Doesn’t this solution require one to pass along gurobi_env to any called functions that are going to solve an optimization problem? That seems pretty undesirable.

Isn’t there a way to just capture and dispose of the message? The solutions with redirect_stdout that were suggested for previous versions of JuMP are what I want – they just don’t seem to work anymore.

Doesn’t this solution require one to pass along gurobi_env to any called functions that are going to solve an optimization problem? That seems pretty undesirable.

Make a global constant.

const GUROBI_ENV = Gurobi.Env()

function solve_model()
    model = Model(with_optimizer(Gurobi.Optimizer, GUROBI_ENV))
end

Isn’t there a way to just capture and dispose of the message?

No. As already stated, this is coming from Gurobi itself. The wrapper won’t provide a mechanism to suppress this.

5 Likes

Yes. As already stated, you should be able to do this with Suppressor.jl. (But a single global environment sounds like a more proper solution.)

The global constant solution works well for my purposes. Thanks.

I was able to get this to work well in JuMP 18.5 using the following syntax:

genv = Gurobi.Env()
m = Model(solver=GurobiSolver(OutputFlag = 0, genv))

However, in JuMP 19 it seems like the way to reuse the environment has changed?
I tried this syntax given by @evanfields:

gurobi_env = Gurobi.Env()
m = Model(with_optimizer(Gurobi.Optimizer, gurobi_env))

and I get this output:

julia> gurobi_env = Gurobi.Env()
Academic license - for non-commercial use only
Gurobi.Env(Ptr{Nothing} @0x000000000342c2d0)

julia> m = Model(with_optimizer(Gurobi.Optimizer, gurobi_env))
ERROR: Gurobi.Optimizer does not have any method with arguments (Gurobi.Env(Ptr{Nothing} @0x000000000342c2d0),).The first argument of `with_optimizer` should be callable with the other argument of `with_optimizer`.
Stacktrace:
 [1] error(::String, ::String, ::String) at ./error.jl:42
 [2] #with_optimizer#1(::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}, ::Function, ::Type, ::Gurobi.Env) at /home/at/.julia/packages/JuMP/jnmGG/src/JuMP.jl:108
 [3] with_optimizer(::Type, ::Gurobi.Env) at /home/at/.julia/packages/JuMP/jnmGG/src/JuMP.jl:107
 [4] top-level scope at none:0

Can someone explain to me what the correct syntax for this is now?

EDIT: The problem was I needed to update Gurobi.jl from 0.5.9 to 0.6.0. After doing that the syntax given by @evanfields works.

In case anyone else comes across this:

with_optimizer(Gurobi.Optimizer, GUROBI_ENV)

is now

optimizer_with_attributes(() -> Gurobi.Optimizer(GUROBI_ENV))
3 Likes

This doesn’t work with the new JuMP v0.21.5. I’m getting the following error. Any ideas?

The provided `optimizer_constructor` is invalid. It must be callable with zero arguments. For example, "Ipopt.Optimizer" or "() -> ECOS.Optimizer()". It should not be an instantiated optimizer like "Ipopt.Optimizer()" or "ECOS.Optimizer()". (Note the difference in parentheses!)
using JuMP, Gurobi
const GRB_ENV = Gurobi.Env()
model = Model(() -> Gurobi.Optimizer(GRB_ENV))
1 Like

After many months in which this solution worked for me, I’m now having a weird (maybe Revise-related?) issue reusing an environment inside a package. I opened an issue at Gurobi.jl where I describe my problem in more detail. Would really appreciate any thoughts!

I’ve replied to the issue.

1 Like