How do I use randperm to produce a completely new sequence (no numbers in same place)?
Show older comments
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
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.
Accepted Answer
More Answers (9)
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
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.
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
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.
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
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
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
Paulo Silva
on 26 Jan 2011
That requires the Financial Toolbox™ because of the plus function.
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
Paulo Silva
on 26 Jan 2011
sorry, my mistake
Bruno Luong
on 26 Jan 2011
1 vote
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
Jan
on 26 Jan 2011
Jos DERANGE disappeared in the last days. There was an earlier version RANDPERMFULL, which replied cyclic permutations by accident only (disappeared also).
But both functions do not match the OPs question: The derangement is a permutation with: not(any(P == 1:length(P))). No element remains at the same position. But the OP asked for two different permutations, which differ in all elements. And if you start with *any* permutation (see RANDPERM in my solution), there are only (n-1) other possible vectors. And the created permutations are only circular, if the reply by RANDPERM is circular.
Note: The permutations in my example are stored in the rows, not in the columns!
Jan
on 26 Jan 2011
See the OPs example: p=[3 4 1 2 5] *is* wanted, although p(5)==5!
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
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.
Jos (10584)
on 26 Jan 2011
1 vote
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]
1 Comment
Jos (10584)
on 26 Jan 2011
Here is the link:
http://www.mathworks.com/matlabcentral/fileexchange/30189
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
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
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
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.
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!