在大型稀疏矩阵中找到“最大”密集子矩阵

时间:2009-08-01 19:59:33

标签: algorithm discrete-mathematics sparse-matrix

给定一个大的稀疏矩阵(比如说10k +乘以1M +),我需要找到形成密集矩阵(所有非零元素)的行和列的子集,不一定是连续的。我希望这个子矩阵在一些宽高比约束中尽可能大(不是最大的和,但是最大的元素数)。

这个问题是否有任何已知的确切或aproxamate解决方案?

对谷歌的快速扫描似乎给出了很多接近但不完全的结果。 我应该寻找哪些条款?


编辑:只是为了澄清;子矩阵不必是连续的。实际上,行和列顺序完全是任意的,因此邻接完全无关紧要。


基于Chad Okere的想法的想法

  1. 将行从最大计数排序到最小计数(不是必需但可能有助于执行)
  2. 选择两个具有“大”重叠的行
  3. 添加不会减少重叠的所有其他行
  4. 记录设置
  5. 添加任何行减少重叠
  6. 在#3处重复,直到结果变小
  7. 从#2开始,使用不同的起始对
  8. 继续,直到您认为结果足够好

4 个答案:

答案 0 :(得分:2)

我认为你想要这样的东西。你有一个像

这样的矩阵
1100101
1110101
0100101

你想要第1,2,5,7列和第1行和第2行,对吗?该子矩阵将具有8个元素的4x2。或者你可以使用第1,2,7列,第1,2,3行,这将是一个3x3矩阵。

如果你想要一个'近似'方法,你可以从一个非零元素开始,然后继续寻找另一个非零元素并将其添加到你的行和列列表中。在某些时候,你会遇到一个非零元素,如果它的行和列被添加到你的集合中,你的集合将不再完全非零。

因此对于上面的矩阵,如果你添加了1,1和2,2你的集合中会有1,2行和1,2列。如果您尝试添加3,7,则会导致问题,因为1,3为零。所以你无法添加它。你可以添加2,5和2,7。创建4x2子矩阵。

您基本上会迭代,直到找不到要添加的新行和列。这将使你太局部最小化。您可以存储结果并使用另一个起始点(可能是一个不适合您当前解决方案的起点)重新开始。

然后在一段时间后再找不到时再停下来。

显然,这需要很长时间,但我不知道你是否能够更快地完成它。

答案 1 :(得分:1)

EDIT。这跟下面的问题不一样。我的不好......

但根据下面的最后一条评论,它可能等同于以下内容:

  1. 找到最远的垂直分离的零点对,它们之间没有零点。
  2. 找到最远的水平分隔的零点对,它们之间没有零点?
  3. 那么你要找的水平区域是适合这两对点的矩形吗?

    这个确切的问题在Jon Bentley的一本名为“Programming Pearls”的书的宝石中讨论过,而且我记得,虽然在一个维度上有一个解决方案,但对于2-d或更高的维度没有简单的答案维度变体......

  4. 1 = D问题实际上是找到一组数字中连续子集的最大总和:

    遍历元素,跟踪特定前一个元素的运行总计,以及到目前为止看到的最大小计(以及生成它的开始和结束元素)...在每个元素处,如果maxrunning小计是大于目前为止看到的最大总数,到目前为止看到的最大值和重要值被重置...如果最大运行总量低于零,则将start元素重置为当前元素,并将运行总计重置为零...

    2-D问题来自于尝试生成可视图像处理算法,该算法试图在表示2色图像中的像素的亮度值流中找到“内部最亮”的矩形区域。图片。即,找到具有最高亮度值总和的所包含的2-D子矩阵,其中“亮度”通过像素的亮度值与整个图像的总体平均亮度之间的差异来测量(因此许多元素具有负值)

    编辑:为了查找一维解决方案,我挖掘了本书第二版的副本,其中,Jon Bentley说:“这个版本打印时,二维版本仍未解决...... “这是在1999年。

答案 2 :(得分:1)

这是Netflix problem吗?

MATLAB或其他一些稀疏矩阵库可能有办法处理它。

你打算自己写吗?

也许每行的1D方法对您有所帮助。算法可能如下所示:

  1. 遍历每一行
  2. 查找第一个非零元素的索引
  3. 查找非零行元素的索引,每行中非零列之间的跨度最大,并存储两者。
  4. 将行从最大到最小的跨度排列在非零列之间。
  5. 此时我开始模糊(对不起,不是算法设计师)。我尝试循环遍历每一行,排列起点的索引,寻找我可能的最大非零列索引。

    您不指定密集矩阵是否必须是正方形。我不会假设。

    我不知道这是多么有效或者它的Big-O行为是什么。但这是一种蛮力的方法。

答案 3 :(得分:1)

我知道你不再在这方面工作,但我认为将来可能会有人和我有同样的问题。

所以,在意识到这是一个NP难题(通过缩减为MAX-CLIQUE)之后,我决定提出一种迄今为止对我有用的启发式方法:

给定 N x M 二进制/布尔矩阵,找到一个大的密集子矩阵:

第一部分:生成合理的候选子矩阵

  1. N 行中的每一行视为 M 维二维向量 v_i ,其中 i = 1到 N
  2. 使用汉明距离
  3. 计算 N 向量的距离矩阵
  4. 使用UPGMA(具有算术平均值的未加权对组方法)算法来聚类矢量
  5. 最初,每个 v_i 向量都是单个群集。上面的步骤3(聚类)给出了矢量应该组合成子矩阵的顺序。因此,分层聚类树中的每个内部节点都是候选子矩阵。

    第二部分:对候选子矩阵进行评分和排名

    1. 对于每个子矩阵,通过消除任何具有一个或多个零的列,计算 D ,即子矩阵向量的密集子集中的元素数。
    2. 选择最大化 D
    3. 的子矩阵

      我还考虑了需要从初始完整矩阵中保留的最小行数,并且在选择max D的子矩阵之前,我会丢弃任何不符合此条件的候选子矩阵价值。