CEDRIC  Revision_backup-2009-02
ublasTools.h
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * Copyright (C) 2008 Max Hermann
4  *
5  * This file is part of the "CEDRIC Event Display" application.
6  *
7  *****************************************************************************/
8 
9 #ifndef UBLASTOOLS_H
10 #define UBLASTOOLS_H
11 
12 // includes for affine_fit
13 #include <boost/numeric/ublas/vector.hpp>
14 #include <boost/numeric/ublas/vector_proxy.hpp>
15 #include <boost/numeric/ublas/matrix.hpp>
16 #include <boost/numeric/ublas/triangular.hpp>
17 #include <boost/numeric/ublas/operation.hpp>
18 #include <boost/numeric/ublas/lu.hpp>
19 
20 namespace ublas = boost::numeric::ublas;
21 
22 #include <iostream>
23 #include <assert.h>
24 
25 
27 namespace ublasTools
28 {
37 template<class ValueType>
38 bool affine_fit( const ublas::matrix<ValueType>& q_, const ublas::matrix<ValueType>& p,
39  ublas::matrix<ValueType>& A, ublas::vector<ValueType>& b )
40 {
41  assert( (q_.size1()==p.size1()) && (q_.size2()==p.size2()) );
42 
43  using namespace ublas;
44 
45  unsigned int n = q_.size1();
46  unsigned int m = q_.size2();
47 
48  // append row of ones to q
49  ublas::matrix<ValueType> q = q_;
50  q.resize( n+1, m );
51  for( unsigned int i=0; i < m; ++i )
52  q(n,i) = 1.0;
53 
54  // build product matrix $Q = \sum_{j=1}^m q_j q_j^T$
55  // $$Q_{ji} = Q_{ij} = \sum_{k=1}^m q_{ik}q{jk}$$
56  ublas::matrix<ValueType> Q( n+1, n+1 );
57  for( unsigned int i=0; i < n+1; ++i )
58  for( unsigned int j=0; j <= i; ++j )
59  {
60  Q(i,j) = 0.0;
61  for( unsigned int k=0; k < m; ++k )
62  Q(i,j) += q(i,k)*q(j,k);
63 
64  // symmetric
65  Q(j,i) = Q(i,j);
66  }
67 
68  // build matrix $C = (C_1,C_2,\ldots,C_n)$ where $C_j = (C_{1j},C_{2j},\ldots,C_{n+1,j})^T$
69  // $$C_{kj} = \sum_{i=1}^{m}q_{ki}p_{ji}$$
70  ublas::matrix<ValueType> C( n+1, n );
71  for( unsigned int k=0; k < n+1; ++k )
72  for( unsigned int j=0; j < n; ++j )
73  {
74  C(k,j) = 0.0;
75  for( unsigned int i=0; i < m; ++i )
76  C(k,j) += q(k,i)*p(j,i);
77  }
78 
79  // compute inverse of $Q$ via LU decomposition
80 
81  // LU decompose $Q=LU$
82  // We use boost's lu_factorize with partial pivoting, but this is needless for spd matrices,
83  // and even destroys the nice spd structure which Q usually has.
84  permutation_matrix<double> perm(n+1);
85  if( lu_factorize( Q, perm ) != 0 )
86  {
87  std::cout << "Stumbled upon a singular matrix during LU decomposition!" << std::endl; //<=========== TODO: throw exception ==============>
88  return false;
89  };
90 
91  // backsubstitute to get the inverse
92  ublas::matrix<ValueType> inverse;
93  inverse = identity_matrix<double>(Q.size1());
94  lu_substitute( Q, perm, inverse );
95 
96  // compute $\tilde{A}=Q^{-1}C$
97  A.resize( n+1, n );
98  A = prod( inverse, C );
99 
100  // extract $A$ and $b$ from $\tilde{A}$
101  b = row( A, n ); // last row of $\tilde{A}$ hold translation $b$
102  A.resize( n, n ); // remove last row
103  A = trans( A ); // $\tilde{A}$ contains $A^t$, so we have to transpose to get $A$
104 
105  return true;
106 }
107 
111 template<class ValueType>
112 ublas::vector<ValueType> column_means( ublas::matrix<ValueType>& A )
113 {
114  using namespace ublas;
115 
116  unsigned int m = A.size1(); // number of rows
117  unsigned int n = A.size2(); // number of columns
118 
119  // compute column means
120 
121  ublas::vector<ValueType> mean(n);
122  mean = zero_vector<ValueType>(n);
123 
124  for( unsigned int i=0; i < m; ++i )
125  mean += matrix_row<matrix<ValueType> >( A, i );
126 
127  mean *= 1.0 / m;
128 
129  return mean;
130 }
131 
135 template<class ValueType>
136 ublas::vector<ValueType> row_means( ublas::matrix<ValueType>& A )
137 {
138  using namespace ublas;
139 
140  unsigned int m = A.size1(); // number of rows
141  unsigned int n = A.size2(); // number of columns
142 
143  // compute row means
144 
145  ublas::vector<ValueType> mean(m);
146  mean = zero_vector<ValueType>(m);
147 
148  for( unsigned int j=0; j < n; ++j )
149  mean += matrix_column<matrix<ValueType> >( A, j );
150 
151  mean *= 1.0 / n;
152 
153  return mean;
154 }
155 
159 template<class ValueType>
160 ValueType grand_mean( const ublas::matrix<ValueType>& A )
161 {
162  double gm = 0.0;
163  for( unsigned int i=0; i < A.size1(); ++i )
164  for( unsigned int j=0; j < A.size2(); ++j )
165  gm += A(i,j);
166 
167  gm *= 1.0 / (A.size1()*A.size2());
168 
169  return gm;
170 }
171 
174 template<class ValueType>
175 void double_center( ublas::matrix<ValueType>& D )
176 {
177  typedef ublas::vector<ValueType> Vector;
178 
179  // compute means of component squared D
180  Vector cmeans = column_means( D );
181  Vector rmeans = row_means( D );
182  double gmean = grand_mean( D );
183 
184  //~ cout << "column means = " << cmeans << endl;
185  //~ cout << "row means = " << rmeans << endl;
186  //~ cout << "grand mean = " << gmean << endl;
187 
188  // double center matrix D
189  for( unsigned int i=0; i < D.size1(); ++i )
190  for( unsigned int j=0; j < D.size2(); ++j )
191  {
192  D(i,j) = D(i,j) - cmeans(i) - rmeans(j) + gmean;
193  }
194 }
195 
197 template<class ValueType>
198 void zero_eps( ublas::matrix<ValueType>& A, ValueType eps = 1e-7 )
199 {
200  for( unsigned int i=0; i < A.size1(); ++i )
201  for( unsigned int j=0; j < A.size2(); ++j )
202  {
203  if( fabs(A(i,j)) < eps ) A(i,j)=0.0;
204  }
205 }
206 
208 template<class ValueType>
209 void zero_eps( ublas::vector<ValueType>& v, ValueType eps = 1e-7 )
210 {
211  for( unsigned int i=0; i < v.size(); ++i )
212  if( fabs(v(i)) < eps ) v(i)=0.0;
213 }
214 
215 } // namespace ublasTools
216 
217 #endif // UBLASTOOLS_H
ublas::vector< ValueType > column_means(ublas::matrix< ValueType > &A)
Calculate column means of a matrix.
Definition: ublasTools.h:112
ValueType grand_mean(const ublas::matrix< ValueType > &A)
Calculate grand means of a matrix.
Definition: ublasTools.h:160
void double_center(ublas::matrix< ValueType > &D)
Double center matrix, i.e. substract column and row means and add in grand mean.
Definition: ublasTools.h:175
void zero_eps(ublas::matrix< ValueType > &A, ValueType eps=1e-7)
Eliminate all matrix entries smaller than some epsilon.
Definition: ublasTools.h:198
ublas::vector< ValueType > row_means(ublas::matrix< ValueType > &A)
Calculate row means of a matrix.
Definition: ublasTools.h:136
bool affine_fit(const ublas::matrix< ValueType > &q_, const ublas::matrix< ValueType > &p, ublas::matrix< ValueType > &A, ublas::vector< ValueType > &b)
Fit affine transformation such that .
Definition: ublasTools.h:38