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.

Reply via email to