迭代两个稀疏矩阵

时间:2009-08-25 15:50:16

标签: c++ boost iterator sparse-matrix

我正在使用持有bool的boost稀疏矩阵并尝试编写一个比较函数来将它们存储在地图中。这是一个非常简单的比较功能。基本上,我们的想法是将矩阵看作二进制数(在被展平成向量之后)并根据该数字的值进行排序。这可以通过这种方式实现:

for(unsigned int j = 0; j < maxJ; j++)
{
  for(unsigned int i = 0; i < maxI; i++)
  {
    if(matrix1(i,j) < matrix2(i,j) return true;
    else if(matrix1(i,j) > matrix2(i,j) return false;
  }
}
return false;

然而,由于矩阵的稀疏性,这是低效的,我想使用迭代器得到相同的结果。使用迭代器的算法似乎很简单,即 1)抓住每个矩阵中的第一个非零单元,2)比较两者的j * maxJ + i,3)如果相等,则抓住每个矩阵中的下一个非零单元并重复。不幸的是,在代码中这非常乏味,我担心错误。

我想知道的是(a)是否有更好的方法来做到这一点;(b)是否有一种简单的方法可以获得两个矩阵的“下一个非零单元格”?显然,我不能使用嵌套的for循环,就像迭代一个稀疏矩阵一样。

感谢您的帮助。

-

由于我上面提出的算法似乎是我特定应用程序中的最佳解决方案,我想我应该发布我为棘手部分开发的代码,在两个稀疏矩阵中获取下一个非零单元。这段代码并不理想,也不是很清楚,但我不确定如何改进它。如果有人发现了一个错误或知道如何改进它,我将不胜感激。否则,我希望这对其他人有用。

typedef boost::numeric::ublas::mapped_matrix<bool>::const_iterator1 iter1;
typedef boost::numeric::ublas::mapped_matrix<bool>::const_iterator2 iter2;

// Grabs the next nonzero cell in a sparse matrix after the cell pointed to by i1, i2.
std::pair<iter1, iter2> next_cell(iter1 i1, iter2 i2, iter1 end) const
{
    if(i2 == i1.end())
    {
        if (i1 == end)
            return std::pair<iter1, iter2>(i1, i2);
        ++i1;
        i2 = i1.begin();
    }
    else
    {
        ++i2;
    }

    for(; i1 != end;)
    {
        for(; i2 != i1.end(); ++i2)
        {
            return std::pair<iter1, iter2>(i1,i2);
        }
        ++i1;
        if(i1 != end) i2 = i1.begin();
    }
    return std::pair<iter1, iter2>(i1, i2);
}

3 个答案:

答案 0 :(得分:1)

顺便说一句,我喜欢这个问题。

让我伪代码我认为你在问什么

declare list of sparse matrices ListA
declare map MatMAp with a sparse Matrix type mapping to a double, along with a
`StrictWeakMatrixOrderer` function which takes two sparse matrices.

Insert ListA into MatMap. 

问题:如何有效地编写StrictWeakMatrixOrderer?

这是一种方法。我正在发明这个......


定义函数flatten()并预先计算展平的矩阵,将展平的向量存储在向量(或具有随机索引上限的另一个容器)中。 flatten()可以像将每行(或列)与前一行(或列)连接一样简单(如果您有一个常量时间函数来获取行/列,则可以在线性时间内完成)。

这产生一组大小为10 ^ 6的向量。这是一种权衡 - 保存这些信息而不是实时计算它。如果您要进行大量比较,这非常有用。

请记住,零包含信息 - 丢弃它们可能会产生两个彼此相等的向量,而它们的生成矩阵可能不相等。

然后,我们将算法问题从“顺序矩阵”转换为“顺序向量”。 我从来没有听说过矩阵的距离度量,但我听说过矢量的距离度量。

您可以使用“差异总和”排序,即汉明距离。 (foreach元素不同,加1)。这将是一个O(n)算法:

for i = 0 to max.
  if(a[i] != b[i])
     distance++

return distance

汉明距离满足这些条件

d(a,b) = d(b,a)
d(a,a) = 0
d(x, z) <= d(x, y) + d(y, z) 

现在做一些袖手旁观的分析......

    矩阵中的
  • 10^6元素(或其相应的向量)。
  • O(n)距离指标。
    • 但它是O(n)比较。如果每个阵列访问权限都有O(m)时间,那么您将拥有O(n*(n+n)) = O(n^2)指标。因此,您have可以< O(n)访问权限。事实证明,根据SGI的STL网站,std::vector []运算符提供了“对任意元素的分期持续时间访问”。
  • 假设您有足够的内存来存储k*2*10^6,其中k是您管理的矩阵的数量,这是一个使用大量内存以换取线性的工作解决方案。

答案 1 :(得分:0)

(a)我不完全理解你想要完成什么,但是如果你想比较两个矩阵在同一个索引上是否具有相同的值,那么使用元素矩阵乘法就足够了(应该实现稀疏的):

matrix3 = element_prod (matrix1, matrix2);

你会得到每个索引:

0 (false) * 1 (true) = 0 (false)
0*0 = 0
1*1 = 1

因此得到的matrix3将使您的解决方案在一行中:)

答案 2 :(得分:0)

在我看来,我们正在谈论在boost :: sparse_matrix上实现按位元素运算符,因为比较一个向量(或矩阵)是否小于另一个而不使用任何标准向量规范需要特殊运算符(或特殊映射/规范)。

据我所知,boost不提供二进制矩阵的特殊算子(更不用说稀疏二进制矩阵)。使用BLAS水平矩阵/向量代数不太可能有任何简单的解决方案。二元矩阵在线性代数领域有自己的位置,所以有技巧和定理,但我怀疑这些比你的解决方案更容易。

您的问题可以重新表述为:我如何有效地排序由2d位图表示的天文数字大数字(n = 100,因此100x100元素会给你一个像2 ^ 10000的数字)。

好问题!