首页 文章

使用boost c ublas矩阵和向量类型的元素操作

提问于
浏览
7

我想在增强矩阵和矢量类型上执行逐元素函数,例如:取每个元素的对数,取幂每个元素,应用特殊函数,如gamma和digamma等(类似于matlab对这些函数的处理应用于矩阵和向量 . )

我想写一个帮助函数,对每个所需的函数强制执行这个就足够了,但这看起来很浪费 .

同样,boost wiki为vectorize standard functions提供了一些代码,但这看起来相当复杂 .

valarray已被建议,但我想避免在数据类型之间进行转换,因为我需要ublas数据类型用于其他操作(矩阵乘积,稀疏矩阵等)

任何帮助是极大的赞赏 .

2 回答

  • 3

    警告

    以下答案不正确 . 请参见底部的编辑 . 我已经离开了原来的答案,为那些指出错误的人提供了背景和信用 .


    我对boost库并不是特别熟悉,所以可能有更标准的方法来做到这一点,但我认为你可以用迭代器和STL transform函数模板做你想做的事 . introduction to the uBLAS library documentation表示它的类被设计为与STL中使用的相同迭代器行为兼容 . 所有have iterators的boost矩阵和矢量模板都可用于访问各个元素 . 向量具有 begin()end() ,矩阵具有 begin1()end1()begin2()end2() . 1 变量是列式迭代器, 2 变量是行式迭代器 . 有关详细信息,请参阅VectorExpressionMatrixExpression上的boost文档 .

    使用STL transform 算法,可以将函数应用于可迭代序列的每个元素,并将结果分配给具有相同长度或相同序列的不同可迭代序列 . 所以要在升压uBLAS矢量上使用它,你可以这样做:

    using namespace boost::numeric::ublas;
    
    // Create a 30 element vector of doubles
    vector<double> vec(30);
    
    // Assign 8.0 to each element.
    std::fill(vec.begin(), vec.end(), 8.0);
    
    // Perform the "Gamma" function on each element and assign the result back
    // to the original element in the vector.
    std::transform(vec.begin(), vec.end(), vec.begin(), boost::math::tgamma);
    

    对于矩阵,它基本上是相同的,你可以使用 12 系列的迭代器 . 您选择使用哪一个取决于矩阵的内存布局是行主要还是列主要 . 粗略扫描uBLAS文档让我相信它可能是一个,因此您需要检查代码并确定使用哪个代码,以便选择最有效的迭代顺序 .

    matrix<double> mat(30, 30);
    .
    .
    .
    
    std::transform(mat.begin1(), mat.end1(), mat.begin1(), boost::math::tgamma);
    

    作为最后一个参数传递的函数可以是一个带有单个double参数并返回double值的函数 . 它也可以是functor .

    这与您引用的矢量化示例不完全相同,但似乎它应该非常接近您想要的 .


    编辑

    看起来我应该在制作之前测试我的推荐 . 正如其他人所指出的那样,'1'和'2'迭代器只沿矩阵的单个行/列进行迭代 . Boost中的概述文档严重误导了这一点 . 它声称 begin1() "Returns a iterator1 pointing to the beginning of the matrix"和 end1() "Returns a iterator1 pointing to the end of the matrix" . 它会杀了他们说"a column of the matrix"而不是"matrix"?我假设 iterator1 是一个列式迭代器,它将迭代整个矩阵 . 有关执行此操作的正确方法,请参阅Lantern Rouge's answer .

  • 9

    使用 begin1() / end1() 将不起作用,因为它提供对默认列位置(0)中元素的访问:因此,您只需访问第一列中的所有元素 . 通过以下方式获得顺序访问更好(在某种意义上,您获得了预期的行为):

    std::transform(mat.data().begin(), mat.data().end(),
                   mat.data().begin(), boost::math::tgamma) ;
    

    我怀疑这可能是实施不完整的情况 .

    请享用!

相关问题