分享

BA无标度网络模型构造算法

 昵称41280102 2017-09-18

 BA无边度网络模型构造算法

(1)增长:从一个具有 m_0 个节点的联通网络开始,每次引入一个新的节点, 并且连到 m 个已经存在的节点上,这里 m <= m_0。

(2)优先连接:一个新的节点与一个已经存在的节点 i 相连的概率 w 与节点 i 的度 k_i 之间的关系为 w = k_i / ( k_1 + k_2 + k_3 + ... + k_n ),其中n为网络中的节点的总个数。


特别的说明下代码中涉及到结构体Node的作用和思路:

三个数据域:

               (1) degree:表示节点的度
               (2) weight:表示被选择的概率,即 w_i = k_i / ( k_1 + k_2 + ... + k_n )
               (3) probabilityDistribution: 给出每一个节点的概率分布,作用是通过产生0~1之间的随机数来做出决策。
               为什么在有了weight的情况下还需要用probabilityDistribution?
               example: 假设在一个网络中一共有5个节点,每个节点的度如下: d_1 = 4,   d_2 = 1,   d_3 = 2,   d_4 = 2,   d_5 = 1.
               那么可以计算出每个节点的weight如下: w_1 = 0.4, w_2 = 0.1, w_3 = 0.2, w_4 = 0.2, w_5 = 0.1
               也就是说, 当有一个新的节点出现时候,它连接到节点1的概率为0.4,连接到节点2的概率为0.1, ...
               可以用下图来表示:

                

               这个时候,这个新的节点要选择已有网络中的那个节点连接是随机的,但是和这些已有节点的度是成正比的,度愈大的节点越有可能被连接,此时,由系统产生一个 0~1 之间的随机数,比如0.6,那么则选择新的节点与节点 3 相连。



