Esempio n. 1
0
def Ptrue(Qp, I, R, S, Q, b, replacement=True):
    """
    Returns the probability of testing with replacement,
    in which tested individuals can be retested on the same day.
    
    Args
    ----
    Qp (int): number of positive tests.
    I (int): number of infecteds.
    R (int): number of recovered.
    S (int): number of suceptibles.
    Q (int): number of tests.
    b (float): biased-testing factor.
    replacement (boolean): testing with/without replacement.
    
    """

    if replacement:
        f0 = (I + R) / (S + I + R)
        Ptrue = binomial(Q, Qp) * power(f0 * exp(b), Qp) * power(
            1 - f0, Q - Qp)
        Ptrue /= power(1 + (exp(b) - 1) * f0, Q)

    else:
        product = [(I + R - k) / (S - Q + Qp - k) for k in range(Qp)]

        Ptrue = binomial(Q, Qp) * fprod(product) * exp(Qp*b) * \
                1/hyp2f1( -I - R, -Q, S - Q + 1, exp(b) )

    return Ptrue
Esempio n. 2
0
def test_print_factorials():
    assert mpp.doprint(factorial(x)) == '<mrow><mi>x</mi><mo>!</mo></mrow>'
    assert mpp.doprint(factorial(x + 1)) == '<mrow><mfenced><mrow><mi>x</mi><mo>+</mo><mn>1</mn></mrow></mfenced><mo>!</mo></mrow>'
    assert mpp.doprint(factorial2(x)) == '<mrow><mi>x</mi><mo>!!</mo></mrow>'
    assert mpp.doprint(factorial2(x + 1)) == '<mrow><mfenced><mrow><mi>x</mi><mo>+</mo><mn>1</mn></mrow></mfenced><mo>!!</mo></mrow>'
    assert mpp.doprint(binomial(x, y)) == '<mfenced><mfrac linethickness="0"><mi>x</mi><mi>y</mi></mfrac></mfenced>'
    assert mpp.doprint(binomial(4, x + y)) == '<mfenced><mfrac linethickness="0"><mn>4</mn><mrow><mi>x</mi><mo>+</mo><mi>y</mi></mrow></mfrac></mfenced>'
Esempio n. 3
0
def test_gosper_sum():
    assert gosper_sum(1, (k, 0, n)) == 1 + n
    assert gosper_sum(k, (k, 0, n)) == n * (1 + n) / 2
    assert gosper_sum(k**2, (k, 0, n)) == n * (1 + n) * (1 + 2 * n) / 6
    assert gosper_sum(k**3, (k, 0, n)) == n**2 * (1 + n)**2 / 4

    assert gosper_sum(2**k, (k, 0, n)) == 2 * 2**n - 1

    assert gosper_sum(factorial(k), (k, 0, n)) is None
    assert gosper_sum(binomial(n, k), (k, 0, n)) is None

    assert gosper_sum(factorial(k) / k**2, (k, 0, n)) is None
    assert gosper_sum((k - 3) * factorial(k), (k, 0, n)) is None

    assert gosper_sum(k * factorial(k), k) == factorial(k)
    assert gosper_sum(k * factorial(k),
                      (k, 0, n)) == n * factorial(n) + factorial(n) - 1

    assert gosper_sum((-1)**k * binomial(n, k), (k, 0, n)) == 0
    assert gosper_sum((-1)**k * binomial(n, k),
                      (k, 0, m)) == -(-1)**m * (m - n) * binomial(n, m) / n

    assert gosper_sum((4*k + 1)*factorial(k)/factorial(2*k + 1), (k, 0, n)) == \
        (2*factorial(2*n + 1) - factorial(n))/factorial(2*n + 1)

    # issue 6033:
    assert gosper_sum(
        n*(n + a + b)*a**n*b**n/(factorial(n + a)*factorial(n + b)), \
        (n, 0, m)).simplify() == -(a*b)**m*gamma(a + 1) \
        *gamma(b + 1)/(gamma(a)*gamma(b)*gamma(a + m + 1)*gamma(b + m + 1)) \
        + 1/(gamma(a)*gamma(b))
 def f(rv):
     if not (isinstance(rv, Pow) and isinstance(rv.base, (sin, cos))):
         return rv
     b, n = rv.as_base_exp()
     x = b.args[0]
     if n.is_Integer and n.is_positive:
         if n.is_odd and isinstance(b, cos):
             rv = 2**(1 - n) * Add(*[
                 binomial(n, k) * cos((n - 2 * k) * x)
                 for k in range((n + 1) / 2)
             ])
         elif n.is_odd and isinstance(b, sin):
             rv = 2**(1 - n) * (-1)**((n - 1) / 2) * Add(*[
                 binomial(n, k) * (-1)**k * sin((n - 2 * k) * x)
                 for k in range((n + 1) / 2)
             ])
         elif n.is_even and isinstance(b, cos):
             rv = 2**(1 - n) * Add(*[
                 binomial(n, k) * cos((n - 2 * k) * x) for k in range(n / 2)
             ])
         elif n.is_even and isinstance(b, sin):
             rv = 2**(1 - n) * (-1)**(n / 2) * Add(*[
                 binomial(n, k) * (-1)**k * cos((n - 2 * k) * x)
                 for k in range(n / 2)
             ])
         if n.is_even:
             rv += 2**(-n) * binomial(n, n / 2)
     return rv
Esempio n. 5
0
def test_limit_seq_fail():
    # improve Summation algorithm or add ad-hoc criteria
    e = (harmonic(n)**3 * Sum(1 / harmonic(k), (k, 1, n)) /
         (n * Sum(harmonic(k) / k, (k, 1, n))))
    assert limit_seq(e, n) == 2

    # No unique dominant term
    e = (Sum(2**k * binomial(2 * k, k) / k**2,
             (k, 1, n)) / (Sum(2**k / k * 2,
                               (k, 1, n)) * Sum(binomial(2 * k, k),
                                                (k, 1, n))))
    assert limit_seq(e, n) == S(3) / 7

    # Simplifications of summations needs to be improved.
    e = n**3 * Sum(2**k / k**2,
                   (k, 1, n))**2 / (2**n * Sum(2**k / k, (k, 1, n)))
    assert limit_seq(e, n) == 2

    e = (harmonic(n) * Sum(2**k / k,
                           (k, 1, n)) / (n * Sum(2**k * harmonic(k) / k**2,
                                                 (k, 1, n))))
    assert limit_seq(e, n) == 1

    e = (Sum(2**k * factorial(k) / k**2,
             (k, 1, 2 * n)) / (Sum(4**k / k**2,
                                   (k, 1, n)) * Sum(factorial(k),
                                                    (k, 1, 2 * n))))
    assert limit_seq(e, n) == S(3) / 16
