我正在使用持有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);
}
答案 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的数字)。
好问题!