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

Reply via email to