{"id":436,"date":"2016-03-12T16:20:33","date_gmt":"2016-03-12T16:20:33","guid":{"rendered":"http:\/\/drsfenner.org\/blog\/?p=436"},"modified":"2016-03-12T16:27:15","modified_gmt":"2016-03-12T16:27:15","slug":"givens-rotations-and-the-case-of-the-blemished-bidiagonal-matrix","status":"publish","type":"post","link":"https:\/\/drsfenner.org\/blog\/2016\/03\/givens-rotations-and-the-case-of-the-blemished-bidiagonal-matrix\/","title":{"rendered":"Givens Rotations and the Case of the Blemished Bidiagonal Matrix"},"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>Last time, we looked at using Givens rotations to perform a QR factorization of a matrix. Today, we&#8217;re going to be a little more selective and use Givens rotations to walk values off the edge of a special class of matrices <!--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=\"old-friends\">Old Friends<\/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>Here are few friends that we <a href=\"http:\/\/drsfenner.org\/blog\/2016\/03\/givens-rotations-and-qr\/\">introduced last time<\/a>. I updated the interfaces a little bit: the parts that define the Givens rotation are tupled together and the target matrix is the left or right argument, depending on which multiplication we are doing.<\/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 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\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">set_printoptions<\/span><span class=\"p\">(<\/span><span class=\"n\">suppress<\/span><span class=\"o\">=<\/span><span class=\"bp\">True<\/span><span class=\"p\">)<\/span>\n<\/pre>\n<\/div>\n<\/div>\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 class=\"c1\"># GvL pg. 216 : algo 5.1.3<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">zeroing_givens_coeffs<\/span><span class=\"p\">(<\/span><span class=\"n\">x<\/span><span class=\"p\">,<\/span><span class=\"n\">z<\/span><span class=\"p\">):<\/span>\n    <span class=\"sd\">&#39;&#39;&#39; for the values x,z compute cos th, sin th <\/span>\n<span class=\"sd\">        s.t. applying a Givens rotation G(cos th,sin th) <\/span>\n<span class=\"sd\">             on 2 rows(or cols) with values x,z will<\/span>\n<span class=\"sd\">             maps x --&gt; r and z --&gt; 0&#39;&#39;&#39;<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">z<\/span> <span class=\"o\">==<\/span> <span class=\"mf\">0.0<\/span><span class=\"p\">:<\/span> <span class=\"c1\"># better to check for &quot;small&quot;: abs(z) &lt; np.finfo(np.double).eps<\/span>\n        <span class=\"k\">return<\/span> <span class=\"mf\">1.0<\/span><span class=\"p\">,<\/span><span class=\"mf\">0.0<\/span>\n    <span class=\"n\">r<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">hypot<\/span><span class=\"p\">(<\/span><span class=\"n\">x<\/span><span class=\"p\">,<\/span><span class=\"n\">z<\/span><span class=\"p\">)<\/span> <span class=\"c1\"># C99 hypot is safe for under\/overflow<\/span>\n    <span class=\"k\">return<\/span> <span class=\"n\">x<\/span><span class=\"o\">\/<\/span><span class=\"n\">r<\/span><span class=\"p\">,<\/span> <span class=\"o\">-<\/span><span class=\"n\">z<\/span><span class=\"o\">\/<\/span><span class=\"n\">r<\/span>\n<\/pre>\n<\/div>\n<\/div>\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;[3]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\" highlight hl-ipython2\">\n<pre><span class=\"c1\"># GvL, pg. 216 .... Section 5.1.9<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">left_givensT<\/span><span class=\"p\">((<\/span><span class=\"n\">c<\/span><span class=\"p\">,<\/span><span class=\"n\">s<\/span><span class=\"p\">,<\/span><span class=\"n\">r1<\/span><span class=\"p\">,<\/span><span class=\"n\">r2<\/span><span class=\"p\">),<\/span> <span class=\"n\">A<\/span><span class=\"p\">):<\/span>\n    <span class=\"sd\">&#39;&#39;&#39; update A &lt;- G.T.dot(A) ... affects rows r1 and r2 &#39;&#39;&#39;<\/span>\n    <span class=\"n\">givensT<\/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=\"n\">c<\/span><span class=\"p\">,<\/span> <span class=\"o\">-<\/span><span class=\"n\">s<\/span><span class=\"p\">],<\/span>   <span class=\"c1\"># manually transposed <\/span>\n                        <span class=\"p\">[<\/span> <span class=\"n\">s<\/span><span class=\"p\">,<\/span>  <span class=\"n\">c<\/span><span class=\"p\">]])<\/span>\n    <span class=\"n\">A<\/span><span class=\"p\">[[<\/span><span class=\"n\">r1<\/span><span class=\"p\">,<\/span><span class=\"n\">r2<\/span><span class=\"p\">],:]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">dot<\/span><span class=\"p\">(<\/span><span class=\"n\">givensT<\/span><span class=\"p\">,<\/span> <span class=\"n\">A<\/span><span class=\"p\">[[<\/span><span class=\"n\">r1<\/span><span class=\"p\">,<\/span><span class=\"n\">r2<\/span><span class=\"p\">],:])<\/span>\n\n<span class=\"k\">def<\/span> <span class=\"nf\">right_givens<\/span><span class=\"p\">(<\/span><span class=\"n\">A<\/span><span class=\"p\">,<\/span> <span class=\"p\">(<\/span><span class=\"n\">c<\/span><span class=\"p\">,<\/span><span class=\"n\">s<\/span><span class=\"p\">,<\/span><span class=\"n\">c1<\/span><span class=\"p\">,<\/span><span class=\"n\">c2<\/span><span class=\"p\">)):<\/span>\n    <span class=\"sd\">&#39;&#39;&#39; update A &lt;- A.dot(G) ... affects cols c1 and c2 &#39;&#39;&#39;<\/span>\n    <span class=\"n\">givens<\/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=\"n\">c<\/span><span class=\"p\">,<\/span> <span class=\"n\">s<\/span><span class=\"p\">],<\/span>\n                       <span class=\"p\">[<\/span><span class=\"o\">-<\/span><span class=\"n\">s<\/span><span class=\"p\">,<\/span> <span class=\"n\">c<\/span><span class=\"p\">]])<\/span>\n    <span class=\"n\">A<\/span><span class=\"p\">[:,[<\/span><span class=\"n\">c1<\/span><span class=\"p\">,<\/span> <span class=\"n\">c2<\/span><span class=\"p\">]]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">dot<\/span><span class=\"p\">(<\/span><span class=\"n\">A<\/span><span class=\"p\">[:,[<\/span><span class=\"n\">c1<\/span><span class=\"p\">,<\/span> <span class=\"n\">c2<\/span><span class=\"p\">]],<\/span> <span class=\"n\">givens<\/span><span class=\"p\">)<\/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=\"zeroing-in-a-bidiagonal-matrix-take-1\">Zeroing in a Bidiagonal Matrix (Take 1)<\/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><span class=\"math display\">\\[\\renewcommand{\\vec}[1]{\\mathbf{#1}}\\]<\/span> With the tools above and the lessons from the <a href=\"http:\/\/drsfenner.org\/blog\/2016\/03\/givens-rotations-and-qr\/\">Givens QR post<\/a> we can come up with other uses for zeroing Givens rotations which I&#8217;ll abbreviate as <span class=\"math inline\">\\(\\vec{G_0}(c,s,i,z)\\)<\/span>.<\/p>\n<p>We&#8217;re going to make use of <span class=\"math inline\">\\(\\vec{G_0}\\)<\/span> in at least two different ways, when we perform an SVD (singular value decomposition). When we perform an SVD, we&#8217;ll take an intermediate step of making an (upper) <em>bidiagonal matrix<\/em> &#8212; that is a matrix where the only non-zero entries are on the main and super-diagonals. Along the way, the <em>clean bidiagonal matrix<\/em> may become <em>blemished<\/em> and have a non-zero entry off the main upper bidiagonal band creating a <em>blemished bidiagonal matrix<\/em> (BBM). We&#8217;ll use Givens rotations to &quot;walk&quot; the non-zero blemish out of the matrix. We can do that in three directions: across a row, up a column, or zig-zagging the main diagonal band.<\/p>\n<p>To get started, we need to easily create upper bidiagonal matrices.<\/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 class=\"k\">def<\/span> <span class=\"nf\">make_upper_bidiag<\/span><span class=\"p\">(<\/span><span class=\"n\">d1<\/span><span class=\"p\">,<\/span><span class=\"n\">d2<\/span><span class=\"p\">):<\/span>\n    <span class=\"sd\">&#39;&#39;&#39; from two arrays, fill the diagonal and superdiagonal&#39;&#39;&#39;<\/span>\n    <span class=\"n\">B<\/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\">d1<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">B<\/span><span class=\"o\">.<\/span><span class=\"n\">flat<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">::<\/span><span class=\"n\">d1<\/span><span class=\"o\">.<\/span><span class=\"n\">size<\/span><span class=\"o\">+<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">d2<\/span> <span class=\"c1\"># awkward, but np.diag_indices is main diag only<\/span>\n    <span class=\"k\">return<\/span> <span class=\"n\">B<\/span>\n\n<span class=\"k\">def<\/span> <span class=\"nf\">extract_upper_bidiag<\/span><span class=\"p\">(<\/span><span class=\"n\">M<\/span><span class=\"p\">):<\/span>\n    <span class=\"sd\">&#39;&#39;&#39;from M, pull out the diagonal and superdiagonal <\/span>\n<span class=\"sd\">       like np.triu or np.tril would&#39;&#39;&#39;<\/span>\n    <span class=\"n\">B<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">triu<\/span><span class=\"p\">(<\/span><span class=\"n\">M<\/span><span class=\"p\">)<\/span> <span class=\"o\">*<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">tril<\/span><span class=\"p\">(<\/span><span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">ones_like<\/span><span class=\"p\">(<\/span><span class=\"n\">M<\/span><span class=\"p\">),<\/span> <span class=\"mi\">1<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">return<\/span> <span class=\"n\">B<\/span>\n    \n<span class=\"n\">extract_upper_bidiag<\/span><span class=\"p\">(<\/span><span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">arange<\/span><span class=\"p\">(<\/span><span class=\"mf\">36.0<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">reshape<\/span><span class=\"p\">(<\/span><span class=\"mi\">6<\/span><span class=\"p\">,<\/span><span class=\"mi\">6<\/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 output_prompt\">Out[4]:<\/div>\n<div class=\"output_text output_subarea output_execute_result\">\n<pre>array([[  0.,   1.,   0.,   0.,   0.,   0.],\n       [  0.,   7.,   8.,   0.,   0.,   0.],\n       [  0.,   0.,  14.,  15.,   0.,   0.],\n       [  0.,   0.,   0.,  21.,  22.,   0.],\n       [  0.,   0.,   0.,   0.,  28.,  29.],\n       [  0.,   0.,   0.,   0.,   0.,  35.]])<\/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<p>We might start by trying to &quot;swap&quot; the 8 with the 0 to its right. Basically, we&#8217;d try to take <span class=\"math inline\">\\(x=0 \\rightarrow 8\\)<\/span> and <span class=\"math inline\">\\(z=8 \\rightarrow 0\\)<\/span>; that is, calling <code>zeroing_givens_coeffs(0, 8)<\/code>). Before we see the results, what rows or columns are going to be modified, if our <span class=\"math inline\">\\(i,j\\)<\/span> are <span class=\"math inline\">\\(1,2\\)<\/span> and we use a right Givens rotation?<\/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;[5]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\" highlight hl-ipython2\">\n<pre><span class=\"k\">def<\/span> <span class=\"nf\">move_nonzero_using_nextright<\/span><span class=\"p\">(<\/span><span class=\"n\">M<\/span><span class=\"p\">,<\/span> <span class=\"n\">row<\/span><span class=\"p\">,<\/span> <span class=\"n\">col<\/span><span class=\"p\">):<\/span>\n    <span class=\"n\">cos_th<\/span><span class=\"p\">,<\/span><span class=\"n\">sin_th<\/span> <span class=\"o\">=<\/span> <span class=\"n\">zeroing_givens_coeffs<\/span><span class=\"p\">(<\/span><span class=\"n\">M<\/span><span class=\"p\">[<\/span><span class=\"n\">row<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"o\">+<\/span><span class=\"mi\">1<\/span><span class=\"p\">],<\/span> <span class=\"n\">M<\/span><span class=\"p\">[<\/span><span class=\"n\">row<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"p\">])<\/span>\n    <span class=\"n\">right_givens<\/span><span class=\"p\">(<\/span><span class=\"n\">M<\/span><span class=\"p\">,<\/span> <span class=\"p\">(<\/span><span class=\"n\">cos_th<\/span><span class=\"p\">,<\/span><span class=\"n\">sin_th<\/span><span class=\"p\">,<\/span> <span class=\"n\">col<\/span><span class=\"o\">+<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"n\">col<\/span><span class=\"p\">))<\/span>\n    \n<span class=\"n\">B<\/span> <span class=\"o\">=<\/span> <span class=\"n\">extract_upper_bidiag<\/span><span class=\"p\">(<\/span><span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">arange<\/span><span class=\"p\">(<\/span><span class=\"mf\">36.0<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">reshape<\/span><span class=\"p\">(<\/span><span class=\"mi\">6<\/span><span class=\"p\">,<\/span><span class=\"mi\">6<\/span><span class=\"p\">))<\/span>\n<span class=\"n\">move_nonzero_using_nextright<\/span><span class=\"p\">(<\/span><span class=\"n\">B<\/span><span class=\"p\">,<\/span> <span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"mi\">2<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">print<\/span> <span class=\"n\">B<\/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>[[  0.   1.   0.   0.   0.   0.]\n [  0.   7.   0.   8.   0.   0.]\n [  0.   0. -15.  14.   0.   0.]\n [  0.   0. -21.   0.  22.   0.]\n [  0.   0.   0.   0.  28.  29.]\n [  0.   0.   0.   0.   0.  35.]]\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<p>The Givens rotation makes use of the next column from the <code>row,col<\/code> values we passed to <code>move_nonzero_using_nextright<\/code>. So, the rotation affects columns 2 and 3 and introduces non-zeros at <code>B[1,3], B[3,2]<\/code>. We modified more values than we really wanted. In particular, when we affect <code>B[3,2]<\/code> we are modifying <em>below<\/em> the diagonal and making more blemishes. Further, we don&#8217;t really care that the <code>8<\/code> stays an <code>8<\/code> when it is &quot;swapped&quot;. So, instead of &quot;swapping&quot; a zero in, let&#8217;s find a value that is non-zero (and can stay <em>any<\/em> non-zero value). We need look no further than the main diagonal.<\/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=\"zeroing-in-a-bidiagonal-matrix-take-2\">Zeroing in a Bidiagonal Matrix (Take 2)<\/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>When I saw &quot;swapping&quot;, I what I really want to do is <em>introduce a zero off the diagonal and compute a new associated <span class=\"math inline\">\\(r\\)<\/span> on the diagonal<\/em>. So, let&#8217;s find a new position to &quot;swap&quot; with. Any of the values on the diagonal are non-zero <em>and<\/em>, as long as they stay non-zero, they don&#8217;t change the bidiagonal form of the matrix. Another aside: we actually care that the bidiagonal part is fully filled with non-zeros, or you might say, <em>dense<\/em> &#8211; although that&#8217;s a slight abuse of the term.<\/p>\n<p>Anywho. Let&#8217;s try to target a &quot;swap&quot; between a spot <span class=\"math inline\">\\(row,col\\)<\/span> and an entry on one of the two diagonal entries it shares in its row and column. When we do this, we will preserve much of the bidagonal matrix structure, since in a bidiagonal matrix, we already have entries on the diagonal. However, we will introduce or propogate a blemish. More on that in second. Here&#8217;s some code that works by using the diagonal elements. A mental quick-check: for right and left Givens rotations, do we use the shared row or column diagonal elements for our &quot;swapping&quot;?<\/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;[6]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\" highlight hl-ipython2\">\n<pre><span class=\"k\">def<\/span> <span class=\"nf\">givens_zero_wdiag_left<\/span><span class=\"p\">(<\/span><span class=\"n\">A<\/span><span class=\"p\">,<\/span> <span class=\"n\">row<\/span><span class=\"p\">,<\/span> <span class=\"n\">col<\/span><span class=\"p\">):<\/span>\n    <span class=\"sd\">&#39;&#39;&#39; update two whole rows and at col: A[row,col] &lt;- 0; A[col,col] &lt;- r<\/span>\n<span class=\"sd\">        moves value up\/down to diagonal ... within the shared column&#39;&#39;&#39;<\/span>\n    <span class=\"n\">c<\/span><span class=\"p\">,<\/span><span class=\"n\">s<\/span> <span class=\"o\">=<\/span> <span class=\"n\">zeroing_givens_coeffs<\/span><span class=\"p\">(<\/span><span class=\"n\">A<\/span><span class=\"p\">[<\/span><span class=\"n\">col<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"p\">],<\/span> <span class=\"n\">A<\/span><span class=\"p\">[<\/span><span class=\"n\">row<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"p\">])<\/span>\n    <span class=\"n\">G<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"n\">c<\/span><span class=\"p\">,<\/span><span class=\"n\">s<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"p\">,<\/span><span class=\"n\">row<\/span><span class=\"p\">)<\/span>  <span class=\"c1\"># swapped order to zero *second* arg<\/span>\n    <span class=\"n\">left_givensT<\/span><span class=\"p\">(<\/span><span class=\"n\">G<\/span><span class=\"p\">,<\/span> <span class=\"n\">A<\/span><span class=\"p\">)<\/span> <span class=\"c1\"># G tells affected *rows* - one col gets 0<\/span>\n    <span class=\"k\">return<\/span> <span class=\"n\">G<\/span>\n\n<span class=\"k\">def<\/span> <span class=\"nf\">givens_zero_wdiag_right<\/span><span class=\"p\">(<\/span><span class=\"n\">A<\/span><span class=\"p\">,<\/span> <span class=\"n\">row<\/span><span class=\"p\">,<\/span> <span class=\"n\">col<\/span><span class=\"p\">):<\/span>\n    <span class=\"sd\">&#39;&#39;&#39; update two whole cols and at row: A[row,col] &lt;- 0; A[row,row] &lt;- r<\/span>\n<span class=\"sd\">        moves value left\/right to diagonal ... within the shared row&#39;&#39;&#39;<\/span>\n    <span class=\"n\">c<\/span><span class=\"p\">,<\/span><span class=\"n\">s<\/span> <span class=\"o\">=<\/span> <span class=\"n\">zeroing_givens_coeffs<\/span><span class=\"p\">(<\/span><span class=\"n\">A<\/span><span class=\"p\">[<\/span><span class=\"n\">row<\/span><span class=\"p\">,<\/span><span class=\"n\">row<\/span><span class=\"p\">],<\/span> <span class=\"n\">A<\/span><span class=\"p\">[<\/span><span class=\"n\">row<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"p\">])<\/span>\n    <span class=\"n\">G<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"n\">c<\/span><span class=\"p\">,<\/span><span class=\"n\">s<\/span><span class=\"p\">,<\/span><span class=\"n\">row<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">right_givens<\/span><span class=\"p\">(<\/span><span class=\"n\">A<\/span><span class=\"p\">,<\/span> <span class=\"n\">G<\/span><span class=\"p\">)<\/span> <span class=\"c1\"># G tells affected *cols* - one row gets 0<\/span>\n    <span class=\"k\">return<\/span> <span class=\"n\">G<\/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<p>I mentioned, in the last post, that I didn&#8217;t like the coupling of two function calls (creating the coefficients and applying them). In the cell directly above, we couple the two calls inside a higher level function. This doesn&#8217;t really fix the argument ordering issue or the that fact that using a <code>givens_zero_wdiag_left<\/code> with a <code>right_givens<\/code> (application) would be legal code with a non-sensical result.<\/p>\n<p>If we really wanted to &quot;fix&quot; the software engineering issue, and stay with a functional (non-object oriented) solution, we could bundle the correct application (left or right) function with the result of the tuple arguments &#8212; which is basically what a class constructor would do. I did write a small set of classes to encapsulate this further, but for now I want to focus on the Givens parts, not the software engineering parts. The classes were even more useful because shortly we&#8217;ll have a special case where we can write a custom multiplication routine and save work on the left and right Givens applications. This gives quite a nice use of inheriting the basics and overriding the special case.<\/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 the code we just wrote. On the left, the application looks like:<\/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;[7]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\" highlight hl-ipython2\">\n<pre><span class=\"n\">B<\/span> <span class=\"o\">=<\/span> <span class=\"n\">extract_upper_bidiag<\/span><span class=\"p\">(<\/span><span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">arange<\/span><span class=\"p\">(<\/span><span class=\"mf\">36.0<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">reshape<\/span><span class=\"p\">(<\/span><span class=\"mi\">6<\/span><span class=\"p\">,<\/span><span class=\"mi\">6<\/span><span class=\"p\">))<\/span>\n<span class=\"n\">givens_zero_wdiag_left<\/span><span class=\"p\">(<\/span><span class=\"n\">B<\/span><span class=\"p\">,<\/span> <span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"mi\">2<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">print<\/span> <span class=\"n\">B<\/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>[[  0.           1.           0.           0.           0.           0.        ]\n [  0.           6.07770199   0.          -7.44208408   0.           0.        ]\n [  0.           3.47297257  16.1245155   13.02364713   0.           0.        ]\n [  0.           0.           0.          21.          22.           0.        ]\n [  0.           0.           0.           0.          28.          29.        ]\n [  0.           0.           0.           0.           0.          35.        ]]\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<p>At this point, you&#8217;re ready to strangle me. That isn&#8217;t upper bidiagonal any more. But wait! What happens if we have and upper-bidiagonal with a zero on the diagonal?<\/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;[8]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\" highlight hl-ipython2\">\n<pre><span class=\"n\">B<\/span> <span class=\"o\">=<\/span> <span class=\"n\">extract_upper_bidiag<\/span><span class=\"p\">(<\/span><span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">arange<\/span><span class=\"p\">(<\/span><span class=\"mf\">36.0<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">reshape<\/span><span class=\"p\">(<\/span><span class=\"mi\">6<\/span><span class=\"p\">,<\/span><span class=\"mi\">6<\/span><span class=\"p\">))<\/span>\n<span class=\"n\">B<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span>\n<span class=\"n\">givens_zero_wdiag_left<\/span><span class=\"p\">(<\/span><span class=\"n\">B<\/span><span class=\"p\">,<\/span> <span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"mi\">2<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">print<\/span> <span class=\"n\">B<\/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>[[  0.           1.           0.           0.           0.           0.        ]\n [  0.           0.           0.          -7.44208408   0.           0.        ]\n [  0.           0.          16.1245155   13.02364713   0.           0.        ]\n [  0.           0.           0.          21.          22.           0.        ]\n [  0.           0.           0.           0.          28.          29.        ]\n [  0.           0.           0.           0.           0.          35.        ]]\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<p>We move a value to the right <em>and<\/em> keep the rest of the matrix upper bidiagonal (outside the blemish in the row we&#8217;re manipulating). That leads us to &#8230;<\/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=\"blemishes\">Blemishes<\/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 also left out one point about the form of the matrix we&#8217;ll be using attacking. In reality, <em>le-subject-d&#8217;-attack<\/em> will be an upper-bidiagonal with a zero somewhere on the diagonal. The super-diagonal entry in the same row will be pushed across the row and out. Once it is off the super-diagonal, it is a &quot;blemish&quot; to the &quot;pure&quot; upper-bidiagonal matrix. Once we push it out, we&#8217;ll have <em>two<\/em> upper-bidiagonal matrices (one above and one below) the row we modified.<\/p>\n<p>Here&#8217;s the general upper-bidiagonal matrix (no blemishes):<\/p>\n<p><span class=\"math display\">\\[G=\\begin{bmatrix}<br \/>\nd_1    &amp; s_1    &amp; 0      &amp;         &amp; \\dots   &amp; 0       \\\\<br \/>\n0      &amp; d_2    &amp; s_2    &amp;         &amp;         &amp; 0       \\\\<br \/>\n       &amp; \\ddots &amp; \\ddots &amp; \\ddots  &amp; \\ddots  &amp; \\vdots  \\\\<br \/>\n\\vdots &amp;        &amp;        &amp; d_{n-2} &amp; s_{n-2} &amp; 0       \\\\<br \/>\n       &amp;        &amp;        &amp;         &amp; d_{n-1} &amp; s_{n-1} \\\\<br \/>\n0      &amp;        &amp; \\dots  &amp;         &amp; 0       &amp; d_n<br \/>\n\\end{bmatrix}\\]<\/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>If we introduce a <span class=\"math inline\">\\(0\\)<\/span> on the diagonal somewhere, we can talk about &quot;walking&quot; the superdiagonal element in that same row off to the right. Here, the <font color=\"red\">two red values<\/font> are passed to <code>zeroing_givens_coeffs<\/code> to compute the coefficient values that will zero the value in the upper row. To the right of an arrow, the <font color=\"blue\">blue elements<\/font> are newly computed updates. The <span class=\"math inline\">\\(\\color{red}{B}\\)<\/span>, our blemish, has also been updated: <span class=\"math inline\">\\(0 \\rightarrow \\color{red}{B}\\)<\/span>. Note, the <span class=\"math inline\">\\(x\\)<\/span> and <span class=\"math inline\">\\(B\\)<\/span> names merely indicate the zeroness of a value &#8211; two different <span class=\"math inline\">\\(x\\)<\/span> or <span class=\"math inline\">\\(B\\)<\/span> will have different values. Generally speaking <span class=\"math inline\">\\(B\\)<\/span> will be different in different steps.<\/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\\renewcommand{\\red}[1]{\\color{red}{#1}}<br \/>\n\\renewcommand{\\blue}[1]{\\color{blue}{#1}}<br \/>\n\\begin{align}<br \/>\nA = \\begin{bmatrix}<br \/>\nx &amp; x &amp; 0 &amp; 0 &amp; 0 \\\\<br \/>\n0 &amp; 0 &amp; \\red{x} &amp; 0 &amp; 0 \\\\<br \/>\n0 &amp; 0 &amp; \\red{x} &amp; x &amp; 0 \\\\<br \/>\n0 &amp; 0 &amp; 0 &amp; x &amp; x \\\\<br \/>\n0 &amp; 0 &amp; 0 &amp; 0 &amp; x \\\\<br \/>\n\\end{bmatrix}<br \/>\n&amp; \\xrightarrow{G^T_z(c,s,2,1) A} &amp;<br \/>\n\\begin{bmatrix}<br \/>\nx &amp; x &amp; 0 &amp; 0 &amp; 0 \\\\<br \/>\n0 &amp; 0 &amp; \\blue{0} &amp; \\red{B} &amp; 0 \\\\<br \/>\n0 &amp; 0 &amp; \\blue{x} &amp; \\blue{x} &amp; 0 \\\\<br \/>\n0 &amp; 0 &amp; 0 &amp; \\color{red}{x} &amp; x \\\\<br \/>\n0 &amp; 0 &amp; 0 &amp; 0 &amp; x \\\\<br \/>\n\\end{bmatrix} \\\\<br \/>\n&amp; \\xrightarrow{G^T_z(c,s,3,2) A} &amp;<br \/>\n\\begin{bmatrix}<br \/>\nx &amp; x &amp; 0 &amp; 0 &amp; 0 \\\\<br \/>\n0 &amp; 0 &amp; 0 &amp; \\blue{0} &amp; \\red{B} \\\\<br \/>\n0 &amp; 0 &amp; x &amp; x &amp; 0 \\\\<br \/>\n0 &amp; 0 &amp; 0 &amp; \\blue{x} &amp; \\blue{x} \\\\<br \/>\n0 &amp; 0 &amp; 0 &amp; 0 &amp; \\color{red}{x} \\\\<br \/>\n\\end{bmatrix} \\\\<br \/>\n&amp; \\xrightarrow{G^T_z(c,s,4,2) A} &amp;<br \/>\n\\begin{bmatrix}<br \/>\nx &amp; x &amp; 0 &amp; 0 &amp; 0 \\\\<br \/>\n0 &amp; 0 &amp; 0 &amp; 0 &amp; \\blue{0} \\\\<br \/>\n0 &amp; 0 &amp; x &amp; x &amp; 0 \\\\<br \/>\n0 &amp; 0 &amp; 0 &amp; x &amp; x \\\\<br \/>\n0 &amp; 0 &amp; 0 &amp; 0 &amp; \\blue{x} \\\\<br \/>\n\\end{bmatrix}<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>When we move <code>A[1,2]<\/code> to the right, we have to involve the <span class=\"math inline\">\\((1,2)\\)<\/span>-plane. That is, we need a Givens rotation on the <span class=\"math inline\">\\((1,2)\\)<\/span>-plane (and zeroing in the 1 plane). Since we&#8217;re applying a left-Givens, we are only updating two rows: <code>1<\/code> and <code>2<\/code>. Within those rows, the only nonzero entries are in columns <code>2<\/code> and <code>3<\/code>. So, using a similar argument to that we used for the QR algorithm last time, we can see that columns <code>0<\/code>, <code>1<\/code>, and <code>4<\/code> are unchanged and remain zero.<\/p>\n<p>We can get a bit more specific about the values for columns <code>2<\/code> and <code>3<\/code>. Let&#8217;s name the relevant <span class=\"math inline\">\\(x\\)<\/span> values:<\/p>\n<ul>\n<li><span class=\"math inline\">\\(b\\)<\/span> the blemish. In <span class=\"math inline\">\\(\\vec{A}\\)<\/span> it&#8217;s the only non-zero in row <span class=\"math inline\">\\(1\\)<\/span>; it&#8217;s also the upper red <span class=\"math inline\">\\(x\\)<\/span>.<\/li>\n<li><span class=\"math inline\">\\(d\\)<\/span> the diagonal value <em>below<\/em> <span class=\"math inline\">\\(b\\)<\/span>. In <span class=\"math inline\">\\(\\vec{A}\\)<\/span>, the lower red <span class=\"math inline\">\\(x\\)<\/span>.<\/li>\n<li><span class=\"math inline\">\\(f\\)<\/span> the friend. The value to the right of <span class=\"math inline\">\\(d\\)<\/span> &#8211; it&#8217;s the super-diagonal super-Friend of <span class=\"math inline\">\\(d\\)<\/span>. In <span class=\"math inline\">\\(\\vec{A}\\)<\/span>, it is at <code>A[2,3]<\/code>.<\/li>\n<\/ul>\n<p>These are the only values from <span class=\"math inline\">\\(\\vec{A}\\)<\/span> we need to calculate <span class=\"math inline\">\\(\\vec{G^TA}\\)<\/span>. Everything else disappears to zero. In the last iteration, there is no value to the right of <span class=\"math inline\">\\(d\\)<\/span>, so we can ignore it. We&#8217;ll can use this knowledge to optimize the matrix multiplication from two dot-products (the length of the whole rows) down to a couple of multiplications and additions.<\/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=\"efficient-blemish-updating\">Efficient Blemish Updating<\/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>Based on the patterns of blue and red above, you might be thinking &quot;gee, I don&#8217;t think we need the whole row&quot; to do that update. We don&#8217;t. Turns out, we can do a &quot;custom&quot; multiplication routine for a Givens rotation against a <em>blemished upper bidiagonal matrix<\/em>, or BBM. Here&#8217;s the same left Givens multiplication (as the first <span class=\"math inline\">\\(\\vec{G^T_z}\\)<\/span> above) written out by hand but not doing any unnecessary computations with zeros. Remember, <code>friend<\/code> is the resulting blue, non-zero superdiagonal entry involved in that step.<\/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;[9]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\" highlight hl-ipython2\">\n<pre><span class=\"n\">B<\/span> <span class=\"o\">=<\/span> <span class=\"n\">extract_upper_bidiag<\/span><span class=\"p\">(<\/span><span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">arange<\/span><span class=\"p\">(<\/span><span class=\"mf\">36.0<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">reshape<\/span><span class=\"p\">(<\/span><span class=\"mi\">6<\/span><span class=\"p\">,<\/span><span class=\"mi\">6<\/span><span class=\"p\">))<\/span>\n<span class=\"n\">B<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span>\n\n<span class=\"c1\"># the setup:<\/span>\n<span class=\"c1\"># . . . . . <\/span>\n<span class=\"c1\"># . 0 B 0 0<\/span>\n<span class=\"c1\"># . 0 D F 0<\/span>\n<span class=\"c1\"># <\/span>\n<span class=\"n\">row<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"mi\">2<\/span>\n<span class=\"n\">blemish_loc<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"n\">row<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">diag_loc<\/span>    <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"n\">col<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">friend_loc<\/span>  <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"n\">col<\/span><span class=\"p\">,<\/span> <span class=\"n\">col<\/span><span class=\"o\">+<\/span><span class=\"mi\">1<\/span><span class=\"p\">)<\/span>\n\n<span class=\"n\">blemish<\/span> <span class=\"o\">=<\/span> <span class=\"n\">B<\/span><span class=\"p\">[<\/span><span class=\"n\">blemish_loc<\/span><span class=\"p\">]<\/span>\n<span class=\"n\">diag<\/span>    <span class=\"o\">=<\/span> <span class=\"n\">B<\/span><span class=\"p\">[<\/span><span class=\"n\">diag_loc<\/span><span class=\"p\">]<\/span>\n<span class=\"n\">friend<\/span>  <span class=\"o\">=<\/span> <span class=\"n\">B<\/span><span class=\"p\">[<\/span><span class=\"n\">friend_loc<\/span><span class=\"p\">]<\/span>\n\n<span class=\"n\">c<\/span><span class=\"p\">,<\/span><span class=\"n\">s<\/span> <span class=\"o\">=<\/span> <span class=\"n\">zeroing_givens_coeffs<\/span><span class=\"p\">(<\/span><span class=\"n\">diag<\/span><span class=\"p\">,<\/span> <span class=\"n\">blemish<\/span><span class=\"p\">)<\/span>\n\n<span class=\"c1\"># G^T = <\/span>\n<span class=\"c1\">#       [s  c]  --&gt; zeroing row<\/span>\n<span class=\"n\">B<\/span><span class=\"p\">[<\/span><span class=\"n\">blemish_loc<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">diag<\/span> <span class=\"o\">*<\/span> <span class=\"n\">s<\/span> <span class=\"o\">+<\/span> <span class=\"n\">blemish<\/span> <span class=\"o\">*<\/span> <span class=\"n\">c<\/span> <span class=\"c1\"># == 0<\/span>\n<span class=\"n\">B<\/span><span class=\"p\">[<\/span><span class=\"n\">diag_loc<\/span><span class=\"p\">]<\/span>    <span class=\"o\">=<\/span> <span class=\"n\">diag<\/span> <span class=\"o\">*<\/span> <span class=\"n\">c<\/span> <span class=\"o\">-<\/span> <span class=\"n\">blemish<\/span> <span class=\"o\">*<\/span> <span class=\"n\">s<\/span>\n\n<span class=\"n\">new_blemish_loc<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"n\">row<\/span><span class=\"p\">,<\/span> <span class=\"n\">col<\/span><span class=\"o\">+<\/span><span class=\"mi\">1<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">B<\/span><span class=\"p\">[<\/span><span class=\"n\">new_blemish_loc<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">s<\/span> <span class=\"o\">*<\/span> <span class=\"n\">friend<\/span>\n<span class=\"n\">B<\/span><span class=\"p\">[<\/span><span class=\"n\">friend_loc<\/span><span class=\"p\">]<\/span>      <span class=\"o\">=<\/span> <span class=\"n\">c<\/span> <span class=\"o\">*<\/span> <span class=\"n\">friend<\/span>\n\n<span class=\"k\">print<\/span> <span class=\"n\">B<\/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>[[  0.           1.           0.           0.           0.           0.        ]\n [  0.           0.           0.          -7.44208408   0.           0.        ]\n [  0.           0.          16.1245155   13.02364713   0.           0.        ]\n [  0.           0.           0.          21.          22.           0.        ]\n [  0.           0.           0.           0.          28.          29.        ]\n [  0.           0.           0.           0.           0.          35.        ]]\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<p>Do we get the same thing using our machinery? We got the same result in <code>In[8]<\/code>. We don&#8217;t need to be nearly as explicit as I was in <code>In[9]<\/code>, nor do we need to save all of those values in temporaries. Trimming it down, we can do this:<\/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;[10]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\" highlight hl-ipython2\">\n<pre><span class=\"k\">def<\/span> <span class=\"nf\">givens_zero_wdiag_left_on_BBM<\/span><span class=\"p\">(<\/span><span class=\"n\">BBM<\/span><span class=\"p\">,<\/span> <span class=\"n\">row<\/span><span class=\"p\">,<\/span> <span class=\"n\">col<\/span><span class=\"p\">):<\/span>\n    <span class=\"c1\">#assert really BBM<\/span>\n    <span class=\"n\">m<\/span><span class=\"p\">,<\/span><span class=\"n\">n<\/span> <span class=\"o\">=<\/span> <span class=\"n\">BBM<\/span><span class=\"o\">.<\/span><span class=\"n\">shape<\/span>\n    <span class=\"n\">c<\/span><span class=\"p\">,<\/span><span class=\"n\">s<\/span> <span class=\"o\">=<\/span> <span class=\"n\">zeroing_givens_coeffs<\/span><span class=\"p\">(<\/span><span class=\"n\">BBM<\/span><span class=\"p\">[<\/span><span class=\"n\">col<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"p\">],<\/span> <span class=\"n\">BBM<\/span><span class=\"p\">[<\/span><span class=\"n\">row<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"p\">])<\/span>\n\n    <span class=\"c1\">#       col   col+1<\/span>\n    <span class=\"c1\"># row   blem new_blem      G^T = <\/span>\n    <span class=\"c1\">#        <\/span>\n    <span class=\"c1\"># col   diag friend              [s  c] ---&gt; zeroing row<\/span>\n\n    <span class=\"n\">old_blemish<\/span> <span class=\"o\">=<\/span> <span class=\"n\">BBM<\/span><span class=\"p\">[<\/span><span class=\"n\">row<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"p\">]<\/span>\n    <span class=\"n\">BBM<\/span><span class=\"p\">[<\/span><span class=\"n\">row<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span>                                  <span class=\"c1\"># from zeroing row<\/span>\n    <span class=\"n\">BBM<\/span><span class=\"p\">[<\/span><span class=\"n\">col<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">BBM<\/span><span class=\"p\">[<\/span><span class=\"n\">col<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"p\">]<\/span> <span class=\"o\">*<\/span> <span class=\"n\">c<\/span> <span class=\"o\">-<\/span> <span class=\"n\">old_blemish<\/span> <span class=\"o\">*<\/span> <span class=\"n\">s<\/span> <span class=\"c1\"># from top row<\/span>\n\n    <span class=\"k\">if<\/span> <span class=\"n\">col<\/span> <span class=\"o\">&lt;<\/span> <span class=\"n\">n<\/span><span class=\"o\">-<\/span><span class=\"mi\">1<\/span><span class=\"p\">:<\/span> <span class=\"c1\"># update these in all but last column<\/span>\n        <span class=\"n\">BBM<\/span><span class=\"p\">[<\/span><span class=\"n\">row<\/span><span class=\"p\">,<\/span> <span class=\"n\">col<\/span><span class=\"o\">+<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">s<\/span> <span class=\"o\">*<\/span> <span class=\"n\">BBM<\/span><span class=\"p\">[<\/span><span class=\"n\">col<\/span><span class=\"p\">,<\/span> <span class=\"n\">col<\/span><span class=\"o\">+<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span>\n        <span class=\"n\">BBM<\/span><span class=\"p\">[<\/span><span class=\"n\">col<\/span><span class=\"p\">,<\/span> <span class=\"n\">col<\/span><span class=\"o\">+<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span> <span class=\"o\">*=<\/span> <span class=\"n\">c<\/span>\n    <span class=\"k\">return<\/span> <span class=\"p\">(<\/span><span class=\"n\">c<\/span><span class=\"p\">,<\/span><span class=\"n\">s<\/span><span class=\"p\">,<\/span><span class=\"n\">row<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"p\">)<\/span> <span class=\"c1\"># == G<\/span>\n<\/pre>\n<\/div>\n<\/div>\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;[11]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\" highlight hl-ipython2\">\n<pre><span class=\"n\">B<\/span> <span class=\"o\">=<\/span> <span class=\"n\">extract_upper_bidiag<\/span><span class=\"p\">(<\/span><span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">sqrt<\/span><span class=\"p\">(<\/span><span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">arange<\/span><span class=\"p\">(<\/span><span class=\"mf\">1.0<\/span><span class=\"p\">,<\/span><span class=\"mf\">26.0<\/span><span class=\"p\">))<\/span><span class=\"o\">.<\/span><span class=\"n\">reshape<\/span><span class=\"p\">(<\/span><span class=\"mi\">5<\/span><span class=\"p\">,<\/span><span class=\"mi\">5<\/span><span class=\"p\">))<\/span>\n<span class=\"n\">B<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"mf\">0.0<\/span>\n<span class=\"k\">print<\/span> <span class=\"n\">B<\/span>\n\n<span class=\"n\">givens_zero_wdiag_left_on_BBM<\/span><span class=\"p\">(<\/span><span class=\"n\">B<\/span><span class=\"p\">,<\/span> <span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"mi\">2<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">print<\/span> <span class=\"n\">B<\/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>[[ 1.          1.41421356  0.          0.          0.        ]\n [ 0.          0.          2.82842712  0.          0.        ]\n [ 0.          0.          3.60555128  3.74165739  0.        ]\n [ 0.          0.          0.          4.35889894  4.47213595]\n [ 0.          0.          0.          0.          5.        ]]\n[[ 1.          1.41421356  0.          0.          0.        ]\n [ 0.          0.          0.         -2.30940108  0.        ]\n [ 0.          0.          4.58257569  2.94392029  0.        ]\n [ 0.          0.          0.          4.35889894  4.47213595]\n [ 0.          0.          0.          0.          5.        ]]\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<p>And finally, we can put that in a loop to walk a value all the way off the right edge of the matrix:<\/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;[12]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\" highlight hl-ipython2\">\n<pre><span class=\"k\">def<\/span> <span class=\"nf\">walk_blemish_out_right<\/span><span class=\"p\">(<\/span><span class=\"n\">B<\/span><span class=\"p\">,<\/span> <span class=\"n\">row<\/span><span class=\"p\">,<\/span> <span class=\"n\">start_col<\/span><span class=\"p\">):<\/span> <span class=\"c1\"># usually start_col = row+1<\/span>\n    <span class=\"n\">m<\/span><span class=\"p\">,<\/span><span class=\"n\">n<\/span> <span class=\"o\">=<\/span> <span class=\"n\">B<\/span><span class=\"o\">.<\/span><span class=\"n\">shape<\/span>\n    <span class=\"k\">for<\/span> <span class=\"n\">col<\/span> <span class=\"ow\">in<\/span> <span class=\"nb\">xrange<\/span><span class=\"p\">(<\/span><span class=\"n\">start_col<\/span><span class=\"p\">,<\/span> <span class=\"n\">n<\/span><span class=\"p\">):<\/span>\n        <span class=\"n\">givens_zero_wdiag_left_on_BBM<\/span><span class=\"p\">(<\/span><span class=\"n\">B<\/span><span class=\"p\">,<\/span> <span class=\"n\">row<\/span><span class=\"p\">,<\/span> <span class=\"n\">col<\/span><span class=\"p\">)<\/span>\n\n<span class=\"n\">B<\/span> <span class=\"o\">=<\/span> <span class=\"n\">extract_upper_bidiag<\/span><span class=\"p\">(<\/span><span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">arange<\/span><span class=\"p\">(<\/span><span class=\"mf\">25.0<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">reshape<\/span><span class=\"p\">(<\/span><span class=\"mi\">5<\/span><span class=\"p\">,<\/span><span class=\"mi\">5<\/span><span class=\"p\">))<\/span>\n<span class=\"n\">B<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"mf\">0.0<\/span>\n<span class=\"k\">print<\/span> <span class=\"n\">B<\/span>\n\n<span class=\"n\">walk_blemish_out_right<\/span><span class=\"p\">(<\/span><span class=\"n\">B<\/span><span class=\"p\">,<\/span> <span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"mi\">2<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">print<\/span> <span class=\"n\">B<\/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>[[  0.   1.   0.   0.   0.]\n [  0.   0.   7.   0.   0.]\n [  0.   0.  12.  13.   0.]\n [  0.   0.   0.  18.  19.]\n [  0.   0.   0.   0.  24.]]\n[[  0.           1.           0.           0.           0.        ]\n [  0.           0.           0.           0.           0.        ]\n [  0.           0.          13.89244399  11.22912571   0.        ]\n [  0.           0.           0.          19.15480973  17.85452348]\n [  0.           0.           0.           0.          24.86394963]]\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<p>Woot! Err, well, at least it&#8217;s done. When you look at the result, you might notice that we took an &quot;almost-full&quot; bidiagonal matrix (with one bad row) and converted it into two &quot;full&quot; bidiagonal matrices separated by an empty row. If that looks like decomposing a larger problem into smaller ones, you&#8217;re right! Although, we are not leading up to the algorithm that is traditionally called &quot;divide-and-conquer SVD&quot;.<\/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=\"walking-up\">Walking Up<\/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>We have one other case to consider. If the zero on the diagonal is in the bottom-right corner, than we <em>can&#8217;t<\/em> swap to the diagonal in that column because we&#8217;d end up taking a zero to a non-zero. So instead, we will walk the blemish <em>up<\/em> the column, swapping to the diagonal in the same row. From one perspective, this is the opposite what we did when walking to the right.<\/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&#8217;s a version using the full Givens multiplication. We can use it to check the output of a customized &quot;blemish-aware&quot; version in a minute.<\/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;[13]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\" highlight hl-ipython2\">\n<pre><span class=\"n\">B<\/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\">extract_upper_bidiag<\/span><span class=\"p\">(<\/span><span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">arange<\/span><span class=\"p\">(<\/span><span class=\"mf\">9.0<\/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\">3<\/span><span class=\"p\">)))<\/span>\n<span class=\"n\">B<\/span><span class=\"p\">[<\/span><span class=\"mi\">2<\/span><span class=\"p\">,<\/span><span class=\"mi\">2<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span>\n<span class=\"k\">print<\/span> <span class=\"n\">B<\/span>\n<span class=\"n\">givens_zero_wdiag_right<\/span><span class=\"p\">(<\/span><span class=\"n\">B<\/span><span class=\"p\">,<\/span> <span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"mi\">2<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">print<\/span> <span class=\"n\">B<\/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>[[ 0.          1.          0.        ]\n [ 0.          2.          2.23606798]\n [ 0.          0.          0.        ]]\n[[ 0.          0.66666667 -0.74535599]\n [ 0.          3.          0.        ]\n [ 0.          0.          0.        ]]\n<\/pre>\n<\/div>\n<\/div>\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;[14]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\" highlight hl-ipython2\">\n<pre><span class=\"k\">def<\/span> <span class=\"nf\">givens_zero_wdiag_right_on_BBM<\/span><span class=\"p\">(<\/span><span class=\"n\">BBM<\/span><span class=\"p\">,<\/span> <span class=\"n\">row<\/span><span class=\"p\">,<\/span> <span class=\"n\">col<\/span><span class=\"p\">):<\/span>\n    <span class=\"c1\">#assert really BBM<\/span>\n    <span class=\"n\">m<\/span><span class=\"p\">,<\/span><span class=\"n\">n<\/span> <span class=\"o\">=<\/span> <span class=\"n\">BBM<\/span><span class=\"o\">.<\/span><span class=\"n\">shape<\/span>\n    <span class=\"n\">c<\/span><span class=\"p\">,<\/span><span class=\"n\">s<\/span> <span class=\"o\">=<\/span> <span class=\"n\">zeroing_givens_coeffs<\/span><span class=\"p\">(<\/span><span class=\"n\">BBM<\/span><span class=\"p\">[<\/span><span class=\"n\">row<\/span><span class=\"p\">,<\/span><span class=\"n\">row<\/span><span class=\"p\">],<\/span> <span class=\"n\">BBM<\/span><span class=\"p\">[<\/span><span class=\"n\">row<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"p\">])<\/span>\n\n    <span class=\"c1\">#         row     col                 zero column<\/span>\n    <span class=\"c1\"># row-1   friend  new_blem    G = <\/span>\n    <span class=\"c1\">#        <\/span>\n    <span class=\"c1\"># row     diag    blem            [-s  c] <\/span>\n\n    <span class=\"n\">old_blemish<\/span> <span class=\"o\">=<\/span> <span class=\"n\">BBM<\/span><span class=\"p\">[<\/span><span class=\"n\">row<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"p\">]<\/span>\n    <span class=\"n\">BBM<\/span><span class=\"p\">[<\/span><span class=\"n\">row<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span>                                  <span class=\"c1\"># from zeroing col<\/span>\n    <span class=\"n\">BBM<\/span><span class=\"p\">[<\/span><span class=\"n\">row<\/span><span class=\"p\">,<\/span><span class=\"n\">row<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">BBM<\/span><span class=\"p\">[<\/span><span class=\"n\">row<\/span><span class=\"p\">,<\/span><span class=\"n\">row<\/span><span class=\"p\">]<\/span> <span class=\"o\">*<\/span> <span class=\"n\">c<\/span> <span class=\"o\">-<\/span> <span class=\"n\">old_blemish<\/span> <span class=\"o\">*<\/span> <span class=\"n\">s<\/span> <span class=\"c1\"># from left col<\/span>\n\n    <span class=\"k\">if<\/span> <span class=\"n\">row<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span><span class=\"p\">:<\/span> <span class=\"c1\"># update these in all but last row<\/span>\n        <span class=\"n\">BBM<\/span><span class=\"p\">[<\/span><span class=\"n\">row<\/span><span class=\"o\">-<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"n\">col<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">s<\/span> <span class=\"o\">*<\/span> <span class=\"n\">BBM<\/span><span class=\"p\">[<\/span><span class=\"n\">row<\/span><span class=\"o\">-<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"n\">row<\/span><span class=\"p\">]<\/span>\n        <span class=\"n\">BBM<\/span><span class=\"p\">[<\/span><span class=\"n\">row<\/span><span class=\"o\">-<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"n\">row<\/span><span class=\"p\">]<\/span> <span class=\"o\">*=<\/span> <span class=\"n\">c<\/span>\n    <span class=\"k\">return<\/span> <span class=\"p\">(<\/span><span class=\"n\">c<\/span><span class=\"p\">,<\/span><span class=\"n\">s<\/span><span class=\"p\">,<\/span><span class=\"n\">row<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"p\">)<\/span> <span class=\"c1\"># == G<\/span>\n<\/pre>\n<\/div>\n<\/div>\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;[15]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\" highlight hl-ipython2\">\n<pre><span class=\"n\">B<\/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\">extract_upper_bidiag<\/span><span class=\"p\">(<\/span><span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">arange<\/span><span class=\"p\">(<\/span><span class=\"mf\">9.0<\/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\">3<\/span><span class=\"p\">)))<\/span>\n<span class=\"n\">B<\/span><span class=\"p\">[<\/span><span class=\"mi\">2<\/span><span class=\"p\">,<\/span><span class=\"mi\">2<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"mf\">0.0<\/span>\n<span class=\"k\">print<\/span> <span class=\"n\">B<\/span>\n\n<span class=\"n\">givens_zero_wdiag_right_on_BBM<\/span><span class=\"p\">(<\/span><span class=\"n\">B<\/span><span class=\"p\">,<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"mi\">2<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">print<\/span> <span class=\"n\">B<\/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>[[ 0.          1.          0.        ]\n [ 0.          2.          2.23606798]\n [ 0.          0.          0.        ]]\n[[ 0.          0.66666667 -0.74535599]\n [ 0.          3.          0.        ]\n [ 0.          0.          0.        ]]\n<\/pre>\n<\/div>\n<\/div>\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;[16]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\" highlight hl-ipython2\">\n<pre><span class=\"k\">def<\/span> <span class=\"nf\">walk_blemish_out_up<\/span><span class=\"p\">(<\/span><span class=\"n\">B<\/span><span class=\"p\">,<\/span> <span class=\"n\">start_row<\/span><span class=\"p\">,<\/span> <span class=\"n\">col<\/span><span class=\"p\">):<\/span> <span class=\"c1\"># usually start_row = col-1<\/span>\n    <span class=\"n\">m<\/span><span class=\"p\">,<\/span><span class=\"n\">n<\/span> <span class=\"o\">=<\/span> <span class=\"n\">B<\/span><span class=\"o\">.<\/span><span class=\"n\">shape<\/span>\n    <span class=\"k\">for<\/span> <span class=\"n\">row<\/span> <span class=\"ow\">in<\/span> <span class=\"nb\">reversed<\/span><span class=\"p\">(<\/span><span class=\"nb\">xrange<\/span><span class=\"p\">(<\/span><span class=\"n\">start_row<\/span><span class=\"o\">+<\/span><span class=\"mi\">1<\/span><span class=\"p\">)):<\/span>\n        <span class=\"n\">givens_zero_wdiag_right_on_BBM<\/span><span class=\"p\">(<\/span><span class=\"n\">B<\/span><span class=\"p\">,<\/span> <span class=\"n\">row<\/span><span class=\"p\">,<\/span> <span class=\"n\">col<\/span><span class=\"p\">)<\/span>\n\n<span class=\"n\">B<\/span> <span class=\"o\">=<\/span> <span class=\"n\">extract_upper_bidiag<\/span><span class=\"p\">(<\/span><span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">arange<\/span><span class=\"p\">(<\/span><span class=\"mf\">25.0<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">reshape<\/span><span class=\"p\">(<\/span><span class=\"mi\">5<\/span><span class=\"p\">,<\/span><span class=\"mi\">5<\/span><span class=\"p\">))<\/span>\n<span class=\"n\">B<\/span><span class=\"p\">[<\/span><span class=\"mi\">4<\/span><span class=\"p\">,<\/span><span class=\"mi\">4<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"mf\">0.0<\/span>\n<span class=\"k\">print<\/span> <span class=\"n\">B<\/span>\n\n<span class=\"n\">walk_blemish_out_up<\/span><span class=\"p\">(<\/span><span class=\"n\">B<\/span><span class=\"p\">,<\/span> <span class=\"mi\">3<\/span><span class=\"p\">,<\/span> <span class=\"mi\">4<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">print<\/span> <span class=\"n\">B<\/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>[[  0.   1.   0.   0.   0.]\n [  0.   6.   7.   0.   0.]\n [  0.   0.  12.  13.   0.]\n [  0.   0.   0.  18.  19.]\n [  0.   0.   0.   0.   0.]]\n[[  0.5849499    0.81106943   0.           0.           0.        ]\n [  0.           7.39764046   5.50226459   0.           0.        ]\n [  0.           0.          15.26644142   8.94068042   0.        ]\n [  0.           0.           0.          26.17250466   0.        ]\n [  0.           0.           0.           0.           0.        ]]\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<p>Here, we&#8217;ve reduced the larger matrix to a slightly smaller matrix. This allows us to solve a single, slightly smaller, problem. It&#8217;s just one subproblem, instead of the two subproblems we got when we walked a blemish out along a row.<\/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=\"and-finally-cleaning-up-the-superdiagonal\">And Finally, Cleaning up the Superdiagonal<\/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>In G&amp;VL, they call the decomposing of a large problem into two smaller problems &quot;decoupling&quot;. And, I&#8217;ll call the reduction part reduce. So, depending on where we find a zero on the main diagonal, we&#8217;ll either decouple or reduce. We can put those together:<\/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;[17]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\" highlight hl-ipython2\">\n<pre><span class=\"k\">def<\/span> <span class=\"nf\">decouple_or_reduce<\/span><span class=\"p\">(<\/span><span class=\"n\">B<\/span><span class=\"p\">,<\/span> <span class=\"n\">zero_idxs<\/span><span class=\"p\">):<\/span>\n    <span class=\"c1\"># see GvL, pg. 454 and pray for mojo<\/span>\n    <span class=\"n\">m<\/span><span class=\"p\">,<\/span><span class=\"n\">n<\/span> <span class=\"o\">=<\/span> <span class=\"n\">B<\/span><span class=\"o\">.<\/span><span class=\"n\">shape<\/span>\n    <span class=\"k\">for<\/span> <span class=\"n\">kk<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">zero_idxs<\/span><span class=\"p\">:<\/span>\n        <span class=\"k\">if<\/span> <span class=\"n\">kk<\/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\">walk_blemish_out_right<\/span><span class=\"p\">(<\/span><span class=\"n\">B<\/span><span class=\"p\">,<\/span> <span class=\"n\">kk<\/span><span class=\"p\">,<\/span> <span class=\"n\">kk<\/span><span class=\"o\">+<\/span><span class=\"mi\">1<\/span><span class=\"p\">)<\/span> <span class=\"c1\"># decouple<\/span>\n        <span class=\"k\">elif<\/span> <span class=\"n\">kk<\/span> <span class=\"o\">==<\/span> <span class=\"n\">n<\/span><span class=\"o\">-<\/span><span class=\"mi\">1<\/span><span class=\"p\">:<\/span>\n            <span class=\"n\">walk_blemish_out_up<\/span><span class=\"p\">(<\/span><span class=\"n\">B<\/span><span class=\"p\">,<\/span> <span class=\"n\">kk<\/span><span class=\"o\">-<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"n\">kk<\/span><span class=\"p\">)<\/span>    <span class=\"c1\"># reduce<\/span>\n<\/pre>\n<\/div>\n<\/div>\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;[18]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\" highlight hl-ipython2\">\n<pre><span class=\"n\">B<\/span> <span class=\"o\">=<\/span> <span class=\"n\">extract_upper_bidiag<\/span><span class=\"p\">(<\/span><span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">arange<\/span><span class=\"p\">(<\/span><span class=\"mf\">25.0<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">reshape<\/span><span class=\"p\">(<\/span><span class=\"mi\">5<\/span><span class=\"p\">,<\/span><span class=\"mi\">5<\/span><span class=\"p\">))<\/span>\n<span class=\"n\">B<\/span><span class=\"p\">[<\/span><span class=\"mi\">4<\/span><span class=\"p\">,<\/span><span class=\"mi\">4<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"mf\">0.0<\/span>\n<span class=\"k\">print<\/span> <span class=\"n\">B<\/span>\n<span class=\"n\">decouple_or_reduce<\/span><span class=\"p\">(<\/span><span class=\"n\">B<\/span><span class=\"p\">,<\/span> <span class=\"p\">[<\/span><span class=\"mi\">4<\/span><span class=\"p\">])<\/span>\n<span class=\"k\">print<\/span> <span class=\"n\">B<\/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>[[  0.   1.   0.   0.   0.]\n [  0.   6.   7.   0.   0.]\n [  0.   0.  12.  13.   0.]\n [  0.   0.   0.  18.  19.]\n [  0.   0.   0.   0.   0.]]\n[[  0.5849499    0.81106943   0.           0.           0.        ]\n [  0.           7.39764046   5.50226459   0.           0.        ]\n [  0.           0.          15.26644142   8.94068042   0.        ]\n [  0.           0.           0.          26.17250466   0.        ]\n [  0.           0.           0.           0.           0.        ]]\n<\/pre>\n<\/div>\n<\/div>\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;[19]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\" highlight hl-ipython2\">\n<pre><span class=\"n\">B<\/span> <span class=\"o\">=<\/span> <span class=\"n\">extract_upper_bidiag<\/span><span class=\"p\">(<\/span><span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">arange<\/span><span class=\"p\">(<\/span><span class=\"mf\">25.0<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">reshape<\/span><span class=\"p\">(<\/span><span class=\"mi\">5<\/span><span class=\"p\">,<\/span><span class=\"mi\">5<\/span><span class=\"p\">))<\/span>\n<span class=\"n\">B<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"mf\">0.0<\/span>\n<span class=\"k\">print<\/span> <span class=\"n\">B<\/span>\n<span class=\"n\">decouple_or_reduce<\/span><span class=\"p\">(<\/span><span class=\"n\">B<\/span><span class=\"p\">,<\/span> <span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">])<\/span>\n<span class=\"k\">print<\/span> <span class=\"n\">B<\/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>[[  0.   1.   0.   0.   0.]\n [  0.   0.   7.   0.   0.]\n [  0.   0.  12.  13.   0.]\n [  0.   0.   0.  18.  19.]\n [  0.   0.   0.   0.  24.]]\n[[  0.           1.           0.           0.           0.        ]\n [  0.           0.           0.           0.           0.        ]\n [  0.           0.          13.89244399  11.22912571   0.        ]\n [  0.           0.           0.          19.15480973  17.85452348]\n [  0.           0.           0.           0.          24.86394963]]\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=\"one-other-walk-out\">One Other Walk Out<\/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>One other scenario we need to deal with (in computing the SVD), is bouncing or zig-zagging a blemish down the band of a &quot;dense&quot; bidiagonal matrix. The red values are used to compute the zeroing coefficients for that <span class=\"math inline\">\\(G_z\\)<\/span>. Here&#8217;s what it looks like:<\/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\\begin{align}<br \/>\nA =<br \/>\n\\begin{bmatrix}<br \/>\n\\red{x} &amp; x &amp; 0 &amp; 0 &amp; 0 \\\\<br \/>\n\\red{B} &amp; x &amp; x &amp; 0 &amp; 0 \\\\<br \/>\n0 &amp; 0 &amp; x &amp; x &amp; 0 \\\\<br \/>\n0 &amp; 0 &amp; 0 &amp; x &amp; x \\\\<br \/>\n0 &amp; 0 &amp; 0 &amp; 0 &amp; x \\\\<br \/>\n\\end{bmatrix}<br \/>\n&amp; \\xrightarrow{G^T_z(c,s,0,1) A} &amp;<br \/>\n\\begin{bmatrix}<br \/>\nx &amp; \\red{x} &amp; \\red{B} &amp; 0 &amp; 0 \\\\<br \/>\n0 &amp; x &amp; x &amp; 0 &amp; 0 \\\\<br \/>\n0 &amp; 0 &amp; x &amp; x &amp; 0 \\\\<br \/>\n0 &amp; 0 &amp; 0 &amp; x &amp; x \\\\<br \/>\n0 &amp; 0 &amp; 0 &amp; 0 &amp; x \\\\<br \/>\n\\end{bmatrix}<br \/>\n&amp; \\xrightarrow{A G_z(c,s,1,2)} &amp;<br \/>\n\\begin{bmatrix}<br \/>\nx &amp; x &amp; 0 &amp; 0 &amp; 0 \\\\<br \/>\n0 &amp; \\red{x} &amp; x &amp; 0 &amp; 0 \\\\<br \/>\n0 &amp; \\red{B} &amp; x &amp; x &amp; 0 \\\\<br \/>\n0 &amp; 0 &amp; 0 &amp; x &amp; x \\\\<br \/>\n0 &amp; 0 &amp; 0 &amp; 0 &amp; x \\\\<br \/>\n\\end{bmatrix} \\\\<br \/>\n&amp; \\xrightarrow{G^T_z(c,s,1,2) A} &amp;<br \/>\n\\begin{bmatrix}<br \/>\nx &amp; x &amp; 0 &amp; 0 &amp; 0 \\\\<br \/>\n0 &amp; x &amp; \\red{x} &amp; \\red{B} &amp; 0 \\\\<br \/>\n0 &amp; 0 &amp; x &amp; x &amp; 0 \\\\<br \/>\n0 &amp; 0 &amp; 0 &amp; x &amp; x \\\\<br \/>\n0 &amp; 0 &amp; 0 &amp; 0 &amp; x \\\\<br \/>\n\\end{bmatrix}<br \/>\n&amp; \\xrightarrow{A G_z(c,s,2,3)} &amp;<br \/>\n\\begin{bmatrix}<br \/>\nx &amp; x &amp; 0 &amp; 0 &amp; 0 \\\\<br \/>\n0 &amp; x &amp; x &amp; 0 &amp; 0 \\\\<br \/>\n0 &amp; x &amp; \\red{x} &amp; x &amp; 0 \\\\<br \/>\n0 &amp; 0 &amp; \\red{B} &amp; x &amp; x \\\\<br \/>\n0 &amp; 0 &amp; 0 &amp; 0 &amp; x \\\\<br \/>\n\\end{bmatrix} \\\\<br \/>\n&amp; \\xrightarrow{G^T_z(c,s,2,3) A} &amp;<br \/>\n\\begin{bmatrix}<br \/>\nx &amp; x &amp; 0 &amp; 0 &amp; 0 \\\\<br \/>\n0 &amp; x &amp; x &amp; 0 &amp; 0 \\\\<br \/>\n0 &amp; 0 &amp; x &amp; \\red{x} &amp; \\red{B} \\\\<br \/>\n0 &amp; 0 &amp; 0 &amp; x &amp; x \\\\<br \/>\n0 &amp; 0 &amp; 0 &amp; 0 &amp; x \\\\<br \/>\n\\end{bmatrix}<br \/>\n&amp; \\xrightarrow{A G_z(c,s,3,4)} &amp;<br \/>\n\\begin{bmatrix}<br \/>\nx &amp; x &amp; 0 &amp; 0 &amp; 0 \\\\<br \/>\n0 &amp; x &amp; x &amp; 0 &amp; 0 \\\\<br \/>\n0 &amp; x &amp; x &amp; x &amp; 0 \\\\<br \/>\n0 &amp; 0 &amp; 0 &amp; \\red{x} &amp; x \\\\<br \/>\n0 &amp; 0 &amp; 0 &amp; \\red{B} &amp; x \\\\<br \/>\n\\end{bmatrix}<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>There is a very important difference between this zig-zagging &#8211; it looks like we&#8217;ve got a drunken blemish on our hands &#8211; and the &quot;straighline&quot; walkouts we performed above. Instead of &quot;swapping&quot; to the diagonal, we are going to &quot;swap&quot; to an adjacent element on the band. The adjacent element will either be (1) in the same row and to the left of us or (2) in the same column and above us. If we don&#8217;t use those neighbors or friends, we end up with more blemishes. Since we have a BBM we use those friends, we keep one, and only one, blemish.<\/p>\n<p>However, using those friend positions, means that we need some slightly different left and right Givens rotations. Here&#8217;s the corresponding functions that perform these two steps:<\/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;[20]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\" highlight hl-ipython2\">\n<pre><span class=\"k\">def<\/span> <span class=\"nf\">givens_zero_adjacent_onband_left<\/span><span class=\"p\">(<\/span><span class=\"n\">A<\/span><span class=\"p\">,<\/span> <span class=\"n\">row<\/span><span class=\"p\">,<\/span> <span class=\"n\">col<\/span><span class=\"p\">):<\/span>\n    <span class=\"c1\"># affecting two rows: need the row above me<\/span>\n    <span class=\"c1\"># assert col==row-1 ... below diag ... row&gt;col<\/span>\n    <span class=\"n\">c<\/span><span class=\"p\">,<\/span><span class=\"n\">s<\/span> <span class=\"o\">=<\/span> <span class=\"n\">zeroing_givens_coeffs<\/span><span class=\"p\">(<\/span><span class=\"n\">A<\/span><span class=\"p\">[<\/span><span class=\"n\">row<\/span><span class=\"o\">-<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"p\">],<\/span> <span class=\"n\">A<\/span><span class=\"p\">[<\/span><span class=\"n\">row<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"p\">])<\/span> <span class=\"c1\"># same col<\/span>\n    <span class=\"n\">G<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"n\">c<\/span><span class=\"p\">,<\/span><span class=\"n\">s<\/span><span class=\"p\">,<\/span><span class=\"n\">row<\/span><span class=\"o\">-<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"n\">row<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">left_givensT<\/span><span class=\"p\">(<\/span><span class=\"n\">G<\/span><span class=\"p\">,<\/span> <span class=\"n\">A<\/span><span class=\"p\">)<\/span> <span class=\"c1\"># G tells affected *rows* - one col gets 0<\/span>\n    <span class=\"k\">return<\/span> <span class=\"n\">G<\/span>\n\n<span class=\"k\">def<\/span> <span class=\"nf\">givens_zero_adjacent_onband_right<\/span><span class=\"p\">(<\/span><span class=\"n\">A<\/span><span class=\"p\">,<\/span> <span class=\"n\">row<\/span><span class=\"p\">,<\/span> <span class=\"n\">col<\/span><span class=\"p\">):<\/span>\n    <span class=\"c1\"># affecting two cols:  need col left of me<\/span>\n    <span class=\"c1\"># assert col-2==row ... above diag ... col&gt;row<\/span>\n    <span class=\"n\">c<\/span><span class=\"p\">,<\/span><span class=\"n\">s<\/span> <span class=\"o\">=<\/span> <span class=\"n\">zeroing_givens_coeffs<\/span><span class=\"p\">(<\/span><span class=\"n\">A<\/span><span class=\"p\">[<\/span><span class=\"n\">row<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"o\">-<\/span><span class=\"mi\">1<\/span><span class=\"p\">],<\/span> <span class=\"n\">A<\/span><span class=\"p\">[<\/span><span class=\"n\">row<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"p\">])<\/span> <span class=\"c1\"># same row<\/span>\n    <span class=\"n\">G<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"n\">c<\/span><span class=\"p\">,<\/span><span class=\"n\">s<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"o\">-<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"n\">col<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">right_givens<\/span><span class=\"p\">(<\/span><span class=\"n\">A<\/span><span class=\"p\">,<\/span> <span class=\"n\">G<\/span><span class=\"p\">)<\/span> <span class=\"c1\"># G tells affected *cols* - one row gets 0<\/span>\n    <span class=\"k\">return<\/span> <span class=\"n\">G<\/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<p>As with <code>givens_zero_wdiag_left<\/code> and <code>givens_zero_wdiag_right<\/code>, when applied to a BBM these have a very efficient form. I&#8217;m going to leave that as an exercise to the highly motivated reader. But, it will be very close to the forms for <code>givens_zero_wdiag_left_on_BBM<\/code> (and for the right side application). If you follow the Givens rotations under &quot;One Other Walkout&quot;, that seems pretty clear. We can turn that into code pretty quickly (adding one last left rotation to clear out the blemish in the bottom row):<\/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;[21]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\" highlight hl-ipython2\">\n<pre><span class=\"k\">def<\/span> <span class=\"nf\">bounce_blemish_down_diagonal<\/span><span class=\"p\">(<\/span><span class=\"n\">BBM<\/span><span class=\"p\">):<\/span>\n    <span class=\"n\">m<\/span><span class=\"p\">,<\/span><span class=\"n\">n<\/span> <span class=\"o\">=<\/span> <span class=\"n\">BBM<\/span><span class=\"o\">.<\/span><span class=\"n\">shape<\/span>\n    <span class=\"k\">for<\/span> <span class=\"n\">k<\/span> <span class=\"ow\">in<\/span> <span class=\"nb\">xrange<\/span><span class=\"p\">(<\/span><span class=\"n\">n<\/span><span class=\"o\">-<\/span><span class=\"mi\">2<\/span><span class=\"p\">):<\/span>\n        <span class=\"n\">givens_zero_adjacent_onband_left<\/span><span class=\"p\">(<\/span> <span class=\"n\">BBM<\/span><span class=\"p\">,<\/span> <span class=\"n\">k<\/span><span class=\"o\">+<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"n\">k<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">givens_zero_adjacent_onband_right<\/span><span class=\"p\">(<\/span><span class=\"n\">BBM<\/span><span class=\"p\">,<\/span> <span class=\"n\">k<\/span><span class=\"p\">,<\/span>   <span class=\"n\">k<\/span><span class=\"o\">+<\/span><span class=\"mi\">2<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">givens_zero_adjacent_onband_left<\/span><span class=\"p\">(<\/span><span class=\"n\">BBM<\/span><span class=\"p\">,<\/span> <span class=\"n\">n<\/span><span class=\"o\">-<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"n\">n<\/span><span class=\"o\">-<\/span><span class=\"mi\">2<\/span><span class=\"p\">)<\/span>\n<\/pre>\n<\/div>\n<\/div>\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;[22]:<\/div>\n<div class=\"inner_cell\">\n<div class=\"input_area\">\n<div class=\" highlight hl-ipython2\">\n<pre><span class=\"n\">A<\/span> <span class=\"o\">=<\/span> <span class=\"n\">extract_upper_bidiag<\/span><span class=\"p\">(<\/span><span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">arange<\/span><span class=\"p\">(<\/span><span class=\"mf\">1.0<\/span><span class=\"p\">,<\/span> <span class=\"mf\">17.0<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">reshape<\/span><span class=\"p\">(<\/span><span class=\"mi\">4<\/span><span class=\"p\">,<\/span><span class=\"mi\">4<\/span><span class=\"p\">))<\/span>\n<span class=\"n\">A<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">99<\/span>\n<span class=\"k\">print<\/span> <span class=\"n\">A<\/span>\n<span class=\"n\">bounce_blemish_down_diagonal<\/span><span class=\"p\">(<\/span><span class=\"n\">A<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">print<\/span> <span class=\"n\">A<\/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>[[  1.   2.   0.   0.]\n [ 99.   6.   7.   0.]\n [  0.   0.  11.  12.]\n [  0.   0.   0.  16.]]\n[[ 99.00505038   9.23223353  -0.           0.        ]\n [  0.           8.42736916  13.72460309   0.        ]\n [  0.           0.          14.11692105   7.60672004]\n [  0.           0.           0.          -2.86896033]]\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>\nAdditional Resources<br \/>\n<\/h3>\n<p>\nYou can grab a <a href=\"http:\/\/drsfenner.org\/public\/notebooks\/GivensRotationsAndTheBlemishedBidiagonal.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\/GivensRotationsAndTheBlemishedBidiagonal.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>Last time, we looked at using Givens rotations to perform a QR factorization of a matrix. Today, we&#8217;re going to be a little more selective and use Givens rotations to walk values off the edge of a special class of matrices<\/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-436","post","type-post","status-publish","format-standard","hentry","category-mrdr","category-sci-math-stat-python"],"_links":{"self":[{"href":"https:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/posts\/436","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/comments?post=436"}],"version-history":[{"count":1,"href":"https:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/posts\/436\/revisions"}],"predecessor-version":[{"id":437,"href":"https:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/posts\/436\/revisions\/437"}],"wp:attachment":[{"href":"https:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/media?parent=436"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/categories?post=436"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/drsfenner.org\/blog\/wp-json\/wp\/v2\/tags?post=436"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}