{"id":456,"date":"2017-02-02T19:35:23","date_gmt":"2017-02-02T19:35:23","guid":{"rendered":"http:\/\/drsfenner.org\/blog\/?p=456"},"modified":"2017-02-02T19:35:40","modified_gmt":"2017-02-02T19:35:40","slug":"dc-svd-i-just-cant-let-it-go","status":"publish","type":"post","link":"http:\/\/drsfenner.org\/blog\/2017\/02\/dc-svd-i-just-cant-let-it-go\/","title":{"rendered":"DC SVD I:  Just Can&#8217;t Let It Go"},"content":{"rendered":"<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>It&#8217;s been way, way, way too long since I&#8217;ve posted. I haven&#8217;t been slacking though, I&#8217;ve merely been busy. Really.<\/p>\n<p>I decided to dive back into the SVD problem and look at an alternative to the QR based SVD computations. Namely, I&#8217;m going to give a breakdown of the <em>divide-and-conquer<\/em> approach to computing the SVD. Similar to the relationship between bidiagonal SVD and tridiagonal QR decompositions, there is a close relationship between dividing-and-conquering QR and SVD. I&#8217;m going to start from &quot;the inside out&quot; with the innermost task of DC (divide-and-conquer) process: solving a particular equation known as the secular equation (secular meaning &quot;not heavenly&quot; &#8211; i.e., earthly or planetly &#8211; check it out on wikipedia).<\/p>\n<p>One note: I feel very guilty about still using Python 2. I had intented to transition this project to Python 3 over the course of the last year. Alas, my major training clients over the last year were using Python 2 and I didn&#8217;t really want to have a mixed development environment on my laptop. Well, at least there&#8217;s something to do if I make a book out of these posts!<\/p>\n<p>Enough preamble, let&#8217;s get down to business.<!--more--><\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<h3 id=\"the-secular-equation\">The Secular Equation<\/h3>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>Divide-and-conquer SVD is built on computing the roots of the <em>secular equation<\/em>. The roots, or zeros, of an equation are the <span class=\"math inline\">\\(\\lambda\\)<\/span>s such that <span class=\"math inline\">\\(f(\\lambda) = 0\\)<\/span>. The secular equation is (where we take <span class=\"math inline\">\\(\\rho=1\\)<\/span>): <span class=\"math display\">\\[f(\\lambda) = 1 + \\rho \\sum_{i=1}^n \\frac{z_{i}^2}{d_i &#8211; \\lambda} = 1 + \\sum_{i=1}^n \\frac{z_{i}^2}{d_i &#8211; \\lambda}\\]<\/span><\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>Here is a graph of a secular equation and its roots:<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing code_cell rendered\">\n<div class=\"input\">\n<div class=\"prompt input_prompt\">In&nbsp;[1]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\" highlight hl-ipython2\">\n<pre><span><\/span><span class=\"kn\">import<\/span> <span class=\"nn\">numpy<\/span> <span class=\"kn\">as<\/span> <span class=\"nn\">np<\/span>\n<span class=\"kn\">import<\/span> <span class=\"nn\">numpy.linalg<\/span> <span class=\"kn\">as<\/span> <span class=\"nn\">nla<\/span>\n<span class=\"kn\">import<\/span> <span class=\"nn\">matplotlib.pyplot<\/span> <span class=\"kn\">as<\/span> <span class=\"nn\">plt<\/span>\n<span class=\"o\">%<\/span><span class=\"k\">matplotlib<\/span> inline \n<span class=\"n\">xs<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">linspace<\/span><span class=\"p\">(<\/span><span class=\"o\">-<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"mi\">10<\/span><span class=\"p\">,<\/span><span class=\"mi\">10000<\/span><span class=\"p\">)<\/span>\n\n<span class=\"c1\"># graph secular equation (blue curve)<\/span>\n<span class=\"c1\"># plot z,d --&gt; y<\/span>\n<span class=\"n\">zs<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">array<\/span><span class=\"p\">([<\/span><span class=\"o\">.<\/span><span class=\"mi\">6<\/span><span class=\"p\">,<\/span><span class=\"mf\">1.2<\/span><span class=\"p\">,<\/span><span class=\"mf\">1.8<\/span><span class=\"p\">])<\/span>\n<span class=\"n\">ds<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">array<\/span><span class=\"p\">([<\/span><span class=\"mf\">0.0<\/span><span class=\"p\">,<\/span><span class=\"mi\">3<\/span><span class=\"p\">,<\/span><span class=\"mi\">5<\/span><span class=\"p\">])<\/span>\n<span class=\"k\">with<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">errstate<\/span><span class=\"p\">(<\/span><span class=\"n\">divide<\/span><span class=\"o\">=<\/span><span class=\"s1\">&#39;ignore&#39;<\/span><span class=\"p\">):<\/span>\n    <span class=\"c1\"># plain vanilla to &quot;fancy-schmancy&quot;<\/span>\n    <span class=\"c1\">#ys1 = 1.0 + (1.0 \/ (0.0-xs_sq)) + (4.0 \/ (9-xs_sq)) + (16.0 \/ (25 - xs_sq))<\/span>\n    <span class=\"c1\">#ys2 = 1.0 + (zs[0]**2 \/ (ds[0]**2-xs_sq)) + (zs[1]**2 \/ (ds[1]**2-xs_sq)) + (zs[2]**2 \/ (ds[2]**2 - xs_sq))<\/span>\n    <span class=\"n\">ys3<\/span> <span class=\"o\">=<\/span> <span class=\"mf\">1.0<\/span> <span class=\"o\">+<\/span> <span class=\"p\">((<\/span><span class=\"n\">zs<\/span><span class=\"o\">**<\/span><span class=\"mi\">2<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">reshape<\/span><span class=\"p\">(<\/span><span class=\"mi\">3<\/span><span class=\"p\">,<\/span><span class=\"mi\">1<\/span><span class=\"p\">)<\/span> <span class=\"o\">\/<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">subtract<\/span><span class=\"o\">.<\/span><span class=\"n\">outer<\/span><span class=\"p\">(<\/span><span class=\"n\">ds<\/span><span class=\"p\">,<\/span> <span class=\"n\">xs<\/span><span class=\"p\">))<\/span><span class=\"o\">.<\/span><span class=\"n\">sum<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">)<\/span>\n    <span class=\"c1\"># assert np.allclose(ys1, ys2) and np.allclose(ys2,ys3)<\/span>\n<span class=\"n\">plt<\/span><span class=\"o\">.<\/span><span class=\"n\">plot<\/span><span class=\"p\">(<\/span><span class=\"n\">xs<\/span><span class=\"p\">,<\/span> <span class=\"n\">ys3<\/span><span class=\"p\">)<\/span>\n\n<span class=\"c1\"># add an x-axis (yellow horizontal line)<\/span>\n<span class=\"n\">plt<\/span><span class=\"o\">.<\/span><span class=\"n\">plot<\/span><span class=\"p\">(<\/span><span class=\"n\">xs<\/span><span class=\"p\">,<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">zeros_like<\/span><span class=\"p\">(<\/span><span class=\"n\">xs<\/span><span class=\"p\">),<\/span> <span class=\"s1\">&#39;y-&#39;<\/span><span class=\"p\">)<\/span>\n\n<span class=\"c1\"># add poles\/asymptotes (grey vertical lines)<\/span>\n<span class=\"n\">plt<\/span><span class=\"o\">.<\/span><span class=\"n\">vlines<\/span><span class=\"p\">(<\/span><span class=\"n\">ds<\/span><span class=\"p\">,<\/span> <span class=\"o\">-<\/span><span class=\"mi\">10<\/span><span class=\"p\">,<\/span> <span class=\"mi\">10<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;.75&#39;<\/span><span class=\"p\">)<\/span>\n\n<span class=\"c1\"># add roots (red dots)<\/span>\n<span class=\"c1\"># use equivalent matrix (for these z,d) and eigenvalue computation to find roots<\/span>\n<span class=\"c1\"># ds are diagonal entries, zs are first columns (note, ds[0] is 0.0 by definition)<\/span>\n<span class=\"n\">ROU<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">diag<\/span><span class=\"p\">(<\/span><span class=\"n\">ds<\/span><span class=\"p\">)<\/span> <span class=\"o\">+<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">outer<\/span><span class=\"p\">(<\/span><span class=\"n\">zs<\/span><span class=\"p\">,<\/span> <span class=\"n\">zs<\/span><span class=\"p\">)<\/span>\n<span class=\"c1\">#tm[:,0] = zs<\/span>\n<span class=\"n\">zeros_act<\/span> <span class=\"o\">=<\/span> <span class=\"n\">nla<\/span><span class=\"o\">.<\/span><span class=\"n\">eig<\/span><span class=\"p\">(<\/span><span class=\"n\">ROU<\/span><span class=\"p\">)[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]<\/span>\n<span class=\"n\">plt<\/span><span class=\"o\">.<\/span><span class=\"n\">plot<\/span><span class=\"p\">(<\/span><span class=\"n\">zeros_act<\/span><span class=\"p\">,<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">zeros_like<\/span><span class=\"p\">(<\/span><span class=\"n\">zeros_act<\/span><span class=\"p\">),<\/span> <span class=\"s1\">&#39;r.&#39;<\/span><span class=\"p\">)<\/span>\n\n<span class=\"c1\">#scaling<\/span>\n<span class=\"n\">plt<\/span><span class=\"o\">.<\/span><span class=\"n\">ylim<\/span><span class=\"p\">(<\/span><span class=\"o\">-<\/span><span class=\"mi\">10<\/span><span class=\"p\">,<\/span><span class=\"mi\">10<\/span><span class=\"p\">),<\/span> <span class=\"n\">plt<\/span><span class=\"o\">.<\/span><span class=\"n\">xlim<\/span><span class=\"p\">(<\/span><span class=\"o\">-<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"mi\">10<\/span><span class=\"p\">);<\/span>\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"output_wrapper\">\n<div class=\"output\">\n<div class=\"output_area\">\n<div class=\"prompt\"><\/div>\n<div class=\"output_png output_subarea \">\n<img decoding=\"async\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAhAAAAFkCAYAAABxWwLDAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAAPYQAAD2EBqD+naQAAIABJREFUeJzt3XeYVeW5\/\/\/3A4JUUSygghULNhDsLbEkqCcaNTGIJrZo\niuUYzInRY85J1K+\/aIxRY4lGY6yAHjWKGkRFxYAKKkhvwlCGYZAyDAPDMO35\/XHPDsM4wOyZtfaz\n15rP67r2tZzNlNs9ZX\/2\/TTnvUdEREQkG21CFyAiIiLJowAhIiIiWVOAEBERkawpQIiIiEjWFCBE\nREQkawoQIiIikjUFCBEREcmaAoSIiIhkTQFCREREsqYAISIiIlmLNUA45052zo10zi11ztU6585t\n5H1ud84VOefKnXPvOOf6xFmTiIiItFzcHYjOwBfANcDXDt1wzv0auA74CXAMsB4Y7ZxrH3NdIiIi\n0gIuV4dpOedqgfO89yPr3VcE3OO9v6\/u7R2A5cBl3vsXc1KYiIiIZC3YHAjn3L5AT2BM5j7v\/Vpg\nAnB8qLpERERk27YL+LV7YsMayxvcv7zu3xrlnNsZGAQsBCriKk5ERCSFOgD7AKO996ta8olCBojm\nGgQ8H7oIERGRBLsEGNaSTxAyQBQDDujB5l2IHsDkrXzcQoDnnnuOvn37xlZccz39NDz1FLzxxnqu\nu+46HnroITp37hy6rNQYOnQo9913X9Aarr0WOnaEP\/6x8X9fv349s2bNom\/fvnn\/vc\/l41lZCccf\nD7\/7HZxzTnYfq8e09dLjGa1Zs2bxwx\/+EOqeS1siWIDw3hc454qB04Gp8O9JlMcCD2\/lQysA+vbt\ny4ABA2KvM1ujRkGHDtC\/fxldunShf\/\/+dO3aNXRZqdGtW7fg3\/fqaujTB7ZURllZGTU1NYn43ufy\n8Vy82K7HHbflx25L9Ji2Xno8Y9PiKQCxBgjnXGegD9ZpANjPOdcPWO29XwLcD\/zGOfcllobuAAqB\n1+KsK07V1dCuXegqJE6rVkH37qGrSJ7iYrv23OIMJxFJkrg7EEcB72OTJT1wb939TwNXeu\/\/4Jzr\nBDwG7Aj8CzjLe18Zc12xqaqC7ZI4s0SabPVq2Hnn0FUkjwKESLrE+lTnvR\/LNpaKeu9\/B\/wuzjpy\nSR2IdKuuhtJSdSCao7gY2raFXXYJXYmIREFnYUSsfgfitNNOC1tMCg0ZMiTo11+92q5p6UDk8vFc\ntgx2281CRJqF\/hlNGz2e+UsBImL1OxCnn3562GJSKPQfEwWI5isubh3DF6F\/RtNGj2f+UoCImOZA\npNuqum1XNISRvdYSIERaCwWIiGkORLqlrQORSwoQIumiABExdSDSTR2I5isuht13D12FiERFASJi\n6kCk26pV0KULtNeB81nxXh0IkbRRgIiYOhDppk2kmqe0FCoqFCBE0kQBImLqQKTb8uV6EmyOJUvs\n2qtX2DpEJDoKEBFTByLdli+HHj1CV5E8hYV27d07bB0iEh0FiIipA5FuChDNs2QJtGmj7o1ImihA\nREwdiHRTgGiewkLYYw\/9boikiQJExNSBSC\/vFSCaa8kSzX8QSRsFiIipA5FepaVQWakA0RxLlmj+\ng0jaKEBErKpKHYi0Wr7crhrHz15hoToQImmjABGxjRth++1DVyFxyAQIdSCy4706ECJppAARMQWI\n9FKAaJ41a6C8XB0IkbRRgIiYAkR6LV9uW1h36xa6kmTJbCKlDoRIuihAREwBIr0yKzCcC11JsmQ2\nkVIHQiRdFCAipgCRXkuXwp57hq4ieRYtspVJmnwqki4KEBHbuFEnNaaV9jJonoIC2GsvLW8WSRsF\niIhVVqoDkVaFhRrHb44FC2C\/\/UJXISJRU4CIkPcawkirzFJEdSCypwAhkk4KEBGqqrKrAkT6lJbC\n+vXqQDRHQQHsu2\/oKkQkagoQEdq40a4KEOmTWYqoDkR2SkpsHwh1IETSRwEiQgoQ6aWliM1TUGBX\ndSBE0kcBIkIKEOm1ZAm0aQO77x66kmRZsMCu6kCIpI8CRIQUINKrsNDCg5YiZqegALp2he7dQ1ci\nIlFTgIhQJkBoH4j0WbxYEyibI7MCQ7t3iqSPAkSE1IFILy1FbJ4FCzT\/QSStFCAiVFlpVwWI9Jk\/\nXwGiOebOhQMOCF2FiMRBASJC6kCk04YNUFQE++8fupJk2bDBzsE46KDQlYhIHBQgIqQAkU6ZpYjq\nQGTnyy9tB8+DDw5diYjEQQEiQhUVdlWASJfMUkR1ILIzZ45d1YEQSScFiAiVl9u1c+ewdUi05s+3\nUKg9ILIzZ44t39xll9CViEgcFCAilAkQHTuGrUOilVmB0Ua\/LVmZM0fdB5E005\/ECJWXQ7t2dpP0\n0AqM5lGAEEk3BYgIlZdDp06hq5CozZqliYDZ8t4ChB43kfRSgIhQebnmP6TNhg22CqNv39CVJMvy\n5XYEujoQIumlABEhdSDSZ84cezV9yCGhK0mWWbPsqg6ESHopQERIASJ9Zs60qzoQ2Zk2zVau9OkT\nuhIRiYsCRITWr1eASJtZs2z55o47hq4kWaZOhUMP1emlImmmABEhdSDSZ+ZMDV80x7RpcPjhoasQ\nkTgpQERIASJ9Zs7U8EW2amth+nQFCJG0U4CIkAJEumzYAPPmwWGHha4kWRYssN+FI44IXYmIxEkB\nIkIKEOkybRrU1MCAAaErSZapU+2qDoRIuilAREgBIl0mTYK2bfVEmK1p0+z8ix49QlciInFSgIjQ\n+vXaSCpNJk+2CZQdOoSuJFmmTrXhC+dCVyIicVKAiNDatbDDDqGrkKhMmqThi+aYNAn69w9dhYjE\nTQEiQqWlChBpUVVlr6QVILKzYgUsXAhHHx26EhGJmwJERCoroaICunULXYlEYcYM+54qQGTn88\/t\netRRYesQkfgpQESkrMyu6kCkw0cf2S6KChDZ+ewz27Vz\/\/1DVyIicVOAiMjatXZVgEiH8eMtPGhV\nTXY++8y6D5pAKZJ+ChARyQQIDWGkw\/jxcOKJoatInk8\/1fwHkdZCASIipaV2VQci+ZYuhUWLFCCy\nVVRkN81\/EGkdFCAioiGM9Bg\/3q4KENn57DO7KkCItA4KEBFRgEiPsWOhTx\/o2TN0Jckyfjz06gW9\ne4euRERyQQEiImvX2qz9jh1DVyIt9fbb8K1vha4ief71LzjpJE2gFGktFCAiUlJiEyj1xzPZFi6E\nL79UgMjWhg02hHHSSaErEZFcUYCIyKpVdoCQJNs770CbNnDqqaErSZZPP7XdOxUgRFoPBYiIrFwJ\nO+8cugppqXfegWOOsc2QpOnGjbP5P4cdFroSEckVBYiIrFypDkTSVVVZgPj2t0NXkjzjxsHxx9vx\n5yLSOihARGTVKnUgkm7sWFizBs47L3QlyVJTY1t\/a\/hCpHVRgIiIOhDJ98orsPfeOoo6W59\/bhup\nad6ISOuiABERzYFIttpaePVVOP98raTJ1rvvQteuNndERFoPBYgIVFdb61sdiOSaOBGWLbMAIdl5\n91345jehXbvQlYhILilARGD1aruqA5Fcw4bZzpPavjo75eW2A+UZZ4SuRERyTQEiAsuW2XX33cPW\nIc1TWQnDh8Mll2gVQbb+9S97\/LTxlkjrEzxAOOd+65yrbXCbGbqubBQV2XWPPcLWIc3z1ls2h+XS\nS0NXkjzvvGM\/9wcfHLoSEcm17UIXUGc6cDqQmb5WHbCWrC1dahPvdPhSMj39tK28OOKI0JUkz+jR\n1n3QxFOR1id4B6JOtfd+hff+q7rb6tAFZaOoCHbbTZPIkmjZMhg5Ei67LHQlyVNQANOnw3e+E7oS\nEQkhXwLEAc65pc65+c6555xziToQuKhIwxdJ9dhj0L49XH556EqS5\/XX7bEbNCh0JSISQj4EiE+A\ny4FBwM+AfYEPnXOdQxaVjaIi2HPP0FVItiorLUBceqnOvmiO11+35Ztdu4auRERCCD4Hwns\/ut6b\n051zE4FFwA+Av2\/p44YOHUq3bt02u2\/IkCEMGTIkljq3prAQjj46519WWuill6C4GK67LnQlyVNa\nCh98APffH7oSEdmS4cOHM3z48M3uKy0tjezzBw8QDXnvS51zc4E+W3u\/++67jwEDBuSoqi3zHhYs\ngMGDQ1ci2aithbvusgmAhx4auprkGT3aNlA755zQlYjIljT2onrSpEkMHDgwks+fD0MYm3HOdcHC\nw7LQtTRFSYm9Gttvv9CVSDZeew2mTYP\/+Z\/QlSTTq69Cv36w116hKxGRUIIHCOfcPc65U5xzezvn\nTgD+AVQBw7fxoXlh\/ny77r9\/2Dqk6byHO+6w8fuTTw5dTfKUl9vKlQsvDF2JiISUD0MYvYBhwM7A\nCmAccJz3flXQqppowQK7qgORHK++CpMnw5gxoStJpjffhPXrNWwn0toFDxDe+9zPeozQ\/PnQvbtm\n8SdFZSXcdJMtPTzttNDVJNMLL8DAgdBnq7OURCTtgg9hJN28eRq+SJKHH7au0R\/\/GLqSZCorsw7E\nRReFrkREQlOAaKFp0+Cww0JXIU2xYgXcfjtcfbW+Z801ciRUVMAPfhC6EhEJTQGiBWpqYMYMOPzw\n0JVIU9xwA7RpYyFCmuf55+GEE7T6QkTyYA5Eks2fb6\/GFCDy35tv2pHdzzxj55ZI9goLbf+Hxx4L\nXYmI5AN1IFpg2jS7KkDktzVr4Gc\/s4mTP\/xh6GqS65lnoEMHDV+IiFGAaIHPP7cjvHv0CF2JbIn3\ncNVVsG6dvXLWsdPNU1sLTz5pez\/ssEPoakQkH2gIowU++sjGgyV\/PfYYvPyy3fbeO3Q1yfWvf9mQ\n3ZNPhq5ERPKFOhDNVFUFn36qAJHPPv8cfvELuOYauOCC0NUk29\/+Zvs+aOdOEclQgGimqVNtS9\/j\njw9diTRm6VI491zo3x\/uvTd0Ncm2YgW8+KINBWkISEQyFCCa6b33oFMn25FP8kt5uYWHtm1t2+oO\nHUJXlGyPP27B4aqrQlciIvlEcyCaadQoOPVU2H770JVIfRs3wve+B3PmwLhxNslVmq+qCv7yF7jk\nEth559DViEg+UQeiGcrK7MnprLNCVyL1VVfDxRfD++\/bcd39+4euKPlefdX2f7j++tCViEi+UQei\nGUaPtldmZ54ZuhLJqK6Gyy+3rZZfeQVOPz10Renw4INwyinQr1\/oSkQk3yhANMPw4Tb3QYdo5YeK\nCjta+p\/\/tK2WzzkndEXpMHGiLd986aXQlYhIPtIQRpbWrLFtkS++OHQlArB2rQ0lvfOODVtol8To\n\/P73cOCBcN55oSsRkXykDkSWhg+34YvBg0NXIvPn22qLpUvh7bfhpJNCV5QeM2fa\/IcnnrDVLCIi\nDakDkYXaWnjgAduUaM89Q1fTuo0ZA0cfbWHuk08UHqJ29932M\/6jH4WuRETylQJEFkaNsuWBv\/hF\n6Epar5oaa60PGgRHHQUTJsDBB4euKl0WLYJhw+CXv4T27UNXIyL5SgGiiWpr4X\/\/17au1vbVYSxd\nCt\/6Ftx6K9x0k02a3Gmn0FWlz91324FZV18duhIRyWeaA9FE\/\/d\/MGkSfPihtvPNNe\/t8b\/mGtu4\n69134bTTQleVTgUFtvPk\/\/t\/0KVL6GpEJJ+pA9EEpaXWzj3nHB0mlGuFhfDd79qk1W98A6ZMUXiI\n02232Y6T110XuhIRyXcKEE3wq1\/ZcsGHHgpdSetRXQ0PPwyHHGKnnmaO5N5ll9CVpdesWfDsszZE\n1Llz6GpEJN8pQGzDiBHW0r3nHthrr9DVtA5vv23bUF93HVx0kT2x6Tju+P3ud9CrF\/zkJ6ErEZEk\n0ByIrZg8Ga680g4S0h\/V+M2caZMj33zThoo++0ynnebKF1\/Ykd1PPKED4kSkadSB2IJZs2yp4CGH\nwF\/\/qomTcZo923b2POwwCxEvvQRjxyo85Ir3tjT5oIPgsstCVyMiSaEORCOmTLHtkXv0sIOzOnUK\nXVE6zZkDd9xhu3vuuacdG33FFdp7INdeeMEC2+jRsJ3+IohIE6kD0cA\/\/2m7Gvbsaecr7Lxz6IrS\nxXs7oOm886BvX3vieughmDcPfvpThYdcW7cO\/uu\/7Pvx7W+HrkZEkkQBos7GjTb+\/p3vwKmn2n4P\nPXuGrio9qqttQuoxx9jx0PPm2eTUefPg5z\/XuHsod94Jq1bBn\/4UuhIRSRo1LIFx4+Daa23ewx\/+\nADfeCG0UrSJRWAh\/+5tNzisshNNPty7PoEF6jEObOxfuvdeWbe67b+hqRCRpWnWAWLDAtqd+\/nk7\nV+GTT2DAgNBVJV9NDbz1Fjz2mK2o6NjRJklec40tz5TwvIcbbrC5JzfdFLoaEUmiVhkg5syxA5me\ne87mODzxhE3e0yvilpk50yZEPv00LFkCRx4JjzwCQ4bY2QqSP15\/3ULeP\/5hAU9EJFutJkBUVsJr\nr9mr4jFjYI89rH179dVaZdESBQU2t2HECJg6Fbp1gwsvtAmRAwdq+Ws+qqiwZZuDBtk24SIizZHq\nAFFdbbP8X3rJtkFescJWWDzzjD3JdegQusJkKiqyw62GD7fjtDt1gnPPhdtvhzPP1ITIfHfPPTYf\nZdQoBTwRab7UBYgVK6zD8PbbMHKkzTDfZx\/bIOfyy+HQQ0NXmEyrVlkIGzECPvjA9gs46ywLEeec\no7MTkmLRIhu+GzrUNo4SEWmuxAeIr76yV8Hjxtm+DZMn2\/2HHAJXXWWdhgED9EqrOcrKbNhn+HAL\nZLW1toriiSfg\/PNhp51CVyjZ+uUvYccd4Te\/CV2JiCRdYgPErbfaMrQFC+zt3XeHM86wsd0zzrA5\nDpK9DRtsmeWIEfDGGzZefuKJcP\/98P3v2+6ckkzvvmtdpOefh65dQ1cjIkmX2ACxdKmNux93nN32\n2ktdhuaqqrLuzYgR8Oqr1nkYMMDmNAwerFNI06CyEq6\/3g4pGzIkdDUikgaJDRBPPaU9G1qittaG\nfYYNswmRq1fDwQfbtsaDB2t8PG0efNA6diNGKGiLSDQSGyAke97bUsthw2xew5Il1l24+mq46CLo\n109PLmm0bBncdptt5NWvX+hqRCQtFCBagcJCW7o6bBjMmGGbZ\/3gB7Y75AknaAOttPv1r21p7e23\nh65ERNJEASKlqqpsG+nHH7cdBzt0sE2D7r7bTl1s1y50hZIL48fDs8\/az4FWzYhIlBQgUmbpUts+\n+sknobgYjj4aHn3Uhig08751qamB666zn4ErrwxdjYikjQJESkyZYltzjxhh3YZLL7W5DRrzbr0e\nfxy++MIOidMwlYhETQEi4SZNsk2BRo2yCZF33WUbaOnwqtZt1SrbK+XKK+HYY0NXIyJppNclCTV3\nru2yOXAgzJ9vJ4t++SXceKPCg1iorKmxbatFROKgDkTClJfDnXfagUh77GFzHX70IzubQgRsOOuv\nf7Uhrd12C12NiKSVnnYS5MMP7VCwoiL47\/+Gm2\/WiaKyOe\/hhhtsI7Brrw1djYikmQJEAlRX2xr+\nO++0cynefhsOOCB0VZKPXnrJjrB\/6y0t1RWReClA5LnSUtv0acwYCxE33wxt24auSvJRebltRX7O\nOTBoUOhqRCTtFCDyWGEhnHmmXUePtqO0Rbbknnts748xY0JXIiKtgQJEnioqgtNOg40b4eOPoW\/f\n0BVJPlu61HYZ\/cUvoE+f0NWISGugAJGHSkrgjDNgwwYbz95vv9AVSb677Tbo1Mkm14qI5IICRJ6p\nrrZtp4uLbQdBhQfZltmzbTnvPfdAt26hqxGR1kIBIs\/89rc2hj16NBx4YOhqJAluvRV69bLjukVE\nckUBIo988oltRX377ZowKU3zySfwyivw9NN2ZLeISK5oK+s8UVkJV1wBRx0Fv\/516GokKW69FQ47\nDC65JHQlItLaqAORJx591M63+OILbUstTTN+PLz3Hrz8svYGEZHcUwciD6xZY7Pof\/xjOPzw0NVI\nUtxxh3UfzjsvdCUi0hrptW4eeOQR20XwtttCVyJJMXGiTbQdPhza6GWAiASgPz2BbdwIDz4Il14K\nu+8euhpJijvvtAOzLrwwdCUi0lqpAxHYCy\/Yng9Dh4auRJJixgwYORKeekpzH0QkHHUgAvv7323J\n5sEHh65EkuKBB2CPPWDIkNCViEhrpgAR0OLF8MEHNnwh0hQrV8Kzz8K110L79qGrEZHWTAEioGHD\noGNHOP\/80JVIUvz1r3b9yU\/C1iEiogAR0GuvwdlnQ9euoSuRJKishIcfhh\/+EHbZJXQ1ItLaKUAE\nsmoVTJhgAUKkKUaOtGPe\/\/M\/Q1ciIpInAcI5d61zrsA5t8E594lz7ujQNcXt7bfBezjzzNCVSFL8\n7W9w3HHabExE8kPwAOGcGwzcC\/wWOBKYAox2zqW6STt6NPTrZ7PpRbZlyRL7mfnxj0NXIiJiggcI\nYCjwmPf+Ge\/9bOBnQDlwZdiy4jV+PJxySugqJCmeesom3A4eHLoSERETdCMp51w7YCDw\/2Xu8957\n59y7wPHBCovT8uVUnvs93vpyGV1H7w5fvQK77Ra6KslXy5fjL\/gel05cxuDuu9N1wyvQVT8vIqmy\nfDl873uwbJltSfzKtp8XKiuhpKTx25o1W75\/9eroyg69E+UuQFtgeYP7lwMHbe0D1679jJKStXHV\n1WIbNpQDcykrK6e6utO\/7+\/y3etpP3E6+wPMXUDVuaezbtSDocqUGGzpe98cXb57Pe0mTGdvgK9a\n789LlI+pSD6prYXO\/3E9HT6fbncsWMBXJ5\/OSzc8SGkplJZCWdmm27p1dq2oaPzzbbedrezr2hW6\ndLEcsv\/+m95etWouv\/99NLWHDhDNdsMNP6VLl83vO+0029Uxn8ydu\/nbxy6GdvXerl48nSlTTs1p\nTZIbDb\/3zaGfl81F8ZiK5JtjizZ\/u2vZdA45pOW\/52PGwHvvbX7funUt\/rT\/FjpArARqgB4N7u8B\nFG\/tAx955FWOPPLQuOpqsfXr1zFjxgwOPfRQOnfelHTa7zMYlk2q9\/YAjjnmhRAlSky29L1vjnZ7\n6+cFon1MRbLlvbX\/V66EFSvstmpV4\/9dUmLvX1+XLrDTTpvfunff9N+HdxtMx3q\/5+32jub3\/Jhj\n4JZbNr9v8uQZnHTSeS3+3BA4QHjvq5xznwOnAyMBnHOu7u0\/b+1jO3bsTadOfeIvsplqasqANXTo\nsD+dOtXbKerVUXza+wL267SMnQ\/dnbavvEKnThrTTpMtfu+bYfxNo\/AXXMBReyyjw76t9+clysdU\npL7KSpt6sHQpFBbareF\/FxVBVdXmH9e1K\/TsCT162PXQQzf9d+basyfsuit06LCNIv5jFFxwwb\/n\nQGz3yitsF9PveceO0Q39h+5AAPwJeKouSEzEVmV0Ap4KWVRcSrffjWMqx\/Hck3DJJaGrkXz33Nu7\nMWrvcRQUAC50NSLJkukcFBTAwoWbbosXbwoHy5dv3jHo1Al694ZevaBPH\/jmN2HPPW3Jff2A0CnK\nqTi77QbjxkX4CXMjeIDw3r9Yt+fD7djQxRfAIO\/9irCVxWPGDLsedljYOiT\/1dbCP\/5hW1c7hQeR\nRq1fD\/PnbwoJDa9r673g7tQJ9tkH9toLjjwSzjnHgkKvXhYSevWCbt30+9ZUwQMEgPf+EeCR0HXk\nwvTp0LYtHLTVNSYi8Pnn9uro3HNDVyIS1saNsGABzJtnE2nrX5cu3fR+HTpYQNhnHzjxROvyZt7e\nd187Q0bhIDp5ESBakzlz7Ad5m2Ni0uq9+SbsuCOccELoSkRyY+1amDnTOrUzZth\/z50LixZZRw6g\nc2c44AA48EALCQceaG\/vt5+NBCgg5I4CRI4VFNgPusi2vPEGDBpk67pF0mTDhk0hYfr0Tf+9eLH9\nu3O2d8Ehh8D3v78pJBxwgO2zpJCQH\/SnKccKCuDYY0NXIflu2TIbwvjFL0JXItIya9fCF1\/A5Mkw\naZLdZs2Cmhr79332sTlhQ4bYSobDDoODD7at2yW\/KUDkWEEBXHRR6Cok340aZa+ydFqrJElFhQXf\njz+Gzz6zsDBvnv3b9tvDEUfYsMP110P\/\/tZhaLghoCSHAkQOlZTYtqT77hu6Esl3Y8bAwIE26Usk\nH3lvp8R+\/PGm2+TJtl9Cp04wYACcfbatdhgwwLoK7dpt+\/NKcihA5FBBgV0VIGRrvIf337flmyL5\nwntbCfH++3YbO3bTCoj994fjj4fLLoPjjrNOg+bupJ++xTm0cKFdFSBka+bOtTkQp7beIy8kTyxZ\nYt2wTGhYsgTatLHu2MUXw0knWWDQgcKtkwJEDhUVQfv2sPPOoSuRfPb++7ZXyEknha5EWpuqKhg\/\nHv75T7vNmGFzcfr3hwsvtFB78sm22ZKIAkQOFRfbNqhagiRb88EHcNRRtte+SNxWrYKRI23fkXfe\nsVUTPXrAWWfBb39rJxx37x66SslHChA5VHdOisgWeW8B4oorQlciabZ8Obz6Krz8sh33XFtrQxG\/\n+pVNfOzf34YqRLZGASKHMh0IkS1ZuND+uJ94YuhKJG1KSuDFF2HECPjwQ+uEfvOb8OCDcP75+tsk\n2VOAyKFly7SJlGzdhAl21c+JRKGqCkaPhmeesWGKqir41rfgr3+F735Xy4SlZRQgckgdCNmWTz6x\nVTq77hq6Ekmy+fPh0UctOHz1FRx+ONx5px0upb9BEhUFiBypqbHWtOZAyNZMmGBj0SLZqqmBt96C\nhx+2nUy7d4dLL7W9Gfr3D12dpJECRI6sWmUTlXr0CF2J5KvKStvJT1udSzbWr4cnnoAHHrDN6gYO\nhCeftJ8jnSchcVKAyJHVq+2q5VCyJVOmwMaNmv8gTbNqFTz0EPz5z7ZF\/kUXwfDhcMwxWiouuaEA\nkSMlJXZVgJAt+fxz2\/5X7WbZmpUr4e674S9\/sa7mVVfBL38Je+8dujJpbRQgckQdCNmWKVPswKEO\nHUJXIvmorAz+9Ce49157e+hQ+M\/\/1IRbCUcBIkcyAWKnncLWIflr6lQ7hEikvqoq6zbccYeFiOuu\ng5tv1hJMCU97jeXI6tU2oUmvLqUxtbUWIPr1C12J5JP337chraFDbd+GefPgj39UeJD8oACRIyUl\nGr6QLVtwHM5BAAAUvElEQVS4ENatUwdCTGEhDB4Mp50GO+4In31mKy169w5dmcgmChA5snq1hi9k\ny6ZOtas6EK2b9xYUDjkExo61jaDGjYMjjwxdmcjXKUDkyOrV6kDIlk2ZYpPhtEtg67V4MZx5Jlx9\ntR2dPXs2\/OhHWpIp+UuTKHNEQxiyNVOn2nbDerJonUaMgJ\/+FHbYwXaRPPPM0BWJbJs6EDlSUmJj\nmSKNmT3b2tbSumzYYMFhyBD4j\/+A6dMVHiQ5FCBypKzMXl2INFRTA19+CQcdFLoSyaV582zX0Wee\ngccfh+efh27dQlcl0nQawsiRdeugS5fQVUg+WrTIzsE48MDQlUiujBkD3\/8+7LYbTJxow1ciSaMO\nRI6UlSlASOPmzLGrOhCtw6OPwqBBdmbFhAkKD5JcChA5sm4ddO0augrJR3Pm2AZjWuOfbt7Dr34F\nP\/85XHMNvPmm5kVJsmkIIweqquyURXUgpDFz58IBB0AbxfnUqqmBn\/zEjtm+\/3644YbQFYm0nAJE\nDqxbZ1cFCGnMnDma\/5BmlZVwySXwj3\/A00\/DpZeGrkgkGnrNkwOZAKEhDGnMnDma\/5BWVVW2JfXI\nkfDyywoPki7qQOSAOhCyJRUVsHQp7L9\/6EokajU1cNll8MYb8Oqrts+DSJooQORAWZld1YGQhhYv\ntuu++4atQ6LlvW0Q9cILtsukwoOkkQJEDqgDIVuycKFd99knZBUStdtug7\/9zeY8XHhh6GpE4qE5\nEDmgACFbsnChrb7o1St0JRKV55+3AHHnnZrzIOmmAJEDGsKQLVm40MJDu3ahK5EojBsHV14Jl18O\nt9wSuhqReClA5MC6dfYqs0OH0JVIvlm4EPbeO3QVEoVly2x76uOPh8ce08mqkn4KEDlQXg6dOukP\ninzdokWa\/5AG1dV2omabNjZxsn370BWJxE8BIgcqKqBjx9BVSD5auFABIg3+939t+GLECOjRI3Q1\nIrmhVRg5UFGh4Qv5uo0boahIASLp3nsPfv97uOsuOOWU0NWI5I46EDmwYYMChHxdYaFd99orbB3S\nfGvXwhVXwKmn2kFZIq2JOhA5oA6ENKaoyK577hm2Dmm+G2+E1ath7FgdhiatjwJEDihASGMyAWKP\nPcLWIc3z1lu2WdTjj2sYSlonZeYcUICQxhQV2eqcHXYIXYlka8MGuOYaOOMM+PGPQ1cjEoY6EDmg\nACGNKSqy7oOW9ybP3XfbHJa33tL3T1ovdSByYMMGLeOUrysq0vyHJJo\/31Zc\/OpXcOCBoasRCUcB\nIgfUgZDGZDoQkiw33mh7Pdx6a+hKRMLSEEYOKEBIY4qKYODA0FVINsaNg5EjYdgwm78i0pqpA5ED\nChDSGHUgksV7uPlmOPJIGDw4dDUi4akDkQMKENJQWZkdsqYAkRxvvAHjx9vESe35IKIORE5oJ0pp\nSHtAJEttrc15OPVU+Pa3Q1cjkh\/UgcgBdSCkoWXL7NqzZ9g6pGnefBOmTYMPP9SyTZEMdSByQKdx\nSkMrVth1t93C1iHb5r0dlnXiiXDyyaGrEckf6kDkgDoQ0tCKFbDddtCtW+hKZFs+\/BA+\/tjmQIjI\nJupA5IAChDS0YgXssova4Ulw111wxBFw9tmhKxHJL+pAxKy6GmpqYPvtQ1ci+WTFCth119BVyLbM\nmWOrLp55RmFPpCF1IGK2caNdFSCkPgWIZHjkEfs+\/eAHoSsRyT8KEDGrqrJru3Zh65D8ogCR\/9at\ng6eegquu0gsAkcYoQMSsqsr6nu3bBy5E8srKlQoQ+e755y1E\/OxnoSsRyU8KEDFTB0Iak5lEKfnr\n0UfhO9+BvfYKXYlIflKAiJkChDTkvToQ+W7KFPjiCxu+EJHGKUDETAFCGlqzxlbnKEDkr2eese\/P\nmWeGrkQkfylAxKy62uZAKEBIRmYXSgWI\/FRdbfMfLr5Yv7ciW6MAEbPKSrtqEqVkKEDkt3fegeXL\n4dJLQ1cikt8UIGKmIQxpaPVqu3bvHrYOadyzz8Khh8KRR4auRCS\/KUDErLrargoQkrFmjV132ils\nHfJ1FRXw+utw0UXaeVJkW4IGCOfcQudcbb1bjXPuppA1RS2zD4QChGSUlNjZKDofJf+8+67t\/fC9\n74WuRCT\/hT4LwwO\/AR4HMnm\/LFw50csMYWgOhGSsWQM77hi6CmnMyy\/DwQdD376hKxHJf6EDBMA6\n7\/2K0EXEJTOJUh0IySgp0fBFPqqqgpEj4ec\/D12JSDLkwxyIm51zK51zk5xz\/+Wcaxu6oChpGac0\npA5Efho71ia4XnBB6EpEkiF0B+IBYBKwGjgBuAvoCfxXyKKipFUY0pA6EPnptddg7721+kKkqSIP\nEM653wO\/3sq7eKCv936u9\/7+evdPd85VAo85527x3ldt7esMHTqUbt26bXbfkCFDGDJkSHNLj4UC\nhDRUUgK9e4euQhp66y04+2ytvpD0GD58OMOHD9\/svtLS0sg+fxwdiD8Cf9\/G+yzYwv0TsZr2AeZt\n7RPcd999DBgwIOvick0bSUlDa9bA4YeHrkLq+\/JLu917b+hKRKLT2IvqSZMmMXDgwEg+f+QBwnu\/\nCljVzA8\/EqgFvoquorA0B0Ia0hBG\/hk92n5HTz01dCUiyRFsDoRz7jjgWOB9bOnmCcCfgGe999H1\nWAKrqoK2bdUWlU00iTL\/jBoFJ50EXbuGrkQkOUKuwtgIXAR8AEwHbgHuBX4asKbIVVWp+yCbVFdD\nWZk6EPmkogLef18nb4pkK1gHwns\/GTg+1NfPlepqBQjZJDN\/SQEif3z0EZSXw6BBoSsRSZZ82Aci\n1SornSZQyr+VlNhVQxj5Y+xYO9hME1tFsqMAETMNYUh9mQChDkT+GDsWTjkF2uivoUhW9CsTMwUI\nqW\/tWrvusEPYOsRUVMAnn8A3vhG6EpHkUYCImeZASH1ldUfFabZ\/fvj0U9i40ToQIpIdBYiYVVc7\ntgu9YbjkDQWI\/DJ2LHTrBv36ha5EJHkUIGJWXY0ChPxbWZn9PGy\/fehKBCxAnHSS7dUiItlRgIhZ\nTY3+OMkmZWXWfdDGYuHV1MDHH1uAEJHsKUDETAFC6ssECAlv1ixYvx6OOy50JSLJpAARs9paBQjZ\nRAEif0yYYEs3jzoqdCUiyaQAETN1IKS+desUIPLFxIlwyCHQpUvoSkSSSQEiZjU1TgFC\/k0diPwx\ncSIce2zoKkSSSwEiZlqFIfWVlekVbz4oL4dp0+CYY0JXIpJcChAx0xCG1KcORH6YPNl+NxUgRJpP\nASJmmkQp9SlA5IeJE6FjRzjssNCViCSXAkTM1IGQ+hQg8sPkyXDEERpeFGkJBYiYKUBIfQoQ+WHq\nVG1fLdJSChAx0yoMqU8BIrzKSpg5UwFCpKUUIGJWU6M2qZiqKjv5UQEirNmz7XuhACHSMgoQMauu\n1hCGmHXr7KoAEdaUKXY9\/PCwdYgknQJEzLQKQzJ0lHd+mDIF9t0XdtghdCUiyaYAETNNopSMTAdC\nG0mFNWWKhi9EoqAAETMFCMkoL7dr585h62jttAJDJBoKEDHTKgzJyASITp3C1tGarVgBX32lDaRE\noqAAETN1ICQjEyA6dgxbR2s2e7Zd+\/YNW4dIGihAxEzLOCVDHYjwZs+GNm2gT5\/QlYgknwJEzNSB\nkAwFiPBmz4b99oPttw9diUjyKUDETAFCMsrLwTk9eYU0ezYcfHDoKkTSQQEiZgoQklFebt0H50JX\n0nopQIhERwEiZgoQkpEJEBJGRQUUFChAiERFASJmWsYpGQoQYc2bB94rQIhERQEiZtrKWjIUIMLK\nLOFUgBCJhgJEzLSMUzLKy7UHREizZ8POO9tNRFpOASJmOo1TMtSBCGv+fDjggNBViKSHAkTMNIlS\nMjZsUIAIqaDA9oAQkWgoQMRMAUIy1IEIa8ECBQiRKClAxEyrMCRDASKcigpYulQBQiRKChAx0yoM\nyVCACGfRIlvCqQAhEh0FiJhpCEMyFCDCWbDArgoQItFRgIhZdbWWcYpRgAhnwQJo3x722CN0JSLp\noQARM3UgJEP7QISzYAHss49+F0WipAARMwUIyVAHIhytwBCJngJEjLwH77UKQ4wCRDgKECLRU4CI\nUW2tXRUgpLrabh06hK6kdSoosCEMEYmOAkSMvHcAOBe4EAlu40a7KkDk3tq1UFYGvXuHrkQkXRQg\nYuS9XdvoUW71KirsqgCRe0uW2LVXr7B1iKSNntpilOlAKEBIpgOx\/fZh62iNMgFCHQiRaOmpLUaZ\nORAKEKIORDhLltgwovaAEImWntpipDkQkqEORDhLlsDuu0O7dqErEUkXBYgYaQ6EZGgSZThLlmj4\nQiQOemqLkYYwJCMzhKEORO4VFipAiMRBT20x0iRKyVAHIpwlS7QCQyQOemqLUaYDoTkQog5EGN5r\nCEMkLgoQsVIHQow6EGGUlNgW4goQItHTU1uMNAdCMtSBCEN7QIjER09tMdIcCMlQByKMoiK77rln\n2DpE0khPbTHSHAjJyASI9u3D1tHaFBfbtUePsHWIpJECRIy0D4RkVFRYeFCYzK3iYth5ZwU3kTjo\nqS1GGsKQjI0bNXwRwrJl0LNn6CpE0klPbTHSJErJqKjQBMoQiosVIETioqe2GOksDMlQByIMBQiR\n+ChAxEhzICRj40Z1IEJQgBCJj57aYqQ5EJJRUaEORAjFxXYSp4hET09tMdIcCMlQByL31q+HsjJ1\nIETioqe2GGkOhGSoA5F7mT0gFCBE4qEAESPNgZAMdSByTwFCJF56aovRRx+NBhQgojR8+PDQJTRL\nvnYgkvp4NkWoAJHmxzQEPZ75K7anNufcfzvnxjvn1jvnVm\/hfXo7596se59i59wfnHOpebqdMOEd\nQAEiSkn9Y5KvHYikPp5NUVwM7drBTjvl9uum+TENQY9n\/orzqa0d8CLwl8b+sS4o\/BPYDjgOuAy4\nHLg9xpqC0BwI0T4QuVdcbGdgKMCLxCO2Xy3v\/W3e+weAaVt4l0HAwcAl3vtp3vvRwP8A1zrntour\nrhD0B0y0E2XuffUV7Lpr6CpE0ivkU9txwDTv\/cp6940GugGHhikpWppEKRn5OoSRZitXKkCIxCnk\nK\/2ewPIG9y2v929TtvBxHQBmzZoVU1nRWL9+PRs2rAMmMXt26GrSo7S0lEmTJoUuY6vWr1\/P3Llz\nadu2LZ07dwagtBRKSiDfSk\/C4wmNP6bbUlBgQxi5\/t9LymOaFHo8o1XvubPFg6rOZ14mN+Wdnfs9\n8OutvIsH+nrv59b7mMuA+7z33Rt8rseAvbz3Z9W7ryOwHjirbkijsRouBp5vctEiIiLS0CXe+2Et\n+QTZdiD+CPx9G++zoImfqxg4usF9Per925aMBi4BFgIVTfxaIiIiYp2HfbDn0hbJKkB471cBq1r6\nRet8DPy3c26XevMgvg2UAjO3UUOLUpOIiEgr9lEUnyS2ORDOud5Ad2BvoK1zrl\/dP33pvV8PvI0F\nhWedc78GdgfuAB7y3lfFVZeIiIi0XFZzILL6xM79Hbi0kX861Xv\/Yd379Mb2ifgmNvfhKeAW731t\nLEWJiIhIJGILECIiIpJe2qFAREREsqYAISIiIllTgIiJc+5a51yBc26Dc+4T51zDJavSBM65W5xz\nE51za51zy51z\/3DOHRi6rjRxzt3snKt1zv0pdC1J5Zzbwzn3rHNupXOu3Dk3xTk3IHRdSeWca+Oc\nu8M5t6Du8fzSOfeb0HUliXPuZOfcSOfc0rrf73MbeZ\/bnXNFdY\/xO865Ptl8DQWIGDjnBgP3Ar8F\njsR21RztnNslaGHJdDLwIHAscAZ2SNvbdZuOSQvVBdufsOWdX2UbnHM7AuOBjdgZP32BXwIlIetK\nuJuBnwLXYGcm3QTc5Jy7LmhVydIZ+AJ7DL822bFu9eN12O\/\/MdhChtHOufZN\/QKaRBkD59wnwATv\n\/Q11bztgCfBn7\/0fghaXcHUh7CvgFO\/9uND1JJlzrgvwOfBz7CC7yd77G8NWlTzOubuA47333whd\nS1o4514Hir33V9e77yWg3Hvf2Oo+2QrnXC1wnvd+ZL37ioB7vPf31b29A3acxGXe+xeb8nnVgYiY\nc64dMBAYk7nPW0p7Fzg+VF0psiOWpleHLiQFHgZe996\/F7qQhDsH+Mw592LdMNsk59xVoYtKuI+A\n051zBwDU7SN0IvDPoFWlhHNuX+zMqfrPU2uBCWTxPJWqY7PzxC5AWxo\/KOyg3JeTHnWdnPuBcd77\nLe5WKtvmnLsI6A8cFbqWFNgP6+LcC9yJtYP\/7Jzb6L1\/NmhlyXUXsAMw2zlXg73YvdV7PyJsWanR\nE3sh1tjzVM+mfhIFCEmSR4BDsFci0kzOuV5YEDtDu75Gog0w0Xv\/P3VvT3HOHQb8DFCAaJ7BwMXA\nRdiOxf2BB5xzRQpl+UNDGNFbCdSw6WCwjB5s\/ZAw2Qrn3EPA2cA3vffLQteTcAOBXYFJzrkq51wV\n8A3gBudcZV2nR5puGTCrwX2zgL0C1JIWfwDu8t7\/n\/d+hvf+eeA+4JbAdaVFMeBo4fOUAkTE6l7R\nfQ6cnrmv7g\/y6UR0gElrUxcevottg744dD0p8C5wOPaqrl\/d7TPgOaCf18zqbI3n68OTBwGLAtSS\nFp2wF2L11aLnrEh47wuwoFD\/eWoHbLVbk5+nNIQRjz8BTznnPgcmAkOxX4inQhaVRM65R4AhwLnA\neudcJjGXeu91nHsz1B1mt9kcEufcemCV977hK2nZtvuA8c65W4AXsT\/CVwFXb\/WjZGteB37jnCsE\nZgADsL+jTwStKkGcc52BPlinAWC\/usmoq733S7BhzN84574EFmKHWRYCrzX5a+jFRjycc9dga5d7\nYGtxr\/fefxa2quSpW37U2A\/pFd77Z3JdT1o5594DvtAyzuZxzp2NTfzrAxQA93rvnwxbVXLVPfnd\nAZwP7AYUAcOAO7z31SFrSwrn3DeA9\/n638+nvfdX1r3P77B9IHYE\/gVc673\/sslfQwFCREREsqXx\nJBEREcmaAoSIiIhkTQFCREREsqYAISIiIllTgBAREZGsKUCIiIhI1hQgREREJGsKECIiIpI1BQgR\nERHJmgKEiIiIZE0BQkRERLL2\/wOI60fL9qNiMAAAAABJRU5ErkJggg==\n\"\n>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>A quick note, the secular equation as written above is most directly used to compute <em>eigenvalues<\/em> not <em>singular values<\/em>. There is a strong relationship between the two sets of values and they lead to only slightly different forms in the secular equation. I mention this because you might see slightly different forms of the secular equation depending on whether you are reading about eigenvalues or singular values. We will use the form above for solving both problems by slightly modifying the resulting <span class=\"math inline\">\\(\\lambda\\)<\/span>s.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>Back to our regularly scheduled program. We will find our desired roots by isolating out <span class=\"math inline\">\\(f(\\lambda)\\)<\/span> between each set of poles. The poles occur at the values of <span class=\"math inline\">\\(d_i\\)<\/span>. So, on the interval <span class=\"math inline\">\\((d_i, d_{i+1})\\)<\/span>, the problem simplifies to finding a single root of the secular equation. Throughout this post, we&#8217;ll assume that <span class=\"math inline\">\\(d_i &lt; d_j\\)<\/span> for <span class=\"math inline\">\\(i&lt;j\\)<\/span> (in English, the <span class=\"math inline\">\\(d_i\\)<\/span>s are distinct and sorted). We&#8217;ll find a single root <span class=\"math inline\">\\(n\\)<\/span> times and find all <span class=\"math inline\">\\(n\\)<\/span> roots. The cleverest will now point out that <span class=\"math inline\">\\(n\\)<\/span> poles only hold <span class=\"math inline\">\\(n-1\\)<\/span> zeros between them. The last zero is to the right of <span class=\"math inline\">\\(d_n\\)<\/span>.<\/p>\n<p>How do we find the single roots?<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<h3 id=\"newtons-method\">Newton&#8217;s Method<\/h3>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>Let&#8217;s take a second and review <em>Newton&#8217;s method<\/em> for finding a root of an equation <span class=\"math inline\">\\(f(x)\\)<\/span> near <span class=\"math inline\">\\(x_0\\)<\/span>.<\/p>\n<ol style=\"list-style-type: decimal\">\n<li>Approximate <span class=\"math inline\">\\(f(x)\\)<\/span> by a linear function <span class=\"math inline\">\\(l(x) = ax+b\\)<\/span><\/li>\n<li>Apply constraints such that <span class=\"math inline\">\\(f(x_0) = l(x_0)\\)<\/span> and <span class=\"math inline\">\\(f&#39;(x_0) = l&#39;(x_0)\\)<\/span>. These determine the coefficients of <span class=\"math inline\">\\(l(x)\\)<\/span>.<\/li>\n<li>Find the root of <span class=\"math inline\">\\(l(x)\\)<\/span> and call it <span class=\"math inline\">\\(x_1\\)<\/span>. In this case, the root is the <span class=\"math inline\">\\(x\\)<\/span>-intercept of <span class=\"math inline\">\\(l(x)\\)<\/span>.<\/li>\n<li>That root of <span class=\"math inline\">\\(l(x)\\)<\/span> is a better guess as to the root of <span class=\"math inline\">\\(f(x)\\)<\/span>.<\/li>\n<\/ol>\n<p>Newton&#8217;s method is a great technique and it is used broadly because it is conceptually and formally simple, easy to implement, and the iteration steps are reasonably fast. However, in the case of the secular equation, as the numerators get very small, the corner in the graph will go from a gentle bend to a sharp corner. In other words, the graph will go from vertical to horizontal very quickly. When this happens, a linear approximation on the nearly horizontal part (which is the majority of the pole-to-pole interval), will also be approximately horizontal and be aimed far away from the true root in this interval.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<h3 id=\"a-modified-newtons-method\">A Modified Newton&#8217;s Method<\/h3>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>So, we need to try something else. Fortunately, we can maintain the outline of Newton&#8217;s method while using a different approximating function. Instead of using a linear form, we will use the following rational function of <span class=\"math inline\">\\(\\lambda\\)<\/span> which has poles at <span class=\"math inline\">\\(d_i\\)<\/span> and <span class=\"math inline\">\\(d_{i+1}\\)<\/span>:<\/p>\n<p><span class=\"math display\">\\[h(\\lambda) = \\frac{C_1}{d_i-\\lambda} + \\frac{C_2}{d_{i+1}-\\lambda} + C_3\\]<\/span><\/p>\n<p>So, we are approximating <span class=\"math inline\">\\(f(\\lambda)\\)<\/span> with <span class=\"math inline\">\\(h(\\lambda)\\)<\/span>:<\/p>\n<p><span class=\"math display\">\\[f(\\lambda) = 1 + \\sum_{i=1}^n \\frac{z_{i}^2}{d_i &#8211; \\lambda} \\approx<br \/>\n\\frac{C_1}{d_i-\\lambda} + \\frac{C_2}{d_{i+1}-\\lambda} + C_3 = h(x)\\]<\/span><\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>Also, since we want to avoid numerical problems with term cancellation, we will break the sum in <span class=\"math inline\">\\(f(\\lambda)\\)<\/span> into two parts: (1) the sum up to term <span class=\"math inline\">\\(k\\)<\/span> and (2) the sum from term <span class=\"math inline\">\\(k+1\\)<\/span> on. Along with the an ordering assumption on the <span class=\"math inline\">\\(d_i\\)<\/span>, this means that the lower terms are all negative and the upper terms are all positive for <span class=\"math inline\">\\(\\lambda \\in (d_i, d_{i+1})\\)<\/span>. We will also give names to those partial sums.<\/p>\n<p><span class=\"math display\">\\[<br \/>\n\\begin{eqnarray}<br \/>\nf(\\lambda) &amp;=&amp; 1 + &amp; \\sum_{i=1}^k \\frac{z_{i}^2}{d_i &#8211; \\lambda} + \\sum_{i=k+1}^n \\frac{z_{i}^2}{d_i &#8211; \\lambda} &amp;=&amp; 1 + \\Psi_1(\\lambda) + \\Psi_2(\\lambda)\\\\<br \/>\nf&#39;(\\lambda) &amp;=&amp; &amp; \\sum_{i=1}^k \\frac{z_i^2}{(d_i &#8211; \\lambda)^2} + \\sum_{i=k+1}^n \\frac{z_i^2}{(d_i &#8211; \\lambda)^2} &amp;=&amp; \\Psi&#39;_1(\\lambda) + \\Psi&#39;_2(\\lambda)<br \/>\n\\end{eqnarray}<br \/>\n\\]<\/span><\/p>\n<p>Note that the derivative (and the derivatives of the partial sums) is strictly positive except at <span class=\"math inline\">\\(\\lambda = d_i\\)<\/span> (the poles of <span class=\"math inline\">\\(f\\)<\/span>).<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>Since we have broken <span class=\"math inline\">\\(f\\)<\/span> into pieces, we will also break <span class=\"math inline\">\\(h\\)<\/span> into pieces:<\/p>\n<p><span class=\"math display\">\\[h(\\lambda)=1 + h_1(\\lambda) + h_2(\\lambda)\\]<\/span><\/p>\n<p>and we will give them each the same form, which is similar to that of <span class=\"math inline\">\\(h\\)<\/span>:<\/p>\n<p><span class=\"math display\">\\[h_1(\\lambda) = \\hat{c}_1 + \\frac{C_1}{d_k &#8211; \\lambda} \\quad<br \/>\nh_2(\\lambda) = \\hat{c}_2 + \\frac{C_2}{d_{k+1} &#8211; \\lambda}\\]<\/span><\/p>\n<p>We will also enforce the <em>&quot;Newton conditions&quot;<\/em> that both the value of the approximations <span class=\"math inline\">\\(h_i\\)<\/span> and the value of the derivative of the approximations <span class=\"math inline\">\\(h&#39;_i\\)<\/span> agree with the target function at <span class=\"math inline\">\\(\\lambda_{\\alpha}\\)<\/span>:<\/p>\n<p><span class=\"math display\">\\[<br \/>\n\\begin{align}<br \/>\nh_1(\\lambda_{\\alpha}) = \\Psi_1(\\lambda_{\\alpha}) &amp;\\quad&amp; h&#39;_1(\\lambda_{\\alpha}) = \\Psi&#39;_1(\\lambda_{\\alpha})\\\\<br \/>\nh_2(\\lambda_{\\alpha}) = \\Psi_2(\\lambda_{\\alpha}) &amp;\\quad&amp; h&#39;_2(\\lambda_{\\alpha}) = \\Psi&#39;_2(\\lambda_{\\alpha})<br \/>\n\\end{align}<br \/>\n\\]<\/span><\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>The result of these constraints is that: <span class=\"math display\">\\[ C_1 = \\Psi&#39;_1(\\lambda_{\\alpha})(d_k &#8211; \\lambda_{\\alpha})^2 \\\\<br \/>\n   \\hat{c}_1 = \\Psi_1(\\lambda_{\\alpha}) &#8211; \\Psi&#39;_1(\\lambda_{\\alpha})(d_k &#8211; \\lambda_{\\alpha})\\]<\/span><\/p>\n<p><span class=\"math display\">\\[ C_2 = \\Psi&#39;_2(\\lambda_{\\alpha})(d_k &#8211; \\lambda_{\\alpha})^2 \\\\<br \/>\n   \\hat{c}_2 = \\Psi_2(\\lambda_{\\alpha}) &#8211; \\Psi&#39;_2(\\lambda_{\\alpha})(d_{k+1} &#8211; \\lambda_{\\alpha})\\]<\/span><\/p>\n<p><span class=\"math display\">\\[C_3 = 1 + \\hat{c}_1 + \\hat{c}_2\\]<\/span><\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>Since we are seeking a root of <span class=\"math inline\">\\(h(\\lambda)\\)<\/span>, we can set<\/p>\n<p><span class=\"math display\">\\[h(\\lambda) = \\frac{C_1}{d_i-\\lambda} + \\frac{C_2}{d_{i+1}-\\lambda} + C_3 = 0\\]<\/span><\/p>\n<p>and multiply out the denominators. This gives us:<\/p>\n<p><span class=\"math display\">\\[0 = C_1 (d_{k+1} &#8211; \\lambda) + C_2 (d_k &#8211; \\lambda) + C_3(d_k &#8211; \\lambda)(d_{k+1} &#8211; \\lambda) \\qquad \\star\\]<\/span><\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>In our original Newton formulation of root finding, we went from a guess of the root <span class=\"math inline\">\\(x_0\\)<\/span> to <span class=\"math inline\">\\(x_1\\)<\/span>. We could phrase that as going <span class=\"math inline\">\\(x_1=x_0+\\kappa\\)<\/span> where <span class=\"math inline\">\\(\\kappa\\)<\/span> is a correction to our our <span class=\"math inline\">\\(x_1\\)<\/span> guess. We will use that &quot;<span class=\"math inline\">\\(\\kappa\\)<\/span>-technique&quot; here. Call our current approximation or guess <span class=\"math inline\">\\(\\lambda_\\alpha\\)<\/span>. Let&#8217;s call our correction <span class=\"math inline\">\\(\\eta\\)<\/span>. Then we can write a <span class=\"math inline\">\\(\\lambda_{\\alpha} + \\eta = \\lambda\\)<\/span>. Another way to think about this is as a variable substitution (or function shift) for <span class=\"math inline\">\\(\\lambda \\rightarrow \\lambda &#8211; \\lambda_{\\alpha} = \\eta\\)<\/span> which centers the function horizontally at <span class=\"math inline\">\\(\\lambda_{\\alpha}\\)<\/span>. If we solve for a <span class=\"math inline\">\\(\\lambda\\)<\/span> that gives a zero, we would also have a corresponding <span class=\"math inline\">\\(\\eta\\)<\/span> value where <span class=\"math inline\">\\(\\lambda_{\\alpha} + \\eta\\)<\/span> gives a zero. Also, the equality means we can write <span class=\"math inline\">\\(\\lambda_\\alpha = \\lambda &#8211; \\eta\\)<\/span>.<\/p>\n<p>Now, to help simplify the terms, let <span class=\"math inline\">\\(\\Delta_k = d_k &#8211; \\lambda_\\alpha\\)<\/span> and <span class=\"math inline\">\\(\\Delta_{k+1} = d_{k+1} &#8211; \\lambda_\\alpha\\)<\/span>. Together, these give us (and likewise for <span class=\"math inline\">\\(\\Delta_{k+1}\\)<\/span>):<\/p>\n<p><span class=\"math display\">\\[\\Delta_k = d_k &#8211; \\lambda_\\alpha = d_k &#8211; (\\lambda &#8211; \\eta) = d_k &#8211; \\lambda + \\eta\\]<\/span><\/p>\n<p>Rearranging:<\/p>\n<p><span class=\"math display\">\\[d_k &#8211; \\lambda = \\Delta_k &#8211; \\eta \\quad \\text{and} \\quad d_{k+1} &#8211; \\lambda = \\Delta_{k+1} &#8211; \\eta\\]<\/span><\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>Since, <span class=\"math inline\">\\(\\lambda_\\alpha\\)<\/span> is a constant during an interation of Newton&#8217;s method, we will drop the functional depence on it. Our <span class=\"math inline\">\\(C\\)<\/span> constants become: <span class=\"math display\">\\[\\begin{align}<br \/>\nC_1 &amp;= \\Psi&#39;_1 \\Delta_{k}^2 \\\\<br \/>\nC_2 &amp;= \\Psi&#39;_2 \\Delta_{k+1}^2 \\\\<br \/>\nC_3 &amp;= 1 + \\Psi_1 + \\Psi_2 &#8211; \\Psi&#39;_1 \\Delta_{k} &#8211; \\Psi&#39;_2 \\Delta_{k+1}<br \/>\n\\end{align}<br \/>\n\\]<\/span><\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>The punchline is an expression we can solve for <span class=\"math inline\">\\(\\eta\\)<\/span> (the correction to our old guess <span class=\"math inline\">\\(\\lambda_\\alpha\\)<\/span>):<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p><span class=\"math display\">\\[\\begin{align}<br \/>\nC_1 (d_{k+1} &#8211; \\lambda) + C_2 (d_k &#8211; \\lambda) + C_3(d_k &#8211; \\lambda)(d_{k+1} &#8211; \\lambda)<br \/>\n    &amp;= C_1 (\\Delta_{k+1} &#8211; \\eta) + C_2 (\\Delta_{k} &#8211; \\eta) + C_3 (\\Delta_{k} &#8211; \\eta) (\\Delta_{k+1} &#8211; \\eta) \\\\<br \/>\n    &amp;= {\\eta}^2 C_3\\ + \\\\<br \/>\n    &amp;\\quad {-\\eta} (C_1 + C_2 + C_3(\\Delta_k + \\Delta_{k+1}))\\ +\\\\<br \/>\n    &amp;{\\quad}C_1\\Delta_{k+1} + C_2\\Delta_{k} + C_3\\Delta_k\\Delta_{k+1}<br \/>\n\\end{align}<br \/>\n\\]<\/span><\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>So, rewriting these constants into the form of the classic quadratic equation <span class=\"math inline\">\\(a\\eta^2+b\\eta+c\\)<\/span>, we have (we introduce <span class=\"math inline\">\\(\\Psi_{\\text{sum}} = 1 + \\Psi_1 + \\Psi_2\\)<\/span>):<\/p>\n<p><span class=\"math display\">\\[<br \/>\n\\begin{align}<br \/>\na &amp;= C_3 \\\\<br \/>\n  &amp;= (1 + \\Psi_1 + \\Psi_2) &#8211; \\Psi&#39;_1 \\Delta_{k} &#8211; \\Psi&#39;_2 \\Delta_{k+1} \\\\<br \/>\n  &amp;= \\Psi_{\\text{sum}} &#8211; \\Psi&#39;_1 \\Delta_{k} &#8211; \\Psi&#39;_2 \\Delta_{k+1} \\\\<br \/>\n\\\\<br \/>\n-b &amp;= C_1 + C_2 + C_3(\\Delta_k + \\Delta_{k+1}) \\\\<br \/>\n&amp;= \\Psi&#39;_1 \\Delta_{k}^2 + \\Psi&#39;_2 \\Delta_{k+1}^2 + C_3(\\Delta_k + \\Delta_{k+1}) \\\\<br \/>\n&amp;= \\Psi&#39;_1 \\Delta_{k}^2 + \\Psi&#39;_2 \\Delta_{k+1}^2 + (\\Psi_{\\text{sum}} &#8211; \\Psi&#39;_1 \\Delta_{k} &#8211; \\Psi&#39;_2 \\Delta_{k+1})(\\Delta_k + \\Delta_{k+1})\\\\<br \/>\n&amp;= \\Psi_{\\text{sum}} (\\Delta_k + \\Delta_{k+1}) &#8211; \\Psi&#39;_1 \\Delta_{k} \\Delta_{k+1} &#8211; \\Psi&#39;_1 \\Delta_{k} \\Delta_{k+1} \\\\<br \/>\n&amp;= \\Psi_{\\text{sum}} (\\Delta_k + \\Delta_{k+1}) &#8211; (\\Psi&#39;_1 + \\Psi&#39;_2)\\Delta_{k} \\Delta_{k+1} \\\\<br \/>\nb &amp;= (\\Psi&#39;_1 + \\Psi&#39;_2)\\Delta_{k} \\Delta_{k+1} &#8211; \\Psi_{\\text{sum}} (\\Delta_k + \\Delta_{k+1}) \\\\<br \/>\n\\\\<br \/>\nc &amp;= C_3\\Delta_k\\Delta_{k+1} + C_1\\Delta_{k+1} + C_2\\Delta_{k} \\\\<br \/>\n&amp;= (\\Psi_{\\text{sum}} &#8211; \\Psi&#39;_1 \\Delta_{k} &#8211; \\Psi&#39;_2 \\Delta_{k+1})\\Delta_k\\Delta_{k+1} + \\Psi&#39;_1 \\Delta_{k}^2\\Delta_{k+1} + \\Psi&#39;_2 \\Delta_{k+1}^2 \\Delta_{k} \\\\<br \/>\n&amp;= \\Psi_{\\text{sum}} \\Delta_{k} \\Delta_{k+1}<br \/>\n\\end{align}<br \/>\n\\]<\/span><\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>The solutions <span class=\"math inline\">\\(\\eta_1, \\eta_2\\)<\/span> to the quadratic above are well known as <span class=\"math inline\">\\(\\eta_1, \\eta_2 = \\frac{-b \\pm \\sqrt{b^2-4ac}}{2a} = \\frac{-b \\pm \\text{root}}{2a}\\)<\/span>. However, there is an interesting (and useful!) alternative formula for the solutions: <span class=\"math inline\">\\(\\eta_2,\\eta_1 = \\frac{2c}{-b \\mp \\sqrt{b^2-4ac}} = \\frac{2c}{-b \\mp \\text{root}}\\)<\/span>. These come from either (1) using different steps to solve the generic quadratic form or (2) applying Vieta&#8217;s formulas to the standard solution. Due to some algebraic magic and inequalities I haven&#8217;t quite figured out yet, the solution that we need can be picked out based on the value of <span class=\"math inline\">\\(b\\)<\/span>. (Li claims &#8211; and tests on running code show &#8211; that based on the quadratic equation and the constaints above &#8211; including <span class=\"math inline\">\\(C_1,C_2 &gt; 0\\)<\/span> &#8211; the correct <span class=\"math inline\">\\(\\eta\\)<\/span> is based on <span class=\"math inline\">\\(b\\)<\/span>. I can&#8217;t demonstrate that, despite trying many different algebraic contortions. I did get to the point of showing <span class=\"math inline\">\\(C_3&gt;0\\)<\/span>, but alas. I&#8217;d love help and I&#8217;ll buy you a cookie or a beer for it.) The punchline is:<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p><span class=\"math display\">\\[<br \/>\n\\eta=\\begin{cases}<br \/>\n\\frac{2c}{-b + \\text{root}} &amp; b&lt;0 \\\\<br \/>\n\\frac{-b &#8211; \\text{root}}{2a} &amp; b \\geq 0<br \/>\n\\end{cases}<br \/>\n\\]<\/span><\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>Two last pieces lead us to our improvised (MacGyvered?) Newton&#8217;s method.<\/p>\n<p>We need to know where to start and when to stop. These topics make varied appearances in the literature. Since all but one root falls between the poles, we can start most root finding iterations at the midpoint of the poles <span class=\"math inline\">\\(\\frac{d_i + d_{i+1}}{2}\\)<\/span>. For the straggler root (which lies to the right of <span class=\"math inline\">\\(d_n\\)<\/span>), we use a starting point at <span class=\"math inline\">\\(d_n + \\|z\\|^2\\)<\/span> (following Arbenz&#8217;s lead). I don&#8217;t use a midpoint to the right (i.e., <span class=\"math inline\">\\(\\frac{d_n + (d_n + \\|z\\|^2)}{2} = d_n + \\frac{\\|z\\|^2}{2}\\)<\/span>) because I&#8217;ve had small numerical differences with LAPACK&#8217;s results. Another note, Gu &amp; Eisenstat say the root should be to the left of <span class=\"math inline\">\\(d_n + \\|z\\|\\)<\/span>. So, there&#8217;s some discreprancy here. Oh well. It happens.<\/p>\n<p><a href=\"http:\/\/epubs.siam.org\/doi\/abs\/10.1137\/S0895479892242232\">Gu &amp; Eisenstat<\/a> propose stopping when <span class=\"math inline\">\\(|\\Psi_{\\text{sum}}| &lt; 10.0\\epsilon(1 + |\\Psi_1| + |\\Psi_2|)\\)<\/span>.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<h3 id=\"code-outline\">Code Outline<\/h3>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>For all that ridiculously long development, the code becomes:<\/p>\n<ol style=\"list-style-type: decimal\">\n<li>Setup: set some variables (including inital <span class=\"math inline\">\\(\\lambda\\)<\/span>), deal with <span class=\"math inline\">\\(n\\)<\/span>-th root, determine closest <span class=\"math inline\">\\(d_i\\)<\/span>, and shift (center) the problem there<\/li>\n<li>Loop until stopping condition is met\n<ol style=\"list-style-type: decimal\">\n<li>Calculate <span class=\"math inline\">\\(\\Psi\\)<\/span>s, <span class=\"math inline\">\\(\\Delta\\)<\/span>s, <span class=\"math inline\">\\(a, b, c\\)<\/span>, and solve the quadratic for <span class=\"math inline\">\\(\\eta\\)<\/span>.<\/li>\n<li>Update <span class=\"math inline\">\\(\\lambda\\)<\/span>.<\/li>\n<\/ol>\n<\/li>\n<li>Undo the shift.<\/li>\n<li>Et voila.<\/li>\n<\/ol>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing code_cell rendered\">\n<div class=\"input\">\n<div class=\"prompt input_prompt\">In&nbsp;[2]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\" highlight hl-ipython2\">\n<pre><span><\/span><span class=\"kn\">import<\/span> <span class=\"nn\">itertools<\/span> <span class=\"kn\">as<\/span> <span class=\"nn\">it<\/span>\n\n<span class=\"n\">EPSILON<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">finfo<\/span><span class=\"p\">(<\/span><span class=\"nb\">float<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">eps<\/span>\n<span class=\"n\">NEPS<\/span> <span class=\"o\">=<\/span> <span class=\"mf\">10.0<\/span> <span class=\"o\">*<\/span> <span class=\"n\">EPSILON<\/span> <span class=\"c1\"># via Gu &amp; Eisenstat<\/span>\n\n<span class=\"k\">def<\/span> <span class=\"nf\">solve_secular_oneroot<\/span><span class=\"p\">(<\/span><span class=\"n\">d<\/span><span class=\"p\">,<\/span> <span class=\"n\">z<\/span><span class=\"p\">,<\/span> <span class=\"n\">i<\/span><span class=\"p\">):<\/span>\n    <span class=\"c1\"># translated and modified from:  Arbenz, Peter. see citation below.<\/span>\n    <span class=\"c1\"># there are no &quot;l&quot; (ells) in the following code, they are all &quot;1&quot; (ones)<\/span>\n    <span class=\"n\">n<\/span> <span class=\"o\">=<\/span> <span class=\"n\">d<\/span><span class=\"o\">.<\/span><span class=\"n\">size<\/span><span class=\"p\">;<\/span> <span class=\"n\">d_i<\/span> <span class=\"o\">=<\/span> <span class=\"n\">d<\/span><span class=\"p\">[<\/span><span class=\"n\">i<\/span><span class=\"p\">];<\/span> <span class=\"n\">z<\/span> <span class=\"o\">=<\/span> <span class=\"n\">z<\/span><span class=\"o\">*<\/span><span class=\"n\">z<\/span>\n    \n    <span class=\"k\">if<\/span> <span class=\"n\">i<\/span> <span class=\"o\">&lt;<\/span> <span class=\"n\">n<\/span> <span class=\"o\">-<\/span> <span class=\"mi\">1<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">d_ip1<\/span>   <span class=\"o\">=<\/span> <span class=\"n\">d<\/span><span class=\"p\">[<\/span><span class=\"n\">i<\/span><span class=\"o\">+<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span>\n        <span class=\"n\">lambda_<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"n\">d_i<\/span> <span class=\"o\">+<\/span> <span class=\"n\">d_ip1<\/span><span class=\"p\">)<\/span> <span class=\"o\">\/<\/span> <span class=\"mf\">2.0<\/span>\n    <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">adder<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">max<\/span><span class=\"p\">(<\/span><span class=\"n\">nla<\/span><span class=\"o\">.<\/span><span class=\"n\">norm<\/span><span class=\"p\">(<\/span><span class=\"n\">z<\/span><span class=\"p\">)<\/span><span class=\"o\">**<\/span><span class=\"mi\">2<\/span><span class=\"p\">,<\/span> <span class=\"mf\">1.0<\/span><span class=\"p\">)<\/span> <span class=\"c1\"># protect against small norm<\/span>\n        <span class=\"n\">d_ip1<\/span>   <span class=\"o\">=<\/span> <span class=\"n\">d<\/span><span class=\"p\">[<\/span><span class=\"o\">-<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span> <span class=\"o\">+<\/span> <span class=\"n\">adder<\/span>\n        <span class=\"n\">lambda_<\/span> <span class=\"o\">=<\/span> <span class=\"n\">d_ip1<\/span>\n\n    <span class=\"n\">left_idx<\/span><span class=\"p\">,<\/span> <span class=\"n\">right_idx<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">slice<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"n\">i<\/span><span class=\"o\">+<\/span><span class=\"mi\">1<\/span><span class=\"p\">),<\/span> <span class=\"nb\">slice<\/span><span class=\"p\">(<\/span><span class=\"n\">i<\/span><span class=\"o\">+<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"bp\">None<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">left_z<\/span><span class=\"p\">,<\/span> <span class=\"n\">right_z<\/span> <span class=\"o\">=<\/span> <span class=\"n\">z<\/span><span class=\"p\">[<\/span><span class=\"n\">left_idx<\/span><span class=\"p\">],<\/span> <span class=\"n\">z<\/span><span class=\"p\">[<\/span><span class=\"n\">right_idx<\/span><span class=\"p\">]<\/span>\n\n    <span class=\"n\">denoms<\/span> <span class=\"o\">=<\/span> <span class=\"n\">d<\/span> <span class=\"o\">-<\/span> <span class=\"n\">lambda_<\/span>    <span class=\"c1\"># PN: this makes a new vector<\/span>\n    <span class=\"n\">psi1<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">sum<\/span><span class=\"p\">(<\/span> <span class=\"n\">left_z<\/span><span class=\"o\">**<\/span><span class=\"mi\">2<\/span> <span class=\"o\">\/<\/span> <span class=\"n\">denoms<\/span><span class=\"p\">[<\/span> <span class=\"n\">left_idx<\/span><span class=\"p\">])<\/span>\n    <span class=\"n\">psi2<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">sum<\/span><span class=\"p\">(<\/span><span class=\"n\">right_z<\/span><span class=\"o\">**<\/span><span class=\"mi\">2<\/span> <span class=\"o\">\/<\/span> <span class=\"n\">denoms<\/span><span class=\"p\">[<\/span><span class=\"n\">right_idx<\/span><span class=\"p\">])<\/span>\n\n    <span class=\"c1\"># determine whether soln is closer to right or left pole<\/span>\n    <span class=\"c1\"># (remember, we are currently at lambda == midpt)<\/span>\n    <span class=\"n\">psi_sum<\/span> <span class=\"o\">=<\/span> <span class=\"mf\">1.0<\/span> <span class=\"o\">+<\/span> <span class=\"n\">psi1<\/span> <span class=\"o\">+<\/span> <span class=\"n\">psi2<\/span>\n    <span class=\"n\">left_half<\/span> <span class=\"o\">=<\/span> <span class=\"n\">psi_sum<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mf\">0.0<\/span>\n    <span class=\"n\">active_d<\/span> <span class=\"o\">=<\/span> <span class=\"n\">d_i<\/span> <span class=\"k\">if<\/span> <span class=\"n\">left_half<\/span> <span class=\"k\">else<\/span> <span class=\"n\">d_ip1<\/span>\n\n    <span class=\"c1\"># shift poles (so one of them is zero), initial guess, and d_i,d_ip1<\/span>\n    <span class=\"n\">d<\/span> <span class=\"o\">=<\/span> <span class=\"n\">d<\/span> <span class=\"o\">-<\/span> <span class=\"n\">active_d<\/span>\n    <span class=\"n\">lambda_<\/span> <span class=\"o\">=<\/span> <span class=\"n\">lambda_<\/span> <span class=\"o\">-<\/span> <span class=\"n\">active_d<\/span>\n\n    <span class=\"k\">if<\/span> <span class=\"n\">left_half<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">d_i<\/span><span class=\"p\">,<\/span> <span class=\"n\">d_ip1<\/span> <span class=\"o\">=<\/span> <span class=\"mf\">0.0<\/span><span class=\"p\">,<\/span> <span class=\"n\">d_ip1<\/span><span class=\"o\">-<\/span><span class=\"n\">d_i<\/span>\n    <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">d_i<\/span><span class=\"p\">,<\/span> <span class=\"n\">d_ip1<\/span> <span class=\"o\">=<\/span> <span class=\"n\">d_i<\/span><span class=\"o\">-<\/span><span class=\"n\">d_ip1<\/span><span class=\"p\">,<\/span> <span class=\"mf\">0.0<\/span>\n\n    <span class=\"n\">stop_cond<\/span> <span class=\"o\">=<\/span> <span class=\"n\">NEPS<\/span> <span class=\"o\">*<\/span> <span class=\"n\">n<\/span> <span class=\"o\">*<\/span> <span class=\"p\">(<\/span><span class=\"mf\">1.0<\/span> <span class=\"o\">+<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">abs<\/span><span class=\"p\">(<\/span><span class=\"n\">psi1<\/span><span class=\"p\">)<\/span> <span class=\"o\">+<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">abs<\/span><span class=\"p\">(<\/span><span class=\"n\">psi2<\/span><span class=\"p\">))<\/span>\n    <span class=\"n\">itct<\/span> <span class=\"o\">=<\/span> <span class=\"n\">it<\/span><span class=\"o\">.<\/span><span class=\"n\">count<\/span><span class=\"p\">()<\/span>\n    <span class=\"k\">while<\/span> <span class=\"p\">(<\/span><span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">abs<\/span><span class=\"p\">(<\/span><span class=\"n\">psi_sum<\/span><span class=\"p\">)<\/span> <span class=\"o\">&gt;<\/span> <span class=\"n\">stop_cond<\/span> <span class=\"ow\">and<\/span> <span class=\"n\">itct<\/span><span class=\"o\">.<\/span><span class=\"n\">next<\/span><span class=\"p\">()<\/span> <span class=\"o\">&lt;<\/span> <span class=\"mi\">10<\/span><span class=\"p\">):<\/span>\n        <span class=\"n\">denoms<\/span> <span class=\"o\">=<\/span> <span class=\"n\">d<\/span> <span class=\"o\">-<\/span> <span class=\"n\">lambda_<\/span>\n        \n        <span class=\"n\">psi1<\/span><span class=\"p\">,<\/span> <span class=\"n\">psi1_p<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">sum<\/span><span class=\"p\">(<\/span><span class=\"n\">left_z<\/span> <span class=\"o\">\/<\/span> <span class=\"n\">denoms<\/span><span class=\"p\">[<\/span> <span class=\"n\">left_idx<\/span><span class=\"p\">]),<\/span>\n                        <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">sum<\/span><span class=\"p\">(<\/span><span class=\"n\">left_z<\/span> <span class=\"o\">\/<\/span> <span class=\"n\">denoms<\/span><span class=\"p\">[<\/span> <span class=\"n\">left_idx<\/span><span class=\"p\">]<\/span><span class=\"o\">**<\/span><span class=\"mi\">2<\/span><span class=\"p\">))<\/span>\n        <span class=\"n\">psi2<\/span><span class=\"p\">,<\/span> <span class=\"n\">psi2_p<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">sum<\/span><span class=\"p\">(<\/span><span class=\"n\">right_z<\/span> <span class=\"o\">\/<\/span> <span class=\"n\">denoms<\/span><span class=\"p\">[<\/span><span class=\"n\">right_idx<\/span><span class=\"p\">]),<\/span>\n                        <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">sum<\/span><span class=\"p\">(<\/span><span class=\"n\">right_z<\/span> <span class=\"o\">\/<\/span> <span class=\"n\">denoms<\/span><span class=\"p\">[<\/span><span class=\"n\">right_idx<\/span><span class=\"p\">]<\/span><span class=\"o\">**<\/span><span class=\"mi\">2<\/span><span class=\"p\">))<\/span>\n        <span class=\"n\">psi_sum<\/span> <span class=\"o\">=<\/span> <span class=\"mf\">1.0<\/span> <span class=\"o\">+<\/span> <span class=\"n\">psi1<\/span> <span class=\"o\">+<\/span> <span class=\"n\">psi2<\/span>\n\n\n        <span class=\"c1\"># D is \\Delta : recall, we&#39;ve shifted d_i, d_ip1 (line 36 above)<\/span>\n        <span class=\"k\">if<\/span> <span class=\"n\">left_half<\/span><span class=\"p\">:<\/span>\n            <span class=\"n\">D_i<\/span><span class=\"p\">,<\/span> <span class=\"n\">D_ip1<\/span> <span class=\"o\">=<\/span> <span class=\"o\">-<\/span><span class=\"n\">lambda_<\/span><span class=\"p\">,<\/span> <span class=\"n\">d_ip1<\/span> <span class=\"o\">-<\/span> <span class=\"n\">lambda_<\/span>\n        <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n            <span class=\"n\">D_i<\/span><span class=\"p\">,<\/span> <span class=\"n\">D_ip1<\/span> <span class=\"o\">=<\/span> <span class=\"n\">d_i<\/span> <span class=\"o\">-<\/span> <span class=\"n\">lambda_<\/span><span class=\"p\">,<\/span> <span class=\"o\">-<\/span><span class=\"n\">lambda_<\/span>\n\n        <span class=\"c1\">#a \\eta^2 + b \\eta + c = 0<\/span>\n        <span class=\"n\">a<\/span> <span class=\"o\">=<\/span> <span class=\"n\">psi_sum<\/span> <span class=\"o\">-<\/span> <span class=\"p\">(<\/span><span class=\"n\">D_i<\/span> <span class=\"o\">*<\/span> <span class=\"n\">psi1_p<\/span><span class=\"p\">)<\/span> <span class=\"o\">-<\/span> <span class=\"p\">(<\/span><span class=\"n\">D_ip1<\/span> <span class=\"o\">*<\/span> <span class=\"n\">psi2_p<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">b<\/span> <span class=\"o\">=<\/span> <span class=\"o\">-<\/span> <span class=\"p\">(<\/span><span class=\"n\">D_i<\/span> <span class=\"o\">+<\/span> <span class=\"n\">D_ip1<\/span><span class=\"p\">)<\/span> <span class=\"o\">*<\/span> <span class=\"n\">psi_sum<\/span> <span class=\"o\">+<\/span> <span class=\"p\">(<\/span><span class=\"n\">D_i<\/span> <span class=\"o\">*<\/span> <span class=\"n\">D_ip1<\/span> <span class=\"o\">*<\/span> <span class=\"p\">(<\/span><span class=\"n\">psi1_p<\/span> <span class=\"o\">+<\/span> <span class=\"n\">psi2_p<\/span><span class=\"p\">))<\/span>\n        <span class=\"n\">c<\/span> <span class=\"o\">=<\/span> <span class=\"n\">D_i<\/span> <span class=\"o\">*<\/span> <span class=\"n\">D_ip1<\/span> <span class=\"o\">*<\/span> <span class=\"n\">psi_sum<\/span>\n\n        <span class=\"n\">root<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">sqrt<\/span><span class=\"p\">(<\/span><span class=\"n\">b<\/span><span class=\"o\">**<\/span><span class=\"mi\">2<\/span> <span class=\"o\">-<\/span> <span class=\"mi\">4<\/span><span class=\"o\">*<\/span><span class=\"n\">a<\/span><span class=\"o\">*<\/span><span class=\"n\">c<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">eta<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"mf\">2.0<\/span> <span class=\"o\">*<\/span> <span class=\"n\">c<\/span><span class=\"p\">)<\/span> <span class=\"o\">\/<\/span> <span class=\"p\">(<\/span><span class=\"o\">-<\/span><span class=\"n\">b<\/span> <span class=\"o\">+<\/span> <span class=\"n\">root<\/span><span class=\"p\">)<\/span> <span class=\"k\">if<\/span> <span class=\"n\">b<\/span> <span class=\"o\">&lt;<\/span> <span class=\"mf\">0.0<\/span> <span class=\"k\">else<\/span> <span class=\"p\">(<\/span><span class=\"o\">-<\/span><span class=\"n\">b<\/span> <span class=\"o\">-<\/span> <span class=\"n\">root<\/span><span class=\"p\">)<\/span><span class=\"o\">\/<\/span><span class=\"p\">(<\/span><span class=\"mf\">2.0<\/span><span class=\"o\">*<\/span><span class=\"n\">a<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">lambda_<\/span> <span class=\"o\">=<\/span> <span class=\"n\">lambda_<\/span> <span class=\"o\">+<\/span> <span class=\"n\">eta<\/span>\n\n        <span class=\"n\">stop_cond<\/span> <span class=\"o\">=<\/span> <span class=\"n\">NEPS<\/span> <span class=\"o\">*<\/span> <span class=\"n\">n<\/span> <span class=\"o\">*<\/span> <span class=\"p\">(<\/span><span class=\"mf\">1.0<\/span> <span class=\"o\">+<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">abs<\/span><span class=\"p\">(<\/span><span class=\"n\">psi1<\/span><span class=\"p\">)<\/span> <span class=\"o\">+<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">abs<\/span><span class=\"p\">(<\/span><span class=\"n\">psi2<\/span><span class=\"p\">))<\/span>\n\n    <span class=\"n\">d_m_lambda<\/span> <span class=\"o\">=<\/span> <span class=\"n\">d<\/span> <span class=\"o\">-<\/span> <span class=\"n\">lambda_<\/span>      <span class=\"c1\"># (both shifted) - this will be discussed next post<\/span>\n    <span class=\"n\">lambda_<\/span> <span class=\"o\">=<\/span> <span class=\"n\">lambda_<\/span> <span class=\"o\">+<\/span> <span class=\"n\">active_d<\/span>\n    <span class=\"k\">return<\/span> <span class=\"n\">lambda_<\/span><span class=\"p\">,<\/span> <span class=\"n\">d_m_lambda<\/span>\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<h3 id=\"testing\">Testing<\/h3>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>I&#8217;d be remiss, if I didn&#8217;t offer some code to test the root-finding code. The basic process is to use NumPy&#8217;s (and hence LAPACK&#8217;s) eigenvalue computation system to calculate the roots in a &quot;known good&quot; fashion. NumPy wants a matrix as input, so we take our <span class=\"math inline\">\\(d\\)<\/span> and <span class=\"math inline\">\\(z\\)<\/span> values and put them in an appropriate matrix. The actual test cases here are a bit <em>ad hoc<\/em> &#8211; they came up during development of the larger D&amp;C SVD code. I&#8217;ll have more thorough testing either in the next post or as a standalone follow-up to the next post.<\/p>\n<p>Here goes:<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing code_cell rendered\">\n<div class=\"input\">\n<div class=\"prompt input_prompt\">In&nbsp;[4]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\" highlight hl-ipython2\">\n<pre><span><\/span><span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">set_printoptions<\/span><span class=\"p\">(<\/span><span class=\"n\">precision<\/span><span class=\"o\">=<\/span><span class=\"mi\">10<\/span><span class=\"p\">,<\/span><span class=\"n\">suppress<\/span><span class=\"o\">=<\/span><span class=\"bp\">False<\/span><span class=\"p\">)<\/span>\n\n<span class=\"k\">def<\/span> <span class=\"nf\">run_for<\/span><span class=\"p\">(<\/span><span class=\"n\">d<\/span><span class=\"p\">,<\/span><span class=\"n\">z<\/span><span class=\"p\">,<\/span> <span class=\"n\">verbose<\/span><span class=\"o\">=<\/span><span class=\"bp\">False<\/span><span class=\"p\">):<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">d<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]<\/span> <span class=\"o\">==<\/span> <span class=\"mf\">0.0<\/span> <span class=\"ow\">and<\/span> <span class=\"n\">d<\/span><span class=\"o\">.<\/span><span class=\"n\">shape<\/span> <span class=\"o\">==<\/span> <span class=\"n\">z<\/span><span class=\"o\">.<\/span><span class=\"n\">shape<\/span>\n    <span class=\"c1\"># ROU is a &quot;rank-one updated&quot; matrix<\/span>\n    <span class=\"n\">ROU<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">diag<\/span><span class=\"p\">(<\/span><span class=\"n\">d<\/span><span class=\"p\">)<\/span> <span class=\"o\">+<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">outer<\/span><span class=\"p\">(<\/span><span class=\"n\">z<\/span><span class=\"p\">,<\/span><span class=\"n\">z<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">verbose<\/span><span class=\"p\">:<\/span>\n        <span class=\"k\">print<\/span> <span class=\"s2\">&quot;cond(ROU): <\/span><span class=\"si\">%5.2g<\/span><span class=\"s2\">&quot;<\/span> <span class=\"o\">%<\/span> <span class=\"n\">nla<\/span><span class=\"o\">.<\/span><span class=\"n\">cond<\/span><span class=\"p\">(<\/span><span class=\"n\">ROU<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">print<\/span> <span class=\"s2\">&quot;Effective ROU:<\/span><span class=\"se\">\\n<\/span><span class=\"s2\">&quot;<\/span><span class=\"p\">,<\/span> <span class=\"n\">ROU<\/span>\n    <span class=\"n\">expected<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">sort<\/span><span class=\"p\">(<\/span><span class=\"n\">nla<\/span><span class=\"o\">.<\/span><span class=\"n\">eigvals<\/span><span class=\"p\">(<\/span><span class=\"n\">ROU<\/span><span class=\"p\">))<\/span>\n    <span class=\"n\">sols<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span><span class=\"n\">solve_secular_oneroot<\/span><span class=\"p\">(<\/span><span class=\"n\">d<\/span><span class=\"p\">,<\/span><span class=\"n\">z<\/span><span class=\"p\">,<\/span><span class=\"n\">i<\/span><span class=\"p\">)[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]<\/span> <span class=\"k\">for<\/span> <span class=\"n\">i<\/span> <span class=\"ow\">in<\/span> <span class=\"nb\">xrange<\/span><span class=\"p\">(<\/span><span class=\"n\">d<\/span><span class=\"o\">.<\/span><span class=\"n\">size<\/span><span class=\"p\">)]<\/span>\n    <span class=\"n\">actual<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">sort<\/span><span class=\"p\">(<\/span><span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">array<\/span><span class=\"p\">(<\/span><span class=\"n\">sols<\/span><span class=\"p\">))<\/span>\n    <span class=\"k\">return<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">allclose<\/span><span class=\"p\">(<\/span><span class=\"n\">expected<\/span><span class=\"p\">,<\/span> <span class=\"n\">actual<\/span><span class=\"p\">)<\/span>\n\n<span class=\"n\">testcases<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[([<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"mi\">2<\/span><span class=\"o\">-.<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"mi\">2<\/span><span class=\"o\">+.<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"mi\">5<\/span><span class=\"p\">],<\/span> <span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"o\">.<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"o\">.<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"mi\">1<\/span><span class=\"p\">]),<\/span>\n             <span class=\"p\">([<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"mi\">2<\/span><span class=\"o\">-<\/span><span class=\"mf\">10e-8<\/span><span class=\"p\">,<\/span> <span class=\"mi\">2<\/span><span class=\"o\">+<\/span><span class=\"mf\">10e-8<\/span><span class=\"p\">,<\/span> <span class=\"mi\">5<\/span><span class=\"p\">],<\/span> <span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"mf\">10e-8<\/span><span class=\"p\">,<\/span> <span class=\"mf\">10e-8<\/span><span class=\"p\">,<\/span> <span class=\"mi\">1<\/span><span class=\"p\">]),<\/span>\n             <span class=\"p\">([<\/span><span class=\"mf\">0.0<\/span><span class=\"p\">,<\/span><span class=\"mi\">5<\/span><span class=\"p\">],<\/span> <span class=\"p\">[<\/span><span class=\"mf\">7.0<\/span><span class=\"p\">,<\/span><span class=\"mi\">2<\/span><span class=\"p\">]),<\/span>\n             <span class=\"p\">([<\/span><span class=\"mf\">0.0<\/span><span class=\"p\">,<\/span> <span class=\"mi\">10<\/span><span class=\"p\">],<\/span> <span class=\"p\">[<\/span><span class=\"mf\">1e-4<\/span><span class=\"p\">,<\/span> <span class=\"mf\">1e-4<\/span><span class=\"p\">]),<\/span>\n             <span class=\"p\">([<\/span><span class=\"mf\">0.0<\/span><span class=\"p\">,<\/span> <span class=\"mf\">1e5<\/span><span class=\"p\">],[<\/span><span class=\"mf\">1.0<\/span><span class=\"p\">,<\/span> <span class=\"mf\">4e-9<\/span><span class=\"p\">])]<\/span>\n\n<span class=\"k\">def<\/span> <span class=\"nf\">run_straight_tests<\/span><span class=\"p\">():<\/span>\n    <span class=\"k\">print<\/span> <span class=\"s2\">&quot;all pass?&quot;<\/span><span class=\"p\">,<\/span> <span class=\"nb\">all<\/span><span class=\"p\">(<\/span><span class=\"n\">run_for<\/span><span class=\"p\">(<\/span><span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">array<\/span><span class=\"p\">(<\/span><span class=\"n\">d<\/span><span class=\"p\">),<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">array<\/span><span class=\"p\">(<\/span><span class=\"n\">z<\/span><span class=\"p\">))<\/span>\n\n<span class=\"n\">run_straight_tests<\/span><span class=\"p\">()<\/span>\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"output_wrapper\">\n<div class=\"output\">\n<div class=\"output_area\">\n<div class=\"prompt\"><\/div>\n<div class=\"output_subarea output_stream output_stdout output_text\">\n<pre>all pass? True\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<h3 id=\"references\">References<\/h3>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<p>The main references for this post come from:<\/p>\n<ol style=\"list-style-type: decimal\">\n<li>Arbenz, Peter. <a href=\"http:\/\/people.inf.ethz.ch\/arbenz\/ewp\/lnotes.html\">Lecture Notes for Solving Large Scale Eigenvalue Problems, Chapter 5: Cuppen&#8217;s Divide and Conquer Algorithm.<\/a> The single most valuable piece of this is working Matlab code for solving the secular equation. I started with this code in octave, translated it to Python+NumPy, factored out some common pieces, renamed some variables, incorporated a different stopping condition, and massaged the variable names to match the discussion in this post.<\/li>\n<li>Li, Ren-Cang. <a href=\"http:\/\/www.netlib.org\/lapack\/lawnspdf\/lawn89.pdf\">Solving Secular Equations Stably and Effciently<\/a>. This describes the theory behind LAPACK&#8217;s solution of the secular equation for the symmetric, tridiagonal eigenvalue problem. Arbenz follow the presentation of Li fairly closely. The LAPACK implementation &#8211; basically the <a href=\"http:\/\/www.netlib.org\/lapack\/explore-html\/d9\/d8b\/slaed0_8f_source.html\">LAPACK slaed<\/a> series of routines &#8211; is described by <a href=\"http:\/\/www.netlib.org\/lapack\/lawnspdf\/lawn69.pdf\">Rutter in a separate LAPACK Working Note<\/a>.<\/li>\n<li>Demmel, James. Applied Numerical Linear Algebra, Section 5.3.3: Divide-and-Conquer. Great discussion of the connection between classical Newton&#8217;s method and the non-linear version we use. Great mathematical presentation of the setup for the approximation, but he punts on the details of solving the quadratic form.<\/li>\n<\/ol>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cell border-box-sizing text_cell rendered\">\n<div class=\"prompt input_prompt\">\n<\/div>\n<div class=\"inner_cell\">\n<div class=\"text_cell_render border-box-sizing rendered_html\">\n<h3>\nAdditional Resources<br \/>\n<\/h3>\n<p>\nYou can grab a <a href=\"http:\/\/drsfenner.org\/public\/notebooks\/DC_SVD_01_SolvingTheSecularEquation.ipynb\">copy of this notebook<\/a>.\n<\/p>\n<p>\nEven better, you can <a href=\"http:\/\/nbviewer.ipython.org\/url\/drsfenner.org\/public\/notebooks\/DC_SVD_01_SolvingTheSecularEquation.ipynb\">view it using nbviewer<\/a>.\n<\/p>\n<h3>\nLicense<br \/>\n<\/h3>\n<p>\nUnless otherwise noted, the contents of this notebook are under the following license. The code in the notebook should be considered part of the text (i.e., licensed and treated as as follows).\n<\/p>\n<p><a rel=\"license\" href=\"http:\/\/creativecommons.org\/licenses\/by-nc-sa\/4.0\/\"><img decoding=\"async\" alt=\"Creative Commons License\" style=\"border-width:0\" src=\"https:\/\/i.creativecommons.org\/l\/by-nc-sa\/4.0\/88x31.png\" \/><\/a><br \/><span xmlns:dct=\"http:\/\/purl.org\/dc\/terms\/\" property=\"dct:title\">DrsFenner.org Blog And Notebooks<\/span> by <a xmlns:cc=\"http:\/\/creativecommons.org\/ns#\" href=\"drsfenner.org\" property=\"cc:attributionName\" rel=\"cc:attributionURL\">Mark and Barbara Fenner<\/a> is licensed under a <a rel=\"license\" href=\"http:\/\/creativecommons.org\/licenses\/by-nc-sa\/4.0\/\">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License<\/a>.<br \/>Permissions beyond the scope of this license may be available at <a xmlns:cc=\"http:\/\/creativecommons.org\/ns#\" href=\"drsfenner.org\/blog\/about-and-contacts\" rel=\"cc:morePermissions\">drsfenner.org\/blog\/about-and-contacts<\/a>.<\/p>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>It&#8217;s been way, way, way too long since I&#8217;ve posted. I haven&#8217;t been slacking though, I&#8217;ve merely been busy. Really. I decided to dive back into the SVD problem and look at an alternative to the QR based SVD computations. Namely, I&#8217;m going to give a breakdown of the divide-and-conquer approach to computing the SVD. [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,7],"tags":[],"class_list":["post-456","post","type-post","status-publish","format-standard","hentry","category-mrdr","category-sci-math-stat-python"],"_links":{"self":[{"href":"http:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/posts\/456","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"http:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/comments?post=456"}],"version-history":[{"count":1,"href":"http:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/posts\/456\/revisions"}],"predecessor-version":[{"id":457,"href":"http:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/posts\/456\/revisions\/457"}],"wp:attachment":[{"href":"http:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/media?parent=456"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/categories?post=456"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/tags?post=456"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}