C++ - Calculating the inverse of a matrix - c++

I've tried to write a program that should be able to calculate the inverse of a matrix:
Here's what I have so far:
#include <iostream>
#include <vector>
#include <math.h>
#include <iomanip>
#include <stdexcept>
double getDeterminant(const std::vector<std::vector<double>> vect) {
if(vect.size() != vect[0].size()) {
throw std::runtime_error("Matrix is not quadratic");
}
int dimension = vect.size();
if(dimension == 0) {
return 1;
}
if(dimension == 1) {
return vect[0][0];
}
//Formula for 2x2-matrix
if(dimension == 2) {
return vect[0][0] * vect[1][1] - vect[0][1] * vect[1][0];
}
double result = 0;
int sign = 1;
for(int i = 0; i < dimension; i++) {
//Submatrix
std::vector<std::vector<double>> subVect(dimension - 1, std::vector<double> (dimension - 1));
for(int m = 1; m < dimension; m++) {
int z = 0;
for(int n = 0; n < dimension; n++) {
if(n != i) {
subVect[m-1][z] = vect[m][n];
z++;
}
}
}
//recursive call
result = result + sign * vect[0][i] * getDeterminant(subVect);
sign = -sign;
}
return result;
}
std::vector<std::vector<double>> getTranspose(const std::vector<std::vector<double>> matrix1) {
//Transpose-matrix: height = width(matrix), width = height(matrix)
std::vector<std::vector<double>> solution(matrix1[0].size(), std::vector<double> (matrix1.size()));
//Filling solution-matrix
for(size_t i = 0; i < matrix1.size(); i++) {
for(size_t j = 0; j < matrix1[0].size(); j++) {
solution[j][i] = matrix1[i][j];
}
}
return solution;
}
std::vector<std::vector<double>> getCofactor(const std::vector<std::vector<double>> vect) {
if(vect.size() != vect[0].size()) {
throw std::runtime_error("Matrix is not quadratic");
}
std::vector<std::vector<double>> solution(vect.size(), std::vector<double> (vect.size()));
std::vector<std::vector<double>> subVect(vect.size() - 1, std::vector<double> (vect.size() - 1));
for(std::size_t i = 0; i < vect.size(); i++) {
for(std::size_t j = 0; j < vect[0].size(); j++) {
int p = 0;
for(size_t x = 0; x < vect.size(); x++) {
if(x == i) {
continue;
}
int q = 0;
for(size_t y = 0; y < vect.size(); y++) {
if(y == j) {
continue;
}
subVect[p][q] = vect[x][y];
q++;
}
p++;
}
solution[i][j] = pow(-1, i + j) * getDeterminant(subVect);
}
}
return solution;
}
std::vector<std::vector<double>> getInverse(const std::vector<std::vector<double>> vect) {
if(getDeterminant(vect) == 0) {
throw std::runtime_error("Determinant is 0");
}
double d = 1.0/getDeterminant(vect);
std::vector<std::vector<double>> solution(vect.size(), std::vector<double> (vect.size()));
for(size_t i = 0; i < vect.size(); i++) {
for(size_t j = 0; j < vect.size(); j++) {
solution[i][j] = vect[i][j] * d;
}
}
return getTranspose(getCofactor(solution));
}
void printMatrix(const std::vector<std::vector<double>> vect) {
for(std::size_t i = 0; i < vect.size(); i++) {
for(std::size_t j = 0; j < vect[0].size(); j++) {
std::cout << std::setw(8) << vect[i][j] << " ";
}
std::cout << "\n";
}
}
int main() {
std::vector<std::vector<double>> matrix(3, std::vector<double> (3));
matrix = {
{1,2,3},
{4,5,6},
{7,8,8}
};
printMatrix(getInverse(matrix));
return 0;
}
The functions for calculating the determinant, the transpose- and the cofactor-matrix work correctly (as far as I can see), but the function for calculating the inverse-matrix doesn't.
I searched the internet and found this, which uses the same function for calculating the inverse.
Is this formula incorrect, or do you have any other idea, why it doesnt work?
The matrix I am using is
and the inverse of it should be

First of all, thanks for your comments.
The problem was the order of execution.
The correct solution is:
std::vector<std::vector<double>> getInverse(const std::vector<std::vector<double>> vect) {
if(getDeterminant(vect) == 0) {
throw std::runtime_error("Determinant is 0");
}
double d = 1.0/getDeterminant(vect);
std::vector<std::vector<double>> solution(vect.size(), std::vector<double> (vect.size()));
for(size_t i = 0; i < vect.size(); i++) {
for(size_t j = 0; j < vect.size(); j++) {
solution[i][j] = vect[i][j];
}
}
solution = getTranspose(getCofactor(solution));
for(size_t i = 0; i < vect.size(); i++) {
for(size_t j = 0; j < vect.size(); j++) {
solution[i][j] *= d;
}
}
return solution;
}

