C语言实现Schelling模型(谢林模型)
2020-12-09 本文已影响0人
Cache_wood
谢林隔离模型是一个基于智能体的模型(Agent Based Model), 所谓的智能体模型有3个元素:
-
会产生行为的智能体
-
智能体行为遵循一定的规则
-
智能体产生的行为会导致宏观上的结果
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<Windows.h>
#include<time.h>
#define N 30
#define DIRECTION 8
#define STATUS 6 //改变初始化条件:empty:poor:rich=2:3:1
#define EMPTY 0
#define POOR 1
#define RICH 2
int city[N][N];
const char statuses[STATUS]={'.','#','$'};
void randomly_set_city(void);
void print_city(void);
double same_neighbors_ratio(int,int);
void move(int,int);
void evolve(double);
int main(void)
{
srand(time(NULL));
printf("plz input a threshold:");
double th;
scanf("%lf",&th);
if(th>1.0 || th<0.0)
{
printf("ERROR INPUT\n");
return -1;
}
randomly_set_city();
int i;
for(i=0;i<10000;i++)
{
evolve(th);
if(i==0 || i%100==0)
{
system("clear");
//windows平台可能是System("cls");
print_city();
if(i==0)
Sleep(10);//windows平台有变化,包括时间的单位。
else
Sleep(1);
}
}
return 0;
}
void randomly_set_city()
{
int i,j,x;
for(i=0;i<N;i++)
for(j=0;j<N;j++)
{
if(i<=N/3&&i<=2*N/3)
{
x=rand()%STATUS;//变更城中心初始化状态为empty:poor:rich=2:1:3
switch(x)
{
case 0:
case 1:
city[i][j]=EMPTY;
break;
case 2:
city[i][j]=POOR;
break;
case 3:
case 4:
case 5:
city[i][j]=RICH;
break;
default:
break;
}
}
x=rand()%STATUS;//改变empty, poor, rich比例为2:3:1
switch(x)
{
case 0:
case 1:
city[i][j]=EMPTY;
break;
case 2:
case 3:
case 4:
city[i][j]=POOR;
break;
case 5:
city[i][j]=RICH;
break;
default:
break;
}
}
}
void print_city()
{
int i,j;
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
{
if(city[i][j]==RICH)
printf("\033[41;31m \033[0m");
if(city[i][j]==EMPTY)
printf("\033[47;37m \033[0m");
if(city[i][j]==POOR)
printf("\033[44;34m \033[0m");
}
printf("\n");
}
}
double same_neighbors_ratio(int i,int j)
{
int sn=0;
int nei=0;
//check all the directions
if(i-1>=0)
{
if(city[i-1][j]!=EMPTY)
{
nei++;
if(city[i][j]==city[i-1][j])
sn++;
}
}
if(i+1<N)
{
if(city[i+1][j]!=EMPTY)
{
nei++;
if(city[i][j]==city[i+1][j])
sn++;
}
}
if(j-1>=0)
{
if(city[i][j-1]!=EMPTY)
{
nei++;
if(city[i][j]==city[i][j-1])
sn++;
}
}
if(j+1<N)
{
if(city[i][j+1]!=EMPTY)
{
nei++;
if(city[i][j]==city[i][j+1])
sn++;
}
}
if(i+1<N && j+1<N)
{
if(city[i+1][j+1]!=EMPTY)
{
nei++;
if(city[i][j]==city[i+1][j+1])
sn++;
}
}
if(i-1>=0 && j-1>=0)
{
if(city[i-1][j-1]!=EMPTY)
{
nei++;
if(city[i][j]==city[i-1][j-1])
sn++;
}
}
if(i-1>0 && j+1<N)
{
if(city[i-1][j+1]!=EMPTY)
{
nei++;
if(city[i][j]==city[i-1][j+1])
sn++;
}
}
if(i+1<N && j-1>=0)
{
if(city[i+1][j-1]!=EMPTY)
{
nei++;
if(city[i][j]==city[i+1][j-1])
sn++;
}
}
//printf("nei=%d,sn=%d\n",nei,sn);
return (double)sn/nei;
}
void move(int i,int j)
{
while(1)
{
int m=rand()%N;
int n=rand()%N;
if(city[m][n]==EMPTY)
{
//find an empty place and move to
city[m][n]=city[i][j];
//set the origin place empty
city[i][j]=EMPTY;
//end
break;
}
}
}
void evolve(double th)
{
while(1)
{
int i=rand()%N;
int j=rand()%N;
if(city[i][j]!=EMPTY)
{
//might move
double ratio=same_neighbors_ratio(i,j);
if(ratio<th)
{
//will move
move(i,j);
}
//end this time of evolution
break;
}
}
}