Tải bản đầy đủ (.pdf) (35 trang)

chương 10 giải hệ phương trình đại số tuyến tính

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (151.64 KB, 35 trang )


145
Chơng 10 : Giải hệ phơng trình đại số tuyến tính

Đ1.Phơng pháp Gauss

Có nhiều phơng pháp để giải một hệ phơng trình tuyến tính dạng AX = B. Phơng
pháp giải sẽ đơn giản hơn nếu ma trận A có dạng tam giác nghĩa là có dạng :










333231
2221
11
aaa
0aa
00a
hay











33
2322
131211
a00
aa0
aaa

Trong trờng hợp đầu tiên,ma trận đợc gọi là ma trận tam giác dới và trờng hợp
thứ hai ma trận đợc gọi là ma trận tam giác trên.Phơng trình tơng ứng với ma trận tam
giác dới có dạng tờng minh là :

11 1 2
3
1
21 1
2
32
31 1
23
3
0
0
0
22
32 33
ax x

x
b
ax
a
x
xb
ax
a
x
a
x
b
++ =
++=
++ =








Với phơng trình dạng này chúng ta sẽ giải phơng trình từ trên xuống.
Chơng trình giải phơng trình ma trận tam giác dới là :

Chơng trình 10-1

#include <conio.h>
#include <stdio.h>

#include <math.h>
#include <stdlib.h>
#include <ctype.h>
#define max 10

void main()
{
float a[max][max];
float b[max],x[max];
int i,j,k,n,t;
float s,c;
char tl;

clrscr();
printf("Cho so phuong trinh n = ");
scanf("%d",&n);
printf("Cho cac phan tu cua ma tran a\n");
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
{
printf("a[%d][%d] = ",i,j);
scanf("%f",&a[i][j]);
}
printf("\n");
printf("Ma tran a ma ban da nhap\n");
printf("\n");

146
for (i=1;i<=n;i++)
{

for (j=1;j<=n;j++)
printf("%15.5f",a[i][j]);
printf("\n");
}
printf("\n");
t=1;
flushall();
while (t)
{
printf("Co sua ma tran a khong(c/k)?");
scanf("%c",&tl);
if (toupper(tl)=='C')
{
printf("Cho chi so hang can sua : ");
scanf("%d",&i);
printf("Cho chi so cot can sua : ");
scanf("%d",&j);
printf("a[%d][%d] = ",i,j);
scanf("%f",&a[i][j]);
}
if (toupper(tl)=='K')
t=0;
}
printf("Ma tran a ban dau\n");
printf("\n");
for (i=1;i<=n;i++)
{
for (j=1;j<=n;j++)
printf("%15.5f",a[i][j]);
printf("\n");

}
printf("\n");
printf("Cho cac phan tu cua ma tran b\n");
for (i=1;i<=n;i++)
{
printf("b[%d] = ",i);
scanf("%f",&b[i]);
}
printf("\n");
printf("Ma tran b ma ban da nhap");
printf("\n");
for (i=1;i<=n;i++)
printf("b[%d] = %10.5f\n",i,b[i]);
printf("\n");
flushall();
t=1;
while (t)
{

147
printf("Co sua ma tran b khong(c/k)?");
scanf("%c",&tl);
if (toupper(tl)=='C')
{
printf("Cho chi so hang can sua : ");
scanf("%d",&i);
printf("b[%d] = ",i);
scanf("%f",&b[i]);
}
if (toupper(tl)=='K')

t=0;
}
printf("\n");
printf("Ma tran b ban dau");
printf("\n");
for (i=1;i<=n;i++)
printf("%15.5f\n",b[i]);
{
if (a[1][1]==0)
if (b[1]!=0)
printf("He da cho vo nghiem\n");
else
{
printf("He da cho co vo so nghiem");
x[n]=c;
}
else
x[1]=b[1]/a[1][1];
for (i=2;i<=n;i++)
{
s=0;
for (k=1;k<=i-1;k++)
s=s+a[i][k]*x[k];
x[i]=(b[i]-s)/a[i][i];
}
printf("\n");
printf("Nghiem cua he da cho la");
printf("\n");
for (i=1;i<=n;i++)
printf("x[%d] = %10.5f\n",i,x[i]);

getch();
}
}

Phơng trình tơng ứng với ma trận tam giác trên có dạng tờng minh là :

11 1
2
3
1
1
23
2
1
2
3
3
12
13
22 23
33
0
0
0
ax
a
x
a
x
b

x
a
x
a
x
b
x
x
a
x
b
++ =
++ =
++ =








Với phơng trình này chúng ta giải từ dới lên.

148
Ch−¬ng tr×nh gi¶i ph−¬ng tr×nh ma trËn tam gi¸c trªn lµ :

Ch−¬ng tr×nh 10-2

#include <conio.h>

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
#define max 10

