Algorithms_in_C++  1.0.0
Set of algorithms implemented in C++.
vector_ops.hpp
Go to the documentation of this file.
1 /**
2  * @file vector_ops.hpp
3  * @author [Deep Raval](https://github.com/imdeep2905)
4  *
5  * @brief Various functions for vectors associated with [NeuralNetwork (aka
6  * Multilayer Perceptron)]
7  * (https://en.wikipedia.org/wiki/Multilayer_perceptron).
8  *
9  */
10 #ifndef VECTOR_OPS_FOR_NN
11 #define VECTOR_OPS_FOR_NN
12 
13 #include <algorithm>
14 #include <chrono>
15 #include <iostream>
16 #include <random>
17 #include <valarray>
18 #include <vector>
19 
20 /**
21  * @namespace machine_learning
22  * @brief Machine Learning algorithms
23  */
24 namespace machine_learning {
25 /**
26  * Overloaded operator "<<" to print 2D vector
27  * @tparam T typename of the vector
28  * @param out std::ostream to output
29  * @param A 2D vector to be printed
30  */
31 template <typename T>
33  std::vector<std::valarray<T>> const &A) {
34  // Setting output precision to 4 in case of floating point numbers
35  out.precision(4);
36  for (const auto &a : A) { // For each row in A
37  for (const auto &x : a) { // For each element in row
38  std::cout << x << ' '; // print element
39  }
41  }
42  return out;
43 }
44 
45 /**
46  * Overloaded operator "<<" to print a pair
47  * @tparam T typename of the pair
48  * @param out std::ostream to output
49  * @param A Pair to be printed
50  */
51 template <typename T>
53  // Setting output precision to 4 in case of floating point numbers
54  out.precision(4);
55  // printing pair in the form (p, q)
56  std::cout << "(" << A.first << ", " << A.second << ")";
57  return out;
58 }
59 
60 /**
61  * Overloaded operator "<<" to print a 1D vector
62  * @tparam T typename of the vector
63  * @param out std::ostream to output
64  * @param A 1D vector to be printed
65  */
66 template <typename T>
68  // Setting output precision to 4 in case of floating point numbers
69  out.precision(4);
70  for (const auto &a : A) { // For every element in the vector.
71  std::cout << a << ' '; // Print element
72  }
74  return out;
75 }
76 
77 /**
78  * Function to insert element into 1D vector
79  * @tparam T typename of the 1D vector and the element
80  * @param A 1D vector in which element will to be inserted
81  * @param ele element to be inserted
82  * @return new resultant vector
83  */
84 template <typename T>
86  std::valarray<T> B; // New 1D vector to store resultant vector
87  B.resize(A.size() + 1); // Resizing it accordingly
88  for (size_t i = 0; i < A.size(); i++) { // For every element in A
89  B[i] = A[i]; // Copy element in B
90  }
91  B[B.size() - 1] = ele; // Inserting new element in last position
92  return B; // Return resultant vector
93 }
94 
95 /**
96  * Function to remove first element from 1D vector
97  * @tparam T typename of the vector
98  * @param A 1D vector from which first element will be removed
99  * @return new resultant vector
100  */
101 template <typename T>
103  std::valarray<T> B; // New 1D vector to store resultant vector
104  B.resize(A.size() - 1); // Resizing it accordingly
105  for (size_t i = 1; i < A.size();
106  i++) { // // For every (except first) element in A
107  B[i - 1] = A[i]; // Copy element in B with left shifted position
108  }
109  return B; // Return resultant vector
110 }
111 
112 /**
113  * Function to remove last element from 1D vector
114  * @tparam T typename of the vector
115  * @param A 1D vector from which last element will be removed
116  * @return new resultant vector
117  */
118 template <typename T>
120  std::valarray<T> B; // New 1D vector to store resultant vector
121  B.resize(A.size() - 1); // Resizing it accordingly
122  for (size_t i = 0; i < A.size() - 1;
123  i++) { // For every (except last) element in A
124  B[i] = A[i]; // Copy element in B
125  }
126  return B; // Return resultant vector
127 }
128 
129 /**
130  * Function to equally shuffle two 3D vectors (used for shuffling training data)
131  * @tparam T typename of the vector
132  * @param A First 3D vector
133  * @param B Second 3D vector
134  */
135 template <typename T>
138  // If two vectors have different sizes
139  if (A.size() != B.size()) {
140  std::cerr << "ERROR (" << __func__ << ") : ";
141  std::cerr
142  << "Can not equally shuffle two vectors with different sizes: ";
143  std::cerr << A.size() << " and " << B.size() << std::endl;
144  std::exit(EXIT_FAILURE);
145  }
146  for (size_t i = 0; i < A.size(); i++) { // For every element in A and B
147  // Genrating random index < size of A and B
148  std::srand(std::chrono::system_clock::now().time_since_epoch().count());
149  size_t random_index = std::rand() % A.size();
150  // Swap elements in both A and B with same random index
151  std::swap(A[i], A[random_index]);
152  std::swap(B[i], B[random_index]);
153  }
154  return;
155 }
156 
157 /**
158  * Function to initialize given 2D vector using uniform random initialization
159  * @tparam T typename of the vector
160  * @param A 2D vector to be initialized
161  * @param shape required shape
162  * @param low lower limit on value
163  * @param high upper limit on value
164  */
165 template <typename T>
167  const std::pair<size_t, size_t> &shape,
168  const T &low, const T &high) {
169  A.clear(); // Making A empty
170  // Uniform distribution in range [low, high]
171  std::default_random_engine generator(
172  std::chrono::system_clock::now().time_since_epoch().count());
173  std::uniform_real_distribution<T> distribution(low, high);
174  for (size_t i = 0; i < shape.first; i++) { // For every row
176  row; // Making empty row which will be inserted in vector
177  row.resize(shape.second);
178  for (auto &r : row) { // For every element in row
179  r = distribution(generator); // copy random number
180  }
181  A.push_back(row); // Insert new row in vector
182  }
183  return;
184 }
185 
186 /**
187  * Function to Intialize 2D vector as unit matrix
188  * @tparam T typename of the vector
189  * @param A 2D vector to be initialized
190  * @param shape required shape
191  */
192 template <typename T>
194  const std::pair<size_t, size_t> &shape) {
195  A.clear(); // Making A empty
196  for (size_t i = 0; i < shape.first; i++) {
198  row; // Making empty row which will be inserted in vector
199  row.resize(shape.second);
200  row[i] = T(1); // Insert 1 at ith position
201  A.push_back(row); // Insert new row in vector
202  }
203  return;
204 }
205 
206 /**
207  * Function to Intialize 2D vector as zeroes
208  * @tparam T typename of the vector
209  * @param A 2D vector to be initialized
210  * @param shape required shape
211  */
212 template <typename T>
214  const std::pair<size_t, size_t> &shape) {
215  A.clear(); // Making A empty
216  for (size_t i = 0; i < shape.first; i++) {
218  row; // Making empty row which will be inserted in vector
219  row.resize(shape.second); // By default all elements are zero
220  A.push_back(row); // Insert new row in vector
221  }
222  return;
223 }
224 
225 /**
226  * Function to get sum of all elements in 2D vector
227  * @tparam T typename of the vector
228  * @param A 2D vector for which sum is required
229  * @return returns sum of all elements of 2D vector
230  */
231 template <typename T>
233  T cur_sum = 0; // Initially sum is zero
234  for (const auto &a : A) { // For every row in A
235  cur_sum += a.sum(); // Add sum of that row to current sum
236  }
237  return cur_sum; // Return sum
238 }
239 
240 /**
241  * Function to get shape of given 2D vector
242  * @tparam T typename of the vector
243  * @param A 2D vector for which shape is required
244  * @return shape as pair
245  */
246 template <typename T>
248  const size_t sub_size = (*A.begin()).size();
249  for (const auto &a : A) {
250  // If supplied vector don't have same shape in all rows
251  if (a.size() != sub_size) {
252  std::cerr << "ERROR (" << __func__ << ") : ";
253  std::cerr << "Supplied vector is not 2D Matrix" << std::endl;
254  std::exit(EXIT_FAILURE);
255  }
256  }
257  return std::make_pair(A.size(), sub_size); // Return shape as pair
258 }
259 
260 /**
261  * Function to scale given 3D vector using min-max scaler
262  * @tparam T typename of the vector
263  * @param A 3D vector which will be scaled
264  * @param low new minimum value
265  * @param high new maximum value
266  * @return new scaled 3D vector
267  */
268 template <typename T>
270  const std::vector<std::vector<std::valarray<T>>> &A, const T &low,
271  const T &high) {
273  A; // Copying into new vector B
274  const auto shape = get_shape(B[0]); // Storing shape of B's every element
275  // As this function is used for scaling training data vector should be of
276  // shape (1, X)
277  if (shape.first != 1) {
278  std::cerr << "ERROR (" << __func__ << ") : ";
279  std::cerr
280  << "Supplied vector is not supported for minmax scaling, shape: ";
281  std::cerr << shape << std::endl;
282  std::exit(EXIT_FAILURE);
283  }
284  for (size_t i = 0; i < shape.second; i++) {
285  T min = B[0][0][i], max = B[0][0][i];
286  for (size_t j = 0; j < B.size(); j++) {
287  // Updating minimum and maximum values
288  min = std::min(min, B[j][0][i]);
289  max = std::max(max, B[j][0][i]);
290  }
291  for (size_t j = 0; j < B.size(); j++) {
292  // Applying min-max scaler formula
293  B[j][0][i] =
294  ((B[j][0][i] - min) / (max - min)) * (high - low) + low;
295  }
296  }
297  return B; // Return new resultant 3D vector
298 }
299 
300 /**
301  * Function to get index of maximum element in 2D vector
302  * @tparam T typename of the vector
303  * @param A 2D vector for which maximum index is required
304  * @return index of maximum element
305  */
306 template <typename T>
308  const auto shape = get_shape(A);
309  // As this function is used on predicted (or target) vector, shape should be
310  // (1, X)
311  if (shape.first != 1) {
312  std::cerr << "ERROR (" << __func__ << ") : ";
313  std::cerr << "Supplied vector is ineligible for argmax" << std::endl;
314  std::exit(EXIT_FAILURE);
315  }
316  // Return distance of max element from first element (i.e. index)
317  return std::distance(std::begin(A[0]),
318  std::max_element(std::begin(A[0]), std::end(A[0])));
319 }
320 
321 /**
322  * Function which applys supplied function to every element of 2D vector
323  * @tparam T typename of the vector
324  * @param A 2D vector on which function will be applied
325  * @param func Function to be applied
326  * @return new resultant vector
327  */
328 template <typename T>
330  const std::vector<std::valarray<T>> &A, T (*func)(const T &)) {
332  A; // New vector to store resultant vector
333  for (auto &b : B) { // For every row in vector
334  b = b.apply(func); // Apply function to that row
335  }
336  return B; // Return new resultant 2D vector
337 }
338 
339 /**
340  * Overloaded operator "*" to multiply given 2D vector with scaler
341  * @tparam T typename of both vector and the scaler
342  * @param A 2D vector to which scaler will be multiplied
343  * @param val Scaler value which will be multiplied
344  * @return new resultant vector
345  */
346 template <typename T>
348  const T &val) {
350  A; // New vector to store resultant vector
351  for (auto &b : B) { // For every row in vector
352  b = b * val; // Multiply row with scaler
353  }
354  return B; // Return new resultant 2D vector
355 }
356 
357 /**
358  * Overloaded operator "/" to divide given 2D vector with scaler
359  * @tparam T typename of the vector and the scaler
360  * @param A 2D vector to which scaler will be divided
361  * @param val Scaler value which will be divided
362  * @return new resultant vector
363  */
364 template <typename T>
366  const T &val) {
368  A; // New vector to store resultant vector
369  for (auto &b : B) { // For every row in vector
370  b = b / val; // Divide row with scaler
371  }
372  return B; // Return new resultant 2D vector
373 }
374 
375 /**
376  * Function to get transpose of 2D vector
377  * @tparam T typename of the vector
378  * @param A 2D vector which will be transposed
379  * @return new resultant vector
380  */
381 template <typename T>
383  const std::vector<std::valarray<T>> &A) {
384  const auto shape = get_shape(A); // Current shape of vector
385  std::vector<std::valarray<T>> B; // New vector to store result
386  // Storing transpose values of A in B
387  for (size_t j = 0; j < shape.second; j++) {
388  std::valarray<T> row;
389  row.resize(shape.first);
390  for (size_t i = 0; i < shape.first; i++) {
391  row[i] = A[i][j];
392  }
393  B.push_back(row);
394  }
395  return B; // Return new resultant 2D vector
396 }
397 
398 /**
399  * Overloaded operator "+" to add two 2D vectors
400  * @tparam T typename of the vector
401  * @param A First 2D vector
402  * @param B Second 2D vector
403  * @return new resultant vector
404  */
405 template <typename T>
407  const std::vector<std::valarray<T>> &A,
408  const std::vector<std::valarray<T>> &B) {
409  const auto shape_a = get_shape(A);
410  const auto shape_b = get_shape(B);
411  // If vectors don't have equal shape
412  if (shape_a.first != shape_b.first || shape_a.second != shape_b.second) {
413  std::cerr << "ERROR (" << __func__ << ") : ";
414  std::cerr << "Supplied vectors have different shapes ";
415  std::cerr << shape_a << " and " << shape_b << std::endl;
416  std::exit(EXIT_FAILURE);
417  }
419  for (size_t i = 0; i < A.size(); i++) { // For every row
420  C.push_back(A[i] + B[i]); // Elementwise addition
421  }
422  return C; // Return new resultant 2D vector
423 }
424 
425 /**
426  * Overloaded operator "-" to add subtract 2D vectors
427  * @tparam T typename of the vector
428  * @param A First 2D vector
429  * @param B Second 2D vector
430  * @return new resultant vector
431  */
432 template <typename T>
434  const std::vector<std::valarray<T>> &A,
435  const std::vector<std::valarray<T>> &B) {
436  const auto shape_a = get_shape(A);
437  const auto shape_b = get_shape(B);
438  // If vectors don't have equal shape
439  if (shape_a.first != shape_b.first || shape_a.second != shape_b.second) {
440  std::cerr << "ERROR (" << __func__ << ") : ";
441  std::cerr << "Supplied vectors have different shapes ";
442  std::cerr << shape_a << " and " << shape_b << std::endl;
443  std::exit(EXIT_FAILURE);
444  }
445  std::vector<std::valarray<T>> C; // Vector to store result
446  for (size_t i = 0; i < A.size(); i++) { // For every row
447  C.push_back(A[i] - B[i]); // Elementwise substraction
448  }
449  return C; // Return new resultant 2D vector
450 }
451 
452 /**
453  * Function to multiply two 2D vectors
454  * @tparam T typename of the vector
455  * @param A First 2D vector
456  * @param B Second 2D vector
457  * @return new resultant vector
458  */
459 template <typename T>
461  const std::vector<std::valarray<T>> &B) {
462  const auto shape_a = get_shape(A);
463  const auto shape_b = get_shape(B);
464  // If vectors are not eligible for multiplication
465  if (shape_a.second != shape_b.first) {
466  std::cerr << "ERROR (" << __func__ << ") : ";
467  std::cerr << "Vectors are not eligible for multiplication ";
468  std::cerr << shape_a << " and " << shape_b << std::endl;
469  std::exit(EXIT_FAILURE);
470  }
471  std::vector<std::valarray<T>> C; // Vector to store result
472  // Normal matrix multiplication
473  for (size_t i = 0; i < shape_a.first; i++) {
474  std::valarray<T> row;
475  row.resize(shape_b.second);
476  for (size_t j = 0; j < shape_b.second; j++) {
477  for (size_t k = 0; k < shape_a.second; k++) {
478  row[j] += A[i][k] * B[k][j];
479  }
480  }
481  C.push_back(row);
482  }
483  return C; // Return new resultant 2D vector
484 }
485 
486 /**
487  * Function to get hadamard product of two 2D vectors
488  * @tparam T typename of the vector
489  * @param A First 2D vector
490  * @param B Second 2D vector
491  * @return new resultant vector
492  */
493 template <typename T>
495  const std::vector<std::valarray<T>> &A,
496  const std::vector<std::valarray<T>> &B) {
497  const auto shape_a = get_shape(A);
498  const auto shape_b = get_shape(B);
499  // If vectors are not eligible for hadamard product
500  if (shape_a.first != shape_b.first || shape_a.second != shape_b.second) {
501  std::cerr << "ERROR (" << __func__ << ") : ";
502  std::cerr << "Vectors have different shapes ";
503  std::cerr << shape_a << " and " << shape_b << std::endl;
504  std::exit(EXIT_FAILURE);
505  }
506  std::vector<std::valarray<T>> C; // Vector to store result
507  for (size_t i = 0; i < A.size(); i++) {
508  C.push_back(A[i] * B[i]); // Elementwise multiplication
509  }
510  return C; // Return new resultant 2D vector
511 }
512 } // namespace machine_learning
513 
514 #endif
T begin(T... args)
T distance(T... args)
T end(T... args)
T endl(T... args)
T exit(T... args)
T make_pair(T... args)
T max_element(T... args)
T max(T... args)
T min(T... args)
Machine learning algorithms.
std::vector< std::vector< std::valarray< T > > > minmax_scaler(const std::vector< std::vector< std::valarray< T >>> &A, const T &low, const T &high)
Definition: vector_ops.hpp:269
size_t argmax(const std::vector< std::valarray< T >> &A)
Definition: vector_ops.hpp:307
std::vector< std::valarray< T > > operator/(const std::vector< std::valarray< T >> &A, const T &val)
Definition: vector_ops.hpp:365
void zeroes_initialization(std::vector< std::valarray< T >> &A, const std::pair< size_t, size_t > &shape)
Definition: vector_ops.hpp:213
std::valarray< T > pop_back(const std::valarray< T > &A)
Definition: vector_ops.hpp:119
T sum(const std::vector< std::valarray< T >> &A)
Definition: vector_ops.hpp:232
std::vector< std::valarray< T > > operator-(const std::vector< std::valarray< T >> &A, const std::vector< std::valarray< T >> &B)
Definition: vector_ops.hpp:433
void equal_shuffle(std::vector< std::vector< std::valarray< T >>> &A, std::vector< std::vector< std::valarray< T >>> &B)
Definition: vector_ops.hpp:136
std::vector< std::valarray< T > > hadamard_product(const std::vector< std::valarray< T >> &A, const std::vector< std::valarray< T >> &B)
Definition: vector_ops.hpp:494
std::valarray< T > insert_element(const std::valarray< T > &A, const T &ele)
Definition: vector_ops.hpp:85
void uniform_random_initialization(std::vector< std::valarray< T >> &A, const std::pair< size_t, size_t > &shape, const T &low, const T &high)
Definition: vector_ops.hpp:166
std::vector< std::valarray< T > > multiply(const std::vector< std::valarray< T >> &A, const std::vector< std::valarray< T >> &B)
Definition: vector_ops.hpp:460
std::vector< std::valarray< T > > apply_function(const std::vector< std::valarray< T >> &A, T(*func)(const T &))
Definition: vector_ops.hpp:329
std::ostream & operator<<(std::ostream &out, std::vector< std::valarray< T >> const &A)
Definition: vector_ops.hpp:32
std::vector< std::valarray< T > > operator+(const std::vector< std::valarray< T >> &A, const std::vector< std::valarray< T >> &B)
Definition: vector_ops.hpp:406
std::vector< std::valarray< T > > operator*(const std::vector< std::valarray< T >> &A, const T &val)
Definition: vector_ops.hpp:347
std::pair< size_t, size_t > get_shape(const std::vector< std::valarray< T >> &A)
Definition: vector_ops.hpp:247
void unit_matrix_initialization(std::vector< std::valarray< T >> &A, const std::pair< size_t, size_t > &shape)
Definition: vector_ops.hpp:193
std::vector< std::valarray< T > > transpose(const std::vector< std::valarray< T >> &A)
Definition: vector_ops.hpp:382
std::valarray< T > pop_front(const std::valarray< T > &A)
Definition: vector_ops.hpp:102
T precision(T... args)
T push_back(T... args)
T rand(T... args)
T size(T... args)
T srand(T... args)
T swap(T... args)