def poincare_dist0(x, c=1.0, precision=None): ''' Distance from 0 to x in the Poincare model with curvature -1/c''' if precision is not None: mpm.mp.dps = precision x_norm = mpm.norm(x) sqrt_c = mpm.sqrt(c) return 2 / sqrt_c * mpm.atanh(x_norm / sqrt_c)
def logistic_gaussian(m, v): if m == oo: if v == oo: return oo return Float('1.0') if v == oo: return Float('0.5') mpmath.mp.dps = 500 mmpf = m._to_mpmath(500) vmpf = v._to_mpmath(500) # The integration routine below is obtained by substituting x = atanh(t) # into the definition of logistic_gaussian # # f = lambda x: mpmath.exp(-(x - mmpf) * (x - mmpf) / (2 * vmpf)) / (1 + mpmath.exp(-x)) # result = 1 / mpmath.sqrt(2 * mpmath.pi * vmpf) * mpmath.quad(f, [-mpmath.inf, mpmath.inf]) # # Such substitution makes mpmath.quad call much faster. tanhm = mpmath.tanh(mmpf) # Not really a precise threshold, but fine for our data if tanhm == mpmath.mpf('1.0'): return Float('1.0') f = lambda t: mpmath.exp(-(mpmath.atanh(t) - mmpf) ** 2 / (2 * vmpf)) / ((1 - t) * (1 + t + mpmath.sqrt(1 - t * t))) coef = 1 / mpmath.sqrt(2 * mpmath.pi * vmpf) int, err = mpmath.quad(f, [-1, 1], error=True) result = coef * int if mpmath.mpf('1e50') * abs(err) > abs(int): print(f"Suspiciously big error when evaluating an integral for logistic_gaussian({m}, {v}).") print(f"Integral: {int}") print(f"integral error estimate: {err}") print(f"Coefficient: {coef}") print(f"Result (Coefficient * Integral): {result}") return Float(result)
def poincare_dist(x, y, c=1.0, precision=None): ''' The hyperbolic distance between points in the Poincare model with curvature -1/c Args: x, y: size 1xD mpmath matrix representing point in the D-dimensional ball |x| < 1 precision (int): bits of precision to use Returns: mpmath float object. Can be converted back to regular float ''' if precision is not None: mpm.mp.dps = precision x2 = mpm.fdot(x, x) y2 = mpm.fdot(y, y) xy = mpm.fdot(x, y) sqrt_c = mpm.sqrt(c) denom = 1 - 2 * c * xy + c**2 * x2 * y2 norm = mpm.norm( (-(1 - 2 * c * xy + c * y2) * x + (1. - c * x2) * y) / denom) return 2 / sqrt_c * mpm.atanh(sqrt_c * norm)
def pearsonr_ci(r, n, alpha, alternative='two-sided'): """ Confidence interval of Pearson's correlation coefficient. This function uses Fisher's transformation to compute the confidence interval of Pearson's correlation coefficient. Examples -------- Imports: >>> import mpmath >>> mpmath.mp.dps = 20 >>> from mpsci.stats import pearsonr, pearsonr_ci Sample data: >>> a = [2, 4, 5, 7, 10, 11, 12, 15, 16, 20] >>> b = [2.53, 2.41, 3.60, 2.69, 3.19, 4.05, 3.71, 4.65, 4.33, 4.70] Compute the correlation coefficient: >>> r, p = pearsonr(a, b) >>> r mpf('0.893060379514729854846') >>> p mpf('0.00050197523992669206603645') Compute the 95% confidence interval for r: >>> rlo, rhi = pearsonr_ci(r, n=len(a), alpha=0.05) >>> rlo mpf('0.60185206817708369265664') >>> rhi mpf('0.97464778383702233502275') """ if alternative not in ['two-sided', 'less', 'greater']: raise ValueError("alternative must be 'two-sided', 'less', or " "'greater'.") with mpmath.mp.extradps(5): zr = mpmath.atanh(r) n = mpmath.mp.mpf(n) alpha = mpmath.mp.mpf(alpha) s = mpmath.sqrt(1 / (n - 3)) if alternative == 'two-sided': h = normal.invcdf(1 - alpha / 2) zlo = zr - h * s zhi = zr + h * s rlo = mpmath.tanh(zlo) rhi = mpmath.tanh(zhi) elif alternative == 'less': h = normal.invcdf(1 - alpha) zhi = zr + h * s rhi = mpmath.tanh(zhi) rlo = -mpmath.mp.one else: # alternative == 'greater' h = normal.invcdf(1 - alpha) zlo = zr - h * s rlo = mpmath.tanh(zlo) rhi = mpmath.mp.one return rlo, rhi
def eval(self, z): return mpmath.atanh(z)
def f(t): one_minus_t = 1 - t one_minus_t_squared = 1 - t * t sqrt_one_minus_t_squared = mpmath.sqrt(one_minus_t_squared) return mpmath.exp(-(mpmath.atanh(t) - mmpf) ** 2 / (2 * vmpf)) * (one_minus_t - sqrt_one_minus_t_squared) / ((one_minus_t_squared + sqrt_one_minus_t_squared) * (one_minus_t + sqrt_one_minus_t_squared))
def f(t): one_minus_t_squared = 1 - t * t return mpmath.exp(-(mpmath.atanh(t) - mmpf) ** 2 / (2 * vmpf)) / (one_minus_t_squared + mpmath.sqrt(one_minus_t_squared))