矩阵中QR算法分解简介和基于Eigen库使用示例

QR 算法是一种用于**特征值分解(Eigen Decomposition)**的迭代数值方法。广泛应用于求解实对称矩阵的特征值与特征向量,是现代数值线性代数中核心算法之一。


一、定义与目标

**QR算法(QR Algorithm)**是一种迭代方法,目标是对矩阵 A 求其特征值:

  • 输入:A∈Rn×nA \in \mathbb{R}^{n \times n}A∈Rn×n(一般为实对称矩阵)
  • 输出:AAA 的特征值和特征向量

该算法通过将矩阵分解为:

Ak=QkRk A_k = Q_k R_k Ak=QkRk

然后重新组合得到:

Ak+1=RkQk A_{k+1} = R_k Q_k Ak+1=RkQk

重复这个过程,多次迭代后 A_kA\_kA_k 收敛为一个上三角矩阵,其对角元素即为特征值。


二、原理与推导

假设 A 可对角化:

A=VΛV−1 A = V \Lambda V^{-1} A=VΛV−1

若我们不断对 A_k 做 QR 分解:

Ak=QkRk⇒Ak+1=RkQk A_k = Q_k R_k \Rightarrow A_{k+1} = R_k Q_k Ak=QkRk⇒Ak+1=RkQk

则:

Ak+1=QkTAkQk A_{k+1} = Q_k^T A_k Q_k Ak+1=QkTAkQk

这是一个相似变换(Similarity Transformation),意味着 A_{k+1}A_k 拥有相同特征值。

由于 A_k 是逐步对角化的,最终趋于上三角矩阵,其对角线收敛到 A 的特征值。


三、算法步骤

