MATLAB:快速创建具有固定度(行总和)的随机对称矩阵

时间:2016-04-19 18:41:41

标签: algorithm performance matlab matrix

我正在寻找一种快速创建具有以下属性的随机矩阵A的方法:

  • A = transpose(A)
  • 所有我
  • A(i,i) = 0
  • A(i,j) >= 0所有我,j
  • sum(A) =~ degree;行的总和由我想指定的分布随机分布(这里=~表示近似相等)。

分发degree来自矩阵orig,特别是degree=sum(orig),因此我知道存在具有此分布的矩阵。

例如:orig=[0 12 7 5; 12 0 1 9; 7 1 0 3; 5 9 3 0]

orig =
 0    12     7     5
12     0     1     9
 7     1     0     3
 5     9     3     0

 sum(orig)=[24 22 11 17];

现在一个可能的矩阵A=[0 11 5 8, 11 0 4 7, 5 4 0 2, 8 7 2 0]

A = 
 0    11     5     8
11     0     4     7
 5     4     0     2
 8     7     2     0

sum(A)=[24 22 11 17]

我正在尝试这段时间,但遗憾的是我的两个想法并不奏效:

版本1:

我将Nswitch次切换为两个随机元素:A(k1,k3)--; A(k1,k4)++; A(k2,k3)++; A(k2,k4)--;(转置元素也是如此)。

不幸的是,Nswitch = log(E)*E(与E=sum(sum(nn)))以使矩阵非常不相关。作为我的E > 5.000.000,这是不可行的(特别是,因为我需要至少10个这样的矩阵)。

第2版:

我根据分布从头开始创建矩阵。我们的想法是,根据i的分布,用degree(i)个数字填充degree的每一行:

nn=orig;
nnR=zeros(size(nn));
for i=1:length(nn)
    degree=sum(nn);
    howmany=degree(i);
    degree(i)=0;
    full=rld_cumsum(degree,1:length(degree));
    rr=randi(length(full),[1,howmany]);
    ff=full(rr);
    xx=i*ones([1,length(ff)]);
    nnR = nnR + accumarray([xx(:),ff(:)],1,size(nnR));
end
A=nnR;

