模拟幂律分布,每个时间步长增加一个点,从两个点开始,度高(即k大)的点优先获得新连接,即一个度为的节点,获得连接的概率为
这样模拟下去,度分布满足
在时,有
实际模拟时,当时,有
编程的一些思路
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;
}