Merge branch 'master' into is_graph_bipartite

This commit is contained in:
Filip Hlásek
2020-08-26 22:09:55 -07:00
5 changed files with 1210 additions and 922 deletions

167
.clang-format Normal file
View File

@@ -0,0 +1,167 @@
---
Language: Cpp
AccessModifierOffset: -3
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: true
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: true
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^<ext/.*\.h>'
Priority: 2
SortPriority: 0
- Regex: '^<.*\.h>'
Priority: 1
SortPriority: 0
- Regex: '^<.*'
Priority: 2
SortPriority: 0
- Regex: '.*'
Priority: 3
SortPriority: 0
IncludeIsMainRegex: '([-_](test|unittest))?$'
IncludeIsMainSourceRegex: ''
IndentCaseLabels: true
IndentGotoLabels: true
IndentPPDirectives: None
IndentWidth: 4
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Never
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
RawStringFormats:
- Language: Cpp
Delimiters:
- cc
- CC
- cpp
- Cpp
- CPP
- 'c++'
- 'C++'
CanonicalDelimiter: ''
BasedOnStyle: google
- Language: TextProto
Delimiters:
- pb
- PB
- proto
- PROTO
EnclosingFunctions:
- EqualsProto
- EquivToProto
- PARSE_PARTIAL_TEXT_PROTO
- PARSE_TEST_PROTO
- PARSE_TEXT_PROTO
- ParseTextOrDie
- ParseTextProtoOrDie
CanonicalDelimiter: ''
BasedOnStyle: google
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
Standard: Auto
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 4
UseCRLF: false
UseTab: Never
...

View File

@@ -16,7 +16,7 @@ jobs:
- name: requirements - name: requirements
run: | run: |
sudo apt -qq -y update sudo apt -qq -y update
sudo apt -qq install clang-tidy-10 sudo apt -qq install clang-tidy-10 clang-format-10
# checks are passing with less errors when used with this version. # checks are passing with less errors when used with this version.
# The default installs v6.0 which did not work out well in my tests # The default installs v6.0 which did not work out well in my tests
- name: Setup Git Specs - name: Setup Git Specs
@@ -44,7 +44,7 @@ jobs:
git "mv" "${fname}" ${new_fname} git "mv" "${fname}" ${new_fname}
fi fi
done done
git commit -am "formatting filenames $GITHUB_SHA" || true git commit -am "formatting filenames ${GITHUB_SHA::8}" || true
- name: Update DIRECTORY.md - name: Update DIRECTORY.md
shell: python shell: python
@@ -124,15 +124,9 @@ jobs:
subprocess.run(["clang-tidy-10", "--fix", "-p=build", "--extra-arg=-std=c++11", *cpp_files, "--"], subprocess.run(["clang-tidy-10", "--fix", "-p=build", "--extra-arg=-std=c++11", *cpp_files, "--"],
check=True, text=True, stderr=subprocess.STDOUT) check=True, text=True, stderr=subprocess.STDOUT)
# for cpp_file in cpp_files:
# subprocess.run(["clang-tidy-10", "--fix", "-p=build", cpp_file, "--"],
# check=True, text=True, stderr=subprocess.STDOUT)
# print("g++:") subprocess.run(["clang-format-10", "-i", "-style=file", *cpp_files],
# compile_exts = tuple(".c .c++ .cc .cpp .cu .cxx".split()) check=True, text=True, stderr=subprocess.STDOUT)
# compile_files = [file for file in cpp_files if file.lower().endswith(compile_exts)]
# for cpp_file in cpp_files:
# subprocess.run(["g++", cpp_file], check=True, text=True)
upper_files = [file for file in cpp_files if file != file.lower()] upper_files = [file for file in cpp_files if file != file.lower()]
if upper_files: if upper_files:
@@ -155,7 +149,7 @@ jobs:
- name: Commit and push changes - name: Commit and push changes
run: | run: |
git diff DIRECTORY.md git diff DIRECTORY.md
git commit -am "clang-tidy fixes for $GITHUB_SHA" || true git commit -am "clang-format and clang-tidy fixes for ${GITHUB_SHA::8}" || true
git push --force origin HEAD:$GITHUB_REF || true git push --force origin HEAD:$GITHUB_REF || true
build: build:

View File

