【问题标题】:Vectorization of MATLAB/Octave loopMATLAB/Octave 循环的向量化
【发布时间】:2014-06-24 20:10:07
【问题描述】:

这个for循环可以进一步向量化吗?

for i = 1:length(formula)
ttable(i,abs(formula(i,:))) = -1*formula(i,:);
end

其中formula 是一个矩阵,ttable = NaN(length(formula),max(max(abs(formula))))。谢谢!

【问题讨论】:

    标签: matlab octave vectorization


    【解决方案1】:

    从代码来看,您所做的是对于ttable 的每一行,您希望使用abs(formula(i,:)) 访问的索引并将这些位置中的每一个设置为-1*formula(i,:)

    注意到@Divakar 的聪明点,我将假设每一行都有唯一的绝对 值。换句话说,每一行都不应该有可以连续有a-a 的实例,其中a 是从1size(formula,2) 的任意数字。原因是因为在您计算 abs(formula(i,:)) 时,-aa 将映射到同一列。这将发生冲突并允许覆盖到同一个条目中(感谢@Divakar!)

    我们可以对formula 的每一行,将这些位置转换为列主索引以访问ttable。之后,将-1*formula 的对应值赋值给ttable。换句话说:

    %// Find those columns that should be accessed
    columnIndices = reshape(abs(formula).', 1, []);
    
    %// For each column we are accessing, find the corresponding row
    rowIndices = reshape(repmat(1:size(formula,2), size(formula, 1), 1), 1, []);
    
    %// Find the column major indices we need to access overall
    indices = sub2ind(size(formula), rowIndices, columnIndices);
    
    %// Take those indices that we have computed above, and map them
    %// to those columns we found earlier
    ttable(indices) = -1*formula.';
    

    这是我创建的一个小测试。这也是基于我之前所做的唯一绝对值的相同假设:

    formula = [1 2 -3 4; 4 -2 3 1; 3 2 4 -1; -4 1 2 3];
    ttable = NaN(length(formula),max(max(abs(formula))));
    
    formula =
    
     1     2    -3     4
     4    -2     3     1
     3     2     4    -1
    -4     1     2     3
    
    
    ttable =
    
    NaN   NaN   NaN   NaN
    NaN   NaN   NaN   NaN
    NaN   NaN   NaN   NaN
    NaN   NaN   NaN   NaN
    

    使用您的方法,我们得到:

    for i = 1:length(formula)
        ttable(i,abs(formula(i,:))) = -1*formula(i,:);
    end
    
    ttable =
    
    -1    -2     3    -4
    -1     2    -3    -4
     1    -2    -3    -4
    -1    -2    -3     4
    

    使用我的方法,我们得到:

    columnIndices = reshape(abs(formula).', 1, []);
    rowIndices = reshape(repmat(1:size(formula,2), size(formula, 1), 1), 1, []);
    indices = sub2ind(size(formula), rowIndices, columnIndices);
    ttable(indices) = -1*formula.';
    
    ttable =
    
    -1    -2     3    -4
    -1     2    -3    -4
     1    -2    -3    -4
    -1    -2    -3     4
    

    如果您的矩阵很小,那么这样做而不是 for 循环的计算开销可能会更大,因此效率会很低。但是,如果您的矩阵更大,那么此代码可能会更快。无论哪种方式,我认为您的 for 循环方法仍然很好。 JIT 应该为for 循环启动。如果您在对使用for 循环作为算法之一的算法进行一些时序测试时查看这篇文章,那么for 循环是最快的算法之一。在这里查看:MATLAB: Subtracting matrix subsets by specific rows

    【讨论】:

    • 我的矩阵很大,所以肯定会有所帮助。谢谢!
    • @RenéG - 不客气!告诉我进展如何。
    • 如果您在同一行中有一个正面和负面对应物,例如-22,该怎么办?
    • @Divakar - 我也考虑过,但我没有质疑 OP 的目标。我只是将他/她上面写的代码翻译成向量化的东西。不过好地方。我假设每一行都有 unique absolute 值。也许这是 OP 已经强制执行的内容,但在帖子中没有这么说。您还可以从我的示例中看到,我确保这些值是这样的。
    • @rayryeng 希望如果在解决方案中添加该假设以避免任何混淆,这不会太麻烦?
    【解决方案2】:

    另一种方法,使用bsxfun 生成线性索引:

    ind = bsxfun(@plus, (1:size(ttable,1)).' , (abs(formula)-1)*size(ttable,1));
    ttable(ind) = -formula;
    

    【讨论】:

      猜你喜欢
      • 2013-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-06
      • 2013-02-18
      • 1970-01-01
      • 2023-03-22
      相关资源
      最近更新 更多