• 一百行写小世界网络和无标度网络


      曾经觉得能写很长的代码就是厉害的表现,随着学习的深入,对于好的代码有了更加深刻的认识,一个好的代码应该:

      1、可读性。好的代码不仅能让机器读懂,更要让看代码的人读懂----合理布局,逻辑清晰。

      2、充分发挥语言的优势,比如接下来的matlab矩阵化编程。

      3、占用尽可能小的内存,运行尽量快,输出结果尽量容易处理。并在此之间找到平衡。

      。。。。。

      需要说明的是,如果没有对复杂网络有基本的了解,下面的东西没有看下去的必要。关于小世界网络和无标度网络,可以参考Watts DJ和Strogatz SH的Collective dynamics of 'small-world' networks(NATURE)以及Barabasi AL和Albert R的 Emergence of scaling in random networks(SCIENCE)。

      之前,国庆期间曾经用了四百行代码(C语言)实现了无标度网络,之后又用一到两百行代码写完了小世界网络。现在看这些代码,确实受制于C语言语法的限制,所以写出来十分冗杂,而且不易理解。由于最近在学习matlab编程,所以尝试了一下,两个代码加起来竟然不到一百行。而且没有使用matlabBGL之类的工具。而且算法上由于语言变的更加自由,所以算法上也优化了不少(由后面的度分度图就可以看出来)

      此外,虽然matlab基于JVM,但是只要算法设计的好,还是可以完爆之前的C语言,关于无标度网络的博客中提到计算1000个节点需要35min,经过测试,这个matlab程序处理10000个节点的时间是38min,1000个节点是21.9s!新的程序时间复杂度O(N^2),N是节点数量(由于数据结构没有时间系统学习,时间复杂度可能说错了!)。

      最后,matlab可以对矩阵进行稀疏化处理,而无标度网络正是一个极其稀疏的网络,所以,借助稀疏化操作,使得matlab也能操作较大的矩阵。

    先贴上实现小世界网络的matlab代码:

     1 NodesNum = 1000;
     2 K = 10;
     3 p = 1;
     4 A = sparse(NodesNum, NodesNum);
     5 for i=1:K/2
     6     A = A + diag(ones(1, length(diag(A, i))), i);
     7 end
     8 A = sparse(A);
     9 for i=1:K/2
    10     A(i, (NodesNum-K/2+i):NodesNum) = 1;
    11 end
    12 A = A + A';
    13 for i=1:K/2
    14     P = rand(1,NodesNum);
    15     P = find(P <= p);
    16     for j=1:length(P)
    17         while true
    18             x = fix(rand()*NodesNum)+1;
    19             if A(x, P(j)) == 0
    20                 A(x, P(j)) = 1;
    21                 A(P(j), x) = 1;
    22                 break;
    23             end
    24         end
    25         
    26         if P(j) <= NodesNum-i
    27             A(NodesNum-i, P(j)) = 0;
    28             A(P(j), NodesNum-i) = 0;
    29         else
    30             A(P(j)-NodesNum+i, P(j)) = 0;
    31             A(P(j), P(j)-NodesNum+i) = 0;
    32         end
    33  
    34     end
    35 end
    36 clear i j P x
    37 B3 =A^3;
    38 B33 = B3(1:NodesNum+1:end);
    39 B2 = A^2;
    40 B22 = B2(1:NodesNum+1:end);
    41 c = B33./(B22.*(B22-1));
    42 c(isnan(c)) = 0;
    43 C = mean(c);
    44 clear B33 B3 B2 B22
    45 
    46 Paths = graphallshortestpaths(tril(A), 'directed', false);
    47 Paths = tril(Paths);
    48 L = sum(sum(Paths)) / nchoosek(NodesNum, 2);

    再贴上无标度网络实现的matlab代码

     1 tic
     2 m0 = 10;
     3 m = 5;
     4 NodesNum = 1000;
     5 A = sparse(NodesNum, NodesNum);
     6 A(1:m0,1:m0) = round(rand(m0));
     7 A = tril(A); 
     8 A = A+A';
     9 A = A - diag(diag(A));
    10 for i=m0+1:NodesNum
    11     Degree = sum(A(1:i-1,1:i-1));
    12     for j=2:i-1
    13         Degree(j) = Degree(j) + Degree(j-1);
    14     end
    15     LinksNum = 0;
    16     while LinksNum<m
    17         link = fix(rand()*Degree(i-1)+1);
    18         for j=1:i-2
    19             if link<=Degree(1) && A(i,1)==0
    20                 A(i,1) = 1;     
    21                 A(1,i) = 1;
    22                 LinksNum = LinksNum+1;
    23             elseif link>Degree(j) && link<=Degree(j+1) && A(i,j+1)==0
    24                 A(i,j+1) = 1;       A(j+1,i) = 1;
    25                 LinksNum = LinksNum+1;
    26             end
    27         end
    28     end
    29 end
    30 Degree = sum(A);
    31 list = unique(Degree);
    32 num = zeros(1,length(list));
    33 for i=1:length(list)
    34     num(i) = length(find(list(i)==Degree));
    35 end
    36 toc
    37 loglog(list,num ./ sum(num),'.','markersize',20)
    38 xlabel('k'),ylabel('P(k)')

    再贴一张小世界网络聚类系数和最短平均路径变化图(最短路径变化有点波动,看来算法还需优化)

    最后贴一张10000节点生成的matlab度分布对数坐标图,确实比之前的明显多了(算法改进立竿见影):

    2015-12-14

  • 相关阅读:
    分布式与云计算有什么区别?
    多线程学习笔记
    docker解决报错WARNING: IPv4 forwarding is disabled. Networking will not work.
    Docker问题解决:Error response from daemon: Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker.io: no such host
    docker学习笔记
    linux命令学习
    Xftp5提示要继续使用此程序,您必须应用最新的更新的解决方案
    Springboot学习笔记
    maven学习笔记
    Spring学习笔记(6)
  • 原文地址:https://www.cnblogs.com/zhaoyu1995/p/5046858.html
Copyright © 2020-2023  润新知