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

小世界网络python 小世界网络算法_聚类稀疏计算代码