Skip to content

Commit

Permalink
Fix other code to work with new Piecewise evaluation
Browse files Browse the repository at this point in the history
Change '.doit()' keyword for evaluating Piecewise objects from
'evaluate' to 'piecewise' and set other functions to use this to
avoid evaluation of Piecewise when required. Having no expr/cond pairs
is treated like having bools in the conditions.
  • Loading branch information
flacjacket committed Feb 27, 2012
1 parent c86dea6 commit 7fe8654
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 21 deletions.
6 changes: 4 additions & 2 deletions sympy/functions/elementary/piecewise.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ def __new__(cls, *args, **options):
# Allow explicit evaluate=False to stop evaluation of nested Piecewise
if evaluate is not False and (any([ isinstance(expr, Piecewise) for (expr, _) in ecs ]) or isinstance(oth, Piecewise)):
ecs, oth = cls._collapse_piecewise_args(ecs, oth)

# TODO: See Issue 3025
# When evaluate=False, remove False conds and move True cond to otherwise
# Should subs True for Basic True, False for Basic False when evaluate!=False
Expand All @@ -127,6 +126,9 @@ def __new__(cls, *args, **options):
ecs = new_ecs
else:
evaluate = True
# Having no expr/cond pairs should also trigger evaluation unless explicitly False
if len(ecs) == 0 and evaluate is not False:
return oth

new_args = ecs + [oth]
if evaluate:
Expand All @@ -152,7 +154,7 @@ def __new__(cls, *args, **options):
return Expr.__new__(cls, *new_args)

def doit(self, **hints):
evaluate = hints.get('evaluate', True)
evaluate = hints.get('piecewise', True)
if hints.get('deep', True):
args = [ arg.doit(**hints) for arg in self.args ]
else:
Expand Down
23 changes: 14 additions & 9 deletions sympy/functions/elementary/tests/test_piecewise.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def test_piecewise():

# Test doit
f_int = Piecewise((Integral(x,(x,0,1)), x < 1))
assert f_int.doit(evaluate=False) == Piecewise( (1.0/2.0, x < 1) )
assert f_int.doit(piecewise=False) == Piecewise( (1.0/2.0, x < 1) )

# Test differentiation
f = x
Expand Down Expand Up @@ -208,8 +208,8 @@ def test_piecewise_duplicate():
def test_doit():
p1 = Piecewise((x, x < 1), (x**2, -1 <= x), (x, 3 < x))
p2 = Piecewise((x, x < 1), (Integral(2 * x), -1 <= x), (x, 3 < x))
assert p2.doit(evaluate = False) == p1
assert p2.doit(deep = False, evaluate=False) == p2
assert p2.doit(piecewise = False) == p1
assert p2.doit(deep = False, piecewise=False) == p2

def test_piecewise_interval():
p1 = Piecewise((x, Interval(0,1).contains(x)), 0)
Expand All @@ -221,7 +221,7 @@ def test_piecewise_interval():
def test_piecewise_collapse():
p1 = Piecewise((x, x<0),(x**2,x>1))
p2 = Piecewise((p1,x<0),(p1,x>1))
assert p2.doit(evaluate = False) == Piecewise((x, x < 0), (x**2, 1 < x))
assert p2.doit(piecewise = False) == Piecewise((x, x < 0), (x**2, 1 < x))

p1 = Piecewise(Piecewise((x,x<0),1))
assert p1 == Piecewise(Piecewise((x,x<0),1))
Expand All @@ -246,15 +246,20 @@ def test_piecewise_series():
assert p1.nseries(x,n=2) == p2

def test_piecewise_evaluate():
# Forced evaluation gives otherwise
assert Piecewise(x).is_Piecewise
assert Piecewise(x, evaluate=True) == x
# Force evaluation=False when only given otherwise
assert Piecewise(x) == x
assert Piecewise(x, evaluate=False).is_Piecewise

# Forcing evaluation when no conds True gives otherwise
assert Piecewise((x, x < 1)).is_Piecewise
assert Piecewise((x, x < 1), evaluate=True) == S.NaN
assert Piecewise((x, x < 1), x**2).is_Piecewise
assert Piecewise((x, x < 1), x**2, evaluate=True) == x**2

