1

I want solve differential equation using sympy on Python3. My equation is relatively simple with two variables. However, the equation has log, power, and exp operators. Whether I use np.exp or sym.exp, it gives me one of the two errors below:

TypeError: 'module' object is not callable

AttributeError: 'Mul' object has no attribute 'log'
AttributeError: 'Mul' object has no attribute 'exp'

I am importing numpy and sympy separately. I am not sure if these two libraries are conflicting.

import math
import sympy as sym
from sympy import symbols, diff, exp, log, power
from sympy import *

data = [3, 33, 146, 227, 342, 351, 353, 444, 556, 571, 709, 759, 836, 860, 968, 1056, 1726, 1846, 1872, 1986, 2311, 2366, 2608, 2676, 3098, 3278, 3288, 4434, 5034, 5049, 5085, 5089, 5089, 5097, 5324, 5389,5565, 5623, 6080, 6380, 6477, 6740, 7192, 7447, 7644, 7837, 7843, 7922, 8738, 10089, 10237, 10258, 10491, 10625, 10982, 11175, 11411, 11442, 11811, 12559, 12559, 12791, 13121, 13486, 14708, 15251, 15261, 15277, 15806, 16185, 16229, 16358, 17168, 17458, 17758, 18287, 18568, 18728, 19556, 20567, 21012, 21308, 23063, 24127, 25910, 26770, 27753, 28460, 28493, 29361, 30085, 32408, 35338, 36799, 37642, 37654, 37915, 39715, 40580, 42015, 42045, 42188, 42296, 42296, 45406, 46653, 47596, 48296, 49171, 49416, 50145, 52042, 52489, 52875, 53321, 53443, 54433, 55381, 56463, 56485, 56560, 57042, 62551, 62651, 62661, 63732, 64103, 64893, 71043, 74364, 75409, 76057, 81542, 82702, 84566, 88682]
n = len(data)
tn = data[n-1]


b, c = sym.symbols('b c', real=True)

f = -(-n +sum(np.log(b*c*np.power(data,(c-1))*exp(-b*np.power(data,c)))))

diff(f,b)
diff(f,c)

Expecting to derive partial derivative of equation 'f' with respect to parameters 'b' and 'c'

This is not similar to What causes this error (AttributeError: 'Mul' object has no attribute 'cos') in Python? since the cause is not the namespace issue

13
  • Possible duplicate of What causes this error (AttributeError: 'Mul' object has no attribute 'cos') in Python? Commented May 19, 2019 at 17:09
  • Problem is you trying to apply numpy log and exp to a list of sympy objects. Those functions are meant to work with arrays of numbers. Don't mix numpy and sympy without a clear understanding of how they work. Commented May 19, 2019 at 17:12
  • @DeveshKumarSingh No, I read through that post before posting this. That was a namespace issue because of from sympy import * from numpy import * Commented May 19, 2019 at 17:12
  • @hpaulj I tried using sym.log and sym.power but that did not resolve the issue. Commented May 19, 2019 at 17:14
  • np.log is the culprit here, try playing around with it and see if you can get it to work Commented May 19, 2019 at 17:24

2 Answers 2

2

In an isympy session (similar to your imports), plus a np import:

In [12]: data = [1,2,3,4,5]                                                  

In [13]: np.power(data,c)                                                    
Out[13]: array([1, 2**c, 3**c, 4**c, 5**c], dtype=object)

In [14]: b*c*np.power(data,c)                                                
Out[14]: array([b*c, 2**c*b*c, 3**c*b*c, 4**c*b*c, 5**c*b*c], dtype=object)

So far these work. When numpy functions and operators encounter an object dtype array (non-numeric ones), they try to apply corresponding operators or methods of the objects. b and c as symbols do respond to ** and *.

But np.log applied to the object array fails with your error message. The elements of the array a sympy Mul objects:

In [17]: type(Out[14][0])                                                    
Out[17]: sympy.core.mul.Mul
In [18]: Out[14][0].log()                                                    
---------------------------------------------------------------------------
AttributeError: 'Mul' object has no attribute 'log'

Same for np.exp.

math.log expects a number, so it won't work with array or the sympy objects either.

sympy.log(Out[14][0]) works - the argument is a sympy Mul. But it doesn't work with Out[14] which a numpy array.

===

I know numpy a lot better than sympy. But I was able to get this sequence of calculations to work:

In [24]: [d**c for d in data]     # list comprehension                                                
Out[24]: 
⎡    c   c   c   c⎤
⎣1, 2 , 3 , 4 , 5 ⎦

In [25]: [b*c*num**c for num in data]                                        
Out[25]: 
⎡      c       c       c       c    ⎤
⎣b⋅c, 2 ⋅b⋅c, 3 ⋅b⋅c, 4 ⋅b⋅c, 5 ⋅b⋅c⎦

In [26]: [log(b*c*num**c) for num in data]                                   
Out[26]: 
⎡             ⎛ c    ⎞     ⎛ c    ⎞     ⎛ c    ⎞     ⎛ c    ⎞⎤
⎣log(b⋅c), log⎝2 ⋅b⋅c⎠, log⎝3 ⋅b⋅c⎠, log⎝4 ⋅b⋅c⎠, log⎝5 ⋅b⋅c⎠⎦

In [27]: sum([log(b*c*num**c) for num in data])                              
Out[27]: 
              ⎛ c    ⎞      ⎛ c    ⎞      ⎛ c    ⎞      ⎛ c    ⎞
log(b⋅c) + log⎝2 ⋅b⋅c⎠ + log⎝3 ⋅b⋅c⎠ + log⎝4 ⋅b⋅c⎠ + log⎝5 ⋅b⋅c⎠

sympy.sum expects an iterable, which this list qualifies.

Now I can do the sympy.diff

In [29]: diff(sum([log(b*c*num**c) for num in data]),b)                      
Out[29]: 
5
─
b

In [30]: diff(sum([log(b*c*num**c) for num in data]),c)                      
Out[30]: 
     -c ⎛ c               c  ⎞    -c ⎛ c               c  ⎞    -c ⎛ c      
1   5  ⋅⎝5 ⋅b⋅c⋅log(5) + 5 ⋅b⎠   4  ⋅⎝4 ⋅b⋅c⋅log(4) + 4 ⋅b⎠   3  ⋅⎝3 ⋅b⋅c⋅l
─ + ────────────────────────── + ────────────────────────── + ─────────────
c              b⋅c                          b⋅c                          b⋅

         c  ⎞    -c ⎛ c               c  ⎞
og(3) + 3 ⋅b⎠   2  ⋅⎝2 ⋅b⋅c⋅log(2) + 2 ⋅b⎠
───────────── + ──────────────────────────
c                          b⋅c    

[log(item) for item in Out[14]] produces the same output as Out[26]. Out[14] is simply the object array equivalent of the Out[25] list.

Sign up to request clarification or add additional context in comments.

3 Comments

sympy.log works but it returns the error that you reported above when you combine it with a power of an array. Is there an alternative method to compute power of an array that is compatible with sympy?
sympy.log is designed to work with sympy objects, but does not work with numpy arrays. Why should it?
Thank you for helping me with this problem. Using list comprehension solves the problem. Here is my revised code that works: f = -(-n +sum([sym.log(bc*(num**(c-1))*sym.exp(-b*(num*c))) for num in data]))
0

As per @hpaulj suggestion, I was able to solve this by using list comprehension. The working code is below:

f = -(-n +sum([sym.log(b*c*(num**(c-1))*sym.exp(-b*(num**c))) for num in data]))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.