m_original:未增长前的网络节点个数
m_add:每次引入新节点时 新生成的边数
m_after_growth:增长后的网络规模
pp:初始网络节点的连接选择
pp=1 节点均孤立 pp=2 节点间构成完全图 pp=3 随机连接一些边(随机图)
代码中这些参数都在最前面给出,可以通过修改代码来修改模型
网络科学导论的BA模型没有考虑孤立节点,但是我感觉孤立节点也应该有几率被连接吧,总得给人家一点机会吧
不考虑孤立节点,那么一个点的连接概率按照该点的度数/总度数可以得到,因为不是孤立节点就有连边,就有度数,就有机会能够连接
但是考虑孤立节点,没有度数,再按上方的公式给孤立节点分配连接概率,是不妥的
这里考虑的模型是我思考出的存在孤立节点的BA模型的一个解决方案
这里有三个值得讨论的点
①.连接概率的设置
首先考虑到稀疏图中这样的场景,一共10个点,只有一条边,也就是只有两个点度数为1,其余8个点度数都是0
这个时候,你如果用上方的公式:点度数/总度数 来分配概率,那么这8个点都没机会连接,其余两个点的连接概率是1/2
这显然不合理,因为,这些边其实相差不大,甚至可以说基本都一样,应该都有机会能够连接。
这里我想出的策略是
每个点的度数:1+原度数
总度数为:原来总度数+总点数(每个点多加一个点数)
这样每个孤立点也有机会进行连接,度数越大连接概率也越大,不影响优先连接机制
②.连接概率存在的情况下,怎么做到随机连边
不是说你概率越大,我就连接,这里还是使用一个随机数的方法
如上图所示,一共ABCDE5个点,A的连接概率体现在0-A这一个区间,也就是A占据了0-A,说明A的连接概率一般
D的连接概率体现在C-D这个区间,也就是D占据了C-D,说明D的连接概率最大
那么我们怎么做到用上面这样的策略达到目的呢?
概率叠加
假设A的连接概率为0.1,B为0.1,C为0.2,D为0.4,E为0.2
那么我们让A就是0.1,B在0.1+0.1=0.2,C在0.1+0.1+0.2=0.4,以此类推
然后每次要选一个点进行连接的时候,取一个0-1之间的随机数,看掉落在这5个区间中的哪一个,然后取这个区间的右端端点所代表的节点进行连接,因为这个区间是他的主场(之前说过哪个区间被哪个节点占据)
③怎么保证每次增加一个节点就增加m_add条边?怎么保证不重复连接
这里我在网上的模型中没找到,我使用了visit数组的概念
当你这个节点已经连接过,那么visit数组值1,下次分配连接概率置0
当然计算总度数的时候这个点的度数就不考虑了
重新给每个点分配一遍概率,进行概率叠加,再进行连接
因为连接过的点连接概率置0,所以不会重复连接,也能够起到随机连接,优先连接的目的
附:模型设定
初始状态有个节点
增长原则:每次加入一个节点i (加入时间记为), 每个节点的加入带来m条边,2m个度的增加
其中老节点分到的度数是m,新加入的那一个节点分到的度数为m
那么到时间t的时候,网络的总节点数是,网络的总度数为。
优先链接原则:每一次从m条边中占有一条边的概率正比于节点的度
那么显然,加入的越早(越小)越容易获得更多的链接数。
从时间0开始,每一个时间步系统中的节点度是不断增加的。
m_original=100; //未增长前网络节点个数m_original
m_add=3; //每次添加一个点增加的边数m_add
m_after_growth=1000; //增长后的网络规模m_after_growth
pp=1;
x=100*rand(1,m_original);
y=100*rand(1,m_original);
rand(1,n)是生成一行n列的列向量,其中每个数的值是0-1,再乘上100,相当于把点分布到100*100的二维空间中
A=zeros(m_original); //初始化邻接矩阵A为全0矩阵
switch pp //通过选择pp,确定A的初始状态
case 1 //节点均孤立
A=zeros(m_original);
case 2 //完全图
A=ones(m_original);
case 3 //随机图
for i=1:m_original
for j=i+1:m_original //操纵上半角矩阵
p=rand(1,1); //生成0-1随机数
if p>0.5 //以1/2的概率生成边
A(i,j)=1;
A(j,i)=1;
end
end
end
end
for k=m_original+1:m_after_growth //一共生成m_after_growth-m_original+1个节点
M=k-1; //当前要生成第K个节点,那么针对的图的规模就是k-1
p=zeros(1,M); //初始化每个点的连接概率为0
x_now=100*rand(1,1); //随机生成第K个节点的坐标
y_now=100*rand(1,1);
x(k)=x_now;
y(k)=y_now;
for i=1:M
p(i)=(length(find(A(i,:)==1))+1)/(length(find(A==1))+M);
end //这里就是前面说的修正孤立节点连接概率为0的方法
p //不加封号的都是为了在控制台显示出来,看看p的生成情况
pp=cumsum(p); //这里就是上面说的叠加概率
pp
备注:对于cumsum()方法,有下方测试帮助理解
visit=zeros(1,M); //初始化访问数组为全0数组(1行M列)
for i=1:m_add //开始生成m_add条边
random_data=rand(1,1);
random_data
aa=find(pp>=random_data); jj=aa(1); //通过上方介绍的叠加概率+随机数的方法,得到随机连边
备注:find函数返回括号内“满足条件的pp的数组的下标”的数组,jj取这个数组的第一个元素,对应占领这块区域的点
A(k,jj)=1;
A(jj,k)=1;
visit(jj)=1; //标记访问
visit //显示访问情况
degree=zeros(1,M); //给出度数组来记录变化后的度值,以达到访问过度数假装变成0的目的
total_degree=0; //总度数
for ii=1:M
if visit(ii)==1
p(ii)=0;
degree(ii)=0;
else
degree(ii)=length(A(i,:)==1)+1; //如果访问过度数为0,没有就照原来的方法
end
total_degree=total_degree+degree(ii); //总度数计算
end
for iii=1:M
p(iii)=degree(iii)/total_degree; //新一轮的p数组计算
end
p
pp=cumsum(p); //新一轮的叠加概率计算
pp
end
end
A
plot(x,y,'ro','MarkerEdgeColor','g','MarkerFaceColor','r','MarkerSize',8); //画出点
hold on;
for i=1:m_after_growth
for j=i+1:m_after_growth //按邻接矩阵上三角矩阵画出连线
if A(i,j)~=0 //~=0是不等于0的意思,就是有边,就画出来
plot([x(i),x(j)],[y(i),y(j)],'linewidth',1.2);
end
end
end
axis equal; //横纵坐标相等
hold off;
m_original=10;
m_add=4;
m_after_growth=11;
pp=1;
x=100*rand(1,m_original);
y=100*rand(1,m_original);
A=zeros(m_original);
switch pp
case 1
A=zeros(m_original);
case 2
A=ones(m_original);
case 3
for i=1:m_original
for j=i+1:m_original
p=rand(1,1);
if p>0.5
A(i,j)=1;
A(j,i)=1;
end
end
end
end
for k=m_original+1:m_after_growth
M=k-1;
p=zeros(1,M);
x_now=100*rand(1,1);
y_now=100*rand(1,1);
x(k)=x_now;
y(k)=y_now;
for i=1:M
p(i)=(length(find(A(i,:)==1))+1)/(length(find(A==1))+M);
end
p
pp=cumsum(p);
pp
visit=zeros(1,M);
for i=1:m_add
random_data=rand(1,1);
random_data
aa=find(pp>=random_data); jj=aa(1);
A(k,jj)=1;
A(jj,k)=1;
visit(jj)=1;
visit
degree=zeros(1,M);
total_degree=0;
for ii=1:M
if visit(ii)==1
p(ii)=0;
degree(ii)=0;
else
degree(ii)=length(A(i,:)==1)+1;
end
total_degree=total_degree+degree(ii);
end
for iii=1:M
p(iii)=degree(iii)/total_degree;
end
p
pp=cumsum(p);
pp
end
end
A
plot(x,y,'ro','MarkerEdgeColor','g','MarkerFaceColor','r','MarkerSize',8);
hold on;
for i=1:m_after_growth
for j=i+1:m_after_growth
if A(i,j)~=0
plot([x(i),x(j)],[y(i),y(j)],'linewidth',1.2);
end
end
end
axis equal;
hold off;
为了有直观的体验,可以把pp设置为1,即完全孤立图
初始点数可以设置成10,增长后的规模可以设置成11,每次连接4个点
之后再慢慢增大网络规模进行测试,验证是否每增加一个点就能有这么多条边
最后设置
得到的图像如下