Fourier transform Sympy does nothing? - python

Is sympy able to compute fourier transforms quickly or do I need another software? Because I tried many things . I am pretty inexperienced in python and Sympy though . Is there a quicker way to do these Fourier transforms with python?
(a +j \omega) / (4a^2 + (a+j \omega)^2) )
I tried as such
from sympy import poly, pi, I, pow
from sympy.abc import a,f, n, k
n = poly(a**2 + t**2)
k = t / n
fourier_transform(k , t, 2*pi*f)
And I get this message:
And another example from Python 3.9 shell :
So what about the actual result?

1
Currently, if the Fourier transform returns a PieceWise expression, it throws a fuss and just returns an unevaluated expression instead. So SymPy can do the integral, it just isn't in a very nice form. Here is the result after manual integration.
You can use this function on your own to attain this result if you want this kind of answer.
def my_fourier_transform(f, t, s):
return integrate(f*exp(-2*S.Pi*I*t*s), (t, -oo, oo)).simplify()
One can see that the long condition has arg(a) and arg(s) which should be sign(a) and sign(s) respectively (assuming they are real-valued). After doing a similar thing in Wolfram Alpha, I think this is a correct result. It is just not a very nice one.
But I found a trick that helps. If SymPy struggles to simplify something, usually giving it stronger assumptions is the way to go if your main goal is just to get an answer. A lot of the time, the answer is still correct even if the assumptions don't hold. So we make the variables positive.
Note that SymPy does the transform differently to Wolfram Alpha as noted in the comment below. This was why my third argument is different.
from sympy import *
a, s, t = symbols('a s t', positive=True)
f = t / (a**2 + t**2)
# Wolfram computes integral(f(t)*exp(I*t*w))
# SymPy computes integral(f(t)*exp(-2*pi*I*s*t))
# So w = -2*pi*s
print(fourier_transform(f, t, -s))
# I*pi*exp(-2*pi*a*s)
2
Correct me if I'm wrong but according to Wikipedia:
So the Fourier transform of the Dirac Delta is 1.
3
Using the my_fourier_transfrom defined above, we get
The first condition is always false. This is probably a failure on SymPy's part since this integral diverges. I assume it's because it can't decide whether it is oo, -oo or zoo.

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.)

Derivatives in python

I am trying to find the coefficients of a finite series, $f(x) = \sum_n a_nx^n$. To get the $m$th coefficient, we can take the $m$th derivative evaluated at zero. Therefore, the $m$th coefficient is
$$
a_n = \frac{1}{2\pi i } \oint_C \frac{f(z)}{z^{n+1}} dz
$$
I believe this code takes the derivative of a function using the above contour integral.
import math
import numpy
import matplotlib.pyplot as plt
def F(x):
mean=10
return math.exp(mean*(x.real-1))
def p(n):
mean=10
return (math.pow(mean, n) * math.exp(-mean)) / math.factorial(n)
def integration(func, a, n, r, n_steps):
z = r * numpy.exp(2j * numpy.pi * numpy.arange(0, 1, 1. / n_steps))
return math.factorial(n) * numpy.mean(func(a + z) / z**n)
ns = list(range(20))
f2 = numpy.vectorize(F)
plt.plot(ns,[p(n) for n in ns], label='Actual')
plt.plot(ns,[integration(f2, a=0., n=n, r=1., n_steps=100).real/math.factorial(n) for n in ns], label='Numerical derivative')
plt.legend()
However, it is clear that the numerical derivative is completely off the actual values of the coefficients of the series. What am I doing wrong?
The formulas in the Mathematics Stack Exchange answer that you're using to derive the coefficients of the power series expansion of F are based on complex analysis - coming for example from Cauchy's residue theorem (though other derivations are possible). One of the assumptions necessary to make those formulas work is that you have a holomorphic (i.e., complex differentiable) function.
Your definition of F gives a function that's not holomorphic. (For one thing, it always gives a real result for any complex input, which isn't possible for a non-constant holomorphic function.) But it's easily fixed to be holomorphic, while continuing to return the same result for real inputs.
Here's a fixed version of F, which replaces x.real with x. Since the input to exp is now complex, it's also necessary to use cmath.exp instead of math.exp to avoid a TypeError:
import cmath
def F(x):
mean=10
return cmath.exp(mean*(x-1))
After that fix for F, if I run your code I get rather surprisingly accurate results. Here's the graph that I get. (I had to print out the values to double check that that graph really did show two lines on top of one another.)

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)

Sympy function derivatives and sets of equations