I know this is an old question but your code does not work when the input matrix's dimension is 1. Here is a workaround that I used:
vector<vector<double>> inverse(const vector<vector<double>> A) {
double d = 1.0/det(A);
vector<vector<double>> solution(A.size(), vector<double> (A.size()));
if(A.size() == 1){
vector<double> ans = {0};
ans[0] = 1.0/det(A);
solution[0] = ans;
return solution;
}
for(size_t i = 0; i < A.size(); i++) {
for(size_t j = 0; j < A.size(); j++) {
solution[i][j] = A[i][j] * d;
}
}
return transpose(cofactor(solution));
}

Related

Matrix multipication is very slow C++

I dont know why but my matrix multipication is very slow and I need to optimize it. and also the print of the matrix (1000X1000) taking long time.
The aim of the function is to calculate the matrix exponential, but my main problem is that this 2 actions are very slow for large matrices like 1000X1000.
These 2 actions implemented at poweMat() function and printeResult() function.
Here is the code:
#define M 1000
#define e 2.71828182845904523536;
//declaration of the functions
void sumMatrices(vector<vector<double> >& mat1, vector<vector<double> >& mat2);
void printResult(vector<vector<double> >&matRes);
void mulMatWithFactorial(long factorialValue);
long factorialCalculate(int n);
void initializeMatrix();
void initializeIdenticalMatrix();
void checkIfTheMatrixIsDiagonal();
void calculateExpoMatrixWithDiagonalMatrix();
void readMatrixFromFile();
void powerMat(vector<vector<double> >& mat, int powNum);
//declaration of the variables
vector<vector<double>> inputMatrix(M, vector<double>(M));
vector<vector<double>> sumMatrixResult(M, vector<double>(M));
vector<vector<double>> powerMatrixResult(M, vector<double>(M));
vector<vector<double>> mulFactorialMatrixResult(M, vector<double>(M));
vector<vector<double>> finalMatrixResult(M, vector<double>(M));
vector<vector<double>> identicalMatrix(M, vector<double>(M));
vector<vector<vector<double>>> listOfMatrices;
bool matrixIsNilpotent = false;
int diagonaMatrixlFlag = 1;
int main() {
//variables
long factorialValue;
initializeIdenticalMatrix();
readMatrixFromFile();
//check if the matrix is diagonal - so we will have easier and faster compute
checkIfTheMatrixIsDiagonal();
if (diagonaMatrixlFlag == 1) {
calculateExpoMatrixWithDiagonalMatrix();
goto endOfLoop;
}
//loop for taylor series
for (int i = 0; i < 5; i++) {
if (i == 0) { // first we add identical matrix when the power is 0
sumMatrices(finalMatrixResult, identicalMatrix); // summarize between this 2 matrices
finalMatrixResult = sumMatrixResult; //copy matrices
}
if (i == 1) { // we add the matrix itself because the power is 1
sumMatrices(finalMatrixResult, inputMatrix);
finalMatrixResult = sumMatrixResult; //copy matrices
}
if (i > 1 ) {
powerMat(inputMatrix, i);
if (matrixIsNilpotent) { // it means that A^i is 0 for some integer, so the series terminates after a finite number
goto endOfLoop;
}
factorialValue = factorialCalculate(i); // calculate the factorial of i
mulMatWithFactorial(factorialValue); // multiply (1/i) * matrix^i - like in the algorithm
sumMatrices(finalMatrixResult, mulFactorialMatrixResult); // summarize it with the previous result
finalMatrixResult = sumMatrixResult; //copy matrices
}
}
endOfLoop:
printResult(finalMatrixResult); // print the final result - e^M
return 0;
}
//Summarize matrices
void sumMatrices(vector<vector<double> >& mat1, vector<vector<double> >& mat2) {
for (int i = 0; i < M; i++)
for (int j = 0; j < M; j++)
sumMatrixResult[i][j] = mat1[i][j] + mat2[i][j];
}
//Print matrix
void printResult(vector<vector<double> >& matRes) {
for (int i = 0; i < M; i++) {
for (int j = 0; j < M; j++) {
printf("%f ", matRes[i][j]);
if (j == M - 1) {
printf("\n");
}
}
}
}
//Calculate the factorial of n
long factorialCalculate(int n) {
long factorial = 1.0;
for (int i = 1; i <= n; ++i) {
factorial *= i;
}
return factorial;
}
// mutiply the matrix with scalar
void mulMatWithFactorial(long factorialValue) {
for (int i = 0; i < M; i++) {
for (int j = 0; j < M; j++) {
mulFactorialMatrixResult[i][j] = powerMatrixResult[i][j] * 1/factorialValue;
}
}
}
//initialize matrix
void initializeMatrix() {
for (int i = 0; i < M; i++) {
for (int j = 0; j < M; j++) {
powerMatrixResult[i][j] = 0;
}
}
}
void checkIfTheMatrixIsDiagonal() {
for (int i = 0; i < M; i++) {
for (int j = 0; j < M; j++) {
if (i == j)
{
if (inputMatrix[i][j] == 0) {
diagonaMatrixlFlag = 0;
goto endOfLoop;
}
}
else
{
if (inputMatrix[i][j] != 0) {
diagonaMatrixlFlag = 0;
goto endOfLoop;
}
}
}
}
endOfLoop:
return;
}
void calculateExpoMatrixWithDiagonalMatrix() {
for (int i = 0; i < M; i++) {
for (int j = 0; j < M; j++) {
if (i == j)
{
for (int k = 0; k < inputMatrix[i][j]; ++k)// loop to calculate the pow of e^alpha
{
finalMatrixResult[i][j] *= e;
}
}
else
{
finalMatrixResult[i][j] = 0;
}
}
}
}
void readMatrixFromFile() {
ifstream f("inv_matrix(1000x1000).txt");
for (int i = 0; i < M; i++)
for (int j = 0; j < M; j++) {
f >> inputMatrix[i][j];
if (f.peek() == ',')
f.ignore();
}
listOfMatrices.push_back(inputMatrix);
}
void initializeIdenticalMatrix() {
for (int i = 0; i < M; i++) {
for (int k = 0; k < M; k++) {
if (i == k) {
identicalMatrix[i][k] = 1;
}
else {
identicalMatrix[i][k] = 0;
}
}
}
}
void powerMat(vector<vector<double> >& mat, int powNum) {
int counterForNilpotent = 0;
initializeMatrix();
auto start = high_resolution_clock::now();
for (int i = 0; i < M; i++) {
for (int k = 0; k < M; k++) {
for (int j = 0; j < M; j++) {
powerMatrixResult[i][j] += mat[i][k] * listOfMatrices[powNum-2][k][j];
}
}
}
auto stop = high_resolution_clock::now();
auto duration = duration_cast<seconds>(stop - start);
cout << duration.count() << " seconds" << endl; // checking run time
listOfMatrices.push_back(powerMatrixResult);
// check if after we we did A^i , the matrix is equal to 0
for (int i = 0; i < M; i++) {
for (int j = 0; j < M; j++) {
if (powerMatrixResult[i][j] == 0) {
counterForNilpotent++;
}
}
}
if (counterForNilpotent == M * M) {
matrixIsNilpotent = true;
}
}
Going through each element of an array of size "n" will have some computational efficiency of O(n^2), meaning for large arrays it will take a while but won't be "life-time-of-the-universe" lengths of time.
Usually to do operations on massive arrays like this, they're reduced in some form first so that the computation can be closer to O(n) or better using some truths about reduced forms of matrices.
So, a faster implementation for matrix multiplication would start with some rref() function upon both matrices and then only evaluating parts of those matrices that would have objects in the columns and rows.
Here are some great places to review/learn (for free) Linear Algebra:
"3b1b (2016): Essence of Linear Algebra" = https://www.youtube.com/watch?v=kjBOesZCoqc&list=PL0-GT3co4r2y2YErbmuJw2L5tW4Ew2O5B
"MIT OpenCourseWare (2009): Linear Algebra" = https://www.youtube.com/watch?v=ZK3O402wf1c&list=PL49CF3715CB9EF31D&index=1
Use SSE2. It’s not a library. It’s a method to use cpu vector hardware.
You set up operations to run in parallel.
https://en.wikipedia.org/wiki/SSE2

