Reputation: 651
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
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
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