Skip to content

Commit 3250703

Browse files
committed
add initial stepsize guess to the LineSearches wrapper, rename a function, disable the I0 (a) heuristic by default.
1 parent e265d8f commit 3250703

5 files changed

Lines changed: 64 additions & 17 deletions

File tree

ext/ManoptLineSearchesExt.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ function (cs::Manopt.LineSearchesStepsize)(
2222
dphi_0 = get_differential(mp, p, η; Y = X_tmp)
2323

2424
# guess initial alpha
25-
α0 = 1.0
25+
α0 = cs.initial_guess(mp, s, k, cs.last_stepsize, η; lf0 = fp, Dlf0 = dphi_0)
2626

2727
# perform actual line-search
2828

@@ -42,6 +42,7 @@ function (cs::Manopt.LineSearchesStepsize)(
4242
end
4343

4444
α, fp = cs.linesearch(ϕ, dϕ, ϕdϕ, α0, fp, dphi_0)
45+
cs.last_stepsize = α
4546
return α
4647
end
4748

ext/ManoptManifoldsExt/manifold_functions.jl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
"""
2+
default_point_distance(::DefaultManifold, p)
13
2-
Manopt.default_point_norm(::Euclidean, p) = norm(p, Inf)
4+
Following [HagerZhang:2006:2](@cite), the expected distance to the optimal solution from `p`
5+
on `DefaultManifold` is the `Inf` norm of `p`.
6+
"""
7+
Manopt.default_point_distance(::Euclidean, p) = norm(p, Inf)
38

49
Manopt.default_vector_norm(::Euclidean, p, X) = norm(p, Inf)
510

src/helpers/LineSearchesTypes.jl

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,42 +21,50 @@ The initial step selection from Linesearches.jl is not yet supported and the val
2121
$(_var(:Keyword, :retraction_method))
2222
$(_var(:Keyword, :vector_transport_method))
2323
"""
24-
struct LineSearchesStepsize{
25-
TLS, TRM <: AbstractRetractionMethod, TVTM <: AbstractVectorTransportMethod,
24+
mutable struct LineSearchesStepsize{
25+
TLS, TIG <: AbstractInitialLinesearchGuess, TRM <: AbstractRetractionMethod, TVTM <: AbstractVectorTransportMethod, TF <: Real,
2626
} <: Stepsize
2727
linesearch::TLS
28+
initial_guess::TIG
2829
retraction_method::TRM
2930
vector_transport_method::TVTM
31+
last_stepsize::TF
3032
end
3133
function LineSearchesStepsize(
3234
M::AbstractManifold,
3335
linesearch;
36+
initial_guess::AbstractInitialLinesearchGuess = ConstantInitialGuess(),
3437
retraction_method::AbstractRetractionMethod = default_retraction_method(M),
3538
vector_transport_method::AbstractVectorTransportMethod = default_vector_transport_method(
3639
M
3740
),
41+
last_stepsize::Real = NaN,
3842
)
3943
return LineSearchesStepsize(
4044
linesearch;
45+
initial_guess = initial_guess,
4146
retraction_method = retraction_method,
4247
vector_transport_method = vector_transport_method,
48+
last_stepsize = last_stepsize
4349
)
4450
end
4551
function LineSearchesStepsize(
4652
linesearch;
53+
initial_guess::AbstractInitialLinesearchGuess = ConstantInitialGuess(),
4754
retraction_method::AbstractRetractionMethod = ExponentialRetraction(),
4855
vector_transport_method::AbstractVectorTransportMethod = ParallelTransport(),
56+
last_stepsize::Real = NaN,
4957
)
5058
return LineSearchesStepsize{
51-
typeof(linesearch), typeof(retraction_method), typeof(vector_transport_method),
59+
typeof(linesearch), typeof(initial_guess), typeof(retraction_method), typeof(vector_transport_method), typeof(last_stepsize),
5260
}(
53-
linesearch, retraction_method, vector_transport_method
61+
linesearch, initial_guess, retraction_method, vector_transport_method, last_stepsize
5462
)
5563
end
5664

5765
function Base.show(io::IO, cs::LineSearchesStepsize)
5866
return print(
5967
io,
60-
"LineSearchesStepsize($(cs.linesearch); retraction_method=$(cs.retraction_method), vector_transport_method=$(cs.vector_transport_method))",
68+
"LineSearchesStepsize($(cs.linesearch); initial_guess=$(cs.initial_guess), retraction_method=$(cs.retraction_method), vector_transport_method=$(cs.vector_transport_method), last_stepsize=$(cs.last_stepsize))",
6169
)
6270
end

src/plans/stepsize/initial_guess.jl

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
abstract type AbstractInitialLinesearchGuess end
22

3+
struct ConstantInitialGuess{TF} <: AbstractInitialLinesearchGuess
4+
α::TF
5+
end
6+
ConstantInitialGuess() = ConstantInitialGuess(1.0)
7+
8+
function (cig::ConstantInitialGuess)(
9+
mp::AbstractManoptProblem, s::AbstractManoptSolverState, ::Int, l::Real, η; kwargs...
10+
)
11+
return cig.α
12+
end
13+
14+
315
struct ArmijoInitialGuess <: AbstractInitialLinesearchGuess end
416

517
"""
@@ -49,10 +61,31 @@ _doc_stepsize_initial_guess(default = "") = """
4961
5062
"""
5163

52-
default_point_norm(::AbstractManifold, p) = one(number_eltype(p))
53-
default_point_norm(::DefaultManifold, p) = norm(p, Inf)
64+
"""
65+
default_point_distance(::AbstractManifold, p)
5466
55-
default_vector_norm(M::AbstractManifold, p, X) = norm(M, p, X)
67+
The default Hager-Zhang guess for distance between `p` the solution to the optimization
68+
problem. The default is 0, which deactivates heuristic I0 (a).
69+
On each manifold with `default_point_distance`, you need to also implement `default_vector_norm`.
70+
"""
71+
default_point_distance(::AbstractManifold, p) = zero(number_eltype(p))
72+
73+
"""
74+
default_point_distance(::DefaultManifold, p)
75+
76+
Following [HagerZhang:2006:2](@cite), the expected distance to the optimal solution from `p`
77+
on `DefaultManifold` is the `Inf` norm of `p`.
78+
"""
79+
default_point_distance(::DefaultManifold, p) = norm(p, Inf)
80+
81+
"""
82+
default_point_distance(::AbstractManifold, p)
83+
84+
The default Hager-Zhang guess for distance between `p` the solution to the optimization
85+
problem along the descent direction. There is no default implementation because it is only
86+
needed for manifolds with a specific `default_point_distance` method.
87+
"""
88+
default_vector_norm(M::AbstractManifold, p, X)
5689
default_vector_norm(::DefaultManifold, p, X) = norm(p, Inf)
5790

5891

@@ -69,7 +102,7 @@ struct HagerZhangInitialGuess{TF <: Real, TPN, TVN} <: AbstractInitialLinesearch
69102
ψ2::TF
70103
constant_guess::TF
71104
quadstep::Bool
72-
point_norm::TPN
105+
point_distance::TPN
73106
vector_norm::TVN
74107
zero_abstol::TF
75108
alphamax::TF
@@ -82,14 +115,14 @@ function HagerZhangInitialGuess{TF}(;
82115
ψ2::TF = 2.0,
83116
constant_guess::TF = NaN,
84117
quadstep::Bool = true,
85-
point_norm::TPN = default_point_norm,
118+
point_distance::TPN = default_point_distance,
86119
vector_norm::TVN = default_vector_norm,
87120
zero_abstol::TF = eps(TF),
88121
alphamax::TF = Inf,
89122
) where {TF <: Real, TPN, TVN}
90123
return HagerZhangInitialGuess{TF, TPN, TVN}(
91124
ψ0, ψ1, ψ2, constant_guess, quadstep,
92-
point_norm, vector_norm, zero_abstol, alphamax
125+
point_distance, vector_norm, zero_abstol, alphamax
93126
)
94127
end
95128

@@ -106,12 +139,12 @@ function (hzi::HagerZhangInitialGuess{TF})(
106139
alphamax = min(hzi.alphamax, max_stepsize(M, p))
107140

108141
if k == 1
109-
pn = hzi.point_norm(M, p)
110-
ηn = hzi.vector_norm(M, p, η)
142+
pn = hzi.point_distance(M, p)
111143
# Step I0
112144
if isnan(hzi.constant_guess)
113145
if pn > hzi.zero_abstol
114146
# I0.(a)
147+
ηn = hzi.vector_norm(M, p, η)
115148
return min(hzi.ψ0 * pn / ηn, alphamax)
116149
elseif abs_lf0 > hzi.zero_abstol
117150
# I0.(b)

test/plans/test_stepsize.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ using ManoptTestSuite
2121

2222
gds1 = GradientDescentState(M; p = p1)
2323
η1 = -X1
24-
@test hzi(dmp, gds1, 1, NaN, η1) hzi.ψ0 * Manopt.default_point_norm(M, p1) / Manopt.default_vector_norm(M, p1, η1)
24+
@test hzi(dmp, gds1, 1, NaN, η1) hzi.ψ0 * Manopt.default_point_distance(M, p1) / Manopt.default_vector_norm(M, p1, η1)
2525
# case I0 (b)
2626
p2 = [0.0, 0.0]
2727
X2 = grad_f(M, p2)
@@ -61,7 +61,7 @@ using ManoptTestSuite
6161

6262
gds = GradientDescentState(MS; p = p4)
6363
η4 = -X4
64-
@test hzi(dmp, gds, 1, NaN, η4) 5.0e-5
64+
@test hzi(dmp, gds, 1, NaN, η4) 2.5e-5
6565
end
6666
end
6767

0 commit comments

Comments
 (0)