details:   http://hg.sympy.org/sympy/rev/7f83ede93315
changeset: 1791:7f83ede93315
user:      Riccardo Gori <[EMAIL PROTECTED]>
date:      Fri Oct 10 19:37:43 2008 +0200
description:
Subs speedup: _eval_subs should call _eval_subs instead of subs

Calling Basic.subs caused some overhead because it had to check len(*args) and
to sympify the args

Using our bench suite:

In [1]: from sympy.utilities import benchmarking

In [2]: benchmarking.main(['sympy/benchmarks'])

Before:
==============================
 *** BENCHMARKING RESULTS ***
==============================

bench_R1   |       301          ms  |  real(f(f(f(f(f(f(f(f(f(f(i/2)))))))))))
bench_R2   |       343          ms  |  Hermite polynomial hermite(15, y)
bench_R3   |            407     us  |  a = [bool(f==f) for _ in range(10)]
bench_R4   |              1.91  us  |  # we don't have Tuples
bench_R5   |        10.8        ms  |  blowup(L, 8); L=uniq(L)
bench_R6   |       225          ms  |  sum(trim((x+sin(i))/x+(x-sin(i))/x) for 
i in xrange(100))
bench_R7   |  38.7              s   |  [f.subs(x, random()) for _ in 
xrange(10**4)]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
bench_R8   |   5.64             s   |  right(x^2,0,5,10^4)
bench_R10  |        68.2        ms  |  v = [-pi,-pi+1/10..,pi]
bench_R11  |   1.52             s   |  a = [random() + random()*I for w in 
[0..1000]]
bench_S1   |  11.5              s   |  e=(x+y+z+1)**7;f=e*(e+1);f.expand()

After:
==============================
 *** BENCHMARKING RESULTS ***
==============================

bench_R1   |       302          ms  |  real(f(f(f(f(f(f(f(f(f(f(i/2)))))))))))
bench_R2   |       345          ms  |  Hermite polynomial hermite(15, y)
bench_R3   |            403     us  |  a = [bool(f==f) for _ in range(10)]
bench_R4   |              2.86  us  |  # we don't have Tuples
bench_R5   |        11          ms  |  blowup(L, 8); L=uniq(L)
bench_R6   |       222          ms  |  sum(trim((x+sin(i))/x+(x-sin(i))/x) for 
i in xrange(100))
bench_R7   |  30.1              s   |  [f.subs(x, random()) for _ in 
xrange(10**4)]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
bench_R8   |   4.9              s   |  right(x^2,0,5,10^4)
bench_R10  |        67.6        ms  |  v = [-pi,-pi+1/10..,pi]
bench_R11  |   1.54             s   |  a = [random() + random()*I for w in 
[0..1000]]
bench_S1   |  11.7              s   |  e=(x+y+z+1)**7;f=e*(e+1);f.expand()

diffs (180 lines):

diff -r 885e35e7f8a2 -r 7f83ede93315 sympy/core/add.py
--- a/sympy/core/add.py Fri Oct 10 23:53:33 2008 +0200
+++ b/sympy/core/add.py Fri Oct 10 19:37:43 2008 +0200
@@ -293,7 +293,7 @@
     def _eval_subs(self, old, new):
         if self == old: return new
         if isinstance(old, FunctionClass):
-            return self.__class__(*[s.subs(old, new) for s in self.args ])
+            return self.__class__(*[s._eval_subs(old, new) for s in self.args 
])
         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
@@ -304,8 +304,8 @@
                 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])
+                    return Add(new, coeff_self, -coeff_old, 
*[s._eval_subs(old, new) for s in ret_set])
+        return self.__class__(*[s._eval_subs(old, new) for s in self.args])
 
     @cacheit
     def extract_leading_order(self, *symbols):
diff -r 885e35e7f8a2 -r 7f83ede93315 sympy/core/function.py
--- a/sympy/core/function.py    Fri Oct 10 23:53:33 2008 +0200
+++ b/sympy/core/function.py    Fri Oct 10 19:37:43 2008 +0200
@@ -509,7 +509,7 @@
     def _eval_subs(self, old, new):
         if self==old:
             return new
