コード例 #1
0
 def _eval_rewrite_as_harmonic(self, n, z, **kwargs):
     if n.is_integer:
         if n.is_zero:
             return harmonic(z - 1) - S.EulerGamma
         else:
             return S.NegativeOne**(n + 1) * factorial(n) * (
                 zeta(n + 1) - harmonic(z - 1, n + 1))
コード例 #2
0
ファイル: test_limitseq.py プロジェクト: vishalbelsare/sympy
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
コード例 #3
0
def test_ideal_soliton():
    raises(ValueError, lambda: IdealSoliton('sol', -12))
    raises(ValueError, lambda: IdealSoliton('sol', 13.2))
    raises(ValueError, lambda: IdealSoliton('sol', 0))
    f = Function('f')
    raises(ValueError, lambda: density(IdealSoliton('sol', 10)).pmf(f))

    k = Symbol('k', integer=True, positive=True)
    x = Symbol('x', integer=True, positive=True)
    t = Symbol('t')
    sol = IdealSoliton('sol', k)
    assert density(sol).low == S.One
    assert density(sol).high == k
    assert density(sol).dict == Density(density(sol))
    assert density(sol).pmf(x) == Piecewise(
        (1 / k, Eq(x, 1)), (1 / (x * (x - 1)), k >= x), (0, True))

    k_vals = [5, 20, 50, 100, 1000]
    for i in k_vals:
        assert E(sol.subs(k, i)) == harmonic(i) == moment(sol.subs(k, i), 1)
        assert variance(sol.subs(
            k, i)) == (i - 1) + harmonic(i) - harmonic(i)**2 == cmoment(
                sol.subs(k, i), 2)
        assert skewness(sol.subs(k, i)) == smoment(sol.subs(k, i), 3)
        assert kurtosis(sol.subs(k, i)) == smoment(sol.subs(k, i), 4)

    assert exp(I * t) / 10 + Sum(exp(I * t * x) / (x * x - x), (x, 2, k)).subs(
        k, 10).doit() == characteristic_function(sol.subs(k, 10))(t)
    assert exp(t) / 10 + Sum(exp(t * x) / (x * x - x), (x, 2, k)).subs(
        k, 10).doit() == moment_generating_function(sol.subs(k, 10))(t)
コード例 #4
0
ファイル: gamma_functions.py プロジェクト: tuomas2/sympy
 def _eval_rewrite_as_harmonic(self, n, z):
     if n.is_integer:
         if n == S.Zero:
             return harmonic(z - 1) - S.EulerGamma
         else:
             return S.NegativeOne**(n + 1) * C.factorial(n) * (
                 C.zeta(n + 1) - harmonic(z - 1, n + 1))
コード例 #5
0
ファイル: gacha.py プロジェクト: mingrammer/yui
    async def collect(self, bot, event: Message, query: str):
        match = COLLECT_QUERY1.match(query)
        if match:
            n = int(match.group('n'))
            total = int(match.group('total')) if match.group('total') else n
        else:
            match = COLLECT_QUERY2.match(query)
            if match:
                n = int(match.group('n'))
                total = int(match.group('total'))
            else:
                await bot.say(event.channel, '요청을 해석하는데에 실패했어요!')
                return
        if total < 2 or total > 512:
            await bot.say(event.channel, '정상적인 전체 갯수를 입력해주세요! (2개 이상 512개 이하)')
            return
        if n < 1 or n > 512:
            await bot.say(event.channel, '정상적인 수집 갯수를 입력해주세요! (1개 이상 512개 이하)')
            return
        if total < n:
            await bot.say(event.channel, '원하는 갯수가 전체 갯수보다 많을 수 없어요!')
            return

        result = n * harmonic(n)
        if total > n:
            result /= n / total
            text = '부분적으로'
        else:
            text = '모두'

        await bot.say(
            event.channel, f'상품 1개 구입시 {total}종류의 특전 중 하나를 무작위로 100%'
            f'확률로 준다고 가정할 때 {n}종류의 특전을 {text} 모으려면, 평균적으로'
            f' {math.ceil(result)}(`{float(result):.2f}`)개의 상품을'
            ' 구입해야 수집에 성공할 수 있어요!')
