def test_harmonic_rewrite_sum(): n = Symbol("n") m = Symbol("m") _k = Dummy("k") assert replace_dummy(harmonic(n).rewrite(Sum), _k) == Sum(1/_k, (_k, 1, n)) assert replace_dummy(harmonic(n, m).rewrite(Sum), _k) == Sum(_k**(-m), (_k, 1, n))
def test_Function(): assert mcode(f(x, y, z)) == "f[x, y, z]" assert mcode(sin(x)**cos(x)) == "Sin[x]^Cos[x]" assert mcode(conjugate(x)) == "Conjugate[x]" assert mcode(Max(x, y, z) * Min(y, z)) == "Max[x, y, z]*Min[y, z]" assert mcode(fresnelc(x)) == "FresnelC[x]" assert mcode(fresnels(x)) == "FresnelS[x]" assert mcode(gamma(x)) == "Gamma[x]" assert mcode(uppergamma(x, y)) == "Gamma[x, y]" assert mcode(polygamma(x, y)) == "PolyGamma[x, y]" assert mcode(loggamma(x)) == "LogGamma[x]" assert mcode(erf(x)) == "Erf[x]" assert mcode(erfc(x)) == "Erfc[x]" assert mcode(erfi(x)) == "Erfi[x]" assert mcode(erf2(x, y)) == "Erf[x, y]" assert mcode(expint(x, y)) == "ExpIntegralE[x, y]" assert mcode(erfcinv(x)) == "InverseErfc[x]" assert mcode(erfinv(x)) == "InverseErf[x]" assert mcode(erf2inv(x, y)) == "InverseErf[x, y]" assert mcode(Ei(x)) == "ExpIntegralEi[x]" assert mcode(Ci(x)) == "CosIntegral[x]" assert mcode(li(x)) == "LogIntegral[x]" assert mcode(Si(x)) == "SinIntegral[x]" assert mcode(Shi(x)) == "SinhIntegral[x]" assert mcode(Chi(x)) == "CoshIntegral[x]" assert mcode(beta(x, y)) == "Beta[x, y]" assert mcode(factorial(x)) == "Factorial[x]" assert mcode(factorial2(x)) == "Factorial2[x]" assert mcode(subfactorial(x)) == "Subfactorial[x]" assert mcode(FallingFactorial(x, y)) == "FactorialPower[x, y]" assert mcode(RisingFactorial(x, y)) == "Pochhammer[x, y]" assert mcode(catalan(x)) == "CatalanNumber[x]" assert mcode(harmonic(x)) == "HarmonicNumber[x]" assert mcode(harmonic(x, y)) == "HarmonicNumber[x, y]"
def test_harmonic_rewrite_sum_fail(): n = Symbol("n") m = Symbol("m") _k = Dummy("k") assert harmonic(n).rewrite(Sum) == Sum(1/_k, (_k, 1, n)) assert harmonic(n, m).rewrite(Sum) == Sum(_k**(-m), (_k, 1, n))
def test_harmonic_rewrite_sum_fail(): n = Symbol("n") m = Symbol("m") _k = Dummy("k") assert harmonic(n).rewrite(Sum) == Sum(1 / _k, (_k, 1, n)) assert harmonic(n, m).rewrite(Sum) == Sum(_k**(-m), (_k, 1, n))
def test_Function(): assert mcode(sin(x) ** cos(x)) == "sin(x).^cos(x)" assert mcode(sign(x)) == "sign(x)" assert mcode(exp(x)) == "exp(x)" assert mcode(log(x)) == "log(x)" assert mcode(factorial(x)) == "factorial(x)" assert mcode(floor(x)) == "floor(x)" assert mcode(atan2(y, x)) == "atan2(y, x)" assert mcode(beta(x, y)) == 'beta(x, y)' assert mcode(polylog(x, y)) == 'polylog(x, y)' assert mcode(harmonic(x)) == 'harmonic(x)' assert mcode(bernoulli(x)) == "bernoulli(x)" assert mcode(bernoulli(x, y)) == "bernoulli(x, y)"
def test_Function(): assert mcode(sin(x)**cos(x)) == "sin(x).^cos(x)" assert mcode(sign(x)) == "sign(x)" assert mcode(exp(x)) == "exp(x)" assert mcode(log(x)) == "log(x)" assert mcode(factorial(x)) == "factorial(x)" assert mcode(floor(x)) == "floor(x)" assert mcode(atan2(y, x)) == "atan2(y, x)" assert mcode(beta(x, y)) == 'beta(x, y)' assert mcode(polylog(x, y)) == 'polylog(x, y)' assert mcode(harmonic(x)) == 'harmonic(x)' assert mcode(bernoulli(x)) == "bernoulli(x)" assert mcode(bernoulli(x, y)) == "bernoulli(x, y)"
def test_harmonic_evalf(): assert str(harmonic(1.5).evalf(n=10)) == '1.280372306' assert str(harmonic(1.5, 2).evalf(n=10)) == '1.154576311' # issue 7443
def test_harmonic_rational(): ne = S(6) no = S(5) pe = S(8) po = S(9) qe = S(10) qo = S(13) Heee = harmonic(ne + pe / qe) Aeee = (-log(10) + 2 * (-1 / S(4) + sqrt(5) / 4) * log(sqrt(-sqrt(5) / 8 + 5 / S(8))) + 2 * (-sqrt(5) / 4 - 1 / S(4)) * log(sqrt(sqrt(5) / 8 + 5 / S(8))) + pi * (1 / S(4) + sqrt(5) / 4) / (2 * sqrt(-sqrt(5) / 8 + 5 / S(8))) + 13944145 / S(4720968)) Heeo = harmonic(ne + pe / qo) Aeeo = (-log(26) + 2 * log(sin(3 * pi / 13)) * cos(4 * pi / 13) + 2 * log(sin(2 * pi / 13)) * cos(32 * pi / 13) + 2 * log(sin(5 * pi / 13)) * cos(80 * pi / 13) - 2 * log(sin(6 * pi / 13)) * cos(5 * pi / 13) - 2 * log(sin(4 * pi / 13)) * cos(pi / 13) + pi * cot(5 * pi / 13) / 2 - 2 * log(sin(pi / 13)) * cos(3 * pi / 13) + 2422020029 / S(702257080)) Heoe = harmonic(ne + po / qe) Aeoe = (-log(20) + 2 * (1 / S(4) + sqrt(5) / 4) * log(-1 / S(4) + sqrt(5) / 4) + 2 * (-1 / S(4) + sqrt(5) / 4) * log(sqrt(-sqrt(5) / 8 + 5 / S(8))) + 2 * (-sqrt(5) / 4 - 1 / S(4)) * log(sqrt(sqrt(5) / 8 + 5 / S(8))) + 2 * (-sqrt(5) / 4 + 1 / S(4)) * log(1 / S(4) + sqrt(5) / 4) + 11818877030 / S(4286604231) + pi * (sqrt(5) / 8 + 5 / S(8)) / sqrt(-sqrt(5) / 8 + 5 / S(8))) Heoo = harmonic(ne + po / qo) Aeoo = (-log(26) + 2 * log(sin(3 * pi / 13)) * cos(54 * pi / 13) + 2 * log(sin(4 * pi / 13)) * cos(6 * pi / 13) + 2 * log(sin(6 * pi / 13)) * cos(108 * pi / 13) - 2 * log(sin(5 * pi / 13)) * cos(pi / 13) - 2 * log(sin(pi / 13)) * cos(5 * pi / 13) + pi * cot(4 * pi / 13) / 2 - 2 * log(sin(2 * pi / 13)) * cos(3 * pi / 13) + 11669332571 / S(3628714320)) Hoee = harmonic(no + pe / qe) Aoee = (-log(10) + 2 * (-1 / S(4) + sqrt(5) / 4) * log(sqrt(-sqrt(5) / 8 + 5 / S(8))) + 2 * (-sqrt(5) / 4 - 1 / S(4)) * log(sqrt(sqrt(5) / 8 + 5 / S(8))) + pi * (1 / S(4) + sqrt(5) / 4) / (2 * sqrt(-sqrt(5) / 8 + 5 / S(8))) + 779405 / S(277704)) Hoeo = harmonic(no + pe / qo) Aoeo = (-log(26) + 2 * log(sin(3 * pi / 13)) * cos(4 * pi / 13) + 2 * log(sin(2 * pi / 13)) * cos(32 * pi / 13) + 2 * log(sin(5 * pi / 13)) * cos(80 * pi / 13) - 2 * log(sin(6 * pi / 13)) * cos(5 * pi / 13) - 2 * log(sin(4 * pi / 13)) * cos(pi / 13) + pi * cot(5 * pi / 13) / 2 - 2 * log(sin(pi / 13)) * cos(3 * pi / 13) + 53857323 / S(16331560)) Hooe = harmonic(no + po / qe) Aooe = (-log(20) + 2 * (1 / S(4) + sqrt(5) / 4) * log(-1 / S(4) + sqrt(5) / 4) + 2 * (-1 / S(4) + sqrt(5) / 4) * log(sqrt(-sqrt(5) / 8 + 5 / S(8))) + 2 * (-sqrt(5) / 4 - 1 / S(4)) * log(sqrt(sqrt(5) / 8 + 5 / S(8))) + 2 * (-sqrt(5) / 4 + 1 / S(4)) * log(1 / S(4) + sqrt(5) / 4) + 486853480 / S(186374097) + pi * (sqrt(5) / 8 + 5 / S(8)) / sqrt(-sqrt(5) / 8 + 5 / S(8))) Hooo = harmonic(no + po / qo) Aooo = (-log(26) + 2 * log(sin(3 * pi / 13)) * cos(54 * pi / 13) + 2 * log(sin(4 * pi / 13)) * cos(6 * pi / 13) + 2 * log(sin(6 * pi / 13)) * cos(108 * pi / 13) - 2 * log(sin(5 * pi / 13)) * cos(pi / 13) - 2 * log(sin(pi / 13)) * cos(5 * pi / 13) + pi * cot(4 * pi / 13) / 2 - 2 * log(sin(2 * pi / 13)) * cos(3 * pi / 13) + 383693479 / S(125128080)) H = [Heee, Heeo, Heoe, Heoo, Hoee, Hoeo, Hooe, Hooo] A = [Aeee, Aeeo, Aeoe, Aeoo, Aoee, Aoeo, Aooe, Aooo] for h, a in zip(H, A): e = expand_func(h).doit() assert cancel(e / a) == 1 assert abs(h.n() - a.n()) < 1e-12
def test_harmonic(): n = Symbol("n") m = Symbol("m") assert harmonic(n, 0) == n assert harmonic(n).evalf() == harmonic(n) assert harmonic(n, 1) == harmonic(n) assert harmonic(1, n).evalf() == harmonic(1, n) assert harmonic(0, 1) == 0 assert harmonic(1, 1) == 1 assert harmonic(2, 1) == Rational(3, 2) assert harmonic(3, 1) == Rational(11, 6) assert harmonic(4, 1) == Rational(25, 12) assert harmonic(0, 2) == 0 assert harmonic(1, 2) == 1 assert harmonic(2, 2) == Rational(5, 4) assert harmonic(3, 2) == Rational(49, 36) assert harmonic(4, 2) == Rational(205, 144) assert harmonic(0, 3) == 0 assert harmonic(1, 3) == 1 assert harmonic(2, 3) == Rational(9, 8) assert harmonic(3, 3) == Rational(251, 216) assert harmonic(4, 3) == Rational(2035, 1728) assert harmonic(oo, -1) == S.NaN assert harmonic(oo, 0) == oo assert harmonic(oo, S.Half) == oo assert harmonic(oo, 1) == oo assert harmonic(oo, 2) == (pi**2) / 6 assert harmonic(oo, 3) == zeta(3) assert harmonic(0, m) == 0
def eval_sum_symbolic(f, limits): from sympy.functions import harmonic, bernoulli f_orig = f (i, a, b) = limits if not f.has(i): return f*(b - a + 1) # Linearity if f.is_Mul: L, R = f.as_two_terms() if not L.has(i): sR = eval_sum_symbolic(R, (i, a, b)) if sR: return L*sR if not R.has(i): sL = eval_sum_symbolic(L, (i, a, b)) if sL: return R*sL try: f = apart(f, i) # see if it becomes an Add except PolynomialError: pass if f.is_Add: L, R = f.as_two_terms() lrsum = telescopic(L, R, (i, a, b)) if lrsum: return lrsum lsum = eval_sum_symbolic(L, (i, a, b)) rsum = eval_sum_symbolic(R, (i, a, b)) if None not in (lsum, rsum): r = lsum + rsum if not r is S.NaN: return r # Polynomial terms with Faulhaber's formula n = Wild('n') result = f.match(i**n) if result is not None: n = result[n] if n.is_Integer: if n >= 0: if (b is S.Infinity and not a is S.NegativeInfinity) or \ (a is S.NegativeInfinity and not b is S.Infinity): return S.Infinity return ((bernoulli(n + 1, b + 1) - bernoulli(n + 1, a))/(n + 1)).expand() elif a.is_Integer and a >= 1: if n == -1: return harmonic(b) - harmonic(a - 1) else: return harmonic(b, abs(n)) - harmonic(a - 1, abs(n)) if not (a.has(S.Infinity, S.NegativeInfinity) or b.has(S.Infinity, S.NegativeInfinity)): # Geometric terms c1 = Wild('c1', exclude=[i]) c2 = Wild('c2', exclude=[i]) c3 = Wild('c3', exclude=[i]) wexp = Wild('wexp') # Here we first attempt powsimp on f for easier matching with the # exponential pattern, and attempt expansion on the exponent for easier # matching with the linear pattern. e = f.powsimp().match(c1 ** wexp) if e is not None: e_exp = e.pop(wexp).expand().match(c2*i + c3) if e_exp is not None: e.update(e_exp) if e is not None: p = (c1**c3).subs(e) q = (c1**c2).subs(e) r = p*(q**a - q**(b + 1))/(1 - q) l = p*(b - a + 1) return Piecewise((l, Eq(q, S.One)), (r, True)) r = gosper_sum(f, (i, a, b)) if not r in (None, S.NaN): return r return eval_sum_hyper(f_orig, (i, a, b))
def eval_sum_symbolic(f, limits): from sympy.functions import harmonic, bernoulli f_orig = f (i, a, b) = limits if not f.has(i): return f * (b - a + 1) # Linearity if f.is_Mul: L, R = f.as_two_terms() if not L.has(i): sR = eval_sum_symbolic(R, (i, a, b)) if sR: return L * sR if not R.has(i): sL = eval_sum_symbolic(L, (i, a, b)) if sL: return R * sL try: f = apart(f, i) # see if it becomes an Add except PolynomialError: pass if f.is_Add: L, R = f.as_two_terms() lrsum = telescopic(L, R, (i, a, b)) if lrsum: return lrsum lsum = eval_sum_symbolic(L, (i, a, b)) rsum = eval_sum_symbolic(R, (i, a, b)) if None not in (lsum, rsum): r = lsum + rsum if not r is S.NaN: return r # Polynomial terms with Faulhaber's formula n = Wild('n') result = f.match(i**n) if result is not None: n = result[n] if n.is_Integer: if n >= 0: if (b is S.Infinity and not a is S.NegativeInfinity) or \ (a is S.NegativeInfinity and not b is S.Infinity): return S.Infinity return ((bernoulli(n + 1, b + 1) - bernoulli(n + 1, a)) / (n + 1)).expand() elif a.is_Integer and a >= 1: if n == -1: return harmonic(b) - harmonic(a - 1) else: return harmonic(b, abs(n)) - harmonic(a - 1, abs(n)) if not (a.has(S.Infinity, S.NegativeInfinity) or b.has(S.Infinity, S.NegativeInfinity)): # Geometric terms c1 = Wild('c1', exclude=[i]) c2 = Wild('c2', exclude=[i]) c3 = Wild('c3', exclude=[i]) wexp = Wild('wexp') # Here we first attempt powsimp on f for easier matching with the # exponential pattern, and attempt expansion on the exponent for easier # matching with the linear pattern. e = f.powsimp().match(c1**wexp) if e is not None: e_exp = e.pop(wexp).expand().match(c2 * i + c3) if e_exp is not None: e.update(e_exp) if e is not None: p = (c1**c3).subs(e) q = (c1**c2).subs(e) r = p * (q**a - q**(b + 1)) / (1 - q) l = p * (b - a + 1) return Piecewise((l, Eq(q, S.One)), (r, True)) r = gosper_sum(f, (i, a, b)) if not r in (None, S.NaN): return r return eval_sum_hyper(f_orig, (i, a, b))
def test_harmonic_rewrite(): n = Symbol("n") m = Symbol("m") assert harmonic(n).rewrite(digamma) == polygamma(0, n + 1) + EulerGamma assert harmonic(n).rewrite(trigamma) == polygamma(0, n + 1) + EulerGamma assert harmonic(n).rewrite(polygamma) == polygamma(0, n + 1) + EulerGamma assert harmonic( n, 3).rewrite(polygamma) == polygamma(2, n + 1) / 2 - polygamma(2, 1) / 2 assert harmonic(n, m).rewrite(polygamma) == (-1)**m * ( polygamma(m - 1, 1) - polygamma(m - 1, n + 1)) / factorial(m - 1) assert expand_func( harmonic(n + 4) ) == harmonic(n) + 1 / (n + 4) + 1 / (n + 3) + 1 / (n + 2) + 1 / (n + 1) assert expand_func(harmonic( n - 4)) == harmonic(n) - 1 / (n - 1) - 1 / (n - 2) - 1 / (n - 3) - 1 / n assert harmonic(n, m).rewrite("tractable") == harmonic(n, m).rewrite(polygamma) _k = Dummy("k") assert harmonic(n).rewrite(Sum).dummy_eq(Sum(1 / _k, (_k, 1, n))) assert harmonic(n, m).rewrite(Sum).dummy_eq(Sum(_k**(-m), (_k, 1, n)))
def test_harmonic_rational(): ne = S(6) no = S(5) pe = S(8) po = S(9) qe = S(10) qo = S(13) Heee = harmonic(ne + pe / qe) Aeee = (-log(10) + 2 * (Rational(-1, 4) + sqrt(5) / 4) * log(sqrt(-sqrt(5) / 8 + Rational(5, 8))) + 2 * (-sqrt(5) / 4 - Rational(1, 4)) * log(sqrt(sqrt(5) / 8 + Rational(5, 8))) + pi * sqrt(2 * sqrt(5) / 5 + 1) / 2 + Rational(13944145, 4720968)) Heeo = harmonic(ne + pe / qo) Aeeo = (-log(26) + 2 * log(sin(pi * Rational(3, 13))) * cos(pi * Rational(4, 13)) + 2 * log(sin(pi * Rational(2, 13))) * cos(pi * Rational(32, 13)) + 2 * log(sin(pi * Rational(5, 13))) * cos(pi * Rational(80, 13)) - 2 * log(sin(pi * Rational(6, 13))) * cos(pi * Rational(5, 13)) - 2 * log(sin(pi * Rational(4, 13))) * cos(pi / 13) + pi * cot(pi * Rational(5, 13)) / 2 - 2 * log(sin(pi / 13)) * cos(pi * Rational(3, 13)) + Rational(2422020029, 702257080)) Heoe = harmonic(ne + po / qe) Aeoe = ( -log(20) + 2 * (Rational(1, 4) + sqrt(5) / 4) * log(Rational(-1, 4) + sqrt(5) / 4) + 2 * (Rational(-1, 4) + sqrt(5) / 4) * log(sqrt(-sqrt(5) / 8 + Rational(5, 8))) + 2 * (-sqrt(5) / 4 - Rational(1, 4)) * log(sqrt(sqrt(5) / 8 + Rational(5, 8))) + 2 * (-sqrt(5) / 4 + Rational(1, 4)) * log(Rational(1, 4) + sqrt(5) / 4) + Rational(11818877030, 4286604231) + pi * sqrt(2 * sqrt(5) + 5) / 2) Heoo = harmonic(ne + po / qo) Aeoo = (-log(26) + 2 * log(sin(pi * Rational(3, 13))) * cos(pi * Rational(54, 13)) + 2 * log(sin(pi * Rational(4, 13))) * cos(pi * Rational(6, 13)) + 2 * log(sin(pi * Rational(6, 13))) * cos(pi * Rational(108, 13)) - 2 * log(sin(pi * Rational(5, 13))) * cos(pi / 13) - 2 * log(sin(pi / 13)) * cos(pi * Rational(5, 13)) + pi * cot(pi * Rational(4, 13)) / 2 - 2 * log(sin(pi * Rational(2, 13))) * cos(pi * Rational(3, 13)) + Rational(11669332571, 3628714320)) Hoee = harmonic(no + pe / qe) Aoee = (-log(10) + 2 * (Rational(-1, 4) + sqrt(5) / 4) * log(sqrt(-sqrt(5) / 8 + Rational(5, 8))) + 2 * (-sqrt(5) / 4 - Rational(1, 4)) * log(sqrt(sqrt(5) / 8 + Rational(5, 8))) + pi * sqrt(2 * sqrt(5) / 5 + 1) / 2 + Rational(779405, 277704)) Hoeo = harmonic(no + pe / qo) Aoeo = (-log(26) + 2 * log(sin(pi * Rational(3, 13))) * cos(pi * Rational(4, 13)) + 2 * log(sin(pi * Rational(2, 13))) * cos(pi * Rational(32, 13)) + 2 * log(sin(pi * Rational(5, 13))) * cos(pi * Rational(80, 13)) - 2 * log(sin(pi * Rational(6, 13))) * cos(pi * Rational(5, 13)) - 2 * log(sin(pi * Rational(4, 13))) * cos(pi / 13) + pi * cot(pi * Rational(5, 13)) / 2 - 2 * log(sin(pi / 13)) * cos(pi * Rational(3, 13)) + Rational(53857323, 16331560)) Hooe = harmonic(no + po / qe) Aooe = ( -log(20) + 2 * (Rational(1, 4) + sqrt(5) / 4) * log(Rational(-1, 4) + sqrt(5) / 4) + 2 * (Rational(-1, 4) + sqrt(5) / 4) * log(sqrt(-sqrt(5) / 8 + Rational(5, 8))) + 2 * (-sqrt(5) / 4 - Rational(1, 4)) * log(sqrt(sqrt(5) / 8 + Rational(5, 8))) + 2 * (-sqrt(5) / 4 + Rational(1, 4)) * log(Rational(1, 4) + sqrt(5) / 4) + Rational(486853480, 186374097) + pi * sqrt(2 * sqrt(5) + 5) / 2) Hooo = harmonic(no + po / qo) Aooo = (-log(26) + 2 * log(sin(pi * Rational(3, 13))) * cos(pi * Rational(54, 13)) + 2 * log(sin(pi * Rational(4, 13))) * cos(pi * Rational(6, 13)) + 2 * log(sin(pi * Rational(6, 13))) * cos(pi * Rational(108, 13)) - 2 * log(sin(pi * Rational(5, 13))) * cos(pi / 13) - 2 * log(sin(pi / 13)) * cos(pi * Rational(5, 13)) + pi * cot(pi * Rational(4, 13)) / 2 - 2 * log(sin(pi * Rational(2, 13))) * cos(3 * pi / 13) + Rational(383693479, 125128080)) H = [Heee, Heeo, Heoe, Heoo, Hoee, Hoeo, Hooe, Hooo] A = [Aeee, Aeeo, Aeoe, Aeoo, Aoee, Aoeo, Aooe, Aooo] for h, a in zip(H, A): e = expand_func(h).doit() assert cancel(e / a) == 1 assert abs(h.n() - a.n()) < 1e-12
def test_harmonic_rewrite_polygamma(): n = Symbol("n") m = Symbol("m") assert harmonic(n).rewrite(digamma) == polygamma(0, n + 1) + EulerGamma assert harmonic(n).rewrite(trigamma) == polygamma(0, n + 1) + EulerGamma assert harmonic(n).rewrite(polygamma) == polygamma(0, n + 1) + EulerGamma assert harmonic( n, 3).rewrite(polygamma) == polygamma(2, n + 1) / 2 - polygamma(2, 1) / 2 assert harmonic(n, m).rewrite(polygamma) == (-1)**m * ( polygamma(m - 1, 1) - polygamma(m - 1, n + 1)) / factorial(m - 1) assert expand_func( harmonic(n + 4) ) == harmonic(n) + 1 / (n + 4) + 1 / (n + 3) + 1 / (n + 2) + 1 / (n + 1) assert expand_func(harmonic( n - 4)) == harmonic(n) - 1 / (n - 1) - 1 / (n - 2) - 1 / (n - 3) - 1 / n assert harmonic(n, m).rewrite("tractable") == harmonic(n, m).rewrite(polygamma)
def test_harmonic_limit_fail(): n = Symbol("n") m = Symbol("m") # For m > 1: assert limit(harmonic(n, m), n, oo) == zeta(m)
def test_harmonic_rewrite_polygamma(): n = Symbol("n") m = Symbol("m") assert harmonic(n).rewrite(digamma) == polygamma(0, n + 1) + EulerGamma assert harmonic(n).rewrite(trigamma) == polygamma(0, n + 1) + EulerGamma assert harmonic(n).rewrite(polygamma) == polygamma(0, n + 1) + EulerGamma assert harmonic(n,3).rewrite(polygamma) == polygamma(2, n + 1)/2 - polygamma(2, 1)/2 assert harmonic(n,m).rewrite(polygamma) == (-1)**m*(polygamma(m - 1, 1) - polygamma(m - 1, n + 1))/factorial(m - 1) assert expand_func(harmonic(n+4)) == harmonic(n) + 1/(n + 4) + 1/(n + 3) + 1/(n + 2) + 1/(n + 1) assert expand_func(harmonic(n-4)) == harmonic(n) - 1/(n - 1) - 1/(n - 2) - 1/(n - 3) - 1/n assert harmonic(n, m).rewrite("tractable") == harmonic(n, m).rewrite(polygamma)
def test_harmonic_rational(): ne = S(6) no = S(5) pe = S(8) po = S(9) qe = S(10) qo = S(13) Heee = harmonic(ne + pe/qe) Aeee = (-log(10) + 2*(-1/S(4) + sqrt(5)/4)*log(sqrt(-sqrt(5)/8 + 5/S(8))) + 2*(-sqrt(5)/4 - 1/S(4))*log(sqrt(sqrt(5)/8 + 5/S(8))) + pi*(1/S(4) + sqrt(5)/4)/(2*sqrt(-sqrt(5)/8 + 5/S(8))) + 13944145/S(4720968)) Heeo = harmonic(ne + pe/qo) Aeeo = (-log(26) + 2*log(sin(3*pi/13))*cos(4*pi/13) + 2*log(sin(2*pi/13))*cos(32*pi/13) + 2*log(sin(5*pi/13))*cos(80*pi/13) - 2*log(sin(6*pi/13))*cos(5*pi/13) - 2*log(sin(4*pi/13))*cos(pi/13) + pi*cot(5*pi/13)/2 - 2*log(sin(pi/13))*cos(3*pi/13) + 2422020029/S(702257080)) Heoe = harmonic(ne + po/qe) Aeoe = (-log(20) + 2*(1/S(4) + sqrt(5)/4)*log(-1/S(4) + sqrt(5)/4) + 2*(-1/S(4) + sqrt(5)/4)*log(sqrt(-sqrt(5)/8 + 5/S(8))) + 2*(-sqrt(5)/4 - 1/S(4))*log(sqrt(sqrt(5)/8 + 5/S(8))) + 2*(-sqrt(5)/4 + 1/S(4))*log(1/S(4) + sqrt(5)/4) + 11818877030/S(4286604231) - pi*sqrt(sqrt(5)/8 + 5/S(8))/(-sqrt(5)/2 + 1/S(2)) ) Heoo = harmonic(ne + po/qo) Aeoo = (-log(26) + 2*log(sin(3*pi/13))*cos(54*pi/13) + 2*log(sin(4*pi/13))*cos(6*pi/13) + 2*log(sin(6*pi/13))*cos(108*pi/13) - 2*log(sin(5*pi/13))*cos(pi/13) - 2*log(sin(pi/13))*cos(5*pi/13) + pi*cot(4*pi/13)/2 - 2*log(sin(2*pi/13))*cos(3*pi/13) + 11669332571/S(3628714320)) Hoee = harmonic(no + pe/qe) Aoee = (-log(10) + 2*(-1/S(4) + sqrt(5)/4)*log(sqrt(-sqrt(5)/8 + 5/S(8))) + 2*(-sqrt(5)/4 - 1/S(4))*log(sqrt(sqrt(5)/8 + 5/S(8))) + pi*(1/S(4) + sqrt(5)/4)/(2*sqrt(-sqrt(5)/8 + 5/S(8))) + 779405/S(277704)) Hoeo = harmonic(no + pe/qo) Aoeo = (-log(26) + 2*log(sin(3*pi/13))*cos(4*pi/13) + 2*log(sin(2*pi/13))*cos(32*pi/13) + 2*log(sin(5*pi/13))*cos(80*pi/13) - 2*log(sin(6*pi/13))*cos(5*pi/13) - 2*log(sin(4*pi/13))*cos(pi/13) + pi*cot(5*pi/13)/2 - 2*log(sin(pi/13))*cos(3*pi/13) + 53857323/S(16331560)) Hooe = harmonic(no + po/qe) Aooe = (-log(20) + 2*(1/S(4) + sqrt(5)/4)*log(-1/S(4) + sqrt(5)/4) + 2*(-1/S(4) + sqrt(5)/4)*log(sqrt(-sqrt(5)/8 + 5/S(8))) + 2*(-sqrt(5)/4 - 1/S(4))*log(sqrt(sqrt(5)/8 + 5/S(8))) + 2*(-sqrt(5)/4 + 1/S(4))*log(1/S(4) + sqrt(5)/4) + 486853480/S(186374097) - pi*sqrt(sqrt(5)/8 + 5/S(8))/(2*(-sqrt(5)/4 + 1/S(4)))) Hooo = harmonic(no + po/qo) Aooo = (-log(26) + 2*log(sin(3*pi/13))*cos(54*pi/13) + 2*log(sin(4*pi/13))*cos(6*pi/13) + 2*log(sin(6*pi/13))*cos(108*pi/13) - 2*log(sin(5*pi/13))*cos(pi/13) - 2*log(sin(pi/13))*cos(5*pi/13) + pi*cot(4*pi/13)/2 - 2*log(sin(2*pi/13))*cos(3*pi/13) + 383693479/S(125128080)) H = [Heee, Heeo, Heoe, Heoo, Hoee, Hoeo, Hooe, Hooo] A = [Aeee, Aeeo, Aeoe, Aeoo, Aoee, Aoeo, Aooe, Aooo] for h, a in zip(H, A): e = expand_func(h).doit() assert cancel(e/a) == 1 assert h.n() == a.n()
def eval_sum_symbolic(f, limits): from sympy.functions import harmonic, bernoulli f_orig = f (i, a, b) = limits if not f.has(i): return f*(b - a + 1) # Linearity if f.is_Mul: L, R = f.as_two_terms() if not L.has(i): sR = eval_sum_symbolic(R, (i, a, b)) if sR: return L*sR if not R.has(i): sL = eval_sum_symbolic(L, (i, a, b)) if sL: return R*sL try: f = apart(f, i) # see if it becomes an Add except PolynomialError: pass if f.is_Add: L, R = f.as_two_terms() lrsum = telescopic(L, R, (i, a, b)) if lrsum: return lrsum lsum = eval_sum_symbolic(L, (i, a, b)) rsum = eval_sum_symbolic(R, (i, a, b)) if None not in (lsum, rsum): r = lsum + rsum if not r is S.NaN: return r # Polynomial terms with Faulhaber's formula n = Wild('n') result = f.match(i**n) if result is not None: n = result[n] if n.is_Integer: if n >= 0: if (b is S.Infinity and not a is S.NegativeInfinity) or \ (a is S.NegativeInfinity and not b is S.Infinity): return S.Infinity return ((bernoulli(n + 1, b + 1) - bernoulli(n + 1, a))/(n + 1)).expand() elif a.is_Integer and a >= 1: if n == -1: return harmonic(b) - harmonic(a - 1) else: return harmonic(b, abs(n)) - harmonic(a - 1, abs(n)) if not (a.has(S.Infinity, S.NegativeInfinity) or b.has(S.Infinity, S.NegativeInfinity)): # Geometric terms c1 = Wild('c1', exclude=[i]) c2 = Wild('c2', exclude=[i]) c3 = Wild('c3', exclude=[i]) wexp = Wild('wexp') # Here we first attempt powsimp on f for easier matching with the # exponential pattern, and attempt expansion on the exponent for easier # matching with the linear pattern. e = f.powsimp().match(c1 ** wexp) if e is not None: e_exp = e.pop(wexp).expand().match(c2*i + c3) if e_exp is not None: e.update(e_exp) if e is not None: p = (c1**c3).subs(e) q = (c1**c2).subs(e) r = p*(q**a - q**(b + 1))/(1 - q) l = p*(b - a + 1) return Piecewise((l, Eq(q, S.One)), (r, True)) r = gosper_sum(f, (i, a, b)) if isinstance(r, (Mul,Add)): from sympy import ordered, Tuple non_limit = r.free_symbols - Tuple(*limits[1:]).free_symbols den = denom(together(r)) den_sym = non_limit & den.free_symbols args = [] for v in ordered(den_sym): try: s = solve(den, v) m = Eq(v, s[0]) if s else S.false if m != False: args.append((Sum(f_orig.subs(*m.args), limits).doit(), m)) break except NotImplementedError: continue args.append((r, True)) return Piecewise(*args) if not r in (None, S.NaN): return r h = eval_sum_hyper(f_orig, (i, a, b)) if h is not None: return h factored = f_orig.factor() if factored != f_orig: return eval_sum_symbolic(factored, (i, a, b))
def test_harmonic(): n = Symbol("n") assert harmonic(n, 0) == n assert harmonic(n, 1) == harmonic(n) assert harmonic(0, 1) == 0 assert harmonic(1, 1) == 1 assert harmonic(2, 1) == Rational(3, 2) assert harmonic(3, 1) == Rational(11, 6) assert harmonic(4, 1) == Rational(25, 12) assert harmonic(0, 2) == 0 assert harmonic(1, 2) == 1 assert harmonic(2, 2) == Rational(5, 4) assert harmonic(3, 2) == Rational(49, 36) assert harmonic(4, 2) == Rational(205, 144) assert harmonic(0, 3) == 0 assert harmonic(1, 3) == 1 assert harmonic(2, 3) == Rational(9, 8) assert harmonic(3, 3) == Rational(251, 216) assert harmonic(4, 3) == Rational(2035, 1728) assert harmonic(oo, -1) == S.NaN assert harmonic(oo, 0) == oo assert harmonic(oo, S.Half) == oo assert harmonic(oo, 1) == oo assert harmonic(oo, 2) == (pi**2)/6 assert harmonic(oo, 3) == zeta(3)
def test_harmonic(): n = Symbol("n") m = Symbol("m") assert harmonic(n, 0) == n assert harmonic(n).evalf() == harmonic(n) assert harmonic(n, 1) == harmonic(n) assert harmonic(1, n).evalf() == harmonic(1, n) assert harmonic(0, 1) == 0 assert harmonic(1, 1) == 1 assert harmonic(2, 1) == Rational(3, 2) assert harmonic(3, 1) == Rational(11, 6) assert harmonic(4, 1) == Rational(25, 12) assert harmonic(0, 2) == 0 assert harmonic(1, 2) == 1 assert harmonic(2, 2) == Rational(5, 4) assert harmonic(3, 2) == Rational(49, 36) assert harmonic(4, 2) == Rational(205, 144) assert harmonic(0, 3) == 0 assert harmonic(1, 3) == 1 assert harmonic(2, 3) == Rational(9, 8) assert harmonic(3, 3) == Rational(251, 216) assert harmonic(4, 3) == Rational(2035, 1728) assert harmonic(oo, -1) is S.NaN assert harmonic(oo, 0) is oo assert harmonic(oo, S.Half) is oo assert harmonic(oo, 1) is oo assert harmonic(oo, 2) == (pi**2) / 6 assert harmonic(oo, 3) == zeta(3) assert harmonic(oo, Dummy(negative=True)) is S.NaN ip = Dummy(integer=True, positive=True) if (1 / ip <= 1) is True: #---------------------------------+ assert None, 'delete this if-block and the next line' #| ip = Dummy(even=True, positive=True) #--------------------+ assert harmonic(oo, 1 / ip) is oo assert harmonic(oo, 1 + ip) is zeta(1 + ip) assert harmonic(0, m) == 0