Cannot capture log with JuMP

I wanna capture CPLEX log in a file when it executes. However, when solving MIP instances the last bit of the log is never captured by redirect_stdout and redirect_stderr. I do not know the reason, I only know it happens every single time. So I decided to do an workaround, and use CPLEX.CPXsetlogfilename to set a filename where the log will be saved. But the problem is, I am reading the instances from an MPS, so I do not have direct_model available (please correct me if I am wrong, but it seems like read_from_file does not allow you to get a DIRECT mode model). So I need to get a Model with a CachingOptimizer and do:

model = JuMP.read_from_file(filepath) 
JuMP.set_optimizer(model, optimizer) 
for (name, value) in optimizer_conf 
    JuMP.set_optimizer_attribute(model, name, value) 
end 
relax && JuMP.relax_integrality(model) 
if optimizer === CPLEX.Optimizer 
    CPX_model = MOI.get(model, MOI.RawSolver()) 
    CPLEX.CPXsetlogfilename( 
      CPX_model.env, "./temporary_CPLEX_log.txt", "w+" 
    )   
end
...

But then I am greeted with the following error message:

ERROR: LoadError: JuMP.OptimizeNotCalled()
Stacktrace:
 [1] _moi_get_result(::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.AbstractOptimizer,MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}, ::MathOptInterface.RawSolver) at /home/henrique/.julia/packages/JuMP/y5vgk/src/JuMP.jl:944
 [2] get(::JuMP.Model, ::MathOptInterface.RawSolver) at /home/henrique/.julia/packages/JuMP/y5vgk/src/JuMP.jl:959
 [3] read_and_solve_file(::String, ::Type{T} where T, ::Array{Pair{String,Any},1}, ::IOStream; relax::Bool, close_delay::Float64) at /home/henrique/Aulas/doutorado/phd/scripts/read_and_solve_mps/script.jl:54
 [4] read_and_solve_file at /home/henrique/Aulas/doutorado/phd/scripts/read_and_solve_mps/script.jl:46 [inlined]

where the offending line is:

CPX_model = MOI.get(model, MOI.RawSolver()) 

So I cannot get the RawSolver (that I need to set the log filename) until I call optimize! but after calling optimize! the log was already written in stdout and it is too late to set the log filename.

1 Like

Use something like

function optimizer()
    model = CPLEX.Optimizer()
    CPXsetlogfilename(model.env, "./temporary_CPLEX_log.txt", "w+")
    return model
end

model = read_from_file(filepath)
set_optimizer(model, optimizer)
2 Likes

Thank your very much @odow, I will try that.

Unfortunately, the problem seem to come from CPLEX, because even in the logfile this last part of the log is not written but instead blurted in the terminal.

If someone is interested, my code with workaround is here.

Did you try Base.Libc.flush_cstdio() before exiting redirect_stdout?

2 Likes

Thank you very much. This seem to have fixed my problem (and this was a problem that bothered many times in the past). I tried using Base.flush in the past but now it seems clear why it did not work. Seems like CPLEX code does not call the C version of flush in their code before finishing, and the text is lost in a limbo, while Gurobi always flushes before returning.