原始 QR 算法(无加速)

  1. 初始化:A_0 = A

  2. A_k 做 QR 分解:

    Ak=QkRk A_k = Q_k R_k Ak=QkRk

  3. 计算 A_{k+1} = R_k Q_k

  4. 判断是否收敛(如 \|A_{k+1} - A_k\| \< \\epsilon

  5. 重复步骤 2~4

改进:带位移的 QR 算法(Shifted QR)

通过引入位移(shift)\\mu_k 加快收敛速度:

Ak−μkI=QkRk⇒Ak+1=RkQk+μkI A_k - \mu_k I = Q_k R_k \Rightarrow A_{k+1} = R_k Q_k + \mu_k I Ak−μkI=QkRk⇒Ak+1=RkQk+μkI

位移常选为 A_k 的最后一行最后一列的元素(Wilkinson shift)。


四、应用场景

应用 描述
特征值计算 高效计算中小型矩阵的所有特征值
PCA QR 算法可用于求协方差矩阵的特征值(降维)
结构力学 解析振动系统特征频率
图像压缩 SVD(特征值分解的推广)相关算法
SLAM 优化 QR 用于线性系统求解,如 BA 优化中稀疏 QR

五、C++ 实现示例(使用 Eigen 库)

示例1

cpp 复制代码
#include <Eigen/Dense>
#include <iostream>

using namespace Eigen;
using namespace std;

int main() {
    MatrixXd A(3, 3);
    A << 2, -1, 0,
         -1, 2, -1,
          0, -1, 2;

    MatrixXd Ak = A;
    int maxIter = 100;
    double tol = 1e-8;

    for (int k = 0; k < maxIter; ++k) {
        HouseholderQR<MatrixXd> qr(Ak);
        MatrixXd Q = qr.householderQ();
        MatrixXd R = qr.matrixQR().triangularView<Upper>();
        Ak = R * Q;

        // 检查是否近似对角化
        MatrixXd offDiag = Ak - Ak.diagonal().asDiagonal();
        if (offDiag.norm() < tol) break;
    }

    cout << "近似对角矩阵 Ak:\n" << Ak << endl;
    cout << "特征值(近似):\n" << Ak.diagonal().transpose() << endl;

    return 0;
}

示例2-Eigen::SparseQR 示例

依赖:

  • #include <Eigen/Sparse>
  • #include <Eigen/SparseQR>

示例代码:稀疏 QR 解线性系统 Ax = b

cpp 复制代码
#include <iostream>
#include <Eigen/Sparse>
#include <Eigen/SparseQR>

int main() {
    using namespace Eigen;

    typedef SparseMatrix<double> SpMat;
    typedef Triplet<double> T;

    // 构造稀疏矩阵 A (5x5 三对角矩阵)
    std::vector<T> tripletList;
    tripletList.reserve(13);
    for (int i = 0; i < 5; ++i) {
        tripletList.emplace_back(i, i, 2.0);       // 对角
        if (i > 0) tripletList.emplace_back(i, i - 1, -1.0); // 下对角
        if (i < 4) tripletList.emplace_back(i, i + 1, -1.0); // 上对角
    }

    SpMat A(5, 5);
    A.setFromTriplets(tripletList.begin(), tripletList.end());

    // 右侧向量 b
    VectorXd b(5);
    b << 1, 2, 3, 4, 5;

    // 使用稀疏 QR 分解
    SparseQR<SpMat, COLAMDOrdering<int>> solver;
    solver.compute(A);
    if (solver.info() != Success) {
        std::cerr << "分解失败!" << std::endl;
        return -1;
    }

    // 解 Ax = b
    VectorXd x = solver.solve(b);
    if (solver.info() != Success) {
        std::cerr << "求解失败!" << std::endl;
        return -1;
    }

    std::cout << "解 x:\n" << x << std::endl;

    return 0;
}

相关注意事项

项目 说明
SparseQR 用于稀疏矩阵的列主元 QR 分解
COLAMDOrdering 使用最少填充的列重排序算法,提高分解效率
Triplet 构造 推荐方式,避免反复插入
矩阵类型 使用 Eigen::SparseMatrix<T>,不要使用 MatrixXd
求解过程 compute() 先分解,solve() 解方程组


六、注意事项与扩展

  • 对称矩阵 QR 收敛较快,非对称时需要更复杂处理(如 Hessenberg 预处理)
  • Eigen 库中已经内建 SelfAdjointEigenSolver 使用分块 + QR 实现
  • 稀疏矩阵场景中用 SparseQR 更合适
  • 在 SLAM 中,QR 分解(尤其是列主元排序 + 稀疏结构保留)常用于优化线性子问题

相关推荐
Msshu1231 天前
PD快充诱骗协议芯片XSP25支持PD+QC+FCP+SCP+AFC协议支持通过串口读取充电器功率信息
人工智能
一RTOS一1 天前
东土科技连投三家核心企业 发力具身机器人领域
人工智能·科技·机器人·具身智能·鸿道实时操作系统·国产嵌入式操作系统选型
坚持编程的菜鸟1 天前
LeetCode每日一题——困于环中的机器人
c语言·算法·leetcode·机器人
ACP广源盛139246256731 天前
(ACP广源盛)GSV1175---- MIPI/LVDS 转 Type-C/DisplayPort 1.2 转换器产品说明及功能分享
人工智能·音视频
Aurorar0rua1 天前
C Primer Plus Notes 09
java·c语言·算法
胡耀超1 天前
隐私计算技术全景:从联邦学习到可信执行环境的实战指南—数据安全——隐私计算 联邦学习 多方安全计算 可信执行环境 差分隐私
人工智能·安全·数据安全·tee·联邦学习·差分隐私·隐私计算
停停的茶1 天前
深度学习(目标检测)
人工智能·深度学习·目标检测
Y200309161 天前
基于 CIFAR10 数据集的卷积神经网络(CNN)模型训练与集成学习
人工智能·cnn·集成学习
老兵发新帖1 天前
主流神经网络快速应用指南
人工智能·深度学习·神经网络
AI量化投资实验室1 天前
15年122倍,年化43.58%,回撤才20%,Optuna机器学习多目标调参backtrader,附python代码
人工智能·python·机器学习