void main()
{
float a[max][max];
float b[max],x[max];
int i,j,k,n,t;
float s,c;
char tl;


clrscr();
printf("Cho so phuong trinh n = ");
scanf("%d",&n);
printf("Cho cac phan tu cua ma tran a :\n");
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
{
printf("a[%d][%d] = ",i,j);
scanf("%f",&a[i][j]);
}
printf("\n");
printf("Ma tran a ma ban da nhap\n");
printf("\n");
for (i=1;i<=n;i++)
{

for (j=1;j<=n;j++)
printf("%15.5f",a[i][j]);
printf("\n");
}
printf("\n");
t=1;
flushall();
while (t)
{
printf("Co sua ma tran a khong(c/k)?");
scanf("%c",&tl);
if (toupper(tl)=='C')
{
printf("Cho chi so hang can sua : ");
scanf("%d",&i);

149
printf("Cho chi so cot can sua : ");
scanf("%d",&j);
printf("a[%d][%d] = ",i,j);
scanf("%f",&a[i][j]);
}
if (toupper(tl)=='K')
t=0;
}
printf("Ma tran a ban dau");
printf("\n");
for (i=1;i<=n;i++)
{
for (j=1;j<=n;j++)

printf("%15.5f",a[i][j]);
printf("\n");
}
printf("\n");
printf("Cho cac phan tu cua ma tran b : \n");
for (i=1;i<=n;i++)
{
printf("b[%d] = ",i);
scanf("%f",&b[i]);
}
printf("\n");
printf("Ma tran b ma ban da nhap");
printf("\n");
for (i=1;i<=n;i++)
printf("b[%d] = %10.5f\n",i,b[i]);
printf("\n");
flushall();
t=1;
while (t)
{
printf("Co sua ma tran b khong(c/k)?");
scanf("%c",&tl);
if (toupper(tl)=='C')
{
printf("Cho chi so hang can sua : ");
scanf("%d",&i);
printf("b[%d] = ",i);
scanf("%f",&b[i]);
}
if (toupper(tl)=='K')

t=0;
}
printf("\n");
printf("Ma tran b ban dau\n");
printf("\n");
for (i=1;i<=n;i++)
printf("b[%d] = %10.5f\n",i,b[i]);

150
printf("\n");
{
if (a[n][n]==0)
if (b[n]!=0)
printf("He da cho vo nghiem");
else
{
printf("He da cho co vo so nghiem");
x[n]=c;
}
else
x[n]=b[n]/a[n][n];
for (i=n-1;i>=1;i )
{
s=0;
for (k=i+1;k<=n;k++)
s=s+a[i][k]*x[k];
x[i]=(b[i]-s)/a[i][i];
}
printf("\n");
printf("Nghiem cua he da cho la\n");

printf("\n");
for (i=1;i<=n;i++)
printf("x[%d] = %10.5f\n",i,x[i]);
getch();
}
}

Tuy nhiên, các hệ phơng trình đơn giản hiếm khi gặp trong thực tế. Các hệ phơng
trình tuyến tính có thể biểu diễn dới dạng tam giác nếu định thức của nó khác không, nghĩa
là phơng trình có nghiệm.Chúng ta biết rằng các nghiệm của hệ không đổi nếu ta thay một
hàng bằng tổ hợp tuyến tính của các hàng khác.Nh vậy bằng một loạt các biến đổi ta có thể
đahệ ban đầu về dạng tam giác. Đó chính là nội dung của phơng pháp loại trừ Gauss.
Chúng ta hãy xét hệ phơng trình :

11 1
2
3
1
21 1
2
3
2
31 1
23
3
12
13
22
23
32 33

ax
a
x
a
x
b
ax
a
x
a
x
b
ax
a
x
a
x
b
++ =
++ =
++ =








Nhân hàng thứ nhất với a

21
/a
11
ta có :

21 1
21
11
12 2
21
11
13 3
21
11
1
ax
a
a
ax
a
a
ax
a
a
b
++=

Số hạng đầu của phơng trình bằng số hạng đầu của hàng thứ hai trong hệ phơng trình ban
đầu.Khi trừ hàng một đã đợc biến đổi cho hàng 2 ta nhận đợc hàng 2 mới


0
1
22
21
11
12
223
21
11
13
3
2
21
11
1
x
a
a
a
a
xa
a
a
a
x
b
a
a
b
+ + =

()()

Ta tiếp tục cách này để loại trừ x
1
ra khỏi hàng thứ 3.Phơng trình trở thành :

11 12 13
22 23
32 33
1
2
3
1
2
3
0
0
,, ,
,,
,,
,
'
,
aa a
aa
aa
x
x
x
b

b
b















































ì=


151
với a
,
11
= a
11
; a
,
12

= a
12
; a
,
13
= a
13
; a
,
13
= a
13
; b
,
1
= b
1


22 22
21
11
12
,
aa
a
a
a
=


