{"id":572,"date":"2016-05-31T20:02:29","date_gmt":"2016-05-31T20:02:29","guid":{"rendered":"https:\/\/blogs.mathworks.com\/developer\/?p=572"},"modified":"2016-06-01T22:10:09","modified_gmt":"2016-06-01T22:10:09","slug":"scaling-fibonacci","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/developer\/2016\/05\/31\/scaling-fibonacci\/","title":{"rendered":"Small Fibs Eventually Become Large Fibs &#8211; Another exercise in scaling"},"content":{"rendered":"<div class=\"content\"><p>OK, I had way too much fun writing that <a href=\"https:\/\/blogs.mathworks.com\/developer\/2016\/05\/24\/performance-algorithm-scaling\/\">last blog post<\/a> exploring algorithmic scaling. I want to explore this a bit more with a some \"real\" code, and what is more real than a function to calculate the lovely <a href=\"https:\/\/en.wikipedia.org\/wiki\/Fibonacci_number\">fibonacci number<\/a>, the darling of interview questions, algorithms classes, and <a href=\"https:\/\/blogs.mathworks.com\/loren\/2006\/05\/17\/fibonacci-and-filter\">our<\/a> <a href=\"https:\/\/blogs.mathworks.com\/loren\/2013\/09\/22\/timing-code\">own<\/a> <a href=\"https:\/\/blogs.mathworks.com\/loren\/2006\/05\/24\/programming-for-multiple-datatypes\/\">previous<\/a> <a href=\"https:\/\/blogs.mathworks.com\/cleve\/2012\/06\/03\/fibonacci-matrices\/\">blogs<\/a>. This will be fun to explore not only to cement the method we are using to explore scalability, but also because it is fun to see how fast and elegantly the fibonacci function can be written in MATLAB.<\/p><p>First, let's look at the most obvious solution based on the definition directly:<\/p><pre class=\"language-matlab\">\r\n<span class=\"keyword\">function<\/span> f = fibonacci1(n)\r\n\r\n<span class=\"keyword\">if<\/span> n &lt; 1\r\n    f = 0;\r\n<span class=\"keyword\">elseif<\/span> n &lt; 3\r\n    f = 1;\r\n<span class=\"keyword\">else<\/span>\r\n    f = fibonacci1(n-1) + fibonacci1(n-2);\r\n<span class=\"keyword\">end<\/span>\r\n\r\n<span class=\"keyword\">end<\/span>\r\n\r\n<\/pre><p>This is very nice and readable and reads exactly like the definition of fibonacci numbers, but we will see that unfortunately it is not very efficient at all. This is not efficient because the recursive approach needs to continually recalculate lower values of $n$      .<\/p><p>Let's create a parameterized test to invoke this algorithm. As I mentioned, this solution explodes pretty quickly so I am just going to take 10 linearly spaced points from 0 to 25. Also note that the calculation is fast for small n so we need to do this in a loop to get valid measurements.<\/p><pre class=\"language-matlab\">\r\n<span class=\"keyword\">classdef<\/span> FirstFibonacciTest &lt; matlab.perftest.TestCase\r\n    \r\n    \r\n    <span class=\"keyword\">properties<\/span>(TestParameter)\r\n        size = num2cell(round(linspace(0,25,10)));\r\n    <span class=\"keyword\">end<\/span>\r\n    \r\n    \r\n    <span class=\"keyword\">methods<\/span>(Test)\r\n        <span class=\"keyword\">function<\/span> testFibonacci(~, size)\r\n            <span class=\"keyword\">for<\/span> idx = 1:1000\r\n                fibonacci1(size);\r\n            <span class=\"keyword\">end<\/span>\r\n        <span class=\"keyword\">end<\/span>\r\n    <span class=\"keyword\">end<\/span>\r\n<span class=\"keyword\">end<\/span>\r\n\r\n\r\n<\/pre><p>How does it do?<\/p><pre class=\"codeinput\">recursiveResult = runperf(<span class=\"string\">'FirstFibonacciTest'<\/span>);\r\n\r\nfindMins = @(resultArray) arrayfun(@(result) min(result.Samples.MeasuredTime), resultArray);\r\n\r\nax = axes(<span class=\"string\">'XScale'<\/span>,<span class=\"string\">'log'<\/span>,<span class=\"string\">'YScale'<\/span>,<span class=\"string\">'log'<\/span>);\r\nylabel(<span class=\"string\">'Execution time (s)'<\/span>);\r\nxlabel(<span class=\"string\">'Problem Size'<\/span>);\r\nhold <span class=\"string\">on<\/span>;\r\ngrid <span class=\"string\">on<\/span>;\r\n\r\nproblemSize = linspace(0,25,10);\r\nplot(ax, problemSize, findMins(recursiveResult), <span class=\"string\">'LineWidth'<\/span>, 2)\r\nleg = legend({<span class=\"string\">'Recursive'<\/span>});\r\n<\/pre><pre class=\"codeoutput\">Running FirstFibonacciTest\r\n..........\r\n..........\r\n..........\r\n..........\r\n..........\r\n..........\r\n..........\r\n..........\r\n.\r\nDone FirstFibonacciTest\r\n__________\r\n\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/developer\/files\/y2016PerfFibonacci_01.png\" alt=\"\"> <p>$\\mathcal{O}(2^n)$. Exponential. Problem sizes larger than 25 quickly become unproductive.<\/p><p>Well, what's the next approach? A common solution to calculate fibonacci numbers is to recognize that we don't need to recalculate $n-1$ and $n-2$ for every single $n$. Rather, we can just store these values into an array and calculate the number <i>iteratively<\/i>. Note this is actually a simple form of dynamic programming as it holds on to previous solutions of the problem in memory and it uses these prior solutions to calculate subsequent values. In essence we get some pretty substantial efficency gains because we leverage memory to our advantage. How does this look? We can just store the $nth$ fibonacci number along with those for $n+1$ and $n+2$ in a three element array and work through each of the fibonacci numbers iteratively continually updating our 3 element vector as we go.<\/p><pre class=\"language-matlab\">\r\n<span class=\"keyword\">function<\/span> f = fibonacci2(n)\r\n\r\nvalues = [0 1 1];\r\n<span class=\"keyword\">for<\/span> q = 1:n\r\n    values(1:2) = values(2:3);\r\n    values(3) = sum(values(1:2));\r\n<span class=\"keyword\">end<\/span>\r\nf = values(1);\r\n\r\n<span class=\"keyword\">end<\/span>\r\n\r\n<\/pre><p>To observe how it scales I am going to modify our test to pass the algorithm in as another test parameter so we can reuse the test we have already written and ensure consistency of our measurements. We don't want one algorithm to be measured using a loop of 1000 and another accidently measured using a loop of 2000.<\/p><p>The test looks the same with the addition of the algorithm test parameter which contains function handles to our different fibonacci implementations.<\/p><pre class=\"language-matlab\">\r\n<span class=\"keyword\">classdef<\/span> SecondFibonacciTest &lt; matlab.perftest.TestCase\r\n    \r\n    \r\n    <span class=\"keyword\">properties<\/span>(TestParameter)\r\n        algorithm = struct(<span class=\"keyword\">...<\/span>\r\n            <span class=\"string\">'Recursive'<\/span>, @fibonacci1, <span class=\"keyword\">...<\/span>\r\n            <span class=\"string\">'Iterative'<\/span>, @fibonacci2);\r\n            \r\n        size = num2cell(round(linspace(0,25,10)));\r\n    <span class=\"keyword\">end<\/span>\r\n    \r\n    \r\n    <span class=\"keyword\">methods<\/span>(Test)\r\n        <span class=\"keyword\">function<\/span> testFibonacci(~, algorithm, size)\r\n            <span class=\"keyword\">for<\/span> idx = 1:1000\r\n                algorithm(size);\r\n            <span class=\"keyword\">end<\/span>\r\n        <span class=\"keyword\">end<\/span>\r\n    <span class=\"keyword\">end<\/span>\r\n<span class=\"keyword\">end<\/span>\r\n\r\n\r\n<\/pre><p>Note that I have used the struct syntax to define the parameter which allows us to give nice names like \"Recursive\" and \"Iterative\" to each of the parameter values. This also allows us to select just these parameters and run the exact subset of interest, in this case, the iterative algorithm.<\/p><pre class=\"codeinput\">iterativeResult = runperf(<span class=\"string\">'SecondFibonacciTest'<\/span>, <span class=\"string\">'ParameterName'<\/span>, <span class=\"string\">'Iterative'<\/span>);\r\nplot(ax, problemSize, findMins(iterativeResult), <span class=\"string\">'LineWidth'<\/span>, 2)\r\nleg = legend([leg.String, <span class=\"string\">'Iterative'<\/span>]);\r\n<\/pre><pre class=\"codeoutput\">Running SecondFibonacciTest\r\n..........\r\n..........\r\n..........\r\n..........\r\n..........\r\n..........\r\n..........\r\n..........\r\n...\r\nDone SecondFibonacciTest\r\n__________\r\n\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/developer\/files\/y2016PerfFibonacci_02.png\" alt=\"\"> <p>Alright we now see the iterative approaches scales linearly ($\\mathcal{O}(n)$)) which us much nicer, but as it turns out we can do better with a closed form solution using <a href=\"https:\/\/en.wikipedia.org\/wiki\/Jacques_Philippe_Marie_Binet\">Binet's formula<\/a>:<\/p><p>$$f_n = \\frac{(1 + \\sqrt{5})^n - (1 - \\sqrt{5})^n}{2^n \\sqrt{5}}$$<\/p><p>Here is how we code that up in MATLAB:<\/p><pre class=\"language-matlab\">\r\n<span class=\"keyword\">function<\/span> f = fibonacci3(n)\r\nsqrt5 = sqrt(5);\r\nnum = (1 + sqrt5)^n - (1 - sqrt5)^n; \r\ndenom = (2^n)*sqrt5;\r\nf = num\/denom;\r\n<span class=\"keyword\">end<\/span>\r\n\r\n<\/pre><p>...and now we can simply add this new algorithm as new parameter to our existing test:<\/p><pre class=\"language-matlab\"><span class=\"keyword\">properties<\/span>(TestParameter)\r\n    size = num2cell(round(linspace(0,25,10)));\r\n    algorithm = struct(<span class=\"keyword\">...<\/span>\r\n        <span class=\"string\">'Recursive'<\/span>, @fibonacci1, <span class=\"keyword\">...<\/span>\r\n        <span class=\"string\">'Iterative'<\/span>, @fibonacci2, <span class=\"keyword\">...<\/span>\r\n        <span class=\"string\">'ClosedForm'<\/span>, @fibonacci3);\r\n<span class=\"keyword\">end<\/span>\r\n<\/pre><p>and runperf it!<\/p><pre class=\"codeinput\">closedFormResult = runperf(<span class=\"string\">'FibonacciTest'<\/span>, <span class=\"string\">'ParameterName'<\/span>, <span class=\"string\">'ClosedForm'<\/span>);\r\nplot(ax, problemSize, findMins(closedFormResult), <span class=\"string\">'LineWidth'<\/span>, 2)\r\nleg = legend([leg.String, <span class=\"string\">'Closed Form'<\/span>]);\r\n<\/pre><pre class=\"codeoutput\">Running FibonacciTest\r\n..........\r\n..........\r\n..........\r\n..........\r\n..........\r\n..........\r\n..........\r\n..........\r\n.\r\nDone FibonacciTest\r\n__________\r\n\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/developer\/files\/y2016PerfFibonacci_03.png\" alt=\"\"> <p>That is looking very nice! In fact it demonstrates $\\mathcal{O}(1)$ constant behavior. Can't get much better than that from a complexity perspective. However, there is one more solution I'd like to show using matrix exponentials. Hmmmm, I seem to remember hearing somewhere that MATLAB is pretty good with matrices. Does that sound familiar? Well lucky us, because the solution is  quite trivial with the power of MATLAB. This is because the $nth$ fibonacci number $f_n$ is governed by the following equation:<\/p><p>$$ \\left[\r\n  \\begin{array}{cc}\r\n      1 &amp; 1 \\\\\r\n      1 &amp; 0\r\n  \\end{array} \\right]^n\r\n  =\r\n\\left[\r\n  \\begin{array}{cc}\r\n      f_{n+1} &amp; f_n \\\\\r\n      f_n &amp; f_{n-1}\r\n  \\end{array} \\right] $$<\/p><p>Yes, that's right, the solution in MATLAB is just that simple.<\/p><pre class=\"language-matlab\">\r\n<span class=\"keyword\">function<\/span> f = fibonacci4(n)\r\n\r\nF = [1 1;1 0]^n;\r\nf = F(1,2);\r\n\r\n<span class=\"keyword\">end<\/span>\r\n\r\n<\/pre><p>How does this scale? Add the test and run it.<\/p><pre class=\"language-matlab\"><span class=\"keyword\">properties<\/span>(TestParameter)\r\n    size = num2cell(round(linspace(0,25,10)));\r\n    algorithm = struct(<span class=\"keyword\">...<\/span>\r\n        <span class=\"string\">'Recursive'<\/span>, @fibonacci1, <span class=\"keyword\">...<\/span>\r\n        <span class=\"string\">'Iterative'<\/span>, @fibonacci2, <span class=\"keyword\">...<\/span>\r\n        <span class=\"string\">'ClosedForm'<\/span>, @fibonacci3, <span class=\"keyword\">...<\/span>\r\n        <span class=\"string\">'MatrixExponential'<\/span>, @fibonacci4);\r\n<span class=\"keyword\">end<\/span>\r\n<\/pre><pre class=\"codeinput\">matrixResult = runperf(<span class=\"string\">'FibonacciTest'<\/span>, <span class=\"string\">'ParameterName'<\/span>, <span class=\"string\">'MatrixExponential'<\/span>);\r\nplot(ax, problemSize, findMins(matrixResult), <span class=\"string\">'LineWidth'<\/span>, 2)\r\nleg = legend([leg.String, <span class=\"string\">'Matrix Exponential'<\/span>]);\r\n<\/pre><pre class=\"codeoutput\">Running FibonacciTest\r\n..........\r\n..........\r\n..........\r\n..........\r\n..........\r\n..........\r\n..........\r\n..........\r\n..........\r\n..........\r\nDone FibonacciTest\r\n__________\r\n\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/developer\/files\/y2016PerfFibonacci_04.png\" alt=\"\"> <p>Look at that! The closed form and the matrix solutions both show very scalable behavior, but the matrix form is not quite as good, showing logarithmic ($\\mathcal{O}(\\log n)$) scaling instead of constant and the constant factor is greater for the matrix case. However, there is another benefit enjoyed by the matrix exponential solution but not by the closed form solution. To show this, I am going to add a quick spot check to this test to confirm that we are actually getting the right answer. Note for this post I am just going to add another test method which validates a single size, but this could be done in the existing test method across all sizes if desired.<\/p><pre class=\"language-matlab\">\r\n<span class=\"keyword\">classdef<\/span> VerifiedFibonacciTest &lt; matlab.perftest.TestCase\r\n    \r\n    \r\n    <span class=\"keyword\">properties<\/span>(TestParameter)\r\n        size = num2cell(round(linspace(0,25,10)));\r\n        algorithm = struct(<span class=\"keyword\">...<\/span>\r\n            <span class=\"string\">'Recursive'<\/span>, @fibonacci1, <span class=\"keyword\">...<\/span>\r\n            <span class=\"string\">'Iterative'<\/span>, @fibonacci2, <span class=\"keyword\">...<\/span>\r\n            <span class=\"string\">'ClosedForm'<\/span>, @fibonacci3, <span class=\"keyword\">...<\/span>\r\n            <span class=\"string\">'MatrixExponential'<\/span>, @fibonacci4);           \r\n    <span class=\"keyword\">end<\/span>\r\n    \r\n    \r\n    <span class=\"keyword\">methods<\/span>(Test)\r\n        <span class=\"keyword\">function<\/span> testFibonacci(~, algorithm, size)\r\n            <span class=\"keyword\">for<\/span> idx = 1:1000\r\n                algorithm(size);\r\n            <span class=\"keyword\">end<\/span>\r\n        <span class=\"keyword\">end<\/span>\r\n        <span class=\"keyword\">function<\/span> testCorrectAnswer(testCase, algorithm)\r\n           testCase.verifyEqual(algorithm(16), 987, <span class=\"keyword\">...<\/span>\r\n               <span class=\"string\">'The 16th fibonacci number should be 987'<\/span>); \r\n        <span class=\"keyword\">end<\/span>\r\n    <span class=\"keyword\">end<\/span>\r\n<span class=\"keyword\">end<\/span>\r\n\r\n\r\n<\/pre><p>Let's run it with <b><tt>runtests<\/tt><\/b> to confirm correctness.<\/p><pre class=\"codeinput\">result = runtests(<span class=\"string\">'VerifiedFibonacciTest'<\/span>)\r\n<\/pre><pre class=\"codeoutput\">Running VerifiedFibonacciTest\r\n..........\r\n..........\r\n..........\r\n..........\r\n..\r\n================================================================================\r\nVerification failed in VerifiedFibonacciTest\/testCorrectAnswer(algorithm=ClosedForm).\r\n\r\n    ----------------\r\n    Test Diagnostic:\r\n    ----------------\r\n    The 16th fibonacci number should be 987\r\n\r\n    ---------------------\r\n    Framework Diagnostic:\r\n    ---------------------\r\n    verifyEqual failed.\r\n    --&gt; The values are not equal using \"isequaln\".\r\n    --&gt; Failure table:\r\n                Actual    Expected           Error               RelativeError    \r\n                ______    ________    ____________________    ____________________\r\n            \r\n                987       987         4.54747350886464e-13    4.60736930989325e-16\r\n    \r\n    Actual double:\r\n             9.870000000000005e+02\r\n    Expected double:\r\n           987\r\n\r\n    ------------------\r\n    Stack Information:\r\n    ------------------\r\n    In \/mathworks\/inside\/files\/dev\/tools\/tia\/mdd\/performanceScaling\/VerifiedFibonacciTest.m (VerifiedFibonacciTest.testCorrectAnswer) at 21\r\n================================================================================\r\n..\r\nDone VerifiedFibonacciTest\r\n__________\r\n\r\nFailure Summary:\r\n\r\n     Name                                                           Failed  Incomplete  Reason(s)\r\n    ============================================================================================================\r\n     VerifiedFibonacciTest\/testCorrectAnswer(algorithm=ClosedForm)    X                 Failed by verification.\r\n    \r\n\r\nresult = \r\n\r\n  1x44 TestResult array with properties:\r\n\r\n    Name\r\n    Passed\r\n    Failed\r\n    Incomplete\r\n    Duration\r\n    Details\r\n\r\nTotals:\r\n   43 Passed, 1 Failed, 0 Incomplete.\r\n   7.3549 seconds testing time.\r\n\r\n<\/pre><p>...and there is the problem with the closed form solution. It is subject to floating point precision errors. Of course we can simply make this test pass by leveraging a tolerance in verifyEqual<\/p><pre class=\"language-matlab\">testCase.verifyEqual(algorithm(16), 987, <span class=\"string\">'RelTol'<\/span>, 1e-14<span class=\"keyword\">...<\/span>\r\n    <span class=\"string\">'The 16th fibonacci number should be 987'<\/span>);\r\n<\/pre><p>but the fact remains that using the closed form solution we compute something that is close to the $nth$ fibonacci number, but the matrix solution computes it exactly. Which one to use depends on your application, but given the constant factor is so small and logarithmic behavior approaches constant for large problem sizes I think I would tend to choose the exact solution. How about you?<\/p><script language=\"JavaScript\"> <!-- \r\n    function grabCode_73aa95edc17442aa9538e38bc645ca2c() {\r\n        \/\/ Remember the title so we can use it in the new page\r\n        title = document.title;\r\n\r\n        \/\/ Break up these strings so that their presence\r\n        \/\/ in the Javascript doesn't mess up the search for\r\n        \/\/ the MATLAB code.\r\n        t1='73aa95edc17442aa9538e38bc645ca2c ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 73aa95edc17442aa9538e38bc645ca2c';\r\n    \r\n        b=document.getElementsByTagName('body')[0];\r\n        i1=b.innerHTML.indexOf(t1)+t1.length;\r\n        i2=b.innerHTML.indexOf(t2);\r\n \r\n        code_string = b.innerHTML.substring(i1, i2);\r\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\r\n\r\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \r\n        \/\/ in the XML parser.\r\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\r\n        \/\/ doesn't go ahead and substitute the less-than character. \r\n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\r\n\r\n        copyright = 'Copyright 2016 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add copyright line at the bottom if specified.\r\n        if (copyright.length > 0) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\\n');\r\n\r\n        d.title = title + ' (MATLAB code)';\r\n        d.close();\r\n    }   \r\n     --> <\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_73aa95edc17442aa9538e38bc645ca2c()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n      the MATLAB code <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; R2016a<br><\/p><\/div><!--\r\n73aa95edc17442aa9538e38bc645ca2c ##### SOURCE BEGIN #####\r\n%%\r\n% \r\n% OK, I had way too much fun writing that\r\n% <https:\/\/blogs.mathworks.com\/developer\/2016\/05\/24\/performance-algorithm-scaling\/\r\n% last blog post> exploring algorithmic scaling. I want to explore this a\r\n% bit more with a some \"real\" code, and what is more real than a function\r\n% to calculate the lovely <https:\/\/en.wikipedia.org\/wiki\/Fibonacci_number\r\n% fibonacci number>, the darling of interview questions and algorithms\r\n% classes. This will be fun to explore not only to cement the method we are\r\n% using to explore scalability, but also because it is fun to see how fast\r\n% and elegantly the fibonacci function can be written in MATLAB.\r\n%\r\n% First, let's look at the most obvious solution based on the definition\r\n% directly:\r\n%\r\n% <include>fibonacci1<\/include>\r\n%\r\n% This is very nice and readable and reads exactly like the definition of\r\n% fibonacci numbers, but we will see that unfortunately it is not very\r\n% efficient at all. This is not efficient because the recursive approach\r\n% needs to continually recalculate lower values of $n$      .\r\n%\r\n% Let's create a parameterized test to invoke this algorithm. As I\r\n% mentioned, this solution explodes pretty quickly so I am just going to\r\n% take 10 linearly spaced points from 0 to 25. Also note that the\r\n% calculation is fast for small n so we need to do this in a\r\n% loop to get valid measurements.\r\n%\r\n% <include>FirstFibonacciTest<\/include>\r\n%\r\n% How does it do?\r\nrecursiveResult = runperf('FirstFibonacciTest');\r\n\r\nfindMins = @(resultArray) arrayfun(@(result) min(result.Samples.MeasuredTime), resultArray);\r\n\r\nax = axes('XScale','log','YScale','log');\r\nylabel('Execution time (s)');\r\nxlabel('Problem Size');\r\nhold on;\r\ngrid on;\r\n\r\nproblemSize = linspace(0,25,10);\r\nplot(ax, problemSize, findMins(recursiveResult), 'LineWidth', 2)\r\nleg = legend({'Recursive'});\r\n\r\n%% \r\n% $\\mathcal{O}(2^n)$. Exponential. Problem sizes larger than 25 quickly become unproductive.\r\n%\r\n% Well, what's the next approach? A common solution to calculate fibonacci\r\n% numbers is to recognize that we don't need to recalculate $n-1$ and $n-2$\r\n% for every single $n$. Rather, we can just store these values into an array\r\n% and calculate the number _iteratively_. Note this is actually a simple\r\n% form of dynamic programming as it holds on to previous solutions of the\r\n% problem in memory and it uses these prior solutions to calculate\r\n% subsequent values. In essence we get some pretty substantial efficency gains\r\n% because we leverage memory to our advantage. How does this look? We can\r\n% just store the $nth$ fibonacci number along with those for $n+1$ and\r\n% $n+2$ in a three element array and work through each of the fibonacci\r\n% numbers iteratively continually updating our 3 element vector as we go.\r\n%\r\n% <include>fibonacci2<\/include>\r\n%\r\n% To observe how it scales I am going to modify our test to pass the\r\n% algorithm in as another test parameter so we can reuse the test we have\r\n% already written and ensure consistency of our measurements. We don't want\r\n% one algorithm to be measured using a loop of 1000 and another accidently\r\n% measured using a loop of 2000.\r\n%\r\n% The test looks the same with the addition of the algorithm test parameter\r\n% which contains function handles to our different fibonacci\r\n% implementations. \r\n%\r\n% <include>SecondFibonacciTest<\/include>\r\n%\r\n% Note that I have used the struct syntax to define the parameter which\r\n% allows us to give nice names like \"Recursive\" and \"Iterative\" to each of\r\n% the parameter values. This also allows us to select just these parameters\r\n% and run the exact subset of interest, in this case, the iterative\r\n% algorithm.\r\niterativeResult = runperf('SecondFibonacciTest', 'ParameterName', 'Iterative');\r\nplot(ax, problemSize, findMins(iterativeResult), 'LineWidth', 2)\r\nleg = legend([leg.String, 'Iterative']);\r\n\r\n%%\r\n% Alright we now see the iterative approaches scales linearly\r\n% ($\\mathcal{O}(n)$)) which us much nicer, but as it turns out we can do\r\n% better with a closed form solution using\r\n% <https:\/\/en.wikipedia.org\/wiki\/Jacques_Philippe_Marie_Binet Binet's\r\n% formula>:\r\n%\r\n% $$f_n = \\frac{(1 + \\sqrt{5})^n - (1 - \\sqrt{5})^n}{2^n \\sqrt{5}}$$\r\n%\r\n% Here is how we code that up in MATLAB:\r\n%\r\n% <include>fibonacci3<\/include>\r\n%\r\n% ...and now we can simply add this new algorithm as new parameter to our\r\n% existing test:\r\n% \r\n%   properties(TestParameter)\r\n%       size = num2cell(round(linspace(0,25,10)));\r\n%       algorithm = struct(...\r\n%           'Recursive', @fibonacci1, ...\r\n%           'Iterative', @fibonacci2, ...\r\n%           'ClosedForm', @fibonacci3);\r\n%   end\r\n%\r\n% and runperf it!\r\nclosedFormResult = runperf('FibonacciTest', 'ParameterName', 'ClosedForm');\r\nplot(ax, problemSize, findMins(closedFormResult), 'LineWidth', 2)\r\nleg = legend([leg.String, 'Closed Form']);\r\n\r\n%%\r\n% That is looking very nice! In fact it demonstrates $\\mathcal{O}(1)$\r\n% constant behavior. Can't get much better than that from a complexity\r\n% perspective. However, there is one more solution I'd like to show using\r\n% matrix exponentials. Hmmmm, I seem to remember hearing somewhere that\r\n% MATLAB is pretty good with matrices. Does that sound familiar? Well lucky\r\n% us, because the solution is  quite trivial with the power of MATLAB. This\r\n% is because the $nth$ fibonacci number $f_n$ is governed by the following\r\n% equation:\r\n%\r\n% $$ \\left[ \r\n%   \\begin{array}{cc} \r\n%       1 & 1 \\\\ \r\n%       1 & 0 \r\n%   \\end{array} \\right]^n \r\n%   = \r\n% \\left[\r\n%   \\begin{array}{cc} \r\n%       f_{n+1} & f_n \\\\\r\n%       f_n & f_{n-1}\r\n%   \\end{array} \\right] $$\r\n%\r\n% Yes, that's right, the solution in MATLAB is just that simple.\r\n%\r\n% <include>fibonacci4<\/include>\r\n%\r\n% How does this scale? Add the test and run it.\r\n%\r\n%   properties(TestParameter)\r\n%       size = num2cell(round(linspace(0,25,10)));\r\n%       algorithm = struct(...\r\n%           'Recursive', @fibonacci1, ...\r\n%           'Iterative', @fibonacci2, ...\r\n%           'ClosedForm', @fibonacci3, ...\r\n%           'MatrixExponential', @fibonacci4);  \r\n%   end\r\nmatrixResult = runperf('FibonacciTest', 'ParameterName', 'MatrixExponential');\r\nplot(ax, problemSize, findMins(matrixResult), 'LineWidth', 2)\r\nleg = legend([leg.String, 'Matrix Exponential']);\r\n\r\n%%\r\n% Look at that! The closed form and the matrix solutions both show very\r\n% scalable behavior, but the matrix form is not quite as good, showing\r\n% logarithmic ($\\mathcal{O}(\\log n)$) scaling instead of constant and the constant factor is\r\n% greater for the matrix case. However, there is another benefit enjoyed by\r\n% the matrix exponential solution but not by the closed form solution. To\r\n% show this, I am going to add a quick spot check to this test to confirm\r\n% that we are actually getting the right answer. Note for this post I am\r\n% just going to add another test method which validates a single size, but\r\n% this could be done in the existing test method across all sizes if\r\n% desired.\r\n%\r\n% <include>VerifiedFibonacciTest<\/include>\r\n%\r\n% Let's run it with *|runtests|* to confirm correctness.\r\nresult = runtests('VerifiedFibonacciTest')\r\n\r\n%%\r\n% ...and there is the problem with the closed form solution. It is subject\r\n% to floating point precision errors. Of course we can simply make this\r\n% test pass by leveraging a tolerance in verifyEqual\r\n%\r\n%   testCase.verifyEqual(algorithm(16), 987, 'RelTol', 1e-14...\r\n%       'The 16th fibonacci number should be 987'); \r\n%\r\n% but the fact remains that using the closed form solution we compute\r\n% something that is close to the $nth$ fibonacci number, but the matrix\r\n% solution computes it exactly. Which one to use depends on your\r\n% application, but given the constant factor is so small and logarithmic\r\n% behavior approaches constant for large problem sizes I think I would tend\r\n% to choose the exact solution. How about you?\r\n##### SOURCE END ##### 73aa95edc17442aa9538e38bc645ca2c\r\n-->","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img src=\"https:\/\/blogs.mathworks.com\/developer\/files\/y2016PerfFibonacci_04.png\" class=\"img-responsive attachment-post-thumbnail size-post-thumbnail wp-post-image\" alt=\"\" decoding=\"async\" loading=\"lazy\" \/><\/div><p>OK, I had way too much fun writing that last blog post exploring algorithmic scaling. I want to explore this a bit more with a some \"real\" code, and what is more real than a function to calculate the... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/developer\/2016\/05\/31\/scaling-fibonacci\/\">read more >><\/a><\/p>","protected":false},"author":90,"featured_media":611,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[13,7],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/posts\/572"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/users\/90"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/comments?post=572"}],"version-history":[{"count":11,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/posts\/572\/revisions"}],"predecessor-version":[{"id":618,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/posts\/572\/revisions\/618"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/media\/611"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/media?parent=572"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/categories?post=572"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/tags?post=572"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}