Skip to content
This repository was archived by the owner on Aug 22, 2025. It is now read-only.

Commit 40e877c

Browse files
committed
Change to centered difference
1 parent 0a47364 commit 40e877c

File tree

2 files changed

+23
-22
lines changed

2 files changed

+23
-22
lines changed

src/differentiation/compute_hessian_ad.jl

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,25 @@ struct ForwardColorHesCache{THS, THC, TI<:Integer, TD, TGF, TGC, TG}
66
buffer::TD
77
grad!::TGF
88
grad_config::TGC
9-
G::TG
10-
dG::TG
9+
G1::TG
10+
G2::TG
1111
end
1212

1313
function make_hessian_buffers(colorvec, x)
1414
ncolors = maximum(colorvec)
1515
D = hcat([float.(i .== colorvec) for i in 1:ncolors]...)
1616
buffer = similar(D)
17-
G = similar(x)
18-
dG = similar(x)
19-
return (;ncolors, D, buffer, G, dG)
17+
G1 = similar(x)
18+
G2 = similar(x)
19+
return (;ncolors, D, buffer, G1, G2)
2020
end
2121

2222
function ForwardColorHesCache(f,
2323
x::AbstractVector{<:Number},
2424
colorvec::AbstractVector{<:Integer}=eachindex(x),
2525
sparsity::Union{AbstractMatrix, Nothing}=nothing,
2626
g! = (G, x, grad_config) -> ForwardDiff.gradient!(G, f, x, grad_config))
27-
ncolors, D, buffer, G, dG = make_hessian_buffers(colorvec, x)
27+
ncolors, D, buffer, G, G2 = make_hessian_buffers(colorvec, x)
2828
grad_config = ForwardDiff.GradientConfig(f, x)
2929

3030
# If user supplied their own gradient function, make sure it has the right
@@ -42,7 +42,7 @@ function ForwardColorHesCache(f,
4242
if sparsity === nothing
4343
sparsity = sparse(ones(length(x), length(x)))
4444
end
45-
return ForwardColorHesCache(sparsity, colorvec, ncolors, D, buffer, g1!, grad_config, G, dG)
45+
return ForwardColorHesCache(sparsity, colorvec, ncolors, D, buffer, g1!, grad_config, G, G2)
4646
end
4747

4848
function numauto_color_hessian!(H::AbstractMatrix{<:Number},
@@ -52,11 +52,12 @@ function numauto_color_hessian!(H::AbstractMatrix{<:Number},
5252
safe = true)
5353
ϵ = cbrt(eps(eltype(x)))
5454
for j in 1:hes_cache.ncolors
55-
hes_cache.grad!(hes_cache.G, x, hes_cache.grad_config)
5655
x .+= ϵ .* @view hes_cache.D[:, j]
57-
hes_cache.grad!(hes_cache.dG, x, hes_cache.grad_config)
58-
x .-= ϵ .* @view hes_cache.D[:, j]
59-
hes_cache.buffer[:, j] .= (hes_cache.dG .- hes_cache.G) ./ ϵ
56+
hes_cache.grad!(hes_cache.G2, x, hes_cache.grad_config)
57+
x .-= 2ϵ .* @view hes_cache.D[:, j]
58+
hes_cache.grad!(hes_cache.G1, x, hes_cache.grad_config)
59+
hes_cache.buffer[:, j] .= (hes_cache.G2 .- hes_cache.G1) ./ 2ϵ
60+
x .+= ϵ .* @view hes_cache.D[:, j] #reset to original value
6061
end
6162
ii, jj, vv = findnz(hes_cache.sparsity)
6263
if safe

test/test_sparse_hessian.jl

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,26 @@ colors = matrix_colors(tril(sparsity))
1313
ncolors = maximum(colors)
1414
D = hcat([float.(i .== colors) for i in 1:ncolors]...)
1515
buffer = similar(D)
16-
G = zero(x)
17-
dG = zero(x)
16+
G1 = zero(x)
17+
G2 = zero(x)
1818

1919
buffers_tup = SparseDiffTools.make_hessian_buffers(colors, x)
2020
@test buffers_tup.ncolors == ncolors
2121
@test buffers_tup.D == D
2222
@test size(buffers_tup.buffer) == size(buffer)
2323
@test eltype(buffers_tup.buffer) == eltype(buffer)
2424
@test typeof(buffers_tup.buffer) == typeof(buffer)
25-
@test size(buffers_tup.G) == size(G)
26-
@test eltype(buffers_tup.G) == eltype(G)
27-
@test size(buffers_tup.dG) == size(dG)
28-
@test eltype(buffers_tup.dG) == eltype(dG)
25+
@test size(buffers_tup.G1) == size(G1)
26+
@test eltype(buffers_tup.G1) == eltype(G1)
27+
@test size(buffers_tup.G2) == size(G2)
28+
@test eltype(buffers_tup.G2) == eltype(G2)
2929

3030

3131
gconfig = ForwardDiff.GradientConfig(fscalar, x)
3232
g(x) = ForwardDiff.gradient(fscalar, x) # allocating
3333
g!(G, x, gconfig) = ForwardDiff.gradient!(G, fscalar, x, gconfig) # non-allocating
3434

35-
hescache1 = ForwardColorHesCache(sparsity, colors, ncolors, D, buffer, g!, gconfig, G, dG)
35+
hescache1 = ForwardColorHesCache(sparsity, colors, ncolors, D, buffer, g!, gconfig, G1, G2)
3636
hescache2 = ForwardColorHesCache(fscalar, x, colors, sparsity, g!)
3737
hescache3 = ForwardColorHesCache(fscalar, x, colors, sparsity)
3838
# custom gradient function
@@ -53,7 +53,7 @@ for name in [:sparsity, :colors, :ncolors, :D]
5353
# hescache5 is the default dense version, so only first axis will match
5454
@eval @test size(hescache1.$name, 1) == size(hescache5.$name, 1)
5555
end
56-
for name in [:buffer, :G, :dG]
56+
for name in [:buffer, :G1, :G2]
5757
@eval @test size(hescache1.$name) == size(hescache2.$name)
5858
@eval @test size(hescache1.$name) == size(hescache3.$name)
5959
@eval @test size(hescache1.$name) == size(hescache4.$name)
@@ -71,9 +71,9 @@ for (i, hescache) in enumerate([hescache1, hescache2, hescache3, hescache4, hesc
7171
H = numauto_color_hessian(fscalar, x, colors, sparsity)
7272
H1 = numauto_color_hessian(fscalar, x, hescache)
7373
H2 = numauto_color_hessian(fscalar, x)
74-
@test all(isapprox.(Hforward, H, rtol=1e-4))
75-
@test all(isapprox.(H, H1, rtol=1e-4))
76-
@test all(isapprox.(H2, H1, rtol=1e-4))
74+
@test all(isapprox.(Hforward, H, rtol=1e-6))
75+
@test all(isapprox.(H, H1, rtol=1e-6))
76+
@test all(isapprox.(H2, H1, rtol=1e-6))
7777

7878
H1 = similar(H)
7979
numauto_color_hessian!(H1, fscalar, x, collect(hescache.colors), hescache.sparsity)

0 commit comments

Comments
 (0)