Write a program to compute the Taylor Series. - python

I am new to python and don't understand how to use the libraries properly. I am trying to write a program to compute the Taylor Series Approximation of a function centered at 0 at a given x and n.
def fact(n): #function to calculate n!
if n <= 0:
return 1
else:
return n * fact(n - 1)
#h= 0.00000000001
#def derivative(f,x,n): #function that calculates the derivative of a
function at a specified x
# return (f(x + h) - f(x - h)) /(2 * h)
from sympy import *
x = symbols('x')
def taylor(f,x,n):
for i in range(0,n):
t = 0
t = t + ((diff(f,x,n))/(fact(n))) * (x ** n)
return t
taylor(sin(x),1/32,1)

Here is what works for me after I fixed stuff from your code. I used sympy factorial.
from sympy import *
x = symbols('x')
def taylor(f,x,x0, n):
t = 0
for i in range(0,n):
t = t + ((diff(f,x,i).subs(x,x0))/(factorial(i))) * (x ** i)
return t
pprint(taylor(sin(x),x,Rational(1,32),4))
and the answer I get is
3 2
x ⋅cos(1/32) x ⋅sin(1/32)
- ──────────── - ──────────── + x⋅cos(1/32) + sin(1/32)
6 2

Related

Reason for "Maximum recursion error" in Python

I wrote this program describing an algorithm for the simulation of a partial differential equation. The basic functions I use are defined by
import numpy as np
import math
from scipy import integrate, stats
def shift(func, x, a=0):
return func(x-a)
def scale(func, a=1):
return a*func
def trunc(func, x):
if x <= 0:
return 0
else:
return func(x)
def quad(func, a, b):
return integrate.quad(func, a, b)
def gauss(func, t, x):
def pregau(z):
k = (-t ** (1 / 2)) * z
return shift(func, x, k)*math.exp(-(z**2)/2)
fa = (1 / ((2 * math.pi) ** (1 / 2)) * integrate.quad(pregau, -np.inf, np.inf)[0])
return fa
The program then simulates the solution to the partial differential equation by
def vundl(x, u, l0=0.0, a=a, b=b, c=c):
v = [u(x)]
l = [l0]
f_temp_rec = u
for i in range(10):
def f_temp(x):
y = x - c * dt + B[i + 1] * 2 * a
z = b * dt
return gauss(f_temp_rec, z, y)
li = l[i] + quad(f_temp, 0, np.inf)[0]
l = np.append(l, li)
if x <= 0:
v = np.append(v, 0)
f_temp_rec = 0
else:
f_temp_rec = f_temp
v = np.append(v, f_temp(x))
return [v, l]
def u0(x):
return stats.beta.pdf(x, 2.7, 3.05)
print(vundl(x = 0.5, u0))
If I run this program for N=0 it produces a vector. Running the program for N>0 gives me the following error:
"RecursionError: maximum recursion depth exceeded"
but it actually should give me a vector v and a vector l.
I'm not sure exactly what you're trying to do in vundl with f_temp and f_temp_rec, but in the else: block you assign:
f_temp_rec = f_temp
and then call f_temp which calls gauss(f_temp_rec, z, y). Since at this point f_temp_rec is f_temp the function f_temp calls itself in an infinite recursion.
You should be able to see in in traceback that f_temp is calling itself repeatedly.

finite difference methods in python

I am trying to calculate g(x_(i+2)) from the value g(x_(i+1)) and g(x_i), i is an integer, assuming I(x) and s(x) are Gaussian function. If we know x_i = 100, then the summation from 0 to 100, I don't know how to handle g(x_i) with the subscript in python, knowing the first and second value, we can find the third value, after n cycle, we can find the nth value.
Equation:
code:
import numpy as np
from matplotlib import pyplot as p
from math import pi
def f_s(x, mu_s, sig_s):
ss = -np.power(x - mu_s, 2) / (2 * np.power(sig_s, 2))
return np.exp(ss) / (np.power(2 * pi, 2) * sig_s)
def f_i(x, mu_i, sig_i):
ii = -np.power(x - mu_i, 2) / (2 * np.power(sig_i, 2))
return np.exp(ii) / (np.power(2 * pi, 2) * sig_i)
# problems occur in this part
def g(x, m, mu_s, sig_s, mu_i, sig_i):
for i in range(1, m): # specify the number x, x_1, x_2, x_3 ......X_m
h = (x[i + 1] - x[i]) / e
for n in range(0, x[i]): # calculate summation
sum_f = (f_i(x[i], mu_i, sig_i) - f_s(x[i] - n, mu_s, sig_s) * g_x[n]) * np.conj(f_s(n +
x[i], mu_s, sig_s))
g_x[1] = 1 # initial value
g_x[2] = 5
g_x[i + 2] = h * sum_f + 2 * g_x[i + 1] - g_x[i]
return g_x[i + 2]
x = np.linspace(-10, 10, 10000)
e = 1
d = 0.01
m = 1000
mu_s = 2
sig_s = 1
mu_i = 1
sig_i = 1
p.plot(x, g(x, m, mu_s, sig_s, mu_i, sig_i))
p.legend()
p.show()
result:
I(x) and s(x)

