How to create a random permutation that has specific values in a specific place?
2 views (last 30 days)
Show older comments
I am trying to get a trial order that randomises between sequences but not within. This code works for my purposes:
temp(1).compound = {'G'};
temp(2).compound = {'R'};
temp(3).compound = {'A'};
temp(4).compound = {'RA'};
temp(5).compound = {'B'};
temp(6).compound = {'B'};
temp(7).compound = {'G'};
temp(8).compound = {'B'};
temp(9).compound = {'G'};
temp(10).compound = {'R'};
temp(11).compound = {'RA'};
sequence1(1) = 3;
sequence2(1)=1;
sequence2(2)=7;
sequence2(3)=9;
sequence3(1)=2;
sequence3(2)=4;
sequence3(3)=10;
sequence3(4)=11;
sequence4(1)=5;
sequence5(1)=6;
sequence5(2)=8;
sequenece = {sequence1, sequence2, sequence3, sequence4, sequence5};
ind = randperm(numel(sequenece));
shuffled_sequenece = [sequenece{ind}];
for i = 1:length(temp)
TRIAL(i)=temp(shuffled_sequenece(i));
end
I need all sequences to be in TRIAL but I want sequence1 or sequence4 to be randomly fixed at trial number 6. How could I do this?
2 Comments
Stephen23
on 23 Aug 2018
Edited: Stephen23
on 24 Aug 2018
@William Nicholson: using numbered variables is a sign that you are doing something wrong. Trying to access variable names dynamically is one way that beginners force themselves into writing slow, complex, buggy code that is hard to debug. Read this to know more:
Your code would be simpler and much more efficient if you just used indexing.
QUESTION: do the index vectors within sequence need to be kept together, or can they be split by element 6? For example, if the index vectors of sequence sequence are arranged like this:
[[1,7,9], [2,4,10,11], ...] ->
[ 1, 7, 9, 2, 4, 10, 11, ... ]
^^ sixth element
then the sixth element is 10: what do you want done to this sequence: split it apart, something like this:
[1,7,9,2,4,5,10,11,...]
^^^^ split and insert one of the required indices?
Accepted Answer
Stephen23
on 24 Aug 2018
Edited: Stephen23
on 25 Aug 2018
One simple solution is to keep generating permutations until one matches your requirements:
C = {'G','G','A','G','B','G','G','G','G','G','RA'};
S = {3, [1,7,9], [2,4,10,11], 5, [6,8]};
X = zeros(1,11);
while ~any(X(6)==[S{[1,4]}])
X = [S{randperm(numel(S))}];
end
Z = C(X) % Don't use a loop! This is MATLAB, so just use indexing.
In theory this might never reach a solution, but for small problems, like the one in your question, it will be quite fast in practice. Note that I used a cell array for simplicity: if you really need a structure, just add this:
TRIAL = struct('compound',Z)
If your actual problem is larger then you might need to consider a more heavy-handed approach. One possibility is to determine all permutations which place either of the two scalar values into the sixth element of X (the method I show here assumes that both S{1} and S{4} are scalar, that there are no other scalars, and that there are no empty arrays). For large problems a recursive function might be more efficient, but here I cheated and just used perms:
S = {3, [1,7,9], [2,4,10,11], 5, [6,8]};
L = cellfun('prodofsize',S);
P = perms(1:numel(S));
Y = sum(ismember(cumsum(L(P),2),[5,6]),2)==2;
M = P(Y,:)
giving a matrix M where each row is one permutation (not random!) of the index vectors in S such that one of the scalar values S{1} or S{4} ends up in the sixth element:
M =
5 2 4 3 1
5 2 4 1 3
5 2 1 4 3
5 2 1 3 4
4 3 1 5 2
4 3 1 2 5
3 4 1 5 2
3 4 1 2 5
3 1 4 5 2
3 1 4 2 5
2 5 4 3 1
2 5 4 1 3
2 5 1 4 3
2 5 1 3 4
1 3 4 5 2
1 3 4 2 5
Then all you need to do is randomly pick one row from that matrix to use as the index:
X = M(randi(size(M,1)),:);
Z = C(X) % Don't use a loop!
0 Comments
More Answers (1)
dpb
on 22 Aug 2018
Writing multiple sequentially-numbered variables is a bad idea in general but won't try to get into fixing that here...but if were indexed or struct fields or other ways to implement wouldn't have to rewrite code lines...
if rand<0.5
sequence = {sequence1, sequence2, sequence3, sequence4, sequence5};
else
sequence = {sequence4, sequence2, sequence3, sequence1, sequence5};
end
if I get your intent.
3 Comments
dpb
on 22 Aug 2018
Yeah, but as noted you need to store the data in arrays or named fields in a struct in order to address it dynamically rather than using sequentially-named variables.
See Also
Categories
Find more on Get Started with MATLAB in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!