コード例 #6
0
    def eval(cls, n, z):
        n, z = map(sympify, (n, z))
        from sympy import unpolarify

        if n.is_integer:
            if n.is_nonnegative:
                nz = unpolarify(z)
                if z != nz:
                    return polygamma(n, nz)

            if n.is_positive:
                if z is S.Half:
                    return (
                        (-1) ** (n + 1)
                        * factorial(n)
                        * (2 ** (n + 1) - 1)
                        * zeta(n + 1)
                    )

            if n is S.NegativeOne:
                return loggamma(z)
            else:
                if z.is_Number:
                    if z is S.NaN:
                        return S.NaN
                    elif z is S.Infinity:
                        if n.is_Number:
                            if n.is_zero:
                                return S.Infinity
                            else:
                                return S.Zero
                        if n.is_zero:
                            return S.Infinity
                    elif z.is_Integer:
                        if z.is_nonpositive:
                            return S.ComplexInfinity
                        else:
                            if n.is_zero:
                                return -S.EulerGamma + harmonic(z - 1, 1)
                            elif n.is_odd:
                                return (-1) ** (n + 1) * factorial(n) * zeta(n + 1, z)

        if n.is_zero:
            if z is S.NaN:
                return S.NaN
            elif z.is_Rational:

                p, q = z.as_numer_denom()

                # only expand for small denominators to avoid creating long expressions
                if q <= 5:
                    return expand_func(polygamma(S.Zero, z, evaluate=False))

            elif z in (S.Infinity, S.NegativeInfinity):
                return S.Infinity
            else:
                t = z.extract_multiplicatively(S.ImaginaryUnit)
                if t in (S.Infinity, S.NegativeInfinity):
                    return S.Infinity
コード例 #7
0
ファイル: gamma_functions.py プロジェクト: xivarri/sympy
    def eval(cls, n, z):
        n, z = list(map(sympify, (n, z)))
        from sympy import unpolarify

        if n.is_integer:
            if n.is_nonnegative:
                nz = unpolarify(z)
                if z != nz:
                    return polygamma(n, nz)

            if n == -1:
                return loggamma(z)
            else:
                if z.is_Number:
                    if z is S.NaN:
                        return S.NaN
                    elif z is S.Infinity:
                        if n.is_Number:
                            if n is S.Zero:
                                return S.Infinity
                            else:
                                return S.Zero
                    elif z.is_Integer:
                        if z.is_nonpositive:
                            return S.ComplexInfinity
                        else:
                            if n is S.Zero:
                                return -S.EulerGamma + harmonic(z - 1, 1)
                            elif n.is_odd:
                                return (-1)**(n + 1)*factorial(n)*zeta(n + 1, z)

        if n == 0:
            if z is S.NaN:
                return S.NaN
            elif z.is_Rational:
                # TODO actually *any* n/m can be done, but that is messy
                lookup = {S(1)/2: -2*log(2) - S.EulerGamma,
                          S(1)/3: -S.Pi/2/sqrt(3) - 3*log(3)/2 - S.EulerGamma,
                          S(1)/4: -S.Pi/2 - 3*log(2) - S.EulerGamma,
                          S(3)/4: -3*log(2) - S.EulerGamma + S.Pi/2,
                          S(2)/3: -3*log(3)/2 + S.Pi/2/sqrt(3) - S.EulerGamma}
                if z > 0:
                    n = floor(z)
                    z0 = z - n
                    if z0 in lookup:
                        return lookup[z0] + Add(*[1/(z0 + k) for k in range(n)])
                elif z < 0:
                    n = floor(1 - z)
                    z0 = z + n
                    if z0 in lookup:
                        return lookup[z0] - Add(*[1/(z0 - 1 - k) for k in range(n)])
            elif z in (S.Infinity, S.NegativeInfinity):
                return S.Infinity
            else:
                t = z.extract_multiplicatively(S.ImaginaryUnit)
                if t in (S.Infinity, S.NegativeInfinity):
                    return S.Infinity
