WS小世界网络的建立及基本特征的求法

来源:互联网 发布:隐形富豪 知乎 编辑:程序博客网 时间:2024/06/06 11:41

WS小世界网络算是复杂网络的基本入门实验了,虽然基础,但是极其重要,里面包含了复杂网络这门学科的很多重要想法。首先,简单介绍一下WS小世界网络,就是具有很小的平均最短路径和很高的聚类系数的一种网络,通俗一点,就是模仿日常生活中人们之间的联系的一种网络,再通俗一点,大马路上任选两个不认识的人,你会发现,他俩只要通过四五个人介绍一下,就认识了,这四五个人,就是他俩的距离,叫做最短路径。另一个例子,Tom和Jack是好朋友,有一天他们聊天,突然发现,Mary是Tom的高中同学,是Jack的大学同学,缘分呐,这种缘分一量化,就叫聚类系数。

一般做这个实验,用1000个点模仿一千个人,从规则图(专业术语叫最近邻耦合网络)开始,经过随机化重连(有规定的重连规则)后,开始做分析(此时,有连线,代表认识,无连线,代表不认识)。

首先,你需要安装matlab(捂脸,看这篇文章的肯定知道的),然后,开始根据规则和公式敲代码了,代码全文如下

%小世界网络

function ws_worldnet(N,K);

tic;

%N=400;%随机节点数

%K=2;%左(右)最邻近节点数


%生成节点

%angle=0:2*pi/N:2*pi-2*pi/N;

%x=100*sin(angle);

%y=100*cos(angle);


%计算L0

B=zeros(N);%全0的n维矩阵

for i=1:N

    for j=i+1:i+K

        jj=j;

        if j>N

            jj=mod(j,N);

        end

        B(i,jj)=1;

        B(jj,i)=1;

    end

end

%计算L0 不需要断边重连 直接开始算节点间的最短路径

D=B;

for i=1:N

    for j=1:N

        if D(i,j)==0

            if i==j

                D(i,j)=0;

            else

                D(i,j)=inf;

            end

        end

    end

end

E=B;%矩阵E是做过变换的邻接矩阵,只用来计算聚类系数C0

for n=1:N

    for i=1:N

        for j=1:N

            if D(i,n)+D(n,j)<D(i,j)

                D(i,j)=D(i,n)+D(n,j);

            end

        end

    end

end

L0=sum(sum(D))/(N*(N-1));

%disp(D);



%计算聚类系数C0

Ci0=zeros(N,1);

for i=1:N

    aa=find(E(i,:)==1);%按行找矩阵的邻接节点

    if isempty(aa)

        Ci0(i)=0;%如果没有 那么节点i的邻居节点数为0

    else

        m1=length(aa);

        if m1==1

            Ci0(i)=0;%规定邻居节点数只有1个的话,该点的聚类系数为0(为1也是可以的)

        else

            B1=E(aa,aa);%特别注释1

            Ci0(i)=length(find(B1==1))/(m1*(m1-1));

        end

    end

end

C0=sum(Ci0)/N;

%disp(C0);



%生成邻接矩阵,模拟节点之间的连线

for x=1:14

    P(x)=1/(2^(x-1));

    for y=1:20

A=zeros(N);%全0的n维矩阵

for i=1:N

    for j=i+1:i+K

        jj=j;

        if j>N

            jj=mod(j,N);

        end

        A(i,jj)=1;

        A(jj,i)=1;

    end

end


%根据概率断边后重新连接(随机化重连)


for i=1:N

    for j=i+1:N

        if A(i,j)==1

            p1(y)=rand(1,1);

            if p1(y)<P(x)

                A(i,j)=0;A(j,i)=0;

                rand_point=unidrnd(N);

                while rand_point==i

                    rand_point=unidrnd(N);

                end

                A(i,rand_point)=1;

                A(rand_point,i)=1;

            end

        end

    end

end



%根据重连后的邻接矩阵,计算Ci

Ci0=zeros(N,1);

E=A;

for i=1:N

    aa=find(E(i,:)==1);%按行找矩阵的邻接节点

    if isempty(aa)

        Ci0(i)=0;%如果没有 那么节点i的邻居节点数为0

    else

        m1=length(aa);

        if m1==1

            Ci0(i)=0;%规定邻居节点数只有1个的话,该点的聚类系数为0(为1也是可以的)

        else

            B1=E(aa,aa);

            Ci0(i)=length(find(B1==1))/(m1*(m1-1));

        end

    end

end

Ci(y)=sum(Ci0)/N;%计算20次


%计算平均路径长度

%根据floyd算法求平均最短路径

%首先,将邻接矩阵变成做变换,点与点之间有线连接,距离记为1,没有线连接,距离记为inf,点自己到自己的距离记为0

D=A;

for i=1:N

    for j=1:N

        if D(i,j)==0

            if i==j

                D(i,j)=0;

            else

                D(i,j)=inf;

            end

        end

    end

end

% D(find(D==0))=inf;

% for i=1:N

%     D(i,i)=0;

% end

%disp(D);

for n=1:N%特别注释2

    for i=1:N

        for j=1:N

            if D(i,n)~=inf&&D(n,j)~=inf&&(D(i,n)+D(n,j)<D(i,j))

                D(i,j)=D(i,n)+D(n,j);

            end

        end

    end

end

%disp(D);

M(y)=sum(sum(D))/(N*(N-1));

    end

L(x)=sum(M)/20;

C(x)=sum(Ci)/20;

%disp(C);

%disp(M);

end

%disp(L0);

figure;

semilogx(P,L/L0,'rd','markersize',4);%画图函数

hold on;

semilogx(P,C/C0,'go','markersize',4);

hold on;

toc;

重要的该注释的已经注释的很清楚了,特地说三处地方,当时花了很长时间才搞明白,第一,取点是很有技巧的,不然得到的图像就很难看,一般都如我上文所示取点,每个概率做20次后算平均值;第二,上文特别注释1处,就是去掉该点所在行所在列,得到的邻接矩阵,也就是得到了与改点连接的点之间的连线的矩阵;第三,上文特别注释2处,弗洛伊德算法求最短路径,外层循环必须是中间节点的遍历,放到内层,会出错,原因的话,自己拿草稿纸画画就知道了

最后,结果大概像这个样子(PS:实验室工作站花了一个小时跑出来的。。。。。。)

原创粉丝点击