class Market(Model): def __init__(self, width=20, height=20, num_customer=50, num_seller=4): # super().__init__(self,seed=seed) self.number_of_customer = num_customer self.number_of_seller = num_seller self.grid = MultiGrid(width, height, False) self.schedule = RandomActivation(self) self.running = True self.customers = [] self.sellers = [] self.create_sellers() self.create_customers() data = { "Customer": lambda m: m.number_of_customer, "Seller": lambda m: m.number_of_seller, } data2 = { "s1": lambda m: m.revenue, "s2": lambda m: m.revenue, } self.datacollector = DataCollector(data) self.datacollector.collect(self) def step(self): self.schedule.step() self.datacollector.collect(self) if not (self.grid.exists_empty_cells()): self.running = False def create_customers(self): for i in range(self.number_of_customer): new_customer = Customer(i, self) self.grid.place_agent(new_customer, self.grid.find_empty()) self.schedule.add(new_customer) self.customers.append(new_customer) def create_sellers(self): for i in range(self.number_of_seller): new_seller = Seller(i, self) self.grid.place_agent(new_seller, self.grid.find_empty()) self.schedule.add(new_seller) self.sellers.append(new_seller)
class SegregationModel(Model): def __init__(self, number_of_agents, width, height, happiness_threshold, minority_rate): self.num_agents = number_of_agents self.grid = MultiGrid(width, height, False) self.schedule = RandomActivation(self) ## Create Agents number_of_minority = round(number_of_agents * (minority_rate)) for i in range(number_of_agents): if (i + 1) <= number_of_minority: ethnicity = 1 else: ethnicity = 2 a = SegregationAgent(i, ethnicity, happiness_threshold, self) self.schedule.add(a) # place agent on grid # x = self.random.randrange(self.grid.width) # y = self.random.randrange(self.grid.height) empty_place = self.grid.find_empty() self.grid.place_agent(a, empty_place) logger.info("Agent " + str(i) + " placed in " + str(empty_place)) self.datacollector = DataCollector( agent_reporters={"Happiness": "happy"}, model_reporters={"Overall_happiness": overall_happiness}, ) def plot_grid(self): ethnicities = np.zeros((self.grid.width, self.grid.height)) for cell in self.grid.coord_iter(): cell_content, x, y = cell agent_present = len(cell_content) if agent_present > 0: cell_content = list(cell_content) ethnicities[x][y] = cell_content[0].ethnicity plt.imshow(ethnicities, interpolation="nearest") plt.colorbar() plt.show() def step(self): self.datacollector.collect(self) self.schedule.step() self.plot_grid()
class GenericModel(Model): schedule_types = { "Sequential": BaseScheduler, "Random": RandomActivation, "Simultaneous": SimultaneousActivation } def __init__( self, height=5, width=5, number_of_agents=1, schedule_type="Random", ): # Model Parameters self.height = height self.width = width self.number_of_agents = number_of_agents self.step_count = 0 self.schedule_type = schedule_type # Model Functions self.schedule = self.schedule_types[self.schedule_type](self) self.grid = MultiGrid(self.height, self.width, torus=True) self.make_agents() self.running = True def make_agents(self): for i in range(self.number_of_agents): x, y = self.grid.find_empty() gagent = Gagent((x, y), self, True) self.grid.place_agent(gagent, (x, y)) self.schedule.add(gagent) print("agent added") def step(self): self.schedule.step() self.step_count += 1 def run_model(self, rounds=1): for i in range(rounds): self.step()
class Disease_Model(Model): # 2D Model initialisation function - initialise with N agents, and # specified width and height. Also pass in the things we need to pass # to our agents when instantiating them. # The comment below which uses triple " will get picked up by the server # if we run a live display of the model. """A model of disease spread. For training purposes only.""" def __init__(self, N, width, height, initial_infection, transmissibility, level_of_movement, mean_length_of_disease): self.running = True # required for BatchRunner self.num_agents = N # assign number of agents at initialisation # Set up a Toroidal multi-grid (Toroidal = if the agent is in a cell # on the border of the grid, and moves towards the border, they'll # come out the other side. Think PacMan :) The True Boolean passed in # switches that on. Multi-Grid just means we can have more than one # agent per cell) self.grid = MultiGrid(width, height, True) # set up a scheduler with random order of agents being activated # each turn. Remember order is important here - if an infected agent # is going to move into a cell with an uninfected agent, but that # uninfected agent moves first, they'll escape infection. self.schedule = RandomActivation(self) # Create person_agent objects up to number specified for i in range(self.num_agents): # Create agent with ID taken from for loop a = Person_Agent(i, self, initial_infection, transmissibility, level_of_movement, mean_length_of_disease) self.schedule.add(a) # add agent to the schedule # Try adding the agent to a random empty cell try: start_cell = self.grid.find_empty() self.grid.place_agent(a, start_cell) # If you can't find an empty cell, just pick any cell at random except: x = random.randrange(self.grid.width) y = random.randrange(self.grid.height) self.grid.place_agent(a, (x, y)) # Function to advance the model by one step def step(self): self.schedule.step()
class Disease_Model(Model): # 2D Model initialisation function - initialise with N agents, and # specified width and height """A model of disease spread. For training purposes only.""" def __init__(self, N, width, height, initial_infection, transmissibility, level_of_movement, mean_length_of_disease, mean_imm_duration, prob_being_immunised): self.running = True # required for BatchRunner self.num_agents = N # assign number of agents at initialisation self.grid = MultiGrid(width, height, True) # setup Toroidal multi-grid # set up a scheduler with random order of agents being activated # each turn self.schedule = RandomActivation(self) # Create agents up to number specified for i in range(self.num_agents): # Create agent with ID taken from for loop a = Person_Agent(i, self, initial_infection, transmissibility, level_of_movement, mean_length_of_disease, mean_imm_duration, prob_being_immunised) self.schedule.add(a) # add agent to the schedule # Try adding the agent to a random empty cell try: start_cell = self.grid.find_empty() self.grid.place_agent(a, start_cell) # If you can't find an empty cell, just pick any cell at random except: x = random.randrange(self.grid.width) y = random.randrange(self.grid.height) self.grid.place_agent(a, (x, y)) self.datacollector = DataCollector(model_reporters={ "Total_Infected": calculate_number_infected, "Total_Imm": calculate_number_immunised }, agent_reporters={}) # Function to advance the model by one step def step(self): self.schedule.step() self.datacollector.collect(self)
class ThirdTestModel(Model): ''' Third Test for the Boxworld Model ''' height = 25 width = 25 initial_walkers = 1 initial_boxes = 10 # initial_items = initial_boxes//2 # -- currently divides int and results in a new int (as opposed to float) initial_total_items = 10 # initial_yellow_items = 3 # initial_green_items = 3 # initial_blue_items = 4 # initial_obstacles = 3 # obstacle_length = 7 empty_boxes = {} full_boxes = {} known_items = {} all_boxes = {} obstacles = [] map_choice = [] verbose = False # Print-monitoring description = 'A model for simulating wolf and sheep (predator-prey) ecosystem modelling.' def __init__( self, height=25, width=25, initial_walkers=1, initial_boxes=10, # initial_items=initial_boxes//2, initial_yellow_items=3, initial_blue_items=4, initial_green_items=3, initial_total_items=10, # initial_obstacles=3, # obstacle_length=7, empty_boxes={}, full_boxes={}, all_boxes={}, obstacles=[], map_choice=[], simple=True): # Model Parameters Init self.height = height self.width = width self.initial_walkers = initial_walkers self.initial_boxes = initial_boxes self.initial_total_items = initial_total_items self.initial_yellow_items = initial_yellow_items self.initial_blue_items = initial_blue_items self.initial_green_items = initial_green_items # self.initial_obstacles = initial_obstacles # self.obstacle_length = obstacle_length self.map_choice = map_choice self.step_count = 0 self.simple = simple self.start_timer = 0 self.empty_boxes = empty_boxes self.full_boxes = full_boxes self.all_boxes = all_boxes self.obstacles = obstacles # Grid self.grid_list = [] for x in range(self.width): for y in range(self.height): self.grid_list.append((x, y)) # Spawn Locations - Simple # NOTE: Could move all of these to another function to save space and to reduce the size of the make boxes/ # obstacles functions, but for now they live here self.map_one_boxes = [(5, 7), (6, 20), (8, 5), (9, 10), (12, 12), (14, 17), (18, 12), (20, 4), (21, 12), (20, 21)] # increased by 3 self.map_one_obstacles = [(6, 19), (5, 19), (7, 19), (8, 19), (10, 14), (10, 13), (10, 12), (10, 11), (10, 10), (10, 9), (15, 20), (15, 19), (15, 18), (15, 17), (15, 16), (15, 15), (15, 14), (19, 17), (20, 17), (21, 17), (22, 17), (19, 6), (20, 6), (21, 6)] # increased by 3 self.map_two_boxes = [(4, 5), (5, 14), (7, 19), (11, 8), (11, 19), (3, 15), (16, 5), (18, 16), (20, 22), (21, 20)] # increased by 3 self.map_two_obstacles = [(4, 10), (5, 10), (6, 10), (9, 21), (9, 20), (9, 19), (9, 18), (9, 17), (13, 10), (13, 9), (13, 8), (13, 7), (13, 6), (13, 5), (18, 18), (19, 18), (20, 18), (21, 18)] # increased by 3 self.map_three_boxes = [(3, 5), (5, 18), (9, 18), (9, 21), (3, 13), (14, 16), (3, 18), (19, 22), (20, 18), (21, 7)] # increased by 3 self.map_three_obstacles = [(6, 20), (6, 19), (6, 18), (6, 17), (6, 16), (11, 21), (11, 20), (11, 19), (11, 18), (11, 17), (11, 16), (11, 15), (16, 6), (16, 5), (16, 7), (16, 8), (16, 4), (3, 16), (2, 16), (18, 13), (19, 13), (20, 20), (19, 20), (18, 20), (19, 13), (20, 13)] # increased by 3 self.map_four_boxes = [(3, 14), (6, 13), (7, 17), (9, 19), (14, 22), (15, 4), (16, 7), (20, 11), (20, 21), (21, 15)] # increased by 3 self.map_four_obstacles = [(5, 18), (5, 17), (5, 16), (5, 15), (5, 14), (5, 13), (5, 12), (5, 11), (8, 19), (8, 18), (8, 17), (8, 18), (11, 20), (11, 19), (11, 18), (11, 17), (18, 18), (19, 18), (20, 18), (21, 18), (18, 8), (19, 8), (20, 8), (21, 8)] # increased by 3 self.map_five_boxes = [(4, 10), (6, 13), (7, 20), (11, 6), (14, 16), (15, 18), (18, 12), (19, 21), (3, 21), (21, 12)] # increased by 3 self.map_five_obstacles = [(5, 17), (6, 17), (7, 17), (8, 17), (8, 13), (8, 12), (8, 11), (8, 10), (8, 9), (8, 8), (16, 20), (16, 19), (16, 18), (16, 17), (16, 16), (16, 15), (16, 14), (18, 17), (19, 17), (20, 17), (21, 17), (20, 6), (21, 6), (19, 6)] # increased by 3 # Spawn Locations - Complex self.map_six_boxes = [(2, 14), (4, 9), (6, 7), (7, 20), (11, 9), (11, 19), (17, 5), (20, 14), (21, 10), (22, 21)] self.map_six_obstacles = [(1, 12), (2, 12), (3, 12), (4, 12), (4, 16), (4, 15), (4, 14), (4, 13), (8, 12), (8, 11), (8, 10), (8, 9), (8, 8), (8, 7), (8, 6), (8, 5), (8, 4), (8, 18), (9, 4), (9, 12), (10, 12), (11, 12), (9, 21), (9, 20), (9, 19), (9, 18), (10, 4), (16, 8), (17, 8), (7, 18), (18, 8), (19, 8), (19, 7), (19, 6), (19, 5), (19, 4), (19, 21), (19, 20), (19, 19), (19, 18), (20, 18), (21, 18)] self.map_seven_boxes = [(4, 19), (1, 11), (7, 12), (6, 2), (12, 20), (14, 15), (13, 9), (16, 2), (20, 17), (21, 5)] self.map_seven_obstacles = [ (2, 20), (2, 19), (2, 18), (2, 17), (2, 16), (3, 16), (4, 16), (5, 16), (6, 16), (6, 20), (6, 19), (6, 18), (6, 17), (3, 13), (3, 12), (3, 11), (3, 10), (3, 9), (3, 8), (2, 8), (11, 12), (11, 11), (11, 10), (11, 9), (11, 8), (11, 7), (12, 12), (13, 12), (14, 12), (15, 12), (16, 12), (16, 17), (16, 16), (16, 15), (16, 14), (16, 13), (19, 13), (20, 12), (21, 13), (22, 12), (15, 4), (16, 4), (17, 4), (17, 3) ] self.map_eight_boxes = [(2, 22), (3, 15), (8, 19), (7, 6), (11, 12), (13, 17), (17, 1), (18, 21), (20, 12), (20, 8)] self.map_eight_obstacles = [(2, 19), (3, 21), (3, 20), (3, 19), (4, 21), (5, 21), (6, 18), (7, 17), (7, 16), (7, 15), (8, 15), (9, 15), (10, 15), (10, 20), (10, 19), (10, 18), (10, 17), (10, 16), (12, 14), (13, 14), (14, 14), (14, 13), (14, 12), (14, 11), (14, 10), (14, 9), (14, 8), (17, 14), (17, 13), (17, 12), (17, 11), (17, 10), (18, 17), (18, 16), (18, 15), (18, 14), (19, 17), (20, 17), (16, 3), (17, 3), (18, 3)] self.map_nine_boxes = [(1, 8), (3, 5), (6, 17), (12, 16), (13, 7), (14, 19), (17, 13), (21, 18), (23, 11), (19, 4)] self.map_nine_obstacles = [(2, 11), (3, 11), (4, 11), (4, 10), (4, 9), (5, 9), (5, 8), (5, 7), (5, 6), (5, 5), (6, 15), (7, 15), (8, 15), (8, 17), (8, 16), (11, 13), (12, 13), (13, 13), (14, 13), (15, 13), (15, 20), (15, 19), (15, 18), (15, 17), (15, 16), (15, 15), (15, 14), (19, 20), (19, 19), (19, 18), (19, 17), (19, 16), (19, 15), (20, 20), (21, 20), (22, 20), (20, 15), (21, 15), (22, 15), (17, 6), (17, 5), (17, 4), (17, 3), (18, 6), (19, 6), (20, 6), (21, 6), (21, 5), (21, 4), (21, 3)] self.map_ten_boxes = [(1, 17), (6, 19), (5, 15), (3, 2), (10, 3), (13, 18), (15, 16), (20, 22), (20, 11), (15, 4)] self.map_ten_obstacles = [(3, 17), (3, 16), (3, 15), (3, 14), (4, 17), (5, 17), (6, 17), (7, 17), (8, 17), (8, 20), (8, 19), (8, 18), (2, 4), (3, 4), (4, 4), (5, 4), (5, 3), (11, 20), (11, 19), (11, 18), (11, 17), (11, 16), (11, 15), (12, 15), (13, 15), (14, 15), (14, 14), (15, 14), (16, 14), (16, 18), (16, 17), (16, 16), (16, 15), (9, 4), (9, 3), (10, 4), (11, 4), (18, 13), (18, 12), (18, 11), (18, 10), (18, 9), (19, 13), (20, 13), (21, 13), (22, 13)] self.map_eleven_boxes = [] self.map_eleven_obstacles = [] self.map_twelve_boxes = [] self.map_twelve_obstacles = [] self.map_thirteen_boxes = [] self.map_thirteen_obstacles = [] self.map_fourteen_boxes = [] self.map_fourteen_obstacles = [] self.map_fifteen_boxes = [] self.map_fifteen_obstacles = [] # Model Functions self.schedule = RandomActivationByType(self) self.grid = MultiGrid(self.height, self.width, torus=True) self.datacollector = DataCollector( {"Closed Boxes": lambda m: m.schedule.get_type_count(ClosedBox)}) # No clue why these are up here in particular - these are the actual parts of the model! self.map_picker() self.make_boxes() self.make_items() self.make_obstacles() self.make_walker_agents() # pick a map def init_timer(self): self.start_timer = time.clock() def map_picker(self): if self.simple: available_maps = ["one", "two", "three", "four", "five"] self.map_choice = random.choice(available_maps) # self.map_choice = "six" print("Map ", self.map_choice) elif not self.simple: available_maps = ["six", "seven", "eight", "nine", "ten"] # add eleven to fifteen here self.map_choice = random.choice(available_maps) print("Map ", self.map_choice) # create Boxes: def make_boxes(self): if self.map_choice == "one": for i in range(self.initial_boxes): x, y = self.map_one_boxes[i] closedBox = ClosedBox((x, y), self, True) self.grid.place_agent(closedBox, (x, y)) self.schedule.add(closedBox) # --- append this box's xy to unordered list/dict keyed by the tuples of (x,y) self.empty_boxes[i] = (x, y) self.all_boxes[i] = (x, y) # print("Empty Box Created") elif self.map_choice == "two": for i in range(self.initial_boxes): x, y = self.map_two_boxes[i] closedBox = ClosedBox((x, y), self, True) self.grid.place_agent(closedBox, (x, y)) self.schedule.add(closedBox) # --- append this box's xy to unordered list/dict keyed by the tuples of (x,y) self.empty_boxes[i] = (x, y) self.all_boxes[i] = (x, y) # print("Empty Box Created") elif self.map_choice == "three": for i in range(self.initial_boxes): x, y = self.map_three_boxes[i] closedBox = ClosedBox((x, y), self, True) self.grid.place_agent(closedBox, (x, y)) self.schedule.add(closedBox) # --- append this box's xy to unordered list/dict keyed by the tuples of (x,y) self.empty_boxes[i] = (x, y) self.all_boxes[i] = (x, y) # print("Empty Box Created") elif self.map_choice == "four": for i in range(self.initial_boxes): x, y = self.map_four_boxes[i] closedBox = ClosedBox((x, y), self, True) self.grid.place_agent(closedBox, (x, y)) self.schedule.add(closedBox) # --- append this box's xy to unordered list/dict keyed by the tuples of (x,y) self.empty_boxes[i] = (x, y) self.all_boxes[i] = (x, y) # print("Empty Box Created") elif self.map_choice == "five": for i in range(self.initial_boxes): x, y = self.map_five_boxes[i] closedBox = ClosedBox((x, y), self, True) self.grid.place_agent(closedBox, (x, y)) self.schedule.add(closedBox) # --- append this box's xy to unordered list/dict keyed by the tuples of (x,y) self.empty_boxes[i] = (x, y) self.all_boxes[i] = (x, y) # print("Empty Box Created") elif self.map_choice == "six": for i in range(self.initial_boxes): x, y = self.map_six_boxes[i] closedBox = ClosedBox((x, y), self, True) self.grid.place_agent(closedBox, (x, y)) self.schedule.add(closedBox) # --- append this box's xy to unordered list/dict keyed by the tuples of (x,y) self.empty_boxes[i] = (x, y) self.all_boxes[i] = (x, y) # print("Empty Box Created") elif self.map_choice == "seven": for i in range(self.initial_boxes): x, y = self.map_seven_boxes[i] closedBox = ClosedBox((x, y), self, True) self.grid.place_agent(closedBox, (x, y)) self.schedule.add(closedBox) # --- append this box's xy to unordered list/dict keyed by the tuples of (x,y) self.empty_boxes[i] = (x, y) self.all_boxes[i] = (x, y) # print("Empty Box Created") elif self.map_choice == "eight": for i in range(self.initial_boxes): x, y = self.map_eight_boxes[i] closedBox = ClosedBox((x, y), self, True) self.grid.place_agent(closedBox, (x, y)) self.schedule.add(closedBox) # --- append this box's xy to unordered list/dict keyed by the tuples of (x,y) self.empty_boxes[i] = (x, y) self.all_boxes[i] = (x, y) # print("Empty Box Created") elif self.map_choice == "nine": for i in range(self.initial_boxes): x, y = self.map_nine_boxes[i] closedBox = ClosedBox((x, y), self, True) self.grid.place_agent(closedBox, (x, y)) self.schedule.add(closedBox) # --- append this box's xy to unordered list/dict keyed by the tuples of (x,y) self.empty_boxes[i] = (x, y) self.all_boxes[i] = (x, y) # print("Empty Box Created") elif self.map_choice == "ten": for i in range(self.initial_boxes): x, y = self.map_ten_boxes[i] closedBox = ClosedBox((x, y), self, True) self.grid.place_agent(closedBox, (x, y)) self.schedule.add(closedBox) # --- append this box's xy to unordered list/dict keyed by the tuples of (x,y) self.empty_boxes[i] = (x, y) self.all_boxes[i] = (x, y) # print("Empty Box Created") elif self.map_choice == "eleven": for i in range(self.initial_boxes): x, y = self.map_eleven_boxes[i] closedBox = ClosedBox((x, y), self, True) self.grid.place_agent(closedBox, (x, y)) self.schedule.add(closedBox) # --- append this box's xy to unordered list/dict keyed by the tuples of (x,y) self.empty_boxes[i] = (x, y) self.all_boxes[i] = (x, y) # print("Empty Box Created") elif self.map_choice == "twelve": for i in range(self.initial_boxes): x, y = self.map_twelve_boxes[i] closedBox = ClosedBox((x, y), self, True) self.grid.place_agent(closedBox, (x, y)) self.schedule.add(closedBox) # --- append this box's xy to unordered list/dict keyed by the tuples of (x,y) self.empty_boxes[i] = (x, y) self.all_boxes[i] = (x, y) # print("Empty Box Created") elif self.map_choice == "thirteen": for i in range(self.initial_boxes): x, y = self.map_thirteen_boxes[i] closedBox = ClosedBox((x, y), self, True) self.grid.place_agent(closedBox, (x, y)) self.schedule.add(closedBox) # --- append this box's xy to unordered list/dict keyed by the tuples of (x,y) self.empty_boxes[i] = (x, y) self.all_boxes[i] = (x, y) # print("Empty Box Created") elif self.map_choice == "fourteen": for i in range(self.initial_boxes): x, y = self.map_fourteen_boxes[i] closedBox = ClosedBox((x, y), self, True) self.grid.place_agent(closedBox, (x, y)) self.schedule.add(closedBox) # --- append this box's xy to unordered list/dict keyed by the tuples of (x,y) self.empty_boxes[i] = (x, y) self.all_boxes[i] = (x, y) # print("Empty Box Created") elif self.map_choice == "fifteen": for i in range(self.initial_boxes): x, y = self.map_fifteen_boxes[i] closedBox = ClosedBox((x, y), self, True) self.grid.place_agent(closedBox, (x, y)) self.schedule.add(closedBox) # --- append this box's xy to unordered list/dict keyed by the tuples of (x,y) self.empty_boxes[i] = (x, y) self.all_boxes[i] = (x, y) # print("Empty Box Created") # --------------------- BELOW: RANDOM BOX GENERATION ------------------------- # for i in range(self.initial_boxes): # x = random.randrange(self.width) # y = random.randrange(self.height) # closedBox = ClosedBox((x, y), self, True) # self.grid.place_agent(closedBox, (x, y)) # self.schedule.add(closedBox) # # --- append this box's xy to unordered list/dict keyed by the tuples of (x,y) # self.empty_boxes[i] = (x, y) # self.all_boxes[i] = (x, y) # # print("Empty Box Created") # Create Walker: def make_walker_agents(self): for i in range(self.initial_walkers): x, y = self.grid.find_empty() print("Start Position: ", (x, y)) walker = Walker((x, y), self, True) self.grid.place_agent(walker, (x, y)) self.schedule.add(walker) def make_items(self): # this function takes the dictionary of empty boxes, selects one and puts an item in it for j in range(self.initial_total_items): chosen_box = self.empty_boxes.pop(j) # print("Box Selected") # chosen_box = self.empty_boxes.popitem() # print("Box Selected") # use the above to pop an arbitrary value from the empty boxes list types_available = ["yellow", "blue", "pink"] item_type = random.choice(types_available) if item_type == "yellow": item = yellowItem(chosen_box, self, True) elif item_type == "blue": item = blueItem(chosen_box, self, True) elif item_type == "pink": item = pinkItem(chosen_box, self, True) self.grid.place_agent(item, chosen_box) self.schedule.add(item) # print("Coloured Item Added") self.full_boxes[j] = chosen_box # print("Box Filled") self.running = True self.datacollector.collect(self) def make_obstacles(self): if self.map_choice == "one": for i in range(len(self.map_one_obstacles)): x, y = self.map_one_obstacles[i] obstacle = Obstacle((x, y), self) self.grid.place_agent(obstacle, (x, y)) self.schedule.add(obstacle) self.obstacles.append((x, y)) elif self.map_choice == "two": for i in range(len(self.map_two_obstacles)): x, y = self.map_two_obstacles[i] obstacle = Obstacle((x, y), self) self.grid.place_agent(obstacle, (x, y)) self.schedule.add(obstacle) self.obstacles.append((x, y)) elif self.map_choice == "three": for i in range(len(self.map_three_obstacles)): x, y = self.map_three_obstacles[i] obstacle = Obstacle((x, y), self) self.grid.place_agent(obstacle, (x, y)) self.schedule.add(obstacle) self.obstacles.append((x, y)) elif self.map_choice == "four": for i in range(len(self.map_four_obstacles)): x, y = self.map_four_obstacles[i] obstacle = Obstacle((x, y), self) self.grid.place_agent(obstacle, (x, y)) self.schedule.add(obstacle) self.obstacles.append((x, y)) elif self.map_choice == "five": for i in range(len(self.map_five_obstacles)): x, y = self.map_five_obstacles[i] obstacle = Obstacle((x, y), self) self.grid.place_agent(obstacle, (x, y)) self.schedule.add(obstacle) self.obstacles.append((x, y)) elif self.map_choice == "six": for i in range(len(self.map_six_obstacles)): x, y = self.map_six_obstacles[i] obstacle = Obstacle((x, y), self) self.grid.place_agent(obstacle, (x, y)) self.schedule.add(obstacle) self.obstacles.append((x, y)) elif self.map_choice == "seven": for i in range(len(self.map_seven_obstacles)): x, y = self.map_six_obstacles[i] obstacle = Obstacle((x, y), self) self.grid.place_agent(obstacle, (x, y)) self.schedule.add(obstacle) self.obstacles.append((x, y)) elif self.map_choice == "eight": for i in range(len(self.map_eight_obstacles)): x, y = self.map_six_obstacles[i] obstacle = Obstacle((x, y), self) self.grid.place_agent(obstacle, (x, y)) self.schedule.add(obstacle) self.obstacles.append((x, y)) elif self.map_choice == "nine": for i in range(len(self.map_nine_obstacles)): x, y = self.map_six_obstacles[i] obstacle = Obstacle((x, y), self) self.grid.place_agent(obstacle, (x, y)) self.schedule.add(obstacle) self.obstacles.append((x, y)) elif self.map_choice == "ten": for i in range(len(self.map_ten_obstacles)): x, y = self.map_six_obstacles[i] obstacle = Obstacle((x, y), self) self.grid.place_agent(obstacle, (x, y)) self.schedule.add(obstacle) self.obstacles.append((x, y)) elif self.map_choice == "eleven": for i in range(len(self.map_eleven_obstacles)): x, y = self.map_six_obstacles[i] obstacle = Obstacle((x, y), self) self.grid.place_agent(obstacle, (x, y)) self.schedule.add(obstacle) self.obstacles.append((x, y)) elif self.map_choice == "twelve": for i in range(len(self.map_twelve_obstacles)): x, y = self.map_six_obstacles[i] obstacle = Obstacle((x, y), self) self.grid.place_agent(obstacle, (x, y)) self.schedule.add(obstacle) self.obstacles.append((x, y)) elif self.map_choice == "thirteen": for i in range(len(self.map_thirteen_obstacles)): x, y = self.map_six_obstacles[i] obstacle = Obstacle((x, y), self) self.grid.place_agent(obstacle, (x, y)) self.schedule.add(obstacle) self.obstacles.append((x, y)) elif self.map_choice == "fourteen": for i in range(len(self.map_fourteen_obstacles)): x, y = self.map_six_obstacles[i] obstacle = Obstacle((x, y), self) self.grid.place_agent(obstacle, (x, y)) self.schedule.add(obstacle) self.obstacles.append((x, y)) elif self.map_choice == "fifteen": for i in range(len(self.map_fifteen_obstacles)): x, y = self.map_six_obstacles[i] obstacle = Obstacle((x, y), self) self.grid.place_agent(obstacle, (x, y)) self.schedule.add(obstacle) self.obstacles.append((x, y)) # ------------------------------ BELOW: RANDOM OBSTACLE GENERATION ------------------------------------ # def make_obstacles(self): # for i in range(self.initial_obstacles): # x, y = self.grid.find_empty() # initial_obstacle = (x, y) # obstacle = Obstacle((x, y), self) # self.grid.place_agent(obstacle, initial_obstacle) # self.schedule.add(obstacle) # # print("Obstacle added!") # # self.obstacles.append(initial_obstacle) # # need to think about how going to store obstacle information # # length = random.randrange(3, self.obstacle_length, 1) # # print("Length is: ", length) # neighbours = self.grid.get_neighborhood(initial_obstacle, False, False, 1) # # print("Neighbours: ", neighbours) # # directions = ["north", "east", "south", "west"] # random_direction = random.choice(directions) # # current_x = initial_obstacle[0] # current_y = initial_obstacle[1] # # for j in range(length): # if random_direction == "north": # new_obstacle = (current_x, (current_y + 1)) # # if self.grid.is_cell_empty(new_obstacle) == True: # self.grid.place_agent(obstacle, new_obstacle) # self.schedule.add(obstacle) # self.obstacles.append(new_obstacle) # current_y = current_y + 1 # print("Obstacle extension added!") # else: # print("Obstacle couldn't be placed.") # return # # if random_direction == "east": # new_obstacle = ((current_x + 1), current_y) # # if self.grid.is_cell_empty(new_obstacle) == True: # self.grid.place_agent(obstacle, new_obstacle) # self.schedule.add(obstacle) # self.obstacles.append(new_obstacle) # current_x = current_x + 1 # print("Obstacle extension added!") # else: # print("Obstacle couldn't be placed.") # return # # if random_direction == "south": # new_obstacle = (current_x, (current_y - 1)) # # if self.grid.is_cell_empty(new_obstacle) == True: # self.grid.place_agent(obstacle, new_obstacle) # self.schedule.add(obstacle) # self.obstacles.append(new_obstacle) # current_y = current_y - 1 # print("Obstacle extension added!") # else: # print("Obstacle couldn't be placed.") # return # # if random_direction == "west": # new_obstacle = ((current_x - 1), current_y) # # if self.grid.is_cell_empty(new_obstacle) == True: # self.grid.place_agent(obstacle, new_obstacle) # self.schedule.add(obstacle) # self.obstacles.append(new_obstacle) # current_x = current_x - 1 # print("Obstacle extension added!") # else: # print("Obstacle couldn't be placed.") # return # # # self.obstacles.sort() # print("Obstacle list:", self.obstacles) def step(self): self.schedule.step() # collect data self.datacollector.collect(self) if self.verbose: print( [self.schedule.time, self.schedule.get_type_count(ClosedBox)]) # stopping agents having conflicting simultaneous actions self.step_count += 1 def run_model(self, step_count=200): if self.verbose: print('Initial number walkers: ', self.schedule.get_type_count(Walker), 'Initial number closed boxes: ', self.schedule.get_type_count(ClosedBox)) for i in range(step_count): self.step() if self.verbose: print('') print('Final number walkers: ', self.schedule.get_type_count(Walker), 'Final number closed boxes: ', self.schedule.get_type_count(ClosedBox))
class EV_Model(Model): def __init__(self, N=50, width=20, height=20, n_poles=10, vision=10, grid_positions="random", initial_bravery=10, battery_size=25, open_grid=True): self.battery_size = battery_size self.initial_bravery = initial_bravery self.num_agents = N self.open = open_grid if self.open == True: self.grid = MultiGrid(width, height, True) else: self.grid = MultiGrid(width, height, False) self.schedule = RandomActivationByBreed(self) self.vision = vision self.grid_size = width # adds CPs based on the input grid position if grid_positions == "circle": center_grid = (int(width / 2), int(height / 2)) circle_list = PointsInCircum(round(self.grid_size / 4), int(N * n_poles)) for i, coord in enumerate(circle_list): new_coord = (coord[0] + center_grid[0], coord[1] + center_grid[1]) charge_pole = Charge_pole(i, new_coord, self) self.grid.place_agent(charge_pole, new_coord) self.schedule.add(charge_pole) elif grid_positions == "big circle": center_grid = (int(width / 2), int(height / 2)) circle_list = PointsInCircum(round(self.grid_size / 2 - 1), int(N * n_poles)) for i, coord in enumerate(circle_list): new_coord = (coord[0] + center_grid[0], coord[1] + center_grid[1]) charge_pole = Charge_pole(i, new_coord, self) self.grid.place_agent(charge_pole, new_coord) self.schedule.add(charge_pole) elif grid_positions == "random": for i in range(int(N * n_poles)): # Add the agent to a random grid cell empty_coord = self.grid.find_empty() charge_pole = Charge_pole(i, empty_coord, self) self.grid.place_agent(charge_pole, empty_coord) self.schedule.add(charge_pole) elif grid_positions == "LHS": coord_list = np.round( lhs(2, samples=int(N * n_poles), criterion="m") * (self.grid_size - 1)) for i in range(int(N * n_poles)): coord = tuple((int(coord_list[i][0]), int(coord_list[i][1]))) if self.grid.is_cell_empty(coord): charge_pole = Charge_pole(i, coord, self) self.grid.place_agent(charge_pole, coord) else: empty_coord = self.grid.find_empty() charge_pole = Charge_pole(i, empty_coord, self) self.grid.place_agent(charge_pole, empty_coord) self.schedule.add(charge_pole) # Create EV agents for i in range(self.num_agents): # Add the agent to a random empty grid cell home_pos = self.grid.find_empty() work_pos = self.grid.find_empty() EV = EV_Agent(i, self, self.vision, home_pos, work_pos, initial_bravery, battery_size) self.schedule.add(EV) self.grid.place_agent(EV, home_pos) self.totalEVs = i self.datacollector = DataCollector( agent_reporters={}, model_reporters={ "Avg_Battery": mean_all_battery, "Usage": avg_usage, "High_Usage": high_usage, "Low_Usage": low_usage, "Total_attempts": totalAttempts, "Percentage_failed": percentageFailed, "Average_lifespan": averageLifespan, "lower25": lowest_25_percent, "timeInState": time_in_state, "unique_battery": specific_battery, "Num_agents": count_agents, "EVs": lambda m: m.schedule.get_breed_count(EV_Agent) }) self.running = True self.current_EVs = self.totalEVs def step(self): self.schedule.step() self.datacollector.collect(self) self.stableAgents() def stableAgents(self): while self.current_EVs < self.num_agents: home_pos = self.grid.find_empty() work_pos = self.grid.find_empty() EV = EV_Agent(self.totalEVs, self, self.vision, home_pos, work_pos, self.initial_bravery, self.battery_size) self.grid.place_agent(EV, home_pos) self.schedule.add(EV) self.totalEVs += 1 self.current_EVs += 1
class AntModel(Model): def __init__(self, num_ln, num_fj, num_mk_col, num_ft_col, width, height): """ :param num_ln: Number of L. Niger agents :param num_fj: Number of F. Japonica agents :param num_mk_col: Number of M. Kuricola colonies :param num_ft_col: Number of F. Tropicalis colonies :param width: Width of the model grid :param height: Height of the model grid """ super().__init__() self.num_ln = num_ln self.num_fj = num_fj self.num_mk_col = num_mk_col self.num_ft_col = num_ft_col self.grid = MultiGrid(width, height, True) self.schedule = RandomActivation(self) self.running = True for h in range(self.num_fj): ant = FJaponica(uuid4(), self) self.schedule.add(ant) self.grid.place_agent(ant, self.grid.find_empty()) for j in range(self.num_mk_col): colony = MKuricolaColony(uuid4(), self) self.schedule.add(colony) self.grid.place_agent(colony, self.grid.find_empty()) for k in range(self.num_ft_col): colony = FTropicalisColony(uuid4(), self) self.schedule.add(colony) self.grid.place_agent(colony, self.grid.find_empty()) for i in range(self.num_ln): ant = LNiger(uuid4(), self) self.schedule.add(ant) self.grid.place_agent(ant, self.grid.find_empty()) ant._init_post_place() self.data_collector = DataCollector( model_reporters={}, agent_reporters={"states": ant_state_collector}) self.weights_dict = json.load(open("newout.json", "r")) def drop_pheromone(self, location): """ Drops a LNPheromone object at the given location if one does not already exist. If one does already exist, 1 is added to the existing object's 'tracks' field. :param location: An (x, y) tuple detailing the location to drop the pheromone. :return: None """ if not self.is_pheromone_in_cell(location): self.grid.place_agent(LNPheromone(uuid4(), self), location) else: self.get_pheromone_in_cell(location).tracks += 1 def is_pheromone_in_cell(self, location): """ Determines if a pheromone already exists in a given cell. :param location: The location to check. :return: boolean """ return True in [ type(x) == LNPheromone for x in self.grid.get_cell_list_contents(location) ] def is_ant_in_cell(self, location): """ Determines whether an ant exists in a given cell. :param location: The location to check. :return: boolean """ return True in [ isinstance(x, Ant) for x in self.grid.get_cell_list_contents(location) ] def is_colony_in_cell(self, location): """ Determines whether an aphid colony exists in a given cell. :param location: The location to check. :return: boolean """ return True in [ type(x) == MKuricolaColony or type(x) == FTropicalisColony for x in self.grid.get_cell_list_contents(location) ] def get_pheromone_in_cell(self, location): """ Returns a LNPheromone object from a cell. ASsumes the cell has already been proven to have a pheromone object in it. :param location: The cell location to check. :return: The LNPheromone object within the cell. """ in_cell_pheromone = None for i in self.grid.get_cell_list_contents(location): if type(i) == LNPheromone: in_cell_pheromone = i return in_cell_pheromone def get_closest_agent_of_type(self, agent, agent_type): """ Gets the closest agent (besides self) of type agent_type. Returns -1 if it cannot find one. :param agent: The agent to find the closest agent_type to. :param agent_type: The type of the agent we are looking for. :return: """ for radius in range(1, self.grid.width): for neighbor in self.grid.get_neighbors(pos=agent.pos, moore=True, include_center=False, radius=radius): if isinstance(neighbor, agent_type): return neighbor return -1 def get_closest_colony(self, agent): """ Gets the closest colony to an agent. If an agent is of type colony, it returns itself. :param agent: The agent to find the closest colony to. :return: The closest colony or -1 if not found. """ return self.get_closest_agent_of_type(agent, Colony) @staticmethod def distance_between_cells(location_a, location_b): """ Calculates the distance between two cells on the grid. :param location_a: First cell location. :param location_b: Second cell location. :return: """ return np.sqrt((location_a[0] - location_b[0])**2 + (location_a[1] - location_a[1])**2) def get_nearest_cell_to_goal(self, goal_cell, possible_cells): """ Returns the cell from a list of possible cells which is closest to the end location. :param goal_cell: The goal cell of the agent :param possible_cells: Candidate cells. :return: The location of the closest cell to the goal cell. """ closest_neighbor_index = -1 closest_neighbor_distance = np.inf for i in range(0, len(possible_cells)): dist = self.distance_between_cells(possible_cells[i], goal_cell) if dist < closest_neighbor_distance: closest_neighbor_index = i closest_neighbor_distance = dist return possible_cells[closest_neighbor_index] def get_number_of_agents_in_radius(self, location, radius, agent_type): """ Returns the number of agents of type agent_type within a radius (not including center) of location. :param location: Location to search around. :param radius: Radius to search. :param agent_type: Type of agent to search for. :return: int """ total_agents = 0 for neighbor in self.grid.get_neighbors(pos=location, moore=True, include_center=False, radius=radius): if isinstance(neighbor, agent_type): total_agents += 1 return total_agents def get_all_of_agent_type(self, agent_type): """ Returns all instances of agents of type agent_type in the Grid. :param agent_type: The type of agent to find. :return: A list of agent objects. """ return [ x for x in self.grid.get_neighbors(pos=(0, 0), moore=True, include_center=True, radius=self.grid.width) if isinstance(x, agent_type) ] def step(self): """ A method called every step that occurs :return: None """ self.data_collector.collect(self) self.schedule.step()
class FireEvacuation(Model): MIN_HEALTH = 0.75 MAX_HEALTH = 1 MIN_SPEED = 1 MAX_SPEED = 2 MIN_NERVOUSNESS = 1 MAX_NERVOUSNESS = 10 MIN_EXPERIENCE = 1 MAX_EXPERIENCE = 10 MIN_VISION = 1 # MAX_VISION is simply the size of the grid def __init__(self, floor_plan_file, human_count, collaboration_percentage, fire_probability, visualise_vision, random_spawn, save_plots): # Load floorplan # floorplan = np.genfromtxt(path.join("fire_evacuation/floorplans/", floor_plan_file)) with open(os.path.join("fire_evacuation/floorplans/", floor_plan_file), "rt") as f: floorplan = np.matrix([line.strip().split() for line in f.readlines()]) # Rotate the floorplan so it's interpreted as seen in the text file floorplan = np.rot90(floorplan, 3) # Check what dimension our floorplan is width, height = np.shape(floorplan) # Init params self.width = width self.height = height self.human_count = human_count self.collaboration_percentage = collaboration_percentage self.visualise_vision = visualise_vision self.fire_probability = fire_probability self.fire_started = False # Turns to true when a fire has started self.save_plots = save_plots # Set up model objects self.schedule = RandomActivation(self) self.grid = MultiGrid(height, width, torus=False) # Used to start a fire at a random furniture location self.furniture_list = [] # Used to easily see if a location is a FireExit or Door, since this needs to be done a lot self.fire_exit_list = [] self.door_list = [] # If random spawn is false, spawn_list will contain the list of possible spawn points according to the floorplan self.random_spawn = random_spawn self.spawn_list = [] # Load floorplan objects for (x, y), value in np.ndenumerate(floorplan): value = str(value) floor_object = None if value is "W": floor_object = Wall((x, y), self) elif value is "E": floor_object = FireExit((x, y), self) self.fire_exit_list.append((x, y)) self.door_list.append((x, y)) # Add fire exits to doors as well, since, well, they are elif value is "F": floor_object = Furniture((x, y), self) self.furniture_list.append((x, y)) elif value is "D": floor_object = Door((x, y), self) self.door_list.append((x, y)) elif value is "S": self.spawn_list.append((x, y)) if floor_object: self.grid.place_agent(floor_object, (x, y)) self.schedule.add(floor_object) # Create a graph of traversable routes, used by agents for pathing self.graph = nx.Graph() for agents, x, y in self.grid.coord_iter(): pos = (x, y) # If the location is empty, or a door if not agents or any(isinstance(agent, Door) for agent in agents): neighbors = self.grid.get_neighborhood(pos, moore=True, include_center=True, radius=1) for neighbor in neighbors: # If there is contents at this location and they are not Doors or FireExits, skip them if not self.grid.is_cell_empty(neighbor) and neighbor not in self.door_list: continue self.graph.add_edge(pos, neighbor) # Collects statistics from our model run self.datacollector = DataCollector( { "Alive": lambda m: self.count_human_status(m, Human.Status.ALIVE), "Dead": lambda m: self.count_human_status(m, Human.Status.DEAD), "Escaped": lambda m: self.count_human_status(m, Human.Status.ESCAPED), "Incapacitated": lambda m: self.count_human_mobility(m, Human.Mobility.INCAPACITATED), "Normal": lambda m: self.count_human_mobility(m, Human.Mobility.NORMAL), "Panic": lambda m: self.count_human_mobility(m, Human.Mobility.PANIC), "Verbal Collaboration": lambda m: self.count_human_collaboration(m, Human.Action.VERBAL_SUPPORT), "Physical Collaboration": lambda m: self.count_human_collaboration(m, Human.Action.PHYSICAL_SUPPORT), "Morale Collaboration": lambda m: self.count_human_collaboration(m, Human.Action.MORALE_SUPPORT) } ) # Calculate how many agents will be collaborators number_collaborators = int(round(self.human_count * (self.collaboration_percentage / 100))) # Start placing human agents for i in range(0, self.human_count): if self.random_spawn: # Place human agents randomly pos = self.grid.find_empty() else: # Place human agents at specified spawn locations pos = random.choice(self.spawn_list) if pos: # Create a random human health = random.randint(self.MIN_HEALTH * 100, self.MAX_HEALTH * 100) / 100 speed = random.randint(self.MIN_SPEED, self.MAX_SPEED) if number_collaborators > 0: collaborates = True number_collaborators -= 1 else: collaborates = False # Vision statistics obtained from http://www.who.int/blindness/GLOBALDATAFINALforweb.pdf vision_distribution = [0.0058, 0.0365, 0.0424, 0.9153] vision = int(np.random.choice(np.arange(self.MIN_VISION, self.width + 1, (self.width / len(vision_distribution))), p=vision_distribution)) nervousness_distribution = [0.025, 0.025, 0.1, 0.1, 0.1, 0.3, 0.2, 0.1, 0.025, 0.025] # Distribution with slight higher weighting for above median nerovusness nervousness = int(np.random.choice(range(self.MIN_NERVOUSNESS, self.MAX_NERVOUSNESS + 1), p=nervousness_distribution)) # Random choice starting at 1 and up to and including 10 experience = random.randint(self.MIN_EXPERIENCE, self.MAX_EXPERIENCE) belief_distribution = [0.9, 0.1] # [Believes, Doesn't Believe] believes_alarm = np.random.choice([True, False], p=belief_distribution) human = Human(pos, health=health, speed=speed, vision=vision, collaborates=collaborates, nervousness=nervousness, experience=experience, believes_alarm=believes_alarm, model=self) self.grid.place_agent(human, pos) self.schedule.add(human) else: print("No tile empty for human placement!") self.running = True # Plots line charts of various statistics from a run def save_figures(self): DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) OUTPUT_DIR = DIR + "/output" results = self.datacollector.get_model_vars_dataframe() dpi = 100 fig, axes = plt.subplots(figsize=(1920 / dpi, 1080 / dpi), dpi=dpi, nrows=1, ncols=3) status_results = results.loc[:, ['Alive', 'Dead', 'Escaped']] status_plot = status_results.plot(ax=axes[0]) status_plot.set_title("Human Status") status_plot.set_xlabel("Simulation Step") status_plot.set_ylabel("Count") mobility_results = results.loc[:, ['Incapacitated', 'Normal', 'Panic']] mobility_plot = mobility_results.plot(ax=axes[1]) mobility_plot.set_title("Human Mobility") mobility_plot.set_xlabel("Simulation Step") mobility_plot.set_ylabel("Count") collaboration_results = results.loc[:, ['Verbal Collaboration', 'Physical Collaboration', 'Morale Collaboration']] collaboration_plot = collaboration_results.plot(ax=axes[2]) collaboration_plot.set_title("Human Collaboration") collaboration_plot.set_xlabel("Simulation Step") collaboration_plot.set_ylabel("Successful Attempts") collaboration_plot.set_ylim(ymin=0) timestr = time.strftime("%Y%m%d-%H%M%S") plt.suptitle("Percentage Collaborating: " + str(self.collaboration_percentage) + "%, Number of Human Agents: " + str(self.human_count), fontsize=16) plt.savefig(OUTPUT_DIR + "/model_graphs/" + timestr + ".png") plt.close(fig) # Starts a fire at a random piece of furniture with file_probability chance def start_fire(self): rand = random.random() if rand < self.fire_probability: fire_furniture = random.choice(self.furniture_list) fire = Fire(fire_furniture, self) self.grid.place_agent(fire, fire_furniture) self.schedule.add(fire) self.fire_started = True print("Fire started at:", fire_furniture) def step(self): """ Advance the model by one step. """ self.schedule.step() # If there's no fire yet, attempt to start one if not self.fire_started: self.start_fire() self.datacollector.collect(self) # If no more agents are alive, stop the model and collect the results if self.count_human_status(self, Human.Status.ALIVE) == 0: self.running = False if self.save_plots: self.save_figures() @staticmethod def count_human_collaboration(model, collaboration_type): """ Helper method to count the number of collaborations performed by Human agents in the model """ count = 0 for agent in model.schedule.agents: if isinstance(agent, Human): if collaboration_type == Human.Action.VERBAL_SUPPORT: count += agent.get_verbal_collaboration_count() elif collaboration_type == Human.Action.MORALE_SUPPORT: count += agent.get_morale_collaboration_count() elif collaboration_type == Human.Action.PHYSICAL_SUPPORT: count += agent.get_physical_collaboration_count() return count @staticmethod def count_human_status(model, status): """ Helper method to count the status of Human agents in the model """ count = 0 for agent in model.schedule.agents: if isinstance(agent, Human): if agent.get_status() == status: count += 1 return count @staticmethod def count_human_mobility(model, mobility): """ Helper method to count the mobility of Human agents in the model """ count = 0 for agent in model.schedule.agents: if isinstance(agent, Human): if agent.get_mobility() == mobility: count += 1 return count
class InfectionModel(Model): """A model for infection spread.""" def __init__(self, human_count, random_spawn, save_plots, floor_plan_file="floorplan_1.txt", N=30, width=10, height=10, ptrans=0.5, progression_period=3, progression_sd=2, death_rate=0.0193, recovery_days=21, recovery_sd=7): # Load floorplan # floorplan = np.genfromtxt(path.join("infection_spread/floorplans/", floor_plan_file)) with open( os.path.join("infection_spread/floorplans/", floor_plan_file), "rt") as f: floorplan = np.matrix( [line.strip().split() for line in f.readlines()]) # Rotate the floorplan so it's interpreted as seen in the text file floorplan = np.rot90(floorplan, 3) # Check what dimension our floorplan is width, height = np.shape(floorplan) # Init params self.num_agents = N self.initial_outbreak_size = 1 self.recovery_days = recovery_days self.recovery_sd = recovery_sd self.ptrans = ptrans self.death_rate = death_rate self.running = True self.dead_agents = [] self.width = width self.height = height self.human_count = human_count # Set up model objects self.schedule = RandomActivation(self) self.grid = MultiGrid(height, width, torus=False) # Used to easily see if a location is an Exit or Door, since this needs to be done a lot self.exit_list = [] self.door_list = [] # If random spawn is false, spawn_list will contain the list of possible spawn points according to the floorplan self.random_spawn = random_spawn self.spawn_list = [] # Load floorplan objects for (x, y), value in np.ndenumerate(floorplan): value = str(value) floor_object = None if value == "W": floor_object = Wall((x, y), self) elif value == "E": floor_object = Exit((x, y), self) self.exit_list.append((x, y)) self.door_list.append((x, y)) # Add exits to doors as well elif value == "D": floor_object = Door((x, y), self) self.door_list.append((x, y)) elif value == "S": self.spawn_list.append((x, y)) if floor_object: self.grid.place_agent(floor_object, (x, y)) self.schedule.add(floor_object) # Create a graph of traversable routes, used by agents for pathing self.graph = nx.Graph() for agents, x, y in self.grid.coord_iter(): pos = (x, y) # If the location is empty, or a door if not agents or any(isinstance(agent, Door) for agent in agents): neighbors = self.grid.get_neighborhood(pos, moore=True, include_center=True, radius=1) for neighbor in neighbors: # If there is contents at this location and they are not Doors or Exits, skip them if not self.grid.is_cell_empty( neighbor) and neighbor not in self.door_list: continue self.graph.add_edge(pos, neighbor) # Collects statistics from our model run self.datacollector = DataCollector({ "Susceptible": lambda m: self.count_human_status(m, Human.State.SUSCEPTIBLE), "Infected": lambda m: self.count_human_status(m, Human.State.INFECTED), "Removed": lambda m: self.count_human_status(m, Human.State.REMOVED) }) # Start placing human agents # for i in range(0, self.human_count): # if self.random_spawn: # Place human agents randomly # pos = self.grid.find_empty() # else: # Place human agents at specified spawn locations # pos = random.choice(self.spawn_list) #if pos: # Create a random human # health = random.randint(self.MIN_HEALTH * 100, self.MAX_HEALTH * 100) / 100 # speed = random.randint(self.MIN_SPEED, self.MAX_SPEED) for i in range(0, self.num_agents): a = Human(unique_id=i, model=self) self.schedule.add(a) # Add the agent to a random grid cell # x = self.random.randrange(self.grid.width) # y = self.random.randrange(self.grid.height) # self.grid.place_agent(a, (x, y)) if self.random_spawn: # Place human agents randomly pos = self.grid.find_empty() else: # Place human agents at specified spawn locations pos = random.choice(self.spawn_list) self.grid.place_agent(a, pos) #make some agents infected at start infected = np.random.choice([0, 1], 1, p=[0.98, 0.02]) if infected == 1: a.state = State.INFECTED a.recovery_time = self.get_recovery_time() self.datacollector = DataCollector( #model_reporters={"Gini": compute_gini}, agent_reporters={"State": "state"}) def get_recovery_time(self): return int( self.random.normalvariate(self.recovery_days, self.recovery_sd)) def step(self): """ Advance the model by one step. """ self.schedule.step() self.datacollector.collect(self)