I'd like to calculate the derivative, then solve for when it is zero.
I am using the sympy module to do this.
r = somefunction(x1,x2)
Using this function, I'd like to be able to call these two matrices.
r_grad = [r.diff(x1), r.diff(x2)]
r_hess = [[r.diff(x1,x1), r.diff(x1,x2)],[r.diff(x2,x1), r.diff(x2,x2)]]
I'd then like to solve for when r_grad[0] and r_grad[1] == 0, and plug that into the hessian.
How can I make these .diff() symbols callable?
SymPy has a lambdify module for these purposes:
from sympy.utilities.lambdify import lambdify
func = lambdify((x1, x2), r.diff(x1))
func(1, 2) # evaluate the function efficiently at (1, 2)
Related
I am using SymPy for analytical handling of variables (e.g. matrix multiplication etc.).
After doing so, I end up with a new SymPy expression which I would like to use for plotting with Matplotlib. So far, my only way to do so, was to print the SymPy expression and paste it into a newly defined function manually.
How can I directly convert the SymPy expression into a function for numerical interpretation without relying on copying and pasting?
A minimal working example is the following:
import sympy as sp
import matplotlib.pyplot as plt
import numpy as np
sp.var('x A B') # x will later be the variable, A and B will be constants
temp = A*x+B # intermediate calculations
f = temp*x # function in reality, it will be more complicated.
print(f) # I printed f in order to find the expression and copy-pasting it into the function below.
def func(x,A,B):
return x*(A*x + B) # This statement was copy-pasted. This line should be changed, s.t. copy-pasting is not necessary!
#Now we can handle the function numerically for plotting (using matplotlib and numpy)
xspace = np.linspace(0,5)
plt.plot(xspace,func(x=xspace,A=1,B=2))
Sympy’s lambdify exists exactly for this. Just replace your definition of func with:
func = sp.lambdify((x,A,B),f)
I need to manipulate a function symbolically, and then numerically integrate the function. How do I correctly use my expression f in the integrand function. How do I use lambdify correctly if that is even the sensible way to do it? Many thanks.
from sympy import *
import scipy.integrate as integrate
r = symbols('r') #define symbol
f = diff(r*r) #carry out symbolic manipulation
def integrand(x): #define function to integrate
return lambdify(x, f) #swap variable x into f
result = integrate.quad(integrand, 0, 5) #integrate numerically
print(result)
lambdify returns a function object, there is no need to use a wrapper function. Also note that the first argument of lambdify should be a tuple of variables representing sympy symbols (in this case, r) that are included in the sympy expression (in this case, f_sym) provided as its second argument.
import sympy as sp
from scipy.integrate import quad
r = sp.symbols('r')
f_sym = sp.diff(r*r, r)
f_lam = sp.lambdify(r, f_sym)
result = quad(f_lam, 0, 5)
print(result)
(25.0, 2.7755575615628914e-13)
Using python 2.7 with PyCharm Community Edition 2016.2.3 + Anaconda distribution.
I have an input similar to :
from sympy import *
x = symbols('x')
f = cos(x)
print (f.subs(x, 25))
The output is cos(25), . Is there a way to evaluate trigonometric identities such as sin/cos, at a certain angle ? I've tried cos(degrees(x)), but nothing differs. Am I missing some crucial part of documentation or there really isn't a way to do this ? Ty for your help :)
Perform a numerical evaluation using function N:
>>> from sympy import N, symbols, cos
>>> x = symbols('x')
>>> f = cos(x)
>>> f.subs(x, 25)
cos(25)
>>> N(f.subs(x, 25)) # evaluate after substitution
0.991202811863474
To make the computation in degrees, convert the angle to radians, using mpmath.radians, so the computation is performed on a rad value:
>>> import mpmath
>>> f.subs(x, mpmath.radians(25))
0.906307787036650
Importing with * (wildcard imports) isn't a very good idea. Imagine what happens if you equally did from math import *, then one of the cos functions from both modules will be out in the wild.
See the PEP 8 guideline on imports.
I am trying to calculate the definite integral of a function with multiple variables over just one variable in scipy.
This is kind of like what my code looks like-
from scipy.integrate import quad
import numpy as np
def integrand(x,y):
return x*np.exp(x/y)
quad(integrand, 1,2, args=())
And it returns this type error:
TypeError: integrand() takes exactly 2 arguments (1 given)
However, it works if I put a number into args. But I don't want to, because I want y to remain as y and not a number. Does anyone know how this can be done?
EDIT: Sorry, don't think I was clear. I want the end result to be a function of y, with y still being a symbol.
Thanks to mdurant, here's what works:
from sympy import integrate, Symbol, exp
from sympy.abc import x
y=Symbol('y')
f=x*exp(x/y)
integrate(f, (x, 1, 2))
Answer:
-(-y**2 + y)*exp(1/y) + (-y**2 + 2*y)*exp(2/y)
You probably just want the result to be a function of y right?:
from scipy.integrate import quad
import numpy as np
def integrand(x,y):
return x*np.exp(x/y)
partial_int = lambda y: quad(integrand, 1,2, args=(y,))
print partial_int(5)
#(2.050684698584342, 2.2767173686148355e-14)
The best you can do is use functools.partial, to bind what arguments you have for the moment. But one fundamentally cannot numerically integrate a definite integral if you havnt got the entire domain specified yet; in that case the resulting expression will necessarily still contain symbolic parts, so the intermediate result isn't numerical.
(Assuming that you are talking about computing the definite integral over x given a specific, fixed value of y.)
You could use a lambda:
quad(lambda x:integrand(x, 10), 1, 2, args=())
or functools.partial():
quad(functools.partial(integrand, y=10), 1, 2, args=())
from scipy.integrate import quad
import numpy as np
def integrand(x,y):
return x*np.exp(x/y)
vec_int = np.vectorize(integrand)
y = np.linspace(0, 10, 100)
vec_int(y)
Is there a built-in Numpy function to convert a complex number in polar form, a magnitude and an angle (degrees) to one in real and imaginary components?
Clearly I could write my own but it seems like the type of thing for which there is an optimised version included in some module?
More specifically, I have an array of magnitudes and an array of angles:
>>> a
array([1, 1, 1, 1, 1])
>>> b
array([120, 121, 120, 120, 121])
And what I would like is:
>>> c
[(-0.5+0.8660254038j),(-0.515038074+0.8571673007j),(-0.5+0.8660254038j),(-0.5+0.8660254038j),(-0.515038074+0.8571673007j)]
There isn't a function to do exactly what you want, but there is angle, which does the hardest part. So, for example, one could define two functions:
def P2R(radii, angles):
return radii * exp(1j*angles)
def R2P(x):
return abs(x), angle(x)
These functions are using radians for input and output, and for degrees, one would need to do the conversion to radians in both functions.
In the numpy reference there's a section on handling complex numbers, and this is where the function you're looking for would be listed (so since they're not there, I don't think they exist within numpy).
There's an error in the previous answer that uses numpy.vectorize - cmath.rect is not a module that can be imported. Numpy also provides the deg2rad function that provides a cleaner piece of code for the angle conversion. Another version of that code could be:
import numpy as np
from cmath import rect
nprect = np.vectorize(rect)
c = nprect(a, np.deg2rad(b))
The code uses numpy's vectorize function to return a numpy style version of the standard library's cmath.rect function that can be applied element wise across numpy arrays.
I used cmath with itertools:
from cmath import rect,pi
from itertools import imap
b = b*pi/180 # convert from deg to rad
c = [x for x in imap(rect,a,b)]
import numpy as np
import cmath.rect
nprect = np.vectorize(rect)
c = nprect(a,b*np.pi/180)
tom10 answer works fine... you can also expand the Euler's formula to:
def P2R(A, phi):
return A * ( np.cos(phi) + np.sin(phi)*1j )