Question

I'm experimenting with sympy and I've hit upon an issue I can't work out.

Using scipy I can write an expression and evaluate it for an array of x values as follows:

import scipy
xvals = scipy.arange(-100,100,0.1)
f = lambda x: x**2
f(xvals)

Using sympy I can write the same expression as follows:

import sympy
x = sympy.symbols('x')
g = x**2

I can evaluate this expression for a single value by doing the following:

g.evalf(subs={x:10})

However I can't work out how to evaluate it for an array of x values, like I did with scipy. How would I do this?

Was it helpful?

Solution

First of all, at the moment SymPy does not guarantee support for numpy arrays which is what you want in this case. Check this bug report http://code.google.com/p/sympy/issues/detail?id=537

Second, If you want to evaluate something numerically for many values SymPy is not the best choice (it is a symbolic library after all). Use numpy and scipy.

However, a valid reason to evaluate something numerically will be that deriving the expression to be evaluated was hard so you derive it in SymPy and then evaluate it in NumPy/SciPy/C/Fortran. To translate an expression to numpy just use

from sympy.utilities.lambdify import lambdify
func = lambdify(x, big_expression_containing_x,'numpy') # returns a numpy-ready function
numpy_array_of_results = func(numpy_array_of_arguments)

Check the docstring of lambdify for more details. Be aware that lambdify still has some issues and may need a rewrite.

And just as a side note, if you want to evaluate the expressions really many times, you can use the codegen/autowrap module from sympy in order to create fortran or C code that is wrapped and callable from python.

EDIT: An updates list of ways to do numerics in SymPy can be found on the wiki https://github.com/sympy/sympy/wiki/Philosophy-of-Numerics-and-Code-Generation-in-SymPy

OTHER TIPS

While the accepted answer makes it clear that the OP was looking for numerical evaluation, I'll still point out that one can also have symbolic evaluation by using symarray:

import sympy
xs = sympy.symarray('x', 10)
f = lambda x: x**2
f(xs)

yields

array([x_0**2, x_1**2, x_2**2, x_3**2, x_4**2, x_5**2, x_6**2, x_7**2,
       x_8**2, x_9**2], dtype=object)

Note that this also uses a numpy array internally, but one filled with sympy.Expressions.

Or you can do it via numpy.vectorize. I am using x, g, and xvals from the question body.

scalar_func = lambda xx: float(g.evalf(subs={x: xx}))
vector_func = numpy.vectorize(scalar_func)
vector_func(xvals) # returns a numpy array [10000.0, 9980.01, 9960.04, ...]

try

import sympy
x = sympy.symbols('x')
f = lambda x: x**2
print [f(k) for k in range(4)]

or you can also try

g = x**2
print [g.subs(x,k) for k in range(4)]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top