Esempio n. 6
0
def dup_zz_mignotte_bound(f, K):
    """
    The Knuth-Cohen variant of Mignotte bound for
    univariate polynomials in `K[x]`.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x = ring("x", ZZ)

    >>> f = x**3 + 14*x**2 + 56*x + 64
    >>> R.dup_zz_mignotte_bound(f)
    152

    By checking `factor(f)` we can see that max coeff is 8

    Also consider a case that `f` is irreducible for example `f = 2*x**2 + 3*x + 4`
    To avoid a bug for these cases, we return the bound plus the max coefficient of `f`

    >>> f = 2*x**2 + 3*x + 4
    >>> R.dup_zz_mignotte_bound(f)
    6

    Lastly,To see the difference between the new and the old Mignotte bound
    consider the irreducible polynomial::

    >>> f = 87*x**7 + 4*x**6 + 80*x**5 + 17*x**4 + 9*x**3 + 12*x**2 + 49*x + 26
    >>> R.dup_zz_mignotte_bound(f)
    744

    The new Mignotte bound is 744 whereas the old one (SymPy 1.5.1) is 1937664.


    References
    ==========

    ..[1] [Abbott2013]_

    """
    from sympy.functions.combinatorial.factorials import binomial

    d = dup_degree(f)
    delta = _ceil(d / 2)
    delta2 = _ceil(delta / 2)

    # euclidean-norm
    eucl_norm = K.sqrt(sum([cf**2 for cf in f]))

    # biggest values of binomial coefficients (p. 538 of reference)
    t1 = binomial(delta - 1, delta2)
    t2 = binomial(delta - 1, delta2 - 1)

    lc = K.abs(dup_LC(f, K))  # leading coefficient
    bound = t1 * eucl_norm + t2 * lc  # (p. 538 of reference)
    bound += dup_max_norm(f, K)  # add max coeff for irreducible polys
    bound = _ceil(bound / 2) * 2  # round up to even integer

    return bound
Esempio n. 7
0
def test_limitseq_sum():
    from sympy.abc import x, y, z
    assert limit_seq(Sum(1 / x, (x, 1, y)) - log(y), y) == S.EulerGamma
    assert limit_seq(Sum(1 / x, (x, 1, y)) - 1 / y, y) is S.Infinity
    assert (limit_seq(
        binomial(2 * x, x) / Sum(binomial(2 * y, y), (y, 1, x)),
        x) == S(3) / 4)
    assert (limit_seq(
        Sum(y**2 * Sum(2**z / z, (z, 1, y)), (y, 1, x)) / (2**x * x), x) == 4)
Esempio n. 8
0
def test_issue_20286():
    n, p = symbols('n p')
    B = Binomial('B', n, p)
    k = Dummy('k', integer=True)
    eq = Sum(
        Piecewise(
            (-p**k * (1 - p)**(-k + n) *
             log(p**k * (1 - p)**(-k + n) * binomial(n, k)) * binomial(n, k),
             (k >= 0) & (k <= n)), (nan, True)), (k, 0, n))
    assert eq.dummy_eq(H(B))
Esempio n. 9
0
def apply(x, m, n, d, delta):
    i = Symbol.i(domain=Interval(0, m - d, right_open=True, integer=True))
    j = Symbol.j(domain=Interval(0, n, right_open=True, integer=True))
    h = Symbol.h(integer=True)

    return Equality(
        LAMBDA[j:m, i](binomial(d, j - i) *
                       (-1)**(d + i - j)) @ LAMBDA[j, i:m](
                           (i + delta)**j * x**i),
        LAMBDA[j, i]((i + delta)**j * x**i) @ LAMBDA[j, i:n](
            binomial(j, i) * Sum[h:0:d](binomial(d, h) *
                                        (-1)**(d - h) * x**h * h**(j - i))))
Esempio n. 10
0
def test_gosper_sum_iterated():
    f1 = binomial(2 * k, k) / 4**k
    f2 = (1 + 2 * n) * binomial(2 * n, n) / 4**n
    f3 = (1 + 2 * n) * (3 + 2 * n) * binomial(2 * n, n) / (3 * 4**n)
    f4 = (1 + 2 * n) * (3 + 2 * n) * (5 + 2 * n) * binomial(2 * n,
                                                            n) / (15 * 4**n)
    f5 = (1 + 2 * n) * (3 + 2 * n) * (5 + 2 * n) * (7 + 2 * n) * binomial(
        2 * n, n) / (105 * 4**n)

    assert gosper_sum(f1, (k, 0, n)) == f2
    assert gosper_sum(f2, (n, 0, n)) == f3
    assert gosper_sum(f3, (n, 0, n)) == f4
    assert gosper_sum(f4, (n, 0, n)) == f5
