class Covid(Model): ''' Covid model class. Handles agent creation, placement and scheduling. ''' def __init__(self, population=100, width=100, height=100, mobility=6, social_distance=2, asymptomatic_percentage=50.0): ''' Create a new Covid model. Args: population: Number of people (density) with one asymptomatic infected person. asymptomatic_percentage: Percentage of infected people that are asymptomatic. Asymptomatic people transmit the virus for 42 time steps versus 15 time steps for those that are symptomatic. social_distance: Distance at which neighboring susceptible agents can b ecome infected. mobility: The maximum distance that an agent can travel. ''' self.current_id = 0 self.population = population self.mobility = mobility self.social_distance = social_distance self.asymptomatic_percentage = asymptomatic_percentage self.state = "home" self.schedule = RandomActivation(self) self.space = ContinuousSpace(width, height, False) self.image = Image.open(r"nmcounties.jpg") self.num = { 'San Juan': 0, 'Rio Arriba': 0, 'Taos': 0, 'Colfax': 0, 'Union': 0, 'Los Alamos': 0, 'Mora': 0, 'Harding': 0, 'McKinley': 0, 'Sandoval': 0, 'Santa Fe': 0, 'San Miguel': 0, 'Quay': 0, 'Cibola': 0, 'Valencia': 0, 'Bernalillo': 0, 'Torrance': 0, 'Guadalupe': 0, 'Curry': 0, 'Catron': 0, 'Socorro': 0, 'Lincoln': 0, 'De Baca': 0, 'Roosevelt': 0, 'Sierra': 0, 'Chaves': 0, 'Hidalgo': 0, 'Grant': 0, 'Luna': 0, 'Doña Ana': 0, 'Otero': 0, 'Eddy': 0, 'Lea': 0, } self.pop = { 'San Juan': 0, 'Rio Arriba': 0, 'Taos': 0, 'Colfax': 0, 'Union': 0, 'Los Alamos': 0, 'Mora': 0, 'Harding': 0, 'McKinley': 0, 'Sandoval': 0, 'Santa Fe': 0, 'San Miguel': 0, 'Quay': 0, 'Cibola': 0, 'Valencia': 0, 'Bernalillo': 0, 'Torrance': 0, 'Guadalupe': 0, 'Curry': 0, 'Catron': 0, 'Socorro': 0, 'Lincoln': 0, 'De Baca': 0, 'Roosevelt': 0, 'Sierra': 0, 'Chaves': 0, 'Hidalgo': 0, 'Grant': 0, 'Luna': 0, 'Doña Ana': 0, 'Otero': 0, 'Eddy': 0, 'Lea': 0, } with open('counties.csv') as csvfile: reader = csv.reader(csvfile, delimiter=',', quotechar='"') for row in reader: county = row[2].replace(' County', '') if (county != '' and county != 'County'): population = row[3].replace(',', '') self.pop[county] = population total = 0 for value in self.pop.values(): total += int(value) for county, value in self.pop.items(): self.pop[county] = round( int(self.population) * int(value) / int(total)) total = 0 for value in self.pop.values(): total += int(value) if (self.population != total): self.pop['Bernalillo'] += self.population - total self.make_agents() self.running = True self.datacollector = DataCollector({ "Susceptible": lambda m: self.count("Susceptible"), "Infected": lambda m: self.count("Infected"), "Recovered": lambda m: self.count("Recovered") }) def counties(self, pixel): if (pixel == (87, 127, 77)): return 'San Juan' elif (pixel == (168, 144, 178)): return 'Rio Arriba' elif (pixel == (131, 141, 91)): return 'Taos' elif (pixel == (189, 204, 119)): return 'Colfax' elif (pixel == (197, 112, 58)): return 'Union' elif (pixel == (211, 165, 80)): return 'Los Alamos' elif (pixel == (186, 81, 52)): return 'Mora' elif (pixel == (106, 97, 126)): return 'Harding' elif (pixel == (91, 124, 143)): return 'McKinley' elif (pixel == (92, 59, 40)): return 'Sandoval' elif (pixel == (75, 113, 116)): return 'Santa Fe' elif (pixel == (109, 103, 53)): return 'San Miguel' elif (pixel == (49, 73, 73)): return 'Quay' elif (pixel == (178, 62, 49)): return 'Cibola' elif (pixel == (138, 99, 84)): return 'Valencia' elif (pixel == (137, 184, 214)): return 'Bernalillo' elif (pixel == (106, 106, 104)): return 'Torrance' elif (pixel == (146, 117, 87)): return 'Guadalupe' elif (pixel == (156, 150, 88)): return 'Curry' elif (pixel == (67, 94, 149)): return 'Catron' elif (pixel == (55, 80, 50)): return 'Socorro' elif (pixel == (145, 186, 178)): return 'Lincoln' elif (pixel == (82, 33, 37)): return 'De Baca' elif (pixel == (195, 189, 189)): return 'Roosevelt' elif (pixel == (238, 219, 99)): return 'Sierra' elif (pixel == (243, 234, 129)): return 'Chaves' elif (pixel == (41, 30, 60)): return 'Hidalgo' elif (pixel == (116, 140, 106)): return 'Grant' elif (pixel == (11, 10, 8)): return 'Luna' elif (pixel == (157, 56, 74)): return 'Doña Ana' elif (pixel == (52, 53, 48)): return 'Otero' elif (pixel == (207, 144, 135)): return 'Eddy' elif (pixel == (138, 171, 80)): return 'Lea' else: return '' def make_agents(self): ''' Create self.population agents, with random positions and starting headings. ''' for i in range(self.population): pos = self.inside() person = Susceptible(self.next_id(), self, pos) self.space.place_agent(person, pos) self.schedule.add(person) agent_key = random.randint(0, self.population - 1) agent = self.schedule._agents[agent_key] asymptomatic = True person = Infected(self.next_id(), self, agent.pos, True) person.set_imperial(agent.home, agent.work, agent.travel) self.space.remove_agent(agent) self.schedule.remove(agent) self.space.place_agent(person, person.pos) self.schedule.add(person) def inside(self): while (1): x = self.random.random() * self.space.x_max y = self.random.random() * self.space.y_max if (y > 10.0 and y < self.space.y_max - 10.0 and x > 10.0 and x < self.space.x_max - 10.0): coordinate = x, y pixel = self.image.getpixel(coordinate) if (pixel != (255, 255, 255)): county = self.counties(pixel) if (county != ''): if (self.num[county] < self.pop[county]): self.num[county] += 1 return np.array((x, y)) def step(self): self.infect() if self.state == "home": self.state = "work" elif self.state == "work": self.state = "community" elif self.state == "community": self.state = "home" self.schedule.step() # collect data self.datacollector.collect(self) if self.count("Infected") == 0: self.running = False def infect(self): agent_keys = list(self.schedule._agents.keys()) susceptible = [] for agent_key in agent_keys: if self.schedule._agents[agent_key].name == "Susceptible": susceptible.append(agent_key) for agent_key in susceptible: agent = self.schedule._agents[agent_key] neighbors = self.space.get_neighbors(agent.pos, self.social_distance) for neighbor in neighbors: if neighbor.name == "Infected": asymptomatic = False if (100.0 * self.random.random() < self.asymptomatic_percentage): asymptomatic = True person = Infected(self.next_id(), self, agent.pos, asymptomatic) person.set_imperial(agent.home, agent.work, agent.travel) self.space.remove_agent(agent) self.schedule.remove(agent) self.space.place_agent(person, person.pos) self.schedule.add(person) break def count(self, type): agent_keys = list(self.schedule._agents.keys()) num = 0 for agent_key in agent_keys: if self.schedule._agents[agent_key].name == type: num += 1 return num
class TestSpaceAgentMapping(unittest.TestCase): ''' Testing a continuous space for agent mapping during removal. ''' def setUp(self): ''' Create a test space and populate with Mock Agents. ''' self.space = ContinuousSpace(70, 50, False, -30, -30) self.agents = [] for i, pos in enumerate(REMOVAL_TEST_AGENTS): a = MockAgent(i, None) self.agents.append(a) self.space.place_agent(a, pos) def test_remove_first(self): ''' Test removing the first entry ''' agent_to_remove = self.agents[0] self.space.remove_agent(agent_to_remove) for i, agent in self.space._index_to_agent.items(): assert agent.pos == tuple(self.space._agent_points[i, :]) assert i == self.space._agent_to_index[agent] assert agent_to_remove not in self.space._agent_to_index assert agent_to_remove.pos is None with self.assertRaises(Exception): self.space.remove_agent(agent_to_remove) def test_remove_last(self): ''' Test removing the last entry ''' agent_to_remove = self.agents[-1] self.space.remove_agent(agent_to_remove) for i, agent in self.space._index_to_agent.items(): assert agent.pos == tuple(self.space._agent_points[i, :]) assert i == self.space._agent_to_index[agent] assert agent_to_remove not in self.space._agent_to_index assert agent_to_remove.pos is None with self.assertRaises(Exception): self.space.remove_agent(agent_to_remove) def test_remove_middle(self): ''' Test removing a middle entry ''' agent_to_remove = self.agents[3] self.space.remove_agent(agent_to_remove) for i, agent in self.space._index_to_agent.items(): assert agent.pos == tuple(self.space._agent_points[i, :]) assert i == self.space._agent_to_index[agent] assert agent_to_remove not in self.space._agent_to_index assert agent_to_remove.pos is None with self.assertRaises(Exception): self.space.remove_agent(agent_to_remove)
class BoidFlockers(Model): """ Flocker model class. Handles agent creation, placement and scheduling. """ def __init__( self, population=100, width=100, height=100, speed=1, vision=10, separation=2, rate = 10, size_factor = 2, sim_length = 1200, angle_min = -180, angle_max = 180): """ Create a new Flockers model. Args: width, height: Size of the space. speed: How fast should the Boids move. vision: 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 """ self.population = population self.unique_id = 1 self.vision = vision self.speed = speed self.separation = separation self.schedule = RandomActivation(self) self.space = ContinuousSpace(width, height, False) self.size_factor = size_factor self.angle_min = angle_min self.angle_max = angle_max self.running = True self.rate = rate self.kill_agents = [] self.queue = [] self.input_rate = 0 self.num_agents = 0 self.arrival = 0 self.departure = 0 self.n_confs = 0 self.n_intrusion = 0 self.dep_del = 0 self.enroute_del = 0 self.tot_del = self.dep_del + self.enroute_del self.sim_length = sim_length self.datacollector = DataCollector( model_reporters= {"Occupancy": compute_N, "Total flow": compute_flow, "Effective flow": compute_eff_flow, "Inpute rate": compute_inp, "Output rate": compute_out, 'Effective speed': compute_eff_speed , 'Speed': compute_speed, 'Queue length': compute_queue_len, 'size':'size_factor', 'inp_rate':'rate', 'vision':'vision', 'def_speed':'speed', 'sep':'separation', 'Departure Delay':'dep_del', 'Enroute Delay': 'enroute_del', 'Total Delay': 'tot_del', 'N Conflicts': 'n_confs', 'N Intrusions': 'n_intrusion', 'N Arrivals': 'arrival', 'N Departures': 'departure' }, agent_reporters = {'id':'unique_id', 'prev_dist':'previos_distance', 'cur_dist':'current_distance', 'phys_speed':'physic_speed', 'vision':'vision', 'def_speed':'speed', 'sep':'separation', 'x': lambda x: x.pos[0], 'y': lambda x: x.pos[1]} ) def make_od(self): x = self.space.x_max/2 + np.random.uniform(-1,1)\ * self.space.x_max/2/self.size_factor y = self.space.y_max/2 + np.random.uniform(-1,1)\ * self.space.y_max/2/self.size_factor pos = np.array((x, y)) x_dest = self.space.x_max/2 + np.random.uniform(-1,1) \ * self.space.x_max/2/self.size_factor y_dest = self.space.y_max/2 + np.random.uniform(-1,1) \ * self.space.y_max/2/self.size_factor dest = np.array((x_dest, y_dest)) return pos,dest def make_od2(self): valid = False while valid == False: x = self.space.x_max/2 + np.random.uniform(-1,1)\ * self.space.x_max/2/self.size_factor y = self.space.y_max/2 + np.random.uniform(-1,1)\ * self.space.y_max/2/self.size_factor pos = np.array((x, y)) x_dest = self.space.x_max/2 + np.random.uniform(-1,1) \ * self.space.x_max/2/self.size_factor y_dest = self.space.y_max/2 + np.random.uniform(-1,1) \ * self.space.y_max/2/self.size_factor dest = np.array((x_dest, y_dest)) vector = (dest - pos)/np.linalg.norm((dest - pos)) angle = np.arctan2(vector[0],vector[1]) * 180 / np.pi if angle >= self.angle_min and angle <= self.angle_max: valid =True else: continue return pos, dest def make_agents(self, od, init_time): pos = od[0] dest = od[1] velocity = np.random.random(2) * 2 - 1 boid = Boid( unique_id=self.unique_id, model=self, pos=pos, speed = self.speed, velocity=velocity, destination = dest, vision=self.vision, separation=self.separation, init_time = init_time ) return boid def place_boid(self, boid): self.space.place_agent(boid, boid.pos) self.schedule.add(boid) def agent_maker(self): per_step = self.rate/60 fractional = per_step % 1 integer = int(per_step - round(fractional)) num_frac = np.random.binomial(size=1, n=1, p= fractional) self.input_rate = int(integer+num_frac) #create agents for i in range(self.input_rate): od = self.make_od2() agent = self.make_agents(od, init_time = self.schedule.time) agent.od_dist = agent.distance() self.unique_id += 1 if self.num_agents >= 1: neighbors = self.space.get_neighbors(od[0], self.separation, False) if len(neighbors) == 0: agent.entry_time = self.schedule.time self.place_boid(agent) self.arrival += 1 self.num_agents += 1 #print('first attempt!') else: self.queue.append(agent) if self.num_agents == 0: agent.entry_time = self.schedule.time self.place_boid(agent) self.arrival += 1 self.num_agents += 1 def queue_clearer(self, time): for index, agent in enumerate(self.queue): od = agent.pos # print(od) neighbors = self.space.get_neighbors(od[0], self.separation, False) if len(neighbors) == 0: agent.entry_time = time # agent.dep_del = max(agent.entry_time - agent.init_time,0) # print('second attempt!',agent.unique_id,agent.init_time, agent.entry_time, agent.dep_del) self.dep_del += agent.entry_time - agent.init_time self.place_boid(agent) self.arrival += 1 self.num_agents += 1 del self.queue[index] else: pass def step(self): """ Create agents here """ #collect data # try: self.n_confs = 0 self.n_intrusion = 0 #compute input rate for step if self.schedule.time <self.sim_length: self.agent_maker() else: pass self.queue_clearer(time= self.schedule.time) self.kill_agents = [] #make 1 step self.schedule.step() #remove agents that arrived at their destinations self.departure += len(self.kill_agents) for i in self.kill_agents: self.enroute_del += i.enroute_del self.schedule.remove(i) self.num_agents -= 1 self.space.remove_agent(i) try: self.datacollector.collect(self) except: pass
class PJIAModel(Model): """A model with some number of agents.""" def __init__( self, # Define canvas width=1000, height=1000 * 480. / 1100, # Define agents n_offloaders=1, offloaders_speed=5, coordinator_memory=2, equipment_speed=10, # Define actions of agents arrival_window=30, interaction_aircraft_offloader=10, interaction_coordinator_offloader=5, interaction_aircraft_coordinator=5, # Define positions [% of canvas] offloaders_position=[0.1, 0.2], coordinator_position=[0.05, 0.5], equipment_position=[0.2, 0.1], terminal_building_pos=[0.25, 0.21]): # Define canvas self.space = ContinuousSpace(width, height, False) self.airport_coordinates = airport_coordinates # Define aircraft agents self.aircraft_schedule = acSchema self.n_aircraft = len(self.aircraft_schedule.Arrival) self.total_amount_cargo = sum(self.aircraft_schedule.Cargo) # Define coordinator agents self.coordinator_position = coordinator_position self.coordinator_memory = coordinator_memory # Define the offloaders agents self.n_offloaders = n_offloaders self.offloaders_position = offloaders_position self.offloaders_speed = offloaders_speed # Define Equipment objects: self.equipment_position = equipment_position self.equipment_speed = equipment_speed # Define Cargo objects: self.cargo_number = 0 # will be used for later agents/objects #self.terminal_building_pos = terminal_building_pos self.terminal_building_pos = [ terminal_building_pos[0] * self.space.x_max, terminal_building_pos[1] * self.space.y_max ] # Define interactions: self.interaction_aircraft_offloader = interaction_aircraft_offloader self.interaction_coordinator_offloader = interaction_coordinator_offloader self.interaction_aircraft_coordinator = interaction_aircraft_coordinator # ============================================================================= # voor taxiing # ============================================================================= # Copy the the table from excel self.taxi_coordinates_excel = pd.DataFrame.copy(airport_coordinates, deep=True) # Multiply the coordinates in excel (which are in percentage) by the width and height of the grid self.taxi_coordinates_excel['X_pos'] *= self.space.x_max self.taxi_coordinates_excel['Y_pos'] *= self.space.y_max # make array with only coordinates self.taxi_coordinates = np.array([[ self.taxi_coordinates_excel['X_pos'][0], self.taxi_coordinates_excel['Y_pos'][0] ]]) for i in range(1, len(self.taxi_coordinates_excel)): self.taxi_coordinates = np.append(self.taxi_coordinates, [[ self.taxi_coordinates_excel['X_pos'][i], self.taxi_coordinates_excel['Y_pos'][i] ]], axis=0) # make array with only taxi nodes coordinates: self.CP_coordinates = self.taxi_coordinates[13:] # Civilian Parking spots, name and occupation #self.CP_spots = {'CP1' : 'Free', 'CP2': 'Free', 'CP3': 'Free', 'CP4': 'Free', 'CP5': 'Free', 'CP6': 'Free', 'CP7': 'Free', 'CP8': 'Free', 'CP9': 'Free', 'CP10': 'Free'} #self.CP_spots_occupation = ['Free','Free', 'Free', 'Free', 'Free', 'Free','Free', 'Free','Free'] self.CP_spots_occupation = [ 'Free', 'Free', 'Occupied', 'Free', 'Occupied', 'Free', 'Free', 'Free', 'Free' ] self.CP_spots_name = [ 'CP1', 'CP2', 'CP3', 'CP4', 'CP5', 'CP6', 'CP7', 'CP8', 'CP9' ] # Determine all the routes from start point to parking self.route_S1_CP14 = np.array([self.taxi_coordinates[0]]) self.route_S2_CP14 = np.array( [self.taxi_coordinates[1], self.taxi_coordinates[0]]) self.route_S1_CP5 = np.array( [self.taxi_coordinates[0], self.taxi_coordinates[1]]) self.route_S2_CP5 = np.array([self.taxi_coordinates[1]]) self.route_S1_CP6 = np.array([ self.taxi_coordinates[0], self.taxi_coordinates[1], self.taxi_coordinates[2] ]) self.route_S2_CP6 = np.array( [self.taxi_coordinates[1], self.taxi_coordinates[2]]) self.route_S1_CP7 = np.array([ self.taxi_coordinates[0], self.taxi_coordinates[1], self.taxi_coordinates[2], self.taxi_coordinates[3] ]) self.route_S2_CP7 = np.array([ self.taxi_coordinates[1], self.taxi_coordinates[2], self.taxi_coordinates[3] ]) self.route_S1_CP89 = np.array([ self.taxi_coordinates[0], self.taxi_coordinates[1], self.taxi_coordinates[2], self.taxi_coordinates[5] ]) self.route_S2_CP89 = np.array([ self.taxi_coordinates[1], self.taxi_coordinates[2], self.taxi_coordinates[5] ]) # Determine routes from parking to exit self.route_CP13_E1 = np.array([ self.taxi_coordinates[4], self.taxi_coordinates[7], self.taxi_coordinates[6], self.taxi_coordinates[11] ]) self.route_CP4_E2 = np.array([ self.taxi_coordinates[1], self.taxi_coordinates[2], self.taxi_coordinates[3], self.taxi_coordinates[12] ]) self.route_CP5_E2 = np.array([ self.taxi_coordinates[2], self.taxi_coordinates[3], self.taxi_coordinates[12] ]) self.route_CP67_E2 = np.array( [self.taxi_coordinates[3], self.taxi_coordinates[12]]) self.route_CP89_E2 = np.array([ self.taxi_coordinates[5], self.taxi_coordinates[2], self.taxi_coordinates[3], self.taxi_coordinates[12] ]) # ============================================================================= # Define the running # Stop when all aircraft have exited self.exited_aircraft = 0 self.schedule = RandomActivation(self) # Make all agents self.make_coordinator() self.make_offloader() self.make_aircraft() self.make_equipment() self.make_cargo() # Start running self.running = True self.start_time = 0 self.exit_step = 1000 # ========================================================================= # Create all aircraft, the aircraft are not all initialized at the same time, # but within an arrival window. # ========================================================================= def make_aircraft(self): # ============================================================================= # # Starting position # pos = np.array((aircraft_schedule.Origin_X[i]* self.space.x_max, aircraft_schedule.Origin_Y[i] * self.space.y_max)) # # Position of parking spot # parking_pos = np.array((aircraft_schedule.Parking_X[i] * self.space.x_max, aircraft_schedule.Parking_Y[i] * self.space.y_max)) # ============================================================================= for i in range(self.n_aircraft): # Look for the correct position of the starting point for x in range(len(self.airport_coordinates)): if self.aircraft_schedule.Start_Name[ i] == self.airport_coordinates.Name[x]: Start_X = airport_coordinates.X_pos[x] Start_Y = airport_coordinates.Y_pos[x] ## Get the aircraft data and schedule from the excel file 'aircraft_schedule' # Starting pos pos = np.array( (Start_X * self.space.x_max, Start_Y * self.space.y_max)) # # Position of exit # exit_pos = np.array((self.aircraft_schedule.Exit_X[i] * self.space.x_max, self.aircraft_schedule.Exit_Y[i] * self.space.y_max)) # Time the aircraft 'lands' arrival_time = self.aircraft_schedule.Arrival[i] # Speed of the aircraft speed = self.aircraft_schedule.Speed[i] # Amount of cargo in the aircraft n_cargo = self.aircraft_schedule.Cargo[i] # The position/ID in the schedule schedule_ID = self.aircraft_schedule.Aircraft_ID[i] print('I am aircraft', schedule_ID, 'my starting pos is:', pos) aircraft = Aircraft( i, self, pos, #parking_pos, arrival_time, speed, n_cargo, schedule_ID) self.space.place_agent(aircraft, pos) self.schedule.add(aircraft) # ========================================================================= # Create all offloaders # ========================================================================= def make_offloader(self): for i in range(self.n_offloaders): # Starting position is the waiting position waiting_pos = np.array( (self.offloaders_position[0] * self.space.x_max, self.offloaders_position[1] * self.space.y_max)) pos = waiting_pos speed = self.offloaders_speed print('I am an offloader and my starting pos is:', pos) offloader = OffloadingAgent(i + self.n_aircraft, self, pos, waiting_pos, speed) self.space.place_agent(offloader, pos) self.schedule.add(offloader) # ========================================================================= # Create coordinator # ========================================================================= def make_coordinator(self): # for i in range(self.n_offloaders): # Starting position is the waiting position waiting_pos = np.array( (self.coordinator_position[0] * self.space.x_max, self.coordinator_position[1] * self.space.y_max)) pos = waiting_pos speed = self.offloaders_speed print('I am a coordinator and my starting pos is:', pos) coordinator = CoordinatingAgent( 1 + self.n_aircraft + self.n_offloaders, self, pos, waiting_pos, speed, coordinator_memory=self.coordinator_memory) self.space.place_agent(coordinator, pos) self.schedule.add(coordinator) # ========================================================================= # Create equipment for offloading # ========================================================================= def make_equipment(self): # for i in range(self.n_offloaders): # Starting position is the waiting position parking_pos = np.array((self.equipment_position[0] * self.space.x_max, self.equipment_position[1] * self.space.y_max)) pos = parking_pos speed = self.equipment_speed equipment = Equipment(1 + self.n_aircraft + self.n_offloaders + 1, self, pos, parking_pos, speed) self.space.place_agent(equipment, pos) self.schedule.add(equipment) # ========================================================================= # Create cargo # ========================================================================= def make_cargo(self): cargo_number = 0 #terminal_building_pos = self.terminal_building_pos for i in range(self.n_aircraft): n_cargo = self.aircraft_schedule.Cargo[i] # Look for the correct position of the starting point for x in range(len(self.airport_coordinates)): if self.aircraft_schedule.Start_Name[ i] == self.airport_coordinates.Name[x]: Start_X = airport_coordinates.X_pos[x] Start_Y = airport_coordinates.Y_pos[x] break for j in range(n_cargo): ## Starting pos pos = np.array( (Start_X * self.space.x_max, Start_Y * self.space.y_max)) # The position/ID in the schedule schedule_ID = self.aircraft_schedule.Aircraft_ID[i] # Cargo_number for the ID when creating a cargo agent cargo_number += 1 #previous_cargo_number = cargo_number cargo = Cargo( cargo_number + self.n_aircraft + self.n_offloaders + 1 + 1, # 1xCoordinator and 1x Equipment self, pos, schedule_ID) self.space.place_agent(cargo, pos) self.schedule.add(cargo) self.cargo_number = cargo_number print('cargo number', cargo_number) # ============================================================================= # # # ============================================================================= # # dummy # # ============================================================================= # def make_dummy(self): # pos = np.array((0.03*self.space.x_max,0.03*self.space.y_max)) # speed = 5 # destinations = np.array([[self.space.x_max-0.0001,0.03*self.space.y_max], [self.space.x_max*0.03,self.space.y_max-0.0001]]) # print('destinations dummies', destinations) # for i in range(2): # destination = destinations[i] # dummy_name = i+1 # print('I am dummy:', dummy_name) # print('my destination is:', destination) # print('I am agent number:', dummy_name + self.cargo_number + self.n_aircraft + self.n_offloaders + 1 + 1) # dummy = Dummy( # dummy_name + self.cargo_number + self.n_aircraft + self.n_offloaders + 1 + 1, # 1xCoordinator and 1x Equipment # self, # pos, # speed, # destination, # dummy_name # ) # # self.space.place_agent(dummy, pos) # self.schedule.add(dummy) # ============================================================================= # ========================================================================= # Define what happens in the model in each step. # ========================================================================= def step(self): #all_arrived = True if self.schedule.steps == 0: self.start_time = time.time() if self.schedule.steps == self.exit_step: self.running = False elif self.n_aircraft == self.exited_aircraft: if self.exit_step == 1000: self.exit_step = self.schedule.steps + 50 print("--- % s seconds ---" % round(time.time() - self.start_time, 2)) self.schedule.step() for agent in self.schedule.agents: if type(agent) == Aircraft: if agent.aircraft_state == 'Gone': self.space.remove_agent(agent) self.schedule.remove(agent)
class Covid(Model): ''' Covid model class. Handles agent creation, placement and scheduling. ''' def __init__(self, population=100, width=100, height=100, mobility=6, social_distance=2, asymptomatic_percentage=50.0, imperial=True): ''' Create a new Covid model. Args: population: Number of people (density) with one asymptomatic infected person. imperial: Agent rotates between home, work and community. For home the agent returns to a random point near a fixed home position. Community has the agent randomly placed in the space. Work has 90% like home but with a fixed work position and 10% random like community. This is patterned after the Imperial College model. Turning off imperial iterates with each agent traveling a random direction and distance from the current position. asymptomatic_percentage: Percentage of infected people that are asymptomatic. Asymptomatic people transmit the virus for 42 time steps versus 15 time steps for those that are symptomatic. social_distance: Distance at which neighboring susceptible agents can b ecome infected. mobility: The maximum distance that an agent can travel. ''' self.current_id = 0 self.population = population self.mobility = mobility self.social_distance = social_distance self.asymptomatic_percentage = asymptomatic_percentage self.imperial = imperial if imperial: self.state = "home" else: self.state = "diffusion" self.schedule = RandomActivation(self) self.space = ContinuousSpace(width, height, True) self.make_agents() self.running = True self.datacollector = DataCollector({ "Susceptible": lambda m: self.count("Susceptible"), "Infected": lambda m: self.count("Infected"), "Recovered": lambda m: self.count("Recovered") }) def make_agents(self): ''' Create self.population agents, with random positions and starting headings. ''' for i in range(0, 1): x = self.random.random() * self.space.x_max y = self.random.random() * self.space.y_max pos = np.array((x, y)) asymptomatic = True person = Infected(self.next_id(), self, pos, asymptomatic) self.space.place_agent(person, pos) self.schedule.add(person) for i in range(self.population - 1): x = self.random.random() * self.space.x_max y = self.random.random() * self.space.y_max pos = np.array((x, y)) person = Susceptible(self.next_id(), self, pos) self.space.place_agent(person, pos) self.schedule.add(person) def step(self): self.infect() if self.state == "home": self.state = "work" elif self.state == "work": self.state = "community" elif self.state == "community": self.state = "home" self.schedule.step() # collect data self.datacollector.collect(self) if self.count("Infected") == 0: self.running = False def infect(self): agent_keys = list(self.schedule._agents.keys()) susceptible = [] for agent_key in agent_keys: if self.schedule._agents[agent_key].name == "Susceptible": susceptible.append(agent_key) for agent_key in susceptible: agent = self.schedule._agents[agent_key] neighbors = self.space.get_neighbors(agent.pos, self.social_distance) for neighbor in neighbors: if neighbor.name == "Infected": asymptomatic = False if (100.0 * self.random.random() < self.asymptomatic_percentage): asymptomatic = True person = Infected(self.next_id(), self, agent.pos, asymptomatic) if self.imperial: person.set_imperial(agent.home, agent.work, agent.travel) self.space.remove_agent(agent) self.schedule.remove(agent) self.space.place_agent(person, person.pos) self.schedule.add(person) break def count(self, type): agent_keys = list(self.schedule._agents.keys()) num = 0 for agent_key in agent_keys: if self.schedule._agents[agent_key].name == type: num += 1 return num
class Classroom(Model): def __init__(self, floorplan, human_count): super().__init__() self.n_agents = human_count self.floorplan = [] self.humans = [] self.obstacles = [] self.exits = [] self.spawns = [] self.scheduler = DistanceScheduler(self) # Loads floorplan textfile with open('C:/Users/jozse/github/ABMasters/floorplans/' + floorplan) as f: [ self.floorplan.append(line.strip().split()) for line in f.readlines() ] # Creates continuous Mesa space & discrete grid for pathfinding size = len(self.floorplan[0]), len(self.floorplan) self.space = ContinuousSpace(size[0], size[1], torus=False) self.grid = [] for y in range(6 * size[1]): row = [] for x in range(6 * size[0]): row.append(ca.Node((x, y))) self.grid.append(row) # Places all elements in Mesa space and grid for x in range(size[0]): for y in range(size[1]): value = str(self.floorplan[y][x]) if value == 'W': self.new_agent(ca.Wall, (x, y)) for i in range(6 * x, 6 * (x + 1)): for j in range(6 * y, 6 * (y + 1)): self.grid[j][i].done = True elif value == 'F': self.new_agent(ca.Furniture, (x, y)) for i in range(6 * x, 6 * (x + 1)): for j in range(6 * y, 6 * (y + 1)): self.grid[j][i].done = True elif value == 'S': self.spawns.append((x, y)) elif value == 'E': self.new_agent(ca.Exit, (x, y)) i = 6 * x + 1 j = 6 * y + 1 self.grid[j][i].exit = True # Spawn specified number of Humans in spawn points humans = rnd.sample(self.spawns, self.n_agents) for pos in humans: self.new_agent(ca.Human, pos) print("Classroom initialised.") def new_agent(self, agent_type, pos): ''' Method that creates a new agent, and adds it to the correct list. ''' agent = agent_type(self, pos) self.space.place_agent(agent, pos) if agent_type.__name__ == "Human": self.humans.append(agent) elif agent_type.__name__ == "Exit": self.exits.append(agent) else: self.obstacles.append(agent) def remove_agent(self, agent): ''' Method that removes an agent from the grid and the correct scheduler. ''' self.space.remove_agent(agent) if {type(agent).__name__} == "Human": self.scheduler.remove(agent) self.humans.remove(agent) def step(self): ''' Method that steps every agent. ''' self.scheduler.step() def run_model(self): self.step()
class Classroom(Model): def __init__(self, floorplan, human_count): super().__init__() self.n_agents = human_count self.floorplan = [] self.humans = [] self.obstacles = [] self.exits = [] self.spawns = [] self.scheduler = DistanceScheduler(self) # Creates continuous Mesa space & discrete grid for pathfinding size = len(self.floorplan[0]), len(self.floorplan) self.space = ContinuousSpace(size[0], size[1], torus=False) self.grid = [] for y in range(6 * size[1]): row = [] for x in range(6 * size[0]): row.append(ca.Node((x, y))) self.grid.append(row) # Places all elements in Mesa space and grid for x in range(size[0]): for y in range(size[1]): value = str(self.floorplan[y][x]) if value == 'W': self.new_agent(ca.Wall, (x, y)) for i in range(6 * x, 6 * (x + 1)): for j in range(6 * y, 6 * (y + 1)): self.grid[j][i].done = True elif value == 'F': self.new_agent(ca.Furniture, (x, y)) for i in range(6 * x, 6 * (x + 1)): for j in range(6 * y, 6 * (y + 1)): self.grid[j][i].done = True elif value == 'S': self.spawns.append((x, y)) elif value == 'E': self.new_agent(ca.Exit, (x, y)) i = 6 * x + 1 j = 6 * y + 1 self.grid[j][i].exit = True # Spawn n_agents according to floorplan for pos in rnd.sample(self.spawns, self.n_agents): self.new_agent(ca.Human, pos) def new_agent(self, agent_type, pos): ''' Method that creates a new agent, and adds it to the correct list. ''' agent = agent_type(self, pos) self.space.place_agent(agent, pos) if agent_type.__name__ == "Human": self.humans.append(agent) elif agent_type.__name__ == "Exit": self.exits.append(agent) else: self.obstacles.append(agent) def remove_agent(self, agent): ''' Method that removes an agent from the grid and the correct scheduler. ''' self.space.remove_agent(agent) if {type(agent).__name__} == "Human": self.scheduler.remove(agent) self.humans.remove(agent) def step(self): ''' Method that steps every agent. ''' self.scheduler.step() def run_model(self): self.step()
class Prey_model(Model): def __init__(self, Prey_count, Tiger_count, width, height, CANVAS): self.count = 0 # Number of agents self.schedule = mesa.time.RandomActivation(self) self.space = ContinuousSpace(width + 1, height + 1, torus=False) self.step_num = 0 self.last_uid = 0 self.canvas = CANVAS self.grass_ticks = dict() self.Prey_count = 0 self.Tiger_count = 0 # Create patches for x, y in itertools.product(range(width), range(height)): a = Patch(self.new_uid(), self) # self.schedule.add(a) self.space.place_agent(a, (x, y)) a.canvas = CANVAS a.draw() # Create Animals: for i in range(Prey_count): x = random.randrange(self.space.width) y = random.randrange(self.space.width) self.create_baby(x, y, age=random.randint(1, 5)) for i in range(Tiger_count): x = random.randrange(self.space.width) y = random.randrange(self.space.width) self.create_baby(x, y, age=random.randint(1, 5), type='Tiger') def kill(self, a): if a.type == 'Prey': self.Prey_count -= 1 else: self.Tiger_count -= 1 x_1, y_1 = pos_box(a.pos)[:2] self.canvas.delete(a.icon) self.count -= 1 self.space.remove_agent(a) self.schedule.remove(a) self.canvas.create_text(x_1, y_1, text="x", font=12, justify='center') def new_uid(self): '''Get a new uid and keep track of the last one''' uid = self.last_uid + 1 self.last_uid = uid return uid def create_baby(self, x, y, age=0, type='Prey'): '''Create an animal and give it a ref to the CANVAS''' if type == 'Prey': a = Prey(self.new_uid(), self, age=age) self.Prey_count += 1 else: a = Tiger(self.new_uid(), self, age=age) self.Tiger_count += 1 self.schedule.add(a) self.space.place_agent(a, (x, y)) self.count += 1 a.canvas = self.canvas a.draw() def step(self): self.step_num += 1 # print("Stepping:", self.step_num) # Regrow any grass that's due # Much faster than trying to call each individual grass cell as an agent every tick if self.step_num in self.grass_ticks: for grass in self.grass_ticks[self.step_num]: grass.regrow() del self.grass_ticks[self.step_num] # Move the agents self.schedule.step() if self.count <= 0: poem = ''' No sun - no moon No morn - no noon No dawn - no dusk - no proper time of day No warmth, no cheerfulness, no healthful ease No comfortable feel in any member No shade, no shine, no butterflies, no bees No fruits, no flowers, no leaves, no birds November''' # A poem by Thomas Hood for line in re.split('\n', poem): print(line) time.sleep(.1)
class TestSpaceAgentMapping(unittest.TestCase): ''' Testing a continuous space for agent mapping during removal. ''' def setUp(self): ''' Create a test space and populate with Mock Agents. ''' self.space = ContinuousSpace(70, 50, False, -30, -30) self.agents = [] for i, pos in enumerate(REMOVAL_TEST_AGENTS): a = MockAgent(i, None) self.agents.append(a) self.space.place_agent(a, pos) def test_remove_first(self): ''' Test removing the first entry ''' agent_to_remove = self.agents[0] self.space.remove_agent(agent_to_remove) for i, agent in self.space._index_to_agent.items(): assert agent.pos == tuple(self.space._agent_points[i, :]) assert i == self.space._agent_to_index[agent] assert agent_to_remove not in self.space._agent_to_index assert agent_to_remove.pos is None with self.assertRaises(Exception): self.space.remove_agent(agent_to_remove) def test_remove_last(self): ''' Test removing the last entry ''' agent_to_remove = self.agents[-1] self.space.remove_agent(agent_to_remove) for i, agent in self.space._index_to_agent.items(): assert agent.pos == tuple(self.space._agent_points[i, :]) assert i == self.space._agent_to_index[agent] assert agent_to_remove not in self.space._agent_to_index assert agent_to_remove.pos is None with self.assertRaises(Exception): self.space.remove_agent(agent_to_remove) def test_remove_middle(self): ''' Test removing a middle entry ''' agent_to_remove = self.agents[3] self.space.remove_agent(agent_to_remove) for i, agent in self.space._index_to_agent.items(): assert agent.pos == tuple(self.space._agent_points[i, :]) assert i == self.space._agent_to_index[agent] assert agent_to_remove not in self.space._agent_to_index assert agent_to_remove.pos is None with self.assertRaises(Exception): self.space.remove_agent(agent_to_remove)