GSL 系列 6 — 线性代数 3 — QR 分解

本文详细介绍了GSL库中线性代数的QR分解,包括Householder和递归版本的实现,以及如何使用QR分解求解线性方程组、计算矩阵乘积和进行秩1更新。此外,还讨论了特殊矩阵和带列转置的QR分解。
摘要由CSDN通过智能技术生成

0 写在前面

关于 QR 分解的背景知识介绍,参见:GSL 系列 6 — 线性代数 1 — 背景知识 1
(QR 分解) 节,本篇只说明相关函数

若无特别说明,本篇代码均来自头文件 gsl_linalg.h

1 QR 分解相关函数

1.1 QR 分解

A = Q R A=QR A=QR

Householder 版:

将 A 分解为 Q R, Q 分别存储在矩阵 A 的下三角部分 ( v v v) 和向量 tau ( τ \tau τ) 中,R 存储在矩阵 A 的上三角部分(含对角)

推荐此方法用于中小型矩阵,或用于 M < N M<N M<N

int gsl_linalg_QR_decomp (gsl_matrix * A, gsl_vector * tau);

递归版 (带 _r):

将 A 分解为 Q R, Q 分别存储在矩阵 A 的下三角部分 ( V V V) 和矩阵 T ( T T T) 中,R 存储在矩阵 A 的上三角部分(含对角)

int gsl_linalg_QR_decomp_r (gsl_matrix * A, gsl_matrix * T);

此方法要求 M ≥ N M\ge N MN,并且该方法对于“高瘦”型矩阵 ( M ≫ N M\gg N MN) 表现更佳

1.2 QR 解包

根据 QR 和 tau (T) 得到矩阵 Q 和矩阵 R

int gsl_linalg_QR_unpack(const gsl_matrix * QR, const gsl_vector * tau, gsl_matrix * Q, gsl_matrix * R);
int gsl_linalg_QR_unpack_r(const gsl_matrix * QR, const gsl_matrix * T, gsl_matrix * Q, gsl_matrix * R);

1.3 QR 求解线性方程组

  1. 根据 QR 分解得到的 QR 和 tau (或 T),求解线性方程组 A x = b Ax=b Ax=b
int gsl_linalg_QR_solve (const gsl_matrix * QR, const gsl_vector * tau, const gsl_vector * b, gsl_vector * x);
int gsl_linalg_QR_solve_r (const gsl_matrix * QR, const gsl_matrix * T, const gsl_vector * b, gsl_vector * x);
// 置换版本
int gsl_linalg_QR_svx (const gsl_matrix * QR, const gsl_vector * tau, gsl_vector * x);
  1. 求解 A x = b Ax=b Ax=b 的最小二乘解(使用欧几里得范数, A ( M > N ) A(M>N) A(M>N)

    Householder 版还输出残差向量 (residual)

    递归版输出的向量 x 包含两个部分,x 的前 N N N 个元素为解,后 M − N M-N MN 个元素的向量范数等于残差范数,递归版还需要一个向量工作空间 (work),长度为 N N N

int gsl_linalg_QR_lssolve (const gsl_matrix * QR, const gsl_vector * tau, const gsl_vector * b, 
                           gsl_vector * x, gsl_vector * residual);
int gsl_linalg_QR_lssolve_r (const gsl_matrix * QR, const gsl_matrix * T, const gsl_vector 
下面是一个基于GSL线性代数实例,演示如何使用GSL库来解决线性方程组和求逆矩阵问题。 ```c #include <stdio.h> #include <gsl/gsl_linalg.h> int main() { // 定义矩阵和向量 double mdata[] = {1.0, 2.0, 3.0, 2.0, 4.0, 5.0, 3.0, 5.0, 6.0}; double vdata[] = {1.0, 2.0, 3.0}; gsl_matrix_view m = gsl_matrix_view_array(mdata, 3, 3); gsl_vector_view v = gsl_vector_view_array(vdata, 3); // 解决线性方程组 Ax = b gsl_vector *x = gsl_vector_alloc(3); gsl_permutation *p = gsl_permutation_alloc(3); int signum; gsl_linalg_LU_decomp(&m.matrix, p, &signum); gsl_linalg_LU_solve(&m.matrix, p, &v.vector, x); printf("Solution to Ax = b:\n"); gsl_vector_fprintf(stdout, x, "%g"); // 求矩阵的逆 gsl_matrix *inv = gsl_matrix_alloc(3, 3); gsl_matrix *mcopy = gsl_matrix_alloc(3, 3); gsl_matrix_memcpy(mcopy, &m.matrix); gsl_linalg_LU_decomp(mcopy, p, &signum); gsl_linalg_LU_invert(mcopy, p, inv); printf("Inverse of A:\n"); gsl_matrix_fprintf(stdout, inv, "%g"); // 释放内存 gsl_vector_free(x); gsl_permutation_free(p); gsl_matrix_free(inv); gsl_matrix_free(mcopy); return 0; } ``` 该程序首先定义了一个3x3的矩阵和一个长度为3的向量,并将它们存储在GSL的矩阵和向量视图中。然后,程序使用GSL库中的LU分解和求解线性方程组函数来解决线性方程组Ax=b,并打印解向量x的值。接下来,程序使用GSL库中的LU分解和求逆矩阵函数来求解矩阵A的逆,并打印逆矩阵的值。最后,程序释放了动态分配的内存。 需要注意的是,在编译该程序时,需要链接GSL库,例如: ``` gcc -o example example.c -lgsl -lgslcblas -lm ``` 此处,-lgsl和-lgslcblas选项用于链接GSL库和BLAS库,-lm选项用于链接数学库。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值