SIS傳染病模型的C語言實現
阿新 • • 發佈:2019-02-15
思路:
- 隨機挑選一個或多個初始感染點,將它們置為I態;
- 開始一輪感染;
- 遍歷每一個I態節點的S態鄰居(每個節點沒輪只訪問一次);
- 遍歷上述鄰居的每個I態鄰居,統計其個數(若為k個),這個節點的感染概率為1-(1-beta)^k,其中beta為感染概率;
- 統計上一輪感染結束後網路中存在的感染點,按照恢復概率將它們恢復為S態;
- 感染結束,返回2。
C語言實現
# include <stdio.h>
# include <stdlib.h>
# include <math.h>
# include <time.h>
# define SUM_OF_VERTEX 1000 // 網路節點總數
# define RATE_OF_INFECTION 1 // 感染率
# define RATE_OF_RECOVER 1 // 恢復率
# define STEP 30 // 感染輪數
# define FILENAME_IN "WS_1000.txt"
# define FILENAME_OUT "data_1.0.txt"
struct Node
{
int is_infected;
}vertex[SUM_OF_VERTEX + 1];
struct LNode
{
int index;
struct LNode *next;
};
void Initial_AdjacencyMatrix();
void Free_AdjacencyMatrix();
void Read_File();
void Output_To_File();
void SIS_Diffusion();
int **AdjacencyMatrix;
int sum_data_to_file[STEP + 1] = {0};
int main()
{
srand( ( unsigned )time( NULL ) );
Initial_AdjacencyMatrix();
Read_File();
SIS_Diffusion();
Output_To_File();
Free_AdjacencyMatrix();
}
void Initial_AdjacencyMatrix()
{
if( !( AdjacencyMatrix = ( int ** )malloc( sizeof( int * ) * ( SUM_OF_VERTEX + 1 ) ) ) )
{
printf( "ERROR: **AdjecentMatrix malloc error.\n" );
exit( -1 );
}
for( int i = 1; i <= SUM_OF_VERTEX; i ++ )
if( !( AdjacencyMatrix[i] = ( int * )malloc( sizeof( int ) * ( SUM_OF_VERTEX + 1 ) ) ) )
{
printf( "ERROR: *AdjecentMatrix malloc error.\n" );
exit( -1 );
}
}
void Free_AdjacencyMatrix()
{
for( int i = 1; i <= SUM_OF_VERTEX; i ++ )
{
free( AdjacencyMatrix[i] );
AdjacencyMatrix[i] = NULL;
}
free( AdjacencyMatrix );
AdjacencyMatrix = NULL;
}
void Read_File()
{
FILE *fp = fopen( FILENAME_IN, "r" );
if( fp == NULL )
{
printf( "ERROR: No such file.\n" );
exit( -1 );
}
for( int i = 1; i <= SUM_OF_VERTEX; i ++ )
{
for( int j = 1; j <= SUM_OF_VERTEX; j ++ )
fscanf( fp, "%d", &AdjacencyMatrix[i][j] );
fscanf( fp, "\n" );
}
}
void Output_To_File()
{
FILE *fout = fopen( FILENAME_OUT, "a" );
if( fout == NULL )
{
printf( "ERROR: No such file.\n" );
exit( -1 );
}
for( int i = 1; i <= STEP; i ++ )
fprintf( fout, "%d ", sum_data_to_file[i] );
fprintf( fout, ";\n" );
}
void SIS_Diffusion()
{
double infected_flag, recovered_flag;
int initial_infected_vertex;
int temp_infected_this_step[SUM_OF_VERTEX + 1] = {0};
int is_visited_this_step[SUM_OF_VERTEX + 1] = {0};
int sum_of_infected_vertices = 0;
int count_infected_neighbors = 0;
int count_infected_this_step = 0;
int count_recovered_this_step = 0;
int sequence_of_infected_vertices[STEP + 1][SUM_OF_VERTEX + 1] = {0}; // 按感染順序儲存每一個STEP被感染的節點序號
for( int i = 1; i <= SUM_OF_VERTEX; i ++ )
vertex[i].is_infected = 0;
/*隨機取一個初始感染點*/
initial_infected_vertex = rand() % SUM_OF_VERTEX + 1;
printf( "Initial = No.%d\n", initial_infected_vertex );
vertex[initial_infected_vertex].is_infected = 1;
sequence_of_infected_vertices[0][1] = initial_infected_vertex;
sum_of_infected_vertices ++;
sum_data_to_file[0] = sum_of_infected_vertices;
for( int step = 1; step <= STEP; step ++ )
{
int k = 1;
/*遍歷每個感染點的每個未被感染的鄰居,若該鄰居有k個被感染的鄰居,則它的感染率為: 1 - ( 1 - beta ) ^ k*/
for( int i = 1; i <= SUM_OF_VERTEX; i ++ )
if( vertex[i].is_infected ) // 感染點i
for( int j = 1; j <= SUM_OF_VERTEX; j ++ ) // 遍歷i的鄰居
if( AdjacencyMatrix[i][j] && !vertex[j].is_infected && !is_visited_this_step[j] ) // 未被感染的鄰居j
{
for( int k = 1; k <= SUM_OF_VERTEX; k ++ )
if( AdjacencyMatrix[j][k] && vertex[k].is_infected ) // 統計j的感染鄰居的個數
count_infected_neighbors ++;
infected_flag = rand() % ( SUM_OF_VERTEX + 1 ) / ( double )SUM_OF_VERTEX;
if( infected_flag <= 1 - pow( 1 - RATE_OF_INFECTION, count_infected_neighbors ) )
{
temp_infected_this_step[j] = 1;
sequence_of_infected_vertices[step][k ++] = j;
count_infected_this_step ++;
}
is_visited_this_step[j] = 1;
count_infected_neighbors = 0;
}
for( int i = 1; i <= SUM_OF_VERTEX; i ++ )
if( temp_infected_this_step[i] )
vertex[i].is_infected = 1;
for( int i = 1; i <= SUM_OF_VERTEX; i ++ )
temp_infected_this_step[i] = 0;
for( int i = 1; i <= SUM_OF_VERTEX; i ++ )
is_visited_this_step[i] = 0;
/*遍歷所有上一個step存在的感染點,依照恢復概率將它們恢復為易感態*/
for( int i = 0; i <= step - 1; i ++ )
for( int j = 1; j <= SUM_OF_VERTEX; j ++ )
{
recovered_flag = rand() % ( SUM_OF_VERTEX + 1 ) / ( double )SUM_OF_VERTEX;
if( sequence_of_infected_vertices[i][j] && recovered_flag < RATE_OF_RECOVER )
{
vertex[sequence_of_infected_vertices[i][j]].is_infected = 0;
sequence_of_infected_vertices[i][j] = 0;
count_recovered_this_step ++;
sum_of_infected_vertices --;
}
}
/*統計輸出*/
sum_of_infected_vertices += count_infected_this_step;
sum_data_to_file[step] = sum_of_infected_vertices;
printf( "Step = %d\n", step );
printf( "Sum = %d\n", sum_of_infected_vertices );
printf( "There are %d vertices newly infected this step.\n", count_infected_this_step );
printf( "There are %d vertices newly recovered this step.\n\n", count_recovered_this_step );
// sum_of_infected_vertices += count_infected_this_step;
count_recovered_this_step = 0;
count_infected_this_step = 0;
}
}