https://pastein.ru/t/xzL
скопируйте уникальную ссылку для отправки
Загрузка данных
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <iomanip>
using namespace std;
const float eps = 1e-4;
const int kmax = 1000;
const int prec = 5; // precision when printing floating point numbers
const string sep = "----------------------------------------\n";
// region util
vector<vector<float>> get_matrix(int n){
vector<vector<float>> matrix(n, vector<float>(n));
for(int i = 0; i < n; i++){
matrix[i][i] = 9.f * (float)pow(i+1, 1./3);
for(int j = 0; j < n; j++)
if(i != j)
matrix[i][j] = 0.01f / (float)(sqrt(i + 1) + sqrt(j + 1));
}
return matrix;
}
bool check_strict_diagonal_dominance(const vector<vector<float>>& matrix){
for(int i = 0; i < matrix.size(); i++){
float sum = 0;
for(int j = 0; j < matrix.size(); j++)
if(i != j)
sum += fabs(matrix[i][j]);
if(fabs(matrix[i][i]) <= sum)
return false;
}
return true;
}
vector<float> get_solution(const vector<vector<float>>& matrix){
vector<float> solution(matrix.size());
for(int i = 0; i < matrix.size(); i++)
solution[i] = (float)i + 5;
return solution;
}
vector<float> get_b(const vector<vector<float>>& matrix, const vector<float>& solution){
vector<float> b(matrix.size());
for(int i = 0; i < matrix.size(); i++){
float sum = 0;
for(int j = 0; j < matrix.size(); j++)
sum += matrix[i][j] * solution[j];
b[i] = sum;
}
return b;
}
vector<vector<float>> get_modified_matrix(const vector<vector<float>>& matrix){
auto modified_matrix = matrix;
for(int i = 1; i < matrix.size(); i++){
float sum = 0;
for(int j = 0; j < matrix.size(); j++)
if(i != j)
sum += fabs(matrix[i][j]);
modified_matrix[i][i] = sum;
}
return modified_matrix;
}
void print_matr(vector<vector<float> >& a, vector<float>& b, int max_rows = 5, int max_cols = 5, int w = 10){
// set fixed notation
cout << fixed << setprecision(prec);
int n = (int)a.size();
for(int i = 0; i < min(n, max_rows); i++){
for(int j = 0; j < min(n, max_cols); j++)
cout << setw(w) << a[i][j] << " ";
// if to many columns, print "..."
if(n > max_cols)
cout << " ...";
cout << " | " << b[i] << endl;
}
// if to many rows, print "..."
if(n > max_rows){
for(int i = 0; i < max_cols; i++)
cout << setw(w) << "..." << " ";
if(n > max_cols)
cout << " ...";
cout << " | ..." << endl;
}
cout << endl;
}
void print_vector(const vector<float>& v, int w = 5){
cout << fixed << setprecision(prec);
for(float i: v)
cout << setw(w) << i << " ";
cout << endl;
}
float norm(const vector<float>& v){
float norm = 0;
for(float i: v)
norm = max(norm, fabs(i));
return norm;
}
vector<float> operator-(const vector<float>& a, const vector<float>& b){
vector<float> c(a.size());
for(int i = 0; i < a.size(); i++)
c[i] = a[i] - b[i];
return c;
}
// endregion
struct solution{
vector<float> x;
int k;
};
// якоби
solution jacobi(const vector<vector<float>>& a, const vector<float>& b, [[maybe_unused]] float o = 1){
int n = (int)a.size();
vector<float> x(n);
vector<float> x_prev(n);
int k = 0;
do{
k++;
x_prev = x;
for(int i = 0; i < n; i++){
float sum = 0;
for(int j = 0; j < n; j++)
if(i != j)
sum += a[i][j] * x_prev[j];
x[i] = (b[i] - sum) / a[i][i];
}
}while(k < kmax && norm(x - x_prev) > eps);
return {x, k};
}
// гаусс-зейдель
solution gauss_seidel(const vector<vector<float>>& a, const vector<float>& b, [[maybe_unused]] float omega = 1){
int n = (int)a.size();
vector<float> x(n);
vector<float> x_prev(n);
int k = 0;
do{
k++;
x_prev = x;
for(int i = 0; i < n; i++){
float sum = 0;
for(int j = 0; j < n; j++)
if(i != j)
sum += a[i][j] * (j < i ? x[j] : x_prev[j]);
x[i] = (b[i] - sum) / a[i][i];
}
}while(k < kmax && norm(x - x_prev) > eps);
return {x, k};
}
// релаксация
solution relaxation(const vector<vector<float>>& a, const vector<float>& b, float omega){
int n = (int)a.size();
vector<float> x(n);
vector<float> x_prev(n);
int k = 0;
do{
k++;
x_prev = x;
for(int i = 0; i < n; i++){
float sum = 0;
for(int j = 0; j < n; j++)
if(i != j)
sum += a[i][j] * (j < i ? x[j] : x_prev[j]);
x[i] = (1 - omega) * x_prev[i] + omega * (b[i] - sum) / a[i][i];
}
}while(k < kmax && norm(x - x_prev) > eps);
return {x, k};
}
void test_method(const string& name, solution f(const vector<vector<float>>&, const vector<float>&, float),
const vector<vector<float>>& a, const vector<float>& b,
const vector<float>& solution, float omega = 1){
cout << name << ":" << endl;
auto method_solution = f(a, b, omega);
print_vector(method_solution.x);
cout << "Iterations: " << method_solution.k << endl;
cout << "Is k limit reached: " << (method_solution.k == kmax ? "yes" : "no") << endl;
float method_norm = norm(solution - method_solution.x);
float method_relative_error = method_norm / norm(solution);
cout << "Norm: " << method_norm << endl;
cout << "Relative error: " << method_relative_error * 100 << "%" << endl;
}
int main(){
cout << fixed << setprecision(prec);
int n = 15;
vector<vector<float>> matrix = get_matrix(n);
vector<float> solution = get_solution(matrix);
vector<float> b = get_b(matrix, solution);
cout << "Matrix:" << endl;
print_matr(matrix, b);
cout << "Strict diagonal dominance: ";
cout << (check_strict_diagonal_dominance(matrix) ? "yes" : "no") << endl;
cout << "Solution:" << endl;
print_vector(solution);
cout << sep;
test_method("Jacobi", jacobi, matrix, b, solution);
cout << sep;
test_method("Gauss-Seidel", gauss_seidel, matrix, b, solution);
cout << sep;
test_method("Relaxation (omega = 0.5)", relaxation, matrix, b, solution, 0.5);
cout << sep;
test_method("Relaxation (omega = 1.5)", relaxation, matrix, b, solution, 1.5);
cout << sep;
auto modified_matrix = get_modified_matrix(matrix);
auto modified_b = get_b(modified_matrix, solution);
cout << "Modified matrix:" << endl;
print_matr(modified_matrix, modified_b);
cout << "Strict diagonal dominance: ";
cout << (check_strict_diagonal_dominance(modified_matrix) ? "yes" : "no") << endl;
cout << "Solution:" << endl;
print_vector(solution);
cout << sep;
test_method("Jacobi", jacobi, modified_matrix, modified_b, solution);
cout << sep;
test_method("Gauss-Seidel", gauss_seidel, modified_matrix, modified_b, solution);
cout << sep;
test_method("Relaxation (omega = 0.5)", relaxation, modified_matrix, modified_b, solution, 0.5);
cout << sep;
test_method("Relaxation (omega = 1.5)", relaxation, modified_matrix, modified_b, solution, 1.5);
cout << sep;
return 0;
}