使用块状或聚合方法随机替换矩阵中的元素

时间:2012-12-01 02:25:38

标签: matlab random matrix replace

在下面的MATLAB代码中,矩阵 B 是通过用随机替换其元素(empty_x)的一部分从矩阵 A 创建的6 。不是在整个矩阵中随机替换empty_x元素的值,而是如何让它们保持丛生(但仍然是随机放置的丛)?

那就是我希望所有 6 - 值元素都是相邻的。如果最简单的方法是将empty_x元素替换为方形矩阵 A ,使用较小的子集ed方矩阵(大小为empty_x)来创建矩阵 B 那就没关系。具有不总是方形矩阵(即异质性)的团块将是很酷的,但不是必需的。

我很欣赏有关如何完成这项任务的一些想法。

干杯。

A = [1 2 3 4 5; 5 4 3 2 1; 1 4 3 2 5; 4 3 2 1 5; 2 1 3 5 4];
B = A;
nA = numel(A);
empty_x = randi(10);
B(randperm(nA,(empty_x))) = 6;

2 个答案:

答案 0 :(得分:1)

我的方法如下:

1) Generate a single random number (uniform distribution)  
     on the interval `[1 numel(A)]`. Use this as the linear index  
     of a seed for your clump.  

while clump_size < desired_clump_size     
    2) Generate a list of all positions in the matrix adjacent to  
         (but not already included in) the existing clump.  
    3) Randomly select one of these indices  
    4) Grow the clump by placing an element in this position.  
end 

我不会写代码;它应该不难实现,特别是如果这段代码不是整个项目的性能瓶颈。

编辑:既然你自己尝试了一下,这里有一些代码:

desired_clump = 5;
matrix_size = 5;
A = zeros(matrix_size);
[C,R]=meshgrid(1:size(A,1), (1:size(A,2))'); %'# row and column numbers for each element

seed = ceil(rand(1)*numel(A));
#% I would have used randi(1) but octave online utility doesn't have it
A(seed) = 1; #% initialize a clump
clump_size = 1;

while clump_size < desired_clump
    CI = A==1; #% logical index of current clump
    CR = reshape(R(CI),1,1,[]); #% 1x1xN index of row values of current clump
    CC = reshape(C(CI),1,1,[]); #% 1x1xN index of col values of current clump
    ADJ = sum(bsxfun(@(x,y)abs(x-y),R,CR)<=1 & bsxfun(@(x,y)abs(x-y),C,CC)<=1, 3)>0 & ~A;
    #% ADJ is the indices of the elements adjacent to the current clump
    B=A; #% for display purposes only
    B(ADJ)=2;
    disp(B)
    disp(' ')
    POS = find(ADJ); #% linear indices of the adjacent elements
    IND = ceil(rand(1)*numel(POS)); #% random index into POS vector
    A(POS(IND))=1; #% grow the clump
    clump_size = clump_size+1;
end
disp(A);

输出: 1表示丛中的元素; 2表示有资格进行丛集扩展

iteration 1:
   0   0   2   1   2
   0   0   2   2   2
   0   0   0   0   0
   0   0   0   0   0
   0   0   0   0   0
iteration 2: 
   0   0   2   1   2
   0   0   2   1   2
   0   0   2   2   2
   0   0   0   0   0
   0   0   0   0   0
iteration 3: 
   0   0   2   1   2
   0   0   2   1   2
   0   0   2   1   2
   0   0   2   2   2
   0   0   0   0   0
iteration 4: 
   0   0   2   1   1
   0   0   2   1   2
   0   0   2   1   2
   0   0   2   2   2
   0   0   0   0   0

Final clump:
   0   0   0   1   1
   0   0   1   1   0
   0   0   0   1   0
   0   0   0   0   0
   0   0   0   0   0

每次生成一个随机数不应该那么慢。如果它确实是一个瓶颈,那么毫无疑问也有办法加快速度。希望这个例子可以让你更进一步。

答案 1 :(得分:0)

使用上面的一些技巧我构建了下面的代码。它适用于较小尺寸的 A ,但是当 A 很大时它会非常慢。感谢您的指导。

clear all
A = zeros(40,40);
[M N] = size(A);
B = A;
nA = numel(A);
per_clump = 10;
dClump = nA*(per_clump/100);
seed = randi(nA);
clumpers = zeros(8,1);
new_seed = seed;
counter = 0;
while counter < dClump; % size of clump
    seed = new_seed;

    for iSize = seed; % find adjacent elements

        west = iSize - M;
        if west < 1
            west = iSize; % the boundary is not periodic
        end;

        east = iSize + M;
        if east > nA
            east = iSize;
        end; %

        north = iSize - 1;
        if north < 1
            north = iSize;
        end; %

        south = iSize + 1;
        if south > nA
            south = iSize;
        end; %

        nwest = iSize - M - 1;
        if nwest < 1
            nwest = iSize;
        end; %

        neast = iSize + M - 1;
        if neast > nA
            neast = iSize;
        end; %

        swest = iSize - M + 1;
        if swest < 1
            swest = iSize;
        end; %

        seast = iSize + M + 1;
        if seast > nA
            seast = iSize;
        end; %

        clumpers = [(west) (east) (north) (south) (nwest) (neast) (seast) (swest)]; % index of adjacent elements
        %new_seed = randsample(clumpers,1); % pick one, really slow

        z = randperm(size(clumpers,2)); % this also really slow
        new_clumpers = clumpers(z);
        new_seed = new_clumpers(randi(8));

        if B(new_seed) == 6;
            %B(new_seed) = B(seed);
            new_seed = seed;
            counter = counter;
        else
            B(new_seed) = 6;
            counter = counter+1;
        end;
    end; %end adj element
end; % end clump size