コード例 #8
0
ファイル: gacha.py プロジェクト: hunj/yui
    async def collect(self, bot, event: Message, n: int):
        result = n * harmonic(n)

        await bot.say(
            event.channel,
            f'상품 1개 구입시 {n}종류의 특전 중 하나를 무작위로 100% 확률로 준다고 가정할 때'
            f' {n}종류의 특전을 모두 모으려면, 평균적으로 {math.ceil(result)}'
            f'(`{float(result):.2f}`)개의 상품을 구입해야 전체 수집에 성공할 수 있어요!'
        )
コード例 #9
0
ファイル: test_limitseq.py プロジェクト: vishalbelsare/sympy
def test_difference_delta__Sum():
    e = Sum(1 / k, (k, 1, n))
    assert dd(e, n) == 1 / (n + 1)
    assert dd(e, n, 5) == Add(*[1 / (i + n + 1) for i in range(5)])

    e = Sum(1 / k, (k, 1, 3 * n))
    assert dd(e, n) == Add(*[1 / (i + 3 * n + 1) for i in range(3)])

    e = n * Sum(1 / k, (k, 1, n))
    assert dd(e, n) == 1 + Sum(1 / k, (k, 1, n))

    e = Sum(1 / k, (k, 1, n), (m, 1, n))
    assert dd(e, n) == harmonic(n)
コード例 #10
0
ファイル: zeta_functions.py プロジェクト: sumollodha/sympy
    def eval(cls, z, a_=None):
        if a_ is None:
            z, a = list(map(sympify, (z, 1)))
        else:
            z, a = list(map(sympify, (z, a_)))

        if a.is_Number:
            if a is S.NaN:
                return S.NaN
            elif a is S.One and a_ is not None:
                return cls(z)
            # TODO Should a == 0 return S.NaN as well?

        if z.is_Number:
            if z is S.NaN:
                return S.NaN
            elif z is S.Infinity:
                return S.One
            elif z is S.Zero:
                if a.is_negative:
                    return S.Half - a - 1
                else:
                    return S.Half - a
            elif z is S.One:
                return S.ComplexInfinity
            elif z.is_Integer:
                if a.is_Integer:
                    if z.is_negative:
                        zeta = (-1)**z * bernoulli(-z + 1) / (-z + 1)
                    elif z.is_even:
                        B, F = bernoulli(z), factorial(z)
                        zeta = 2**(z - 1) * abs(B) * pi**z / F
                    else:
                        return

                    if a.is_negative:
                        return zeta + harmonic(abs(a), z)
                    else:
                        return zeta - harmonic(a - 1, z)
コード例 #11
0
ファイル: test_limitseq.py プロジェクト: vishalbelsare/sympy
def test_limit_seq():
    e = binomial(2 * n, n) / Sum(binomial(2 * k, k), (k, 1, n))
    assert limit_seq(e) == S(3) / 4
    assert limit_seq(e, m) == e

    e = (5 * n**3 + 3 * n**2 + 4) / (3 * n**3 + 4 * n - 5)
    assert limit_seq(e, n) == S(5) / 3

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

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

    e = (Sum(binomial(3 * k, k) * binomial(5 * k, k),
             (k, 1, n)) / (binomial(3 * n, n) * binomial(5 * n, n)))
    assert limit_seq(e, n) == S(84375) / 83351

    e = Sum(harmonic(k)**2 / k, (k, 1, 2 * n)) / harmonic(n)**3
    assert limit_seq(e, n) == S.One / 3

    raises(ValueError, lambda: limit_seq(e * m))
