我有以下矩阵:
1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2
0 0 1 2 0 0 1 2 0 0 1 2 0 0 1 2 0 0 1 2 0 0 1 2
0 0 0 0 1 1 1 1 2 2 2 2 0 0 0 0 1 1 1 1 2 2 2 2
我想随机置换列,约束第二行中的每四个数字应包含某种形式的
0 0 1 2
e.g。以下示例中的第1:4,5:8,9:12,13:16,17:20,21:24列均包含数字0 0 1 2。
0 1 0 2 2 0 1 0 0 0 2 1 1 2 0 0 2 0 1 0 1 0 0 2
置换矩阵中的每一列应在第一个矩阵中具有相应的列。换句话说,在列中不应该改变任何内容。
我似乎无法想到一个直观的解决方案 - 是否有另一种方法来提出某种形式的初始矩阵,它既满足约束又保留了列的完整性?每列代表实验中的条件,这就是我希望它们平衡的原因。
答案 0 :(得分:2)
您可以通过以下方式直接计算排列:首先,在第二行中排列0
的所有列,然后在它们之间置换所有1
,最后全部{{1}他们之间。这样可以确保,例如,任何两个2
列同样可能是0
生成的排列中的前两列。
第二步是对4个块中的所有列进行置换:随机置换列1-4,随机置换列5-8等。一旦这样做,你就有了一个矩阵,为每个列保持(0 0 1 2)模式4列的块,但每组(0 0 1 2)同样可能在4的任何给定块中,并且(0 0 1 2)同样可能是任何顺序。
A
示例结果:
A = [1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2
0 0 1 2 0 0 1 2 0 0 1 2 0 0 1 2 0 0 1 2 0 0 1 2
0 0 0 0 1 1 1 1 2 2 2 2 0 0 0 0 1 1 1 1 2 2 2 2];
%% Find the indices of the zeros and generate a random permutation with that size
zeroes = find(A(2,:)==0);
perm0 = zeroes(randperm(length(zeroes)));
%% Find the indices of the ones and generate a random permutation with that size
wons = find(A(2,:) == 1);
perm1 = wons(randperm(length(wons)));
%% NOTE: the spelling of `zeroes` and `wons` is to prevent overwriting
%% the MATLAB builtin functions `zeros` and `ones`
%% Find the indices of the twos and generate a random permutation with that size
twos = find(A(2,:) == 2);
perm2 = twos(randperm(length(twos)));
%% permute the zeros among themselves, the ones among themselves and the twos among themselves
A(:,zeroes) = A(:,perm0);
A(:,wons) = A(:,perm1);
A(:,twos) = A(:,perm2);
%% finally, permute each block of 4 columns, so that the (0 0 1 2) pattern is preserved, but each column still has an
%% equi-probable chance of being in any position
for i = 1:size(A,2)/4
perm = randperm(4) + 4*i-4;
A(:, 4*i-3:4*i) = A(:,perm);
end
我能够在运行MATLAB 2016a的大约9.32秒内生成100 A =
Columns 1 through 15
1 1 2 2 2 2 1 1 2 2 1 2 2 1 2
0 0 2 1 0 2 0 1 0 2 1 0 1 2 0
0 1 2 2 2 0 1 1 1 1 2 0 0 2 0
Columns 16 through 24
2 1 1 1 1 1 2 2 1
0 2 0 0 1 0 0 1 2
1 1 2 2 0 0 2 1 0
的约束排列,让您了解此代码需要多长时间。当然有一些方法可以优化排列选择,因此你不必进行相当多的随机抽取,但我总是喜欢简单明了的方法,直到证明不足为止。
答案 1 :(得分:1)
你可以使用rejection method:继续尝试随机排列,选择等概率,直到满足要求。这保证了所有有效排列具有相同的被选择概率。
A = [ 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2
0 0 1 2 0 0 1 2 0 0 1 2 0 0 1 2 0 0 1 2 0 0 1 2
0 0 0 0 1 1 1 1 2 2 2 2 0 0 0 0 1 1 1 1 2 2 2 2 ]; % data matrix
required = [0 0 1 2]; % restriction
row = 2; % row to which the resitriction applies
sorted_req = sort(required(:)); % sort required values
done = false; % initiallize
while ~done
result = A(:, randperm(size(A,2))); % random permutation of columns of A
test = sort(reshape(result(row,:), numel(required), []), 1); % reshape row
% into blocks, each block in a column; and sort each block
done = all(all(bsxfun(@eq, test, sorted_req))); % test if valid
end
以下是一个示例结果:
result =
2 1 1 1 1 2 1 2 1 2 2 1 2 2 1 2 2 2 1 1 1 2 1 2
2 0 0 1 2 1 0 0 0 1 0 2 2 0 1 0 1 2 0 0 2 0 1 0
2 1 2 2 1 2 2 0 1 1 1 2 1 1 0 0 0 0 0 0 0 2 1 2