9#include "tensor_utilities.h"
11#define GET_VARIABLE_NAME(Variable) (#Variable)
17void initialize_sequential(Tensor<type, 1>& vector)
19 for(Index i = 0; i < vector.size(); i++) vector(i) = type(i);
23void multiply_rows(Tensor<type, 2>& matrix,
const Tensor<type, 1>& vector)
25 const Index columns_number = matrix.dimension(1);
26 const Index rows_number = matrix.dimension(0);
30 for(Index i = 0; i < rows_number; i++)
32 for(Index j = 0; j < columns_number; j++)
34 matrix(i,j) *= vector(j);
40void divide_columns(Tensor<type, 2>& matrix,
const Tensor<type, 1>& vector)
42 const Index columns_number = matrix.dimension(1);
43 const Index rows_number = matrix.dimension(0);
47 for(Index j = 0; j < columns_number; j++)
49 for(Index i = 0; i < rows_number; i++)
51 matrix(i,j) /= vector(i) == type(0) ? type(1) : vector(i);
57bool is_zero(
const Tensor<type, 1>& tensor)
59 const Index size = tensor.size();
61 for(Index i = 0; i < size; i++)
63 if(
abs(tensor[i]) > type(NUMERIC_LIMITS_MIN))
return false;
69bool is_zero(
const Tensor<type,1>& tensor,
const type& limit)
71 const Index size = tensor.size();
73 for(Index i = 0; i < size; i++)
75 if(
abs(tensor[i]) > type(limit))
return false;
82bool is_false(
const Tensor<bool, 1>& tensor)
84 const Index size = tensor.size();
86 for(Index i = 0; i < size; i++)
88 if(tensor(i))
return false;
95bool is_binary(
const Tensor<type, 2>& matrix)
97 const Index size = matrix.size();
99 for(Index i = 0; i < size; i++)
101 if(matrix(i) != type(0) && matrix(i) != type(1))
return false;
108bool is_constant(
const Tensor<type, 1>& vector)
110 const Index size = vector.size();
112 for(Index i = 0; i < size; i++)
114 for(Index j = 0; j < size; j++)
116 if((vector(i) - vector(j)) != type(0))
return false;
124bool is_equal(
const Tensor<type, 2>& matrix,
const type& value,
const type& tolerance)
126 const Index size = matrix.size();
128 for(Index i = 0; i < size; i++)
130 if(
abs(matrix(i) - value) > tolerance)
return false;
138bool are_equal(
const Tensor<type, 1>& vector_1,
const Tensor<type, 1>& vector_2,
const type& tolerance)
140 const Index size = vector_1.size();
142 for(Index i = 0; i < size; i++)
144 if(
abs(vector_1(i) - vector_2(i)) > tolerance)
return false;
151bool are_equal(
const Tensor<type, 2>& matrix_1,
const Tensor<type, 2>& matrix_2,
const type& tolerance)
153 const Index size = matrix_1.size();
155 for(Index i = 0; i < size; i++)
157 if(
abs(matrix_1(i) - matrix_2(i)) > tolerance)
return false;
164void save_csv(
const Tensor<type,2>& data,
const string& filename)
166 ofstream file(filename);
170 ostringstream buffer;
172 buffer <<
"OpenNN Exception: Matrix template." << endl
173 <<
"void save_csv(const Tensor<type,2>&, const string&) method." << endl
174 <<
"Cannot open matrix data file: " << filename << endl;
176 throw logic_error(buffer.str());
181 const Index data_rows = data.dimension(0);
182 const Index data_columns = data.dimension(1);
184 char separator_char =
';';
186 for(Index i = 0; i < data_rows; i++)
188 for(Index j = 0; j < data_columns; j++)
192 if(j != data_columns-1)
194 file << separator_char;
205Tensor<Index, 1> calculate_rank_greater(
const Tensor<type, 1>& vector)
207 const Index size = vector.size();
209 Tensor<Index, 1> rank(size);
210 iota(rank.data(), rank.data() + rank.size(), 0);
213 rank.data() + rank.size(),
214 [&](Index i, Index j){return vector[i] > vector[j];});
220Tensor<Index, 1> calculate_rank_less(
const Tensor<type, 1>& vector)
222 const Index size = vector.size();
224 Tensor<Index, 1> rank(size);
225 iota(rank.data(), rank.data() + rank.size(), 0);
228 rank.data() + rank.size(),
229 [&](Index i, Index j){return vector[i] < vector[j];});
235void scrub_missing_values(Tensor<type, 2>& matrix,
const type& value)
237 std::replace_if(matrix.data(), matrix.data()+matrix.size(), [](type x){return isnan(x);}, value);
241Tensor<type, 2> kronecker_product(
const Tensor<type, 1>& vector,
const Tensor<type, 1>& other_vector)
243 const Index size = vector.size();
245 Tensor<type, 2> direct(size, size);
247 #pragma omp parallel for
249 for(Index i = 0; i < size; i++)
251 for(Index j = 0; j < size; j++)
253 direct(i, j) = vector(i) * other_vector(j);
261type l1_norm(
const ThreadPoolDevice* thread_pool_device,
const Tensor<type, 1>& vector)
263 Tensor<type, 0> norm;
265 norm.device(*thread_pool_device) = vector.abs().sum();
271void l1_norm_gradient(
const ThreadPoolDevice* thread_pool_device,
const Tensor<type, 1>& vector, Tensor<type, 1>& gradient)
273 gradient.device(*thread_pool_device) = vector.sign();
277void l1_norm_hessian(
const ThreadPoolDevice*,
const Tensor<type, 1>&, Tensor<type, 2>& hessian)
285type l2_norm(
const ThreadPoolDevice* thread_pool_device,
const Tensor<type, 1>& vector)
287 Tensor<type, 0> norm;
289 norm.device(*thread_pool_device) = vector.square().sum().sqrt();
306void l2_norm_gradient(
const ThreadPoolDevice* thread_pool_device,
const Tensor<type, 1>& vector, Tensor<type, 1>& gradient)
308 const type norm = l2_norm(thread_pool_device, vector);
310 if(norm < type(NUMERIC_LIMITS_MIN))
317 gradient.device(*thread_pool_device) = vector/norm;
321void l2_norm_hessian(
const ThreadPoolDevice* thread_pool_device,
const Tensor<type, 1>& vector, Tensor<type, 2>& hessian)
323 const type norm = l2_norm(thread_pool_device, vector);
325 if(norm < type(NUMERIC_LIMITS_MIN))
332 hessian.device(*thread_pool_device) = kronecker_product(vector, vector)/(norm*norm*norm);
336void sum_diagonal(Tensor<type, 2>& matrix,
const type& value)
338 const Index rows_number = matrix.dimension(0);
340 #pragma omp parallel for
341 for(Index i = 0; i < rows_number; i++)
342 matrix(i,i) += value;
347Tensor<type, 1> perform_Householder_QR_decomposition(
const Tensor<type, 2>& A,
const Tensor<type, 1>& b)
349 const Index n = A.dimension(0);
351 Tensor<type, 1> x(n);
353 const Map<Matrix<type, Dynamic, Dynamic>> A_eigen((type*)A.data(), n, n);
354 const Map<Matrix<type, Dynamic, 1>> b_eigen((type*)b.data(), n, 1);
355 Map<Matrix<type, Dynamic, 1>> x_eigen((type*)x.data(), n);
357 x_eigen = A_eigen.colPivHouseholderQr().solve(b_eigen);
363void fill_submatrix(
const Tensor<type, 2>& matrix,
364 const Tensor<Index, 1>& rows_indices,
365 const Tensor<Index, 1>& columns_indices,
366 type* submatrix_pointer)
368 const Index rows_number = rows_indices.size();
369 const Index columns_number = columns_indices.size();
371 const type* matrix_pointer = matrix.data();
373 #pragma omp parallel for
375 for(Index j = 0; j < columns_number; j++)
377 const type* matrix_column_pointer = matrix_pointer + matrix.dimension(0)*columns_indices[j];
378 type* submatrix_column_pointer = submatrix_pointer + rows_number*j;
380 const type* value_pointer =
nullptr;
381 const Index* rows_indices_pointer = rows_indices.data();
382 for(Index i = 0; i < rows_number; i++)
384 value_pointer = matrix_column_pointer + *rows_indices_pointer;
385 rows_indices_pointer++;
386 *submatrix_column_pointer = *value_pointer;
387 submatrix_column_pointer++;
392Index count_NAN(
const Tensor<type, 1>& x)
394 Index NAN_number = 0;
396 for(Index i = 0; i < x.size(); i++)
398 if(
isnan(x(i))) NAN_number++;
405void check_size(
const Tensor<type, 1>& vector,
const Index& size,
const string&
log)
407 if(vector.size() != size)
409 ostringstream buffer;
411 buffer <<
"OpenNN Exception: " <<
log
412 <<
"Size of vector is " << vector.size() <<
", but must be " << size <<
".";
414 throw logic_error(buffer.str());
419void check_dimensions(
const Tensor<type, 2>& matrix,
const Index& rows_number,
const Index& columns_number,
const string&
log)
421 if(matrix.dimension(0) != rows_number)
423 ostringstream buffer;
425 buffer <<
"OpenNN Exception: " <<
log
426 <<
"Number of rows in matrix is " << matrix.dimension(0) <<
", but must be " << rows_number <<
".";
428 throw logic_error(buffer.str());
431 if(matrix.dimension(1) != columns_number)
433 ostringstream buffer;
435 buffer <<
"OpenNN Exception: " <<
log
436 <<
"Number of columns in matrix is " << matrix.dimension(0) <<
", but must be " << columns_number <<
".";
438 throw logic_error(buffer.str());
443void check_columns_number(
const Tensor<type, 2>& matrix,
const Index& columns_number,
const string&
log)
445 if(matrix.dimension(1) != columns_number)
447 ostringstream buffer;
449 buffer <<
"OpenNN Exception: " <<
log
450 <<
"Number of columns in matrix is " << matrix.dimension(0) <<
", but must be " << columns_number <<
".";
452 throw logic_error(buffer.str());
456Tensor<type, 2> assemble_vector_vector(
const Tensor<type, 1>& x,
const Tensor<type, 1>& y)
458 const Index rows_number = x.size();
459 const Index columns_number = 2;
461 Tensor<type, 2> data(rows_number, columns_number);
463 for(Index i = 0; i < rows_number; i++)
473Tensor<type, 2> assemble_vector_matrix(
const Tensor<type, 1>& x,
const Tensor<type, 2>& y)
475 const Index rows_number = x.size();
476 const Index columns_number = 1 + y.dimension(1);
478 Tensor<type, 2> data(rows_number, columns_number);
480 for(Index i = 0; i < rows_number; i++)
484 for(Index j = 0; j < y.dimension(1); j++)
486 data(i, 1+j) = y(i,j);
494Tensor<type, 2> assemble_matrix_vector(
const Tensor<type, 2>& x,
const Tensor<type, 1>& y)
496 const Index rows_number = x.size();
497 const Index columns_number = x.dimension(1) + 1;
499 Tensor<type, 2> data(rows_number, columns_number);
501 for(Index i = 0; i < rows_number; i++)
503 for(Index j = 0; j < x.dimension(1); j++)
508 data(i, columns_number-1) = y(i);
515Tensor<type, 2> assemble_matrix_matrix(
const Tensor<type, 2>& x,
const Tensor<type, 2>& y)
517 const Index rows_number = x.dimension(0);
518 const Index columns_number = x.dimension(1) + y.dimension(1);
520 Tensor<type, 2> data(rows_number, columns_number);
522 for(Index i = 0; i < rows_number; i++)
524 for(Index j = 0; j < x.dimension(1); j++)
529 for(Index j = 0; j < y.dimension(1); j++)
531 data(i, x.dimension(1) + j) = y(i,j);
541bool is_less_than(
const Tensor<type, 1>& column,
const type& value)
543 const Tensor<bool, 1> if_sentence = column <= column.constant(value);
545 Tensor<bool, 1> sentence(column.size());
546 sentence.setConstant(
true);
548 Tensor<bool, 1> else_sentence(column.size());
549 else_sentence.setConstant(
false);
551 const Tensor<bool, 0> is_less = (if_sentence.select(sentence, else_sentence)).any();
HALF_CONSTEXPR half abs(half arg)
HALF_CONSTEXPR bool isnan(half arg)