在两个值之间随机化矩阵元素,同时保持行和列总和不变(MATLAB)

时间:2014-12-11 21:20:38

标签: arrays matlab random probability

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

我所拥有的是一个随机的n×n矩阵0' s,用

生成
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)

我想要的是一种以某种算法方式重绘rand_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)]的元素。这个我事先定义,比如说0.001或者其他什么。

有没有人能够帮助我找到一种方法来做到这一点?我尝试过一种方法,我只是随意地重新编写数字,但这真的不能让我到任何地方。它也不一定是疯狂有效的,我只需要在有限的时间内为大小的网络工作,比如,n = 50。

要清楚,最终输出是满足这些约束的矩阵A_rand

编辑: 好吧,所以在思考了一下之后,我认为它可能对某些while语句有用,它会遍历矩阵的每个元素。困难的部分是存在四种可能性:如果您处于特定元素A_rand(i,j)中,则可能A_rand_c(j)A_rand_r(i)太小,太大或相反。前两种情况很好,因为那样你就可以重新绘制随机数,直到它小于当前值并改善情况。但另外两个案例是有问题的,因为你会改善一种情况而不是另一种情况。我想它必须看看哪个标准不太满意,所以它试图修复那个更糟糕的标准。但这不是一件轻而易举的事情。

1 个答案:

答案 0 :(得分:1)

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

您可以在查找这些单项行/列之间切换,并将随机数分配给值不重要的条目。

这是该过程的骨架:

  • A_rand=zeros(size(A))是您要填写的矩阵
  • entries_left = A>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×200矩阵,它在大约20秒内工作。