class Schelling(Model): ''' Model class for the Schelling segregation model. ''' def __init__(self, height=20, width=20, density=0.8, minority_pc=0.2, homophily=3): ''' ''' self.height = height self.width = width self.density = density self.minority_pc = minority_pc self.homophily = homophily self.schedule = RandomActivation(self) self.grid = SingleGrid(height, width, torus=True) self.happy = 0 self.datacollector = DataCollector( {"happy": "happy"}, # Model-level count of happy agents # For testing purposes, agent's individual x and y {"x": lambda a: a.pos[0], "y": lambda a: a.pos[1]}) # Set up agents # We use a grid iterator that returns # the coordinates of a cell as well as # its contents. (coord_iter) for cell in self.grid.coord_iter(): x = cell[1] y = cell[2] if self.random.random() < self.density: if self.random.random() < self.minority_pc: agent_type = 1 else: agent_type = 0 agent = SchellingAgent((x, y), self, agent_type) self.grid.position_agent(agent, (x, y)) self.schedule.add(agent) self.running = True self.datacollector.collect(self) def step(self): ''' Run one step of the model. If All agents are happy, halt the model. ''' self.happy = 0 # Reset counter of happy agents self.schedule.step() # collect data self.datacollector.collect(self) if self.happy == self.schedule.get_agent_count(): self.running = False
class SchellingModel(Model): """ Model class for the Schelling segregation model. """ def __init__(self, height, width, density, minority_pc, homophily): """ """ self.height = height self.width = width self.density = density self.minority_pc = minority_pc self.homophily = homophily self.schedule = RandomActivation(self) self.grid = SingleGrid(height, width, torus=True) self.happy = 0 self.total_agents = 0 self.datacollector = DataCollector( {"unhappy": lambda m: m.total_agents - m.happy}, # For testing purposes, agent's individual x and y {"x": lambda a: a.pos[X], "y": lambda a: a.pos[Y]}, ) self.running = True # Set up agents # We use a grid iterator that returns # the coordinates of a cell as well as # its contents. (coord_iter) for cell, x, y in self.grid.coord_iter(): if random.random() < self.density: if random.random() < self.minority_pc: agent_type = 1 else: agent_type = 0 agent = SchellingAgent(self.total_agents, agent_type) self.grid.position_agent(agent, x, y) self.schedule.add(agent) self.total_agents += 1 def step(self): """ Run one step of the model. If All agents are happy, halt the model. """ self.happy = 0 # Reset counter of happy agents self.schedule.step() self.datacollector.collect(self) if self.happy == self.total_agents: self.running = False
class PartyModel(Model): def __init__(self, height=20, width=20, number_introvert=30, number_ambivert=40, number_extrovert=30): ''' ''' self.height = height self.width = width self.number_attendees = 1.0 * \ (number_introvert + number_ambivert + number_extrovert) self.number_introvert = number_introvert self.number_ambivert = number_ambivert self.number_extrovert = number_extrovert self.percent_introvert = number_introvert / self.number_attendees self.percent_ambivert = number_ambivert / self.number_attendees self.percent_extrovert = number_extrovert / self.number_attendees self.introvert_cutoff = self.percent_introvert self.ambivert_cutoff = self.percent_introvert + self.percent_ambivert self.schedule = RandomActivation(self) self.grid = SingleGrid(width, height, torus=True) self.happy = 0 self.happy_introverts = 0 self.happy_ambiverts = 0 self.happy_extroverts = 0 self.datacollector = DataCollector( {"happy": "happy"}, # Model-level count of happy agents # For testing purposes, agent's individual x and y { "x": lambda a: a.pos[0], "y": lambda a: a.pos[1] }) count = 0 # Set up agents # We use a grid iterator that returns # the coordinates of a cell as well as # its contents. (coord_iter) for cell in self.grid.coord_iter(): x = cell[1] y = cell[2] if count < self.number_attendees: extroversion = self.random.random() if extroversion < self.introvert_cutoff: agent_type = "introvert" else: if extroversion < self.ambivert_cutoff: agent_type = "ambivert" else: agent_type = "extrovert" agent = PartyAgent((x, y), self, agent_type) self.grid.position_agent(agent, (x, y)) self.schedule.add(agent) count = count + 1 self.running = True self.datacollector.collect(self) ''' Run one step of the model. If all agents are happy, halt the model. ''' def step(self): # Reset counters of happy agents self.happy = 0 self.schedule.step() # collect data self.datacollector.collect(self) if self.happy > self.schedule.get_agent_count() * 0.95: self.running = False
class NaSchTraffic(Model): """ Model class for the Nagel and Schreckenberg traffic model. """ def __init__(self, height=1, width=60, vehicle_quantity=5, general_max_speed=4, seed=None): """""" super().__init__(seed=seed) self.height = height self.width = width self.vehicle_quantity = vehicle_quantity self.general_max_speed = general_max_speed self.schedule = SimultaneousActivation(self) self.grid = SingleGrid(width, height, torus=True) self.average_speed = 0.0 self.averages = [] self.total_speed = 0 self.datacollector = DataCollector( model_reporters={ "Average_Speed": "average_speed" }, # Model-level count of average speed of all agents # For testing purposes, agent's individual x position and speed agent_reporters={ "PosX": lambda x: x.pos[0], "Speed": lambda x: x.speed, }, ) # Set up agents # We use a grid iterator that returns # the coordinates of a cell as well as # its contents. (coord_iter) cells = list(self.grid.coord_iter()) self.random.shuffle(cells) for vehicle_iter in range(0, self.vehicle_quantity): cell = cells[vehicle_iter] (content, x, y) = cell agent = VehicleAgent((x, y), self, general_max_speed) self.grid.position_agent(agent, (x, y)) self.schedule.add(agent) self.running = True self.datacollector.collect(self) def step(self): """ Run one step of the model. Calculate current average speed of all agents. """ if self.schedule.steps == 100: self.running = False self.total_speed = 0 # Step all agents, then advance all agents self.schedule.step() if self.schedule.get_agent_count() > 0: self.average_speed = self.total_speed / self.schedule.get_agent_count( ) else: self.average_speed = 0 self.averages.append(self.average_speed) # collect data self.datacollector.collect(self)
class Schelling(Model): """ Model class for the Schelling segregation model. """ def __init__(self, height=30, width=30, density=0.9, minority_pc=0.5, homophily=3): """ """ # Height and width of the Grid; # Height and width also defines the maximum number of agents that could be in the environment self.height = height self.width = width # Define the population density; Float between 0 and 1 self.density = density # Ratio between blue and red. # Blue is minority, red is majority; Float between 0 and 1; if > 0.5, blue becomes majority # 1 에 가까워 질수록 파란색이 많아지고, # 0 에 가까워 질수록 빨간색이 많아진다. self.minority_pc = minority_pc # number of similar neighbors required for the agents to be happy # Takes integer value between 0 and 8 since you can only be surrounded by 8 neighbors self.homophily = homophily # Scheduler controls the order in which agents are activated self.schedule = RandomActivation(self) self.grid = SingleGrid(width, height, torus=True) self.happy = 0 # Obtain data after each step self.datacollector = DataCollector( {"happy": "happy"}, # Model-level count of happy agents # For testing purposes, agent's individual x and y {"x": lambda a: a.pos[0], "y": lambda a: a.pos[1]}, ) # Set up agents # We use a grid iterator that returns # the coordinates of a cell as well as # its contents. (coord_iter) for cell in self.grid.coord_iter(): x = cell[1] y = cell[2] if self.random.random() < self.density: if self.random.random() < self.minority_pc: agent_type = 1 else: agent_type = 0 agent = SchellingAgent((x, y), self, agent_type) self.grid.position_agent(agent, (x, y)) self.schedule.add(agent) self.running = True self.datacollector.collect(self) # The class requires a step function that represent each run def step(self): """ Run one step of the model. If All agents are happy, halt the model. """ self.happy = 0 # Reset counter of happy agents self.schedule.step() # collect data self.datacollector.collect(self) # 여기서 terminate 하는 것을 manage 한다. if self.happy == self.schedule.get_agent_count(): self.running = False
class Schelling(Model): ''' Model class for the Schelling segregation model. ''' def __init__(self, height=20, width=20, density=0.8, minority_pc=0.2, homophily=3): ''' ''' self.height = height self.width = width self.density = density self.minority_pc = minority_pc self.homophily = homophily self.schedule = RandomActivation(self) self.grid = SingleGrid(height, width, torus=True) self.happy = 0 self.datacollector = DataCollector( {"happy": "happy"}, # Model-level count of happy agents # For testing purposes, agent's individual x and y { "x": lambda a: a.pos[0], "y": lambda a: a.pos[1] }) # Set up agents # We use a grid iterator that returns # the coordinates of a cell as well as # its contents. (coord_iter) for cell in self.grid.coord_iter(): x = cell[1] y = cell[2] if self.random.random() < self.density: if self.random.random() < self.minority_pc: agent_type = 1 else: agent_type = 0 agent = SchellingAgent((x, y), self, agent_type) self.grid.position_agent(agent, (x, y)) self.schedule.add(agent) self.running = True self.datacollector.collect(self) def step(self): ''' Run one step of the model. If All agents are happy, halt the model. ''' self.happy = 0 # Reset counter of happy agents self.schedule.step() # collect data self.datacollector.collect(self) if self.happy == self.schedule.get_agent_count(): self.running = False
class Robot2D(Model): """ Model class for the 2D robot model. """ def __init__(self, height=75, width=75): self.height = height self.width = width self.schedule = BaseScheduler(self) self.grid = SingleGrid(width, height, torus=True) self.ready=0 self.localizedRobots=0 self.movingAgents=0 self.seeds=[] # Seed robots self.datacollector = DataCollector( model_reporters={"Ready": "ready", "Localized": "localizedRobots"}, agent_reporters={"x": lambda a: a.pos[0], "y": lambda a: a.pos[1], "Gradient": "gradient"} ) # Set up agents # We use a grid iterator that returns # the coordinates of a cell as well as # its contents. (coord_iter) margin1X=[i for i in range(15)] margin2X=[i for i in range(height-41, height)] margin1Y=[i for i in range(5)] margin2Y=[i for i in range(height-5, height)] nRobots=0 for cell in self.grid.coord_iter(): # Change coordinates order y = cell[1] x = cell[2] if x in margin1X or x in margin2X or y in margin1Y or y in margin2Y: continue if nRobots < MAX_ROBOTS: agent = RobotAgent((x,y), self, 1, figure1) self.grid.place_agent(agent, (x, y)) self.schedule.add(agent) nRobots+=1 else: # SEED ROBOTS if x > 40: x=37 y+=1 # SEED 1 agent = RobotAgent((x,y), self, 0, figure1, loc=[0,0], grad=0) self.grid.place_agent(agent, (x, y)) self.seeds.append(agent) self.schedule.add(agent) # SEED 2 agent = RobotAgent((x+1,y), self, 0, figure1, loc=[1,0], grad=1) self.grid.place_agent(agent, (x+1, y)) self.seeds.append(agent) self.schedule.add(agent) # SEED 3 agent = RobotAgent((x,y+1), self, 0, figure1, loc=[0,1], grad=1) self.grid.place_agent(agent, (x, y+1)) self.seeds.append(agent) self.schedule.add(agent) # SEED 4 agent = RobotAgent((x+1,y+1), self, 0, figure1, loc=[1,1], grad=1) self.grid.place_agent(agent, (x+1, y+1)) self.seeds.append(agent) self.schedule.add(agent) else: # SEED 1 x-=1 y+=1 agent = RobotAgent((x,y), self, 0, figure1, loc=[0,0], grad=0) self.grid.place_agent(agent, (x, y)) self.seeds.append(agent) self.schedule.add(agent) # SEED 2 agent = RobotAgent((x+1,y), self, 0, figure1, loc=[1,0], grad=1) self.grid.place_agent(agent, (x+1, y)) self.seeds.append(agent) self.schedule.add(agent) # SEED 3 agent = RobotAgent((x,y+1), self, 0, figure1, loc=[0,1], grad=1) self.grid.place_agent(agent, (x, y+1)) self.seeds.append(agent) self.schedule.add(agent) # SEED 4 agent = RobotAgent((x+1,y+1), self, 0, figure1, loc=[1,1], grad=1) self.grid.place_agent(agent, (x+1, y+1)) self.seeds.append(agent) self.schedule.add(agent) break self.running = True def step(self): """ Run one step of the model. """ # collect data self.datacollector.collect(self) self.schedule.step()
class Model(Model): """ Model class for the Schelling segregation model. """ def __init__(self, height=30, width=30, density=0.1, oxy_den_count=1): """ """ self.height = height self.width = width self.density = density self.schedule = RandomActivation(self) self.grid = SingleGrid(width, height, torus=True) self.datacollector = DataCollector( {"happy": "happy"}, # Model-level count of happy agents # For testing purposes, agent's individual x and y { "x": lambda a: a.pos[0], "y": lambda a: a.pos[1] }, ) # Set up agents # We use a grid iterator that returns # the coordinates of a cell as well as # its contents. (coord_iter) for cell in self.grid.coord_iter(): x = cell[1] y = cell[2] if self.random.random() < self.density: agent = SchellingAgent((x, y), self) self.grid.position_agent(agent, (x, y)) self.schedule.add(agent) self.running = True self.datacollector.collect(self) def get_height(): return self.height def get_width(): return self.width def get_oxygen(self, x, y): return -1 * pow((x / 5) - 5, 2) - pow((y / 5) - 5, 2) + 25 def get_oxy_grad(self, x, y): a = -(((2 * x) / 25) - 2) b = -(((2 * y) / 25) - 2) if abs(b) != 0: b = b / abs(b) if abs(a) != 0: a = a / abs(a) total = -1 * a - b return a, b, total def step(self): """ Run one step of the model. If All agents are happy, halt the model. """ self.schedule.step() # collect data self.datacollector.collect(self)
class MondoModel(Model): """Questo è il mondo fatto a griglia""" def __init__(self, popolazione, width, height): super().__init__() self.popolazione = popolazione self.grid = SingleGrid(width, height, True) self.schedule = RandomActivation(self) self.points = [] # Create agents for i in range(self.popolazione): a = PersonAgent(i, self) self.schedule.add(a) emptyspace = self.grid.find_empty() if emptyspace is not None: self.grid.place_agent(a, emptyspace) paziente_zero = self.schedule.agents[0] paziente_zero.virus = Virus(mortalita=20, tempo_incubazione=3, infettivita=70) paziente_zero.ttl = paziente_zero.virus.tempo_incubazione def step(self): '''Advance the model by one step.''' self.schedule.step() suscettibili = 0 infetti = 0 morti = 0 immuni = 0 for persona in self.schedule.agents: if persona.isAlive is False: morti += 1 elif persona.isImmune is True: immuni += 1 elif persona.virus is not None: infetti += 1 else: suscettibili += 1 self.points.append([suscettibili, infetti, morti, immuni]) def crea_grafico(self): global_health_status = np.zeros((self.grid.width, self.grid.height)) for persona, x, y in self.grid.coord_iter( ): # ctrl+click per spiegare meglio if persona is None: global_health_status[x][y] = StatoCella.vuoto elif persona.isAlive is False: global_health_status[x][y] = StatoCella.morto elif persona.isImmune is True: global_health_status[x][y] = StatoCella.guarito elif persona.virus is not None: global_health_status[x][y] = StatoCella.infetto else: global_health_status[x][y] = StatoCella.suscettibile cmap = matplotlib.colors.ListedColormap([(0, 0, 0), (1, 0, 0), (1, 1, 0), (0, 0, 1), (0, 1, 0)]) img = plt.imshow(global_health_status, interpolation='nearest', vmin=0, vmax=4, cmap=cmap) plt.colorbar(img, ticks=[0, 1, 2, 3, 4]) plt.show() def crea_grafico_2(self): matplotlib.pyplot.plot(self.points) matplotlib.pyplot.show()
class Anthill(Model): def __init__(self): self.grid = SingleGrid(WIDTH, HEIGHT, False) self.schedule = RandomActivation(self) self.running = True self.internalrate = 0.2 self.ant_id = 1 self.tau = np.zeros((WIDTH,HEIGHT)) self.datacollector = DataCollector({"Total number of Ants": lambda m: self.get_total_ants_number(), "mean tau": lambda m: self.evaluation1(), "sigma": lambda m: self.evaluation2(), "sigma*" : lambda m: self.evaluation3(), }) # List containing all coordinates of the boundary, initial ants location and brood location self.bound_vals = [] self.neigh_bound = [] self.middle=[] self.datacollector.collect(self) self.passage_to_right = [] self.passage_to_left = [] # for i in range(WIDTH): # for j in range(HEIGHT): # if i == 0 or j == 0 or i == WIDTH-1 or j == HEIGHT-1: # self.bound_vals.append((i,j)) # if i == 1 or i == WIDTH - 2 or j == 1 or j == HEIGHT-2: # self.neigh_bound.append((i,j)) ## for i in range(WIDTH): for j in range(HEIGHT): ##make boundary if i == 0 or j == 0 or i == WIDTH - 1 or j == HEIGHT - 1: self.bound_vals.append((i,j)) if i == MIDDLE and 0<j<WIDTH - 1: self.bound_vals.append((i,j)) self.middle.append((i,j)) ##save neighbor if j ==1 and 1<= i <= MIDDLE-2: self.neigh_bound.append((i,j)) if j ==1 and MIDDLE+2<=i<=WIDTH - 2: self.neigh_bound.append((i,j)) if j ==HEIGHT - 1 and 1<= i <= MIDDLE-2: self.neigh_bound.append((i,j)) if j ==HEIGHT - 1 and MIDDLE+2<=i<=WIDTH - 2: self.neigh_bound.append((i,j)) if i == 1 and 2<= j<= MIDDLE-3: self.neigh_bound.append((i, j)) if i == HEIGHT - 2 and 2<= j<= MIDDLE-3: self.neigh_bound.append((i, j)) ## we let the columns next to th middle become the entrance to next chamber if i == MIDDLE-1 and 0<j<WIDTH-1: self.passage_to_left.append((i, j)) if i == MIDDLE + 1 and 0 < j < WIDTH - 1: self.passage_to_right.append((i, j)) # Make a Fence boundary b = 0 for h in self.bound_vals: br = Fence(b,self) self.grid.place_agent(br,(h[0],h[1])) b += 1 def step(self): '''Advance the model by one step.''' # Add new ants into the internal area ont he boundary for xy in self.neigh_bound: # Add with probability internal rate and if the cell is empty if self.random.uniform(0, 1) < self.internalrate and self.grid.is_cell_empty(xy) == True: a = Ant(self.ant_id, self) self.schedule.add(a) self.grid.place_agent(a,xy) self.ant_id += 1 # Move the ants self.schedule.step() self.datacollector.collect(self) # with open("data/p02_b0_tau.txt", "a") as myfile: # myfile.write(str(self.mean_tau_ant) + '\n') # with open("data/p02_b0_sigma.txt", "a") as myfile: # myfile.write(str(self.sigma) + '\n') # with open("data/p02_b0_sigmastar.txt","a") as myfile: # myfile.write(str(self.sigmastar) + "\n") def get_total_ants_number(self): total_ants=0 for (agents, _, _) in self.grid.coord_iter(): if type(agents) is Ant: total_ants += 1 return total_ants def evaluation1(self): ##creat a empty grid to store currently information total_ants = np.zeros((WIDTH,HEIGHT)) ## count the number of currently information for (agents, i, j) in self.grid.coord_iter(): if type(agents) is Ant: total_ants[i][j] = 1 else: total_ants[i][j] = 0 ##update the tau self.tau = self.tau + total_ants ##calcualte the mean tau self.mean_tau_ant = self.tau.sum()/((WIDTH-2)**2) return self.mean_tau_ant def evaluation2(self): ## we need to minus the mean tau so we need to ensure the result of boundary is zero ## so we let the bounday equal mean_tau_ant in this way the (tau-mean_tau_ant) is zero of boundary for site in self.bound_vals: self.tau[site[0]][site[1]] = self.mean_tau_ant ##calculate the sigmaa self.sigma = ((self.tau-self.mean_tau_ant)**2).sum()/((WIDTH-2)**2) ## rechange the boundaryy for site in self.bound_vals: self.tau[site[0]][site[1]] = 0 return np.sqrt(self.sigma) def evaluation3(self): ##calculate the sigmastar self.sigmastar = np.sqrt(self.sigma)/self.mean_tau_ant return self.sigmastar
class VirtuousEmotivistModel(Model): ''' Model class for the "Virtuous-Emotivist segregating opinion transfer model". ''' def __init__(self, init_seed, height, width, density, minority_pc, homophily, virtuous_homophily, nudge_amount, num_to_argue, num_to_convert, convert_prob, convinced_threshold \ , random_move_prob, traditionless_life_decrease, vir_a, vir_b, vir_c, emo_a, emo_b \ , emo_c , emo_bias_a, emo_bias_b, emo_bias_c , strongest_belief_weight, count_extra_pow, count_extra_det \ , count_extra_det_pow, extra_pow, extra_det , belief_of_extra_pow, belief_of_extra_det, belief_of_extra_det_pow): # uncomment to make runs reproducible super().__init__(seed=init_seed) self.height = height self.width = width self.density = density self.minority_pc = minority_pc # segregation logic taken from the Schelling segregation model example self.homophily = homophily self.virtuous_homophily = virtuous_homophily self.convert_prob = convert_prob self.num_to_convert = num_to_convert self.traditionless_life_decrease = traditionless_life_decrease self.steps_since = 0 self.schedule = RandomActivation(self) self.grid = SingleGrid(height, width, torus=True) self.happy = 0 self.convinced = 0 self.virtuous_count = 0 self.emotivist_count = 0 self.virtuous_death_count = 0 self.datacollector = DataCollector( # Model-level variables for graphs {"happy": "happy", "convinced": "convinced", "emotivist_count": "emotivist_count" \ , "virtuous_count": "virtuous_count", "virtuous_death_count": "virtuous_death_count"}, {"x": lambda a: a.pos[0], "y": lambda a: a.pos[1], "happy": lambda a: a.happy, # Agent-level variables "convinced": lambda a: a.convinced, "strongest_belief": lambda a: a.strongest_belief() , "beliefs": lambda a: a.beliefs_string(), "type": lambda a: 0 if isinstance(a, EmotivistAgent) else 1}) self.nudge_amount = nudge_amount self.num_to_argue = num_to_argue self.convinced_threshold = convinced_threshold self.random_move_prob = random_move_prob population = [ "A", "B", "C" ] # defined here because of dependencies on the visualization side (emo_bias in server.py) self.population = population probs_emotivist = np.array([emo_a, emo_b, emo_c]) probs_emotivist = probs_emotivist / np.sum( probs_emotivist) # normalize probs to 1.0 probs_virtuous = np.array([vir_a, vir_b, vir_c]) probs_virtuous = probs_virtuous / np.sum(probs_virtuous) initial_bias_emotivist = { "A": emo_bias_a, "B": emo_bias_b, "C": emo_bias_c } self.strongest_belief_weight = strongest_belief_weight # Set up agents # We get a list of cells in order from the grid iterator # and randomize the list cell_list = list(self.grid.coord_iter()) random.shuffle(cell_list) total_num_agents = self.density * self.width * self.height det_emotivists_added = 0 pow_emotivists_added = 0 det_pow_emotivists_added = 0 # pregenerate a list of strongest_beliefs in random order according to distribution # currently only works with a population of 3 beliefs list_emotivist_choices = [] emo_length = ceil((1.0 - self.minority_pc) * total_num_agents) for i in range(0, emo_length): if (float(i) / emo_length < probs_emotivist[0]): list_emotivist_choices.append(population[0]) elif (float(i) / emo_length < probs_emotivist[0] + probs_emotivist[1]): list_emotivist_choices.append(population[1]) else: list_emotivist_choices.append(population[2]) random.shuffle(list_emotivist_choices) list_virtuous_choices = [] vir_length = ceil(self.minority_pc * total_num_agents) for i in range(0, vir_length): if (float(i) / vir_length < probs_virtuous[0]): list_virtuous_choices.append(population[0]) elif (float(i) / vir_length < probs_virtuous[0] + probs_virtuous[1]): list_virtuous_choices.append(population[1]) else: list_virtuous_choices.append(population[2]) random.shuffle(list_virtuous_choices) # create agents and add to grid i = 0 for cell in cell_list: x = cell[1] y = cell[2] if i < total_num_agents: if i < self.minority_pc * total_num_agents: #initial_strongestbelief_virtuous = random.choices(population, weights=probs_virtuous, k=1)[0] initial_strongestbelief_virtuous = list_virtuous_choices.pop( ) initial_beliefs_virtuous = {} for belief in population: if (belief == initial_strongestbelief_virtuous): initial_beliefs_virtuous[ belief] = strongest_belief_weight else: initial_beliefs_virtuous[belief] = ( 1 - strongest_belief_weight) / ( len(population) - 1) agent = VirtuousAgent(i, (x, y), self, initial_beliefs_virtuous) self.virtuous_count += 1 else: #agent_type = 0 #initial_strongestbelief_emotivist = random.choices(population, weights=probs_emotivist, k=1)[0] initial_strongestbelief_emotivist = list_emotivist_choices.pop( ) initial_beliefs_emotivist = {} det = 0.0 pow = 1.0 if (initial_strongestbelief_emotivist == belief_of_extra_det and det_emotivists_added < count_extra_det): det = extra_det det_emotivists_added += 1 elif (initial_strongestbelief_emotivist == belief_of_extra_pow and pow_emotivists_added < count_extra_pow): pow = extra_pow pow_emotivists_added += 1 elif (initial_strongestbelief_emotivist == belief_of_extra_det_pow and det_pow_emotivists_added < count_extra_det_pow): pow = extra_pow det_pow_emotivists_added += 1 for belief in population: if (belief == initial_strongestbelief_emotivist): initial_beliefs_emotivist[ belief] = strongest_belief_weight else: initial_beliefs_emotivist[belief] = ( 1 - strongest_belief_weight) / ( len(population) - 1) agent = EmotivistAgent(i, (x, y), self, initial_beliefs_emotivist, initial_bias_emotivist, pow, det) self.emotivist_count += 1 i += 1 self.grid.position_agent(agent, (x, y)) self.schedule.add(agent) self.last_agent_id = i # update message with starting probs self.message = "Emotivist probs: " + str(list(map(lambda x: "{:.2f}".format(x), probs_emotivist.tolist()))) \ + ", Virtuous probs: " + str(list(map(lambda x: "{:.2f}".format(x), probs_virtuous.tolist()))) self.running = True self.datacollector.collect(self) def update_emo_vir_count(self): emotivist_count = 0 virtuous_count = 0 for agent_type in self.datacollector.agent_vars["type"][-1]: if (agent_type[1] == 0): emotivist_count += 1 else: virtuous_count += 1 self.emotivist_count = emotivist_count self.virtuous_count = virtuous_count def update_happy_convinced_count(self): tmphappy = 0 for agent_happy in self.datacollector.agent_vars["happy"][-1]: if (agent_happy[1]): tmphappy += 1 tmpconvinced = 0 for agent_convinced in self.datacollector.agent_vars["convinced"][-1]: if (agent_convinced[1]): tmpconvinced += 1 self.happy = tmphappy self.convinced = tmpconvinced def step(self): ''' Run one step of the model. Uncomment "self.running = False" to enable auto-stopping after the model has run for 200 steps with almost all agents happy and convinced ''' # Reset counter of happy agents self.schedule.step() # collect data self.datacollector.collect(self) # update model-level counts self.update_happy_convinced_count() self.update_emo_vir_count() # optional auto-stopping if self.happy > self.schedule.get_agent_count( ) - 3 and self.convinced == self.schedule.get_agent_count() - 3: self.steps_since += 1 if (self.steps_since > 200): #self.running = False pass
class Anthill(Model): def __init__(self): self.grid = SingleGrid(WIDTH, HEIGHT, False) self.schedule = RandomActivation(self) self.running = True self.internalrate = 0.2 self.ant_id = 1 self.tau = np.zeros((WIDTH, HEIGHT)) self.datacollector = DataCollector({ "Total number of Ants": lambda m: self.get_total_ants_number(), "mean tau": lambda m: self.evaluation1(), "sigma": lambda m: self.evaluation2(), "sigma*": lambda m: self.evaluation3(), }) # List containing all coordinates of the boundary, initial ants location and brood location self.bound_vals = [] self.neigh_bound = [] self.datacollector.collect(self) # Make the bound_vals and neigh_bound lists by one of the following: # self.nowalls() self.onewall() # self.twowalls() # self.threewalls() # Make a Fence boundary b = 0 for h in self.bound_vals: br = Fence(b, self) self.grid.place_agent(br, (h[0], h[1])) b += 1 def step(self): '''Advance the model by one step.''' # Add new ants into the internal area ont he boundary for xy in self.neigh_bound: # Add with probability internal rate and if the cell is empty if self.random.uniform( 0, 1) < self.internalrate and self.grid.is_cell_empty( xy) == True: a = Ant(self.ant_id, self) self.schedule.add(a) self.grid.place_agent(a, xy) self.ant_id += 1 # Move the ants self.schedule.step() self.datacollector.collect(self) # Remove all ants in neigh_bound for (agents, i, j) in self.grid.coord_iter(): if (i, j) in self.neigh_bound and type(agents) is Ant: self.grid.remove_agent(agents) self.schedule.remove(agents) data_tau.append(self.mean_tau_ant) data_sigma.append(np.sqrt(self.sigma)) data_sigmastar.append(self.sigmastar) if len(data_sigmastar) > 2000: if abs(data_sigmastar[-2] - data_sigmastar[-1]) < 0.0000001: try: # TAU with open("results/m1_tau_inf.pkl", 'rb') as f: tau_old = pickle.load(f) tau_old[int(len(tau_old) + 1)] = data_tau f.close() pickle.dump(tau_old, open("results/m1_tau_inf.pkl", 'wb')) except: pickle.dump({1: data_tau}, open("results/m1_tau_inf.pkl", 'wb')) try: # SIGMA with open("results/m1_sigma_inf.pkl", 'rb') as f: sigma_old = pickle.load(f) sigma_old[int(len(sigma_old) + 1)] = data_sigma f.close() pickle.dump(sigma_old, open("results/m1_sigma_inf.pkl", 'wb')) except: pickle.dump({1: data_sigma}, open("results/m1_sigma_inf.pkl", 'wb')) try: # SIGMASTAR with open("results/m1_sigmastar_inf.pkl", 'rb') as f: sigmastar_old = pickle.load(f) sigmastar_old[int(len(sigmastar_old) + 1)] = data_sigmastar f.close() pickle.dump(sigmastar_old, open("results/m1_sigmastar_inf.pkl", 'wb')) except: pickle.dump({1: data_sigmastar}, open("results/m1_sigmastar_inf.pkl", 'wb')) try: # MATRIX with open("results/m1_matrix_inf.pkl", 'rb') as f: matrix_old = pickle.load(f) matrix_old[int(len(matrix_old) + 1)] = self.tau f.close() pickle.dump(matrix_old, open("results/m1_matrix_inf.pkl", 'wb')) except: pickle.dump({1: self.tau}, open("results/m1_matrix_inf.pkl", 'wb')) self.running = False # with open("tau2_new.txt", "a") as myfile: # myfile.write(str(self.mean_tau_ant) + '\n') # with open("sigma2_new.txt", "a") as myfile: # myfile.write(str(np.sqrt(self.sigma)) + '\n') # with open("datasigmastar2_new.txt","a") as myfile: # myfile.write(str(self.sigmastar) + "\n") def nowalls(self): # For model without walls: for i in range(WIDTH): for j in range(HEIGHT): if i == 0 or j == 0 or i == WIDTH - 1 or j == HEIGHT - 1: self.bound_vals.append((i, j)) if i == 1 or i == WIDTH - 2 or j == 1 or j == HEIGHT - 2: self.neigh_bound.append((i, j)) def onewall(self): # For model with ONE wall: for i in range(WIDTH): for j in range(HEIGHT): if i == 0 or j == 0 or i == WIDTH - 1 or j == HEIGHT - 1: self.bound_vals.append((i, j)) if i == WIDTH - 2 or j == 1 or j == HEIGHT - 2: self.neigh_bound.append((i, j)) def twowalls(self): # For model with TWO walls: for i in range(WIDTH): for j in range(HEIGHT): if i == 0 or j == 0 or i == WIDTH - 1 or j == HEIGHT - 1: self.bound_vals.append((i, j)) if j == 1 or j == HEIGHT - 2: self.neigh_bound.append((i, j)) def threewalls(self): # For model with THREE walls: for i in range(WIDTH): for j in range(HEIGHT): if i == 0 or j == 0 or i == WIDTH - 1 or j == HEIGHT - 1: self.bound_vals.append((i, j)) if j == HEIGHT - 2: self.neigh_bound.append((i, j)) def get_total_ants_number(self): total_ants = 0 for (agents, _, _) in self.grid.coord_iter(): if type(agents) is Ant: total_ants += 1 return total_ants def evaluation1(self): ##creat a empty grid to store currently information total_ants = np.zeros((WIDTH, HEIGHT)) ## count the number of currently information for (agents, i, j) in self.grid.coord_iter(): if type(agents) is Ant: total_ants[i][j] = 1 else: total_ants[i][j] = 0 ##update the tau self.tau = self.tau + total_ants ##calcualte the mean tau self.mean_tau_ant = self.tau.sum() / ((WIDTH - 2)**2) return self.mean_tau_ant def evaluation2(self): ## we need to minus the mean tau so we need to ensure the result of boundary is zero ## so we let the bounday equal mean_tau_ant in this way the (tau-mean_tau_ant) is zero of boundary for site in self.bound_vals: self.tau[site[0]][site[1]] = self.mean_tau_ant ## calculate the sigmaa self.sigma = ((self.tau - self.mean_tau_ant)**2).sum() / ( (WIDTH - 2)**2) ## rechange the boundaryy for site in self.bound_vals: self.tau[site[0]][site[1]] = 0 return np.sqrt(self.sigma) def evaluation3(self): ## calculate the sigmastar self.sigmastar = np.sqrt(self.sigma) / self.mean_tau_ant return self.sigmastar
class Schelling(Model): """Model class for the Schelling segregation model.""" def __init__( self, height=20, width=20, density=0.8, minority_pc=0.2, homophily=3, education_boost=0, education_pc=0.2, seed=None, ): """Seed is used to set randomness in the __new__ function of the Model superclass.""" # pylint: disable-msg=unused-argument,super-init-not-called self.height = height self.width = width self.density = density self.minority_pc = minority_pc self.homophily = homophily self.education_boost = education_boost self.education_pc = education_pc self.schedule = RandomActivation(self) self.grid = SingleGrid(height, width, torus=True) self.happy = 0 self.datacollector = DataCollector( {"happy": "happy"}, # Model-level count of happy agents # For testing purposes, agent's individual x and y { "x": lambda a: a.pos[0], "y": lambda a: a.pos[1] }, ) # Set up agents # We use a grid iterator that returns # the coordinates of a cell as well as # its contents. (coord_iter) for cell in self.grid.coord_iter(): x_coord = cell[1] y_coord = cell[2] if self.random.random() < self.density: if self.random.random() < self.minority_pc: agent_type = 1 else: agent_type = 0 agent_homophily = homophily if self.random.random() < self.education_pc: agent_homophily += self.education_boost agent = SchellingAgent((x_coord, y_coord), self, agent_type, agent_homophily) self.grid.position_agent(agent, (x_coord, y_coord)) self.schedule.add(agent) self.running = True self.datacollector.collect(self) def step(self): """Run one step of the model. If All agents are happy, halt the model.""" self.happy = 0 # Reset counter of happy agents self.schedule.step() # collect data self.datacollector.collect(self) if self.happy == self.schedule.get_agent_count(): self.running = False
class SeparationBarrierModel(Model): def __init__(self, height, width, palestinian_density, settlement_density, settlers_violence_rate, settlers_growth_rate, suicide_rate, greed_level, settler_vision=1, palestinian_vision=1, movement=True, max_iters=1000): super(SeparationBarrierModel, self).__init__() self.height = height self.width = width self.palestinian_density = palestinian_density self.settler_vision = settler_vision self.palestinian_vision = palestinian_vision self.settlement_density = settlement_density self.movement = movement self.running = True self.max_iters = max_iters self.iteration = 0 self.schedule = RandomActivation(self) self.settlers_violence_rate = settlers_violence_rate self.settlers_growth_rate = settlers_growth_rate self.suicide_rate = suicide_rate self.greed_level = greed_level self.total_violence = 0 self.grid = SingleGrid(height, width, torus=False) model_reporters = { } agent_reporters = { # "x": lambda a: a.pos[0], # "y": lambda a: a.pos[1], } self.dc = DataCollector(model_reporters=model_reporters, agent_reporters=agent_reporters) self.unique_id = 0 # Israelis and palestinans split the region in half for (contents, x, y) in self.grid.coord_iter(): if random.random() < self.palestinian_density: palestinian = Palestinian(self.unique_id, (x, y), vision=self.palestinian_vision, breed="Palestinian", model=self) self.unique_id += 1 self.grid.position_agent(palestinian, x,y) self.schedule.add(palestinian) elif ((y > (self.grid.height) * (1-self.settlement_density)) and random.random() < self.settlement_density): settler = Settler(self.unique_id, (x, y), vision=self.settler_vision, model=self, breed="Settler") self.unique_id += 1 self.grid.position_agent(settler, x,y) self.schedule.add(settler) def add_settler(self, pos): settler = Settler(self.unique_id, pos, vision=self.settler_vision, model=self, breed="Settler") self.unique_id += 1 self.grid.position_agent(settler, pos[0], pos[1]) self.schedule.add(settler) def set_barrier(self,victim_pos, violent_pos): #print("Set barrier - Greed level", self.greed_level) visible_spots = self.grid.get_neighborhood(victim_pos, moore=True, radius=self.greed_level + 1) furthest_empty = self.find_furthest_empty_or_palestinian(victim_pos, visible_spots) x,y = furthest_empty current = self.grid[y][x] #print ("Set barrier!!", pos, current) free = True if (current is not None and current.breed == "Palestinian"): #print ("Relocating Palestinian") free = self.relocate_palestinian(current, current.pos) if (free): barrier = Barrier(-1, furthest_empty, model=self) self.grid.position_agent(barrier, x,y) # Relocate the violent palestinian #violent_x, violent_y = violent_pos #if violent_pos != furthest_empty: # violent_palestinian = self.grid[violent_y][violent_x] # self.relocate_palestinian(violent_palestinian, furthest_empty) def relocate_palestinian(self, palestinian, destination): #print ("Relocating Palestinian in ", palestinian.pos, "To somehwhere near ", destination) visible_spots = self.grid.get_neighborhood(destination, moore=True, radius=palestinian.vision) nearest_empty = self.find_nearest_empty(destination, visible_spots) #print("First Nearest empty to ", palestinian.pos, " Is ", nearest_empty) if (nearest_empty): self.grid.move_agent(palestinian, nearest_empty) else: #print ("Moveing to random empty") if (self.grid.exists_empty_cells()): self.grid.move_to_empty(palestinian) else: return False return True def find_nearest_empty(self, pos, neighborhood): nearest_empty = None sorted_spots = self.sort_neighborhood_by_distance(pos, neighborhood) index = 0 while (nearest_empty is None and index < len(sorted_spots)): if self.grid.is_cell_empty(sorted_spots[index]): nearest_empty = sorted_spots[index] index += 1 return nearest_empty def find_furthest_empty_or_palestinian(self, pos, neighborhood): furthest_empty = None sorted_spots = self.sort_neighborhood_by_distance(pos, neighborhood) sorted_spots.reverse() index = 0 while (furthest_empty is None and index < len(sorted_spots)): spot = sorted_spots[index] if self.grid.is_cell_empty(spot) or self.grid[spot[1]][spot[0]].breed == "Palestinian" : furthest_empty = sorted_spots[index] index += 1 return furthest_empty def sort_neighborhood_by_distance(self, from_pos, neighbor_spots): from_x, from_y = from_pos return sorted(neighbor_spots, key = lambda spot: self.eucledean_distance(from_x, spot[0], from_y, spot[1], self.grid.width, self.grid.height)) def eucledean_distance(self, x1,x2,y1,y2,w,h): # http://stackoverflow.com/questions/2123947/calculate-distance-between-two-x-y-coordinates return math.sqrt(min(abs(x1 - x2), w - abs(x1 - x2)) ** 2 + min(abs(y1 - y2), h - abs(y1-y2)) ** 2) def step(self): """ Advance the model by one step and collect data. """ self.violence_count = 0 # for i in range(100): self.schedule.step() self.total_violence += self.violence_count # average = self.violence_count / 100 #print("Violence average %f " % average) print("Total Violence: ", self.total_violence)
class EconomicSystemModel(Model): """ A simple model of an economic system. All agents begin with certain revenue, each time step the agents execute its expenditures and sell its production. If they retain a healthy revenue, they can choose to hire and grow; otherwise they can choose to shrink; if too much debt is acquired the agent goes bankrupt. Let's see what happens to the system. """ def __init__(self, width=10, height=10, industry_pc=0.8, services_pc=0.6, tax_industry=0.1, tax_services=0.2, nsteps=60): """ Initialization method of economic system model class Parameters ---------- width : int Grid width height : int Grid height industry_pc : float Industry percentage in the system services_pc : float Services percentage in the industry tax_industry : float Tax rate for industry sector tax_services : float Tax rate for services sector nsteps : int Number of time steps in months """ # Model input attributes self.width = width self.height = height self.industry_pc = industry_pc self.services_pc = services_pc self.nsteps = nsteps # Order in which agents perform their steps, # random activation means no particular preference self.schedule = RandomActivation(self) # Grid initialization self.grid = SingleGrid(width, height, torus=True) # Data to be located per time step self.datacollector = DataCollector(model_reporters={ "GDP": compute_gdp, "Employment": compute_employment }, agent_reporters={ "Employees": "employees", "Value": "value", "Industry": "type" }) # Set up agents using a grid iterator that returns # the coordinates of a cell as well as its contents for cell in self.grid.coord_iter(): # Cell coordinates x = cell[1] y = cell[2] # Assign industry type if self.random.random() < self.industry_pc: if self.random.random() < self.services_pc: agent_type = 1 else: agent_type = 0 # Initialize agent tax_rates = [tax_industry, tax_services] agent = IndustryAgent((x, y), self, agent_type, tax_rates) self.grid.position_agent(agent, (x, y)) self.schedule.add(agent) # Running set to true and collect initial conditions self.running = True self.datacollector.collect(self) # Computed initial conditions of the model self.gdp = compute_gdp(self) self.employment = compute_employment(self) self.max_size_services = max_size_industry(self, 1) self.max_size_industry = max_size_industry(self, 0) self.max_size_industries = max_size_industry(self, -2) def step(self): ''' Method to run one time step of the model ''' # Run time step self.schedule.step() # Collect data self.datacollector.collect(self) # Computed metrics self.gdp = compute_gdp(self) self.employment = compute_employment(self) self.max_size_services = max_size_industry(self, 1) self.max_size_industry = max_size_industry(self, 0) self.max_size_industries = max_size_industry(self, -2) # Halt model after maximum number of time steps if self.schedule.steps == self.nsteps: self.running = False
class Schelling(Model): ''' Define the Model The other core class ''' ''' mesa/space.py/Grid has 3 properties: - width - height - torus So `minority_pc` and `homophily` are customized properties here. ''' def __init__(self, height=20, width=20, density=0.8, minority_pc=0.2, homophily=3): self.height = height self.width = width self.density = density self.minority_pc = minority_pc self.homophily = homophily # Scheduler is used `RandomActivation`, which is defined in mesa/time.py/RandomActivation. # Specify *time* of the model. self.schedule = RandomActivation(self) # `SingleGrid` is defined in mesa/space.py/SingleGrid. # Grid which strictly enforces one object per cell. # Specify *space* of the model. # width, height, torus are the native properties. self.grid = SingleGrid(width, height, torus=True) # Without happy agents initially self.happy = 0 # DataCollector collects 3 types of data: # model-level data, agent-level data, and tables # A DataCollector is instantiated with 2 dictionaries of reporter names and associated variable names or functions for each, one for model-level data and one for agent-level data; a third dictionary provides table names and columns. Variable names are converted into functions which retrieve attributes of that name. self.datacollector = DataCollector( { 'happy': 'happy' }, # Model-level count of happy agents, only one agent-level reporter # For testing purposes, agent’s individual x and y # lambda function, it is like: # lambda x, y: x ** y { 'x': lambda a: a.pos[0], 'y': lambda a: a.pos[1] }, ) # Set up agents # We use grid iterator that returns # the coordinates of a cell as well # as its contents. (coord_iter) # coord_iter is defined in mesa/space.py, which, which returns coordinates as well as cell contents. for cell in self.grid.coord_iter(): # Grid cells are indexed by [x][y] (tuple), where [0][0] is assumed to be the bottom-left and [width-1][height-1] is the top-right. If a grid is toroidal, the top and bottom, and left and right, edges wrap to each other. x = cell[1] y = cell[2] if self.random.random() < self.density: if self.random.random() < self.minority_pc: agent_type = 1 else: agent_type = 0 agent = SchellingAgent((x, y), self, agent_type) # position_agent is defined in mesa/space.py. Position an agent on the grid. This is used when first placing agents! self.grid.position_agent(agent, (x, y)) # schedule.add() method is defined in mesa/time.py. # Add an Agent object to the schedule. # # Aggs: # agent: An Agent to be added to the schedule. Note: the agent must have a step() method. self.schedule.add(agent) self.running = True # datacollector.collect() method is defined in mesa/datacollection.py. When the collect(…) method is called, it collects these attributes and executes these functions one by one and store the results. self.datacollector.collect(self) # Oh, I did’t understand step(…) method previously. Now I know as a consequential method, it executes all stages for all agents. def step(self): ''' Run one step of the model. If all agents are happy, halt the model. ''' self.happy = 0 # Reset counter of happy agents self.schedule.step() # collect data self.datacollector.collect(self) # Method get_agent_count is defined in mesa/time.py. It returns the current number agents in the queue. if self.happy == self.schedule.get_agent_count(): self.running = False
class SIRModel(Model): '''Description of the model''' def __init__(self, width, height, infectivity=2.0, infection_duration = 10, immunity_duration = 15, mutation_probability=0, mutation_strength=10, visualise_each_x_timesteps=-1): # Set the model parameters self.infectivity = infectivity # Infection strength per infected individual self.infection_duration = infection_duration # Duration of infection self.immunity_duration = immunity_duration # Duration of infection #mutations self.mutation_probability = mutation_probability self.mutation_strength = mutation_strength #self.mean_inf_duration_list = [] percentage_starting_infected = 0.01 percentage_starting_recovered = 0.01 self.visualise_each_x_timesteps = visualise_each_x_timesteps self.grid = SingleGrid(width, height, torus=False) self.schedule = SimultaneousActivation(self) for (contents, x, y) in self.grid.coord_iter(): # Place randomly generated individuals rand = random.random() cell = Cell((x,y), self) # place random infected cells with a chance if rand < percentage_starting_infected: cell.initialise_as_infected() # place random infected cells with a chance elif rand < percentage_starting_infected + percentage_starting_recovered: cell.initialise_as_recovered() self.grid.place_agent(cell, (x,y)) self.schedule.add(cell) # Add data collector, to plot the number of individuals of different types self.datacollector_cells = DataCollector(model_reporters={ "Infected": fracI, "Susceptible": fracS, "Recovered": fracR, }) # Add data collector, to plot the mean infection duration self.datacollector_meaninfectionduration = DataCollector(model_reporters={"Mean_inf_duration": compute_mean_infduration}) # collects grids per amount of time steps self.grids_saved = [] self.running = True def get_grid_cells(self): return np.array([cell.state for cell in self.schedule.agents]) def step(self): # collect grids for running without browser if self.visualise_each_x_timesteps != -1: if self.schedule.time % self.visualise_each_x_timesteps == 0: print(f'timestep: {self.schedule.time}, saved grid.') self.grids_saved.append(self.get_grid_cells()) self.datacollector_cells.collect(self) self.datacollector_meaninfectionduration.collect(self) self.schedule.step()
class Schelling(Model): ''' Model class for the Schelling segregation model. This class has been modified from the original model of mesa. Complexity has been added such that the model be used with a model of the policy making process. ''' def __init__(self, height=20, width=20, density=0.8, minority_pc=0.2, homophilyType0=0.5, homophilyType1=0.5, movementQuota=0.30, happyCheckRadius=5, moveCheckRadius=5): ''' ''' self.height = height self.width = width self.density = density self.minority_pc = minority_pc self.homophilyType0 = homophilyType0 self.homophilyType1 = homophilyType1 self.movementQuota = movementQuota self.happyCheckRadius = happyCheckRadius self.moveCheckRadius = moveCheckRadius self.schedule = RandomActivation(self) self.grid = SingleGrid(height, width, torus=True) self.happy = 0 self.stepCount = 0 self.evenness = 0 self.empty = 0 self.type0agents = 0 self.type1agents = 0 self.movementQuotaCount = 0 self.numberOfAgents = 0 self.datacollector = DataCollector( # Model-level count of happy agents { "step": "stepCount", "happy": "happy", "evenness": "evenness", "numberOfAgents": "numberOfAgents" }, # For testing purposes, agent's individual x and y { "x": lambda a: a.pos[0], "y": lambda a: a.pos[1] }) # Set up agents # We use a grid iterator that returns # the coordinates of a cell as well as # its contents. (coord_iter) for cell in self.grid.coord_iter(): x = cell[1] y = cell[2] if self.random.random() < self.density: if self.random.random() < self.minority_pc: agent_type = 1 else: agent_type = 0 agent = SchellingAgent((x, y), self, agent_type) self.grid.position_agent(agent, (x, y)) self.schedule.add(agent) print("Schedule", len(self.schedule.agents)) self.running = True self.numberOfAgents = self.schedule.get_agent_count() self.datacollector.collect(self) def step(self): ''' Run one step of the model. If All agents are happy, halt the model. Note on the eveness paramater calculation: It cannot be performed in the step function of the agents as then it would not take consider periods of time during which the agents are still moving, making the parameter calculation inaccurate. ''' self.happy = 0 # Reset counter of happy agents self.empty = 0 # Reset counter of empty cells self.type0agents = 0 # Reset count of type 0 agents self.type1agents = 0 # Reset count of type 1 agents self.movementQuotaCount = 0 # Reset count of the movement quota # run the step for the agents self.schedule.step() print(self.movementQuotaCount, " agents moved.") print(round(self.happy / self.schedule.get_agent_count() * 100, 2), "percent are happy agents.") # calculating empty counter self.empty = (self.height * self.width) - self.schedule.get_agent_count() # calculating type 0 and type 1 agent numbers for agent in self.schedule.agent_buffer(shuffled=True): if agent.type == 0: self.type0agents += 1 if agent.type == 1: self.type1agents += 1 # calculation of evenness (segregation parameter) using Haw (2015). self.evenness_calculation() # iterate the steps counter self.stepCount += 1 # collect data self.datacollector.collect(self) if self.happy == self.schedule.get_agent_count(): self.running = False print("All agents are happy, the simulation ends!") def evenness_calculation(self): ''' To calculate the evenness parameter, one needs to first subdivide the grid into areas of more than one square each. The evenness will be then calculated based on the distribution of type 0 and type 1 agents in each of these areas. The division into area needs to be done carefully as it depends on the inputs within the model (width and height of the grid). ''' # check for a square grid if self.height != self.width: self.running = False print( "WARNING - The grid is not a square, please insert the same width and height" ) # reset the evenness parameter self.evenness = 0 # algorithm to calculate evenness n = 4 # number of big areas considered in width and height if self.height % n == 0: # consider all big areas for big_dy in range(n): for big_dx in range(n): # looking within one big areas, going through all cells listAgents = [] for small_dy in range(int(self.height / n)): for small_dx in range(int(self.height / n)): for agents in self.schedule.agent_buffer( shuffled=True): if agents.pos == (self.height / n * big_dx + small_dx, self.height / n * big_dy + small_dy): listAgents.append(agents) # calculating evenness for each big area countType0agents = 0 # Reset of the type counter for type 0 agents countType1agents = 0 # Reset of the type counter for type 1 agents # checking the type of agents in the big area for agents in listAgents: if agents.type == 0: countType0agents += 1 if agents.type == 1: countType1agents += 1 self.evenness += 0.5 * abs( (countType0agents / self.type0agents) - (countType1agents / self.type1agents)) print("evenness :", round(self.evenness, 2))
class EconMod(Model): ''' Model class for arming model. ''' def __init__(self, height, width, density, domestic_min, domestic_max, domestic_mean, domestic_sd, num_adversaries, expenditures): ''' ''' self.height = height self.width = width self.density = density self.domestic_min = domestic_min self.domestic_max = domestic_max self.domestic_mean = domestic_mean self.domestic_sd = domestic_sd self.num_adversaries = num_adversaries self.expenditures = expenditures self.schedule = RandomActivation(self) # All agents act at once self.grid = SingleGrid(height, width, torus=True) self.datacollector = DataCollector( # Collect data on each agent's arms levels agent_reporters = { "Arms": "arms", "Military_Burden": "mil_burden", "Econ": "econ", "Domestic": "domestic" }) # Set up agents for cell in self.grid.coord_iter(): x = cell[1] y = cell[2] if random.random() < self.density: ## Set starting economy for all ##econ_start = 10 # Draw from pareto -- parameter set to 3, arbitrary econ_start = pareto.rvs(3,1) econ_growth = 0.03 # domestic need -- determines econ variation #domestic_need = np.random.uniform( # self.domestic_min, # self.domestic_max # ) #https://stackoverflow.com/questions/18441779/how-to-specify-upper-and-lower-limits-when-using-numpy-random-normal lower, upper = self.domestic_min, self.domestic_max mu, sigma = self.domestic_mean, self.domestic_sd X = truncnorm( (lower - mu) / sigma, (upper - mu) / sigma, loc=mu, scale=sigma) domestic_need = X.rvs(1) expenditures = self.expenditures # starting percent of wealth spent on weapons arms_start_perc = np.random.uniform(0, 0.06) arms = arms_start_perc * econ_start # create agent agent = state((x, y), self, econ_start = econ_start, econ_growth = econ_growth, arms = arms, domestic_need = domestic_need, num_adversaries = num_adversaries, expenditures = expenditures) # place agent in grid self.grid.position_agent(agent, (x, y)) # add schedule self.schedule.add(agent) self.running = True self.datacollector.collect(self) def step(self): ''' Run one step of the model. ''' # Collect data self.datacollector.collect(self) self.schedule.step()
class Schelling(Model): """ Model class for the Schelling segregation model. Parameters ---------- height : int height of grid width : int height of width density : float fraction of grid cells occupied minority_fraction : float fraction of agent of minority color tolerance_threshold : int Attributes ---------- height : int width : int density : float minority_fraction : float schedule : RandomActivation instance grid : SingleGrid instance """ def __init__(self, height=20, width=20, density=0.8, minority_fraction=0.2, tolerance_threshold=4, seed=None): super().__init__(seed=seed) self.height = height self.width = width self.density = density self.minority_fraction = minority_fraction self.schedule = RandomActivation(self) self.grid = SingleGrid(width, height, torus=True) self.datacollector = DataCollector( model_reporters={'happy': count_happy}) # Set up agents # We use a grid iterator that returns # the coordinates of a cell as well as # its contents. (coord_iter) for cell in self.grid.coord_iter(): x = cell[1] y = cell[2] if self.random.random() < self.density: if self.random.random() < self.minority_fraction: agent_color = Color.RED else: agent_color = Color.BLUE agent = SchellingAgent((x, y), self, agent_color, tolerance_threshold) self.grid.position_agent(agent, (x, y)) self.schedule.add(agent) def step(self): """ Run one step of the model. """ self.schedule.step() self.datacollector.collect(self)
class SchellingModel(Model): '''Model class for Schelling segregation model''' def __init__(self, height=20, width=20, density=.8, group_ratio=.66, minority_ratio=.5, homophily=3): self.height = height self.width = width self.density = density self.group_ratio = group_ratio self.minority_ratio = minority_ratio self.homophily = homophily self.happy = 0 self.segregated = 0 self.schedule = RandomActivation(self) self.grid = SingleGrid(height, width, torus=False) self.place_agents() self.datacollector = DataCollector( {'happy': (lambda m: m.happy), 'segregated': (lambda m: m.segregated)}) self.running = True def step(self): '''Run one step of model''' self.schedule.step() self.calculate_stats() self.datacollector.collect(self) if self.happy == self.schedule.get_agent_count(): self.running = False def place_agents(self): for cell in self.grid.coord_iter(): x, y = cell[1:3] if random.random() < self.density: if random.random() < self.group_ratio: if random.random() < self.minority_ratio: group = 0 else: group = 1 else: group = 2 agent = SchellingAgent((x,y), group) self.grid.position_agent(agent, (x,y)) self.schedule.add(agent) for agent in self.schedule.agents: count = 0 for neighbour in self.grid.iter_neighbors(agent.pos, moore=False): if neighbour.group == agent.group: count += 1 agent.similar = count def calculate_stats(self): happy_count = 0 avg_seg = 0 for agent in self.schedule.agents: avg_seg += agent.similar if agent.similar >= self.homophily: happy_count += 1 self.happy = happy_count self.segregated = avg_seg/self.schedule.get_agent_count()