Comment #8 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
Because I don't know how to actually patch the language, I'll just post the code I have written. I ended up using a chunk of yaukwankiu's code. Basically, I've just rewritten the _eval_subs method in the mul.py file. Here goes: 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 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: 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) else: temp.append(self_set[i]) 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 I also made the attached test file, which it passes. Here is the code for that so you don't have to download it: import sympy as sp def subs_test(): # Define symbols t,w,x,y,z = sp.symbols('twxyz',commutative=False) # Start off easy a = x*y b = 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 assert a.subs(x*y,t) == t; print 'test A passed' assert b.subs(x*y,t) == 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' subs_test() I hope this helps! -wflynny Attachments: test.py 658 bytes -- 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 -~----------~----~----~----~------~----~------~--~---