2
* VMMLib - Tensor Classes
4
* @author Susanne Suter
7
* The cp3 tensor class is consists of three basis matrices u1-u3 and R lambda values for a given rank-R approximation
8
* CP stands for Candecomp/Parafac (1970)
9
* - Carroll & Chang, 1970: Analysis of Individual Differences in Multidimensional Scaling via an N-way generalization of ``Eckart--Young'' decompositions, Psychometrika.
10
* - Harshman, 1970: Foundations of the PARAFAC procedure: Models and conditions for an 'explanatory' multi-modal factor analysis,UCLA Working Papers in Phonetics.
11
* - De Lathauwer, De Moor, Vandewalle, 2000: A multilinear singular value decomposition, SIAM J. Matrix Anal. Appl.
12
* - Kolda & Bader, 2009: Tensor Decompositions and Applications, SIAM Review.
16
#ifndef __VMML__CP3_TENSOR__HPP__
17
#define __VMML__CP3_TENSOR__HPP__
19
#include <vmmlib/t3_hopm.hpp>
20
#include <vmmlib/tensor3_iterator.hpp>
21
#include <vmmlib/matrix_pseudoinverse.hpp>
26
template< size_t R, size_t I1, size_t I2, size_t I3, typename T_value = float, typename T_coeff = float >
30
typedef float T_internal;
32
typedef tensor3< I1, I2, I3, T_value > t3_type;
33
typedef typename t3_type::iterator t3_iterator;
34
typedef typename t3_type::const_iterator t3_const_iterator;
36
typedef tensor3< I1, I2, I3, T_internal > t3_comp_type;
38
typedef tensor3< I1, I2, I3, T_coeff > t3_coeff_type;
39
typedef typename t3_coeff_type::iterator t3_coeff_iterator;
40
typedef typename t3_coeff_type::const_iterator t3_coeff_const_iterator;
42
typedef matrix< I1, R, T_coeff > u1_type;
43
typedef typename u1_type::iterator u1_iterator;
44
typedef typename u1_type::const_iterator u1_const_iterator;
46
typedef matrix< I2, R, T_coeff > u2_type;
47
typedef typename u2_type::iterator u2_iterator;
48
typedef typename u2_type::const_iterator u2_const_iterator;
50
typedef matrix< I3, R, T_coeff > u3_type;
51
typedef typename u3_type::iterator u3_iterator;
52
typedef typename u3_type::const_iterator u3_const_iterator;
54
typedef matrix< I1, R, T_internal > u1_comp_type;
55
typedef matrix< I2, R, T_internal > u2_comp_type;
56
typedef matrix< I3, R, T_internal > u3_comp_type;
58
typedef vector< R, T_internal > lambda_comp_type;
59
typedef vector< R, T_coeff > lambda_type;
61
cp3_tensor( u1_type& U1, u2_type& U2, u3_type& U3, lambda_type& lambdas_ );
65
void get_lambdas( lambda_type& data_ ) const { data_ = *_lambdas; } ;
66
void get_u1( u1_type& U1 ) const { U1 = *_u1; } ;
67
void get_u2( u2_type& U2 ) const { U2 = *_u2; } ;
68
void get_u3( u3_type& U3 ) const { U3 = *_u3; } ;
70
void set_core( const lambda_type& lambdas_ ) { _lambdas = lambda_type( lambdas_ ); _lambdas_comp.cast_from( _lambdas ); } ;
71
void set_u1( u1_type& U1 ) { *_u1 = U1; _u1_comp->cast_from( U1 ); } ;
72
void set_u2( u2_type& U2 ) { *_u2 = U2; _u1_comp->cast_from( U2 ); } ;
73
void set_u3( u3_type& U3 ) { *_u3 = U3; _u1_comp->cast_from( U3 ); } ;
75
void set_lambda_comp( lambda_comp_type& lambdas_ ) { _lambdas_comp = lambda_comp_type( lambdas_ ); _lambdas.cast_from( _lambdas_comp ); } ;
76
void set_u1_comp( u1_comp_type& U1 ) { *_u1_comp = U1; _u1->cast_from( U1 ); } ;
77
void set_u2_comp( u2_comp_type& U2 ) { *_u2_comp = U2; _u1->cast_from( U2 ); } ;
78
void set_u3_comp( u3_comp_type& U3 ) { *_u3_comp = U3; _u1->cast_from( U3 ); } ;
80
void get_lambda_comp( lambda_comp_type& data_ ) const { data_ = _lambdas_comp; } ;
81
void get_u1_comp( u1_comp_type& U1 ) const { U1 = *_u1_comp; } ;
82
void get_u2_comp( u2_comp_type& U2 ) const { U2 = *_u2_comp; } ;
83
void get_u3_comp( u3_comp_type& U3 ) const { U3 = *_u3_comp; } ;
85
void export_to( std::vector< T_coeff >& data_ ) const;
86
void import_from( std::vector< T_coeff >& data_ );
88
void reconstruct( t3_type& data_ ) const;
89
template< typename T_init >
90
void decompose( const t3_type& data_, T_init init, const size_t max_iterations_ = 100 );
91
template< typename T_init >
92
void cp_als( const t3_type& data_, T_init init, const size_t max_iterations_ = 100 );
97
cp3_tensor( const cp3_tensor< R, I1, I1, I1, T_value, T_coeff >& other ) {};
98
cp3_tensor< R, I1, I1, I1, T_value, T_coeff > operator=( const cp3_tensor< R, I1, I1, I1, T_value, T_coeff >& other ) { return *this; };
101
void cast_comp_members();
104
lambda_type* _lambdas ;
109
lambda_comp_type* _lambdas_comp ;
110
u1_comp_type* _u1_comp ;
111
u2_comp_type* _u2_comp ;
112
u3_comp_type* _u3_comp ;
114
}; // class cp3_tensor
117
#define VMML_TEMPLATE_STRING template< size_t R, size_t I1, size_t I2, size_t I3, typename T_value, typename T_coeff >
118
#define VMML_TEMPLATE_CLASSNAME cp3_tensor< R, I1, I2, I3, T_value, T_coeff >
122
VMML_TEMPLATE_CLASSNAME::cp3_tensor( u1_type& U1, u2_type& U2, u3_type& U3, lambda_type& lambdas_ )
124
set_lambdas(lambdas_);
131
VMML_TEMPLATE_CLASSNAME::cp3_tensor()
133
_lambdas = new vector< R, T_coeff>();
135
_u1 = new u1_type(); _u1->zero();
136
_u2 = new u2_type(); _u2->zero();
137
_u3 = new u3_type(); _u3->zero();
138
_lambdas_comp = new vector< R, T_internal>;
139
_lambdas_comp->set( 0 );
140
_u1_comp = new u1_comp_type; _u1_comp->zero();
141
_u2_comp = new u2_comp_type; _u2_comp->zero();
142
_u3_comp = new u3_comp_type; _u3_comp->zero();
146
VMML_TEMPLATE_CLASSNAME::~cp3_tensor()
155
delete _lambdas_comp;
161
VMML_TEMPLATE_CLASSNAME::cast_members()
163
_u1->cast_from( *_u1_comp );
164
_u2->cast_from( *_u2_comp );
165
_u3->cast_from( *_u3_comp );
166
_lambdas->cast_from( *_lambdas_comp );
171
VMML_TEMPLATE_CLASSNAME::cast_comp_members()
173
_u1_comp->cast_from( *_u1 );
174
_u2_comp->cast_from( *_u2 );
175
_u3_comp->cast_from( *_u3 );
176
_lambdas_comp->cast_from( _lambdas );
182
VMML_TEMPLATE_CLASSNAME::reconstruct( t3_type& data_ ) const
184
//FIXME: check data types
186
data.cast_from( data_ );
188
typedef t3_hopm< R, I1, I2, I3, T_internal > hopm_type;
189
hopm_type::reconstruct( data, *_u1_comp, *_u2_comp, *_u3_comp, *_lambdas_comp );
191
//convert reconstructed data, which is in type T_internal (double, float) to T_value (uint8 or uint16)
192
if( (sizeof(T_value) == 1) || (sizeof(T_value) == 2) ){
193
data_.float_t_to_uint_t( data );
195
data_.cast_from( data );
201
template< typename T_init >
203
VMML_TEMPLATE_CLASSNAME::decompose( const t3_type& data_, T_init init, const size_t max_iterations_ )
205
cp_als( data_, init, max_iterations_ );
209
template< typename T_init >
211
VMML_TEMPLATE_CLASSNAME::cp_als( const t3_type& data_, T_init init, const size_t max_iterations_ )
214
data.cast_from( data_ );
216
typedef t3_hopm< R, I1, I2, I3, T_internal > hopm_type;
217
hopm_type::als( data, *_u1_comp, *_u2_comp, *_u3_comp, *_lambdas_comp, init, max_iterations_ );
225
VMML_TEMPLATE_CLASSNAME::export_to( std::vector< T_coeff >& data_ ) const
227
u1_const_iterator it = _u1.begin(),
229
for( ; it != it_end; ++it )
231
data_.push_back( *it );
234
u2_const_iterator u2_it = _u2.begin(),
235
u2_it_end = _u2.end();
236
for( ; u2_it != u2_it_end; ++u2_it )
238
data_.push_back( *u2_it );
241
u3_const_iterator u3_it = _u3.begin(),
242
u3_it_end = _u3.end();
243
for( ; u3_it != u3_it_end; ++u3_it )
245
data_.push_back( *u3_it );
248
//TODO: iterate over lambdas
254
VMML_TEMPLATE_CLASSNAME::import_from( std::vector< T_coeff >& data_ )
256
size_t i = 0; //iterator over data_
258
u1_iterator it = _u1.begin(),
260
for( ; it != it_end; ++it, ++i )
265
u2_iterator u2_it = _u2.begin(),
266
u2_it_end = _u2.end();
267
for( ; u2_it != u2_it_end; ++u2_it, ++i )
269
*u2_it = data_.at(i);
272
u3_iterator u3_it = _u3.begin(),
273
u3_it_end = _u3.end();
274
for( ; u3_it != u3_it_end; ++u3_it, ++i )
276
*u3_it = data_.at(i);
279
//TODO: import lambdas
285
VMML_TEMPLATE_CLASSNAME::nnz() const
289
counter += _u1_comp->nnz();
290
counter += _u2_comp->nnz();
291
counter += _u3_comp->nnz();
292
counter += _lambdas_comp->nnz();
299
#undef VMML_TEMPLATE_STRING
300
#undef VMML_TEMPLATE_CLASSNAME