Skip to content

Commit ac2a7ff

Browse files
authored
Add more tests and robust file check (#127)
* Add more tests and robust file check * loose
1 parent 4748679 commit ac2a7ff

File tree

2 files changed

+58
-22
lines changed

2 files changed

+58
-22
lines changed

src/NLPModelsIpopt.jl

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -239,35 +239,45 @@ function SolverCore.solve!(
239239
real_time = time()
240240
status = IpoptSolve(problem)
241241
real_time = time() - real_time
242-
ipopt_output = readlines(ipopt_log_file)
243-
244-
Δt = 0.0
245-
dual_feas = primal_feas = Inf
246-
iter = -1
247-
for line in ipopt_output
248-
if occursin("Total seconds", line)
249-
Δt += Meta.parse(split(line, "=")[2])
250-
elseif occursin("Dual infeasibility", line)
251-
dual_feas = Meta.parse(split(line)[4])
252-
elseif occursin("Constraint violation", line)
253-
primal_feas = Meta.parse(split(line)[4])
254-
elseif occursin("Number of Iterations....", line)
255-
iter = Meta.parse(split(line)[4])
256-
end
257-
end
258242

259243
set_status!(stats, get(ipopt_statuses, status, :unknown))
260244
set_solution!(stats, problem.x)
261245
set_objective!(stats, problem.obj_val)
262-
set_residuals!(stats, primal_feas, dual_feas)
263-
set_iter!(stats, iter)
264-
set_time!(stats, Δt)
265246
set_constraint_multipliers!(stats, problem.mult_g)
266247
if has_bounds(nlp)
267248
set_bounds_multipliers!(stats, problem.mult_x_L, problem.mult_x_U)
268249
end
269250
set_solver_specific!(stats, :internal_msg, Ipopt._STATUS_CODES[status])
270251
set_solver_specific!(stats, :real_time, real_time)
252+
253+
try
254+
ipopt_output = readlines(ipopt_log_file)
255+
256+
Δt = 0.0
257+
dual_feas = primal_feas = Inf
258+
iter = -1
259+
for line in ipopt_output
260+
if occursin("Total seconds", line)
261+
Δt += Meta.parse(split(line, "=")[2])
262+
elseif occursin("Dual infeasibility", line)
263+
dual_feas = Meta.parse(split(line)[4])
264+
elseif occursin("Constraint violation", line)
265+
primal_feas = Meta.parse(split(line)[4])
266+
elseif occursin("Number of Iterations....", line)
267+
iter = Meta.parse(split(line)[4])
268+
end
269+
end
270+
set_residuals!(stats, primal_feas, dual_feas)
271+
set_iter!(stats, iter)
272+
set_time!(stats, Δt)
273+
catch e
274+
@warn("could not parse Ipopt log file. $e")
275+
stats.primal_residual_reliable = false
276+
stats.dual_residual_reliable = false
277+
stats.iter_reliable = false
278+
stats.time_reliable = false
279+
end
280+
271281
stats
272282
end
273283

test/runtests.jl

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,50 @@ using ADNLPModels, NLPModelsIpopt, NLPModels, Ipopt, SolverCore, Test
77
stats = solve!(solver, nlp, stats, print_level = 0)
88
@test isapprox(stats.solution, [1.0; 1.0], rtol = 1e-6)
99
@test stats.status == :first_order
10+
@test stats.iter == 21
11+
@test stats.elapsed_time > 0
12+
@test stats.primal_feas 0.0
13+
@test stats.dual_feas 0.0 atol = 1.49e-8
14+
1015
nlp = ADNLPModel(x -> (x[1])^2 + 100 * (x[2] - x[1]^2)^2, [-1.2; 1.0])
1116
reset!(solver, nlp)
1217
stats = solve!(solver, nlp, stats, print_level = 0)
1318
@test isapprox(stats.solution, [0.0; 0.0], atol = 1e-6)
1419
@test stats.status == :first_order
20+
@test stats.iter == 16
21+
@test stats.elapsed_time > 0
22+
@test stats.primal_feas 0.0
23+
@test stats.dual_feas 0.0 atol = 1.49e-8
1524
end
1625

17-
function tests()
26+
@testset "Unit tests NLPModelsIpopt" begin
1827
nlp = ADNLPModel(x -> (x[1] - 1)^2 + 100 * (x[2] - x[1]^2)^2, [-1.2; 1.0])
1928
stats = ipopt(nlp, print_level = 0)
2029
@test isapprox(stats.solution, [1.0; 1.0], rtol = 1e-6)
2130
@test stats.status == :first_order
2231
@test stats.elapsed_time > 0
32+
@test stats.iter == 21
33+
@test stats.primal_feas 0.0
34+
@test stats.dual_feas 0.0 atol = 1.49e-8
2335

2436
nlp = ADNLPModel(x -> (x[1] - 1)^2 + 100 * (x[2] - x[1]^2)^2, [-1.2; 1.0])
2537
stats = ipopt(nlp, tol = 1e-12, print_level = 0)
2638
@test isapprox(stats.solution, [1.0; 1.0], rtol = 1e-6)
2739
@test stats.status == :first_order
2840
@test stats.elapsed_time > 0
41+
@test stats.iter == 22
42+
@test stats.primal_feas 0.0
43+
@test stats.dual_feas 0.0
2944

3045
# solve again from solution
3146
x0 = copy(stats.solution)
3247
stats = ipopt(nlp, x0 = x0, tol = 1e-12, print_level = 0)
3348
@test isapprox(stats.solution, x0, rtol = 1e-6)
3449
@test stats.status == :first_order
3550
@test stats.iter == 0
51+
@test stats.elapsed_time >= 0
52+
@test stats.primal_feas 0.0
53+
@test stats.dual_feas 0.0
3654

3755
function callback(alg_mod, iter_count, args...)
3856
return iter_count < 1
@@ -43,6 +61,8 @@ function tests()
4361
@test first(stats.solver_specific[:internal_msg]) == :User_Requested_Stop
4462
@test stats.iter == 1
4563
@test stats.elapsed_time > 0
64+
@test stats.primal_feas 0.0
65+
# @test stats.dual_feas ≈ 4.63
4666

4767
nlp =
4868
ADNLPModel(x -> (x[1] - 1)^2 + 4 * (x[2] - 3)^2, zeros(2), x -> [sum(x) - 1.0], [0.0], [0.0])
@@ -51,6 +71,8 @@ function tests()
5171
@test stats.iter == 1
5272
@test stats.status == :first_order
5373
@test stats.elapsed_time > 0
74+
@test stats.primal_feas 0.0
75+
@test stats.dual_feas 0.0 atol = 1.49e-8
5476

5577
# solve constrained problem again from solution
5678
x0 = copy(stats.solution)
@@ -65,8 +87,11 @@ function tests()
6587
@test isapprox(stats.multipliers_L, zL, rtol = 1e-6)
6688
@test isapprox(stats.multipliers_U, zU, rtol = 1e-6)
6789
end
90+
@test stats.elapsed_time >= 0
6891
@test stats.iter == 0
6992
@test stats.status == :first_order
93+
@test stats.primal_feas 0.0
94+
@test stats.dual_feas 0.0 atol = 1.49e-8
7095

7196
x0, f = rand(1), x -> x[1]
7297
nlp = ADNLPModel(f, x0, zeros(1), ones(1), minimize = false)
@@ -78,6 +103,7 @@ function tests()
78103
@test isapprox(stats.multipliers_U, -ones(1), rtol = 1e-6)
79104
@test stats.status == :first_order
80105
@test stats.elapsed_time > 0
106+
@test stats.iter == 5
107+
@test stats.primal_feas 0.0
108+
@test stats.dual_feas 0.0 atol = 1.49e-8
81109
end
82-
83-
tests()

0 commit comments

Comments
 (0)