Public Documentation
Documentation for ConvolvedDistributions's public interface.
Contents
Index
ConvolvedDistributions.AbstractCombinedDistributionConvolvedDistributions.AbstractSolverMethodConvolvedDistributions.AnalyticalSolverConvolvedDistributions.ConvolvedConvolvedDistributions.DifferenceConvolvedDistributions.GaussLegendreConvolvedDistributions.NumericSolverConvolvedDistributions._ccdf_ad_safeConvolvedDistributions._logccdf_ad_safeConvolvedDistributions._pdf_ad_safeConvolvedDistributions.convolve_seriesConvolvedDistributions.convolvedConvolvedDistributions.differenceConvolvedDistributions.gl_integrateConvolvedDistributions.integrate
Public API
ConvolvedDistributions.AbstractCombinedDistribution Type
abstract type AbstractCombinedDistribution{F<:Distributions.VariateForm, S<:Distributions.ValueSupport} <: Distributions.Distribution{F<:Distributions.VariateForm, S<:Distributions.ValueSupport}Supertype of the multi-base algebraic combinations: Convolved (the sum of independent components) and Difference (Z = X - Y). These combine two or more base distributions by an algebraic operation. Parametric on variate form and value support for symmetry with the wider EpiAware family model (Distribution{F, S}), so the univariate members keep their UnivariateDistribution{Continuous} supertype and existing dispatch is unchanged.
Required of a concrete subtype:
params(d);logpdf(d, x)finite on its support;Base.show(io, d).
Verify a subtype with ConvolvedDistributions.TestUtils.test_combined_interface, and family membership with ConvolvedDistributions.TestUtils.test_abstract_membership.
Fields
sourceConvolvedDistributions.AbstractSolverMethod Type
abstract type AbstractSolverMethodAbstract type for solver methods used in CDF/PDF computation.
Subtypes determine whether analytical solutions are preferred or numerical integration is forced.
Fields
sourceConvolvedDistributions.AnalyticalSolver Type
struct AnalyticalSolver{S} <: ConvolvedDistributions.AbstractSolverMethodSolver that attempts analytical solutions when available, falling back to numerical integration.
Stores a numerical integration solver for use when no analytical solution exists for a given distribution pair.
Fields
solver::Any: Fallback solver for when no analytical solution exists.
ConvolvedDistributions.Convolved Type
struct Convolved{C<:Tuple, M<:ConvolvedDistributions.AbstractSolverMethod} <: ConvolvedDistributions.AbstractCombinedDistribution{Distributions.Univariate, Distributions.Continuous}Distribution of a sum of independent random variables (a convolution).
Convolved represents
Components may have negative support (for example a Normal capturing pre-symptomatic transmission timing); minimum and maximum are the sums of the component supports, taking the value
CDF computation
The CDF is computed by integrating one component out against the CDF of the others:
where
Where an analytical convolution is available (Distributions.convolve applies, e.g. Normal+Normal, equal-scale Gamma, equal-rate Exponential) the two-component result is taken directly from the convolved distribution unless a NumericSolver method is set. All other cases use AD-safe fixed-node Gauss-Legendre quadrature: the integral is mapped from the fixed reference domain gl_integrate), which lets every AD backend specialise on the integrand's own type so component Duals and tangents propagate.
The method field selects the CDF/PDF backend: an AnalyticalSolver (the default) uses the analytic convolution when one exists and falls back to quadrature otherwise, while a NumericSolver forces the numeric quadrature path even when an analytic convolution exists; the latter is useful for validation and debugging.
See also
convolved: Constructor function
Fields
components::Tuple: Tuple of independent component distributions to be summed.method::ConvolvedDistributions.AbstractSolverMethod: Solver method choose the analytic vs numeric quadrature backend.
ConvolvedDistributions.Difference Type
struct Difference{X<:(Distributions.UnivariateDistribution), Y<:(Distributions.UnivariateDistribution), M<:ConvolvedDistributions.AbstractSolverMethod} <: ConvolvedDistributions.AbstractCombinedDistribution{Distributions.Univariate, Distributions.Continuous}Distribution of a difference of two independent random variables.
Difference represents X and Y are independent univariate distributions. It is the dual of Convolved (the sum X with the reflection of Y. Where a convolution gathers two delays into one longer gap, a difference is the signed gap between two events, so it arises as a derived observation (for example the offset between two independently timed measurements) rather than as a delay leaf.
Because the subtraction reflects Y, the support of Z is in general two-sided and can be negative: it runs from Z is therefore not a non-negative delay distribution; treat a Difference as an observation or derived quantity, not as a delay leaf.
Independence
The construction assumes X and Y are independent. The density, CDF, mean and variance below all rely on this; they are not correct for dependent components.
Density and CDF computation
The density is the cross-correlation of the two component densities:
and the CDF integrates X's CDF against Y's density:
For a Normal-Normal pair the closed form NumericSolver method is set. All other cases use AD-safe fixed-node Gauss-Legendre quadrature (gl_integrate), the same construction Convolved uses: the integral is mapped from the fixed reference domain Duals and tangents propagate.
The method field selects the backend: an AnalyticalSolver (the default) uses the analytic difference where one exists and falls back to quadrature otherwise, while a NumericSolver forces the numeric path even for a Normal-Normal pair (useful for validation).
See also
difference: Constructor functionConvolved: The dual sum
Fields
x::Distributions.UnivariateDistribution: The minuend component (theXinZ = X - Y).y::Distributions.UnivariateDistribution: The subtrahend component (theYinZ = X - Y).method::ConvolvedDistributions.AbstractSolverMethod: Solver method choose the analytic vs numeric quadrature backend.
ConvolvedDistributions.GaussLegendre Type
struct GaussLegendre{R}Fixed-node Gauss-Legendre quadrature solver (the package default).
Integrates with a Gauss-Legendre rule of n nodes, evaluated as a bare weighted dot product (see gl_integrate). The constant control flow and the accumulator type being seeded from the integrand make this the AD-safe default: every supported AD backend can differentiate through it, unlike adaptive schemes whose node count depends on integrand values.
The reference nodes and weights are built once at construction and held on the solver, so the differentiated hot path is a pure weighted sum with no shared mutable state. This matters for trace-based reverse-mode backends (Enzyme, ReverseDiff): resolving the rule through a mutated global cache inside the integrand crashes Enzyme reverse, so the rule travels with the solver instead.
n = 64 is accurate to about 1e-13 on the smooth, density-weighted integrands used in this package. This is the core default and needs no heavy dependency. Load Integrals.jl and pass an Integrals.jl algorithm (e.g. QuadGKJL()) when adaptive accuracy is wanted and AD is not.
See also
gl_integrate: The underlying quadrature reduction.integrate: The pluggable entry point dispatching on a solver.
Fields
n::Int64: Number of Gauss-Legendre nodes.rule::Any: The reference Gauss-Legendre rule (nodes/weights on[-1, 1]).
ConvolvedDistributions.NumericSolver Type
struct NumericSolver{S} <: ConvolvedDistributions.AbstractSolverMethodSolver that always uses numerical integration.
Forces numerical computation even when analytical solutions are available, useful for testing and validation.
The solver field contains the numerical integration solver to use.
Fields
solver::Any: Numerical integration solver to use.
ConvolvedDistributions._ccdf_ad_safe Function
_ccdf_ad_safe(
dist::Distributions.UnivariateDistribution,
u::Real
) -> AnyAD-safe ccdf(dist, u): the survival
_ccdf_ad_safe is the survival companion to _cdf_ad_safe. Generic dispatch falls through to Distributions.ccdf; the Gamma method routes through the AD-safe
Public (not exported): ComposedDistributions.jl imports it and adds methods for its racing-hazard composers, so this is a supported downstream extension point.
Arguments
dist: the distribution whose survival is evaluated.u: the evaluation point.
Examples
using ConvolvedDistributions: _ccdf_ad_safe
using Distributions
_ccdf_ad_safe(Gamma(2.0, 1.0), 3.0)ConvolvedDistributions._logccdf_ad_safe Function
_logccdf_ad_safe(
dist::Distributions.UnivariateDistribution,
u::Real
) -> AnyAD-safe logccdf(dist, u): the log survival
_logccdf_ad_safe is the log-survival companion to _logcdf_ad_safe. Generic dispatch falls through to Distributions.logccdf; the Gamma method routes through the AD-safe logccdf(::Gamma) calls _gammalogccdf, which has no ForwardDiff.Dual shape method and errors).
Public (not exported): ComposedDistributions.jl imports it and adds methods for its racing-hazard composers, so this is a supported downstream extension point.
Arguments
dist: the distribution whose log survival is evaluated.u: the evaluation point.
Examples
using ConvolvedDistributions: _logccdf_ad_safe
using Distributions
_logccdf_ad_safe(Gamma(2.0, 1.0), 3.0)ConvolvedDistributions._pdf_ad_safe Function
_pdf_ad_safe(
dist::Distributions.UnivariateDistribution,
t::Real
) -> AnyAD-safe pdf(dist, t) for the component density inside the quadratures.
_pdf_ad_safe is the density companion to _cdf_ad_safe: the numeric convolution and difference integrands evaluate component densities through it. Generic dispatch falls through to Distributions.pdf, and a downstream extension can add a method for a component whose stock pdf routes through functions that are not differentiable under the supported AD backends.
Public (not exported): ModifiedDistributions.jl hooks it so its modified components stay differentiable inside the quadrature, the same pattern as _ccdf_ad_safe.
Arguments
dist: the component distribution whose density is evaluated.t: the evaluation point.
Examples
using ConvolvedDistributions: _pdf_ad_safe
using Distributions
_pdf_ad_safe(Gamma(2.0, 1.0), 3.0)ConvolvedDistributions.convolve_series Function
convolve_series(
delay::Distributions.UnivariateDistribution,
series::AbstractVector{<:Real};
interval
) -> AnyConvolve a timeseries with the discretised delay PMF of a distribution.
convolve_series(delay, series) discretises delay to a PMF over the unit grid and returns the causal discrete convolution of series with that PMF, truncated to the series window. With series the expected events at times 0, 1, ..., t (e.g. infections), the result is the expected downstream event counts at the same times (the EpiNow2-style latent / renewal observation layer).
The PMF masses are the raw CDF differences
Unlike convolved, which combines distributions into a single Convolved distribution, this returns a numeric series; the separate verb keeps convolved strictly for distribution construction.
Arguments
delay: the delay distribution (anyUnivariateDistribution, including aConvolvedtotal delay).series: the input timeseries (expected events at unit-spaced times from 0).
Keyword Arguments
interval: the discretisation grid width, which is also the series time-step. The series is unit-spaced and the causal convolution shifts by integer series steps, so this must be1(the default); any other value is rejected with anArgumentErrorto avoid conflating the grid width with the series step.
Examples
using ConvolvedDistributions, Distributions
delay = convolved(Gamma(2.0, 1.0), LogNormal(0.5, 0.4))
infections = [0.0, 1.0, 3.0, 6.0, 8.0, 5.0, 2.0]
expected_counts = convolve_series(delay, infections)See also
sourceConvolvedDistributions.convolved Function
convolved(
components::AbstractVector{<:Distributions.UnivariateDistribution};
method
) -> ConvolvedDistributions.Convolved{C, AnalyticalSolver{ConvolvedDistributions.GaussLegendre{ConvolvedDistributions._GL{Vector{Float64}, Vector{Float64}}}}} where C<:TupleCreate the distribution of a sum of independent delays (a convolution).
Accepts either two or more positional component distributions, or a single vector/tuple of components. Returns a Convolved distribution.
Arguments
components: Two or moreUnivariateDistributions, or a vector/tuple of them.
Keyword Arguments
method: The solver method, anAnalyticalSolver(the default) orNumericSolver.NumericSolverforces numeric quadrature even when an analytic convolution is available.
Examples
using ConvolvedDistributions, Distributions
# Sum of two delays
d = convolved(Gamma(2.0, 1.0), LogNormal(1.5, 0.5))
cdf_at_5 = cdf(d, 5.0)
# Sum of three delays from a vector
d3 = convolved([Gamma(2.0, 1.0), Gamma(1.0, 1.0), Normal(0.0, 1.0)])
mean_sample = rand(d3)
# Force numeric quadrature even for an analytic pair
dn = convolved(Normal(0.0, 1.0), Normal(1.0, 2.0);
method = NumericSolver())
cdf_numeric = cdf(dn, 2.0)See also
Convolved: The distribution type
ConvolvedDistributions.difference Function
difference(
x::Distributions.UnivariateDistribution,
y::Distributions.UnivariateDistribution;
method
) -> Difference{X, Y, AnalyticalSolver{ConvolvedDistributions.GaussLegendre{ConvolvedDistributions._GL{Vector{Float64}, Vector{Float64}}}}} where {X<:(Distributions.UnivariateDistribution), Y<:(Distributions.UnivariateDistribution)}Create the distribution of a difference of two independent variables.
Returns a Difference representing convolved: a convolution forms the sum of two delays, a difference the signed gap between two events. The support of Z can be negative, so Z is an observation or derived quantity rather than a non-negative delay leaf (see Difference).
X and Y are assumed independent.
Arguments
x: The minuend distribution (theXinZ = X - Y), aUnivariateDistribution.y: The subtrahend distribution (theYinZ = X - Y), aUnivariateDistribution.
Keyword Arguments
method: The solver method, anAnalyticalSolver(the default) orNumericSolver.NumericSolverforces numeric quadrature even for aNormal-Normalpair, mirroringconvolved.
Examples
using ConvolvedDistributions, Distributions
# Difference of two delays; mean is the difference of the means (≈ 3)
d = difference(Normal(5.0, 1.0), Normal(2.0, 1.0))
mean(d)See also
Difference: The distribution typeconvolved: The dual sum
ConvolvedDistributions.gl_integrate Function
gl_integrate(f, lo, hi) -> Any
gl_integrate(
f,
lo,
hi,
rule::ConvolvedDistributions._GL
) -> AnyIntegrate a scalar function f over [lo, hi] by fixed-node Gauss-Legendre quadrature.
The reference domain [-1, 1] is mapped onto [lo, hi] inside the integrand and the result reduced as a weighted dot product, so the accumulator's element type is taken from the integrand and AD Duals and tangents propagate. Returns a typed zero when hi <= lo.
Arguments
f: The scalar integrand.lo: Lower integration bound.hi: Upper integration bound.rule: Gauss-Legendre rule to use (default: the 192-node convolution rule).
Examples
using ConvolvedDistributions
# Integrate x^2 over [0, 1] (exact value 1/3)
approx = ConvolvedDistributions.gl_integrate(x -> x^2, 0.0, 1.0)See also
GaussLegendre: The default solver wrapping this rule.integrate: The pluggable entry point.
ConvolvedDistributions.integrate Function
integrate(
solver::ConvolvedDistributions.GaussLegendre,
f,
lower,
upper
) -> AnyIntegrate a scalar function f over [lower, upper] using solver.
This is the pluggable integration entry point: every integral in the package calls integrate, dispatching on the solver type. The default GaussLegendre solver routes to gl_integrate. Loading the optional Integrals.jl extension adds a method for Integrals.jl algorithms (e.g. QuadGKJL()), which builds an IntegralProblem and calls solve.
Arguments
solver: The integration backend.GaussLegendreby default; any Integrals.jl algorithm when that extension is loaded.f: The scalar integrand.lower: Lower integration bound.upper: Upper integration bound.
Examples
using ConvolvedDistributions
solver = ConvolvedDistributions.GaussLegendre(; n = 64)
approx = ConvolvedDistributions.integrate(solver, x -> x^2, 0.0, 1.0)See also
GaussLegendre: The default solver.gl_integrate: The default quadrature reduction.