vmmlib  1.7.0
 All Classes Namespaces Functions Pages
t4_hosvd.hpp
1 /*
2  * Copyright (c) 2006-2014, Visualization and Multimedia Lab,
3  * University of Zurich <http://vmml.ifi.uzh.ch>,
4  * Eyescale Software GmbH,
5  * Blue Brain Project, EPFL
6  *
7  * This file is part of VMMLib <https://github.com/VMML/vmmlib/>
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  *
12  * Redistributions of source code must retain the above copyright notice, this
13  * list of conditions and the following disclaimer. Redistributions in binary
14  * form must reproduce the above copyright notice, this list of conditions and
15  * the following disclaimer in the documentation and/or other materials provided
16  * with the distribution. Neither the name of the Visualization and Multimedia
17  * Lab, University of Zurich nor the names of its contributors may be used to
18  * endorse or promote products derived from this software without specific prior
19  * written permission.
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #ifndef __VMML__T4_HOSVD__HPP__
34 #define __VMML__T4_HOSVD__HPP__
35 
36 #include <vmmlib/tensor4.hpp>
37 #include <vmmlib/lapack_svd.hpp>
38 #include <vmmlib/lapack_sym_eigs.hpp>
39 #include <vmmlib/blas_dgemm.hpp>
40 #include <vmmlib/blas_daxpy.hpp>
41 
42 namespace vmml
43 {
44 
45  template< size_t R1, size_t R2, size_t R3, size_t R4, size_t I1, size_t I2, size_t I3, size_t I4, typename T = float >
46  class t4_hosvd
47  {
48  public:
49 
51 
56 
61 
66 
67  static void apply_mode1(const t4_type& data_, u1_type& u1_);
68  static void apply_mode2(const t4_type& data_, u2_type& u2_);
69  static void apply_mode3(const t4_type& data_, u3_type& u3_);
70  static void apply_mode4(const t4_type& data_, u4_type& u4_);
71 
72  protected:
73 
74  //hosvd on eigenvalue decomposition = hoeigs
75  template< size_t N, size_t R >
76  static void get_eigs_u_red( const matrix< N, N, T >& data_, matrix< N, R, T >& u_ );
77 
78  static void eigs_mode1( const t4_type& data_, u1_type& u1_ );
79  static void eigs_mode2( const t4_type& data_, u2_type& u2_ );
80  static void eigs_mode3( const t4_type& data_, u3_type& u3_ );
81  static void eigs_mode4( const t4_type& data_, u4_type& u4_ );
82 
83  }; //end hosvd class
84 
85 #define VMML_TEMPLATE_STRING template< size_t R1, size_t R2, size_t R3, size_t R4, size_t I1, size_t I2, size_t I3, size_t I4, typename T >
86 #define VMML_TEMPLATE_CLASSNAME t4_hosvd< R1, R2, R3, R4, I1, I2, I3, I4, T >
87 
88 VMML_TEMPLATE_STRING
89 void
90 VMML_TEMPLATE_CLASSNAME::apply_mode1( const t4_type& data_, u1_type& u1_)
91 {
92  eigs_mode1( data_, u1_ );
93 }
94 
95 VMML_TEMPLATE_STRING
96 void
97 VMML_TEMPLATE_CLASSNAME::apply_mode2( const t4_type& data_, u2_type& u2_)
98 {
99  eigs_mode2( data_, u2_ );
100 }
101 
102 VMML_TEMPLATE_STRING
103 void
104 VMML_TEMPLATE_CLASSNAME::apply_mode3( const t4_type& data_, u3_type& u3_)
105 {
106  eigs_mode3( data_, u3_ );
107 }
108 
109 VMML_TEMPLATE_STRING
110 void
111 VMML_TEMPLATE_CLASSNAME::apply_mode4( const t4_type& data_, u4_type& u4_)
112 {
113  eigs_mode4( data_, u4_ );
114 }
115 
116 /* EIGS for mode 1, 2, 3 and 4*/
117 
118 VMML_TEMPLATE_STRING
119 void
120 VMML_TEMPLATE_CLASSNAME::eigs_mode1( const t4_type& data_, u1_type& u1_ )
121 {
122  //unfolding / matricization
123  u1_unfolded_type* unfolding = new u1_unfolded_type;
124  data_.mode1_unfolding_fwd( *unfolding );
125 
126  //covariance matrix of unfolded data
127  u1_cov_type* cov = new u1_cov_type;
128  blas_dgemm< I1, I2*I3*I4, I1, T>* blas_cov = new blas_dgemm< I1, I2*I3*I4, I1, T>;
129  blas_cov->compute( *unfolding, *cov );
130  delete blas_cov;
131  delete unfolding;
132 
133  //compute x largest magnitude eigenvalues; x = R
134  get_eigs_u_red( *cov, u1_ );
135 
136  delete cov;
137 }
138 
139 VMML_TEMPLATE_STRING
140 void
141 VMML_TEMPLATE_CLASSNAME::eigs_mode2( const t4_type& data_, u2_type& u2_ )
142 {
143  //unfolding / matricization
144  u2_unfolded_type* unfolding = new u2_unfolded_type;
145  data_.mode2_unfolding_fwd( *unfolding );
146 
147  //covariance matrix of unfolded data
148  u2_cov_type* cov = new u2_cov_type;
149  blas_dgemm< I2, I1*I3*I4, I2, T>* blas_cov = new blas_dgemm< I2, I1*I3*I4, I2, T>;
150  blas_cov->compute( *unfolding, *cov );
151  delete blas_cov;
152  delete unfolding;
153 
154  //compute x largest magnitude eigenvalues; x = R
155  get_eigs_u_red( *cov, u2_ );
156 
157  delete cov;
158 }
159 
160 VMML_TEMPLATE_STRING
161 void
162 VMML_TEMPLATE_CLASSNAME::eigs_mode3( const t4_type& data_, u3_type& u3_)
163 {
164  //unfolding / matricization
165  u3_unfolded_type* unfolding = new u3_unfolded_type;
166  data_.mode3_unfolding_fwd( *unfolding );
167 
168  //covariance matrix of unfolded data
169  u3_cov_type* cov = new u3_cov_type;
170  blas_dgemm< I3, I1*I2*I4, I3, T>* blas_cov = new blas_dgemm< I3, I1*I2*I4, I3, T>;
171  blas_cov->compute( *unfolding, *cov );
172  delete blas_cov;
173  delete unfolding;
174 
175  //compute x largest magnitude eigenvalues; x = R
176  get_eigs_u_red( *cov, u3_ );
177 
178  delete cov;
179 }
180 
181 VMML_TEMPLATE_STRING
182 void
183 VMML_TEMPLATE_CLASSNAME::eigs_mode4( const t4_type& data_, u4_type& u4_)
184 {
185  //unfolding / matricization
186  u4_unfolded_type* unfolding = new u4_unfolded_type;
187  data_.mode4_unfolding_fwd( *unfolding );
188 
189  //covariance matrix of unfolded data
190  u4_cov_type* cov = new u4_cov_type;
191  blas_dgemm< I4, I1*I2*I3, I4, T>* blas_cov = new blas_dgemm< I4, I1*I2*I3, I4, T>;
192  blas_cov->compute( *unfolding, *cov );
193  delete blas_cov;
194  delete unfolding;
195 
196  //compute x largest magnitude eigenvalues; x = R
197  get_eigs_u_red( *cov, u4_ );
198 
199  delete cov;
200 }
201 
202 /* helper methods for SVD and EIGS*/
203 
204 VMML_TEMPLATE_STRING
205 template< size_t N, size_t R >
206 void
207 VMML_TEMPLATE_CLASSNAME::get_eigs_u_red( const matrix< N, N, T >& data_, matrix< N, R, T >& u_ )
208 {
209  typedef matrix< N, N, T > cov_matrix_type;
210  typedef vector< R, T > eigval_type;
211  typedef matrix< N, R, T > eigvec_type;
212  //typedef matrix< N, R, T_coeff > coeff_type;
213 
214  //compute x largest magnitude eigenvalues; x = R
215  eigval_type* eigxvalues = new eigval_type;
216  eigvec_type* eigxvectors = new eigvec_type;
217 
218  lapack_sym_eigs< N, T > eigs;
219  cov_matrix_type* data = new cov_matrix_type;
220  data->cast_from( data_ );
221  if( !eigs.compute_x( *data, *eigxvectors, *eigxvalues) ) {
222 
223  /*if( _is_quantify_coeff ){
224  coeff_type* evec_quant = new coeff_type;
225  T min_value = 0; T max_value = 0;
226  u_.cast_from( *eigxvectors );
227  u_.quantize( *evec_quant, min_value, max_value );
228  evec_quant->dequantize( u_, min_value, max_value );
229  delete evec_quant;
230  } else */
231  std::cerr << "Warning: lapack eigenvector computation returned error code" << std::endl;
232  }
233  u_ = *eigxvectors;
234 
235  delete eigxvalues;
236  delete eigxvectors;
237  delete data;
238 }
239 
240 #undef VMML_TEMPLATE_STRING
241 #undef VMML_TEMPLATE_CLASSNAME
242 
243 }//end vmml namespace
244 
245 #endif