Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Turbo Pascal / Учебники / Григорьев ''Основы Turbo Pascal''.rtf
Скачиваний:
85
Добавлен:
15.06.2014
Размер:
1.23 Mб
Скачать

Решение систем линейных алгебраических уравнений

Следующая группа вычислительных алгоритмов применяется для решения систем линейных алгебраических уравнений A·X=B. Для не слишком больших матриц применяют точный метод исключения Гаусса с выбором главного элемента. Система решается в два этапа: прямой ход приводит матрицу A к треугольному виду:

.

В начале каждого шага по k стрки расширенной матрицы системы переставляются таким образом, чтобы выполнилось условие

.

Обратный ход дает искомый вектор X :

.

Несколько модифицированный метод Гаусса можно с успехом применять для вычисления определителя и обратной матрицы. Запишем программу, реализующую этот метод:

CONST Nmax=40;

{Максимальный размер матрицы, вы можете выбрать другое число}

TYPE VectorType = ARRAY[1..Nmax] OF Real;

MatrixType = ARRAY[1..Nmax] OF VectorType;

FUNCTION Gauss( n : Byte {размер системы}; A : MatrixType {матрица системы};

B : VectorType {правые части}; VAR X : VectorType {вектор неизвестных}) : Boolean;

{ Функция будет возвращать TRUE, если систему удалось решить, и FALSE, если матрица системы вырождена }

VAR i,j,k,iMax : Byte; tmp,Max,d : Real; v : VectorType;

BEGIN FOR k:=1 TO n-1 DO BEGIN { прямой ход }

{ ищем главный элемент }

Max:=Abs(A[k,k]); iMax:=k;

FOR i:=k+1 TO n DO

IF Abs(A[i,k])>Max THEN BEGIN Max:=Abs(A[i,k]); iMax:=i; END;

IF Max=0 THEN BEGIN { матрица вырождена } Gauss:=FALSE; Exit; END;

IF iMax<>k THEN BEGIN { переставляем строки }

Tmp:=B[k]; B[k]:=B[iMax]; B[iMax]:=Tmp; v:=A[k]; A[k]:=A[iMax]; A[iMax]:=v; END;

FOR i:=k+1 TO n DO BEGIN {вычитаем из i-ой строки k-ю }

d:=A[i,k]/A[k,k];

FOR j:=k TO n DO A[i,j]:=A[i,j]-d*A[k,j];

B[i]:=B[i]-d*B[k]; END;

END;

{ сейчас матрица системы - треугольная }

IF A[n,n]=0 THEN BEGIN { матрица вырождена } Gauss:=FALSE; Exit; END;

{ обратный ход }

X[n]:=B[n]/A[n,n];

FOR i:=n-1 DOWNTO 1 DO BEGIN

tmp:=B[i];

FOR j:=i+1 TO n DO tmp:=tmp-A[i,j]*X[j];

X[i]:=tmp/A[i,i]; END;

Gauss:=TRUE;

END;

VAR n,i,j : Byte; a : MatrixType; b,x : VectorType;

BEGIN WRITE('Введите размер системы '); READ(n);

WRITELN('Введите расширенную матрицу системы');

FOR i:=1 TO n DO BEGIN

FOR j:=1 TO n DO READ(a[i,j]); READ(b[i]); END;

IF NOT Gauss(n,a,b,x) THEN BEGIN

WRITELN('Матрица системы вырождена'); Halt; END;

WRITELN('Решение системы и невязки :');

FOR i:=1 TO n DO BEGIN

FOR j:=1 TO n DO b[i]:=b[i]-a[i,j]*x[j];

WRITELN(x[i]:12,' ',b[i]:12); END;

END.

Хотя метод Гаусса и называют точным методом, невязки или погрешности, которые мы вывели в программе, не будут равны нулю. Но эти погрешности обусловлены не неточностью самого метода, а исключительно погрешностью вычисления арифметических операций.

Для очень больших систем, когда метод Гаусса становится неэффективным, применяют итерационные методы, например, метод простой итерации или метод Зейделя. Вычисления по методу простой итерации начинаются с произвольного вектора X0 ={x10, x20 ,..., xn0}. Итерационный процесс осуществляется по формуле:

,

т.е. все неизвестные на следующей итерации вычисляются только через неизвестные на предыдущей итерации.

В методе Зейделя используется итерационная формула

,

в которой при вычислении очередного неизвестного используются последние найденные значения остальных неизвестных. Вычисления заканчиваются, когда невязки системы становятся достаточно малыми. Итерационные методы сходятся не для всякой матрицы. Достаточным условием сходимости является положительная определенность матриц. Запишем программу, использующую метод простой итерации и метод Зейделя:

CONST Nmax=6;

TYPE VectorType = ARRAY[1..Nmax] OF Real;

MatrixType = ARRAY[1..Nmax] OF VectorType;

PROCEDURE SimpleIteration(n:Byte; A:MatrixType;B:VectorType;Epsilon:Real; VAR X:VectorType);

VAR i,k : Byte; X0 : VectorType; s,Max,Tmp : Real;

BEGIN X0:=X;

REPEAT

FOR i:=1 TO n DO BEGIN s:=B[i];

FOR k:=1 TO n DO s:=s-A[i,k]*X0[k]; X[i]:=X0[i]+s/A[i,i]; END;

{ Вычисляем максимальную невязку }

Max:=0;

FOR i:=1 TO n DO BEGIN Tmp:=Abs(X[i]-X0[i]);

IF Max<Tmp THEN Max:=Tmp; END;

X0:=X;

UNTIL Max<Epsilon;

END;

PROCEDURE Zeidel (n:Byte; A:MatrixType; B:VectorType; Epsilon:Real; VAR X:VectorType);

VAR i,k : Byte; s,Max,Tmp : Real;

BEGIN REPEAT Max:=0;

FOR i:=1 TO n DO BEGIN s:=B[i];

FOR k:=1 TO n DO s:=s-A[i,k]*X[k];

Tmp:=X[i]; X[i]:=X[i]+s/A[i,i];

Tmp:=Abs(X[i]-Tmp);

IF Max<Tmp THEN Max:=Tmp;

END;

UNTIL Max<Epsilon;

END;

CONST a : MatrixType = ( (110, 3, 4, -5, 16, 20), ( 1, 85, -6, 12, 11, -16), ( 24, -3, 54, -2, 0, 11),

( -8, 9, 0, 75, -9, 12), ( 0, 2, 3, -5, 98, 34), ( 16, 9, -4, -11, 0, 5));

b : VectorType = (100,200,300,400,500,600);

x0 : VectorType = (0,0,0,0,0,0);

CONST Eps = 1E-8;

VAR n,i,j : Byte; x : VectorType; d : Real;

BEGIN

n:=Nmax; x:=x0;

SimpleIteration(n,a,b,Eps,x);

WRITELN('Решение системы методом простой итерации и невязки:');

FOR i:=1 TO n DO BEGIN d:=b[i];

FOR j:=1 TO n DO d:=d-a[i,j]*x[j];

WRITELN(x[i]:12,' ',d:12); END;

x:=x0;

Zeidel(n,a,b,Eps,x);

WRITELN('Решение системы методом Зейделя и невязки :');

FOR i:=1 TO n DO BEGIN

d:=b[i]; FOR j:=1 TO n DO d:=d-a[i,j]*x[j];

WRITELN(x[i]:12,' ',d:12); END;

END.

Соседние файлы в папке Учебники