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 BoidModel(Model): ''' Flocker model class. Handles agent creation, placement and scheduling. ''' def __init__(self, target, predators=False, mouse=True, population=50, width=100, height=100, speed=2, vision=10, separation=1, collision_separation=30, cohere=0.05, separate=1.25, match=0.4): ''' Create a new Flockers model. Args: population: Number of Boids 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 cohere, separate, match: factors for the relative importance of the three drives. ''' self.target = target self.predators = predators self.mouse = mouse self.population = population self.vision = vision self.speed = speed self.separation = separation self.collision_separation = collision_separation self.schedule = RandomActivation(self) self.space = ContinuousSpace(width, height, True) self.factors = dict(cohere=cohere, separate=separate, match=match) self.make_agents() self.running = True def update_target(self, target): self.target = target def make_agents(self): ''' Create self.population agents, with random positions and starting headings. ''' for i in range(50): x = random.random() * self.space.x_max y = random.random() * self.space.y_max center_x = self.space.x_max / 2 center_y = self.space.y_max / 2 pos = np.array((x, y)) center = np.array((center_x, center_y)) velocity = np.random.random(2) * 2 - 1 velocity = np.zeros(2) + self.space.get_distance(pos, center) velocity[0] *= self.target[0] velocity[1] *= self.target[1] boid = Boid(i, self, pos, self.speed, velocity, self.vision, self.separation, self.collision_separation, "boid.png", 10, **self.factors) self.space.place_agent(boid, pos) self.schedule.add(boid) for i in range(4): x = random.random() * self.space.x_max y = random.random() * self.space.y_max pos = np.array((x, y)) obstacle = Obstacle(i + self.population, self, pos, 30) obstacle2 = Obstacle(i + self.population + 5, self, pos, 4) self.space.place_agent(obstacle, pos) self.space.place_agent(obstacle2, pos) self.schedule.add(obstacle) self.schedule.add(obstacle2) if self.predators: x = random.random() * self.space.x_max y = random.random() * self.space.y_max pos = np.array((x, y)) velocity = np.random.random(2) * 2 - 1 predator = Predator(2003, self, pos, self.speed + 0.1, velocity, self.vision + 5, 12, self.collision_separation, "predator.png") self.space.place_agent(predator, pos) self.schedule.add(predator) def step(self): self.schedule.step()
class BoidFlockers(Model): ''' A Mesa implementation of flocking agents inspired by https://doi.org/10.1109/IROS.2014.6943105. ''' def __init__(self, formation, population, width, height, vision, min_dist, flock_vel, accel_time, equi_dist, repulse_max, repulse_spring, align_frict, align_slope, align_min, wall_decay, wall_frict, form_shape, form_track, form_decay, wp_tolerance): ''' Create a new Flockers model. Args: population: Number of agents. width, height: Size of the space. vision: How far around should each agents look for its neighbors. min_dist: Minimum allowed distance between agents before a collision occurs. This is only used for statistics. ''' # set parameters self.population = population self.space = ContinuousSpace(width, height, torus=False) self.vision = vision self.min_dist = min_dist self.params = dict(formation=formation, population=population, flock_vel=flock_vel, accel_time=accel_time, equi_dist=equi_dist, repulse_max=repulse_max, repulse_spring=repulse_spring, align_frict=align_frict, align_slope=align_slope, align_min=align_min, wall_decay=wall_decay, wall_frict=wall_frict, form_shape=form_shape, form_track=form_track, form_decay=form_decay, wp_tolerance=wp_tolerance) # data collection for plots self.datacollector = DataCollector( model_reporters={ "Minimum Distance": minimum_distance, "Maximum Distance": maximum_distance, "Average Distance": average_distance, "Collisions": collisions, "Messags Distributed": messages_distributed, "Messags Centralized": messages_centralized }) # execute agents sequentially in a random order self.schedule = RandomActivation(self) # place agents self.make_agents() # pairwise distances self.agent_distances() # run model self.running = True # collect initial data sample self.datacollector.collect(self) def agent_distances(self): ''' Compute the pairwise distances between all agents. ''' self.density = [ self.space.get_distance(pair[0].pos, pair[1].pos) for pair in it.combinations(self.schedule.agent_buffer(), 2) ] def make_agents(self): ''' Create self.population agents and place it at the center of the environment. ''' s = np.floor(np.sqrt(self.population)) for i in range(self.population): x = self.space.center[ 0] - self.min_dist * s + 2 * self.min_dist * (i % s) y = self.space.center[1] - self.min_dist * np.floor( self.population / s) + 2 * self.min_dist * np.floor(i / s) pos = np.array((x, y)) velocity = np.array([0, 1.0]) boid = Boid(i, self, pos, velocity, self.vision, **self.params) self.space.place_agent(boid, pos) self.schedule.add(boid) def step(self): ''' Execute one step of the simulation. ''' self.schedule.step() self.agent_distances() self.datacollector.collect(self)
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)