23 23
21
11
13
,
aa
a
a
a
=

32 32
31
11
12
,
aa
a
a
a
=

33 33
31
11
13
,
aa
a
a

a
=

22
21
11
1
,
bb
a
a
b
=

33
31
11
1
,
bb
a
a
b
=

Ta loại trừ số hạng chứa x
3
trong dòng thứ 3 bằng cách tơng tự.Ta nhân hàng thứ 2 trong hệ
A
'

X = B
'
với a
,
32
/a
,
22
và đem trừ đi hàng thứ 3 trong hệ mới.Nh vậy số hạng chứa x
3
biến
mất và ta nhận đợc ma trận tam giác trên.

11 12 13
22 23
33
1
2
3
1
2
3
0
0
0
,, ,, ,,
,, ,,
,,
,,
,,

,,
aa a
aa
a
x
x
x
b
b
b















































ì=

với
11 11

,, ,
aa
=

12 12
,, ,
aa
=

13 13
,, ,
aa
=

11
,, ,
bb
=

22 22
,, ,
aa
=

23 23
,, ,
aa
=

22

,, ,
bb
=


33 33
32
22
23
,, ,
,
,
,
aa
a
a
a
=

33
33
22
2
,, ,
,
,
,
bb
a
a

b
=

Các phép tính này chỉ thực hiện đợc khi a
11
0 và a
,
11
0.
Với một hệ có n phơng trình,thuật tính hoàn toàn tơng tự.Sau đây là chơng trình
giải hệ phơng trình n ẩn số bằng phơng pháp loại trừ Gauss.

Chơng trình 10-3

#include <conio.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
#define max 10

void main()
{
float b[max],x[max];
float a[max][max];
int i,j,k,n,t;
float c,s,d;
char tl;

clrscr();

printf("Cho so phuong trinh n = ");
scanf("%d",&n);
printf("Cho cac phan tu cua ma tran a :\n");
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
{
printf("a[%d][%d] = ",i,j);
scanf("%f",&a[i][j]);
}
printf("\n");
printf("Ma tran a ma ban da nhap\n");
printf("\n");

152
for (i=1;i<=n;i++)
{
for (j=1;j<=n;j++)
printf("%15.5f",a[i][j]);
printf("\n");
}
printf("\n");
t=1;
flushall();
while (t)
{
printf("Co sua ma tran a khong(c/k)?");
scanf("%c",&tl);
if (toupper(tl)=='C')
{
printf("Cho chi so hang can sua : ");

scanf("%d",&i);
printf("Cho chi so cot can sua : ");
scanf("%d",&j);
printf("a[%d][%d] = ",i,j);
scanf("%f",&a[i][j]);
}
if (toupper(tl)=='K')
t=0;
}
printf("Ma tran a ban dau\n");
printf("\n");
for (i=1;i<=n;i++)
{
for (j=1;j<=n;j++)
printf("%15.5f",a[i][j]);
printf("\n");
}
printf("\n");
printf("Cho cac phan tu cua ma tran b : \n");
for (i=1;i<=n;i++)
{
printf("b[%d] = ",i);
scanf("%f",&b[i]);
}
printf("\n");
printf("Ma tran b ma ban da nhap\n");
printf("\n");
for (i=1;i<=n;i++)
printf("b[%d] = %15.5f\n",i,b[i]);
printf("\n");

flushall();
t=1;
while (t)
{

153
printf("Co sua ma tran b khong(c/k)?");
scanf("%c",&tl);
if (toupper(tl)=='C')
{
printf("Cho chi so hang can sua : ");
scanf("%f",&i);
printf("b[%d] = ",i);
scanf("%f",&b[i]);
}
if (toupper(tl)=='K')
t=0;
}
printf("\n");
printf("Ma tran b\n");
for (i=1;i<=n;i++)
printf("b[%d] = %15.5f\n",i,b[i]);
printf("\n");
for (k=1;k<=n-1;k++)
{
for (i=k+1;i<=n;i++)
{
b[i]=b[i]-b[k]*a[i][k]/a[k][k];
for (j=k+1;j<=n;j++)
a[i][j]=a[i][j]-a[k][j]*a[i][k]/a[k][k];

}
}

{
if (a[n][n]==0)
if (b[n]==0)
printf("He da cho vo nghiem");
else
{
printf("He da cho co vo so nghiem");
x[n]=c;
}
else
x[n]=b[n]/a[n][n];
for (i=n-1;i>=1;i )
{
s=0;
for (k=i+1;k<=n;k++)
s=s+a[i][k]*x[k];
x[i]=(b[i]-s)/a[i][i];
}
printf("\n");
printf("Nghiem cua he da cho la\n");
printf("\n");
for (i=1;i<=n;i++)
printf("x[%d] = %15.5f\n",i,x[i]);

154
getch();
}

}


Đ2.Phơng pháp Gauss-Jordan

