带约束的矩阵排列

时间:2016-06-15 21:11:40

标签: arrays matlab matrix permutation

我有以下矩阵:

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

置换矩阵中的每一列应在第一个矩阵中具有相应的列。换句话说,在列中不应该改变任何内容。

我似乎无法想到一个直观的解决方案 - 是否有另一种方法来提出某种形式的初始矩阵,它既满足约束又保留了列的完整性?每列代表实验中的条件,这就是我希望它们平衡的原因。

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