{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "using LinearAlgebra" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Fibonacci recurrence\n", "\n", "The [Fibonacci numbers](https://en.wikipedia.org/wiki/Fibonacci_number) are:\n", "\n", "$$\n", "1,1,2,3,5,8,13,21,34,\\ldots\n", "$$\n", "\n", "Each number $f_n$ in the sequence is the sum of the previous two, defining the [recurrence relation](https://en.wikipedia.org/wiki/Recurrence_relation):\n", "\n", "$$\n", "f_n = f_{n-1} + f_{n-2}\n", "$$\n", "\n", "Perhaps the most obvious way to implement this in a programming language is via [recursion](https://en.wikipedia.org/wiki/Recursion_(computer_science)):" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "slowfib (generic function with 1 method)" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "function slowfib(n)\n", " if n < 2\n", " return BigInt(1) # use bigint type to support huge integers\n", " else\n", " return slowfib(n-1) + slowfib(n-2)\n", " end\n", "end" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that there is a slight catch: we have to make sure to do our computations with the `BigInt` integer type, which implements [arbitrary precision arithmetic](https://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic). The Fibonacci numbers quickly get so big that they [overflow](https://en.wikipedia.org/wiki/Integer_overflow) the maximum representable integer using the default (fast, fixed numbrer of binary digits) hardware integer type." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "10-element Vector{BigInt}:\n", " 1\n", " 2\n", " 3\n", " 5\n", " 8\n", " 13\n", " 21\n", " 34\n", " 55\n", " 89" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[slowfib(n) for n = 1:10]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Not that it matters for toy calculations like this, but there are much faster ways to compute Fibonacci numbers than the [recursive](https://en.wikipedia.org/wiki/Recursion) function defined above. The [GMP library](https://en.wikipedia.org/wiki/GNU_Multiple_Precision_Arithmetic_Library) used internally by Julia for `BigInt` arithmetic actually provides an [optimized Fibonacci-calculating function `mpz_fib_ui`](https://gmplib.org/manual/Number-Theoretic-Functions.html) that we can call if we want to using the low-level [`ccall` technique](https://docs.julialang.org/en/latest/manual/calling-c-and-fortran-code.html):" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "fastfib (generic function with 1 method)" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "function fastfib(n)\n", " z = BigInt()\n", " ccall((:__gmpz_fib_ui, :libgmp), Cvoid, (Ref{BigInt}, Culong), z, n)\n", " return z\n", "end" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "100-element Vector{BigInt}:\n", " 1\n", " 1\n", " 2\n", " 3\n", " 5\n", " 8\n", " 13\n", " 21\n", " 34\n", " 55\n", " 89\n", " 144\n", " 233\n", " ⋮\n", " 1779979416004714189\n", " 2880067194370816120\n", " 4660046610375530309\n", " 7540113804746346429\n", " 12200160415121876738\n", " 19740274219868223167\n", " 31940434634990099905\n", " 51680708854858323072\n", " 83621143489848422977\n", " 135301852344706746049\n", " 218922995834555169026\n", " 354224848179261915075" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[fastfib(i) for i = 1:100]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It's about 1000x faster even for the 20th Fibonacci number. It turns out that the recursive algorithm is pretty terrible — the [time increases exponentially with `n`](https://www.youtube.com/watch?v=pqivnzmSbq4)." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " 0.000002 seconds (2 allocations: 40 bytes)\n", " 0.000002 seconds (2 allocations: 40 bytes)\n", " 0.000002 seconds (2 allocations: 40 bytes)\n", " 0.000628 seconds (43.78 k allocations: 940.625 KiB)\n", " 0.000650 seconds (43.78 k allocations: 940.625 KiB)\n", " 0.007222 seconds (43.78 k allocations: 940.625 KiB, 74.82% gc time)\n" ] }, { "data": { "text/plain": [ "10946" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "@time fastfib(20)\n", "@time fastfib(20)\n", "@time fastfib(20)\n", "@time slowfib(20)\n", "@time slowfib(20)\n", "@time slowfib(20)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Fibonacci as matrices" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can represent the Fibonacci recurrence as repeated multiplication by a $2 \\times 2$ matrix, since:\n", "\n", "$$\n", "\\begin{pmatrix} f_{n+1} \\\\ f_n \\end{pmatrix} = \n", "\\underbrace{\\begin{pmatrix} 1 & 1 \\\\ 1 & 0 \\end{pmatrix}}_F\n", "\\begin{pmatrix} f_{n} \\\\ f_{n-1} \\end{pmatrix}\n", "$$" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2×2 Matrix{Int64}:\n", " 1 1\n", " 1 0" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "F = [1 1\n", " 1 0]" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2-element Vector{Int64}:\n", " 34\n", " 21" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "F^7 * [1,1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So, plugging in $f_1 = 1, f_2 = 1$, then\n", "\n", "$$\n", "\\begin{pmatrix} f_{n+2} \\\\ f_{n+1} \\end{pmatrix} = \n", "F^n\n", "\\begin{pmatrix} 1 \\\\ 1 \\end{pmatrix}\n", "$$\n", "\n", "and the key to understanding $F^n$ is the eigenvalues of $F$:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2-element Vector{Float64}:\n", " -0.6180339887498948\n", " 1.618033988749895" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "eigvals(F)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Analytically, we can easily solve this $2 \\times 2$ eigenproblem to show that the eigenvalues are $(1 \\pm \\sqrt{5})/2$ (just the roots of the quadratic characteristic polynomial $\\det (F-\\lambda I) = \\lambda^2 - \\lambda - 1$):" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1.618033988749895" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(1 + √5)/2" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "-0.6180339887498949" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(1 - √5)/2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For example, to compute $f_{100}$, we can multiply $F^{98}$ by $(1,1)$ (again converting to `BigInt` using `big` first to avoid overflow):" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2-element Vector{BigInt}:\n", " 354224848179261915075\n", " 218922995834555169026" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "big.(F)^98 * [1, 1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This matches our `fastfib` function from above:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(354224848179261915075, 218922995834555169026)" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fastfib(100), fastfib(99)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "An important thing about $F^n$ is that, for large $n$, the behavior is dominated by the biggest $|\\lambda|$. That is, for large $n$, we must have $(f_{n}, f_{n-1})$ approximately parallel to the corresponding eigenvector, and hence:\n", "\n", "$$\n", "\\begin{pmatrix} f_{n+1} \\\\ f_{n} \\end{pmatrix} =\n", "F \\begin{pmatrix} f_{n} \\\\ f_{n-1} \\end{pmatrix}\n", "\\approx \n", "\\lambda_1\n", "\\begin{pmatrix} f_{n} \\\\ f_{n-1} \\end{pmatrix}\n", "$$\n", "\n", "where $\\lambda_1 = (1 + \\sqrt{5})/2$ is the so-called [golden ratio](https://en.wikipedia.org/wiki/Golden_ratio).\n", "\n", "Let's compute the ratios of $f_{n+1}/f_{n}$ and show that they approach the golden ratio:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1.61803398874989484820458683436563811772030917980576286213544862270526046281891" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(1 + √big(5))/2 # golden ratio computed to many digits" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also plot the ratio vs. $n$:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1.618033988749894848204586834365638117720312743963795685753591851088290198698868" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fastfib(101) / fastfib(100)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "Figure(PyObject
)" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "PyObject Text(0.5, 1.0, 'ratios of successive Fibonacci numbers')" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "using PyPlot\n", "plot(1:10, [Float64(fastfib(n+1)/fastfib(n)) for n=1:10], \"ro-\")\n", "plot([0,10], (1+√5)/2 * [1,1], \"k--\")\n", "xlabel(L\"n\")\n", "ylabel(L\"f_{n+1}/f_n\")\n", "title(\"ratios of successive Fibonacci numbers\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Clearly, it converges rapidly as expected!\n", "\n", "(In fact, it converges exponentially rapidly, with the error going exponentially to zero with $n$. We will discuss this in more detail later when discussing the **power method**.)" ] } ], "metadata": { "@webio": { "lastCommId": null, "lastKernelId": null }, "anaconda-cloud": {}, "kernelspec": { "display_name": "Julia 1.7.1", "language": "julia", "name": "julia-1.7" }, "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", "version": "1.7.1" }, "widgets": { "state": { "8e329874-d1fc-4e80-ad8d-1dbbd5b2474b": { "views": [ { "cell_index": 13 } ] } }, "version": "1.2.0" } }, "nbformat": 4, "nbformat_minor": 2 }