谢林隔离模型的Python实现

先引用一下果壳网对谢林模型的介绍

该模型由马里兰大学的经济学家托马斯·谢林建立。主要感兴趣的隔离有两种:一种是种族隔离,另一种是由收入差异导致的隔离。

  • 种族隔离:

每一个红点代表城市中白人的聚集地,每一个蓝点代表城市中美国黑人的聚集地,每一个黄点代表城市中拉美人的聚集地,绿点则代表城市中亚裔的聚集地。从这幅图可以看到非常明显的种族隔离。

谢林隔离模型的Python实现_第1张图片

  • 收入隔离:

图片每个红点代表富人,浅蓝色的点代表穷人,而深蓝点则代表中产阶层。从这幅图可以看到收入隔离现象尽管非常明显,但并没有种族隔离现象明显。

谢林隔离模型的Python实现_第2张图片


谢林构建了一个基于代理人的模型。该类模型要点有三个:代理人,规则,以及群体表现。

谢林模型是个关于人们选择在哪居住的模型。他把每个人放置在棋盘上,整个城市看作是一块巨大的棋盘。棋盘上每一个小格子可以住一个人也可以空着。

假设红格子表示住着富人,灰格子表示住了穷人,白格子表示没有主人。对在中间X格子的富人来说,周围7个邻居有3个是同类,他应该留下还是搬走?

谢林隔离模型的Python实现_第3张图片

谢林设定了规则称作阈值基本准则:每个人都有一个阈值(threshold),根据阈值做决定是留下还是搬走。比如假设X的阈值是33%,则此时他会选择留下。而当他的富人邻居有一位搬走时,由于只剩2/7是同类所以那时会选择搬走。

•进行蒙特卡洛仿真
–参数设置

居住地总数:60*60;居民总数:2800

满意度阈值:(0,1) 设定

红蓝两色代表不同肤色,绿色代表空

每个节点相似比低于相似度阈值随机搬家,所有节点相似比不低于相似度阈值,停止迭代


下面是我用python实现的仿真:python2.7+matplotlib+numpy

import random
import numpy as np
import matplotlib.pyplot as plt
import time
# plt.ion()
vector = range(1,3601) #1-3600
random.shuffle(vector)
white = vector[0:1400]
black = vector[1400:2800]
temp = vector[2800:3600]
tmap = np.zeros((62,62,3))
# init
for i in range(1,3601):
    if i in white:
        tmap[(i - 1) / 60 + 1][(i - 1) % 60 + 1] = [1, 0, 0]
    elif i in black:
        tmap[(i - 1) / 60 + 1][(i - 1) % 60 + 1] = [0, 0, 1]
    else:
        tmap[(i - 1) / 60 + 1][(i - 1) % 60 + 1] = [0, 1, 0]
row = [-1,-1,-1, 0, 0, 1, 1, 1] #neiborhood
col = [-1, 0, 1,-1, 1,-1, 0, 1]
simv = []
for m in range(7):
    thd = 0.3+m*0.1  #threshold
    print 'Threshold:'+str(thd)
    sim = 0.0 #similarity
    nosat = 1
    times = 0
    while nosat and times<50:
        times=times+1
        sim = 0.0
        bnosat = 0
        wnosat = 0
        nosatv=[]
        for i in range(1,61):
            for j in range(1,61):
                if(tmap[i][j][1] != 1):
                    ns=0.0
                    n=0.0
                    for k in range(8):
                        if tmap[i+row[k]][j+col[k]][0]==1 or tmap[i+row[k]][j+col[k]][2]==1:
                            n=n+1.0
                            if tmap[i+row[k]][j+col[k]][0] == tmap[i][j][0]:
                                ns=ns+1.0
                    if n!=0:
                        sim = sim + ns/n #similarity plus
                        
                        if(ns/n < thd):
                            if(tmap[i][j][0]==1):
                                wnosat = wnosat+1
                            else:
                                bnosat = bnosat+1
                            nosatv.append([i, j])
                else:
                    nosatv.append([i, j])
        nosat = wnosat + bnosat
        print 'Unsatisfied:' + str(nosat / 2800.0*100)+'%'
        #-------------move--------------
        random.shuffle(nosatv)
        wnosatv=nosatv[0:wnosat]
        bnosatv=nosatv[wnosat:wnosat+bnosat]
        tempv = nosatv[wnosat+bnosat:]
        for i in range(wnosat):
            tmap[wnosatv[i][0]][wnosatv[i][1]]=[1,0,0]
        for i in range(bnosat):
            tmap[bnosatv[i][0]][bnosatv[i][1]]=[0,0,1]
        for i in range(tempv.__len__()):
            tmap[tempv[i][0]][tempv[i][1]] = [0, 1, 0]

    sim = sim/2800.0
    simv.append(sim)
    print 'Similarity:' + str(sim*100)+'%'

    plt.figure()
    plt.axis("off")
    plt.imshow(tmap, interpolation="nearest")
    plt.title('Threshold = '+str(thd)+'    Similarity:'+ str(sim*100)+'%')
    plt.show()

plt.figure()
plt.plot([0.3+m*0.1 for m in range(7)],simv,'-')
plt.title('Similarity of different threshold')
plt.xlabel('threshold')# make axis labels
plt.ylabel('Similarity')
plt.xlim(0.2, 1.0)
plt.xlim(0.2, 1.0)
plt.show()






你可能感兴趣的:(python)