--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"sympy" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/sympy?hl=en
-~----------~----~----~----~------~----~------~--~---
Fix for Issue 801: Add._eval_subs() now uses sets + tests
Before:
In [2]: (a+b+c).subs(a+b,c)
Out[2]: a + b + c
In [3]: (c+b+exp(c+b)).subs(c+b,a)
Out[3]:
b + c
a + â¯
In [4]: (a+b+exp(a+b)).subs(a+b,c)
Out[4]:
c
a + b + â¯
After:
In [2]: (a+b+c).subs(a+b,c)
Out[2]: 2â
c
In [3]: (c+b+exp(c+b)).subs(c+b,a)
Out[3]:
a
a + â¯
In [4]: (a+b+exp(a+b)).subs(a+b,c)
Out[4]:
c
c + â¯
diff --git a/sympy/core/add.py b/sympy/core/add.py
--- a/sympy/core/add.py
+++ b/sympy/core/add.py
@@ -291,21 +291,20 @@
return S.One,(self,)
def _eval_subs(self, old, new):
- if self==old: return new
+ if self == old: return new
if isinstance(old, FunctionClass):
return self.__class__(*[s.subs(old, new) for s in self.args ])
- coeff1,factors1 = self.as_coeff_factors()
- coeff2,factors2 = old.as_coeff_factors()
- if factors1==factors2: # (2+a).subs(3+a,y) -> 2-3+y
- return new + coeff1 - coeff2
+ coeff_self, factors_self = self.as_coeff_factors()
+ coeff_old, factors_old = old.as_coeff_factors()
+ if factors_self == factors_old: # (2+a).subs(3+a,y) -> 2-3+y
+ return Add(new, coeff_self, -coeff_old)
if old.is_Add:
- l1,l2 = len(factors1),len(factors2)
- if l2<l1: # (a+b+c+d).subs(b+c,x) -> a+x+d
- for i in xrange(l1-l2+1):
- if factors2==factors1[i:i+l2]:
- factors1 = list(factors1)
- factors2 = list(factors2)
- return Add(*([coeff1-coeff2]+factors1[:i]+[new]+factors1[i+l2:]))
+ if len(factors_old) < len(factors_self): # (a+b+c+d).subs(b+c,x) -> a+x+d
+ self_set = set(factors_self)
+ old_set = set(factors_old)
+ if old_set < self_set:
+ ret_set = self_set - old_set
+ return Add(new, coeff_self, -coeff_old, *[s.subs(old, new) for s in ret_set])
return self.__class__(*[s.subs(old, new) for s in self.args])
@cacheit
diff --git a/sympy/core/tests/test_subs.py b/sympy/core/tests/test_subs.py
--- a/sympy/core/tests/test_subs.py
+++ b/sympy/core/tests/test_subs.py
@@ -136,10 +136,14 @@
assert (a**2 - c).subs(a**2 - c, d) == d
assert (a**2 - b - c).subs(a**2 - c, d) in [d - b, a**2 - b - c]
assert (a**2 - x - c).subs(a**2 - c, d) in [d - x, a**2 - x - c]
+ assert (a**2 - b - sqrt(a)).subs(a**2 - sqrt(a), c) == c - b
+ assert (a+b+exp(a+b)).subs(a+b,c) == c + exp(c)
+ assert (c+b+exp(c+b)).subs(c+b,a) == a + exp(a)
# this should work everytime:
e = a**2 - b - c
assert e.subs(Add(*e.args[:2]), d) == d + e.args[2]
+ assert e.subs(a**2 - c, d) == d - b
def test_subs_issue910():
assert (I*Symbol("a")).subs(1, 2) == I*Symbol("a")