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
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 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 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 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 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 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 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 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 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 Company(Model): """ Model of a company; pyramidal structure with n different levels; workers at different levels weigh differently on the efficiency of the company as a whole. In the paper, the default parameters are level_sizes = [1, 5, 11, 21, 41, 81] (for a total of 160 employees) level_weights = [1.0, 0.9, 0.8, 0.6, 0.4, 0.2] """ def __init__(self, level_sizes=(1, 5, 10, 30), level_weights=(1.0, 0.8, 0.5, 0.2), age_distribution=default_age_dist, competency_distribution=default_competency_dist, dismissal_threshold=4, retirement_age=65, timestep_years=1 / 12., initial_vacancy_fraction=0.2, p_employee_leaves=1 / 24., competency_mechanism='common_sense', promotion_strategy='best'): assert len(level_sizes) == len(level_weights), \ "Incompatible dimensions (level sizes and weights)" assert hasattr(age_distribution, 'rvs'), \ "age_distribution must have a rvs method returning random values" assert hasattr(competency_distribution, 'rvs'), \ "competency_distribution must have a rvs method returning random values" assert promotion_strategy in ['best', 'worst', 'random'], \ "Unrecognized promotion_strategy" assert competency_mechanism in ['common_sense', 'peter'], \ "Unrecognized competency_mechanism" super().__init__() # Not the best way to pack all the constants I have self.level_sizes = level_sizes self.level_weights = level_weights self.age_distribution = age_distribution self.competency_distribution = competency_distribution self.dismissal_threshold = dismissal_threshold self.retirement_age = retirement_age self.timestep_years = timestep_years self.initial_vacancy_fraction = initial_vacancy_fraction self.dist_employees_leaving = bernoulli(p=p_employee_leaves) self.competency_mechanism = competency_mechanism self.promotion_strategy = promotion_strategy self.current_id = 0 self.schedule = SimultaneousActivation(self) # Create agents self.levels = [] for level_size in level_sizes: level = [] n_initial_agents = binom(n=level_size, p=1 - self.initial_vacancy_fraction).rvs() n_initial_agents = max(1, n_initial_agents) for i in range(n_initial_agents): agent = Employee(self.next_id(), self) self.schedule.add(agent) level.append(agent) self.levels.append(level) # Initialize data collection self.data_collector = DataCollector( model_reporters={'efficiency': calculate_efficiency}) def remove_employees(self): for level in self.levels: for employee in level: if employee.has_to_go: level.remove(employee) self.schedule.remove(employee) def pick_for_promotion_from(self, source_level): if self.promotion_strategy == 'best': return max(source_level, key=lambda e: e.competency) elif self.promotion_strategy == 'worst': return min(source_level, key=lambda e: e.competency) elif self.promotion_strategy == 'random': return self.random.choice(source_level) def recalculate_competency(self, employee): # Peter hypothesis: competency in new role not dependent on competency # in previous role if self.competency_mechanism == 'peter': employee.competency = self.competency_distribution.rvs() # Common-sense: competency mostly transferable from previous role elif self.competency_mechanism == 'common_sense': # TODO: abstract parameters used here random_variation = self.random.uniform(-1, 1) employee.competency += random_variation employee.competency = min(max(0, employee.competency), 10) # Clip def promote_employees(self): for upper_level, lower_level, target_size in zip( self.levels, self.levels[1:], self.level_sizes): while len(upper_level) < target_size and len(lower_level): chosen_employee = self.pick_for_promotion_from(lower_level) lower_level.remove(chosen_employee) self.recalculate_competency(chosen_employee) upper_level.append(chosen_employee) def hire_employees(self): bottom_level = self.levels[-1] bottom_level_target_size = self.level_sizes[-1] vacant_bottom_positions = bottom_level_target_size - len(bottom_level) for i in range(vacant_bottom_positions): agent = Employee(self.next_id(), self) self.schedule.add(agent) bottom_level.append(agent) def step(self): self.data_collector.collect(self) self.schedule.step() self.remove_employees() self.promote_employees() self.hire_employees()
class PitchModel(Model): def __init__(self, N, width, height): '''Initiate the model''' self.num_agents = 2 * N self.grid = MultiGrid(width, height, False) self.schedule = SimultaneousActivation(self) self.running = True self.justConceded = 0 self.score1 = 0 self.score2 = 0 self.i = 0 self.newPossession = -1 #Initialise potential fields for each state self.movePotentialGK1 = np.zeros((width, height)) self.movePotentialGK2 = np.zeros((width, height)) self.movePotentialGKP1 = np.zeros((width, height)) self.movePotentialGKP2 = np.zeros((width, height)) self.movePotentialDF1 = np.zeros((width, height)) self.movePotentialDF2 = np.zeros((width, height)) self.movePotentialPO1 = np.zeros((width, height)) self.movePotentialPO2 = np.zeros((width, height)) self.movePotentialBP1 = np.zeros((width, height)) self.movePotentialBP2 = np.zeros((width, height)) #Set initial potential field due to goals self.goalPotentialGK1 = np.zeros((width, height)) self.goalPotentialGK2 = np.zeros((width, height)) self.goalPotentialGKP1 = np.zeros((width, height)) self.goalPotentialGKP2 = np.zeros((width, height)) self.goalPotentialDF1 = np.zeros((width, height)) self.goalPotentialDF2 = np.zeros((width, height)) self.goalPotentialPO1 = np.zeros((width, height)) self.goalPotentialPO2 = np.zeros((width, height)) self.goalPotentialBP1 = np.zeros((width, height)) self.goalPotentialBP2 = np.zeros((width, height)) for x in range(8): for y in range(height): widthVal = ((width / 2) - 4) + x self.goalPotentialGK1[int(widthVal)][ y] = self.goalPotentialGK1[int(widthVal)][y] + (y + 1) self.goalPotentialGK1[int(widthVal)][ height - (y + 1)] = self.goalPotentialGK1[int(widthVal)][ height - (y + 1)] - np.log2(height - (y + 1)) self.goalPotentialGK2[int( widthVal)][y] = self.goalPotentialGK2[int( widthVal)][y] - np.log2(height - (y + 1)) self.goalPotentialGK2[int(widthVal)][height - ( y + 1)] = self.goalPotentialGK2[int(widthVal)][height - (y + 1)] + ( y + 1) self.goalPotentialGKP1[int(widthVal)][ y] = self.goalPotentialGKP1[int(widthVal)][y] + (y + 1) self.goalPotentialGKP1[int(widthVal)][ height - (y + 1)] = self.goalPotentialGKP1[int(widthVal)][ height - (y + 1)] - np.log2(height - (y + 1)) self.goalPotentialGKP2[int( widthVal)][y] = self.goalPotentialGKP2[int( widthVal)][y] - np.log2(height - (y + 1)) self.goalPotentialGKP2[int(widthVal)][height - ( y + 1 )] = self.goalPotentialGKP2[int(widthVal)][height - (y + 1)] + (y + 1) self.goalPotentialDF1[int(widthVal)][ y] = self.goalPotentialDF1[int(widthVal)][y] + (y + 1) self.goalPotentialDF1[int(widthVal)][ height - (y + 1)] = self.goalPotentialDF1[int(widthVal)][ height - (y + 1)] - np.log2(height - (y + 1)) self.goalPotentialDF2[int( widthVal)][y] = self.goalPotentialDF2[int( widthVal)][y] - np.log2(height - (y + 1)) self.goalPotentialDF2[int(widthVal)][height - ( y + 1)] = self.goalPotentialDF2[int(widthVal)][height - (y + 1)] + ( y + 1) self.goalPotentialPO1[int( widthVal)][y] = self.goalPotentialPO1[int( widthVal)][y] - np.log2(height - (y + 1)) self.goalPotentialPO1[int(widthVal)][height - ( y + 1)] = self.goalPotentialPO1[int(widthVal)][height - (y + 1)] + ( y + 1) self.goalPotentialPO2[int(widthVal)][ y] = self.goalPotentialPO2[int(widthVal)][y] + (y + 1) self.goalPotentialPO2[int(widthVal)][ height - (y + 1)] = self.goalPotentialPO2[int(widthVal)][ height - (y + 1)] - np.log2(height - (y + 1)) self.goalPotentialBP1[int( widthVal)][y] = self.goalPotentialBP1[int( widthVal)][y] - np.log2(height - (y + 1)) self.goalPotentialBP1[int(widthVal)][height - ( y + 1)] = self.goalPotentialBP1[int(widthVal)][height - (y + 1)] + ( y + 1) self.goalPotentialBP2[int(widthVal)][ y] = self.goalPotentialBP2[int(widthVal)][y] + (y + 1) self.goalPotentialBP2[int(widthVal)][ height - (y + 1)] = self.goalPotentialBP2[int(widthVal)][ height - (y + 1)] - np.log2(height - (y + 1)) for x in range(int((width / 2) - 4)): for y in range(height): r1 = (((x + 1)**2) + ((y + 1)**2))**0.5 r2 = (((x + 1)**2) + ((height - (y + 1))**2))**0.5 goalStart = ((width / 2) - 5) - x goalEnd = ((width / 2) + 4) + x self.goalPotentialGK1[int(goalStart)][ y] = self.goalPotentialGK1[int(goalStart)][y] + (r1) self.goalPotentialGK1[int(goalEnd)][y] = self.goalPotentialGK1[ int(goalEnd)][y] + (r1) self.goalPotentialGK1[int(goalStart)][ height - (y + 1)] = self.goalPotentialGK1[int(goalStart)][ height - (y + 1)] - np.log2(r2) self.goalPotentialGK1[int(goalEnd)][height - ( y + 1 )] = self.goalPotentialGK1[int(goalEnd)][height - (y + 1)] - np.log2(r2) self.goalPotentialGK2[int(goalStart)][ y] = self.goalPotentialGK2[int(goalStart)][y] - np.log2(r2) self.goalPotentialGK2[int(goalEnd)][y] = self.goalPotentialGK2[ int(goalEnd)][y] - np.log2(r2) self.goalPotentialGK2[int(goalStart)][height - ( y + 1)] = self.goalPotentialGK2[int(goalStart)][height - (y + 1)] + (r1) self.goalPotentialGK2[int(goalEnd)][height - ( y + 1)] = self.goalPotentialGK2[int(goalEnd)][height - (y + 1)] + (r1) self.goalPotentialGKP1[int(goalStart)][ y] = self.goalPotentialGKP1[int(goalStart)][y] + (r1) self.goalPotentialGKP1[int(goalEnd)][ y] = self.goalPotentialGKP1[int(goalEnd)][y] + (r1) self.goalPotentialGKP1[int(goalStart)][ height - (y + 1)] = self.goalPotentialGKP1[int(goalStart)][ height - (y + 1)] - np.log2(r2) self.goalPotentialGKP1[int(goalEnd)][ height - (y + 1)] = self.goalPotentialGKP1[int(goalEnd)][ height - (y + 1)] - np.log2(r2) self.goalPotentialGKP2[int( goalStart )][y] = self.goalPotentialGKP2[int(goalStart)][y] - np.log2(r2) self.goalPotentialGKP2[int(goalEnd)][ y] = self.goalPotentialGKP2[int(goalEnd)][y] - np.log2(r2) self.goalPotentialGKP2[int(goalStart)][height - ( y + 1 )] = self.goalPotentialGKP2[int(goalStart)][height - (y + 1)] + (r1) self.goalPotentialGKP2[int(goalEnd)][height - ( y + 1)] = self.goalPotentialGKP2[int(goalEnd)][height - (y + 1)] + (r1) self.goalPotentialDF1[int(goalStart)][ y] = self.goalPotentialDF1[int(goalStart)][y] + (r1) self.goalPotentialDF1[int(goalEnd)][y] = self.goalPotentialDF1[ int(goalEnd)][y] + (r1) self.goalPotentialDF1[int(goalStart)][ height - (y + 1)] = self.goalPotentialDF1[int(goalStart)][ height - (y + 1)] - np.log2(r2) self.goalPotentialDF1[int(goalEnd)][height - ( y + 1 )] = self.goalPotentialDF1[int(goalEnd)][height - (y + 1)] - np.log2(r2) self.goalPotentialDF2[int(goalStart)][ y] = self.goalPotentialDF2[int(goalStart)][y] - np.log2(r2) self.goalPotentialDF2[int(goalEnd)][y] = self.goalPotentialDF2[ int(goalEnd)][y] - np.log2(r2) self.goalPotentialDF2[int(goalStart)][height - ( y + 1)] = self.goalPotentialDF2[int(goalStart)][height - (y + 1)] + (r1) self.goalPotentialDF2[int(goalEnd)][height - ( y + 1)] = self.goalPotentialDF2[int(goalEnd)][height - (y + 1)] + (r1) self.goalPotentialPO1[int(goalStart)][ y] = self.goalPotentialPO1[int(goalStart)][y] - np.log2(r2) self.goalPotentialPO1[int(goalEnd)][y] = self.goalPotentialPO1[ int(goalEnd)][y] - np.log2(r2) self.goalPotentialPO1[int(goalStart)][height - ( y + 1)] = self.goalPotentialPO1[int(goalStart)][height - (y + 1)] + (r1) self.goalPotentialPO1[int(goalEnd)][height - ( y + 1)] = self.goalPotentialPO1[int(goalEnd)][height - (y + 1)] + (r1) self.goalPotentialPO2[int(goalStart)][ y] = self.goalPotentialPO2[int(goalStart)][y] + (r1) self.goalPotentialPO2[int(goalEnd)][y] = self.goalPotentialPO2[ int(goalEnd)][y] + (r1) self.goalPotentialPO2[int(goalStart)][ height - (y + 1)] = self.goalPotentialPO2[int(goalStart)][ height - (y + 1)] - np.log2(r2) self.goalPotentialPO2[int(goalEnd)][height - ( y + 1 )] = self.goalPotentialPO2[int(goalEnd)][height - (y + 1)] - np.log2(r2) self.goalPotentialBP1[int(goalStart)][ y] = self.goalPotentialBP1[int(goalStart)][y] - np.log2(r2) self.goalPotentialBP1[int(goalEnd)][y] = self.goalPotentialBP1[ int(goalEnd)][y] - np.log2(r2) self.goalPotentialBP1[int(goalStart)][height - ( y + 1)] = self.goalPotentialBP1[int(goalStart)][height - (y + 1)] + (r1) self.goalPotentialBP1[int(goalEnd)][height - ( y + 1)] = self.goalPotentialBP1[int(goalEnd)][height - (y + 1)] + (r1) self.goalPotentialBP2[int(goalStart)][ y] = self.goalPotentialBP2[int(goalStart)][y] + (r1) self.goalPotentialBP2[int(goalEnd)][y] = self.goalPotentialBP2[ int(goalEnd)][y] + (r1) self.goalPotentialBP2[int(goalStart)][ height - (y + 1)] = self.goalPotentialBP2[int(goalStart)][ height - (y + 1)] - np.log2(r2) self.goalPotentialBP2[int(goalEnd)][height - ( y + 1 )] = self.goalPotentialBP2[int(goalEnd)][height - (y + 1)] - np.log2(r2) #Create Agents for i in range(self.num_agents): if i > ((2 * N) - 3): a = PlayerAgent(i, self, True) else: a = PlayerAgent(i, self) self.schedule.add(a) x = self.random.randrange(self.grid.width) y = self.random.randrange(self.grid.height) self.grid.place_agent(a, (x, y)) #Set Up Kickoff self.kickoff() #Set Up DataCollector self.datacollector = DataCollector(model_reporters={ "Score 1": "score1", "Score 2": "score2" }, agent_reporters={ "Avg. Displacement": "avgDisp", "Max Displacement": "maxDisp" }) def kickoff(self): posBoy = -1 newPositions = {} if self.justConceded == 0: posTeam = self.random.randint(1, 2) else: posTeam = self.justConceded for cellContents, x, y in self.grid.coord_iter(): if len(cellContents) == 0: pass else: for i in cellContents: if posBoy == -1: if i.teamID == posTeam: if i.goalkeeper == True: pass else: i.possession = True posBoy = i.unique_id newPositions[i] = ((self.grid.width / 2) - 1, (self.grid.height / 2) - 1) if i.unique_id != posBoy: if i.teamID == 1: if i.goalkeeper == True: x = self.random.randint( (self.grid.width / 2) - 5, (self.grid.width / 2) + 3) y = self.random.randint(0, 17) newPositions[i] = (x, y) else: x = self.random.randrange(self.grid.width) y = self.random.randint( 0, (self.grid.height / 2) - 1) newPositions[i] = (x, y) else: if i.goalkeeper == True: x = self.random.randint( (self.grid.width / 2) - 5, (self.grid.width / 2) + 3) y = self.random.randint( self.grid.height - 18, self.grid.height - 1) newPositions[i] = (x, y) else: x = self.random.randrange(self.grid.width) y = self.random.randint( (self.grid.height / 2) - 1, self.grid.height - 1) newPositions[i] = (x, y) for key in newPositions.keys(): (x, y) = newPositions[key] x = int(x) y = int(y) self.grid.move_agent(key, (x, y)) self.justConceded = 0 def calcPotential(self): for x in range(self.grid.width): for y in range(self.grid.height): self.movePotentialGK1[x][y] = self.goalPotentialGK1[x][y] self.movePotentialGK2[x][y] = self.goalPotentialGK2[x][y] self.movePotentialGKP1[x][y] = self.goalPotentialGKP1[x][y] self.movePotentialGKP2[x][y] = self.goalPotentialGKP2[x][y] self.movePotentialDF1[x][y] = self.goalPotentialDF1[x][y] self.movePotentialDF2[x][y] = self.goalPotentialDF2[x][y] self.movePotentialPO1[x][y] = self.goalPotentialPO1[x][y] self.movePotentialPO2[x][y] = self.goalPotentialPO2[x][y] self.movePotentialBP1[x][y] = self.goalPotentialBP1[x][y] self.movePotentialBP2[x][y] = self.goalPotentialBP2[x][y] playerPos = {} for agent, x, y in self.grid.coord_iter(): if len(agent) == 0: pass else: for i in agent: playerPos[i.unique_id] = {"x": x, "y": y, "state": i.state} if i.state == "": i.checkState() playerPos[i.unique_id]['state'] = i.state for key in playerPos.keys(): agent = playerPos[key] for i in range(self.grid.width): for j in range(self.grid.height): r = ((agent['x'] - i)**2 + (agent['y'] - j)**2)**(0.5) if r != 0: if agent['state'] == "GK": self.movePotentialGK1[i][ j] = self.movePotentialGK1[i][j] + (20 / (r**2)) self.movePotentialGK2[i][ j] = self.movePotentialGK2[i][j] + (20 / (r**2)) self.movePotentialGKP1[i][ j] = self.movePotentialGKP1[i][j] + (20 / (r**2)) self.movePotentialGKP2[i][ j] = self.movePotentialGKP2[i][j] + (20 / (r**2)) self.movePotentialDF1[i][ j] = self.movePotentialDF1[i][j] + 40 * ( (5 * (2**(-1 / 6)) / r)**12 - (5 * (2**(-1 / 6)) / r)**6) self.movePotentialDF2[i][ j] = self.movePotentialDF2[i][j] + 40 * ( (5 * (2**(-1 / 6)) / r)**12 - (5 * (2**(-1 / 6)) / r)**6) self.movePotentialPO1[i][ j] = self.movePotentialPO1[i][j] + (20 / (r**2)) self.movePotentialPO2[i][ j] = self.movePotentialPO2[i][j] + (20 / (r**2)) self.movePotentialBP1[i][ j] = self.movePotentialBP1[i][j] + (20 / (r**2)) self.movePotentialBP2[i][ j] = self.movePotentialBP2[i][j] + (20 / (r**2)) elif agent['state'] == "GKP": self.movePotentialGK1[i][ j] = self.movePotentialGK1[i][j] + (20 / (r**2)) self.movePotentialGK2[i][ j] = self.movePotentialGK2[i][j] + (20 / (r**2)) self.movePotentialGKP1[i][ j] = self.movePotentialGKP1[i][j] self.movePotentialGKP2[i][ j] = self.movePotentialGKP2[i][j] self.movePotentialDF1[i][ j] = self.movePotentialDF1[i][j] + (20 / (r**2)) self.movePotentialDF2[i][ j] = self.movePotentialDF2[i][j] + (20 / (r**2)) self.movePotentialPO1[i][ j] = self.movePotentialPO1[i][j] + (20 / (r**2)) self.movePotentialPO2[i][ j] = self.movePotentialPO2[i][j] + (20 / (r**2)) self.movePotentialBP1[i][ j] = self.movePotentialBP1[i][j] self.movePotentialBP2[i][ j] = self.movePotentialBP2[i][j] elif agent['state'] == "DF": self.movePotentialGK1[i][ j] = self.movePotentialGK1[i][j] + (20 / (r**2)) self.movePotentialGK2[i][ j] = self.movePotentialGK2[i][j] + (20 / (r**2)) self.movePotentialGKP1[i][ j] = self.movePotentialGKP1[i][j] + (20 / (r**2)) self.movePotentialGKP2[i][ j] = self.movePotentialGKP2[i][j] + (20 / (r**2)) self.movePotentialDF1[i][ j] = self.movePotentialDF1[i][j] + (20 / (r**2)) self.movePotentialDF2[i][ j] = self.movePotentialDF2[i][j] + (20 / (r**2)) self.movePotentialPO1[i][ j] = self.movePotentialPO1[i][j] + (20 / (r**2)) self.movePotentialPO2[i][ j] = self.movePotentialPO2[i][j] + (20 / (r**2)) self.movePotentialBP1[i][ j] = self.movePotentialBP1[i][j] + (20 / (r**2)) self.movePotentialBP2[i][ j] = self.movePotentialBP2[i][j] + (20 / (r**2)) elif agent['state'] == "PO": self.movePotentialGK1[i][ j] = self.movePotentialGK1[i][j] - (20 / (r**2)) self.movePotentialGK2[i][ j] = self.movePotentialGK2[i][j] - (20 / (r**2)) self.movePotentialGKP1[i][ j] = self.movePotentialGKP1[i][j] - (20 / (r**2)) self.movePotentialGKP2[i][ j] = self.movePotentialGKP2[i][j] - (20 / (r**2)) self.movePotentialDF1[i][ j] = self.movePotentialDF1[i][j] + 40 * ( (2.5 * (2**(-1 / 6)) / r)**12 - (2.5 * (2**(-1 / 6)) / r)**6) self.movePotentialDF2[i][ j] = self.movePotentialDF2[i][j] + 40 * ( (2.5 * (2**(-1 / 6)) / r)**12 - (2.5 * (2**(-1 / 6)) / r)**6) self.movePotentialPO1[i][ j] = self.movePotentialPO1[i][j] + (20 / (r**2)) self.movePotentialPO2[i][ j] = self.movePotentialPO2[i][j] + (20 / (r**2)) self.movePotentialBP1[i][ j] = self.movePotentialBP1[i][j] + (20 / (r**2)) self.movePotentialBP2[i][ j] = self.movePotentialBP2[i][j] + (20 / (r**2)) elif agent['state'] == "BP": self.movePotentialGK1[i][ j] = self.movePotentialGK1[i][j] - (20 / (r**2)) self.movePotentialGK2[i][ j] = self.movePotentialGK2[i][j] - (20 / (r**2)) self.movePotentialGKP1[i][ j] = self.movePotentialGKP1[i][j] self.movePotentialGKP2[i][ j] = self.movePotentialGKP2[i][j] self.movePotentialDF1[i][ j] = self.movePotentialDF1[i][j] - (20 / (r**2)) self.movePotentialDF2[i][ j] = self.movePotentialDF2[i][j] - (20 / (r**2)) self.movePotentialPO1[i][ j] = self.movePotentialPO1[i][j] + 40 * ( (5 * (2**(-1 / 6)) / r)**12 - (5 * (2**(-1 / 6)) / r)**6) self.movePotentialPO2[i][ j] = self.movePotentialPO2[i][j] + 40 * ( (5 * (2**(-1 / 6)) / r)**12 - (5 * (2**(-1 / 6)) / r)**6) self.movePotentialBP1[i][ j] = self.movePotentialBP1[i][j] self.movePotentialBP2[i][ j] = self.movePotentialBP2[i][j] else: print( "Error in CalcPotential: Player has no state") def scoreCheck(self): '''Checks if any player agent has successfully scored and increments the team's score by 1''' if self.justConceded == 0: pass else: if self.justConceded == 1: self.score2 = self.score2 + 1 self.kickoff() else: self.score1 = self.score1 + 1 self.kickoff() def gridVisual(self): grid = np.zeros((self.grid.width, self.grid.height)) for agent, x, y in self.grid.coord_iter(): if len(agent) != 0: for k in agent: grid[x][y] = k.teamID name = "Visualisation\Latest Test\Figure_" + str(self.i) + ".jpg" plt.imsave(name, grid) def bugTest(self): self.calcPotential() plt.figure(1) plt.clf() plt.imshow(self.movePotentialBP1, interpolation="nearest") plt.figure(2) plt.clf() plt.imshow(self.movePotentialBP2, interpolation="nearest") plt.figure(3) plt.clf() plt.imshow(self.movePotentialDF1, interpolation="nearest") plt.figure(4) plt.clf() plt.imshow(self.movePotentialDF2, interpolation="nearest") plt.figure(5) plt.clf() plt.imshow(self.movePotentialGK1, interpolation="nearest") plt.figure(6) plt.clf() plt.imshow(self.movePotentialGK2, interpolation="nearest") plt.figure(7) plt.clf() plt.imshow(self.movePotentialGKP1, interpolation="nearest") plt.figure(8) plt.clf() plt.imshow(self.movePotentialGKP2, interpolation="nearest") plt.figure(9) plt.clf() plt.imshow(self.movePotentialPO1, interpolation="nearest") plt.figure(10) plt.clf() plt.imshow(self.movePotentialPO2, interpolation="nearest") def step(self): '''Advance the model by one step.''' self.calcPotential() self.scoreCheck() self.datacollector.collect(self) self.schedule.step() self.i = self.i + 1 self.gridVisual() print("Step: " + str(self.i)) print(str(self.score1) + " - " + str(self.score2))
class FormationFlying(Model): # ========================================================================= # Create a new FormationFlying model. # # Args: # n_flights: Number of flights # width, height: Size of the space, in kilometers. # speed: cruise-speed of flights in m/s. # communication_range: How far around should each Boid look for its neighbors # separation: What's the minimum distance each Boid will attempt to # keep from any other the three drives. # ========================================================================= def __init__( self, n_flights=2, n_origin_airports=2, n_destination_airports=2, width=1500, # [km] height=1500, speed=0.220, #[km/second] communication_range=50, #[km] departure_window = 3, origin_airport_x = [0.0, 0.3], # the origin airports are randomly generated within these boundaries origin_airport_y = [0.0, 0.3], destination_airport_x = [0.7, 0.9], # same for destination airports destination_airport_y = [0.7, 0.9], fuel_reduction = 0.75, negotiation_method = 0, PercentageAlliance = 40 ): # ===================================================================== # Initialize parameters, the exact values will be defined later on. # ===================================================================== self.n_flights = n_flights self.n_origin_airports = n_origin_airports self.n_destination_airports = n_destination_airports self.vision = communication_range self.speed = speed # The agents are activated in random order at each step, in a space that # has a certain width and height and that is not toroidal # (which means that edges do not wrap around) self.schedule = SimultaneousActivation(self) self.space = ContinuousSpace(width, height, False) # These are values between [0,1] that limit the boundaries of the # position of the origin- and destination airports. self.origin_airport_x = origin_airport_x self.origin_airport_y = origin_airport_y self.destination_airport_x = destination_airport_x self.destination_airport_y = destination_airport_y self.destination_agent_list = [] self.departure_window = departure_window self.fuel_reduction = fuel_reduction self.negotiation_method = negotiation_method self.PercentageAlliance = PercentageAlliance self.fuel_savings_closed_deals = 0 self.total_planned_fuel = 0 self.total_planned_time = 0 self.new_formation_counter = 0 self.add_to_formation_counter = 0 self.flights_not_in_formation = n_flights self.total_steps_till_formations = 0 self.total_fuel_consumption = 0 self.total_flight_time = 0 self.origin_list = [] self.destination_list = [] self.make_airports() self.make_agents() self.running = True self.datacollector = DataCollector(model_reporter_parameters, agent_reporter_parameters) # ========================================================================= # Create all flights, the flights are not all initialized at the same time, # but within a departure window. # ========================================================================= def make_agents(self): for i in range(self.n_flights): departure_time = self.random.uniform(0, self.departure_window) pos = self.random.choice(self.origin_list) destination_agent = self.random.choice(self.destination_agent_list) destination_pos = destination_agent.pos flight = Flight( i, self, pos, destination_agent, destination_pos, departure_time, self.speed, self.vision, ) self.space.place_agent(flight, pos) self.schedule.add(flight) # ============================================================================= # Create all airports. The option "inactive_airports" gives you the # opportunity to have airports close later on in the simulation. # ============================================================================= def make_airports(self): inactive_airports = 0 for i in range(self.n_origin_airports): x = self.random.uniform(self.origin_airport_x[0], self.origin_airport_x[1]) * self.space.x_max y = self.random.uniform(self.origin_airport_y[0], self.origin_airport_y[1]) * self.space.y_max closure_time = 0 pos = np.array((x, y)) airport = Airport(i + self.n_flights, self, pos, "Origin", closure_time) self.space.place_agent(airport, pos) self.schedule.add(airport) # they are only plotted if they are part of the schedule for i in range(self.n_destination_airports): x = self.random.uniform(self.destination_airport_x[0], self.destination_airport_x[1]) * self.space.x_max y = self.random.uniform(self.destination_airport_y[0], self.destination_airport_y[1]) * self.space.y_max if inactive_airports: closure_time = 50 inactive_airports = 0 else: closure_time = 0 pos = np.array((x, y)) airport = Airport(i + self.n_flights + self.n_origin_airports, self, pos, "Destination", closure_time) self.space.place_agent(airport, pos) self.destination_agent_list.append(airport) self.schedule.add(airport) # agents are only plotted if they are part of the schedule # ========================================================================= # Define what happens in the model in each step. # ========================================================================= def step(self): all_arrived = True total_deal_value = 0 for agent in self.schedule.agents: if type(agent) is Flight: total_deal_value += agent.deal_value if agent.state != "arrived": all_arrived = False if all_arrived: self.running = False # This is a verification that no deal value is created or lost (total deal value # must be 0, and 0.001 is chosen here to avoid any issues with rounded numbers) if abs(total_deal_value) > 0.001: raise Exception("Deal value is {}".format(total_deal_value)) self.schedule.step() 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