Codewars UndefinedBehaviorSanitizer:DEADLYSIGNAL

When I use this code in Visual Studio, it works normally, but when I paste it to Codewars, this error appears. What did I suppose to do? Also, is the output function are valid?
This code for Skyscrapers 4x4 kata from codewars https://www.codewars.com/kata/5671d975d81d6c1c87000022/train/cpp
Also can change it to 6x6 (and any other size) easily.
STDERR
UndefinedBehaviorSanitizer:DEADLYSIGNAL
==1==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0x0000ffffffff (pc 0x0000004254dd bp 0x000000000000 sp 0x7fff88975810 T1)
==1==The signal is caused by a WRITE memory access.
==1==WARNING: invalid path to external symbolizer!
==1==WARNING: Failed to use and restart external symbolizer!
#0 0x4254dc (/workspace/test+0x4254dc)
#1 0x42cf0a (/workspace/test+0x42cf0a)
#2 0x42b79e (/workspace/test+0x42b79e)
#3 0x42b31f (/workspace/test+0x42b31f)
#4 0x42af7b (/workspace/test+0x42af7b)
#5 0x42f2f5 (/workspace/test+0x42f2f5)
#6 0x42566d (/workspace/test+0x42566d)
#7 0x7f929bdf5bf6 (/lib/x86_64-linux-gnu/libc.so.6+0x21bf6)
#8 0x404249 (/workspace/test+0x404249)
UndefinedBehaviorSanitizer can not provide additional info.
==1==ABORTING
Code:
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
#include <iterator>
#include <string>
using namespace std;
void print(vector<int> array) {
for (unsigned int i = 0; i < array.size(); i++) cout << array[i] << " ";
}
int check_visible(vector<int> row) {
int visible = 0, current_height = 0;
for (unsigned int i = 0; i < row.size(); i++) {
if (row[i] > current_height) {
current_height = row[i];
visible++;
}
}
return visible;
}
class possible_vars {
public:
vector<int> vars;
/*possible_vars& operator= (const possible_vars& vars2)
{
vars = vars2.vars;
return *this;
}*/
possible_vars& operator= (const vector<int>& vars2)
{
vars = vars2;
return *this;
}
possible_vars(int bsize) {
for (int i = 0; i < bsize; i++) vars.push_back(i + 1);
}
possible_vars(vector<int> input) {
vars = input;
}
int size() {
return vars.size();
}
bool remove_variant(int num) {
bool is_changed = false;
for (unsigned int i = 0; i < vars.size(); i++) {
if (vars[i] == num) {
vars.erase(vars.begin() + i);
is_changed = true;
break;
}
}
return is_changed;
}
bool is_var_here(int var) {
if (find(vars.begin(), vars.end(), var) != vars.end()) return true;
else return false;
}
};
class skyscrapers {
public:
vector<vector<possible_vars>> solution;
vector<vector<short>> solution_static;
vector<int> clues;
vector<vector<int>> patterns;
vector<int> pattern;
int basic_size;
skyscrapers(int size_of_field) {
solution = vector<vector<possible_vars>>(size_of_field, vector<possible_vars>(size_of_field,possible_vars(size_of_field)));
solution_static = vector<vector<short>>(size_of_field, vector<short>(size_of_field, false));
clues = vector<int>(size_of_field * size_of_field);
basic_size = size_of_field;
}
vector<vector<possible_vars>> patterns_by_det;
vector<vector<possible_vars>> excluding_patterns;
void generate_excluding_base() {
possible_vars for_one_number(basic_size);
vector<possible_vars> for_one_pattern;
for (int i = 0; i < basic_size; i++) {
for_one_pattern.push_back(for_one_number);
}
for (int i = 0; i < basic_size; i++) {
excluding_patterns.push_back(for_one_pattern);
}
}
void generate_patterns() {
vector<int> base;
for (int i = 0; i < basic_size; i++) {
base.push_back(i + 1);
}
generate_patterns_re(base);
int seen;
patterns_by_det = vector<vector<possible_vars>>(basic_size);
for (unsigned int i = 0; i < patterns.size(); i++) {
seen = check_visible(patterns[i]);
patterns_by_det[seen - 1].push_back(possible_vars(patterns[i]));
}
generate_excluding_base();
for (unsigned int i = 0; i < patterns_by_det.size(); i++) {
for (unsigned int j = 0; j < patterns_by_det.size(); j++) {
for (unsigned int k = 0; k < patterns_by_det[i].size(); k++) {
excluding_patterns[i][j].remove_variant(patterns_by_det[i][k].vars[j]);
}
}
}
}
void generate_patterns_re(vector<int> possible_vars) {
vector<int> next;
if (possible_vars.size() > 1) {
for (unsigned int i = 0; i < possible_vars.size(); i++) {
pattern.push_back(possible_vars[i]);
next = possible_vars;
next.erase(next.begin() + i);
generate_patterns_re(next);
pattern.pop_back();
}
}
else {
pattern.push_back(possible_vars[0]);
patterns.push_back(pattern);
pattern.pop_back();
}
}
vector<possible_vars*> get_row(int row_index) {
vector<possible_vars*> row;
possible_vars* cell;
if (row_index / basic_size == 0) {
for (int i = 0; i < basic_size; i++) {
cell = &solution[i][row_index % basic_size];
row.push_back(cell);
}
}
else if (row_index / basic_size == 1) {
for (int i = 0; i < basic_size; i++) {
cell = &solution[row_index % basic_size][basic_size - 1 - i];
row.push_back(cell);
}
}
else if (row_index / basic_size == 2) {
for (int i = 0; i < basic_size; i++) {
cell = &solution[basic_size - 1 - i][basic_size - 1 - row_index % basic_size];
row.push_back(cell);
}
}
else if (row_index / basic_size == 3) {
for (int i = 0; i < basic_size; i++) {
cell = &solution[basic_size - 1 - row_index % basic_size][i];
row.push_back(cell);
}
}
return row;
}
vector<short*> get_static_row(int row_index) {
vector<short*> row;
short* cell;
if (row_index / basic_size == 0) {
for (int i = 0; i < basic_size; i++) {
cell = &solution_static[i][row_index % basic_size];
row.push_back(cell);
}
}
else if (row_index / basic_size == 1) {
for (int i = 0; i < basic_size; i++) {
cell = &solution_static[row_index % basic_size][basic_size - 1 - i];
row.push_back(cell);
}
}
else if (row_index / basic_size == 2) {
for (int i = 0; i < basic_size; i++) {
cell = &solution_static[basic_size - 1 - i][basic_size - 1 - row_index % basic_size];
row.push_back(cell);
}
}
else if (row_index / basic_size == 3) {
for (int i = 0; i < basic_size; i++) {
cell = &solution_static[basic_size - 1 - row_index % basic_size][i];
row.push_back(cell);
}
}
return row;
}
void remove_all_vars(int y, int x) {
for (int i = 0; i < basic_size; i++) {
if (i != x) solution[y][i].remove_variant(solution[y][x].vars[0]);
}
for (int i = 0; i < basic_size; i++) {
if (i != y) solution[i][x].remove_variant(solution[y][x].vars[0]);
}
}
bool normalize() {
bool is_changed = false;
for (int i = 0; i < basic_size; i++) {
for (int j = 0; j < basic_size; j++) {
if (solution_static[i][j] == false and solution[i][j].vars.size() == 1) {
solution_static[i][j] = true;
remove_all_vars(i, j);
is_changed = true;
}
}
}
return is_changed;
}
bool add_obvious() {
bool is_changed = false;
map<int, int> counting;
for (int i = 0; i < basic_size; i++) counting.insert(pair<int, int>(i + 1, 0));
for (int i = 0; i < basic_size; i++) {
for (int j = 1; j <= basic_size; j++) counting[j] = 0;
for (int j = 0; j < basic_size; j++) {
for (int k = 0; k < solution[i][j].size(); k++) {
counting[solution[i][j].vars[k]] += 1;
}
}
for (int k = 1; k <= basic_size; k++) {
if (counting[k] == 1) {
for (int j = 0; j < basic_size; j++) {
if (solution_static[i][j] == false and solution[i][j].is_var_here(k)) {
solution[i][j].vars = { k };
solution_static[i][j] = true;
remove_all_vars(i, j);
is_changed = true;
}
}
}
}
}
for (int j = 0; j < basic_size; j++) {
for (int j = 1; j <= basic_size; j++) counting[j] = 0;
for (int i = 0; i < basic_size; i++) {
for (int k = 0; k < solution[i][j].size(); k++) {
counting[solution[i][j].vars[k]] += 1;
}
}
for (int k = 1; k <= basic_size; k++) {
if (counting[k] == 1) {
for (int i = 0; i < basic_size; i++) {
if (solution_static[i][j] == false and solution[i][j].is_var_here(k)) {
solution[i][j].vars = { k };
solution_static[i][j] = true;
remove_all_vars(i, j);
is_changed = true;
}
}
}
}
}
return is_changed;
}
bool fix_matrix() {
bool is_changed = false, is_changed_global = false;
do {
is_changed = normalize();
is_changed_global += is_changed;
} while (is_changed == true);
do {
is_changed = add_obvious();
is_changed_global += is_changed;
} while (is_changed == true);
return is_changed_global;
}
bool use_excluding_patterns() {
bool is_changed = false;
vector<possible_vars*> row;
int current_value;
for (unsigned int curr_clue = 0; curr_clue < clues.size(); curr_clue++) {
if (clues[curr_clue] != 0) {
row = get_row(curr_clue);
current_value = clues[curr_clue] - 1;
for (unsigned int i = 0; i < excluding_patterns[current_value].size(); i++) {
for (int j = 0; j < excluding_patterns[current_value][i].size(); j++) {
is_changed += row[i]->remove_variant(excluding_patterns[current_value][i].vars[j]);
}
}
}
}
return is_changed;
}
bool use_patterns() {
bool is_changed = false, is_suitable;
vector<possible_vars*> row;
vector<short*> static_row;
int current_value;
vector<possible_vars> current_patterns;
for (unsigned int curr_clue = 0; curr_clue < clues.size(); curr_clue++) {
if (clues[curr_clue] != 0) {
row = get_row(curr_clue);
static_row = get_static_row(curr_clue);
current_value = clues[curr_clue] - 1;
current_patterns = patterns_by_det[current_value];
for (unsigned int i = 0; i < current_patterns.size(); i++) {
//for (int print = 0; print < current_patterns[i].size(); print++) cout << current_patterns[i].vars[print] << " ";
//cout << endl;
for (int j = 0; j < current_patterns[i].size(); j++) {
is_suitable = row[j]->is_var_here(current_patterns[i].vars[j]);
// cout << j+1 << "-> " << is_suitable << endl;
if (is_suitable == false) {
current_patterns.erase(current_patterns.begin() + i);
i--;
//cout << endl << "Erased, now current patterns:" << endl;
/*for (int print1 = 0; print1 < current_patterns.size(); print1++) {
for (int print2 = 0; print2 < current_patterns[print1].size(); print2++) cout << current_patterns[print1].vars[print2] << " ";
cout << endl;
}
cout << endl;*/
break;
}
}
}
if (current_patterns.size() == 1) {
for (unsigned int i = 0; i < row.size(); i++) {
if (*static_row[i] == false) {
*static_row[i] = true;
is_changed = true;
*row[i] = possible_vars(vector<int>(1, current_patterns[0].vars[i]));
}
}
}
}
}
return is_changed;
}
void print() {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
for (int k = 0; k < solution[i][j].size(); k++) cout << solution[i][j].vars[k];
cout << " ";
}
cout << endl;
}
cout << endl;
}
};
int** SolvePuzzle(int* clues) {
skyscrapers result(4);
result.generate_patterns();
for (int i = 0; i < 16; i++) {
result.clues[i] = clues[i];
}
bool is_changed = true;
result.use_excluding_patterns();
result.fix_matrix();
while (is_changed) {
is_changed = result.use_patterns();
is_changed += result.fix_matrix();
}
int** answer[4][4];
for (unsigned int i = 0; i < result.solution.size(); i++) {
for (unsigned int j = 0; j < result.solution[i].size(); j++) {
*answer[i][j] = &result.solution[i][j].vars[0];
}
}
return **answer;
}
This block of code appears suspicious for several reasons:
int** answer[4][4];
for (unsigned int i = 0; i < result.solution.size(); i++) {
for (unsigned int j = 0; j < result.solution[i].size(); j++) {
*answer[i][j] = &result.solution[i][j].vars[0];
}
}
return **answer;
&result.solution[i][j].vars[0] is a pointer to something inside that result object. As soon as the function returns, result will destruct and the pointers assigned to answer[i][j] is no longer valid when the function returns.
Also, returning **answer is really suspicious. With regards to a local 2-d array, this statement would in essence only return the int** inside answer[0][0]. None of the other values inside answer would be passed back - even if result wasn't destructing.
The problem is that you made a 4x4 array of int**. Here is the fixed code:
int** answer = new int*[4];
for (unsigned int i = 0; i < result.solution.size(); i++) {
answer[i] = new int[4];
for (unsigned int j = 0; j < result.solution[i].size(); j++) {
answer[i][j] = result.solution[i][j].vars[0];
}
}

