【问题标题】:Randomly replace elements in matrix with a clumpy or aggregated method用块状或聚合方法随机替换矩阵中的元素
【发布时间】:2012-11-19 07:07:10
【问题描述】:

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

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

【问题讨论】:

  • 所以你有一个方阵,你想用 6 替换该矩阵的一些随机方子集吗?那是问题吗?我不确定你所说的“聚集”是什么意思
  • @NatoSaichek 那行得通。我使用 clumped 表示具有 6's 的元素会像子集方阵或其他形状一样相互接触。谢谢。
  • 看看这个link
  • @nofunsally 您还设想了哪些其他限制?每个矩阵是否需要插入相同数量的 6?团块是否需要在整个矩阵中均匀分布?他们可以触摸吗?
  • @jerad 对于任何给定的模拟,要插入的 6 的数量可以相同。团块不需要均匀分布。 @bonCodigo 我现在正在查看 MATLAB 的 datasample。谢谢。

标签: matlab random matrix replace


【解决方案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

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

【讨论】:

  • 我进行了编辑以展示我将如何去做。我看到您当前的问题是随机数生成的速度。我很想知道这是否效果更好。根据矩阵和块的大小,最好将行与bsxfuns 交换循环(循环不再可怕,通常 - 如果您使用大型矩阵)。
  • 这不是随机数生成,我的代码有其他缺陷。在寻找非 6 邻居时(经常)会卡住。
  • 上面的代码很好用,我需要了解更多关于我收集到的索引的信息,因为上面的很多内容对我来说仍然是魔法(即使使用 cmets)。我需要阅读这些程序。非常感谢。
【解决方案2】:

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

【讨论】:

  • 上述代码的问题在于,随着块大小的增长,它越来越有可能找不到合适的位置(例如~= 6)来替换自己
猜你喜欢
  • 2014-05-05
  • 2023-04-08
  • 2022-01-24
  • 2014-12-07
  • 1970-01-01
  • 2017-05-09
  • 2013-07-29
  • 2022-07-11
  • 2016-11-13
相关资源
最近更新 更多