Skip to content

Commit

Permalink
More sophisticated checks in restoreoptsum. (#775)
Browse files Browse the repository at this point in the history
Co-authored-by: Phillip Alday <phillip.alday@beacon.bio>
  • Loading branch information
dmbates and palday authored Jun 27, 2024
1 parent 34899cf commit a45fc14
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 8 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ docs/jmd
LocalPreferences.toml
benchmark.md

lcov.info
coverage/
5 changes: 5 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
MixedModels v4.25.1 Release Notes
==============================
- Use more sophisticated checks on property names in `restoreoptsum` to allow for optsums saved by pre-v4.25 versions to be used with this version and later. [#775]

MixedModels v4.25 Release Notes
==============================
- Add type notations in `pwrss(::LinearMixedModel)` and `logdet(::LinearMixedModel)` to enhance type inference. [#773]
Expand Down Expand Up @@ -538,3 +542,4 @@ Package dependencies
[#769]: https://github.com/JuliaStats/MixedModels.jl/issues/769
[#772]: https://github.com/JuliaStats/MixedModels.jl/issues/772
[#773]: https://github.com/JuliaStats/MixedModels.jl/issues/773
[#775]: https://github.com/JuliaStats/MixedModels.jl/issues/775
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "MixedModels"
uuid = "ff71e718-51f3-5ec2-a782-8ffcbfa3c316"
author = ["Phillip Alday <me@phillipalday.com>", "Douglas Bates <dmbates@gmail.com>", "Jose Bayoan Santiago Calderon <jbs3hp@virginia.edu>"]
version = "4.25.0"
version = "4.25.1"

[deps]
Arrow = "69666777-d1a9-59fb-9406-91d4454c9d45"
Expand Down
2 changes: 2 additions & 0 deletions src/MixedModels.jl
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ include("mimeshow.jl")
include("serialization.jl")
include("profile/profile.jl")

# COV_EXCL_START
@setup_workload begin
# Putting some things in `setup` can reduce the size of the
# precompile file and potentially make loading faster.
Expand All @@ -227,5 +228,6 @@ include("profile/profile.jl")
progress)
end
end
# COV_EXCL_STOP

end # module
31 changes: 24 additions & 7 deletions src/serialization.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,24 @@ function restoreoptsum!(
) where {T}
dict = JSON3.read(io)
ops = m.optsum
okay =
(setdiff(propertynames(ops), keys(dict)) == [:lowerbd]) &&
all(ops.lowerbd .≤ dict.initial) &&
all(ops.lowerbd .≤ dict.final)
if !okay
allowed_missing = (
:lowerbd, # never saved, -Inf not allowed in JSON
:xtol_zero_abs, # added in v4.25.0
:ftol_zero_abs, # added in v4.25.0
:sigma, # added in v4.1.0
:fitlog, # added in v4.1.0
)
nmdiff = setdiff(
propertynames(ops), # names in freshly created optsum
union!(Set(keys(dict)), allowed_missing), # names in saved optsum plus those we allow to be missing
)
if !isempty(nmdiff)
throw(ArgumentError(string("optsum names: ", nmdiff, " not found in io")))
end
if length(setdiff(allowed_missing, keys(dict))) > 1 # 1 because :lowerbd
@warn "optsum was saved with an older version of MixedModels.jl: consider resaving."
end
if any(ops.lowerbd .> dict.initial) || any(ops.lowerbd .> dict.final)
throw(ArgumentError("initial or final parameters in io do not satisfy lowerbd"))
end
for fld in (:feval, :finitial, :fmin, :ftol_rel, :ftol_abs, :maxfeval, :nAGQ, :REML)
Expand All @@ -33,12 +46,16 @@ function restoreoptsum!(
end
ops.optimizer = Symbol(dict.optimizer)
ops.returnvalue = Symbol(dict.returnvalue)
# provides compatibility with fits saved before the introduction of fixed sigma
# compatibility with fits saved before the introduction of various extensions
for prop in [:xtol_zero_abs, :ftol_zero_abs]
fallback = getproperty(ops, prop)
setproperty!(ops, prop, get(dict, prop, fallback))
end
ops.sigma = get(dict, :sigma, nothing)
fitlog = get(dict, :fitlog, nothing)
ops.fitlog = if isnothing(fitlog)
# compat with fits saved before fitlog
[(ops.initial, ops.finitial, ops.final, ops.fmin)]
[(ops.initial, ops.finitial), (ops.final, ops.fmin)]
else
[(convert(Vector{T}, first(entry)), T(last(entry))) for entry in fitlog]
end
Expand Down
100 changes: 100 additions & 0 deletions test/pls.jl
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,106 @@ end
@test loglikelihood(fm) loglikelihood(m)
@test bic(fm) bic(m)
@test coef(fm) coef(m)

# check restoreoptsum from older versions
m = LinearMixedModel(
@formula(reaction ~ 1 + days + (1 + days | subj)),
MixedModels.dataset(:sleepstudy),
)
iob = IOBuffer(
"""
{
"initial":[1.0,0.0,1.0],
"finitial":1784.642296192436,
"ftol_rel":1.0e-12,
"ftol_abs":1.0e-8,
"xtol_rel":0.0,
"xtol_abs":[1.0e-10,1.0e-10,1.0e-10],
"initial_step":[0.75,1.0,0.75],
"maxfeval":-1,
"maxtime":-1.0,
"feval":57,
"final":[0.9292213195402981,0.01816837807519162,0.22264487477788353],
"fmin":1751.9393444646712,
"optimizer":"LN_BOBYQA",
"returnvalue":"FTOL_REACHED",
"nAGQ":1,
"REML":false
}
"""
)
@test_logs((:warn,
r"optsum was saved with an older version of MixedModels.jl: consider resaving"),
restoreoptsum!(m, seekstart(iob)))
@test loglikelihood(fm) loglikelihood(m)
@test bic(fm) bic(m)
@test coef(fm) coef(m)
iob = IOBuffer(
"""
{
"initial":[1.0,0.0,1.0],
"finitial":1784.642296192436,
"ftol_rel":1.0e-12,
"xtol_rel":0.0,
"xtol_abs":[1.0e-10,1.0e-10,1.0e-10],
"initial_step":[0.75,1.0,0.75],
"maxfeval":-1,
"maxtime":-1.0,
"feval":57,
"final":[0.9292213195402981,0.01816837807519162,0.22264487477788353],
"fmin":1751.9393444646712,
"optimizer":"LN_BOBYQA",
"returnvalue":"FTOL_REACHED",
"nAGQ":1,
"REML":false,
"sigma":null,
"fitlog":[[[1.0,0.0,1.0],1784.642296192436]]
}
"""
)
@test_throws(ArgumentError("optsum names: [:ftol_abs] not found in io"),
restoreoptsum!(m, seekstart(iob)))

iob = IOBuffer(
"""
{
"initial":[1.0,0.0,1.0],
"finitial":1784.642296192436,
"ftol_rel":1.0e-12,
"ftol_abs":1.0e-8,
"xtol_rel":0.0,
"xtol_abs":[1.0e-10,1.0e-10,1.0e-10],
"initial_step":[0.75,1.0,0.75],
"maxfeval":-1,
"maxtime":-1.0,
"feval":57,
"final":[-0.9292213195402981,0.01816837807519162,0.22264487477788353],
"fmin":1751.9393444646712,
"optimizer":"LN_BOBYQA",
"returnvalue":"FTOL_REACHED",
"nAGQ":1,
"REML":false,
"sigma":null,
"fitlog":[[[1.0,0.0,1.0],1784.642296192436]]
}
"""
)
@test_throws(ArgumentError("initial or final parameters in io do not satisfy lowerbd"),
restoreoptsum!(m, seekstart(iob)))

# make sure new fields are correctly restored
mktemp() do path, io
m = deepcopy(last(models(:sleepstudy)))
m.optsum.xtol_zero_abs = 0.5
m.optsum.ftol_zero_abs = 0.5
saveoptsum(io, m)
m.optsum.xtol_zero_abs = 1.0
m.optsum.ftol_zero_abs = 1.0
restoreoptsum!(m, seekstart(io))
@test m.optsum.xtol_zero_abs == 0.5
@test m.optsum.ftol_zero_abs == 0.5
end

end

@testset "profile" begin
Expand Down

2 comments on commit a45fc14

@palday
Copy link
Member

@palday palday commented on a45fc14 Jun 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/109969

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v4.25.1 -m "<description of version>" a45fc146d67233aa9d13fb3b0676e1dc1e6d9f37
git push origin v4.25.1

Please sign in to comment.