Matlab 0和1的矩阵,其中后续行中的赋值取决于前一行

Matlab 0和1的矩阵,其中后续行中的赋值取决于前一行,matlab,psychtoolbox,Matlab,Psychtoolbox,我想在MATLAB中创建一个矩阵,其中: 第一行由0和1的随机排列组成,均匀分割(即50-50) 第二行随机将0分配给第一行中0和1的50%,将1分配给剩余的50% 第三行随机将0分配给第二行中0和1的50%,将1分配给剩余的50% 非随机化示例: 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 有什么建议吗?使用randperm的解决方案:

我想在MATLAB中创建一个矩阵,其中:

第一行由0和1的随机排列组成,均匀分割(即50-50)

第二行随机将0分配给第一行中0和1的50%,将1分配给剩余的50%

第三行随机将0分配给第二行中0和1的50%,将1分配给剩余的50%

非随机化示例:

0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1  
0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1  
0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1

有什么建议吗?

使用
randperm
的解决方案:

nrows = 3;
ncols = 16;
M = zeros(nrows,ncols);    

%// seed the first row
M(1,1:ncols/2) = 1;
M(1,:) = M(1,randperm(ncols));

for r = 2:nrows

    %// Find ncols/4 random between 1 and ncols/2. These will be used to index half of the previous rows 1 elements and set them to one
    idx = randperm(ncols/2);
    idx1 =  idx(1:ncols/4);
    %// Do the same thing again, but this time it will be used for the 0 elements of the previous row
    idx = randperm(ncols/2);
    idx0 =  idx(1:ncols/4);

    idx_prev1 = find(M(r-1,:)); %// Find where the 1 elements were in the last row
    idx_prev0 = find(~M(r-1,:)); %// Find where the 0 elements were in the last row   

    M(r,idx_prev1(idx1))=1; %// Set half of the previous rows 1 elements in this row to 1
    M(r,idx_prev0(idx0))=1; %// Set half of the previous rows 0 elements in this row to 1

end

基于检查数字是否大于或小于中值的解决方案。只要测试的列数是偶数,一组随机双精度数据中正好有一半将大于中值,而另一半将更小。这保证了正好有50%的位被翻转

nRows = 3;
nCols = 16; %# divisible by 4

%# seed the array
%# assume that the numbers in each row are unique (very, very likely)
array = rand(nRows,nCols); 


out = false(nRows,nCols);

%# first row is special
out(1,:) = array(1,:) > median(array(1,:));

%# for the rest of the row, check median for the zeros/ones in the previous row
for iRow = 2:nRows
    zeroIdx = out(iRow-1,:) == 0;
    %# > or < do not matter, both will replace zeros/ones 
    %# and replace with exactly half zeros and half ones
    out(iRow,zeroIdx) = array(iRow,zeroIdx) > median(array(iRow,zeroIdx));
    out(iRow,~zeroIdx) = array(iRow,~zeroIdx) > median(array(iRow,~zeroIdx));
end
nRows=3;
nCols=16;%#可被4整除的
%#为阵列添加种子
%#假设每行中的数字都是唯一的(非常可能)
数组=兰德(nRows,nCols);
out=假(nRows、nCols);
%#第一排是特别的
out(1,:)=数组(1,:)>中值(数组(1,:));
%#对于该行的其余部分,检查前一行中0/1的中值
对于iRow=2:nrow
zeroIdx=out(iRow-1,:)=0;
%#>或<无所谓,两者都将替换0/1
%#并替换为半个零和半个一
out(iRow,zeroIdx)=数组(iRow,zeroIdx)>中值(数组(iRow,zeroIdx));
out(iRow,~zeroIdx)=数组(iRow,~zeroIdx)>中值(数组(iRow,~zeroIdx));
结束

我想提供一个简短的
bsxfun
解决方案:

%// number of divisions
n = 4;

%// unshuffled matrix like in your example
unshuffled = bsxfun(@(a,b) mod(a,2*b) > b-1, meshgrid(1:n^2,1:n) - 1, (2.^((n-1):-1:0)).') %'

%// shuffle columns
shuffled = unshuffled(:,randperm(n^2))


首先,您需要创建非缓冲矩阵,这可以通过将
meshgrid(1:n^2,1:n)
生成的矩阵与依赖于行的模数进行比较来完成。最后,您只需对列进行无序排列。

如果您有统计工具箱,您可以使用以下工具轻松完成此操作:

示例结果:

result = 
     0 1 0 1 1 0 0 0 0 1 0 1 1 0 1 1
     1 1 0 0 0 1 1 1 0 1 0 1 0 0 0 1
     1 0 0 0 1 0 0 1 0 1 1 0 1 1 0 1

这不就是洗牌非随机示例的列吗?如果是这样的话,只需使用
randperm
@Dan:我不这么认为,如果我理解正确的描述,第三行可能看起来像第一行。置换,你不能做到这一点。正如在对问题的评论中指出的,洗牌完美非随机矩阵的列可能是不够的。由于问题的措辞不恰当,因此没有理由不能有两列,例如只有
1
s。这种方法有效地考虑了每一步前面的所有行,而不仅仅是前一行。@Dan无论我怎么扭曲我的想法,我都不能这样解释这个问题。我们必须等待OP猜测。OP状态“第三行随机地将零点分配给第二行中的50%和50%,剩下的第三行,所以第三行根本不考虑第一行,因此事实上可以与第一行相同……我不认为这是正确的。我的理解是,对于第2行中的8个
1
s,第3行中对应的元素中正好有4个应该是
1
。在您的示例
结果中
只有2个是
1
@Dan感谢您指出这一点。缺少一行,无法将每一行初始化为上一行。更正!
M = 3; %// number of rows
N = 16; %// number of columns. Should be multiple of 4, according to problem definition 
result = zeros(M,N); %// preallocate and initiallize to zeros
result(1, randsample(1:N,N/2)) = 1; %// first row: half values set to one, half to zero
for m = 2:M
    result(m, :) = result(m-1, :); %// initiallize row m equal to row m-1
    result(m, randsample(find(result(m-1,:)), N/4)) = 0; %// change half of ones
    result(m, randsample(find(~result(m-1,:)), N/4)) = 1; %// change half of zeros
end
result = 
     0 1 0 1 1 0 0 0 0 1 0 1 1 0 1 1
     1 1 0 0 0 1 1 1 0 1 0 1 0 0 0 1
     1 0 0 0 1 0 0 1 0 1 1 0 1 1 0 1