-        return Derivative(self.args[0].subs(old, new), *self.args[1:], 
**{'evaluate': True})
+        return Derivative(self.args[0]._eval_subs(old, new), *self.args[1:], 
**{'evaluate': True})
 
     def matches(pattern, expr, repl_dict={}, evaluate=False):
         # this method needs a cleanup.
diff -r 885e35e7f8a2 -r 7f83ede93315 sympy/core/mul.py
--- a/sympy/core/mul.py Fri Oct 10 23:53:33 2008 +0200
+++ b/sympy/core/mul.py Fri Oct 10 19:37:43 2008 +0200
@@ -608,7 +608,7 @@
         if self == old:
             return new
         if isinstance(old, FunctionClass):
-            return self.__class__(*[s.subs(old, new) for s in self.args ])
+            return self.__class__(*[s._eval_subs(old, new) for s in self.args 
])
         coeff_self,terms_self = self.as_coeff_terms()
         coeff_old,terms_old = old.as_coeff_terms()
         if terms_self == terms_old: # (2*a).subs(3*a,y) -> 2/3*y
@@ -616,7 +616,7 @@
         l1, l2 = len(terms_self), len(terms_old)
         if l2 == 0:
             # if old is just a number, go through the self.args one by one
-            return Mul(*[x.subs(old, new) for x in self.args])
+            return Mul(*[x._eval_subs(old, new) for x in self.args])
         elif l2 < l1:
             # old is some something more complex, like:
             # (a*b*c*d).subs(b*c,x) -> a*x*d
@@ -626,8 +626,8 @@
             old_set = set(terms_old)
             if old_set < self_set:
                 ret_set = self_set - old_set
-                return Mul(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])
+                return Mul(new, coeff_self/coeff_old, *[s._eval_subs(old, new) 
for s in ret_set])
+        return self.__class__(*[s._eval_subs(old, new) for s in self.args])
 
     def _eval_nseries(self, x, x0, n):
         terms = [t.nseries(x, x0, n) for t in self.args]
diff -r 885e35e7f8a2 -r 7f83ede93315 sympy/core/power.py
--- a/sympy/core/power.py       Fri Oct 10 23:53:33 2008 +0200
+++ b/sympy/core/power.py       Fri Oct 10 19:37:43 2008 +0200
@@ -189,7 +189,7 @@
             coeff1,terms1 = old.args[0].as_coeff_terms()
             coeff2,terms2 = (self.exp * C.log(self.base)).as_coeff_terms()
             if terms1==terms2: return new ** (coeff1/coeff2) # 
(x**(2*y)).subs(exp(3*y*log(x)),z) -> z**(2/3*y)
-        return self.base.subs(old, new) ** self.exp.subs(old, new)
+        return self.base._eval_subs(old, new) ** self.exp._eval_subs(old, new)
 
     def as_powers_dict(self):
         return { self.base : self.exp }
diff -r 885e35e7f8a2 -r 7f83ede93315 sympy/core/relational.py
--- a/sympy/core/relational.py  Fri Oct 10 23:53:33 2008 +0200
+++ b/sympy/core/relational.py  Fri Oct 10 19:37:43 2008 +0200
@@ -135,8 +135,8 @@
     def rhs(self):
         return self._args[1]
 
-    def subs(self, old, new):
-        return self.__class__(self.lhs.subs(old, new), self.rhs.subs(old, new))
+    def _eval_subs(self, old, new):
+        return self.__class__(self.lhs._eval_subs(old, new), 
self.rhs._eval_subs(old, new))
 
 class Equality(Relational):
 
diff -r 885e35e7f8a2 -r 7f83ede93315 sympy/functions/elementary/exponential.py
--- a/sympy/functions/elementary/exponential.py Fri Oct 10 23:53:33 2008 +0200
+++ b/sympy/functions/elementary/exponential.py Fri Oct 10 19:37:43 2008 +0200
@@ -145,12 +145,12 @@
                 old_al = []
                 coeff2,terms2 = oarg.as_coeff_terms()
                 for a in arg.args:
-                    a = a.subs(old, new)
+                    a = a._eval_subs(old, new)
                     coeff1,terms1 = a.as_coeff_terms()
                     if terms1==terms2:
                         new_l.append(new**(coeff1/coeff2))
                     else:
