МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
Національний університет “Львівська політехніка”
Інститут післядипломної освіти
ЗВІТ
Про виконання лабораторної роботи №2
«Чисельні методи розв’язування системи лінійних рівнянь»
з дисципліни «Чисельні методи»
Мета роботи: ознайомлення на практиці з прямими методами розв’язування систем лінійних алгебраїчних рівнянь.
Теоретичні відомості
Метод Гаусса, також званий методом покрокового виключення невідомих змінних, названий ім’ям видатного німецького вченого К.Ф. Гаусса, ще за життя отримав неофіційний титул “короля математики”. Однак даний метод був відомий задовго до зародження європейської цивілізації, ще в I ст. до н. е.. стародавні китайські вчені використовували його в своїх працях.
Метод Гаусса є класичним способом вирішення систем лінійних алгебраїчних рівнянь (СЛАР). Він ідеальний для швидкого вирішення обмежених за розміром матриць.
Сам метод складається з двох ходів: прямого і зворотного. Прямим ходом називається послідовне приведення СЛАР до трикутного вигляду, тобто обнулення значень, що знаходяться під головною діагоналлю. Зворотний хід передбачає послідовне знаходження значень змінних, висловлюючи кожну змінну через попередню.
Навчитися застосовувати на практиці метод Гаусса просто, достатньо знання елементарних правил множення, додавання і віднімання чисел.
Для того щоб наочно показати алгоритм розв’язання лінійних систем даним методом, розберемо один приклад.
Отже, вирішити, використовуючи метод Гаусса:
x +2 y +4 z = 3 2x +6 y + 11z = 6 4x-2y-2z = -6
Нам потрібно у другій і третій рядках позбутися від змінної х. Для цього ми додаємо до них першу, помножену на -2 і -4 відповідно. Отримаємо:
x +2 y +4 z = 3 2y +3 z = 0 -10y-18z = -18
Тепер 2-й рядок помножимо на 5 і додамо її до 3-ої:
x +2 y +4 z = 3 2y +3 z = 0 -3z = -18 Ми привели нашу систему до трикутного вигляду. Тепер здійснюємо зворотний хід. Починаємо з останнього рядка: -3z = -18, z = 6.
Друга строчка: 2y +3 z = 0 2y +18 = 0 2y = -18, y = -9
Перша строчка : x +2 y +4 z = 3 x-18 +24 = 3 x = 18-24 +3 х = -3
Підставляючи отримані значення змінних у вихідні дані, переконуємося в правильності рішення.
Даний приклад може вирішуватися безліччю будь-яких інших підстановок, але відповідь повинен вийти той же самий.
Буває так, що на провідній першої рядку розташовані елементи із занадто малими значеннями. Це не страшно, але досить ускладнює обчислення. Рішенням даної проблеми є метод Гауса з вибором головного елемента по стовпцю. Суть його полягає в наступному: в першому рядку відшукується максимальний по модулю елемент, той стовпець, в якому він розташований, міняють місцями з 1-м стовпцем, тобто наш максимальний елемент стає першим елементом головної діагоналі. Далі йде стандартний процес обчислення. При необхідності процедуру зміни місцями стовпців можна повторити.
LU розклад матриці — представлення матриці у вигляді добутку нижньої трикутної матриці та верхньої трикутної матриці.
Квадратна матриця A розміру n може бути представлена у вигляді
/
де L та U — нижня та верхня трикутна матриця того ж розміру.
LDU розклад матриці — це представлення у вигляді
/
де D — діагональна матриця, а L та U є одиничними трикутними матрицями, тобто, всі їх діагональні елементи рівні одиниці.
LUP розклад матриці — це представлення в формі
/
де L та U — нижня та верхня трикутна матриця того ж розміру, а P — матриця перестановки.
Хід роботи
Написати програму розв’язку системи лінійних алгебраїчних рівнянь у відповідності до варіанту:
методом Гауса з вибором головного елемента;
Текст програми :
#include <iostream>
#include <conio.h>
#include <stdio.h>
#include <algorithm>
using namespace std;
double a[3][3], b[3][1], N;
int indStovpZmaxElem;
double x[3];
void enterA ();
void enterB ();
void enterA () // вводимо матрицю коефіціентів а
{
for(int j=0; j<3; j++)
{for(int i=0; i<3; i++)
{cout << "Vvedit element a[" << i << "][" << j << "] ";
cin>>a[i][j];}
}
}
void enterB () // вводимо стовпець коефіціентів b
{
int j=0;
for(int i=0; i<3; i++)
{cout << "Vvedit element b[" << i << "][" << j << "] ";
cin>>b[i][j];}
}
int maxElemPershRjadka () // пошук максимального елемента в першому рядку
{
int max=0;
for( int i=0;i<3; i++ )
{if (abs(a[0][max])<abs(a[0][i])) max=i;}
indStovpZmaxElem=max;
return indStovpZmaxElem; // функція повертае номеря стовпця, що містить макс елем 1-го рядка
}
void perestanovkaElementiv() // стовпець, який містить макс елем мін місцями з 1-м стовпцем
{
for (int i=0; i<3; i++)
swap (a[i][0],a[i][indStovpZmaxElem]);
}
void PryamyiXid ()
{
double A[3][1] ;//видаляємо 1-шу змінну з рівнянь
for(int i=1; i<3; i++)
{
A[i][0]=a[i][0]/a[0][0];
a[i][0]=a[i][0]-a[0][0]*A[i][0];
a[i][1]=a[i][1]-a[0][1]*A[i][0];
a[i][2]=a[i][2]-a[0][2]*A[i][0];
b[i][0]=b[i][0]-b[0][0]*A[i][0];
}
double B[1][1] ;//видаляємо 2-гу змінну з рівнянь
B[0][0]=a[2][1]/a[1][1];
a[2][1]=a[2][1]-a[1][1]*B[0][0];
a[2][2]=a[2][2]-a[1][2]*B[0][0];
b[2][0]=b[2][0]-b[1][0]*B[0][0];
}
void ZvorotnyiXid ()
{
double x1, x2, x3;
x1=b[2][0]/a[2][2];
x2=(b[1][0]-a[1][2]*x1)/a[1][1];
x3=(b[0][0]-a[0][2]*x1-a[0][1]*x2)/a[0][0];
cout<<endl;
if(indStovpZmaxElem==0)
cout<<"x="<<x3<<" "<<"y="<<x2<<" "<<"z="<<x1<<" "<<endl;
else{
if(indStovpZmaxElem==1) cout<<"x="<<x2<<" "<<"y="<<x3<<" "<<"z="<<x1<<" "<<endl;
else if(indStovpZmaxElem==2) cout<<"x="<<x1<<" "<<"y="<<x2<<" "<<"z="<<x3<<" "<<endl;
}
}
void showA () // вводимо матрицю коефіціентів а
{
for(int i=0; i<3; i++,cout<<endl)
{
for(int j=0; j<3; j++)
cout <<a[i][j]<<"\t";
cout<<"\t"<<b[i][0];
}
}
void main()
{
enterA ();
cout<<endl;
enterB ();
cout<<endl;
showA ();
cout<<endl;
cout<<maxElemPershRjadka ();
cout<<endl;
perestanovkaElementiv();
cout<<endl;
showA ();
cout<<endl;
PryamyiXid ();
showA ();
ZvorotnyiXid ();
_getch();
}
Результат роботи програми:
/
Написати програму розв’язку системи лінійних алгебраїчних рівнянь у відповідності до варіанту:
2)методом LU-розкладу.
#include <iostream>
#include <conio.h>
#include <stdio.h>
#include <algorithm>
using namespace std;
double a[3][3], b[3][1], N;
int indStovpZmaxElem;
double x[3];
double L [3][3];
double U [3][3];
double y[3][1];
double xx[3][1];
void showLU (double c[3][3], double d[3][3]);
void enterA ();
void enterB ();
void enterA () // вводимо матрицю коефіціентів а
{
for(int j=0; j<3; j++)
{for(int i=0; i<3; i++)
{cout << "Vvedit element a[" << i << "][" << j << "] ";
cin>>a[i][j];}
}
}
void enterB () // вводимо стовпець коефіціентів b
{
int j=0;
for(int i=0; i<3; i++)
{cout << "Vvedit element b[" << i << "][" << j << "] ";
cin>>b[i][j];}
}
void LU ()// обчислюємо елементи матриць, на добуток яких буде розкладено а
{
//U*L*x=b
U[0][0]=a[0][0];// перший рядок а = перш. рядок U
U[0][1]=a[0][1];
U[0][2]=a[0][2];
L[1][0]=a[1][0]/U[0][0];
L[2][0]=a[2][0]/U[0][0];
U[1][1]=a[1][1]-L[1][0]*U[0][1];
L[2][1]=(a[2][1]-L[2][0]*U[0][1])/U[1][1];
U[1][2]=a[1][2]-L[1][0]*U[0][2];
U[2][2]=a[2][2]-L[2][1]*U[1][2]-L[2][0]*U[0][2];
L[0][0]=1;
L[1][1]=1;
L[2][2]=1;
}
void showLU (double c[3][3], double d[3][3]) // виводить матриці L i U на друк
{
for(int i=0; i<3; i++,cout<<endl)
{
for(int j=0; j<3; j++)
cout <<c[i][j]<<"\t"<<"\t";
}
cout<<endl;
for(int i=0; i<3; i++,cout<<endl)
{
for(int j=0; j<3; j++)
cout<<d[i][j]<<"\t"<<"\t";
}
}
void showA () // вводимо матрицю коефіціентів а та б
{
for(int i=0; i<3; i++,cout<<endl)
{
for(int j=0; j<3; j++)
cout <<a[i][j]<<"\t";
cout<<"\t"<<b[i][0];
}
}
void Y ()// позначимо U*x=Y
{
y[0][0]=b[0][0];
y[1][0]=b[1][0]-L[1][0]*y[0][0];
y[2][0]=b[2][0]-L[2][0]*y[0][0]-L[2][1]*y[1][0];
cout<<"y1="<<y[0][0]<<" "<<"y2="<<y[1][0]<<" "<<"y3="<<y[2][0];
}
void X ()
{
xx[2][0]=y[2][0]/U[2][2];
xx[1][0]=(y[1][0]-U[1][2]*xx[2][0])/U[1][1];
xx[0][0]=(y[0][0]-U[0][2]*xx[2][0]-U[0][1]*xx[1][0])/U[0][0];
cout<<endl;
cout<<endl;
cout<<"x1="<<xx[0][0]<<" "<<"x2="<<xx[1][0]<<" "<<"x3="<<xx[2][0];
}
void main()
{
enterA ();
cout<<endl;
enterB ();
cout<<endl;
showA ();
cout<<endl;
LU ();
showLU(L, U);
Y ();
cout<<endl;
X ();
_getch();
}
/
Висновки
Під час виконання цієї лабораторної роботи здійснено пошук розв’язку системи лінійних алгебраїчних рівнянь у відповідності до варіанту:
1)методом Гауса з вибором головного елемента;
2)методом LU-розкладу.