https://pastein.ru/t/fYV
скопируйте уникальную ссылку для отправки
Загрузка данных
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstdio>
using namespace std;
const int N = 10;
const double eps = 1e-6;
// region util
template <typename T>
void print_matrix(vector<vector<T>> &A){
for(int i = 0; i < A.size(); i++){
for(int j = 0; j < A.size(); j++){
printf("%10.3lf ", A[i][j]);
}
printf("\n");
}
}
template <typename T>
void print_vector(vector<T> &v){
for(int i = 0; i < v.size(); i++){
printf("%10.3lf ", v[i]);
}
printf("\n");
}
vector<vector<double>> generate_matrix(int n){
vector<vector<double>> A(n, vector<double>(n));
for(int i = 0; i < n; i++){
for(int j = i; j < n; j++){
A[i][j] = A[j][i] = rand() % 100;
}
}
return A;
}
// вспомогательные методы
double norm(vector<double> &v){
double res = 0;
for(double e: v){
res += e * e;
}
return sqrt(res);
}
vector<double> operator-(vector<double> &a, vector<double> &b){
vector<double> res(a.size());
for(int i = 0; i < a.size(); i++){
res[i] = a[i] - b[i];
}
return res;
}
vector<double> operator*(vector<vector<double>> &A, vector<double> &v){
vector<double> res(v.size());
for(int i = 0; i < v.size(); i++){
for(int j = 0; j < v.size(); j++){
res[i] += A[i][j] * v[j];
}
}
return res;
}
vector<double> operator*(double a, vector<double> &v){
vector<double> res(v.size());
for(int i = 0; i < v.size(); i++){
res[i] = a * v[i];
}
return res;
}
vector<vector<double>> operator*(vector<vector<double>> &A, vector<vector<double>> &B){
vector<vector<double>> res(A.size(), vector<double>(B[0].size()));
for(int i = 0; i < A.size(); i++){
for(int j = 0; j < B[0].size(); j++){
for(int k = 0; k < B.size(); k++){
res[i][j] += A[i][k] * B[k][j];
}
}
}
return res;
}
vector<double> operator/(vector<double> &v, double a){
vector<double> res(v.size());
for(int i = 0; i < v.size(); i++){
res[i] = v[i] / a;
}
return res;
}
// поиск максимума, возвращает tuple<row, value>
tuple<int, double> max(vector<double> &v){
int i_max = 0;
for(int i = 1; i < v.size(); i++){
if(abs(v[i]) > abs(v[i_max])){
i_max = i;
}
}
return {i_max, v[i_max]};
}
// поиск максимума, возвращает tuple<row, col, value>
tuple<int, int, double> max(vector<vector<double>> &A){
int i_max = 0, j_max = 1;
for(int i = 0; i < A.size(); i++){
for(int j = i + 1; j < A.size(); j++){
if(fabs(A[i][j]) > fabs(A[i_max][j_max])){
i_max = i;
j_max = j;
}
}
}
return {i_max, j_max, A[i_max][j_max]};
}
vector<vector<double>> transpose(vector<vector<double>> A){
for(int i = 0; i < A.size(); i++){
for(int j = i + 1; j < A[0].size(); j++){
swap(A[i][j], A[j][i]);
}
}
return A;
}
// endregion
struct Eigen{
vector<double> values;
vector<vector<double>> vectors;
};
// метод вращений якоби
Eigen jacobi(vector<vector<double>> A){
Eigen eigen;
eigen.vectors = vector<vector<double>>(A.size(), vector<double>(A.size()));
for(int i = 0; i < A.size(); i++){
eigen.vectors[i][i] = 1;
}
int iter = 0;
while(true){
int i_max, j_max;
double a_max;
tie(i_max, j_max, a_max) = max(A);
if(fabs(a_max) < eps){
break;
}
double phi = 0.5 * atan(2 * a_max / (A[i_max][i_max] - A[j_max][j_max]));
double c = cos(phi), s = sin(phi);
vector<vector<double>> U(A.size(), vector<double>(A.size()));
for(int i = 0; i < A.size(); i++){
U[i][i] = 1;
}
U[i_max][i_max] = U[j_max][j_max] = c;
U[i_max][j_max] = -s;
U[j_max][i_max] = s;
auto U_T = transpose(U);
auto tmp = U_T * A;
A = tmp * U;
eigen.vectors = eigen.vectors * U;
iter++;
}
eigen.vectors = transpose(eigen.vectors);
eigen.values = vector<double>(A.size());
for(int i = 0; i < A.size(); i++){
eigen.values[i] = A[i][i];
}
printf("iterations: %d\n", iter);
return eigen;
}
// степенной метод(максимальное по модулю собственное значение)
Eigen power(vector<vector<double>> A){
Eigen eigen;
eigen.vectors = vector<vector<double>>(A.size(), vector<double>(A.size()));
for(int i = 0; i < A.size(); i++){
eigen.vectors[i][i] = 1;
}
int iter = 0;
double lambda;
while(true){
vector<double> v = A * eigen.vectors[0];
lambda = norm(v);
v = v / lambda;
auto tmp = v - eigen.vectors[0];
auto t1 = A*v;
auto t2 = lambda*v;
auto t3 = t1-t2;
if(norm(t3) < eps){
break;
}
eigen.vectors[0] = v;
iter++;
}
eigen.values = vector<double>(A.size());
for(int i = 0; i < A.size(); i++){
eigen.values[i] = lambda;
}
printf("iterations: %d\n", iter);
return eigen;
}
int main(){
srand(time(0));
vector<vector<double>> A = generate_matrix(N);
printf("matrix A:\n");
print_matrix(A);
printf("\n------------------------\n\n");
printf("Jacobi:\n");
Eigen eigen = jacobi(A);
printf("eigen values:\n");
print_vector(eigen.values);
printf("eigen vectors:\n");
print_matrix(eigen.vectors);
printf("Ax - lambda x:\n");
for(int i = 0; i < eigen.values.size(); i++){
vector<double> v = A * eigen.vectors[i];
auto tmp = eigen.values[i] * eigen.vectors[i];
v = v - tmp;
printf("%10.8lf\n", norm(v));
}
printf("\n------------------------\n\n");
printf("Power:\n");
eigen = power(A);
printf("eigen max value: %f\n", eigen.values[0]);
printf("eigen max vector:\n");
print_vector(eigen.vectors[0]);
printf("Ax - lambda x:\n");
vector<double> v = A * eigen.vectors[0];
auto tmp = eigen.values[0] * eigen.vectors[0];
v = v - tmp;
printf("%10.8lf\n", norm(v));
return 0;
}