接上一篇。。。

下面我们将 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的更多相关文章

  1. 用 GSL 求解超定方程组及矩阵的奇异值分解(SVD)

    用 GSL 求解超定方程组及矩阵的奇异值分解(SVD) 最近在学习高动态图像(HDR)合成的算法,其中需要求解一个超定方程组,因此花了点时间研究了一下如何用 GSL 来解决这个问题. GSL 里是有最 ...

  2. Python最小二乘法解非线性超定方程组

    求解非线性超定方程组,网上搜到的大多是线性方程组的最小二乘解法,对于非线性方程组无济于事. 这里分享一种方法:SciPy库的scipy.optimize.leastsq函数. import numpy ...

  3. 小游戏 Lights Out (关灯) 的求解 —— 异或方程组

    Author : Evensgn  Blog Link : http://www.cnblogs.com/JoeFan/ Article Link : http://www.cnblogs.com/J ...

  4. 高斯消元法求解异或方程组: cojs.tk 539.//BZOJ 1770 牛棚的灯

    高斯消元求解异或方程组: 比较不错的一篇文章:http://blog.sina.com.cn/s/blog_51cea4040100g7hl.html cojs.tk  539. 牛棚的灯 ★★☆   ...

  5. 【poj1830-开关问题】高斯消元求解异或方程组

    第一道高斯消元题目~ 题目:有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为开就变为关 ...

  6. 机器学习降维方法概括, LASSO参数缩减、主成分分析PCA、小波分析、线性判别LDA、拉普拉斯映射、深度学习SparseAutoEncoder、矩阵奇异值分解SVD、LLE局部线性嵌入、Isomap等距映射

    机器学习降维方法概括   版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u014772862/article/details/52335970 最近 ...

  7. 矩阵奇异值分解(SVD)及其应用

    机器学习中的数学(5)-强大的矩阵奇异值分解(SVD)及其应用(好文) [简化数据]奇异值分解(SVD) <数学之美> 第15章 矩阵运算和文本处理中的两个分类问题

  8. 矩阵的奇异值分解(SVD)(理论)

    矩阵的奇异值分解(Singular Value Decomposition,SVD)是数值计算中的精彩之处,在其它数学领域和机器学习领域得到了广泛的应用,如矩阵的广义逆,主分成分析(PCA),自然语言 ...

  9. 奇异值分解(SVD)和最小二乘解在解齐次线性超定方程中的应用

    奇异值分解,是在A不为方阵时的对特征值分解的一种拓展.奇异值和特征值的重要意义相似,都是为了提取出矩阵的主要特征. 对于齐次线性方程 A*X =0;当A的秩大于列数时,就需要求解最小二乘解,在||X| ...

随机推荐

  1. 排序算法(2) 堆排序 C++实现

    堆 1 数组对象 2 可以视为一棵完全二叉树 3 一个堆可以被看作一棵二叉树和一个数组,如下图所示: 4 下标计算(通常使用内联函数或者宏来定义下标操作): 已知某个结点的下标为i 其父节点下标:i/ ...

  2. 搭建企业级NFS网络文件共享服务说明[一]

    1.1.0. 概述: 共享/NFS目录给整个192.168.25.0/24网段主机读写 man nfs 可以查看mount的信息 rpc端口111 nfs主端口2049 1.1.1. 搭建NFS环境 ...

  3. CSS学习摘要-定位实例

    CSS学习摘要-定位实例 注:全文摘自MDN-CSS定位实例 列表消息盒子 我们研究的第一个例子是一个经典的选项卡消息框,你想用一块小区域包括大量信息时,一个非常常用的特征.这包括含有大信息量的应用, ...

  4. EclEmma安装与使用

    安装 EclEmma 插件的过程和大部分 Eclipse 插件相同,我们既可以通过 Eclipse 标准的 Update 机制来远程安装 EclEmma 插件(图 1),也可以从站点(参阅参考资源)下 ...

  5. log4j.properties的配置详解

    log4j.rootLogger=ERROR,A1log4j.appender.A1=org.apache.log4j.ConsoleAppenderlog4j.appender.A1.layout= ...

  6. hadoop学习;hdfs操作;执行抛出权限异常: Permission denied;api查看源代码方法;源代码不停的向里循环;抽象类通过debug查找源代码

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u010026901/article/details/26587251 eclipse快捷键alt+s ...

  7. [Java多线程] LinkedBlockingQueue

    java.util.concurrent包下的新类.LinkedBlockingQueue就是其中之一,是一个阻塞的线程安全的队列,底层采用链表实现. LinkedBlockingQueue Link ...

  8. 3631. [JLOI2014]松鼠的新家【树形DP】

    Description 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在“树”上.松鼠想邀 ...

  9. 2339: [HNOI2011]卡农

    Description 首先去除顺序不同算一种的麻烦,就是最后答案除以总片段数\(2^m-1\) 设\(f_i\)表示安排\(i\)个片段的合法种类 那么对于任何一个包含\(i-1\)个片段的序列(除 ...

  10. 基于PHP的cURL快速入门教程 (小偷采集程序)

    cURL 是一个利用URL语法规定来传输文件和数据的工具,支持很多协议,如HTTP.FTP.TELNET等.很多小偷程序都是使用这个函数.     最爽的是,PHP也支持 cURL 库.本文将介绍 c ...