TooN 2.1
QR.h
00001 //-*- c++ -*-
00002 
00003 // Copyright (C) 2012, Edward Rosten (ed@edwardrosten.com)
00004 //
00005 // This file is part of the TooN Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 2, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // You should have received a copy of the GNU General Public License along
00017 // with this library; see the file COPYING.  If not, write to the Free
00018 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
00019 // USA.
00020 
00021 // As a special exception, you may use this file as part of a free software
00022 // library without restriction.  Specifically, if other files instantiate
00023 // templates or use macros or inline functions from this file, or you compile
00024 // this file and link it with other files to produce an executable, this
00025 // file does not by itself cause the resulting executable to be covered by
00026 // the GNU General Public License.  This exception does not however
00027 // invalidate any other reasons why the executable file might be covered by
00028 // the GNU General Public License.
00029 
00030 
00031 #ifndef TOON_INC_QR_H
00032 #define TOON_INC_QR_H
00033 #include <TooN/TooN.h>
00034 #include <cmath>
00035 
00036 namespace TooN
00037 {
00038 /**
00039 Performs %QR decomposition.
00040 
00041 @warning this will only work if the number of columns is greater than 
00042 the number of rows!
00043 
00044 The QR decomposition operates on a matrix A. 
00045 In general:
00046 \f[
00047 A = QR
00048 \f]
00049 
00050 @ingroup gDecomps
00051 */
00052 template<int Rows=Dynamic, int Cols=Rows, typename Precision=double> class QR
00053 {
00054     
00055     private:
00056         static const int square_Size = (Rows>=0 && Cols>=0)?(Rows<Cols?Rows:Cols):Dynamic;
00057 
00058     public: 
00059         /// Construct the %QR decomposition of a matrix. This initialises the class, and
00060         /// performs the decomposition immediately.
00061         /// @param m The matrix to decompose
00062         template<int R, int C, class P, class B> 
00063         QR(const Matrix<R,C,P,B>& m_)
00064         :m(m_), Q(Identity(square_size()))
00065         {
00066             //pivot is set to all zeros, which means all columns are free columns
00067             //and can take part in column pivoting.
00068 
00069             compute();
00070         }
00071         
00072         ///Return R
00073         const Matrix<Rows, Cols, Precision>& get_R()
00074         {
00075             return m;
00076         }
00077         
00078         ///Return Q
00079         const Matrix<square_Size, square_Size, Precision, ColMajor>& get_Q()
00080         {
00081             return Q;
00082         }   
00083 
00084     private:
00085 
00086         template<class B1, class B2>        
00087         void pre_multiply_by_householder(Matrix<Dynamic, Dynamic, Precision, B1>& A, const Vector<Dynamic, Precision, B2>& v, Precision s)
00088         {
00089             //The Householder matrix is P = 1 - v*v/s
00090             
00091             //PA = (1 - v*v^T/s) A = A - v*v^T A 
00092             //                                               
00093             //          [ v1 ]  [ v1   v2  v2  v4 ]  [    |     |     ]
00094             //   = A -  [ v2 ]                       [ a1 |  a2 | ... ]   
00095             //          [ v3 ]                       [    |     |     ]
00096             //          [ v4 ]                       [    |     |     ]
00097 
00098             //          [ v1 ]  [ va1   va2  va3 va4 ]
00099             //   = A -  [ v2 ]                      
00100             //          [ v3 ]                     
00101             //          [ v4 ]                    
00102 
00103             //          [ v1 (v a1) ]
00104             //   = A -  [ v2 (v a2) ]
00105             //          [ v3 (v a3) ]
00106             //          [ v4 (v a4) ]
00107 
00108             for(int col=0; col < A.num_cols(); col++)
00109             {
00110                 Precision va = v * A.T()[col] / s;
00111 
00112                 for(int row=0; row < A.num_rows(); row++)
00113                     A[row][col] -= v[row] * va;
00114             }
00115         }
00116 
00117         void compute()
00118         {
00119             
00120             //QR decomposition makes use of Householder reflections.
00121             // A = QR, 
00122 
00123             //Q1 A = Q1 QR
00124             // Q2 Q1 A = Q2 Q1 R
00125             // ... 
00126             // Q^-1 A  = R
00127             //
00128             // Pick a sequence of Qn which makes R upper triangular.
00129             //
00130             // The sequence Qn ... Q1 is equal to Q^-1
00131             //
00132             // Qi has the form of a Householder reflection
00133 
00134             for(int n=0; n < square_size()-1; n++)  
00135             {
00136                 using std::sqrt;
00137 
00138                 int sz = square_size() - n;
00139                 int nc = m.num_cols() - n;
00140 
00141                 //Compute the reflection on a submatrix
00142                 //such that it never breaks the triangular 
00143                 //properties of the matrix being created.
00144 
00145                 Matrix<Dynamic, Dynamic, Precision, typename Matrix<Rows,Cols,Precision>::SliceBase> s = m.slice(n, n, sz, nc);
00146 
00147                 //Now perform a householder reduction on the first column
00148 
00149                 //Define x to be the first column
00150                 //auto x = s.T()[0];
00151 
00152 
00153                 //The reflection vector is u = x - |x| * [ 1 0 ... 0] * sgn(x_0)
00154                 //
00155                 //let a = |x| * sgn(x_0])
00156 
00157                 Precision  nx2 = norm_sq(s.T()[0]);
00158 
00159                 Precision a = sqrt(nx2) * (s.T()[0][0] < 0?-1:1);
00160 
00161                 //We now want the vector u = x - ae
00162                 //
00163                 // Multipling (I - 2 hat(u) * hat(u)^T) * s will zero out the first column of s except
00164                 // for the first element. The matrix P = is orthogonal, a bit like Qn 
00165                 //
00166                 //Since x is no longer needed, we can just modify the first element
00167                 s.T()[0][0] -= a;
00168                 //auto& u = x;
00169 
00170                 //We want H = norm_sq(u)/2 =  a (a - x_0) = a * -u_0
00171                 Precision H = -a * s.T()[0][0];
00172 
00173 
00174                 //Note that we're working on a reduced sized matrix here.
00175                 //
00176                 //The actual householder matrix, P,  is:
00177                 //                                                                  
00178                 //  [ 1  |   0         ]                                               
00179                 //  [___1|_____________]                                                
00180                 //  [    |[ ^   ^T  ]  ]                                                
00181                 //  [  0 |[ u * u   ]  ]                                                        
00182                 //  [    |[         ]  ]                                                
00183 
00184                 // We want m <- P * m
00185                 // and Q <- P * Q
00186                 //
00187                 //
00188                 // Since m is going towards upper triangular and so has lots of zeros
00189                 // we can compute it by performing the multiplication in just the
00190                 // lower block:
00191                 //
00192 
00193                 //  [ 1  |   0         ]  [ m1 | m2     ]     [ m1 |  m2  ]
00194                 //  [___1|_____________]  [____|_______ ]     [____|______]               
00195                 //  [    |[  ^  ^T  ]  ]  [    |        ]   = [    |      ]               
00196                 //  [  0 |[I-u* u   ]  ]  [ 0  |  m3    ]     [  0 | .... ]                       
00197                 //  [    |[         ]  ]  [    |        ]     [    |      ]                
00198                 
00199                 // Q does not have the column of zeros, so the multiplication has to be performed on
00200                 // the whole width
00201 
00202                 //This can be done in place except that the first column of s holds u
00203                 pre_multiply_by_householder(s.slice(0, 1, sz, nc-1).ref(), s.T()[0], H);
00204 
00205                 //Also update the Q matrix
00206                 pre_multiply_by_householder(Q.slice(n,0,sz,square_size()).ref(), s.T()[0], H);
00207 
00208                 //Now do the first column multiplication...
00209                 //Which makes it upper triangular.
00210 
00211                 s[0][0] = a;
00212                 s.T()[0].slice(1, sz-1) = Zeros;
00213 
00214             }
00215                 
00216             //Note above that we've build up Q^-1, so we need to transpose Q now 
00217             //to invert it
00218 
00219             using std::swap;
00220             for(int r=0; r < Q.num_rows(); r++)
00221                 for(int c=r+1; c < Q.num_cols(); c++)
00222                     swap(Q[r][c], Q[c][r]);
00223 
00224         }
00225 
00226         Matrix<Rows, Cols, Precision> m;
00227         Matrix<square_Size, square_Size, Precision, ColMajor> Q;
00228         
00229 
00230         int square_size()
00231         {
00232             return std::min(m.num_rows(), m.num_cols());    
00233         }
00234 };
00235 
00236 
00237 
00238 
00239 
00240 
00241 }
00242 
00243 #endif