From 6326eb58c24c907d131d45560cb1e96130b14009 Mon Sep 17 00:00:00 2001 From: Phillip Alday Date: Tue, 2 Sep 2025 15:34:03 +0200 Subject: [PATCH 1/4] fix lowerbd(::MixedModel) to work as singularity reference check --- Project.toml | 2 +- src/generalizedlinearmixedmodel.jl | 8 ++++++++ src/linearmixedmodel.jl | 10 +++++++++- src/mixedmodel.jl | 2 +- test/pls.jl | 1 + 5 files changed, 20 insertions(+), 3 deletions(-) diff --git a/Project.toml b/Project.toml index 0ed61fc22..ed744c8e8 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "MixedModels" uuid = "ff71e718-51f3-5ec2-a782-8ffcbfa3c316" author = ["Phillip Alday ", "Douglas Bates "] -version = "5.0.2" +version = "5.0.3" [deps] Arrow = "69666777-d1a9-59fb-9406-91d4454c9d45" diff --git a/src/generalizedlinearmixedmodel.jl b/src/generalizedlinearmixedmodel.jl index 36f67f97c..60b113e9f 100644 --- a/src/generalizedlinearmixedmodel.jl +++ b/src/generalizedlinearmixedmodel.jl @@ -523,6 +523,14 @@ function StatsAPI.loglikelihood(m::GeneralizedLinearMixedModel{T}) where {T} return accum - (mapreduce(u -> sum(abs2, u), +, m.u) + logdet(m)) / 2 end +""" + lowerbd(m::GeneralizedLinearMixedModel) + +Return the vector of _canonical_ lower bounds on the parameters, `θ`. + +Note that this method does not distinguish between constrained optimization and +unconstrained optimization with post-fit canonicalization. +""" lowerbd(m::GeneralizedLinearMixedModel) = lowerbd(m.LMM) # Base.Fix1 doesn't forward kwargs diff --git a/src/linearmixedmodel.jl b/src/linearmixedmodel.jl index 2f5ab3a20..d00ebd8b6 100644 --- a/src/linearmixedmodel.jl +++ b/src/linearmixedmodel.jl @@ -787,7 +787,15 @@ function StatsAPI.loglikelihood(m::LinearMixedModel) return -objective(m) / 2 end -lowerbd(m::LinearMixedModel) = foldl(vcat, lowerbd(c) for c in m.reterms) +""" + lowerbd(m::LinearMixedModel) + +Return the vector of _canonical_ lower bounds on the parameters, `θ`. + +Note that this method does not distinguish between constrained optimization and +unconstrained optimization with post-fit canonicalization. +""" +lowerbd(m::LinearMixedModel) = [(pm[2] == pm[3]) ? zero(T) : T(-Inf) for pm in m.parmap] function mkparmap(reterms::Vector{<:AbstractReMat{T}}) where {T} parmap = NTuple{3,Int}[] diff --git a/src/mixedmodel.jl b/src/mixedmodel.jl index efd498af1..036e65253 100644 --- a/src/mixedmodel.jl +++ b/src/mixedmodel.jl @@ -71,7 +71,7 @@ Equality comparisons are used b/c small non-negative θ values are replaced by 0 function issingular( m::MixedModel{T}, θ=m.θ; atol::Real=0, rtol::Real=atol > 0 ? 0 : √eps() ) where {T} - lb = [(pm[2] == pm[3]) ? zero(T) : T(-Inf) for pm in m.parmap] + lb = lowerbd(m) return _issingular(lb, θ; atol, rtol) end diff --git a/test/pls.jl b/test/pls.jl index d5d3af870..d86ceadcf 100644 --- a/test/pls.jl +++ b/test/pls.jl @@ -43,6 +43,7 @@ end @test length(fm1.A) == 3 @test size(fm1.reterms) == (1,) @test fm1.optsum.initial == ones(1) + @test lowerbd(fm1) == zeros(1) fm1.θ = ones(1) @test fm1.θ == ones(1) @test islinear(fm1) From 4ca4386fe42d6ee255cc495d1ef84008b1920f2c Mon Sep 17 00:00:00 2001 From: Phillip Alday Date: Tue, 2 Sep 2025 15:35:43 +0200 Subject: [PATCH 2/4] NEWS --- NEWS.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS.md b/NEWS.md index 8ce4cb1bd..5aa022cfb 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +MixedModels v5.0.3 Release Notes +============================== +- `lowerbd(::MixedModel)` returns the _canonical_ lower bounds of a model's parameters, i.e. the expected bounds after rectification in unconstrained optimization. [#864] + MixedModels v5.0.2 Release Notes ============================== - The default display and `confint` methods for bootstrap results from models without dispersion parameters has been fixed. [#861] @@ -695,3 +699,4 @@ Package dependencies [#858]: https://github.com/JuliaStats/MixedModels.jl/issues/858 [#860]: https://github.com/JuliaStats/MixedModels.jl/issues/860 [#861]: https://github.com/JuliaStats/MixedModels.jl/issues/861 +[#864]: https://github.com/JuliaStats/MixedModels.jl/issues/864 From e52e90571967bb8c499ee37bf5785efb3846622a Mon Sep 17 00:00:00 2001 From: Phillip Alday Date: Tue, 2 Sep 2025 15:36:53 +0200 Subject: [PATCH 3/4] missing type parameter --- src/linearmixedmodel.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linearmixedmodel.jl b/src/linearmixedmodel.jl index d00ebd8b6..3c3812186 100644 --- a/src/linearmixedmodel.jl +++ b/src/linearmixedmodel.jl @@ -795,7 +795,7 @@ Return the vector of _canonical_ lower bounds on the parameters, `θ`. Note that this method does not distinguish between constrained optimization and unconstrained optimization with post-fit canonicalization. """ -lowerbd(m::LinearMixedModel) = [(pm[2] == pm[3]) ? zero(T) : T(-Inf) for pm in m.parmap] +lowerbd(m::LinearMixedModel{T}) where {T} = [(pm[2] == pm[3]) ? zero(T) : T(-Inf) for pm in m.parmap] function mkparmap(reterms::Vector{<:AbstractReMat{T}}) where {T} parmap = NTuple{3,Int}[] From b323260b8c36fddd80d6811e5c856e90f70d9ec0 Mon Sep 17 00:00:00 2001 From: Phillip Alday Date: Tue, 2 Sep 2025 08:41:45 -0500 Subject: [PATCH 4/4] Update src/linearmixedmodel.jl Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- src/linearmixedmodel.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/linearmixedmodel.jl b/src/linearmixedmodel.jl index 3c3812186..de2b3bcc6 100644 --- a/src/linearmixedmodel.jl +++ b/src/linearmixedmodel.jl @@ -795,7 +795,8 @@ Return the vector of _canonical_ lower bounds on the parameters, `θ`. Note that this method does not distinguish between constrained optimization and unconstrained optimization with post-fit canonicalization. """ -lowerbd(m::LinearMixedModel{T}) where {T} = [(pm[2] == pm[3]) ? zero(T) : T(-Inf) for pm in m.parmap] +lowerbd(m::LinearMixedModel{T}) where {T} = + [(pm[2] == pm[3]) ? zero(T) : T(-Inf) for pm in m.parmap] function mkparmap(reterms::Vector{<:AbstractReMat{T}}) where {T} parmap = NTuple{3,Int}[]