Esempio n. 11
0
 def _calc_bernoulli(n):
     s = 0
     a = int(binomial(n + 3, n - 6))
     for j in range(1, n//6 + 1):
         s += a * bernoulli(n - 6*j)
         # Avoid computing each binomial coefficient from scratch
         a *= _product(n - 6 - 6*j + 1, n - 6*j)
         a //= _product(6*j + 4, 6*j + 9)
     if n % 6 == 4:
         s = -Rational(n + 3, 6) - s
     else:
         s = Rational(n + 3, 3) - s
     return s / binomial(n + 3, n)
Esempio n. 12
0
def test_binomial_rewrite():
    n = Symbol('n', integer=True)
    k = Symbol('k', integer=True)
    x = Symbol('x')

    assert binomial(n,
                    k).rewrite(factorial) == factorial(n) / (factorial(k) *
                                                             factorial(n - k))
    assert binomial(
        n,
        k).rewrite(gamma) == gamma(n + 1) / (gamma(k + 1) * gamma(n - k + 1))
    assert binomial(n, k).rewrite(ff) == ff(n, k) / factorial(k)
    assert binomial(n, x).rewrite(ff) == binomial(n, x)
Esempio n. 13
0
def apply(x, y, n=None, free_symbol=None):
    if free_symbol is None:
        k = Symbol.k(integer=True)
    else:
        k = free_symbol
    if n is None:
        n = Symbol.n(integer=True, nonnegative=True)
        return Equality((x + y)**n,
                        Sum[k:0:n](binomial(n, k) * x**k * y**(n - k)))
    elif n < 0:
        return None
    else:
        return Equality((x + y)**n,
                        Sum[k:0:n](binomial(n, k) * x**k * y**(n - k)))
Esempio n. 14
0
    def rule(n, k):
        coeff, rewrite = S.One, False

        cn, _n = n.as_coeff_Add()

        if _n and cn.is_Integer and cn:
            coeff *= _rf(_n + 1, cn)/_rf(_n - k + 1, cn)
            rewrite = True
            n = _n

        # this sort of binomial has already been removed by
        # rising factorials but is left here in case the order
        # of rule application is changed
        if k.is_Add:
            ck, _k = k.as_coeff_Add()
            if _k and ck.is_Integer and ck:
                coeff *= _rf(n - ck - _k + 1, ck)/_rf(_k + 1, ck)
                rewrite = True
                k = _k

        if count_ops(k) > count_ops(n - k):
            rewrite = True
            k = n - k

        if rewrite:
            return coeff*binomial(n, k)
Esempio n. 15
0
    def rule(n, k):
        coeff, rewrite = S.One, False

        cn, _n = n.as_coeff_Add()

        if _n and cn.is_Integer and cn:
            coeff *= _rf(_n + 1, cn) / _rf(_n - k + 1, cn)
            rewrite = True
            n = _n

        # this sort of binomial has already been removed by
        # rising factorials but is left here in case the order
        # of rule application is changed
        if k.is_Add:
            ck, _k = k.as_coeff_Add()
            if _k and ck.is_Integer and ck:
                coeff *= _rf(n - ck - _k + 1, ck) / _rf(_k + 1, ck)
                rewrite = True
                k = _k

        if count_ops(k) > count_ops(n - k):
            rewrite = True
            k = n - k

        if rewrite:
            return coeff * binomial(n, k)
Esempio n. 16
0
def test_binomial_symbolic():
    n = 2
    p = symbols('p', positive=True)
    X = Binomial('X', n, p)
    t = Symbol('t')

    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
    assert cancel((kurtosis(X)) - (3 + (1 - 6 * p * (1 - p)) / (n * p *
                                                                (1 - p)))) == 0
    assert characteristic_function(X)(t) == p**2 * exp(
        2 * I * t) + 2 * p * (-p + 1) * exp(I * t) + (-p + 1)**2
    assert moment_generating_function(X)(
        t) == p**2 * exp(2 * t) + 2 * p * (-p + 1) * exp(t) + (-p + 1)**2

    # 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

    # test symbolic dimensions
    n = symbols('n')
    B = Binomial('B', n, p)
    raises(NotImplementedError, lambda: P(B > 2))
    assert density(B).dict == Density(BinomialDistribution(n, p, 1, 0))
    assert set(density(B).dict.subs(n, 4).doit().keys()) == \
    {S.Zero, S.One, S(2), S(3), S(4)}
    assert set(density(B).dict.subs(n, 4).doit().values()) == \
    {(1 - p)**4, 4*p*(1 - p)**3, 6*p**2*(1 - p)**2, 4*p**3*(1 - p), p**4}
    k = Dummy('k', integer=True)
    assert E(B > 2).dummy_eq(
        Sum(
            Piecewise((k * p**k * (1 - p)**(-k + n) * binomial(n, k), (k >= 0)
                       & (k <= n) & (k > 2)), (0, True)), (k, 0, n)))
Esempio n. 17
0
 def pmf(self, x):
     n, p = self.n, self.p
     x = sympify(x)
     if not (x.is_number or x.is_Symbol or is_random(x)):
         raise ValueError("'x' expected as an argument of type 'number', 'Symbol', or "
                     "'RandomSymbol' not %s" % (type(x)))
     cond = Ge(x, 0) & Le(x, n) & Contains(x, S.Integers)
     return Piecewise((binomial(n, x) * p**x * (1 - p)**(n - x), cond), (S.Zero, True))
Esempio n. 18
0
    def _eval_rewrite_as_Sum(self, arg):
        if arg.is_even:
            k = Dummy("k", integer=True)
            j = Dummy("j", integer=True)
            n = self.args[0] / 2
            Em = (S.ImaginaryUnit * C.Sum(C.Sum(binomial(k, j) * ((-1)**j * (k - 2*j)**(2*n + 1)) /
                  (2**k*S.ImaginaryUnit**k * k), (j, 0, k)), (k, 1, 2*n + 1)))

            return Em
Esempio n. 19
0
 def component_calc(self, a, b, epsilon, d):
     # Calculates a component in the Lie bracket
     d_index = int(str(epsilon)[-1])
     epsilon = [0 if i + 1 != d_index else 1 for i in range(self.m)]
     n = [a[i] + b[i] - epsilon[i] for i in range(self.m)]
     if any(i < 0 or i >= self.p for i in n):
         return 0
     binom = np.prod([binomial(n[i], a[i]) for i in range(self.m)]) % self.p
     return binom * self.exp_to_monomial(n) * d
 def get_size(self):
     r"""
     Returns
     -------
     size: int
         The size of set T. Set T is the set of all possible
         monomials of the n variables for degree equal to the
         degree_m
     """
     return binomial(self.degree_m + self.n - 1, self.n - 1)
 def get_size(self):
     r"""
     Returns
     -------
     size: int
         The size of set T. Set T is the set of all possible
         monomials of the n variables for degree equal to the
         degree_m
     """
     return binomial(self.degree_m + self.n - 1, self.n - 1)
Esempio n. 22
0
def test_gosper_sum_AeqB_part2():
    f2a = n**2 * a**n
    f2b = (n - r / 2) * binomial(r, n)
    f2c = factorial(n - 1)**2 / (factorial(n - x) * factorial(n + x))

    g2a = -a * (a + 1) / (a - 1)**3 + a**(m + 1) * (
        a**2 * m**2 - 2 * a * m**2 + m**2 - 2 * a * m + 2 * m + a + 1) / (a -
                                                                          1)**3
    g2b = (m - r) * binomial(r, m) / 2
    ff = factorial(1 - x) * factorial(1 + x)
    g2c = 1 / ff * (1 - 1 / x**2) + factorial(m)**2 / (
        x**2 * factorial(m - x) * factorial(m + x))

    g = gosper_sum(f2a, (n, 0, m))
    assert g is not None and simplify(g - g2a) == 0
    g = gosper_sum(f2b, (n, 0, m))
    assert g is not None and simplify(g - g2b) == 0
    g = gosper_sum(f2c, (n, 1, m))
    assert g is not None and simplify(g - g2c) == 0
Esempio n. 23
0
def test_binomial_diff():
    n = Symbol('n', integer=True)
    k = Symbol('k', integer=True)

    assert binomial(n, k).diff(n) == \
        (-polygamma(0, 1 + n - k) + polygamma(0, 1 + n))*binomial(n, k)
    assert binomial(n**2, k**3).diff(n) == \
        2*n*(-polygamma(
            0, 1 + n**2 - k**3) + polygamma(0, 1 + n**2))*binomial(n**2, k**3)

    assert binomial(n, k).diff(k) == \
        (-polygamma(0, 1 + k) + polygamma(0, 1 + n - k))*binomial(n, k)
    assert binomial(n**2, k**3).diff(k) == \
        3*k**2*(-polygamma(
            0, 1 + k**3) + polygamma(0, 1 + n**2 - k**3))*binomial(n**2, k**3)
    raises(ArgumentIndexError, lambda: binomial(n, k).fdiff(3))
Esempio n. 24
0
def test_hypergeometric_symbolic():
    N, m, n = symbols('N, m, n')
    H = Hypergeometric('H', N, m, n)
    dens = density(H).dict
    expec = E(H > 2)
    assert dens == Density(HypergeometricDistribution(N, m, n))
    assert dens.subs(N,
                     5).doit() == Density(HypergeometricDistribution(5, m, n))
    assert set(dens.subs({N: 3, m: 2, n: 1}).doit().keys()) == {S.Zero, S.One}
    assert set(dens.subs({
        N: 3,
        m: 2,
        n: 1
    }).doit().values()) == {Rational(1, 3), Rational(2, 3)}
    k = Dummy('k', integer=True)
    assert expec.dummy_eq(
        Sum(
            Piecewise(
                (k * binomial(m, k) * binomial(N - m, -k + n) / binomial(N, n),
                 k > 2), (0, True)), (k, 0, n)))
Esempio n. 25
0
def test_hyperexpand():
    # Luke, Y. L. (1969), The Special Functions and Their Approximations,
    # Volume 1, section 6.2

    assert hyperexpand(hyper([], [], z)) == exp(z)
    assert hyperexpand(hyper([1, 1], [2], -z)*z) == log(1 + z)
    assert hyperexpand(hyper([], [S.Half], -z**2/4)) == cos(z)
    assert hyperexpand(z*hyper([], [S('3/2')], -z**2/4)) == sin(z)
    assert hyperexpand(hyper([S('1/2'), S('1/2')], [S('3/2')], z**2)*z) \
        == asin(z)
    assert isinstance(Sum(binomial(2, z)*z**2, (z, 0, a)).doit(), Expr)
Esempio n. 26
0
    def _eval_rewrite_as_polynomial(self, n, x, **kwargs):
        from sympy import Sum

        k = Dummy("k")
        kern = (
            (-1) ** k
            * binomial(n, k) ** 2
            * ((1 + x) / 2) ** (n - k)
            * ((1 - x) / 2) ** k
        )
        return Sum(kern, (k, 0, n))
Esempio n. 27
0
def test_legendre():
    assert legendre(0, x) == 1
    assert legendre(1, x) == x
    assert legendre(2, x) == ((3 * x**2 - 1) / 2).expand()
    assert legendre(3, x) == ((5 * x**3 - 3 * x) / 2).expand()
    assert legendre(4, x) == ((35 * x**4 - 30 * x**2 + 3) / 8).expand()
    assert legendre(5, x) == ((63 * x**5 - 70 * x**3 + 15 * x) / 8).expand()
    assert legendre(6, x) == ((231 * x**6 - 315 * x**4 + 105 * x**2 - 5) /
                              16).expand()

    assert legendre(10, -1) == 1
    assert legendre(11, -1) == -1
    assert legendre(10, 1) == 1
    assert legendre(11, 1) == 1
    assert legendre(10, 0) != 0
    assert legendre(11, 0) == 0

    assert legendre(-1, x) == 1
    k = Symbol('k')
    assert legendre(5 - k, x).subs(k, 2) == ((5 * x**3 - 3 * x) / 2).expand()

    assert roots(legendre(4, x), x) == {
        sqrt(Rational(3, 7) - Rational(2, 35) * sqrt(30)): 1,
        -sqrt(Rational(3, 7) - Rational(2, 35) * sqrt(30)): 1,
        sqrt(Rational(3, 7) + Rational(2, 35) * sqrt(30)): 1,
        -sqrt(Rational(3, 7) + Rational(2, 35) * sqrt(30)): 1,
    }

    n = Symbol("n")

    X = legendre(n, x)
    assert isinstance(X, legendre)
    assert unchanged(legendre, n, x)

    assert legendre(n,
                    0) == sqrt(pi) / (gamma(S.Half - n / 2) * gamma(n / 2 + 1))
    assert legendre(n, 1) == 1
    assert legendre(n, oo) is oo
    assert legendre(-n, x) == legendre(n - 1, x)
    assert legendre(n, -x) == (-1)**n * legendre(n, x)
    assert unchanged(legendre, -n + k, x)

    assert conjugate(legendre(n, x)) == legendre(n, conjugate(x))

    assert diff(legendre(n, x), x) == \
        n*(x*legendre(n, x) - legendre(n - 1, x))/(x**2 - 1)
    assert diff(legendre(n, x), n) == Derivative(legendre(n, x), n)

    _k = Dummy('k')
    assert legendre(n, x).rewrite("polynomial").dummy_eq(
        Sum((-1)**_k * (S.Half - x / 2)**_k * (x / 2 + S.Half)**(-_k + n) *
            binomial(n, _k)**2, (_k, 0, n)))
    raises(ArgumentIndexError, lambda: legendre(n, x).fdiff(1))
    raises(ArgumentIndexError, lambda: legendre(n, x).fdiff(3))
Esempio n. 28
0
def _stirling1(n, k):
    if n == k == 0:
        return S.One
    if 0 in (n, k):
        return S.Zero
    n1 = n - 1

    # some special values
    if n == k:
        return S.One
    elif k == 1:
        return factorial(n1)
    elif k == n1:
        return binomial(n, 2)
    elif k == n - 2:
        return (3*n - 1)*binomial(n, 3)/4
    elif k == n - 3:
        return binomial(n, 2)*binomial(n, 4)

    # general recurrence
    return n1*_stirling1(n1, k) + _stirling1(n1, k - 1)
Esempio n. 29
0
def binomial_coefficient(
        n: Union[int, float, complex],
        k: Union[int, float, complex]) -> Union[int, float, complex]:
    try:
        import sympy.functions.combinatorial.factorials as fs
    except ModuleNotFoundError:
        if isinstance(n, int) and isinstance(k, int):
            return factorial(n) // factorial(k) // factorial(n - k)
        elif isinstance(n, (int, float)) and isinstance(k, (int, float)):
            return factorial(n) / factorial(k) / factorial(float(n) - float(k))
        else:
            raise Exception(
                "Can't take binomial coefficient of complex number (install sympy)"
            )

    if isinstance(n, int) and isinstance(k, int):
        return int(fs.binomial(n, k))
    elif isinstance(n, (int, float)) and isinstance(k, (int, float)):
        return float(fs.binomial(float(n), k))
    else:
        return complex(fs.binomial(complex(n),
                                   k))  # type: ignore # seems to work...
Esempio n. 30
0
def test_binomial_numeric():
    nvals = range(5)
    pvals = [0, Rational(1, 4), S.Half, 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))
                assert kurtosis(X) == 3 + (1 - 6 * p * (1 - p)) / (n * p *
                                                                   (1 - p))
            for k in range(n + 1):
                assert P(Eq(X, k)) == binomial(n, k) * p**k * (1 - p)**(n - k)
