(r1,c1) and (r2,c2) are number of Rows and columns of matrix a[][] and matrix b[][]
matrix c[][] is the matrix multiplication of a[][] and b[][]
The user enters the number of rows and columns of a[][] and b[][] and enters elements of both.
this is the output given by the complete program for specific a[][], b[][]
the expected output of the program for the same a[][] and b[][] is:
c[2][2]={{7,14},{17,34}}
However, I cant seem to find the error in the logic.
the following part of the code is the logic to carry out the matrix multiplication
for (i = 0; i < r1; i++) {
for (j = 0; j < c2; j++) {
c[i][j] = 0;
for (k = 0; k < c1; k++) {
c[i][j] += a[i][j] * b[k][j];
}
}
}
for (i = 0; i < r1; i++) {
for (j = 0; j < c2; j++) {
printf("%d ", c[i][j]);
}
printf("\n");
}
You are doing math incorrectly.
According to mat multiplication,
for(i=0 ; i<r1 ; i++)
{
for(j=0 ; j<c2 ; j++)
{
c[i][j]=0;
for(k=0 ; k<c1 ; k++)
{
c[i][j]+=a[i][j]*b[k][j];
//--^-- should be k
}
}
}
Some strategic renaming gives
for(int row = 0; row < r1; row++)
{
for(int column = 0; column < c2; column++)
{
c[row][column] = 0;
for(int element = 0; element < c1 ; element++)
{
c[row][column] += a[row][column] * b[element][column];
}
}
}
where you can see more clearly that the multiplication is wrong - you're multiplying with the same element from a in every step.
It should be
c[row][column] += a[row][element] * b[element][column];
I guess that this could help you to solve your problem:
c[i][j]+=a[i][k]*b[k][j];
Related
I'm trying to implement a quick program to solve a system of linear equations. The program reads the input from a file and then writes the upper-triangular system and solutions to a file. It is working with no pivoting, but when I try to implement the pivoting it produces incorrect results.
As example input, here is the following system of equations:
w+2x-3y+4z=12
2w+2x-2y+3z=10
x+y=-1
w-x+y-2z=-4
I expect the results to be w=1, x=0, y=-1 and z=2. When I don't pivot, I get this answer (with some rounding error on x). When I add in the pivoting, I get the same numbers but in the wrong order: w=2,x=1,y=-1 and z=0.
What do I need to do to get these in the correct order? Am I missing a step somewhere? I need to do column swapping instead of rows because I need to adapt this to a parallel algorithm later that requires that. Here is the code that does the elimination and back substitution:
void gaussian_elimination(double** A, double* b, double* x, int n)
{
int maxIndex;
double temp;
int i;
for (int k = 0; k < n; k++)
{
i = k;
for (int j = k+1; j < n; j++)
{
if (abs(A[k][j]) > abs(A[k][i]))
{
i = j;
}
}
if (i != k)
{
for (int j = 0; j < n; j++)
{
temp = A[j][k];
A[j][k] = A[j][i];
A[j][i] = temp;
}
}
for (int j = k + 1; j < n; j++)
{
A[k][j] = A[k][j] / A[k][k];
}
b[k] = b[k] / A[k][k];
A[k][k] = 1;
for (i = k + 1; i < n; i++)
{
for (int j = k + 1; j < n; j++)
{
A[i][j] = A[i][j] - A[i][k] * A[k][j];
}
b[i] = b[i] - A[i][k] * b[k];
A[i][k] = 0;
}
}
}
void back_substitution(double**U, double*x, double*y, int n)
{
for (int k = n - 1; k >= 0; k--)
{
x[k] = y[k];
for (int i = k - 1; i >= 0; i--)
{
y[i] = y[i] - x[k]*U[i][k];
}
}
}
I believe what you implemented is actually complete pivoting.
With complete pivoting, you must keep track of the permutation of columns, and apply the same permutation to your answer.
You can do this with an array {0, 1, ..., n}, where you swap the i'th and k'th values in the second loop. Then, rearange the solution using this array.
If what you were trying to do is partial pivoting, you need to look for the maximum in the respective row, and swap the rows and the values of 'b' accordingly.
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 understand the operation count of the code given below.
void add(matrix a, matrix b, matrix c, int m, int n)
{
for(int i = 0; i < m; i++)
{
count++; //for 'for' i -------(a)
for(int j = 0; j < n; j++)
{
count++; //for 'for' j -------(b)
c[i][j] = a[i][j] + b[i][j];
count++; //for assignment ------(c)
}
count++; //for last time of 'for' j ------(d)
}
count++; //for lastime of 'for' i ---------(e)
}
The variable count has been used by the author in which this code is to calculate operation count. I do know that the declarative statements (int i = 0; int j = 0) have operation count of 0.
Every time each the for loop will run it, the following expressions should do 2 operation counts for i < m; i++ when only 1 operation i < m is performed.
for(int i = 0; i < m; i++)
for(int j = 0; j < n; j++)
But the author has only calculated it once (a) and (b). Does that means i < m and j < n is not calculated in operation count?
In this line the operation count should be 2: 1 addition operation and 1 assignment operation.
c[i][j] = a[i][j] + b[i][j];
Again he has only calculated it once (c).
Because of the questions I don't know why he incremented count at (d) and (e).
//Simplified program with counting only
line void add (matrix a, matrix b, matrix c, int m, int n)
{
for(int i = 0; i < m; i++)
{
for(int j = 0; j < m; j++)
count += 2;
count += 2;
}
count++;
}
Thank you :)
I have tried without error, [2x2] * [2x2] and [2x3] * [3x2].
The "odd one" is the output from the [3x2] * [2x3]. its output looks something like this: row 1: [9 10 11], row 2: [39 44 49], row 3: [69 78 87 0 0 0297 0]. Rows 3's output is adding elements unlike it did with the previous trials of 2x2 and the (2x3 * 3x2).
Here's a snippet of my code where I believe the problem may lie.
int sum;
outputVec.resize(vec1.size());
for(int i = 0; i < vec1.size(); i++) {
for(int k = 0; k < vec2[i].size(); k++) {
sum = 0;
for(int j = 0; j < vec1[i].size(); j++) {
sum += (vec1[i][j] * vec2[j][k]);
}
outputVec[i].push_back(sum);
}
}
for(int i = 0; i < outputVec.size(); i++) {
for(int j = 0; j < outputVec[i].size(); j++) {
printf("%3d",outputVec[i][j]);
}
cout << endl;
}
for(int i = 0; i < vec1.size(); i++)
{
for(int k = 0; k < vec2[i].size(); k++)
...
vec2 doesn't necessarily have as many rows as vec1 (as in the (3x2) * (2x3) case). You're reading past the end of vec2 and getting undefined behavior.
So what I am trying to do is multiply one 2d vector by another 2d vector.
I come from Java,Python and C# so I am pretty much learning C++ as I go along.
I have the code down to generate the vector and display the vector but I can't seem to finish the multiplication part.
v1 is another matrix that is already generated.
vector<vector<int> > v2 = getVector();
int n1 = v1[0].size();
int n2 = v2.size();
vector<int> a1(n2, 0);
vector<vector<int> > ans(n1, a1);
for (int i = 0; i < n1; i++) {
for (int j = 0; j < n2; j++) {
for (int k = 0; k < 10; k++) {
// same as z[i][j] = z[i][j] + x[i][k] * y[k][j];
ans[i][j] += v1[i][k] * v2[k][j];
}
}
}
displayVector(ans);
My guess for where I am going wrong is in the inner-most loop. I can't figure out what to actually put in place of that 10 I have there now.
When you multiply matrices, the number of columns of the matrix on the left side must equal the number of rows of the matrix on the right side. You need to check that that is true, and use that common number for your size of the k variable:
int nCommon = v1.size();
assert(v2[0].size() == nCommon);
for (int i = 0; i < n1; i++) {
for (int j = 0; j < n2; j++) {
for (int k = 0; k < nCommon ; k++) {
ans[i][j] += v1[i][k] * v2[k][j];
}
}
}
For you inner loop, you should do something like this
ans[i][j] = 0;
for (int k = 0; k < n2; k++) {
ans[i][j] += v1[i][k] * v2[k][j];
}
I don't know where the 10 comes from.