计算线性索引并以行优先顺序计算大稀疏矩阵的非零条目

时间:2012-02-22 19:28:15

标签: matlab

假设我有一个稀疏的非矩形矩阵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

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

3 个答案:

答案 0 :(得分:3)

如果我明白你在问什么,那么几个转换应该可以解决问题。关键是find(A.')将对A进行“行优先”索引,其中.'是2D矩阵转置的简写。所以:

>> 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

答案 1 :(得分:1)

大纲(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))。
  4. 或者,正如@IanHincks建议的那样,让B = A'; B(find(B)) = find(B)。 (我不确定为什么建议使用.',但是,再次,我没有在前面检查Matlab。)对于C,只需使用C(find(C)) = 1:nnz(A)。并按照他的建议转而回归。

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

答案 2 :(得分:1)

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

>> 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