MATLAB / Octave循环的矢量化

时间:2014-06-23 23:55:23

标签: matlab octave vectorization

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

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

formula是矩阵和ttable = NaN(length(formula),max(max(abs(formula))))。谢谢!

2 个答案:

答案 0 :(得分:3)

根据代码判断,您正在做的是ttable的每一行,您希望使用abs(formula(i,:))访问的索引,并将每个位置设置为-1*formula(i,:)

注意到@Divakar的聪明之处,我将假设每一行都有唯一的绝对值。换句话说,每行不应包含连续a-a行的实例,其中a是从1size(formula,2)的任意数字}。原因是因为在计算abs(formula(i,:))时,-aa会映射到同一列。这将发生冲突并允许覆盖相同的条目(Thanks @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

答案 1 :(得分:0)

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

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