4

我需要循环移动矩阵的各个列。

如果您想将所有列移动相同的数量,这很容易,但是,在我的情况下,我需要将它们全部移动不同的数量。

目前我正在使用循环,如果可能的话,我想删除循环并使用更快的基于矢量的方法。

我当前的代码

A = randi(2, 4, 2);
B = A;
for i = 1:size( A,2 );
   d = randi( size( A,1 ));
   B(:,i) = circshift( A(:,i), [d, 0] );
end

是否可以从此代码中删除循环?

更新 我测试了所有三种方法,并将它们与这个问题中描述的循环进行了比较。我计算了在 1000x1000 矩阵上执行 100 次逐列循环移位需要多长时间。我重复了这个测试几次。

结果

  • 我的循环耗时超过 12 秒
  • Pursuit的建议不到一秒
  • Zroth 的原始回答只用了 2 秒多一点
  • Ansari 的建议比原始循环慢
4

3 回答 3

3

编辑

追求是对的:使用 for 循环和适当的索引似乎是这里的方法。这是一种方法:

[m, n] = size(A);
D = randi([0, m - 1], [1, n]);
B = zeros(m, n);

for i = (1 : n)
    B(:, i) = [A((m - D(i) + 1 : m), i); A((1 : m - D(i) ), i)];
end

原始答案

我以前曾寻找过类似的东西,但我从未遇到过好的解决方案。对此处使用的一种算法的修改在我的测试中略微提高了性能:

[m, n] = size(A);
mtxLinearIndices ...
    = bsxfun(@plus, ...
             mod(bsxfun(@minus, (0 : m - 1)', D), m), ...
             (1 : m : m * n));
C = A(idxs);

丑陋?确实。就像我说的,它似乎稍微快一点(对我来说快 2--3 倍);但是这两种算法都在不到一秒的时间内运行m = 3000n = 1000(在一台相当旧的计算机上也是如此)。

值得注意的是,对我来说,这两种算法似乎都优于 Ansari 提供的算法,尽管他的回答肯定更直接。(对我来说,Ansari 的算法的输出与其他两种算法不一致;但这可能只是应用转换方式的差异。)总的来说,arrayfun当我尝试使用它时,它似乎很慢。单元阵列对我来说似乎也很慢。但我的测试可能会以某种方式存在偏差。

于 2012-07-20T19:43:35.053 回答
0

不知道这会快多少,但你可以试试这个:

[nr, nc] = size(A);
B = arrayfun(@(i) circshift(A(:, i), randi(nr)), 1:nc, 'UniformOutput', false);
B = cell2mat(B);

您必须对其进行基准测试,但使用 arrayfun 可能会加快一点速度。

于 2012-07-20T19:20:06.593 回答
-1

我怀疑,您对随机整数矩阵的循环移位操作不会使其变得更加随机,因为这些数字是均匀分布的。

因此,我希望您的问题仅将 randi() 用于演示目的。

于 2012-07-20T22:55:15.010 回答