On Feb 22, 2010, at 12:43 PM, Øyvind Jensen wrote: > Before, 'refine_Pow' would simplify (-1)**exp only if 'exp' as a whole couold > be determined as even or odd. A doctest like, > > >>> refine_Pow((-1)**(x+y), Assume(x, Q.even)) > (-1)**y > > would fail. This patch fixes that by treating powers of S.NegativeOne as > a special case. Every term in the exponent is checked, and even terms are > discarded. After the even terms have been discarded, we check the remaining > terms for pairs that are even. This fixes another pair of doctests: > > >>> refine_Pow((-1)**(x+y+z+1), Assume(x, Q.odd)) > (-1)**(y + z) > >>> refine_Pow((-1)**(x+y+z), Assume(x, Q.odd) & Assume(z, Q.odd)) > (-1)**y > > These doctests are included in the patch. > --- > sympy/assumptions/refine.py | 41 +++++++++++++++++++++++++++++++++++++++-- > 1 files changed, 39 insertions(+), 2 deletions(-) > > diff --git a/sympy/assumptions/refine.py b/sympy/assumptions/refine.py > index a3ffd18..42d58c7 100644 > --- a/sympy/assumptions/refine.py > +++ b/sympy/assumptions/refine.py > @@ -1,4 +1,4 @@ > -from sympy.core import S, Symbol, sympify > +from sympy.core import S, Symbol, sympify, Add > from sympy.utilities.source import get_class > from sympy.assumptions import Q, ask > from sympy.logic.boolalg import fuzzy_not > @@ -63,13 +63,23 @@ def refine_Pow(expr, assumptions): > >>>> from sympy import Symbol, Assume, Q >>>> from sympy.assumptions.refine import refine_Pow > - >>> from sympy.abc import x > + >>> from sympy.abc import x,y,z >>>> refine_Pow((-1)**x, Assume(x, Q.real)) >>>> refine_Pow((-1)**x, Assume(x, Q.even)) > 1 >>>> refine_Pow((-1)**x, Assume(x, Q.odd)) > -1 > > + For powers of -1, even parts of the exponent can be simplified: > + > + >>> refine_Pow((-1)**(x+y), Assume(x, Q.even)) > + (-1)**y > + >>> refine_Pow((-1)**(x+y+z), Assume(x, Q.odd) & Assume(z, Q.odd)) > + (-1)**y > + >>> refine_Pow((-1)**(x+y+z+1), Assume(x, Q.odd)) > + (-1)**(y + z) > + > + > """ > from sympy.core import Pow, Rational > from sympy.functions import sign > @@ -82,6 +92,33 @@ def refine_Pow(expr, assumptions): > if isinstance(expr.exp, Rational): > if type(expr.base) is Pow: > return abs(expr.base.base) ** (expr.base.exp * expr.exp) > + if expr.base is S.NegativeOne: > + if expr.exp.is_Add: > + > + # see if we can remove single terms in the exponent > + terms = expr.exp.args > + removable_terms = set([]) > + for t in terms: > + if ask(t, Q.even, assumptions): > + removable_terms.add(t) > + if len(removable_terms) > 0: > + terms = list(set(terms)-removable_terms) > + Could you add a test for this part? Just a regular test should be fine (i.e., in the test_refine.py file). Also, couldn't you optimize this by skipping over terms in the outer loop if they have already been tagged for removal? > + # see if we can remove terms pairwise > + len_args = len(terms) > + removable_terms.clear() > + for i in range(0, len_args-1): > + for j in range(i+1, len_args): > + if ask(terms[i]+terms[j], Q.even, assumptions): > + removable_terms.add(terms[i]) > + removable_terms.add(terms[j]) > + > + if len(removable_terms) > 0: > + terms = list(set(terms)-removable_terms) > + > + if len(expr.exp.args) > len(terms): > + return expr.base**(Add(*terms)) > + > > def refine_exp(expr, assumptions): > """ > -- > 1.6.5 How about removing pairs of odd terms too? It would make things easier on the nested for loop if collect them first.
Aaron Meurer -- You received this message because you are subscribed to the Google Groups "sympy-patches" group. To post to this group, send email to sympy-patc...@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.