模拟幂律分布(附C语言代码)

模拟幂律分布,每个时间步长增加一个点,从两个点开始,度高(即k大)的点优先获得新连接,即一个度为的节点,获得连接的概率为

\pi(k_i)=\frac{k_i}{\sum_j k_j}

 这样模拟下去,度分布满足

p(k)=\frac{2m}{k(k+1)(k+2)}

N\sim\infty时,有p(k)\sim k^{-3}

实际模拟时,当N=10^6时,有p(k)\sim k^{-2.79}

编程的一些思路

1、int sites[N]

sites[ii]=0表示该点还未产生,sites[ii]=1表示该点已产生

2、link[N][N]

记录两节点之间的连接

link[ii][jj]=0

ii、jj这两个节点之间不能连接(一般指自己和自己不能连接)

link[ii][jj]=1

ii、jj这两个节点之间已有连接

link[ii][jj]=N

ii、jj这两个节点之间还未连接,可以连接

3、利用随机投点法选择和谁连接

如图所示,sumkk[ii]表示前ii个节点的度的总和,在0-sumkk[N]之间投点,落到哪个区间,就与该区间右端点代表的节点连接,这样可以保证一个节点获得连接的概率与它的度成正比。

模拟结果

 

源代码(C语言)

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>

#define N 10000//节点数目


int main(){
     static int sites[N];//记录节点是否已经产生
     static int kk[N];//记录节点的度
     static int link[N][N];//记录两节点之间的连接
     static int sumkk[N];//记录前ii个节点的度的总和,方便进行随机投点决定新加入的点与哪个点连接
     static int countnum[N];//计数:记录连接度为ii的节点个数

     int temp_mm=0;
     for (int ii=0;ii<N;ii++){
         sites[ii]=0;
         kk[ii]=0;
         sumkk[ii]=0;
      }//sites[ii]=0表示该点不存在,sites[ii]=1表示该点存在
     for(int ii=0;ii<N;ii++){
                     for(int jj=0;jj<N;jj++){
                        link[ii][jj]=N;//初始化为N,表示未连接
                     }link[ii][ii]=0;//初始化为0,表示自己与自己不可以连接
                  }
                  sites[0]=1;kk[0]=1;

                   srand((unsigned)time(NULL));
     for(int jj=1;jj<N;jj++){
             sites[jj]=1;
             sumkk[0]=kk[0];
            for(int ii=1;ii<N;ii++){
               sumkk[ii]=sumkk[ii-1]+kk[ii];
            }

            int true=1;
            while(true){
               double temp=sumkk[N-1]*rand()/(RAND_MAX*1.0);
                  if(temp<=sumkk[0]) {
                        temp_mm=0;
                  }
                  else{
                     for(int mm=1;mm<N;mm++){
                     if((temp>sumkk[mm-1])&&(temp<=sumkk[mm])){
                        temp_mm=mm;
                        break;
                     }}
                  }

                  if(link[temp_mm][jj]==N){//两点可以连接的前提是它们未连接,即link不为1;且它们可以连接,link不为0
                     link[temp_mm][jj]=1;
                     link[jj][temp_mm]=1;
                     kk[jj]=kk[jj]+1;
                     kk[temp_mm]=kk[temp_mm]+1;
                     true=0;//成功找到连接,可以退出while循环,否则将继续循环找连接
                  }
            }

     }
      FILE* fp = fopen("kk.csv", "w");
      for(int ii=0;ii<N;ii++){
          fprintf(fp,"%d  %d\n",ii,kk[ii]);
      }
      for(int ii=0;ii<N;ii++){
         countnum[kk[ii]]++;
      }
      FILE* fp2 = fopen("countnum.csv", "w");
      for(int ii=0;ii<N;ii++){
          fprintf(fp2,"%d  %d\n",ii,countnum[ii]);
      }
      fclose(fp);
      fclose(fp2);

     return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值