How to execute a column on a circular displacement matrix without a loop

I need to cyclically shift the individual columns of the matrix.

This is easy if you want to move all the columns by the same amount, however in my case I need to move them to a different amount.

I am currently using a loop, and if possible, I would like to remove the loop and use a faster vector approach.

My current code

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 

Is it possible to remove a loop from this code?

Update . I tested all three methods and compared them to the loop described in this question. I calculated how long it would take to complete a column by circularly shifting columns on a 1000x1000 matrix 100 times. I repeated this test several times.

results

  • My loop took more than 12 seconds
  • Offer for pursuit in less than a second
  • Zroth's original answer took a little over 2 seconds.
  • Ansari's suggestion was slower than the original loop
+4
source share
3 answers

Edit

The correct pursuit: using a for loop and appropriate indexing seems to be the way for you. Here is one way to do this:

 [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 

Original answer

I have been looking for something like this before, but I have never come across a good solution. A modification of one of the algorithms used here gives a slight increase in performance in my tests:

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

Nasty? Definitely. As I said, it looks a little faster (2 to 3 times faster for me); but both algorithms work in seconds for m = 3000 and n = 1000 (on a rather old computer too).

It may be worth noting that for me both algorithms are superior to the algorithm provided by Ansari, although its answer is certainly simpler. (The Ansari algorithm output is not consistent with the other two algorithms for me, but it may just be a mismatch in how shifts are applied.) Overall, arrayfun seems pretty slow when I tried to use it. Cells also seem slow to me. But my testing may be biased in some way.

+3
source

Not sure how much faster it will be, but you can try the following:

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

You will need to compare it, but using arrayfun can speed it up a bit.

0
source

I suspect that your cyclic shifts, operations on a random integer matrix donton make it more random, as the numbers are evenly distributed.

So, I hope your question uses randi () for demo purposes only.

-1
source

All Articles