МІНІСТЕРСТВО ОСВІТИ І НАУКИ, МОЛОДІ ТА СПОРТУ УКРАЇНИ
НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ «ЛЬВІВСЬКА ПОЛІТЕХНІКА»
ІКТА
кафедра ЗІ
З В І Т
до лабораторної роботи №2
з курсу: «Комп'ютерні методи дослідження інформаційних
процесів і систем»
на тему: «Метод Гауса для розв’язання систем лінійних алгебраїчних рівнянь»
Львів – 2012
РЕЗУЛЬТАТ РОБОТИ ПРОГРАМИ
Мета роботи – ознайомлення з методами уточнення коренів нелінійних рівнянь з одним невідомим.
КОРОТКІ ТЕОРИТИЧНІ ВІДОМОСТІ:
Методи розв’язування систем лінійних алгебраїчних рівнянь
Нехай задано систему лінійних алгебраїчних рівнянь:
,
де А – квадратна невироджена матриця розмірності , X – вектор-стовпець невідомих розмірності n, В – вектор-стовпець вільних членів розмірності n.
Методи розв’язування систем такого виду поділяються на дві групи : прямі та ітераційні.
1) Прямі методи зводяться до скінчених алгоритмів для обчислення коренів рівнянь (тобто розв’язки шукають за певними формулами). Вони дають розв’язки після виконання відомого для даного n (n – порядок системи) числа арифметичних операцій.
Іншими словами, прямими методом розв’язування лінійної системи називають будь-який метод, котрий дозволяє знайти елементи вектора X з допомогою скінченого числа елементарних математичних операцій: додавання, віднімання, ділення, множення, та, можливо, кореня квадратного.
Оцінити ефективність будь-якого методу можна за допомогою таких основних характеристик:
числа операцій, необхідних для реалізації даного методу;
об’єму пам’яті;
чутливості до переносу похибок заокруглення (або обчислювальної стійкості).
Практично всі прямі методи розв’язування систем базуються на зведені матриці А до матриці простішої структури – діагональної (тоді розв’язок очевидний) або трикутної, та методів розв’язування таких систем.
До групи прямих методів розв’язування систем лінійних алгебраїчних рівнянь належать:
– метод Гаусса та його різновиди:
а) класичний метод Гаусса із зведенням матриці А до верхньої трикутної матриці і одержанням розв’язків з допомогою обернених підстановок. Число операцій (вартість методу) – операцій додавання, множення та операцій ділення (можна ними знехтувати в порівнянні з ).
б) метод Гаусса з вибором головного елемента (частковим або повним). Число арифметичних операцій при цьому складає ~ додавань та ~ множень.
Повна вартість методу в основному визначається вартістю зведення матриці А до трикутного вигляду, оскільки вартість розв’язку вже самої трикутної системи незначна в порівнянні з вартістю зведення матриці до трикутного вигляду.
– LU-розклад (lower-upper –нижній-верхній)
Якщо використовувати алгоритм Краута, то число операцій складе .
З точки зору об’єму обчислень метод LU- розкладу еквівалентний методу Гаусса з частковим вибором головного елемента; його переваги – це можливість роботи з різними векторами вільних членів В та з транспонованими матрицями (розв’язок рівняння знаходиться за тим же LU-розкладом).
– метод (схема) Халецького.
При розкладі симетричних матриць можна зменшити число операцій і необхідний об’єм пам’яті. Повна вартість методу Халецького складає половину вартості методу Гаусса + n обчислень квадратного кореня. Метод чисельно стійкий.
– метод Жордана (роблять діагональну матрицю замість трикутної). Метод рідко використовується на практиці.
До прямих методів відносяться також методи для кліткових та розріджених матриць.
2) Ітераційні (або наближені) методи – це методи послідовних наближень. В них необхідно задати деякий наближений розв’язок – так зване початкове наближення. Після цього з допомогою деякого алгоритму проводиться один цикл обчислень, котрий називається ітерацією. В результаті ітерації знаходять нове наближення. Ітерації проводять до тих пір, доки не одержать розв’язок із заданою похибкою. Об’єм обчислень при цьому наперед не відомий.
Основний недолік прямих методів – це нагромадження похибок в процесі розв’язування, оскільки обчислення на будь-якому етапі використовують результати (з похибками) попередніх операцій. Це особливо небезпечно для великих систем ( і більше) – наростає число операцій, а також для погано обумовлених систем () (малі похибки обчислень або вхідних даних можуть породити значні похибки в розв’язку). Тому прямі методи використовують для відносно невеликих () систем з густо заповненою матрицею та .
Перевагою ітераційних методів над прямими є те, що окремі похибки, що виникають при обчисленнях, не впливають на кінцевий результат (ітерації закінчуються тільки тоді, коли одержано розв’язок із наперед заданою точністю), а ведуть лише до збільшення числа необхідних ітерацій.
Крім того, розв’язування систем ітераційними методами спрощується ще й тому, що на кожній ітерації розв’язується система з одними і тими ж матрицями.
До ітераційних належить: метод простої ітерації, метод Зейделя, метод верхньої релаксації, та інші.
Метод Гаусса з вибором головного елемента.
Запишемо розширену прямокутну матрицю коефіцієнтів системи з рівнянь.
Серед елементів матриці вибираємо найбільший за модулем елемент, який називається головним елементом. Нехай ним буде . Рядок з номером називається головним рядком. Обчислюємо множники для всіх .
Далі перетворюємо матрицю наступним чином: з кожного го неголовного рядка віднімаємо почленно головний рядок, домножений на . Отримаємо матрицю, у якої всі елементи го стовпця за винятком , дорівнюють нулю. Відкидаючи цей стовпець і головний рядок, отримуємо нову матрицю з меншою на одиницю кількістю рядків та стовпців. Над матрицею повторюємо такі ж дії й тримаємо матрицю і т.д. Ці перетворення продовжуємо доки не отримаємо матрицю, що містить один рядок з двох елементів, який вважаємо головним.
Об’єднаємо всі головні рядки починаючи з останнього. Після перестановки вони утворять трикутну матрицю, еквівалентну початковій матриці . Цей етап називають прямим ходом обчислень. Розв’язавши систему з отриманою трикутною матрицею коефіцієнтів, знайдемо послідовно невідомі . Цей етап обчислень називають зворотним ходом. Усі описані обчислення проводять аналогічно до методу Гауса. Сенс вибирання головного елемента полягає в тому, щоб зробити як найменшими числа і завдяки цьому зменшити похибку обчислень.
ЗАВДАННЯ:
Розв’язати систему лінійних алгебраїчних рівнянь методом Гаусса.
Текст роботи програми
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace kmd_lab_2
{
class Program
{
static void Main(string[] args)
{
SLAR3 slar = new SLAR3();
slar.Max();
slar.Mnozhnuku();
slar.ArrayTransformation();
slar.NewArray();
// slar.WriteArrays();
slar.GolRadok();
slar.Max1();
slar.Mnozhnuku1();
slar.ArrayTransformation1();
slar.NewArray1();
// slar.WriteArrays1();
slar.GolRadok1();
slar.Max2();
slar.Mnozhnuku2();
slar.ArrayTransformation2();
slar.NewArray2();
// slar.WriteArrays2();
slar.GolRadok2();
slar.BackTrack();
Console.ReadKey();
}
}
class SLAR
{
static public int radok = 4, stovpec = 5;
public double[,] A = new double[,] { { 8.3, 3.02, 4.1, 1.9, -10.55 }, { 3.92, 8.45, 7.38, 2.46, 12.21 }, { 3.77, 7.61, 8.04, 2.28, 15.45 }, { 2.21, 3.25, 1.69, 6.99, -8.35 } };
public double[,] B = new double[radok, stovpec];
public double[] m = new double[3];
public double[] m1 = new double[2];
public double[] m2 = new double[1];
public int p = 0, k = 0, f = 0, f1 = 0, f2 = 0;
public double[,] M1 = new double[radok - 1, stovpec - 1];
public double[,] M2 = new double[radok - 2, stovpec - 2];
public double[,] M3 = new double[radok - 3, stovpec - 3];
public void Max()
{
Console.WriteLine("Задана матриця:");
for (int i = 0; i < A.GetLength(0); i++)
{
Console.WriteLine();
for (int j = 0; j < (A.GetLength(1) - 1); j++)
Console.Write(A[i, j] + "\t");
}
double max = A[0, 0];
for (int i = 0; i < A.GetLength(0); i++)
for (int j = 0; j < (A.GetLength(1) - 1); j++)
if (Math.Abs(A[i, j]) > max)
{
max = A[i, j];
p = i;
k = j;
}
}
public void Mnozhnuku()
{
for (int i = 0; i < A.GetLength(0); i++)
{
if (i != p)
{
m[f] = (A[i, k] / A[p, k]);
f++;
}
}
}
public void ArrayTransformation()
{
f = 0;
for (int i = 0; i < A.GetLength(0); i++)
{
if (i == p)
{
f = 1;
continue;
}
for (int j = 0; j < (A.GetLength(1) - 1); j++)
{
A[i, j] = A[i, j] - (A[p, j] * m[f]);
}
f++;
}
}
public void NewArray()
{
for (int i = 0, I = 0; i < A.GetLength(0); i++)
{
if (i == p)
continue;
for (int j = 0, J = 0; j < (A.GetLength(1) - 1); j++)
{
if (j == k)
continue;
M1[I, J] = A[i, j];
J++;
}
I++;
}
}
public void WriteArrays()
{
Console.WriteLine();
foreach (double s in m)
Console.Write("\n" + (float)s + "\t");
Console.WriteLine();
for (int i = 0; i < A.GetLength(0); i++)
{
Console.WriteLine();
for (int j = 0; j < (A.GetLength(1) - 1); j++)
Console.Write((float)A[i, j] + "\t");
}
Console.WriteLine();
for (int i = 0; i < 3; i++)
{
Console.WriteLine();
for (int j = 0; j < 4; j++)
Console.Write("{0}\t", (float)M1[i, j]);
}
}
public void GolRadok()
{
for (int j = 0; j < (A.GetLength(1) - 1); j++)
B[3, j] = A[p, j];
}
}
class SLAR2 : SLAR
{
public void Max1()
{
p = 0; k = 0;
double max = M1[0, 0];
for (int i = 0; i < M1.GetLength(0); i++)
for (int j = 0; j < (M1.GetLength(1) - 1); j++)
if (Math.Abs(M1[i, j]) > max)
{
max = M1[i, j];
p = i;
k = j;
}
}
public void Mnozhnuku1()
{
for (int i = 0; i < M1.GetLength(0); i++)
{
if (i != p)
{
m1[f1] = (M1[i, k] / M1[p, k]);
f1++;
}
}
}
public void ArrayTransformation1()
{
f1 = 0;
for (int i = 0; i < M1.GetLength(0); i++)
{
if (i == p)
{
f1 = 0;
continue;
}
for (int j = 0; j < (M1.GetLength(1) - 1); j++)
{
M1[i, j] = M1[i, j] - (M1[p, j] * m1[f1]);
}
f1++;
}
}
public void NewArray1()
{
for (int i = 0, I = 0; i < M1.GetLength(0); i++)
{
if (i == p)
continue;
for (int j = 0, J = 0; j < (M1.GetLength(1) - 1); j++)
{
if (j == k)
continue;
M2[I, J] = M1[i, j];
J++;
}
I++;
}
}
public void WriteArrays1()
{
Console.WriteLine();
foreach (double s in m1)
Console.Write("\n" + (float)s + "\t");
Console.WriteLine();
for (int i = 0; i < M1.GetLength(0); i++)
{
Console.WriteLine();
for (int j = 0; j < (M1.GetLength(1) - 1); j++)
Console.Write((float)M1[i, j] + "\t");
}
Console.WriteLine();
for (int i = 0; i < M2.GetLength(0); i++)
{
Console.WriteLine();
for (int j = 0; j < (M2.GetLength(1) - 1); j++)
Console.Write("{0}\t", (float)M2[i, j]);
}
}
public void GolRadok1()
{
for (int j = 0; j < (M1.GetLength(1) - 1); j++)
B[2, j] = M1[p, j];
}
}
class SLAR3 : SLAR2
{
public void Max2()
{
p = 0; k = 0;
double max = M2[0, 0];
for (int i = 0; i < M2.GetLength(0); i++)
for (int j = 0; j < (M2.GetLength(1) - 1); j++)
if (Math.Abs(M2[i, j]) > max)
{
max = M2[i, j];
p = i;
k = j;
}
}
public void Mnozhnuku2()
{
for (int i = 0; i < M2.GetLength(0); i++)
{
if (i != p)
{
m2[f2] = (M2[i, k] / M2[p, k]);
f2++;
}
}
}
public void ArrayTransformation2()
{
f2 = 0;
for (int i = 0; i < M2.GetLength(0); i++)
{
if (i == p)
{
continue;
}
for (int j = 0; j < (M2.GetLength(1) - 1); j++)
{
M2[i, j] = M2[i, j] - (M2[p, j] * m2[f2]);
}
f2++;
}
}
public void NewArray2()
{
for (int i = 0, I = 0; i < M2.GetLength(0); i++)
{
if (i == p)
continue;
for (int j = 0, J = 0; j < (M2.GetLength(1) - 1); j++)
{
if (j == k)
continue;
M3[I, J] = M2[i, j];
J++;
}
I++;
}
}
public void WriteArrays2()
{
Console.WriteLine();
foreach (double s in m2)
Console.Write("\n" + (float)s + "\t");
Console.WriteLine();
for (int i = 0; i < M2.GetLength(0); i++)
{
Console.WriteLine();
for (int j = 0; j < (M2.GetLength(1) - 1); j++)
Console.Write((float)M2[i, j] + "\t");
}
Console.WriteLine();
for (int i = 0; i < M3.GetLength(0); i++)
{
Console.WriteLine();
for (int j = 0; j < (M3.GetLength(1) - 1); j++)
Console.Write("{0}\t", (float)M3[i, j]);
}
}
public void GolRadok2()
{
Console.WriteLine("\n Отримана трикутна матриця:");
for (int j = 0; j < (M2.GetLength(1) - 1); j++)
B[1, j] = M2[p, j];
for (int j = 0; j < (M3.GetLength(1) - 1); j++)
B[0, j] = M3[0, j];
for (int i = 0; i < B.GetLength(0); i++)
{
Console.WriteLine();
for (int j = 0; j < (B.GetLength(1) - 1); j++)
Console.Write("{0}\t", (float)B[i, j]);
}
}
public void BackTrack()
{
double x1, x2, x3, x4;
x1 = A[0, 4] / B[0, 0];
x2 = (A[1, 4] - B[1, 0] * x1) / B[1, 1];
x3 = (A[2, 4] - B[2, 0] * x1 - B[2, 1] * x2) / B[2, 2];
x4 = (A[3, 4] - B[3, 0] * x1 - B[3, 1] * x2 - B[3, 2] * x3) / B[3, 3];
Console.WriteLine("\n Корені СЛАР:\nx1 = {0}, x2 = {1}, x3 = {2}, x4 = {3}", (float)x1, (float)x2, (float)x3, (float)x4);
double z = x1 * B[0, 0] + x2 * B[0, 1] + x3 * B[0, 2] + x4 * B[0, 3];
double z1 = x1 * B[1, 0] + x2 * B[1, 1] + x3 * B[1, 2] + x4 * B[1, 3];
double z2 = x1 * B[2, 0] + x2 * B[2, 1] + x3 * B[2, 2] + x4 * B[2, 3];
double z3 = x1 * B[3, 0] + x2 * B[3, 1] + x3 * B[3, 2] + x4 * B[3, 3];
if (((int)z == (int)A[0, 4]) && ((int)z1 == (int)A[1, 4]) && ((int)z2 == (int)A[2, 4]) && ((int)z3) == ((int)A[3, 4]))
Console.WriteLine("СЛАР розв'язана вірно!!!");
}
}
}