Define a function that calculates the partial derivative of another function - python

I have learned how to automatically find the partial derivative of a function with sympy. My problem is, I need to define a new function that returns the partial derivative of the other function.
from sympy import Symbol, Derivative
y= Symbol('y')
function = y ** 2
deriv = Derivative(function, y).doit()
def func(y):
return deriv
Something like that. Hope you all understood. Thanks!

So y is another function as in predefined like y = Symbol('x') ** 2? I believe your function need another input.
x = Symbol('x')
y = x ** 2
def func(function, symbol):
deriv = Derivative(function, symbol).doit()
return deriv
derivative = func(y, x)
You can't do it without specifying symbol - especially since this is partial derivative you need to tell which symbol it's trying to derive against.

Related

Getting the derivative of a function as a function with sympy (for later evaluation and substitution)

I want to work with generic functions as long as possible, and only substitute functions at the end.
I'd like to define a function as the derivative of another one, define a generic expression with the function and its derivative, and substitute the function at the end.
Right now my attempts is as follows, but I get the error 'Derivative' object is not callable:
from sympy import Function
x, y, z = symbols('x y z')
f = Function('f')
df = f(x).diff(x) # <<< I'd like this to be a function of dummy variable x
expr = f(x) * df(z) + df(y) + df(0) # df is unfortunately not callable
# At the end, substitute with example function
expr.replace(f, Lambda(X, cos(X))) # should return: -cos(x)*sin(z) - sin(y) - sin(0)
I think I got it to work with integrals as follows:
I= Lambda( x, integrate( f(y), (y, 0, x))) but that won't work for derivatives.
If that helps, I'm fine restricting myself to functions of a single variable for now.
As a bonus, I'd like to get this to work with any combination (products, derivatives, integrals) of the original function.
It's pretty disappointing that f.diff(x) doesn't work, as you say. Maybe someone will create support it sometime in the future. In the mean time, there are 2 ways to go about it: either substitute x for your y, z, ... OR lambdify df.
I think the first option will work more consistently in the long run (for example, if you decide to extend to multivariate calculus). But the expr in second option is far more natural.
Using substitution:
from sympy import *
x, y, z = symbols('x y z')
X = Symbol('X')
f = Function('f')
df = f(x).diff(x)
expr = f(x) * df.subs(x, z) + df.subs(x, y) + df.subs(x, 0)
print(expr.replace(f, Lambda(X, cos(X))).doit())
Lambdifying df:
from sympy import *
x, y, z = symbols('x y z')
X = Symbol('X')
f = Function('f')
df = lambda t: f(t).diff(t) if isinstance(t, Symbol) else f(X).diff(X).subs(X, t)
expr = f(x) * df(z) + df(y) + df(0)
print(expr.replace(f, Lambda(X, cos(X))).doit())
Both give the desired output.

Having trouble with using sympy subs command when trying to solve a function at an x value of 0

I have a function [ -4*x/sqrt(1 - (1 - 2*x^2)^2) + 2/sqrt(1 - x^2) ] that I need to evaluate at x=0. However, whenever you graph this function, for some interval of y there are many y-values at x=0. This leads me to think that the (subs) command can only return one y-value. Any help or elaboration on this? Thank you!
Here's my code if it might help:
x = symbols('x')
f = 2*asin(x) # f(x) function
g = acos(1-2*x**2) # g(x) function
eq = diff(f-g) # evaluating the derivative of f(x) - g(x)
eq.subs(x, 0) # substituting 0 for x in the derivative of f(x) - g(x)
After I run the code, it returns NaN, which I assume is because substituting in 0 for x returns not a single number, but a range of numbers.
Here is the graph of the function to be evaluated at x=0:
You should always give SymPy as many assumptions as possible. For example, it can't pull an x**2 out of a sqrt because it thinks x is complex.
A factorization an then a simplification solves the problem. SymPy can't do L'Hopital on eq = A + B since it does not know that both A and B converge. So you have to guide it a little by bringing the fractions together and then simplifying:
from sympy import *
x = symbols('x', real=True)
f = 2*asin(x) # f(x) function
g = acos(1-2*x**2) # g(x) function
eq = diff(f-g) # evaluating the derivative of f(x) - g(x)
eq = simplify(factor(eq))
print(eq)
print(limit(eq, x, 0, "+"))
print(limit(eq, x, 0, "-"))
Outputs:
(-2*x + 2*Abs(x))/(sqrt(1 - x**2)*Abs(x))
0
4
simplify, factor and expand do wonders.

How to put an integral in a function in python/matplotlib

