On Tue, Mar 10, 2009 at 2:31 PM, Fabian Seoane <fab...@fseoane.net> wrote: > > Ondrej Certik wrote: >> Hi, >> >> sending a trivial patch to remove hacks from trigsimp. >> > > removing hacks is always good news, but I do not agree that > sin(x)**2/cos(x)**2 is a valid answer. > By definition, trigsimp will try to return the simplest possible > expression, and although 'the simplest possible > expression' is a rather vague term, imho tan**2 is a better answer than > sin(x)**2/cos(x)**2 > > Related to this, I would expect the following to return True: > > In [2]: trigsimp(tan(x)) == trigsimp(sin(x)/cos(x)) > Out[2]: False
All of this is fixed in the attached patch. Please review. Ondrej --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "sympy-patches" group. To post to this group, send email to sympy-patches@googlegroups.com To unsubscribe from this group, send email to sympy-patches+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/sympy-patches?hl=en -~----------~----~----~----~------~----~------~--~---
From bddf677be04b62d450229a622c8e8bd73d92e38d Mon Sep 17 00:00:00 2001 From: Ondrej Certik <ond...@certik.cz> Date: Tue, 24 Mar 2009 21:13:59 -0700 Subject: [PATCH] trigsimp() two hacks removed and done right Previously trigsimp() failed to simplify sin(x)/cos(x) to tan(x) and similar things and also it required an ugly hack. Many of those are now fixed and tests written. Signed-off-by: Ondrej Certik <ond...@certik.cz> --- sympy/simplify/simplify.py | 46 ++++++++++++++++++++++++-------- sympy/simplify/tests/test_simplify.py | 18 ++++++++++++- 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/sympy/simplify/simplify.py b/sympy/simplify/simplify.py index 2ab5cf3..1c0c42e 100644 --- a/sympy/simplify/simplify.py +++ b/sympy/simplify/simplify.py @@ -764,15 +764,39 @@ def trigsimp(expr, deep=False, recursive=False): >>> trigsimp(log(e), deep=True) log(2) """ + from sympy.core.basic import S + sin, cos, tan, cot = C.sin, C.cos, C.tan, C.cot if recursive: w, g = cse(expr) g = trigsimp_nonrecursive(g[0]) for sub in reversed(w): g = g.subs(sub[0], sub[1]) g = trigsimp_nonrecursive(g) - return(g) + result = g else: - return trigsimp_nonrecursive(expr, deep) + result = trigsimp_nonrecursive(expr, deep) + + # do some final simplifications like sin/cos -> tan: + a,b,c = map(Wild, 'abc') + matchers = ( + (a*sin(b)**c/cos(b)**c, a*tan(b)**c), + ) + for pattern, simp in matchers: + res = result.match(pattern) + if res is not None: + # if c is missing or zero, do nothing: + if (not c in res) or res[c] == 0: + continue + # if "a" contains the argument of sin/cos "b", skip the + # simplification: + if res[a].has(res[b]): + continue + # simplify and finish: + result = simp.subs(res) + break + + return result + def trigsimp_nonrecursive(expr, deep=False): """ @@ -796,28 +820,26 @@ def trigsimp_nonrecursive(expr, deep=False): >>> e = 2*sin(x)**2 + 2*cos(x)**2 >>> trigsimp(e) 2 - >>> trigsimp(log(e)) + >>> trigsimp_nonrecursive(log(e)) log(2*cos(x)**2 + 2*sin(x)**2) - >>> trigsimp(log(e), deep=True) + >>> trigsimp_nonrecursive(log(e), deep=True) log(2) """ from sympy.core.basic import S sin, cos, tan, cot = C.sin, C.cos, C.tan, C.cot - #XXX this stopped working: - if expr == 1/cos(Symbol("x"))**2 - 1: - return tan(Symbol("x"))**2 - if expr.is_Function: if deep: - return expr.func( trigsimp(expr.args[0], deep) ) + return expr.func( trigsimp_nonrecursive(expr.args[0], deep) ) elif expr.is_Mul: ret = S.One for x in expr.args: - ret *= trigsimp(x, deep) + ret *= trigsimp_nonrecursive(x, deep) + return ret elif expr.is_Pow: - return Pow(trigsimp(expr.base, deep), trigsimp(expr.exp, deep)) + return Pow(trigsimp_nonrecursive(expr.base, deep), + trigsimp_nonrecursive(expr.exp, deep)) elif expr.is_Add: # TODO this needs to be faster @@ -832,7 +854,7 @@ def trigsimp_nonrecursive(expr, deep=False): # Scan for the terms we need ret = S.Zero for term in expr.args: - term = trigsimp(term, deep) + term = trigsimp_nonrecursive(term, deep) res = None for pattern, result in matchers: res = term.match(pattern) diff --git a/sympy/simplify/tests/test_simplify.py b/sympy/simplify/tests/test_simplify.py index b62ea40..b45ef5e 100644 --- a/sympy/simplify/tests/test_simplify.py +++ b/sympy/simplify/tests/test_simplify.py @@ -33,7 +33,7 @@ def test_ratsimp_X2(): assert e != 1 assert ratsimp(e) == 1 -def test_trigsimp(): +def test_trigsimp1(): x, y = symbols('x y') assert trigsimp(1 - sin(x)**2) == cos(x)**2 @@ -53,11 +53,27 @@ def test_trigsimp(): assert trigsimp(cos(0.12345)**2 + sin(0.12345)**2) == 1 e = 2*sin(x)**2 + 2*cos(x)**2 assert trigsimp(log(e), deep=True) == log(2) + +def test_trigsimp2(): + x, y = symbols('x y') assert trigsimp(cos(x)**2*sin(y)**2 + cos(x)**2*cos(y)**2 + sin(x)**2, recursive=True) == 1 assert trigsimp(sin(x)**2*sin(y)**2 + sin(x)**2*cos(y)**2 + cos(x)**2, recursive=True) == 1 +def test_trigsimp3(): + x, y = symbols('x y') + assert trigsimp(sin(x)/cos(x)) == tan(x) + assert trigsimp(sin(x)**2/cos(x)**2) == tan(x)**2 + assert trigsimp(sin(x)**3/cos(x)**3) == tan(x)**3 + assert trigsimp(sin(x)**10/cos(x)**10) == tan(x)**10 + + assert trigsimp(cos(x)/sin(x)) == 1/tan(x) + assert trigsimp(cos(x)**2/sin(x)**2) == 1/tan(x)**2 + assert trigsimp(cos(x)**10/sin(x)**10) == 1/tan(x)**10 + + assert trigsimp(tan(x)) == trigsimp(sin(x)/cos(x)) + @XFAIL def test_factorial_simplify(): # There are more tests in test_factorials.py. These are just to -- 1.6.0.4