## loading python libraries
# necessary to display plots inline:
%matplotlib inline
# load the libraries
import matplotlib.pyplot as plt # 2D plotting library
import numpy as np # package for scientific computing
from pylab import *
from math import * # package for mathematics (pi, arctan, sqrt, factorial ...)
import sympy as sympy # package for symbolic computation
from sympy import *
Let us first explain how we will manipulate generating functions with SymPy. We consider the example of
$$
f(x)=\frac{1}{1-2x}=1+2x+4x^2+8x^3+16x^4+ \dots
$$
We first introduce a symbolic variable $x$ and an expression $f$ as follows:
x=var('x')
f=(1/(1-2*x))
print('f = '+str(f))
print('-----')
print('We check that coefficients are correct:')
print('series expansion of f at 0 and of order 10 is: '+str(f.series(x,0,10)))
f = 1/(1 - 2*x) ----- We check that coefficients are correct: series expansion of f at 0 and of order 10 is: 1 + 2*x + 4*x**2 + 8*x**3 + 16*x**4 + 32*x**5 + 64*x**6 + 128*x**7 + 256*x**8 + 512*x**9 + O(x**10)
One can extract $n$-th coefficient as follows:
f.series(x,0,k)f.coeff(x**n)f_truncated = f.series(x,0,8)
print('Truncation of f is '+str(f_truncated))
n=6
nthcoefficient=f_truncated.coeff(x**n)
print(str(n)+'th coefficient is: '+str(nthcoefficient))
Truncation of f is 1 + 2*x + 4*x**2 + 8*x**3 + 16*x**4 + 32*x**5 + 64*x**6 + 128*x**7 + O(x**8) 6th coefficient is: 64
Let $f_n$ be the Fibonacci sequence defined by $f_0=1$, $f_1=1$ and for all $n\geq 2$, $$ f_n=f_{n-1}+f_{n-2}. $$
def Fibonacci(n):
if n==0 or n==1:
return 1
else:
return Fibonacci(n-1)+Fibonacci(n-2)
print([Fibonacci(n) for n in range(20)])
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]
var('x F')
SeriesF=solve(F-1-x-x*(F-1)-x**2*F,F)
print('The expression of F is: ')
display(SeriesF[0])
The expression of F is:
def FibonacciGF(n):
x=var('x')
f=(1/(1-x-x**2))
f_truncated=f.series(x,0,n+1)
return f_truncated.coeff(x**n)
print('Coefficients computed by recursion:')
print([Fibonacci(n) for n in range(1,20)])
print('Coefficients computed with GF:')
print([FibonacciGF(n) for n in range(1,20)])
Coefficients computed by recursion: [1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765] Coefficients computed with GF: [1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]
Let $j_n$ be defined by
\begin{align} j_0&=0, \notag\\ j_1&=1, \notag\\ j_2&=2,\notag\\ j_n&=2j_{n-2}+5 \quad (\text{ for every }n\geq 3). \qquad \text{(#)} \end{align}x=symbols('x')
j=symbols('j')
SeriesJ=solve(j-x-2*x**2-2*x**2*j-5*x**3/(1-x),j)
print('The solution is: J(x)= ')
display(SeriesJ[0])
solutionJ=SeriesJ[0]
The solution is: J(x)=
# Question 1
def j_GF(n):
x=symbols('x')
j= Function('j')
j=solutionJ
j_truncated=j.series(x,0,n+1)
return j_truncated.coeff(x**n)
print('With GFs we obtain:')
print([j_GF(n) for n in range(1,15)])
# Question 2
def j_recursive(n):
if n==1:
return 1
elif n==2:
return 2
else:
return 2*j_recursive(n-2)+5
print('With recursion we obtain:')
print([j_recursive(n) for n in range(1,15)])
With GFs we obtain: [1, 2, 7, 9, 19, 23, 43, 51, 91, 107, 187, 219, 379, 443] With recursion we obtain: [1, 2, 7, 9, 19, 23, 43, 51, 91, 107, 187, 219, 379, 443]
solve(2*x**3-2*x**2-x+1,x)
[1, -sqrt(2)/2, sqrt(2)/2]
N=80
RenormalizedValues=[j_recursive(n)**(1/(n+0.0)) for n in range(1,N)]
plt.plot(RenormalizedValues)
plt.plot([0,N],[np.sqrt(2),np.sqrt(2)],label='root(2)')
plt.legend()
plt.show()
Let $a_n,b_n$ be defined by $a_1=b_1=1$ and, for every $n\geq 1$, \begin{equation} \begin{cases} a_{n+1}&= a_n +2b_n,\\ b_{n+1}&= a_n +b_n. \end{cases} \tag{&} \end{equation}
#---- Question 2
# We solve the system
var('A B x')
Solutions=solve([A-x-x*A-2*x*B,B-x-x*A-x*B],[A,B])
print(Solutions)
# We obtain the following expression:
FunctionA=-x*(x + 1)/(x**2 + 2*x - 1)
FunctionB=-x/(x**2 + 2*x - 1)
print("A(x) = "+str(FunctionA.series(x,0,10)))
print("B(x) = "+str(FunctionB.series(x,0,10)))
# We extract a_1,a_2,...
N=20
A_truncated = FunctionA.series(x,0,N+2)
FirstCoefficients= [A_truncated.coeff(x**n) for n in range(1,N+1)]
print(FirstCoefficients)
{B: -x/(x**2 + 2*x - 1), A: -x*(x + 1)/(x**2 + 2*x - 1)}
A(x) = x + 3*x**2 + 7*x**3 + 17*x**4 + 41*x**5 + 99*x**6 + 239*x**7 + 577*x**8 + 1393*x**9 + O(x**10)
B(x) = x + 2*x**2 + 5*x**3 + 12*x**4 + 29*x**5 + 70*x**6 + 169*x**7 + 408*x**8 + 985*x**9 + O(x**10)
[1, 3, 7, 17, 41, 99, 239, 577, 1393, 3363, 8119, 19601, 47321, 114243, 275807, 665857, 1607521, 3880899, 9369319, 22619537]
In class we saw that for GFs it is useful to decompose fractions like this:
$$
\frac{1-x+x^2}{(1-2x)(1-x)^2} = \frac{3}{1-2x} - \frac{1}{1-x} - \frac{1}{(1-x)^2}.
$$
Here are examples on how to do that with SymPy.
# Question 2
# We solve "denominator of A = 0" to find a,b
var('x')
solve(x**2+2*x-1,x)
[-1 + sqrt(2), -sqrt(2) - 1]
# Question 3
# We use A(1), A(0) to find alpha,beta
var('a b alpha beta x')
alpha=-1 + sqrt(2)
beta=-sqrt(2) - 1
# Left-hand side:
def A_factorized(x):
return -(x*(x+1))/(x**2+2*x-1)
# Right-hand side:
def A_decomposed(x,a,b,alpha,beta):
return a/(x-alpha)+b/(x-beta)+(-1)
# we identify a,b,c by solving the following system:
Solutions=solve([A_factorized(0)-A_decomposed(0,a,b,alpha,beta),A_factorized(1)-A_decomposed(1,a,b,alpha,beta)],[a,b])
print(Solutions)
astar=Solutions[a]
bstar=Solutions[b]
# to get a nice formula:
var('x')
print(latex(A_decomposed(x,astar,bstar,alpha,beta)))
{b: 1/2 + sqrt(2)/2, a: -sqrt(2)/2 + 1/2}
-1 + \frac{- \frac{\sqrt{2}}{2} + \frac{1}{2}}{x - \sqrt{2} + 1} + \frac{\frac{1}{2} + \frac{\sqrt{2}}{2}}{x + 1 + \sqrt{2}}
# We first solve the equation
var('G x')
Solutions=solve(G-x-x*G*G-1,G)
print('2 solutions:')
display(Solutions)
# We obtain the following expression:
FunctionG0=Solutions[0]
FunctionG1=Solutions[1]
print("First solution G(x) = "+str(FunctionG0.series(x,0,10)))
print("2d solution G(x) = "+str(FunctionG1.series(x,0,10)))
# Only G0 has non-negative coefficients.
# We extract a_0,a_1,a_2,...,a_N
N=50
G_truncated = FunctionG0.series(x,0,N+2)
FirstCoefficients= [G_truncated.coeff(x**n) for n in range(N+1)]
print(FirstCoefficients)
print(str(N)+'th coefficient = '+str(G_truncated.coeff(x**N)))
2 solutions:
[(1 - sqrt(-4*x**2 - 4*x + 1))/(2*x), (sqrt(-4*x**2 - 4*x + 1) + 1)/(2*x)]
First solution G(x) = 1 + 2*x + 4*x**2 + 12*x**3 + 40*x**4 + 144*x**5 + 544*x**6 + 2128*x**7 + 8544*x**8 + 35008*x**9 + O(x**10) 2d solution G(x) = 1/x - 1 - 2*x - 4*x**2 - 12*x**3 - 40*x**4 - 144*x**5 - 544*x**6 - 2128*x**7 - 8544*x**8 - 35008*x**9 + O(x**10) [1 + O(x**52), 2, 4, 12, 40, 144, 544, 2128, 8544, 35008, 145792, 615296, 2625792, 11311616, 49124352, 214838528, 945350144, 4182412288, 18593224704, 83015133184, 372090122240, 1673660915712, 7552262979584, 34178799378432, 155096251351040, 705533929816064, 3216803739664384, 14697663906643968, 67285883401928704, 308597946991247360, 1417760538257522688, 6523879609950076928, 30064851377109467136, 138746816195824713728, 641153552757443526656, 2966493611621557469184, 13741593946629012979712, 63725837416706682650624, 295837567713348211965952, 1374760234138205341876224, 6394620177713789566713856, 29771215840837951027150848, 138724675767751307004215296, 646947142691253321799303168, 3019434407939117723773042688, 14102918112088228830023516160, 65918118131858348222305009664, 308318650681281957474020098048, 1443050558483785877407508987904, 6758314293478709364443450441728, 31670822300738653776902841434112] 50th coefficient = 31670822300738653776902841434112
var('rho')
radius=solve(1-4*rho**2-4*rho,rho)
print("rho =")
display(radius[0])
print("1/rho =")
display(simplify(1/radius[0]))
rho =
1/rho =
def u_n(n):
if n==1:
return Rational(1,4)
else:
return Rational(1,3+u_n(n-1))
for n in range(1,27):
print(n,'---',u_n(n))
print(N(u_n(25)))
1 --- 1/4 2 --- 4/13 3 --- 13/43 4 --- 43/142 5 --- 142/469 6 --- 469/1549 7 --- 1549/5116 8 --- 5116/16897 9 --- 16897/55807 10 --- 55807/184318 11 --- 184318/608761 12 --- 608761/2010601 13 --- 2010601/6640564 14 --- 6640564/21932293 15 --- 21932293/72437443 16 --- 72437443/239244622 17 --- 239244622/790171309 18 --- 790171309/2609758549 19 --- 2609758549/8619446956 20 --- 8619446956/28468099417 21 --- 28468099417/94023745207 22 --- 94023745207/310539335038 23 --- 310539335038/1025641750321 24 --- 1025641750321/3387464586001 25 --- 3387464586001/11188035508324 26 --- 11188035508324/36951571110973 0.302775637731995