Skip to content

Commit c3d0763

Browse files
authored
Unify interface for linesearches (#121)
* Standardise line search arguments * Update example with new interface.
1 parent 2119606 commit c3d0763

File tree

5 files changed

+31
-32
lines changed

5 files changed

+31
-32
lines changed

docs/src/examples/customoptimizer.jl

+6-21
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ function gdoptimize(f, g!, fg!, x0::AbstractArray{T}, linesearch,
4444
s .= -gvec
4545

4646
dϕ_0 = dot(s, gvec)
47-
α, fx = perform_linesearch(ϕ, dϕ, ϕdϕ, 1.0,
48-
fx, dϕ_0, linesearch)
47+
α, fx = linesearch(ϕ, dϕ, ϕdϕ, 1.0, fx, dϕ_0)
48+
4949
@. x = x + α*s
5050
g!(gvec, x)
5151
gnorm = norm(gvec)
@@ -62,29 +62,12 @@ end
6262
# LineSearches algorithms do.
6363

6464
# The Gradient Descent `gdoptimize` method selects a descent direction and calls
65-
# a method `perform_linesearch` that returns the step length `α` and the
65+
# the line search algorithm `linesearch` which returns the step length `α` and the
6666
# objective value `fx = f(x + α*s)`.
6767
#
68-
# We use multiple dispatch on `linesearch` to call the different line search procedures:
69-
70-
using LineSearches
71-
perform_linesearch(ϕ, dϕ, ϕdϕ, α0, ϕ_0, dϕ_0,
72-
linesearch::BackTracking) =
73-
linesearch(ϕ, α0, ϕ_0, dϕ_0)
74-
perform_linesearch(ϕ, dϕ, ϕdϕ, α0, ϕ_0, dϕ_0,
75-
linesearch::HagerZhang) =
76-
linesearch(ϕ, ϕdϕ, α0, ϕ_0, dϕ_0)
77-
perform_linesearch(ϕ, dϕ, ϕdϕ, α0, ϕ_0, dϕ_0,
78-
linesearch::MoreThuente) =
79-
linesearch(ϕdϕ, α0, ϕ_0, dϕ_0)
80-
perform_linesearch(ϕ, dϕ, ϕdϕ, α0, ϕ_0, dϕ_0,
81-
linesearch::StrongWolfe) =
82-
linesearch(ϕ, dϕ, ϕdϕ, α0, ϕ_0, dϕ_0)
83-
8468
# The functions ϕ and dϕ represent a univariate objective
8569
# and its derivative, which is used by the line search algorithms.
86-
# To utilize the `fg!` function call in the optimizer, `HagerZhang`,
87-
# `MoreThuente`, and `StrongWolfe` also
70+
# To utilize the `fg!` function call in the optimizer, some of the line searches
8871
# require a function ϕdϕ which returns the univariate objective and the
8972
# derivative at the same time.
9073

@@ -111,6 +94,8 @@ end
11194
# from a given initial condition `x0`.
11295

11396
x0 = [-1., 1.0]
97+
98+
using LineSearches
11499
ls = BackTracking(order=3)
115100
fx_bt3, x_bt3, iter_bt3 = gdoptimize(f, g!, fg!, x0, ls)
116101

src/backtracking.jl

+5-2
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,11 @@ function (ls::BackTracking)(df::AbstractObjective, x::AbstractArray{T}, s::Abstr
3232
α_0 = min(α_0, min(alphamax, ls.maxstep / vecnorm(s, Inf)))
3333
ls(ϕ, α_0, ϕ_0, dϕ_0)
3434
end
35-
function (ls::BackTracking)(ϕ, α_0::Tα, ϕ_0, dϕ_0) where
3635

36+
(ls::BackTracking)(ϕ, dϕ, ϕdϕ, αinitial, ϕ_0, dϕ_0) = ls(ϕ, αinitial, ϕ_0, dϕ_0)
37+
38+
# TODO: Should we deprecate the interface that only uses the ϕ argument?
39+
function (ls::BackTracking)(ϕ, αinitial::Tα, ϕ_0, dϕ_0) where
3740
@unpack c_1, ρ_hi, ρ_lo, iterations, order = ls
3841

3942
iterfinitemax = -log2(eps(real(Tα)))
@@ -52,7 +55,7 @@ function (ls::BackTracking)(ϕ, α_0::Tα, ϕ_0, dϕ_0) where Tα
5255

5356
ϕx_0, ϕx_1 = ϕ_0, ϕ_0
5457

55-
α_1, α_2 = α_0, α_0
58+
α_1, α_2 = αinitial, αinitial
5659

5760
ϕx_1 = ϕ(α_1)
5861

src/hagerzhang.jl

+6-4
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,13 @@ function (ls::HagerZhang)(df::AbstractObjective, x::AbstractArray{T},
101101
ls(ϕ, ϕdϕ, α::Real, phi_0, dphi_0)
102102
end
103103

104-
function (ls::HagerZhang)(ϕ, ϕdϕ,
105-
c::T,
106-
phi_0::Real,
107-
dphi_0::Real) where T
104+
(ls::HagerZhang)(ϕ, dϕ, ϕdϕ, c, phi_0, dphi_0) = ls(ϕ, ϕdϕ, c, phi_0, dphi_0)
108105

106+
# TODO: Should we deprecate the interface that only uses the ϕ and ϕd\phi arguments?
107+
function (ls::HagerZhang)(ϕ, ϕdϕ,
108+
c::T,
109+
phi_0::Real,
110+
dphi_0::Real) where T # Should c and phi_0 be same type?
109111
@unpack delta, sigma, alphamax, rho, epsilon, gamma,
110112
linesearchmax, psi3, display, mayterminate = ls
111113

src/morethuente.jl

+7-3
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,14 @@ function (ls::MoreThuente)(df::AbstractObjective, x::AbstractArray{T},
153153
ϕdϕ = make_ϕdϕ(df, x_new, x, s)
154154
ls(ϕdϕ, alpha, ϕ_0, dϕ_0)
155155
end
156+
157+
(ls::MoreThuente)(ϕ, dϕ, ϕdϕ, alpha, ϕ_0, dϕ_0) = ls(ϕdϕ, alpha, ϕ_0, dϕ_0)
158+
159+
# TODO: Should we deprecate the interface that only uses the ϕdϕ argument?
156160
function (ls::MoreThuente)(ϕdϕ,
157-
alpha::T,
158-
ϕ_0,
159-
dϕ_0) where T
161+
alpha::T,
162+
ϕ_0,
163+
dϕ_0) where T
160164
@unpack f_tol, gtol, x_tol, alphamin, alphamax, maxfev = ls
161165

162166
iterfinitemax = -log2(eps(T))

src/static.jl

+7-2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ function (ls::DeprecatedStatic)(df::AbstractObjective, x, s, α, x_new = similar
3737
ls(ϕ, α)
3838
end
3939

40+
(ls::DeprecatedStatic)(ϕ, dϕ, ϕdϕ, α, ϕ_0, dϕ_0) = ls(ϕ, α)
41+
4042
function (ls::DeprecatedStatic)(ϕ, α::Tα) where
4143
@unpack α, scaled = ls
4244
@assert α > (0) # This should really be done at the constructor level
@@ -73,10 +75,13 @@ immutable NewStatic end
7375

7476
function (ls::NewStatic)(df::AbstractObjective, x, s, α, x_new = similar(x), ϕ_0 = nothing, dϕ_0 = nothing)
7577
ϕ = make_ϕ(df, x_new, x, s)
76-
ls(ϕ, x, s, α)
78+
ls(ϕ, α)
7779
end
7880

79-
function (ls::NewStatic)(ϕ, x, s, α::Tα) where
81+
(ls::NewStatic)(ϕ, dϕ, ϕdϕ, α, ϕ_0, dϕ_0) = ls(ϕ, α)
82+
83+
# TODO: Should we deprecate the interface that only uses the ϕ argument?
84+
function (ls::NewStatic)(ϕ, α::Tα) where
8085
@assert α > real((0))
8186
ϕα = ϕ(α)
8287

0 commit comments

Comments
 (0)