Isomorphic graph parallel code implementation using openmp

I am trying to implement a parallel code for graph isomorphism(checking if 2 graphs are isomorphic or not) using openmp. I have the sequential code below, written in C++ which works only for regular graphs.
I have taken the input from a text file (input.txt) which contains number of nodes and 2 adjacency matrices representing 2 graphs. The output.txt file indicates whether the graphs are isomorphic or NON isomorphic along with the execution time.
I have used is_regular() function to check if a graph is regular graph or not.
Can someone please help me parallelize this code using openmp.
#include <time.h>
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
#include <string>
using namespace std;
bool is_regular(vector<string> &adj) {
int nv = adj.size();
int cnt = 0;
for (int j = 0; j < nv; ++j)
if (adj[0][j] == '1') ++cnt;
for (int i = 1; i < nv; ++i) {
int sch = 0;
for (int j = 0; j < nv; ++j)
if (adj[i][j] == '1') ++sch;
if (sch != cnt) return false;
}
return true;
}
vector<vector<int> > foo1(vector<string> &adj, char R) {
int nv = adj.size();
vector<vector<int> > res;
for (int v1 = 0; v1 < nv; ++v1) {
vector<int> tmp;
vector<bool> b(nv);
vector<int> p, q;
p.push_back(v1);
b[v1] = true;
while (!p.empty()) {
q.clear();
for (size_t i = 0; i < p.size(); ++i) {
for (int j = 0; j < nv; ++j)
{
if (!b[j] && adj[p[i]][j] == R) {
b[j] = true;
q.push_back(j);
}
}
}
if (q.empty()) break;
vector<int> d(p.size());
vector<int> e(q.size());
for (size_t i = 0; i < p.size(); ++i) {
for (size_t j = 0; j < q.size(); ++j) {
if (adj[p[i]][q[j]] == R) {++d[i]; --e[j];}
}
}
sort(d.begin(), d.end());
sort(e.begin(), e.end());
copy(d.begin(), d.end(), back_inserter(tmp));
copy(e.begin(), e.end(), back_inserter(tmp));
p.swap(q);
}
res.push_back(tmp);
}
sort(res.begin(), res.end());
return res;
}
vector<vector<int> > foo2(vector<string> &adj, char R) {
int nv = adj.size();
vector<vector<int> > res;
for (int v1 = 0; v1 < nv; ++v1) {
for (int v2 = v1 + 1; v2 < nv; ++v2) {
vector<int> tmp;
vector<bool> b(nv);
vector<int> p, q;
p.push_back(v1);
p.push_back(v2);
b[v1] = true;
b[v2] = true;
while (!p.empty()) {
q.clear();
for (size_t i = 0; i < p.size(); ++i) {
for (int j = 0; j < nv; ++j) {
if (!b[j] && adj[p[i]][j] == R) {
b[j] = true;
q.push_back(j);
}
}
}
if (q.empty()) break;
vector<int> d(p.size());
vector<int> e(q.size());
for (size_t i = 0; i < p.size(); ++i) {
for (size_t j = 0; j < q.size(); ++j) {
if (adj[p[i]][q[j]] == R) {++d[i]; --e[j];}
}
}
sort(d.begin(), d.end());
sort(e.begin(), e.end());
copy(d.begin(), d.end(), back_inserter(tmp));
copy(e.begin(), e.end(), back_inserter(tmp));
p.swap(q);
}
res.push_back(tmp);
}
}
sort(res.begin(), res.end());
return res;
}
vector<vector<int> > foo3(vector<string> &adj, char R) {
int nv = adj.size();
vector<vector<int> > res;
for (int v1 = 0; v1 < nv; ++v1) {
for (int v2 = v1 + 1; v2 < nv; ++v2) {
for (int v3 = v2 + 1; v3 < nv; ++v3) {
vector<int> tmp;
vector<bool> b(nv);
vector<int> p, q;
p.push_back(v1);
p.push_back(v2);
p.push_back(v3);
b[v1] = true;
b[v2] = true;
b[v3] = true;
while (!p.empty()) {
q.clear();
for (size_t i = 0; i < p.size(); ++i) {
for (int j = 0; j < nv; ++j) {
if (!b[j] && adj[p[i]][j] == R) {
b[j] = true;
q.push_back(j);
}
}
}
if (q.empty()) break;
vector<int> d(p.size());
vector<int> e(q.size());
for (size_t i = 0; i < p.size(); ++i) {
for (size_t j = 0; j < q.size(); ++j) {
if (adj[p[i]][q[j]] == R) {++d[i]; --e[j];}
}
}
sort(d.begin(), d.end());
sort(e.begin(), e.end());
copy(d.begin(), d.end(), back_inserter(tmp));
copy(e.begin(), e.end(), back_inserter(tmp));
p.swap(q);
}
res.push_back(tmp);
}
}
}
sort(res.begin(), res.end());
return res;
}
int main() {
int nt = 1;
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
int n;
int tc = 0;
while (cin >> n) {
vector<string> adj1(n);
vector<string> adj2(n);
for (int i = 0; i < n; ++i) cin >> adj1[i];
for (int i = 0; i < n; ++i) cin >> adj2[i];
clock_t start = clock();
string answer = "NON-isomorphic";
if (!is_regular(adj1) || !is_regular(adj2)) {
answer = "Non regular graph";
goto mmm;
}
if (foo1(adj1,'1') != foo1(adj2,'1') || foo1(adj1,'0') != foo1(adj2,'0')) {
answer += " * ";
goto mmm;
}
if (foo2(adj1,'1') != foo2(adj2,'1') || foo2(adj1,'0') != foo2(adj2,'0')) {
answer += " ** ";
goto mmm;
}
if (foo3(adj1,'1') != foo3(adj2,'1') || foo3(adj1,'0') != foo3(adj2,'0')) {
answer += " ***";
goto mmm;
}
answer = "isomorphic";
mmm:
++tc;
printf("%d) n = %d %s", tc, n, answer.c_str());
printf(" %f\n", (double)(clock() - start) / CLOCKS_PER_SEC);
}
return 0;
}

