pure sympy: "loop of ufunc does not support argument 0 of type Mul which has no callable log method"

Question:

I am confused by sympy. First some setup. I entered the following into a python console

>>> import sympy as smp
>>> x, y = smp.symbols('x y', real=True)
>>> f = smp.log(x) + y

followed by

>>> smp.lambdify(x, f)(1)
y

which makes sense to me.

Then I went on to enter

>>> smp.lambdify(y, f)(1)
AttributeError: 'Symbol' object has no attribute 'log'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<lambdifygenerated-9>", line 2, in _lambdifygenerated
TypeError: loop of ufunc does not support argument 0 of type Symbol which has no callable log method

I did not think much of it, because it is plausible to me that just entering 1 can break things. But then

>>> smp.lambdify(y, f)(smp.sympify(1))
AttributeError: 'Symbol' object has no attribute 'log'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<lambdifygenerated-10>", line 2, in _lambdifygenerated
TypeError: loop of ufunc does not support argument 0 of type Symbol which has no callable log method

and now I am confused over why not evaluating the logarithm breaks things. I will have a good time for the next few days if I can successfully evaluate y at a number of my choosing and get a sympy object again, so advice from someone who resolved this / found an alternative way of achieving my goal would be much appreciated!

Asked By: midi3

||

Answers:

lambdify is mainly used to retrieve numerical data. Essentially, that error is telling you that you should always lambdify your expressions by specifying the appropriate amount of free symbols. So, your expressions contains two symbols, x, y, and you should generate a numerical function using both symbols: nf = lambdify([x, y], f), and then evaluate it as nf(x, 0). This, again will raise an error, because you asked lambdify to generate a numerical function to be evaluated with Numpy, which doesn’t support symbolic objects, like x. One way to solve it is to request lambdify to use SymPy as the evaluation module: nf = lambdify([x, y], f, modules="sympy"), and then evaluate it as nf(x, 1) to get log(x) + 1.

But, if you just want to get back a symbolic expression, then lambdify is overkill. Just substitute the numerical values into your symbolic expression. For example:

f.subs(y, 1)
# out: log(x) + 1
Answered By: Davide_sd

To complement the other answer, I’ll try to explain what happens with the lambdify and symbols.

lambdify of smp.log(x) + y creates a function like

 def f(x): 
     return np.log(x) + y

f(1) is then np.log(1)+y, where y is the globally defined symbol.

In the f(y) case, it’s trying to evaluate np.log(x) + 1. np.log(x) will be evaluated as np.log(np.array(x)). np.array(x) will be an object dtype array. np.log on an object dtype array tries to call a .log method for each element, hence the no callable log method error.

The same happens with sin and exp. Operators like + and * don’t give problems because symbols and numbers all have the corresponding __add__ and __mul__ methods. In other works, math on object dtype arrays is hit-or-miss, ok for operators, seldom working for ufunc like log.

Answered By: hpaulj
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.