【c++/c】幂法求解绝对值最大的特征值、最大和最小的特征值

【part 1:幂法的迭代格式】

    

 

 【part 2:计算绝对值最大特征值的步骤】

  1.明确要求解特征值的矩阵A和初始非零向量u0

  2.将u0单位化得到yk-1

  3.通过矩阵乘法计算得到uk

  4.通过矩阵乘法计算得到βk(上图中的βk-1应为βk,为书写时的笔误),判断误差

    如果误差小于允许误差,即为计算得到的绝对值最大的特征值

    反之,则继续迭代计算

  5.如果迭代次数大于设定的最大次数,计算失败。

示例:

step1:确定向量/矩阵

  1.需要求解特征值的矩阵A:

#include <iostream>
#include <vector>
#include <math.h>
using vec = std::vector<std::vector<double>>;
using vecRow = std::vector<double>;
int g_time{ 5000 };
double g_err{ 10e-12 };
vec createA(double b = 0.16, double c = -0.064,int size = 501) {
    vec A(size, vecRow(size));
    double e{ exp(1) };
    for (int i = 0;i != size;++i) {
        for (int j = 0;j != size;++j) {
            if (i == j) {
                A[i][j] = (1.64 - 0.024 * (i+1)) * sin(0.2 * (i+1)) - 0.64 * exp(0.1/(i+1));
            }
            else if (fabs(i - j) == 1) {
                A[i][j] = b;
            }
            else if (fabs(i - j) == 2) {
                A[i][j] = c;
            }
            else {
                A[i][j] = 0;
            }
        }
    }
    return A;
}

  2.初始非零向量u0。当然可以是别的形式。

vecRow createU(int num = 1,int size=501) {
    vecRow u(size);
    for (int i = 0;i < size;++i) {
        u[i] = num;
    }
    return u;
}

Step2  矩阵单位化

vecRow normalize(vecRow u) {
    double mid{};
    mid = multi(u, u);
    double eta{ sqrt(mid) };
    int row{ static_cast<int> (u.size()) };
    vecRow y(row);
    for (int i = 0;i < row;++i) {
        y[i] = u[i] / eta;
    }
    return y;
}

Step3 矩阵乘法

vec multi(vec A, vec B) {
    int row1{ static_cast<int> (A.size()) };
    int col1{ static_cast<int>(A[0].size()) };
    int row2{ static_cast<int>(B.size()) };
    int col2{ static_cast<int>(B[0].size()) };
    vec res(row1, vecRow(col2));
    double temp{};
    assert(col1 == row2 && "第一个矩阵的列和第二个矩阵的行不相等");
    for (int i = 0;i != row1;++i) {
        for (int j = 0;j != col2;++j) {
            temp = 0;
            for (int k = 0;k != col1;++k) {
                temp += A[i][k] * B[k][j];
            }
            res[i][j] = temp;
        }
    }
    return res;
}

double multi(vecRow A, vecRow B) {
    int row1{ static_cast<int> (A.size()) };
    int row2{ static_cast<int>(B.size()) };
    assert(row1 == row2 && "第一个矩阵的列和第二个矩阵的行不相等");
    double sum{0.0};
    for (int i = 0;i != row1;++i) {
        sum += A[i] * B[i];
    }
    return sum;
}

vecRow multi(vec A, vecRow y) {
    int row1{ static_cast<int> (A.size()) };
    int col1{ static_cast<int>(A[0].size()) };
    int row2{ static_cast<int>(y.size()) };
    vecRow result(row2);
    double sum{};
    assert(col1 == row2 && "第一个矩阵的列和第二个矩阵的行不相等");
    for (int i = 0;i != row1;++i) {
        sum = 0;
        for (int j = 0;j != col1;++j) {
            sum += A[i][j] * y[j];
        }
        result[i] = sum;
    }
    return result;
}

Step4 迭代计算

double mi(vec A, vecRow u0) {
    int k{ 1 };
    int row{ static_cast<int> (u0.size()) };
    vecRow y(row);
    vecRow uk(row);
    //double betaSet[static_cast<int>(g_time)]{};
    //vecRow betaSet(g_time);
   // betaSet[0]= 0;
    double beta0{};
    double betaStep{};
    double distance{};
    double beta{};
    while (k) {
        y = normalize(u0);
       // print(y);
        uk = multi(A, y);
        //betaSet[k] = multi(y, uk);
        //std::cout << betaSet[k];
        beta0 = betaStep;
        betaStep = multi(y, uk);
        distance = fabs((betaStep - beta0) / betaStep);
        if(distance<=g_err){
            beta = betaStep;
            //std::cout <<beta<< " is found\n";
            return beta;
        }
        if (k > g_time) {
            std::cout << "out of g_time" << '\n';
            return 0;
        }
        u0 = uk;
        //std::cout << "step " << k << '\n';
        ++k;
    }
    return 0;
}

 【part 3:计算最小和最大特征值】

 设绝对值最大的特征值为β

  (1)beta > 0,则最大特征值为β

  (2)beta < 0,则最小特征值为β

如何求解另一个最小/最大的特征值? 令矩阵B为A-βI,利用幂法计算得出B的绝对值最大的特征值。特征值再加上减去的β,即为我们想要的另一个特征值。

step 1 创建B矩阵

vec createB(vec A, double beta) {
    int row{ static_cast<int> (A.size()) };
    int col{ static_cast<int>(A[0].size()) };
    for (int i = 0;i < row;++i) {
        for (int j = 0;j < col;++j) {
            if (i == j) {
                A[i][j] -= beta * 1;
            }
            else {
                continue;
            }
        }
    }
    return A;
}

Step 2 判断矩阵A的绝对值最大的特征值的正负

vecRow chargeMi(vec A,double beta,vecRow u0) {
    vec B{ createB(A, beta) };
    double lambda{ mi(B, u0) + beta };
    vecRow lambdaMinMax(2);
    if (beta > 0) {
        lambdaMinMax[0] = lambda;
        lambdaMinMax[1] = beta;
    }
    else {
        lambdaMinMax[0] = beta;
        lambdaMinMax[1] = lambda;
    }
    return lambdaMinMax;
}

 

posted @ 2023-02-17 23:54  致命一姬  阅读(507)  评论(0编辑  收藏  举报