【问题标题】:MATLAB - Efficient methods for populating matrices using information in other (sparse) matrices?MATLAB - 使用其他(稀疏)矩阵中的信息填充矩阵的有效方法?
【发布时间】:2011-11-29 18:27:07
【问题描述】:

抱歉标题尴尬,这里是对问题的更具体描述。我有一个大的(例如 10^6 x 10^6)稀疏对称矩阵,它定义了节点之间的键。

例如矩阵A = [0 1 0 0 0; 1 0 0 2 3; 0 0 0 4 0; 0 2 4 0 5; 0 3 0 5 0] 将描述一个 5 节点系统,其中节点 1 和 2 通过键号 A(1,2) = 1 连接,节点 3 和 4 通过键号 A(3,4) = 4 连接,等等。

我想形成两个新矩阵。第一个 B 将列出连接到每个节点的节点(即 B 的每一行 i 具有由 find(A(i,:)) 给出的元素,并在必要时在末尾填充零),第二个 C 将列出连接到的键该节点(即 C 的每一行 i 都有由 nonzeros(A(i,:)) 给出的元素,必要时再次填充)。

例如对于上面的矩阵 A,我想形成 B = [2 0 0; 1 4 5; 4 0 0; 2 3 5; 2 4 0]C = [1 0 0; 1 2 3; 4 0 0; 2 4 5; 3 5 0]

目前的代码是:

B=zeros(length(A), max(sum(spones(A))))
C=zeros(length(A), max(sum(spones(A))))
for i=1:length(A)
    B(i,1:length(find(A(i,:)))) = find(A(i,:));
    C(i,1:length(nonzeros(A(i,:)))) = nonzeros(A(i,:));
end

这可行,但对于大长度(A)来说很慢。我尝试过其他公式,但它们都包含 for 循环并且没有带来太大改进。

如何在不遍历行的情况下执行此操作?

【问题讨论】:

    标签: matlab


    【解决方案1】:

    嗯。不确定如何向量化(find 在给定矩阵时返回线性索引,这不是您想要的),但您是否尝试过:

    B=zeros(length(A), 0);
    C=zeros(length(A), 0);
    for i=1:length(A)
        Bi = find(A(i,:));
        B(i,1:length(Bi)) = Bi;
        Ci = nonzeros(A(i,:));
        C(i,1:length(Ci)) = Ci;
    end
    

    我做了两处改动:

    • 删除了对 spones 的调用(似乎没有必要;扩展 B 和 C 中的列数所需的性能影响可能很小)
    • find() 和 nonzeros() 的缓存结果,因此它们不会被调用两次

    【讨论】:

    • sum(spones(A)) 之前在代码中用于其他目的,因此重用它是有意义的。不过感谢您提供有关缓存的提示。
    【解决方案2】:

    我知道这很难阅读,但该代码是您的代码的矢量化版本:

    [ i j k ] = find(A);
    A2=(A~=0);
    j2=nonzeros(cumsum(A2,2).*A2);
    C2=accumarray([i,j2],k)
    k2=nonzeros(bsxfun(@times,1:size(A,2),A2));
    B2=accumarray([i,j2],k2);
    

    试一试,告诉我它是否适合你。

    【讨论】:

    • 工作,并且可能更快,但是...??? Error using ==> cumsum Out of memory. Type HELP MEMORY for your options.
    • ...所以也许你可以把问题分成小块...或者买一些内存,它最近变得超级便宜:P
    猜你喜欢
    • 1970-01-01
    • 2023-04-06
    • 2012-07-28
    • 1970-01-01
    • 2018-05-06
    • 1970-01-01
    • 1970-01-01
    • 2013-04-11
    • 1970-01-01
    相关资源
    最近更新 更多