【问题标题】:Randomize matrix elements between two values while keeping row and column sums fixed (MATLAB)在两个值之间随机化矩阵元素,同时保持行和列总和固定(MATLAB)
【发布时间】:2015-02-10 12:15:51
【问题描述】:

我有一点技术问题,但我觉得使用 MATLAB 强大的工具集应该可以解决。

我所拥有的是一个由 0 和 w 组成的随机 n × n 矩阵,比如使用生成的

A=w*(rand(n,n)<p);

w 的典型值是 3000,但这并不重要。

现在,这个矩阵有两个重要的量,向量

c = sum(A,1); 
r = sum(A,2)';

这是两个行向量,第一个表示每列的总和,第二个表示每行的总和。

接下来我要做的是随机化 w 的每个值,例如在 0.5 和 2 之间。我会这样做

rand_M = (0.5-2).*rand(n,n) + 0.5
A_rand = rand_M.*A;

但是,我不想只选择这些随机数:我希望它们对于每一列和每一行来说,总和仍然等于 c 和 r 的元素。所以要稍微清理一下符号,比如说我们定义

A_rand_c = sum(A_rand,1);
A_rand_r = sum(A_rand,2)';

我希望所有j = 1:n, A_rand_c(j) = c(j)A_rand_r(j) = r(j) 都使用它。

我正在寻找的是一种以某种算法方式重绘 ran​​d_M 元素的方法,我认为,以便最终满足这些要求。

当然,除非我有无限的时间,否则这可能不会真正发生。因此,我接受这些数量属于特定范围:A_rand_c(j) 必须是 [(1-e)*c(j),(1+e)*c(j)]A_rand_r(j)[(1-e)*r(j),(1+e)*r(j)] 的一个元素。我预先定义了这个 e,比如 0.001 之类的。

在寻找方法的过程中,有人可以帮助我吗?我尝试了一种方法,我只是随机重新选择数字,但这真的没有让我到任何地方。它也不必非常高效,我只需要它在有限的时间内为大小的网络工作,比如 n = 50。

需要明确的是,最终输出是满足这些约束的矩阵A_rand

编辑: 好吧,经过一番思考,我想它可能可以通过一些 while 语句来实现,它会遍历矩阵的每个元素。困难的部分是有四种可能性:如果您在特定元素A_rand(i,j) 中,则可能是A_rand_c(j)A_rand_r(i) 都太小、都太大或相反。前两种情况很好,因为这样你就可以重新绘制随机数,直到它小于当前值并改善这种情况。但是另外两种情况是有问题的,因为你会改善一种情况而不是另一种。我想它必须查看哪些标准不太满足,以便尝试修复更糟糕的标准。但这并不是微不足道的..

【问题讨论】:

  • 我看到您使用的是rand 而不是randn。随机值可以是正态分布吗?
  • 嗯,是的,原则上可以。 Uniform 有轻微的偏好,但无论如何,在进行了所有更改之后,它们不会是真正的统一。
  • 要随机化,同时保持每行(或每列)的总和,您可以使用this 的小变化。保持行 列的总和似乎要困难得多。我假设你想要一个 uniform 随机分布
  • 如果我理解正确的话,你不能只生成一个介于 0 和 min(c,r) 之间的随机数,称之为 x0。然后生成一个介于 0 和 min(c,r)-x0 之间的随机数,称为 x1。然后生成一个介于 0 和 min(c,r)-x0-x1 之间的随机数,称为 x2。以此类推。
  • @LuisMendo 我的意图是让它大致一致,是的。我知道这很难做到,所以如果数字有点偏斜也没关系,但原则上它们应该在给定范围内保持一致。您提到的帖子确实对单个专栏有意义,但遗憾的是这不是我需要的:(

标签: arrays matlab random probability


【解决方案1】:

您可以利用 A 中具有单个非零条目的行/列自动为您提供 A_rand 中相同条目的结果这一事实。如果A(2,5) = w 并且它是其列中唯一的非零条目,那么A_rand(2,5) = w 也是如此。还能是什么?

您可以交替查找这些单条目行/列,并将随机数分配给值无关紧要的条目。

这是该过程的框架:

  • A_rand=zeros(size(A)) 是你要填充的矩阵
  • entries_left = A&gt;0 是一个二进制矩阵,显示您仍需要填写 A_rand 中的哪些条目
  • col_totals=sum(A,1) 是您仍需要在 A_rand 的每一列中添加的数量
  • row_totals=sum(A,2) 是您仍需要在 A_rand 的每一行中添加的数量


while sum( entries_left(:) ) > 0

% STEP 1:
% function to fill entries in A_rand if entries_left has rows/cols with one nonzero entry
% you will need to keep looping over this function until nothing changes
% update() A_rand, entries_left, row_totals, col_totals every time you loop

% STEP 2:
% let (i,j) be the indeces of the next non-zero entry in entries_left
% assign a random number to A_rand(i,j) <= col_totals(j) and <= row_totals(i)
% update() A_rand, entries_left, row_totals, col_totals

end

update()
    A_rand(i,j) = random_value;
    entries_left(i,j) = 0;
    col_totals(j) = col_totals(j) - random_value;
    row_totals(i) = row_totals(i) - random_value;
end

选择random_value 的范围可能有点棘手。我能想到的最好的方法是从以N*w*p 为中心的相对狭窄的分布中提取它,其中pA 中的条目非零的概率(这将是行/列总计的平均值)。

这不能很好地扩展到大型矩阵,因为它会随着n^2 的复杂性而增长。我测试了一个 200 x 200 的矩阵,它在大约 20 秒内工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-14
    • 2016-08-12
    • 1970-01-01
    • 2017-01-02
    • 2012-06-08
    • 2014-10-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多