Xét hệ phơng trình AX=B. Khi giải hệ bằng phơng pháp Gauss ta đa nó về dạng
ma trận tam giác sau một loạt biến đổi. Phơng pháp khử Gauss-Jordan cải tiến khử Gauss
bằng cách đa hệ về dạng :
EX = B
*

và khi đó nghiệm của hệ chính là B
*
.Trong phơng pháp Gauss-Jordan mỗi bớc tính phải
tính nhiều hơn phơng pháp Gauss nhng lại không phải tính nghiệm.Để đa ma trận A về
dạng ma trận E tại bớc thứ i ta phải có a
ii
= 1 và a
ij
=0.Nh vậy tại lần khử thứ i ta biến đổi :
1.a
ij
= a
ij
/a
ii
(j=i+1,i+2, ,n)
2.k=1,2, ,n
a
kj

= a
kj
- a
ij
a
ki
(j=i+1,i+2, ,n)
b
k
= b
k
- b
i
a
ki


Ví dụ : Cho hệ










=













ì










21
26
32
24
x
x
x
x

9440
45.652
45104
0248
4
3
2
1

Biến đổi lần 1 : ta chia hàng 1 cho a
11
= 8;nhân hàng 1 vừa nhận đợc với 4 và lấy hàng 2
trừ đi; nhân hàng 1 vừa nhận đợc với 2 và lấy hàng 3 trừ đi;giữ nguyên hàng 4 vì phần tử
đầu tiên đã bằng 0 ta có











=













ì










21
20
20
3
x
x
x
x
9440
4640
4480

025.05.01
4
3
2
1

Biến đổi lần 2 : ta chia hàng 2 cho a
22
= 8;nhân hàng 2 vừa nhận đợc với 0.5 và lấy hàng 1
trừ đi; nhân hàng 2 vừa nhận đợc với 4 và lấy hàng 3 trừ đi; nhân hàng 2 vừa nhận đợc với
4 và lấy hàng 4 trừ đi ta có :











=













ì











11
10
5.2
75.1
x
x
x
x
7200
2400
5.05.010
25.0001
4

3
2
1


Biến đổi lần 3 : ta chia hàng 3 cho a
33
= 4;giữ nguyên hàng 1;nhân hàng 3 vừa nhận đợc
với 0.5 và lấy hàng 2 trừ đi; nhân hàng 3 vừa nhận đợc với 2 và lấy hàng 4 trừ đi ta có :











=













ì











6
5.2
25.1
75.1
x
x
x
x
6000
5.0100
25.0010
25.0001
4
3
2

1


155
BiÕn ®æi lÇn 4 : ta chia hµng 4 cho a
44
= 6;nh©n hµng 4 võa nhËn ®−îc víi -0.25 vµ lÊy hµng
1 trõ ®i; nh©n hµng 4 võa nhËn ®−îc víi 0.25 vµ lÊy hµng 2 trõ ®i; nh©n hµng 4 võa nhËn
®−îc víi 0.5 vµ lÊy hµng 3 trõ ®i ta cã :











=













×










1
2
1
2
x
x
x
x
1000
0100
0010
0001
4
3
2
1


vµ ta cã ngay vec t¬ nghiÖm.

Ch−¬ng tr×nh10-4

#include <conio.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
#define spt 10