I'm working with nonlinear systems of equations. These systems are generally a nonlinear vector differential equation.
I now want to use functions and derive them with respect to time and to their time-derivatives, and find equilibrium points by solving the nonlinear equations 0=rhs(eqs).
Similar things are needed to calculate the Euler-Lagrange equations, where you need the derivative of L wrt. diff(x,t).
Now my question is, how do I implement this in Sympy?
My main 2 problems are, that deriving a Symbol f wrt. t diff(f,t), I get 0. I can see, that with
x = Symbol('x',real=True);
diff(x.subs(x,x(t)),t) # because diff(x,t) => 0
and
diff(x**2, x)
does kind of work.
However, with
x = Fuction('x')(t);
diff(x,t);
I get this to work, but I cannot differentiate wrt. the funtion x itself, like
diff(x**2,x) -DOES NOT WORK.
Since I need these things, especially not only for scalars, but for vectors (using jacobian) all the time, I really want this to be a clean and functional workflow.
Which kind of type should I initiate my mathematical functions in Sympy in order to avoid strange substitutions?
It only gets worse for matricies, where I cannot get
eqns = Matrix([f1-5, f2+1]);
variabs = Matrix([f1,f2]);
nonlinsolve(eqns,variabs);
to work as expected, since it only allows symbols as input. Is there an easy conversion here? Like eqns.tolist() - which doesn't work either?
EDIT:
I just found this question, which was answered towards using expressions and matricies. I want to be able to solve sets of nonlinear equations, build the jacobian of a vector wrt. another vector and derive wrt. functions as stated above. Can anyone point me into a direction to start a concise workflow for this purpose? I guess the most complex task is calculating the Lie-derivative wrt. a vector or list of functions, the rest should be straight forward.
Edit 2:
def substi(expr,variables):
return expr.subs( {w:w(t)} )
would automate the subsitution, such that substi(vector_expr,varlist_vector).diff(t) is not all 0.
Yes, one has to insert an argument in a function before taking its derivative. But after that, differentiation with respect to x(t) works for me in SymPy 1.1.1, and I can also differentiate with respect to its derivative. Example of Euler-Lagrange equation derivation:
t = Symbol("t")
x = Function("x")(t)
L = x**2 + diff(x, t)**2 # Lagrangian
EL = -diff(diff(L, diff(x, t)), t) + diff(L, x)
Now EL is 2*x(t) - 2*Derivative(x(t), t, t) as expected.
That said, there is a build-in method for Euler-Lagrange:
EL = euler_equations(L)
would yield the same result, except presented as a differential equation with right-hand side 0: [Eq(2*x(t) - 2*Derivative(x(t), t, t), 0)]
The following defines x to be a function of t
import sympy as s
t = s.Symbol('t')
x = s.Function('x')(t)
This should solve your problem of diff(x,t) being evaluated as 0. But I think you will still run into problems later on in your calculations.
I also work with calculus of variations and Euler-Lagrange equations. In these calculations, x' needs to be treated as independent of x. So, it is generally better to use two entirely different variables for x and x' so as not to confuse Sympy with the relationship between those two variables. After we are done with the calculations in Sympy and we go back to our pen and paper we can substitute x' for the second variable.

On ordinary differential equations (ODE) and optimization, in Python

