diff --git a/src/R2_alg.jl b/src/R2_alg.jl index 1a482fb3..fddf1c33 100644 --- a/src/R2_alg.jl +++ b/src/R2_alg.jl @@ -380,6 +380,7 @@ function SolverCore.solve!( end local ξ::T + local ρk::T σk = max(1 / ν, σmin) ν = 1 / σk sqrt_ξ_νInv = one(T) @@ -438,7 +439,7 @@ function SolverCore.solve!( improper = (hkn == -Inf) Δobj = (fk + hk) - (fkn + hkn) + max(1, abs(fk + hk)) * 10 * eps() - global ρk = Δobj / ξ + ρk = Δobj / ξ verbose > 0 && stats.iter % verbose == 0 && diff --git a/test/runtests.jl b/test/runtests.jl index 28e91086..39f3a9a0 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,7 +1,7 @@ using LinearAlgebra: length using LinearAlgebra, Random, Test using ProximalOperators -using NLPModels, NLPModelsModifiers, RegularizedProblems, RegularizedOptimization +using NLPModels, NLPModelsModifiers, RegularizedProblems, RegularizedOptimization, SolverCore const global compound = 1 const global nz = 10 * compound @@ -135,3 +135,4 @@ for (h, h_name) ∈ ((NormL1(λ), "l1"),) end include("test_bounds.jl") +include("test_allocs.jl") diff --git a/test/test_allocs.jl b/test/test_allocs.jl new file mode 100644 index 00000000..cfd338f6 --- /dev/null +++ b/test/test_allocs.jl @@ -0,0 +1,49 @@ +""" + @wrappedallocs(expr) + +Given an expression, this macro wraps that expression inside a new function +which will evaluate that expression and measure the amount of memory allocated +by the expression. Wrapping the expression in a new function allows for more +accurate memory allocation detection when using global variables (e.g. when +at the REPL). + +This code is based on that of https://github.com/JuliaAlgebra/TypedPolynomials.jl/blob/master/test/runtests.jl + +For example, `@wrappedallocs(x + y)` produces: + +```julia +function g(x1, x2) + @allocated x1 + x2 +end +g(x, y) +``` + +You can use this macro in a unit test to verify that a function does not +allocate: + +``` +@test @wrappedallocs(x + y) == 0 +``` +""" +macro wrappedallocs(expr) + argnames = [gensym() for a in expr.args] + quote + function g($(argnames...)) + @allocated $(Expr(expr.head, argnames...)) + end + $(Expr(:call, :g, [esc(a) for a in expr.args]...)) + end +end + + +# Test non allocating solve! +@testset "allocs" begin + for (h, h_name) ∈ ((NormL0(λ), "l0"), (NormL1(λ), "l1")) + for solver ∈ (:R2Solver, ) + reg_nlp = RegularizedNLPModel(bpdn, h) + solver = eval(solver)(reg_nlp) + stats = GenericExecutionStats(bpdn, solver_specific = Dict{Symbol, Float64}()) + @test @wrappedallocs(solve!(solver, reg_nlp, stats)) == 0 + end + end +end