From 77dc871982e8a84008a8b6b8460921ff8aca5bca Mon Sep 17 00:00:00 2001 From: Penelope Yong Date: Thu, 10 Apr 2025 18:32:08 +0100 Subject: [PATCH 1/2] Error on NaN's --- HISTORY.md | 4 ++++ Project.toml | 2 +- src/debug_utils.jl | 28 ++++++++++++++-------------- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 5113a43ed..f43f543c3 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,9 @@ # DynamicPPL Changelog +## 0.35.7 + +`check_model_and_trace` now errors if any NaN's are encountered when evaluating the model. + ## 0.35.6 Fixed the implementation of `.~`, such that running a model with it no longer requires DynamicPPL itself to be loaded. diff --git a/Project.toml b/Project.toml index e49d11908..5790eaeb1 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "DynamicPPL" uuid = "366bfd00-2699-11ea-058f-f148b4cae6d8" -version = "0.35.6" +version = "0.35.7" [deps] ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b" diff --git a/src/debug_utils.jl b/src/debug_utils.jl index 328fe6983..76c097e94 100644 --- a/src/debug_utils.jl +++ b/src/debug_utils.jl @@ -231,20 +231,11 @@ function record_varname!(context::DebugContext, varname::VarName, dist) end end -# tilde -_isassigned(x::AbstractArray, i) = isassigned(x, i) -# HACK(torfjelde): Julia v1.7 only supports `isassigned(::AbstractArray, ::Int...)`. -# TODO(torfjelde): Determine exactly in which version this change was introduced. -if VERSION < v"v1.9.0-alpha1" - _isassigned(x::AbstractArray, inds::Tuple) = isassigned(x, inds...) - _isassigned(x::AbstractArray, idx::CartesianIndex) = _isassigned(x, Tuple(idx)) -end - _has_missings(x) = ismissing(x) function _has_missings(x::AbstractArray) # Can't just use `any` because `x` might contain `undef`. for i in eachindex(x) - if _isassigned(x, i) && _has_missings(x[i]) + if isassigned(x, i) && _has_missings(x[i]) return true end end @@ -293,9 +284,18 @@ function record_pre_tilde_observe!(context::DebugContext, left, dist, varinfo) # Check for `missing`s; these should not end up here. if _has_missings(left) error( - "Encountered missing value(s) in observe!\n" * - "Remember that using `missing` to de-condition a variable is only " * - "supported for univariate distributions, not for $dist", + "Encountered `missing` value(s) on the left-hand side" * + " of an observe statement. Using `missing` to de-condition" * + " a variable is only supported for univariate distributions," * + " not for $dist.", + ) + end + # Check for NaN's as well + if any(isnan, left) + error( + "Encountered a NaN value on the left-hand side of an" * + " observe statement; this may indicate that your data" * + " contain NaN values.", ) end end @@ -474,7 +474,7 @@ end Check that `model` is valid, warning about any potential issues. -See [`check_model_and_trace`](@ref) for more details on supported keword arguments +See [`check_model_and_trace`](@ref) for more details on supported keyword arguments and details of which types of checks are performed. # Returns From c215fb281c2798e99f79a9063ac0751784220a42 Mon Sep 17 00:00:00 2001 From: Penelope Yong Date: Thu, 10 Apr 2025 18:53:03 +0100 Subject: [PATCH 2/2] Add a test --- test/debug_utils.jl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/debug_utils.jl b/test/debug_utils.jl index d4f6601f5..b79ff1fbc 100644 --- a/test/debug_utils.jl +++ b/test/debug_utils.jl @@ -123,6 +123,17 @@ end end + @testset "NaN in data" begin + @model function demo_nan_in_data(x) + a ~ Normal() + for i in eachindex(x) + x[i] ~ Normal(a) + end + end + model = demo_nan_in_data([1.0, NaN]) + @test_throws ErrorException check_model(model; error_on_failure=true) + end + @testset "incorrect use of condition" begin @testset "missing in multivariate" begin @model function demo_missing_in_multivariate(x)