40 #ifndef __VMML__T3_IHOOI_HPP__
41 #define __VMML__T3_IHOOI_HPP__
43 #include <vmmlib/t3_hopm.hpp>
44 #include <vmmlib/t3_hooi.hpp>
48 template<
size_t R1,
size_t R2,
size_t R3,
size_t NBLOCKS,
size_t I1,
size_t I2,
size_t I3,
typename T_val =
float,
typename T_coeff =
double >
88 #define VMML_TEMPLATE_STRING template< size_t R1, size_t R2, size_t R3, size_t NBLOCKS, size_t I1, size_t I2, size_t I3, typename T_val, typename T_coeff >
89 #define VMML_TEMPLATE_CLASSNAME t3_ihooi< R1, R2, R3, NBLOCKS, I1, I2, I3, T_val, T_coeff >
93 VMML_TEMPLATE_CLASSNAME::i_als(
const t3_type& data_, u1_type& u1_, u2_type& u2_, u3_type& u3_, t3_core_type& core_,
const float tolerance) {
96 if ((R1 % NBLOCKS != 0) or (R2 % NBLOCKS != 0) or (R3 % NBLOCKS != 0)) {
97 std::ostringstream convert1, convert2, convert3, convert4;
102 VMMLIB_ERROR(
"In incremental Tucker, (R1,R2,R3) = (" + convert1.str() +
"," + convert2.str() +
"," + convert3.str() +
"), NBLOCKS = " + convert2.str() +
" (must be divisible)", VMMLIB_HERE);
104 t3_coeff_type* approx_data =
new t3_coeff_type;
106 t3_coeff_type* residual_data =
new t3_coeff_type;
107 residual_data->cast_from(data_);
109 t3_core_tmp_type* t3_core_tmp =
new t3_core_tmp_type;
111 u1_tmp_type* u1_tmp =
new u1_tmp_type;
112 u2_tmp_type* u2_tmp =
new u2_tmp_type;
113 u3_tmp_type* u3_tmp =
new u3_tmp_type;
115 t3_core_incr_type* t3_core_incr =
new t3_core_incr_type;
116 t3_core_incr->zero();
117 u1_incr_type* u1_incr =
new u1_incr_type;
119 u2_incr_type* u2_incr =
new u2_incr_type;
121 u3_incr_type* u3_incr =
new u3_incr_type;
124 u1_1col_type* u1_1col =
new u1_1col_type;
125 u2_1col_type* u2_1col =
new u2_1col_type;
126 u3_1col_type* u3_1col =
new u3_1col_type;
128 typedef t3_hooi < R1 / NBLOCKS, R2 / NBLOCKS, R3 / NBLOCKS, I1, I2, I3, T_coeff > hooi_type;
130 for (
size_t i = 0; i < NBLOCKS; ++i) {
132 std::cout <<
"Incremental Tucker: block number '" << i <<
"'" << std::endl;
136 result += hooi_type::als(*residual_data, *u1_tmp, *u2_tmp, *u3_tmp, *t3_core_tmp,
typename hooi_type::init_hosvd(), tolerance);
139 for (
size_t r = 0; r < R1 / NBLOCKS; ++r) {
140 u1_tmp->get_column(r, *u1_1col);
141 u1_incr->set_column(i * R1 / NBLOCKS + r, *u1_1col);
143 for (
size_t r = 0; r < R2 / NBLOCKS; ++r) {
144 u2_tmp->get_column(r, *u2_1col);
145 u2_incr->set_column(i * R2 / NBLOCKS + r, *u2_1col);
147 for (
size_t r = 0; r < R3 / NBLOCKS; ++r) {
148 u3_tmp->get_column(r, *u3_1col);
149 u3_incr->set_column(i * R3 / NBLOCKS + r, *u3_1col);
153 t3_core_incr->set_sub_tensor3(*t3_core_tmp, i * R1 / NBLOCKS, i * R2 / NBLOCKS, i * R3 / NBLOCKS);
156 t3_ttm::full_tensor3_matrix_multiplication(*t3_core_tmp, *u1_tmp, *u2_tmp, *u3_tmp, *approx_data);
157 *residual_data = *residual_data - *approx_data;
160 u1_.cast_from(*u1_incr);
161 u2_.cast_from(*u2_incr);
162 u3_.cast_from(*u3_incr);
164 core_.cast_from(*t3_core_incr);
177 delete residual_data;
186 VMML_TEMPLATE_CLASSNAME::i_cp_als(
const t3_type& data_, u1_type& u1_, u2_type& u2_, u3_type& u3_, t3_core_type& core_,
const size_t max_iterations_,
const float tolerance) {
189 if ((R1 % NBLOCKS != 0) or (R2 % NBLOCKS != 0) or (R3 % NBLOCKS != 0)) {
190 std::ostringstream convert1, convert2, convert3, convert4, convert5;
196 VMMLIB_ERROR(
"In incremental CP-Tucker, R = " + convert1.str() +
", (R1,R2,R3) = (" + convert2.str() +
"," + convert3.str() +
"," + convert4.str() +
"), NBLOCKS = " + convert5.str() +
" (must be divisible, and R1,R2,R3 <= R)", VMMLIB_HERE);
199 t3_coeff_type* approx_data =
new t3_coeff_type;
201 t3_coeff_type* residual_data =
new t3_coeff_type;
202 residual_data->cast_from(data_);
204 t3_core_tmp_type* t3_core_tmp =
new t3_core_tmp_type;
206 u1_tmp_type* u1_tmp =
new u1_tmp_type;
207 u1_tmp_type* u1_tmp2 =
new u1_tmp_type;
208 u2_tmp_type* u2_tmp =
new u2_tmp_type;
209 u2_tmp_type* u2_tmp2 =
new u2_tmp_type;
210 u3_tmp_type* u3_tmp =
new u3_tmp_type;
211 u3_tmp_type* u3_tmp2 =
new u3_tmp_type;
213 t3_core_incr_type* t3_core_incr =
new t3_core_incr_type;
214 t3_core_incr->zero();
215 u1_incr_type* u1_incr =
new u1_incr_type;
217 u2_incr_type* u2_incr =
new u2_incr_type;
219 u3_incr_type* u3_incr =
new u3_incr_type;
222 u1_1col_type* u1_1col =
new u1_1col_type;
223 u2_1col_type* u2_1col =
new u2_1col_type;
224 u3_1col_type* u3_1col =
new u3_1col_type;
226 typedef t3_hopm < R / NBLOCKS, I1, I2, I3, T_coeff > hopm_type;
227 typedef vector < R / NBLOCKS, T_coeff > lambda_tmp_type;
228 lambda_tmp_type* lambdas_tmp =
new lambda_tmp_type;
229 typedef matrix < I1, R / NBLOCKS, T_coeff > u1_cp_tmp_type;
230 u1_cp_tmp_type* u1_cp_tmp =
new u1_cp_tmp_type;
231 typedef matrix < I2, R / NBLOCKS, T_coeff > u2_cp_tmp_type;
232 u2_cp_tmp_type* u2_cp_tmp =
new u2_cp_tmp_type;
233 typedef matrix < I3, R / NBLOCKS, T_coeff > u3_cp_tmp_type;
234 u3_cp_tmp_type* u3_cp_tmp =
new u3_cp_tmp_type;
236 typedef matrix < R1 / NBLOCKS, I1, T_coeff > u1_inv_tmp_type;
237 u1_inv_tmp_type* u1_inv_tmp =
new u1_inv_tmp_type;
238 typedef matrix < R2 / NBLOCKS, I2, T_coeff > u2_inv_tmp_type;
239 u2_inv_tmp_type* u2_inv_tmp =
new u2_inv_tmp_type;
240 typedef matrix < R3 / NBLOCKS, I3, T_coeff > u3_inv_tmp_type;
241 u3_inv_tmp_type* u3_inv_tmp =
new u3_inv_tmp_type;
243 for (
size_t i = 0; i < NBLOCKS; ++i) {
245 std::cout <<
"Incremental CP-Tucker: block number '" << i <<
"'" << std::endl;
249 result += hopm_type::als(*residual_data, *u1_cp_tmp, *u2_cp_tmp, *u3_cp_tmp, *lambdas_tmp,
typename hopm_type::init_hosvd(), max_iterations_, tolerance);
252 u1_cp_tmp->get_sub_matrix(*u1_tmp, 0, 0);
253 compute_pseudoinverse< u1_tmp_type > compute_pinv1;
254 compute_pinv1(*u1_tmp, *u1_tmp2);
255 u1_tmp2->transpose_to(*u1_inv_tmp);
257 u2_cp_tmp->get_sub_matrix(*u2_tmp, 0, 0);
258 compute_pseudoinverse< u2_tmp_type > compute_pinv2;
259 compute_pinv2(*u2_tmp, *u2_tmp2);
260 u2_tmp2->transpose_to(*u2_inv_tmp);
262 u3_cp_tmp->get_sub_matrix(*u3_tmp, 0, 0);
263 compute_pseudoinverse< u3_tmp_type > compute_pinv3;
264 compute_pinv3(*u3_tmp, *u3_tmp2);
265 u3_tmp2->transpose_to(*u3_inv_tmp);
269 t3_ttm::full_tensor3_matrix_multiplication(*residual_data, *u1_inv_tmp, *u2_inv_tmp, *u3_inv_tmp, *t3_core_tmp);
272 for (
size_t r = 0; r < R1 / NBLOCKS; ++r) {
273 u1_tmp->get_column(r, *u1_1col);
274 u1_incr->set_column(i * R1 / NBLOCKS + r, *u1_1col);
276 for (
size_t r = 0; r < R2 / NBLOCKS; ++r) {
277 u2_tmp->get_column(r, *u2_1col);
278 u2_incr->set_column(i * R2 / NBLOCKS + r, *u2_1col);
280 for (
size_t r = 0; r < R3 / NBLOCKS; ++r) {
281 u3_tmp->get_column(r, *u3_1col);
282 u3_incr->set_column(i * R3 / NBLOCKS + r, *u3_1col);
286 t3_core_incr->set_sub_tensor3(*t3_core_tmp, i * R1 / NBLOCKS, i * R2 / NBLOCKS, i * R3 / NBLOCKS);
289 t3_ttm::full_tensor3_matrix_multiplication(*t3_core_tmp, *u1_tmp, *u2_tmp, *u3_tmp, *approx_data);
290 *residual_data = *residual_data - *approx_data;
293 u1_.cast_from(*u1_incr);
294 u2_.cast_from(*u2_incr);
295 u3_.cast_from(*u3_incr);
297 core_.cast_from(*t3_core_incr);
310 delete residual_data;
316 #undef VMML_TEMPLATE_STRING
317 #undef VMML_TEMPLATE_CLASSNAME