Issue 1161: Wrong result if calling Basic.subs() with a dictionary
http://code.google.com/p/sympy/issues/detail?id=1161

New issue report by hastebrot:
Under certain circumstances expr.subs(dictionary.items()) and
expr.subs(dictionary) called with SymPy 0.6.2 give different results.

Here is how I discovered this misbehavior.

     In [1]: from sympy import symbols, Eq, tsolve
     In [2]: K, L = symbols("KL")

Lets transpose an equation. That is what comes out with SymPy 0.6.0:

     In [2]: equation = Eq(K**0.4 * L, 3)
     In [3]: tsolve(equation, K)
     Out[3]: 15.5884572681199*(1/L)**2.5

But with SymPy 0.6.2 we get:

     In [2]: equation = Eq(K**0.4 * L, 3)
     In [3]: tsolve(equation, K)
     Out[3]: -15.5884572681199*(1/L)**2.5

SymPy 0.6.0 gives us the right result since:

     K**0.4 * L = 3                              [divide through L]
         K**0.4 = 3 * (L**-1)                    [power 2.5]
              K = (3**2.5) * (L**-2.5)           [evaluate 3**2.5]
              K = 15.5884572681199 * (L**-2.5)

Slightly changing the exponent, and both SymPy versions give us the same
result:

     In [4]: equation = Eq(K**0.5 * L, 3)
     In [5]: tsolve(equation, K)
     Out[5]: 9.0*(1/L)**2.0

I was tracking down this bug with pdb. Extracting the state of the variables
from calling tsolve(Eq(K**0.4 * L, 3), K) with SymPy 0.6.2. Here a code  
example
to reproduce the bug with a possible workaround.

     In [6]: from sympy import Symbol, Wild
     In [7]: x = Symbol("x", dummy=True)
     In [8]: a, b, c, d, e = [Wild(t, exclude=[x]) for t in "abcde"]
     In [9]: L = Symbol("L")

     In [10]: m = {a: L, b: 1, c: 0, d: 0.4, e: -3}
     In [11]: sol = (-c + (-e/a)**(1/d))/b

     In [12]: sol.subs(m)
     Out[12]: -15.5884572681199*(1/L)**2.5
     In [13]: sol.subs(m.items())
     Out[13]: 15.5884572681199*(1/L)**2.5

We get different results here! There is some trouble with the order in
which variables are substituted. Changing Basic._subs_list() so that it
prints out the substitution:

     def _subs_list(self, sequence):
         if not isinstance(sequence, (list, tuple)):
             raise TypeError("Not an iterable container")
         result = self
         print "result = %s" % result
         for old, new in sequence:
             result = result.subs(old, new)
             print "result.subs(%s, %3s) -> %s" % (old, new, result)
         return result

     # sol.subs(m)
     result = (-c_ + (-e_/a_)**(1/d_))/b_
     result.subs(d_, 0.4) -> (-c_ + I*e_**2.5*(1/a_)**2.5)/b_
     result.subs(a_,   L) -> (-c_ + I*e_**2.5*(1/L)**2.5)/b_
     result.subs(c_,   0) -> I*e_**2.5*(1/L)**2.5/b_
     result.subs(e_,  -3) -> -15.5884572681199*(1/L)**2.5/b_
     result.subs(b_,   1) -> -15.5884572681199*(1/L)**2.5

     # sol.subs(m.items())
     result = (-c_ + (-e_/a_)**(1/d_))/b_
     result.subs(b_,   1) -> -c_ + (-e_/a_)**(1/d_)
     result.subs(e_,  -3) -> -c_ + (3/a_)**(1/d_)
     result.subs(c_,   0) -> (3/a_)**(1/d_)
     result.subs(a_,   L) -> (3/L)**(1/d_)
     result.subs(d_, 0.4) -> 15.5884572681199*(1/L)**2.5

Now changing _subs_list(), so that sequence is delivered in reversed order:

     def _subs_list(self, sequence):
         ...
         for old, new in reversed(sequence):
         ...

     # sol.subs(m)
     result = (-c_ + (-e_/a_)**(1/d_))/b_
     result.subs(b_,   1) -> -c_ + (-e_/a_)**(1/d_)
     result.subs(e_,  -3) -> -c_ + (3/a_)**(1/d_)
     result.subs(c_,   0) -> (3/a_)**(1/d_)
     result.subs(a_,   L) -> (3/L)**(1/d_)
     result.subs(d_, 0.4) -> 15.5884572681199*(1/L)**2.5

     # sol.subs(m.items())
     result = (-c_ + (-e_/a_)**(1/d_))/b_
     result.subs(d_, 0.4) -> (-c_ + I*e_**2.5*(1/a_)**2.5)/b_
     result.subs(a_,   L) -> (-c_ + I*e_**2.5*(1/L)**2.5)/b_
     result.subs(c_,   0) -> I*e_**2.5*(1/L)**2.5/b_
     result.subs(e_,  -3) -> -15.5884572681199*(1/L)**2.5/b_
     result.subs(b_,   1) -> -15.5884572681199*(1/L)**2.5



Issue attributes:
        Status: New
        Owner: ----
        Labels: Type-Defect Priority-Medium

-- 
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 [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sympy-issues?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to