【问题标题】:Computing linear indices and counting non-zero entries of large sparse matrices in row-first order计算线性索引并按行优先顺序计算大型稀疏矩阵的非零条目
【发布时间】:2012-02-22 19:28:14
【问题描述】:

假设我有一个稀疏的非矩形矩阵 A:

>> A = round(rand(4,5))
A =

     0     1     0     1     1
     0     1     0     0     1
     0     0     0     0     1
     0     1     1     0     0

我想获得矩阵B,其中 A 的非零条目被它们的线性索引替换为行优先顺序

B =

     0     2     0     4     5
     0     7     0     0    10
     0     0     0     0    15
     0    17    18     0     0

以及矩阵C,其中A 的非零条目被替换为在行优先搜索中找到它们的顺序:

C =

     0     1     0     2     3
     0     4     0     0     5
     0     0     0     0     6
     0     7     8     0     0

我正在为这个问题寻找可扩展到大型稀疏矩阵的矢量化解决方案。

【问题讨论】:

  • 我觉得我错过了什么——你能不能不把B转置一下?
  • @agander3 我相信它在这种情况下有效,因为他们使用的是个矩阵。
  • 我认为问题应该是“我的问题是,有没有办法以 row-first 方式有效地计算索引?”
  • 建议:为可重复性设置一个种子值。

标签: matlab


【解决方案1】:

如果我理解您的要求,那么几个换位应该可以解决问题。关键是find(A.') 将在 A 上执行“行优先”索引,其中.' 是二维矩阵转置的简写。所以:

>> A = round(rand(4,5))
A =

     0     1     0     1     1
     0     1     0     0     1
     0     0     0     0     1
     0     1     1     0     0

然后

B=A.';
B(find(B)) = find(B);
B=B.';

给予

B =

     0     2     0     4     5
     0     7     0     0    10
     0     0     0     0    15
     0    17    18     0     0

【讨论】:

  • 谢谢伊恩。我已经更新了我的问题。很抱歉从一开始就没有更清楚。我正在寻找与稀疏矩阵A 关联的两个矩阵BC。您的答案正确输出矩阵B 我正在寻找。
【解决方案2】:

这是一个不需要任何来回转置的解决方案:

>> B = A;              %# Initialize B
>> C = A;              %# Initialize C
>> mask = logical(A);  %# Create a logical mask using A

>> [r,c] = find(A);    %# Find the row and column indices of non-zero values
>> index = c + (r - 1).*size(A,2);  %# Compute the row-first linear index
>> [~,order] = sort(index);         %# Compute the row-first order with
>> [~,order] = sort(order);         %#   two sorts

>> B(mask) = index     %# Fill non-zero elements of B

B =

     0     2     0     4     5
     0     7     0     0    10
     0     0     0     0    15
     0    17    18     0     0

>> C(mask) = order     %# Fill non-zero elements of C

C =

     0     1     0     2     3
     0     4     0     0     5
     0     0     0     0     6
     0     7     8     0     0

【讨论】:

  • 感谢新手。这很好,虽然我有点担心ismember 的速度。根据我的经验,ismember 在处理大量输入时往往会很慢。其他电话似乎足够快。有没有办法避免使用ismember 计算C
  • @roseck:还有另一种使用两种排序而不是 ISMEMBER 和一种排序的方法。我已经更新了我的答案。
【解决方案3】:

大纲(本机没有matlab,所以验证延迟):

  1. 您可以使用find() 获取坐标列表。让T = A'; [r,c] = find(T)
  2. 从坐标列表中,你可以同时创建B和C。让valB = sub2ind([r,c],T)valC = 1:length(r)
  3. 使用sparse 命令创建 B 和 C,例如B = sparse(r,c,valB),然后转置,例如B = B'(或者可以做sparse(c,r,valB))。

或者,正如@IanHincks 建议的那样,让B = A'; B(find(B)) = find(B)。 (我不知道为什么推荐.',但是,我前面没有Matlab 可以检查。)对于C,只需使用C(find(C)) = 1:nnz(A)。并按照他的建议转回。

就我个人而言,我一直在使用坐标列表,已经从稀疏矩阵表示中迁移出来,只是为了减少索引查找的成本。

【讨论】:

  • 我不确定.'' 之间的速度差异是多少...但由于我通常处理复杂数据,因此我倾向于在需要时使用.'一个转置,当我想要一个共轭转置时'
猜你喜欢
  • 2015-01-10
  • 1970-01-01
  • 2015-09-14
  • 1970-01-01
  • 2021-05-09
  • 2013-09-17
  • 1970-01-01
  • 1970-01-01
  • 2010-11-22
相关资源
最近更新 更多