コード例 #12
0
ファイル: zeta_functions.py プロジェクト: amitsaha/sympy
    def eval(cls, z, a_=None):
        if a_ is None:
            z, a = list(map(sympify, (z, 1)))
        else:
            z, a = list(map(sympify, (z, a_)))

        if a.is_Number:
            if a is S.NaN:
                return S.NaN
            elif a is S.One and a_ is not None:
                return cls(z)
            # TODO Should a == 0 return S.NaN as well?

        if z.is_Number:
            if z is S.NaN:
                return S.NaN
            elif z is S.Infinity:
                return S.One
            elif z is S.Zero:
                if a.is_negative:
                    return S.Half - a - 1
                else:
                    return S.Half - a
            elif z is S.One:
                return S.ComplexInfinity
            elif z.is_Integer:
                if a.is_Integer:
                    if z.is_negative:
                        zeta = (-1)**z * bernoulli(-z + 1)/(-z + 1)
                    elif z.is_even:
                        B, F = bernoulli(z), factorial(z)
                        zeta = 2**(z - 1) * abs(B) * pi**z / F
                    else:
                        return

                    if a.is_negative:
                        return zeta + harmonic(abs(a), z)
                    else:
                        return zeta - harmonic(a - 1, z)
コード例 #13
0
def test_digamma():
    assert digamma(nan) == nan

    assert digamma(oo) == oo
    assert digamma(-oo) == oo
    assert digamma(I*oo) == oo
    assert digamma(-I*oo) == oo

    assert digamma(-9) == zoo

    assert digamma(-9) == zoo
    assert digamma(-1) == zoo

    assert digamma(0) == zoo

    assert digamma(1) == -EulerGamma
    assert digamma(7) == Rational(49, 20) - EulerGamma

    def t(m, n):
        x = S(m)/n
        r = digamma(x)
        if r.has(digamma):
            return False
        return abs(digamma(x.n()).n() - r.n()).n() < 1e-10
    assert t(1, 2)
    assert t(3, 2)
    assert t(-1, 2)
    assert t(1, 4)
    assert t(-3, 4)
    assert t(1, 3)
    assert t(4, 3)
    assert t(3, 4)
    assert t(2, 3)
    assert t(123, 5)

    assert digamma(x).rewrite(zeta) == polygamma(0, x)

    assert digamma(x).rewrite(harmonic) == harmonic(x - 1) - EulerGamma

    assert digamma(I).is_real is None

    assert digamma(x,evaluate=False).fdiff() == polygamma(1, x)

    assert digamma(x,evaluate=False).is_real is None

    assert digamma(x,evaluate=False).is_positive is None

    assert digamma(x,evaluate=False).is_negative is None

    assert digamma(x,evaluate=False).rewrite(polygamma) == polygamma(0, x)
コード例 #14
0
    def eval(cls, n, z):
        n, z = list(map(sympify, (n, z)))
        from sympy import unpolarify

        if n.is_integer:
            if n.is_nonnegative:
                nz = unpolarify(z)
                if z != nz:
                    return polygamma(n, nz)

            if n == -1:
                return loggamma(z)
            else:
                if z.is_Number:
                    if z is S.NaN:
                        return S.NaN
                    elif z is S.Infinity:
                        if n.is_Number:
                            if n is S.Zero:
                                return S.Infinity
                            else:
                                return S.Zero
                    elif z.is_Integer:
                        if z.is_nonpositive:
                            return S.ComplexInfinity
                        else:
                            if n is S.Zero:
                                return -S.EulerGamma + harmonic(z - 1, 1)
                            elif n.is_odd:
                                return (-1)**(n + 1)*factorial(n)*zeta(n + 1, z)

        if n == 0:
            if z is S.NaN:
                return S.NaN
            elif z.is_Rational:

                p, q = z.as_numer_denom()

                # only expand for small denominators to avoid creating long expressions
                if q <= 5:
                    return expand_func(polygamma(n, z, evaluate=False))

            elif z in (S.Infinity, S.NegativeInfinity):
                return S.Infinity
            else:
                t = z.extract_multiplicatively(S.ImaginaryUnit)
                if t in (S.Infinity, S.NegativeInfinity):
                    return S.Infinity
