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.
Related
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.
Consider this simple MWE:
from sympy.solvers.diophantine import diophantine
from sympy import symbols
x, y, z = symbols("x, y, z", integer=True)
diophantine(x*(2*x + 3*y - z))
This outputs:
[(t_0, t_1, 2*t_0 + 3*t_1), (0, n1, n2)]
If I want to create instances of these solutions I would like, for
example, to able to substitute integer values into t_0 and t_1. How
can you do that?
I tried e.g.
diof = diophantine(x*(2*x + 3*y - z))
list(diof)[0][0].subs(t_0, 0)
but that gives
NameError: name 't_0' is not defined
t_0 is not defined as a Python variable. You can create the Python variable in a couple of different ways:
from sympy import symbols
t_0 = symbols("t_0")
Alternatively, you can capture the symbol generated from your SymPy calculation into a Python variable. Here's one way:
diofl = list(diof) # Assuming that diof is as you had defined it.
t_0 = diofl[1][0] # Presuming that this is the part of diofl
# that contains the correct symbol. Print
# diofl[1][0] to be sure!
After that, you can then use t_0 as an argument of the subs() method.
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.
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.
The full mathematical problem is here.
Briefly I want to integrate a function with a double integral. The inner integral has boundaries 20 and x-2, while the outer has boundaries 22 and 30.
I know that with Scipy I can compute the double integral with scipy.integrate.nquad. I would like to do something like this:
def f(x, y):
return (x ** 2 + y ** 2)
res = sp.integrate.nquad(f, [[22, 30], [20, x-2]])
Is it possible? Maybe using also sympy?
I solved with sympy:
from sympy import *
x, y = symbols("x y")
f = (x ** 2 + y ** 2)
res = integrate(f, (y, 20, x-2), (x, 22, 30))
Basically sympy.integrate is able to deal with multiple integrations, also with variable boundaries.
If you need the numerical integration and sympy is not an option. Then you could try something like the following.
For this example it seems quick, but I have a suspicion you may run into problems in general, see how well it does for your use case.Perhaps this possibly imperfect answer will prompt someone to submit something better.
I use the fact that we can do the integrations one after the other, integrating out the y first, to get a function of x, then integrating that.
from scipy.integrate import quad
def integrand(x, y):
return (x ** 2 + y ** 2)
def y_integral(x):
# Note scipy will pass args as the second argument
# we can fiddle it to work correctly, but by symmetry we don't need to here.
return quad(integrand, 20, x-2, args=(x))[0]
We then use this y_integral function as the result function of the inner integral.
res = quad(y_integral, 22, 30)
print res
You could wrap this in a function if you use it regularly.