当前位置: 首页 > news >正文

基于 Householder 变换的 qr 分解 算法与源码实现

1,算法描述

1.1 算法1 反射向量

计算 Householder 向量

给定 \mathbf{x} \in \mathbb{R}^m 算法计算满足 v(1) = 1.0 的 \mathbf{v}\in \mathbb{R}^m\beta \in \mathbb{R} , 使得 \mathbf{P} = \mathbf{I}_m - \beta \mathbf{v}\mathbf{v}^ T 是正交矩阵且 \mathbf{Px} = \parallel \mathbf{x} \parallel_2\mathbf{e}_1 , 即,将m维向量 \mathbf{x} 通过反射变换 \mathbf{P} 反射至 \mathbf{e}_1 轴上去。

\mathbf{function} [v, \beta] = \mathbf{house(x)}

        m = \mathbf{length(x)}

        \sigma = \mathbf{x(2:m)^T x(2:m)}

        \mathbf{v}=\left[\begin{array}{c} 1\\ \mathbf{x(2:m)}\end{array} \right ]

        \mathbf{if( } \sigma==0 \&\& \mathbf{x(1) >= 0} \mathbf{)}

                \beta = 0

        \mathbf{elseif(} \sigma==0 \&\& \mathbf{x(1)} <0 \mathbf{)}

                \beta = 2.0

       \mathbf{else}

                u = \sqrt{\mathbf{x(1)}+\sigma}

                \mathbf{if(x(1)}<=0\mathbf{)}

                        \mathbf{v(1) = x(1)} - u

                \mathbf{else}

                       \mathbf{v(1)} = -\sigma/(\mathbf{x(1)}+u)

                \mathbf{end}

                \beta = 2*\mathbf{v(1)}^2/(\sigma + \mathbf{v(1)}^2)

               \mathbf{v} = \mathbf{v}/\mathbf{v(1)}

        \mathbf{end}

1.2 算法2 QR 分解

Householder QR 分解

未完待补。。。。

2,源码实现

由如下几个文件组成:

Makefile
householder_qr_dec.cpp
householder_vector.cpp
householder_vector.h
utils.cpp
utils.h

Makefile


EXE := householder_qr_decall: $(EXE)%: %.cpp utils.cppg++ $^ -o $@ -lm -DBUILD_MAINhouseholder_qr_dec: householder_qr_dec.cpp householder_vector.cpp utils.cppg++ -g $^ -o $@ -lm -DBUILD_MAIN.PHONY: clean
clean:-rm -rf $(EXE)


householder_qr_dec.cpp

