[英]MATLAB: Fast creation of random symmetric Matrix with fixed degree (sum of rows)
我正在寻找一种快速创建具有以下特性的随机矩阵A
方法:
A = transpose(A)
A(i,i) = 0
A(i,j) >= 0
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]
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
次转换Nswitch
两个随机元素: A(k1,k3)--; A(k1,k4)++; A(k2,k3)++; A(k2,k4)--;
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:
我根据从头开始的分布创建矩阵。 这个想法是,根据degree
的分布, degree
degree(i)
数填充每一行i
:
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')=degree
, sum(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]
。
我的随机矩阵开始看起来像
A =
0 7 3 6
7 0 . .
3 . 0 .
6 . . 0
新的行总和向量rnew = [r(2)-p(2),...,r(n)-p(n)] = [15 4 7]
第二次迭代(此处出现问题):
编辑2:
这是(据我所知)代表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]
让您的行总和向量由矩阵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在评论中指出的那样,这种幼稚的算法失败了。 原因是所讨论的矩阵在其条目上还具有其他必要条件,如下所示:
事实:
如果A
是一个行总和为[r(1), r(2), ..., r(n)]
的orig矩阵,则对于每个i=1..n
它必然满足r(i)<=-r(i)+sum(r(j),j=1..n)
。
也就是说,任何行总和,例如第i
个, r(i)
,最多必须与其他行总和(不包括r(i)
)一样大。
鉴于此,可以修改算法。 请注意,在步骤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)].
我不确定这种方法是否可以为您提供随机矩阵,但是肯定可以为您提供不同的矩阵。
这里的想法是在本地更改orig
矩阵的某些部分 ,以保持其所有属性的方式。
您应该在主对角线下方寻找一个随机的2x2子矩阵,该子矩阵包含严格为正的项,例如[[a,b],[c,d]]
并用r
到[[a+r,br],[cr,d+r]]
。 您也可以在主对角线上方进行相同的更改,以保持新矩阵对称。 这里的要点是条目内的更改彼此“抵消”。
当然,应该以br>=0
和cr>=0
的方式选择r
。
您也可以遵循此想法来修改较大的子矩阵。 例如,您可以选择3个随机行坐标r1
, r2
, r2
和3个随机列坐标c1
, c2
和c3
,然后按以下方式在orig
矩阵的9个位置(ri,cj)
更改:您更改了3x3
子矩阵[[abc],[def], [ghi]]
至[[ar b+rc] [d+re fr], [g hr i+r]]
。 您可以在转置的位置执行相同的操作。 再次,必须以使得ar>=0
和fr>=0
且hr>=0
的方式选择随机值r
。 而且, c1
和r1
以及c3
和r3
必须是不同的,因为您不能更改矩阵orig
的主对角线中的0项。
您可以一遍又一遍地重复这样的事情,比如说100
次,直到找到看起来随机的东西。 请注意,此想法使用的事实是您具有解决方案的现有知识,这是矩阵orig
,而第一种方法根本不使用此类知识。
由于足以大致保留度数序列,因此让我提出一个随机分布,其中根据Poisson分布选择对角线上方的每个条目。 我的直觉是,我们希望找到权重w_i
,以使i != j
的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.
可以通过从w_i = d_i / sqrt(sum_j d_j)
的初始解采用如下所述的牛顿法来解决后者。
一旦有了w_i
,就可以使用poissrnd
重复采样一次生成多个Poisson分布的样本。
(如果有时间,我将尝试在numpy中实现。)
对于4 x 4问题的方程组的雅可比矩阵为
(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_i
。 令u = [w_1, ..., w_n]'
和v = [1, ..., 1]'
。 雅可比行列式可以写成J = A + u*v'
。 由Sherman-Morrison公式给出逆
A^-1*u*v'*A^-1
J^-1 = (A + u*v')^-1 = A^-1 - -------------- .
1 + v'*A^-1*u
对于牛顿步骤,我们需要为给定的y
计算J^-1*y
y
。 使用上述公式,可以在时间O(n)
直接完成此操作。 如果有机会,我会添加更多细节。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.