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

news2024/9/20 0:55:29

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_dec

all: $(EXE)

%: %.cpp utils.cpp
	g++ $^ -o $@ -lm -DBUILD_MAIN

householder_qr_dec: householder_qr_dec.cpp householder_vector.cpp utils.cpp
	g++ -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 )^t

    if(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,运行效果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2092991.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

什么是RS485总线?

1.什么是RS485总线&#xff1f; RS485 是一种通用的通信标准&#xff0c;广泛用于数据采集和控制应用中。 它的主要优点之一是它允许将多个 RS485 设备放在同一条总线上&#xff0c;这使得多个节点可以相互连接。 RS-485是美国电子工业协会&#xff08;EIA&#xff09;在1983年…

2024HarmonyOS应用开发者高级认证最新整理题库和答案(已收录182道 )

更新截止2024-08-27,完整题库一共182道题,足够覆盖90%考题,如有新题和遗漏我会持续补充 所有题目的选项都是打乱顺序的,记答案不要记序号 完整题库请在我的网盘下载或查看在线文档 完整题库在线文档预览 单选(已收录102道) 1 . 以下哪个装饰器用来表示并发共享对象。(B) A. @…

Windows服务器应急响应(下)

目录 介绍步骤 介绍 进程&#xff08;Process&#xff09;是计算机中的程序关于某数据集合上的一次运行活动&#xff0c;是系统进行资源分配和调度的基本单位&#xff0c;是操作系统结构的基础。在早期面向进程设计的计算机结构中&#xff0c;进程是程序的基本执行实体&#x…

基于FPGA的lz4解压缩仿真调试

1、简介 对于任意长度顺序呈现的输入数据流&#xff0c;通过对冗余byte的数据编码&#xff0c;完成数据压缩的问题。数据包格式 从数据包长度可知&#xff0c;最少需要5个字节才能压缩&#xff0c;否则压缩无意义&#xff0c;对于lz其他的介绍可以百度&#xff0c;本文只介绍…

JobScheduler 开发自测调试

1. 目标 例如以下模拟数据 相同时间内灭屏待机情况 有Job优化版本 无Job优化版本 数据展示 剩余电量 50 45 续航提升5% 时间延迟次数 100 0 N/A,体现数据优化原因 拦截Job次数 132 0 N/A,体现数据优化原因 第三方App的Job 执行总次数(越大越耗电) 20 200 优化后,减少(1-20/…

C++ 变量、输入输出、表达式和顺序语句 ac-wing

输入两个整数&#xff0c;求这两个整数的和是多少。 #include <iostream> using namespace std; int main () {int a, b;cin >> a >> b;cout << a b << endl;return 0; }差 #include<iostream> using namespace std; int main() {int A…

easy_fastapi 后端开发框架

GitHub easy_fastapi by one-ccs 遵循 MIT 开源协议 Easy FastAPI 基于 FastAPI 开发的后端框架&#xff0c;集成 SQLAlchemy、Pydantic、Alembic、PyJWT 等插件。 一、目录结构说明 project-root/ │ ├─ backend/ # 后端项目目录&#xff08;python 3.12.4&#xff09; │…

微信小程序背景图无法显示

文章目录 不知道有没有人跟我一样&#xff0c;刚接触微信小程序&#xff0c;在写代码的时候&#xff0c;背景图莫名奇妙不显示。 网上有很多解决方法&#xff0c;比如转 base64 &#xff0c;网络图片地址等等&#xff0c;但我觉得都太麻烦了&#xff0c;这里直接给出我的解决方…

Unity实战案例全解析 之 背包/贩卖/锻造系统(左侧类图实现)

物品类 using System.Collections; using System.Collections.Generic; using UnityEngine; public class Item {#region 物品类的基础属性public int ID { get; set; }public string Name { get; set; }public Typeitem typeitem { get; set; }//物品类型public Qualityitem…

VMware17 虚拟机使用NAT模式上网配置

1、. 确认网络适配器选择NAT模式 2、 查看所需要配置的网络信息 在NAT设置里面找到网关ip 在DHCP设置中查看可用ip的范围 后面设置虚拟机的etc/sysconfig/network-scripts/下面的ens文件会用到 查看网卡名称 ip addr 我这里的网卡名称是ens33 配置网关、ip地址、DNS地址 vi…

[线程]单例模式 及 指令重排序

文章目录 一. 单例模式饿汉模式懒汉模式单例模式中涉及到的线程安全问题 二. 指令重排序引起线程安全问题 一. 单例模式 单例模式, 是一种经典的设计模式 设计模式: 类似于棋谱, 把编程中各种经典的问题场景给你盘一盘, 并给出一下解决方案 遇到这种场景, 代码就这样写, 绝对不…

Linux和Unix的区别及为什么鸿蒙系统不用Unix的原因

目录 Linux是什么? Unix是什么&#xff1f; 他们的区别&#xff1a; 鸿蒙系统介绍及鸿蒙系统不用Unix的原因 Linux是什么? Linux的历史可以追溯到1991年&#xff0c;由芬兰的计算机科学家林纳斯托瓦兹&#xff08;Linus Torvalds&#xff09;为了学习操作系统的工作原理而…

【 OpenHarmony 系统应用源码魔改 】-- Launcher 之「桌面布局定制」

前言 阅读本篇文章之前&#xff0c;有几个需要说明一下&#xff1a; 调试设备&#xff1a;平板&#xff0c;如果你是开发者手机&#xff0c;一样可以加 Log 调试&#xff0c;源码仍然是手机和平板一起分析&#xff1b;文章中的 Log 信息所显示的数值可能跟你的设备不一样&…

STM32GPIO操作底层解析

我们使用HAL 和 标准库时&#xff0c;常常忽略他两的底层&#xff0c;只知道怎么用不知其原理&#xff0c;其实是大忌&#xff0c;因为底层丢了代码的灵魂就丢了&#xff0c;对以后的Linux开发不利 常用的指令函数&#xff1a; void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint…

本地编写Markdown格式文件,浏览器查看

编写准备 下载VsCode并安装&#xff0c;打开后在内部安装Markdown All in One、Markdown Preview Enhanced、Paste Image三个插件。新建一个文件夹用以后期保存你的笔记等文件在左侧新建文件&#xff0c;.md结尾&#xff0c;即完成创建右侧可实时的查看你的编写结果&#xff0…

SpringBoot3集成Spring Authorization Server实现SSO单点登录

1. 概述 在之前的文章中介绍过SpringBoot集成OAuth2老版本的方案SpringCloud搭建微服务之OAuth2实现SSO单点登录&#xff0c;随着Spring Authorization Server框架的成熟和SpringBoot版本的更新&#xff0c;新项目必然会采用新的技术和框架&#xff0c;本文将使用最新的Spring…

推理引擎测试-算力共享:test_inference_engine

目录 算力共享:test_inference_engine 关键点解释 实际应用和注意事项 算力共享:test_inference_engine 这段代码设计用于测试一个名为 InferenceEngine 的推理引擎,特别是测试其在处理不同分片(Shards)时的连续性和一致性。在机器学习和深度学习模型中,尤其是当模型非…

jenkins+python+appium 本地(简洁版)

jenkinspythonappium 本地&#xff08;简洁版&#xff09; 等服务器到了配到服务器上去&#xff0c;先在自己电脑上试一下。踩了n个坑&#xff0c;网上找的资料太深奥TAT 直接上操作 先把jenkins安装好&#xff08;肯定安装啦&#xff09;我的版本是2.462 新建任务 输入名称 选…

市占率最高的显示器件,TFT_LCD的驱动系统设计--Part 1

目录 一、简介 二、TFT-LCD驱动系统概述 &#xff08;一&#xff09;系统概述 &#xff08;二&#xff09;设计要点 二、扫描驱动电路设计 &#xff08;一&#xff09;概述 扫描驱动电路的功能 扫描驱动电路的组成部分 设计挑战 驱动模式 &#xff08;二&#xff09…

互联网全景消息(1)之RabbitMq基础入门

一、消息中间件 1.1消息队列回顾 消息队列中间件是分布式系统中重要的组件&#xff0c;主要解决应用解耦&#xff0c;异步消息&#xff0c;流量削锋等问题&#xff0c;实 现高性能&#xff0c;高可用&#xff0c;可伸缩和最终一致性架构。目前使用较多的消息队列有ActiveMQ &a…