@@ -1,50 +1,103 @@
/**
* @file
* @brief [Eight Queens](https://en.wikipedia.org/wiki/Eight_queens_puzzle)
* puzzle, printing all solutions
*
* @author [Himani Negi](https://github.com/Himani2000)
* @author [David Leal](https://github.com/Panquesito7)
*
*/
#include <iostream> #include <iostream>
#define n 4 #include <array>
void PrintSol(int Board[n][n]) { /**
* @namespace backtracking
* @brief Backtracking algorithms
*/
namespace backtracking {
/**
* @namespace n_queens_all_solutions
* @brief Functions for [Eight
* Queens](https://en.wikipedia.org/wiki/Eight_queens_puzzle) puzzle with all solutions.
*/
namespace n_queens_all_solutions {
/**
* Utility function to print matrix
* @tparam n number of matrix size
* @param board matrix where numbers are saved
*/
template <size_t n>
void PrintSol(const std::array<std::array<int, n>, n>& board) {
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) { for (int j = 0; j < n; j++) {
std::cout << Board[i][j] << " "; std::cout << board[i][j] << " ";
} }
std::cout << std::endl; std::cout << std::endl;
} }
std::cout << std::endl; std::cout << std::endl;
} }
bool CanIMove(int Board[n][n], int row, int col) { /**
* Check if a queen can be placed on matrix
* @tparam n number of matrix size
* @param board matrix where numbers are saved
* @param row current index in rows
* @param col current index in columns
* @returns `true` if queen can be placed on matrix
* @returns `false` if queen can't be placed on matrix
*/
template <size_t n>
bool CanIMove(const std::array<std::array<int, n>, n>& board, int row, int col) {
/// check in the row /// check in the row
for (int i = 0; i < col; i++) { for (int i = 0; i < col; i++) {
if (Board[row][i] == 1) if (board[row][i] == 1) {
return false; return false;
}
} }
/// check the first diagonal /// check the first diagonal
for (int i = row, j = col; i >= 0 && j >= 0; i--, j--) { for (int i = row, j = col; i >= 0 && j >= 0; i--, j--) {
if (Board[i][j] == 1) if (board[i][j] == 1) {
return false; return false;
}
} }
/// check the second diagonal /// check the second diagonal
for (int i = row, j = col; i <= n - 1 && j >= 0; i++, j--) { for (int i = row, j = col; i <= n - 1 && j >= 0; i++, j--) {
if (Board[i][j] == 1) if (board[i][j] == 1) {
return false; return false;
}
} }
return true; return true;
} }
void NQueenSol(int Board[n][n], int col) { /**
* Solve n queens problem
* @tparam n number of matrix size
* @param board matrix where numbers are saved
* @param col current index in columns
*/
template <size_t n>
void NQueenSol(std::array<std::array<int, n>, n> board, int col) {
if (col >= n) { if (col >= n) {
PrintSol(Board); PrintSol(board);
return; return;
} }
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
if (CanIMove(Board, i, col)) { if (CanIMove(board, i, col)) {
Board[i][col] = 1; board[i][col] = 1;
NQueenSol(Board, col + 1); NQueenSol(board, col + 1);
Board[i][col] = 0; board[i][col] = 0;
} }
} }
} }
} // namespace n_queens_all_solutions
} // namespace backtracking
/**
* Main function
*/
int main() { int main() {
int Board[n][n] = {0}; const int n = 4;
NQueenSol(Board, 0); std::array<std::array<int, n>, n> board{0};
backtracking::n_queens_all_solutions::NQueenSol(board, 0);
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,20 +1,21 @@
/** /**
* @file vector_ops.hpp * @file vector_ops.hpp
* @author [Deep Raval](https://github.com/imdeep2905) * @author [Deep Raval](https://github.com/imdeep2905)
* *
* @brief Various functions for vectors associated with [NeuralNetwork (aka Multilayer Perceptron)] * @brief Various functions for vectors associated with [NeuralNetwork (aka
* Multilayer Perceptron)]
* (https://en.wikipedia.org/wiki/Multilayer_perceptron). * (https://en.wikipedia.org/wiki/Multilayer_perceptron).
* *
*/ */
#ifndef VECTOR_OPS_FOR_NN #ifndef VECTOR_OPS_FOR_NN
#define VECTOR_OPS_FOR_NN #define VECTOR_OPS_FOR_NN
#include <iostream>
#include <algorithm> #include <algorithm>
#include <vector>
#include <valarray>
#include <chrono> #include <chrono>
#include <iostream>
#include <random> #include <random>
#include <valarray>
#include <vector>
/** /**
* @namespace machine_learning * @namespace machine_learning
@@ -31,18 +32,18 @@ template <typename T>
std::ostream &operator<<(std::ostream &out, std::ostream &operator<<(std::ostream &out,
std::vector<std::valarray<T>> const &A) { std::vector<std::valarray<T>> const &A) {
// Setting output precision to 4 in case of floating point numbers // Setting output precision to 4 in case of floating point numbers
out.precision(4); out.precision(4);
for(const auto &a : A) { // For each row in A for (const auto &a : A) { // For each row in A
for(const auto &x : a) { // For each element in row for (const auto &x : a) { // For each element in row
std::cerr << x << ' '; // print element std::cout << x << ' '; // print element
} }
std::cerr << std::endl; std::cout << std::endl;
} }
return out; return out;
} }
/** /**
* Overloaded operator "<<" to print a pair * Overloaded operator "<<" to print a pair
* @tparam T typename of the pair * @tparam T typename of the pair
* @param out std::ostream to output * @param out std::ostream to output
* @param A Pair to be printed * @param A Pair to be printed
@@ -52,7 +53,7 @@ std::ostream &operator<<(std::ostream &out, const std::pair<T, T> &A) {
// Setting output precision to 4 in case of floating point numbers // Setting output precision to 4 in case of floating point numbers
out.precision(4); out.precision(4);
// printing pair in the form (p, q) // printing pair in the form (p, q)
std::cerr << "(" << A.first << ", " << A.second << ")"; std::cout << "(" << A.first << ", " << A.second << ")";
return out; return out;
} }
@@ -66,10 +67,10 @@ template <typename T>
std::ostream &operator<<(std::ostream &out, const std::valarray<T> &A) { std::ostream &operator<<(std::ostream &out, const std::valarray<T> &A) {
// Setting output precision to 4 in case of floating point numbers // Setting output precision to 4 in case of floating point numbers
out.precision(4); out.precision(4);
for(const auto &a : A) { // For every element in the vector. for (const auto &a : A) { // For every element in the vector.
std::cerr << a << ' '; // Print element std::cout << a << ' '; // Print element
} }
std::cerr << std::endl; std::cout << std::endl;
return out; return out;
} }
@@ -81,14 +82,14 @@ std::ostream &operator<<(std::ostream &out, const std::valarray<T> &A) {
* @return new resultant vector * @return new resultant vector
*/ */
template <typename T> template <typename T>
std::valarray<T> insert_element(const std::valarray <T> &A, const T &ele) { std::valarray<T> insert_element(const std::valarray<T> &A, const T &ele) {
std::valarray <T> B; // New 1D vector to store resultant vector std::valarray<T> B; // New 1D vector to store resultant vector
B.resize(A.size() + 1); // Resizing it accordingly B.resize(A.size() + 1); // Resizing it accordingly
for(size_t i = 0; i < A.size(); i++) { // For every element in A for (size_t i = 0; i < A.size(); i++) { // For every element in A
B[i] = A[i]; // Copy element in B B[i] = A[i]; // Copy element in B
} }
B[B.size() - 1] = ele; // Inserting new element in last position B[B.size() - 1] = ele; // Inserting new element in last position
return B; // Return resultant vector return B; // Return resultant vector
} }
/** /**
@@ -98,13 +99,14 @@ std::valarray<T> insert_element(const std::valarray <T> &A, const T &ele) {
* @return new resultant vector * @return new resultant vector
*/ */
template <typename T> template <typename T>
std::valarray <T> pop_front(const std::valarray<T> &A) { std::valarray<T> pop_front(const std::valarray<T> &A) {
std::valarray <T> B; // New 1D vector to store resultant vector std::valarray<T> B; // New 1D vector to store resultant vector
B.resize(A.size() - 1); // Resizing it accordingly B.resize(A.size() - 1); // Resizing it accordingly
for(size_t i = 1; i < A.size(); i ++) { // // For every (except first) element in A for (size_t i = 1; i < A.size();
B[i - 1] = A[i]; // Copy element in B with left shifted position i++) { // // For every (except first) element in A
B[i - 1] = A[i]; // Copy element in B with left shifted position
} }
return B; // Return resultant vector return B; // Return resultant vector
} }
/** /**
@@ -114,13 +116,14 @@ std::valarray <T> pop_front(const std::valarray<T> &A) {
* @return new resultant vector * @return new resultant vector
*/ */
template <typename T> template <typename T>
std::valarray <T> pop_back(const std::valarray<T> &A) { std::valarray<T> pop_back(const std::valarray<T> &A) {
std::valarray <T> B; // New 1D vector to store resultant vector std::valarray<T> B; // New 1D vector to store resultant vector
B.resize(A.size() - 1); // Resizing it accordingly B.resize(A.size() - 1); // Resizing it accordingly
for(size_t i = 0; i < A.size() - 1; i ++) { // For every (except last) element in A for (size_t i = 0; i < A.size() - 1;
B[i] = A[i]; // Copy element in B i++) { // For every (except last) element in A
B[i] = A[i]; // Copy element in B
} }
return B; // Return resultant vector return B; // Return resultant vector
} }
/** /**
@@ -130,16 +133,17 @@ std::valarray <T> pop_back(const std::valarray<T> &A) {
* @param B Second 3D vector * @param B Second 3D vector
*/ */
template <typename T> template <typename T>
void equal_shuffle(std::vector < std::vector <std::valarray<T>> > &A, void equal_shuffle(std::vector<std::vector<std::valarray<T>>> &A,
std::vector < std::vector <std::valarray<T>> > &B) { std::vector<std::vector<std::valarray<T>>> &B) {
// If two vectors have different sizes // If two vectors have different sizes
if(A.size() != B.size()) if (A.size() != B.size()) {
{ std::cerr << "ERROR (" << __func__ << ") : ";
std::cerr << "ERROR : Can not equally shuffle two vectors with different sizes: "; std::cerr
<< "Can not equally shuffle two vectors with different sizes: ";
std::cerr << A.size() << " and " << B.size() << std::endl; std::cerr << A.size() << " and " << B.size() << std::endl;
std::exit(EXIT_FAILURE); std::exit(EXIT_FAILURE);
} }
for(size_t i = 0; i < A.size(); i++) { // For every element in A and B for (size_t i = 0; i < A.size(); i++) { // For every element in A and B
// Genrating random index < size of A and B // Genrating random index < size of A and B
std::srand(std::chrono::system_clock::now().time_since_epoch().count()); std::srand(std::chrono::system_clock::now().time_since_epoch().count());
size_t random_index = std::rand() % A.size(); size_t random_index = std::rand() % A.size();
@@ -159,26 +163,26 @@ void equal_shuffle(std::vector < std::vector <std::valarray<T>> > &A,
* @param high upper limit on value * @param high upper limit on value
*/ */
template <typename T> template <typename T>
void uniform_random_initialization(std::vector<std::valarray<T>> &A, void uniform_random_initialization(std::vector<std::valarray<T>> &A,
const std::pair<size_t, size_t> &shape, const std::pair<size_t, size_t> &shape,
const T &low, const T &low, const T &high) {
const T &high) { A.clear(); // Making A empty
A.clear(); // Making A empty
// Uniform distribution in range [low, high] // Uniform distribution in range [low, high]
std::default_random_engine generator(std::chrono::system_clock::now().time_since_epoch().count()); std::default_random_engine generator(
std::uniform_real_distribution <T> distribution(low, high); std::chrono::system_clock::now().time_since_epoch().count());
for(size_t i = 0; i < shape.first; i++) { // For every row std::uniform_real_distribution<T> distribution(low, high);
std::valarray <T> row; // Making empty row which will be inserted in vector for (size_t i = 0; i < shape.first; i++) { // For every row
std::valarray<T>
row; // Making empty row which will be inserted in vector
row.resize(shape.second); row.resize(shape.second);
for(auto &r : row) { // For every element in row for (auto &r : row) { // For every element in row
r = distribution(generator); // copy random number r = distribution(generator); // copy random number
} }
A.push_back(row); // Insert new row in vector A.push_back(row); // Insert new row in vector
} }
return; return;
} }
/** /**
* Function to Intialize 2D vector as unit matrix * Function to Intialize 2D vector as unit matrix
* @tparam T typename of the vector * @tparam T typename of the vector
@@ -186,15 +190,15 @@ void uniform_random_initialization(std::vector<std::valarray<T>> &A,
* @param shape required shape * @param shape required shape
*/ */
template <typename T> template <typename T>
void unit_matrix_initialization(std::vector<std::valarray<T>> &A, void unit_matrix_initialization(std::vector<std::valarray<T>> &A,
const std::pair<size_t, size_t> &shape const std::pair<size_t, size_t> &shape) {
) { A.clear(); // Making A empty
A.clear(); // Making A empty for (size_t i = 0; i < shape.first; i++) {
for(size_t i = 0; i < shape.first; i++) { std::valarray<T>
std::valarray <T> row; // Making empty row which will be inserted in vector row; // Making empty row which will be inserted in vector
row.resize(shape.second); row.resize(shape.second);
row[i] = T(1); // Insert 1 at ith position row[i] = T(1); // Insert 1 at ith position
A.push_back(row); // Insert new row in vector A.push_back(row); // Insert new row in vector
} }
return; return;
} }
@@ -206,14 +210,14 @@ void unit_matrix_initialization(std::vector<std::valarray<T>> &A,
* @param shape required shape * @param shape required shape
*/ */
template <typename T> template <typename T>
void zeroes_initialization(std::vector<std::valarray<T>> &A, void zeroes_initialization(std::vector<std::valarray<T>> &A,
const std::pair<size_t, size_t> &shape const std::pair<size_t, size_t> &shape) {
) { A.clear(); // Making A empty
A.clear(); // Making A empty for (size_t i = 0; i < shape.first; i++) {
for(size_t i = 0; i < shape.first; i++) { std::valarray<T>
std::valarray <T> row; // Making empty row which will be inserted in vector row; // Making empty row which will be inserted in vector
row.resize(shape.second); // By default all elements are zero row.resize(shape.second); // By default all elements are zero
A.push_back(row); // Insert new row in vector A.push_back(row); // Insert new row in vector
} }
return; return;
} }
@@ -226,11 +230,11 @@ void zeroes_initialization(std::vector<std::valarray<T>> &A,
*/ */
template <typename T> template <typename T>
T sum(const std::vector<std::valarray<T>> &A) { T sum(const std::vector<std::valarray<T>> &A) {
T cur_sum = 0; // Initially sum is zero T cur_sum = 0; // Initially sum is zero
for(const auto &a : A) { // For every row in A for (const auto &a : A) { // For every row in A
cur_sum += a.sum(); // Add sum of that row to current sum cur_sum += a.sum(); // Add sum of that row to current sum
} }
return cur_sum; // Return sum return cur_sum; // Return sum
} }
/** /**
@@ -242,52 +246,59 @@ T sum(const std::vector<std::valarray<T>> &A) {
template <typename T> template <typename T>
std::pair<size_t, size_t> get_shape(const std::vector<std::valarray<T>> &A) { std::pair<size_t, size_t> get_shape(const std::vector<std::valarray<T>> &A) {
const size_t sub_size = (*A.begin()).size(); const size_t sub_size = (*A.begin()).size();
for(const auto &a : A) { for (const auto &a : A) {
// If supplied vector don't have same shape in all rows // If supplied vector don't have same shape in all rows
if(a.size() != sub_size) { if (a.size() != sub_size) {
std::cerr << "ERROR: (get_shape) Supplied vector is not 2D Matrix" << std::endl; std::cerr << "ERROR (" << __func__ << ") : ";
std::cerr << "Supplied vector is not 2D Matrix" << std::endl;
std::exit(EXIT_FAILURE); std::exit(EXIT_FAILURE);
} }
} }
return std::make_pair(A.size(), sub_size); // Return shape as pair return std::make_pair(A.size(), sub_size); // Return shape as pair
} }
/** /**
* Function to scale given 3D vector using min-max scaler * Function to scale given 3D vector using min-max scaler
* @tparam T typename of the vector * @tparam T typename of the vector
* @param A 3D vector which will be scaled * @param A 3D vector which will be scaled
* @param low new minimum value * @param low new minimum value
* @param high new maximum value * @param high new maximum value
* @return new scaled 3D vector * @return new scaled 3D vector
*/ */
template <typename T> template <typename T>
std::vector<std::vector<std::valarray<T>>> std::vector<std::vector<std::valarray<T>>> minmax_scaler(
minmax_scaler(const std::vector<std::vector<std::valarray<T>>> &A, const T &low, const T &high) { const std::vector<std::vector<std::valarray<T>>> &A, const T &low,
std::vector<std::vector<std::valarray<T>>> B = A; // Copying into new vector B const T &high) {
const auto shape = get_shape(B[0]); // Storing shape of B's every element std::vector<std::vector<std::valarray<T>>> B =
// As this function is used for scaling training data vector should be of shape (1, X) A; // Copying into new vector B
if(shape.first != 1) { const auto shape = get_shape(B[0]); // Storing shape of B's every element
std::cerr << "ERROR: (MinMax Scaling) Supplied vector is not supported for minmax scaling, shape: "; // As this function is used for scaling training data vector should be of
// shape (1, X)
if (shape.first != 1) {
std::cerr << "ERROR (" << __func__ << ") : ";
std::cerr
<< "Supplied vector is not supported for minmax scaling, shape: ";
std::cerr << shape << std::endl; std::cerr << shape << std::endl;
std::exit(EXIT_FAILURE); std::exit(EXIT_FAILURE);
} }
for(size_t i = 0; i < shape.second; i++) { for (size_t i = 0; i < shape.second; i++) {
T min = B[0][0][i], max = B[0][0][i]; T min = B[0][0][i], max = B[0][0][i];
for(size_t j = 0; j < B.size(); j++) { for (size_t j = 0; j < B.size(); j++) {
// Updating minimum and maximum values // Updating minimum and maximum values
min = std::min(min, B[j][0][i]); min = std::min(min, B[j][0][i]);
max = std::max(max, B[j][0][i]); max = std::max(max, B[j][0][i]);
} }
for(size_t j = 0; j < B.size(); j++) { for (size_t j = 0; j < B.size(); j++) {
// Applying min-max scaler formula // Applying min-max scaler formula
B[j][0][i] = ((B[j][0][i] - min) / (max - min)) * (high - low) + low; B[j][0][i] =
((B[j][0][i] - min) / (max - min)) * (high - low) + low;
} }
} }
return B; // Return new resultant 3D vector return B; // Return new resultant 3D vector
} }
/** /**
* Function to get index of maximum element in 2D vector * Function to get index of maximum element in 2D vector
* @tparam T typename of the vector * @tparam T typename of the vector
* @param A 2D vector for which maximum index is required * @param A 2D vector for which maximum index is required
* @return index of maximum element * @return index of maximum element
@@ -295,13 +306,16 @@ minmax_scaler(const std::vector<std::vector<std::valarray<T>>> &A, const T &low,
template <typename T> template <typename T>
size_t argmax(const std::vector<std::valarray<T>> &A) { size_t argmax(const std::vector<std::valarray<T>> &A) {
const auto shape = get_shape(A); const auto shape = get_shape(A);
// As this function is used on predicted (or target) vector, shape should be (1, X) // As this function is used on predicted (or target) vector, shape should be
if(shape.first != 1) { // (1, X)
std::cerr << "ERROR: (argmax) Supplied vector is ineligible for argmax" << std::endl; if (shape.first != 1) {
std::exit(EXIT_FAILURE); std::cerr << "ERROR (" << __func__ << ") : ";
std::cerr << "Supplied vector is ineligible for argmax" << std::endl;
std::exit(EXIT_FAILURE);
} }
// Return distance of max element from first element (i.e. index) // Return distance of max element from first element (i.e. index)
return std::distance(std::begin(A[0]), std::max_element(std::begin(A[0]), std::end(A[0]))); return std::distance(std::begin(A[0]),
std::max_element(std::begin(A[0]), std::end(A[0])));
} }
/** /**
@@ -311,46 +325,51 @@ size_t argmax(const std::vector<std::valarray<T>> &A) {
* @param func Function to be applied * @param func Function to be applied
* @return new resultant vector * @return new resultant vector
*/ */
template <typename T> template <typename T>
std::vector <std::valarray <T>> apply_function(const std::vector <std::valarray <T>> &A, std::vector<std::valarray<T>> apply_function(
T (*func) (const T &)) { const std::vector<std::valarray<T>> &A, T (*func)(const T &)) {
std::vector<std::valarray<double>> B = A; // New vector to store resultant vector std::vector<std::valarray<double>> B =
for(auto &b : B) { // For every row in vector A; // New vector to store resultant vector
b = b.apply(func); // Apply function to that row for (auto &b : B) { // For every row in vector
b = b.apply(func); // Apply function to that row
} }
return B; // Return new resultant 2D vector return B; // Return new resultant 2D vector
} }
/** /**
* Overloaded operator "*" to multiply given 2D vector with scaler * Overloaded operator "*" to multiply given 2D vector with scaler
* @tparam T typename of both vector and the scaler * @tparam T typename of both vector and the scaler
* @param A 2D vector to which scaler will be multiplied * @param A 2D vector to which scaler will be multiplied
* @param val Scaler value which will be multiplied * @param val Scaler value which will be multiplied
* @return new resultant vector * @return new resultant vector
*/ */
template <typename T> template <typename T>
std::vector <std::valarray <T> > operator * (const std::vector<std::valarray<T>> &A, const T& val) { std::vector<std::valarray<T>> operator*(const std::vector<std::valarray<T>> &A,
std::vector<std::valarray<double>> B = A; // New vector to store resultant vector const T &val) {
for(auto &b : B) { // For every row in vector std::vector<std::valarray<double>> B =
b = b * val; // Multiply row with scaler A; // New vector to store resultant vector
for (auto &b : B) { // For every row in vector
b = b * val; // Multiply row with scaler
} }
return B; // Return new resultant 2D vector return B; // Return new resultant 2D vector
} }
/** /**
* Overloaded operator "/" to divide given 2D vector with scaler * Overloaded operator "/" to divide given 2D vector with scaler
* @tparam T typename of the vector and the scaler * @tparam T typename of the vector and the scaler
* @param A 2D vector to which scaler will be divided * @param A 2D vector to which scaler will be divided
* @param val Scaler value which will be divided * @param val Scaler value which will be divided
* @return new resultant vector * @return new resultant vector
*/ */
template <typename T> template <typename T>
std::vector <std::valarray <T> > operator / (const std::vector<std::valarray<T>> &A, const T& val) { std::vector<std::valarray<T>> operator/(const std::vector<std::valarray<T>> &A,
std::vector<std::valarray<double>> B = A; // New vector to store resultant vector const T &val) {
for(auto &b : B) { // For every row in vector std::vector<std::valarray<double>> B =
b = b / val; // Divide row with scaler A; // New vector to store resultant vector
for (auto &b : B) { // For every row in vector
b = b / val; // Divide row with scaler
} }
return B; // Return new resultant 2D vector return B; // Return new resultant 2D vector
} }
/** /**
@@ -360,125 +379,136 @@ std::vector <std::valarray <T> > operator / (const std::vector<std::valarray<T>>
* @return new resultant vector * @return new resultant vector
*/ */
template <typename T> template <typename T>
std::vector <std::valarray <T>> transpose(const std::vector<std::valarray<T>> &A) { std::vector<std::valarray<T>> transpose(
const auto shape = get_shape(A); // Current shape of vector const std::vector<std::valarray<T>> &A) {
std::vector <std::valarray <T> > B; // New vector to store result const auto shape = get_shape(A); // Current shape of vector
std::vector<std::valarray<T>> B; // New vector to store result
// Storing transpose values of A in B // Storing transpose values of A in B
for(size_t j = 0; j < shape.second; j++) { for (size_t j = 0; j < shape.second; j++) {
std::valarray <T> row; std::valarray<T> row;
row.resize(shape.first); row.resize(shape.first);
for(size_t i = 0; i < shape.first; i++) { for (size_t i = 0; i < shape.first; i++) {
row[i] = A[i][j]; row[i] = A[i][j];
} }
B.push_back(row); B.push_back(row);
} }
return B; // Return new resultant 2D vector return B; // Return new resultant 2D vector
} }
/** /**
* Overloaded operator "+" to add two 2D vectors * Overloaded operator "+" to add two 2D vectors
* @tparam T typename of the vector * @tparam T typename of the vector
* @param A First 2D vector * @param A First 2D vector
* @param B Second 2D vector * @param B Second 2D vector
* @return new resultant vector * @return new resultant vector
*/ */
template <typename T> template <typename T>
std::vector <std::valarray <T> > operator + (const std::vector<std::valarray<T>> &A, const std::vector<std::valarray<T>> &B) { std::vector<std::valarray<T>> operator+(
const std::vector<std::valarray<T>> &A,
const std::vector<std::valarray<T>> &B) {
const auto shape_a = get_shape(A); const auto shape_a = get_shape(A);
const auto shape_b = get_shape(B); const auto shape_b = get_shape(B);
// If vectors don't have equal shape // If vectors don't have equal shape
if(shape_a.first != shape_b.first || shape_a.second != shape_b.second) { if (shape_a.first != shape_b.first || shape_a.second != shape_b.second) {
std::cerr << "ERROR: (vector addition) Supplied vectors have different shapes "; std::cerr << "ERROR (" << __func__ << ") : ";
std::cerr << "Supplied vectors have different shapes ";
std::cerr << shape_a << " and " << shape_b << std::endl; std::cerr << shape_a << " and " << shape_b << std::endl;
std::exit(EXIT_FAILURE); std::exit(EXIT_FAILURE);
} }
std::vector<std::valarray <T>> C; std::vector<std::valarray<T>> C;
for(size_t i = 0; i < A.size(); i++) { // For every row for (size_t i = 0; i < A.size(); i++) { // For every row
C.push_back(A[i] + B[i]); // Elementwise addition C.push_back(A[i] + B[i]); // Elementwise addition
} }
return C; // Return new resultant 2D vector return C; // Return new resultant 2D vector
} }
/** /**
* Overloaded operator "-" to add subtract 2D vectors * Overloaded operator "-" to add subtract 2D vectors
* @tparam T typename of the vector * @tparam T typename of the vector
* @param A First 2D vector * @param A First 2D vector
* @param B Second 2D vector * @param B Second 2D vector
* @return new resultant vector * @return new resultant vector
*/ */
template <typename T> template <typename T>
std::vector <std::valarray <T>> operator - (const std::vector<std::valarray<T>> &A, const std::vector<std::valarray<T>> &B) { std::vector<std::valarray<T>> operator-(
const std::vector<std::valarray<T>> &A,
const std::vector<std::valarray<T>> &B) {
const auto shape_a = get_shape(A); const auto shape_a = get_shape(A);
const auto shape_b = get_shape(B); const auto shape_b = get_shape(B);
// If vectors don't have equal shape // If vectors don't have equal shape
if(shape_a.first != shape_b.first || shape_a.second != shape_b.second) { if (shape_a.first != shape_b.first || shape_a.second != shape_b.second) {
std::cerr << "ERROR: (vector subtraction) Supplied vectors have different shapes "; std::cerr << "ERROR (" << __func__ << ") : ";
std::cerr << "Supplied vectors have different shapes ";
std::cerr << shape_a << " and " << shape_b << std::endl; std::cerr << shape_a << " and " << shape_b << std::endl;
std::exit(EXIT_FAILURE); std::exit(EXIT_FAILURE);
} }
std::vector<std::valarray<T>> C; // Vector to store result std::vector<std::valarray<T>> C; // Vector to store result
for(size_t i = 0; i < A.size(); i++) { // For every row for (size_t i = 0; i < A.size(); i++) { // For every row
C.push_back(A[i] - B[i]); // Elementwise substraction C.push_back(A[i] - B[i]); // Elementwise substraction
} }
return C; // Return new resultant 2D vector return C; // Return new resultant 2D vector
} }
/** /**
* Function to multiply two 2D vectors * Function to multiply two 2D vectors
* @tparam T typename of the vector * @tparam T typename of the vector
* @param A First 2D vector * @param A First 2D vector
* @param B Second 2D vector * @param B Second 2D vector
* @return new resultant vector * @return new resultant vector
*/ */
template <typename T> template <typename T>
std::vector <std::valarray <T>> multiply(const std::vector<std::valarray<T>> &A, const std::vector<std::valarray<T>> &B) { std::vector<std::valarray<T>> multiply(const std::vector<std::valarray<T>> &A,
const std::vector<std::valarray<T>> &B) {
const auto shape_a = get_shape(A); const auto shape_a = get_shape(A);
const auto shape_b = get_shape(B); const auto shape_b = get_shape(B);
// If vectors are not eligible for multiplication // If vectors are not eligible for multiplication
if(shape_a.second != shape_b.first ) { if (shape_a.second != shape_b.first) {
std::cerr << "ERROR: (multiply) Supplied vectors are not eligible for multiplication "; std::cerr << "ERROR (" << __func__ << ") : ";
std::cerr << "Vectors are not eligible for multiplication ";
std::cerr << shape_a << " and " << shape_b << std::endl; std::cerr << shape_a << " and " << shape_b << std::endl;
std::exit(EXIT_FAILURE); std::exit(EXIT_FAILURE);
} }
std::vector<std::valarray<T>> C; // Vector to store result std::vector<std::valarray<T>> C; // Vector to store result
// Normal matrix multiplication // Normal matrix multiplication
for (size_t i = 0; i < shape_a.first; i++) { for (size_t i = 0; i < shape_a.first; i++) {
std::valarray<T> row; std::valarray<T> row;
row.resize(shape_b.second); row.resize(shape_b.second);
for(size_t j = 0; j < shape_b.second; j++) { for (size_t j = 0; j < shape_b.second; j++) {
for(size_t k = 0; k < shape_a.second; k++) { for (size_t k = 0; k < shape_a.second; k++) {
row[j] += A[i][k] * B[k][j]; row[j] += A[i][k] * B[k][j];
} }
} }
C.push_back(row); C.push_back(row);
} }
return C; // Return new resultant 2D vector return C; // Return new resultant 2D vector
} }
/** /**
* Function to get hadamard product of two 2D vectors * Function to get hadamard product of two 2D vectors
* @tparam T typename of the vector * @tparam T typename of the vector
* @param A First 2D vector * @param A First 2D vector
* @param B Second 2D vector * @param B Second 2D vector
* @return new resultant vector * @return new resultant vector
*/ */
template <typename T> template <typename T>
std::vector <std::valarray <T>> hadamard_product(const std::vector<std::valarray<T>> &A, const std::vector<std::valarray<T>> &B) { std::vector<std::valarray<T>> hadamard_product(
const std::vector<std::valarray<T>> &A,
const std::vector<std::valarray<T>> &B) {
const auto shape_a = get_shape(A); const auto shape_a = get_shape(A);
const auto shape_b = get_shape(B); const auto shape_b = get_shape(B);
// If vectors are not eligible for hadamard product // If vectors are not eligible for hadamard product
if(shape_a.first != shape_b.first || shape_a.second != shape_b.second) { if (shape_a.first != shape_b.first || shape_a.second != shape_b.second) {
std::cerr << "ERROR: (hadamard_product) Supplied vectors have different shapes "; std::cerr << "ERROR (" << __func__ << ") : ";
std::cerr << "Vectors have different shapes ";
std::cerr << shape_a << " and " << shape_b << std::endl; std::cerr << shape_a << " and " << shape_b << std::endl;
std::exit(EXIT_FAILURE); std::exit(EXIT_FAILURE);
} }
std::vector<std::valarray<T>> C; // Vector to store result std::vector<std::valarray<T>> C; // Vector to store result
for(size_t i = 0; i < A.size(); i++) { for (size_t i = 0; i < A.size(); i++) {
C.push_back(A[i] * B[i]); // Elementwise multiplication C.push_back(A[i] * B[i]); // Elementwise multiplication
} }
return C; // Return new resultant 2D vector return C; // Return new resultant 2D vector
} }
} // namespace machine_learning } // namespace machine_learning
#endif #endif