Coverage for src/lsqfitgp/_kernels/_wendland.py: 100%
34 statements
« prev ^ index » next coverage.py v7.6.3, created at 2024-10-15 19:54 +0000
« prev ^ index » next coverage.py v7.6.3, created at 2024-10-15 19:54 +0000
1# lsqfitgp/_kernels/_wendland.py
2#
3# Copyright (c) 2023, Giacomo Petrillo
4#
5# This file is part of lsqfitgp.
6#
7# lsqfitgp is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11#
12# lsqfitgp is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with lsqfitgp. If not, see <http://www.gnu.org/licenses/>.
20from jax import numpy as jnp 1efabcd
22from .. import _jaxext 1efabcd
23from .._Kernel import stationarykernel, isotropickernel 1efabcd
25def _wendland_derivable(k=0, **_): 1efabcd
26 return k 1abcd
28def _wendland_maxdim(k=0, alpha=1): 1efabcd
29 with _jaxext.skipifabstract(): 1abcd
30 return int(jnp.floor(2 * alpha - 1)) 1abcd
32@isotropickernel(input='posabs', derivable=_wendland_derivable, maxdim=_wendland_maxdim) 1efabcd
33def Wendland(r, k=0, alpha=1): 1efabcd
34 """
35 Wendland kernel.
37 .. math::
38 k(r) &= \\frac1{B(2k+1,\\nu)}
39 \\int_r^\\infty \\mathrm du\\, (u^2 - r^2)^k (1 - u)_+^{\\nu-1}, \\\\
40 \\quad k &\\in \\mathbb N,\\ \\nu = k + \\alpha,\\ \\alpha \\ge 1.
42 An isotropic kernel with finite support. The covariance is nonzero only
43 when the distance between the points is less than 1. Parameter :math:`k \\in \\{0,
44 1, 2, 3\\}` sets the differentiability, while the maximum dimensionality the
45 kernel can be used in is :math:`\\lfloor 2\\alpha-1 \\rfloor`. Default is
46 :math:`k = 0` (non derivable), :math:`\\alpha = 1` (can be used only in
47 1D).
49 Reference: Gneiting (2002), Wendland (2004, p. 128), Rasmussen and Williams
50 (2006, p. 87), Porcu, Furrer and Nychka (2020, p. 4).
52 """
54 # TODO compute the kernel only on the nonzero points.
56 # TODO find the nonzero points in O(nlogn) instead of O(n^2) by sorting
57 # the inputs, and output a sparse matrix => on second thought this should
58 # be a general mechanism implemented in GP that gives sparse x and y to
59 # the kernel
61 with _jaxext.skipifabstract(): 1abcd
62 D = _wendland_maxdim(k, alpha) 1abcd
63 assert D >= 1, D 1abcd
65 if k == 0: 1abcd
66 poly = [ 1abcd
67 [1],
68 ]
69 elif k == 1: 1abcd
70 poly = [ 1abcd
71 [1, 1],
72 [1],
73 ]
74 elif k == 2: 1abcd
75 poly = [ 1abcd
76 [1/3, 4/3, 1],
77 [1, 2],
78 [1],
79 ]
80 elif k == 3: 1abcd
81 poly = [ 1abcd
82 [1/15, 3/5, 23/15, 1],
83 [2/5, 12/5, 3],
84 [1, 3],
85 [1],
86 ]
87 else:
88 raise NotImplementedError 1abcd
90 nu = k + alpha 1abcd
91 coeffs = jnp.array([jnp.polyval(jnp.array(pj), nu) for pj in poly]) 1abcd
92 poly = jnp.polyval(coeffs, r) 1abcd
93 return jnp.where(r < 1, (1 - r) ** (nu + k) * poly, 0) 1abcd
96# adapted from the "GP-circular" example in the PyMC documentation
98# TODO maxdim actually makes sense only for isotropic. I need a way to say
99# structured/non structured. Maybe all this should just live in the test suite.
101# TODO Any stationary kernel supported on [0, pi] would be fine combined with
102# the geodesic distance. Use the generic wendland kernel. Options:
103# 1) add here the parameters of Wendland
104# 2) add a distance option in stationary to use the angular distance, then
105# let the user apply it to wendland => the problem is that the user would
106# need to be careful with positiveness, while wendland checks it for him
108@stationarykernel(derivable=1, maxdim=1, input='posabs') 1efabcd
109def Circular(delta, tau=4, c=1/2): 1efabcd
110 """
111 Circular kernel.
113 .. math:: k(x, y) &= W_c(d_{\\text{geo}}(x, y)), \\\\
114 W_c(t) &= \\left(1 + \\tau\\frac tc\\right)
115 \\left(1 - \\frac tc\\right)^\\tau_+,
116 \\quad c \\in (0, 1/2], \\tau \\ge 4, \\\\
117 d_{\\text{geo}}(x, y) &= \\arccos\\cos(2\\pi(x-y)).
119 It is a stationary periodic kernel with period 1.
121 Reference: Padonou and Roustant (2016).
122 """
123 with _jaxext.skipifabstract(): 1abcd
124 assert tau >= 4, tau 1abcd
125 assert 0 < c <= 1/2, c 1abcd
126 x = delta % 1 1abcd
127 t = jnp.minimum(x, 1 - x) 1abcd
128 return (1 + tau * t / c) * jnp.maximum(1 - t / c, 0) ** tau 1abcd