7

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

我想为每个所需的功能编写一个强力的辅助函数就足够了,但这似乎很浪费。

同样,boost wiki 提供了一些代码来矢量化标准函数,但这似乎相当复杂。

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

任何帮助是极大的赞赏。

4

2 回答 2

10

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

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

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

享受!

于 2010-10-15T16:31:45.907 回答
3

警告

以下答案不正确。请参阅底部的编辑。我保留了原始答案,以便为指出错误的人提供上下文和信誉。


我对 boost 库不是特别熟悉,所以可能有更标准的方法可以做到这一点,但我认为你可以使用迭代器和 STL转换函数模板做你想做的事。uBLAS 库文档的介绍说它的类被设计为与 STL 中使用的相同迭代器行为兼容。boost 矩阵和向量模板都有迭代器,可用于访问各个元素。向量有begin()end(),矩阵有begin1()end1()begin2()end2()。品种是按列的1迭代器,2品种是按行的迭代器。请参阅VectorExpression上的 boost 文档MatrixExpression了解更多信息。

使用 STLtransform算法,您可以将函数应用于可迭代序列的每个元素,并将结果分配给具有相同长度或相同序列的不同可迭代序列。因此,要在 boost 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);

作为最后一个参数传递的函数可以是一个接受单个双精度参数并返回双精度值的函数。它也可以是函子

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


编辑

看起来我应该在提出建议之前测试一下我的建议。正如其他人所指出的,“1”和“2”迭代器仅沿矩阵的单行/列进行迭代。Boost 中的概述文档在这方面存在严重误导。它声称begin1()“返回指向矩阵开头的 iterator1”和end1()“返回指向矩阵末尾的 iterator1”。说“矩阵的一列”而不是“矩阵”会杀死他们吗?我假设 aniterator1是一个按列迭代的迭代器,它将迭代整个矩阵。有关执行此操作的正确方法,请参阅Lantern Rouge 的回答

于 2009-05-16T05:51:33.827 回答