CEDRIC  Revision_backup-2009-02
FastMDS.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 REDUKT_FastMDS_H
10 #define REDUKT_FastMDS_H
11 
12 #include "CMDS.h"
13 #include "SVD.h"
14 
15 #include <boost/numeric/ublas/matrix_proxy.hpp>
16 #include <ext/algorithm> // for random_sample_n()
17 #include <limits>
18 #include <iostream>
19 #include <assert.h>
20 
30 template<class ValueType>
31 class FastMDS
32 {
33 public:
34  typedef ublas::matrix<ValueType> Matrix;
35  typedef ublas::vector<ValueType> Vector;
36 
37  FastMDS( Matrix& D, int k, int p, int s );
38 
39  const Matrix& getPoints() const { return m_points; }
40 
41 private:
42  Matrix m_points;
43 };
44 
45 
46 template<class T>
47 FastMDS<T>::FastMDS( Matrix& D, int k, int p, int s ): m_points(D.size1(),k)
48 {
49  using namespace ublas;
50  using namespace ublasTools;
51  using std::cout;
52  using std::endl;
53  using std::flush;
54 
55  assert( D.size1() == D.size2() );
56 
57  int n = D.size1();
58  //int p = ;
59  //int s = 2*(k+1);
60 
61  cout << "FastMDS with n=" << n << ", p=" << p << ", dim_low=k=" << k << ", s=" << s << endl;
62 
63  // compute s*p sample indices
64  cout << "Computing sample indices, taking " << s << " samples from each range, total " << s*p << endl;
65  std::vector<int> indices(n); for( int i=0; i < n; ++i ) indices[i]=i;
66  std::vector<int> sample( s*p );
67  std::vector<int>::iterator it = sample.begin();
68  for( int i=0; i < p; ++i )
69  {
70  //cout << "[" << i*(n/p) << "," << (i+1)*(n/p) << "]" << endl;
71 
72  // take s samples from D_i submatrix range
73  it = __gnu_cxx::random_sample_n( indices.begin() + i *(n/p),
74  indices.begin() + (i+1)*(n/p),
75  it,
76  s );
77  }
78  cout << "Sample indices are: " << endl;
79  for( int i=0; i < s*p; ++i )
80  cout << sample[i] << " ";
81  cout << endl;
82 
83  // build align matrix M
84  Matrix M( s*p, s*p );
85  cout << "Build align " << M.size1() << "x" << M.size2() << " matrix M..." << flush;
86  for( int row=0; row < s*p; ++row )
87  for( int col=0; col < s*p; ++col )
88  {
89  M(row,col) = D(sample[row],sample[col]);
90  }
91  cout << "done" << endl;
92 
93  // solve CMDS for M
94  cout << "Solve CMDS for align matrix M..." << flush;
95  CMDS<T> M_cmds( M );
96  M_cmds.project( k ); // M = CMDS(M) projected to k dimensions
97  cout << "done (result is a " << M.size1() << "x" << M.size2() << " matrix)" << endl;
98 
99 
100  for( int i=0; i < p; ++i )
101  {
102  // sub matrix D_i from proxy
103  int first = i *(n/p),
104  last = (i+1)*(n/p);
105 
106  cout << "Submatrix D_" << i << " from point " << first << " to " << last << endl;
107  Matrix D_i = matrix_range<Matrix>( D,
108  range(first,last),
109  range(first,last) );
110 
111  // solve CMDS for D_i
112  cout << "Solve CMDS for D_" << i << "..." << flush;
113  CMDS<T> Di_cmds( D_i );
114  Di_cmds.project( k ); // D_i = CMDS(D_i) projected to k dimension
115  cout << "done (result is a " << D_i.size1() << "x" << D_i.size2() << " matrix)" << endl;
116 
117 
118 
119  // build matrices containing solutions for sampled points in D_i and M
120  cout << " Build " << k << "x" << s << " matrices mdsDs and mdsMs" << endl;
121  Matrix mdsDs( k, s );
122  Matrix mdsMs( k, s );
123  for( int row=0; row < s; ++row )
124  {
125  int ofs = i*s + row;
126  //~ cout << "* sample[" << ofs << "] - i*(n/p) = " << flush;
127  int idx = sample[ofs] - i*(n/p);
128  //~ cout << idx << endl;
129 
130  for( int col=0; col < k; ++col )
131  {
132  mdsDs(col,row) = D_i( idx , col );
133  mdsMs(col,row) = M ( ofs, col );
134  }
135  }
136 
137  // fit affine transformation mdsMs = A*mdsDs + b
138  cout << " Find affine mapping A_" << i << endl;
139  Matrix A; Vector b;
140  if( !affine_fit<T>( mdsDs, mdsMs, A, b ) )
141  {
142  cout << "BOGUS!" << endl;
143  assert( false );
144  }
145 
146  #if 0
147  // map mdsDs into mdsDs for debugging purposes
148  cout << " mdsDs = " << mdsDs << endl;
149  cout << " mdsMs = " << mdsMs << endl;
150  Matrix estimate = prod( A, mdsDs );
151  for( unsigned int j=0; j < estimate.size2(); ++j )
152  column(estimate,j) += b;
153  cout << " A*mdsDs+b1' = " << estimate << endl;
154  #endif
155 
156 
157 
159 
160  // affine mapping A_i is stored in A
161 
162  cout << "Align CMDS(D_" << i << ") with CMDS(M)..." << flush;
163 
164  // align CMDS(D_i) in common coordinate system
165  D_i = trans( D_i );
166  D_i = prod( A, D_i );
167  cout << "done (result is a " << D_i.size1() << "x" << D_i.size2() << " matrix)" << endl;
168 
169  cout << "Copy resulting points into solution matrix" << endl;
170  D_i = trans(D_i);
171 
172  // copy points to result matrix
173  for( unsigned int row=0; row < D_i.size1(); ++row )
174  for( int col=0; col < k; ++col ) // k must match D_i.size2() (or something is fucked up)
175  m_points(row+first,col) = D_i(row,col);
176  }
177 }
178 
Definition: FastMDS.h:31
ublas::matrix< ValueType > Matrix
Definition: FastMDS.h:34
const Matrix & getPoints() const
Definition: FastMDS.h:39
ublas::vector< ValueType > Vector
Definition: FastMDS.h:35
Classical Multidimensional Scaling (suited for small instances)
Definition: CMDS.h:36
void project(int dim=2)
Project referenced matrix D to dim dimensions.
Definition: CMDS.h:119
FastMDS(Matrix &D, int k, int p, int s)
Definition: FastMDS.h:47