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

MATLABrandpermsequence

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?

Best Answer

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!