def test_binomial_symbolic(): n = 10 # Because we're using for loops, can't do symbolic n p = symbols('p', positive=True) X = Binomial('X', n, p) assert simplify(E(X)) == n * p == simplify(moment(X, 1)) assert simplify(variance(X)) == n * p * (1 - p) == simplify(cmoment(X, 2)) assert cancel((skewness(X) - (1 - 2 * p) / sqrt(n * p * (1 - p)))) == 0 # Test ability to change success/failure winnings H, T = symbols('H T') Y = Binomial('Y', n, p, succ=H, fail=T) assert simplify(E(Y) - (n * (H * p + T * (1 - p)))) == 0
def test_binomial_numeric(): nvals = range(5) pvals = [0, Rational(1, 4), Rational(1, 2), Rational(3, 4), 1] for n in nvals: for p in pvals: X = Binomial('X', n, p) assert E(X) == n * p assert variance(X) == n * p * (1 - p) if n > 0 and 0 < p < 1: assert skewness(X) == (1 - 2 * p) / sqrt(n * p * (1 - p)) for k in range(n + 1): assert P(Eq(X, k)) == binomial(n, k) * p**k * (1 - p)**(n - k)
def test_binomial_verify_parameters(): pytest.raises(ValueError, lambda: Binomial('b', .2, .5)) pytest.raises(ValueError, lambda: Binomial('b', 3, 1.5))
def compute_moment(self, k): if self.distribution == 'finite': return sum([p * (b**k) for b, p in self.parameters]) if self.distribution == 'uniform': l, u = self.parameters return (u**(k + 1) - l**(k + 1)) / ((k + 1) * (u - l)) if self.distribution == 'gauss' or self.distribution == 'normal': mu, sigma_squared = self.parameters # For low moments avoid scipy.stats.moments as it does not support # parametric parameters. In the future get all moments directly, # using the following properties: # https://math.stackexchange.com/questions/1945448/methods-for-finding-raw-moments-of-the-normal-distribution if k == 0: return 1 elif k == 1: return mu elif k == 2: return mu**2 + sigma_squared elif k == 3: return mu * (mu**2 + 3 * sigma_squared) elif k == 4: return mu**4 + 6 * mu**2 * sigma_squared + 3 * sigma_squared**2 moment = norm(loc=mu, scale=sqrt(sigma_squared)).moment(k) return Rational(moment) if self.distribution == 'bernoulli': return sympify(self.parameters[0]) if self.distribution == 'geometric': p = sympify(self.parameters[0]) return p * polylog(-k, 1 - p) if self.distribution == 'exponential': lambd = sympify(self.parameters[0]) return factorial(k) / (lambd**k) if self.distribution == 'beta': alpha, beta = self.parameters alpha = sympify(alpha) beta = sympify(beta) r = symbols('r') return product((alpha + r) / (alpha + beta + r), (r, 0, k - 1)) if self.distribution == 'chi-squared': n = sympify(self.parameters[0]) i = symbols('i') return product(n + 2 * i, (i, 0, k - 1)) if self.distribution == 'rayleigh': s = sympify(self.parameters[0]) return (2**(k / 2)) * (s**k) * gamma(1 + k / 2) if self.distribution == 'unknown': return sympify(f"{self.var_name}(0)^{k}") if self.distribution == 'laplace': mu, b = self.parameters mu = sympify(mu) b = sympify(b) x = Laplace("x", mu, b) return E(x**k) if self.distribution == 'binomial': n, p = self.parameters n = sympify(n) p = sympify(p) x = Binomial("x", n, p) return E(x**k) if self.distribution == 'hypergeometric': N, K, n = self.parameters N = sympify(N) K = sympify(K) n = sympify(n) x = Hypergeometric("x", N, K, n) return E(x**k)