Adding a new pair-copula
A contributor who wants to make a Copulas.jl bivariate family work reliably inside vines should implement and test the conditional primitive contract.
Required contract
For a bivariate copula C::Copulas.Copula{2}, vines need:
_pair_logpdf(C, u, v, buf) # scalar log-density contribution
hfunc1(C, u, v) # F₁|₂(u | v)
hfunc2(C, u, v) # F₂|₁(v | u)
hinv1(C, q, v) # inverse in u, given v
hinv2(C, q, u) # inverse in v, given uThe expected identities are:
For singular families, generalized inverses are acceptable, but tests should encode the correct monotonic inequalities.
Step-by-step checklist
Confirm that the family exists and has valid
pdf,logpdf, andcdfinCopulas.jl.Check whether the generic
ForwardDiff/root-finding fallback is accurate enough.If the fallback is unstable, add specialized methods in an appropriate file under
src/PairCopulas/.Add a pair-copula test using
M.check_paircopula(C)or a singular-aware variant.Add at least one vine-level test using the family inside a small
CVineCopulaorDVineCopula.Update
docs/src/paircopulas/supported_families.md.Add a short example if the family has special interpretation.
Where should code go?
| Family type | Suggested file |
|---|---|
| Elliptical | src/PairCopulas/Ellipticals/<Family>.jl |
| Archimedean or BB | src/PairCopulas/Archimedeans/<Family>.jl |
| Extreme-value | src/PairCopulas/ExtremeValue/ExtremeValueCopula.jl |
| Survival/rotated/miscellaneous | src/PairCopulas/Miscellaneous/<Family>.jl |
Example skeleton
@inline function _pair_logpdf(C::Copulas.SomeCopula{2}, u::Real, v::Real, buf::Vector{Float64})
# return log c(u,v) without allocating if possible
end
@inline function hfunc1(C::Copulas.SomeCopula{2}, u::Real, v::Real)
u, v = _clp(u), _clp(v)
# return F_{1|2}(u | v)
end
@inline function hfunc2(C::Copulas.SomeCopula{2}, u::Real, v::Real)
u, v = _clp(u), _clp(v)
# return F_{2|1}(v | u)
end
@inline hfunc1(C::Copulas.SomeCopula{2}, uv::Tuple{<:Real,<:Real}) = hfunc1(C, uv[1], uv[2])
@inline hfunc2(C::Copulas.SomeCopula{2}, uv::Tuple{<:Real,<:Real}) = hfunc2(C, uv[1], uv[2])
function hinv1(C::Copulas.SomeCopula{2}, q::Real, v::Real)
q, v = _clp(q), _clp(v)
# return u such that hfunc1(C, u, v) ≈ q
end
function hinv2(C::Copulas.SomeCopula{2}, q::Real, u::Real)
q, u = _clp(q), _clp(u)
# return v such that hfunc2(C, u, v) ≈ q
endDo not overpromise support
A family should move from “exists in Copulas.jl” to “supported in VineCopulas.jl” only after the conditional and inverse conditional primitives pass tests in the vine interface.