You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
367 lines
14 KiB
367 lines
14 KiB
from sympy.core.function import Function
|
|
from sympy.core.mul import Mul
|
|
from sympy.core.numbers import (E, I, Rational, oo, pi)
|
|
from sympy.core.singleton import S
|
|
from sympy.core.symbol import (Dummy, Symbol, symbols)
|
|
from sympy.functions.elementary.exponential import (exp, log)
|
|
from sympy.functions.elementary.miscellaneous import (root, sqrt)
|
|
from sympy.functions.elementary.trigonometric import sin
|
|
from sympy.functions.special.gamma_functions import gamma
|
|
from sympy.functions.special.hyper import hyper
|
|
from sympy.matrices.expressions.matexpr import MatrixSymbol
|
|
from sympy.simplify.powsimp import (powdenest, powsimp)
|
|
from sympy.simplify.simplify import (signsimp, simplify)
|
|
from sympy.core.symbol import Str
|
|
|
|
from sympy.abc import x, y, z, a, b
|
|
|
|
|
|
def test_powsimp():
|
|
x, y, z, n = symbols('x,y,z,n')
|
|
f = Function('f')
|
|
assert powsimp( 4**x * 2**(-x) * 2**(-x) ) == 1
|
|
assert powsimp( (-4)**x * (-2)**(-x) * 2**(-x) ) == 1
|
|
|
|
assert powsimp(
|
|
f(4**x * 2**(-x) * 2**(-x)) ) == f(4**x * 2**(-x) * 2**(-x))
|
|
assert powsimp( f(4**x * 2**(-x) * 2**(-x)), deep=True ) == f(1)
|
|
assert exp(x)*exp(y) == exp(x)*exp(y)
|
|
assert powsimp(exp(x)*exp(y)) == exp(x + y)
|
|
assert powsimp(exp(x)*exp(y)*2**x*2**y) == (2*E)**(x + y)
|
|
assert powsimp(exp(x)*exp(y)*2**x*2**y, combine='exp') == \
|
|
exp(x + y)*2**(x + y)
|
|
assert powsimp(exp(x)*exp(y)*exp(2)*sin(x) + sin(y) + 2**x*2**y) == \
|
|
exp(2 + x + y)*sin(x) + sin(y) + 2**(x + y)
|
|
assert powsimp(sin(exp(x)*exp(y))) == sin(exp(x)*exp(y))
|
|
assert powsimp(sin(exp(x)*exp(y)), deep=True) == sin(exp(x + y))
|
|
assert powsimp(x**2*x**y) == x**(2 + y)
|
|
# This should remain factored, because 'exp' with deep=True is supposed
|
|
# to act like old automatic exponent combining.
|
|
assert powsimp((1 + E*exp(E))*exp(-E), combine='exp', deep=True) == \
|
|
(1 + exp(1 + E))*exp(-E)
|
|
assert powsimp((1 + E*exp(E))*exp(-E), deep=True) == \
|
|
(1 + exp(1 + E))*exp(-E)
|
|
assert powsimp((1 + E*exp(E))*exp(-E)) == (1 + exp(1 + E))*exp(-E)
|
|
assert powsimp((1 + E*exp(E))*exp(-E), combine='exp') == \
|
|
(1 + exp(1 + E))*exp(-E)
|
|
assert powsimp((1 + E*exp(E))*exp(-E), combine='base') == \
|
|
(1 + E*exp(E))*exp(-E)
|
|
x, y = symbols('x,y', nonnegative=True)
|
|
n = Symbol('n', real=True)
|
|
assert powsimp(y**n * (y/x)**(-n)) == x**n
|
|
assert powsimp(x**(x**(x*y)*y**(x*y))*y**(x**(x*y)*y**(x*y)), deep=True) \
|
|
== (x*y)**(x*y)**(x*y)
|
|
assert powsimp(2**(2**(2*x)*x), deep=False) == 2**(2**(2*x)*x)
|
|
assert powsimp(2**(2**(2*x)*x), deep=True) == 2**(x*4**x)
|
|
assert powsimp(
|
|
exp(-x + exp(-x)*exp(-x*log(x))), deep=False, combine='exp') == \
|
|
exp(-x + exp(-x)*exp(-x*log(x)))
|
|
assert powsimp(
|
|
exp(-x + exp(-x)*exp(-x*log(x))), deep=False, combine='exp') == \
|
|
exp(-x + exp(-x)*exp(-x*log(x)))
|
|
assert powsimp((x + y)/(3*z), deep=False, combine='exp') == (x + y)/(3*z)
|
|
assert powsimp((x/3 + y/3)/z, deep=True, combine='exp') == (x/3 + y/3)/z
|
|
assert powsimp(exp(x)/(1 + exp(x)*exp(y)), deep=True) == \
|
|
exp(x)/(1 + exp(x + y))
|
|
assert powsimp(x*y**(z**x*z**y), deep=True) == x*y**(z**(x + y))
|
|
assert powsimp((z**x*z**y)**x, deep=True) == (z**(x + y))**x
|
|
assert powsimp(x*(z**x*z**y)**x, deep=True) == x*(z**(x + y))**x
|
|
p = symbols('p', positive=True)
|
|
assert powsimp((1/x)**log(2)/x) == (1/x)**(1 + log(2))
|
|
assert powsimp((1/p)**log(2)/p) == p**(-1 - log(2))
|
|
|
|
# coefficient of exponent can only be simplified for positive bases
|
|
assert powsimp(2**(2*x)) == 4**x
|
|
assert powsimp((-1)**(2*x)) == (-1)**(2*x)
|
|
i = symbols('i', integer=True)
|
|
assert powsimp((-1)**(2*i)) == 1
|
|
assert powsimp((-1)**(-x)) != (-1)**x # could be 1/((-1)**x), but is not
|
|
# force=True overrides assumptions
|
|
assert powsimp((-1)**(2*x), force=True) == 1
|
|
|
|
# rational exponents allow combining of negative terms
|
|
w, n, m = symbols('w n m', negative=True)
|
|
e = i/a # not a rational exponent if `a` is unknown
|
|
ex = w**e*n**e*m**e
|
|
assert powsimp(ex) == m**(i/a)*n**(i/a)*w**(i/a)
|
|
e = i/3
|
|
ex = w**e*n**e*m**e
|
|
assert powsimp(ex) == (-1)**i*(-m*n*w)**(i/3)
|
|
e = (3 + i)/i
|
|
ex = w**e*n**e*m**e
|
|
assert powsimp(ex) == (-1)**(3*e)*(-m*n*w)**e
|
|
|
|
eq = x**(a*Rational(2, 3))
|
|
# eq != (x**a)**(2/3) (try x = -1 and a = 3 to see)
|
|
assert powsimp(eq).exp == eq.exp == a*Rational(2, 3)
|
|
# powdenest goes the other direction
|
|
assert powsimp(2**(2*x)) == 4**x
|
|
|
|
assert powsimp(exp(p/2)) == exp(p/2)
|
|
|
|
# issue 6368
|
|
eq = Mul(*[sqrt(Dummy(imaginary=True)) for i in range(3)])
|
|
assert powsimp(eq) == eq and eq.is_Mul
|
|
|
|
assert all(powsimp(e) == e for e in (sqrt(x**a), sqrt(x**2)))
|
|
|
|
# issue 8836
|
|
assert str( powsimp(exp(I*pi/3)*root(-1,3)) ) == '(-1)**(2/3)'
|
|
|
|
# issue 9183
|
|
assert powsimp(-0.1**x) == -0.1**x
|
|
|
|
# issue 10095
|
|
assert powsimp((1/(2*E))**oo) == (exp(-1)/2)**oo
|
|
|
|
# PR 13131
|
|
eq = sin(2*x)**2*sin(2.0*x)**2
|
|
assert powsimp(eq) == eq
|
|
|
|
# issue 14615
|
|
assert powsimp(x**2*y**3*(x*y**2)**Rational(3, 2)
|
|
) == x*y*(x*y**2)**Rational(5, 2)
|
|
|
|
|
|
def test_powsimp_negated_base():
|
|
assert powsimp((-x + y)/sqrt(x - y)) == -sqrt(x - y)
|
|
assert powsimp((-x + y)*(-z + y)/sqrt(x - y)/sqrt(z - y)) == sqrt(x - y)*sqrt(z - y)
|
|
p = symbols('p', positive=True)
|
|
reps = {p: 2, a: S.Half}
|
|
assert powsimp((-p)**a/p**a).subs(reps) == ((-1)**a).subs(reps)
|
|
assert powsimp((-p)**a*p**a).subs(reps) == ((-p**2)**a).subs(reps)
|
|
n = symbols('n', negative=True)
|
|
reps = {p: -2, a: S.Half}
|
|
assert powsimp((-n)**a/n**a).subs(reps) == (-1)**(-a).subs(a, S.Half)
|
|
assert powsimp((-n)**a*n**a).subs(reps) == ((-n**2)**a).subs(reps)
|
|
# if x is 0 then the lhs is 0**a*oo**a which is not (-1)**a
|
|
eq = (-x)**a/x**a
|
|
assert powsimp(eq) == eq
|
|
|
|
|
|
def test_powsimp_nc():
|
|
x, y, z = symbols('x,y,z')
|
|
A, B, C = symbols('A B C', commutative=False)
|
|
|
|
assert powsimp(A**x*A**y, combine='all') == A**(x + y)
|
|
assert powsimp(A**x*A**y, combine='base') == A**x*A**y
|
|
assert powsimp(A**x*A**y, combine='exp') == A**(x + y)
|
|
|
|
assert powsimp(A**x*B**x, combine='all') == A**x*B**x
|
|
assert powsimp(A**x*B**x, combine='base') == A**x*B**x
|
|
assert powsimp(A**x*B**x, combine='exp') == A**x*B**x
|
|
|
|
assert powsimp(B**x*A**x, combine='all') == B**x*A**x
|
|
assert powsimp(B**x*A**x, combine='base') == B**x*A**x
|
|
assert powsimp(B**x*A**x, combine='exp') == B**x*A**x
|
|
|
|
assert powsimp(A**x*A**y*A**z, combine='all') == A**(x + y + z)
|
|
assert powsimp(A**x*A**y*A**z, combine='base') == A**x*A**y*A**z
|
|
assert powsimp(A**x*A**y*A**z, combine='exp') == A**(x + y + z)
|
|
|
|
assert powsimp(A**x*B**x*C**x, combine='all') == A**x*B**x*C**x
|
|
assert powsimp(A**x*B**x*C**x, combine='base') == A**x*B**x*C**x
|
|
assert powsimp(A**x*B**x*C**x, combine='exp') == A**x*B**x*C**x
|
|
|
|
assert powsimp(B**x*A**x*C**x, combine='all') == B**x*A**x*C**x
|
|
assert powsimp(B**x*A**x*C**x, combine='base') == B**x*A**x*C**x
|
|
assert powsimp(B**x*A**x*C**x, combine='exp') == B**x*A**x*C**x
|
|
|
|
|
|
def test_issue_6440():
|
|
assert powsimp(16*2**a*8**b) == 2**(a + 3*b + 4)
|
|
|
|
|
|
def test_powdenest():
|
|
x, y = symbols('x,y')
|
|
p, q = symbols('p q', positive=True)
|
|
i, j = symbols('i,j', integer=True)
|
|
|
|
assert powdenest(x) == x
|
|
assert powdenest(x + 2*(x**(a*Rational(2, 3)))**(3*x)) == (x + 2*(x**(a*Rational(2, 3)))**(3*x))
|
|
assert powdenest((exp(a*Rational(2, 3)))**(3*x)) # -X-> (exp(a/3))**(6*x)
|
|
assert powdenest((x**(a*Rational(2, 3)))**(3*x)) == ((x**(a*Rational(2, 3)))**(3*x))
|
|
assert powdenest(exp(3*x*log(2))) == 2**(3*x)
|
|
assert powdenest(sqrt(p**2)) == p
|
|
eq = p**(2*i)*q**(4*i)
|
|
assert powdenest(eq) == (p*q**2)**(2*i)
|
|
# -X-> (x**x)**i*(x**x)**j == x**(x*(i + j))
|
|
assert powdenest((x**x)**(i + j))
|
|
assert powdenest(exp(3*y*log(x))) == x**(3*y)
|
|
assert powdenest(exp(y*(log(a) + log(b)))) == (a*b)**y
|
|
assert powdenest(exp(3*(log(a) + log(b)))) == a**3*b**3
|
|
assert powdenest(((x**(2*i))**(3*y))**x) == ((x**(2*i))**(3*y))**x
|
|
assert powdenest(((x**(2*i))**(3*y))**x, force=True) == x**(6*i*x*y)
|
|
assert powdenest(((x**(a*Rational(2, 3)))**(3*y/i))**x) == \
|
|
(((x**(a*Rational(2, 3)))**(3*y/i))**x)
|
|
assert powdenest((x**(2*i)*y**(4*i))**z, force=True) == (x*y**2)**(2*i*z)
|
|
assert powdenest((p**(2*i)*q**(4*i))**j) == (p*q**2)**(2*i*j)
|
|
e = ((p**(2*a))**(3*y))**x
|
|
assert powdenest(e) == e
|
|
e = ((x**2*y**4)**a)**(x*y)
|
|
assert powdenest(e) == e
|
|
e = (((x**2*y**4)**a)**(x*y))**3
|
|
assert powdenest(e) == ((x**2*y**4)**a)**(3*x*y)
|
|
assert powdenest((((x**2*y**4)**a)**(x*y)), force=True) == \
|
|
(x*y**2)**(2*a*x*y)
|
|
assert powdenest((((x**2*y**4)**a)**(x*y))**3, force=True) == \
|
|
(x*y**2)**(6*a*x*y)
|
|
assert powdenest((x**2*y**6)**i) != (x*y**3)**(2*i)
|
|
x, y = symbols('x,y', positive=True)
|
|
assert powdenest((x**2*y**6)**i) == (x*y**3)**(2*i)
|
|
|
|
assert powdenest((x**(i*Rational(2, 3))*y**(i/2))**(2*i)) == (x**Rational(4, 3)*y)**(i**2)
|
|
assert powdenest(sqrt(x**(2*i)*y**(6*i))) == (x*y**3)**i
|
|
|
|
assert powdenest(4**x) == 2**(2*x)
|
|
assert powdenest((4**x)**y) == 2**(2*x*y)
|
|
assert powdenest(4**x*y) == 2**(2*x)*y
|
|
|
|
|
|
def test_powdenest_polar():
|
|
x, y, z = symbols('x y z', polar=True)
|
|
a, b, c = symbols('a b c')
|
|
assert powdenest((x*y*z)**a) == x**a*y**a*z**a
|
|
assert powdenest((x**a*y**b)**c) == x**(a*c)*y**(b*c)
|
|
assert powdenest(((x**a)**b*y**c)**c) == x**(a*b*c)*y**(c**2)
|
|
|
|
|
|
def test_issue_5805():
|
|
arg = ((gamma(x)*hyper((), (), x))*pi)**2
|
|
assert powdenest(arg) == (pi*gamma(x)*hyper((), (), x))**2
|
|
assert arg.is_positive is None
|
|
|
|
|
|
def test_issue_9324_powsimp_on_matrix_symbol():
|
|
M = MatrixSymbol('M', 10, 10)
|
|
expr = powsimp(M, deep=True)
|
|
assert expr == M
|
|
assert expr.args[0] == Str('M')
|
|
|
|
|
|
def test_issue_6367():
|
|
z = -5*sqrt(2)/(2*sqrt(2*sqrt(29) + 29)) + sqrt(-sqrt(29)/29 + S.Half)
|
|
assert Mul(*[powsimp(a) for a in Mul.make_args(z.normal())]) == 0
|
|
assert powsimp(z.normal()) == 0
|
|
assert simplify(z) == 0
|
|
assert powsimp(sqrt(2 + sqrt(3))*sqrt(2 - sqrt(3)) + 1) == 2
|
|
assert powsimp(z) != 0
|
|
|
|
|
|
def test_powsimp_polar():
|
|
from sympy.functions.elementary.complexes import polar_lift
|
|
from sympy.functions.elementary.exponential import exp_polar
|
|
x, y, z = symbols('x y z')
|
|
p, q, r = symbols('p q r', polar=True)
|
|
|
|
assert (polar_lift(-1))**(2*x) == exp_polar(2*pi*I*x)
|
|
assert powsimp(p**x * q**x) == (p*q)**x
|
|
assert p**x * (1/p)**x == 1
|
|
assert (1/p)**x == p**(-x)
|
|
|
|
assert exp_polar(x)*exp_polar(y) == exp_polar(x)*exp_polar(y)
|
|
assert powsimp(exp_polar(x)*exp_polar(y)) == exp_polar(x + y)
|
|
assert powsimp(exp_polar(x)*exp_polar(y)*p**x*p**y) == \
|
|
(p*exp_polar(1))**(x + y)
|
|
assert powsimp(exp_polar(x)*exp_polar(y)*p**x*p**y, combine='exp') == \
|
|
exp_polar(x + y)*p**(x + y)
|
|
assert powsimp(
|
|
exp_polar(x)*exp_polar(y)*exp_polar(2)*sin(x) + sin(y) + p**x*p**y) \
|
|
== p**(x + y) + sin(x)*exp_polar(2 + x + y) + sin(y)
|
|
assert powsimp(sin(exp_polar(x)*exp_polar(y))) == \
|
|
sin(exp_polar(x)*exp_polar(y))
|
|
assert powsimp(sin(exp_polar(x)*exp_polar(y)), deep=True) == \
|
|
sin(exp_polar(x + y))
|
|
|
|
|
|
def test_issue_5728():
|
|
b = x*sqrt(y)
|
|
a = sqrt(b)
|
|
c = sqrt(sqrt(x)*y)
|
|
assert powsimp(a*b) == sqrt(b)**3
|
|
assert powsimp(a*b**2*sqrt(y)) == sqrt(y)*a**5
|
|
assert powsimp(a*x**2*c**3*y) == c**3*a**5
|
|
assert powsimp(a*x*c**3*y**2) == c**7*a
|
|
assert powsimp(x*c**3*y**2) == c**7
|
|
assert powsimp(x*c**3*y) == x*y*c**3
|
|
assert powsimp(sqrt(x)*c**3*y) == c**5
|
|
assert powsimp(sqrt(x)*a**3*sqrt(y)) == sqrt(x)*sqrt(y)*a**3
|
|
assert powsimp(Mul(sqrt(x)*c**3*sqrt(y), y, evaluate=False)) == \
|
|
sqrt(x)*sqrt(y)**3*c**3
|
|
assert powsimp(a**2*a*x**2*y) == a**7
|
|
|
|
# symbolic powers work, too
|
|
b = x**y*y
|
|
a = b*sqrt(b)
|
|
assert a.is_Mul is True
|
|
assert powsimp(a) == sqrt(b)**3
|
|
|
|
# as does exp
|
|
a = x*exp(y*Rational(2, 3))
|
|
assert powsimp(a*sqrt(a)) == sqrt(a)**3
|
|
assert powsimp(a**2*sqrt(a)) == sqrt(a)**5
|
|
assert powsimp(a**2*sqrt(sqrt(a))) == sqrt(sqrt(a))**9
|
|
|
|
|
|
def test_issue_from_PR1599():
|
|
n1, n2, n3, n4 = symbols('n1 n2 n3 n4', negative=True)
|
|
assert (powsimp(sqrt(n1)*sqrt(n2)*sqrt(n3)) ==
|
|
-I*sqrt(-n1)*sqrt(-n2)*sqrt(-n3))
|
|
assert (powsimp(root(n1, 3)*root(n2, 3)*root(n3, 3)*root(n4, 3)) ==
|
|
-(-1)**Rational(1, 3)*
|
|
(-n1)**Rational(1, 3)*(-n2)**Rational(1, 3)*(-n3)**Rational(1, 3)*(-n4)**Rational(1, 3))
|
|
|
|
|
|
def test_issue_10195():
|
|
a = Symbol('a', integer=True)
|
|
l = Symbol('l', even=True, nonzero=True)
|
|
n = Symbol('n', odd=True)
|
|
e_x = (-1)**(n/2 - S.Half) - (-1)**(n*Rational(3, 2) - S.Half)
|
|
assert powsimp((-1)**(l/2)) == I**l
|
|
assert powsimp((-1)**(n/2)) == I**n
|
|
assert powsimp((-1)**(n*Rational(3, 2))) == -I**n
|
|
assert powsimp(e_x) == (-1)**(n/2 - S.Half) + (-1)**(n*Rational(3, 2) +
|
|
S.Half)
|
|
assert powsimp((-1)**(a*Rational(3, 2))) == (-I)**a
|
|
|
|
def test_issue_15709():
|
|
assert powsimp(3**x*Rational(2, 3)) == 2*3**(x-1)
|
|
assert powsimp(2*3**x/3) == 2*3**(x-1)
|
|
|
|
|
|
def test_issue_11981():
|
|
x, y = symbols('x y', commutative=False)
|
|
assert powsimp((x*y)**2 * (y*x)**2) == (x*y)**2 * (y*x)**2
|
|
|
|
|
|
def test_issue_17524():
|
|
a = symbols("a", real=True)
|
|
e = (-1 - a**2)*sqrt(1 + a**2)
|
|
assert signsimp(powsimp(e)) == signsimp(e) == -(a**2 + 1)**(S(3)/2)
|
|
|
|
|
|
def test_issue_19627():
|
|
# if you use force the user must verify
|
|
assert powdenest(sqrt(sin(x)**2), force=True) == sin(x)
|
|
assert powdenest((x**(S.Half/y))**(2*y), force=True) == x
|
|
from sympy.core.function import expand_power_base
|
|
e = 1 - a
|
|
expr = (exp(z/e)*x**(b/e)*y**((1 - b)/e))**e
|
|
assert powdenest(expand_power_base(expr, force=True), force=True
|
|
) == x**b*y**(1 - b)*exp(z)
|
|
|
|
|
|
def test_issue_22546():
|
|
p1, p2 = symbols('p1, p2', positive=True)
|
|
ref = powsimp(p1**z/p2**z)
|
|
e = z + 1
|
|
ans = ref.subs(z, e)
|
|
assert ans.is_Pow
|
|
assert powsimp(p1**e/p2**e) == ans
|
|
i = symbols('i', integer=True)
|
|
ref = powsimp(x**i/y**i)
|
|
e = i + 1
|
|
ans = ref.subs(i, e)
|
|
assert ans.is_Pow
|
|
assert powsimp(x**e/y**e) == ans
|