Esempio n. 31
0
def _stirling2(n, k):
    if n == k == 0:
        return S.One
    if 0 in (n, k):
        return S.Zero
    n1 = n - 1

    # some special values
    if k == n1:
        return binomial(n, 2)
    elif k == 2:
        return 2**n1 - 1

    # general recurrence
    return k*_stirling2(n1, k) + _stirling2(n1, k - 1)
Esempio n. 32
0
    def eval(cls, n, sym=None):
        if n.is_Number:
            if n.is_Integer and n.is_nonnegative:
                if n is S.Zero:
                    return S.One
                elif n is S.One:
                    if sym is None:
                        return -S.Half
                    else:
                        return sym - S.Half
                # Bernoulli numbers
                elif sym is None:
                    if n.is_odd:
                        return S.Zero
                    n = int(n)
                    # Use mpmath for enormous Bernoulli numbers
                    if n > 500:
                        p, q = bernfrac(n)
                        return Rational(int(p), int(q))
                    case = n % 6
                    highest_cached = cls._highest[case]
                    if n <= highest_cached:
                        return cls._cache[n]
                    # To avoid excessive recursion when, say, bernoulli(1000) is
                    # requested, calculate and cache the entire sequence ... B_988,
                    # B_994, B_1000 in increasing order
                    for i in range(highest_cached + 6, n + 6, 6):
                        b = cls._calc_bernoulli(i)
                        cls._cache[i] = b
                        cls._highest[case] = i
                    return b
                # Bernoulli polynomials
                else:
                    n, result = int(n), []
                    for k in range(n + 1):
                        result.append(binomial(n, k)*cls(k)*sym**(n - k))
                    return Add(*result)
            else:
                raise ValueError("Bernoulli numbers are defined only"
                                 " for nonnegative integer indices.")

        if sym is None:
            if n.is_odd and (n - 1).is_positive:
                return S.Zero
Esempio n. 33
0
    def f(rv):
        if not rv.is_Mul:
            return rv
        rvd = rv.as_powers_dict()
        nd_fact_args = [[], []] # numerator, denominator

        for k in rvd:
            if isinstance(k, factorial) and rvd[k].is_Integer:
                if rvd[k].is_positive:
                    nd_fact_args[0].extend([k.args[0]]*rvd[k])
                else:
                    nd_fact_args[1].extend([k.args[0]]*-rvd[k])
                rvd[k] = 0
        if not nd_fact_args[0] or not nd_fact_args[1]:
            return rv

        hit = False
        for m in range(2):
            i = 0
            while i < len(nd_fact_args[m]):
                ai = nd_fact_args[m][i]
                for j in range(i + 1, len(nd_fact_args[m])):
                    aj = nd_fact_args[m][j]

                    sum = ai + aj
                    if sum in nd_fact_args[1 - m]:
                        hit = True

                        nd_fact_args[1 - m].remove(sum)
                        del nd_fact_args[m][j]
                        del nd_fact_args[m][i]

                        rvd[binomial(sum, ai if count_ops(ai) <
                                count_ops(aj) else aj)] += (
                                -1 if m == 0 else 1)
                        break
                else:
                    i += 1

        if hit:
            return Mul(*([k**rvd[k] for k in rvd] + [factorial(k)
                    for k in nd_fact_args[0]]))/Mul(*[factorial(k)
                    for k in nd_fact_args[1]])
        return rv
