Home > Mobile >  How can I randomize two binary vectors that are similar while making sure all possible combinations
How can I randomize two binary vectors that are similar while making sure all possible combinations

Time:12-16

Been trying to solve this simple problem for a while but just couldn't find the solution for the life of me...

I'm programming an experiment in PsychToolbox but I'll spare you the details, basically I have two vectors A and B of equal size with the same number of ones and zeroes:

A = [0 0 1 1]
B = [0 0 1 1]

Both vectors A and B must be randomized independently but in such a way that one combination of items between the two vectors is never repeated. That is, I must end up with this

A = [1 1 0 0]
B = [1 0 0 1]

or this:

A = [0 0 1 1]
B = [0 1 0 1]

but I should never end up with this:

A = [1 1 0 0]
B = [1 1 0 0]

or this

A = [0 1 0 1]
B = [0 1 0 1]

One way to determine this is to check the sum of items between the two vectors A B, which should always contain only one 2 or only one 0:

A = [1 1 0 0]
B = [1 0 0 1]

A B = 2 1 0 1

Been trying to make this a condition within a 'while' loop (e.g. so long as the number of zeroes in the vector obtained by A B is superior to 1, keep randomizing A and B), but either it still produces repeated combination or it just never stops looping. I know this is a trivial problem but I just can't get my head around it somehow. Anyone care to help?

This is a simplified version of the script I got:


A = [1 1 0 0];
B = A;
ARand = randperm(length(A));
A = A(ARand);
BRand = randperm(length(B));
B = B(BRand);


while nnz(~(A B)) > 1
    ARand = randperm(length(A));
    A = A(ARand);
    BRand = randperm(length(B));
    B = B(BRand);
end

Still, I end up with repeated combinations.

CodePudding user response:

Here's a possible solution:

A = [0 0 1 1];
B = [0 0 1 1];

% Randomize A and B independently
ARand = randperm(length(A));
A = A(ARand);
BRand = randperm(length(B));
B = B(BRand);

% Keep randomizing A and B until the condition is met
while sum(A B) ~= 1 && sum(A B) ~= length(A)
    ARand = randperm(length(A));
    A = A(ARand);
    BRand = randperm(length(B));
    B = B(BRand);
end

This solution checks if the sum of the elements in A B is either 1 or the length of A, which indicates that only one element in A B is either a 0 or a 2, respectively. If either of these conditions is not met, the vectors A and B are randomized again.

CodePudding user response:

% If you are only looking for an answer to this scenario the easiest way is
% as follows:

A = [0 0 1 1];
B = [0 0 1 1];
nn = length(A);

keepset = [0 0 1 1;0 1 0 1];
keepset = keepset(:,randperm(nn))


% If you want a more general solution for arbitrary A & B (for example)
A = [0 0 0 1 1 1 2 2 2];
B = [0 0 0 1 1 1 2 2 2];
nn = length(A);

Ai = A(randperm(nn));
Bi = B(randperm(nn));

% initialize keepset with the first combination of A & B
keepset = [Ai(1);Bi(1)];

loopcnt = 0;
while (size(keepset,2) < nn) 

    % randomize the elements in A and B independently
    Ai = A(randperm(nn));
    Bi = B(randperm(nn));
    % test each combination of Ai and Bi to see if it is already in the
    % keepset
    for ii = 1:nn
        tstcombo = [Ai(ii);Bi(ii)];
        matchtest = bsxfun(@eq,tstcombo,keepset);
        matchind = find((matchtest(1,:) & matchtest(2,:)));
        if isempty(matchind)
            keepset = [keepset tstcombo];
        end
    end
    loopcnt = loopcnt   1;
    
    if loopcnt > 1000
        disp('Execution halted after 1000 attempts')
        break
    elseif (size(keepset,2) >= nn)
        disp(sprintf('Completed in %0.f iterations',loopcnt))
    end
        
end
keepset
  • Related