How do I use randperm to produce a completely new sequence (no numbers in same place)?

7 views (last 30 days)
Is there a way to permute numbers with randperm and get a completely new permutation every time?
For example,
randperm(5)
to generate multiple rows of 5 numbers, none of which have the same number in the same column?
For example:
4 2 5 1 3
and
3 4 1 2 5
NOT
4 2 5 1 3
and
3 2 4 5 1
which have the different sequences, but the 2 is in the same location.
  1 Comment
Jan
Jan on 29 Jan 2011
Please explain, if you need just 2 index vectors (then the derangment is useful) or a set of all n index vectors with no value appearing twice in a row and column.

Sign in to comment.

Accepted Answer

Jan
Jan on 26 Jan 2011
Thanks Bruno! Now I see the limitations and the connection to the derangement.
Next approach:
a = mod(bsxfun(@plus, 0:4, transpose(0:4)), 5) + 1;
b = a(randperm(5), :);
b = b(:, randperm(5))
Or simpler:
b = mod(bsxfun(@plus, randperm(5), transpose(randperm(5))), 5) + 1;
Does this now reduce the correlation between neighboring elements to the minimum considering the OPs demands? Jan
  2 Comments
Joseph Kirk
Joseph Kirk on 27 Jan 2011
This is the best answer. It will be fast for any N and it has a very small memory requirement. More importantly, it is not excessively complex and still gives the OP exactly what they asked for.

Sign in to comment.

More Answers (9)

Walter Roberson
Walter Roberson on 25 Jan 2011
Not directly with randperm(), except perhaps by way of looping and rejecting the ones that do not fit.
Once you have a particular solution, say S, you can generate other solutions isomorphic to it by using
T = randperm(5);
T(S)
I have in mind an idea that might work to generate such matrices, but I have not fleshed it out. Probably someone else will come up with a complete solution before I have time to revisit this.
  1 Comment
Chris
Chris on 4 May 2015
I am not sure this would work. For example if T comes out as the inverse of S, than T(S) will be the identity, and all elements will be fixed.

Sign in to comment.


Paulo Silva
Paulo Silva on 25 Jan 2011
b=randperm(5);t=0;
for a=1:10
while(1)
c=randperm(5);
e=0;
for d=1:5
if (ismember(c(d),b(:,d)))
e=1;
break
end
end
if (e==0)
t=0;
break
else
t=t+1;
if ((t>2000) | (numel(b(:,1)))==5)
return
end
end
end
b=[b;c]
end
  1 Comment
Paulo Silva
Paulo Silva on 26 Jan 2011
It's a brute force method, t is used just to stop the function from infinite looping, it stops when the output got 5 lines but the user might change the number of lines to a greater value than the one possible, it stops after failing 2000 times.

Sign in to comment.


Matt Fig
Matt Fig on 26 Jan 2011
O.k., I see I misread the requirements. You want no two elements to be equal, correct? This should work too, if A is not really large:
function As = mix(A)
T = perms(A);
As = T(1,:);
S = size(T,1);
L = length(A);
P = prod(1:L-1);
for jj =1+P:P:S
for ii = 0:P-1
if ~any(bsxfun(@eq,As,T(jj+ii,:)),2)
As = [As;T(jj+ii,:)];
end
end
end

Matt Fig
Matt Fig on 26 Jan 2011
Or, perhaps more efficient even:
function As = mix2(A)
T = A(randperm(length(A))).';
As = zeros(length(A));
As(:,1) = T;
for jj =2:length(A)
As(:,jj) = circshift(As(:,jj-1),1);
end
Then from the command line:
F = mix2([3 6 7 8 9 12])
F =
7 3 12 8 6 9
9 7 3 12 8 6
6 9 7 3 12 8
8 6 9 7 3 12
12 8 6 9 7 3
3 12 8 6 9 7
The rows of F are your permutations.

Jan
Jan on 26 Jan 2011
A set of completely different permutations of length 5 contains just 5 vectors. For example:
a = randperm(5);
b = bsxfun(@plus, a, transpose(1:5));
R = mod(b, 5) + 1
>> 5 2 3 4 1
1 3 4 5 2
2 4 5 1 3
3 5 1 2 4
4 1 2 3 5
Then you can choose any lines of this matrix.
  3 Comments
Walter Roberson
Walter Roberson on 26 Jan 2011
No, "plus" is the name of the function that does addition:
+ Plus.
X + Y adds matrices X and Y. X and Y must have the same
dimensions unless one is a scalar (a 1-by-1 matrix).
A scalar can be added to anything.
C = PLUS(A,B) is called for the syntax 'A + B' when A or B is an
object.
Overloaded methods:
timeseries/plus
laurpoly/plus
laurmat/plus

Sign in to comment.


Bruno Luong
Bruno Luong on 26 Jan 2011
Jan's method only concerns circular permutation, which is limited.
In general, any permutation of a set of cardinal n can be decomposed k non overlap cycles. The sum of cardinals of the cycle is n.
OP's request can be translated in term of permutation theory as "all cycle have cardinal > 1" (cycle of cardinal 1 is a fixed point).
Jan's is one realization of, i.e., there is one (k=1) linear cycle of cardinal n.
One can program more generic of all valid permutations by splitting (randomly) the set 1:n in k subsets of cardinal >= 2, then select a (random) circular permutation of each subset.
This decomposition a little cumbersome to code, but it should give a better randomized permutation.
I believe there is a smarter way to do it. There one of the code by JOS in FEX, then name escape me now (something like derangement).
  4 Comments
Bruno Luong
Bruno Luong on 26 Jan 2011
Jan's quote: [...But the OP asked for two different permutations, which differ in all elements...]
Simply apply the derangement on the first permutation.
Both problems are then equivalent.
Bruno
Jan
Jan on 28 Jan 2011
I think the new order of answers is really confusing. Bruno's "Jan's method" concerns my first answer:
a = randperm(5); b = bsxfun(@plus, a, transpose(1:5)); R = mod(b, 5) + 1;
But not my second answer using two RANDPERMs, which is found on top of the answer list now - confusingly.

Sign in to comment.


Jos (10584)
Jos (10584) on 26 Jan 2011
I just resubmitted RANDPERMFULL to the FEX. It will be available in few days.
To the OP, should the next permutation be different from the current permutation (i.e., a derangement of the current permutation) only, or should it be different from all previously obtained permutations? In other words, is this sequence of permutations allowed?
[2 3 1 4] -> [3 4 2 1] -> [2 1 3 4] -> [3 2 4 1]

Bruno Luong
Bruno Luong on 29 Jan 2011
This tool by Derek O'Connor can return efficiently a derangement:
Use it to get two permutations with zero repeat
n = 10;
a = randperm(n)
b = a(GRDrej(n))
% Check
all(a~=b)
Bruno

Matt Fig
Matt Fig on 25 Jan 2011
You could do this with the PERMS function.
A = [4 2 5 1 3]; % Sample code
T = perms(A);
B = randperm(size(T,1));
% display random permutations of A:
for ii = 1:size(T,1)
T(B(ii),:)
end
If your A matrix is large enough, you may want to consider my NEXTPERM function on the FEX:
  2 Comments
Paulo Silva
Paulo Silva on 26 Jan 2011
that perms is great, didn't know it, thanks
but there's something wrong with that code, I believe that the results aren't the correct ones
Matt Fig
Matt Fig on 26 Jan 2011
I must have missed the part where she said she didn't want to have any two elements in the same place.

Sign in to comment.

Categories

Find more on Creating and Concatenating Matrices in Help Center and File Exchange

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!