From 7578593c07a1021d3a8669bef703f107135e322d Mon Sep 17 00:00:00 2001 From: Chris Smith Date: Fri, 19 Nov 2021 10:34:16 -0600 Subject: [PATCH 1/8] 4077: use signsimp as first step in cancel --- sympy/polys/polytools.py | 3 ++- sympy/polys/tests/test_polytools.py | 16 +++++++++++++++- sympy/utilities/tests/test_wester.py | 23 ++++++++++++----------- 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/sympy/polys/polytools.py b/sympy/polys/polytools.py index d50c63541be2..a39959a56dde 100644 --- a/sympy/polys/polytools.py +++ b/sympy/polys/polytools.py @@ -6671,11 +6671,12 @@ def cancel(f, *gens, **args): >>> together(_) (x + 2)/2 """ + from sympy.simplify.simplify import signsimp from sympy.functions.elementary.piecewise import Piecewise from sympy.polys.rings import sring options.allowed_flags(args, ['polys']) - f = sympify(f) + f = signsimp(sympify(f)) opt = {} if 'polys' in args: opt['polys'] = args['polys'] diff --git a/sympy/polys/tests/test_polytools.py b/sympy/polys/tests/test_polytools.py index 51d08ad53419..13cc41d7e6ef 100644 --- a/sympy/polys/tests/test_polytools.py +++ b/sympy/polys/tests/test_polytools.py @@ -71,7 +71,7 @@ from sympy.functions.elementary.miscellaneous import sqrt from sympy.functions.elementary.piecewise import Piecewise from sympy.functions.elementary.trigonometric import sin -from sympy.matrices.dense import Matrix +from sympy.matrices.dense import Matrix, eye from sympy.matrices.expressions.matexpr import MatrixSymbol from sympy.polys.rootoftools import rootof from sympy.utilities.iterables import iterable @@ -3087,6 +3087,20 @@ def test_cancel(): assert cancel((x**2 - 1)/(x + 1)*p3) == (x - 1)*p4 assert cancel((x**2 - 1)/(x + 1) + p3) == (x - 1) + p4 + # issue 4077 + m = Matrix([ + [ 0, -1, 0, 0, 0, 0, -1, 0, 0], + [-1, x, -1, 0, 0, 0, 0, -1, 0], + [ 0, -1, x, 0, 0, 0, 0, 0, -1], + [ 0, 0, 0, x, -1, 0, -1, 0, 0], + [ 0, 0, 0, -1, x, -1, 0, -1, 0], + [ 0, 0, 0, 0, -1, 0, 0, 0, -1], + [-1, 0, 0, -1, 0, 0, x, -1, 0], + [ 0, -1, 0, 0, -1, 0, -1, 0, -1], + [ 0, 0, -1, 0, 0, -1, 0, -1, x]]) + eq = m.row_join(eye(9)).rref()[0][0, 11] + assert cancel(eq) == -1/(2*x) # this should return very quickly (< 1 sec) + # issue 9363 M = MatrixSymbol('M', 5, 5) assert cancel(M[0,0] + 7) == M[0,0] + 7 diff --git a/sympy/utilities/tests/test_wester.py b/sympy/utilities/tests/test_wester.py index 2e513542ea69..6171102b0344 100644 --- a/sympy/utilities/tests/test_wester.py +++ b/sympy/utilities/tests/test_wester.py @@ -918,17 +918,18 @@ def test_M6(): def test_M7(): # TODO: Replace solve with solveset, as of now test fails for solveset - sol = solve(x**8 - 8*x**7 + 34*x**6 - 92*x**5 + 175*x**4 - 236*x**3 + - 226*x**2 - 140*x + 46, x) - assert [s.simplify() for s in sol] == [ - 1 - sqrt(-6 - 2*I*sqrt(3 + 4*sqrt(3)))/2, - 1 + sqrt(-6 - 2*I*sqrt(3 + 4*sqrt(3)))/2, - 1 - sqrt(-6 + 2*I*sqrt(3 + 4*sqrt(3)))/2, - 1 + sqrt(-6 + 2*I*sqrt(3 + 4*sqrt (3)))/2, - 1 - sqrt(-6 + 2*sqrt(-3 + 4*sqrt(3)))/2, - 1 + sqrt(-6 + 2*sqrt(-3 + 4*sqrt(3)))/2, - 1 - sqrt(-6 - 2*sqrt(-3 + 4*sqrt(3)))/2, - 1 + sqrt(-6 - 2*sqrt(-3 + 4*sqrt(3)))/2] + assert set(solve(x**8 - 8*x**7 + 34*x**6 - 92*x**5 + 175*x**4 - 236*x**3 + + 226*x**2 - 140*x + 46, x)) == set([ + 1 - sqrt(2)*I*sqrt(-sqrt(-3 + 4*sqrt(3)) + 3)/2, + 1 - sqrt(2)*sqrt(-3 + I*sqrt(3 + 4*sqrt(3)))/2, + 1 - sqrt(2)*I*sqrt(sqrt(-3 + 4*sqrt(3)) + 3)/2, + 1 - sqrt(2)*sqrt(-3 - I*sqrt(3 + 4*sqrt(3)))/2, + 1 + sqrt(2)*I*sqrt(sqrt(-3 + 4*sqrt(3)) + 3)/2, + 1 + sqrt(2)*sqrt(-3 - I*sqrt(3 + 4*sqrt(3)))/2, + 1 + sqrt(2)*sqrt(-3 + I*sqrt(3 + 4*sqrt(3)))/2, + 1 + sqrt(2)*I*sqrt(-sqrt(-3 + 4*sqrt(3)) + 3)/2, + 1 + sqrt(2)*I*sqrt(sqrt(-3 + 4*sqrt(3)) + 3)/2, + ]) @XFAIL # There are an infinite number of solutions. From 25bb85b701f68fe2ec73269e6df2cf15acd4e8b0 Mon Sep 17 00:00:00 2001 From: Chris Smith Date: Fri, 19 Nov 2021 12:10:10 -0600 Subject: [PATCH 2/8] remove factor from calculate_series --- sympy/integrals/tests/test_heurisch.py | 4 ++-- sympy/physics/control/tests/test_lti.py | 2 +- sympy/polys/polytools.py | 6 ++++-- sympy/series/gruntz.py | 4 +++- sympy/series/tests/test_series.py | 4 ++-- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/sympy/integrals/tests/test_heurisch.py b/sympy/integrals/tests/test_heurisch.py index e676ec292940..df6f051bcd1a 100644 --- a/sympy/integrals/tests/test_heurisch.py +++ b/sympy/integrals/tests/test_heurisch.py @@ -220,8 +220,8 @@ def test_heurisch_wrapper(): (-log(x - y)/(2*y) + log(x + y)/(2*y), Ne(y, 0)), (1/x, True)) # issue 6926 f = sqrt(x**2/((y - x)*(y + x))) - assert heurisch_wrapper(f, x) == x*sqrt(x**2/(-x**2 + y**2)) \ - - y**2*sqrt(x**2/(-x**2 + y**2))/x + assert heurisch_wrapper(f, x) == x*sqrt(-x**2/(x**2 - y**2)) \ + - y**2*sqrt(-x**2/(x**2 - y**2))/x def test_issue_3609(): assert heurisch(1/(x * (1 + log(x)**2)), x) == atan(log(x)) diff --git a/sympy/physics/control/tests/test_lti.py b/sympy/physics/control/tests/test_lti.py index 2fd1f665eaf1..7fa49fc3a5b2 100644 --- a/sympy/physics/control/tests/test_lti.py +++ b/sympy/physics/control/tests/test_lti.py @@ -1077,7 +1077,7 @@ def test_MIMOFeedback_functions(): (TransferFunction(0, 1, s), TransferFunction(-s**2 + s, 1, s)))) assert F_2.doit() == \ TransferFunctionMatrix(((TransferFunction(s*(-2*s**2 + s*(2*s - 1) + 1), s**2 - s + 1, s), - TransferFunction(2*s**3*(1 - s), s**2 - s + 1, s)), (TransferFunction(0, 1, s), TransferFunction(s*(1 - s), 1, s)))) + TransferFunction(-2*s**3*(s - 1), s**2 - s + 1, s)), (TransferFunction(0, 1, s), TransferFunction(s*(1 - s), 1, s)))) assert F_2.doit(expand=True) == \ TransferFunctionMatrix(((TransferFunction(-s**2 + s, s**2 - s + 1, s), TransferFunction(-2*s**4 + 2*s**3, s**2 - s + 1, s)), (TransferFunction(0, 1, s), TransferFunction(-s**2 + s, 1, s)))) diff --git a/sympy/polys/polytools.py b/sympy/polys/polytools.py index a39959a56dde..3729ecee2818 100644 --- a/sympy/polys/polytools.py +++ b/sympy/polys/polytools.py @@ -6647,7 +6647,7 @@ def nth_power_roots_poly(f, n, *gens, **args): @public -def cancel(f, *gens, **args): +def cancel(f, *gens, _signsimp=True, **args): """ Cancel common factors in a rational function ``f``. @@ -6676,7 +6676,9 @@ def cancel(f, *gens, **args): from sympy.polys.rings import sring options.allowed_flags(args, ['polys']) - f = signsimp(sympify(f)) + f = sympify(f) + if _signsimp: + f = signsimp(f) opt = {} if 'polys' in args: opt['polys'] = args['polys'] diff --git a/sympy/series/gruntz.py b/sympy/series/gruntz.py index c3e512a6a3b5..6aa13b4943cd 100644 --- a/sympy/series/gruntz.py +++ b/sympy/series/gruntz.py @@ -120,6 +120,7 @@ from sympy.core import Basic, S, Mul, PoleError from sympy.core.cache import cacheit +from sympy.core.exprtools import factor_terms from sympy.core.numbers import ilcm, I, oo from sympy.core.symbol import Dummy, Wild from sympy.core.traversal import bottom_up @@ -496,7 +497,8 @@ def calculate_series(e, x, logx=None): # -exp(p/(p + 1)) + exp(-p**2/(p + 1) + p). No current simplification # methods reduce this to 0 while not expanding polynomials. t = bottom_up(t, lambda w: getattr(w, 'normal', lambda: w)()) - t = cancel(t, expand=False).factor() + t = factor_terms(cancel(t, expand=False)) + # XXX try t = bottom_up(t, lambda x: cancel(x, expand=False)) instead of the two calls if t.has(exp) and t.has(log): t = powdenest(t) diff --git a/sympy/series/tests/test_series.py b/sympy/series/tests/test_series.py index 7258845f9a1e..d6ae85668a51 100644 --- a/sympy/series/tests/test_series.py +++ b/sympy/series/tests/test_series.py @@ -344,8 +344,8 @@ def test_issue_20697(): def test_issue_21245(): fi = (1 + sqrt(5))/2 assert (1/(1 - x - x**2)).series(x, 1/fi, 1).factor() == \ - (-6964*sqrt(5) - 15572 + 2440*sqrt(5)*x + 5456*x\ - + O((x - 2/(1 + sqrt(5)))**2, (x, 2/(1 + sqrt(5)))))/((1 + sqrt(5))**2\ + (-4812 - 2152*sqrt(5) + 1686*x + 754*sqrt(5)*x\ + + O((x - 2/(1 + sqrt(5)))**2, (x, 2/(1 + sqrt(5)))))/((1 + sqrt(5))\ *(20 + 9*sqrt(5))**2*(x + sqrt(5)*x - 2)) From 05610d11adb4efb36f3bc49cbfc349fc28875b3a Mon Sep 17 00:00:00 2001 From: Chris Smith Date: Fri, 19 Nov 2021 14:16:52 -0600 Subject: [PATCH 3/8] fix tests --- sympy/concrete/tests/test_gosper.py | 12 ++++----- sympy/integrals/tests/test_integrals.py | 5 ++-- sympy/physics/control/lti.py | 34 ++++++++++++------------- sympy/series/tests/test_limits.py | 2 +- 4 files changed, 27 insertions(+), 26 deletions(-) diff --git a/sympy/concrete/tests/test_gosper.py b/sympy/concrete/tests/test_gosper.py index bb6d6c22a272..15e70f337979 100644 --- a/sympy/concrete/tests/test_gosper.py +++ b/sympy/concrete/tests/test_gosper.py @@ -48,15 +48,15 @@ def test_gosper_sum(): 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) + 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() == -exp(m*log(a) + m*log(b))*gamma(a + 1) \ - *gamma(b + 1)/(gamma(a)*gamma(b)*gamma(a + m + 1)*gamma(b + m + 1)) \ - + 1/(gamma(a)*gamma(b)) + 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 test_gosper_sum_indefinite(): diff --git a/sympy/integrals/tests/test_integrals.py b/sympy/integrals/tests/test_integrals.py index 6bfde75bd6c4..e9409424c0f1 100644 --- a/sympy/integrals/tests/test_integrals.py +++ b/sympy/integrals/tests/test_integrals.py @@ -1208,7 +1208,7 @@ def test_atom_bug(): def test_limit_bug(): z = Symbol('z', zero=False) assert integrate(sin(x*y*z), (x, 0, pi), (y, 0, pi)).together() == \ - (log(z) - Ci(pi**2*z) + EulerGamma + 2*log(pi))/z + (log(pi*z) - Ci(pi**2*z) + EulerGamma + log(pi))/z def test_issue_4703(): @@ -1712,7 +1712,8 @@ def test_issue_17473(): def test_issue_17671(): assert integrate(log(log(x)) / x**2, [x, 1, oo]) == -EulerGamma assert integrate(log(log(x)) / x**3, [x, 1, oo]) == -log(2)/2 - EulerGamma/2 - assert integrate(log(log(x)) / x**10, [x, 1, oo]) == -2*log(3)/9 - EulerGamma/9 + assert integrate(log(log(x)) / x**10, [x, 1, oo] + ) == -log(9)/9 - EulerGamma/9 - I*pi/9 def test_issue_2975(): diff --git a/sympy/physics/control/lti.py b/sympy/physics/control/lti.py index 135039e7f9ea..7a811917eb29 100644 --- a/sympy/physics/control/lti.py +++ b/sympy/physics/control/lti.py @@ -2248,13 +2248,13 @@ def doit(self, cancel=True, expand=False, **kwargs): | [ - -----] [- -] | [ - -----] \ [ 1 s ]{t} [1 1]{t}/ [ 1 s ]{t} >>> pprint(F_1.doit(), use_unicode=False) - [ -s 1 - s ] - [ ------- ----------- ] - [ 6*s - 1 s*(1 - 6*s) ] - [ ] - [25*s*(s - 1) + 5*(1 - s)*(6*s - 1) (s - 1)*(6*s + 24)] - [---------------------------------- ------------------] - [ (1 - s)*(6*s - 1) s*(6*s - 1) ]{t} + [ -s s - 1 ] + [------- ----------- ] + [6*s - 1 s*(6*s - 1) ] + [ ] + [5*s - 5 (s - 1)*(6*s + 24)] + [------- ------------------] + [6*s - 1 s*(6*s - 1) ]{t} If the user wants the resultant ``TransferFunctionMatrix`` object without canceling the common factors then the ``cancel`` kwarg should be passed ``False``. @@ -2273,16 +2273,16 @@ def doit(self, cancel=True, expand=False, **kwargs): the ``expand`` kwarg should be passed as ``True``. >>> pprint(F_1.doit(expand=True), use_unicode=False) - [ -s 1 - s ] - [ ------- ---------- ] - [ 6*s - 1 2 ] - [ - 6*s + s ] - [ ] - [ 2 2 ] - [- 5*s + 10*s - 5 6*s + 18*s - 24] - [----------------- ----------------] - [ 2 2 ] - [ - 6*s + 7*s - 1 6*s - s ]{t} + [ -s s - 1 ] + [------- -------- ] + [6*s - 1 2 ] + [ 6*s - s ] + [ ] + [ 2 ] + [5*s - 5 6*s + 18*s - 24] + [------- ----------------] + [6*s - 1 2 ] + [ 6*s - s ]{t} """ _mat = self.sensitivity * self.sys1.doit()._expr_mat diff --git a/sympy/series/tests/test_limits.py b/sympy/series/tests/test_limits.py index 22e99781d853..b444ff26bf59 100644 --- a/sympy/series/tests/test_limits.py +++ b/sympy/series/tests/test_limits.py @@ -133,7 +133,7 @@ def test_log(): expr = tau**2*((tau - 1)*(tau + 1)*log(x + 1)/(tau**2 + 1)**2 + 1/((tau**2\ + 1)*(x + 1)) - (-2*tau*atan(x/tau) + (tau**2/2 - 1/2)*log(tau**2\ + x**2))/(tau**2 + 1)**2) - assert limit(expr, x, oo) == pi*tau**3/(tau**2 + 1)**2 + assert limit(expr, x, oo) == pi*tau**3/(tau**4 + 2*tau**2 + 1) def test_piecewise(): From cf625c37ad6d08c66d7fca5273d534b813c5bc58 Mon Sep 17 00:00:00 2001 From: Chris Smith Date: Fri, 19 Nov 2021 14:44:50 -0600 Subject: [PATCH 4/8] expand exp(1 + b)->E*exp(b) --- sympy/series/gruntz.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sympy/series/gruntz.py b/sympy/series/gruntz.py index 6aa13b4943cd..f898362a01dc 100644 --- a/sympy/series/gruntz.py +++ b/sympy/series/gruntz.py @@ -500,6 +500,13 @@ def calculate_series(e, x, logx=None): t = factor_terms(cancel(t, expand=False)) # XXX try t = bottom_up(t, lambda x: cancel(x, expand=False)) instead of the two calls + # not sure if the has to be generalized to expand all exp + # but it is sufficient for the failing test of + # limit((2*exp(3*x)/(exp(2*x) + 1))**(1/x), x, oo) == E + if isinstance(t, exp): + from sympy.core.function import expand_power_exp, expand_mul + t = expand_power_exp(t.func(expand_mul(t.exp))) + if t.has(exp) and t.has(log): t = powdenest(t) From 5e55c1bf114fbf3618b2e77b4906dba8856badd1 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Fri, 19 Nov 2021 16:09:41 -0600 Subject: [PATCH 5/8] Update test_gosper.py --- sympy/concrete/tests/test_gosper.py | 1 - sympy/integrals/tests/test_integrals.py | 2 +- sympy/polys/tests/test_polytools.py | 18 ++++++------------ sympy/utilities/tests/test_wester.py | 1 - 4 files changed, 7 insertions(+), 15 deletions(-) diff --git a/sympy/concrete/tests/test_gosper.py b/sympy/concrete/tests/test_gosper.py index 15e70f337979..3f95542f29b3 100644 --- a/sympy/concrete/tests/test_gosper.py +++ b/sympy/concrete/tests/test_gosper.py @@ -4,7 +4,6 @@ from sympy.core.singleton import S from sympy.core.symbol import Symbol from sympy.functions.combinatorial.factorials import (binomial, factorial) -from sympy.functions.elementary.exponential import (exp, log) from sympy.functions.elementary.miscellaneous import sqrt from sympy.functions.special.gamma_functions import gamma from sympy.polys.polytools import Poly diff --git a/sympy/integrals/tests/test_integrals.py b/sympy/integrals/tests/test_integrals.py index e9409424c0f1..f23e6a51b238 100644 --- a/sympy/integrals/tests/test_integrals.py +++ b/sympy/integrals/tests/test_integrals.py @@ -1713,7 +1713,7 @@ def test_issue_17671(): assert integrate(log(log(x)) / x**2, [x, 1, oo]) == -EulerGamma assert integrate(log(log(x)) / x**3, [x, 1, oo]) == -log(2)/2 - EulerGamma/2 assert integrate(log(log(x)) / x**10, [x, 1, oo] - ) == -log(9)/9 - EulerGamma/9 - I*pi/9 + ) == -log(9)/9 - EulerGamma/9 def test_issue_2975(): diff --git a/sympy/polys/tests/test_polytools.py b/sympy/polys/tests/test_polytools.py index 13cc41d7e6ef..cfc56f66c22f 100644 --- a/sympy/polys/tests/test_polytools.py +++ b/sympy/polys/tests/test_polytools.py @@ -3088,18 +3088,12 @@ def test_cancel(): assert cancel((x**2 - 1)/(x + 1) + p3) == (x - 1) + p4 # issue 4077 - m = Matrix([ - [ 0, -1, 0, 0, 0, 0, -1, 0, 0], - [-1, x, -1, 0, 0, 0, 0, -1, 0], - [ 0, -1, x, 0, 0, 0, 0, 0, -1], - [ 0, 0, 0, x, -1, 0, -1, 0, 0], - [ 0, 0, 0, -1, x, -1, 0, -1, 0], - [ 0, 0, 0, 0, -1, 0, 0, 0, -1], - [-1, 0, 0, -1, 0, 0, x, -1, 0], - [ 0, -1, 0, 0, -1, 0, -1, 0, -1], - [ 0, 0, -1, 0, 0, -1, 0, -1, x]]) - eq = m.row_join(eye(9)).rref()[0][0, 11] - assert cancel(eq) == -1/(2*x) # this should return very quickly (< 1 sec) + n = -1 + 1/x + z = n/x/(-n)**2 - 1/n/x + # z is zero so it's derivative should be zero + zd = z.diff() + assert zd != 0 # if it is, use the explicit expression + assert cancel(zd) == 0 # issue 9363 M = MatrixSymbol('M', 5, 5) diff --git a/sympy/utilities/tests/test_wester.py b/sympy/utilities/tests/test_wester.py index 6171102b0344..ea346816fb7d 100644 --- a/sympy/utilities/tests/test_wester.py +++ b/sympy/utilities/tests/test_wester.py @@ -928,7 +928,6 @@ def test_M7(): 1 + sqrt(2)*sqrt(-3 - I*sqrt(3 + 4*sqrt(3)))/2, 1 + sqrt(2)*sqrt(-3 + I*sqrt(3 + 4*sqrt(3)))/2, 1 + sqrt(2)*I*sqrt(-sqrt(-3 + 4*sqrt(3)) + 3)/2, - 1 + sqrt(2)*I*sqrt(sqrt(-3 + 4*sqrt(3)) + 3)/2, ]) From 74973b066aa66d318c8e9a259c065be221b134f3 Mon Sep 17 00:00:00 2001 From: Chris Smith Date: Mon, 22 Nov 2021 11:35:44 -0600 Subject: [PATCH 6/8] clean up pre-existing sign irregularities without this, it takes multiple pass (4) to resolve sign issues in the `q` expression in the test. --- sympy/polys/tests/test_polytools.py | 45 ++++++++++++++++++++++++----- sympy/simplify/simplify.py | 6 ++-- 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/sympy/polys/tests/test_polytools.py b/sympy/polys/tests/test_polytools.py index cfc56f66c22f..4a770fd5e685 100644 --- a/sympy/polys/tests/test_polytools.py +++ b/sympy/polys/tests/test_polytools.py @@ -71,9 +71,10 @@ from sympy.functions.elementary.miscellaneous import sqrt from sympy.functions.elementary.piecewise import Piecewise from sympy.functions.elementary.trigonometric import sin -from sympy.matrices.dense import Matrix, eye +from sympy.matrices.dense import Matrix from sympy.matrices.expressions.matexpr import MatrixSymbol from sympy.polys.rootoftools import rootof +from sympy.simplify.simplify import signsimp from sympy.utilities.iterables import iterable from sympy.testing.pytest import raises, warns_deprecated_sympy @@ -3088,12 +3089,42 @@ def test_cancel(): assert cancel((x**2 - 1)/(x + 1) + p3) == (x - 1) + p4 # issue 4077 - n = -1 + 1/x - z = n/x/(-n)**2 - 1/n/x - # z is zero so it's derivative should be zero - zd = z.diff() - assert zd != 0 # if it is, use the explicit expression - assert cancel(zd) == 0 + q = S('''(2*1*(x - 1/x)/(x*(2*x - (-x + 1/x)/(x**2*(x - 1/x)**2) - 1/(x**2*(x - + 1/x)) - 2/x)) - 2*1*((x - 1/x)/((x*(x - 1/x)**2)) - 1/(x*(x - + 1/x)))*((-x + 1/x)*((x - 1/x)/((x*(x - 1/x)**2)) - 1/(x*(x - + 1/x)))/(2*x - (-x + 1/x)/(x**2*(x - 1/x)**2) - 1/(x**2*(x - 1/x)) - + 2/x) + 1)*((x - 1/x)/((x - 1/x)**2) - ((x - 1/x)/((x*(x - 1/x)**2)) - + 1/(x*(x - 1/x)))**2/(2*x - (-x + 1/x)/(x**2*(x - 1/x)**2) - 1/(x**2*(x + - 1/x)) - 2/x) - 1/(x - 1/x))*(2*x - (-x + 1/x)/(x**2*(x - 1/x)**2) - + 1/(x**2*(x - 1/x)) - 2/x)/x - 1/x)*(((-x + 1/x)/((x*(x - 1/x)**2)) + + 1/(x*(x - 1/x)))*((-(x - 1/x)/(x*(x - 1/x)) - 1/x)*((x - 1/x)/((x*(x - + 1/x)**2)) - 1/(x*(x - 1/x)))/(2*x - (-x + 1/x)/(x**2*(x - 1/x)**2) - + 1/(x**2*(x - 1/x)) - 2/x) - 1 + (x - 1/x)/(x - 1/x))/((x*((x - + 1/x)/((x - 1/x)**2) - ((x - 1/x)/((x*(x - 1/x)**2)) - 1/(x*(x - + 1/x)))**2/(2*x - (-x + 1/x)/(x**2*(x - 1/x)**2) - 1/(x**2*(x - 1/x)) - + 2/x) - 1/(x - 1/x))*(2*x - (-x + 1/x)/(x**2*(x - 1/x)**2) - 1/(x**2*(x + - 1/x)) - 2/x))) + ((x - 1/x)/((x*(x - 1/x))) + 1/x)/((x*(2*x - (-x + + 1/x)/(x**2*(x - 1/x)**2) - 1/(x**2*(x - 1/x)) - 2/x))) + 1/x)/(2*x + + 2*((x - 1/x)/((x*(x - 1/x)**2)) - 1/(x*(x - 1/x)))*((-(x - 1/x)/(x*(x + - 1/x)) - 1/x)*((x - 1/x)/((x*(x - 1/x)**2)) - 1/(x*(x - 1/x)))/(2*x - + (-x + 1/x)/(x**2*(x - 1/x)**2) - 1/(x**2*(x - 1/x)) - 2/x) - 1 + (x - + 1/x)/(x - 1/x))/((x*((x - 1/x)/((x - 1/x)**2) - ((x - 1/x)/((x*(x - + 1/x)**2)) - 1/(x*(x - 1/x)))**2/(2*x - (-x + 1/x)/(x**2*(x - 1/x)**2) + - 1/(x**2*(x - 1/x)) - 2/x) - 1/(x - 1/x))*(2*x - (-x + 1/x)/(x**2*(x + - 1/x)**2) - 1/(x**2*(x - 1/x)) - 2/x))) - 2*((x - 1/x)/((x*(x - + 1/x))) + 1/x)/(x*(2*x - (-x + 1/x)/(x**2*(x - 1/x)**2) - 1/(x**2*(x - + 1/x)) - 2/x)) - 2/x) - ((x - 1/x)/((x*(x - 1/x)**2)) - 1/(x*(x - + 1/x)))*((-x + 1/x)*((x - 1/x)/((x*(x - 1/x)**2)) - 1/(x*(x - + 1/x)))/(2*x - (-x + 1/x)/(x**2*(x - 1/x)**2) - 1/(x**2*(x - 1/x)) - + 2/x) + 1)/(x*((x - 1/x)/((x - 1/x)**2) - ((x - 1/x)/((x*(x - 1/x)**2)) + - 1/(x*(x - 1/x)))**2/(2*x - (-x + 1/x)/(x**2*(x - 1/x)**2) - + 1/(x**2*(x - 1/x)) - 2/x) - 1/(x - 1/x))*(2*x - (-x + 1/x)/(x**2*(x - + 1/x)**2) - 1/(x**2*(x - 1/x)) - 2/x)) + (x - 1/x)/((x*(2*x - (-x + + 1/x)/(x**2*(x - 1/x)**2) - 1/(x**2*(x - 1/x)) - 2/x))) - 1/x''', + evaluate=False) + assert cancel(q, _signsimp=False) == -1/(2*x) + assert q.subs(x, 2) is S.NaN + assert signsimp(q) is S.NaN # issue 9363 M = MatrixSymbol('M', 5, 5) diff --git a/sympy/simplify/simplify.py b/sympy/simplify/simplify.py index cfbbfdf180e4..3e6c59a1032d 100644 --- a/sympy/simplify/simplify.py +++ b/sympy/simplify/simplify.py @@ -402,7 +402,9 @@ def signsimp(expr, evaluate=None): expr = sympify(expr) if not isinstance(expr, (Expr, Relational)) or expr.is_Atom: return expr - e = sub_post(sub_pre(expr)) + # get rid of an pre-existing unevaluation regarding sign + e = expr.replace(lambda x: x.is_Mul and -(-x) != x, lambda x: -(-x)) + e = sub_post(sub_pre(e)) if not isinstance(e, (Expr, Relational)) or e.is_Atom: return e if e.is_Add: @@ -412,7 +414,7 @@ def signsimp(expr, evaluate=None): return Mul(S.NegativeOne, -rv, evaluate=False) return rv if evaluate: - e = e.xreplace({m: -(-m) for m in e.atoms(Mul) if -(-m) != m}) + e = e.replace(lambda x: x.is_Mul and -(-x) != x, lambda x: -(-x)) return e From 17b963fcb0aafd6f5a93fe213ee68ba0f1f5ef57 Mon Sep 17 00:00:00 2001 From: Chris Smith Date: Tue, 23 Nov 2021 10:25:19 -0600 Subject: [PATCH 7/8] gruntz tweak --- sympy/series/gruntz.py | 25 ++++++++++++------------- sympy/series/tests/test_gruntz.py | 4 ++-- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/sympy/series/gruntz.py b/sympy/series/gruntz.py index f898362a01dc..ff6b3197cbc3 100644 --- a/sympy/series/gruntz.py +++ b/sympy/series/gruntz.py @@ -120,7 +120,6 @@ from sympy.core import Basic, S, Mul, PoleError from sympy.core.cache import cacheit -from sympy.core.exprtools import factor_terms from sympy.core.numbers import ilcm, I, oo from sympy.core.symbol import Dummy, Wild from sympy.core.traversal import bottom_up @@ -494,18 +493,18 @@ def calculate_series(e, x, logx=None): for t in e.lseries(x, logx=logx): # bottom_up function is required for a specific case - when e is - # -exp(p/(p + 1)) + exp(-p**2/(p + 1) + p). No current simplification - # methods reduce this to 0 while not expanding polynomials. - t = bottom_up(t, lambda w: getattr(w, 'normal', lambda: w)()) - t = factor_terms(cancel(t, expand=False)) - # XXX try t = bottom_up(t, lambda x: cancel(x, expand=False)) instead of the two calls - - # not sure if the has to be generalized to expand all exp - # but it is sufficient for the failing test of - # limit((2*exp(3*x)/(exp(2*x) + 1))**(1/x), x, oo) == E - if isinstance(t, exp): - from sympy.core.function import expand_power_exp, expand_mul - t = expand_power_exp(t.func(expand_mul(t.exp))) + # -exp(p/(p + 1)) + exp(-p**2/(p + 1) + p) + t = bottom_up(t, lambda w: + getattr(w, 'normal', lambda: w)()) + # And the expression + # `(-sin(1/x) + sin((x + exp(x))*exp(-x)/x))*exp(x)` + # from the first test of test_gruntz_eval_special needs to + # be expanded. But other forms need to be have at least + # factor_terms applied. `factor` accomplishes both and is + # faster than using `factor_terms` for the gruntz suite. It + # does not appear that use of `cancel` is necessary. + # t = cancel(t, expand=False) + t = t.factor() if t.has(exp) and t.has(log): t = powdenest(t) diff --git a/sympy/series/tests/test_gruntz.py b/sympy/series/tests/test_gruntz.py index a69e4c4503ee..efcbca86c76e 100644 --- a/sympy/series/tests/test_gruntz.py +++ b/sympy/series/tests/test_gruntz.py @@ -398,12 +398,12 @@ def test_MrvTestCase_page47_ex3_21(): assert mmrv(expr, x) == {1/h, exp(-x), exp(x), exp(x - h), exp(x/(1 + h))} -def test_I(): +def test_gruntz_I(): y = Symbol("y") assert gruntz(I*x, x, oo) == I*oo assert gruntz(y*I*x, x, oo) == y*I*oo assert gruntz(y*3*I*x, x, oo) == y*I*oo - assert gruntz(y*3*sin(I)*x, x, oo).simplify().rewrite(sign) == y*I*oo + assert gruntz(y*3*sin(I)*x, x, oo) == y*I*oo def test_issue_4814(): From a48b36d8ec49fb7678a72b3af45385371f2883bf Mon Sep 17 00:00:00 2001 From: Chris Smith Date: Sun, 28 Nov 2021 01:40:01 -0600 Subject: [PATCH 8/8] undo test changes for together --- sympy/concrete/tests/test_gosper.py | 13 +++++++------ sympy/integrals/tests/test_integrals.py | 5 ++--- sympy/series/gruntz.py | 1 - sympy/series/tests/test_limits.py | 2 +- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/sympy/concrete/tests/test_gosper.py b/sympy/concrete/tests/test_gosper.py index 3f95542f29b3..bb6d6c22a272 100644 --- a/sympy/concrete/tests/test_gosper.py +++ b/sympy/concrete/tests/test_gosper.py @@ -4,6 +4,7 @@ from sympy.core.singleton import S from sympy.core.symbol import Symbol from sympy.functions.combinatorial.factorials import (binomial, factorial) +from sympy.functions.elementary.exponential import (exp, log) from sympy.functions.elementary.miscellaneous import sqrt from sympy.functions.special.gamma_functions import gamma from sympy.polys.polytools import Poly @@ -47,15 +48,15 @@ def test_gosper_sum(): 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) + 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)) + n*(n + a + b)*a**n*b**n/(factorial(n + a)*factorial(n + b)), \ + (n, 0, m)).simplify() == -exp(m*log(a) + m*log(b))*gamma(a + 1) \ + *gamma(b + 1)/(gamma(a)*gamma(b)*gamma(a + m + 1)*gamma(b + m + 1)) \ + + 1/(gamma(a)*gamma(b)) def test_gosper_sum_indefinite(): diff --git a/sympy/integrals/tests/test_integrals.py b/sympy/integrals/tests/test_integrals.py index f23e6a51b238..6bfde75bd6c4 100644 --- a/sympy/integrals/tests/test_integrals.py +++ b/sympy/integrals/tests/test_integrals.py @@ -1208,7 +1208,7 @@ def test_atom_bug(): def test_limit_bug(): z = Symbol('z', zero=False) assert integrate(sin(x*y*z), (x, 0, pi), (y, 0, pi)).together() == \ - (log(pi*z) - Ci(pi**2*z) + EulerGamma + log(pi))/z + (log(z) - Ci(pi**2*z) + EulerGamma + 2*log(pi))/z def test_issue_4703(): @@ -1712,8 +1712,7 @@ def test_issue_17473(): def test_issue_17671(): assert integrate(log(log(x)) / x**2, [x, 1, oo]) == -EulerGamma assert integrate(log(log(x)) / x**3, [x, 1, oo]) == -log(2)/2 - EulerGamma/2 - assert integrate(log(log(x)) / x**10, [x, 1, oo] - ) == -log(9)/9 - EulerGamma/9 + assert integrate(log(log(x)) / x**10, [x, 1, oo]) == -2*log(3)/9 - EulerGamma/9 def test_issue_2975(): diff --git a/sympy/series/gruntz.py b/sympy/series/gruntz.py index ff6b3197cbc3..7d496b1b9b7f 100644 --- a/sympy/series/gruntz.py +++ b/sympy/series/gruntz.py @@ -489,7 +489,6 @@ def calculate_series(e, x, logx=None): This is a place that fails most often, so it is in its own function. """ - from sympy.polys import cancel for t in e.lseries(x, logx=logx): # bottom_up function is required for a specific case - when e is diff --git a/sympy/series/tests/test_limits.py b/sympy/series/tests/test_limits.py index b444ff26bf59..22e99781d853 100644 --- a/sympy/series/tests/test_limits.py +++ b/sympy/series/tests/test_limits.py @@ -133,7 +133,7 @@ def test_log(): expr = tau**2*((tau - 1)*(tau + 1)*log(x + 1)/(tau**2 + 1)**2 + 1/((tau**2\ + 1)*(x + 1)) - (-2*tau*atan(x/tau) + (tau**2/2 - 1/2)*log(tau**2\ + x**2))/(tau**2 + 1)**2) - assert limit(expr, x, oo) == pi*tau**3/(tau**4 + 2*tau**2 + 1) + assert limit(expr, x, oo) == pi*tau**3/(tau**2 + 1)**2 def test_piecewise():