Esempio n. 34
0
    def eval(cls, n, alpha, x):
        # L_{n}^{0}(x)  --->  L_{n}(x)
        if alpha == S.Zero:
            return laguerre(n, x)

        if not n.is_Number:
            # We can evaluate for some special values of x
            if x == S.Zero:
                return binomial(n + alpha, alpha)
            elif x == S.Infinity and n > S.Zero:
                return S.NegativeOne**n * S.Infinity
            elif x == S.NegativeInfinity and n > S.Zero:
                return S.Infinity
        else:
            # n is a given fixed integer, evaluate into polynomial
            if n.is_negative:
                raise ValueError(
                    "The index n must be nonnegative integer (got %r)" % n)
            else:
                return laguerre_poly(n, x, alpha)
Esempio n. 35
0
def nC(n, k=None, replacement=False):
    """Return the number of combinations of ``n`` items taken ``k`` at a time.

    Possible values for ``n``::
        integer - set of length ``n``
        sequence - converted to a multiset internally
        multiset - {element: multiplicity}

    If ``k`` is None then the total of all combinations of length 0
    through the number of items represented in ``n`` will be returned.

    If ``replacement`` is True then a given item can appear more than once
    in the ``k`` items. (For example, for 'ab' sets of 2 would include 'aa',
    'ab', and 'bb'.) The multiplicity of elements in ``n`` is ignored when
    ``replacement`` is True but the total number of elements is considered
    since no element can appear more times than the number of elements in
    ``n``.

    Examples
    ========

    >>> from sympy.functions.combinatorial.numbers import nC
    >>> from sympy.utilities.iterables import multiset_combinations
    >>> nC(3, 2)
    3
    >>> nC('abc', 2)
    3
    >>> nC('aab', 2)
    2

    When ``replacement`` is True, each item can have multiplicity
    equal to the length represented by ``n``:

    >>> nC('aabc', replacement=True)
    35
    >>> [len(list(multiset_combinations('aaaabbbbcccc', i))) for i in range(5)]
    [1, 3, 6, 10, 15]
    >>> sum(_)
    35

    If there are ``k`` items with multiplicities ``m_1, m_2, ..., m_k``
    then the total of all combinations of length 0 hrough ``k`` is the
    product, ``(m_1 + 1)*(m_2 + 1)*...*(m_k + 1)``. When the multiplicity
    of each item is 1 (i.e., k unique items) then there are 2**k
    combinations. For example, if there are 4 unique items, the total number
    of combinations is 16:

    >>> sum(nC(4, i) for i in range(5))
    16

    References
    ==========

    .. [1] http://en.wikipedia.org/wiki/Combination
    .. [2] http://tinyurl.com/cep849r

    See Also
    ========
    sympy.utilities.iterables.multiset_combinations
    """
    from sympy.functions.combinatorial.factorials import binomial
    from sympy.core.mul import prod

    if isinstance(n, SYMPY_INTS):
        if k is None:
            if not replacement:
                return 2**n
            return sum(nC(n, i, replacement) for i in range(n + 1))
        if k < 0:
            raise ValueError("k cannot be negative")
        if replacement:
            return binomial(n + k - 1, k)
        return binomial(n, k)
    if isinstance(n, _MultisetHistogram):
        N = n[_N]
        if k is None:
            if not replacement:
                return prod(m + 1 for m in n[_M])
            return sum(nC(n, i, replacement) for i in range(N + 1))
        elif replacement:
            return nC(n[_ITEMS], k, replacement)
        # assert k >= 0
        elif k in (1, N - 1):
            return n[_ITEMS]
        elif k in (0, N):
            return 1
        return _AOP_product(tuple(n[_M]))[k]
    else:
        return nC(_multiset_histogram(n), k, replacement)
Esempio n. 36
0
 def _eval_rewrite_as_polynomial(self, n, x):
     from sympy import Sum
     k = Dummy("k")
     kern = (-1)**k*binomial(n, k)**2*((1 + x)/2)**(n - k)*((1 - x)/2)**k
     return Sum(kern, (k, 0, n))
Esempio n. 37
0
 def _eval_rewrite_as_polynomial(self, n, x):
     from sympy import Sum
     k = Dummy("k")
     kern = binomial(n, 2*k) * (x**2 - 1)**k * x**(n - 2*k)
     return Sum(kern, (k, 0, floor(n/2)))
