[writen by chatgpt]
Summary
Recent full test runs fail with Roots.ConvergenceFailed("Algorithm failed to converge") from quantile/root-finding paths that used to pass.
This started showing up after dependency updates around Roots/Optim. It may be a Roots 3 behavior/tolerance change, or it may expose that our quantile calls rely on overly strict/default convergence behavior.
Observed failures
From the attached test output:
BC2Copula sampling through ExtremeDist.quantile:
Roots.ConvergenceFailed("Algorithm failed to converge")
Stacktrace:
Roots.find_zero(..., Roots.Brent())
quantile @ src/UnivariateDistribution/ExtremeDist.jl:42
rand @ src/UnivariateDistribution/ExtremeDist.jl:47
_rand!(::StableRNGs.LehmerRNG, ::BC2Copula{Float64}, ::Matrix{Float64})
@ src/ExtremeValueCopula.jl:80
Examples in the test output include:
BC2Copula{Float64}(a = 0.5, b = 0.3)
BC2Copula{Float64}(a = 0.5, b = 0.5)
BC2Copula{Float64}(a = 0.5516353577049822, b = 0.33689370624999193)
BC2Copula{Float64}(a = 0.7, b = 0.3)
BC2Copula{Float64}(a = 0.6, b = 0.8)
The relevant code currently does:
Roots.find_zero(x -> Distributions.cdf(d, x) - p,
(eps(), 1.0 - eps()), Roots.Brent())
- Bernstein inverse Rosenblatt through Distributions mixture quantile:
Roots.ConvergenceFailed("Algorithm failed to converge")
Stacktrace:
Roots.find_zero(...)
quantile_bisect @ Distributions/src/quantilealgs.jl:18
quantile @ Distributions/src/mixtures/mixturemodel.jl:449
inverse_rosenblatt(::BernsteinCopula{2}, ...)
@ src/Conditioning.jl:340
The failing test is the generic roundtrip:
rosenblatt ∘ inverse_rosenblatt = Id
Version trail
Current local manifest / failing run:
- Julia:
1.12.1
- Copulas:
0.1.35
- Roots:
3.0.2
- Optim:
2.2.1
- Distributions:
0.25.129
Recent compat history from this repo:
- Before
ad9988b3 / PR #354, Project.toml had Roots = "1, 2".
- After
ad9988b3 / PR #354, Project.toml has Roots = "1, 2, 3".
- Before
a75b08cf / PR #355, Project.toml had Optim = "1.13.2".
- After
a75b08cf / PR #355, Project.toml has Optim = "2".
Manifest.toml is not tracked historically in this repo, so I could not recover the exact old resolved Roots version from git. Installed local Roots versions include:
2.2.10 installed 2025-09-02
3.0.0 installed 2026-05-11
3.0.2 installed 2026-07-10
Given the old compat was Roots = "1, 2", the previous resolver target was presumably a Roots 2.x release, likely 2.2.10 in this local environment.
Initial hypothesis
This may be due to Roots 3 returning NaN / throwing ConvergenceFailed more readily when the bracketing solver reaches a plateau or a very tight tolerance near floating-point resolution. The two failure paths both rely on library quantile/root-finding defaults:
- our explicit
Roots.find_zero(..., Roots.Brent()) in ExtremeDist.quantile;
- Distributions'
quantile_bisect, which now delegates to find_zero(..., ITP()) and relies on Roots defaults.
Things to investigate
- Reproduce with Roots 3.0.2 versus Roots 2.2.10.
- Check whether
ExtremeDist.quantile should use a more robust local bisection/ITP call with explicit tolerances or endpoint guards.
- Check whether the Bernstein failures are upstream in Distributions/Roots defaults or whether our
inverse_rosenblatt passes probabilities close enough to a flat/atomic mixture boundary that we should clamp or handle endpoints.
[writen by chatgpt]
Summary
Recent full test runs fail with
Roots.ConvergenceFailed("Algorithm failed to converge")from quantile/root-finding paths that used to pass.This started showing up after dependency updates around Roots/Optim. It may be a Roots 3 behavior/tolerance change, or it may expose that our quantile calls rely on overly strict/default convergence behavior.
Observed failures
From the attached test output:
BC2Copulasampling throughExtremeDist.quantile:Examples in the test output include:
BC2Copula{Float64}(a = 0.5, b = 0.3)BC2Copula{Float64}(a = 0.5, b = 0.5)BC2Copula{Float64}(a = 0.5516353577049822, b = 0.33689370624999193)BC2Copula{Float64}(a = 0.7, b = 0.3)BC2Copula{Float64}(a = 0.6, b = 0.8)The relevant code currently does:
The failing test is the generic roundtrip:
Version trail
Current local manifest / failing run:
1.12.10.1.353.0.22.2.10.25.129Recent compat history from this repo:
ad9988b3/ PR#354,Project.tomlhadRoots = "1, 2".ad9988b3/ PR#354,Project.tomlhasRoots = "1, 2, 3".a75b08cf/ PR#355,Project.tomlhadOptim = "1.13.2".a75b08cf/ PR#355,Project.tomlhasOptim = "2".Manifest.tomlis not tracked historically in this repo, so I could not recover the exact old resolved Roots version from git. Installed local Roots versions include:2.2.10installed 2025-09-023.0.0installed 2026-05-113.0.2installed 2026-07-10Given the old compat was
Roots = "1, 2", the previous resolver target was presumably a Roots 2.x release, likely2.2.10in this local environment.Initial hypothesis
This may be due to Roots 3 returning
NaN/ throwingConvergenceFailedmore readily when the bracketing solver reaches a plateau or a very tight tolerance near floating-point resolution. The two failure paths both rely on library quantile/root-finding defaults:Roots.find_zero(..., Roots.Brent())inExtremeDist.quantile;quantile_bisect, which now delegates tofind_zero(..., ITP())and relies on Roots defaults.Things to investigate
ExtremeDist.quantileshould use a more robust local bisection/ITP call with explicit tolerances or endpoint guards.inverse_rosenblattpasses probabilities close enough to a flat/atomic mixture boundary that we should clamp or handle endpoints.