I.e.: the algorithm depends on the data structure
A x = b | write: A = M - N
=> (M - N) x = b
<=> Mx - Nx = b
<=> Mx = Nx + b
<=> x = M-1Nx + M-1b
<=> x = Px + Qb
|
Jacobi Iteration:
xn+1 = Pxn + Qb
|
There are two operations in the Jacobi iteration:
|
The algorithm will be different when the matrix and the vector are stored differently
class Vector
{
public:
double x[3];
Vector operator+(Vector &v)
{
Vector z;
int i;
for (i = 0; i < 3; i = i + 1)
z.x[i] = x[i] + v.x[i];
return(z);
}
}
|
class DenseMatrix
{
public:
double A[3][3];
Vector operator*(Vector &v)
{
Vector z;
int i, j;
for (i = 0; i < 3; i=i+1)
z.x[i] = 0;
for (i = 0; i < 3; i=i+1)
for (j = 0; j < 3; j=j+1)
z.x[i] = z.x[i] + A[i][j]*v.x[j];
return z;
}
};
|
double distance(Vector a, Vector b)
{
double sum = 0;
int i;
for (i = 0; i < 3; i = i + 1)
sum = sum + fabs(a.x[i] - b.x[i]);
return(sum);
}
Vector Jacobi(DenseMatrix & P, DenseMatrix & Q, Vector b)
{
Vector v1, v2;
int i;
double d;
for (i = 0; i < 3; i = i + 1)
{ v1.x[i] = 0;
v2.x[i] = 1;
}
d = 0.1;
while ( d > 0.0001 )
{
v2 = P*v1 + Q*b;
d = distance(v1, v2);
v1 = v2;
}
return(v2);
}
|
Notice that
v2 = P*v1 + Q*b; |
will invoke the Matrix-vector multiply function defined in the class DenseMatrix
[ 11 12 14 ]
[ 22 23 25 ]
[ 31 33 34 ]
[ 42 45 46 ]
[ 55 ]
[ 65 66 67 ]
[ 75 77 78 ]
[ 87 88 ]
|
|
Representation using Coordinate-wise method:
Index 0 1 2 3 4 5 6 7 8 9 10 ----------------------------------------------------------- Val 11 12 14 22 23 25 31 33 34 42 45 Row 0 0 0 1 1 1 2 2 2 3 3 Col 0 1 3 1 2 4 0 2 3 1 4 Index 11 12 13 14 15 16 17 18 19 20 21 ------------------------------------------------------------ Val 46 55 65 66 67 75 77 78 87 88 - Row 3 4 5 5 5 6 6 6 7 7 - Col 5 4 4 5 6 4 6 7 6 7 - |
for (k = 0; k < N; k = k + 1)
result[i] = 0;
for (k = 0; k < nnz; k = k + 1)
result[Row[k]] = result[Row[k]] + Val[k]*d[Col[k]];
|
class Vector
{
public:
double x[3];
Vector operator+(Vector &v)
{
Vector z;
int i;
for (i = 0; i < 3; i = i + 1)
z.x[i] = x[i] + v.x[i];
return(z);
}
}
|
class SparseMatrix
{
public:
int nnz;
double val[6];
int row[6];
int col[6];
Vector operator*(Vector &v)
{
Vector z;
int k;
for (k = 0; k < 3; k = k + 1)
z.x[k] = 0;
for (k = 0; k < nnz; k = k + 1)
z.x[row[k]] = z.x[row[k]] + val[k]*v.x[col[k]];
return z;
}
};
|
Vector Jacobi(SparseMatrix & P, SparseMatrix & Q, Vector b)
{
Vector v1, v2;
int i;
double d;
for (i = 0; i < 3; i = i + 1)
{ v1.x[i] = 0;
v2.x[i] = 1;
}
d = 0.1;
while ( d > 0.0001 )
{
v2 = P*v1 + Q*b;
d = distance(v1, v2);
v1 = v2;
}
return(v2);
}
|
Notice that
v2 = P*v1 + Q*b; |
will invoke the Matrix-vector multiply function defined in the class SparseMatrix
We CANNOT the first Jacobi function:
Vector Jacobi(DenseMatrix & P, DenseMatrix & Q, Vector b)
{
...
}
|
because the input parameters are of different type and therefore, different functions are invoked.
Vector Jacobi(Matrix P, Matrix Q, Vector b)
{
Vector v1, v2;
int i;
double d;
for (i = 0; i < 3; i = i + 1)
{ v1.x[i] = 0;
v2.x[i] = 1;
}
d = 0.1;
while ( d > 0.0001 )
{
v2 = P*v1 + Q*b;
d = distance(v1, v2);
v1 = v2;
}
return(v2);
}
|
This function that implements the Jacobi algorithm using a generic matrix-vector multiplication (and vector-vector addition) operations.
DenseMatrix P1, Q1; Vector sol, b; sol = Jacobi( P1, Q1, b); |
SparseMatrix P1, Q1; Vector sol, b; sol = Jacobi( P1, Q1, b); |
Nothing else need to be changed !!!
But before we can explain the technique, we need some background knowledge on derived classes and polymorphism.