0xC0000005: Access violation reading location 0xFDFDFDED

So I wrote this:
Matrix.h:
#pragma once
class Matrix
{
private:
int m, n;
double** M = nullptr;
public:
Matrix();
Matrix(int,int);
Matrix(const Matrix&);
~Matrix();
void set_m(int);
void set_n(int);
int get_m() const;
int get_n() const;
void setM(double**,int,int);
double** getM() const;
void show();
Matrix operator*(Matrix&) const;
};
Matrix.cpp:
#include "Matrix.h"
#include<iostream>
using namespace std;
/*
*/
Matrix::Matrix()
{
set_n(1);
set_m(1);
delete[] M;
M = new double*[get_m()];
for (int i = 0; i < m; i++) {
M[i] = new double[get_n()];
}
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++) M[i][j] = 1.0;
}
Matrix::Matrix(int m_,int n_)
{
set_n(n_);
set_m(m_);
delete[] M;
M = new double *[get_m()];
for (int i = 0; i < m; i++) {
M[i] = new double[get_n()];
}
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++) M[i][j] = 1.0;
}
Matrix::Matrix(const Matrix& M_)
{
set_n(M_.get_n());
set_m(M_.get_m());
delete[] M;
M = new double*[get_m()];
for (int i = 0; i < m; i++) {
M[i] = new double[get_n()];
}
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++) M[i][j] = M_.getM()[i][j];
}
void Matrix::set_m(int m_) {
if (m_ > 0)
m = m_;
else
m = 1;
}
void Matrix::set_n(int n_) {
if (n_ > 0)
n = n_;
else
n = 1;
}
double** Matrix::getM() const {
return M;
}
Matrix Matrix::operator*(Matrix &M_) const
{
if (get_n() != M_.get_m()) {
if (get_m() != M_.get_n()) return Matrix();
else {
Matrix T(*this);
return M_*T;
}
}
else {
//n = m
Matrix R(get_m(), M_.get_n());
for (int i = 0; i < get_m(); i++) {
for (int j = 0; j < M_.get_n(); j++) {
double res = 0;
for (int k = 0; k < get_n(); k++) {
res += getM()[i][k] * M_.getM()[k][j];
}
R.getM()[i][j] = res;
}
}
return R;
}
}
int Matrix::get_m() const {
return m;
}
int Matrix::get_n() const {
return n;
}
void Matrix::setM(double** M_, int m_, int n_) {
set_m(m_);
set_n(n_);
for (int i = 0; i < get_m(); i++) {
delete M[i];
}
delete[] M;
M = new double*[m_];
for (int i = 0; i < m; i++) {
M[i] = new double[n_];
}
for (int i = 0; i < m_; i++)
for (int j = 0; j < n_; j++) M[i][j] = M_[i][j];
}
void Matrix::show() {
for (int i = 0; i < get_m(); i++) {
for (int j = 0; j < get_n(); j++) {
cout << getM()[i][j]<<" ";
}
cout << endl;
}
}
Matrix::~Matrix()
{
for (int i = 0; i < get_m(); i++) {
delete M[i];
}
delete[] M;
}
It crashes at void Matrix::setM(...) when I try to delete M[i] for i = 1; it doe perfectly fine for i=0; but crashes later and I do not have a rational explanation why does it do that. I can see the debugger showing me that the memory cannot be read even before it actually crashing but I do not understand how to fix it. Thanks in advance!
You are setting your m before deleting your array based on the old value of m and end up deleting your old array using the new value of m. You should first delete your array, then set mm, and then create your new array.