代码实

  1. #include<stdio.h>  
  2. #include<stdlib.h>  
  3. #include<time.h>  
  4. #include<string.h>  
  5. #include "for_plot.c"  
  6.   
  7. int NETWORK_SIZE, M, M_0;  
  8.   
  9. struct Node;  
  10. typedef struct Node* NodePtr;  
  11. typedef struct Node{  
  12.     int degree;  
  13.     double weight;  
  14.     double probabilityDistribution;  
  15. }Node;  
  16.   
  17. Node* decisionMaking;  
  18. int** adjacentMatrix;  
  19. int* initalNetwork;  
  20.   
  21. void initial();  
  22. void initalNetwork_M0_connected();  
  23. void updateDecisionMakingData();  
  24. void generateFreeScaleNetwork();  
  25. void showAdjacentMatrix();  
  26. void writeDataToFile();  
  27.   
  28. int main(int argc, char** argv)  
  29. {  
  30.     if( 4 != argc )  
  31.     {  
  32.         printf("this algorithm requires 4 user-specify parameters\n");  
  33.         printf("\t1.the size of network\n");  
  34.         printf("\t2.the initial size of network\n");  
  35.         printf("\t1.the size of \n");  
  36.         printf("\texample: \"a.exe 100 3 3\"\n");  
  37.         exit(0);  
  38.     }  
  39.     NETWORK_SIZE = atoi(argv[1]);  
  40.     M_0 = atoi(argv[2]);  
  41.     M = atoi(argv[3]);  
  42.     srand((unsigned)time(NULL));  
  43.     initial();  
  44.     initalNetwork_M0_connected();  
  45.     generateFreeScaleNetwork();  
  46.     writeDataToFile();  
  47.     showAdjacentMatrix();  
  48.   
  49.     write2file(adjacentMatrix, NETWORK_SIZE, "freeScale_edges.data");  
  50.     return 0;  
  51. }  
  52.   
  53. void initial()  
  54. {  
  55.     if( !(decisionMaking = (NodePtr)malloc(sizeof(Node) * (NETWORK_SIZE + 1))) )  
  56.     {  
  57.         printf("decisionMaking* malloc error\n");  
  58.         exit(0);  
  59.     }  
  60.     if( !(adjacentMatrix = (int**)malloc(sizeof(int*) * (NETWORK_SIZE + 1))) )  
  61.     {  
  62.         printf("adjacentMatrix** malloc error\n");  
  63.         exit(0);  
  64.     }  
  65.     int i;  
  66.     for( i = 1; i <= NETWORK_SIZE; i++ )  
  67.     {  
  68.         if( !(adjacentMatrix[i] = (int*)malloc(sizeof(int) * (NETWORK_SIZE + 1))) )  
  69.         {  
  70.             printf("adjacentMatrix[%d]* malloc error\n", i);  
  71.             exit(0);  
  72.         }  
  73.     }  
  74.     if( !(initalNetwork = (int*)malloc(sizeof(int) * (M_0 + 1))) )  
  75.     {  
  76.         printf("initalNetwork* malloc error\n");  
  77.         exit(0);  
  78.     }  
  79. }  
  80.   
  81. /* 
  82.  * 初始化:在NETWORK_SIZE中随机选择M_0个节点构成连通的网络。 
  83.  * */  
  84. void initalNetwork_M0_connected(){  
  85.     int i, j, randomFirst, randomSecond;  
  86. <span style="white-space:pre">  </span>for( i = 1; i <= NETWORK_SIZE; i++ )  
  87.         for( j = 1; j <= NETWORK_SIZE; j++ )  
  88.             adjacentMatrix[i][j] = 0;  
  89.     // 随机产生M_0个节点  
  90.     for( i = 1; i <= M_0; i++ )  
  91.     {  
  92.         initalNetwork[i] = rand() % NETWORK_SIZE + 1;  
  93.         for( j = 1; j < i; j++ )  
  94.             if( initalNetwork[i] == initalNetwork[j] )  
  95.             {  
  96.                 i--;  
  97.                 break;  
  98.             }  
  99.     }  
  100.     for( i = 1; i < M_0; i++ )  
  101.         adjacentMatrix[initalNetwork[i]][initalNetwork[i+1]] = adjacentMatrix[initalNetwork[i+1]][initalNetwork[i]] = 1;  
  102.     adjacentMatrix[initalNetwork[M_0]][initalNetwork[1]] = adjacentMatrix[initalNetwork[1]][initalNetwork[M_0]] = 1;  
  103.   
  104.     //showAdjacentMatrix();  
  105.     updateDecisionMakingData();  
  106. }  
  107.   
  108. /* 
  109.  * 通过adjacentMatrix更新decisionMaking数组 
  110.  * */  
  111. void updateDecisionMakingData(){  
  112.     int i, j, totalDegree = 0;  
  113.   
  114.     for( i = 1; i <= NETWORK_SIZE; i++ )  
  115.         decisionMaking[i].degree = 0;  
  116.     for( i = 1; i <= NETWORK_SIZE; i++ )  
  117.         for( j = 1; j <= NETWORK_SIZE; j++ )  
  118.             decisionMaking[i].degree += adjacentMatrix[i][j];  
  119.     for( i = 1; i <= NETWORK_SIZE; i++ )  
  120.         totalDegree += decisionMaking[i].degree;  
  121.     //printf("\n%d\n", totalDegree);  
  122.     for( i = 1; i <= NETWORK_SIZE; i++ )  
  123.         decisionMaking[i].weight = decisionMaking[i].degree/(double)totalDegree;  
  124.     decisionMaking[1].probabilityDistribution = decisionMaking[1].weight;  
  125.     for( i = 2; i <= NETWORK_SIZE; i++ )  
  126.         decisionMaking[i].probabilityDistribution = decisionMaking[i - 1].probabilityDistribution + decisionMaking[i].weight;  
  127. }  
  128.   
  129. /* 
  130.  * 构造BA无标度网络模型 
  131.  * */  
  132. void generateFreeScaleNetwork(){  
  133.     int i, k, j = 1, length = 0;  
  134.     int random_auxiliary_old[NETWORK_SIZE + 1];  
  135.     int random_auxiliary[NETWORK_SIZE + 1 - M_0];  
  136.   
  137.     /* 
  138.      * 要保证每次引入一个<新的>的节点,所以要随机选择不重复的节点加入,并且把初始网络中的M_0个节点先删除 
  139.      * */  
  140.     for( i = 1; i <= NETWORK_SIZE; i++ )  
  141.         random_auxiliary_old[i] = i;  
  142.       
  143.     for( i = 1; i <= M_0; i++ )  
  144.         random_auxiliary_old[initalNetwork[i]] = 0;  
  145.     for( i = 1; i <= NETWORK_SIZE; i++ )  
  146.         if( random_auxiliary_old[i] != 0 )  
  147.             random_auxiliary[j++] = random_auxiliary_old[i];  
  148.       
  149.     /* 
  150.      * 添加新的节点构造无标度网络 
  151.      * */  
  152.     int new_node_index, new_node_value;  
  153.     double random_decision = 0.0;  
  154.     int targetNode;                 //表示找到的已经在网络中的将要连接的节点  
  155.     length = NETWORK_SIZE - M_0;  
  156.     int flag;  
  157.     for( i = 1; i <= NETWORK_SIZE - M_0; i++ )  
  158.     {  
  159.         new_node_index = rand() % length + 1;  
  160.         new_node_value = random_auxiliary[new_node_index];  
  161.         random_auxiliary[new_node_index] = random_auxiliary[length--];  
  162.         for( j = 1; j <= M; j++ )        //根据概率连接到已存在网络中的M个节点,不可以重边,不可以自连。  
  163.         {  
  164.             flag = 0;  
  165.             random_decision = (rand()%1000)/(double)1000;  
  166.             for( k = 1; k <= NETWORK_SIZE; k++ )  
  167.             {  
  168.                 // 从第一个节点到最后一个节点比较probabilityDistribution和random_desction的大小,  
  169.                 // 由于probabilityDistribution是有序的,所以可以使用一些高级的算法来提高查找的效率.  
  170.                 if( decisionMaking[k].probabilityDistribution >= random_decision && decisionMaking[k].degree != 0 && adjacentMatrix[new_node_value][k] != 1 )  
  171.                 {     
  172.                     /* 
  173.                      * 
  174.                      *  如何按照可能性大小来选择要连哪一个点: 
  175.                      *         选择的已经在网络中的点是:随机产生的0-1之间的概率p,找这样的点: 
  176.                      *         它的累加概率(probabilityDistribution)是大于p的最小的值所对应的点。 
  177.                      * 
  178.                      */  
  179.                     targetNode = k;   
  180.                     flag = 1;  
  181.                     break;  
  182.                 }  
  183.             }  
  184.             if( flag == 0 )   
  185.                     /* 
  186.                      * 之前少考虑了这种情况,因为总要选择一个网络中的点接入。但是当产生了比较大的随机概率p,可能 
  187.                      * 在他后面(按probabilityDistribution来说)没有可选的点(要么选择过了,要么不在网络中),则重新开始 
  188.                      */  
  189.             {  
  190.                 for( k = 1; k <= NETWORK_SIZE; k++ )  
  191.                 {  
  192.                     if( decisionMaking[k].degree != 0 && adjacentMatrix[new_node_value][k] != 1 )  
  193.                     {  
  194.                         targetNode = k;  
  195.                         break;  
  196.                     }  
  197.                 }  
  198.             }  
  199.             //printf(" target node is %d\n", targetNode);  
  200.             adjacentMatrix[new_node_value][targetNode] = adjacentMatrix[targetNode][new_node_value] = 1;  
  201.         }  
  202.         updateDecisionMakingData();     //else新选的加入节点和已有网络中的M个边都链接后再更新  
  203.     }  
  204. }  
  205.   
  206. void showAdjacentMatrix(){  
  207.     int i, j;  
  208.     int numberOfEage = 0;  
  209.     printf("\tshow adjacentMatrix\n");  
  210.     for( i = 1; i <= NETWORK_SIZE; i++ )  
  211.     {  
  212.         for( j = 1; j <= NETWORK_SIZE; j++ )  
  213.         {  
  214.             printf("%d", adjacentMatrix[i][j]);  
  215.             if( adjacentMatrix[i][j] == 1 )  
  216.                 numberOfEage++;  
  217.         }  
  218.         printf("\n");  
  219.     }  
  220.     printf("the number of eage is %d\n", numberOfEage/2);  
  221. }  
  222.   
  223. void writeDataToFile(){  
  224.     FILE* fout;  
  225.     if( NULL == (fout = fopen("freeScaleNetwork.data", "w")))  
  226.     {  
  227.         printf("open file(freeScaleNetwork) error!\n");  
  228.         exit(0);  
  229.     }  
  230.     int i;  
  231.     int j;  
  232.     for( i = 1; i <= NETWORK_SIZE; i++ )  
  233.     {  
  234.         for( j = 1; j <= NETWORK_SIZE; j++ )  
  235.             fprintf(fout, "%d ", adjacentMatrix[i][j]);  
  236.         fprintf(fout, "\n");  
  237.     }  
  238. }  

