Skip to content

Commit e3308ce

Browse files
committed
nonmonotone ZeroFPR
1 parent 2820f45 commit e3308ce

File tree

5 files changed

+70
-4
lines changed

5 files changed

+70
-4
lines changed

src/algorithms/zerofpr.jl

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ See also: [`ZeroFPR`](@ref).
3333
- `minimum_gamma=1e-7`: lower bound to `gamma` in case `adaptive == true`.
3434
- `max_backtracks=20`: maximum number of line-search backtracks.
3535
- `directions=LBFGS(5)`: strategy to use to compute line-search directions.
36+
- `monotonicity=1`: parameter controlling the averaging scheme for nonmonotone linesearch; monotonicity ∈ (0,1], monotone scheme by default.
3637
3738
# References
3839
1. Themelis, Stella, Patrinos, "Forward-backward envelope for the sum of two nonconvex functions: Further properties and nonmonotone line-search algorithms", SIAM Journal on Optimization, vol. 28, no. 3, pp. 2274-2303 (2018).
@@ -50,6 +51,7 @@ Base.@kwdef struct ZeroFPRIteration{R,Tx,Tf,TA,Tg,TLf,Tgamma,D}
5051
minimum_gamma::R = real(eltype(x0))(1e-7)
5152
max_backtracks::Int = 20
5253
directions::D = LBFGS(5)
54+
monotonicity::R = real(eltype(x0))(1)
5355
end
5456

5557
Base.IteratorSize(::Type{<:ZeroFPRIteration}) = Base.IsInfinite()
@@ -66,6 +68,7 @@ Base.@kwdef mutable struct ZeroFPRState{R,Tx,TAx,TH}
6668
g_xbar::R # value of nonsmooth term (at xbar)
6769
res::Tx # fixed-point residual at iterate (= x - xbar)
6870
H::TH # variable metric
71+
merit::R = zero(gamma)
6972
tau::R = zero(gamma)
7073
Axbar::TAx = similar(Ax)
7174
grad_f_Axbar::TAx = similar(Ax)
@@ -106,6 +109,8 @@ function Base.iterate(iter::ZeroFPRIteration{R}) where {R}
106109
res = x - xbar,
107110
H = initialize(iter.directions, x),
108111
)
112+
# initialize merit
113+
state.merit = f_model(iter, state) + state.g_xbar
109114
return state, state
110115
end
111116

@@ -170,9 +175,6 @@ function Base.iterate(iter::ZeroFPRIteration{R}, state::ZeroFPRState) where {R}
170175
f_model(iter, state), f_Axbar
171176
end
172177

