diff --git a/HISTORY.md b/HISTORY.md index ee680fea1..475b345f9 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -2,6 +2,10 @@ Fixed `apply_transform_strategy` to return only the target transform's forward log-Jacobian when converting a `DynamicLink` value to a `FixedTransform` target. It previously added the source's forward Jacobian as well, so `getlogjac`, `getlogjoint_internal`, and `getlogprior_internal` were wrong whenever linked values were fed into a fixed-transform strategy. See [#1407](https://github.com/TuringLang/DynamicPPL.jl/issues/1407). +`marginalize` now constructs its default marginalizer with an explicit `Optim.LBFGS()`. The previous default, `MarginalLogDensities.LaplaceApprox()`, threw an `UndefVarError` once OptimizationOptimJL 0.4.19 stopped re-exporting `LBFGS`. See [#1447](https://github.com/TuringLang/DynamicPPL.jl/issues/1447). + +`LogDensityProblems.logdensity(ldf, x)` now throws an `ArgumentError` when `x` does not have the dimension the `LogDensityFunction` was constructed with. A shorter vector previously threw a `BoundsError` from inside model evaluation, and a longer one silently returned the log density of the first `dimension(ldf)` elements. + # 0.42.4 `arraydist` on a vector of univariate distributions now builds its `Distributions.Product` through the inner constructor instead of `Product(dists)`, which is deprecated. The outer constructor calls `Base.depwarn`, and that walks a backtrace on every call, so models with an `arraydist` likelihood paid it once per evaluation. The return type is unchanged. diff --git a/src/logdensityfunction.jl b/src/logdensityfunction.jl index 81f373039..a6aa7e386 100644 --- a/src/logdensityfunction.jl +++ b/src/logdensityfunction.jl @@ -529,6 +529,13 @@ end @inline function LogDensityProblems.logdensity( ldf::LogDensityFunction, params::AbstractVector{<:Real} ) + if length(params) != ldf._dim + throw( + ArgumentError( + "The length of the input vector is $(length(params)), but the LogDensityFunction expects a vector of length $(ldf._dim) based on the ranges that were extracted when the LogDensityFunction was constructed.", + ), + ) + end return logdensity_internal( params, ldf.model, diff --git a/test/logdensityfunction.jl b/test/logdensityfunction.jl index 66fe01ed1..66f5b6194 100644 --- a/test/logdensityfunction.jl +++ b/test/logdensityfunction.jl @@ -180,6 +180,18 @@ end @test LogDensityProblems.dimension(ldf) == 4 end + @testset "logdensity checks the input length" begin + @model function m3() + x ~ Normal() + y ~ Normal() + return nothing + end + ldf = DynamicPPL.LogDensityFunction(m3()) + @test LogDensityProblems.logdensity(ldf, zeros(2)) isa Real + @test_throws ArgumentError LogDensityProblems.logdensity(ldf, zeros(1)) + @test_throws ArgumentError LogDensityProblems.logdensity(ldf, zeros(3)) + end + @testset "capabilities" begin @model f() = x ~ Normal() model = f()