C++ PCA - Calculating covariance MATRIX

I'm trying to calculate the Covariance (matrix) of a vector in C++ ...
I have carried out the following:
std::vector<std::vector<double> > data = { {2.5, 2.4}, {0.5, 0.7} };
I have then calculated and subtracted the mean, which gave the following result:
data = { {0.05, -0.05}, {-0.1, 0.1} }
As far as I'm aware, the next step is to transpose the matrix, and multiply the origin together, take the sum and finally divide by the dimensions X - 1..
I have written the following:
void cover(std::vector<std::vector<double> > &d)
{
double cov = 0.0;
for(unsigned i=0; (i < d.size()); i++)
{
for(unsigned j=0; (j < d[i].size()); j++)
{
cov += d[i][j] * d[j][i] / (d[i].size() - 1);
std::cout << cov << " ";
}
std::cout << std::endl;
}
}
Where d is the vector after the mean has been subtracted from each of the points
Which gives me the result:
0.0025, 0.0075
0.0125, 0.0225
Where compared with matlab:
2.0000 1.7000
1.7000 1.4450
Does anyone have any ideas to where I am going wrong?
Thanks
This statement:
As far as I'm aware, the next step is to transpose the matrix, and multiply the origin together, take the sum and finally divide by the dimensions X - 1..
And this implementation:
cov += d[i][j] * d[j][i] / (d[i].size() - 1);
Don't say the same thing. Based on the definition here:
void outer_product(vector<double> row, vector<double> col, vector<vector<double>>& dst) {
for(unsigned i = 0; i < row.size(); i++) {
for(unsigned j = 0; j < col.size(); i++) {
dst[i][j] = row[i] * col[j];
}
}
}
//computes row[i] - val for all i;
void subtract(vector<double> row, double val, vector<double>& dst) {
for(unsigned i = 0; i < row.size(); i++) {
dst[i] = row[i] - val;
}
}
//computes m[i][j] + m2[i][j]
void add(vector<vector<double>> m, vector<vector<double>> m2, vector<vector<double>>& dst) {
for(unsigned i = 0; i < m.size(); i++) {
for(unsigned j = 0; j < m[i].size(); j++) {
dst[i][j] = m[i][j] + m2[i][j];
}
}
}
double mean(std::vector<double> &data) {
double mean = 0.0;
for(unsigned i=0; (i < data.size());i++) {
mean += data[i];
}
mean /= data.size();
return mean;
}
void scale(vector<vector<double>> & d, double alpha) {
for(unsigned i = 0; i < d.size(); i++) {
for(unsigned j = 0; j < d[i].size(); j++) {
d[i][j] *= alpha;
}
}
}
So, given these definitions, we can compute the value for the covariance matrix.
void compute_covariance_matrix(vector<vector<double>> & d, vector<vector<double>> & dst) {
for(unsigned i = 0; i < d.size(); i++) {
double y_bar = mean(d[i]);
vector<double> d_d_bar(d[i].size());
subtract(d[i], y_bar, d_d_bar);
vector<vector<double>> t(d.size());
outer_product(d_d_bar, d_d_bar, t);
add(dst, t, dst);
}
scale(dst, 1/(d.size() - 1));
}
I think maybe For loop in outer_product it's wrong:
void outer_product(vector<double> row, vector<double> col, vector<vector<double>>& dst) {
for(unsigned i = 0; i < row.size(); i++) {
for(unsigned j = 0; j < col.size(); i++) {
dst[i][j] = row[i] * col[j];
}
}
I will change i++ -> j++