void main()
{
float a[spt][2*spt];
float b[spt];
int i,j,k,n,m,t;
float max,c;
char tl;

clrscr();
printf("Cho so phuong trinh n = ");
scanf("%d",&n);
printf("Cho cac phan tu cua ma tran a :\n");
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
{
printf("a[%d][%d] = ",i,j);
scanf("%f",&a[i][j]);
}

printf("\n");
printf("Ma tran a ma ban da nhap");
printf("\n");
for (i=1;i<=n;i++)
{
for (j=1;j<=n;j++)
printf("%15.5f",a[i][j]);
printf("\n");
}
printf("\n");
t=1;
flushall();

156
while (t)
{
printf("Co sua ma tran a khong(c/k)?");
scanf("%c",&tl);
if (toupper(tl)=='C')
{
printf("Cho chi so hang can sua : ");
scanf("%d",&i);
printf("Cho chi so cot can sua : ");
scanf("%d",&j);
printf("a[%d][%d] = ",i,j);
scanf("%f",&a[i][j]);
}
if (toupper(tl)=='K')
t=0;
}

printf("Ma tran a\n");
printf("\n");
for (i=1;i<=n;i++)
{
for (j=1;j<=n;j++)
printf("%15.5f",a[i][j]);
printf("\n");
}
printf("\n");
printf("Cho cac phan tu cua ma tran b : \n");
for (i=1;i<=n;i++)
{
printf("b[%d] = ",i);
scanf("%f",&b[i]);
}
printf("\n");
printf("Ma tran b ma ban da nhap\n");
printf("\n");
for (i=1;i<=n;i++)
printf("b[%d] = %15.5f\n",i,b[i]);
printf("\n");
t=1;
flushall();
while (t)
{
printf("Co sua ma tran b khong(c/k)?");
scanf("%c",&tl);
if (toupper(tl)=='C')
{
printf("Cho chi so hang can sua : ");

scanf("%d",&i);
printf("b[%d] = ",i);
scanf("%f",&b[i]);
}

157
if (toupper(tl)=='K')
t=0;
}
printf("\n");
printf("Ma tran b\n");
printf("\n");
for (i=1;i<=n;i++)
printf("%15.5f\n",b[i]);
printf("\n");
t=1;
flushall();
i=1;
while (t)
{
if (a[i][i]==0)
{
max=0;
m=i;
for (k=i+1;k<=n;k++)
if (max<fabs(a[k][i]))
{
m=k;
max=fabs(a[i][i]);
}

if (m!=i)
{
for (j=i;j<=n;j++)
{
c=a[i][j];
a[i][j]=a[m][j];
a[m][j]=c;
}
c=b[i];
b[i]=b[m];
b[m]=c;
}
if (m==i)
{
t=0;
printf("MA TRAN SUY BIEN");
}
}
if (a[i][i]!=0)
{
c=1/a[i][i];
for (j=i;j<=n;j++)
a[i][j]=a[i][j]*c;
b[i]=b[i]*c;
for (k=1;k<=n;k++)
if (k!=i)

158
{
c=a[k][i];

for (j=i;j<=n;j++)
a[k][j]=a[k][j]-a[i][j]*c;
b[k]=b[k]-b[i]*c;
}
}
i=i+1;
if (i==(n+1))
t=0;
}
if (i==(n+1))
{
printf("NGHIEM CUA HE");
printf("\n");
for (i=1;i<=n;i++)
printf("x[%d] = %15.5f\n",i,b[i]);
}
getch();
}


Đ3.Phơng pháp Cholesky

Trong phơng pháp Cholesky một ma trận đối xứng A đợc phân tích thành dạng A =
R
T
R trong đó R là một ma trận tam giác trên.Hệ phơng trình lúc đó chuyển thành AX =
R
T
RX = B.Nh vậy trớc hết ta phân tích ma trận A thành tích hai ma trận.Sau đó giải hệ
phơng trình R

T
Y = B và cuối cùng là hệ RX = Y.Chơng trình mô tả thuật toán này đợc
cho dới đây :

Chơng trình 10-5

#include <conio.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
#define max 6

void main()
{
float a[max][max],r[max][max];
float b[max],x[max],y[max];
int i,j,k,l,n,t;
float s;
char tl;

clrscr();
printf("Cho so phuong trinh n = ");

159
scanf("%d",&n);
printf("Cho cac phan tu cua ma tran a : \n");
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
{

printf("a[%d][%d] = ",i,j);
scanf("%f",&a[i][j]);
}
printf("\n");
printf("Ma tran a ma ban da nhap\n");
printf("\n");
for (i=1;i<=n;i++)
{
for (j=1;j<=n;j++)
printf("%15.5f",a[i][j]);
printf("\n");
}
printf("\n");
flushall();
t=1;
while (t)
{
printf("Co sua ma tran a khong(c/k)?");
scanf("%c",&tl);
if (toupper(tl)=='C')
{
printf("Cho chi so hang can sua : ");
scanf("%d",&i);
printf("Cho chi so cot can sua : ");
scanf("%d",&j);
printf("a[",i,",",j,"] = ");
scanf("%f",&a[i][j]);
}
if (toupper(tl)=='K')
t=0;

}
printf("Ma tran a\n");
printf("\n");
for (i=1;i<=n;i++)
{
for (j=1;j<=n;j++)
printf("%15.5f",a[i][j]);
printf("\n");
}
printf("\n");
printf("Cho cac phan tu cua ma tran b : \n");
for (i=1;i<=n;i++)
{
printf("b[%d] = ",i);
scanf("%f",&b[i]);

160
}
printf("\n");
printf("Ma tran b ma ban da nhap\n");
printf("\n");
for (i=1;i<=n;i++)
printf("b[%d] = %15.5f\n",i,b[i]);
printf("\n");
flushall();
t=1;
while (t)
{
printf("Co sua ma tran b khong(c/k)?");
scanf("%c",&tl);

if (toupper(tl)=='C')
{
printf("Cho chi so hang can sua : ");
scanf("%d",&i);
printf("b[%d] = ",i);
scanf("%f",&b[i]);
}
if (toupper(tl)=='K')
t=0;
}
printf("\n");
printf("Ma tran b\n");
printf("\n");
for (i=1;i<=n;i++)
printf("b[%d] = %15.5f\n",i,b[i]);
printf("\n");
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
r[i][j]=0.0;
for (i=1;i<=n;i++)
{
if (a[i][i]>=0)
{
r[i][i]=sqrt(a[i][i]);
for (j=1+i;j<=n;j++)
r[i][j]=a[i][j]/r[i][i];
for (k=i+1;k<=n;k++)
for (l=k;l<=n;l++)
a[k][l]=a[k][l]-r[i][k]*r[i][l];
}

}
for (k=1;k<=n;k++)
{
s=b[k];
if (k!=1)
for (i=1;i<=k-1;i++)
s=s+r[i][k]*y[i];

161
y[k]=-s/r[k][k];
}
for (i=n;i>=1;i )
{
s=-y[i];
if (i!=n)
for (k=i+1;k<=n;k++)
s=s-r[i][k]*x[k];
x[i]=s/r[i][i];
}
printf("Nghiem cua he phuong trinh la\n ");
for (i=1;i<=n;i++)
printf("x[%d] = %10.5f\n",i,x[i]);
getch();
}