以下分别是该算法产生的BA网络的可视化图以及度分布。





for_plot.c文件

  1. <span style="font-family:Courier New;">/* 
  2.  * 将给定的网络@adjacentMatrix(节点的个数为@size)中的所有的连边以有序对的 
  3.  * 形式输出到文件@out_filename中,每一对使用','隔开,方便python处理。 
  4.  * 该函数被所有产生网络结构的函数(generateRandomNetwork.c, 
  5.  * generateSmallNetwork.c和generateFreeScale.c)调用 
  6.  * */  
  7. void write2file(int** adjacentMatrix, int size, char* out_filename)  
  8. {  
  9.     int i, j;  
  10.     FILE* fout;  
  11.     if( NULL == (fout = fopen(out_filename,"w")) )  
  12.     {  
  13.         printf("%s cann't open!\n", out_filename);  
  14.         exit(0);  
  15.     }  
  16.     for( i = 1; i <= size; i++ )  
  17.     {  
  18.         for( j = i + 1; j <= size; j++ )  
  19.         {  
  20.             if( adjacentMatrix[i][j] )  
  21.             {  
  22.                 fprintf(fout, "%d %d\n", i, j);   
  23.             }  
  24.         }  
  25.     }  
  26.     fclose(fout);  
  27. }  
  28. </span>  

