Hessians
Hessians are a crucial ingredient in NewtonSolver
s and SimpleSolvers.NewtonOptimizerState
s.
using SimpleSolvers
using LinearAlgebra: norm
x = rand(3)
obj = MultivariateObjective(x -> norm(x - vcat(0., 0., 1.)) ^ 2, x)
hes = HessianAutodiff(obj, x)
HessianAutodiff{Float64, Main.var"#1#2", Matrix{Float64}, ForwardDiff.HessianConfig{ForwardDiff.Tag{Main.var"#1#2", Float64}, Float64, 3, Vector{ForwardDiff.Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}, ForwardDiff.Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}, Float64, 3}, 3}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}, Float64, 3}}}}(Main.var"#1#2"(), [NaN NaN NaN; NaN NaN NaN; NaN NaN NaN], ForwardDiff.HessianConfig{ForwardDiff.Tag{Main.var"#1#2", Float64}, Float64, 3, Vector{ForwardDiff.Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}, ForwardDiff.Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}, Float64, 3}, 3}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}, Float64, 3}}}(ForwardDiff.JacobianConfig{ForwardDiff.Tag{Main.var"#1#2", Float64}, Float64, 3, Vector{ForwardDiff.Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}, Float64, 3}}}((Partials(1.0, 0.0, 0.0), Partials(0.0, 1.0, 0.0), Partials(0.0, 0.0, 1.0)), ForwardDiff.Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}, Float64, 3}[Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(2.3873e-320,2.71615463615e-312,1.02534836643315e-310,1.02534836643315e-310), Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(1.02534836643315e-310,1.02534836653276e-310,1.02534836643315e-310,2.71615461307e-312), Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(1.0253483661944e-310,1.0255605660123e-310,1.02556056608186e-310,1.0253483665075e-310)]), ForwardDiff.GradientConfig{ForwardDiff.Tag{Main.var"#1#2", Float64}, ForwardDiff.Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}, Float64, 3}, 3, Vector{ForwardDiff.Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}, ForwardDiff.Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}, Float64, 3}, 3}}}((Partials(Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(1.0,0.0,0.0,0.0), Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(0.0,0.0,0.0,0.0), Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(0.0,0.0,0.0,0.0)), Partials(Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(0.0,0.0,0.0,0.0), Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(1.0,0.0,0.0,0.0), Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(0.0,0.0,0.0,0.0)), Partials(Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(0.0,0.0,0.0,0.0), Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(0.0,0.0,0.0,0.0), Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(1.0,0.0,0.0,0.0))), ForwardDiff.Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}, ForwardDiff.Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}, Float64, 3}, 3}[Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(6.9471846511176e-310,6.947184651097e-310,6.94718465429857e-310,6.94718465110177e-310),Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(6.9471846510986e-310,6.9471846543033e-310,6.94718465111283e-310,6.94718465111125e-310),Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(6.94718465112074e-310,6.9471846511223e-310,6.9471846511239e-310,6.9471846511255e-310),Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(6.94718465112706e-310,6.94718465112864e-310,6.94718465111916e-310,6.94718465173417e-310)), Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(6.94718465173575e-310,6.94718465173733e-310,6.9471846517389e-310,6.9471846517405e-310),Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(0.0,6.94718465161085e-310,6.9471846497516e-310,6.9471846497516e-310),Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(6.9472336220297e-310,6.94718464975e-310,6.94718465174208e-310,6.9471846517468e-310),Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(6.9471846497484e-310,5.0e-324,6.9471846517484e-310,6.94718465175e-310)), Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(6.94718465175156e-310,6.94718465175314e-310,6.9471846517563e-310,6.9471846517579e-310),Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(6.94718465174366e-310,6.94718464975316e-310,6.94718464975475e-310,6.94718464975633e-310),Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(6.9471846497579e-310,6.9471846497595e-310,6.94718464976107e-310,6.94718464976265e-310),Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}}(1.5e-323,3.5e-322,1.0e-323,8.4e-323))])))
An instance of HessianAutodiff
stores a Hessian matrix:
hes.H
3×3 Matrix{Float64}:
NaN NaN NaN
NaN NaN NaN
NaN NaN NaN
The instance of HessianAutodiff
can be called:
hes(x)
3×3 Matrix{Float64}:
2.0 0.0 0.0
0.0 2.0 -1.11022e-16
5.55112e-17 1.11022e-16 2.0
Or equivalently with:
update!(hes, x)
This updates hes.H
:
hes.H
3×3 Matrix{Float64}:
2.0 0.0 0.0
0.0 2.0 -1.11022e-16
5.55112e-17 1.11022e-16 2.0
BFGS Hessian
using SimpleSolvers: initialize!
hes = HessianBFGS(obj, x)
initialize!(hes, x)
HessianBFGS{Float64, Vector{Float64}, Matrix{Float64}, MultivariateObjective{Float64, Vector{Float64}, Main.var"#1#2", GradientAutodiff{Float64, Main.var"#1#2", ForwardDiff.GradientConfig{ForwardDiff.Tag{Main.var"#1#2", Float64}, Float64, 3, Vector{ForwardDiff.Dual{ForwardDiff.Tag{Main.var"#1#2", Float64}, Float64, 3}}}}, Float64, Vector{Float64}}}(MultivariateObjective (for vector-valued quantities only the first component is printed):
f(x) = NaN
g(x)₁ = 3.82e-01
x_f₁ = NaN
x_g₁ = 1.91e-01
number of f calls = 0
number of g calls = 1
, [NaN, NaN, NaN], [0.19090669902576285, 0.5256623915420473, 0.3905882754313441], [NaN, NaN, NaN], [NaN, NaN, NaN], [0.3818133980515257, 1.0513247830840946, -1.2188234491373118], [NaN, NaN, NaN], [1.0 0.0 0.0; 0.0 1.0 0.0; 0.0 0.0 1.0], [0.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 0.0], [0.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 0.0], [0.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 0.0], [0.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 0.0], [0.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 0.0])
For computational reasons we save the inverse of the Hessian, it can be accessed by calling inv
:
inv(hes)
3×3 Matrix{Float64}:
1.0 0.0 0.0
0.0 1.0 0.0
0.0 0.0 1.0
Similarly to HessianAutodiff
we can call update!
:
update!(hes, x)