Imagine we have a function like f(xy), how can one can take derivatives with respect to xy in python?
I tried to rename u=x*y and take derivative with respect to u, but it apparently doesn't work.
from sympy import symbols, diff
x, y, z = symbols('x y z', real=True)
f = 4*x*y + x*sin(z) + x**3 + z**8*y
u=x*y
diff(f, x)
and for one step further how can we do that if we don't have the exact definition of f(x*y)?
thank you.
Related
Suppose I have an eq1 such that
from sympy import symbols, solve, plot, Eq, diff
a, b, X, Y, U = symbols('a b X Y U')
eq1 = Eq(U, X**a*Y**b)
$U=(X^a)(Y^b)$
but When I run diff(eq1 , X)
the differential does not evaluate I merele just get the DU/DX symbol but not evaluated
I know I could defined the function as
U = X**a * Y**b
and easily compute diff(U)
but printing the U expression will not look nice.
I am surprised that you even get what you got. In general, algebraic operations on Eq are not supported.
>>> from sympy import Derivative
>>> ediff=lambda e, *x: e.func(Derivative(e.lhs,*x), e.rhs.diff(*x))
>>> ediff(eq1, X)
Eq(Derivative(U, X), X**a*Y**b*a/X)
I would like to evaluate the solution of a differential equation against some x_test
array
from sympy import *
init_printing()
from __future__ import division
from sympy import *
x, y, z, t = symbols('x y z t')
# Constants
C, R, u_rest = symbols('C R u_rest')
f, g, h = symbols('f g h', cls=Function)
solution = dsolve(C*Derivative(f(x), x) + (1/R)*(f(x) - u_rest ),f(x))
x_text = np.array(range(0,100))
but I fail
# 1. attempt with evalf(Not working)
solution.args[1].evalf(subs={x: 3.14})
# 2. attempt with lambdify(Not working)
lambdify(x,solution.args[1])(3.14)
What is the right way to do it?
If you look at your solution.args[1] value you will see that it is an expression of several variables, including x. It will not evaluate to a number until you supply values for all variables. Your first attempt doesn't fail, but you don't explain why it is not giving you what you hoped for:
>>> solution.args[1].evalf(subs={x: 3.14})
u_rest*(1.0 - exp((C1 - 3.14/R)/C))
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.
We know that the Fourier Transform of a derivative is
where k is the fourier variable. Explanation here
My question is, why doesn't sympy use this knowledge? For example:
from sympy import Function, symbols, fourier_transform, Derivative
f = Function('f')
x, k= symbols('x, k')
G = fourier_transform(Derivative(f(x), x, x) + f(x), x, k)
print(G)
This prints
FourierTransform(f(x), x, k) + FourierTransform(Derivative(f(x), x, x), x, k)
But I expected it to print (up to some factors of 2 pi i)
FourierTransform(f(x), x, k) + k**2 FourierTransform(f(x), x, k)
Is there a way to tell sympy it's save to make this simplification because I expect f(x) -> 0 as x goes to infinity?
If not, what would be the cleanest way to make the substitution?
The simple reason Sympy doesn't do this is that it's not implemented yet. As a workaround for now, you can manually replace the FourierTransform of the derivative with a multiplication:
from sympy import Wild, FourierTransform, Derivative
a, b, c = symbols('a b c', cls=Wild)
G.replace(
FourierTransform(Derivative(a, b, b), b, c),
c**2 * FourierTransform(a, b, c)
)
As far as I know, Sympy doesn't offer a pattern that matches an arbitrary number of arguments, so you can't have a single pattern that matches Derivative(f(x), x), Derivative(f(x), x, x), Derivative(f(x), x, x, x), and so on. You could get around that by using the function-function form of replace(), but if you know what order of derivative you're dealing with, it's probably simpler to just put in that many bs explicitly, as I did in the example.
I've been doing derivatives in sympy, and I didn't know how that would syntactically be written. I tried looking it up, but none of the solutions made sense. For example, if I'm trying to differentiate x**5 + y**2 + z**4 = 8xyz by computation, how would I do that? Would z be a symbol, or a function like in regular derivatives? Thank you.
For two variables you can use idiff.
In your case, the simplest way is to set x and y to be functions of z, like
x = Function('x')(z)
y = Function('y')(z)
Then normal diff(expr, z) will take the derivative correctly.
You commented you used idiff, here is the corresponding code for those who want to know:
from sympy import symbols, idiff, simplify
x, y, z = symbols('x y z')
ex = x**5 + y**2 + z**4 - 8*x*y*z
ex_d = simplify(idiff(ex,(x,y),z))
display(ex_d)
In idiff(ex,(x,y),z), (x,y) are the dependent variables, and z the variable the derivative is being taken with respect to.