I want to solve this kind of problem:
dy/dt = 0.01*y*(1-y), find t when y = 0.8 (0<t<3000)
I've tried the ode function in Python, but it can only calculate y when t is given.
So are there any simple ways to solve this problem in Python?
PS: This function is just a simple example. My real problem is so complex that can't be solve analytically. So I want to know how to solve it numerically. And I think this problem is more like an optimization problem:
Objective function y(t) = 0.8, Subject to dy/dt = 0.01*y*(1-y), and 0<t<3000
PPS: My real problem is:
objective function: F(t) = 0.85,
subject to: F(t) = sqrt(x(t)^2+y(t)^2+z(t)^2),
x''(t) = (1/F(t)-1)*250*x(t),
y''(t) = (1/F(t)-1)*250*y(t),
z''(t) = (1/F(t)-1)*250*z(t)-10,
x(0) = 0, y(0) = 0, z(0) = 0.7,
x'(0) = 0.1, y'(0) = 1.5, z'(0) = 0,
0<t<5
This differential equation can be solved analytically quite easily:
dy/dt = 0.01 * y * (1-y)
rearrange to gather y and t terms on opposite sides
100 dt = 1/(y * (1-y)) dy
The lhs integrates trivially to 100 * t, rhs is slightly more complicated. We can always write a product of two quotients as a sum of the two quotients * some constants:
1/(y * (1-y)) = A/y + B/(1-y)
The values for A and B can be worked out by putting the rhs on the same denominator and comparing constant and first order y terms on both sides. In this case it is simple, A=B=1. Thus we have to integrate
1/y + 1/(1-y) dy
The first term integrates to ln(y), the second term can be integrated with a change of variables u = 1-y to -ln(1-y). Our integrated equation therefor looks like:
100 * t + C = ln(y) - ln(1-y)
not forgetting the constant of integration (it is convenient to write it on the lhs here). We can combine the two logarithm terms:
100 * t + C = ln( y / (1-y) )
In order to solve t for an exact value of y, we first need to work out the value of C. We do this using the initial conditions. It is clear that if y starts at 1, dy/dt = 0 and the value of y never changes. Thus plug in the values for y and t at the beginning
100 * 0 + C = ln( y(0) / (1 - y(0) )
This will give a value for C (assuming y is not 0 or 1) and then use y=0.8 to get a value for t. Note that because of the logarithm and the factor 100 multiplying t y will reach 0.8 within a relatively short range of t values, unless the initial value of y is incredibly small. It is of course also straightforward to rearrange the equation above to express y in terms of t, then you can plot the function as well.
Edit: Numerical integration
For a more complexed ODE which cannot be solved analytically, you will have to try numerically. Initially we only know the value of the function at zero time y(0) (we have to know at least that in order to uniquely define the trajectory of the function), and how to evaluate the gradient. The idea of numerical integration is that we can use our knowledge of the gradient (which tells us how the function is changing) to work out what the value of the function will be in the vicinity of our starting point. The simplest way to do this is Euler integration:
y(dt) = y(0) + dy/dt * dt
Euler integration assumes that the gradient is constant between t=0 and t=dt. Once y(dt) is known, the gradient can be calculated there also and in turn used to calculate y(2 * dt) and so on, gradually building up the complete trajectory of the function. If you are looking for a particular target value, just wait until the trajectory goes past that value, then interpolate between the last two positions to get the precise t.
The problem with Euler integration (and with all other numerical integration methods) is that its results are only accurate when its assumptions are valid. Because the gradient is not constant between pairs of time points, a certain amount of error will arise for each integration step, which over time will build up until the answer is completely inaccurate. In order to improve the quality of the integration, it is necessary to use more sophisticated approximations to the gradient. Check out for example the Runge-Kutta methods, which are a family of integrators which remove progressive orders of error term at the cost of increased computation time. If your function is differentiable, knowing the second or even third derivatives can also be used to reduce the integration error.
Fortunately of course, somebody else has done the hard work here, and you don't have to worry too much about solving problems like numerical stability or have an in depth understanding of all the details (although understanding roughly what is going on helps a lot). Check out http://docs.scipy.org/doc/scipy/reference/generated/scipy.integrate.ode.html#scipy.integrate.ode for an example of an integrator class which you should be able to use straightaway. For instance
from scipy.integrate import ode
def deriv(t, y):
return 0.01 * y * (1 - y)
my_integrator = ode(deriv)
my_integrator.set_initial_value(0.5)
t = 0.1 # start with a small value of time
while t < 3000:
y = my_integrator.integrate(t)
if y > 0.8:
print "y(%f) = %f" % (t, y)
break
t += 0.1
This code will print out the first t value when y passes 0.8 (or nothing if it never reaches 0.8). If you want a more accurate value of t, keep the y of the previous t as well and interpolate between them.
As an addition to Krastanov`s answer:
Aside of PyDSTool there are other packages, like Pysundials and Assimulo which provide bindings to the solver IDA from Sundials. This solver has root finding capabilites.
Use scipy.integrate.odeint to handle your integration, and analyse the results afterward.
import numpy as np
from scipy.integrate import odeint
ts = np.arange(0,3000,1) # time series - start, stop, step
def rhs(y,t):
return 0.01*y*(1-y)
y0 = np.array([1]) # initial value
ys = odeint(rhs,y0,ts)
Then analyse the numpy array ys to find your answer (dimensions of array ts matches ys). (This may not work first time because I am constructing from memory).
This might involve using the scipy interpolate function for the ys array, such that you get a result at time t.
EDIT: I see that you wish to solve a spring in 3D. This should be fine with the above method; Odeint on the scipy website has examples for systems such as coupled springs that can be solved for, and these could be extended.
What you are asking for is a ODE integrator with root finding capabilities. They exist and the low-level code for such integrators is supplied with scipy, but they have not yet been wrapped in python bindings.
For more information see this mailing list post that provides a few alternatives: http://mail.scipy.org/pipermail/scipy-user/2010-March/024890.html
You can use the following example implementation which uses backtracking (hence it is not optimal as it is a bolt-on addition to an integrator that does not have root finding on its own): https://github.com/scipy/scipy/pull/4904/files

Categories