Esempio n. 38
0
def combsimp(expr):
    r"""
    Simplify combinatorial expressions.

    This function takes as input an expression containing factorials,
    binomials, Pochhammer symbol and other "combinatorial" functions,
    and tries to minimize the number of those functions and reduce
    the size of their arguments. The result is be given in terms of
    binomials and factorials.

    The algorithm works by rewriting all combinatorial functions as
    expressions involving rising factorials (Pochhammer symbols) and
    applies recurrence relations and other transformations applicable
    to rising factorials, to reduce their arguments, possibly letting
    the resulting rising factorial to cancel. Rising factorials with
    the second argument being an integer are expanded into polynomial
    forms and finally all other rising factorial are rewritten in terms
    more familiar functions. If the initial expression contained any
    combinatorial functions, the result is expressed using binomial
    coefficients and gamma functions. If the initial expression consisted
    of gamma functions alone, the result is expressed in terms of gamma
    functions.

    If the result is expressed using gamma functions, the following three
    additional steps are performed:

    1. Reduce the number of gammas by applying the reflection theorem
       gamma(x)*gamma(1-x) == pi/sin(pi*x).
    2. Reduce the number of gammas by applying the multiplication theorem
       gamma(x)*gamma(x+1/n)*...*gamma(x+(n-1)/n) == C*gamma(n*x).
    3. Reduce the number of prefactors by absorbing them into gammas, where
       possible.

    All transformation rules can be found (or was derived from) here:

    1. http://functions.wolfram.com/GammaBetaErf/Pochhammer/17/01/02/
    2. http://functions.wolfram.com/GammaBetaErf/Pochhammer/27/01/0005/

    Examples
    ========

    >>> from sympy.simplify import combsimp
    >>> from sympy import factorial, binomial
    >>> from sympy.abc import n, k

    >>> combsimp(factorial(n)/factorial(n - 3))
    n*(n - 2)*(n - 1)
    >>> combsimp(binomial(n+1, k+1)/binomial(n, k))
    (n + 1)/(k + 1)

    """

    # as a rule of thumb, if the expression contained gammas initially, it
    # probably makes sense to retain them
    as_gamma = not expr.has(factorial, binomial)


    expr = expr.replace(binomial,
        lambda n, k: _rf((n - k + 1).expand(), k.expand())/_rf(1, k.expand()))
    expr = expr.replace(factorial,
        lambda n: _rf(1, n.expand()))
    expr = expr.rewrite(gamma)
    expr = expr.replace(gamma,
        lambda n: _rf(1, (n - 1).expand()))

    if as_gamma:
        expr = expr.replace(_rf,
            lambda a, b: gamma(a + b)/gamma(a))
    else:
        expr = expr.replace(_rf,
            lambda a, b: binomial(a + b - 1, b)*factorial(b))

    def rule(n, k):
        coeff, rewrite = S.One, False

        cn, _n = n.as_coeff_Add()

        if _n and cn.is_Integer and cn:
            coeff *= _rf(_n + 1, cn)/_rf(_n - k + 1, cn)
            rewrite = True
            n = _n

        # this sort of binomial has already been removed by
        # rising factorials but is left here in case the order
        # of rule application is changed
        if k.is_Add:
            ck, _k = k.as_coeff_Add()
            if _k and ck.is_Integer and ck:
                coeff *= _rf(n - ck - _k + 1, ck)/_rf(_k + 1, ck)
                rewrite = True
                k = _k

        if rewrite:
            return coeff*binomial(n, k)

    expr = expr.replace(binomial, rule)

    def rule_gamma(expr, level=0):
        """ Simplify products of gamma functions further. """

        if expr.is_Atom:
            return expr

        def gamma_rat(x):
            # helper to simplify ratios of gammas
            was = x.count(gamma)
            xx = x.replace(gamma, lambda n: _rf(1, (n - 1).expand()
                ).replace(_rf, lambda a, b: gamma(a + b)/gamma(a)))
            if xx.count(gamma) < was:
                x = xx
            return x

        def gamma_factor(x):
            # return True if there is a gamma factor in shallow args
            if x.func is gamma:
                return True
            if x.is_Add or x.is_Mul:
                return any(gamma_factor(xi) for xi in x.args)
            if x.is_Pow and (x.exp.is_integer or x.base.is_positive):
                return gamma_factor(x.base)
            return False

        # recursion step
        if level == 0:
            expr = expr.func(*[rule_gamma(x, level + 1) for x in expr.args])
            level += 1

        if not expr.is_Mul:
            return expr

        # non-commutative step
        if level == 1:
            args, nc = expr.args_cnc()
            if not args:
                return expr
            if nc:
                return rule_gamma(Mul._from_args(args), level + 1)*Mul._from_args(nc)
            level += 1

        # pure gamma handling, not factor absorbtion
        if level == 2:
            sifted = sift(expr.args, gamma_factor)
            gamma_ind = Mul(*sifted.pop(False, []))
            d = Mul(*sifted.pop(True, []))
            assert not sifted

            nd, dd = d.as_numer_denom()
            for ipass in range(2):
                args = list(ordered(Mul.make_args(nd)))
                for i, ni in enumerate(args):
                    if ni.is_Add:
                        ni, dd = Add(*[
                            rule_gamma(gamma_rat(a/dd), level + 1) for a in ni.args]
                            ).as_numer_denom()
                        args[i] = ni
                        if not dd.has(gamma):
                            break
                nd = Mul(*args)
                if ipass ==  0 and not gamma_factor(nd):
                    break
                nd, dd = dd, nd  # now process in reversed order
            expr = gamma_ind*nd/dd
            if not (expr.is_Mul and (gamma_factor(dd) or gamma_factor(nd))):
                return expr
            level += 1

        # iteration until constant
        if level == 3:
            while True:
                was = expr
                expr = rule_gamma(expr, 4)
                if expr == was:
                    return expr

        numer_gammas = []
        denom_gammas = []
        numer_others = []
        denom_others = []
        def explicate(p):
            if p is S.One:
                return None, []
            b, e = p.as_base_exp()
            if e.is_Integer:
                if b.func is gamma:
                    return True, [b.args[0]]*e
                else:
                    return False, [b]*e
            else:
                return False, [p]

        newargs = list(ordered(expr.args))
        while newargs:
            n, d = newargs.pop().as_numer_denom()
            isg, l = explicate(n)
            if isg:
                numer_gammas.extend(l)
            elif isg is False:
                numer_others.extend(l)
            isg, l = explicate(d)
            if isg:
                denom_gammas.extend(l)
            elif isg is False:
                denom_others.extend(l)

        # =========== level 2 work: pure gamma manipulation =========

        # Try to reduce the number of gamma factors by applying the
        # reflection formula gamma(x)*gamma(1-x) = pi/sin(pi*x)
        for gammas, numer, denom in [(
            numer_gammas, numer_others, denom_others),
                (denom_gammas, denom_others, numer_others)]:
            new = []
            while gammas:
                g1 = gammas.pop()
                if g1.is_integer:
                    new.append(g1)
                    continue
                for i, g2 in enumerate(gammas):
                    n = g1 + g2 - 1
                    if not n.is_Integer:
                        continue
                    numer.append(S.Pi)
                    denom.append(sin(S.Pi*g1))
                    gammas.pop(i)
                    if n > 0:
                        for k in range(n):
                            numer.append(1 - g1 + k)
                    elif n < 0:
                        for k in range(-n):
                            denom.append(-g1 - k)
                    break
                else:
                    new.append(g1)
            # /!\ updating IN PLACE
            gammas[:] = new

        # Try to reduce the number of gammas by using the duplication
        # theorem to cancel an upper and lower: gamma(2*s)/gamma(s) =
        # 2**(2*s + 1)/(4*sqrt(pi))*gamma(s + 1/2). Although this could
        # be done with higher argument ratios like gamma(3*x)/gamma(x),
        # this would not reduce the number of gammas as in this case.
        for ng, dg, no, do in [(numer_gammas, denom_gammas, numer_others,
                                denom_others),
                               (denom_gammas, numer_gammas, denom_others,
                                numer_others)]:

            while True:
                for x in ng:
                    for y in dg:
                        n = x - 2*y
                        if n.is_Integer:
                            break
                    else:
                        continue
                    break
                else:
                    break
                ng.remove(x)
                dg.remove(y)
                if n > 0:
                    for k in range(n):
                        no.append(2*y + k)
                elif n < 0:
                    for k in range(-n):
                        do.append(2*y - 1 - k)
                ng.append(y + S(1)/2)
                no.append(2**(2*y - 1))
                do.append(sqrt(S.Pi))

        # Try to reduce the number of gamma factors by applying the
        # multiplication theorem (used when n gammas with args differing
        # by 1/n mod 1 are encountered).
        #
        # run of 2 with args differing by 1/2
        #
        # >>> combsimp(gamma(x)*gamma(x+S.Half))
        # 2*sqrt(2)*2**(-2*x - 1/2)*sqrt(pi)*gamma(2*x)
        #
        # run of 3 args differing by 1/3 (mod 1)
        #
        # >>> combsimp(gamma(x)*gamma(x+S(1)/3)*gamma(x+S(2)/3))
        # 6*3**(-3*x - 1/2)*pi*gamma(3*x)
        # >>> combsimp(gamma(x)*gamma(x+S(1)/3)*gamma(x+S(5)/3))
        # 2*3**(-3*x - 1/2)*pi*(3*x + 2)*gamma(3*x)
        #
        def _run(coeffs):
            # find runs in coeffs such that the difference in terms (mod 1)
            # of t1, t2, ..., tn is 1/n
            u = list(uniq(coeffs))
            for i in range(len(u)):
                dj = ([((u[j] - u[i]) % 1, j) for j in range(i + 1, len(u))])
                for one, j in dj:
                    if one.p == 1 and one.q != 1:
                        n = one.q
                        got = [i]
                        get = list(range(1, n))
                        for d, j in dj:
                            m = n*d
                            if m.is_Integer and m in get:
                                get.remove(m)
                                got.append(j)
                                if not get:
                                    break
                        else:
                            continue
                        for i, j in enumerate(got):
                            c = u[j]
                            coeffs.remove(c)
                            got[i] = c
                        return one.q, got[0], got[1:]

        def _mult_thm(gammas, numer, denom):
            # pull off and analyze the leading coefficient from each gamma arg
            # looking for runs in those Rationals

            # expr -> coeff + resid -> rats[resid] = coeff
            rats = {}
            for g in gammas:
                c, resid = g.as_coeff_Add()
                rats.setdefault(resid, []).append(c)

            # look for runs in Rationals for each resid
            keys = sorted(rats, key=default_sort_key)
            for resid in keys:
                coeffs = list(sorted(rats[resid]))
                new = []
                while True:
                    run = _run(coeffs)
                    if run is None:
                        break

                    # process the sequence that was found:
                    # 1) convert all the gamma functions to have the right
                    #    argument (could be off by an integer)
                    # 2) append the factors corresponding to the theorem
                    # 3) append the new gamma function

                    n, ui, other = run

                    # (1)
                    for u in other:
                        con = resid + u - 1
                        for k in range(int(u - ui)):
                            numer.append(con - k)

                    con = n*(resid + ui)  # for (2) and (3)

                    # (2)
                    numer.append((2*S.Pi)**(S(n - 1)/2)*
                                 n**(S(1)/2 - con))
                    # (3)
                    new.append(con)

                # restore resid to coeffs
                rats[resid] = [resid + c for c in coeffs] + new

            # rebuild the gamma arguments
            g = []
            for resid in keys:
                g += rats[resid]
            # /!\ updating IN PLACE
            gammas[:] = g

        for l, numer, denom in [(numer_gammas, numer_others, denom_others),
                                (denom_gammas, denom_others, numer_others)]:
            _mult_thm(l, numer, denom)

        # =========== level >= 2 work: factor absorbtion =========

        if level >= 2:
            # Try to absorb factors into the gammas: x*gamma(x) -> gamma(x + 1)
            # and gamma(x)/(x - 1) -> gamma(x - 1)
            # This code (in particular repeated calls to find_fuzzy) can be very
            # slow.
            def find_fuzzy(l, x):
                if not l:
                    return
                S1, T1 = compute_ST(x)
                for y in l:
                    S2, T2 = inv[y]
                    if T1 != T2 or (not S1.intersection(S2) and
                                    (S1 != set() or S2 != set())):
                        continue
                    # XXX we want some simplification (e.g. cancel or
                    # simplify) but no matter what it's slow.
                    a = len(cancel(x/y).free_symbols)
                    b = len(x.free_symbols)
                    c = len(y.free_symbols)
                    # TODO is there a better heuristic?
                    if a == 0 and (b > 0 or c > 0):
                        return y

            # We thus try to avoid expensive calls by building the following
            # "invariants": For every factor or gamma function argument
            #   - the set of free symbols S
            #   - the set of functional components T
            # We will only try to absorb if T1==T2 and (S1 intersect S2 != emptyset
            # or S1 == S2 == emptyset)
            inv = {}

            def compute_ST(expr):
                if expr in inv:
                    return inv[expr]
                return (expr.free_symbols, expr.atoms(Function).union(
                        set(e.exp for e in expr.atoms(Pow))))

            def update_ST(expr):
                inv[expr] = compute_ST(expr)
            for expr in numer_gammas + denom_gammas + numer_others + denom_others:
                update_ST(expr)

            for gammas, numer, denom in [(
                numer_gammas, numer_others, denom_others),
                    (denom_gammas, denom_others, numer_others)]:
                new = []
                while gammas:
                    g = gammas.pop()
                    cont = True
                    while cont:
                        cont = False
                        y = find_fuzzy(numer, g)
                        if y is not None:
                            numer.remove(y)
                            if y != g:
                                numer.append(y/g)
                                update_ST(y/g)
                            g += 1
                            cont = True
                        y = find_fuzzy(denom, g - 1)
                        if y is not None:
                            denom.remove(y)
                            if y != g - 1:
                                numer.append((g - 1)/y)
                                update_ST((g - 1)/y)
                            g -= 1
                            cont = True
                    new.append(g)
                # /!\ updating IN PLACE
                gammas[:] = new

        # =========== rebuild expr ==================================

        return Mul(*[gamma(g) for g in numer_gammas]) \
            / Mul(*[gamma(g) for g in denom_gammas]) \
            * Mul(*numer_others) / Mul(*denom_others)

    # (for some reason we cannot use Basic.replace in this case)
    was = factor(expr)
    expr = rule_gamma(was)
    if expr != was:
        expr = factor(expr)

    return expr
