繁体   English   中英

在犰狳中,如何解释子矩阵上的查找结果

[英]In armadillo, how to interpret result of find on submatrix

考虑下面的代码,使用Armadillo在矩阵的指定行和列中查找前7个(首先向下搜索列):

using namespace arma;

uvec2 firstEqual7(const mat& X, const uvec& rows, const uvec& cols)
{
    const uword findCount = 1;
    uvec results = find(X.submat(rows, cols) == 7, findCount);
    if (results.empty()) throw std::logic_error("no 7 found!");
    return ind2sub(X, results[0]);
}

这有两个问题。 首先,find为每个结果提供了一个向量索引,因此要将其转换为行和列,我们必须调用类似于MATLAB ind2subind2sub ,但令人惊讶的是Armadillo中不存在该函数。 好,那很痛苦,但是我可以自己写成两行。 (但是我提到这是为了防止有人知道更好的方法。)

更大的问题是,结果是子矩阵的索引例如,如果X为100x100,但是rows=cols={98,99}则右下角由find(...)==3而不是find(...)==9999 我怎么能得到绝对的结果?

一种选择是:

using namespace arma;

uvec2 firstEqual7(const mat& X, const uvec& rows, const uvec& cols)
{
    const uword findCount = 1;
    auto submatOfX = X.submat(rows, cols);  // DO NOT DO THIS!
    uvec results = find(submatOfX == 7, findCount);
    if (results.empty()) throw std::logic_error("no 7 found!");
    uvec2 submatIndices = ind2sub(submatOfX, results[0]);
    return uvec2{rows[submatIndices[0]], cols[submatIndices[1]]}; 
}

我认为这可以运行(假设我们已经实现了ind2sub ),但是效率很低。 问题涉及一个事实,即submatOfX并不是一个矩阵,而是一个小的代理类型,因此Armadillo不需要将所有子矩阵元素都复制到一个新的矩阵中即可执行查找操作。 但是将其传递给ind2sub会将其隐式转换为mat ,这使得矩阵复制毕竟发生了!

继续使用这种可能的解决方案,我可以将ind2sub模板ind2sub类似矩阵的类型,以便直接传递代理。 这可能会起作用,但是对于我最初希望功能非常短的解决方案而言,它似乎是相当复杂的解决方案。 更重要的是,Armadillo中的代理类型并没有真正记录下来,我不认为用户是想弄乱它们的,所以我担心将一个变量放在变量中,甚至是简短地,都有些脆弱。 有谁有更好的主意吗?

在没有任何答案的情况下,我认为结论必须是Armadillo的类似于MATLAB的语法不足以执行此类任务。 对于适合一行的小东西来说,这很好,但是如果它更复杂,那么我们就不得不自己拼出迭代。 可以说,尽管稍长一些,但以下代码无论如何至少与第一个代码段一样清晰。

using namespace arma;

// NOTE: rows and cols are now logical vectors (i.e. {1 0 1 1 0 ...}),
// rather than vectors of indices (i.e. {0, 2, 3, ...})
uvec2 firstEqual7(const mat& X, const uvec& rows, const uvec& cols)
{
    for (uword c = 0; c < X.n_cols; ++c) {
        if (!cols(c)) continue;
        for (uword r = 0; r < X.n_rows; ++r) {
            if (!rows(r)) continue;
            if (X(r, c) == 7) {
                return uvec2{r, c};
            }
        }
    }
    throw std::logic_error("no 7 found!");
}

请注意,重要的是外部循环是列,内部循环是行。 矩阵是由Armadillo按列存储的,因此这种迭代方式遍历内存,而不是跳转,这会加快速度,因为我们得到了更多的缓存命中率。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM