使用数组填充对称矩阵

Posted

技术标签:

【中文标题】使用数组填充对称矩阵【英文标题】:Fill a symmetric matrix using an array 【发布时间】:2018-02-21 17:03:16 【问题描述】:

我正在尝试使用c++ 中的boost 库创建一个对称矩阵n x n 矩阵并使用n*(n+1)/2 维数组填充它。

到目前为止,我能够创建矩阵,并使用以下代码用随机值填充它

#include <iostream>
#include <fstream>    
#include </usr/include/boost/numeric/ublas/matrix.hpp>
#include </usr/include/boost/numeric/ublas/matrix_sparse.hpp>
#include </usr/include/boost/numeric/ublas/symmetric.hpp>
#include </usr/include/boost/numeric/ublas/io.hpp>

using namespace std;



int test_boost () 
    using namespace boost::numeric::ublas;
    symmetric_matrix<double, upper> m_sym (3, 3);

    double filler[6] = 0, 1, 2, 3, 4, 5;        

    for (unsigned i = 0; i < m_sym.size1 (); ++ i)
        for (unsigned j = i; j < m_sym.size2 (); ++ j)
            m_sym (i, j) = filler[i+j*m_sym.size1()];

    std::cout << m_sym << std::endl;
    return 0;

我要做的是使用数组filler 中的值填充对称矩阵的上(或下)部分。所以输出的上对称矩阵应该是

         |      0    |      1    |      2    |
------------------------------------------------
   0 |          0           1           3    
   1 |          1           2           4
   2 |          3           4           5

你知道怎么做吗?

【问题讨论】:

好吧,我想你已经准备好回答你自己的问题了。回答这个问题:index 必须是什么才能使以下内容正确:m_sym(i, j) = filler[index];? @YSC:非常感谢您的评论!这就是问题所在...我想不出办法...矩阵中的元素00 应该填充数组中的元素001102 和@987654335 @、113 等等……所以我想不出一个明显的方法! 【参考方案1】:

我会通过只保留一个从头到尾遍历填充物的迭代器来简化这一点:

symmetric_matrix<double, upper> m_sym (3, 3);

double filler[6] = 0, 1, 2, 3, 4, 5;        

assert(m_sym.size1() == m_sym.size2());

double const* in = std::begin(filler);
for (size_t i = 0; i < m_sym.size1(); ++ i)
    for (size_t j = 0; j <= i && in != std::end(filler); ++ j)
        m_sym (i, j) = *in++;

打印:Live On Coliru

我个人建议创建一个辅助函数,例如:

Live On Wandbox

#include <iostream>
#include <fstream>    
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include <boost/numeric/ublas/symmetric.hpp>
#include <boost/numeric/ublas/io.hpp>

namespace bnu = boost::numeric::ublas;

template <typename T = double>
bnu::symmetric_matrix<T, bnu::upper> make_symmetric(std::initializer_list<T> filler) 
    size_t n = (sqrt(8*filler.size() + 1) - 1)/2;
    assert((n*(n+1))/2 == filler.size());

    bnu::symmetric_matrix<T, bnu::upper> result(n, n);

    auto in = std::begin(filler);
    for (size_t i = 0; i < result.size1(); ++ i)
        for (size_t j = 0; j <= i && in != std::end(filler); ++ j)
            result (i, j) = *in++;

    return result;


int main() 
    std::cout << make_symmetric(0,1,2) << "\n";
    std::cout << make_symmetric(0,1,2,3,4,5) << "\n";
    std::cout << make_symmetric(0,1,2,3,4,5,6,7,8,9) << "\n";

打印

[2,2]((0,1),(1,2))
[3,3]((0,1,3),(1,2,4),(3,4,5))
[4,4]((0,1,3,6),(1,2,4,7),(3,4,5,8),(6,7,8,9))

注意:大小检查使用series expansion for 1 + ... + n 和它的倒数:n = 1/2 (sqrt(8 x + 1) - 1)

【讨论】:

哇!非常感谢您的回复和帮助!我不得不说我对 for 循环的第一部分感到困惑。我不知道你可以在`for循环中添加条件!至于第二部分,我不得不说,我希望我能学会这样做!真是个美女! for(a;b;c)/*...*/ 真的只是 a; while(b) /*...*/ continue_label: c; en.cppreference.com/w/cpp/language/for 我不明白的是如何将第二部分用作构造函数,即make_symmetric m_sym(size, filler),或用作填充对称的函数,即symmetric_matrix&lt;double, upper&gt; m_sym (3, 3); m_sym-&gt;make_symmetric(filler) 稍微改变一下定义。我可以稍后给你看 非常非常非常感谢!

以上是关于使用数组填充对称矩阵的主要内容,如果未能解决你的问题,请参考以下文章

对称对角矩阵的表示

Numpy“智能”对称矩阵

特殊矩阵的压缩存储(转自chunlanse2014)

当 B 是犰狳中的对称矩阵时的 A * B 计算

Java数据结构之对称矩阵的压缩算法---

对称矩阵和稀疏矩阵