11"""
22 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 )
44
55An implementation of `LimitedMemoryBroyden` [ziani2008autoadaptative](@cite) with resetting
66and line search.
@@ -12,54 +12,61 @@ and line search.
1212 `sqrt(eps(real(eltype(u))))`.
1313 - `threshold`: the number of vectors to store in the low rank approximation. Defaults
1414 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))`.
1517"""
1618function 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 )
1820 threshold isa Int && (threshold = Val (threshold))
1921 return ApproximateJacobianSolveAlgorithm {false, :LimitedMemoryBroyden} (; linesearch,
2022 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))
2325end
2426
2527"""
26- BroydenLowRankInitialization{T}(threshold::Val{T})
28+ BroydenLowRankInitialization{T}(alpha, threshold::Val{T})
2729
2830An initialization for `LimitedMemoryBroyden` that uses a low rank approximation of the
2931Jacobian. The low rank updates to the Jacobian matrix corresponds to what SciPy calls
3032["simple"](https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.broyden2.html#scipy-optimize-broyden2).
3133"""
32- struct BroydenLowRankInitialization{T} <: AbstractJacobianInitialization
34+ @concrete struct BroydenLowRankInitialization{T} <: AbstractJacobianInitialization
35+ alpha
3336 threshold:: Val{T}
3437end
3538
3639jacobian_initialized_preinverted (:: BroydenLowRankInitialization ) = true
3740
3841function 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 }
4144 if u isa Number # Use the standard broyden
4245 return init (prob, IdentityInitialization (true , FullStructure ()), solver, f, fu, u,
4346 p; maxiters, kwargs... )
4447 end
4548 # Pay to cost of slightly more allocations to prevent type-instability for StaticArrays
49+ α = inv (__initial_alpha (alg. alpha, u, fu, internalnorm))
4650 if u isa StaticArray
47- J = BroydenLowRankJacobian (fu, u; alg. threshold)
51+ J = BroydenLowRankJacobian (fu, u; alg. threshold, alpha = α )
4852 else
4953 threshold = min (_unwrap_val (alg. threshold), maxiters)
50- J = BroydenLowRankJacobian (fu, u; threshold)
54+ J = BroydenLowRankJacobian (fu, u; threshold, alpha = α )
5155 end
52- return InitializedApproximateJacobianCache (J, FullStructure (), alg, nothing , true , 0.0 )
56+ return InitializedApproximateJacobianCache (J, FullStructure (), alg, nothing , true ,
57+ internalnorm)
5358end
5459
5560function (cache:: InitializedApproximateJacobianCache )(alg:: BroydenLowRankInitialization , fu,
5661 u)
62+ α = __initial_alpha (alg. alpha, u, fu, cache. internalnorm)
5763 cache. J. idx = 0
64+ cache. J. alpha = inv (α)
5865 return
5966end
6067
6168"""
62- BroydenLowRankJacobian{T}(U, Vᵀ, idx, cache)
69+ BroydenLowRankJacobian{T}(U, Vᵀ, idx, cache, alpha )
6370
6471Low Rank Approximation of the Jacobian Matrix. Currently only used for
6572[`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
6976 Vᵀ
7077 idx:: Int
7178 cache
79+ alpha
7280end
7381
7482__safe_inv!! (workspace, op:: BroydenLowRankJacobian ) = op # Already Inverted form
@@ -88,61 +96,61 @@ for op in (:adjoint, :transpose)
8896 # FIXME : adjoint might be a problem here. Fix if a complex number issue shows up
8997 @eval function Base. $ (op)(operator:: BroydenLowRankJacobian{T} ) where {T}
9098 return BroydenLowRankJacobian {T} (operator. Vᵀ, operator. U,
91- operator. idx, operator. cache)
99+ operator. idx, operator. cache, operator . alpha )
92100 end
93101end
94102
95103# Storing the transpose to ensure contiguous memory on splicing
96104function 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}
98106 T = promote_type (T1, T2)
99107 fuSize, uSize = Size (fu), Size (u)
100108 U = MArray {Tuple{prod(fuSize), Th}, T} (undef)
101109 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) )
103111end
104112
105- function BroydenLowRankJacobian (fu, u; threshold:: Int = 10 )
113+ function BroydenLowRankJacobian (fu, u; threshold:: Int = 10 , alpha = true )
106114 T = promote_type (eltype (u), eltype (fu))
107115 U = similar (fu, T, length (fu), threshold)
108116 Vᵀ = similar (u, T, length (u), threshold)
109117 cache = similar (u, T, threshold)
110- return BroydenLowRankJacobian {T} (U, Vᵀ, 0 , cache)
118+ return BroydenLowRankJacobian {T} (U, Vᵀ, 0 , cache, T (alpha) )
111119end
112120
113121function Base.:* (J:: BroydenLowRankJacobian , x:: AbstractVector )
114122 J. idx == 0 && return - x
115123 cache, U, Vᵀ = __get_components (J)
116- return U * (Vᵀ * x) .- x
124+ return U * (Vᵀ * x) .- J . alpha .* x
117125end
118126
119127function LinearAlgebra. mul! (y:: AbstractVector , J:: BroydenLowRankJacobian , x:: AbstractVector )
120128 if J. idx == 0
121- @. y = - x
129+ @. y = - J . alpha * x
122130 return y
123131 end
124132 cache, U, Vᵀ = __get_components (J)
125133 @bb cache = Vᵀ × x
126134 mul! (y, U, cache)
127- @bb @. y -= x
135+ @bb @. y -= J . alpha * x
128136 return y
129137end
130138
131139function Base.:* (x:: AbstractVector , J:: BroydenLowRankJacobian )
132140 J. idx == 0 && return - x
133141 cache, U, Vᵀ = __get_components (J)
134- return Vᵀ' * (U' * x) .- x
142+ return Vᵀ' * (U' * x) .- J . alpha .* x
135143end
136144
137145function LinearAlgebra. mul! (y:: AbstractVector , x:: AbstractVector , J:: BroydenLowRankJacobian )
138146 if J. idx == 0
139- @. y = - x
147+ @. y = - J . alpha * x
140148 return y
141149 end
142150 cache, U, Vᵀ = __get_components (J)
143151 @bb cache = transpose (U) × x
144152 mul! (y, transpose (Vᵀ), cache)
145- @bb @. y -= x
153+ @bb @. y -= J . alpha * x
146154 return y
147155end
148156
0 commit comments