Esempio n. 39
0
 def _eval_rewrite_as_binomial(self, n):
     return binomial(2*n, n)/(n + 1)
Esempio n. 40
0
    def __mul__(self, other):
        ann_self = self.annihilator

        if not isinstance(other, HolonomicFunction):
            other = sympify(other)

            if not other.is_constant():
                raise NotImplementedError(" Can't multiply a HolonomicFunction and expressions/functions.")

            if not self._have_init_cond:
                return self
            else:
                y0 = _extend_y0(self, ann_self.order)
                y1 = []
                for j in y0:
                    y1.append(j * other)
                return HolonomicFunction(ann_self, self.x, self.x0, y1)

        ann_other = other.annihilator
        list_self = []
        list_other = []
        a = ann_self.order
        b = ann_other.order

        R = ann_self.parent.base
        K = R.get_field()

        for j in ann_self.listofpoly:
            list_self.append(K.new(j.rep))

        for j in ann_other.listofpoly:
            list_other.append(K.new(j.rep))

        # will be used to reduce the degree
        self_red = [-list_self[i] / list_self[a] for i in range(a)]

        other_red = [-list_other[i] / list_other[b] for i in range(b)]

        # coeff_mull[i][j] is the coefficient of Dx^i(f).Dx^j(g)
        coeff_mul = [[S(0) for i in range(b + 1)] for j in range(a + 1)]
        coeff_mul[0][0] = S(1)

        # making the ansatz
        lin_sys = [[coeff_mul[i][j] for i in range(a) for j in range(b)]]

        homo_sys = [[S(0) for q in range(a * b)]]
        homo_sys = NewMatrix(homo_sys).transpose()

        sol = (NewMatrix(lin_sys).transpose()).gauss_jordan_solve(homo_sys)

        # until a non trivial solution is found
        while sol[0].is_zero:

            # updating the coefficents Dx^i(f).Dx^j(g) for next degree
            for i in range(a - 1, -1, -1):
                for j in range(b - 1, -1, -1):
                    coeff_mul[i][j + 1] += coeff_mul[i][j]
                    coeff_mul[i + 1][j] += coeff_mul[i][j]
                    if isinstance(coeff_mul[i][j], K.dtype):
                        coeff_mul[i][j] = DMFdiff(coeff_mul[i][j])
                    else:
                        coeff_mul[i][j] = coeff_mul[i][j].diff()

            # reduce the terms to lower power using annihilators of f, g
            for i in range(a + 1):
                if not coeff_mul[i][b] == S(0):
                    for j in range(b):
                        coeff_mul[i][j] += other_red[j] * \
                            coeff_mul[i][b]
                    coeff_mul[i][b] = S(0)

            # not d2 + 1, as that is already covered in previous loop
            for j in range(b):
                if not coeff_mul[a][j] == 0:
                    for i in range(a):
                        coeff_mul[i][j] += self_red[i] * \
                            coeff_mul[a][j]
                    coeff_mul[a][j] = S(0)

            lin_sys.append([coeff_mul[i][j] for i in range(a)
                            for j in range(b)])

            sol = (NewMatrix(lin_sys).transpose()).gauss_jordan_solve(homo_sys)


        sol_ann = _normalize(sol[0][0:], self.annihilator.parent, negative=False)

        if self._have_init_cond and other._have_init_cond:
            if self.x0 == other.x0:

                # try to find more inital conditions
                y0_self = _extend_y0(self, sol_ann.order)
                y0_other = _extend_y0(other, sol_ann.order)
                # h(x0) = f(x0) * g(x0)
                y0 = [y0_self[0] * y0_other[0]]

                # coefficient of Dx^j(f)*Dx^i(g) in Dx^i(fg)
                for i in range(1, min(len(y0_self), len(y0_other))):
                    coeff = [[0 for i in range(i + 1)] for j in range(i + 1)]
                    for j in range(i + 1):
                        for k in range(i + 1):
                            if j + k == i:
                                coeff[j][k] = binomial(i, j)

                    sol = 0
                    for j in range(i + 1):
                        for k in range(i + 1):
                            sol += coeff[j][k]* y0_self[j] * y0_other[k]

                    y0.append(sol)
                return HolonomicFunction(sol_ann, self.x, self.x0, y0)
            else:
                raise NotImplementedError

        return HolonomicFunction(sol_ann, self.x)
