I have a task to calculate a scalar product
s=(B*(r+q+r), A*A*p)
As I understand, I need to calculate 2 vectors: first - B*(r+q+r), second - AAp, and then calculate a scalar product.
#include <iostream>
#include <vector>
using namespace std;
using matrix = vector<vector<double>>;
matrix add(matrix A, matrix B) {
matrix C;
C.resize(A.size());
for (int i = 0; i< A.size(); i++) {
C[i].resize(B.size());
for (int j = 0; j < B.size(); j++) {
C[i][j] = A[i][j] + B[i][j];
}
}
return C;
}
matrix multiple(matrix A, matrix B)
{
matrix C;
C.reserve(100);
C.resize(B.size());
for (int i = 0; i < A.size(); i++) {
C[i].resize(B.size());
for (int j = 0; j < B.size(); j++) {
for (int k = 0; k < B.size(); k++)
C[i][j] += A[i][k] * B[k][j];
}
}
return C;
}
void main() {
matrix A = { {1,2,3}, {1,2,1}, {3,2,0} };
matrix B = { {4,1,2},{0,4,3},{1,1,1} };
matrix r = { {-0.7f, 1.3, 0.2} };
matrix q = { { -1.6f, 0.8, 1.1} };
matrix p = { {0.1, 1.7, -1.5} };
matrix r_q = add(r, q);
for (int i = 0; i < r_q.size(); i++) {
for (int j = 0; j < r_q.size(); j++) {
cout << r_q[i][j] << "\t";
}
cout << "\n";
}
matrix a_a = multiple(A, A);
matrix a_a_p = multiple(a_a,p);
getchar();
}
Problems:
add method work not correct, it put in result only one number - sum of the first items.
Multipling matrix with the same dimensions (A*A) work correct. Multipling matrix with the different dimensions (a_a * p) - return error "vector subscript out of range".
Thanks for any advice.
The OP chose to implement both matrices and vectors using a std::vector<std::vector<double>>.
This may not be a good design choice in general, but also in particular, to be consistent to the mathematical meaning of all the involved operations, all the vectors should be considered (and declared as well) as "column" matrices (or Nx1 matrices):
matrix r = { {-0.7}, {1.3}, {0.2} };
matrix q = { {-1.6}, {0.8}, {1.1} };
matrix p = { {0.1}, {1.7}, {-1.5} };
Then, in the functions that perform the calculations, special attention should be paid to the correct sizes of rows and columns to avoid out of bounds accesses.
matrix add(matrix const &A, matrix const &B)
{
if (A.size() != B.size() || A.size() == 0)
throw std::runtime_error("number of rows mismatch");
size_t columns = A[0].size();
matrix C(A.size(), std::vector<double>(columns, 0.0));
for (size_t i = 0; i < A.size(); i++)
{
if ( A[i].size() != columns || B[i].size() != columns )
throw std::runtime_error("number of columns mismatch");
for (size_t j = 0; j < columns; j++)
{
C[i][j] = A[i][j] + B[i][j];
}
}
return C;
}
matrix multiple(matrix const &A, matrix const &B)
{
if ( A.size() == 0 || B.size() == 0 || B[0].size() == 0)
throw std::runtime_error("size mismatch");
size_t columns = B[0].size();
matrix C(A.size(), std::vector<double>(columns, 0.0));
for (size_t i = 0; i < A.size(); i++)
{
if ( A[i].size() != B.size() || B[i].size() != columns )
throw std::runtime_error("inner size mismatch");
for (size_t j = 0; j < columns; j++)
{
for (size_t k = 0; k < B.size(); k++)
C[i][j] += A[i][k] * B[k][j];
}
}
return C;
}
The compiler should have also warned the OP about the incorrect use of void main instead of int main and about the comparisons between signed and unsigned integer expressions (I used size_t instead of int).
From a mathematical point of view, it's worth noting that to solve OP problem, that is to calculate the scalar product s = (B(r+q+r), AAp), the operations really needed (to be implemented) are the sum of vectors, the product of a matrix by a vector (easier and more efficient then matrix multiplication) and the dot product of two vectors:
t = r + q + r
b = Bt
u = Ap
a = Au
s = (b, a)
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 need make Pascal Triangle matrix using vectors and then print it.
This algorithm would work with arrays, but somehow it doesn't work with matrix using vectors.
#include <iomanip>
#include <iostream>
#include <vector>
typedef std::vector<std::vector<int>> Matrix;
int NumberOfRows(Matrix m) { return m.size(); }
int NumberOfColumns(Matrix m) {
if (m.size() != 0)
return m[0].size();
return 0;
}
Matrix PascalTriangle(int n) {
Matrix mat;
int a;
for (int i = 1; i <= n; i++) {
a = 1;
for (int j = 1; j <= i; j++) {
if (j == 1)
mat.push_back(j);
else
mat.push_back(a);
a = a * (i - j) / j;
}
}
return mat;
}
void PrintMatrix(Matrix m, int width) {
for (int i = 0; i < NumberOfRows(m); i++) {
for (int j = 0; j < NumberOfColumns(m); j++)
std::cout << std::setw(width) << m[i][j];
std::cout << std::endl;
}
}
int main() {
Matrix m = PascalTriangle(7);
PrintMatrix(m, 10);
return 0;
}
I get nothing on screen, and here's the same code just without matrix using vectors program (which works fine).
Could you help me fix this code?
The main problem is that in PascalTriangle, you are starting out with an empty Matrix in both the number of rows and columns.
Since my comments mentioned push_back, here is the way to use it if you did not initialize the Matrix with the number of elements that are passed in.
The other issue is that NumberOfColumns should specify the row, not just the matrix vector.
The final issue is that you should be passing the Matrix by const reference, not by value.
Addressing all of these issues, results in this:
Matrix PascalTriangle(int n)
{
Matrix mat;
for (int i = 0; i < n; i++)
{
mat.push_back({}); // creates a new empty row
std::vector<int>& newRow = mat.back(); // get reference to this row
int a = 1;
for (int j = 0; j < i + 1; j++)
{
if (j == 0)
newRow.push_back(1);
else
newRow.push_back(a);
a = a * (i - j) / (j + 1);
}
}
return mat;
}
And then in NumberOfColumns:
int NumberOfColumns(const Matrix& m, int row)
{
if (!m.empty())
return m[row].size();
return 0;
}
And then, NumberOfRows:
int NumberOfRows(const Matrix& m) { return m.size(); }
And last, PrintMatrix:
void PrintMatrix(const Matrix& m, int width)
{
for (int i = 0; i < NumberOfRows(m); i++)
{
for (int j = 0; j < NumberOfColumns(m, i); j++)
std::cout << std::setw(width) << m[i][j];
std::cout << std::endl;
}
}
Here is a live demo
Your code won't compile because you have numerous errors in PascalTriangle.
For one, you initialize a matrix with no elements. Additionally, you use matrix indices starting at 1 rather than 0.
The following prints things for me:
Matrix PascalTriangle(int n) {
Matrix mat(n, std::vector<int>(n, 0)); // Construct Matrix Properly
int a;
for (int i = 0; i < n; i++) { // Start index at 0
a = 1;
for (int j = 0; j < i + 1; j++) { // Start index at 0
if (j == 0) // Changed 1 to 0
mat[i][j] = 1;
else
mat[i][j] = a;
a = a * (i - j) / (j+1); // Changed j to j+1 since j starts at 0
}
}
return mat;
}
I made a zero-one matrix with power 2. However, I want the code to be applied to any power the user enters. I tried several times, but it didn't work.
Here's a part of the code that would concern you.
Notes: Suppose the user has entered his (n*m) matrix which is "a", as n and m are equals and they are denoted by s.
k=0;
for(int j=0; j<s; j++)
for(int i=0; i<s; i++)
{
m[k]=0;
for(int t=0; t<s; t++)
m[k]+=a[j][t]*a[t][i];
k++;
}
Here is my implementation for matrix exponentiation:
struct matrix {
intt m[K][K];
matrix() {
memset (m, 0, sizeof (m));
}
matrix operator * (matrix b) {
matrix c = matrix();
for (intt i = 0; i < K; i++) {
for (intt k = 0; k < K; k++) {
for (intt j = 0; j < K; j++) {
c.m[i][j] = (c.m[i][j] + m[i][k] * b.m[k][j]) % MOD;
}
}
}
return c;
}
matrix pow (intt n) {
if (n <= 0) {
return matrix();
}
if (n == 1) {
return *this;
}
if (n % 2 == 1) {
return (*this) * pow (n - 1);
} else {
matrix X = pow (n / 2);
return X * X;
}
}
};
So far I have this code for an LU decomposition. It takes in an input array and it returns the lower and upper triangular matrix.
void LUFactorization ( int d, const double*S, double*L, double*U )
{
for(int k = 0; k < d; ++k){
if (
for(int j = k; j < d; ++j){
double sum = 0.;
for(int p = 0; p < k; ++p) {
sum+=L[k*d+p]*L[p*d+j];
cout << L[k*d+p] << endl;
}
sum = S[k*d+j] - sum;
L[k*d+j]=sum;
U[k*d+j]=sum;
}
for(int i = k + 1; i < d; ++i){
double sum=0.;
for(int p = 0; p < k; ++p) sum+=L[i*d+p]*L[p*d+k];
L[i*d+k]=(S[i*d+k]-sum)/L[k*d+k];
}
}
for(int k = 0; k < d; ++k){
for(int j = k; j < d; ++j){
if (k < j) L[k*d+j]=0;
else if (k == j) L[k*d+j]=1;
}
}
}
Is there some way I can adapt this to perform row exchanges? If not, is there some other algorithm I could be directed towards?
Thanks
The usual approach for LU decompositions with pivoting is to store a permutation array P which is initialized as the identity permutation (P={0,1,2,...,d - 1}) and then swapping entries in P instead of swapping rows in S
If you have this permutation array, every access to S must use P[i] instead of i for the row number.
Note that P itself is part of the output, since it represents the permutation matrix such that
P*A = L*U, so if you want to use it to solve systems of linear equations, you'll have to apply P on the right-hand side before applying backward and forward substitution
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++