Đ4.Phơng pháp Crout

Phơng pháp Crout là một dạng của phơng pháp Gauss.Với phơng pháp
Gauss,chúng ta biến đổi ma trận A thành một ma trận tam giác thì ở phơng pháp Crout

chúng ta phân tích ma trận này thành tích của ma trận tam giác trên R và ma trận tam giác
dới L.Trong ma trận L,các hệ số trên đờng chéo chính bằng 1.Nh vậy phơng trình AX =
B đợc viết thành :
A.X = L.R.X = B
Chúng ta đặt RX = Y
nên : LY = B
Nh vậy trớc hết chúng ta phân tích ma trận thành tích của L.R.Tiếp theo ta giải phơng
trình LY = B và sau đó giải phơng trình RX = A để tìm nghiệm X.

Chơng trình 10-6

#include <conio.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
#define max 6

void main()
{
float b[max],x[max],y[max];
float a[max][max],r[max][max],l[max][max];
int i,j,k,n,t;
float c,tr,tl,s;
char tloi;

clrscr();
printf("Cho so phuong trinh n = ");

162

scanf("%d",&n);
printf("Cho cac phan tu cua ma tran a : \n");
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
{
printf("a[%d][%d] = ",i,j);
scanf("%f",&a[i][j]);
}
printf("\n");
printf("Ma tran a ma ban da nhap");
printf("\n");
for (i=1;i<=n;i++)
{
for (j=1;j<=n;j++)
printf("%10.5f",a[i][j]);
printf("\n");
}
printf("\n");
t=1;
flushall();
while (t)
{
printf("Co sua ma tran a khong(c/k)?");
scanf("%c",&tloi);
if (toupper(tloi)=='C')
{
printf("Cho chi so hang can sua : ");
scanf("%d",&i);
printf("Cho chi so cot can sua : ");
scanf("%d",&j);

printf("a[%d][%d] = ",i,j);
scanf("%f",&a[i][j]);
flushall();
}
if (toupper(tloi)=='K')
t=0;
}
printf("Ma tran a\n");
printf("\n");
for (i=1;i<=n;i++)
{
for (j=1;j<=n;j++)
printf("%10.5f",a[i][j]);
printf("\n");
}
printf("\n");
printf("Cho cac phan tu cua ma tran b : \n");
for (i=1;i<=n;i++)
{
printf("b[%d] = ",i);

163
scanf("%f",&b[i]);
}
printf("\n");
printf("Ma tran b ma ban da nhap");
printf("\n");
for (i=1;i<=n;i++)
printf("b[%d] = %10.5f\n",i,b[i]);
printf("\n");

t=1;
flushall();
while (t)
{
printf("Co sua ma tran b khong(c/k)?");
scanf("%c",&tloi);
if (toupper(tloi)=='C')
{
printf("Cho chi so hang can sua : ");
scanf("%d",&i);
printf("b[%d] = ",i);
scanf("%f",&b[i]);
flushall();
}
if (toupper(tloi)=='K')
t=0;
}
printf("\n");
printf("Ma tran b\n");
printf("\n");
for (i=1;i<=n;i++)
printf("b[%d] = %10.5f\n",i,b[i]);
printf("\n");
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
r[i][j]=0.0;
l[i][j]=0.0;
}
for (i=1;i<=n;i++)

{
r[1][i]=a[1][i];
l[i][i]=1.0;
l[i][1]=a[i][1]/a[1][1];
}
for (k=2;k<=n;k++)
{
for (j=k;j<=n;j++)
{
tr=0.0;
for (i=1;i<=k;i++)
tr=tr+l[k][i]*r[i][j];

164
r[k][j]=a[k][j]-tr;
}
if (k!=n)
{
for (i=1;i<=n;i++)
{
tl=0.0;
for (j=1;j<=k-1;j++)
tl=tl+l[i][j]*r[j][k];
l[i][k]=(a[i][k]-tl)/r[k][k];
}
}
else
printf("\n");
}
if (l[1][1]==0.0)