# Explicit evaluate=False stops automatic evaluation
assert Piecewise((x, True), S.NaN) == x
assert Piecewise((x, True), S.NaN, evaluate=False) == Piecewise(x)
assert Piecewise((x, True), S.NaN, evaluate=False).is_Piecewise
assert Piecewise((x, True), S.NaN, evaluate=False) == Piecewise(x, evaluate=False)
assert Piecewise((x, x < 1), (0, True), S.NaN) == 0
assert Piecewise((x, x < 1), (0, True), S.NaN, evaluate=False) == Piecewise((x, x < 1), 0)

Expand All @@ -277,7 +282,7 @@ def test_piecewise_evaluate():
p1 = Piecewise((x, x < 1), x**2)
assert p1.is_Piecewise
assert p1.doit() == x**2
assert p1.doit(evaluate=False) == p1
assert p1.doit(piecewise=False) == p1

@XFAIL
def test_piecewise_evaluate_false():
Expand Down
6 changes: 2 additions & 4 deletions sympy/functions/special/hyper.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
"""Hypergeometric and Meijer G-functions"""

from sympy import S
from sympy.core.compatibility import iterable
from sympy.core.function import Function, ArgumentIndexError
from sympy.core.containers import Tuple
from sympy.core.sympify import sympify
from sympy.core.mul import Mul

# TODO should __new__ accept **options?
Expand Down Expand Up @@ -540,7 +538,7 @@ def get_period(self):
12*pi
"""
# This follows from slater's theorem.
from sympy import oo, ilcm, pi, Min, Mod
from sympy import oo, ilcm, pi, Mod
def compute(l):
# first check that no two differ by an integer
for i, b in enumerate(l):
Expand Down Expand Up @@ -688,7 +686,7 @@ def _eval_rewrite_as_nonrep(self, *args):

if big == small:
return small
return Piecewise((big, abs(x) > 1), (small, True))
return Piecewise((big, abs(x) > 1), small)

def _eval_rewrite_as_nonrepsmall(self, *args):
x, n = self.args[-1].extract_branch_factor(allow_half=True)
Expand Down
8 changes: 5 additions & 3 deletions sympy/integrals/meijerint.py
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,8 @@ def _eval_cond(cond):
""" Re-evaluate the conditions. """
if isinstance(cond, bool):
return cond
return _condsimp(cond.doit())
# Keep Piecewises from being evaluated
return _condsimp(cond.doit(**{'piecewise': False}))

####################################################################
# Now the "backbone" functions to do actual integration.
Expand Down Expand Up @@ -882,7 +883,8 @@ def lambda_s0(c1, c2):
And(Eq(arg(sigma), 0), Ne(arg(omega), 0))),
(lambda_s0(+1, sign(arg(sigma)))*lambda_s0(-1, sign(arg(sigma))),
And(Ne(arg(sigma), 0), Eq(arg(omega), 0))),
lambda_s0(sign(arg(omega)), sign(arg(sigma))))
lambda_s0(sign(arg(omega)), sign(arg(sigma))),
**{'evaluate': False})

_debug('Checking antecedents:')
_debug(' sigma=%s, s=%s, t=%s, u=%s, v=%s, b*=%s, rho=%s'
Expand Down Expand Up @@ -1548,7 +1550,7 @@ def tr(p): return [a + rho + 1 for a in p]
for expr, cond in res.exprcondpairs:
expr = _my_unpolarify(Add(*expand_mul(expr).as_coeff_add(x)[1]))
nargs.append((expr, cond))
if res.otherwise is not None:
if res.otherwise is not S.NaN:
expr = _my_unpolarify(Add(*expand_mul(res.otherwise).as_coeff_add(x)[1]))
nargs.append(expr)
cond = True
Expand Down
6 changes: 3 additions & 3 deletions sympy/integrals/tests/test_meijerint.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,9 +549,9 @@ def test_expint():
assert integrate(expint(1, x)*sin(x), (x, 0, oo), meijerg=True) == log(2)/2

def test_messy():
from sympy import (laplace_transform, Si, Ci, Shi, Chi, atan, Piecewise,
atanh, acoth, E1, besselj, acosh, asin, Ne, And, re,
fourier_transform, sqrt, Abs)
from sympy import (laplace_transform, Si, Shi, Chi, atan, Piecewise, acoth,
E1, besselj, acosh, asin, And, re, fourier_transform,
sqrt)
assert laplace_transform(Si(x), x, s) == ((pi - 2*atan(s))/(2*s), 0, True)

assert laplace_transform(Shi(x), x, s) == (acoth(s)/s, 1, True)
Expand Down

0 comments on commit 7fe8654

Please sign in to comment.