class NormModel(Model): def __init__(self, size): self.num_agents = size self.num_nodes = self.num_agents # self.G = the_network[0] self.G = another_network self.grid = NetworkGrid(self.G) self.schedule = SimultaneousActivation(self) self.running = True for i, node in enumerate(self.G.nodes()): a = NormAgent(i, self) self.schedule.add(a) self.grid.place_agent(a, node) self.datacollector = DataCollector( model_reporters={ "PerHate": percent_haters, "AverageSens": average_sensitivity, }, agent_reporters={"Hate": "behavior"}) def step(self): self.datacollector.collect(self) self.schedule.step() if percent_haters( self ) > 0.8: # When the percentage of haters in the model exceeds 80, self.running = False # the simulation is stopped, data collected, and next one is started.
class EpidexusModel(Model): """The main simulation model. This is the entry point for MESA-based simulations. """ def __init__(self, start_date: datetime, sim_time_step=timedelta(minutes=15)): self.schedule = SimultaneousActivation(self) self.current_date = start_date self.sim_time_step = sim_time_step self.datacollector = DataCollector(model_reporters={"S": self.report_s, "E": self.report_e, "I": self.report_i, "R": self.report_r}) self.seir_counts = [0, 0, 0, 0] logging.basicConfig(filename='debug.log',level=logging.DEBUG) logging.info("-- Started Epidexus Simulation --") logging.info("Current date: " + str(self.current_date)) logging.info("Simulation time step: " + str(self.sim_time_step)) logging.info("---------------------------------") def step(self): last_date = copy(self.current_date) self.current_date = self.current_date + self.sim_time_step # Report SEIR only once a day if self.current_date.date() > last_date.date(): self.count_seir() self.datacollector.collect(self) self.schedule.step() def add_person(self, person: Agent): self.schedule.add(person) logging.debug("Added person: " + str(person)) def count_seir(self): """Count the agents in each bin. Run this function before the report_x functions to update the counts. This is to avoid iterating over all agent for each of the four reporters. """ self.seir_counts = [0, 0, 0, 0] for a in self.schedule.agents: self.seir_counts[a.infection_state.seir.value] += 1 def report_s(self, model): return self.seir_counts[0] def report_e(self, model): return self.seir_counts[1] def report_i(self, model): return self.seir_counts[2] def report_r(self, model): return self.seir_counts[3]
class SimulationModel(Model): def __init__(self, x_max, y_max, species, iterations): super(SimulationModel, self).__init__() self.starved = 0 self.space = ContinuousSpace(x_max, y_max, grid_width=20, grid_height=20, torus=True) self.schedule = SimultaneousActivation(self) self.iterations = iterations self.species = [] self.create_population(species) def create_population(self, species): for specie, lamarck, params in species: individuals = [] for param in params: individuals.append( self.create_individual(specie, lamarck, param)) self.schedule.add(individuals[-1]) self.species.append(individuals) def create_individual(self, specie, lamarck, param): x = random.random() * self.space.x_max y = random.random() * self.space.y_max ind = specie(self.space, x, y, lamarck, param) self.space.place_agent(ind, ind.pos) return ind def step(self): self.schedule.step() self.cleanup_corpses() self.update_iterations() def update_iterations(self): self.iterations -= 1 if not self.iterations: self.running = False def cleanup_corpses(self): for agent in filter(t_matcher(AutonomicAgent), self.schedule.agents): if agent.energy <= 0: self.schedule.remove(agent) # noinspection PyProtectedMember self.space._remove_agent(agent.pos, agent) self.starved += 1 def results(self): def get_energy(individual): return individual.eaten, individual.energy def get_energies(specie): return map(get_energy, specie) return map(get_energies, self.species)
class MoniModel(Model): """ A model for monitoring agents """ def __init__(self, N, width, height): #Monitoring space self.width = width self.height = height self.grid = MultiGrid(height, width, False) #non toroidal grid self.schedule = SimultaneousActivation(self) self.abCount = 0 #initial abnormality count self.detectedAb = 0 self.interactionCount = 0 # ============================================================================= # self.coveredArea = [] # self.interactionRateAverage = 0 # self.coveragePercentage = 0 # self.coveragePercentageAverage = 0 # ============================================================================= # Create agents self.num_agents = N for i in range(self.num_agents): x = floor(self.width / N * i + self.width / N / 2) # create and add agent with id number i to the scheduler a = MoniAgent(i, self) self.schedule.add(a) #place agent at the center of its limit coor self.grid.place_agent(a, (x, 0)) # this part is for visualization only # self.running = True def step(self): # self.interactionCount = 0 self.schedule.step() def run_model(self, n): for i in range(n): # self.initPos() self.step() # print(self.schedule.steps) """ Calculate fitness of a swarm (success ratio) """ def fitness(self): for _ in range(100): self.step() if self.abCount == 0: self.abCount = 1 #avoid division by 0 error # return self.detectedAb/self.abCount return (sum(self.schedule.agents[0].genome))
class HexSnowflake(Model): ''' Represents the hex grid of cells. The grid is represented by a 2-dimensional array of cells with adjacency rules specific to hexagons. ''' def __init__(self, height=50, width=50, server = True, num_steps = 1000): ''' Create a new playing area of (height, width) cells. ''' # Set up the grid and schedule. # Use SimultaneousActivation which simulates all the cells # computing their next state simultaneously. This needs to # be done because each cell's next state depends on the current # state of all its neighbors -- before they've changed. self.schedule = SimultaneousActivation(self) self.num_steps = num_steps # Use a hexagonal grid, where edges wrap around. self.grid = HexGrid(height, width, torus=True) self.server = server # Place a dead cell at each location. for (contents, x, y) in self.grid.coord_iter(): cell = Cell((x, y), self) self.grid.place_agent(cell, (x, y)) self.schedule.add(cell) # activate the center(ish) cell. centerishCell = self.grid[width // 2][height // 2] centerishCell.state = 1 for a in centerishCell.neighbors: a.isConsidered = True self.running = True #Datacollector -- default for this model is no data collection, but one can use OABM to assign one. #so this is an empty DataCollector instance from MESA self.datacollector = DataCollector() def step(self): ''' Have the scheduler advance each cell by one step ''' self.schedule.step() def run_model(self, n = None): if n: self.num_steps = n if self.server == False: for _ in range(self.num_steps): self.step() return self else: from .server import server server.launch()
class Oundahodou(Model): """これはモデル 連続空間に配置する""" def __init__(self): self.num_agents = 20 self.num_kabe = 1 self.schedule = SimultaneousActivation(self) self.width = 10 self.height = 50 self.space = ContinuousSpace(self.width, self.height, True) self.syudan_hito = np.zeros((self.num_agents, 2)) self.syudan_kabe = np.zeros((self.num_kabe, 2)) self.time = 1000 # Create agents for i in range(self.num_agents): a = Hokousya(i, self) self.schedule.add(a) self.syudan_hito[i, 0] = a.iti_x self.syudan_hito[i, 1] = a.iti_y #壁を作る for i in range(self.num_kabe): b = Kabe(i, self) self.schedule.add(b) self.syudan_kabe[i, 0] = b.iti[0] self.syudan_kabe[i, 1] = b.iti[1] def make_agents(self): """途中からアクティブになるエージェントの作成""" def step(self): '''Advance the model by one step.''' self.schedule.step() self.dasu_syudan_hito() self.fasu_num_agents() self.dasu_kabe() self.dasu_nu_kabe() """モデル描画を目指す""" #def make_im(self): #for i in range(self.num_agents): #im = ax.plot() def ptint_syudan(self): print(self.syudan) def dasu_syudan_hito(self): return self.syudan_hito def fasu_num_agents(self): return self.num_agents def dasu_kabe(self): return self.syudan_kabe def dasu_nu_kabe(self): return self.num_kabe
class Population(Model): """Population Adapted from https://www.medrxiv.org/content/10.1101/2020.03.18.20037994v1.full.pdf Model Parameters: spread_chance: probability of infection based on contact gamma: mean incubation period alpha: probability of become asymptomatic vs symptomatic gamma_AR: infectious period for asymptomatic people gamma_YR: infectious period for symptomatic people delta: death rate due to disease """ def __init__(self, graph, model_parameters): # Model initialization self.population_size = model_parameters['population_size'] self.initial_outbreak_size = model_parameters['initial_outbreak_size'] self.graph = graph self.grid = NetworkGrid(self.graph) self.schedule = SimultaneousActivation(self) self.datacollector = DataCollector({ "Exposed": count_exposed, "Susceptible": count_susceptible, "Removed": count_removed, "Asymptomatic": count_asymptomatic, "Symptomatic": count_symptomatic }) self.model_parameters = model_parameters for i, node in enumerate(self.graph.nodes()): a = Person(i, self, State.SUSCEPTIBLE, model_parameters) self.schedule.add(a) self.grid.place_agent(a, i) if i % 100 == 0: logger.info("Finished with agent " + str(i)) infected_nodes = self.random.sample(self.graph.nodes(), self.initial_outbreak_size) for a in self.grid.get_cell_list_contents(infected_nodes): a.status = State.EXPOSED self.datacollector.collect(self) print("Model initialized...\n", str(self.model_parameters)) def step(self): self.datacollector.collect(self) self.schedule.step() def run(self, n): for i in range(n): #logger.info("Steps Completed: " + str(i)) #print("Steps completed: ", i) self.step()
class MoneyModel(Model): """A model with some number of agents""" def __init__(self,N,width,height): self.running = True self.num_agents = N self.grid = MultiGrid(width, height, True) #self.schedule = RandomActivation(self) self.schedule = SimultaneousActivation(self) #create agents for i in range(self.num_agents): a = MoneyAgent(i,self) #i becomes the unique id. Use of self here is still a question... self.schedule.add(a) #adding agent to a random grid cell x = random.randrange(self.grid.width) y = random.randrange(self.grid.height) self.grid.place_agent(a,(x,y)) self.datacollector = DataCollector( model_reporters = {"Gini": compute_gini,"Number": "num_agents"}, #a function to call agent_reporters = {"Wealth": "wealth"}) #agent attribute def step(self): '''Ádvance the model by one step''' self.datacollector.collect(self) self.schedule.step() #it shuffles the order of the agents, then activates them all, one at a time. #print(self.unique_id) #print(a.wealth) # ============================================================================= # #empty_model = MoneyModel(10) #initialize model with N = 10 #empty_model.step()#running the model for one step # # ============================================================================= # ============================================================================= #TIME - mesa has a scheduler # # The scheduler is a special model component which controls the order in which agents are activated. # For example, all the agents may activate in the same order every step; their order might be shuffled; # we may try to simulate all the agents acting at the same time; and more. # Mesa offers a few different built-in scheduler classes, with a common interface. # That makes it easy to change the activation regime a given model uses, and see whether it changes the model behavior. # This may not seem important, but scheduling patterns can have an impact on your results [Comer2014]_. # # =============================================================================
class ConwaysGameOfLife(Model): ''' Represents the 2-dimensional array of cells in Conway's Game of Life. ''' def __init__(self, height=50, width=50, server=True): ''' Create a new playing area of (height, width) cells. ''' # Set up the grid and schedule. # Use SimultaneousActivation which simulates all the cells # computing their next state simultaneously. This needs to # be done because each cell's next state depends on the current # state of all its neighbors -- before they've changed. self.schedule = SimultaneousActivation(self) self.server = server # Use a simple grid, where edges wrap around. self.grid = Grid(height, width, torus=True) #Datacollector -- default for this model is no data collection, but one can use OABM to assign one. #so this is an empty DataCollector instance from MESA self.datacollector = DataCollector() # Place a cell at each location, with some initialized to # ALIVE and some to DEAD. for (contents, x, y) in self.grid.coord_iter(): cell = Cell((x, y), self) if self.random.random() < 0.1: cell.state = cell.ALIVE self.grid.place_agent(cell, (x, y)) self.schedule.add(cell) self.running = True def step(self): ''' Have the scheduler advance each cell by one step ''' self.schedule.step() def run_model(self, n=None): if n: self.num_steps = n if self.server == False: for _ in range(self.num_steps): self.step() return self else: from .server import server server.launch()
class Parkur(Model): def __init__(self): super().__init__() self.schedule = SimultaneousActivation(self) self.grid = ContinuousSpace(75, 40, False) ## Creation des agents de base for _ in range(1): a = Walker(self.next_id(), self) self.schedule.add(a) self.grid.place_agent(a, (0, 0)) def step(self): self.schedule.step()
class CampusModel(Model): def __init__(self, N, width, height): self.num_agents = N self.grid = ContinuousSpace(width, height, False) self.schedule = SimultaneousActivation(self) for i in range(self.num_agents): a = StudentAgent(i, self) self.schedule.add(a) x = random.randrange(self.grid.width) y = random.randrange(self.grid.height) self.grid.place_agent(a, (x, y)) def step(self): self.schedule.step()
class ConwayGameOfLifeModel(Model): """ Class describing Conway's game of life using the mesa agent based model framowork The model contains a grid. In each cell of the grid there is an agent. The agent can be dead or alive. At each step of the simulation, the state of the agent can change. The model is responsible of creating the grid and handling the iteration of the simulation """ def __init__(self, grid_height, grid_width, percentage_of_cell_alive): """ Constructor """ self.grid = SingleGrid(grid_width, grid_height, False) self.scheduler = SimultaneousActivation(self) self.number_of_agent = grid_width * grid_height # Creation of all agent for i in range(self.number_of_agent): # Randomly chooses the initial state of the agent (0 is alive and 1 is dead) # We use choices from the random module because it allows us to specify a distribution # (ie. a list of probability for each state). Choices will return a list with ne element # which is our state probability_alive = percentage_of_cell_alive / 100 probability_dead = 1 - probability_alive state = choices([0, 1], [probability_dead, probability_alive])[0] # Creating the agent and adding it to the scheduler agent = CellAgent(i, state, self) self.scheduler.add(agent) # Adding the new agent to the grid agent_coordinates = self.grid.find_empty() self.grid.place_agent(agent, agent_coordinates) # Define if the simulation is running or not self.running = True def step(self): """ Method to advance the model by one step. It will call the step method of each agent. We use a simultaneous scheduler which means we we'll be iterating through all the agent at once to determine their next state and then apply the new state """ self.scheduler.step()
class NormModel(Model): def __init__(self, size, type_no, subset_no): self.num_agents = size self.num_nodes = self.num_agents self.set = str(type_no) self.subset = subset_no self.I = networks_for_use[self.set][self.subset][0] # self.type = str(self.set) self.avg_deg = networks_for_use[self.set][self.subset][1][ 0] # 1st parameter - average node degree self.big_nodes = networks_for_use[self.set][self.subset][1][ 1] # 2nd parameter - degree of highest-degree node self.connectivity = networks_for_use[self.set][self.subset][1][ 2] # 3rd parameter - mean network connectivity self.clustering = networks_for_use[self.set][self.subset][1][ 3] # Network's clustering coeff. self.grid = NetworkGrid(self.I) self.schedule = SimultaneousActivation(self) self.running = True self.step_counter = 1 for i, node in enumerate(self.I.nodes()): a = NormAgent(i, self) self.schedule.add(a) self.grid.place_agent(a, node) print(f"processing network number {self.subset+1}, type {self.set}") self.datacollector = DataCollector( model_reporters={ "PerHate": percent_haters, "NetworkType": network_type, "AveSensitivity": average_sensitivity, "MeanDeg": net_avg_deg, "MaxDeg": net_max_deg, "NetConnect": net_conn, "NetClust": net_clust, "FinalStep": final_step, }, # agent_reporters={"Hate": "behavior"} ) def step(self): self.datacollector.collect(self) self.schedule.step() self.step_counter += 1 if average_sensitivity(self) < 0.1 or self.step_counter > 250: self.running = False
class ColorPatchModel(Model): ''' represents a 2D lattice where agents live ''' def __init__(self, width, height): ''' Create a 2D lattice with strict borders where agents live The agents next state is first determined before updating the grid ''' self._grid = Grid(width, height, torus=False) self._schedule = SimultaneousActivation(self) # self._grid.coord_iter() # --> should really not return content + col + row # -->but only col & row # for (contents, col, row) in self._grid.coord_iter(): # replaced content with _ to appease linter for (_, row, col) in self._grid.coord_iter(): cell = ColorCell((row, col), self, ColorCell.OPINIONS[random.randrange(0, 16)]) self._grid.place_agent(cell, (row, col)) self._schedule.add(cell) self.running = True def step(self): ''' Advance the model one step. ''' self._schedule.step() # the following is a temporary fix for the framework classes accessing # model attributes directly # I don't think it should # --> it imposes upon the model builder to use the attributes names that # the framework expects. # # Traceback included in docstrings @property def grid(self): return self._grid @property def schedule(self): return self._schedule
class SIR_Network_Model(Model): def __init__(self, g=None, outbreak_size=3, si_trans=0.025, ir_trans=0.05): self.schedule = SimultaneousActivation(self) if g is None: g = nx.random_graphs.watts_strogatz_graph(100, 4, 0.05) self.si_trans = si_trans self.ir_trans = ir_trans nodes = g.nodes() agent_nodes = list(map(lambda x: SIR_Agent(x), nodes)) n_map = dict(zip(nodes, agent_nodes)) agent_edges = list(map(lambda e: (n_map[e[0]], n_map[e[1]]) , g.edges())) for agent in agent_nodes: self.schedule.add(agent) # set the initial outbreak for node in sample(list(agent_nodes), outbreak_size): node.state = State.infected self.network = NetworkSpace(agent_nodes, agent_edges) self.dc = DataCollector({"susceptible": lambda m: self.count_state(m, State.susceptible), "infected": lambda m: self.count_state(m, State.infected), "resistant": lambda m: self.count_state(m, State.resistant)}, {"state": lambda a: a.state.value} ) self.dc.collect(self) #initial state self.running = True def step(self): self.schedule.step() self.dc.collect(self) # disease dead? if self.count_state(self, State.infected) == 0: self.running = False @staticmethod def count_state(model,state): count = 0 for agent in model.schedule.agents: if agent.state == state: count +=1 return count
class Population(Model): """Population""" def __init__(self, population_size, initial_outbreak_size, spread_chance): print("Beginning model setup...\n") self.population_size = population_size print("Creating graph...") self.graph = nx.powerlaw_cluster_graph(population_size, 100, 0.5) #self.graph = nx.complete_graph(population_size) print(len(self.graph.edges)) print("Initializing grid...") self.grid = NetworkGrid(self.graph) self.schedule = SimultaneousActivation(self) self.initial_outbreak_size = initial_outbreak_size self.spread_chance = spread_chance print("Initializing data collector...") self.datacollector = DataCollector({ "Infected:": count_infected, "Susceptible:": count_susceptible, "Removed:": count_removed }) for i, node in enumerate(self.graph.nodes()): a = Person(i, self, State.SUSCEPTIBLE, spread_chance) self.schedule.add(a) self.grid.place_agent(a, i) if i % 100 == 0: print("Finished with agent ", i) infected_nodes = self.random.sample(self.graph.nodes(), self.initial_outbreak_size) for a in self.grid.get_cell_list_contents(infected_nodes): a.status = State.INFECTED self.datacollector.collect(self) print("Model initialized...\n") def step(self): self.datacollector.collect(self) self.schedule.step() def run(self, n): for i in range(n): print("Steps completed: ", i) self.step()
class MockModel(Model): """Test model for testing""" def __init__(self, width, height, key1=103, key2=104): self.width = width self.height = height self.key1 = (key1, ) self.key2 = key2 self.schedule = SimultaneousActivation(self) self.grid = Grid(width, height, torus=True) for (c, x, y) in self.grid.coord_iter(): a = MockAgent(x + y * 100, self, x * y * 3) self.grid.place_agent(a, (x, y)) self.schedule.add(a) def step(self): self.schedule.step()
class MockModel(Model): """ Test model for testing """ def __init__(self, width, height, key1=103, key2=104): self.width = width self.height = height self.key1 = key1, self.key2 = key2 self.schedule = SimultaneousActivation(self) self.grid = Grid(width, height, torus=True) for (c, x, y) in self.grid.coord_iter(): a = MockAgent(x + y * 100, self, x * y * 3) self.grid.place_agent(a, (x, y)) self.schedule.add(a) def step(self): self.schedule.step()
class CGoLModel(Model): ''' Represents the 2-dimensional array of cells in Conway's Game of Life. ''' def __init__(self, height, width): ''' Create a new playing area of (height, width) cells. ''' # Set up the grid and schedule. # Use SimultaneousActivation which simulates all the cells # computing their next state simultaneously. This needs to # be done because each cell's next state depends on the current # state of all its neighbors -- before they've changed. self.schedule = SimultaneousActivation(self) # Use a simple grid, where edges wrap around. self.grid = Grid(height, width, torus=True) # Place a cell at each location, with some initialized to # ALIVE and some to DEAD. for (contents, x, y) in self.grid.coord_iter(): pos = (x, y) init_state = CGoLCell.DEAD # Initially, make 10% of the cells ALIVE. if random.random() < 0.1: init_state = CGoLCell.ALIVE cell = CGoLCell(pos, self, init_state) # Put this cell in the grid at position (x, y) self.grid.place_agent(cell, pos) # Add this cell to the scheduler. self.schedule.add(cell) self.running = True def step(self): ''' Advance the model by one step. ''' self.schedule.step()
class ConwaysGameOfLife(Model): """ Represents the 2-dimensional array of cells in Conway's Game of Life. """ def __init__(self, size, **kwargs): """ Create a new playing area of (height, width) cells. """ # Set up the grid and schedule. # Use SimultaneousActivation which simulates all the cells # computing their next state simultaneously. This needs to # be done because each cell's next state depends on the current # state of all its neighbors -- before they've changed. self.schedule = SimultaneousActivation(self) # Use a simple grid, where edges wrap around. self.grid = Grid(size, size, torus=True) # Place a cell at each location, with some initialized to # ALIVE and some to DEAD. for (_contents, x, y) in self.grid.coord_iter(): cell = Cell((x, y), self) if self.random.random() < 0.1: cell.state = cell.ALIVE self.grid.place_agent(cell, (x, y)) self.schedule.add(cell) self.running = True def step(self): """ Have the scheduler advance each cell by one step """ self.schedule.step() def on_click(self, x, y, **kwargs): print(x, y) cell = self.grid[x][y] cell.state = cell.ALIVE
class NormModel(Model): def __init__(self, size, net_type): self.num_agents = size self.num_nodes = self.num_agents self.type = net_type if self.type == 1: self.G, self.avg_degree, self.big_nodes, self.connectivity, self.clustering = netgen_ba( 100, 4) if self.type == 2: self.G, self.avg_degree, self.big_nodes, self.connectivity, self.clustering = netgen_er( 100, .078) if self.type == 3: self.G, self.avg_degree, self.big_nodes, self.connectivity, self.clustering = netgen_rr( 100, 4) self.grid = NetworkGrid(self.G) self.schedule = SimultaneousActivation(self) self.running = True self.step_counter = 1 for i, node in enumerate(self.G.nodes()): a = NormAgent(i, self) self.schedule.add(a) self.grid.place_agent(a, node) self.datacollector = DataCollector( model_reporters={ "PerHate": percent_haters, "AverageSens": average_sensitivity, }, agent_reporters={"Hate": "behavior"}) def step(self): self.datacollector.collect(self) self.schedule.step() self.step_counter += 1 if percent_haters( self ) > 0.35 or self.step_counter > 250: # When the percentage of haters in the model exceeds 80, self.running = False # the simulation is stopped, data collected, and next one is started. # Alternatively: if average_sensitivity(self) < 0.1 or self.step_counter > 250: self.running = False
class HexSnowflake(Model): ''' Represents the hex grid of cells. The grid is represented by a 2-dimensional array of cells with adjacency rules specific to hexagons. ''' def __init__(self, height=50, width=50): ''' Create a new playing area of (height, width) cells. ''' # Set up the grid and schedule. # Use SimultaneousActivation which simulates all the cells # computing their next state simultaneously. This needs to # be done because each cell's next state depends on the current # state of all its neighbors -- before they've changed. self.schedule = SimultaneousActivation(self) # Use a hexagonal grid, where edges wrap around. self.grid = HexGrid(height, width, torus=True) # Place a dead cell at each location. for (contents, x, y) in self.grid.coord_iter(): cell = Cell((x, y), self) self.grid.place_agent(cell, (x, y)) self.schedule.add(cell) # activate the center(ish) cell. centerishCell = self.grid[width // 2][height // 2] centerishCell.state = 1 for a in centerishCell.neighbors: a.isConsidered = True self.running = True def step(self): ''' Have the scheduler advance each cell by one step ''' self.schedule.step()
class CarModel(Model): """A model with some number of agents.""" def __init__(self, car_count, width, acceleration, vision_range, randomization, speed_limit): self.num_agents = car_count self.grid = MultiGrid(width, 1, torus=True) self.schedule = SimultaneousActivation(self) self.running = True # Create agents for i in range(car_count): a = CarAgent(i, self, acceleration, vision_range, randomization, speed_limit) self.schedule.add(a) # Add the agent to a random grid cell ran = random.randrange(0, width) self.grid.place_agent(a, (ran, 0)) def step(self): """ All cars anticipate for next step.""" self.schedule.step()
class NormModel(Model): def __init__(self, size, set_no): self.num_agents = size self.num_nodes = self.num_agents self.set = set_no self.I = networks_for_use[self.set][0] self.net_deg = networks_for_use[self.set][ 1] # 1st parameter - average node degree self.big_nodes = networks_for_use[self.set][ 2] # 2nd parameter - huge networks allowed? self.culling = networks_for_use[self.set][ 3] # 3rd parameter - maximum node degree allowed. only use if # big_nodes = True! self.grid = NetworkGrid(self.I) self.schedule = SimultaneousActivation(self) self.running = True for i, node in enumerate(self.I.nodes()): a = NormAgent(i, self) self.schedule.add(a) self.grid.place_agent(a, node) self.datacollector = DataCollector( model_reporters={ "PerHate": percent_haters, "AveKnowing": percent_hate_knowing, "AveHate": average_hate, "MeanDeg": net_avg_deg, "Culling": net_culling, "MaxDeg": max_deg, }, agent_reporters={"Hate": "behavior"}) def step(self): self.datacollector.collect(self) self.schedule.step() if percent_haters( self ) > 0.8: # When the percentage of haters in the model exceeds 80, self.running = False # the simulation is stopped, data collected, and next one is started.
class ConwaysGameOfLife(Model): ''' Respresents the 2-dimentional array of cells in Conway's Game of Life. ''' def __init__(self, height=50, width=50): ''' Create a new playing area of (height, width) cells. ''' # Set up the grid and schedule. # Use SimultaneousActivation which simulates all the cells # Computing their next state simultaneously. # This needs to be done because each cell's next state depends on # the current state of all its neighbors -- before they've changed self.schedule = SimultaneousActivation(self) # Use a single grid, where edges wrap around. self.grid = Grid(height, width, torus=True) # Place a cell at each location, with some initialized to # ALIVE and some to DEAD for (contents, x, y) in self.grid.coord_iter(): cell = Cell((x, y), self) if self.random.random() < 0.1: cell.state = cell.ALIVE # place_agent: Position an agent on the Grid, and set its pos variable self.grid.place_agent(cell, (x, y)) # add(): Add an agent object to the schedule self.schedule.add(cell) self.running = True def step(self): ''' Have the schedular advance each cell by one step ''' # step(): Execute the step of all the agents, one at a time. self.schedule.step()
class ConwaysGameOfLife(Model): ''' Represents the 2-dimensional array of cells in Conway's Game of Life. ''' def __init__(self, height=50, width=50): ''' Create a new playing area of (height, width) cells. ''' # Set up the grid and schedule. # Use SimultaneousActivation which simulates all the cells # computing their next state simultaneously. This needs to # be done because each cell's next state depends on the current # state of all its neighbors -- before they've changed. self.schedule = SimultaneousActivation(self) # Use a simple grid, where edges wrap around. self.grid = Grid(height, width, torus=True) # Place a cell at each location, with some initialized to # ALIVE and some to DEAD. for (contents, x, y) in self.grid.coord_iter(): cell = Cell((x, y), self) if self.random.random() < 0.1: cell.state = cell.ALIVE self.grid.place_agent(cell, (x, y)) self.schedule.add(cell) self.running = True def step(self): ''' Have the scheduler advance each cell by one step ''' self.schedule.step()
class ForestFireModel(Model): def __init__(self, L, p): super().__init__() self.grid = Grid(L, L, False) self.schedule = SimultaneousActivation(self) self.running = True self.p = p for i in range(L): for j in range(L): if self.random.random() <= self.p: if i == L - 1: tree = TreeAgent((i, j), self, "burning") else: tree = TreeAgent((i, j), self, "occupied") self.schedule.add(tree) self.grid.place_agent(tree, (i, j)) self.datacollector = DataCollector(model_reporters={ "p*": compute_p, "Cluster": compute_cluster }) def step(self): self.schedule.step() if not self.exists_status("burning"): self.datacollector.collect(self) self.running = False def exists_status( self, status ): # function to check is exist any tree which has some status for tree in self.schedule.agents: if tree.status == status: return True
class TOPRAction(Model): """ Represents the 2-dimensional array of cells """ def __init__(self, h=height, w=width): """ Create a action area of (height, width) cells. """ super().__init__() self.height = h self.width = w self.tourists_on_trail = 0 self.frequency = 5 self.steps_of_tourist_1 = 1 self.schedule_tourists = SimultaneousActivation(self) self.schedule_trail_elements = SimultaneousActivation(self) self.step_performed = 1 self.grid = MultiGrid(self.height, self.width, torus=False) self.trail = Trail(self) self.maximum_probability = 0 self.minimum_probability = 1 def step(self): """ Have the scheduler advance each cell by one step """ self.maximum_probability = 0 self.minimum_probability = 1 self.schedule_tourists.step() self.schedule_tourists = SimultaneousActivation(self) for element in self.trail.trail: if type(element) is TrailElement: if element.get_trail_gradient() == self.step_performed: self.schedule_trail_elements.add(element) self.schedule_trail_elements.step() self.step_performed += 1
class Intersection(Model): def __init__(self, **args): """ Setup the intersection :param args: all the parameters """ # @TODO: can/should be made different on different roads super().__init__() # Set parameters self.parameters = [] if 'parameters_as_dict' in args: for field in args['parameters']: setattr(self, field, args['parameters'][field]) self.parameters.append(field) else: for field in args: setattr(self, field, args[field]) self.parameters.append(field) self.roads = [] self.create_roads() self.cars = [] self.cars_removed = 0 self.finished_cars = [] # Visualisation self.bins = list(range(10)) self.is_locked_section = { Direction.NORTH_WEST: False, Direction.NORTH_EAST: False, Direction.SOUTH_WEST: False, Direction.SOUTH_EAST: False, Direction.NORTH: True, Direction.WEST: True, Direction.EAST: True, Direction.SOUTH: True, } self.locked_by = { Direction.NORTH_WEST: None, Direction.NORTH_EAST: None, Direction.SOUTH_WEST: None, Direction.SOUTH_EAST: None } # size 216x216 is big enough to hold 10 cars per lane and the intersection self.size = 216 self.grid = MultiGrid(self.size, self.size, True) self.schedule = SimultaneousActivation(self) self.average_speed = DataCollector( {"Average speed": lambda m: self.get_average_speed()}) self.mean_crossover = DataCollector( {"Mean crossover time": lambda m: self.get_mean_crossover()}) self.mean_crossover_hist = DataCollector({ "Mean crossover histogram": lambda m: self.get_mean_crossover_hist() }) self.throughput = DataCollector( {"Throughput": lambda m: self.get_throughput()}) self.waiting_cars = DataCollector( {"Number of waiting cars": lambda m: self.get_waiting_cars()}) self.number_of_locked_sections = DataCollector({ "Number of locked sections": lambda m: self.get_number_of_locked_sections() }) self.running = True self.average_speed.collect(self) self.mean_crossover.collect(self) self.mean_crossover_hist.collect(self) self.throughput.collect(self) self.waiting_cars.collect(self) self.number_of_locked_sections.collect(self) self.intersection_corners = self.get_intersection_corners() self.visualisations = [] intersection_to_visualisation_function = { 'Fourway': lambda m: fourway_get_visualisations(m), 'Traffic lights': lambda m: trafficlights_get_visualisations(m), 'Equivalent': lambda m: fourway_get_visualisations(m), 'Smart lights': lambda m: trafficlights_get_visualisations(m) } self.visualisation_function = intersection_to_visualisation_function[ self.intersection_type] self.priority_queue = None self.car_per_stopline = {} if self.seed == 0: self.rnd = np.random.RandomState() else: self.rnd = np.random.RandomState(self.seed) self.alpha_factor = 2 self.beta_factor = 5 # If BMW factor of a car is bigger than this value it is a BMW self.bmw_threshold = self.calculate_bmw_threshold() self.smart_lights_counter = 0 self.green_light_direction = None def calculate_bmw_threshold(self): """ Calculates the threshold needed to make `bmw_fraction` of the cars BMWs :return: Float threshold """ data = np.array([ np.random.beta(self.alpha_factor, self.beta_factor) for _ in range(10000) ]) for x in np.arange(0, 1, 0.001): if len(data[data < x]) / len(data) >= 1 - self.bmw_fraction: return x return 1 def section_is_locked(self, direction): """ Check if the section is locked :param direction: Direction to check :return: Boolean """ return self.is_locked_section[direction] def turn_is_locked(self, directions): """ Check if turn is already locked :param directions: The directions associated with the turn :return: Boolean """ for direction in directions: if self.section_is_locked(direction): return True return False def lock_sections(self, directions, car): """ Lock the sections :param directions: Directions associated with the turn :param car: Car that wants to lock the sections :return: None """ for direction in directions: if not self.locked_by[direction] in [None, car]: raise Exception( 'Car tries to lock section which is not his. ' + str(self.locked_by[direction]) + ' != ' + str(car)) self.is_locked_section[direction] = True self.locked_by[direction] = car def unlock_section(self, direction, car): """ Unlock sections :param direction: Direction to unlock :param car: The car that wants to unlock the direction :return: None """ if self.locked_by[direction] in [None, car]: self.is_locked_section[direction] = False self.locked_by[direction] = None else: raise Exception('Car tries to unlock section which is not his. ' + str(self.locked_by[direction]) + ' != ' + str(car)) def get_intersection_corners(self): """ Calculate the corners of the intersection :return: [(top_left_x, top_left_y), (bottom_right_x, bottom_right_y)] """ lane_width = 8 mid_x = self.size // 2 mid_y = self.size // 2 tl_x = mid_x - lane_width tl_y = mid_y + lane_width br_x = mid_x + lane_width br_y = mid_y - lane_width points = [] points.append((tl_x, tl_y)) points.append((br_x, br_y)) return points def create_roads(self): """ Create the roads :return: None """ self.roads.append( Road(self, (103, 215), Direction.SOUTH, self.p_car_spawn_north, [ self.p_north_to_east, self.p_north_to_north, self.p_north_to_west, self.p_north_to_south, ], self.max_speed_vertical)) self.roads.append( Road(self, (0, 103), Direction.EAST, self.p_car_spawn_west, [ self.p_west_to_east, self.p_west_to_north, self.p_west_to_west, self.p_west_to_south, ], self.max_speed_horizontal)) self.roads.append( Road(self, (215, 112), Direction.WEST, self.p_car_spawn_east, [ self.p_east_to_east, self.p_east_to_north, self.p_east_to_west, self.p_east_to_south, ], self.max_speed_horizontal)) self.roads.append( Road(self, (112, 0), Direction.NORTH, self.p_car_spawn_south, [ self.p_south_to_east, self.p_south_to_north, self.p_south_to_west, self.p_south_to_south, ], self.max_speed_vertical)) def step(self): """ Step of the intersection :return: None """ # Let roads add cars to their queue and place the car on the grid if it there is space for road in self.roads: road.step() if road.free_space and len(road.car_queue) > 0: car = road.car_queue.pop() self.schedule.add(car) self.grid.grid[car.pos[0]][car.pos[1]].add(car) car.start_step = self.schedule.steps # Update priority queues if self.intersection_type == 'Fourway': self.update_fourway_priority_queue() elif self.intersection_type == 'Equivalent': self.get_car_per_stopline() self.update_equivalent_priority_queue() # Let cars take a step self.schedule.step() # Collect the data self.average_speed.collect(self) self.throughput.collect(self) self.mean_crossover.collect(self) self.mean_crossover_hist.collect(self) self.waiting_cars.collect(self) self.number_of_locked_sections.collect(self) # Rotate the traffic lights if self.intersection_type == 'Traffic lights': rotate_trafficlights(self) elif self.intersection_type == 'Smart lights': self.smart_traffic_lights() self.visualisation_function(self) def smart_traffic_lights(self): """ Determine which road should get a green light based on the number of cars per road :return: None """ # Calculate cars per road cars_per_road = {} total = 0 for road in self.roads: cars = road.count_cars_before_stopline() total += cars cars_per_road[road.direction] = cars # Set the traffic light of the current green light road to red if there are no more cars on it if self.green_light_direction and cars_per_road[ self.green_light_direction] == 0: self.smart_lights_counter = max(10, self.smart_lights_counter) directions = [ Direction.NORTH, Direction.EAST, Direction.WEST, Direction.SOUTH ] for direction in directions: self.is_locked_section[direction] = True # Determine the next road the should get a green light if self.smart_lights_counter == 0: # If there are no cars on the intersection all lights are red if total == 0: self.green_light_direction = None directions = [ Direction.NORTH, Direction.EAST, Direction.WEST, Direction.SOUTH ] for direction in directions: self.is_locked_section[direction] = True else: # Determine the next road that gets a green light based on probability x = self.rnd.randint(0, total) current_count = 0 for direction, cars in cars_per_road.items(): current_count += cars if x < current_count: self.green_light_direction = direction break directions = [ Direction.NORTH, Direction.EAST, Direction.WEST, Direction.SOUTH ] for direction in directions: self.is_locked_section[direction] = ( direction != self.green_light_direction) # Set counter + 10 (for the last turing car) if self.green_light_direction == Direction.NORTH: self.smart_lights_counter = self.t_from_north + 10 elif self.green_light_direction == Direction.EAST: self.smart_lights_counter = self.t_from_east + 10 elif self.green_light_direction == Direction.SOUTH: self.smart_lights_counter = self.t_from_south + 10 elif self.green_light_direction == Direction.WEST: self.smart_lights_counter = self.t_from_west + 10 else: raise Exception('Invalid green light direction') else: # Set all light to red and keep some time for the last car to turn if self.smart_lights_counter <= 10: directions = [ Direction.NORTH, Direction.EAST, Direction.WEST, Direction.SOUTH ] for direction in directions: self.is_locked_section[direction] = True self.smart_lights_counter -= 1 def update_fourway_priority_queue(self): """ Update priority queue by collecting the time steps each car arrived at the intersection :return: None """ priority_queue = {} for road in self.roads: if road.first: # BMWs take priority if road.first.bmw_factor >= self.bmw_threshold: priority_queue[road.first] = 0 else: priority_queue[road.first] = road.first.stop_step self.priority_queue = priority_queue def get_car_per_stopline(self): """ Get which car is at each stopline :return: """ for road in self.roads: self.car_per_stopline[Direction( (int(road.direction) + 4) % 8)] = road.car_at_stopline() def update_equivalent_priority_queue(self): """ Create the priority queue for an equivalent intersection :return: None """ # Make sure there are cars in the priority queue if len([car for car in self.car_per_stopline.values() if car]) == 0: self.priority_queue = {} return priority_queue = {} # Normal rules for direction, car in self.car_per_stopline.items(): if car: car_to_right = self.car_per_stopline[Direction( (int(direction) + 2) % 8)] car_across = self.car_per_stopline[Direction( (int(direction) + 4) % 8)] priority_queue[car] = True if car_to_right: if car.turn_type == Turn.SHORT: if car_to_right.turn_type == Turn.U: priority_queue[car] = False else: priority_queue[car] = False if car_across and car_across.turn_type == Turn.STRAIGHT: priority_queue[car] = False # BMW takes priority highest_bmw = max([(car, car.bmw_factor) for car in self.car_per_stopline.values() if car], key=lambda x: x[1]) if highest_bmw[1] >= self.bmw_threshold: priority_queue[highest_bmw[0]] = True for _, car in self.car_per_stopline.items(): if car and car != highest_bmw[0]: priority_queue[car] = False self.priority_queue = priority_queue return # Nobody can take priority if len(priority_queue) > 0 and sum([ 1 for _, has_priority in priority_queue.items() if has_priority ]) == 0: cars = [(car, car.stop_step) for car in priority_queue if car.road.first == car] first_cars = [ car for (car, stop_step) in cars if stop_step == min(cars, key=lambda x: x[1])[1] ] if len(first_cars) == 4: # Highest BMW factor takes priority priority_queue[max(priority_queue.keys(), key=(lambda k: priority_queue[k]))] = True else: for car in first_cars: car_to_right = self.car_per_stopline[Direction( (int(car.current_direction) - 2) % 8)] if car_to_right is None or car_to_right.stop_step != car.stop_step: priority_queue[car] = True break self.priority_queue = priority_queue def run_model(self, n=100): for _ in range(n): self.step() def get_average_speed(self): """ Calculate average speed of the cars :return: Float """ number_of_agents = len(self.schedule.agents) if number_of_agents > 0: return sum([agent.velocity for agent in self.schedule.agents]) / number_of_agents return 0 def get_throughput(self): """ Calculate the throughput :return: Float """ if self.schedule.steps > 0: return len(self.finished_cars) / self.schedule.steps return 0 def get_mean_crossover(self): """ Calculate the mean crossover time :return: Float """ if len(self.finished_cars) > 0: return sum([ agent.finish_step - agent.start_step for agent in self.finished_cars ]) / len(self.finished_cars) return 0 def get_mean_crossover_hist(self): """ Create histogram of the mean crossover time :return: Histogram """ if len(self.finished_cars) > 0: crossover_vals = [ agent.finish_step - agent.start_step for agent in self.finished_cars ] hist = np.histogram(crossover_vals, bins=self.bins)[0] return [int(x) for x in hist] return [0] def get_waiting_cars(self): """ Calculate number of waiting cars :return: Integer """ return sum( [1 for agent in self.schedule.agents if agent.velocity == 0]) def get_number_of_locked_sections(self): """ Calculate number of locked sections :return: Integer """ return sum( [1 for s in self.is_locked_section if self.is_locked_section[s]])
class InfoSpread(Model): """A virus model with some number of agents""" def __init__(self, num_nodes=10, avg_node_degree=3, rewire_prob=.1, initial_outbreak_size=1, threshold_fake=2, threshold_real=-2, fake_p=1, real_p=1): self.fake_p = fake_p self.real_p = real_p self.num_nodes = num_nodes self.G = nx.watts_strogatz_graph( n=self.num_nodes, k=avg_node_degree, p=rewire_prob) #G generate graph structure self.grid = NetworkGrid( self.G ) #grid is the Masa native defintion of space: a coorindate with specified topology on which agents sits and interact self.schedule = SimultaneousActivation(self) self.initial_outbreak_size = (initial_outbreak_size if initial_outbreak_size <= num_nodes else num_nodes) self.datacollector = DataCollector({ "Infected_fake": number_infected_fake, "Infected_real": number_infected_real, }) # Create agents for i, node in enumerate(self.G.nodes()): a = User( i, self, 0, #make the state a int threshold_fake, threshold_real) self.schedule.add(a) # Add the agent to the node self.grid.place_agent(a, node) # Infect some nodes, initial infection bug free infected_nodes_fake = self.random.sample(self.G.nodes(), self.initial_outbreak_size) infected_nodes_real = self.random.sample(self.G.nodes(), self.initial_outbreak_size) for a in self.grid.get_cell_list_contents(infected_nodes_fake): a.state = 1 neighbors_nodes = self.grid.get_neighbors(a.pos) for n in self.grid.get_cell_list_contents(neighbors_nodes): n.state = 1 for a in self.grid.get_cell_list_contents(infected_nodes_real): a.state = -1 neighbors_nodes = self.grid.get_neighbors(a.pos) for n in self.grid.get_cell_list_contents(neighbors_nodes): n.state = -1 """ state measures fake score!! the more negative the less likely to spread fake news also this model assumes that 1 one piece of real news can cancel out one piece of fake news This model can be modulated by changing the value of fake and real 2 the inital braeakout size of fake and real news are the same This can be chaged by introducing a different initial breaksize for real and fake news however this score is kepet the same intentionally because too uch complexity is not good for modeling """ self.running = True self.datacollector.collect(self) def proportion_infected_fake(self): try: tot_fake = 0 for i in self.grid.get_cell_list_contents(self.G): if i.state == 1: tot_fake += 1 return tot_fake / self.num_nodes except ZeroDivisionError: return math.inf def proportion_infected_real(self): try: tot_real = 0 for i in self.grid.get_cell_list_contents(self.G): if i.state == -1: tot_real += 1 return tot_real / self.num_nodes except ZeroDivisionError: return math.inf def step(self): self.schedule.step( ) #this model updates with symoutanous schedule, meaning, # collect data self.datacollector.collect(self) def run_model(self, n): ''' could experiment terminating model here too''' for i in range(n): self.step()
class Oundahodou(Model): """これはモデル 連続空間に配置する""" def __init__(self): self.num_agents_sita = 20 self.num_agents_ue = 20 self.num_kabe = 1 self.schedule = SimultaneousActivation(self) self.width = 10 self.height = 50 self.space = ContinuousSpace(self.width, self.height, True) self.syudan_hito_sita = np.zeros((self.num_agents_sita, 2)) self.syudan_hito_ue = np.zeros((self.num_agents_ue, 2)) self.syudan_kabe = np.zeros((self.num_kabe, 2)) self.time = 1000 self.sonzai_ue = np.array([]) self.sonzai_sita = np.array([]) # Create agents エージェントは存在した self.im_x_sita = [] self.im_y_sita = [] self.im_x_ue = [] self.im_y_ue = [] for j in range(self.num_agents_sita): a = Hokousya_sita(j, self) self.syudan_hito_sita[j, 0] = a.iti_x self.syudan_hito_sita[j, 1] = a.iti_y self.schedule.add(a) self.sonzai_sita = np.append(self.sonzai_sita, j) print(a.unique_id, "の下から来るエージェントは生成されました") #self.syudan_hito_sita[i,0] = a.iti_x #self.syudan_hito_sita[i,1] = a.iti_y for i in range(self.num_agents_ue): b = Hokousya_ue(i, self) self.syudan_hito_ue[i, 0] = b.iti_x self.syudan_hito_ue[i, 1] = b.iti_y self.schedule.add(b) self.sonzai_ue = np.append(self.sonzai_ue, i) #self.syudan_hito_ue[i,0] = b.iti_x #self.syudan_hito_ue[i,1] = b.iti_y #壁を作る #for i in range(self.num_kabe): #c = Kabe(i, self) #self.schedule.add(c) #self.syudan_kabe[i, 0] = c.iti[0] #self.syudan_kabe[i, 1] = c.iti[1] def make_agents(self): """途中からアクティブになるエージェントの作成""" def step(self): '''Advance the model by one step.''' self.im_x_sita = [] self.im_y_sita = [] self.im_x_ue = [] self.im_y_ue = [] self.schedule.step() self.dasu_syudan_hito() self.fasu_num_agents() self.dasu_kabe() self.dasu_nu_kabe() """モデル描画を目指す""" #def make_im(self): #for i in range(self.num_agents): #im = ax.plot() def ptint_syudan(self): print(self.syudan) def dasu_syudan_hito(self): self.syudan_hito = np.append(self.syudan_hito_sita, self.syudan_hito_ue, axis=0) return self.syudan_hito def fasu_num_agents(self): return self.num_agents_sita + self.num_agents_ue def dasu_kabe(self): return self.syudan_kabe def dasu_nu_kabe(self): return self.num_kabe
class GentrificationModel(Model): ''' Model class for the Gentrification model. ''' def __init__(self, height, width, depreciation_rate, mobility, status, stat_var, d_factor): # Set model parameters self.depreciation_rate = depreciation_rate self.mobility = mobility self.status = status self.stat_var = stat_var self.d_factor = d_factor self.height = height # Global tracking variables self.mean_income = 0.0 self.schedule = SimultaneousActivation(self) self.grid = SingleGrid(height, width, torus=False) self.datacollector = DataCollector(model_reporters={ "status": lambda m: m.status, "income": lambda m: m.mean_income, "condition": lambda m: m.mean_condition }, agent_reporters={ "x": lambda a: a.pos[0], "y": lambda a: a.pos[1] }) self.running = True self.hit_bottom = False self.last_bottom = 0 self.gent_time = None self.conditions = np.zeros((width, height)) # 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, y = cell[1], cell[2] self.conditions[x, y] = bounded_normal(0.50, 0.1, 0.0, 1.0) # Income initially differs little from property conditions while True: income = self.conditions[x, y] + np.random.normal(0.0, 0.025) if income >= 0.0 and income <= 1.0: self.mean_income += income break agent = PropertyAgent((x, y), self, income) self.grid.position_agent(agent, (x, y)) self.schedule.add(agent) self.mean_condition = np.sum(self.conditions) / self.conditions.size self.mean_income /= self.conditions.size def step(self): ''' Run one step of the model. ''' # For tracking change old_conditions = np.copy(self.conditions) # Initialize change tracking variables self.income_change = 0.0 self.schedule.step() # Update property conditions self.conditions -= self.depreciation_rate self.conditions = np.clip(self.conditions, 0, 1) conditions_change = self.conditions - old_conditions # Update neighborhood status self.status += ((self.income_change + np.sum(conditions_change)) / (conditions_change.size)) self.status += np.random.normal(0.0, self.stat_var) self.status = np.clip(self.status, 0, 1) # Update datacollector variables self.mean_income += self.income_change / self.conditions.size self.mean_condition = np.sum(self.conditions) / self.conditions.size self.datacollector.collect(self) if self.status == 0.0: self.hit_bottom = True self.last_bottom = self.schedule.steps if self.schedule.steps > 2999: # self.gent_time = None self.running = False if (self.status == 1.0 and 0.5 * (self.mean_condition + self.mean_income) > 0.5 and self.hit_bottom == True): self.running = False self.gent_time = (self.schedule.steps - self.last_bottom) / 12
class NaSchTraffic(Model): """ Agent based model of traffic flow, with responsive street lighting. Happiness is measured by the level of lighting in cells occupied by, and ahead of, agents. """ def __init__(self, height=1, width=200, vehicle_density=0.1, general_max_speed=5, p_randomisation=0.4, debug=0, seed=None): """""" super().__init__(seed=seed) self.height = height self.width = width self.vehicle_density = vehicle_density self.general_max_speed = general_max_speed self.p_randomisation = p_randomisation self.debug = debug self.schedule = SimultaneousActivation(self) self.grid = SingleGrid(width, height, torus=True) self.light_range = int(floor(36 / 4.5)) self.lighting_grid = [20] * width self.agent_position_log = [] self.total_street_lights = 0 self.total_speed = 0 self.total_happy = 0 self.total_vehicles = 0 self.total_flow = 0 self.average_speed = 0.0 self.average_happy = 0.0 self.current_density = 0.0 self.average_lighting_level = 0.0 self.speed_averages = [] self.happiness_averages = [] self.densities = [] self.flows = [] self.lighting_averages = [] if self.debug == 1 or self.debug == 3: self.datacollector = DataCollector( model_reporters={ "Average_Speed": "average_speed", # Model-level count of average speed of all agents # "Average_Happiness": "average_happy", # Model-level count of agent happiness "Density": "current_density", "Flow": "total_flow", # "Lighting_Level": "average_lighting_level", "Agent_Positions": "agent_position_log", }, # For testing purposes, agent's individual x position and speed # agent_reporters={ # "PosX": lambda x: x.pos[0], # "Speed": lambda x: x.speed, # }, ) else: self.datacollector = DataCollector( model_reporters={ "Average_Speed": "average_speed", # Model-level count of average speed of all agents # "Average_Happiness": "average_happy", # Model-level count of agent happiness "Density": "current_density", "Flow": "total_flow", # "Lighting_Level": "average_lighting_level", }, ) # Set up agents # Street lights first as these are fixed y = 0 for light_iter in range(0, int(width / self.light_range)): x = light_iter * self.light_range agent = StreetLightAgent((x, y), self, self.light_range) self.schedule.add(agent) self.total_street_lights += 1 if self.debug > 1: print("Added " + str(self.total_street_lights) + " lights") # 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) vehicle_quantity = int(width * self.vehicle_density) for vehicle_iter in range(0, 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) if self.debug > 1: print("Added " + str(vehicle_quantity) + " vehicles") self.running = True self.datacollector.collect(self) def step(self): """ Run one step of the model. Calculate current average speed of all agents. """ self.total_speed = 0 self.total_happy = 0 self.total_vehicles = 0 self.total_flow = 0 self.agent_position_log = [] # Step all agents, then advance all agents self.schedule.step() if self.total_vehicles > 0: self.average_speed = self.total_speed / self.total_vehicles self.average_happy = self.total_happy / self.total_vehicles self.current_density = self.total_vehicles / (self.width * 0.6) else: self.average_speed = 0 self.average_happy = 0 self.current_density = 0 lighting_subset = self.lighting_grid[int(self.width * 0.2):int(self.width * 0.8)] self.average_lighting_level = sum(lighting_subset) / len( lighting_subset) self.speed_averages.append(self.average_speed) # self.happiness_averages.append(self.average_happy) self.densities.append(self.current_density) self.flows.append(float(self.total_flow)) # self.lighting_averages.append(self.average_lighting_level) # collect data self.datacollector.collect(self)
class ColorPatchModel(Model): ''' represents a 2D lattice where agents live ''' def __init__(self, width, height): ''' Create a 2D lattice with strict borders where agents live The agents next state is first determined before updating the grid ''' self._grid = Grid(width, height, torus=False) self._schedule = SimultaneousActivation(self) # self._grid.coord_iter() # --> should really not return content + col + row # -->but only col & row # for (contents, col, row) in self._grid.coord_iter(): # replaced content with _ to appease linter for (_, row, col) in self._grid.coord_iter(): cell = ColorCell((row, col), self, ColorCell.OPINIONS[random.randrange(0, 16)]) self._grid.place_agent(cell, (row, col)) self._schedule.add(cell) self.running = True def step(self): ''' Advance the model one step. ''' self._schedule.step() # the following is a temporary fix for the framework classes accessing # model attributes directly # I don't think it should # --> it imposes upon the model builder to use the attributes names that # the framework expects. # # Traceback included in docstrings @property def grid(self): """ /mesa/visualization/modules/CanvasGridVisualization.py is directly accessing Model.grid 76 def render(self, model): 77 grid_state = defaultdict(list) ---> 78 for y in range(model.grid.height): 79 for x in range(model.grid.width): 80 cell_objects = model.grid.get_cell_list_contents([(x, y)]) AttributeError: 'ColorPatchModel' object has no attribute 'grid' """ return self._grid @property def schedule(self): """ mesa_ABM/examples_ABM/color_patches/mesa/visualization/ModularVisualization.py", line 278, in run_model while self.model.schedule.steps < self.max_steps and self.model.running: AttributeError: 'NoneType' object has no attribute 'steps' """ return self._schedule