-                        old_al.append(a.subs(old, new))
+                        old_al.append(a._eval_subs(old, new))
                 if new_l:
                     new_l.append(self.func(C.Add(*old_al)))
                     r = C.Mul(*new_l)
@@ -466,12 +466,12 @@
 # MrvLog is used by limit.py
 class MrvLog(log):
 
-    def subs(self, old, new):
+    def _eval_subs(self, old, new):
         old = sympify(old)
         if old==self.func:
             arg = self.args[0]
             new = sympify(new)
-            return new(arg.subs(old, new))
+            return new(arg._eval_subs(old, new))
         return self
 
 
diff -r 885e35e7f8a2 -r 7f83ede93315 sympy/functions/elementary/piecewise.py
--- a/sympy/functions/elementary/piecewise.py   Fri Oct 10 23:53:33 2008 +0200
+++ b/sympy/functions/elementary/piecewise.py   Fri Oct 10 19:37:43 2008 +0200
@@ -50,5 +50,5 @@
             return new
         new_pieces = []
         for start, end, f in self.args[1:]:
-            new_pieces.append( (start, end, f.subs(old,new)) )
+            new_pieces.append( (start, end, f._eval_subs(old,new)) )
         return Piecewise(self.args[0], *new_pieces)
diff -r 885e35e7f8a2 -r 7f83ede93315 sympy/polys/polynomial.py
--- a/sympy/polys/polynomial.py Fri Oct 10 23:53:33 2008 +0200
+++ b/sympy/polys/polynomial.py Fri Oct 10 19:37:43 2008 +0200
@@ -2074,10 +2074,10 @@
                 else:
                     return self.evaluate((old, new))
         elif not new.has_any_symbols(*symbols):
-            coeffs = [ sympify(coeff).subs(old, new) for coeff in self.coeffs ]
+            coeffs = [ sympify(coeff)._eval_subs(old, new) for coeff in 
self.coeffs ]
             return self.__class__((coeffs, self.monoms), *symbols, 
**self.flags)
 
-        result = self.as_basic().subs(old, new)
+        result = self.as_basic()._eval_subs(old, new)
 
         try:
             return self.__class__(result, *symbols, **self.flags)
diff -r 885e35e7f8a2 -r 7f83ede93315 sympy/series/order.py
--- a/sympy/series/order.py     Fri Oct 10 23:53:33 2008 +0200
+++ b/sympy/series/order.py     Fri Oct 10 19:37:43 2008 +0200
@@ -263,9 +263,9 @@
         if isinstance(old, C.Symbol) and old in self.symbols:
             i = list(self.symbols).index(old)
             if isinstance(new, C.Symbol):
-                return Order(self.expr.subs(old, new), 
*(self.symbols[:i]+(new,)+self.symbols[i+1:]))
-            return Order(self.expr.subs(old, new), 
*(self.symbols[:i]+self.symbols[i+1:]))
-        return Order(self.expr.subs(old, new), *self.symbols)
+                return Order(self.expr._eval_subs(old, new), 
*(self.symbols[:i]+(new,)+self.symbols[i+1:]))
+            return Order(self.expr._eval_subs(old, new), 
*(self.symbols[:i]+self.symbols[i+1:]))
+        return Order(self.expr._eval_subs(old, new), *self.symbols)
 
     def _sage_(self):
         #XXX: SAGE doesn't have Order yet. Let's return 0 instead.
diff -r 885e35e7f8a2 -r 7f83ede93315 sympy/simplify/cse_opts.py
--- a/sympy/simplify/cse_opts.py        Fri Oct 10 23:53:33 2008 +0200
+++ b/sympy/simplify/cse_opts.py        Fri Oct 10 19:37:43 2008 +0200
@@ -34,7 +34,7 @@
         if self==old:
             return new
         else:
-            return self.__class__(*[s.subs(old, new) for s in self.args ])
+            return self.__class__(*[s._eval_subs(old, new) for s in self.args 
])
 
 def sub_pre(e):
     """ Replace Add(x, Mul(NegativeOne(-1), y)) with Sub(x, y).

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sympy-commits" group.
To post to this group, send email to sympy-commits@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sympy-commits?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to