计算网络中节点的度分布的代码(网络大小即宏NETWORK_SIZE要按照实际网络的大小修改)

  1. <span style="font-family:Courier New;">#include<stdio.h>  
  2. #include<stdlib.h>  
  3. #include<string.h>  
  4.   
  5. #define NETWORK_SIZE    20000  
  6.   
  7. char targetfilename[200];  
  8. char distribution[200];  
  9. int adjacentMatrix[NETWORK_SIZE + 1][NETWORK_SIZE + 1];  
  10. int degree[NETWORK_SIZE + 1];       //统计每一个节点的度  
  11. double statistic[NETWORK_SIZE];     //用来统计,statistic[2] = 4,表示度为2的点有4个,有度为0的,  
  12.                     //不可能有度为NETWORK_SIZE的点  
  13.   
  14. void readDataFromFile();  
  15. void calculateDegreeDistribution();  
  16. void writeDataToFile();  
  17.   
  18. int main(int argc, char* argv[]){  
  19.     if( argc != 2 )  
  20.     {  
  21.         printf("need a parameter to indicate the network data name\n");  
  22.         printf("for example: smallworldnetwork.data\n");  
  23.         exit(0);  
  24.     }  
  25.     strcat(targetfilename, argv[1]);  
  26.     printf("%s\n", targetfilename);  
  27.   
  28.     readDataFromFile();  
  29.     calculateDegreeDistribution();  
  30.     writeDataToFile();  
  31.     return 0;  
  32. }  
  33.   
  34. /* 
  35.  * 读入网络的结构 
  36.  * */  
  37. void readDataFromFile(){  
  38.     FILE* fread;  
  39.     if( NULL == (fread = fopen(targetfilename, "r")))  
  40.     {  
  41.         printf("open file(%s) error!\n");  
  42.         exit(0);  
  43.     }  
  44.     int i;  
  45.     int j;  
  46.     for( i = 1; i <= NETWORK_SIZE; i++ ){  
  47.         for( j = 1; j <= NETWORK_SIZE; j++ )  
  48.         {  
  49.             if( 1 != fscanf(fread, "%d ", &adjacentMatrix[i][j]))  
  50.             {  
  51.                 printf("fscanf error: file: %s\t(%d, %d)\n", targetfilename, i, j);  
  52.                 exit(0);  
  53.             }  
  54.         }  
  55.     }  
  56.     fclose(fread);  
  57. }  
  58.   
  59. void calculateDegreeDistribution(){  
  60.     int i;  
  61.     int j;  
  62.     double averageDegree = 0.0;  
  63.     for( i = 1; i <= NETWORK_SIZE; i++ )  
  64.         for( j = 1; j <= NETWORK_SIZE; j++ )  
  65.             degree[i] = degree[i] + adjacentMatrix[i][j];  
  66.     for( i = 1; i <= NETWORK_SIZE; i++ )  
  67.         averageDegree += degree[i];  
  68.     printf("%f----<k> = %f\n", averageDegree,averageDegree/NETWORK_SIZE);  
  69.   
  70.     for( i = 1; i <= NETWORK_SIZE; i++ )  
  71.         statistic[degree[i]]++;  
  72.   
  73.     double indentify = 0.0;  
  74.     for( i = 0; i < NETWORK_SIZE; i++ )  
  75.     {  
  76.         statistic[i] = statistic[i]/(double)(NETWORK_SIZE);  
  77.         indentify += statistic[i];  
  78.     }  
  79.     printf("\nindentify: %f\n", indentify);  
  80. }  
  81.   
  82. /* 
  83.  * 将网络的度分布写入文件 distributionOf@targetfilename 
  84.  * */  
  85. void writeDataToFile(){  
  86.     FILE* fwrite;  
  87.     strcat(distribution, "distributionOf");  
  88.     strcat(distribution, targetfilename);  
  89.     printf("%s\n", distribution);  
  90.     if( NULL == (fwrite = fopen(distribution, "w")))  
  91.     {  
  92.         printf("open file(%s) error!\n", distribution);  
  93.         exit(0);  
  94.     }  
  95.     int i;  
  96.     for( i = 0; i < NETWORK_SIZE; i++ )  
  97.     {  
  98.         fprintf(fwrite, "%d %f\n",i, statistic[i]);  
  99.     }  
  100.     fclose(fwrite);  
  101. }  
  102. </span>  
