首页 > 编程语言 >【c++/c】幂法求解绝对值最大的特征值、最大和最小的特征值

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

时间:2023-02-18 00:00:27浏览次数:46  
标签:特征值 cast int double vecRow c++ 幂法 static size

【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:计算最小和最大特征值】(待更ing)

 

标签:特征值,cast,int,double,vecRow,c++,幂法,static,size
From: https://www.cnblogs.com/zhimingyiji/p/17131801.html

相关文章

  • 第十八章 用于大型程序的工具 Part1 C++异常处理
    异常基本概念BjarneStroustrup说:提供异常的基本目的就是为了处理上面的问题。基本思想是:让一个函数在发现了自己无法处理的错误时抛出(throw)一个异常,然后它的(直接或者间接......
  • 为什么C++既有指针又有引用?
    C++从C继承了指针,所以我不能在不导致严重的兼容性问题的情况下删除它们。引用在很多方面都很有用,但我在C++中引入它们的直接原因是为了支持运算符重载。例如:void......
  • 记录一个有意思c++现象
      即使类没有带参初始化函数依然可以给对象数组赋值,而且有多个成员时是每个对象每个成员逐个赋值的。====================  也可以这样两层赋值。============......
  • C++代码并行优化心得(OpenMP & TBB & Thread Pool)
    待更!  cmake引入OpenMP使用cmake中find_package指令查找openmp,格式如下:find_package(OpenMPREQUIRED)cmaketarget_link_libraries链接openmp:target_link_......
  • C/C++学生个人消费记录管理系统[2023-02-17]
    C/C++学生个人消费记录管理系统[2023-02-17]学生个人消费记录管理系统学生个人消费记录管理系统给学生一个管理个人财务的平台,主要用于对学生的生活费用收入、支出进行添......
  • 【AI入门】C++构建BP神经网络,并实现手写数字识别
    目录BP神经网络的基本原理BP神经网络的C++实现将BP神经网络应用于手写数字识别存在的疑惑BP神经网络的基本原理参考资料:机器学习(西瓜书)-周志华如图所示,一个简单的BP......
  • C++ 猜数字
    #include<iostream>#include<random>#include<limits>namespacerandom{std::random_devicerd;std::seed_seqrr={rd(),rd(),rd(),rd(),rd(),rd......
  • C++中的静态成员
    在一个类的定义中,关键字static声明一个不属于类实例的成员。一些细节如果类定义中某个成员的声明说明符包含关键字static,那么它就是类的静态成员。静态成员的名称不能......
  • C++继承--公有继承
    C++继承--公有继承#include<iostream>#include<cstdio>usingnamespacestd;classStudent{//基类public:voidget_value();voiddisplay();private:intnu......
  • c++继承---私有继承
    私有继承   在声明一个派生类的时候将基类的继承方式指定为private的,称为私有继承,用私有继承方式建立的派生类称为私有派生类,其基类称为私有基类.私有继承中的......