This is in, thank you!

Vinzent

2010/2/23 Øyvind Jensen <jensen.oyv...@gmail.com>:
> Before, 'refine_Pow' would simplify (-1)**exp only if 'exp' as a whole could
> 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
> simply discarded.  Odd terms are collected to an even quantity and then
> discarded, possibly introducing a new term +1 in the exponent.  Finally,
> a number N is replaced with N % 2.
>
> We are now able to refine:
>
>        >>> refine_Pow((-1)**(x+y+z), Assume(x, Q.odd) & Assume(z, Q.odd))
>        (-1)**y
>        >>> refine_Pow((-1)**(x+y+2), Assume(x, Q.odd))
>        (-1)**(1 + y)
>        >>> refine((-1)**(x+3))
>        (-1)**(x+1)
>
> These examples are implemented as doctests and regular tests.
> ---
>  sympy/assumptions/refine.py            |   50 ++++++++++++++++++++++++++++++-
>  sympy/assumptions/tests/test_refine.py |   10 ++++++-
>  2 files changed, 57 insertions(+), 3 deletions(-)
>
> diff --git a/sympy/assumptions/refine.py b/sympy/assumptions/refine.py
> index a3ffd18..d81d817 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,25 @@ 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+2), Assume(x, Q.odd))
> +    (-1)**(1 + y)
> +    >>> refine_Pow((-1)**(x+3), True)
> +    (-1)**(1 + x)
> +
> +
>     """
>     from sympy.core import Pow, Rational
>     from sympy.functions import sign
> @@ -83,6 +95,40 @@ def refine_Pow(expr, assumptions):
>             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:
> +
> +                # For powers of (-1) we can remove
> +                #  - even terms
> +                #  - pairs of odd terms
> +                #  - a single odd term + 1
> +                #  - A numerical constant N can be replaced with mod(N,2)
> +
> +                coeff, terms = expr.exp.as_coeff_factors()
> +                terms = set(terms)
> +                even_terms = set([])
> +                odd_terms = set([])
> +                initial_number_of_terms = len(terms)
> +
> +                for t in terms:
> +                    if ask(t, Q.even, assumptions):
> +                        even_terms.add(t)
> +                    elif ask(t, Q.odd, assumptions):
> +                        odd_terms.add(t)
> +
> +                terms -= even_terms
> +                if len(odd_terms)%2:
> +                    terms -= odd_terms
> +                    new_coeff = (coeff + S.One) % 2
> +                else:
> +                    terms -= odd_terms
> +                    new_coeff = coeff % 2
> +
> +                if new_coeff != coeff or len(terms) < 
> initial_number_of_terms:
> +                    terms.add(new_coeff)
> +                    return expr.base**(Add(*terms))
> +
> +
>  def refine_exp(expr, assumptions):
>     """
>     Handler for exponential function.
> diff --git a/sympy/assumptions/tests/test_refine.py 
> b/sympy/assumptions/tests/test_refine.py
> index 58b24b8..59a6dc0 100644
> --- a/sympy/assumptions/tests/test_refine.py
> +++ b/sympy/assumptions/tests/test_refine.py
> @@ -12,7 +12,7 @@ def test_abs():
>     assert refine(abs(x**2), Assume(x, Q.real)) == x**2
>
>  def test_pow():
> -    x, y = symbols('x y')
> +    x, y, z = symbols('x y z')
>     assert refine((-1)**x, Assume(x, Q.even)) == 1
>     assert refine((-1)**x, Assume(x, Q.odd)) == -1
>     assert refine((-2)**x, Assume(x, Q.even)) == 2**x
> @@ -30,6 +30,14 @@ def test_pow():
>     assert refine(sqrt(1/x), Assume(x, Q.real)) != 1/sqrt(x)
>     assert refine(sqrt(1/x), Assume(x, Q.positive)) == 1/sqrt(x)
>
> +    # powers of (-1)
> +    assert refine((-1)**(x+y), Assume(x, Q.even)) == (-1)**y
> +    assert refine((-1)**(x+y+z), Assume(x, Q.odd)&Assume(z, Q.odd))==(-1)**y
> +    assert refine((-1)**(x+y+1), Assume(x, Q.odd))==(-1)**y
> +    assert refine((-1)**(x+y+2), Assume(x, Q.odd))==(-1)**(y+1)
> +    assert refine((-1)**(x+3)) == (-1)**(x+1)
> +
> +
>  def test_exp():
>     x = symbols('x')
>     assert refine(exp(pi*I*2*x), Assume(x, Q.integer)) == 1
> --
> 1.6.5
>
> --
> 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.
>
>

-- 
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