可视化网络(即绘制如上的网络图的代码)的代码(需要安装igraph)
[python] view plain copy
  1. # -*- coding:UTF8 -*-  
  2.   
  3. from igraph import *  
  4.   
  5. edges = []  
  6.   
  7. # 从文件@filename中读入网络的边  
  8. def read_edges(filename):  
  9.     fin = open(filename, "r")  
  10.     for line in fin:  
  11.         line = line.strip()  
  12.         line = line.split(" ")  
  13.         edges.append((int(line[0]) - 1, int(line[1]) - 1))  
  14.   
  15. def plot_network(size):  
  16.     g = Graph()  
  17.     g.add_vertices(size)  
  18.     g.add_edges(edges)  
  19.     layout = g.layout('kk')  
  20.     visual_style = {}  
  21.     visual_style['layout'] = layout  
  22.     visual_style['bbox'] = (500,500)  
  23.     visual_style['vertex_label'] = [(label + 1) for label in range(size)]  
  24.     visual_style['vertex_color'] = 'white'  
  25.     visual_style['vertex_size'] = g.degree()  # 节点的大小与度成正比  
  26.     # visual_style['vertex_size'] = 20    # 所有节点的大小都是相同的:20  
  27.     plot(g, **visual_style)  
  28.   
  29. def main(size):  
  30.     read_edges("random_edge.data")  #包含网络的连边的信息的文件的名称  
  31.     plot_network(size)  
  32.   
  33. main(10)    # 这里的10需要更改为网络中的节点的个数  



    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多