From 384be7ff1f4c4efd62614833f7f6deebed5dab11 Mon Sep 17 00:00:00 2001 From: d-monnet Date: Fri, 5 Apr 2024 17:15:06 -0400 Subject: [PATCH 1/4] add unbounded below obj test. Fix unbounded test in fomo. --- src/fomo.jl | 6 ++---- test/runtests.jl | 10 ++++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/fomo.jl b/src/fomo.jl index 831d07e8..9ce21527 100644 --- a/src/fomo.jl +++ b/src/fomo.jl @@ -346,10 +346,7 @@ function SolverCore.solve!( step_underflow = x == c # step addition underfow on every dimensions, should happen before solver.α == 0 ΔTk = ((oneT - βmax) * norm_∇fk^2 + βmax * mdot∇f) * λk # = dot(d,∇fk) * λk with momentum, ‖∇fk‖²λk without momentum fck = obj(nlp, c) - if fck == -Inf - set_status!(stats, :unbounded) - break - end + unbounded = isinf(fck) ρk = (stats.objective - fck) / ΔTk # Update regularization parameters if ρk >= η2 @@ -406,6 +403,7 @@ function SolverCore.solve!( nlp, elapsed_time = stats.elapsed_time, optimal = optimal, + unbounded = unbounded, max_eval = max_eval, iter = stats.iter, max_iter = max_iter, diff --git a/test/runtests.jl b/test/runtests.jl index bb41eeba..de60b0d7 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -35,6 +35,16 @@ end end end +@testset "Test unbounded below" begin + @testset "$fun" for fun in (R2, fomo, lbfgs, tron, trunk) + f(x) = -exp(x[1]) + nlp = ADNLPModel(f, [2.]) + + stats = eval(fun)(nlp) + @test stats.status == :unbounded + end +end + include("restart.jl") include("callback.jl") include("consistency.jl") From befdf2d030af942587ff846c77f8e03440603601 Mon Sep 17 00:00:00 2001 From: d-monnet Date: Fri, 5 Apr 2024 17:15:06 -0400 Subject: [PATCH 2/4] add unbounded below obj test. Fix unbounded test in fomo. --- src/fomo.jl | 6 ++---- test/runtests.jl | 10 ++++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/fomo.jl b/src/fomo.jl index 831d07e8..9ce21527 100644 --- a/src/fomo.jl +++ b/src/fomo.jl @@ -346,10 +346,7 @@ function SolverCore.solve!( step_underflow = x == c # step addition underfow on every dimensions, should happen before solver.α == 0 ΔTk = ((oneT - βmax) * norm_∇fk^2 + βmax * mdot∇f) * λk # = dot(d,∇fk) * λk with momentum, ‖∇fk‖²λk without momentum fck = obj(nlp, c) - if fck == -Inf - set_status!(stats, :unbounded) - break - end + unbounded = isinf(fck) ρk = (stats.objective - fck) / ΔTk # Update regularization parameters if ρk >= η2 @@ -406,6 +403,7 @@ function SolverCore.solve!( nlp, elapsed_time = stats.elapsed_time, optimal = optimal, + unbounded = unbounded, max_eval = max_eval, iter = stats.iter, max_iter = max_iter, diff --git a/test/runtests.jl b/test/runtests.jl index bb41eeba..de60b0d7 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -35,6 +35,16 @@ end end end +@testset "Test unbounded below" begin + @testset "$fun" for fun in (R2, fomo, lbfgs, tron, trunk) + f(x) = -exp(x[1]) + nlp = ADNLPModel(f, [2.]) + + stats = eval(fun)(nlp) + @test stats.status == :unbounded + end +end + include("restart.jl") include("callback.jl") include("consistency.jl") From 1359be721761f6d4a0108260bfb6105e823f3b3b Mon Sep 17 00:00:00 2001 From: d-monnet Date: Tue, 9 Apr 2024 12:29:38 -0400 Subject: [PATCH 3/4] standardize fomo :unbounded condition, add objective value test in unbounded tests. --- src/fomo.jl | 9 +++++++-- test/runtests.jl | 5 ++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/fomo.jl b/src/fomo.jl index 9ce21527..b666dad9 100644 --- a/src/fomo.jl +++ b/src/fomo.jl @@ -279,7 +279,8 @@ function SolverCore.solve!( d = use_momentum ? solver.d : solver.g # g = d if no momentum p = use_momentum ? solver.p : nothing # not used if no momentum set_iter!(stats, 0) - set_objective!(stats, obj(nlp, x)) + fk = obj(nlp, x) + set_objective!(stats, fk) grad!(nlp, x, ∇fk) norm_∇fk = norm(∇fk) @@ -288,6 +289,9 @@ function SolverCore.solve!( solver.α = init_alpha(norm_∇fk, step_backend) # Stopping criterion: + fmin = min(-one(T), fk) / eps(T) + unbounded = fk < fmin + ϵ = atol + rtol * norm_∇fk optimal = norm_∇fk ≤ ϵ step_param_name = is_r2 ? "σ" : "Δ" @@ -321,6 +325,7 @@ function SolverCore.solve!( nlp, elapsed_time = stats.elapsed_time, optimal = optimal, + unbounded = unbounded, max_eval = max_eval, iter = stats.iter, max_iter = max_iter, @@ -346,7 +351,7 @@ function SolverCore.solve!( step_underflow = x == c # step addition underfow on every dimensions, should happen before solver.α == 0 ΔTk = ((oneT - βmax) * norm_∇fk^2 + βmax * mdot∇f) * λk # = dot(d,∇fk) * λk with momentum, ‖∇fk‖²λk without momentum fck = obj(nlp, c) - unbounded = isinf(fck) + unbounded = fck < fmin ρk = (stats.objective - fck) / ΔTk # Update regularization parameters if ρk >= η2 diff --git a/test/runtests.jl b/test/runtests.jl index de60b0d7..ba032047 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -37,11 +37,14 @@ end @testset "Test unbounded below" begin @testset "$fun" for fun in (R2, fomo, lbfgs, tron, trunk) + T = Float64 + x0 = [T(0)] f(x) = -exp(x[1]) - nlp = ADNLPModel(f, [2.]) + nlp = ADNLPModel(f, x0) stats = eval(fun)(nlp) @test stats.status == :unbounded + @test stats.objective < -one(T)/eps(T) end end From bf929172333443b6eb445330a0e7a6f31f15c099 Mon Sep 17 00:00:00 2001 From: d-monnet Date: Tue, 9 Apr 2024 12:35:26 -0400 Subject: [PATCH 4/4] rename: fk -> f0 --- src/fomo.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/fomo.jl b/src/fomo.jl index b666dad9..dc7dd338 100644 --- a/src/fomo.jl +++ b/src/fomo.jl @@ -279,8 +279,8 @@ function SolverCore.solve!( d = use_momentum ? solver.d : solver.g # g = d if no momentum p = use_momentum ? solver.p : nothing # not used if no momentum set_iter!(stats, 0) - fk = obj(nlp, x) - set_objective!(stats, fk) + f0 = obj(nlp, x) + set_objective!(stats, f0) grad!(nlp, x, ∇fk) norm_∇fk = norm(∇fk) @@ -289,8 +289,8 @@ function SolverCore.solve!( solver.α = init_alpha(norm_∇fk, step_backend) # Stopping criterion: - fmin = min(-one(T), fk) / eps(T) - unbounded = fk < fmin + fmin = min(-one(T), f0) / eps(T) + unbounded = f0 < fmin ϵ = atol + rtol * norm_∇fk optimal = norm_∇fk ≤ ϵ