tensor.h
1 // OpenNN: Open Neural Networks Library
2 // www.opennn.net
3 //
4 // T E N S O R C O N T A I N E R
5 //
6 // Artificial Intelligence Techniques, SL
7 // artelnics@artelnics.com
8 
9 #ifndef TENSOR_H
10 #define TENSOR_H
11 
12 // System includes
13 
14 #include <cmath>
15 #include <cstdlib>
16 #include <fstream>
17 #include <iomanip>
18 #include <iostream>
19 #include <sstream>
20 #include <stdexcept>
21 
22 // OpenNN includes
23 
24 #include "vector.h"
25 
26 using namespace std;
27 
28 namespace OpenNN
29 {
30 
32 
35 
36 template <typename T>
37 class Tensor : public vector<T>
38 {
39 
40 public:
41 
42  // Constructors
43 
44  explicit Tensor();
45 
46  explicit Tensor(const Vector<size_t>&);
47 
48  explicit Tensor(const Vector<size_t>&, const T&);
49 
50  explicit Tensor(const size_t&);
51 
52  explicit Tensor(const size_t&, const size_t&);
53 
54  explicit Tensor(const size_t&, const size_t&, const size_t&);
55 
56  explicit Tensor(const size_t&, const size_t&, const size_t&, const size_t&);
57 
58  explicit Tensor(const Matrix<T>&);
59 
60  // Destructor
61 
62  virtual ~Tensor();
63 
64  // Operators
65 
66  inline Tensor<T>& operator = (const Tensor<T>&);
67 
68  inline bool operator == (const T&);
69  inline bool operator == (const Tensor<T>&);
70 
71  inline bool operator >= (const T&);
72  inline bool operator <= (const T&);
73 
74  inline T& operator()(const size_t&);
75  inline T& operator()(const size_t&, const size_t&);
76  inline T& operator()(const size_t&, const size_t&, const size_t&);
77  inline T& operator()(const size_t&, const size_t&, const size_t&, const size_t&);
78 
79  inline const T& operator()(const size_t&) const;
80  inline const T& operator()(const size_t&, const size_t&) const;
81  inline const T& operator()(const size_t&, const size_t&, const size_t&) const;
82  inline const T& operator()(const size_t&, const size_t&, const size_t&, const size_t&) const;
83 
84  Tensor<T> operator + (const T&) const;
85  Tensor<T> operator - (const T&) const;
86  Tensor<T> operator * (const T&) const;
87  Tensor<T> operator / (const T&) const;
88 
89  Tensor<T> operator + (const Tensor<T>&) const;
90  Tensor<T> operator - (const Tensor<T>&) const;
91  Tensor<T> operator * (const Tensor<T>&) const;
92  Tensor<T> operator / (const Tensor<T>&) const;
93 
94  void operator *= (const Tensor<T>&);
95 
96  // Get methods
97 
98  size_t get_dimensions_number() const;
99  size_t get_dimension(const size_t&) const;
100 
101  size_t get_element(const size_t&, const size_t&) const;
102 
103  void add_matrix(const Matrix<T>&);
104 
105  Vector<T> get_row(const size_t&) const;
106  Vector<T> get_column(const size_t&) const;
107  Vector<string> get_header() const;
108 
109  Tensor<T> get_tensor(const size_t&) const;
110  Matrix<T> get_matrix(const size_t&) const;
111  Matrix<T> get_matrix(const size_t&, const size_t&) const;
112 
113  void embed(const size_t&, const size_t&, const Matrix<T>&);
114 
115  void embed(const size_t&, const size_t&, const Tensor<T>&);
116 
117  Vector<T> to_vector() const;
118  Matrix<T> to_matrix() const;
119 
120  Tensor<T> to_2d_tensor() const;
121 
122  // Get methods
123 
124  Vector<size_t> get_dimensions() const;
125 
126  // Set methods
127 
128  void set();
129  void set(const size_t&);
130  void set(const size_t&, const size_t&);
131  void set(const Vector<size_t>&);
132  void set(const Vector<size_t>&, const T&);
133  void set(const Tensor<T>&);
134  void set_row(const size_t&, const Vector<T>&);
135  void set_matrix(const size_t&, const size_t&, const Matrix<T>&);
136  void set_matrix(const size_t&, const Matrix<T>&);
137  void set_tensor(const size_t&, const Tensor<T>&);
138 
139  void embed(const size_t&, const Vector<T>&);
140 
141  void initialize(const T&);
142  void initialize_sequential();
143 
144  void randomize_uniform(const T&, const T&);
145  void randomize_normal(const double & = 0.0, const double & = 1.0);
146 
147  T calculate_sum() const;
148 
149  Tensor<T> divide(const Vector<T>&, const size_t&) const;
150 
151 private:
152 
153  Vector<size_t> dimensions;
154 
155 };
156 
157 
160 
161 template <class T>
162 Tensor<T>::Tensor() : vector<T>()
163 {
164  set();
165 }
166 
167 
172 
173 template <class T>
174 Tensor<T>::Tensor(const Vector<size_t>& new_dimensions) : vector<T> (new_dimensions.calculate_product())
175 {
176  dimensions = new_dimensions;
177 }
178 
179 
184 
185 template <class T>
186 Tensor<T>::Tensor(const Vector<size_t>& new_dimensions, const T& value) : vector<T> (new_dimensions.calculate_product(), value)
187 {
188  dimensions = new_dimensions;
189 }
190 
191 
195 
196 template <class T>
197 Tensor<T>::Tensor(const size_t& dimension_1) : vector<T>(dimension_1)
198 {
199  dimensions = Vector<size_t>({dimension_1});
200 }
201 
202 
207 
208 template <class T>
209 Tensor<T>::Tensor(const size_t& dimension_1, const size_t& dimension_2) : vector<T>(dimension_1*dimension_2)
210 {
211  dimensions = Vector<size_t>({dimension_1, dimension_2});
212 }
213 
214 
220 
221 template <class T>
222 Tensor<T>::Tensor(const size_t& dimension_1, const size_t& dimension_2, const size_t& dimension_3) : vector<T>(dimension_1*dimension_2*dimension_3)
223 {
224  dimensions = Vector<size_t>({dimension_1, dimension_2, dimension_3});
225 }
226 
227 
234 
235 template <class T>
236 Tensor<T>::Tensor(const size_t& dimension_1, const size_t& dimension_2, const size_t& dimension_3, const size_t& dimension_4) : vector<T>(dimension_1*dimension_2*dimension_3*dimension_4)
237 {
238  dimensions = Vector<size_t>({dimension_1, dimension_2, dimension_3, dimension_4});
239 }
240 
241 
245 
246 template <class T>
247 Tensor<T>::Tensor(const Matrix<T>& matrix) : vector<T> (matrix)
248 {
249  dimensions = Vector<size_t>({ matrix.get_rows_number(), matrix.get_columns_number() });
250 
251  for(size_t i = 0; i < matrix.size(); i++)
252  {
253  (*this)[i] = matrix[i];
254  }
255 }
256 
257 
259 
260 template <class T>
262 {
263 }
264 
265 
269 
270 template<class T>
271 ostream& operator << (ostream& os, const Tensor<T>& tensor)
272 {
273  const size_t dimensions_number = tensor.get_dimensions_number();
274 
275  os << "Dimensions number: " << dimensions_number << endl;
276  os << "Dimensions: " << tensor.get_dimensions() << endl;
277  os << "Values: " << endl;
278 
279  if(dimensions_number == 1)
280  {
281  const size_t size = tensor.get_dimension(0);
282 
283  for(size_t i = 0; i < size; i ++)
284  {
285  os << tensor[i] << " ";
286  }
287 
288  os << "\n";
289  }
290  else if(dimensions_number == 2)
291  {
292  const size_t rows_number = tensor.get_dimension(0);
293  const size_t columns_number = tensor.get_dimension(1);
294 
295  for(size_t i = 0; i < rows_number; i ++)
296  {
297  for(size_t j = 0; j < columns_number; j++)
298  {
299  os << tensor(i,j) << " ";
300  }
301 
302  os << endl;
303  }
304  }
305  else if(dimensions_number == 3)
306  {
307  const size_t rank = tensor.get_dimension(2);
308  const size_t rows_number = tensor.get_dimension(0);
309  const size_t columns_number = tensor.get_dimension(1);
310 
311  for(size_t k = 0; k < rank; k ++)
312  {
313  os << "submatrix_" << k << "\n";
314 
315  for(size_t i = 0; i < rows_number; i ++)
316  {
317  for(size_t j = 0; j < columns_number; j++)
318  {
319  os << tensor(i,j,k) << "\t";
320  }
321 
322  os << "\n";
323  }
324  }
325  }
326  else if(dimensions_number > 3)
327  {
328  const size_t rank_1 = tensor.get_dimension(3);
329  const size_t rank_2 = tensor.get_dimension(2);
330  const size_t rows_number = tensor.get_dimension(0);
331  const size_t columns_number = tensor.get_dimension(1);
332 
333  for(size_t l = 0; l < rank_1; l++)
334  {
335  for(size_t k = 0; k < rank_2; k ++)
336  {
337  os << "submatrix_" << l << "_" << k << "\n";
338 
339  for(size_t i = 0; i < rows_number; i ++)
340  {
341  for(size_t j = 0; j < columns_number; j++)
342  {
343  os << tensor(i,j,k,l) << "\t";
344  }
345 
346  os << "\n";
347  }
348  }
349  }
350  }
351 
352  return os;
353 }
354 
355 
358 
359 template <class T>
361 {
362  if(other_tensor.dimensions != this->dimensions)
363  {
364  set(other_tensor.dimensions);
365  }
366 
367  copy(other_tensor.begin(), other_tensor.end(), this->begin());
368 
369  return *this;
370 }
371 
372 
375 
376 template <class T>
378 {
379  const size_t size = this->size();
380 
381  for(size_t i = 0; i < size; i++)
382  if((*this)[i] != other[i]) return false;
383 
384  return true;
385 }
386 
387 
390 
391 template <class T>
392 bool Tensor<T>::operator == (const T& value)
393 {
394  const size_t size = this->size();
395 
396  for(size_t i = 0; i < size; i++)
397  if((*this)[i] != value) return false;
398 
399  return true;
400 }
401 
402 
405 
406 template <class T>
407 bool Tensor<T>::operator >= (const T& value)
408 {
409  const size_t size = this->size();
410 
411  for(size_t i = 0; i < size; i++)
412  if((*this)[i] < value) return false;
413 
414  return true;
415 }
416 
417 
420 
421 template <class T>
422 bool Tensor<T>::operator <= (const T& value)
423 {
424  const size_t size = this->size();
425 
426  for(size_t i = 0; i < size; i++)
427  if((*this)[i] > value) return false;
428 
429  return true;
430 }
431 
432 
433 template<class T>
434 inline const T& Tensor<T>::operator()(const size_t& row, const size_t& column) const
435 {
436 #ifdef __OPENNN_DEBUG__
437 
438  const size_t dimensions_number = get_dimensions_number();
439 
440  if(dimensions_number != 2)
441  {
442  ostringstream buffer;
443 
444  buffer << "OpenNN Exception: Tensor template.\n"
445  << "const T& Tensor<T>::operator()(const size_t&, const size_t&) const.\n"
446  << "Number of dimensions (" << dimensions_number << ") must be 2.\n";
447 
448  throw logic_error(buffer.str());
449  }
450 
451  if(row >= dimensions[0])
452  {
453  ostringstream buffer;
454 
455  buffer << "OpenNN Exception: Tensor template.\n"
456  << "const T& Tensor<T>::operator()(const size_t&, const size_t&) const.\n"
457  << "Row index (" << row << ") must be less than rows number (" << dimensions[0] << ").\n";
458 
459  throw logic_error(buffer.str());
460  }
461 
462  if(column >= dimensions[1])
463  {
464  ostringstream buffer;
465 
466  buffer << "OpenNN Exception: Tensor template.\n"
467  << "const T& Tensor<T>::operator()(const size_t&, const size_t&) const.\n"
468  << "Column index (" << column << ") must be less than columns number (" << dimensions[1] << ").\n";
469 
470  throw logic_error(buffer.str());
471  }
472 
473 #endif
474 
475  return (*this)[dimensions[0]*column + row];
476 }
477 
478 
479 template <class T>
480 inline const T& Tensor<T>::operator()(const size_t& index_0 , const size_t& index_1, const size_t& index_2) const
481 {
482 #ifdef __OPENNN_DEBUG__
483 
484  const size_t dimensions_number = get_dimensions_number();
485 
486  if(dimensions_number != 3)
487  {
488  ostringstream buffer;
489 
490  buffer << "OpenNN Exception: Tensor template.\n"
491  << "const T& Tensor<T>::operator()(const size_t&, const size_t&, const size_t&) const.\n"
492  << "Number of dimensions (" << dimensions_number << ") must be 3.\n";
493 
494  throw logic_error(buffer.str());
495  }
496 
497 #endif
498 
499  return (*this)[index_2 * dimensions[0] * dimensions[1] + index_1 * dimensions[0] + index_0];
500 }
501 
502 
503 template <class T>
504 inline const T& Tensor<T>::operator()(const size_t& index_0 , const size_t& index_1, const size_t& index_2, const size_t& index_3) const
505 {
506 #ifdef __OPENNN_DEBUG__
507 
508  const size_t dimensions_number = get_dimensions_number();
509 
510  if(dimensions_number != 4)
511  {
512  ostringstream buffer;
513 
514  buffer << "OpenNN Exception: Tensor template.\n"
515  << "const T& Tensor<T>::operator()(const size_t&, const size_t&, const size_t&, const size_t&) const.\n"
516  << "Number of dimensions (" << dimensions_number << ") must be 4.\n";
517 
518  throw logic_error(buffer.str());
519  }
520 
521 #endif
522 
523  return (*this)[index_3 * dimensions[0] * dimensions[1] * dimensions[2] + index_2 *dimensions[0] * dimensions[1] + index_1 * dimensions[0] + index_0];
524 }
525 
526 
527 template <class T>
528 T& Tensor<T>::operator()(const size_t& row, const size_t& column)
529 {
530 #ifdef __OPENNN_DEBUG__
531 
532  const size_t dimensions_number = get_dimensions_number();
533 
534  if(dimensions_number != 2)
535  {
536  ostringstream buffer;
537 
538  buffer << "OpenNN Exception: Tensor template.\n"
539  << "T& Tensor<T>::operator()(const size_t&, const size_t&) const.\n"
540  << "Number of dimensions (" << dimensions_number << ") must be 2.\n";
541 
542  throw logic_error(buffer.str());
543  }
544 
545  if(row >= dimensions[0])
546  {
547  ostringstream buffer;
548 
549  buffer << "OpenNN Exception: Tensor template.\n"
550  << "T& Tensor<T>::operator()(const size_t&, const size_t&) const.\n"
551  << "Row index (" << row << ") must be less than rows number (" << dimensions[0] << ").\n";
552 
553  throw logic_error(buffer.str());
554  }
555 
556  if(column >= dimensions[1])
557  {
558  ostringstream buffer;
559 
560  buffer << "OpenNN Exception: Tensor template.\n"
561  << "T& Tensor<T>::operator()(const size_t&, const size_t&) const.\n"
562  << "Column index (" << column << ") must be less than columns number (" << dimensions[1] << ").\n";
563 
564  throw logic_error(buffer.str());
565  }
566 
567 #endif
568 
569  return (*this)[dimensions[0]*column+row];
570 }
571 
572 
573 template <class T>
574 T& Tensor<T>::operator()(const size_t& index_0 , const size_t& index_1, const size_t& index_2)
575 {
576 #ifdef __OPENNN_DEBUG__
577 
578  const size_t dimensions_number = get_dimensions_number();
579 
580  if(dimensions_number != 3)
581  {
582  ostringstream buffer;
583 
584  buffer << "OpenNN Exception: Tensor template.\n"
585  << "const T& Tensor<T>::operator()(const size_t&, const size_t&, const size_t&) const.\n"
586  << "Number of dimensions (" << dimensions_number << ") must be 3.\n";
587 
588  throw logic_error(buffer.str());
589  }
590 
591 #endif
592 
593  return (*this)[index_2 * (dimensions[0] * dimensions[1]) + index_1 * dimensions[0] + index_0];
594 }
595 
596 
597 template <class T>
598 T& Tensor<T>::operator()(const size_t& index_0 , const size_t& index_1, const size_t& index_2, const size_t& index_3)
599 {
600 #ifdef __OPENNN_DEBUG__
601 
602  const size_t dimensions_number = get_dimensions_number();
603 
604  if(dimensions_number != 4)
605  {
606  ostringstream buffer;
607 
608  buffer << "OpenNN Exception: Tensor template.\n"
609  << "const T& Tensor<T>::operator()(const size_t&, const size_t&, const size_t&, const size_t&) const.\n"
610  << "Number of dimensions (" << dimensions_number << ") must be 4.\n";
611 
612  throw logic_error(buffer.str());
613  }
614 
615 #endif
616 
617  return (*this)[index_3 * dimensions[0] * dimensions[1] * dimensions[2] + index_2 *dimensions[0] * dimensions[1] + index_1 * dimensions[0] + index_0];
618 }
619 
620 
623 
624 template <class T>
625 Tensor<T> Tensor<T>::operator + (const T& value) const
626 {
627  Tensor<T> output(dimensions);
628 
629  for(size_t i = 0; i < this->size(); i++)
630  {
631  output[i] = (*this)[i] + value;
632  }
633 
634  return output;
635 }
636 
637 
640 
641 template <class T>
643 {
644  Tensor<T> output(other.get_dimensions());
645 
646  for(size_t i = 0; i < other.size(); i++)
647  {
648  output[i] = (*this)[i] + other[i];
649  }
650 
651  return output;
652 }
653 
654 
657 
658 template <class T>
659 Tensor<T> Tensor<T>::operator - (const T& value) const
660 {
661  Tensor<T> output(dimensions);
662 
663  for(size_t i = 0; i < this->size(); i++)
664  {
665  output[i] = (*this)[i] - value;
666  }
667 
668  return output;
669 }
670 
671 
674 
675 template <class T>
677 {
678  Tensor<T> output(other.get_dimensions());
679 
680  for(size_t i = 0; i < other.size(); i++)
681  {
682  output[i] = (*this)[i]-other[i];
683  }
684 
685  return output;
686 }
687 
688 
691 
692 template <class T>
693 Tensor<T> Tensor<T>::operator * (const T& value) const
694 {
695  Tensor<T> output(dimensions);
696 
697  for(size_t i = 0; i < this->size(); i++)
698  {
699  output[i] = (*this)[i] * value;
700  }
701 
702  return output;
703 }
704 
705 
708 
709 template <class T>
711 {
712  Tensor<T> output(other.get_dimensions());
713 
714  for(size_t i = 0; i < other.size(); i++)
715  {
716  output[i] = (*this)[i]*other[i];
717  }
718 
719  return output;
720 }
721 
722 
725 
726 template <class T>
727 Tensor<T> Tensor<T>::operator / (const T& value) const
728 {
729  Tensor<T> output(dimensions);
730 
731  for(size_t i = 0; i < this->size(); i++)
732  {
733  output[i] = (*this)[i] / value;
734  }
735 
736  return output;
737 }
738 
739 
742 
743 template <class T>
745 {
746  Tensor<T> output(other.get_dimensions());
747 
748  for(size_t i = 0; i < other.size(); i++)
749  {
750  output[i] = (*this)[i]/other[i];
751  }
752 
753  return output;
754 }
755 
756 
759 
760 template <class T>
762 {
763  for(size_t i = 0; i < this->size(); i++)
764  {
765  (*this)[i] *= other[i];
766  }
767 }
768 
769 
771 
772 template<class T>
774 {
775  return dimensions;
776 }
777 
778 
782 
783 template <class T>
784 size_t Tensor<T>::get_dimension(const size_t& index_dimension) const
785 {
786  return dimensions[index_dimension];
787 }
788 
789 
791 
792 template <class T>
794 {
795  return dimensions.size();
796 }
797 
798 
803 
804 template <class T>
805 size_t Tensor<T>::get_element(const size_t& row, const size_t& column) const
806 {
807  return (*this)[dimensions[0]*column+row];
808 }
809 
810 
814 
815 template <class T>
816 Vector<T> Tensor<T>::get_row(const size_t& i) const
817 {
818  Vector<T> row(dimensions[1]);
819 
820  for(size_t j = 0; j < dimensions[1]; j++)
821  {
822  row[j] = (*this)(i,j);
823  }
824 
825  return row;
826 }
827 
828 
832 
833 template <class T>
834 Vector<T> Tensor<T>::get_column(const size_t& j) const
835 {
836  Vector<T> column(dimensions[0]);
837 
838  for(size_t i = 0; i < dimensions[0]; i++)
839  {
840  column[i] = (*this)(i,j);
841  }
842 
843  return column;
844 }
845 
846 
848 
849 template <class T>
851 {
852  Vector<string> header(dimensions[1]);
853 
854  for(size_t j = 0; j < dimensions[1]; j++)
855  {
856  header[j] = (*this)(0,j);
857  }
858 
859  return header;
860 }
861 
862 
864 
865 template <class T>
866 Tensor<T> Tensor<T>::get_tensor(const size_t& index_0) const
867 {
868  Tensor<T> tensor(Vector<size_t>({dimensions[1], dimensions[2], dimensions[3]}));
869 
870  for(size_t i = 0; i < dimensions[1]; i++)
871  for(size_t j = 0; j < dimensions[2]; j++)
872  for(size_t k = 0; k < dimensions[3]; k++)
873  tensor(i,j,k) = (*this)(index_0,i,j,k);
874 
875  return tensor;
876 }
877 
878 
881 
882 template <class T>
883 Matrix<T> Tensor<T>::get_matrix(const size_t& matrix_index) const
884 {
885  const size_t dimensions_number = get_dimensions_number();
886 
887  if(dimensions_number == 2)
888  {
889  const size_t rows_number = dimensions[0];
890  const size_t columns_number = dimensions[1];
891  const size_t elements_number = rows_number * columns_number;
892 
893  Matrix<T> matrix(rows_number, columns_number);
894 
895  for(size_t i = 0; i < elements_number; i++)
896  {
897  matrix[i] = (*this)[i];
898  }
899 
900  return matrix;
901  }
902  else if(dimensions_number > 2)
903  {
904 
905  if(matrix_index > dimensions[2])
906  {
907 // throw exception("Matrix out of bounds");
908  }
909 
910  const size_t rows_number = dimensions[0];
911  const size_t columns_number = dimensions[1];
912 
913  const size_t elements_number = rows_number * columns_number;
914 
915  Matrix<T> matrix(rows_number, columns_number);
916 
917  for(size_t i = 0; i < elements_number; i ++)
918  matrix[i] = (*this)[matrix_index * elements_number + i];
919 
920  return matrix;
921  }
922  else
923  {
924  return Matrix<T>();
925  }
926 }
927 
928 
932 
933 template <class T>
934 Matrix<T> Tensor<T>::get_matrix(const size_t& index_0, const size_t& index_1) const
935 {
936  const size_t dimension_2 = dimensions[2];
937  const size_t dimension_3 = dimensions[3];
938 
939  Matrix<T> matrix(dimension_2, dimension_3);
940 
941  for(size_t i = 0; i < dimension_2; i++)
942  {
943  for(size_t j = 0; j < dimension_3; j++)
944  {
945  matrix(i,j) = (*this)(index_0, index_1, i, j);
946  }
947  }
948 
949  return matrix;
950 }
951 
952 
953 template <class T>
954 void Tensor<T>::add_matrix(const Matrix<T>& a_matrix)
955 {
956  const size_t order = 2;
957 
958  if(order < 2)
959  {
960 // throw exception("OpenNN Exception: Tensor<T> template\n\
961 // Cannot add a new matrix to this tensor.");
962 
963  }
964  else if(order == 2)
965  {
966  this->insert(this->end(), a_matrix.begin(), a_matrix.end());
967 
968  dimensions = Vector<size_t>({ dimensions[0], dimensions[1], 2} );
969 
970  }
971  else if(order == 3)
972  {
973  // set_dimensions({ dimensions[0], dimensions[1], dimensions[2] });
974 
975  this->insert(this->end(), a_matrix.begin(), a_matrix.end());
976 
977  dimensions[2] += 1;
978 
979  cout << *this << endl;
980  }
981  else
982  {
983  //
984  }
985 }
986 
987 
989 
990 template <class T>
992 {
993  this->resize(0);
994 }
995 
996 
1000 
1001 template <class T>
1002 void Tensor<T>::set(const size_t& size)
1003 {
1004  dimensions.set({size});
1005 
1006  this->resize(size);
1007 }
1008 
1009 
1010 template <class T>
1011 void Tensor<T>::set(const size_t&, const size_t&)
1012 {
1013 }
1014 
1015 
1019 
1020 template <class T>
1021 void Tensor<T>::set(const Vector<size_t>& new_dimensions)
1022 {
1023  dimensions = new_dimensions;
1024 
1025  this->resize(new_dimensions.calculate_product());
1026 }
1027 
1028 
1032 
1033 template <class T>
1034 void Tensor<T>::set(const Vector<size_t>& new_dimensions, const T& value)
1035 {
1036  dimensions = new_dimensions;
1037 
1038  this->resize(new_dimensions.calculate_product());
1039 
1040  this->initialize(value);
1041 }
1042 
1043 
1044 template <class T>
1045 void Tensor<T>::set(const Tensor<T>& other_tensor)
1046 {
1047  if(other_tensor.dimensions != this->dimensions)
1048  {
1049  set(other_tensor.dimensions);
1050  }
1051 
1052  copy(other_tensor.begin(), other_tensor.end(), this->begin());
1053 }
1054 
1055 
1059 // @tochek
1060 template <class T>
1061 void Tensor<T>::set_row(const size_t& row_index, const Vector<T>& new_row)
1062 {
1063  const size_t size = new_row.size();
1064 
1065  for(size_t i = 0; i < size; i++)
1066  {
1067  (*this)(row_index, i) = new_row[i];
1068  }
1069 }
1070 
1071 
1077 
1078 template <class T>
1079 void Tensor<T>::embed(const size_t& row_position, const size_t& column_position, const Matrix<T>& other_matrix)
1080 {
1081  const size_t other_rows_number = other_matrix.get_rows_number();
1082  const size_t other_columns_number = other_matrix.get_columns_number();
1083 
1084  #ifdef __OPENNN_DEBUG__
1085 
1086 // if(row_position + other_rows_number > this.rows_number)
1087  if(row_position + other_rows_number > this->get_dimensions()[0])
1088  {
1089  ostringstream buffer;
1090 
1091  buffer << "OpenNN Exception: Tensor Template.\n"
1092  << "void insert(const size_t&, const size_t&, const Matrix<T>&) const method.\n"
1093  << "Cannot tuck in matrix.\n";
1094 
1095  throw logic_error(buffer.str());
1096  }
1097 
1098 // if(column_position + other_columns_number > this.columns_number)
1099  if(row_position + other_rows_number > this->get_dimensions()[0])
1100  {
1101  ostringstream buffer;
1102 
1103  buffer << "OpenNN Exception: Tensor Template.\n"
1104  << "void insert(const size_t&, const size_t&, const Matrix<T>&) const method.\n"
1105  << "Cannot tuck in matrix.\n";
1106 
1107  throw logic_error(buffer.str());
1108  }
1109 
1110  #endif
1111 
1112  for(size_t i = 0; i < other_rows_number; i++)
1113  {
1114  for(size_t j = 0; j < other_columns_number; j++)
1115  {
1116  (*this)(row_position+i,column_position+j) = other_matrix(i,j);
1117  }
1118  }
1119 }
1120 
1121 
1127 
1128 template <class T>
1129 void Tensor<T>::embed(const size_t& row_position, const size_t& column_position, const Tensor<T>& other_tensor)
1130 {
1131  const size_t other_rows_number = other_tensor.get_rows_number();
1132  const size_t other_columns_number = other_tensor.get_columns_number();
1133 
1134  #ifdef __OPENNN_DEBUG__
1135 
1136 // if(row_position + other_rows_number > this.rows_number)
1137  if(row_position + other_rows_number > this->get_dimensions()[1])
1138  {
1139  ostringstream buffer;
1140 
1141  buffer << "OpenNN Exception: Tensor Template.\n"
1142  << "void insert(const size_t&, const size_t&, const Matrix<T>&) const method.\n"
1143  << "Cannot tuck in matrix.\n";
1144 
1145  throw logic_error(buffer.str());
1146  }
1147 
1148 // if(column_position + other_columns_number > this.columns_number)
1149  if(row_position + other_rows_number > this->get_dimensions()[1])
1150  {
1151  ostringstream buffer;
1152 
1153  buffer << "OpenNN Exception: Tensor Template.\n"
1154  << "void insert(const size_t&, const size_t&, const Matrix<T>&) const method.\n"
1155  << "Cannot tuck in matrix.\n";
1156 
1157  throw logic_error(buffer.str());
1158  }
1159 
1160  #endif
1161 
1162  for(size_t i = 0; i < other_rows_number; i++)
1163  {
1164  for(size_t j = 0; j < other_columns_number; j++)
1165  {
1166  (*this)(row_position+i,column_position+j) = other_tensor(i,j);
1167  }
1168  }
1169 }
1170 
1171 
1173 
1174 template <class T>
1176 {
1177  return Vector<T>(this->begin(),this->end());
1178 }
1179 
1180 
1182 
1183 template <class T>
1185 {
1186  const size_t dimensions_number = get_dimensions_number();
1187 
1188 #ifdef __OPENNN_DEBUG__
1189 
1190 if(dimensions_number != 2)
1191 {
1192  ostringstream buffer;
1193 
1194  buffer << "OpenNN Exception: Tensor Template.\n"
1195  << "Matrix<T> to_matrix() const method.\n"
1196  << "Dimension of tensor ("<< dimensions_number << ") must be 2.\n";
1197 
1198  throw logic_error(buffer.str());
1199 }
1200 
1201 #endif
1202 
1203  Matrix<T> matrix(dimensions[0], dimensions[1]);
1204 
1205  for(size_t i = 0; i < this->size(); i++)
1206  matrix[i] = (*this)[i];
1207 
1208  return matrix;
1209 }
1210 
1211 
1213 
1214 template <class T>
1216 {
1217  Tensor<T> tensor;
1218 
1219  const size_t size = this->size();
1220 
1221  if(get_dimensions_number() == 1)
1222  {
1223  tensor.set(Vector<size_t>({1, size}));
1224  for(size_t s = 0; s < size; s++)
1225  {
1226  tensor(0, s) = (*this)[s];
1227  }
1228  }
1229  else if(get_dimensions_number() == 2)
1230  {
1231  tensor = (*this);
1232  }
1233  else if(get_dimensions_number() == 3)
1234  {
1235  tensor.set(Vector<size_t>({1, size}));
1236  for(size_t s = 0; s < size; s++)
1237  {
1238  tensor(0, s) = (*this)(s%get_dimension(0), s/get_dimension(0), s/(get_dimension(0)*get_dimension(1)));
1239  }
1240  }
1241  else if(get_dimensions_number() == 4)
1242  {
1243  tensor.set(Vector<size_t>({get_dimension(0), get_dimension(1) * get_dimension(2)* get_dimension(3)}));
1244  for(size_t s = 0; s < get_dimension(1) * get_dimension(2) * get_dimension(3); s++)
1245  {
1246  for(size_t n = 0; n < get_dimension(0); n++)
1247  {
1248  tensor(n, s) = (*this)(n, s%get_dimension(1), (s/get_dimension(1))%get_dimension(2), s/(get_dimension(1) * get_dimension(2)));
1249  }
1250  }
1251  }
1252  else if (get_dimensions_number() > 4)
1253  {
1254  ostringstream buffer;
1255 
1256  buffer << "OpenNN Exception: Tensor template.\n"
1257  << "void Tensor<T>::set_new_dimensions(const Vector<size_t>&) method.\n"
1258  << "The number of dimensions of tensor (" << get_dimensions_number() << ") must not be greater than four.\n";
1259 
1260  throw logic_error(buffer.str());
1261  }
1262 
1263  return tensor;
1264 }
1265 
1270 
1271 // Number of dimension of tensor must be 3?
1272 template <class T>
1273 void Tensor<T>::set_matrix(const size_t& index_0, const size_t& index_1, const Matrix<T>& matrix)
1274 {
1275 #ifdef __OPENNN_DEBUG__
1276 
1277  const size_t dimensions_number = get_dimensions_number();
1278 
1279 if(dimensions_number != 4)
1280 {
1281  ostringstream buffer;
1282 
1283  buffer << "OpenNN Exception: Tensor Template.\n"
1284  << "Matrix<T> set_matrix(const size_t&, const size_t&, const Matrix<double>&) const method.\n"
1285  << "Number of dimension of tensor must be 4.\n";
1286 
1287  throw logic_error(buffer.str());
1288 }
1289 
1290 #endif
1291 
1292  const size_t rows_number = dimensions[2];
1293  const size_t columns_number = dimensions[3];
1294 
1295  for(size_t i = 0; i < rows_number; i++)
1296  {
1297  for(size_t j = 0; j < columns_number; j++)
1298  {
1299  (*this)(index_0, index_1, i, j) = matrix(i,j);
1300  }
1301  }
1302 }
1303 
1304 
1308 
1309 template <class T>
1310 void Tensor<T>::set_matrix(const size_t& index_0, const Matrix<T>& matrix)
1311 {
1312 
1313  const size_t rows_number = dimensions[0];
1314  const size_t columns_number = dimensions[1];
1315 
1316  for(size_t i = 0; i < rows_number; i++)
1317  {
1318  for(size_t j = 0; j < columns_number; j++)
1319  {
1320  (*this)(i, j, index_0) = matrix(i,j);
1321  }
1322  }
1323 }
1324 
1325 
1329 
1330 template <class T>
1331 void Tensor<T>::set_tensor(const size_t& index_0, const Tensor<T>& tensor)
1332 {
1333  for(size_t i = 0; i < dimensions[1]; i++)
1334  for(size_t j = 0; j < dimensions[2]; j++)
1335  for(size_t k = 0; k < dimensions[3]; k++)
1336  (*this)(index_0,i,j,k) = tensor(i,j,k);
1337 }
1338 
1339 
1344 
1345 template <class T>
1346 void Tensor<T>::embed(const size_t& index, const Vector<T>& vector)
1347 {
1348  const size_t dimension_0 = dimensions[0];
1349 
1350  const size_t vector_size = vector.size();
1351 
1352  for(size_t i = 0; i < vector_size; i++)
1353  {
1354  (*this)[index+i*dimension_0] = vector[i];
1355  }
1356 }
1357 
1358 
1361 
1362 template <class T>
1363 void Tensor<T>::initialize(const T&value)
1364 {
1365  fill(this->begin(),this->end(), value);
1366 }
1367 
1368 
1370 
1371 template <class T>
1373  for(size_t i = 0; i < this->size(); i++) {
1374  (*this)[i] = static_cast<T>(i);
1375  }
1376 }
1377 
1378 
1383 
1384 template <class T>
1385 void Tensor<T>::randomize_uniform(const T& minimum, const T& maximum)
1386 {
1387 #ifdef __OPENNN_DEBUG__
1388 
1389  if(minimum > maximum) {
1390  ostringstream buffer;
1391 
1392  buffer << "OpenNN Exception: Tensor Template.\n"
1393  << "void randomize_uniform(const double&, const double&) method.\n"
1394  << "Minimum value must be less or equal than maximum value.\n";
1395 
1396  throw logic_error(buffer.str());
1397  }
1398 
1399 #endif
1400 
1401  const size_t this_size = this->size();
1402 
1403  for(size_t i = 0; i < this_size; i++)
1404  {
1405  (*this)[i] = calculate_random_uniform(minimum, maximum);
1406  }
1407 }
1408 
1409 
1415 
1416 template <class T>
1417 void Tensor<T>::randomize_normal(const double &mean,
1418  const double &standard_deviation)
1419 {
1420 #ifdef __OPENNN_DEBUG__
1421 
1422  if(standard_deviation < 0.0) {
1423  ostringstream buffer;
1424 
1425  buffer << "OpenNN Exception: Tensor Template.\n"
1426  << "void randomize_normal(const double&, const double&) method.\n"
1427  << "Standard deviation must be equal or greater than zero.\n";
1428 
1429  throw logic_error(buffer.str());
1430  }
1431 
1432 #endif
1433 
1434  const size_t this_size = this->size();
1435 
1436  for(size_t i = 0; i < this_size; i++) {
1437  (*this)[i] = calculate_random_normal(mean, standard_deviation);
1438  }
1439 }
1440 
1441 
1443 
1444 template <class T>
1446 {
1447  T sum = 0;
1448 
1449  for(size_t i = 0; i < this->size(); i++)
1450  {
1451  sum += (*this)[i];
1452  }
1453 
1454  return sum;
1455 }
1456 
1457 
1458 template <class T>
1459 Tensor<T> Tensor<T>::divide(const Vector<T>&, const size_t&) const
1460 {
1461  return Tensor<double>();
1462 }
1463 
1464 
1465 }
1466 // end namespace
1467 
1468 #endif
1469 
1470 // OpenNN: Open Neural Networks Library.
1471 // Copyright(C) 2005-2019 Artificial Intelligence Techniques, SL.
1472 //
1473 // This library is free software; you can redistribute it and/or
1474 // modify it under the terms of the GNU Lesser General Public
1475 // License as published by the Free Software Foundation; either
1476 // version 2.1 of the License, or any later version.
1477 //
1478 // This library is distributed in the hope that it will be useful,
1479 // but WITHOUT ANY WARRANTY; without even the implied warranty of
1480 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1481 // Lesser General Public License for more details.
1482 
1483 // You should have received a copy of the GNU Lesser General Public
1484 // License along with this library; if not, write to the Free Software
1485 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1486 
OpenNN::Matrix::get_rows_number
const size_t & get_rows_number() const
Returns the number of rows in the matrix.
Definition: matrix.h:1287
OpenNN::Vector::calculate_product
T calculate_product() const
Returns the product of the elements of this vector.
Definition: vector.h:2519
OpenNN::Matrix
This template class defines a matrix for general purpose use.
Definition: matrix.h:42
OpenNN::Tensor::set
void set()
Sets the size of this tensor to zero.
Definition: tensor.h:991
OpenNN::Tensor::get_dimension
size_t get_dimension(const size_t &) const
Definition: tensor.h:784
OpenNN::Tensor
This template class defines a tensor for general purpose use.
Definition: tensor.h:37
OpenNN::Tensor::get_dimensions_number
size_t get_dimensions_number() const
Returns the number of dimensions of the tensor.
Definition: tensor.h:793
OpenNN::Matrix::get_columns_number
const size_t & get_columns_number() const
Returns the number of columns in the matrix.
Definition: matrix.h:1296
OpenNN::Tensor::get_dimensions
Vector< size_t > get_dimensions() const
Returns the total number of dimensions of the tensor.
Definition: tensor.h:773
OpenNN::Vector< size_t >