复杂网络实验3:BA模型(matlab)

一.思路

1.首先确定BA模型中最重要的4个参数

m_original:未增长前的网络节点个数

m_add:每次引入新节点时 新生成的边数

m_after_growth:增长后的网络规模

pp:初始网络节点的连接选择

pp=1 节点均孤立  pp=2 节点间构成完全图  pp=3 随机连接一些边(随机图)

代码中这些参数都在最前面给出,可以通过修改代码来修改模型

2.在100*100的空间中生成m_original个点

3.通过pp值,初始化邻接矩阵A

4.最后生成节点,每个节点和之前m_add个节点相连

网络科学导论的BA模型没有考虑孤立节点,但是我感觉孤立节点也应该有几率被连接吧,总得给人家一点机会吧

不考虑孤立节点,那么一个点的连接概率按照该点的度数/总度数可以得到,因为不是孤立节点就有连边,就有度数,就有机会能够连接

但是考虑孤立节点,没有度数,再按上方的公式给孤立节点分配连接概率,是不妥的

这里考虑的模型是我思考出的存在孤立节点的BA模型的一个解决方案

这里有三个值得讨论的点

①.连接概率的设置

首先考虑到稀疏图中这样的场景,一共10个点,只有一条边,也就是只有两个点度数为1,其余8个点度数都是0

这个时候,你如果用上方的公式:点度数/总度数 来分配概率,那么这8个点都没机会连接,其余两个点的连接概率是1/2

这显然不合理,因为,这些边其实相差不大,甚至可以说基本都一样,应该都有机会能够连接。

这里我想出的策略是

每个点的度数:1+原度数

总度数为:原来总度数+总点数(每个点多加一个点数)

这样每个孤立点也有机会进行连接,度数越大连接概率也越大,不影响优先连接机制

 

②.连接概率存在的情况下,怎么做到随机连边

不是说你概率越大,我就连接,这里还是使用一个随机数的方法

复杂网络实验3:BA模型(matlab)_第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开始,每一个时间步系统中的节点度是不断增加的。

 

二.代码+解析

1.第一部分,四个参数

m_original=100;                   //未增长前网络节点个数m_original
m_add=3;                             //每次添加一个点增加的边数m_add
m_after_growth=1000;         //增长后的网络规模m_after_growth
pp=1;                                   

 

2.得到m_original个点的横纵坐标(初始网络的横纵坐标)

x=100*rand(1,m_original);  
y=100*rand(1,m_original);

rand(1,n)是生成一行n列的列向量,其中每个数的值是0-1,再乘上100,相当于把点分布到100*100的二维空间中

 

3.通过pp值得到初始网络(初始邻接矩阵A)的状态

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

4.生成增加的节点和边

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()方法,有下方测试帮助理解

复杂网络实验3:BA模型(matlab)_第2张图片
    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个点
之后再慢慢增大网络规模进行测试,验证是否每增加一个点就能有这么多条边

最后设置

得到的图像如下

 

你可能感兴趣的:(复杂网络实验)