So pretty much, I am aiming to achieve a function f(x)
My problem is that my function has an integral in it, and I only know how to construct definite integrals, so my question is how does one create an indefinite integral in a function (or there may be some other method I am currently unaware of)
My function is defined as :
(G is gravitational constant, although you can leave G out of your answer for simplicity, I'll add it in my code)
Here is the starting point, but I don't know how to do the integral portion
import numpy as np
def f(x):
rho = 5*(1/(1+((x**2)/(3**2))))
function_result = rho * 4 * np.pi * x**2
return function_result
Please let me know if I need to elaborate on something.
EDIT-----------------------------------------------------
I made some major progress, but I still have one little error.
Pretty much, I did this:
from sympy import *
x = Symbol('x')
rho = p0()*(1/(1+((x**2)/(rc()**2))))* 4 * np.pi * x**2
fooply = integrate(rho,x)
def f(rx):
function_result = fooply.subs({x:rx})
return function_result
Which works fine when I plug in one number for f; however, when I plug in an array (as I need to later), I get the error:
raise SympifyError(a)
sympy.core.sympify.SympifyError: SympifyError: [3, 3, 3, 3, 3]
(Here, I did print(f([3,3,3,3,3]))). Usually, the function returns an array of values. So if I did f([3,2]) it should return [f(3),f(2)]. Yet, for some reason, it doesn't for my function....
Thanks in advance
how about:
from sympy import *
x, p0, rc = symbols('x p0 rc', real=True, positive=True)
rho = p0*(1/(1+((x**2)/(rc))))* 4 * pi * x**2
fooply = integrate(rho,x)/x
rho, fooply
(4*pi*p0*x**2/(1 + x**2/rc),
4*pi*p0*rc*(-sqrt(rc)*atan(x/sqrt(rc)) + x)/x)
fooply = fooply.subs({p0: 2.0, rc: 3.0})
np_fooply = lambdify(x, fooply, 'numpy')
print(np_fooply(np.array([3,3,3,3,3])))
[ 29.81247362 29.81247362 29.81247362 29.81247362 29.81247362]
To plug in an array to a SymPy expression, you need to use lambdify to convert it to a NumPy function (f = lambdify(x, fooply)). Just using def and subs as you have done will not work.
Also, in general, when using symbolic computations, it's better to use sympy.pi instead of np.pi, as the former is symbolic and can simplify. It will automatically be converted to the numeric pi by lambdify.

How to find root of two implicit functions in Python, without using fsolve for the set of equations

I am dealing with a set of several non-linear equations that I was able to reduce analytically to set of two implicit equations with two variables. Now I wish to find roots of those equations using Brent's method. I would like to pass one function as an argument to another and solve the equation for variable 2 depending on every variable 1.
In mathematical terms I wish to solve: f(x,y) and g(x,y) in this way f(x,g(x)).
Simplify example of what I wish to do can be presented here.
Instead of:
import scipy.optimize
from scipy.optimize import fsolve
def equations(p):
y,z = p
f1 = -10*z + 4*y*z - 5*y + 4*z**2 - 7
f2 = 2*y*z + 5*y - 3
return (f1,f2)
and solve it by:
y, z = fsolve(equations,[0,19])
I wish to write something like that:
def func2(x, y):
f2= 2*y*x + 5*y - 3
return brentq(f2, -5, 5)
def func(x,y):
y = func2(x,y)
return -10*x + 4*x*y - 5*y + 4*x**2 - 7
sol, = brentq(lambda x: func(x, func2), -5, 5)
I wish to ask for help in how to pass a function as an argument for this particular purpose and explain what am I doing wrong. I am new to Python and maybe there is a better way to ensure precise solution to my problem.

Take Python Function and Generate All Derivatives

I have a python function with variable number of arguments:
F(x1, x2, ... , xN)
I want to automatically generate N functions representing the derivatives of F with respect to each argument.
F'_1 = dF/dx1
F'_2 = dF/dx2
...
F'_N = dF/dxN
For example, I be able to give both
F(x1) = sin(x1)
and
F(x1, x2) = sin(x1) * cos(x2)
and get all the derivatives automatically.
Edit2:
If function F was 2 variable (fixed number of arguments), I could use
def f(x,y):
return sin(x)*cos(y)
from sympy import *
x, y = symbols('x y')
f_1 = lambdify((x,y), f(x,y).diff(x))
The trick is to use inspect.getargspec to get the names of all the arguments to the function. After that, it's a simple list comprehension:
import inspect
from sympy import *
def get_derivatives(func):
arg_symbols = symbols(inspect.getargspec(func).args)
sym_func = func(*arg_symbols)
return [lambdify(arg_symbols, sym_func.diff(a)) for a in arg_symbols]
For example:
def f(x, y):
return sin(x)*cos(y)
all_derivatives = get_derivatives(f)

Categories