Specializations
The specializations module provides trait-dispatched implementations for specific kernel types, enabling optimized matrix representations and operations.
Overview
FunctionalGPs.jl uses a trait system to automatically select the most efficient algorithm for assembling covariance matrices. When you apply functionals (evaluation, integration, differentiation) to a kernel, the system:
Queries the kernel's structure via
kernel_structure(k)Dispatches to a specialized implementation based on the trait
Returns a lazy or sparse matrix representation when available
This happens transparently - you get optimal performance without manual intervention.
Kernel Structure Traits
FunctionalGPs.KernelStructureTrait Type
KernelStructureTraitTrait describing structural properties of a kernel that influence how linear functionals should assemble covariance matrices. Subtypes enable specialised lazy matrix representations.
sourceFunctionalGPs.GenericKernelTrait Type
GenericKernelTrait()Fallback trait used when a kernel does not expose special structure.
sourceFunctionalGPs.StationaryKernelTrait Type
StationaryKernelTrait()Trait indicating that the kernel is stationary and supports fast evaluation via StationaryKernelMatrix when both sides are evaluation functionals with point coordinates.
FunctionalGPs.SignedStationaryKernelTrait Type
SignedStationaryKernelTrait()Trait for kernels that are signed-stationary (e.g., kernels involving derivatives with odd total order). These kernels have structure k(x,y) = sign(x-y) * f(|x-y|) and support specialized lazy matrix representations.
sourceFunctionalGPs.kernel_structure Function
kernel_structure(k)Return the structural trait associated with kernel k. The default returns GenericKernelTrait(); specific kernels override this to signal richer structure.
Examples
julia> k = HalfIntegerMaternKernel(2, [1.0]);
julia> kernel_structure(k)
StationaryKernelTrait()
julia> k_compact = CompactPolynomialKernel(Polynomial([1.0, -2.0]));
julia> kernel_structure(k_compact)
StationaryKernelTrait()Trait-Dispatched Operations
These functions form the core interface for efficient kernel operations:
FunctionalGPs.kernel_evaluate_evaluate Function
kernel_evaluate_evaluate(k, X)
kernel_evaluate_evaluate(k, X_left, X_right)Assemble the covariance matrix resulting from applying evaluation functionals at coordinate collections X (and optionally X_left, X_right) to kernel k. The return value is a subtype of CovarianceMatrix or a fully materialised matrix when no lazy representation is available.
Examples
julia> k = HalfIntegerMaternKernel(2, [1.0]);
julia> X = collect(range(0, 1, length=10));
julia> K = kernel_evaluate_evaluate(k, X); # Lazy Toeplitz matrix
julia> size(K)
(10, 10)
julia> X_left = [0.0, 0.5];
julia> X_right = [0.2, 0.7, 0.9];
julia> K_cross = kernel_evaluate_evaluate(k, X_left, X_right);
julia> size(K_cross)
(2, 3)kernel_evaluate_evaluate(::StationaryKernelTrait, k::Kernel, X::AbstractRange)Construct a symmetric Toeplitz covariance matrix for a stationary kernel evaluated on a uniformly spaced range. Exploits the constant spacing to avoid redundant kernel evaluations.
Returns a SymmetricToeplitz matrix when the kernel supports stationary specialization; otherwise falls back to kernelmatrix.
kernel_evaluate_evaluate(::StationaryKernelTrait, k::Kernel, X)Construct a lazy StationaryKernelMatrix for a stationary kernel evaluated at arbitrary point coordinates. The matrix computes entries on-demand using scaled squared distances.
Falls back to kernelmatrix if the input cannot be converted to stationary coordinates or the kernel does not provide a stationary specification.
kernel_evaluate_evaluate(::StationaryKernelTrait, k::Kernel, X_left, X_right)Construct a lazy StationaryKernelMatrix representing the cross-covariance between two sets of points for a stationary kernel. Uses the kernel's radial map on scaled squared distances.
kernel_evaluate_evaluate(::SignedStationaryKernelTrait, k::Kernel, X)Construct a lazy SignedStationaryKernelMatrix for kernels with signed-stationary structure (e.g., odd-order derivative kernels). The kernel value depends on both the squared distance and the sign of the coordinate difference.
kernel_evaluate_evaluate(::SignedStationaryKernelTrait, k::Kernel, X_left, X_right)Construct a lazy SignedStationaryKernelMatrix for cross-covariance between two point sets using a signed-stationary kernel.
FunctionalGPs.kernel_integrate_integrate Function
kernel_integrate_integrate(k, domains)
kernel_integrate_integrate(k, domains1, domains2)Assemble the covariance matrix resulting from applying integration functionals over domain collections domains (and optionally domains1, domains2) to kernel k. The return value is a lazy matrix representation when the kernel has exploitable structure (e.g., stationary), or a fully materialised matrix otherwise.
The single-argument version applies integration to both sides with the same domains (symmetric case). Implementations may specialize this for efficiency.
Examples
julia> k = HalfIntegerMaternKernel(1, [0.8]);
julia> domains = [Interval(0.0, 0.2), Interval(0.2, 0.5), Interval(0.5, 1.0)];
julia> K = kernel_integrate_integrate(k, domains); # Lazy Toeplitz-like matrix
julia> size(K)
(3, 3)
julia> domains_left = [Interval(0.0, 0.3), Interval(0.3, 0.6)];
julia> domains_right = [Interval(0.0, 0.25), Interval(0.25, 0.5), Interval(0.5, 1.0)];
julia> K_cross = kernel_integrate_integrate(k, domains_left, domains_right);
julia> size(K_cross)
(2, 3)kernel_integrate_integrate(::StationaryKernelTrait, k::Kernel, domains1, domains2)Compute the covariance matrix for two-sided integration of a stationary kernel over 1D interval domains. Uses the kernel's second radial antiderivative (radial_antiderivative(k, Val(2))) to construct a lazy matrix as a sum of StationaryKernelMatrix terms.
The result represents Cov(∫_{domains1[i]} k, ∫_{domains2[j]} k).
kernel_integrate_integrate(::StationaryKernelTrait, k::Kernel, domains)Symmetric version of two-sided integration where both sides use the same domains. Delegates to the two-argument form.
sourcekernel_integrate_integrate(::StationaryKernelTrait, k::CompactPolynomialKernel, domains1, domains2)Compute a sparse covariance matrix for two-sided integration of a compact polynomial kernel. Uses BallTree spatial indexing to efficiently find potentially interacting domain pairs, exploiting the kernel's compact support.
Returns a SparseMatrixCSC where entry [i,j] is Cov(∫_{domains1[i]} k, ∫_{domains2[j]} k).
FunctionalGPs.kernel_integrate_evaluate Function
kernel_integrate_evaluate(k, domains, points)Assemble the covariance matrix resulting from applying integration functionals over domains to one argument and evaluation functionals at points to the other argument of kernel k. The return value is a lazy matrix representation when available, or a fully materialised matrix otherwise.
Examples
julia> k = HalfIntegerMaternKernel(2, [1.3]);
julia> domains = [Interval(0.0, 0.4), Interval(0.4, 0.9)];
julia> X = collect(range(0.0, 1.0, length=5));
julia> K = kernel_integrate_evaluate(k, domains, X);
julia> size(K)
(2, 5)Notes
The resulting matrix K[i,j] represents cov(∫ over domains[i], evaluate at X[j]).
sourcekernel_integrate_evaluate(::StationaryKernelTrait, k::Kernel, domains, X)Compute the covariance matrix for one-sided integration (integrate over domains, evaluate at points). Uses the kernel's first radial antiderivative (radial_antiderivative(k, Val(1))) and returns a lazy matrix via SignedStationaryKernelMatrix.
The result represents Cov(∫_{domains[i]} k, k(X[j])).
kernel_integrate_evaluate(::StationaryKernelTrait, k::CompactPolynomialKernel, domains, X)Compute a sparse covariance matrix for one-sided integration of a compact polynomial kernel (integrate over domains, evaluate at points). Uses BallTree spatial indexing for efficient neighbor search.
Returns a SparseMatrixCSC where entry [i,j] is Cov(∫_{domains[i]} k, k(X[j])).
Lazy Matrix Types
Specialized kernels return lazy matrix representations that defer computation:
FunctionalGPs.StationaryKernelMatrix Type
StationaryKernelMatrix{T,TX,TY,TV,TW,F}Lazy stationary covariance or cross-covariance matrix. Fields:
scaled_left: column-scaled left inputs of size(n_left, d)scaled_right: column-scaled right inputs of size(n_right, d)norms_left: row-wise squared norms of the left inputsnorms_right: row-wise squared norms of the right inputskernel_map: callable taking squared distance and returning covariance valuejitter: diagonal adjustment applied lazily when both sides alias
FunctionalGPs.SignedStationaryKernelMatrix Type
SignedStationaryKernelMatrix{T,TX,TY,TV,TW,F}Lazy stationary matrix where the kernel depends on both squared distance and signed differences between points. Suitable for one-sided integrals and odd derivatives that introduce direction-dependent factors.
sourceStationary Kernel Specifications
For kernels that are stationary (depend only on |x - y|), the system uses compact specifications:
FunctionalGPs.StationaryKernelSpec Type
StationaryKernelSpec(scales, radial_map)Container describing how a stationary kernel should be assembled lazily. The scales vector rescales coordinate columns, while radial_map maps squared distances to covariance values.
FunctionalGPs.SignedStationaryKernelSpec Type
SignedStationaryKernelSpec(scales, signed_map)Container for signed stationary kernels where the kernel depends on both squared distance and the sign of the coordinate difference.
sourceFunctionalGPs.stationary_kernel_spec Function
stationary_kernel_spec(k, ::Type{T})Return a StationaryKernelSpec describing how to construct covariance matrices for kernel k with element type T. The default returns nothing, signalling that no stationary specialisation is available.
stationary_kernel_spec(k::HalfIntegerMaternKernel{P}, ::Type{T})Return a StationaryKernelSpec for efficient lazy matrix construction with a half-integer Matérn kernel. The radial map evaluates the exponential-polynomial form at scaled distances.
stationary_kernel_spec(k::HalfIntegerMaternDerivativeOddKernel, ::Type{T})Return a SignedStationaryKernelSpec for odd-order derivatives of half-integer Matérn kernels. The signed map accounts for the antisymmetric structure introduced by odd total derivative order.
stationary_kernel_spec(k::HalfIntegerMaternDerivativeEvenKernel, ::Type{T})Return a StationaryKernelSpec for even-order derivatives of half-integer Matérn kernels. Even total derivative order preserves the symmetric radial structure.
stationary_kernel_spec(k::SqExponentialKernel, ::Type{T})Return a StationaryKernelSpec for the base Squared Exponential kernel (unit scale). The radial map evaluates exp(-r²/2) at distances.
stationary_kernel_spec(k::TransformedKernel{<:SqExponentialKernel, <:ScaleTransform}, ::Type{T})Return a StationaryKernelSpec for a scaled SE kernel. The scale factor s = 1/ℓ is incorporated into the scales vector.
stationary_kernel_spec(k::SEDerivativeEvenKernel, ::Type{T})Return a StationaryKernelSpec for even-order SE derivatives.
stationary_kernel_spec(k::SEDerivativeOddKernel, ::Type{T})Return a SignedStationaryKernelSpec for odd-order SE derivatives.
FunctionalGPs.radial_antiderivative Function
radial_antiderivative(k, ::Val{N})Generic function for computing the Nth radial antiderivative of a kernel. Specific kernel types implement this for N=1 (one-sided integration) and N=2 (two-sided integration).
sourceSupported Kernel Specializations
Half-Integer Matern Kernels
Half-integer Matern kernels (HalfIntegerMaternKernel{P} for smoothness nu = P + 1/2) support:
Lazy evaluation via
StationaryKernelMatrixToeplitz matrices for uniformly spaced points
Closed-form radial antiderivatives for integration
Automatic derivative kernel construction
using FunctionalGPs
# Create a Matern 5/2 kernel
k = HalfIntegerMaternKernel(2, [1.0])
# The trait system recognizes this as stationary
kernel_structure(k) # Returns StationaryKernelTrait()
# Evaluation returns a lazy matrix
X = collect(range(0, 1, length=100))
K = kernel_evaluate_evaluate(k, X) # StationaryKernelMatrix
# Derivatives are also specialized
dk = derivative(k, 1, 0) # First derivative kernel
kernel_structure(dk.inner_kernel) # SignedStationaryKernelTrait()Compact Polynomial Kernels
Compact kernels (including Wendland kernels) have finite support and return sparse matrices:
using FunctionalGPs, SparseArrays
# Wendland kernel with support radius 1.0
k = WendlandKernel(1, 2, 1.0)
# Kernel matrix is sparse
X = collect(range(0, 2, length=100))
K = kernelmatrix(k, X)
issparse(K) # true
# Integration also produces sparse matrices
domains = [Interval(i*0.1, (i+1)*0.1) for i in 0:19]
K_int = kernel_integrate_integrate(StationaryKernelTrait(), k.inner_kernel, domains)Extending with Custom Kernels
To add specialization support for a custom kernel:
- Declare the trait by implementing
kernel_structure:
kernel_structure(::MyKernel) = StationaryKernelTrait()- Provide a stationary specification if applicable:
function stationary_kernel_spec(k::MyKernel, ::Type{T}) where {T}
scales = T[1 / k.lengthscale]
radial_map = r2 -> my_radial_function(sqrt(r2))
return StationaryKernelSpec(scales, radial_map)
end- Implement radial antiderivatives for integration support:
function radial_antiderivative(k::MyKernel, ::Val{1})
return r -> my_first_antiderivative(r)
end
function radial_antiderivative(k::MyKernel, ::Val{2})
return r -> my_second_antiderivative(r)
end