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