Consistent way to suppress solver output

Is there a consistent way to suppress the solver output in JuMP v0.19 or MOI? It isn’t clear to me if there is.

Not really; it’s all handled through each individual solver’s options API. As a hack, I suppose you could use

redirect_stdout(devnull) do
    # code here
end

but that doesn’t remove the overhead of the solver printing status info (which may or may not be a problem).

devnull is of type IO not IOStream:

ERROR: MethodError: no method matching redirect_stderr(::Base.DevNull)
Closest candidates are:
  redirect_stderr() at stream.jl:1001
  redirect_stderr(::Union{IOStream, Base.LibuvStream}) at stream.jl:995
  redirect_stderr(::Function, ::Any) at stream.jl:1051

What’s the best way to convert from IO to IOStream?

The solution I ended up with was:
redirect_stdout((()->optimize!(model)),open("/dev/null", "w"))

3 Likes

Yep. Sorry, should have tested my code. Related issue: https://github.com/JuliaLang/julia/issues/22879.

Just came across this old problem. If you want to use parts of the output you can redirect stdout to a string:

function capture_stdout(f)
    stdout_orig = stdout
    (rd, wr) = redirect_stdout()
    f()
    close(wr)
    redirect_stdout(stdout_orig)
    read(rd, String)
end

s = capture_stdout() do
    optimize!(model)
end

#print the summary (which starts with "Number of Iterations")
try
    s[findlast("Number of Iterations", s)[1]:end] |> print
catch
    print(s)
end

EDIT:
Digged a bit further and found that most solvers support some kind of loglevel setting, e.g.:

  • Ipopt: “print_level”
  • Cbc: “LogLevel”
  • Clp: “logLevel”

These options can be set either when initialising the model, e.g.

model = Model(with_optimizer(Ipopt.Optimizer, tol = 1e-8, max_iter = 1000, print_level = 1))`

or afterwards using the MOI Api (which is currently not so nicely documented …)

MOI.set(model, MOI.RawParameter("print_level"), 1)
2 Likes

Is this a portable solution or it works only in Linux/Mac ?

Use set_silent:

model = Model(Ipopt.Optimizer)
set_silent(model)
3 Likes

Had some trouble with this where output was still printed.
It was due to the C level output not being flushed before the stdout gets restored.
So might be helpful to call :

Base.Libc.flush_cstdio()

Can use the following to print to a file as well :

open("/dev/null", "w") do f
    redirect_stdout(f) do
    # redirect_stdio(stdout=f,stderr=f) do
        optimize!(model)
        Base.Libc.flush_cstdio()
    end
end
1 Like