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

このコードからループを削除することは可能ですか?

更新 3つの方法すべてをテストし、この質問で説明したループと比較しました。1000x1000マトリックスで列ごとの循環シフトを100回実行するのにかかる時間を計測しました。このテストを数回繰り返しました。

結果

  • 私のループは12秒以上かかりました
  • 追跡の提案は1秒未満
  • Zrothの元の回答は2秒強かかりました
  • アンサリの提案は元のループよりも遅かった
4

3 に答える 3

3

編集

追求は正しいです。for ループと適切なインデックスを使用することが、ここに進む方法のようです。これを行う1つの方法は次のとおりです。

[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

元の答え

以前に似たようなものを探したことがありますが、良い解決策は見つかりませんでした。ここで使用されているアルゴリズムの 1 つを変更すると、テストのパフォーマンスがわずかに向上します。

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

醜い?絶対。私が言ったように、少し速いようです(私にとっては2〜3倍速い)。しかし、どちらのアルゴリズムも 1 秒未満でクロックインしていますm = 3000(n = 1000かなり古いコンピューターでも)。

私にとって、両方のアルゴリズムが Ansari によって提供されたアルゴリズムよりも優れているように見えることは注目に値するかもしれませんが、彼の答えは確かにより簡単です。(Ansari のアルゴリズムの出力は、私にとっては他の 2 つのアルゴリズムと一致しません。しかし、それは、シフトの適用方法の不一致である可能性があります。) 一般に、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 に答える