Skip to content

Commit 596f20c

Browse files
authored
Use callback instead of logs to grep informations (#138)
* Use callback instead of logs to grep informations * Update runtests.jl * Update runtests.jl
1 parent baa3feb commit 596f20c

File tree

2 files changed

+12
-56
lines changed

2 files changed

+12
-56
lines changed

src/NLPModelsIpopt.jl

Lines changed: 10 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -273,17 +273,8 @@ function SolverCore.solve!(
273273
end
274274

275275
# pass options to IPOPT
276-
# make sure IPOPT logs to file so we can grep time, residuals and number of iterations
277-
ipopt_log_to_file = false
278-
ipopt_file_log_level = 3
279-
local ipopt_log_file
280276
for (k, v) in kwargs
281-
if k == :output_file
282-
ipopt_log_file = v
283-
ipopt_log_to_file = true
284-
elseif k == :file_print_level
285-
ipopt_file_log_level = v
286-
elseif typeof(v) <: Integer
277+
if typeof(v) <: Integer
287278
AddIpoptIntOption(problem, string(k), v)
288279
elseif typeof(v) <: Real
289280
AddIpoptNumOption(problem, string(k), v)
@@ -298,22 +289,15 @@ function SolverCore.solve!(
298289
AddIpoptNumOption(problem, "obj_scaling_factor", -1.0)
299290
end
300291

301-
if ipopt_log_to_file
302-
0 < ipopt_file_log_level < 3 && @warn(
303-
"`file_print_level` should be 0 or ≥ 3 for IPOPT to report elapsed time, final residuals and number of iterations"
304-
)
305-
else
306-
# log to file anyways to parse the output
307-
ipopt_log_file = tempname()
308-
# make sure the user didn't specify a file log level without a file name
309-
0 < ipopt_file_log_level < 3 && (ipopt_file_log_level = 3)
310-
end
311-
312-
AddIpoptStrOption(problem, "output_file", ipopt_log_file)
313-
AddIpoptIntOption(problem, "file_print_level", ipopt_file_log_level)
314-
315292
# Callback
316-
SetIntermediateCallback(problem, callback)
293+
function solver_callback(
294+
alg_mod, iter_count, obj_value, inf_pr, inf_du, mu, d_norm, regularization_size, alpha_du, alpha_pr, ls_trials, args...; stats = stats
295+
)
296+
set_residuals!(stats, inf_pr, inf_du)
297+
set_iter!(stats, Int(iter_count))
298+
return callback(alg_mod, iter_count, obj_value, inf_pr, inf_du, mu, d_norm, regularization_size, alpha_du, alpha_pr, ls_trials, args...)
299+
end
300+
SetIntermediateCallback(problem, solver_callback)
317301

318302
real_time = time()
319303
status = IpoptSolve(problem)
@@ -327,35 +311,7 @@ function SolverCore.solve!(
327311
set_bounds_multipliers!(stats, problem.mult_x_L, problem.mult_x_U)
328312
end
329313
set_solver_specific!(stats, :internal_msg, ipopt_internal_statuses[status])
330-
set_solver_specific!(stats, :real_time, real_time)
331-
332-
try
333-
ipopt_output = readlines(ipopt_log_file)
334-
335-
Δt = 0.0
336-
dual_feas = primal_feas = Inf
337-
iter = -1
338-
for line in ipopt_output
339-
if occursin("Total seconds", line)
340-
Δt += Meta.parse(split(line, "=")[2])
341-
elseif occursin("Dual infeasibility", line)
342-
dual_feas = Meta.parse(split(line)[4])
343-
elseif occursin("Constraint violation", line)
344-
primal_feas = Meta.parse(split(line)[4])
345-
elseif occursin("Number of Iterations....", line)
346-
iter = Meta.parse(split(line)[4])
347-
end
348-
end
349-
set_residuals!(stats, primal_feas, dual_feas)
350-
set_iter!(stats, iter)
351-
set_time!(stats, Δt)
352-
catch e
353-
@warn("could not parse Ipopt log file. $e")
354-
stats.primal_residual_reliable = false
355-
stats.dual_residual_reliable = false
356-
stats.iter_reliable = false
357-
stats.time_reliable = false
358-
end
314+
set_time!(stats, real_time)
359315

360316
stats
361317
end

test/runtests.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ end
104104
@test isapprox(stats.multipliers_U, -ones(1), rtol = 1e-6)
105105
@test stats.status == :first_order
106106
@test stats.elapsed_time > 0
107-
@test stats.iter == 5
107+
@test stats.iter in [4; 5]
108108
@test stats.primal_feas 0.0
109109
@test stats.dual_feas 0.0 atol = 1.49e-8
110110
end
@@ -131,7 +131,7 @@ end
131131

132132
# Change initial guess and reset solver
133133
nlp.meta.x0 .= 2.0
134-
reset!(solver)
134+
SolverCore.reset!(solver)
135135

136136
# Solve again with new initial guess
137137
stats = solve!(solver, nlp, stats, print_level = 0)

0 commit comments

Comments
 (0)