コード例 #15
0
ファイル: gacha.py プロジェクト: item4/yui
    async def collect(self, bot, event: Message, query: str):
        match = COLLECT_QUERY1.match(query)
        if match:
            n = int(match.group("n"))
            total = int(match.group("total")) if match.group("total") else n
        else:
            match = COLLECT_QUERY2.match(query)
            if match:
                n = int(match.group("n"))
                total = int(match.group("total"))
            else:
                await bot.say(event.channel, "요청을 해석하는데에 실패했어요!")
                return
        if total < 2 or total > 512:
            await bot.say(event.channel, "정상적인 전체 갯수를 입력해주세요! (2개 이상 512개 이하)")
            return
        if n < 1 or n > 512:
            await bot.say(event.channel, "정상적인 수집 갯수를 입력해주세요! (1개 이상 512개 이하)")
            return
        if total < n:
            await bot.say(event.channel, "원하는 갯수가 전체 갯수보다 많을 수 없어요!")
            return

        result = n * harmonic(n)
        if total > n:
            result /= n / total
            text = "부분적으로"
        else:
            text = "모두"

        await bot.say(
            event.channel,
            f"상품 1개 구입시 {total}종류의 특전 중 하나를 무작위로 100%"
            f"확률로 준다고 가정할 때 {n}종류의 특전을 {text} 모으려면, 평균적으로"
            f" {math.ceil(result)}(`{float(result):.2f}`)개의 상품을"
            " 구입해야 수집에 성공할 수 있어요!",
        )
コード例 #16
0
ファイル: test_args.py プロジェクト: 101man/sympy
def test_sympy__functions__combinatorial__numbers__harmonic():
    from sympy.functions.combinatorial.numbers import harmonic
    assert _test_args(harmonic(x, 2))
コード例 #17
0
 def _eval_rewrite_as_harmonic(self, z, **kwargs):
     return -harmonic(z - 1, 2) + S.Pi**2 / 6
コード例 #18
0
 def _eval_rewrite_as_harmonic(self, z, **kwargs):
     return harmonic(z - 1) - S.EulerGamma
コード例 #19
0
ファイル: gamma_functions.py プロジェクト: Krastanov/sympy
 def _eval_rewrite_as_harmonic(self, n, z):
     if n.is_integer:
         if n == S.Zero:
             return harmonic(z - 1) - S.EulerGamma
         else:
             return S.NegativeOne ** (n + 1) * C.factorial(n) * (C.zeta(n + 1) - harmonic(z - 1, n + 1))
コード例 #20
0
ファイル: test_args.py プロジェクト: Visheshk/sympy
def test_sympy__functions__combinatorial__numbers__harmonic():
    from sympy.functions.combinatorial.numbers import harmonic
    assert _test_args(harmonic(x, 2))
