Skip to content

Commit

Permalink
Merge pull request #13265 from ylemkimon/exptrigsimp
Browse files Browse the repository at this point in the history
Improve exptrigsimp()
  • Loading branch information
Upabjojr committed Sep 11, 2017
2 parents 5a5d97d + e059c14 commit ba63f8a
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 43 deletions.
4 changes: 2 additions & 2 deletions sympy/simplify/simplify.py
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ def shorter(*choices):
short = shorter(short, cancel(short))
short = shorter(short, factor_terms(short), expand_power_exp(expand_mul(short)))
if short.has(TrigonometricFunction, HyperbolicFunction, ExpBase):
short = exptrigsimp(short, simplify=False)
short = exptrigsimp(short)

# get rid of hollow 2-arg Mul factorization
hollow_mul = Transform(
Expand Down Expand Up @@ -1093,7 +1093,7 @@ def tofunc(nu, z):
def expander(fro):
def repl(nu, z):
if (nu % 1) == S(1)/2:
return exptrigsimp(trigsimp(unpolarify(
return simplify(trigsimp(unpolarify(
fro(nu, z0).rewrite(besselj).rewrite(jn).expand(
func=True)).subs(z0, z)))
elif nu.is_Integer and nu > 1:
Expand Down
7 changes: 5 additions & 2 deletions sympy/simplify/tests/test_simplify.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,11 @@ def test_simplify_other():
def test_simplify_complex():
cosAsExp = cos(x)._eval_rewrite_as_exp(x)
tanAsExp = tan(x)._eval_rewrite_as_exp(x)
assert simplify(cosAsExp*tanAsExp).expand() == (
sin(x))._eval_rewrite_as_exp(x).expand() # issue 4341
assert simplify(cosAsExp*tanAsExp) == sin(x) # issue 4341

# issue 10124
assert simplify(exp(Matrix([[0, -1], [1, 0]]))) == Matrix([[cos(1),
-sin(1)], [sin(1), cos(1)]])


def test_simplify_ratio():
Expand Down
10 changes: 4 additions & 6 deletions sympy/simplify/tests/test_trigsimp.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,8 @@ def valid(a, b):

assert exptrigsimp(exp(x) + exp(-x)) == 2*cosh(x)
assert exptrigsimp(exp(x) - exp(-x)) == 2*sinh(x)
assert exptrigsimp((2*exp(x)-2*exp(-x))/(exp(x)+exp(-x))) == 2*tanh(x)
assert exptrigsimp((2*exp(2*x)-2)/(exp(2*x)+1)) == 2*tanh(x)
e = [cos(x) + I*sin(x), cos(x) - I*sin(x),
cosh(x) - sinh(x), cosh(x) + sinh(x)]
ok = [exp(I*x), exp(-I*x), exp(-x), exp(x)]
Expand All @@ -378,12 +380,8 @@ def valid(a, b):
for a in (1, I, x, I*x, 1 + I):
w = exp(a)
eq = y*(w - 1/w)/(w + 1/w)
s = simplify(eq)
assert s == exptrigsimp(eq)
res.append(s)
sinv = simplify(1/eq)
assert sinv == exptrigsimp(1/eq)
res.append(sinv)
res.append(simplify(eq))
res.append(simplify(1/eq))
assert all(valid(i, j) for i, j in zip(res, ok))

for a in range(1, 3):
Expand Down
81 changes: 48 additions & 33 deletions sympy/simplify/trigsimp.py
Original file line number Diff line number Diff line change
Expand Up @@ -513,12 +513,9 @@ def traverse(e):
return trigsimpfunc(expr)


def exptrigsimp(expr, simplify=True):
def exptrigsimp(expr):
"""
Simplifies exponential / trigonometric / hyperbolic functions.
When ``simplify`` is True (default) the expression obtained after the
simplification step will be then be passed through simplify to
precondition it so the final transformations will be applied.
Examples
========
Expand All @@ -544,35 +541,53 @@ def exp_trig(e):
return min(*choices, key=count_ops)
newexpr = bottom_up(expr, exp_trig)

if simplify:
newexpr = newexpr.simplify()

# conversion from exp to hyperbolic
ex = newexpr.atoms(exp, S.Exp1)
ex = [ei for ei in ex if 1/ei not in ex]
## sinh and cosh
for ei in ex:
e2 = ei**-2
if e2 in ex:
a = e2.args[0]/2 if not e2 is S.Exp1 else S.Half
newexpr = newexpr.subs((e2 + 1)*ei, 2*cosh(a))
newexpr = newexpr.subs((e2 - 1)*ei, 2*sinh(a))
## exp ratios to tan and tanh
for ei in ex:
n, d = ei - 1, ei + 1
et = n/d
etinv = d/n # not 1/et or else recursion errors arise
a = ei.args[0] if ei.func is exp else S.One
if a.is_Mul or a is S.ImaginaryUnit:
c = a.as_coefficient(I)
if c:
t = S.ImaginaryUnit*tan(c/2)
newexpr = newexpr.subs(etinv, 1/t)
newexpr = newexpr.subs(et, t)
continue
t = tanh(a/2)
newexpr = newexpr.subs(etinv, 1/t)
newexpr = newexpr.subs(et, t)
def f(rv):
if not rv.is_Mul:
return rv
rvd = rv.as_powers_dict()
newd = rvd.copy()

def signlog(expr, sign=1):
if expr is S.Exp1:
return sign, 1
elif isinstance(expr, exp):
return sign, expr.args[0]
elif sign == 1:
return signlog(-expr, sign=-1)
else:
return None, None

ee = rvd[S.Exp1]
for k in rvd:
if k.is_Add and len(k.args) == 2:
# k == c*(1 + sign*E**x)
c = k.args[0]
sign, x = signlog(k.args[1]/c)
if not x:
continue
m = rvd[k]
newd[k] -= m
if ee == -x*m/2:
# sinh and cosh
newd[S.Exp1] -= ee
ee = 0
if sign == 1:
newd[2*c*cosh(x/2)] += m
else:
newd[-2*c*sinh(x/2)] += m
elif newd[1 - sign*S.Exp1**x] == -m:
# tanh
del newd[1 - sign*S.Exp1**x]
if sign == 1:
newd[-c/tanh(x/2)] += m
else:
newd[-c*tanh(x/2)] += m
else:
newd[1 + sign*S.Exp1**x] += m
newd[c] += m

return Mul(*[k**newd[k] for k in newd])
newexpr = bottom_up(newexpr, f)

# sin/cos and sinh/cosh ratios to tan and tanh, respectively
if newexpr.has(HyperbolicFunction):
Expand Down

0 comments on commit ba63f8a

Please sign in to comment.