program SimpleIterationMethod;
uses
Math;
const
EPS = 1e-12; // Точность вычислений
MAX_ITER = 1000; // Максимальное количество итераций
type
// Типы для матриц и векторов
TMatrix = array[1..3, 1..3] of Double;
TVector = array[1..3] of Double;
var
A: TMatrix; // Исходная матрица коэффициентов
B: TVector; // Исходный вектор свободных членов
Alpha: TMatrix; // Матрица коэффициентов в нормальном виде
Beta: TVector; // Вектор свободных членов в нормальном виде
X, X_prev: TVector; // Текущее и предыдущее приближения
NormAlpha: Double; // Норма матрицы Alpha
k_apr: Integer; // Априорная оценка количества итераций
k_real: Integer; // Реальное количество итераций
converged: Boolean; // Флаг сходимости
apostEstimate: Double; // Апостериорная оценка
// 1. Процедура приведения системы к нормальному виду
procedure ConvertToNormalForm(var Alpha: TMatrix; var Beta: TVector);
var
i, j: Integer;
begin
for i := 1 to 3 do
begin
// Вычисляем Beta[i] = B[i] / A[i,i]
Beta[i] := B[i] / A[i, i];
// Вычисляем элементы матрицы Alpha
for j := 1 to 3 do
begin
if i = j then
Alpha[i, j] := 0 // Диагональные элементы равны 0
else
Alpha[i, j] := -A[i, j] / A[i, i];
end;
end;
end;
// 2. Функция проверки условия сходимости (по норме матрицы)
function CheckConvergence(Alpha: TMatrix): Boolean;
var
i, j: Integer;
rowSum, maxSum: Double;
begin
maxSum := 0;
// Проверяем условие сходимости по строкам (кубическая норма)
for i := 1 to 3 do
begin
rowSum := 0;
for j := 1 to 3 do
rowSum := rowSum + Abs(Alpha[i, j]);
if rowSum > maxSum then
maxSum := rowSum;
end;
NormAlpha := maxSum;
CheckConvergence := (NormAlpha < 1);
if not CheckConvergence then
Writeln('Внимание: условие сходимости не выполнено! Норма = ', NormAlpha:0:6);
end;
// 3. Выбор начального приближения
function GetInitialApproximation(Beta: TVector): TVector;
var
i: Integer;
X0: TVector;
begin
// В качестве начального приближения берем вектор Beta
for i := 1 to 3 do
X0[i] := Beta[i];
GetInitialApproximation := X0;
end;
// 4. Вычисление априорной оценки количества итераций
function CalculateAPrioriEstimation(NormAlpha: Double; EPS: Double): Integer;
var
k: Integer;
begin
// k >= ln(eps * (1 - ||Alpha||) / ||Beta||) / ln(||Alpha||)
// Для упрощения используем приближенную формулу
if NormAlpha < 1 then
k := Ceil(Ln(EPS * (1 - NormAlpha)) / Ln(NormAlpha))
else
k := MAX_ITER;
if k < 1 then k := 1;
if k > MAX_ITER then k := MAX_ITER;
CalculateAPrioriEstimation := k;
end;
// 5. Метод простых итераций
function SimpleIteration(Alpha: TMatrix; Beta: TVector; var X: TVector;
var iterations: Integer): Boolean;
var
i, j: Integer;
error, maxError: Double;
X_new: TVector;
begin
iterations := 0;
SimpleIteration := True;
repeat
Inc(iterations);
// Сохраняем предыдущее приближение
X_prev := X;
// Вычисляем новое приближение: X_new = Alpha * X + Beta
for i := 1 to 3 do
begin
X_new[i] := Beta[i];
for j := 1 to 3 do
X_new[i] := X_new[i] + Alpha[i, j] * X[j];
end;
X := X_new;
// Вычисляем погрешность (максимальное изменение по компонентам)
maxError := 0;
for i := 1 to 3 do
begin
error := Abs(X[i] - X_prev[i]);
if error > maxError then
maxError := error;
end;
// Проверяем условие остановки
if iterations >= MAX_ITER then
begin
Writeln('Достигнуто максимальное количество итераций: ', MAX_ITER);
SimpleIteration := False;
Exit;
end;
until (maxError < EPS);
end;
// 6. Апостериорная оценка погрешности
function AposterioriEstimate(Alpha: TMatrix; X, X_prev: TVector): Double;
var
i, j: Integer;
normDiff, normAlpha, rowSum: Double;
begin
// Вычисляем норму разности приближений
normDiff := 0;
for i := 1 to 3 do
begin
if Abs(X[i] - X_prev[i]) > normDiff then
normDiff := Abs(X[i] - X_prev[i]);
end;
// Вычисляем норму матрицы Alpha
normAlpha := 0;
for i := 1 to 3 do
begin
rowSum := 0;
for j := 1 to 3 do
rowSum := rowSum + Abs(Alpha[i, j]);
if rowSum > normAlpha then
normAlpha := rowSum;
end;
// Апостериорная оценка: ||X^k - X^*|| <= (||Alpha|| * ||X^k - X^{k-1}||) / (1 - ||Alpha||)
AposterioriEstimate := (normAlpha * normDiff) / (1 - normAlpha);
end;
// 7. Вывод результатов
procedure PrintResults(X: TVector; k_apr, k_real: Integer;
apostEstimate: Double; converged: Boolean);
var
i: Integer;
begin
Writeln('========================================');
Writeln('РЕЗУЛЬТАТЫ РЕШЕНИЯ СЛАУ');
Writeln('========================================');
if converged then
begin
Writeln('Решение найдено за ', k_real, ' итераций:');
for i := 1 to 3 do
Writeln('x[', i, '] = ', X[i]:0:15);
Writeln;
Writeln('Априорная оценка количества итераций: ', k_apr);
Writeln('Реальное количество итераций: ', k_real);
Writeln('Апостериорная оценка погрешности: ', apostEstimate:0:15);
end
else
begin
Writeln('Решение не найдено с заданной точностью.');
Writeln('Последнее приближение:');
for i := 1 to 3 do
Writeln('x[', i, '] = ', X[i]:0:15);
end;
Writeln('========================================');
end;
// 8. Вывод матриц и векторов (для отладки)
procedure PrintMatrix(M: TMatrix; name: string);
var
i, j: Integer;
begin
Writeln('Матрица ', name, ':');
for i := 1 to 3 do
begin
for j := 1 to 3 do
Write(M[i, j]:10:6, ' ');
Writeln;
end;
Writeln;
end;
procedure PrintVector(V: TVector; name: string);
var
i: Integer;
begin
Writeln('Вектор ', name, ':');
for i := 1 to 3 do
Write(V[i]:10:6, ' ');
Writeln;
Writeln;
end;
// Основная программа
var
i, j: Integer;
residual: Double;
begin
// Инициализация исходной матрицы A
A[1, 1] := 9.9; A[1, 2] := -1.5; A[1, 3] := 2.6;
A[2, 1] := 0.4; A[2, 2] := 13.6; A[2, 3] := -4.2;
A[3, 1] := 0.7; A[3, 2] := 0.4; A[3, 3] := 7.1;
// Инициализация вектора B
B[1] := 0;
B[2] := 8.2;
B[3] := -1.3;
Writeln('МЕТОД ПРОСТЫХ ИТЕРАЦИЙ');
Writeln('========================================');
Writeln('Исходная матрица A:');
PrintMatrix(A, 'A');
Writeln('Вектор свободных членов B:');
PrintVector(B, 'B');
// 1. Приведение к нормальному виду
ConvertToNormalForm(Alpha, Beta);
Writeln('После приведения к нормальному виду:');
PrintMatrix(Alpha, 'Alpha');
PrintVector(Beta, 'Beta');
// 2. Проверка условия сходимости
if not CheckConvergence(Alpha) then
begin
Writeln('Программа продолжает работу, но сходимость не гарантирована.');
end;
Writeln('Норма матрицы Alpha: ', NormAlpha:0:6);
// 3. Выбор начального приближения
X := GetInitialApproximation(Beta);
Writeln('Начальное приближение:');
PrintVector(X, 'X0');
// 4. Априорная оценка количества итераций
k_apr := CalculateAPrioriEstimation(NormAlpha, EPS);
Writeln('Априорная оценка количества итераций: ', k_apr);
// 5. Решение методом простых итераций
converged := SimpleIteration(Alpha, Beta, X, k_real);
if converged then
begin
// 6. Апостериорная оценка
apostEstimate := AposterioriEstimate(Alpha, X, X_prev);
// 7. Вывод результатов
PrintResults(X, k_apr, k_real, apostEstimate, True);
// Дополнительная проверка: подстановка решения в исходную систему
Writeln('Проверка решения (A*X - B):');
for i := 1 to 3 do
begin
residual := 0;
for j := 1 to 3 do
residual := residual + A[i, j] * X[j];
residual := residual - B[i];
Writeln('Уравнение ', i, ': невязка = ', residual:0:15);
end;
end
else
begin
PrintResults(X, k_apr, k_real, 0, False);
end;
Writeln('Нажмите Enter для выхода...');
Readln;
end.