Sympy function evaluated at symbol - python

I have a problem with the symbolic Python package Sympy.
Perhaps I am missing some obvious tools in Sympy but I have read through the documentation and not come across a solution.
My question is can the derivative of g(f(y)) = g(f(x))|_(x=y) with respect to x be obtained in the form Derivative(f(x), x)(y) in Sympy? And if so how?
Here is a simple example: I have a symbolic function of one variable e.g. f(x).
I have another expression g, which calls this function with input arguments
represented by other symbols, i.e. g(f(y)) where y = Symbol('y').
I implement this with the following:
x = Symbol('x')
f = Function('f')(x)
y = Symbol('y')
g = Function('g')(f).subs('x','y')
My goal is then to evaluate the derivative of g wrt x at x=y, something like
Derivative(f(x), x)(y) * Derivative(g(f), f)(f(y))
This can be roughly achieved with
diff(g, y) = Derivative(f(y), y)*Derivative(g(f(y)), f(y)).
The problem here is that the term Derivative(f(y), y) in this case is the derivative evaluated at y.
I have expressions for the derivatives of functions wrt all input variables, i.e. Derivative(f(x), x) in this case, and not wrt y since it is not a variable of f. Hence, I would like the derivative expressed in the form Derivative(f(x), x)(y) to avoid repeating the same expression for all the possible variables used.
(For completeness, the term diff(g, x)=0 since any instances of x have been replaced by y.)
To enforce the notion that g is a function of x evaluated at y, replacing the method subs of the fourth line above with the evalf method could be the right path. But it seems that expression can only be evaluated at particular values and not other symbolic variables.
Any help and advice is most appreciated.

Wrapping the differentiation in Subs seems to work; it is a delayed substitution.
>>> from sympy import Subs, sin, cos
>>> from sympy.abc import x, y
>>> f, g = symbols('f g', cls=Function)
>>> Subs(g(f(x)).diff(x),x,y).subs(g,sin).subs(f,cos).doit(
... ) == Subs(sin(cos(x)).diff(x),x,y).doit()
True

Related

Python Scipy dblquad function giving wrong answer on short range

