WS小世界模型构造算法:
(1)从规则图开始:给定一个含有N个节点的环状最近邻耦合网络,其中的每个节点都与它左右相邻的各K/2个节点相连,K为偶数是程序的输入参数。
(2)随机化重连:以概率p随机的重新连接网络中的原有的每一条边,即把每一条边的一个端点保持不变,另外一个端点改取网络中随机选择的另外的一个端点,其中规定不可以有自连和重边。
Note: p = 0对应于完全规则网络,p = 1对应于完全的随机网络。通过调整p的值可以实现从规则网络到随机网络的过渡。在具体的算法的实现时,可以把网络中的所有的节点编号为1,2,3,..N,对于每一个节点 i ,顺时针的选取与 i 相连的K/2条边中的每一条,边的一个端点仍然固定为i,以概率p随机的选取网络中的任一节点作为该边的另一端点。
代码实现
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include "for_plot.c"
int NETWORK_SIZE, K;
double P;
/*
* @NETWORK_SIZE: 网络的大小。
* @K: 初始的最近邻网络中的参数,每一个节点和它左右相邻的K/2个节点相连,K是偶数。
* @P: 以概率P绝对是否对边进行重连。
* */
int** adjacentMatrix;
void initial();
void generate_NearestNeighborCoupledNetwork();
void generateSmallWorld();
void writeDataToFile();
int main(int argc, char** argv)
{
if( 4 != argc )
{
printf("This algorithms requires 3 user-specified parameters\n");
printf("\t1.the size of network\n");
printf("\t2.the value of K\n");
printf("\t3.the vlaue of P\n");
printf("\texample: \"a.exe 100 6 0.3\n");
exit(0);
}
srand((unsigned)time(NULL));
NETWORK_SIZE = atoi(argv[1]);
K = atoi(argv[2]);
P = atof(argv[3]);
initial();
generate_NearestNeighborCoupledNetwork();
generateSmallWorld();
writeDataToFile();
write2file(adjacentMatrix, NETWORK_SIZE, "smallworld_edges.data");
return 0;
}
void initial()
{
if( !( adjacentMatrix = (int**)malloc(sizeof(int*) * (NETWORK_SIZE + 1))) )
{
printf("adjacentMatrix** malloc error");
exit(0);
}
int i;
for( i = 1; i <= NETWORK_SIZE; i++ )
{
if( !(adjacentMatrix[i] = (int*)malloc(sizeof(int) * (NETWORK_SIZE + 1))) )
{
printf("adjacentMatrix[i]* malloc error");
exit(0);
}
}
}
/*
* 首先产生最邻近藕合网络:每一个节点和他的左右各K/2个节点相连
* */
void generate_NearestNeighborCoupledNetwork(){
int i;
int j;
for( i = 1; i <= NETWORK_SIZE; i++ )
for( j = 1; j <= NETWORK_SIZE; j++ )
adjacentMatrix[i][j] = 0;
for( i = 1; i <= NETWORK_SIZE; i++ )
for( j = 1; j <= K/2; j++ )
if( i - j >= 1 && i + j <= NETWORK_SIZE )
adjacentMatrix[i][i - j] = adjacentMatrix[i][i + j] = 1;
else if( i - j < 1 )
adjacentMatrix[i][NETWORK_SIZE + i - j] = adjacentMatrix[i][i + j] = 1;
else if( i + j > NETWORK_SIZE )
adjacentMatrix[i][i + j - NETWORK_SIZE] = adjacentMatrix[i][i - j] = 1;
//test
/*
for( i = 1; i <= NETWORK_SIZE; i++ )
{
for( j = 1; j <= NETWORK_SIZE; j++ )
{
printf("%d ", adjacentMatrix[i][j]);
}
printf("\n");
}
*/
//test END
}
/*
* 构造WS小世界模型
* */
void generateSmallWorld(){
int i, j;
double isChange = 0.0; //随机产生的0~1之间的数,决定是否要对选择的边进行重连,当isChange < p时,进行重连
int re_connectRandomNode; //在决定了要重连某一条边时,随机的选择一个将要连接到的端点(不可以是本身,不可以是重边)
int hasEage[NETWORK_SIZE + 1]; //用于在选择另外一个节点进行重连的时候,判断是否重边,以及是否随机选择了自身
int number_changedEage = 0;
for( i = 1; i <= NETWORK_SIZE; i++ )
{
for( j = 1; j <= K/2; j++ )
{
//重连的边是:adjacentMatrix[i][i + j]; 或者: adjacentMatrix[i][i + j - NETWORK_SIZE];
isChange = (rand()%NETWORK_SIZE)/(double)NETWORK_SIZE;
//printf("(%d, %d)random probability is %f\n", i, i+j, isChange);
if( isChange < P ) //重连
{
while( 1 ) //随机选择一个端点:不可以产生自连和重边
{
re_connectRandomNode = (rand() % NETWORK_SIZE) + 1;
//printf("-->%d", re_connectRandomNode);
if( adjacentMatrix[i][re_connectRandomNode] == 0 && re_connectRandomNode != i )
break;
}
//printf("\n(%d, %d)----->(%d, %d)\n", i, i+j, i, re_connectRandomNode);
if( i + j <= NETWORK_SIZE )
adjacentMatrix[i][i + j] = adjacentMatrix[i + j][i] = 0;
else
adjacentMatrix[i][i + j - NETWORK_SIZE] = adjacentMatrix[i + j - NETWORK_SIZE][i] = 0;
adjacentMatrix[i][re_connectRandomNode] = adjacentMatrix[re_connectRandomNode][i] = 1;
number_changedEage++;
}
else
{
//printf("(%d, %d) no change\n", i, i+j);
}
}
}
//test
printf("Small World NetWork\n");
for( i = 1; i <= NETWORK_SIZE; i++ )
{
for( j = 1; j <= NETWORK_SIZE; j++ )
printf("%d", adjacentMatrix[i][j]);
printf("\n");
}
printf("the number of changed eage is %d, ratio is %f\n", number_changedEage, (double)number_changedEage/(NETWORK_SIZE * K / 2));
}
/*
* 将产生的小世界网络的adjacentMatrix写入文件中
* */
void writeDataToFile(){
FILE* fout;
int i, j;
if( NULL == (fout = fopen("smallWorldNetwork.data", "w")))
{
printf("open file(smallWorldNetwork.data) error!");
exit(0);
}
for( i = 1; i <= NETWORK_SIZE; i++ )
{
for( j = 1; j <= NETWORK_SIZE; j++ )
fprintf(fout, "%d ", adjacentMatrix[i][j]);
fprintf(fout,"\n");
}
fclose(fout);
}
用于进行可视化的辅助函数文件for_plot.c的代码如下
/*
* 将给定的网络@adjacentMatrix(节点的个数为@size)中的所有的连边以有序对的
* 形式输出到文件@out_filename中,每一对使用','隔开,方便python处理。
* 该函数被所有产生网络结构的函数(generateRandomNetwork.c,
* generateSmallNetwork.c和generateFreeScale.c)调用
* */
void write2file(int** adjacentMatrix, int size, char* out_filename)
{
int i, j;
FILE* fout;
if( NULL == (fout = fopen(out_filename,"w")) )
{
printf("%s cann't open!\n", out_filename);
exit(0);
}
for( i = 1; i <= size; i++ )
{
for( j = i + 1; j <= size; j++ )
{
if( adjacentMatrix[i][j] )
{
fprintf(fout, "%d %d\n", i, j);
}
}
}
fclose(fout);
}
使用igraph对算法生成的小世界网络进行可视化的结构图如下,网络的大小为300,K=6,p=0.5