【问题标题】:Checking membership in an array without for loop in matlab在matlab中检查没有for循环的数组中的成员资格
【发布时间】:2020-06-03 17:41:57
【问题描述】:

我想将此代码简化为无需 for 循环即可工作。

for i=1:N
    for j=1:N
        if ismember(j,A)

           PID(i,i)=TFP(i,j)+ PID(i,i);

        end
    end
end

其中A 是一个包含一些标签的矩阵。我之前以 N*N 稀疏双精度的形式存储了TFP。所以,我想出了以下解决方案,但我找不到一种方法来实现成员资格条件(由 ? 指定)。

PID = sum(TFP).*(?);

可以不循环实现吗?

【问题讨论】:

    标签: matlab loops for-loop vectorization


    【解决方案1】:

    您的ismember(j,A) 相当于只使用A 的值来索引。所以你可以使用它并完全避免 ismember 函数(这是迄今为止代码中最慢的部分)。

    所以优化的第一步是

    A2=unique(A); % just in case you do not do this already
    for i=1:N
        for j=A2
            PID(i,i)=TFP(i,j)+ PID(i,i);
        end
    end
    

    这应该已经非常快了。循环在 MATLAB 中还不错,并且由 JIT 编译器进行了高度优化。

    优化的下一步是将所有索引放在一起并删除辅助循环。你可以用线性索引来做到这一点,所以

    A2=unique(A); % just in case you do not do this already
    for i=1:N
        PID(i,i)=sum(TFP(i,A2));
    end
    

    最后,您可以通过对所需列的总和进行对角化来消除此问题:

    A2=unique(A); % just in case you do not do this already
    PID=diag(sum(TFP(:,A2),2));
    

    【讨论】:

      【解决方案2】:

      您可以使用矩阵乘法,而不是对元素乘法的结果求和。它在不创建临时数组的情况下计算产品的总和:

      J = ismember(1:N, A).';
      PID = diag(TFP * J);
      

      【讨论】:

        【解决方案3】:

        我不确定我是否完全理解您的问题 你试过这个吗?

        j=1:N;
        PID = sum(TFP).*ismember(j,A);
        

        ismember 将作为一个矩阵工作,当为真时等于'1',因此它允许相乘。

        【讨论】:

        • [我没有投反对票,我认为这个答案几乎就在那里]。这将输出一个行向量,OP 的总和总是在索引(i,i) 上进行整理,即在对角线上。我认为您最终也会以 N 的系数结束,因为 OP 会重复检查您已删除的 i = 1:N
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-01-28
        • 2016-06-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多