Skip to content

Commit 4840b88

Browse files
committed
Add power_spectral_density to RatQuad covariance kernel for HSGP support
1 parent f69e159 commit 4840b88

File tree

2 files changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

pymc/gp/cov.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,27 @@ def full_from_distance(self, dist: TensorLike, squared: bool = False) -> TensorV
614614
-1.0 * self.alpha,
615615
)
616616

617+
def power_spectral_density(self, omega: TensorLike) -> TensorVariable:
618+
r"""
619+
Power spectral density for the Rational Quadratic kernel.
620+
621+
.. math::
622+
S(\boldsymbol\omega) = \frac{2 (2\pi\alpha)^{D/2} \prod_{i=1}^D \ell_i}{\Gamma(\alpha)}
623+
\left(\frac{z}{2}\right)^{\nu}
624+
K_{\nu}(z)
625+
where :math:`z = \sqrt{2\alpha} \sqrt{\sum \ell_i^2 \omega_i^2}` and :math:`\nu = \alpha - D/2`.
626+
"""
627+
ls = pt.ones(self.n_dims) * self.ls
628+
alpha = self.alpha
629+
D = self.n_dims
630+
nu = alpha - D / 2.0
631+
632+
z = pt.sqrt(2 * alpha) * pt.sqrt(pt.dot(pt.square(omega), pt.square(ls)))
633+
coeff = 2.0 * pt.power(2.0 * np.pi * alpha, D / 2.0) * pt.prod(ls) / pt.gamma(alpha)
634+
term_z = pt.power(z / 2.0, nu) * pt.kv(nu, z)
635+
636+
return coeff * term_z
637+
617638

618639
class Matern52(Stationary):
619640
r"""

tests/gp/test_cov.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import pytensor.tensor as pt
1919
import pytest
2020

21-
from scipy.special import iv
21+
from scipy.special import gamma, iv, kv
2222

2323
import pymc as pm
2424

@@ -533,6 +533,26 @@ def test_1d(self):
533533
Kd = cov(X, diag=True).eval()
534534
npt.assert_allclose(np.diag(K), Kd, atol=1e-5)
535535

536+
def test_psd(self):
537+
omega = np.linspace(0.1, 2, 10)
538+
ell = 0.5
539+
alpha = 5.0
540+
D = 1
541+
542+
z = np.sqrt(2 * alpha) * ell * np.abs(omega)
543+
nu = alpha - D / 2.0
544+
545+
coeff = 2.0 * (2.0 * np.pi * alpha) ** (D / 2.0) * ell / gamma(alpha)
546+
true_1d_psd = coeff * np.power(z / 2.0, nu) * kv(nu, z)
547+
548+
test_1d_psd = (
549+
pm.gp.cov.RatQuad(1, ls=ell, alpha=alpha)
550+
.power_spectral_density(omega[:, None])
551+
.flatten()
552+
.eval()
553+
)
554+
npt.assert_allclose(true_1d_psd, test_1d_psd, atol=1e-5)
555+
536556

537557
class TestExponential:
538558
def test_1d(self):

0 commit comments

Comments
 (0)