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



在下面的 MATLAB 代码中,矩阵 B 是通过将其元素的一部分 (empty_x) 随机替换为 6 从矩阵 A 创建的。 与其在整个矩阵中随机替换empty_x元素的值,我怎样才能使它们保持聚集(但仍然是随机放置团块)?

也就是说,我希望所有 6 值元素都是相邻的。如果最简单的方法是将方阵 A 替换为较小的子集方阵 A empty_x(大小为 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;

我的方法是以下几点:

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

每次生成一个随机数不应该那么慢。 如果它真的是一个瓶颈,无疑也有办法加快它。 希望这个例子能让你走得更远。

使用上面的一些技巧,我构建了下面的代码。 它适用于较小尺寸的 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

最新更新