import matplotlib.pyplot as plt import itertools import random import copy class Schelling: def __init__(self, width, height, empty_ratio, similarity_threshold, n_iterations, races=2): self.old_agents = None self. remaining_houses = None self.n_empty = None self.all_houses = None self. width = width self. height = height self.races = races self.empty_ratio = empty_ratio self. similarity_threshold = similarity_threshold self.n_iterations = n_iterations self.empty_houses = [] self. agents = {} def populate(self): self.all_houses = list(itertools.product(range(self.width), range(self.height))) random.shuffle(self.all_houses) self.n_empty = int(self.empty_ratio * len(self.all_houses)) self.empty_houses = self.all_houses[:self.n_empty] self.remaining_houses = self.all_houses[self.n_empty:] houses_by_race = [self. remaining_houses[i::self. races] for i in range(self. races)] for i in range(self.races): self. agents = dict( list(self.agents.items()) + list(dict(zip(houses_by_race[i], [i + 1] * len(houses_by_race[i]))).items())) def is_unsatisfied(self, x, y): race = self. agents[(x, y)] count_similar = 0 count_different = 0 if x > 0 and y > 0 and (x - 1, y - 1) not in self.empty_houses: if self. agents[(x - 1, y - 1)] == race: count_similar += 1 else: count_different += 1 if y > 0 and (x, y - 1) not in self.empty_houses: if self. agents[(x, y - 1)] == race: count_similar += 1 else: count_different += 1 if x < (self.width - 1) and y > 0 and (x + 1, y - 1) not in self.empty_houses: if self. agents[(x + 1, y - 1)] == race: count_similar += 1 else: count_different += 1 if x > 0 and (x - 1, y) not in self.empty_houses: if self. agents[(x - 1, y)] == race: count_similar += 1 else: count_different += 1 if x < (self.width - 1) and (x + 1, y) not in self.empty_houses: if self. agents[(x + 1, y)] == race: count_similar += 1 else: count_different += 1 if x > 0 and y < (self. height - 1) and (x - 1, y + 1) not in self. empty_houses: if self. agents[(x - 1, y + 1)] == race: count_similar += 1 else: count_different += 1 if x > 0 and y < (self. height - 1) and (x, y + 1) not in self. empty_houses: if self. agents[(x, y + 1)] == race: count_similar += 1 else: count_different += 1 if x < (self.width - 1) and y < (self.height - 1) and (x + 1, y + 1) not in self.empty_houses: if self. agents[(x + 1, y + 1)] == race: count_similar += 1 else: count_different += 1 if (count_similar + count_different) == 0: return False else: return float(count_similar) / (count_different + count_similar) < self. happy_threshold def update(self): for i in range(self. n_iterations): self.old_agents = copy.deepcopy(self.agents) n_changes = 0 for agent in self.old_agents: agent_race = self. agents[agent] empty_house = random.choice(self.empty_houses) self.agents[empty_house] = agent_race del self. agents[agent] self.empty_houses.remove(empty_house) self.empty_houses.append(agent) n_changes += 1 print(n_changes) if n_changes == 0: break def plot(self, title, file_name): fig, ax = plt.subplots() # If you want to simulate more than 7 colors, you should set accordingly agent_colors = {1: 'b', 2: 'r', 3: 'g', 4: 'c', 5: 'm', 6: 'y' , 7: 'k'} for agent in self. agents: ax.scatter(agent[0] + 0.5, agent[1] + 0.5, color=agent_colors[self.agents[agent]]) ax.set_title(title, fontsize=10, fontweight='bold') ax.set_xlim([0, self.width]) ax.set_ylim([0, self.height]) ax. set_xticks([]) ax. set_yticks([]) plt. savefig(file_name) if __name__ == '__main__': Schelling_1 = Schelling(50, 50, 0.3, 0.3, 500, 2) schelling_1.populate() Schelling_2 = Schelling(50, 50, 0.3, 0.5, 500, 2) schelling_2.populate() Schelling_3 = Schelling(50, 50, 0.3, 0.8, 500, 2) schelling_3.populate() schelling_1.plot('Schelling Model with 2 colors: Initial State', 'schelling_2_initial.png') schelling_1. update() schelling_2. update() schelling_3. update() schelling_1.plot('Schelling Model with 2 colors: Final State with Similarity Threshold 30%', 'schelling_2_30_final.png') schelling_2.plot('Schelling Model with 2 colors: Final State with Similarity Threshold 50%', 'schelling_2_50_final.png') schelling_3.plot('Schelling Model with 2 colors: Final State with Similarity Threshold 80%', 'schelling_2_80_final.png')
operation result