散文简友广场想法

C语言实现Schelling模型(谢林模型)

2020-12-09  本文已影响0人  Cache_wood

谢林隔离模型是一个基于智能体的模型(Agent Based Model), 所谓的智能体模型有3个元素:

  1. 会产生行为的智能体

  2. 智能体行为遵循一定的规则

  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;
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读