用 GSL 求解超定方程组及矩阵的奇异值分解(SVD) 2
接上一篇。。。
下面我们将 SVD 相关的功能封装成一个类,以方便我们提取 S 和 V 的值。
另外,当我们一个 A 有多组 x 需要求解时,也只需要计算一次 SVD 分解,用下面的类能减少很多计算量。
头文件如下:
#ifndef GSLSINGULARVALUEDECOMPOSITION_H
#define GSLSINGULARVALUEDECOMPOSITION_H
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_blas.h>
#include <gsl/gsl_linalg.h>
#include <gsl/gsl_errno.h>
void linearSolve_SVD(const gsl_matrix * A, const gsl_vector * b, gsl_vector * x);
class GslSVD
{
public:
GslSVD();
~GslSVD();
int SV_decomp(const gsl_matrix * A);
int SV_decomp_mod(const gsl_matrix * A);
int SV_decomp_jacobi (gsl_matrix * A);
int SV_solve(const gsl_vector *b, gsl_vector *x);
gsl_vector * getVectorS();
gsl_matrix * getMatrixU();
gsl_matrix * getMatrixV();
int trimVectorS(double abseps);
private:
gsl_vector * S;
gsl_matrix * U;
gsl_matrix * V;
void alloc_suv(int rows, int cols);
};
#endif // GSLSINGULARVALUEDECOMPOSITION_H
程序文件如下:
#include "gsl_SVD.h"
void linearSolve_SVD(const gsl_matrix * A, const gsl_vector * b, gsl_vector * x)
{
int rows = A->size1;
int cols = A->size2;
gsl_vector * work = gsl_vector_alloc (cols);
gsl_vector * S = gsl_vector_alloc (cols);
gsl_matrix * U = gsl_matrix_alloc(rows, cols);;
gsl_matrix * V = gsl_matrix_alloc(cols, cols);
gsl_matrix_memcpy (U, A); // 为了不破坏 A 中原始的数据,这里全都拷贝到 U 中
gsl_linalg_SV_decomp( U, V, S, work );
gsl_linalg_SV_solve ( U, V, S, b, x );
gsl_vector_free(work);
gsl_vector_free(S);
gsl_matrix_free(V);
gsl_matrix_free(U);
}
int GslSVD::trimVectorS(double abseps)
{
int count = 0;
for(int i = 0; i < S->size; i++)
{
if(fabs(gsl_vector_get(S, i)) < abseps)
{
count ++;
gsl_vector_set(S, i, 0);
}
}
return count;
}
gsl_vector * GslSVD::getVectorS()
{
if(S == NULL) return NULL;
gsl_vector * s = gsl_vector_alloc(S->size);
gsl_vector_memcpy(s, S);
return s;
}
gsl_matrix * GslSVD::getMatrixU()
{
if(U == NULL) return NULL;
gsl_matrix * u = gsl_matrix_alloc(U->size1, U->size2);
gsl_matrix_memcpy(u, U);
return u;
}
gsl_matrix * GslSVD::getMatrixV()
{
if(V == NULL) return NULL;
gsl_matrix * v = gsl_matrix_alloc(V->size1, V->size2);
gsl_matrix_memcpy(v, V);
return v;
}
GslSVD::GslSVD()
{
S = NULL;
U = NULL;
V = NULL;
}
void GslSVD::alloc_suv(int rows, int cols)
{
if( S != NULL )
{
gsl_vector_free(S);
gsl_matrix_free(U);
gsl_matrix_free(V);
}
S = gsl_vector_alloc (cols);
U = gsl_matrix_alloc(rows, cols);
V = gsl_matrix_alloc(cols, cols);
}
int GslSVD::SV_decomp(const gsl_matrix * A)
{
int rows = A->size1;
int cols = A->size2;
gsl_vector * work = gsl_vector_alloc (cols);
alloc_suv(rows, cols);
gsl_matrix_memcpy (U, A); // 为了不破坏 A 中原始的数据,这里全都拷贝到 U 中
int ret = gsl_linalg_SV_decomp( U, V, S, work );
gsl_vector_free(work);
return ret;
}
int GslSVD::SV_decomp_mod(const gsl_matrix * A)
{
int rows = A->size1;
int cols = A->size2;
gsl_vector * work = gsl_vector_alloc (cols);
gsl_matrix *X = gsl_matrix_alloc(cols, cols);
alloc_suv(rows, cols);
gsl_matrix_memcpy (U, A); // 为了不破坏 A 中原始的数据,这里全都拷贝到 U 中
int ret = gsl_linalg_SV_decomp_mod( U, X, V, S, work );
gsl_matrix_free(X);
gsl_vector_free(work);
return ret;
}
int GslSVD::SV_decomp_jacobi (gsl_matrix * A)
{
int rows = A->size1;
int cols = A->size2;
alloc_suv(rows, cols);
gsl_matrix_memcpy (U, A); // 为了不破坏 A 中原始的数据,这里全都拷贝到 U 中
int ret = gsl_linalg_SV_decomp_jacobi( U, V, S );
return ret;
}
int GslSVD::SV_solve(const gsl_vector *b, gsl_vector *x)
{
if(U != NULL)
{
return gsl_linalg_SV_solve (U, V, S, b, x);
}
return -1;
}
GslSVD::~GslSVD()
{
if(S != NULL)
{
gsl_vector_free(S);
gsl_matrix_free(V);
gsl_matrix_free(U);
}
}
下面是个简单的测试代码:
void test5()
{
double a_data[] = {1, 2,
2, 4};
gsl_matrix_view A = gsl_matrix_view_array (a_data, 2, 2);
GslSVD svd;
svd.SV_decomp(&A.matrix);
puts("S = ");
gsl_vector_fprintf (stdout, svd.getVectorS(), "%f");
puts("\nV = ");
gsl_matrix_fprintf (stdout, svd.getMatrixV(), "%f");
double b_data[] = {3, 6};
gsl_vector_view b = gsl_vector_view_array (b_data, 2);
gsl_vector * x = gsl_vector_alloc (2);
svd.SV_solve(&b.vector, x);
puts("\nx = ");
gsl_vector_fprintf (stdout, x, "%f");
}
用 GSL 求解超定方程组及矩阵的奇异值分解(SVD) 2的更多相关文章
- 用 GSL 求解超定方程组及矩阵的奇异值分解(SVD)
用 GSL 求解超定方程组及矩阵的奇异值分解(SVD) 最近在学习高动态图像(HDR)合成的算法,其中需要求解一个超定方程组,因此花了点时间研究了一下如何用 GSL 来解决这个问题. GSL 里是有最 ...
- Python最小二乘法解非线性超定方程组
求解非线性超定方程组,网上搜到的大多是线性方程组的最小二乘解法,对于非线性方程组无济于事. 这里分享一种方法:SciPy库的scipy.optimize.leastsq函数. import numpy ...
- 小游戏 Lights Out (关灯) 的求解 —— 异或方程组
Author : Evensgn Blog Link : http://www.cnblogs.com/JoeFan/ Article Link : http://www.cnblogs.com/J ...
- 高斯消元法求解异或方程组: cojs.tk 539.//BZOJ 1770 牛棚的灯
高斯消元求解异或方程组: 比较不错的一篇文章:http://blog.sina.com.cn/s/blog_51cea4040100g7hl.html cojs.tk 539. 牛棚的灯 ★★☆ ...
- 【poj1830-开关问题】高斯消元求解异或方程组
第一道高斯消元题目~ 题目:有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为开就变为关 ...
- 机器学习降维方法概括, LASSO参数缩减、主成分分析PCA、小波分析、线性判别LDA、拉普拉斯映射、深度学习SparseAutoEncoder、矩阵奇异值分解SVD、LLE局部线性嵌入、Isomap等距映射
机器学习降维方法概括 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u014772862/article/details/52335970 最近 ...
- 矩阵奇异值分解(SVD)及其应用
机器学习中的数学(5)-强大的矩阵奇异值分解(SVD)及其应用(好文) [简化数据]奇异值分解(SVD) <数学之美> 第15章 矩阵运算和文本处理中的两个分类问题
- 矩阵的奇异值分解(SVD)(理论)
矩阵的奇异值分解(Singular Value Decomposition,SVD)是数值计算中的精彩之处,在其它数学领域和机器学习领域得到了广泛的应用,如矩阵的广义逆,主分成分析(PCA),自然语言 ...
- 奇异值分解(SVD)和最小二乘解在解齐次线性超定方程中的应用
奇异值分解,是在A不为方阵时的对特征值分解的一种拓展.奇异值和特征值的重要意义相似,都是为了提取出矩阵的主要特征. 对于齐次线性方程 A*X =0;当A的秩大于列数时,就需要求解最小二乘解,在||X| ...
随机推荐
- selenium&phantomjs实战--漫话爬取
为什么直接保存当前网页,而不是找到所有漫话链接,再有针对性的保存图片? 因为防盗链的原因,当直接保存漫话链接图片时,只能保存到防盗链的图片. #!/usr/bin/env python # _*_ c ...
- 关于nicescroll滚动条现在浏览器上滚动问题
nativeparentscrolling: false //检测内容底部,并让父节点来滚动,作为原生滚动 有时候 当自定义滚动条在底部 滚动无效 可以把这个参数设置一下
- Jboss的jmx-console中查看内存和线程状态
步骤: 1.假设jboss运行在 192.168.1.100:8080 地址和端口上. 2. 浏览器中访问http://192.168.1.100:8080/,然后选择jmx-console 3.选择 ...
- linux centos5.8装yum安装mysql
默认的yum安装mysql都是5.1版本的 想要安装5.7的可以进行配置rpm包进行, mysql5.7安装路径 下面是默认的5.1安装路径 首先我们在使用yum安装的的时候会默认使用最新安装的,最 ...
- iOS开发中常用的数学函数
iOS开发中常用的数学函数 /*---- 常用数学公式 ----*/ //指数运算 3^2 3^3 NSLog(,)); //result 9 NSLog(,)); //result 27 //开平方 ...
- [翻译] GCDObjC
GCDObjC https://github.com/mjmsmith/gcdobjc GCDObjC is an Objective-C wrapper for the most commonly ...
- 利用Django实现RESTful API(一)
RESTful API现在很流行,这里是它的介绍 理解RESTful架构和 RESTful API设计指南.按照Django的常规方法当然也可以实现REST,但有一种更快捷.强大的方法,那就是 Dja ...
- 利用Linode面板Clone克隆搬家迁移不同VPS数据及利用IP Swap迁移IP地址
在众多海外VPS服务商中,老蒋个人认为Linode提供的VPS方案和性价比还是比较高的,尤其目前基础1GB方案仅需10美元每月且全部是SSD固态硬盘,无论是流量还是硬盘大小,基本上可以满足我们大部分用 ...
- 生成器-yield初接触
什么是生成器? 生成器的实质就是迭代器 在python中有三种方式来获取生成器 1. 通过生成器函数 2. 通过各种推导式实现生成器 3. 通过数据的转换也可以获取生成器 将函数中的return换成y ...
- Notepad++调用python
***首先确保在cmd下能直接运行python*** (博主的环境:win10 下2和3共存) 接下来进入主题,用Notepad++打开py文件,然后按 F5 键弹出运行窗口,输入以下内容: pyth ...