Linear 2nd order difference equation example: Fibonacci numbers
Fibonacci number sequence is a sequence where each number is a sum of the
previous two numbers: 1, 1, 2, 3, 5, 8, 13, 21, ....
Therefore, it corresponds to a difference equation Fn+2 = Fn+1 + Fn
or, equivalently, one can also write this as Fn = Fn-1 + Fn-2
with initial conditions F0=1, F1=1.
Fibonacci is an Italian mathematician who came up with this sequence in
year 1202, as a simple model of rabbit reproduction. Fibonacci sequence has a lot
of interesting properties. If you are curious, there is a lot of information
on the web, for instance
here and also
here
Now that we know how to solve linear 2-nd order difference equations, we can find Fn
for
any n
. As you learned last week, such solution has the form:
Fn = c1 r1n + c2 r2n
where r1
and r2
are solutions of the quadratic equation obtained from the
original difference equation:
r2 = r + 1
It is easy to see that r1 = (1 + sqrt(5)) / 2
and r2 = (1 - sqrt(5)) / 2
.
Now we only have to find c1
and c2
, using the initial conditions:
F0 = c1 r10 + c2 r20 =
c1 + c2 = 1
and
F1 = c1 r1 + c2 r2 = 1
The first equation yields c2 = 1 - c1
. Plugging this value into the 2nd equation, we get
c2 = (1 - r2) / (r1 - r2) = r1 / sqrt(5)
Now let us finally write a Matlab program that calculates our solution
Fn = c1 r1n + c2 r2n
, and compares
it to the exact result, calculated directly from the definition of the Fibonacci sequence. In order to calculate Fn
directly, let's introduce
variables Fnew=Fn
, Fold=Fn-1
and Folder=Fn-2
, and swap
("rotate") the values of these variables after each iteration:
Folder = 1; Fold = 1;
r1 = (1 + sqrt(5)) / 2; r2 = (1 - sqrt(5) ) / 2;
c1 = r1 / sqrt(5); c2 = 1 - c1;
fprintf('\n n Direct_F(n) Solution_F(n) error \n\n');
for n=2:30
Fnew = Fold + Folder;
Fn = c1 * r1^n + c2 * r2^n;
fprintf('%2d %12d %12.0f %9.1e\n', n, Fnew, Fn, abs(Fnew-Fn));
Folder = Fold;
Fold = Fnew;
end;
Note that this is the most computationally efficient method, but not the simplest one. Here is a simpler way to directly
calculate Fn
, which avoids additional variables Fold
and Folder
:
F(1) = 1; F(2) = 2;
% Note that F2 = F1 + F0 = 2
r1 = (1 + sqrt(5)) / 2; r2 = (1 - sqrt(5) ) / 2;
c1 = r1 / sqrt(5); c2 = 1 - c1;
fprintf('\n n Direct_F(n) Solution_F(n) error \n\n');
for n=3:30
F(n) = F(n-1) + F(n-2);
Fn = c1 * r1^n + c2 * r2^n;
fprintf('%2d %12d %12.0f %9.1e\n', n, F(n), Fn, abs(F(n)-Fn));
end;
The only disadvantage of this second program is that it creates an array F(n)
, where the Fibonacci numbers
will be stored; this uses up memory resources when n
is very large.
Note also that in this case we have to start with term n=3
instead of n=2
, since array indices
must be greater than zero (so an error would result in F(n-2)
when n=2
).
When running these programs, note how quickly the round-off error accumulates.
Non-homogeneous linear 2nd order difference equation
To practice solving non-homogeneous linear difference equations,
we will change slightly the Fibonacci equation by adding a constant 1
to this equation:
Fn = Fn-1 + Fn-2 + 1
The solution will now have the form
Fn = c1 r1n + c2 r2n + c
where r1
and r2
are solutions of the same quadratic equation that we already
solved, while the additional constant c
is the solution of the non-homogeneous equation. Therefore, to find c
,
we plug in Fn=Fn-1=Fn-2=c
into our equation, and obtain
c = c + c + 1
, from which we find c=-1
.
Now, we have to once again determine c1
and c2
using the initial conditions:
F0 = c1 r10 + c2 r20 + c =
c1 + c2 - 1 = 1
and
F1 = c1 r1 + c2 r2 - 1 = 1
The first equation yields c2 = 2 - c1
. Plugging this value into the 2nd equation, we get
c2 = 2 (1 - r2) / (r1 - r2) = 2 r1 / sqrt(5)
.
So our program will now read:
Folder = 1; Fold = 1;
r1 = (1 + sqrt(5)) / 2; r2 = (1 - sqrt(5) ) / 2;
c1 = r1 / sqrt(5); c2 = 1 - c1;
fprintf('\n n Direct_F(n) Solution_F(n) error \n\n');
for n=2:30
Fnew = Fold + Folder;
Fn = c1 * r1^n + c2 * r2^n;
fprintf('%2d %12d %12.0f %9.1e\n', n, Fnew, Fn, abs(Fnew-Fn));
Folder = Fold;
Fold = Fnew;
end;
or, using the simpler but more memory-consuming method:
F(1) = 1; F(2) = 3; % Note that F2 = F1 + F0 + 1 = 3
r1 = (1 + sqrt(5)) / 2; r2 = (1 - sqrt(5) ) / 2;
c1 = 2 * r1 / sqrt(5); c2 = 2 - c1;
fprintf('\n n Direct_F(n) Solution_F(n) error \n\n');
for n=3:30
F(n) = F(n-1) + F(n-2) + 1;
Fn = c1 * r1^n + c2 * r2^n - 1;
fprintf('%2d %12d %12.0f %9.1e\n', n, F(n), Fn, abs(F(n)-Fn));
end;
If you understand these steps, homework #6 will be easy!