From 8253801949ce809e88ab8285120a3b723717370c Mon Sep 17 00:00:00 2001 From: "William S. Moses" Date: Fri, 12 Sep 2025 17:14:30 -0500 Subject: [PATCH 1/6] Fix step size calculation if some results are non-deterministic (inf derivative) or nan --- src/methods.jl | 9 +++++++++ test/grad.jl | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/methods.jl b/src/methods.jl index f3d8ea7..9958446 100644 --- a/src/methods.jl +++ b/src/methods.jl @@ -371,11 +371,20 @@ function estimate_step( return _limit_step(m, x, step, acc) end +function finite_or_zero(fs::AbstractArray{<:Number}) + ifelse.(isfinite.(fs), fs, zero(fs)) +end + +function finite_or_zero(fs::AbstractArray{<:AbstractArray}) + finite_or_zero.(fs) +end + function _estimate_magnitudes( m::FiniteDifferenceMethod{P,Q}, f::TF, x::T, ) where {P,Q,TF,T<:AbstractFloat} step = first(estimate_step(m, f, x)) fs = _eval_function(m, f, x, step) + fs = finite_or_zero(fs) # Estimate magnitude of `∇f` in a neighbourhood of `x`. ∇fs = SVector{3}( _compute_estimate(m, fs, x, step, m.coefs_neighbourhood[1]), diff --git a/test/grad.jl b/test/grad.jl index 095777e..757d1df 100644 --- a/test/grad.jl +++ b/test/grad.jl @@ -217,3 +217,35 @@ using FiniteDifferences: grad, jacobian, _jvp, jvp, j′vp, _j′vp, to_vec @test [real(ȳ), imag(ȳ)] ≈ Jy'z̄_vec end end + +using LinearAlgebra + +function partial_nan_returning(x) + y = Matrix{Float64}(undef, 5, 5) + y .= NaN + y = Hermitian(y) + y .= x + return parent(y) +end + +randvar = 1 +function partial_nondet_returning(x) + global randvar + y = Matrix{Float64}(undef, 5, 5) + y .= randvar + randvar += 1 + y = Hermitian(y) + y .= x + return parent(y) +end + +@testset "jvp: Estimate step correctly for when some terms are nan/infinite" begin + fdm = FiniteDifferences.central_fdm(5, 1) + res = jvp(fdm, partial_nan_returning, 3.1, 2.7) + @show res + @test Hermitian(res) .≈ 2.7 + + res = jvp(fdm, partial_nondet_returning, 3.1, 2.7) + @show res + @test Hermitian(res) .≈ 2.7 +end From 539ee50d3384834f62eff852a664bde36d094a58 Mon Sep 17 00:00:00 2001 From: "William S. Moses" Date: Fri, 12 Sep 2025 17:17:41 -0500 Subject: [PATCH 2/6] fix --- Project.toml | 2 +- test/grad.jl | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Project.toml b/Project.toml index d6c26eb..a0a1ebc 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "FiniteDifferences" uuid = "26cc04aa-876d-5657-8c51-4c34ba976000" -version = "0.12.32" +version = "0.12.33" [deps] ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" diff --git a/test/grad.jl b/test/grad.jl index 757d1df..bce4520 100644 --- a/test/grad.jl +++ b/test/grad.jl @@ -241,11 +241,11 @@ end @testset "jvp: Estimate step correctly for when some terms are nan/infinite" begin fdm = FiniteDifferences.central_fdm(5, 1) - res = jvp(fdm, partial_nan_returning, 3.1, 2.7) + res = jvp(fdm, partial_nan_returning, (3.1, 2.7)) @show res @test Hermitian(res) .≈ 2.7 - - res = jvp(fdm, partial_nondet_returning, 3.1, 2.7) + + res = jvp(fdm, partial_nondet_returning, (3.1, 2.7)) @show res @test Hermitian(res) .≈ 2.7 end From 9a09989faf28f2e797930064b509fdeede6b52f2 Mon Sep 17 00:00:00 2001 From: "William S. Moses" Date: Fri, 12 Sep 2025 17:20:39 -0500 Subject: [PATCH 3/6] all --- test/grad.jl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/grad.jl b/test/grad.jl index bce4520..d8d09e7 100644 --- a/test/grad.jl +++ b/test/grad.jl @@ -242,10 +242,8 @@ end @testset "jvp: Estimate step correctly for when some terms are nan/infinite" begin fdm = FiniteDifferences.central_fdm(5, 1) res = jvp(fdm, partial_nan_returning, (3.1, 2.7)) - @show res - @test Hermitian(res) .≈ 2.7 + @test all(Hermitian(res) .≈ 2.7) res = jvp(fdm, partial_nondet_returning, (3.1, 2.7)) - @show res - @test Hermitian(res) .≈ 2.7 + @test all(Hermitian(res) .≈ 2.7) end From bab3793f6d8504113d8d19f3b563e6aec1962082 Mon Sep 17 00:00:00 2001 From: "William S. Moses" Date: Fri, 12 Sep 2025 17:32:44 -0500 Subject: [PATCH 4/6] more finite or zero --- src/methods.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/methods.jl b/src/methods.jl index 9958446..bcc993f 100644 --- a/src/methods.jl +++ b/src/methods.jl @@ -391,6 +391,7 @@ function _estimate_magnitudes( _compute_estimate(m, fs, x, step, m.coefs_neighbourhood[2]), _compute_estimate(m, fs, x, step, m.coefs_neighbourhood[3]) ) + ∇fs = finite_or_zero(∇fs) ∇f_magnitude = maximum(maximum.(abs, ∇fs)) # Estimate magnitude of `f` in a neighbourhood of `x`. f_magnitude = maximum(maximum.(abs, fs)) From 60e6855c3d9ee512d2afcc68ba229bbca2d3e092 Mon Sep 17 00:00:00 2001 From: "William S. Moses" Date: Fri, 12 Sep 2025 17:38:05 -0500 Subject: [PATCH 5/6] simpler --- test/grad.jl | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/test/grad.jl b/test/grad.jl index d8d09e7..13351a9 100644 --- a/test/grad.jl +++ b/test/grad.jl @@ -221,29 +221,22 @@ end using LinearAlgebra function partial_nan_returning(x) - y = Matrix{Float64}(undef, 5, 5) - y .= NaN - y = Hermitian(y) - y .= x - return parent(y) + return Float64[NaN, x] end randvar = 1 function partial_nondet_returning(x) global randvar - y = Matrix{Float64}(undef, 5, 5) - y .= randvar + y = Float64[randvar, x] randvar += 1 - y = Hermitian(y) - y .= x - return parent(y) + return y end @testset "jvp: Estimate step correctly for when some terms are nan/infinite" begin fdm = FiniteDifferences.central_fdm(5, 1) res = jvp(fdm, partial_nan_returning, (3.1, 2.7)) - @test all(Hermitian(res) .≈ 2.7) + @test res[1] ≈ 2.7 res = jvp(fdm, partial_nondet_returning, (3.1, 2.7)) - @test all(Hermitian(res) .≈ 2.7) + @test res[1] ≈ 2.7 end From 09c6767bc66c998ede8b4491b3859719d7731499 Mon Sep 17 00:00:00 2001 From: "William S. Moses" Date: Fri, 12 Sep 2025 17:39:04 -0500 Subject: [PATCH 6/6] fix --- test/grad.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/grad.jl b/test/grad.jl index 13351a9..ac9673c 100644 --- a/test/grad.jl +++ b/test/grad.jl @@ -235,8 +235,8 @@ end @testset "jvp: Estimate step correctly for when some terms are nan/infinite" begin fdm = FiniteDifferences.central_fdm(5, 1) res = jvp(fdm, partial_nan_returning, (3.1, 2.7)) - @test res[1] ≈ 2.7 + @test res[2] ≈ 2.7 res = jvp(fdm, partial_nondet_returning, (3.1, 2.7)) - @test res[1] ≈ 2.7 + @test res[2] ≈ 2.7 end