def Rlam(x, lam=None): v1 = kve(lam + 1, x) * np.exp(x) v0 = kve(lam, x) * np.exp(x) val = v1 / v0 if np.isinf(v1) or np.isinf(v0) or v0 == 0 or v1 == 0: lv1 = np.log(sympy.Float(mpmath.besselk(np.abs(lam + 1), x))) lv0 = np.log(sympy.Float(mpmath.besselk(np.abs(lam), x))) val = np.exp(lv1 - lv0) return val
def R0(kpsigr, b, N): h = float(b) / N k = 0.0 for i in range(1, N): x = i * h if i % 2 == 1: k += 4.0 * x * mp.besselk(0, x) * rho_perp(x, kpsigr) else: k += 2.0 * x * mp.besselk(0, x) * rho_perp(x, kpsigr) return (h / 3.0) * (b * mp.besselk(0, b) * rho_perp(b, kpsigr) + k)
def f(th_e, A): tmp = A - chi*(m_e/m_i)*th_e if (tmp <= 0.0): tmp = 1.0e-20 th_e = mp.mpf(th_e) th_i = mp.mpf(tmp) tmp = (1/(mp.besselk(2, 1/th_e) * mp.besselk(2, 1/th_i))) * (((2*(th_e + th_i)**2 + 1)/(th_e + th_i)) * mp.besselk(1, (th_e + th_i)/(th_e*th_i)) + 2*mp.besselk(0, (th_e + th_i)/(th_e*th_i))) # print repr(tmp) return float(tmp)
def mpbesselk(v, x): r = float(mpmath.besselk(v, x, **HYPERKW)) if abs(r) > 1e305: # overflowing to inf a bit earlier is OK r = np.inf * np.sign(r) if abs(v) == abs(x) and abs(r) == np.inf and abs(x) > 1: # wrong result (kv(x,x) -> 0 for x > 1), # try with higher dps old_dps = mpmath.mp.dps mpmath.mp.dps = 200 try: r = float(mpmath.besselk(v, x, **HYPERKW)) finally: mpmath.mp.dps = old_dps return r
def roughness_spectrum(sp, xx, wvnb, sig, L, Ts): wn = np.zeros(Ts) # -- math.exponential correl func if sp.lower() == 'math.exponential': for n in np.arange(1,Ts+1): wn[n-1] = L ** 2 / n ** 2 * (1 + (wvnb * L / n) ** 2) ** (-1.5) rss = sig / L # -- gaussian correl func if sp.lower() == 'gaussian': for n in np.arange(1,Ts+1): wn[n-1] = L ** 2 / (2 * n) * math.exp(-(wvnb * L) ** 2 / (4 * n)) rss = sqrt(2) * sig / L # -- x - power correl func if sp.lower() == 'power_spec': for n in np.arange(1,Ts+1): if wvnb == 0: wn[n-1] = L ** 2 / (3 * n - 2) else: wn[n-1] = L ** 2 * (wvnb * L) ** (-1 + xx * n) * besselk(1 - xx * n, wvnb * L) \ / (2 ** (xx * n - 1) * math.gamma(xx * n)) return(wn, rss)
def pdf(x, p, b, loc=0, scale=1): """ Probability density function of the generalized inverse Gaussian distribution. The PDF for x > loc is: z**(p - 1) * exp(-b*(z + 1/z)/2)) --------------------------------- s * K_p(b) where s is the scale, z = (x - loc)/s, and K_p(b) is the modified Bessel function of the second kind. For x <= loc, the PDF is zero. """ x = mpmath.mpf(x) p = mpmath.mpf(p) b = mpmath.mpf(b) loc = mpmath.mpf(loc) scale = mpmath.mpf(scale) if x <= loc: return mpmath.mp.zero z = (x - loc) / scale return (mpmath.power(z, p - 1) * mpmath.exp(-b * (z + 1 / z) / 2) / (2 * mpmath.besselk(p, b)) / scale)
def matern_function(Xi, Xj, *args): r"""Matern covariance function of arbitrary dimension, for use with :py:class:`ArbitraryKernel`. The Matern kernel has the following hyperparameters, always referenced in the order listed: = ===== ==================================== 0 sigma prefactor 1 nu order of kernel 2 l1 length scale for the first dimension 3 l2 ...and so on for all dimensions = ===== ==================================== The kernel is defined as: .. math:: k_M = \sigma^2 \frac{2^{1-\nu}}{\Gamma(\nu)} \left (\sqrt{2\nu \sum_i\left (\frac{\tau_i^2}{l_i^2}\right )}\right )^\nu K_\nu\left(\sqrt{2\nu \sum_i\left(\frac{\tau_i^2}{l_i^2}\right)}\right) Parameters ---------- Xi, Xj : :py:class:`Array`, :py:class:`mpf`, tuple or scalar float Points to evaluate the covariance between. If they are :py:class:`Array`, :py:mod:`scipy` functions are used, otherwise :py:mod:`mpmath` functions are used. *args Remaining arguments are the 2+num_dim hyperparameters as defined above. """ num_dim = len(args) - 2 nu = args[1] if isinstance(Xi, scipy.ndarray): if isinstance(Xi, scipy.matrix): Xi = scipy.asarray(Xi, dtype=float) Xj = scipy.asarray(Xj, dtype=float) tau = scipy.asarray(Xi - Xj, dtype=float) l_mat = scipy.tile(args[-num_dim:], (tau.shape[0], 1)) r2l2 = scipy.sum((tau / l_mat)**2, axis=1) y = scipy.sqrt(2.0 * nu * r2l2) k = 2.0**(1 - nu) / scipy.special.gamma(nu) * y**nu * scipy.special.kv( nu, y) k[r2l2 == 0] = 1 else: try: tau = [xi - xj for xi, xj in zip(Xi, Xj)] except TypeError: tau = Xi - Xj try: r2l2 = sum([(t / l)**2 for t, l in zip(tau, args[2:])]) except TypeError: r2l2 = (tau / args[2])**2 y = mpmath.sqrt(2.0 * nu * r2l2) k = 2.0**(1 - nu) / mpmath.gamma(nu) * y**nu * mpmath.besselk(nu, y) k *= args[0]**2.0 return k
def matern_function(Xi, Xj, *args): r"""Matern covariance function of arbitrary dimension, for use with :py:class:`ArbitraryKernel`. The Matern kernel has the following hyperparameters, always referenced in the order listed: = ===== ==================================== 0 sigma prefactor 1 nu order of kernel 2 l1 length scale for the first dimension 3 l2 ...and so on for all dimensions = ===== ==================================== The kernel is defined as: .. math:: k_M = \sigma^2 \frac{2^{1-\nu}}{\Gamma(\nu)} \left (\sqrt{2\nu \sum_i\left (\frac{\tau_i^2}{l_i^2}\right )}\right )^\nu K_\nu\left(\sqrt{2\nu \sum_i\left(\frac{\tau_i^2}{l_i^2}\right)}\right) Parameters ---------- Xi, Xj : :py:class:`Array`, :py:class:`mpf`, tuple or scalar float Points to evaluate the covariance between. If they are :py:class:`Array`, :py:mod:`scipy` functions are used, otherwise :py:mod:`mpmath` functions are used. *args Remaining arguments are the 2+num_dim hyperparameters as defined above. """ num_dim = len(args) - 2 nu = args[1] if isinstance(Xi, scipy.ndarray): if isinstance(Xi, scipy.matrix): Xi = scipy.asarray(Xi, dtype=float) Xj = scipy.asarray(Xj, dtype=float) tau = scipy.asarray(Xi - Xj, dtype=float) l_mat = scipy.tile(args[-num_dim:], (tau.shape[0], 1)) r2l2 = scipy.sum((tau / l_mat)**2, axis=1) y = scipy.sqrt(2.0 * nu * r2l2) k = 2.0**(1 - nu) / scipy.special.gamma(nu) * y**nu * scipy.special.kv(nu, y) k[r2l2 == 0] = 1 else: try: tau = [xi - xj for xi, xj in zip(Xi, Xj)] except TypeError: tau = Xi - Xj try: r2l2 = sum([(t / l)**2 for t, l in zip(tau, args[2:])]) except TypeError: r2l2 = (tau / args[2])**2 y = mpmath.sqrt(2.0 * nu * r2l2) k = 2.0**(1 - nu) / mpmath.gamma(nu) * y**nu * mpmath.besselk(nu, y) k *= args[0]**2.0 return k
def mean(p, b, loc=0, scale=1): """ Mean of the generalized inverse Gaussian distribution. The mean is: K_{p + 1}(b) loc + scale -------------- K_p(b) where K_n(x) is the modified Bessel function of the second kind (implemented in mpmath as besselk(n, x)). """ p = mpmath.mpf(p) b = mpmath.mpf(b) loc = mpmath.mpf(loc) scale = mpmath.mpf(scale) return loc + scale * mpmath.besselk(p + 1, b) / mpmath.besselk(p, b)
def cramerVonMises(x, y): try: x = sorted(x) y = sorted(y) pool = x + y ps, pr = _sortRank(pool) rx = array([pr[ind] for ind in [ps.index(element) for element in x]]) ry = array([pr[ind] for ind in [ps.index(element) for element in y]]) n = len(x) m = len(y) i = array(range(1, n + 1)) j = array(range(1, m + 1)) u = n * sum(power((rx - i), 2)) + m * sum(power((ry - j), 2)) t = u / (n * m * (n + m)) - (4 * n * m - 1) / (6 * (n + m)) Tmu = 1 / 6 + 1 / (6 * (n + m)) Tvar = 1 / 45 * ((m + n + 1) / power( (m + n), 2)) * (4 * m * n * (m + n) - 3 * (power(m, 2) + power(n, 2)) - 2 * m * n) / (4 * m * n) t = (t - Tmu) / power(45 * Tvar, 0.5) + 1 / 6 if t < 0: return -1 elif t <= 12: a = 1 - mp.nsum( lambda x: (mp.gamma(x + 0.5) / (mp.gamma(0.5) * mp.fac(x))) * mp.power(4 * x + 1, 0.5) * mp. exp(-mp.power(4 * x + 1, 2) / (16 * t)) * mp.besselk(0.25, mp.power(4 * x + 1, 2) / (16 * t)), [0, 100]) / (mp.pi * mp.sqrt(t)) return float(mp.nstr(a, 3)) else: return 0 except Exception as e: print e return -1
def shot_noise_laplace_A_norm(X, g): """ Returns the normalized pdf of a shot noise process with laplace distributed amplitudes, A~Laplace(0,a) Input: X: Variable values, 1d numpy array. g: shape parameter Output: F: The pdf """ F = np.zeros(len(X)) assert (g > 0) g = mm.mpf(g) for i in range(len(X)): x = abs(X[i]) F[i] = (np.sqrt(g) * x / 2)**((g - 1) / 2) * mm.besselk((1 - g) / \ 2, np.sqrt(g) * x) * np.sqrt(g / np.pi) / mm.gamma(g / 2) return F
def spectrm1(sp, xx, kl2, L, rx, ry, s, np_, nr): wn = np.zeros((np_,nr)) if sp.lower() == 'exponential': # exponential for n in np.arange(1,np_+1): wn[n-1, :] = n* kl2/(n**2 + kl2 *((rx-s)**2+ry**2))**1.5 if sp.lower() == 'gaussian': # gaussian for n in np.arange(1,np_+1): wn[n-1,:] = 0.5 * kl2/n* math.exp(-kl2*((rx-s)**2 + ry**2)/(4*n)) if sp.lower() == 'power_spec': # x-power for n in np.arange(1,np_+1): wn[n-1,:] = kl2/(2.**(xx*n-1)*math.gamma(xx*n))* ( ( (rx-s)**2. + ry**2)*L)**(xx*n-1)* besselk(-xx*n+1, L*((rx-s)**2 + ry**2)) return wn
def norm_sym_dsn_dist(X, g): """ Returns the normalized pdf of the derivative of a symmetric shot noise process, (td/2)*dS(t)/dt, lambda = 1/2. Input: X: The normalized variable X = (x-<x>)/x_rms, 1d numpy array g: shape parameter Output: F: The pdf of X. """ F = np.zeros(len(X)) assert (g > 0) g = mm.mpf(g) for i in range(len(X)): x = mm.mpf(np.abs(X[i])) F[i] = mm.sqrt(2. * g / mm.pi) * 2.**(-g / 2.) * (mm.sqrt(g) * x)**( (g - 1.) / 2.) * mm.besselk((1. - g) / 2., mm.sqrt(g) * x) / mm.gamma(g / 2.) return F
def shot_noise_laplace_A(X, g, a): """ Returns the pdf of a shot noise process with laplace distributed amplitudes, A~Laplace(0,a) Input: X: Variable values, 1d numpy array. g: shape parameter a: scale parameter Output: F: The pdf """ F = np.zeros(len(X)) assert (g > 0) assert (a > 0) g = mm.mpf(g) a = mm.mpf(a) for i in range(len(X)): x = abs(X[i]) F[i] = (x / (2 * a))**((g - 1) / 2) * mm.besselk( (1 - g) / 2, x / a) / (a * np.sqrt(np.pi) * mm.gamma(g / 2)) return F
def psi(index, variable, b, a, beta): if b == 0: if beta < 0: return math.pow(variable, 0.5) * besseli( v(beta), sqrt(2 * index * q(a, beta, variable))) else: return math.pow(variable, 0.5) * besselk( v(beta), sqrt(2 * index * q(a, beta, variable))) else: if beta < 0: return math.pow(variable, beta + 0.5) * math.exp( 0.5 * eps(b, beta) * h(b, a, beta, variable)) * whitm( k(b, beta, index), m(beta), h(b, a, beta, variable)) else: return math.pow(variable, beta + 0.5) * math.exp( 0.5 * eps(b, beta) * h(b, a, beta, variable)) * whitw( k(b, beta, index), m(beta), h(b, a, beta, variable))
def logpdf(x, p, b, loc=0, scale=1): """ Log of the PDF of the generalized inverse Gaussian distribution. The PDF for x > loc is: z**(p - 1) * exp(-b*(z + 1/z)/2)) --------------------------------- scale * K_p(b) where s is the scale, z = (x - loc)/s, and K_p(b) is the modified Bessel function of the second kind. For x <= loc, the PDF is zero. """ x = mpmath.mpf(x) p = mpmath.mpf(p) b = mpmath.mpf(b) loc = mpmath.mpf(loc) scale = mpmath.mpf(scale) if x <= loc: return -mpmath.mp.inf z = (x - loc) / scale return ((p - 1) * mpmath.log(z) - b * (z + 1 / z) / 2 - mpmath.log(2 * mpmath.besselk(p, b)) - mpmath.log(scale))
def f94(x): # synchrotron_2 x = mpmath.mpf(x) coff = mpmath.mpf(2) / mpmath.mpf(3) return x * mpmath.besselk(coff, x)
def f31(x): # bessel_k2_scaled x = mpmath.mpf(x) y = mpmath.sqrt(mpmath.pi / (2 * x)) * mpmath.besselk(2.5, x) * mpmath.exp(x) return y
def f29(x): # bessel_k0_scaled x = mpmath.mpf(x) y = mpmath.sqrt(mpmath.pi / (2 * x)) * mpmath.besselk(0.5, x) * mpmath.exp(x) return y
def f19(x): # bessel_K1_scaled scale = mpmath.exp(x) return mpmath.besselk(1, x) * scale
def _compute_dk_dy(self, y, n): r"""Evaluate the derivative of the outer form of the Matern kernel. Uses the general Leibniz rule to compute the n-th derivative of: .. math:: f(y) = \frac{2^{1-\nu}}{\Gamma(\nu)} y^\nu K_\nu(y) Notice that this is very poorly-behaved at :math:`x=0`. There, the value is approximated using :py:func:`mpmath.diff` with the `singular` keyword. This is rather slow, so if you require a fixed value of `nu` you may wish to consider implementing the appropriate kernel separately. Parameters ---------- y : :py:class:`Array`, (`M`,) `M` inputs to evaluate at. n : non-negative scalar int. Order of derivative to compute. Returns ------- dk_dy : :py:class:`Array`, (`M`,) Specified derivative at specified locations. """ warnings.warn( "The Matern kernel has not been verified for derivatives. Consider using MaternKernelArb." ) dk_dy = scipy.zeros_like(y, dtype=float) non_zero_idxs = (y != 0) for k in xrange(0, n + 1): dk_dy[non_zero_idxs] += ( scipy.special.binom(n, k) * scipy.special.poch(1 - k + self.nu, k) * (y[non_zero_idxs])**(-k + self.nu) * scipy.special.kvp(self.nu, y[non_zero_idxs], n=n - k)) # Handle the cases at y=0. # Compute the appropriate value using mpmath's arbitrary precision # arithmetic. This is potentially slow, but seems to behave pretty # well. In cases where the value should be infinite, very large # (but still finite) floats are returned with the appropriate sign. if n >= 2 * self.nu: warnings.warn("n >= 2*nu can yield inaccurate results.", RuntimeWarning) # Use John Wright's expression for n < 2 * nu: if n < 2.0 * self.nu: if n % 2 == 1: dk_dy[~non_zero_idxs] = 0.0 else: m = n / 2.0 dk_dy[~non_zero_idxs] = ((-1.0)**m * 2.0**(self.nu - 1.0 - n) * scipy.special.gamma(self.nu - m) * scipy.misc.factorial(n) / scipy.misc.factorial(m)) else: # Fall back to mpmath to handle n >= 2 * nu: core_expr = lambda x: x**self.nu * mpmath.besselk(self.nu, x) deriv = mpmath.chop( mpmath.diff(core_expr, 0, n=n, singular=True, direction=1)) dk_dy[~non_zero_idxs] = deriv dk_dy *= 2.0**(1 - self.nu) / (scipy.special.gamma(self.nu)) return dk_dy
def test_besselk_int(self): assert_mpmath_equal(sc.kn, _exception_to_nan(lambda v, z: mpmath.besselk(v, z, **HYPERKW)), [IntArg(), Arg()], n=1000)
def test_besselk_complex(self): assert_mpmath_equal( lambda v, z: sc.kv(v.real, z), _exception_to_nan(lambda v, z: mpmath.besselk(v, z, **HYPERKW)), [Arg(-1e100, 1e100), ComplexArg()])
def sph_kn_bessel(n, z): out = besselk(n + mpf(1)/2, z)*sqrt(pi/(2*z)) return out
def log_besselKvFA(nu, y): val = np.log(kv(nu, y)) if np.isinf(val): val = np.log(sympy.Float(mpmath.besselk(nu, y))) return val
def test_besselk(self): assert_mpmath_equal( sc.kv, _exception_to_nan(lambda v, z: mpmath.besselk(v, z, **HYPERKW)), [Arg(-1e100, 1e100), Arg()], n=1000)
def f16(x): # bessel_K0 return mpmath.besselk(0, x)
def test_besselk_int(self): assert_mpmath_equal( sc.kn, _exception_to_nan(lambda v, z: mpmath.besselk(v, z, **HYPERKW)), [IntArg(), Arg()], n=1000)
def f17(x): # bessel_K1 return mpmath.besselk(1, x)
def test_besselk(self): assert_mpmath_equal(sc.kv, _exception_to_nan(lambda v, z: mpmath.besselk(v, z, **HYPERKW)), [Arg(-1e100, 1e100), Arg()], n=1000)
def f18(x): # bessel_K0_scaled scale = mpmath.exp(x) return mpmath.besselk(0, x) * scale
def test_besselk_complex(self): assert_mpmath_equal(lambda v, z: sc.kv(v.real, z), _exception_to_nan(lambda v, z: mpmath.besselk(v, z, **HYPERKW)), [Arg(-1e100, 1e100), ComplexArg()])
def _compute_dk_dy(self, y, n): r"""Evaluate the derivative of the outer form of the Matern kernel. Uses the general Leibniz rule to compute the n-th derivative of: .. math:: f(y) = \frac{2^{1-\nu}}{\Gamma(\nu)} y^\nu K_\nu(y) Notice that this is very poorly-behaved at :math:`x=0`. There, the value is approximated using :py:func:`mpmath.diff` with the `singular` keyword. This is rather slow, so if you require a fixed value of `nu` you may wish to consider implementing the appropriate kernel separately. Parameters ---------- y : :py:class:`Array`, (`M`,) `M` inputs to evaluate at. n : non-negative scalar int. Order of derivative to compute. Returns ------- dk_dy : :py:class:`Array`, (`M`,) Specified derivative at specified locations. """ warnings.warn("The Matern kernel has not been verified for derivatives. Consider using MaternKernelArb.") dk_dy = scipy.zeros_like(y, dtype=float) non_zero_idxs = (y != 0) for k in xrange(0, n + 1): dk_dy[non_zero_idxs] += (scipy.special.binom(n, k) * scipy.special.poch(1 - k + self.nu, k) * (y[non_zero_idxs])**(-k + self.nu) * scipy.special.kvp(self.nu, y[non_zero_idxs], n=n-k)) # Handle the cases at y=0. # Compute the appropriate value using mpmath's arbitrary precision # arithmetic. This is potentially slow, but seems to behave pretty # well. In cases where the value should be infinite, very large # (but still finite) floats are returned with the appropriate sign. if n >= 2 * self.nu: warnings.warn("n >= 2*nu can yield inaccurate results.", RuntimeWarning) # Use John Wright's expression for n < 2 * nu: if n < 2.0 * self.nu: if n % 2 == 1: dk_dy[~non_zero_idxs] = 0.0 else: m = n / 2.0 dk_dy[~non_zero_idxs] = ( (-1.0)**m * 2.0**(self.nu - 1.0 - n) * scipy.special.gamma(self.nu - m) * scipy.misc.factorial(n) / scipy.misc.factorial(m) ) else: # Fall back to mpmath to handle n >= 2 * nu: core_expr = lambda x: x**self.nu * mpmath.besselk(self.nu, x) deriv = mpmath.chop(mpmath.diff(core_expr, 0, n=n, singular=True, direction=1)) dk_dy[~non_zero_idxs] = deriv dk_dy *= 2.0**(1 - self.nu) / (scipy.special.gamma(self.nu)) return dk_dy
from math import gamma # Been there a while #has_scipy = False if has_scipy: from scipy.special import lambertw, ellipe, gammaincc, gamma # fluids from scipy.special import i1, i0, k1, k0, iv # ht from scipy.special import hyp2f1 if erf is None: from scipy.special import erf else: import mpmath # scipy is not available... fall back to mpmath as a Pure-Python implementation from mpmath import lambertw # Same branches as scipy, supports .real from mpmath import ellipe # seems the same so far # Figured out this definition from test_precompute_gammainc.py in scipy gammaincc = lambda a, x: mpmath.gammainc(a, a=x, regularized=True) iv = mpmath.besseli i1 = lambda x: mpmath.besseli(1, x) i0 = lambda x: mpmath.besseli(0, x) k1 = lambda x: mpmath.besselk(1, x) k0 = lambda x: mpmath.besselk(0, x) if erf is None: from mpmath import erf
def sph_kn_bessel(n, z): out = besselk(n + mpf(1) / 2, z) * sqrt(pi / (2 * z)) return out