diff --git a/GPy/kern/src/sde_brownian.py b/GPy/kern/src/sde_brownian.py new file mode 100644 index 00000000..55950143 --- /dev/null +++ b/GPy/kern/src/sde_brownian.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +""" +Classes in this module enhance Brownian motion covariance function with the +Stochastic Differential Equation (SDE) functionality. +""" + +from .brownian import Brownian + +import numpy as np + +class sde_Brownian(Brownian): + """ + + Class provide extra functionality to transfer this covariance function into + SDE form. + + Linear kernel: + + .. math:: + + k(x,y) = \sigma^2 min(x,y) + + """ + + def sde_update_gradient_full(self, gradients): + """ + Update gradient in the order in which parameters are represented in the + kernel + """ + + self.variance.gradient = gradients[0] + + def sde(self): + """ + Return the state space representation of the covariance. + """ + + variance = float(self.variance.values) # this is initial variancve in Bayesian linear regression + + F = np.array( ((0,1.0),(0,0) )) + L = np.array( ((1.0,),(0,)) ) + Qc = np.array( ((variance,),) ) + H = np.array( ((1.0,0),) ) + + Pinf = np.array( ( (0, -0.5*variance ), (-0.5*variance, 0) ) ) + #P0 = Pinf.copy() + P0 = np.zeros((2,2)) + #Pinf = np.array( ( (t0, 1.0), (1.0, 1.0/t0) ) ) * variance + dF = np.zeros((2,2,1)) + dQc = np.ones( (1,1,1) ) + + dPinf = np.zeros((2,2,1)) + dPinf[:,:,0] = np.array( ( (0, -0.5), (-0.5, 0) ) ) + #dP0 = dPinf.copy() + dP0 = np.zeros((2,2,1)) + + return (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0) diff --git a/GPy/kern/src/sde_linear.py b/GPy/kern/src/sde_linear.py new file mode 100644 index 00000000..031f0f5f --- /dev/null +++ b/GPy/kern/src/sde_linear.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +""" +Classes in this module enhance Linear covariance function with the +Stochastic Differential Equation (SDE) functionality. +""" +from .linear import Linear + +import numpy as np + +class sde_Linear(Linear): + """ + + Class provide extra functionality to transfer this covariance function into + SDE form. + + Linear kernel: + + .. math:: + + k(x,y) = \sum_{i=1}^{input dim} \sigma^2_i x_iy_i + + """ + def __init__(self, input_dim, X, variances=None, ARD=False, active_dims=None, name='linear'): + """ + Modify the init method, because one extra parameter is required. X - points + on the X axis. + """ + + super(sde_Linear, self).__init__(input_dim, variances, ARD, active_dims, name) + + self.t0 = np.min(X) + + + def sde_update_gradient_full(self, gradients): + """ + Update gradient in the order in which parameters are represented in the + kernel + """ + + self.variances.gradient = gradients[0] + + def sde(self): + """ + Return the state space representation of the covariance. + """ + + variance = float(self.variances.values) # this is initial variancve in Bayesian linear regression + t0 = float(self.t0) + + F = np.array( ((0,1.0),(0,0) )) + L = np.array( ((0,),(1.0,)) ) + Qc = np.zeros((1,1)) + H = np.array( ((1.0,0),) ) + + Pinf = np.zeros((2,2)) + P0 = np.array( ( (t0**2, t0), (t0, 1) ) ) * variance + dF = np.zeros((2,2,1)) + dQc = np.zeros( (1,1,1) ) + + dPinf = np.zeros((2,2,1)) + dP0 = np.zeros((2,2,1)) + dP0[:,:,0] = P0 / variance + + return (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0) diff --git a/GPy/kern/src/sde_matern.py b/GPy/kern/src/sde_matern.py new file mode 100644 index 00000000..0ce1cf98 --- /dev/null +++ b/GPy/kern/src/sde_matern.py @@ -0,0 +1,135 @@ +# -*- coding: utf-8 -*- +""" +Classes in this module enhance Matern covariance functions with the +Stochastic Differential Equation (SDE) functionality. +""" +from .stationary import Matern32 +from .stationary import Matern52 +import numpy as np + +class sde_Matern32(Matern32): + """ + + Class provide extra functionality to transfer this covariance function into + SDE forrm. + + Matern 3/2 kernel: + + .. math:: + + k(r) = \sigma^2 (1 + \sqrt{3} r) \exp(- \sqrt{3} r) \\ \\ \\ \\ \text{ where } r = \sqrt{\sum_{i=1}^{input dim} \frac{(x_i-y_i)^2}{\ell_i^2} } + + """ + def sde_update_gradient_full(self, gradients): + """ + Update gradient in the order in which parameters are represented in the + kernel + """ + + self.variance.gradient = gradients[0] + self.lengthscale.gradient = gradients[1] + + def sde(self): + """ + Return the state space representation of the covariance. + """ + + variance = float(self.variance.values) + lengthscale = float(self.lengthscale.values) + + foo = np.sqrt(3.)/lengthscale + F = np.array(((0, 1.0), (-foo**2, -2*foo))) + L = np.array(( (0,), (1.0,) )) + Qc = np.array(((12.*np.sqrt(3) / lengthscale**3 * variance,),)) + H = np.array(((1.0, 0),)) + Pinf = np.array(((variance, 0.0), (0.0, 3.*variance/(lengthscale**2)))) + P0 = Pinf.copy() + + # Allocate space for the derivatives + dF = np.empty([F.shape[0],F.shape[1],2]) + dQc = np.empty([Qc.shape[0],Qc.shape[1],2]) + dPinf = np.empty([Pinf.shape[0],Pinf.shape[1],2]) + # The partial derivatives + dFvariance = np.zeros((2,2)) + dFlengthscale = np.array(((0,0), (6./lengthscale**3,2*np.sqrt(3)/lengthscale**2))) + dQcvariance = np.array((12.*np.sqrt(3)/lengthscale**3)) + dQclengthscale = np.array((-3*12*np.sqrt(3)/lengthscale**4*variance)) + dPinfvariance = np.array(((1,0),(0,3./lengthscale**2))) + dPinflengthscale = np.array(((0,0), (0,-6*variance/lengthscale**3))) + # Combine the derivatives + dF[:,:,0] = dFvariance + dF[:,:,1] = dFlengthscale + dQc[:,:,0] = dQcvariance + dQc[:,:,1] = dQclengthscale + dPinf[:,:,0] = dPinfvariance + dPinf[:,:,1] = dPinflengthscale + dP0 = dPinf.copy() + + return (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0) + +class sde_Matern52(Matern52): + """ + + Class provide extra functionality to transfer this covariance function into + SDE forrm. + + Matern 5/2 kernel: + + .. math:: + + k(r) = \sigma^2 (1 + \sqrt{5} r + \frac{5}{3}r^2) \exp(- \sqrt{5} r) \\ \\ \\ \\ \text{ where } r = \sqrt{\sum_{i=1}^{input dim} \frac{(x_i-y_i)^2}{\ell_i^2} } + + """ + def sde_update_gradient_full(self, gradients): + """ + Update gradient in the order in which parameters are represented in the + kernel + """ + + self.variance.gradient = gradients[0] + self.lengthscale.gradient = gradients[1] + + def sde(self): + """ + Return the state space representation of the covariance. + """ + + variance = float(self.variance.values) + lengthscale = float(self.lengthscale.values) + + lamda = np.sqrt(5.0)/lengthscale + kappa = 5.0/3.0*variance/lengthscale**2 + + F = np.array(((0, 1,0), (0, 0, 1), (-lamda**3, -3.0*lamda**2, -3*lamda))) + L = np.array(((0,),(0,),(1,))) + Qc = np.array((((variance*400.0*np.sqrt(5.0)/3.0/lengthscale**5),),)) + H = np.array(((1,0,0),)) + + Pinf = np.array(((variance,0,-kappa), (0, kappa, 0), (-kappa, 0, 25.0*variance/lengthscale**4))) + P0 = Pinf.copy() + # Allocate space for the derivatives + dF = np.empty((3,3,2)) + dQc = np.empty((1,1,2)) + dPinf = np.empty((3,3,2)) + + # The partial derivatives + dFvariance = np.zeros((3,3)) + dFlengthscale = np.array(((0,0,0),(0,0,0),(15.0*np.sqrt(5.0)/lengthscale**4, + 30.0/lengthscale**3, 3*np.sqrt(5.0)/lengthscale**2))) + dQcvariance = np.array((((400*np.sqrt(5)/3/lengthscale**5,),))) + dQclengthscale = np.array((((-variance*2000*np.sqrt(5)/3/lengthscale**6,),))) + + dPinf_variance = Pinf/variance + kappa2 = -2.0*kappa/lengthscale + dPinf_lengthscale = np.array(((0,0,-kappa2),(0,kappa2,0),(-kappa2, + 0,-100*variance/lengthscale**5))) + # Combine the derivatives + dF[:,:,0] = dFvariance + dF[:,:,1] = dFlengthscale + dQc[:,:,0] = dQcvariance + dQc[:,:,1] = dQclengthscale + dPinf[:,:,0] = dPinf_variance + dPinf[:,:,1] = dPinf_lengthscale + dP0 = dPinf.copy() + + return (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0) \ No newline at end of file diff --git a/GPy/kern/src/sde_standard_periodic.py b/GPy/kern/src/sde_standard_periodic.py new file mode 100644 index 00000000..c3df7d92 --- /dev/null +++ b/GPy/kern/src/sde_standard_periodic.py @@ -0,0 +1,178 @@ +# -*- coding: utf-8 -*- +""" +Classes in this module enhance Matern covariance functions with the +Stochastic Differential Equation (SDE) functionality. +""" +from .standard_periodic import StdPeriodic + +import numpy as np +import scipy as sp + +from scipy import special as special + +class sde_StdPeriodic(StdPeriodic): + """ + + Class provide extra functionality to transfer this covariance function into + SDE form. + + Standard Periodic kernel: + + .. math:: + + k(x,y) = \theta_1 \exp \left[ - \frac{1}{2} {}\sum_{i=1}^{input\_dim} + \left( \frac{\sin(\frac{\pi}{\lambda_i} (x_i - y_i) )}{l_i} \right)^2 \right] } + + """ + def sde_update_gradient_full(self, gradients): + """ + Update gradient in the order in which parameters are represented in the + kernel + """ + + self.variance.gradient = gradients[0] + self.wavelengths.gradient = gradients[1] + self.lengthscales.gradient = gradients[2] + + def sde(self): + """ + Return the state space representation of the covariance. + + + ! Note: one must constrain lengthscale not to drop below 0.25. + After this bessel functions of the first kind grows to very high. + + ! Note: one must keep wevelength also not very low. Because then + the gradients wrt wavelength become ustable. + However this might depend on the data. For test example with + 300 data points the low limit is 0.15. + """ + + # Params to use: (in that order) + #self.variance + #self.wavelengths + #self.lengthscales + N = 7 # approximation order + + + w0 = 2*np.pi/self.wavelengths # frequency + lengthscales = 2*self.lengthscales + + [q2,dq2l] = seriescoeff(N,lengthscales,self.variance) + # lengthscale is multiplied by 2 because of slightly different + # formula for periodic covariance function. + # For the same reason: + + dq2l = 2*dq2l + + if np.any( np.isfinite(q2) == False): + raise ValueError("SDE periodic covariance error 1") + + if np.any( np.isfinite(dq2l) == False): + raise ValueError("SDE periodic covariance error 2") + + F = np.kron(np.diag(range(0,N+1)),np.array( ((0, -w0), (w0, 0)) ) ) + L = np.eye(2*(N+1)) + Qc = np.zeros((2*(N+1), 2*(N+1))) + P_inf = np.kron(np.diag(q2),np.eye(2)) + H = np.kron(np.ones((1,N+1)),np.array((1,0)) ) + P0 = P_inf.copy() + + # Derivatives + dF = np.empty((F.shape[0], F.shape[1], 3)) + dQc = np.empty((Qc.shape[0], Qc.shape[1], 3)) + dP_inf = np.empty((P_inf.shape[0], P_inf.shape[1], 3)) + + # Derivatives wrt self.variance + dF[:,:,0] = np.zeros(F.shape) + dQc[:,:,0] = np.zeros(Qc.shape) + dP_inf[:,:,0] = P_inf / self.variance + + # Derivatives self.wavelengths + dF[:,:,1] = np.kron(np.diag(range(0,N+1)),np.array( ((0, w0), (-w0, 0)) ) / self.wavelengths ); + dQc[:,:,1] = np.zeros(Qc.shape) + dP_inf[:,:,1] = np.zeros(P_inf.shape) + + # Derivatives self.lengthscales + dF[:,:,2] = np.zeros(F.shape) + dQc[:,:,2] = np.zeros(Qc.shape) + dP_inf[:,:,2] = np.kron(np.diag(dq2l),np.eye(2)) + dP0 = dP_inf.copy() + + return (F, L, Qc, H, P_inf, P0, dF, dQc, dP_inf, dP0) + + + + +def seriescoeff(m=6,lengthScale=1.0,magnSigma2=1.0, true_covariance=False): + """ + Calculate the coefficients q_j^2 for the covariance function + approximation: + + k(\tau) = \sum_{j=0}^{+\infty} q_j^2 \cos(j\omega_0 \tau) + + Reference is: + + [1] Arno Solin and Simo Särkkä (2014). Explicit link between periodic + covariance functions and state space models. In Proceedings of the + Seventeenth International Conference on Artifcial Intelligence and + Statistics (AISTATS 2014). JMLR: W&CP, volume 33. + + Note! Only the infinite approximation (through Bessel function) + is currently implemented. + + Input: + ---------------- + + m: int + Degree of approximation. Default 6. + lengthScale: float + Length scale parameter in the kerenl + magnSigma2:float + Multiplier in front of the kernel. + + + Output: + ----------------- + + coeffs: array(m+1) + Covariance series coefficients + + coeffs_dl: array(m+1) + Derivatives of the coefficients with respect to lengthscale. + + """ + + if true_covariance: + + bb = lambda j,m: (1.0 + np.array((j != 0), dtype=np.float64) ) / (2**(j)) *\ + sp.special.binom(j, sp.floor( (j-m)/2.0 * np.array(m<=j, dtype=np.float64) ))*\ + np.array(m<=j, dtype=np.float64) *np.array(sp.mod(j-m,2)==0, dtype=np.float64) + + M,J = np.meshgrid(range(0,m+1),range(0,m+1)) + + coeffs = bb(J,M) / sp.misc.factorial(J) * sp.exp( -lengthScale**(-2) ) *\ + (lengthScale**(-2))**J *magnSigma2 + + coeffs_dl = np.sum( coeffs*lengthScale**(-3)*(2.0-2.0*J*lengthScale**2),0) + + coeffs = np.sum(coeffs,0) + + else: + coeffs = 2*magnSigma2*sp.exp( -lengthScale**(-2) ) * special.iv(range(0,m+1),1.0/lengthScale**(2)) + if np.any( np.isfinite(coeffs) == False): + raise ValueError("sde_standard_periodic: Coefficients are not finite!") + #import pdb; pdb.set_trace() + coeffs[0] = 0.5*coeffs[0] + + # Derivatives wrt (lengthScale) + coeffs_dl = np.zeros(m+1) + coeffs_dl[1:] = magnSigma2*lengthScale**(-3) * sp.exp(-lengthScale**(-2))*\ + (-4*special.iv(range(0,m),lengthScale**(-2)) + 4*(1+np.arange(1,m+1)*lengthScale**(2))*special.iv(range(1,m+1),lengthScale**(-2)) ) + + # The first element + coeffs_dl[0] = magnSigma2*lengthScale**(-3) * np.exp(-lengthScale**(-2))*\ + (2*special.iv(0,lengthScale**(-2)) - 2*special.iv(1,lengthScale**(-2)) ) + + + return coeffs, coeffs_dl diff --git a/GPy/kern/src/sde_static.py b/GPy/kern/src/sde_static.py new file mode 100644 index 00000000..ae8ed194 --- /dev/null +++ b/GPy/kern/src/sde_static.py @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- +""" +Classes in this module enhance Static covariance functions with the +Stochastic Differential Equation (SDE) functionality. +""" +from .static import White +from .static import Bias + +import numpy as np + +class sde_White(White): + """ + + Class provide extra functionality to transfer this covariance function into + SDE forrm. + + White kernel: + + .. math:: + + k(x,y) = \alpha*\delta(x-y) + + """ + + def sde_update_gradient_full(self, gradients): + """ + Update gradient in the order in which parameters are represented in the + kernel + """ + + self.variance.gradient = gradients[0] + + def sde(self): + """ + Return the state space representation of the covariance. + """ + + variance = float(self.variance.values) + + F = np.array( ((-np.inf,),) ) + L = np.array( ((1.0,),) ) + Qc = np.array( ((variance,),) ) + H = np.array( ((1.0,),) ) + + Pinf = np.array( ((variance,),) ) + P0 = Pinf.copy() + + dF = np.zeros((1,1,1)) + dQc = np.zeros((1,1,1)) + dQc[:,:,0] = np.array( ((1.0,),) ) + + dPinf = np.zeros((1,1,1)) + dPinf[:,:,0] = np.array( ((1.0,),) ) + dP0 = dPinf.copy() + + return (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0) + + +class sde_Bias(Bias): + """ + + Class provide extra functionality to transfer this covariance function into + SDE forrm. + + Bias kernel: + + .. math:: + + k(x,y) = \alpha + + """ + def sde_update_gradient_full(self, gradients): + """ + Update gradient in the order in which parameters are represented in the + kernel + """ + + self.variance.gradient = gradients[0] + + def sde(self): + """ + Return the state space representation of the covariance. + """ + variance = float(self.variance.values) + + F = np.array( ((0.0,),)) + L = np.array( ((1.0,),)) + Qc = np.zeros((1,1)) + H = np.array( ((1.0,),)) + + Pinf = np.zeros((1,1)) + P0 = np.array( ((variance,),) ) + + dF = np.zeros((1,1,1)) + dQc = np.zeros((1,1,1)) + + dPinf = np.zeros((1,1,1)) + dP0 = np.zeros((1,1,1)) + dP0[:,:,0] = np.array( ((1.0,),) ) + + return (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0) \ No newline at end of file diff --git a/GPy/kern/src/sde_stationary.py b/GPy/kern/src/sde_stationary.py new file mode 100644 index 00000000..9504c5c3 --- /dev/null +++ b/GPy/kern/src/sde_stationary.py @@ -0,0 +1,190 @@ +# -*- coding: utf-8 -*- +""" +Classes in this module enhance several stationary covariance functions with the +Stochastic Differential Equation (SDE) functionality. +""" +from .rbf import RBF +from .stationary import Exponential +from .stationary import RatQuad + +import numpy as np +import scipy as sp + +class sde_RBF(RBF): + """ + + Class provide extra functionality to transfer this covariance function into + SDE form. + + Radial Basis Function kernel: + + .. math:: + + k(r) = \sigma^2 \exp \\bigg(- \\frac{1}{2} r^2 \\bigg) \\ \\ \\ \\ \text{ where } r = \sqrt{\sum_{i=1}^{input dim} \frac{(x_i-y_i)^2}{\ell_i^2} } + + """ + def sde_update_gradient_full(self, gradients): + """ + Update gradient in the order in which parameters are represented in the + kernel + """ + + self.variance.gradient = gradients[0] + self.lengthscale.gradient = gradients[1] + + def sde(self): + """ + Return the state space representation of the covariance. + """ + + N = 10# approximation order ( number of terms in exponent series expansion) + roots_rounding_decimals = 6 + + fn = np.math.factorial(N) + + kappa = 1.0/2.0/self.lengthscale**2 + + Qc = np.array((self.variance*np.sqrt(np.pi/kappa)*fn*(4*kappa)**N,),) + + pp = np.zeros((2*N+1,)) # array of polynomial coefficients from higher power to lower + + for n in range(0, N+1): # (2N+1) - number of polynomial coefficients + pp[2*(N-n)] = fn*(4.0*kappa)**(N-n)/np.math.factorial(n)*(-1)**n + + pp = sp.poly1d(pp) + roots = sp.roots(pp) + + neg_real_part_roots = roots[np.round(np.real(roots) ,roots_rounding_decimals) < 0] + aa = sp.poly1d(neg_real_part_roots, r=True).coeffs + + F = np.diag(np.ones((N-1,)),1) + F[-1,:] = -aa[-1:0:-1] + + L= np.zeros((N,1)) + L[N-1,0] = 1 + + H = np.zeros((1,N)) + H[0,0] = 1 + + # Infinite covariance: + Pinf = sp.linalg.solve_lyapunov(F, -np.dot(L,np.dot( Qc[0,0],L.T))) + Pinf = 0.5*(Pinf + Pinf.T) + # Allocating space for derivatives + dF = np.empty([F.shape[0],F.shape[1],2]) + dQc = np.empty([Qc.shape[0],Qc.shape[1],2]) + dPinf = np.empty([Pinf.shape[0],Pinf.shape[1],2]) + + # Derivatives: + dFvariance = np.zeros(F.shape) + dFlengthscale = np.zeros(F.shape) + dFlengthscale[-1,:] = -aa[-1:0:-1]/self.lengthscale * np.arange(-N,0,1) + + dQcvariance = Qc/self.variance + dQclengthscale = np.array(((self.variance*np.sqrt(2*np.pi)*fn*2**N*self.lengthscale**(-2*N)*(1-2*N,),))) + + dPinf_variance = Pinf/self.variance + + lp = Pinf.shape[0] + coeff = np.arange(1,lp+1).reshape(lp,1) + np.arange(1,lp+1).reshape(1,lp) - 2 + coeff[np.mod(coeff,2) != 0] = 0 + dPinf_lengthscale = -1/self.lengthscale*Pinf*coeff + + dF[:,:,0] = dFvariance + dF[:,:,1] = dFlengthscale + dQc[:,:,0] = dQcvariance + dQc[:,:,1] = dQclengthscale + dPinf[:,:,0] = dPinf_variance + dPinf[:,:,1] = dPinf_lengthscale + + P0 = Pinf.copy() + dP0 = dPinf.copy() + + # Benefits of this are not very sound. Helps only in one case: + # SVD Kalman + RBF kernel + import GPy.models.state_space_main as ssm + (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf,dP0, T) = ssm.balance_ss_model(F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0 ) + + return (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0) + +class sde_Exponential(Exponential): + """ + + Class provide extra functionality to transfer this covariance function into + SDE form. + + Exponential kernel: + + .. math:: + + k(r) = \sigma^2 \exp \\bigg(- \\frac{1}{2} r \\bigg) \\ \\ \\ \\ \text{ where } r = \sqrt{\sum_{i=1}^{input dim} \frac{(x_i-y_i)^2}{\ell_i^2} } + + """ + + def sde_update_gradient_full(self, gradients): + """ + Update gradient in the order in which parameters are represented in the + kernel + """ + + self.variance.gradient = gradients[0] + self.lengthscale.gradient = gradients[1] + + def sde(self): + """ + Return the state space representation of the covariance. + """ + variance = float(self.variance.values) + lengthscale = float(self.lengthscale) + + F = np.array(((-1.0/lengthscale,),)) + L = np.array(((1.0,),)) + Qc = np.array( ((2.0*variance/lengthscale,),) ) + H = np.array(((1.0,),)) + Pinf = np.array(((variance,),)) + P0 = Pinf.copy() + + dF = np.zeros((1,1,2)); + dQc = np.zeros((1,1,2)); + dPinf = np.zeros((1,1,2)); + + dF[:,:,0] = 0.0 + dF[:,:,1] = 1.0/lengthscale**2 + + dQc[:,:,0] = 2.0/lengthscale + dQc[:,:,1] = -2.0*variance/lengthscale**2 + + dPinf[:,:,0] = 1.0 + dPinf[:,:,1] = 0.0 + + dP0 = dPinf.copy() + + return (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0) + +class sde_RatQuad(RatQuad): + """ + + Class provide extra functionality to transfer this covariance function into + SDE form. + + Rational Quadratic kernel: + + .. math:: + + k(r) = \sigma^2 \\bigg( 1 + \\frac{r^2}{2} \\bigg)^{- \alpha} \\ \\ \\ \\ \text{ where } r = \sqrt{\sum_{i=1}^{input dim} \frac{(x_i-y_i)^2}{\ell_i^2} } + + """ + + def sde(self): + """ + Return the state space representation of the covariance. + """ + + assert False, 'Not Implemented' + + # Params to use: + + # self.lengthscale + # self.variance + #self.power + + #return (F, L, Qc, H, Pinf, dF, dQc, dPinf)