I want to integrate the following double integral:
I want to use the dblquad method from the scipy.integrate package, which allows you to do double integrals with limits of the inner integral as a function of the outer integral variable:
import scipy.integrate as spi
import numpy as np
x_limit = 0
y_limit = lambda x: np.arccos(np.cos(x))
integrand = lambda x, y: np.exp(-(2+np.cos(x)-np.cos(y)))
low_limit_y = 0 # inner integral
up_limit_y = y_limit
low_limit_x = x_limit # outer integral
up_limit_x = 2*np.pi-x_limit
integral = spi.dblquad(integrand, low_limit_x, up_limit_x, low_limit_y, up_limit_y)
print(integral)
Output:
(0.6934912861906996, 2.1067956428653226e-12)
The code runs, but does not give me the right answer. Using Wolfram Alpha I get the right answer: 3.58857
Wolfram Alpha method
The only thing I've noticed is that the values from the two methods agree when the signs on the cosines are switched from + to - and vice versa:
Wolfram Alpha method with signs on the cosines swapped
However, I have no plausible reason for why this should be the case. Does anyone have any clue what is going on here? I can separate the function out into the inner integral looping over all values of x and then summing the results which gives the right answer, but that is really quite slow.
Take another look at the docstring of dblquad; it says
Return the double (definite) integral of ``func(y, x)`` from ``x = a..b``
and ``y = gfun(x)..hfun(x)``.
Note the order of arguments of func(y, x): y first, then x.
If you change your definition of integrand to
integrand = lambda y, x: np.exp(-(2+np.cos(x)-np.cos(y)))
you get the expected answer. That is also (in effect) what you did when you changed the signs of the cos terms in the integrand.
(You're not the first one to get tripped up by the expected order of the arguments to func.)

Fastest way to integrate a function that depends on a variable

I wish to evaluate the function y(x), which consists of an integral with the integrand depending on x. The integrand thus depends on two variables z and x. Here z is the variable that I wish to integrate over the range (0,1), and x is the variable that the function y(x) depends on.
The result should thus be an array y that is the integral of this integrand over z for each x.
My approach is the following
import numpy as np
from scipy.integrate import quad
x = np.linspace(0,6,1000)
integrand = lambda z, x: z**x
y = lambda x: quad(integrand, 0, 1, args = (x))[0]
y = np.vectorize(y)(x)
This works, but it also takes some time if I want to do more complicated integrals multiple times. This makes me wonder if there is a way to improve the computation time for this procedure. Please ignore the fact that here the integral can be solved analytically. This is just an illustrative example.

Represent placeholder for inverse of a function in SymPy

I am interested in solving integro-differential equations that not only contain functions of variables, but also inverse functions. In SymPy a function can be represented by Function:
from sympy import *
x = Symbol('x')
f = Function(x)
However I did not find an inverse function method. While Function has the method inverse, it is more specifically the multiplicative inverse.
Attempting to setup an equation and solve it to obtain a symbolic inverse is not implemented:
from sympy import *
x = Symbol('x')
y = Symbol('y')
f = Function(x)
solve(Eq(y, f))
NotImplementedError:
No algorithms are implemented to solve equation y - f(x)
Is there a way to setup a symbolic inverse of a function in SymPy?

How to draw a general equation with matplotlib?

The following problem has been researched - primarily with matplotlib in python.
"Basic" functions are possible, such as y = x^2, but if I want to plot an equation (which isn't necessarily a function due to multiple x-y associations), e.g.:
x^2 + y^2 = 1 (just a basic circle with a radius of 1 around the point (0/0) in a two-dimensional coordinate system).
Is there any way to plot such equation with matplotlib or any library alike?
The idea of re-writing the equation to a drawable function has come to my mind, but due to the absolute value assignment it just looks harder than the original equation, e.g. the equation above into a "function": |y| = sqrt(1-x²) with -y and +y.
//EDIT: On request from #mkrieger1 an edit of this question.
The aim of my software is to use an input (given by another function; string representing any equation, e.g. "y^3-sqrt(sin(x^2)-2)*2 = 3x") and turn it into a plot. I personally failed with the approach to solve the functions for y (as mentioned previously), especially with more complex functions. Splitting these equations into "smaller pieces" is, given the broad variety of mathematical inputs, pretty hard as well, thus I thought that going with a Contour-solving approach would be the best part. (As #mkrieger1 suggested).
Once again, this approach is critical due to a needed "editing" of the equation before implementing it in a plt.contour(X, Y, func, [0]), as well as a UserWarning later on.
You can also use sympy to convert an expression in a string to an equation and then plot it. I left out the -2 of the example, as this would lead to a quite empty plot. Sympy's parser supports special functions to allow multiplication be left out (as in 3x) and to convert Python's xor function (^) to a power.
from sympy import plot_implicit, Eq
from sympy.parsing.sympy_parser import parse_expr
from sympy.parsing.sympy_parser import standard_transformations, convert_xor, implicit_multiplication
string = "y^3-sqrt(sin(x^2))*2 = 3x"
transformations = (standard_transformations + (implicit_multiplication,) + (convert_xor,))
lhs = parse_expr(string.split('=')[0], transformations=transformations)
rhs = parse_expr(string.split('=')[1], transformations=transformations)
plot_implicit(Eq(lhs, rhs))
Another example:
from sympy import plot_implicit, Eq, cos
from sympy.abc import x, y
plot_implicit(Eq(x/y, cos(y)), (x, -10, 10), (y, -10, 10))
Note that without explicitly setting the range for the variables, plot_implicit supposes default ranges between -5 and 5.
If you use matplotlib at all, you will notice that plot accepts a pair of arrays of equal length, representing sequences of x-y pairs. It has no knowledge of functions, equations, or any of the other concepts you mention.
The assertion that plotting a simple function is supported is therefore largely meaningless, even if true. That being said, a standard approach to converting something that is a non-function in Cartesian space, like a circle, is to parametrize it. One possible parameterization for many popular non-functions is to use polar coordinates.
For example:
t = np.linspace(0, 2 * np.pi, 100) # the parameter
x = np.cos(t)
y = np.sin(t)

Finding upper or lower limits given one of the limits and the solution using Python

I would like to calculate the lower bound of an integral, given the f(x), the upper bound and a given solution.
or
the upper bound of an integral, given the f(x), the lower bound and a given solution using python.
How do I do this?
Thanks in Advance
This will work if a) the integral is known for your integrand when there are symbolic limits and b) the resulting equation can be solved:
from sympy import integrate
from sympy.abc import x, u
f = x + 3
lo = u
hi = 10
eq = integrate(f, (x, lo, hi))
eq, solve(eq, lo)
That gives
(-u**2/2 - 3*u + 80, [-16, 10])
But if you define f = exp(x) + 1/x you will end up with an equation that SymPy cannot solve with solve, but nsolve will work. (If you end up with an expression containing and Integral then you might need to use bisection by repeatedly plugging in a specific value for the unknown limit and numerically evaluate the integral until you get the desired result.)
If you want the integral to equal a certain value, v, then solve(eq - v, u) where u is the symbol that was used for the unknown limit.

Categories