但是,虽然sum(A')=degreesum(A)系统地偏离了degree,但我无法找到原因。

当然,与degree的小偏差很好,但是在某些地方大量的矩阵中,似乎存在系统偏差。

如果某人可以向我显示版本1的快速方法,或者版本2中分布的系统偏差的原因,或者以不同方式创建此类矩阵的方法,我将非常高兴。谢谢!

修改

这是 matsmath 提出的解决方案中的问题: 想象一下你有矩阵:

orig = 
 0    12     3     1
12     0     1     9
 3     1     0     3
 1     9     3     0

r(i)=[16 22 7 13]

  • 步骤1:r(1)= 16,我的随机整数分区为p(i)= [0 7 3 6]。
  • 第2步:检查所有p(i)< = r(i),情况就是这样。
  • 第3步:

我的随机矩阵开始看起来像

A = 
 0    7     3     6
 7    0     .     .
 3    .     0     .
 6    .     .     0

新行和向量rnew = [r(2)-p(2),...,r(n)-p(n)] = [15 4 7]

第二次迭代(这里出现问题):

  • 步骤1:rnew(1)= 15,我的随机整数分区是p(i)= [0 A B]:rnew(1)= 15 = A + B.
  • 步骤2:检查所有p(i)&lt; = rnew(i),其给出A <= 4,B <= 7。所以A + B <= 11,但A + B必须是15. 矛盾: - /

EDIT2:

这是代表(据我所知) David Eisenstat 发布的解决方案的代码:

orig=[0 12 3 1; 12 0 1 9; 3 1 0 3; 1 9 3 0];
w=[2.2406 4.6334 0.8174 1.6902];
xfull=zeros(4);

for ii=1:1000
    rndmat=[poissrnd(w(1),1,4); poissrnd(w(2),1,4); poissrnd(w(3),1,4); poissrnd(w(4),1,4)];
    kkk=rndmat.*(ones(4)-eye(4)); % remove diagonal
    hhh=sum(sum(orig))/sum(sum(kkk))*kkk; % normalisation
    xfull=xfull+hhh;
end

xf=xfull/ii;
disp(sum(orig)); % gives [16    22     7    13]
disp(sum(xf));   % gives [14.8337    9.6171   18.0627   15.4865] (obvious systematic problem)
disp(sum(xf'))   % gives [13.5230   28.8452    4.9635   10.6683] (which is also systematically different from [16, 22, 7, 13]

2 个答案:

答案 0 :(得分:1)

第一种方法(基于版本2)

让你的行和向量由矩阵orig [r(1),r(2),...,r(n)]给出。

Step 1. Take a random integer partition of the integer r(1) into exactly n-1 parts, say p(2), p(3), ..., p(n)
Step 2. Check if p(i)<=r(i) for all i=2...n. If not, go to Step 1.
Step 3. Fill out your random matrix first row and colum by the entries 0, p(2), ... , p(n), and consider the new row sum vector [r(2)-p(2),...,r(n)-p(n)].

使用n-1阶矩阵重复这些步骤。

关键是,您一次随机化一行,并将问题减少到搜索大小少一的矩阵。

正如OP在评论中指出的那样,这种天真的算法失败了。原因是所讨论的矩阵在其条目上具有进一步必要条件,如下所示:

FACT:

如果A是行总和为[r(1), r(2), ..., r(n)]的原始矩阵,那么每个i=1..n必然,它会保留r(i)<=-r(i)+sum(r(j),j=1..n)

也就是说,任何行总和,比如ir(i),最多必须与其他行总和(不包括r(i))的总和一样大。< / p>

鉴于此,可以修改算法。请注意,在步骤2b中。我们检查新的行和向量是否具有上面讨论的属性。

Step 1. Take a random integer partition of the integer r(1) into exactly n-1 parts, say p(2), p(3), ..., p(n)
Step 2a. Check if p(i)<=r(i) for all i=2...n. If not, go to Step 1.
Step 2b. Check if r(i)-p(i)<=-r(i)+p(i)+sum(r(j)-p(j),j=2..n) for all i=2..n. If not, go to Step 1.
Step 3. Fill out your random matrix first row and colum by the entries 0, p(2), ... , p(n), and consider the new row sum vector [r(2)-p(2),...,r(n)-p(n)].

第二种方法(基于版本1)

我不确定这种方法是否为您提供了随机矩阵,但它肯定会为您提供不同的矩阵。

这里的想法是在本地更改orig矩阵的某些部分,以维护其所有属性。

你应该在主对角线下面寻找一个随机的2x2子矩阵,它包含严格的正条目,例如[[a,b],[c,d]],并通过随机值r[[a+r,b-r],[c-r,d+r]]来扰动它的内容。您也可以在主对角线上方进行相同的更改,以保持新矩阵的对称性。这里的要点是条目中的变化“相互抵消”。

当然,r应该以{{1​​}}和b-r>=0的方式选择。

你可以追求这个想法来修改更大的子矩阵。例如,您可以选择3个随机行坐标c-r>=0r1r2和3个随机列坐标r2c1c2然后在9个c3位置的orig矩阵中进行更改,如下所示:您将(ri,cj)子矩阵3x3更改为[[a b c],[d e f], [g h i]]。你在转置的地方做同样的事情。同样,必须以某种方式选择随机值[[a-r b+r c] [d+r e f-r], [g h-r i+r]],以便ra-r>=0以及f-r>=0。此外,h-r>=0c1以及r1c3必须是不同的,因为您无法更改矩阵r3的主对角线中的0条目

你可以一遍又一遍地重复这些事情,比如说orig次,直到找到一些看似随机的东西。请注意,这个想法使用的事实是您已经拥有解决方案的知识,这是矩阵100,而第一种方法根本不使用这些知识。

答案 1 :(得分:1)

因为它足以大致保留度序列,所以让我提出一个随机分布,其中对角线上方的每个条目都是根据Poisson distribution选择的。我的直觉是我们想要找到权重w_i,使i,j的{​​{1}}条目具有均值i != j(所有对角线条目都为零)。这给了我们一个非线性方程组:

w_i*w_j

其中for all i, (sum_{j != i} w_i*w_j) = d_i, d_i的程度。等价地,

i

后者可以通过从for all i, w_i * (sum_j w_j) - w_i^2 = d_i. 的起始解决方案应用Newton's method来解决,如下所述。

获得w_i = d_i / sqrt(sum_j d_j)后,我们可以使用w_i重复采样,一次生成多个泊松分布的样本。

(如果我有时间,我会尝试在numpy中实现这个。)

4乘4问题的方程组的雅可比矩阵是

poissrnd

通常,让(w_2 + w_3 + w_4) w_1 w_1 w_1 w_2 (w_1 + w_3 + w_4) w_2 w_2 w_3 w_3 (w_1 + w_2 + w_4) w_3 w_4 w_4 w_4 (w_1 + w_2 + w_3). 成为A的对角矩阵。设A_{i,i} = sum_j w_j - 2*w_iu = [w_1, ..., w_n]'。雅可比人可以写成v = [1, ..., 1]'。逆由Sherman--Morrison公式

给出
J = A + u*v'

对于牛顿步骤,我们需要为某些给定的 A^-1*u*v'*A^-1 J^-1 = (A + u*v')^-1 = A^-1 - -------------- . 1 + v'*A^-1*u 计算J^-1*y。这可以使用上面的等式在y时间内直接完成。当我有机会时,我会添加更多细节。