Shiva
Shiva

Reputation: 651

Evaluating math equation in Python

I would like to evaluate a first derivative of a math equation. I can hard code the formula and get the results but how I can do the same with different user input formulae. I am using Anaconda Python 2.7.9

The following one works when I first compile the snippet of code (formula) and eval it later.

>>> import numpy as np
>>> import parse
>>> from sympy.mpmath import *
>>> from math import *

>>> f = "xv**2"  # x ** 2
>>> code = parser.expr(f).compile()
>>> for xv in np.arange(-2.0, 2.0, 0.1):
...     eval(code)
... 
4.0
3.6099999999999999
3.2399999999999993
2.8899999999999992
2.5599999999999987
...

But now I would like to pass the formula (f) to first derivative method (mpmath.diff) but is getting the following error message:

>>> for xv in np.arange(-2.0, 2.0, 0.1):
...     diff(lambda x: f, xv, 1)
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/Users/anaconda/lib/python2.7/site-packages/sympy/mpmath/calculus/differentiation.py", line 190, in diff
    v = ctx.difference(values, n) / norm**n
  File "/Users/anaconda/lib/python2.7/site-packages/sympy/mpmath/calculus/differentiation.py", line 27, in difference
    d += b * s[k]
TypeError: unsupported operand type(s) for +=: 'mpf' and 'str' 

But again by passing the hard-coded formula it is fine. See below.

>>> mp.pretty = True
>>> for xv in np.arange(-2.0, 2.0, 0.1):
...     diff(lambda x: x**2, xv, 1)    # Note x**2 formula and so 1st derivative will simply be 2*xv
... 
-4.0
-3.8
...
...

Upvotes: 2

Views: 1358

Answers (2)

asmeurer
asmeurer

Reputation: 91680

Since you are using SymPy, why not take the derivative of the expression symbolically?

>>> import sympy
>>> x = sympy.symbols('x')
>>> f = x**2
>>> d = sympy.diff(f, x)
>>> d
2*x

To evaluate these as functions on numpy arrays, use lambdify

>>> import numpy as np
>>> dfunc = sympy.lambdify(x, d)
>>> a = np.arange(-2.0, 2.0, 0.1)
>>> dfunc(a)
array([ -4.00000000e+00,  -3.80000000e+00,  -3.60000000e+00,
        -3.40000000e+00,  -3.20000000e+00,  -3.00000000e+00,
        -2.80000000e+00,  -2.60000000e+00,  -2.40000000e+00,
        -2.20000000e+00,  -2.00000000e+00,  -1.80000000e+00,
        -1.60000000e+00,  -1.40000000e+00,  -1.20000000e+00,
        -1.00000000e+00,  -8.00000000e-01,  -6.00000000e-01,
        -4.00000000e-01,  -2.00000000e-01,   3.55271368e-15,
         2.00000000e-01,   4.00000000e-01,   6.00000000e-01,
         8.00000000e-01,   1.00000000e+00,   1.20000000e+00,
         1.40000000e+00,   1.60000000e+00,   1.80000000e+00,
         2.00000000e+00,   2.20000000e+00,   2.40000000e+00,
         2.60000000e+00,   2.80000000e+00,   3.00000000e+00,
         3.20000000e+00,   3.40000000e+00,   3.60000000e+00,
         3.80000000e+00])

And to create a SymPy expression from an arbitrary use inputed expression, use sympify:

>>> sympy.sympify('x**2 + sin(x)')
x**2 + sin(x)

Upvotes: 1

Alex Martelli
Alex Martelli

Reputation: 882851

The first argument of mpmath.diff must be a function accepting a number and returning a number, not returning a string as you have it now. Given the rest of your code as shown, try instead

diff(lambda xv: eval(code), xv, 1)

Upvotes: 1

Related Questions