173-
# compute FBE
174-
FBE_x = f_Axbar_upp + state.g_xbar
175-
176178
# compute residual at xbar
177179
mul!(state.At_grad_f_Axbar, iter.A', state.grad_f_Axbar)
178180
state.y .= state.xbar .- state.gamma .* state.At_grad_f_Axbar
@@ -193,6 +195,8 @@ function Base.iterate(iter::ZeroFPRIteration{R}, state::ZeroFPRState) where {R}
193195
state.tau = R(1)
194196
mul!(state.Ad, iter.A, state.d)
195197

198+
# retrieve merit and set threshold
199+
FBE_x = state.merit
196200
sigma = iter.beta * (0.5 / state.gamma) * (1 - iter.alpha)
197201
tol = 10 * eps(R) * (1 + abs(FBE_x))
198202
threshold = FBE_x - sigma * norm(state.res)^2 + tol
@@ -215,7 +219,8 @@ function Base.iterate(iter::ZeroFPRIteration{R}, state::ZeroFPRState) where {R}
215219

216220
state.tau = k >= iter.max_backtracks - 1 ? R(0) : state.tau / 2
217221
end
218-
222+
# update merit with averaging rule
223+
state.merit = (1 - iter.monotonicity) * state.merit + iter.monotonicity * FBE_x
219224
return state, state
220225
end
221226

test/problems/test_lasso_small.jl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,17 @@ using ProximalAlgorithms:
145145
@test x0 == x0_backup
146146
end
147147

148+
@testset "ZeroFPR (fixed step, nonmonotone)" begin
149+
x0 = zeros(T, n)
150+
x0_backup = copy(x0)
151+
solver = ProximalAlgorithms.ZeroFPR(tol = TOL, monotonicity = R(0.2))
152+
x, it = @inferred solver(x0 = x0, f = f_autodiff, A = A, g = g, Lf = Lf)
153+
@test eltype(x) == T
154+
@test norm(x - x_star, Inf) <= TOL
155+
@test it < 20
156+
@test x0 == x0_backup
157+
end
158+
148159
@testset "ZeroFPR (adaptive step)" begin
149160
x0 = zeros(T, n)
150161
x0_backup = copy(x0)
@@ -156,6 +167,17 @@ using ProximalAlgorithms:
156167
@test x0 == x0_backup
157168
end
158169

170+
@testset "ZeroFPR (adaptive step, nonmonotone)" begin
171+
x0 = zeros(T, n)
172+
x0_backup = copy(x0)
173+
solver = ProximalAlgorithms.ZeroFPR(adaptive = true, tol = TOL, monotonicity = R(0.2))
174+
x, it = @inferred solver(x0 = x0, f = f_autodiff, A = A, g = g)
175+
@test eltype(x) == T
176+
@test norm(x - x_star, Inf) <= TOL
177+
@test it < 30
178+
@test x0 == x0_backup
179+
end
180+
159181
@testset "PANOC (fixed step)" begin
160182

161183
x0 = zeros(T, n)

test/problems/test_lasso_small_strongly_convex.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,24 @@ using ProximalAlgorithms
161161
@test x0 == x0_backup
162162
end
163163

164+
@testset "ZeroFPR (fixed, nonmonotone)" begin
165+
solver = ProximalAlgorithms.ZeroFPR(tol = TOL, monotonicity = T(0.2))
166+
y, it = solver(x0 = x0, f = fA_autodiff, g = g, Lf=Lf)
167+
@test eltype(y) == T
168+
@test norm(y - x_star, Inf) <= TOL
169+
@test it < 30
170+
@test x0 == x0_backup
171+
end
172+
173+
@testset "ZeroFPR (adaptive, nonmonotone)" begin
174+
solver = ProximalAlgorithms.ZeroFPR(adaptive = true, tol = TOL, monotonicity = T(0.2))
175+
y, it = solver(x0 = x0, f = fA_autodiff, g = g, Lf=Lf)
176+
@test eltype(y) == T
177+
@test norm(y - x_star, Inf) <= TOL
178+
@test it < 30
179+
@test x0 == x0_backup
180+
end
181+
164182
@testset "PANOC" begin
165183
solver = ProximalAlgorithms.PANOC(tol=TOL)
166184
y, it = solver(x0=x0, f=fA_autodiff, g=g, Lf=Lf)

test/problems/test_nonconvex_qp.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,16 @@ end
142142
@test x0 == x0_backup
143143
end
144144

145+
@testset "ZeroFPR (nonmonotone)" begin
146+
x0 = zeros(T, n)
147+
x0_backup = copy(x0)
148+
solver = ProximalAlgorithms.ZeroFPR(tol = TOL, monotonicity=T(0.4))
149+
x, it = solver(x0 = x0, f = f, g = g)
150+
z = min.(upp, max.(low, x .- gamma .* (Q * x + q)))
151+
@test norm(x - z, Inf) / gamma <= TOL
152+
@test x0 == x0_backup
153+
end
154+
145155
@testset "LiLin" begin
146156
x0 = zeros(T, n)
147157
x0_backup = copy(x0)

test/problems/test_sparse_logistic_small.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,17 @@ using LinearAlgebra
9898
@test x0 == x0_backup
9999
end
100100

101+
@testset "ZeroFPR (adaptive, nonmonotone)" begin
102+
x0 = zeros(T, n)
103+
x0_backup = copy(x0)
104+
solver = ProximalAlgorithms.ZeroFPR(adaptive = true, tol = TOL, monotonicity=R(0.5))
105+
x, it = solver(x0 = x0, f = f_autodiff, A = A, g = g)
106+
@test eltype(x) == T
107+
@test norm(x - x_star, Inf) <= 1e-4
108+
@test it < 30
109+
@test x0 == x0_backup
110+
end
111+
101112
@testset "PANOC (adaptive step)" begin
102113
x0 = zeros(T, n)
103114
x0_backup = copy(x0)

0 commit comments

Comments
 (0)