コード例 #21
0
def test_polygamma():
    assert polygamma(n, nan) is nan

    assert polygamma(0, oo) is oo
    assert polygamma(0, -oo) is oo
    assert polygamma(0, I*oo) is oo
    assert polygamma(0, -I*oo) is oo
    assert polygamma(1, oo) == 0
    assert polygamma(5, oo) == 0

    assert polygamma(0, -9) is zoo

    assert polygamma(0, -9) is zoo
    assert polygamma(0, -1) is zoo

    assert polygamma(0, 0) is zoo

    assert polygamma(0, 1) == -EulerGamma
    assert polygamma(0, 7) == Rational(49, 20) - EulerGamma

    assert polygamma(1, 1) == pi**2/6
    assert polygamma(1, 2) == pi**2/6 - 1
    assert polygamma(1, 3) == pi**2/6 - Rational(5, 4)
    assert polygamma(3, 1) == pi**4 / 15
    assert polygamma(3, 5) == 6*(Rational(-22369, 20736) + pi**4/90)
    assert polygamma(5, 1) == 8 * pi**6 / 63

    assert polygamma(1, S.Half) == pi**2 / 2
    assert polygamma(2, S.Half) == -14*zeta(3)
    assert polygamma(11, S.Half) == 176896*pi**12

    def t(m, n):
        x = S(m)/n
        r = polygamma(0, x)
        if r.has(polygamma):
            return False
        return abs(polygamma(0, x.n()).n() - r.n()).n() < 1e-10
    assert t(1, 2)
    assert t(3, 2)
    assert t(-1, 2)
    assert t(1, 4)
    assert t(-3, 4)
    assert t(1, 3)
    assert t(4, 3)
    assert t(3, 4)
    assert t(2, 3)
    assert t(123, 5)

    assert polygamma(0, x).rewrite(zeta) == polygamma(0, x)
    assert polygamma(1, x).rewrite(zeta) == zeta(2, x)
    assert polygamma(2, x).rewrite(zeta) == -2*zeta(3, x)
    assert polygamma(I, 2).rewrite(zeta) == polygamma(I, 2)
    n1 = Symbol('n1')
    n2 = Symbol('n2', real=True)
    n3 = Symbol('n3', integer=True)
    n4 = Symbol('n4', positive=True)
    n5 = Symbol('n5', positive=True, integer=True)
    assert polygamma(n1, x).rewrite(zeta) == polygamma(n1, x)
    assert polygamma(n2, x).rewrite(zeta) == polygamma(n2, x)
    assert polygamma(n3, x).rewrite(zeta) == polygamma(n3, x)
    assert polygamma(n4, x).rewrite(zeta) == polygamma(n4, x)
    assert polygamma(n5, x).rewrite(zeta) == (-1)**(n5 + 1) * factorial(n5) * zeta(n5 + 1, x)

    assert polygamma(3, 7*x).diff(x) == 7*polygamma(4, 7*x)

    assert polygamma(0, x).rewrite(harmonic) == harmonic(x - 1) - EulerGamma
    assert polygamma(2, x).rewrite(harmonic) == 2*harmonic(x - 1, 3) - 2*zeta(3)
    ni = Symbol("n", integer=True)
    assert polygamma(ni, x).rewrite(harmonic) == (-1)**(ni + 1)*(-harmonic(x - 1, ni + 1)
                                                                 + zeta(ni + 1))*factorial(ni)

    # Polygamma of non-negative integer order is unbranched:
    k = Symbol('n', integer=True, nonnegative=True)
    assert polygamma(k, exp_polar(2*I*pi)*x) == polygamma(k, x)

    # but negative integers are branched!
    k = Symbol('n', integer=True)
    assert polygamma(k, exp_polar(2*I*pi)*x).args == (k, exp_polar(2*I*pi)*x)

    # Polygamma of order -1 is loggamma:
    assert polygamma(-1, x) == loggamma(x)

    # But smaller orders are iterated integrals and don't have a special name
    assert polygamma(-2, x).func is polygamma

    # Test a bug
    assert polygamma(0, -x).expand(func=True) == polygamma(0, -x)

    assert polygamma(2, 2.5).is_positive == False
    assert polygamma(2, -2.5).is_positive == False
    assert polygamma(3, 2.5).is_positive == True
    assert polygamma(3, -2.5).is_positive is True
    assert polygamma(-2, -2.5).is_positive is None
    assert polygamma(-3, -2.5).is_positive is None

    assert polygamma(2, 2.5).is_negative == True
    assert polygamma(3, 2.5).is_negative == False
    assert polygamma(3, -2.5).is_negative == False
    assert polygamma(2, -2.5).is_negative is True
    assert polygamma(-2, -2.5).is_negative is None
    assert polygamma(-3, -2.5).is_negative is None

    assert polygamma(I, 2).is_positive is None
    assert polygamma(I, 3).is_negative is None

    # issue 17350
    assert polygamma(pi, 3).evalf() == polygamma(pi, 3)
    assert (I*polygamma(I, pi)).as_real_imag() == \
           (-im(polygamma(I, pi)), re(polygamma(I, pi)))
    assert (tanh(polygamma(I, 1))).rewrite(exp) == \
           (exp(polygamma(I, 1)) - exp(-polygamma(I, 1)))/(exp(polygamma(I, 1)) + exp(-polygamma(I, 1)))
    assert (I / polygamma(I, 4)).rewrite(exp) == \
           I*sqrt(re(polygamma(I, 4))**2 + im(polygamma(I, 4))**2)\
           /((re(polygamma(I, 4)) + I*im(polygamma(I, 4)))*Abs(polygamma(I, 4)))
    assert unchanged(polygamma, 2.3, 1.0)

    # issue 12569
    assert unchanged(im, polygamma(0, I))
    assert polygamma(Symbol('a', positive=True), Symbol('b', positive=True)).is_real is True
    assert polygamma(0, I).is_real is None