if (b[1]==0.0)
printf("He da cho vo nghiem\n");
else
{
printf("He da cho co vo so nghiem\n");
y[n]=c;
}
else
y[1]=b[1]/l[1][1];
for (i=2;i<=n;i++)
{
s=0.0;
for (k=1;k<=i-1;k++)
s=s+l[i][k]*y[k];
y[i]=(b[i]-s)/l[i][i];
}
if (r[n][n]==0.0)
if (y[n]==0.0)
printf("He da cho vo nghiem\n");
else
{
printf("He da cho co vo so nghiem\n");
x[n]=c;
}
else
x[n]=y[n]/r[n][n];
for (i=n-1;i>=1;i )
{
s=0.0;
for (k=i+1;k<=n;k++)

s+=r[i][k]*x[k];
x[i]=(y[i]-s)/r[i][i];
}
printf("\n");

165
printf("Nghiem cua he da cho la\n");
printf("\n");
for (i=1;i<=n;i++)
printf("x[%d] = %15.5f\n",i,x[i]);
getch();
}


Đ5.Phơng pháp lặp đơn

Xét hệ phơng trình AX = F.Bằng cách nào đó ta đa hệ phơng trình về dạng
X = BX + G
trong đó B = (b
ij
)
n,n

G = (g
1
,g
2
, ,g
n
)

T

Chọn vectơ X = ( x
1
(o)
,x
2
(o)
, ,x
n
(o)
)
T

