Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Метод Гауса - Жордана.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
142.31 Кб
Скачать
  1. Реалізація

Наведемо тут реалізацію алгоритму Гауса-Жордана з евристикою partial pivoting (вибором опорного елемента як максимуму за стовпцем).

На вхід функції gauss() передається сама матриця системи a. Останній стовпець матриці a — це в наших старих позначеннях стовпець b вільних коефіцієнтів (так зроблено для зручності програмування — т. к. в самому алгоритмі всі операції з вільними коефіцієнтами b повторюють операції з матрицею A).

Функція повертає число розв'язків системи (0, 1 або ) (нескінченність позначена в коді спеціальної константою INF, якій можна задати будь-яке велике значення). Якщо хоча б одне рішення існує, то воно повертається у векторі ans.

int gauss (vector < vector<double> > a, vector<double> & ans) {

int n = (int) a.size();

int m = (int) a[0].size() - 1;

 

vector<int> where (m, -1);

for (int col=0, row=0; col<m && row<n; ++col) {

int sel = row;

for (int i=row; i<n; ++i)

if (abs (a[i][col]) > abs (a[sel][col]))

sel = i;

if (abs (a[sel][col]) < EPS)

continue;

for (int i=col; i<=m; ++i)

swap (a[sel][i], a[row][i]);

where[col] = row;

 

for (int i=0; i<n; ++i)

if (i != row) {

double c = a[i][col] / a[row][col];

for (int j=col; j<=m; ++j)

a[i][j] -= a[row][j] * c;

}

++row;

}

 

ans.assign (m, 0);

for (int i=0; i<m; ++i)

if (where[i] != -1)

ans[i] = a[where[i]][m] / a[where[i]][i];

for (int i=0; i<n; ++i) {

double sum = 0;

for (int j=0; j<m; ++j)

sum += ans[j] * a[i][j];

if (abs (sum - a[i][m]) > EPS)

return 0;

}

 

for (int i=0; i<m; ++i)

if (where[i] == -1)

return INF;

return 1;

}

У функції підтримуються два покажчика — на поточний стовпець col і поточний рядок row.

Також заводиться вектор where, в якому для кожної змінної записано, в якому рядку повинна вийти (іншими словами, для кожного стовпця записаний номер рядка, в якому цей стовпець відмінний від нуля). Цей вектор потрібен, оскільки деякі змінні могли не "визначитися" в ході рішення (тобто це-незалежні змінні, яким можна присвоїти довільне значення, наприклад, у наведеній реалізації нулі).

Реалізація використовує техніку partial pivoting, виробляючи пошук рядка максимальним за модулем елементом, і переставляючи потім цю рядок у позицію row (хоча явну перестановку рядків можна замінити обміном двох індексів в деякому масиві, на практиці це не дасть реального виграшу, т. к. на обміни витрачається O(n2) операцій).

У цілях простоти поточний рядок не ділиться на опорний елемент — так що в підсумку після закінчення роботи алгоритму матриця стає не одиничною, а діагональною (втім, мабуть, поділ рядка на провідний елемент дозволяє дещо зменшити виникають похибки).

Після знаходження рішення воно підставляється назад в матрицю — щоб перевірити, чи система хоча б одне рішення чи ні. Якщо перевірка знайденого рішення пройшла успішно, то функція повертає 1 або — в залежності від того, чи є хоча б одна незалежна змінна або немає.