Comment #9 on issue 1358 by wflynny: (e*f*e*f).subs(e*f,f*e+h) fails if e*f is not commutative http://code.google.com/p/sympy/issues/detail?id=1358
Here's an updated version of the rewritten material. It crashed a lot of stuff not in the tests so I had to fix it. The patch: def _eval_subs(self, old, new): if self == old: return new if isinstance(old, FunctionClass): 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 return new * coeff_self/coeff_old # BEGIN: MY PATCH 6/11/09 l_temp = [] #temporary for i in terms_old: if i.is_Pow and type(i.exp) is Integer: for j in range(i.exp): l_temp.append(i.base) #convert (...h**2...) to (...h,h...) else: l_temp.append(i) terms_old=tuple(l_temp) l_temp = [] #temporary for i in terms_self: if i.is_Pow and type(i.exp) is Integer: for j in range(i.exp): l_temp.append(i.base) #convert (...h**2...) to (...h,h...) else: l_temp.append(i) terms_self=tuple(l_temp) 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._eval_subs(old, new) for x in self.args]) elif l2 < l1: self_set = [element for element in terms_self] old_set = [element for element in terms_old] len_old = len(terms_old) len_self = len(terms_self) temp = [] if len(old_set) < len(self_set): # Scan through list of self for i in range(len_self): # If a member of self matches the first in the set to be replaced # Scan through the list of to-be-replaced set and make sure the # Next terms all match. If they don't, break. if self_set[i] == old_set[0]: for j in range(len_old): if i+j < len_self and self_set[i+j] != old_set[j]: for k in range(i,i+j): temp.append(self_set[k]) break elif j == len_old - 1 and i+j < len_self and self_set[i+j] == old_set[j]: temp.append(new) for k in range(i+j+1,len_self): temp.append(self_set[k]) return Mul(coeff_self/coeff_old, *[element for element in temp])._eval_subs(old,new) elif j == len_old - 1 and i+j >= len_self: for k in range(i,len_self): temp.append(self_set[k]) break else: temp.append(self_set[i]) if temp != self_set: return Mul(coeff_self/coeff_old, *[element for element in temp]) return self.__class__(*[s._eval_subs(old, new) for s in self.args]) # END: MY PATCH ATTEMPT 6/11/09 The test: import sympy as sp from sympy import exp def subs_test(): # Define symbols t,w,x,y,z = sp.symbols('twxyz',commutative=False) # Start off easy a = x*y b = w*y*x # Add some noise c = w*x*y*z # Double d = x*y*x*y # Hard e = x*x*y # Hardest f = x*x*y*y # New Hardest g = w*x*y # Check other functions still work h = x+y i = x-y j = exp(x*y-z) k = x/y assert a.subs(x*y,t) == t; print 'test A passed' assert b.subs(x*y,t) == w*y*x; print 'test B passed' assert c.subs(x*y,t) == w*t*z; print 'test C passed' assert d.subs(x*y,t) == t**2; print 'test D passed' assert e.subs(x*y,t) == x*t; print 'test E passed' assert f.subs(x*y,t) == x*t*y; print 'test F passed' assert g.subs(x*y*z,t) == w*x*y; print 'test G passed' assert h.subs(x+y,t) == t; print 'test H passed' assert i.subs(x-y,t) == t; print 'test I passed' assert j.subs(x*y,t) == exp(t-z); print 'test J passed' assert k.subs(x,t) == t/y; print 'test K passed' print a,h; print 'printing functional' subs_test() -wflynny -- You received this message because you are listed in the owner or CC fields of this issue, or because you starred this issue. You may adjust your issue notification preferences at: http://code.google.com/hosting/settings --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "sympy-issues" group. To post to this group, send email to sympy-issues@googlegroups.com To unsubscribe from this group, send email to sympy-issues+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/sympy-issues?hl=en -~----------~----~----~----~------~----~------~--~---