Compare Methods of Jacobi with Gauss-Seidel
Use Jacobi and Gauss-Seidel methods to solve a given n×n linear system Ax=b with an initial approximation x(0) .
Note: When checking each aii , first scan downward for the entry with maximum absolute value (aii included). If that entry is non-zero, swap it to the diagonal. Otherwise if that entry is zero, scan upward for the entry with maximum absolute value. If that entry is non-zero, then add that row to the i-th row.
Format of functions:
int Jacobi( int n, double a[][MAX_SIZE], double b[], double x[], double TOL, int MAXN );
int Gauss_Seidel( int n, double a[][MAX_SIZE], double b[], double x[], double TOL, int MAXN );
The function must return:
- k if there is a solution found after k iterations;
- 0 if maximum number of iterations exceeded;
- -1 if the matrix has a zero column and hence no unique solution exists;
- -2 if there is no convergence, that is, there is an entry of x(K) that is out of the range [-bound, bound] where bound is a constant defined by the judge.
Sample program of judge:
#include <stdio.h>
#include <math.h>
#define MAX_SIZE 10
#define bound pow(2, 127)
#define ZERO 1e-9 /* X is considered to be 0 if |X|<ZERO */
enum bool { false = 0, true = 1 };
#define bool enum bool
int Jacobi( int n, double a[][MAX_SIZE], double b[], double x[], double TOL, int MAXN );
int Gauss_Seidel( int n, double a[][MAX_SIZE], double b[], double x[], double TOL, int MAXN );
int main()
{
int n, MAXN, i, j, k;
double a[MAX_SIZE][MAX_SIZE], b[MAX_SIZE], x[MAX_SIZE];
double TOL;
scanf("%d", &n);
for (i=0; i<n; i++) {
for (j=0; j<n; j++)
scanf("%lf", &a[i][j]);
scanf("%lf", &b[i]);
}
scanf("%lf %d", &TOL, &MAXN);
printf("Result of Jacobi method:\n");
for ( i=0; i<n; i++ )
x[i] = 0.0;
k = Jacobi( n, a, b, x, TOL, MAXN );
switch ( k ) {
case -2:
printf("No convergence.\n");
break;
case -1:
printf("Matrix has a zero column. No unique solution exists.\n");
break;
case 0:
printf("Maximum number of iterations exceeded.\n");
break;
default:
printf("no_iteration = %d\n", k);
for ( j=0; j<n; j++ )
printf("%.8f\n", x[j]);
break;
}
printf("Result of Gauss-Seidel method:\n");
for ( i=0; i<n; i++ )
x[i] = 0.0;
k = Gauss_Seidel( n, a, b, x, TOL, MAXN );
switch ( k ) {
case -2:
printf("No convergence.\n");
break;
case -1:
printf("Matrix has a zero column. No unique solution exists.\n");
break;
case 0:
printf("Maximum number of iterations exceeded.\n");
break;
default:
printf("no_iteration = %d\n", k);
for ( j=0; j<n; j++ )
printf("%.8f\n", x[j]);
break;
}
return 0;
}
/* Your function will be put here */
Sample Input 1:
3
2 -1 1 -1
2 2 2 4
-1 -1 2 -5
0.000000001 1000
Sample Output 1:
Result of Jacobi method:
No convergence.
Result of Gauss-Seidel method:
no_iteration = 37
1.00000000
2.00000000
-1.00000000
Sample Input 2:
3
1 2 -2 7
1 1 1 2
2 2 1 5
0.000000001 1000
Sample Output 2:
Result of Jacobi method:
no_iteration = 232
1.00000000
2.00000000
-1.00000000
Result of Gauss-Seidel method:
No convergence.
Sample Input 3:
5
2 1 0 0 0 1
1 2 1 0 0 1
0 1 2 1 0 1
0 0 1 2 1 1
0 0 0 1 2 1
0.000000001 100
Sample Output 3:
Result of Jacobi method:
Maximum number of iterations exceeded.
Result of Gauss-Seidel method:
no_iteration = 65
0.50000000
0.00000000
0.50000000
0.00000000
0.50000000
基本的Jacobi和Gauss-Seidel迭代的应用,分别如下:
注意在实际代码中不宜选择矩阵形式,因为计算很复杂。
My Answer:
/* Your function will be put here */
#define max(a,b) ((a)>(b)?(a):(b))
#include <stdlib.h>
bool ZeroConlumn(double a[][MAX_SIZE], int n)
{
for (int j = 0; j < n; j++) {
bool allzero = true;
for (int i = 0; i < n; i++) {
if (a[i][j] != 0) {
allzero = false;
break;
}
}
if (allzero)return true;
}
return false;
}
bool NoConverge(double x[], int n)
{
for (int i = 0; i < n; i++)
if (x[i] > bound || x[i] < -bound) return true;
return false;
}
void Swap(double a[], double b[], int n)
{
double* t = (double*)malloc(n * sizeof(double));
for (int i = 0; i < n; i++) {
t[i] = a[i]; a[i] = b[i]; b[i] = t[i];
}
}
double DiffNorm(double a[], double b[], int n)
{
double m = 0.0;
for (int i = 0; i < n; i++)
m = max(m, fabs(a[i] - b[i]));
return m;
}
int Jacobi(int n, double a[][MAX_SIZE], double b[], double x[], double TOL, int MAXN)
{
if (ZeroConlumn(a, n))return -1;
double* x1 = (double*)malloc(n * sizeof(double));
double* x2 = (double*)malloc(n * sizeof(double));
for (int i = 0; i < n; i++) x1[i] = x[i];
int k;
double sum;
for (k = 0; k < MAXN; k++) {
for (int i = 0; i < n; i++) {
sum = 0;
for (int j = 0; j < n; j++) {
if (j == i)continue;
sum += a[i][j] * x1[j];
}
x2[i] = (b[i] - sum) / a[i][i];
}
if (DiffNorm(x2, x1, n) < TOL) { // find the solution
for (int cnt = 0; cnt < n; cnt++) x[cnt] = x2[cnt];
return k + 1;
}
if (NoConverge(x2, n))return -2;
Swap(x1, x2, n);
}
if (NoConverge(x1, n))return -2;
if (k == MAXN)return 0;
}
int Gauss_Seidel(int n, double a[][MAX_SIZE], double b[], double x[], double TOL, int MAXN)
{
if (ZeroConlumn(a, n))return -1;
double* x1 = (double*)malloc(n * sizeof(double));
double* x2 = (double*)malloc(n * sizeof(double));
for (int i = 0; i < n; i++) x1[i] = x[i];
int k;
double sum;
for (k = 0; k < MAXN; k++) {
for (int i = 0; i < n; i++) {
sum = 0;
for (int j = 0; j < n; j++)
{
if (j < i) sum += a[i][j] * x2[j];
if (j > i) sum += a[i][j] * x1[j];
}
x2[i] = (b[i] - sum) / a[i][i];
}
if (DiffNorm(x2, x1, n) < TOL) { // find the solution
for (int cnt = 0; cnt < n; cnt++) x[cnt] = x2[cnt];
return k + 1;
}
if (NoConverge(x2, n))return -2;
Swap(x1, x2, n);
}
if (NoConverge(x1, n))return -2;
if (k == MAXN)return 0;
}