How do you control the number of times a functions calls, in a recursive function. I.e the number of times the recursive function calls on itself

I have 2 functions right now, one of them is to code a simple recursive function that will calculate exponents in n number of steps
the second function which is my primary problem, is n/2 steps. I am confused on how to negotiate or control the number of recursive calls which is represented by n.
this is an assignment question, i am not allowed to use loops of any kind, "while" and "for" are not allowed, only if thens, so please go easy on me because i know it looks simple.
def simple_recursive_power(x, n):
print("n="+str(n))
if n ==1:
return x
else:
return x* simple_recursive_power(x,n-1)
print("the simple recurse method="+ str(simple_recursive_power(3,3)))
""the above works, the one below is working the wrong way""
def advanced_recursive_power(x, n):
print("n="+str(n))
if n <= 1:
return x
else:
return x * advanced_recursive_power(x, n-1/2)
print("advanced recursion="+ str(advanced_recursive_power(3,3)))
The better exponential function that takes half of the cycles does not just need an adjustment of N, it needs a better algorithm.
The simple exponent works like this: take N steps, at each step multiply what you have with X.
If you want to halve the number of steps, the crucial detail to notice is that, if you multiply with X*X, you are taking two steps at a time.
def advanced_recursive_power(x, n):
print("n="+str(n))
if n == 0:
return 1
elif n == 1:
return x
else:
return x * x * advanced_recursive_power(x, n - 2)
Now, this cuts down number of function invocations, but not number of multiplications: for example with N = 7, we went from X * X * X * X * X * X * X to X * (X * X) * (X * X) * (X * X). If we could just pre-calculate X * X, we could actually cut down on multiplications as well... This will calculate (X2 = X * X); X * X2 * X2 * X2, with four multiplications, not seven:
def super_advanced_recursive_power(x, n):
print("n="+str(n))
if n % 2 == 0:
start = 1
else:
start = x
return start * simple_recursive_power(x * x, n // 2)
You can drastically cut down the number of steps if you pass on powers:
def arp(x, n):
"""Advanced recursive power equivalent to x ** n"""
print('#', x, n)
if n == 0:
return 1
elif n == 1:
return x
elif n % 2: # odd exponential
return x * arp(x * x, (n - 1) // 2)
else: # even exponential
return arp(x * x, n // 2)
This takes O(log n) steps only.
>>> arp(3, 15)
# 3 15
# 9 7
# 81 3
# 6561 1
14348907
This is the equivalent of expressing addition as a series of decrements and increments:
def recursive_add(x, y):
if y == 0:
return x
return (x + 1, y - 1)
This uses that x + y == (x + 1) + (y - 1). Similarly, for powers the relation x ** n == (x * x) ** (n / 2) holds true. While it is pretty slow for addition (linear) it is fast for powers (exponential).
This exploits that even powers repeat terms. For example, 2**8 can be written as ((2 * 2) * (2 * 2)) * ((2 * 2) * (2 * 2)) - notice how the term 2 * 2 and (2 * 2) * (2 * 2) repeats. We can rewrite 2**8 as ((2 ** 2) ** 2) ** 2. This is exactly what the last term for even exponentials does recursively.
For odd exponentials, we have the problem that we would go from, say, 2 ** 3 to 4 ** 1.5. Thus, we use x ** n == x * (x ** (n - 1)) to go from an odd to an even exponent. Since we have excluded the case of n == 1, we know that n >= 3 and thus it is safe to proceed with x * x, (n-1) // 2 directly.
The net effect is that n is halved on each step, not just once.

Approximation by sin waves using DFT on python. What's wrong?

I'm writing the prorgram on python that can approximate time series by sin waves.
The program uses DFT to find sin waves, after that it chooses sin waves with biggest amplitudes.
Here's my code:
__author__ = 'FATVVS'
import math
# Wave - (amplitude,frequency,phase)
# This class was created to sort sin waves:
# - by anplitude( set freq_sort=False)
# - by frequency (set freq_sort=True)
class Wave:
#flag for choosing sort mode:
# False-sort by amplitude
# True-by frequency
freq_sort = False
def __init__(self, amp, freq, phase):
self.freq = freq #frequency
self.amp = amp #amplitude
self.phase = phase
def __lt__(self, other):
if self.freq_sort:
return self.freq < other.freq
else:
return self.amp < other.amp
def __gt__(self, other):
if self.freq_sort:
return self.freq > other.freq
else:
return self.amp > other.amp
def __le__(self, other):
if self.freq_sort:
return self.freq <= other.freq
else:
return self.amp <= other.amp
def __ge__(self, other):
if self.freq_sort:
return self.freq >= other.freq
else:
return self.amp >= other.amp
def __str__(self):
s = "(amp=" + str(self.amp) + ",frq=" + str(self.freq) + ",phase=" + str(self.phase) + ")"
return s
def __repr__(self):
return self.__str__()
#Discrete Fourier Transform
def dft(series: list):
n = len(series)
m = int(n / 2)
real = [0 for _ in range(n)]
imag = [0 for _ in range(n)]
amplitude = []
phase = []
angle_const = 2 * math.pi / n
for w in range(m):
a = w * angle_const
for t in range(n):
real[w] += series[t] * math.cos(a * t)
imag[w] += series[t] * math.sin(a * t)
amplitude.append(math.sqrt(real[w] * real[w] + imag[w] * imag[w]) / n)
phase.append(math.atan(imag[w] / real[w]))
return amplitude, phase
#extract waves from time series
# series - time series
# num - number of waves
def get_waves(series: list, num):
amp, phase = dft(series)
m = len(amp)
waves = []
for i in range(m):
waves.append(Wave(amp[i], 2 * math.pi * i / m, phase[i]))
waves.sort()
waves.reverse()
waves = waves[0:num]#extract best waves
print("the program found the next %s sin waves:"%(num))
print(waves)#print best waves
return waves
#approximation by sin waves
#series - time series
#num- number of sin waves
def sin_waves_appr(series: list, num):
n = len(series)
freq = get_waves(series, num)
m = len(freq)
model = []
for i in range(n):
summ = 0
for j in range(m): #sum by sin waves
summ += freq[j].amp * math.sin(freq[j].freq * i + freq[j].phase)
model.append(summ)
return model
if __name__ == '__main__':
import matplotlib.pyplot as plt
N = 500 # length of time series
num = 2 # number of sin wawes, that we want to find
#y - generate time series
y = [2 * math.sin(0.05 * t + 0.5) + 0.5 * math.sin(0.2 * t + 1.5) for t in range(N)]
model = sin_waves_appr(y, num) #generate approximation model
## ------------------plotting-----------------
plt.figure(1)
# plotting of time series and his approximation model
plt.subplot(211)
h_signal, = plt.plot(y, label='source timeseries')
h_model, = plt.plot(model, label='model', linestyle='--')
plt.legend(handles=[h_signal, h_model])
plt.grid()
# plotting of spectre
amp, _ = dft(y)
xaxis = [2*math.pi*i / N for i in range(len(amp))]
plt.subplot(212)
h_freq, = plt.plot(xaxis, amp, label='spectre')
plt.legend(handles=[h_freq])
plt.grid()
plt.show()
But I've got a strange result:
In the program I've created a time series from two sin waves:
y = [2 * math.sin(0.05 * t + 0.5) + 0.5 * math.sin(0.2 * t + 1.5) for t in range(N)]
And my program found wrong parameters of the sin waves:
the program found the next 2 sin waves:
[(amp=0.9998029885151699,frq=0.10053096491487339,phase=1.1411803525843616), (amp=0.24800925225626422,frq=0.40212385965949354,phase=0.346757128184013)]
I suppuse, that my problem is wrong scaling of wave parameters, but I'm not sure.
There're two places, where the program does scaling. The first place is creating of waves:
for i in range(m):
waves.append(Wave(amp[i], 2 * math.pi * i / m, phase[i]))
And the second place is sclaling of the x-axis:
xaxis = [2*math.pi*i / N for i in range(len(amp))]
But my suppose may be wrong. I've tried to change scaling many times, and it haven't solved my problem.
What may be wrong with the code?
So, these lines I believe are wrong:
for t in range(n):
real[w] += series[t] * math.cos(a * t)
imag[w] += series[t] * math.sin(a * t)
amplitude.append(math.sqrt(real[w] * real[w] + imag[w] * imag[w]) / n)
phase.append(math.atan(imag[w] / real[w]))
I believe it should be dividing by m instead of n, since you are only working with computing half the points. That will fix the amplitude problem. Also, the computation of imag[w] is missing a negative sign. Taking into account the atan2 fix, it would look like:
for t in range(n):
real[w] += series[t] * math.cos(a * t)
imag[w] += -1 * series[t] * math.sin(a * t)
amplitude.append(math.sqrt(real[w] * real[w] + imag[w] * imag[w]) / m)
phase.append(math.atan2(imag[w], real[w]))
The next one is here:
for i in range(m):
waves.append(Wave(amp[i], 2 * math.pi * i / m, phase[i]))
The divide by m is not right. amp has only half the points it should, so using the length of amp isn't right here. It should be:
for i in range(m):
waves.append(Wave(amp[i], 2 * math.pi * i / (m * 2), phase[i]))
Finally, your model reconstruction has a problem:
for j in range(m): #sum by sin waves
summ += freq[j].amp * math.sin(freq[j].freq * i + freq[j].phase)
It should use cosine instead (sine introduces a phase shift):
for j in range(m): #sum by cos waves
summ += freq[j].amp * math.cos(freq[j].freq * i + freq[j].phase)
When I fix all of that, the model and the DFT both make sense:

Python double integral taking too long to compute

I am trying to compute the fresnel integral over a grid of coordinates using dblquad. But its taking very long and finally it's not giving any result.
Below is my code. In this code I integrated only over a 10 x 10 grid but I need to integrate at least over a 500 x 500 grid.
import time
st = time.time()
import pylab
import scipy.integrate as inte
import numpy as np
print 'imhere 0'
def sinIntegrand(y,x, X , Y):
a = 0.0001
R = 2e-3
z = 10e-3
Lambda = 0.5e-6
alpha = 0.01
k = np.pi * 2 / Lambda
return np.cos(k * (((x-R)**2)*a + (R-(x**2 + y**2)) * np.tan(np.radians(alpha)) + ((x - X)**2 + (y - Y)**2) / (2 * z)))
print 'im here 1'
def cosIntegrand(y,x,X,Y):
a = 0.0001
R = 2e-3
z = 10e-3
Lambda = 0.5e-6
alpha = 0.01
k = np.pi * 2 / Lambda
return np.sin(k * (((x-R)**2)*a + (R-(x**2 + y**2)) * np.tan(np.radians(alpha)) + ((x - X)**2 + (y - Y)**2) / (2 * z)))
def y1(x,R = 2e-3):
return (R**2 - x**2)**0.5
def y2(x, R = 2e-3):
return -1*(R**2 - x**2)**0.5
points = np.linspace(-1e-3,1e-3,10)
points2 = np.linspace(1e-3,-1e-3,10)
yv,xv = np.meshgrid(points , points2)
#def integrate_on_grid(func, lo, hi,y1,y2):
# """Returns a callable that can be evaluated on a grid."""
# return np.vectorize(lambda n,m: dblquad(func, lo, hi,y1,y2,(n,m))[0])
#
#intensity = abs(integrate_on_grid(sinIntegrand,-1e-3 ,1e-3,y1, y2)(yv,xv))**2 + abs(integrate_on_grid(cosIntegrand,-1e-3 ,1e-3,y1, y2)(yv,xv))**2
Intensity = []
print 'im here2'
for i in points:
row = []
for j in points2:
print 'im here'
intensity = abs(inte.dblquad(sinIntegrand,-1e-3 ,1e-3,y1, y2,(i,j))[0])**2 + abs(inte.dblquad(cosIntegrand,-1e-3 ,1e-3,y1, y2,(i,j))[0])**2
row.append(intensity)
Intensity.append(row)
Intensity = np.asarray(Intensity)
pylab.imshow(Intensity,cmap = 'gray')
pylab.show()
print str(time.time() - st)
I would really appreciate if you could tell any better way of doing this.
Using a scipy.integrate.dblquad to calculate every pixel of your image is going to be slow in any case.
You should try rewriting your mathematical problem so you can use some classical function in scipy.special instead. For instance, scipy.special.fresnel might work, although it is 1D and your problem seems to be in 2D. Otherwise, that there is a relationship between the Fresnel integral and the incomplete Gamma function (scipy.special.gammainc), if that helps.
If none of this work, as a last resort you can spend time optimizing your code and adapting it to Cython. This it will probably give a speed up of a factor of 10 to 100 (see this answer). Though this wouldn't be sufficient to go from a grid 10x10 to a grid 500x500.

Categories