Calculating Fibonacci Numbers with Matrices and Linear Algebra
In this post we solve the Fibonacci sequence using linear algebra. The Fibonacci equation is a second-order difference equation which is a particular type of sequence.
Sequences
A sequence is a (possibly infinite) set of numbers with a defined order.
an=n1, for n=0,1,2,...,
Difference Equations
A difference equation is a type of sequence. A difference equation expresses the value of the sequence relative to the value of another point in the sequence.
xn+1=1.5xn, for n=0,1,2,...,
To evaluate this equation at n=3 we need to know the initial value x0, and evaluate n=1,2,3 in succession. For example, if x0=100:
In the example above, we evaluate the equation recursively. It would be better to be able to evaluate the equation at n=100 without performing 100 calculations. Note that we can also write the equation above in this form:
x3=100×1.5×1.5×1.5=337.5
Solving a difference equation means writing the same equation such that it can be evaluated at a given n without first evaluating n=1,2,etc. The solution to the equation above is:
xn=1.5n×x0, for n=0,1,2,...,
Second Order Difference Equations
The previous example is a first order difference equation because it expresses the value of xn as a function of one other sample, xn−1. A second order difference equation is a function of two other samples, for example
xn+2=1.5xn+1.4xn+1, for n=0,1,2,...,
Fibonacci Numbers
The easiest way to describe the Fibonacci sequence is with a second order difference equation. Assume F0=0 and F1=1
Fk+2=Fk+1+Fk
The first eight Fibonacci numbers are:
Fk=0,1,1,2,3,5,8,13,...
We can solve the sequence with linear algebra. Let us start our sequence with a vector, u0=[10]. Find the next vector in our sequence, u1 like this:
u1=[1110][10]=[11]
More generally:
uk+1=[1110]uk
Note that u0 contains [F1F0].
The key to solving the sequence is in the eigenvalues and eigenvectors of [1110]. We can write u3 as
u3=[1110][1110][1110][10]=[32]=[F4F3]
import numpy as np
fib = np.matrix([[1,1],[1,0]])
u_0 = np.matrix([[1],[0]])
fib * fib * fib * u_0 # The * operator is dot product for np.matrix (but not np.array)
matrix([[3],
[2]])
Eigenvector Solution
The general case of the previous example is:
ukuk=[1110]k[10]=Aku0
We can use eigenvectors and eigenvalues to solve the matrix power (see Eigenvalues and Eigenvectors). First, find the eigenvalues of A:
det1−λ11−λ−λ(1−λ)−1λ2−λ−1=0=0=0
Solve using the quadratic formula 2a−b±b2−4ac⟹21±5≈21±2.236, which gives the eigenvalues for our matrix:
λ1λ2≈≈1.618−0.618
Now we plug our constant eigenvalues (λ1 and λ2) into (A−λI)x=0 to find the eigenvectors.
[1−λ111−λ1]x1=0⟹x1=[λ11]
Note that this solution is not necessarily intuitive. This is not a valid solution for any arbitrary value of λ: our values, λ1 and λ2 are valid solutions. We can use the same process to solve for λ2, revealing eigenvectors [λ11] and [λ21]. Now create the eigenvector matrix, S and eigenvalue matrix, Λ.
SΛ=[λ11λ21]=[λ100λ2]
Remember that Ak=S−1ΛkS. To proceed, invert S. Remember this shortcut for inverting a 2×2 matrix.