class TestSpaceNonToroidal(unittest.TestCase): ''' Testing a toroidal continuous space. ''' def setUp(self): ''' Create a test space and populate with Mock Agents. ''' self.space = ContinuousSpace(70, 20, False, -30, -30, 100, 100) self.agents = [] for i, pos in enumerate(TEST_AGENTS): a = MockAgent(i, None) self.agents.append(a) self.space.place_agent(a, pos) def test_agent_positions(self): ''' Ensure that the agents are all placed properly. ''' for i, pos in enumerate(TEST_AGENTS): a = self.agents[i] assert a.pos == pos def test_distance_calculations(self): ''' Test toroidal distance calculations. ''' pos_2 = (70, 20) pos_3 = (-30, -20) assert self.space.get_distance(pos_2, pos_3) == 107.70329614269008 def test_neighborhood_retrieval(self): ''' Test neighborhood retrieval ''' neighbors_1 = self.space.get_neighbors((-20, -20), 1) assert len(neighbors_1) == 2 neighbors_2 = self.space.get_neighbors((40, -10), 10) assert len(neighbors_2) == 0 neighbors_3 = self.space.get_neighbors((-30, -30), 10) assert len(neighbors_3) == 0 def test_bounds(self): ''' Test positions outside of boundary ''' for i, pos in enumerate(OUTSIDE_POSITIONS): a = MockAgent(len(self.agents) + i, None) with self.assertRaises(Exception): self.space.place_agent(a, pos) a = self.agents[0] for pos in OUTSIDE_POSITIONS: assert self.space.out_of_bounds(pos) with self.assertRaises(Exception): self.space.move_agent(a, pos)
class TestSpaceToroidal(unittest.TestCase): ''' Testing a toroidal continuous space. ''' def setUp(self): ''' Create a test space and populate with Mock Agents. ''' self.space = ContinuousSpace(70, 20, True, -30, -30, 100, 100) self.agents = [] for i, pos in enumerate(TEST_AGENTS): a = MockAgent(i, None) self.agents.append(a) self.space.place_agent(a, pos) def test_agent_positions(self): ''' Ensure that the agents are all placed properly. ''' for i, pos in enumerate(TEST_AGENTS): a = self.agents[i] assert a.pos == pos def test_distance_calculations(self): ''' Test toroidal distance calculations. ''' pos_1 = (-30, -30) pos_2 = (70, 20) assert self.space.get_distance(pos_1, pos_2) == 0 pos_3 = (-30, -20) assert self.space.get_distance(pos_1, pos_3) == 10 def test_neighborhood_retrieval(self): ''' Test neighborhood retrieval ''' neighbors_1 = self.space.get_neighbors((-20, -20), 1) assert len(neighbors_1) == 2 neighbors_2 = self.space.get_neighbors((40, -10), 10) assert len(neighbors_2) == 0 neighbors_3 = self.space.get_neighbors((-30, -30), 10) assert len(neighbors_3) == 1
class TestSpaceToroidal(unittest.TestCase): ''' Testing a toroidal continuous space. ''' def setUp(self): ''' Create a test space and populate with Mock Agents. ''' self.space = ContinuousSpace(70, 20, True, -30, -30) self.agents = [] for i, pos in enumerate(TEST_AGENTS): a = MockAgent(i, None) self.agents.append(a) self.space.place_agent(a, pos) def test_agent_positions(self): ''' Ensure that the agents are all placed properly. ''' for i, pos in enumerate(TEST_AGENTS): a = self.agents[i] assert a.pos == pos def test_agent_matching(self): ''' Ensure that the agents are all placed and indexed properly. ''' 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] def test_distance_calculations(self): ''' Test toroidal distance calculations. ''' pos_1 = (-30, -30) pos_2 = (70, 20) assert self.space.get_distance(pos_1, pos_2) == 0 pos_3 = (-30, -20) assert self.space.get_distance(pos_1, pos_3) == 10 pos_4 = (20, -5) pos_5 = (20, -15) assert self.space.get_distance(pos_4, pos_5) == 10 pos_6 = (-30, -29) pos_7 = (21, -5) assert self.space.get_distance(pos_6, pos_7) == np.sqrt(49**2 + 24**2) def test_heading(self): pos_1 = (-30, -30) pos_2 = (70, 20) self.assertEqual((0, 0), self.space.get_heading(pos_1, pos_2)) pos_1 = (65, -25) pos_2 = (-25, -25) self.assertEqual((10, 0), self.space.get_heading(pos_1, pos_2)) def test_neighborhood_retrieval(self): ''' Test neighborhood retrieval ''' neighbors_1 = self.space.get_neighbors((-20, -20), 1) assert len(neighbors_1) == 2 neighbors_2 = self.space.get_neighbors((40, -10), 10) assert len(neighbors_2) == 0 neighbors_3 = self.space.get_neighbors((-30, -30), 10) assert len(neighbors_3) == 1 def test_bounds(self): ''' Test positions outside of boundary ''' boundary_agents = [] for i, pos in enumerate(OUTSIDE_POSITIONS): a = MockAgent(len(self.agents) + i, None) boundary_agents.append(a) self.space.place_agent(a, pos) for a, pos in zip(boundary_agents, OUTSIDE_POSITIONS): adj_pos = self.space.torus_adj(pos) assert a.pos == adj_pos a = self.agents[0] for pos in OUTSIDE_POSITIONS: assert self.space.out_of_bounds(pos) self.space.move_agent(a, pos)
class TestSpaceNonToroidal(unittest.TestCase): """ Testing a toroidal continuous space. """ def setUp(self): """ Create a test space and populate with Mock Agents. """ self.space = ContinuousSpace(70, 20, False, -30, -30) self.agents = [] for i, pos in enumerate(TEST_AGENTS): a = MockAgent(i, None) self.agents.append(a) self.space.place_agent(a, pos) def test_agent_positions(self): """ Ensure that the agents are all placed properly. """ for i, pos in enumerate(TEST_AGENTS): a = self.agents[i] assert a.pos == pos def test_agent_matching(self): """ Ensure that the agents are all placed and indexed properly. """ 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] def test_distance_calculations(self): """ Test toroidal distance calculations. """ pos_2 = (70, 20) pos_3 = (-30, -20) assert self.space.get_distance(pos_2, pos_3) == 107.70329614269008 def test_heading(self): pos_1 = (-30, -30) pos_2 = (70, 20) self.assertEqual((100, 50), self.space.get_heading(pos_1, pos_2)) pos_1 = (65, -25) pos_2 = (-25, -25) self.assertEqual((-90, 0), self.space.get_heading(pos_1, pos_2)) def test_neighborhood_retrieval(self): """ Test neighborhood retrieval """ neighbors_1 = self.space.get_neighbors((-20, -20), 1) assert len(neighbors_1) == 2 neighbors_2 = self.space.get_neighbors((40, -10), 10) assert len(neighbors_2) == 0 neighbors_3 = self.space.get_neighbors((-30, -30), 10) assert len(neighbors_3) == 0 def test_bounds(self): """ Test positions outside of boundary """ for i, pos in enumerate(OUTSIDE_POSITIONS): a = MockAgent(len(self.agents) + i, None) with self.assertRaises(Exception): self.space.place_agent(a, pos) a = self.agents[0] for pos in OUTSIDE_POSITIONS: assert self.space.out_of_bounds(pos) with self.assertRaises(Exception): self.space.move_agent(a, pos)
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 PredatorPreyModel(Model): def __init__(self, height=100, width=100, init_prey=100, prey_reproduction=0.03, init_predator=10, predator_vision=1, predator_reproduction=0.5, predator_death=0.02, local_offspring=False, max_iters=500, seed=None): super().__init__() self.height = height self.width = width self.init_prey = init_prey self.prey_reproduction = prey_reproduction self.init_predator = init_predator self.predator_vision = predator_vision self.predator_reproduction = predator_reproduction self.predator_death = predator_death self.local_offspring = local_offspring self.iteration = 0 self.max_iters = max_iters self.schedule = RandomActivation(self) self.space = ContinuousSpace(height, width, torus=True) model_reporters = { 'Prey': lambda model: self.count('Prey'), 'Predator': lambda model: self.count('Predator'), } self.datacollector = DataCollector(model_reporters=model_reporters) # Place prey for i in range(self.init_prey): x = self.random.uniform(0, self.width) y = self.random.uniform(0, self.height) # next_id() starts at 1 prey = Prey(self.next_id(), self, (x, y), self.prey_reproduction) self.space.place_agent(prey, (x, y)) self.schedule.add(prey) # Place predators for i in range(self.init_predator): x = self.random.uniform(0, self.width) y = self.random.uniform(0, self.height) predator = Predator(self.next_id(), self, (x, y), self.predator_reproduction, self.predator_death, self.predator_vision) self.space.place_agent(predator, (x, y)) self.schedule.add(predator) self.running = True self.datacollector.collect(self) def step(self): """ Advance the model by one step and collect data. Returns ------- None. """ self.schedule.step() self.iteration += 1 self.datacollector.collect(self) # Stop system if maximum of iterations is reached if self.iteration > self.max_iters: self.running = False return None def count(self, breed): """ Count agent by breed. Parameters ---------- breed : string Breed of agent Can be 'Prey' or 'Predator'. Returns ------- count : int Number of agents of type breed. """ count = 0 for agent in self.schedule.agents: if agent.breed == breed: count += 1 if breed == 'Predator' and count == 0: self.running = False return count def warm_up(self): for agent in self.schedule.agents: if agent.breed == 'Prey': continue neighbors = self.space.get_neighbors(agent.pos, radius=agent.vision) for prey in neighbors: if prey.breed == 'Prey': x = self.random.uniform(0, self.width) y = self.random.uniform(0, self.height) self.space.move_agent(prey, (x, y))
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 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 TestSpaceToroidal(unittest.TestCase): ''' Testing a toroidal continuous space. ''' def setUp(self): ''' Create a test space and populate with Mock Agents. ''' self.space = ContinuousSpace(70, 20, True, -30, -30, 100, 100) self.agents = [] for i, pos in enumerate(TEST_AGENTS): a = MockAgent(i, None) self.agents.append(a) self.space.place_agent(a, pos) def test_agent_positions(self): ''' Ensure that the agents are all placed properly. ''' for i, pos in enumerate(TEST_AGENTS): a = self.agents[i] assert a.pos == pos def test_distance_calculations(self): ''' Test toroidal distance calculations. ''' pos_1 = (-30, -30) pos_2 = (70, 20) assert self.space.get_distance(pos_1, pos_2) == 0 pos_3 = (-30, -20) assert self.space.get_distance(pos_1, pos_3) == 10 def test_heading(self): pos_1 = (-30, -30) pos_2 = (70, 20) self.assertEqual((0, 0), self.space.get_heading(pos_1, pos_2)) pos_1 = (65, -25) pos_2 = (-25, -25) self.assertEqual((10, 0), self.space.get_heading(pos_1, pos_2)) def test_neighborhood_retrieval(self): ''' Test neighborhood retrieval ''' neighbors_1 = self.space.get_neighbors((-20, -20), 1) assert len(neighbors_1) == 2 neighbors_2 = self.space.get_neighbors((40, -10), 10) assert len(neighbors_2) == 0 neighbors_3 = self.space.get_neighbors((-30, -30), 10) assert len(neighbors_3) == 1 def test_bounds(self): ''' Test positions outside of boundary ''' boundary_agents = [] for i, pos in enumerate(OUTSIDE_POSITIONS): a = MockAgent(len(self.agents) + i, None) boundary_agents.append(a) self.space.place_agent(a, pos) for a, pos in zip(boundary_agents, OUTSIDE_POSITIONS): adj_pos = self.space.torus_adj(pos) assert a.pos == adj_pos a = self.agents[0] for pos in OUTSIDE_POSITIONS: assert self.space.out_of_bounds(pos) self.space.move_agent(a, pos)
class TestSpaceNonToroidal(unittest.TestCase): ''' Testing a toroidal continuous space. ''' def setUp(self): ''' Create a test space and populate with Mock Agents. ''' self.space = ContinuousSpace(70, 20, False, -30, -30) self.agents = [] for i, pos in enumerate(TEST_AGENTS): a = MockAgent(i, None) self.agents.append(a) self.space.place_agent(a, pos) def test_agent_positions(self): ''' Ensure that the agents are all placed properly. ''' for i, pos in enumerate(TEST_AGENTS): a = self.agents[i] assert a.pos == pos def test_agent_matching(self): ''' Ensure that the agents are all placed and indexed properly. ''' 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] def test_distance_calculations(self): ''' Test toroidal distance calculations. ''' pos_2 = (70, 20) pos_3 = (-30, -20) assert self.space.get_distance(pos_2, pos_3) == 107.70329614269008 def test_heading(self): pos_1 = (-30, -30) pos_2 = (70, 20) self.assertEqual((100, 50), self.space.get_heading(pos_1, pos_2)) pos_1 = (65, -25) pos_2 = (-25, -25) self.assertEqual((-90, 0), self.space.get_heading(pos_1, pos_2)) def test_neighborhood_retrieval(self): ''' Test neighborhood retrieval ''' neighbors_1 = self.space.get_neighbors((-20, -20), 1) assert len(neighbors_1) == 2 neighbors_2 = self.space.get_neighbors((40, -10), 10) assert len(neighbors_2) == 0 neighbors_3 = self.space.get_neighbors((-30, -30), 10) assert len(neighbors_3) == 0 def test_bounds(self): ''' Test positions outside of boundary ''' for i, pos in enumerate(OUTSIDE_POSITIONS): a = MockAgent(len(self.agents) + i, None) with self.assertRaises(Exception): self.space.place_agent(a, pos) a = self.agents[0] for pos in OUTSIDE_POSITIONS: assert self.space.out_of_bounds(pos) with self.assertRaises(Exception): self.space.move_agent(a, pos)