Esempio n. 41
0
def test_sympy__functions__combinatorial__factorials__binomial():
    from sympy.functions.combinatorial.factorials import binomial
    assert _test_args(binomial(2, x))
Esempio n. 42
0
 def fit(d, r, p):
     return -np.log(np.float(c.binomial(d, r)) * (p ** r) * (1 - p) ** (d - r))
Esempio n. 43
0
def rational_algorithm(f, x, k, order=4, full=False):
    """Rational algorithm for computing
    formula of coefficients of Formal Power Series
    of a function.

    Applicable when f(x) or some derivative of f(x)
    is a rational function in x.

    :func:`rational_algorithm` uses :func:`apart` function for partial fraction
    decomposition. :func:`apart` by default uses 'undetermined coefficients
    method'. By setting ``full=True``, 'Bronstein's algorithm' can be used
    instead.

    Looks for derivative of a function up to 4'th order (by default).
    This can be overriden using order option.

    Returns
    =======

    formula : Expr
    ind : Expr
        Independent terms.
    order : int

    Examples
    ========

    >>> from sympy import log, atan, I
    >>> from sympy.series.formal import rational_algorithm as ra
    >>> from sympy.abc import x, k

    >>> ra(1 / (1 - x), x, k)
    (1, 0, 0)
    >>> ra(log(1 + x), x, k)
    (-(-1)**(-k)/k, 0, 1)

    >>> ra(atan(x), x, k, full=True)
    ((-I*(-I)**(-k)/2 + I*I**(-k)/2)/k, 0, 1)

    Notes
    =====

    By setting ``full=True``, range of admissible functions to be solved using
    ``rational_algorithm`` can be increased. This option should be used
    carefully as it can signifcantly slow down the computation as ``doit`` is
    performed on the :class:`RootSum` object returned by the ``apart`` function.
    Use ``full=False`` whenever possible.

    See Also
    ========

    sympy.polys.partfrac.apart

    References
    ==========

    .. [1] Formal Power Series - Dominik Gruntz, Wolfram Koepf
    .. [2] Power Series in Computer Algebra - Wolfram Koepf
    """
    from sympy.polys import RootSum, apart
    from sympy.integrals import integrate

    diff = f
    ds = []  # list of diff

    for i in range(order + 1):
        if i:
            diff = diff.diff(x)

        if diff.is_rational_function(x):
            coeff, sep = S.Zero, S.Zero

            terms = apart(diff, x, full=full)
            if terms.has(RootSum):
                terms = terms.doit()

            for t in Add.make_args(terms):
                num, den = t.as_numer_denom()
                if not den.has(x):
                    sep += t
                else:
                    if isinstance(den, Mul):
                        # m*(n*x - a)**j -> (n*x - a)**j
                        ind = den.as_independent(x)
                        den = ind[1]
                        num /= ind[0]

                    # (n*x - a)**j -> (x - b)
                    den, j = den.as_base_exp()
                    a, xterm = den.as_coeff_add(x)

                    # term -> m/x**n
                    if not a:
                        sep += t
                        continue

                    xc = xterm[0].coeff(x)
                    a /= -xc
                    num /= xc**j

                    ak = ((-1)**j * num *
                          binomial(j + k - 1, k).rewrite(factorial) /
                          a**(j + k))
                    coeff += ak

            # Hacky, better way?
            if coeff is S.Zero:
                return None
            if (coeff.has(x) or coeff.has(zoo) or coeff.has(oo) or
                    coeff.has(nan)):
                return None

            for j in range(i):
                coeff = (coeff / (k + j + 1))
                sep = integrate(sep, x)
                sep += (ds.pop() - sep).limit(x, 0)  # constant of integration
            return (coeff.subs(k, k - i), sep, i)

        else:
            ds.append(diff)

    return None
Esempio n. 44
0
    def __mul__(self, other):

        ann_self = self.annihilator
        ann_other = other.annihilator
        list_self = ann_self.listofpoly
        list_other = ann_other.listofpoly
        a = ann_self.order
        b = ann_other.order

        for i, j in enumerate(list_self):
            if isinstance(j, ann_self.parent.base.dtype):
                list_self[i] = ann_self.parent.base.to_sympy(j)

        for i, j in enumerate(list_other):
            if isinstance(j, ann_other.parent.base.dtype):
                list_other[i] = ann_other.parent.base.to_sympy(j)
        # will be used to reduce the degree
        self_red = [-list_self[i] / list_self[a]
                    for i in range(a)]

        other_red = [-list_other[i] / list_other[b]
                     for i in range(b)]
        # coeff_mull[i][j] is the coefficient of Dx^i(f).Dx^j(g)
        coeff_mul = [[S(0) for i in range(b + 1)]
                     for j in range(a + 1)]
        coeff_mul[0][0] = S(1)
        # making the ansatz
        lin_sys = [[coeff_mul[i][j]
                    for i in range(a) for j in range(b)]]

        homo_sys = [[0 for q in range(a * b)]]
        homo_sys = Matrix(homo_sys).transpose()

        sol = (Matrix(lin_sys).transpose()).gauss_jordan_solve(homo_sys)
        # until a non trivial solution is found
        while sol[0].is_zero:
            # updating the coefficents Dx^i(f).Dx^j(g) for next degree
            for i in range(a - 1, -1, -1):
                for j in range(b - 1, -1, -1):
                    coeff_mul[i][j + 1] += coeff_mul[i][j]
                    coeff_mul[i + 1][j] += coeff_mul[i][j]
                    coeff_mul[i][j] = coeff_mul[i][j].diff()
            # reduce the terms to lower power using annihilators of f, g
            for i in range(a + 1):
                if not coeff_mul[i][b] == S(0):
                    for j in range(b):
                        coeff_mul[i][j] += other_red[j] * \
                            coeff_mul[i][b]
                    coeff_mul[i][b] = S(0)

            # not d2 + 1, as that is already covered in previous loop
            for j in range(b):
                if not coeff_mul[a][j] == 0:
                    for i in range(a):
                        coeff_mul[i][j] += self_red[i] * \
                            coeff_mul[a][j]
                    coeff_mul[a][j] = S(0)

            lin_sys.append([coeff_mul[i][j] for i in range(a)
                            for j in range(b)])

            sol = (Matrix(lin_sys).transpose()).gauss_jordan_solve(homo_sys)

        sol = sol[0] / sol[1]

        sol_ann = DifferentialOperator(_normalize(
            sol[0:], self.x, negative=False), ann_self.parent)

        if self._have_init_cond and other._have_init_cond:
            if self.x0 == other.x0:

                # try to find more inital conditions
                y0_self = _extend_y0(self, sol_ann.order)
                y0_other = _extend_y0(other, sol_ann.order)
                # h(x0) = f(x0) * g(x0)
                y0 = [y0_self[0] * y0_other[0]]

                # coefficient of Dx^j(f)*Dx^i(g) in Dx^i(fg)
                for i in range(1, min(len(y0_self), len(y0_other))):
                    coeff = [[0 for i in range(i + 1)] for j in range(i + 1)]
                    for j in range(i + 1):
                        for k in range(i + 1):
                            if j + k == i:
                                coeff[j][k] = binomial(i, j)

                    sol = 0
                    for j in range(i + 1):
                        for k in range(i + 1):
                            sol += coeff[j][k]* y0_self[j] * y0_other[k]

                    y0.append(sol)
                return HolonomicFunction(sol_ann, self.x, self.x0, y0)
            else:
                raise NotImplementedError

        return HolonomicFunction(sol_ann, self.x)