#include <stdlib.h>
#include <string.h>
#include "utils.h"
#include "householder_vector.h"void vector_mul_matrix(int m, int n, float* vt, float* A, int lda, float* C)// C(1, n) = vt(1, m) * A(m, n)
{for(int j=0; j<n; j++){float sigma = 0.0f;for(int k=0; k<m; k++){sigma += vt[k] * A[k + j*lda];}C[j] = sigma;}
}// A(m, n) = A - b * v(m) * C(n)
void rank_one_update(int m, int n, float beta, float* v, float* C, float* A, int lda)
{for(int i=0; i<m; i++){for(int j=0; j<n; j++){A[i + j*lda] -= beta * v[i] * C[j];}}
}void store_householder_vector(float* A, float* v, int len)
{for(int i=0; i<len; i++){A[i] = v[i];}
}// (Householder QR)
void householder_qr(int m, int n, float* A, int lda, float* tau)
{float* v = nullptr;float beta = 0;float* C = nullptr;C = (float*)malloc(m*sizeof(float));v = (float*)malloc(m*sizeof(float));for(int j=0; j<n; j++){//step1, [v, beta] = house(A(j:m, j))//void house(int m, float* x, float* v, float& beta);house(m-j, A+j+j*lda, v, beta);tau[j] = beta;//step2, A(j:m, j:n) = (I - beta*v*v^T)A(j:m, j:n)//m 可能挺大,n<=32 or 64;// A = A - b*v*(v^t * A) = A - b*v*C;  (j:m, j:n),   v(j:m),   (v^t * A)(j:n)//step2.1 C(j:n) = (v^t)(1, j:m) * A(j:m, j:n)vector_mul_matrix(m-j, n-j, v, A+j+j*lda, lda, C);//step2.2 A(j:m, j:n) = A -  b*v*C;rank_one_update(m-j, n-j, beta, v, C, A+j+j*lda, lda);//step3, if(j<m) A(j+1 : m, j) = v(2 : m-j+1)store_householder_vector(A+(j+1 + j*lda), v+1, m-j-1);}
}int main()
{int m = 4;int n = 4;int lda = m;int ldb = lda;float* A = nullptr;float* B = nullptr;A = (float*)malloc(lda*n*sizeof(float));B = (float*)malloc(ldb*n*sizeof(float));init_matrix(m, n, A, lda, 2024); printf("A =[ ...\n");   print_matrix(m, n, A, lda);memcpy(B, A, lda*n*sizeof(float));float* tau = nullptr;tau = (float*)malloc(n*sizeof(float));householder_qr(m, n, A, lda, tau);printf("R+tau =\n");print_matrix(m, n, A, lda);printf("\ntau = \n");print_vector(n, tau);return 0;
}


householder_vector.cpp

#include <stdlib.h>#include "utils.h"//#define BUILD_MAIN
void v_is_1_x_2_m(int M, float* x, float* v)
{v[0] = 1.0f;for(int i=1; i<M; i++){v[i] = x[i];}
}void dot_vector(int n, float* x, float* y, float& sigma)
{sigma = 0.0f;for(int i=0; i<n; i++){sigma += x[i]*y[i];}
}void vector_div_scalar(int M, float* v, float alpha)
{for(int i=0; i<M; i++){v[i] /= alpha;}
}void house(int m, float* x, float* v, float& beta)
{float sigma;dot_vector(m-1, x+1, x+1, sigma);//    printf("in house() sigma = %7.3f\n", sigma);v_is_1_x_2_m(m, x, v);// v= ( 1 x(2 : m)^t )^tif(sigma==0.0f && x[0]>=0.0f){beta = 0.0f;}else if(sigma==0.0f && x[0]<0.0f){beta = 2.0f;}else{float miu;miu = sqrt(x[0]*x[0] + sigma);if(x[0]<= 0.0f){v[0] = x[0] - miu;}else{v[0] = -sigma/(x[0]+miu);}beta = 2.0f*v[0]*v[0]/(sigma + v[0]*v[0]);vector_div_scalar(m, v, v[0]);}
}


householder_vector.h

#pragma once void house(int m, float* x, float* v, float& beta);


utils.cpp

#include "utils.h"void init_matrix(int M, int N, float* A, int lda, int seed)
{srand(seed);for(int i=0; i<M; i++){for(int j=0; j<N; j++){int r;r = rand();A[i + j*lda] = (((r>(RAND_MAX/3)) ? 3.0f : -3.0f)*rand())/RAND_MAX;}}
}void print_matrix(int M, int N, float* A, int lda)
{for(int i=0; i<M; i++){for(int j=0; j<N; j++){printf("%7.4f, ", A[i + j*lda]);}printf("\n");}
}void print_vector(int N, float* A)
{print_matrix(1, N, A, 1);
}


utils.h

#pragma once
#include <stdio.h>
#include <math.h>void init_matrix(int M, int N, float* A, int lda, int seed);
void print_matrix(int M, int N, float* A, int lda);
void print_vector(int M, float* A);

3,运行效果

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • sdk监控平台
  • 14.JS学习篇-CSR和SSR
  • golang并发编程——概述
  • sql中exist和in的区别
  • 240828-Gradio结合Html+Css+Javascript制作年历
  • Open3D编译安装
  • 同人小游戏之斗罗大陆3
  • 【STM32】IIC
  • es集群详解
  • IDEA导入第三方jar包, 并在Maven中打包该jar包
  • 医疗数字化转型数据中台架构方案(一)
  • vim 简易配置
  • 【视频讲解】SMOTEBoost、RBBoost和RUSBoost不平衡数据集的集成分类酵母数据集、治癌候选药物|数据分享...
  • 【奇某信-注册/登录安全分析报告】
  • 哪些领域最适合采用音视频私有化解决方案?
  • 分享的文章《人生如棋》
  • 【编码】-360实习笔试编程题(二)-2016.03.29
  • 0基础学习移动端适配
  • 2018天猫双11|这就是阿里云!不止有新技术,更有温暖的社会力量
  • CSS实用技巧
  • docker-consul
  • iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码...
  • Mocha测试初探
  • Python socket服务器端、客户端传送信息
  • Ruby 2.x 源代码分析:扩展 概述
  • select2 取值 遍历 设置默认值
  • STAR法则
  • Synchronized 关键字使用、底层原理、JDK1.6 之后的底层优化以及 和ReenTrantLock 的对比...
  • uni-app项目数字滚动
  • Vultr 教程目录
  • 大快搜索数据爬虫技术实例安装教学篇
  • 动态魔术使用DBMS_SQL
  • 快速构建spring-cloud+sleuth+rabbit+ zipkin+es+kibana+grafana日志跟踪平台
  • 盘点那些不知名却常用的 Git 操作
  • 深度学习在携程攻略社区的应用
  • 使用权重正则化较少模型过拟合
  • 小李飞刀:SQL题目刷起来!
  • 用jQuery怎么做到前后端分离
  • 正则表达式
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • # 睡眠3秒_床上这样睡觉的人,睡眠质量多半不好
  • #define MODIFY_REG(REG, CLEARMASK, SETMASK)
  • #Java第九次作业--输入输出流和文件操作
  • #pragma multi_compile #pragma shader_feature
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (zz)子曾经曰过:先有司,赦小过,举贤才
  • (保姆级教程)Mysql中索引、触发器、存储过程、存储函数的概念、作用,以及如何使用索引、存储过程,代码操作演示
  • (第61天)多租户架构(CDB/PDB)
  • (附源码)ssm高校志愿者服务系统 毕业设计 011648
  • (机器学习-深度学习快速入门)第三章机器学习-第二节:机器学习模型之线性回归
  • (十六)一篇文章学会Java的常用API
  • (学习日记)2024.03.12:UCOSIII第十四节:时基列表
  • (一)python发送HTTP 请求的两种方式(get和post )
  • (转)Windows2003安全设置/维护
  • ***利用Ms05002溢出找“肉鸡