I am trying to transpose a matrix built with vectors.
Here is the transpose function I wrote:
void transpose(std::vector<std::vector<int>>& fill_mat) {
for (int i = 0; i < fill_mat.size(); ++i) {
for (int j = 0; j < fill_mat.size(); ++j) {
std::swap(fill_mat[i][j], fill_mat[j][i]);
}
}
}
It doesn't seem to be doing anything: my final results are the same as the starting ones.
Here is my full program:
#include<iostream>
#include<vector>
#include<utility>
void print_matrix(std::vector<std::vector<int>>& to_print) {
for (int i = 0; i < to_print.size(); ++i) {
for (int j = 0; j < to_print.size(); ++j) {
std::cout << " " << to_print[i][j];
}
std::cout << std::endl;
}
}
void make_matrix(std::vector<std::vector<int>>& fill_mat) {
for (int i = 0; i < fill_mat.size(); ++i) {
for (int j = 0; j < fill_mat.size(); ++j) {
fill_mat[i][j] = rand() % 15;
}
}
}
void transpose(std::vector<std::vector<int>>& fill_mat) {
for (int i = 0; i < fill_mat.size(); ++i) {
for (int j = 0; j < fill_mat.size(); ++j) {
std::swap(fill_mat[i][j], fill_mat[j][i]);
}
}
}
int main() {
int size = 3;
std::vector<std::vector<int>> matrix_sample(size, std::vector<int>(size));
make_matrix(matrix_sample);
print_matrix(matrix_sample);
transpose(matrix_sample);
std::cout << "----## transpose ##-----" << std::endl;
print_matrix(matrix_sample);
}
I expected to print out the transposed matrix but the input ends up being the same as the output. What am I doing wrong?
You swap (i,j) with (j,i) twice! That's why it has no effect.
You should only work on one half of your matrix. Plus minors improvements, we get:
void transpose(std::vector<std::vector<int>>& fill_mat)
{
using size_type = decltype(fill_mat)::size_type; // better use your matrix' size type
for (size_type i = 0; i < fill_mat.size(); ++i) {
for (size_type j = 0; j < i; ++j) {
using std::swap; // see swap idiom
swap(fill_mat[i][j], fill_mat[j][i]);
}
}
}
Related
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
I am trying to copy a matrix from an old matrix class to an armadillo matrix. Unfortunately when attempting to do this with a for loop the armadillo matrix will copy the value from the old matrix to the ENTIRE column when the lowest-most element is non-zero (I am using sparse matrices). I have attached the code that is being used below. This is very simplified because I need to figure out why it is doing this first. According to the documentation this should work.
main()
{
OldMatrixClass MatrixA(size, size);
FillMatrix(MatrixA, size);
for (auto i = 0; i < size; i++)
{
for (auto j = 0; j < size; j++)
{
file << MatrixA[i][j] << "\t";
}
file << "\n";
}
arma::Mat<double> ArmaA(size, size);
ArmaA.zeros();
CopyMatrix(MatrixA, ArmaA, size);
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
file << ArmaA[i,j] << "\t";
}
file << "\n";
}
}
void FillMatrix(OldMatrixClass &A, int size)
{
double num = 0.15;
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
if (rand() % 101 < 26)
{
A[i][j] = num;
}
else
{
A[i][j] = 0;
}
}
}
}
void CopyMatrix(OldMatrixClass A, arma::Mat<double> &B, int size)
{
for (int k = 0; k < size; k++)
{
for (int j = 0; j < size; j++)
{
B[j, k] = A[j][k];
}
}
}
This is the output when I run this code... As you can see only the entire columns are altered if the last element in MatrixA column is non-zero.
Output
Is there something I'm doing wrong? Is my syntax messed up somewhere?
See the documentation:
Caveat: accessing elements via [i,j] and [i,j,k] does not work correctly in C++; instead use (i,j) and (i,j,k)
Alright so I have created this code. However, when i run it, it stops when it displays 104 for the counter??? I am so frustrated because I don't know how this could happen. The purpose of the code is to do the typical magic number output where the rows all add up to the same thing, the columns all add up to the same thing, and the diaganols all add up to the same thing. I believe the functions to do these calculations are correct, but the counter keeps stopping short of the 10000 attempts I am trying to do.
#include <iostream>
#include<time.h>
#include<stdlib.h>
using namespace std;
void getrandom();
void insertnumber(int n);
bool magic();
void create();
const int rows = 3;
const int cols = 3;
int arr[rows][cols] = { {0,0,0}, {0,0,0} , {0,0,0} };
int main() {
int counter = 0;
do
{
counter++;
cout << counter << endl;
getrandom();
if (counter == 100000)
break;
} while (!magic());
create();
cout << "It took " << counter << " tries." << endl;
return 0;
}
void getrandom() {
int n = 0;
const int size = 9;
int oldnum[size];
for (int i = 0; i < rows * cols; i++) {
oldnum[i] = 0;
}
srand(time(NULL)); // had to import the new libraries to use this
bool used = true;
for (int i = 0; i < size; i++) {
do
{
used = true;
n = rand() % 9 + 1;
if (oldnum[n - 1] == 0)
{
oldnum[n - 1] = n;
used = false;
}
} while (used);
insertnumber(n);
}
}
void insertnumber(int n) {
for (int i = 0; i < rows; i++) {
for (int j = 0; i < cols; j++) {
if (arr[i][j] == 0) {
arr[i][j] = n;
return;
}
}
}
}
bool magic() {
int rowsum = arr[0][0] + arr[0][1] + arr[0][2];
for (int i = 1; i < cols; i++)
{
if (arr[i][0] + arr[i][1] + arr[i][2] != rowsum)
return false;
}
for (int j = 0; j < rows; j++)
{
if (arr[0][j] + arr[1][j] + arr[2][j] != rowsum)
return false;
}
if (arr[0][0] + arr[1][1] + arr[2][2] != rowsum)
return false;
if (arr[0][2] + arr[1][1] + arr[2][0] != rowsum)
return false;
return true;
}
void create() {
{
for (int i = 0; i < rows; i++) {
for (int j = 0; i < cols; j++) {
cout << arr[i][j] << " ";
}
cout << endl;
}
}
}
You can try using a debugger for such problems.
I think you code crashes because of this:
for (int i = 0; i < rows; i++) {
for (int j = 0; i < cols; j++) {
It looks like you mean j < cols here :)
Check line 76. When I compile and run the code, line 76 is where the exception is thrown.
This line specifically
arr[i][j] = n;
It seems your insertnumber() function is the culprit.
i am working on multiplication of matrix
it is something like
m5 = m2 * m3;
cout << "m2 * m3 is : " << endl<< m5 << endl;
and this is my code
const Matrix Matrix::operator*(const Matrix &a)
{
Matrix temp(a.row,a.col);
for (int i = 0; i<row; i++)
{
for (int j = 0; j<col; j++)
{
for (int k = 0; k<a.row; k++)
{
temp.data[i][j] = temp.data[i][j] + data[i][k] * a.data[k][j];
}
}
}
return temp;
}
However, there is an error always showing at my printing function
ostream& operator<<(ostream &output, const Matrix &a)
{
for (int i = 0; i < a.row; i++)
{
for (int j = 0; j < a.col; j++)
{
output << a.data[i][j] << "\t";
}
output << "" << endl;
}
return output;
}
seems there has a problem on a.data[i][j] which i dont know what's the problem
it works fine on addition.
it is showing an error {data0x005fba90{0xfeeefeee{???}}
can anybody give any advice or suggestions or help on this situation
this is my copy constructor
Matrix::Matrix(const Matrix&m2)
{
row = m2.row;
col = m2.col;
setUp(row, col);
for (int i = 0; i<row; i++)
{
for (int j = 0; j<col; j++)
{
data[i][j] = 0;
}
}
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
data[i][j] = m2.data[i][j];
}
}
}
this is the set up and default
Matrix::Matrix()
{
row =0;
col = 0;
for (int i = 0; i<row; i++)
{
for (int j = 0; j<col; j++)
{
data[i][j] = 0;
}
}
}
Matrix::Matrix(int a, int b, double d[], int c)
{
row = a;
col = b;
setUp(row, col);
int counter = 0;
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
data[i][j] = d[counter];
counter++;
}
}
}
and the set up
void Matrix::setUp(int a, int b)
{
row = a;
col = b;
data = new double*[row];
for (int i = 0; i < row; i++) data[i] = new double[col];
}
Without seeing your Matrix constructor, or the class definition, it's hard to say for certain, but if you look at this expression
temp.data[i][j] + data[i][k] * a.data[k][j]
Depending on what data is, if you don't explicitly initialize the data member in the constructor when you create temp then its contents will not automatically be initialized, and the contents will be indeterminate and using it will lead to undefined behavior.
Another possible source of problems might be the lack of a copy-constructor, or a faulty copy-constructor. This is a problem since you return temp by value which invokes the copy-constructor.
I am currently working on a program that prints a 5 variable truth table. I am using a 2d array. My code currently produces the table, but says it is corrupt and "the stack around the variable "table" was corrupted. Any help?
#include <iostream>
using namespace std;
int main() {
bool table[5][32];
for (int i = 0; i < 32; i++) {
for (int j = 0; j < 5; j++) {
table[i][j] = ((i >> j)& 1);
}
}
for (int i = 0; i < 32; i++) {
for (int j = 0; j < 5; j++) {
cout << table[i][j] << " ";
}
cout << endl;
}
return 0;
}
This is homework, so I would like to understand it, not just have an answer.
The index is wrong. Only table[0] to table[4] are available, so accessing table[5] to table[31] is illegal.
Try this:
#include <iostream>
using namespace std;
int main() {
bool table[32][5]; // swap 32 and 5
for (int i = 0; i < 32; i++) {
for (int j = 0; j < 5; j++) {
table[i][j] = ((i >> j)& 1);
}
}
for (int i = 0; i < 32; i++) {
for (int j = 0; j < 5; j++) {
cout << table[i][j] << " ";
}
cout << endl;
}
return 0;
}
There is attempt to read out of bound values from array.
If you need 5x32 matrix Use code below:
for (int i = 0; i < 5; i++) { // 32-> 5
for (int j = 0; j < 32; j++) { // 5->32
If you need 32x5 matrix then replace code below:
bool table[32][5]; //it was table[5][32];