How to create a random permutation that has specific values in a specific place?

5 Ansichten (letzte 30 Tage)
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 Kommentare
Stephen23
Stephen23 am 23 Aug. 2018
Bearbeitet: Stephen23 am 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?
William Nicholson
William Nicholson am 24 Aug. 2018
Apologies for not being clear enough but index vectors within sequence need to be kept together and not split by element 6.
So this would be a valid order: [1 7 9], [6 8], 3, [2 4 10 11], 5
but this would not be: [1 7 9], [2 4 5 10 11]

Melden Sie sich an, um zu kommentieren.

Akzeptierte Antwort

Stephen23
Stephen23 am 24 Aug. 2018
Bearbeitet: Stephen23 am 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!

Weitere Antworten (1)

dpb
dpb am 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 Kommentare
dpb
dpb am 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.
William Nicholson
William Nicholson am 24 Aug. 2018
Having stored the data in a cell array I still wish for sequence1 ('3') or sequence4 ('5') to be randomly fixed at trial number 6 in TRIAL. How could I do this?
if true
temp(1).compound = {'G'};
temp(2).compound = {'G'};
temp(3).compound = {'A'};
temp(4).compound = {'G'};
temp(5).compound = {'B'};
temp(6).compound = {'G'};
temp(7).compound = {'G'};
temp(8).compound = {'G'};
temp(9).compound = {'G'};
temp(10).compound = {'G'};
temp(11).compound = {'RA'};
sequence = {3, [1 7 9], [2 4 10 11], 5, [6 8]};
rand_ind=randperm(length(sequence));
sequence_random=sequence(rand_ind);
Shuffled_sequence = cell2mat(sequence_random);
for i = 1:length(temp)
TRIAL(i)=temp(Shuffled_sequence(i));
end
end

Melden Sie sich an, um zu kommentieren.

Kategorien

Mehr zu Get Started with MATLAB finden Sie in Help Center und File Exchange

Produkte


Version

R2014b

Community Treasure Hunt

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

Start Hunting!

Translated by