class SlimeModel(Model): def __init__(self, height, width, color, numAgents, gDense, kRate, dcDiffu, dhRes, dtRes, secRate): # number of agents per tile self.n = numAgents # grid density self.gD = gDense # rate of cAMP decay self.k = kRate # diffusion constant of cAMP self.Dc = dcDiffu # spatial resolution for cAMP simulation self.Dh = dhRes # time resolution for cAMP simulation self.Dt = dtRes # rate of cAMP secretion by an agent self.f = secRate # number of rows/columns in spatial array self.w = masterHeight # agent color self.color = color # height of grid self.height = masterHeight # width of grid self.width = masterWidth # Counter for generating sequential unique id's self.j = 0 # Counter for DataVis agents' unique id's self.dv = 0 # Counter for NumDataVis agents' unique id's self.ndv = 0 # Create randomly ordered scheduler self.schedule = SimultaneousActivation(self) # Create grid (of type MultiGrid to support multiple agents per cell self.grid = MultiGrid(self.width, self.height, torus=False) # Initialize list of cAMP molecules self.cAMPs = list() # Initialize dict for datacollector with total datacollector dc = {"Total Amount of cAMP": self.getAmts} # Initialize for iterating through columns (x) and rows (y) self.x = 0 self.y = 0 # Loop to fill datacollector dictionary with dict entries for each column and row for x in range(masterWidth): dc.update({("x: " + str(x)): self.getColAmts}) dc.update({("y: " + str(x)): self.getRowAmts}) # Create datacollector to retrieve total amounts of cAMP from dc dict created above self.datacollector = DataCollector(dc) # Variable for storing random numbers r = 0 # Initial loop to create agents and fill agents list with them for (contents, x, y) in self.grid.coord_iter(): # Create object of type cAMP cell = cAMP([x, y], self, self.j, 0) # Add random amoutn of cAMP to cell (<1) cell.add(random.random()) # Place cAMP onto grid at coordinates x, y self.grid._place_agent((x, y), cell) # Add cAMP molecule to list self.cAMPs.append(cell) # print("x:", x, " y:", y) if x == 50: # Create DataVis agent ag = DataVis([x, y], self, self.dv) # Place DataVis agent self.grid.place_agent(ag, tuple([x, y])) # Increment unique id counter self.dv += 1 elif x > 50: # Create NumDataVis agent with appropriate slice num ag = NumDataVis([x, y], self, self.ndv) # Place NumDataVis agent self.grid.place_agent(ag, tuple([x, y])) # Increment unique id counter self.ndv += 1 else: # Loop to create SlimeAgents if self.gD % 1 != 0: r = random.random() if r <= self.gD: for i in range(self.n): # Create object of type SlimeAgent ag = SlimeAgent([x, y], self, self.j, self.color) # Place agent onto grid at coordinates x, y self.grid.place_agent(ag, tuple([x, y])) # Add agent to schedule self.schedule.add(ag) # Increment j (unique_id variable) self.j += 1 else: for i in range(self.n): # Create object of type SlimeAgent ag = SlimeAgent([x, y], self, self.j, self.color) # Place agent onto grid at coordinates x, y self.grid.place_agent(ag, tuple([x, y])) # Add agent to schedule self.schedule.add(ag) # Increment j (unique_id variable) self.j += 1 # Print out number of agents print("# of agents:", self.j) self.running = True # Method for getting total cAMP amount def getAmts(self): # Initialize empty total variable total = 0 # Loop to get total amount of cAMP from cAMPs list for molecule in self.cAMPs: total += molecule.getAmt() return total def getRowAmts(self): total = 0 for x in range(masterWidth): try: total += self.grid.get_cell_list_contents( (x, self.y))[0].getAmt() except IndexError: continue if self.y == 49: self.y = 0 else: self.y += 1 return total def getRowAmt(self, y): total = 0 for x in range(masterWidth - 1): try: total += self.grid.get_cell_list_contents((x, y))[0].getAmt() except IndexError: continue if self.y == 49: self.y = 0 else: self.y += 1 return total def getColAmts(self): total = 0 for y in range(masterHeight): try: total += self.grid.get_cell_list_contents( (self.x, y))[0].getAmt() except IndexError: continue if self.x == 49: self.x = 0 else: self.x += 1 return total def sweepForClusters(): blacklist = list() neighbors = list() for (contents, x, y) in self.grid.coord_iter(): for agent in contents[1::]: if type(agent) == SlimeAgent and agent not in blacklist: neighbors = agent.getNeighbors() for neighbor in neighbors: blacklist.append(neighbor) ''' density = blacklist.length / density_coefficent_based_on_area clusteredAgents = ''' # Step method def step(self): cNeighbors = list() neighbors = list() lap = 0 amtSelf = 0 cAMPobj = cAMP newDiag = 0 oldDiag = 0 nAgents = 0 layer = 1 secRate = 0 ''' Perform cAMP decay and diffusion actions ''' for (contents, x, y) in self.grid.coord_iter(): # This block is a bit messy but it works for now cont = True for content in contents: # Set row amounts if an object is DataVis if type(content) is DataVis or type(content) is NumDataVis: content.setRowAmt(self.getRowAmt(y)) cont = False if cont: # Initialize number of agents for layer coloring nAgents = len(contents) - 1 # Reset lap to 0 lap = 0 # Set cAMPobj to current tile's cAMP agent cAMPobj = contents[0] # Set neighbors to cAMPobj's neighbors (Von Neumann) neighbors = cAMPobj.getNeighbors() # Add cAMP objects form neighbors to cNeighbors for neighbor in neighbors: if type(neighbor) is cAMP: cNeighbors.append(neighbor) # Add sum of neighbors to lap for mol in cNeighbors: lap += mol.getAmt() amtSelf = cAMPobj.getAmt() # Reassign lap to the laplacian (using previous neighbor sum value) lap = (lap - 4 * amtSelf) / (self.Dh**2) # Add decay to current cAMP object cAMPobj.add( (-cAMPobj.getDecayRate() * amtSelf + self.Dc * lap) * self.Dt) # Wipe cNeighbors cNeighbors.clear() # Iterate through all contents of a grid cell for agent in contents[1::]: # Get all neighbors (excuding self) neighbors = agent.getNeighbors() # Examine each neighbor for neighbor in neighbors: # Add cAMP neighbors to list if type(neighbor) is cAMP: cNeighbors.append(neighbor) # Add cAMP secretion to the cell that the agent shares with a cAMP object cAMPobj.add(agent.getSecRate() * self.Dt) # Decide whether or not to move newx = (x + random.randint(-1, 2)) % self.w newy = (y + random.randint(-1, 2)) % self.w # Calculate differences newDiag = ((self.grid[newx - 1][newy - 1])[0]).getAmt() diff = ((self.grid[x - 1][y - 1])[0]).getAmt() # Fix if there are crazy values for diff if diff > 10: diff = 10 elif diff < 10: diff = -10 # Decide to move if random.random() < np.exp(diff) / (1 + np.exp(diff)): agent.move(tuple([newx, newy])) # Layers for coloring agents based on density agent.addLayer() layer = agent.getLayer() # Only change color of agent that is on top of a stack if layer >= nAgents: self.pickColor(agent, nAgents) # Wipe cNeighbors cNeighbors.clear() # Add step to schedule self.schedule.step() # Collect new data self.datacollector.collect(self) # Method to select a color based on the topmost agent def pickColor(self, topAgent, nAgents): shade = topAgent.getShades() if nAgents <= 2: topAgent.setShade(shade[0]) elif nAgents == 3: topAgent.setShade(shade[1]) elif nAgents == 4: topAgent.setShade(shade[2]) elif nAgents == 5: topAgent.setShade(shade[3]) elif nAgents == 6: topAgent.setShade(shade[4]) elif nAgents == 7: topAgent.setShade(shade[5]) elif nAgents == 8: topAgent.setShade(shade[6]) elif nAgents == 9: topAgent.setShade(shade[7])
class ForestDisease(Model): """ Simple Forest Fire model. """ def __init__(self, height=100, width=100, density=0.65, mortality=1, wind='N', distance='1'): """ Create a new forest fire model. Args: height, width: The size of the grid to model density: What fraction of grid cells have a tree in them. """ # Initialize model parameters self.height = height self.width = width self.density = density self.mortality = mortality self.wind = wind self.distance = distance # Set up model objects self.schedule = RandomActivation(self) self.grid = MultiGrid(height, width, torus=False) self.datacollector = DataCollector({ "Fine": lambda m: self.count_type(m, "Fine"), "Infected": lambda m: self.count_type(m, "Infected"), "Dead": lambda m: self.count_type(m, "Dead") }) # Place a tree in each cell with Prob = density for (contents, x, y) in self.grid.coord_iter(): if self.random.random() < self.density: # Create a tree new_tree = TreeCell((x, y), self) self.grid._place_agent((x, y), new_tree) self.schedule.add(new_tree) center = (int(width / 2), int(height / 2)) movingAgent = MovingAgent(center, self) self.grid._place_agent(center, movingAgent) new_tree = TreeCell(center, self) self.grid._place_agent(center, new_tree) self.schedule.add(new_tree) self.schedule.add(movingAgent) self.running = True self.datacollector.collect(self) def step(self): """ Advance the model by one step. """ self.schedule.step() # collect data self.datacollector.collect(self) # Halt if no more fire if self.count_type(self, "Fine") == 0: self.running = False @staticmethod def count_type(model, tree_condition): """ Helper method to count trees in a given condition in a given model. """ count = 0 for tree in model.schedule.agents: if tree.condition == tree_condition: count += 1 return count
class ForestFire(Model): """ Simple Forest Fire model. """ def __init__(self, height, width, density, catch_chance, burnout_chance, bird_density): """ Create a new forest fire model. Args: height, width: The size of the grid to model density: What fraction of grid cells have a tree in them. """ # Initialize model parameters self.height = height self.width = width self.density = density self.catch_chance = catch_chance self.burnout_chance = burnout_chance # Set up model objects self.schedule = RandomActivation(self) self.grid = MultiGrid(height, width, torus=False) self.datacollector = DataCollector({ "Fine": lambda m: self.count_type(m, "Fine"), "On Fire": lambda m: self.count_type(m, "On Fire"), "Burned Out": lambda m: self.count_type(m, "Burned Out") }) # Place a tree in each cell with Prob = density for (contents, x, y) in self.grid.coord_iter(): if random.random() < self.density: # Create a tree new_tree = TreeCell((x, y), self, self.catch_chance, self.burnout_chance) # Set all trees in the first column on fire. if x == 0: new_tree.condition = "On Fire" self.grid._place_agent((x, y), new_tree) self.schedule.add(new_tree) for (contents, x, y) in self.grid.coord_iter(): if random.random() < (bird_density): new_bird = Bird((x, y), self) self.grid._place_agent((x, y), new_bird) self.schedule.add(new_bird) for (contents, x, y) in self.grid.coord_iter(): new_empty = Empty((x, y), self) self.grid._place_agent((x, y), new_empty) self.schedule.add(new_empty) self.running = True # Place a bird in every 10th tree def step(self): """ Advance the model by one step. """ self.schedule.step() self.datacollector.collect(self) # Halt if no more fire if self.count_type(self, "On Fire") == 0: self.running = False @staticmethod def count_type(model, tree_condition): """ Helper method to count trees in a given condition in a given model. """ count = 0 for tree in model.schedule.agents: if tree.condition == tree_condition: count += 1 return count
class SquashBee(Model): def __init__(self, height=50, width=50, time=0, density_bee=50, density_gender_bee=50, gain_polline_raccolto=40, density_zucca=50, prob_accoppiamento=50, offsetX=5, offsetY=5): self.height = height self.width = width self.time = 200 self.density_bee = density_bee self.density_gender_bee = density_gender_bee self.gain_polline_raccolto = gain_polline_raccolto self.density_zucca = density_zucca self.prob_accoppiamento = prob_accoppiamento self.offsetX = offsetX self.offsetY = offsetY self.anno = 1 self.schedule = RandomActivation(self) self.grid = MultiGrid(self.width, self.height, torus=True) self.datacollector = DataCollector({ "Zucche_fiori": lambda m: self.count_type(m, "Flower"), "Zucche": lambda m: self.count_type(m, "Zucca"), "Seed": lambda m: self.count_type(m, "Seed"), "Api": lambda m: self.count_type(m, "Bee"), "Larve": lambda m: self.count_type(m, "Bee_son") }) # metto le api nella griglia for i in range(self.density_bee): x = self.random.randrange(2, 33) y = self.random.randrange(2, 33) new_bee = Bee((x, y), self, self.density_gender_bee, self.gain_polline_raccolto, 120) self.grid.place_agent(new_bee, (x, y)) self.schedule.add(new_bee) # metto i fiori delle zucche nella griglia for i in range(self.density_zucca): x = self.random.randrange(5, 30) y = self.random.randrange(5, 30) new_zucca = Zucca_flower((x, y), self, self.prob_accoppiamento, 45) self.grid._place_agent((x, y), new_zucca) self.schedule.add(new_zucca) # metto i fiori nella griglia for i in range(150): x = self.random.randrange(self.height) y = self.random.randrange(self.width) new_f = flower((x, y), self) self.grid._place_agent((x, y), new_f) self.schedule.add(new_f) self.running = True self.datacollector.collect(self) def step(self): self.time += 1 #fioritura primaverile if self.time == 90: # metto i fiori nella griglia for i in range(150): x = self.random.randrange(self.height) y = self.random.randrange(self.width) if (self.grid.is_cell_empty((x, y))): new_f = flower((x, y), self) self.grid._place_agent((x, y), new_f) self.schedule.add(new_f) # semina ogni anno if self.time == 160: # metto i semi delle zucche nella griglia if self.anno % 2 == 0: for i in range(self.density_zucca): x = self.random.randrange(5 + self.offsetX, 30 + self.offsetX) y = self.random.randrange(5 + self.offsetY, 30 + self.offsetY) if (self.grid.is_cell_empty((x, y))): new_seme = Zucca_seed((x, y), self) self.grid._place_agent((x, y), new_seme) self.schedule.add(new_seme) if self.anno % 2 == 1: for i in range(self.density_zucca): x = self.random.randrange(5, 30) y = self.random.randrange(5, 30) if (self.grid.is_cell_empty((x, y))): new_seme = Zucca_seed((x, y), self) self.grid._place_agent((x, y), new_seme) self.schedule.add(new_seme) # reset anno if self.time == 360: self.time = 0 self.anno += 1 self.schedule.step() # collect data self.datacollector.collect(self) @staticmethod def count_type(model, agent_type): """ Helper method to count trees in a given condition in a given model. """ count = 0 for agent in model.schedule.agents: if agent.type_agent == agent_type: count += 1 return count