làm xấp xỉ thứ 0 của nghiệm đúng và xây dựng xấp xỉ
X
(m+1)
= BX
(m)
+ G ( m = 0,1, )
Ngời ta chứng minh rằng nếu phơng trình ban đầu có nghiệm duy nhất và một
trong ba chuẩn của ma trận B nhỏ hơn 1 thì dãy xấp xỉ hội tụ về nghiệm duy nhất đó.(Cho
một ma trận B,chuẩn của ma trận B,kí hiệu là || B || là một trong 3 số :

1
1
B
b
i
ij

j
n
=
=

max


2
1
B
b
ji
ij
i
n
=
=

max


3
12
1
2
1
B
b
i

n
ij
j
n
=
==

/
()

(Chuẩn của ma trận quan hệ tới sự hội tụ của phơng pháp lặp)
Ví dụ chúng ta có phơng trình

1
23
1
2
3
12
3
10
2
10
10
2
12
10 8
x
xx
x

x
x
xx
x
++=
++=
++=








Chúng ta đa phơng trình về dạng :

123
213
312
1
5
1
10
1
1
10
1
5
6

5
1
10
1
10
4
5
xxx
xxx
xxx
= +
= +
= +














Nh vậy :

B =






















0
1
5
1
10
1
10
0
1

5
1
10
1
10
0
và G =
















1
5
6
4
5

Dễ thấy || B ||

1
= 3/10 ; || B ||
2
= 3/10 và || B ||
3
= 12/100 nên phép lặp hội tụ .Chơng trình lặp
đơn là :

166
Ch−¬ng tr×nh 10-7

#include <conio.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
#define max 10

void main()
{
float a[max][max];
float f[max],x0[max],x1[max];
int i,j,k,n,l,t;
float s,c,epsi;
char tl;

clrscr();
printf("Cho so phuong trinh n = ");
scanf("%d",&n);
printf("Cho cac phan tu cua ma tran a : \n");

for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
{
printf("a[%d][%d] = ",i,j);
scanf("%f",&a[i][j]);
}
printf("\n");
printf("Ma tran a ma ban da nhap");
printf("\n");
for (i=1;i<=n;i++)
{
for (j=1;j<=n;j++)
printf("%15.5f",a[i][j]);
printf("\n");
}
printf("\n");
t=1;
flushall();
while (t)
{
printf("Co sua ma tran a khong(c/k)?");
scanf("%c",&tl);
if (toupper(tl)=='C')
{
printf("Cho chi so hang can sua : ");
scanf("%d",&i);
printf("Cho chi so cot can sua : ");
scanf("%d",&j);
printf("a[%d][%d] = ",i,j);


167
scanf("%f",&a[i][j]);
flushall();
}
if (toupper(tl)=='K')
t=0;
}
printf("Ma tran a\n");
printf("\n");
for (i=1;i<=n;i++)
{
for (j=1;j<=n;j++)
printf("%10.5f",a[i][j]);
printf("\n");
}
printf("\n");
printf("Cho cac phan tu cua ma tran f : \n");
for (i=1;i<=n;i++)
{
printf("f[%d] = ",i);
scanf("%f",&f[i]);
}
printf("\n");
printf("Ma tran f ma ban da nhap");
printf("\n");
for (i=1;i<=n;i++)
printf("f[%d] = %10.5f\n",i,f[i]);
printf("\n");
t=1;
flushall();

while (t)
{
printf("Co sua ma tran f khong(c/k)?");
scanf("%c",&tl);
if (toupper(tl)=='C')
{
printf("Cho chi so hang can sua : ");
scanf("%d",&i);
printf("f[%d] = ",i);
scanf("%f",&f[i]);
flushall();
}
if (toupper(tl)=='K')
t=0;
}
printf("\n");
printf("Ma tran f");
printf("\n");
for (i=1;i<=n;i++)
printf("f[%d] = %10.5f\n",i,f[i]);
printf("\n");

168
for (i=1;i<=n;i++)
x0[i]=0.0;
x0[1]=1.0;
printf("Cho so lan lap l = ");
scanf("%d",&l);
epsi=1e-5;
for (i=1;i<=n;i++)

{
c=1.0/a[i][i];
for (j=1;j<=n;j++)
if (j!=i)
a[i][j]*=c;
f[i]*=c;
a[i][i]=0.0;
}
k=1;
t=0;
do
{
for (i=1;i<=n;i++)
{
x1[i]=f[i];
for (j=1;j<=n;j++)
x1[i]=x1[i]-a[i][j]*x0[j];
}
s=0.0;
for (i=1;i<=n;i++)
s=s+fabs(x1[i]-x0[i]);
if (s>=epsi)
for (i=1;i<=n;i++)
x0[i]=x1[i];
if (s<epsi)
{
t=1;
printf("\n");
printf("Phep lap hoi tu sau %d buoc tinh",k);
printf("\n");

printf("NGHIEM CUA HE");
printf("\n");
for (i=1;i<=n;i++)
printf("x[%d] = %10.5f\n",i,x1[i]);
}
k=k+1;
if (k>l)
{
t=1;
printf("Phep lap khong hoi tu sau %d buoc tinh",k-1);
}
}
while (t==0);

169
getch();
}


Đ6. Phơng pháp lặp Gauss-Seidel

Phơng pháp lặp Gauss-Seidel đợc cải tiến từ phơng pháp lặp đơn . Nội dung cơ
bản của phơng pháp là ở chỗ khi tính nghiệm xấp xỉ thứ (k+1) của ẩn x
i
ta sở dụng các xấp
xỉ thứ (k+1) đã tính của các ẩn x
1
, ,x
i-1
.Giả sử đã cho hệ : AX = B và ta có nghiệm :


i
i
ij
j
n
j
xx
in
=+
=

=

1
1( , , )

Lấy xấp xỉ ban đầu tuỳ ý x
1
(o)
, x
2
(o)
, , x
n
(o)

và tất nhiên ta cố gắng lấy chúng tơng ứng với
x
1

,x
2
, ,x
n
(càng gần càng tốt). Tiếp theo ta giả sử rằng đã biết xấp xỉ thứ k x
i
(k)
của nghiệm
. Theo Seidel ta sẽ tìm xấp xỉ thứ (k+1) của nghiệm theo các công thức sau :

1
1
1
1
1
() ()k
j
j
n
j
k
xx
+
=
=+






2
1
2
1
1
2
2
21
()
()
()k
k
j
j
n
j
k
x
x
x
+
+
=
=+ +








i
k
i
ij
j
i
j
k
ij
j
n
j
k
xxx
() () ()+
=

+
=
=+ +

1
1
1
1
1






ni
k
n
ij
j
n
j
k
nn
n
k
xxx
() () ()+
=

+
=+ +

1
1
1
1



Thông thờng phơng pháp Gauss - Seidel hội tụ nhanh hơn phơng pháp lặp đon
nhng tính toán phức tạp hơn.Dể dễ hiểu phơng pháp này chúng ta xét một ví dụ cụ thể :
Cho hệ phơng trình :


1
23
1
2
3
12
3
10 12
2
10 13
22
10 14
x
xx
x
x
x
xx
x
++=
++=
++=









nghiệm đúng của hệ là (1 , 1, 1)
Ta đa về dạng thuận tiện cho phép lặp :

123
213
322
12
01 01
13
02 01
14
02 02
xxx
xxx
xxx
=
=
=







,

,


,


Lấy x
1
(o)
= 1.2 ; x
2
(o)
= 0 ; x
3
(o)
= 0;
Sử dụng phơng pháp lặp Seidel ta có :






=ìì=
=ìì=
=ìì=
948.006.12.02.12.04.1x
06.101.02.12.03.1x
2.101.001.02.1x
1
3
1
2

1
1



1
2
2
2
3
2
12
01 106 01 0 948 0 9992
13
0 2 0 9992 01 0 948 100536
14
0 2 0 9992 0 2 100536 0 999098
x
x
x
= =
= =
= =










ìì
ìì
ìì
,
. . .
,
.
,
.

và cứ thế tiếp tục . Chơng trình mô tả thuật toán Gauss - Seidel nh sau :

×