1
1
"""
2
2
LimitedMemoryBroyden(; max_resets::Int = 3, linesearch = NoLineSearch(),
3
- threshold::Val = Val(10), reset_tolerance = nothing)
3
+ threshold::Val = Val(10), reset_tolerance = nothing, alpha = nothing )
4
4
5
5
An implementation of `LimitedMemoryBroyden` [ziani2008autoadaptative](@cite) with resetting
6
6
and line search.
@@ -12,54 +12,61 @@ and line search.
12
12
`sqrt(eps(real(eltype(u))))`.
13
13
- `threshold`: the number of vectors to store in the low rank approximation. Defaults
14
14
to `Val(10)`.
15
+ - `alpha`: The initial Jacobian inverse is set to be `(αI)⁻¹`. Defaults to `nothing`
16
+ which implies `α = max(norm(u), 1) / (2 * norm(fu))`.
15
17
"""
16
18
function LimitedMemoryBroyden (; max_resets:: Int = 3 , linesearch = NoLineSearch (),
17
- threshold:: Union{Val, Int} = Val (10 ), reset_tolerance = nothing )
19
+ threshold:: Union{Val, Int} = Val (10 ), reset_tolerance = nothing , alpha = nothing )
18
20
threshold isa Int && (threshold = Val (threshold))
19
21
return ApproximateJacobianSolveAlgorithm {false, :LimitedMemoryBroyden} (; linesearch,
20
22
descent = NewtonDescent (), update_rule = GoodBroydenUpdateRule (), max_resets,
21
- initialization = BroydenLowRankInitialization {_unwrap_val(threshold)} (threshold) ,
22
- reinit_rule = NoChangeInStateReset (; reset_tolerance))
23
+ initialization = BroydenLowRankInitialization {_unwrap_val(threshold)} (alpha ,
24
+ threshold), reinit_rule = NoChangeInStateReset (; reset_tolerance))
23
25
end
24
26
25
27
"""
26
- BroydenLowRankInitialization{T}(threshold::Val{T})
28
+ BroydenLowRankInitialization{T}(alpha, threshold::Val{T})
27
29
28
30
An initialization for `LimitedMemoryBroyden` that uses a low rank approximation of the
29
31
Jacobian. The low rank updates to the Jacobian matrix corresponds to what SciPy calls
30
32
["simple"](https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.broyden2.html#scipy-optimize-broyden2).
31
33
"""
32
- struct BroydenLowRankInitialization{T} <: AbstractJacobianInitialization
34
+ @concrete struct BroydenLowRankInitialization{T} <: AbstractJacobianInitialization
35
+ alpha
33
36
threshold:: Val{T}
34
37
end
35
38
36
39
jacobian_initialized_preinverted (:: BroydenLowRankInitialization ) = true
37
40
38
41
function SciMLBase. init (prob:: AbstractNonlinearProblem ,
39
- alg:: BroydenLowRankInitialization{T} ,
40
- solver, f :: F , fu, u, p; maxiters = 1000 , kwargs... ) where {T, F}
42
+ alg:: BroydenLowRankInitialization{T} , solver, f :: F , fu, u, p; maxiters = 1000 ,
43
+ internalnorm :: IN = DEFAULT_NORM , kwargs... ) where {T, F, IN }
41
44
if u isa Number # Use the standard broyden
42
45
return init (prob, IdentityInitialization (true , FullStructure ()), solver, f, fu, u,
43
46
p; maxiters, kwargs... )
44
47
end
45
48
# Pay to cost of slightly more allocations to prevent type-instability for StaticArrays
49
+ α = inv (__initial_alpha (alg. alpha, u, fu, internalnorm))
46
50
if u isa StaticArray
47
- J = BroydenLowRankJacobian (fu, u; alg. threshold)
51
+ J = BroydenLowRankJacobian (fu, u; alg. threshold, alpha = α )
48
52
else
49
53
threshold = min (_unwrap_val (alg. threshold), maxiters)
50
- J = BroydenLowRankJacobian (fu, u; threshold)
54
+ J = BroydenLowRankJacobian (fu, u; threshold, alpha = α )
51
55
end
52
- return InitializedApproximateJacobianCache (J, FullStructure (), alg, nothing , true , 0.0 )
56
+ return InitializedApproximateJacobianCache (J, FullStructure (), alg, nothing , true ,
57
+ internalnorm)
53
58
end
54
59
55
60
function (cache:: InitializedApproximateJacobianCache )(alg:: BroydenLowRankInitialization , fu,
56
61
u)
62
+ α = __initial_alpha (alg. alpha, u, fu, cache. internalnorm)
57
63
cache. J. idx = 0
64
+ cache. J. alpha = inv (α)
58
65
return
59
66
end
60
67
61
68
"""
62
- BroydenLowRankJacobian{T}(U, Vᵀ, idx, cache)
69
+ BroydenLowRankJacobian{T}(U, Vᵀ, idx, cache, alpha )
63
70
64
71
Low Rank Approximation of the Jacobian Matrix. Currently only used for
65
72
[`LimitedMemoryBroyden`](@ref). This computes the Jacobian as ``U \\ times V^T``.
@@ -69,6 +76,7 @@ Low Rank Approximation of the Jacobian Matrix. Currently only used for
69
76
Vᵀ
70
77
idx:: Int
71
78
cache
79
+ alpha
72
80
end
73
81
74
82
__safe_inv!! (workspace, op:: BroydenLowRankJacobian ) = op # Already Inverted form
@@ -88,61 +96,61 @@ for op in (:adjoint, :transpose)
88
96
# FIXME : adjoint might be a problem here. Fix if a complex number issue shows up
89
97
@eval function Base. $ (op)(operator:: BroydenLowRankJacobian{T} ) where {T}
90
98
return BroydenLowRankJacobian {T} (operator. Vᵀ, operator. U,
91
- operator. idx, operator. cache)
99
+ operator. idx, operator. cache, operator . alpha )
92
100
end
93
101
end
94
102
95
103
# Storing the transpose to ensure contiguous memory on splicing
96
104
function BroydenLowRankJacobian (fu:: StaticArray{S2, T2} , u:: StaticArray{S1, T1} ;
97
- threshold:: Val{Th} = Val (10 )) where {S1, S2, T1, T2, Th}
105
+ alpha = true , threshold:: Val{Th} = Val (10 )) where {S1, S2, T1, T2, Th}
98
106
T = promote_type (T1, T2)
99
107
fuSize, uSize = Size (fu), Size (u)
100
108
U = MArray {Tuple{prod(fuSize), Th}, T} (undef)
101
109
Vᵀ = MArray {Tuple{prod(uSize), Th}, T} (undef)
102
- return BroydenLowRankJacobian {T} (U, Vᵀ, 0 , nothing )
110
+ return BroydenLowRankJacobian {T} (U, Vᵀ, 0 , nothing , T (alpha) )
103
111
end
104
112
105
- function BroydenLowRankJacobian (fu, u; threshold:: Int = 10 )
113
+ function BroydenLowRankJacobian (fu, u; threshold:: Int = 10 , alpha = true )
106
114
T = promote_type (eltype (u), eltype (fu))
107
115
U = similar (fu, T, length (fu), threshold)
108
116
Vᵀ = similar (u, T, length (u), threshold)
109
117
cache = similar (u, T, threshold)
110
- return BroydenLowRankJacobian {T} (U, Vᵀ, 0 , cache)
118
+ return BroydenLowRankJacobian {T} (U, Vᵀ, 0 , cache, T (alpha) )
111
119
end
112
120
113
121
function Base.:* (J:: BroydenLowRankJacobian , x:: AbstractVector )
114
122
J. idx == 0 && return - x
115
123
cache, U, Vᵀ = __get_components (J)
116
- return U * (Vᵀ * x) .- x
124
+ return U * (Vᵀ * x) .- J . alpha .* x
117
125
end
118
126
119
127
function LinearAlgebra. mul! (y:: AbstractVector , J:: BroydenLowRankJacobian , x:: AbstractVector )
120
128
if J. idx == 0
121
- @. y = - x
129
+ @. y = - J . alpha * x
122
130
return y
123
131
end
124
132
cache, U, Vᵀ = __get_components (J)
125
133
@bb cache = Vᵀ × x
126
134
mul! (y, U, cache)
127
- @bb @. y -= x
135
+ @bb @. y -= J . alpha * x
128
136
return y
129
137
end
130
138
131
139
function Base.:* (x:: AbstractVector , J:: BroydenLowRankJacobian )
132
140
J. idx == 0 && return - x
133
141
cache, U, Vᵀ = __get_components (J)
134
- return Vᵀ' * (U' * x) .- x
142
+ return Vᵀ' * (U' * x) .- J . alpha .* x
135
143
end
136
144
137
145
function LinearAlgebra. mul! (y:: AbstractVector , x:: AbstractVector , J:: BroydenLowRankJacobian )
138
146
if J. idx == 0
139
- @. y = - x
147
+ @. y = - J . alpha * x
140
148
return y
141
149
end
142
150
cache, U, Vᵀ = __get_components (J)
143
151
@bb cache = transpose (U) × x
144
152
mul! (y, transpose (Vᵀ), cache)
145
- @bb @. y -= x
153
+ @bb @. y -= J . alpha * x
146
154
return y
147
155
end
148
156
0 commit comments