Skip to content

Commit cb8fe69

Browse files
format code
1 parent da02bba commit cb8fe69

File tree

4 files changed

+68
-81
lines changed

4 files changed

+68
-81
lines changed

src/R2DH.jl

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ mutable struct R2DHSolver{
66
T <: Real,
77
G <: ShiftedProximableFunction,
88
V <: AbstractVector{T},
9-
QN <: AbstractDiagonalQuasiNewtonOperator{T}
9+
QN <: AbstractDiagonalQuasiNewtonOperator{T},
1010
} <: AbstractOptimizationSolver
1111
xk::V
1212
∇fk::V
@@ -25,7 +25,11 @@ mutable struct R2DHSolver{
2525
m_fh_hist::V
2626
end
2727

28-
function R2DHSolver(reg_nlp::AbstractRegularizedNLPModel{T, V}; m_monotone::Int = 6, D :: Union{Nothing, AbstractDiagonalQuasiNewtonOperator} = nothing) where{T, V}
28+
function R2DHSolver(
29+
reg_nlp::AbstractRegularizedNLPModel{T, V};
30+
m_monotone::Int = 6,
31+
D::Union{Nothing, AbstractDiagonalQuasiNewtonOperator} = nothing,
32+
) where {T, V}
2933
x0 = reg_nlp.model.meta.x0
3034
l_bound = reg_nlp.model.meta.lvar
3135
u_bound = reg_nlp.model.meta.uvar
@@ -49,8 +53,14 @@ function R2DHSolver(reg_nlp::AbstractRegularizedNLPModel{T, V}; m_monotone::Int
4953
end
5054
m_fh_hist = fill(T(-Inf), m_monotone - 1)
5155

52-
ψ = has_bnds ? shifted(reg_nlp.h, xk, l_bound_m_x, u_bound_m_x, reg_nlp.selected) : shifted(reg_nlp.h, xk)
53-
isnothing(D) && (D = isa(reg_nlp.model, AbstractDiagonalQNModel) ? hess_op(reg_nlp.model, x0) : SpectralGradient(T(1), reg_nlp.model.meta.nvar))
56+
ψ =
57+
has_bnds ? shifted(reg_nlp.h, xk, l_bound_m_x, u_bound_m_x, reg_nlp.selected) :
58+
shifted(reg_nlp.h, xk)
59+
isnothing(D) && (
60+
D =
61+
isa(reg_nlp.model, AbstractDiagonalQNModel) ? hess_op(reg_nlp.model, x0) :
62+
SpectralGradient(T(1), reg_nlp.model.meta.nvar)
63+
)
5464

5565
return R2DHSolver(
5666
xk,
@@ -67,10 +77,9 @@ function R2DHSolver(reg_nlp::AbstractRegularizedNLPModel{T, V}; m_monotone::Int
6777
u_bound,
6878
l_bound_m_x,
6979
u_bound_m_x,
70-
m_fh_hist
80+
m_fh_hist,
7181
)
7282
end
73-
7483

7584
"""
7685
R2DH(reg_nlp; kwargs…)
@@ -141,12 +150,7 @@ Notably, you can access, and modify, the following:
141150
- `stats.status`: current status of the algorithm. Should be `:unknown` unless the algorithm has attained a stopping criterion. Changing this to anything will stop the algorithm, but you should use `:user` to properly indicate the intention.
142151
- `stats.elapsed_time`: elapsed time in seconds.
143152
"""
144-
function R2DH(
145-
nlp::AbstractNLPModel{T, V},
146-
h,
147-
options::ROSolverOptions{T};
148-
kwargs...,
149-
) where{T, V}
153+
function R2DH(nlp::AbstractNLPModel{T, V}, h, options::ROSolverOptions{T}; kwargs...) where {T, V}
150154
kwargs_dict = Dict(kwargs...)
151155
selected = pop!(kwargs_dict, :selected, 1:(nlp.meta.nvar))
152156
x0 = pop!(kwargs_dict, :x0, nlp.meta.x0)
@@ -200,14 +204,11 @@ function R2DH(
200204
θ = options.θ,
201205
kwargs...,
202206
)
203-
207+
204208
return stats.solution, stats.iter, nothing
205209
end
206210

207-
function R2DH(
208-
reg_nlp::AbstractRegularizedNLPModel{T, V};
209-
kwargs...
210-
) where{T, V}
211+
function R2DH(reg_nlp::AbstractRegularizedNLPModel{T, V}; kwargs...) where {T, V}
211212
kwargs_dict = Dict(kwargs...)
212213
m_monotone = pop!(kwargs_dict, :m_monotone, 6)
213214
D = pop!(kwargs_dict, :D, nothing)
@@ -236,8 +237,7 @@ function SolverCore.solve!(
236237
ν::T = eps(T)^(1 / 5),
237238
γ::T = T(3),
238239
θ::T = 1/(1 + eps(T)^(1 / 5)),
239-
) where{T, V}
240-
240+
) where {T, V}
241241
reset!(stats)
242242

243243
# Retrieve workspace
@@ -269,7 +269,6 @@ function SolverCore.solve!(
269269
end
270270
m_monotone = length(m_fh_hist) + 1
271271

272-
273272
# initialize parameters
274273
improper = false
275274
hk = @views h(xk[selected])
@@ -324,7 +323,7 @@ function SolverCore.solve!(
324323
set_objective!(stats, fk + hk)
325324
set_solver_specific!(stats, :smooth_obj, fk)
326325
set_solver_specific!(stats, :nonsmooth_obj, hk)
327-
m_monotone > 1 && (m_fh_hist[(stats.iter)%(m_monotone - 1) + 1] = fk + hk)
326+
m_monotone > 1 && (m_fh_hist[(stats.iter) % (m_monotone - 1) + 1] = fk + hk)
328327

329328
φ(d) = begin
330329
result = zero(T)
@@ -334,12 +333,12 @@ function SolverCore.solve!(
334333
end
335334
return result
336335
end
337-
336+
338337
mk(d)::T = φ(d) + ψ(d)::T
339338

340339
spectral_test ? prox!(s, ψ, mν∇fk, ν₁) : iprox!(s, ψ, ∇fk, dkσk)
341340

342-
mks = mk(s)
341+
mks = mk(s)
343342

344343
ξ = hk - mks + max(1, abs(hk)) * 10 * eps()
345344
sqrt_ξ_νInv = ξ 0 ? sqrt/ ν₁) : sqrt(-ξ / ν₁)
@@ -431,7 +430,7 @@ function SolverCore.solve!(
431430
ν₁ = θ / (DNorm + σk)
432431

433432
@. mν∇fk = -ν₁ * ∇fk
434-
m_monotone > 1 && (m_fh_hist[stats.iter%(m_monotone - 1) + 1] = fk + hk)
433+
m_monotone > 1 && (m_fh_hist[stats.iter % (m_monotone - 1) + 1] = fk + hk)
435434

436435
spectral_test ? prox!(s, ψ, mν∇fk, ν₁) : iprox!(s, ψ, ∇fk, dkσk)
437436
mks = mk(s)
@@ -479,7 +478,7 @@ function SolverCore.solve!(
479478
@info "R2DH: terminating with √(ξ/ν) = $(sqrt_ξ_νInv)"
480479
end
481480

482-
set_solution!(stats,xk)
481+
set_solution!(stats, xk)
483482
set_residuals!(stats, zero(eltype(xk)), sqrt_ξ_νInv)
484483
return stats
485-
end
484+
end

src/R2N.jl

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ mutable struct R2NSolver{
77
G <: ShiftedProximableFunction,
88
V <: AbstractVector{T},
99
ST <: AbstractOptimizationSolver,
10-
PB <: AbstractRegularizedNLPModel
10+
PB <: AbstractRegularizedNLPModel,
1111
} <: AbstractOptimizationSolver
1212
xk::V
1313
∇fk::V
@@ -28,7 +28,11 @@ mutable struct R2NSolver{
2828
substats::GenericExecutionStats{T, V, V, T}
2929
end
3030

31-
function R2NSolver(reg_nlp::AbstractRegularizedNLPModel{T, V}; subsolver = R2Solver, m_monotone::Int = 1) where {T, V}
31+
function R2NSolver(
32+
reg_nlp::AbstractRegularizedNLPModel{T, V};
33+
subsolver = R2Solver,
34+
m_monotone::Int = 1,
35+
) where {T, V}
3236
x0 = reg_nlp.model.meta.x0
3337
l_bound = reg_nlp.model.meta.lvar
3438
u_bound = reg_nlp.model.meta.uvar
@@ -53,15 +57,12 @@ function R2NSolver(reg_nlp::AbstractRegularizedNLPModel{T, V}; subsolver = R2Sol
5357
end
5458
m_fh_hist = fill(T(-Inf), m_monotone - 1)
5559

56-
ψ = has_bnds ? shifted(reg_nlp.h, xk, l_bound_m_x, u_bound_m_x, reg_nlp.selected) : shifted(reg_nlp.h, xk)
60+
ψ =
61+
has_bnds ? shifted(reg_nlp.h, xk, l_bound_m_x, u_bound_m_x, reg_nlp.selected) :
62+
shifted(reg_nlp.h, xk)
5763

5864
Bk = hess_op(reg_nlp.model, x0)
59-
sub_nlp = R2NModel(
60-
Bk,
61-
∇fk,
62-
T(1),
63-
x0
64-
)
65+
sub_nlp = R2NModel(Bk, ∇fk, T(1), x0)
6566
subpb = RegularizedNLPModel(sub_nlp, ψ)
6667
substats = RegularizedExecutionStats(subpb)
6768
subsolver = subsolver(subpb)
@@ -83,10 +84,9 @@ function R2NSolver(reg_nlp::AbstractRegularizedNLPModel{T, V}; subsolver = R2Sol
8384
m_fh_hist,
8485
subsolver,
8586
subpb,
86-
substats
87+
substats,
8788
)
8889
end
89-
9090

9191
"""
9292
R2N(reg_nlp; kwargs…)
@@ -212,9 +212,9 @@ function SolverCore.solve!(
212212
ν::T = eps(T)^(1 / 5),
213213
γ::T = T(3),
214214
β::T = 1 / eps(T),
215-
θ::T = 1/(1+eps(T)^(1 / 5)),
216-
kwargs...
217-
) where{T, V, G}
215+
θ::T = 1/(1 + eps(T)^(1 / 5)),
216+
kwargs...,
217+
) where {T, V, G}
218218
reset!(stats)
219219

220220
# Retrieve workspace
@@ -263,7 +263,7 @@ function SolverCore.solve!(
263263
@info log_header(
264264
[:outer, :inner, :fx, :hx, :xi, , , :normx, :norms, :normB, :arrow],
265265
[Int, Int, T, T, T, T, T, T, T, T, Char],
266-
hdr_override = Dict{Symbol, String}(
266+
hdr_override = Dict{Symbol, String}(
267267
:fx => "f(x)",
268268
:hx => "h(x)",
269269
:xi => "√(ξ1/ν)",
@@ -294,7 +294,7 @@ function SolverCore.solve!(
294294

295295
ν₁ = θ / (λmax + σk)
296296
ν_sub = ν₁
297-
297+
298298
sqrt_ξ1_νInv = one(T)
299299

300300
@. mν∇fk = -ν₁ * ∇fk
@@ -305,7 +305,7 @@ function SolverCore.solve!(
305305
set_objective!(stats, fk + hk)
306306
set_solver_specific!(stats, :smooth_obj, fk)
307307
set_solver_specific!(stats, :nonsmooth_obj, hk)
308-
m_monotone > 1 && (m_fh_hist[stats.iter%(m_monotone - 1) + 1] = fk + hk)
308+
m_monotone > 1 && (m_fh_hist[stats.iter % (m_monotone - 1) + 1] = fk + hk)
309309

310310
φ1 = let ∇fk = ∇fk
311311
d -> dot(∇fk, d)
@@ -328,7 +328,7 @@ function SolverCore.solve!(
328328
(ξ1 < 0 && sqrt_ξ1_νInv > neg_tol) &&
329329
error("R2N: prox-gradient step should produce a decrease but ξ1 = $(ξ1)")
330330
atol += rtol * sqrt_ξ1_νInv # make stopping test absolute and relative
331-
331+
332332
set_status!(
333333
stats,
334334
get_status(
@@ -348,20 +348,19 @@ function SolverCore.solve!(
348348
done = stats.status != :unknown
349349

350350
while !done
351+
sub_atol = stats.iter == 0 ? 1.0e-3 : min(sqrt_ξ1_νInv ^ (1.5), sqrt_ξ1_νInv * 1e-3)
351352

352-
sub_atol = stats.iter == 0 ? 1.0e-3 : min(sqrt_ξ1_νInv ^ (1.5) , sqrt_ξ1_νInv * 1e-3)
353-
354353
solver.subpb.model.σ = σk
355354
isa(solver.subsolver, R2DHSolver) && (solver.subsolver.D.d[1] = 1/ν₁)
356355
ν_sub = isa(solver.subsolver, R2DHSolver) ? 1/σk : ν₁
357356
solve!(
358-
solver.subsolver,
359-
solver.subpb,
357+
solver.subsolver,
358+
solver.subpb,
360359
solver.substats;
361360
x = s1,
362361
atol = sub_atol,
363362
ν = ν_sub,
364-
kwargs...
363+
kwargs...,
365364
)
366365

367366
s .= solver.substats.solution
@@ -424,7 +423,7 @@ function SolverCore.solve!(
424423
push!(nlp, s, ∇fk⁻)
425424
end
426425
solver.subpb.model.B = hess_op(nlp, xk)
427-
426+
428427
λmax, found_λ = opnorm(solver.subpb.model.B)
429428
found_λ || error("operator norm computation failed")
430429

@@ -438,25 +437,25 @@ function SolverCore.solve!(
438437
if ρk < η1 || ρk == Inf
439438
σk = σk * γ
440439
end
441-
440+
442441
ν₁ = θ / (λmax + σk)
443-
m_monotone > 1 && (m_fh_hist[stats.iter%(m_monotone - 1) + 1] = fk + hk)
442+
m_monotone > 1 && (m_fh_hist[stats.iter % (m_monotone - 1) + 1] = fk + hk)
444443

445444
set_objective!(stats, fk + hk)
446445
set_solver_specific!(stats, :smooth_obj, fk)
447446
set_solver_specific!(stats, :nonsmooth_obj, hk)
448447
set_iter!(stats, stats.iter + 1)
449448
set_time!(stats, time() - start_time)
450449

451-
@. mν∇fk = - ν₁ * ∇fk
450+
@. mν∇fk = - ν₁ * ∇fk
452451
prox!(s1, ψ, mν∇fk, ν₁)
453452
mks = mk1(s1)
454453

455454
ξ1 = hk - mks + max(1, abs(hk)) * 10 * eps()
456455

457456
sqrt_ξ1_νInv = ξ1 0 ? sqrt(ξ1 / ν₁) : sqrt(-ξ1 / ν₁)
458457
solved = (ξ1 < 0 && sqrt_ξ1_νInv neg_tol) || (ξ1 0 && sqrt_ξ1_νInv atol)
459-
458+
460459
(ξ1 < 0 && sqrt_ξ1_νInv > neg_tol) &&
461460
error("R2N: prox-gradient step should produce a decrease but ξ1 = $(ξ1)")
462461
set_status!(
@@ -501,4 +500,4 @@ function SolverCore.solve!(
501500
set_solution!(stats, xk)
502501
set_residuals!(stats, zero(eltype(xk)), sqrt_ξ1_νInv)
503502
return stats
504-
end
503+
end

src/R2NModel.jl

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,50 +14,39 @@ this model represents the smooth R2N subproblem:
1414
where `B` is either an approximation of the Hessian of `f` or the Hessian itself and `∇f` represents the gradient of `f` at `x0`.
1515
`σ > 0` is a regularization parameter and `v` is a vector of the same size as `x0` used for intermediary computations.
1616
"""
17-
mutable struct R2NModel{T <: Real, V <: AbstractVector{T}, G <: AbstractLinearOperator{T}} <: AbstractNLPModel{T, V}
18-
B :: G
19-
∇f :: V
20-
v :: V
21-
σ :: T
17+
mutable struct R2NModel{T <: Real, V <: AbstractVector{T}, G <: AbstractLinearOperator{T}} <:
18+
AbstractNLPModel{T, V}
19+
B::G
20+
∇f::V
21+
v::V
22+
σ::T
2223
meta::NLPModelMeta{T, V}
2324
counters::Counters
2425
end
25-
26-
function R2NModel(
27-
B :: G,
28-
∇f :: V,
29-
σ :: T,
30-
x0 :: V
31-
) where{T, V, G}
26+
27+
function R2NModel(B::G, ∇f::V, σ::T, x0::V) where {T, V, G}
3228
@assert length(x0) == length(∇f)
3329
meta = NLPModelMeta(
3430
length(∇f),
3531
x0 = x0, # Perhaps we should add lvar and uvar as well here.
3632
)
3733
v = similar(x0)
38-
return R2NModel(
39-
B :: G,
40-
∇f :: V,
41-
v :: V,
42-
σ :: T,
43-
meta,
44-
Counters()
45-
)
34+
return R2NModel(B::G, ∇f::V, v::V, σ::T, meta, Counters())
4635
end
47-
36+
4837
function NLPModels.obj(nlp::R2NModel, x::AbstractVector)
4938
@lencheck nlp.meta.nvar x
5039
increment!(nlp, :neval_obj)
5140
mul!(nlp.v, nlp.B, x)
52-
return dot(nlp.v, x)/2 + dot(nlp.∇f, x) + nlp.σ * dot(x, x) / 2
41+
return dot(nlp.v, x)/2 + dot(nlp.∇f, x) + nlp.σ * dot(x, x) / 2
5342
end
54-
43+
5544
function NLPModels.grad!(nlp::R2NModel, x::AbstractVector, g::AbstractVector)
5645
@lencheck nlp.meta.nvar x
5746
@lencheck nlp.meta.nvar g
5847
increment!(nlp, :neval_grad)
5948
mul!(g, nlp.B, x)
6049
g .+= nlp.∇f
6150
g .+= nlp.σ .* x
62-
return g
63-
end
51+
return g
52+
end

test/test_allocs.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ end
4141

4242
# Test non allocating solve!
4343
@testset "allocs" begin
44-
for (h, h_name) ((NormL0(λ), "l0"), )
44+
for (h, h_name) ((NormL0(λ), "l0"),)
4545
for (solver, solver_name) ((:R2Solver, "R2"), (:R2DHSolver, "R2DH"), (:R2NSolver, "R2N"))
4646
@testset "$(solver_name)" begin
4747
solver_name == "R2N" && continue #FIXME

0 commit comments

Comments
 (0)