class ShoalModel(Model): """ Shoal model class. Handles agent creation, placement and scheduling. """ # Todo: removed vision. Do neighbours need to be included here too? def __init__(self, population=100, width=100, height=100, speed=1, separation=2, cohere=0.025, separate=0.25, match=0.04): """ Create a new Boids model. Args: N: Number of Boids width, height: Size of the space. speed: how fast the boids should move. 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.population = population self.speed = speed self.separation = separation self.schedule = RandomActivation(self) self.space = ContinuousSpace(width, height, True, grid_width=10, grid_height=10) self.factors = dict(cohere=cohere, separate=separate, match=match) self.make_agents() self.running = True def make_agents(self): """ Create N agents, with random positions and starting velocities. """ # Todo: fix issue with "1 missing required positional argument: 'separation' for i in range(self.population): 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 fish = Fish(i, self, pos, self.speed, velocity, self.separation, **self.factors) self.space.place_agent(fish, pos) self.schedule.add(fish) self.datacollector = DataCollector(model_reporters={ "Polarization": polar, "Nearest Neighbour Distance": nnd }) def step(self): self.datacollector.collect(self) self.schedule.step()
class FireSupportModel(Model): def __init__(self, ax, ax2): self.schedule = RandomActivation(self) self.grid = ContinuousSpace(400, 400, True) self.ax = ax self.ax2 = ax2 # Creating all agents enemy_inf1 = EnInfantry(1, self, 10, enemy1_locx, enemy1_locy, self.ax) self.schedule.add(enemy_inf1) self.grid.place_agent(enemy_inf1, (enemy1_locx, enemy1_locy)) enemy_arty1 = EnArty(10, self, 30, enemy2_locx, enemy2_locy, self.ax) self.schedule.add(enemy_arty1) self.grid.place_agent(enemy_arty1, (enemy2_locx, enemy2_locy)) enemy_tank1 = EnArmour(20, self, 20, enemy3_locx, enemy3_locy, self.ax) self.schedule.add(enemy_tank1) self.grid.place_agent(enemy_tank1, (enemy3_locx, enemy3_locy)) friendly_unit1 = FrUnit(30, self, friendly_unit_health, frUnit_init_locx, frUnit_init_locy, self.ax, self.ax2) self.schedule.add(friendly_unit1) self.grid.place_agent(friendly_unit1, (frUnit_init_locx, frUnit_init_locy)) friendly_arty = FrArty(40, self, 10, fs_init_locx, fs_init_locy, self.ax) self.schedule.add(friendly_arty) self.grid.place_agent(friendly_arty, (fs_init_locx, fs_init_locy)) def step(self): self.schedule.step()
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 PopulationModel(Model): """ a model with population in a district """ num_S = 0 num_I = 0 num_R = 0 num_agents = 0 def __init__(self, N, r, p, width, height): self.num_agents = N self.num_S = N self.required_social_dist = r self.infect_overallprob = p """ scheduler controls the order at which agents are activated """ """ RandomActivation activates all the agents once per step """ self.schedule = RandomActivation(self) """ create a continuous space """ self.district = ContinuousSpace(width, height, True) # create agents for i in range(self.num_agents): a = PersonAgent(i, self.required_social_dist, self.infect_overallprob, self) # i is the id number self.schedule.add(a) """ add an agent to the schedule using add method """ # place the agent in the continuous space x = self.random.randrange(self.district.width) y = self.random.randrange(self.district.height) self.district.place_agent(a, (x, y)) print("id " + str(i) + " is at " + str(x) + "," + str(y)) def step(self): """ advance the model by one step """ self.schedule.step()
class ShoalModel(Model): """ Shoal model class. Handles agent creation, placement and scheduling. """ def __init__(self, population=100, width=100, height=100, speed=1, vision=10, separation=2, cohere=0.025, separate=0.25, match=0.04): # Todo: add parameter for blind spot """ Create a new Boids model. Args: N: Number of Boids width, height: Size of the space. speed: how fast the boids should 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.population = population self.vision = vision self.speed = speed self.separation = separation self.schedule = RandomActivation(self) self.space = ContinuousSpace(width, height, torus=True, grid_width=10, grid_height=10) self.factors = dict(cohere=cohere, separate=separate, match=match) self.make_agents() self.running = True def make_agents(self): """ Create N agents, with random positions and starting velocities. """ for i in range(self.population): 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 fish = Fish(i, self, pos, self.speed, velocity, self.vision, self.separation, **self.factors) self.space.place_agent(fish, pos) self.schedule.add(fish) self.datacollector = DataCollector( model_reporters={"Polarization": polar, "Nearest Neighbour Distance": nnd, "Shoal Area": area, "Mean Distance from Centroid": centroid_dist}) def step(self): self.datacollector.collect(self) self.schedule.step()
class SimulationModel(Model): def __init__(self, x_max, y_max, species, iterations): super(SimulationModel, self).__init__() self.starved = 0 self.space = ContinuousSpace(x_max, y_max, grid_width=20, grid_height=20, torus=True) self.schedule = SimultaneousActivation(self) self.iterations = iterations self.species = [] self.create_population(species) def create_population(self, species): for specie, lamarck, params in species: individuals = [] for param in params: individuals.append( self.create_individual(specie, lamarck, param)) self.schedule.add(individuals[-1]) self.species.append(individuals) def create_individual(self, specie, lamarck, param): x = random.random() * self.space.x_max y = random.random() * self.space.y_max ind = specie(self.space, x, y, lamarck, param) self.space.place_agent(ind, ind.pos) return ind def step(self): self.schedule.step() self.cleanup_corpses() self.update_iterations() def update_iterations(self): self.iterations -= 1 if not self.iterations: self.running = False def cleanup_corpses(self): for agent in filter(t_matcher(AutonomicAgent), self.schedule.agents): if agent.energy <= 0: self.schedule.remove(agent) # noinspection PyProtectedMember self.space._remove_agent(agent.pos, agent) self.starved += 1 def results(self): def get_energy(individual): return individual.eaten, individual.energy def get_energies(specie): return map(get_energy, specie) return map(get_energies, self.species)
class BattleFieldModel(Model): """A model of an agent-based battle simulation using Lanchester’s Law. First assume it is analogous to the continuous model whereby all troops are homogenous and jumbled together. At combat start, each troop is put in a random position. A shooting occurs on each side at each time step, if any enemies are left to kill. The soldier shooting shall be chosen randomly from among the remaining troops. Thus each is equally likely to be the random shooter on his/her side. The probability of killing an opposing troop is expressed in the lethality coefficients. """ def __init__(self, N=200, width=20, height=20): self.num_agents = int(N / 2) self.grid = ContinuousSpace(height, width, True) self.redAgentList = [] self.blueAgentList = [] self.turn = 1 #redLethality = input("Enter Red team lethality coefficient") #blueLethality = input("Enter Blue team lethality coefficient") # Create Red and Blue agents for i in range(self.num_agents): a = RedSoldier(i, self) self.redAgentList.append(a) # add red soldier to random location on grid rx = self.random.randrange(self.grid.width) ry = self.random.randrange(self.grid.height) self.grid.place_agent(a, (rx, ry)) b = BlueSoldier(i, self) self.blueAgentList.append(b) # add blue soldier to random location on grid bx = self.random.randrange(self.grid.width) by = self.random.randrange(self.grid.height) self.grid.place_agent(b, (bx, by)) self.running = True def step(self): numRed = len(self.redAgentList) numBlue = len(self.blueAgentList) if ((numRed > 0) and (numBlue > 0)): if (self.turn == 1): print("Red Turn") self.redAgentList[random.randint(0, numRed - 1)].step() self.turn = 0 else: print("Blue Turn") self.blueAgentList[random.randint(0, numBlue - 1)].step() self.turn = 1 else: if (numRed == 0): print("Battle Over! Blue Team Wins.") else: print("Battle Over! Red Team Wins.") self.running = False
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 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 BoidModel(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, cohere=0.025, separate=0.25, match=0.04): ''' 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.population = population self.vision = vision self.speed = speed self.separation = separation self.schedule = RandomActivation(self) self.space = ContinuousSpace(width, height, True, grid_width=10, grid_height=10) self.factors = dict(cohere=cohere, separate=separate, match=match) self.make_agents() self.running = True def make_agents(self): ''' Create self.population agents, with random positions and starting headings. ''' for i in range(self.population): 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 boid = Boid(i, self, pos, self.speed, velocity, self.vision, self.separation, **self.factors) self.space.place_agent(boid, pos) self.schedule.add(boid) def step(self): self.schedule.step()
class BoidModel(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, cohere=0.025, separate=0.25, match=0.04): ''' 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.population = population self.vision = vision self.speed = speed self.separation = separation self.schedule = RandomActivation(self) self.space = ContinuousSpace(width, height, True, grid_width=10, grid_height=10) self.factors = dict(cohere=cohere, separate=separate, match=match) self.make_agents() self.running = True def make_agents(self): ''' Create self.population agents, with random positions and starting headings. ''' for i in range(self.population): 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 boid = Boid(i, self, pos, self.speed, velocity, self.vision, self.separation, **self.factors) self.space.place_agent(boid, pos) self.schedule.add(boid) def step(self): self.schedule.step()
class GangRivalry(Model): """ """ def __init__(self, grid_size=GRID_DIM, gang_info=GANGS, pars=PARS): super().__init__() self.width, self.height = grid_size self.area = ContinuousSpace(self.width, self.height, False) self.gang_info = gang_info self.parameters = pars self.total_gangs = len(self.gang_info) self.rivalry_matrix = np.zeros((self.total_gangs, self.total_gangs)) self.road_density = np.random.rand(self.width, self.height) self.schedule_GangMember = OneRandomActivation(self) self.init_population() self.datacollector = DataCollector({ "Interaction": lambda m: self.schedule_GangMember.get_agent_count() }) self.running = True self.datacollector.collect(self) def init_population(self): """ """ for gang in self.gang_info: size = gang["gang_size"] pos = gang["anchor"] name = gang["name"] for _ in range(size): self.new_agent(pos, name) def new_agent(self, pos, name): """ """ agent = GangMember(self.next_id(), self, pos, name) self.area.place_agent(agent, pos) self.schedule_GangMember.add(agent) def update_rivalry(self, agent1, agent2): """ """ self.rivalry_matrix[agent1.gang, agent2.gang] += 1 def step(self): self.schedule_GangMember.step() self.datacollector.collect(self) def run_model(self, step_count=200): for _ in range(step_count): self.step()
class Parkur(Model): def __init__(self): super().__init__() self.schedule = SimultaneousActivation(self) self.grid = ContinuousSpace(75, 40, False) ## Creation des agents de base for _ in range(1): a = Walker(self.next_id(), self) self.schedule.add(a) self.grid.place_agent(a, (0, 0)) def step(self): self.schedule.step()
class CampusModel(Model): def __init__(self, N, width, height): self.num_agents = N self.grid = ContinuousSpace(width, height, False) self.schedule = SimultaneousActivation(self) for i in range(self.num_agents): a = StudentAgent(i, self) self.schedule.add(a) x = random.randrange(self.grid.width) y = random.randrange(self.grid.height) self.grid.place_agent(a, (x, y)) def step(self): self.schedule.step()
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 BoidModel(Model): ''' Flocker model class. Handles agent creation, placement and scheduling. ''' N = 100 width = 100 height = 100 def __init__(self, N, width, height, speed, vision, separation): ''' Create a new Flockers model. Args: N: 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 separtion: What's the minimum distance each Boid will attempt to keep from any other ''' self.N = N self.vision = vision self.speed = speed self.separation = separation self.schedule = RandomActivation(self) self.space = ContinuousSpace(width, height, True, grid_width=10, grid_height=10) self.make_agents() self.running = True def make_agents(self): ''' Create N agents, with random positions and starting headings. ''' for i in range(self.N): x = random.random() * self.space.x_max y = random.random() * self.space.y_max pos = (x, y) heading = np.random.random(2) * 2 - np.array((1, 1)) heading /= np.linalg.norm(heading) boid = Boid(i, pos, self.speed, heading, self.vision, self.separation) self.space.place_agent(boid, pos) self.schedule.add(boid) def step(self): self.schedule.step()
class FireSupportModel(Model): def __init__(self, ax, ax2): self.schedule = BaseScheduler(self) self.grid = ContinuousSpace(400, 400, True) self.ax = ax self.ax2 = ax2 # Creating all agents # All agents are activated in the order they are added to the scheduler. friendly_arty = FrArty(10, self, 10, fsUnit_loc[0], fsUnit_loc[1], self.ax, enemy1_loc, fsUnit_loc, ammunition_heavy_round, ammunition_light_round) self.schedule.add(friendly_arty) self.grid.place_agent(friendly_arty, (fsUnit_loc[0], fsUnit_loc[1])) friendly_unit1 = FrUnit(11, self, friendly_unit_health, frUnit_init_loc[0], frUnit_init_loc[1], self.ax, self.ax2, fsUnit_loc) self.schedule.add(friendly_unit1) self.grid.place_agent(friendly_unit1, (frUnit_init_loc[0], frUnit_init_loc[1])) enemy_inf1 = EnInfantry(1, self, 20, enemy1_loc[0], enemy1_loc[1], self.ax, fsUnit_loc, enemy1_loc) self.schedule.add(enemy_inf1) self.grid.place_agent(enemy_inf1, (enemy1_loc[0], enemy1_loc[1])) enemy_arty1 = EnArty(2, self, 20, enemy2_loc[0], enemy2_loc[1], self.ax, fsUnit_loc, enemy2_loc) self.schedule.add(enemy_arty1) self.grid.place_agent(enemy_arty1, (enemy2_loc[0], enemy2_loc[1])) enemy_tank1 = EnArmour(3, self, 20, enemy3_loc[0], enemy3_loc[1], self.ax, fsUnit_loc, enemy3_loc) self.schedule.add(enemy_tank1) self.grid.place_agent(enemy_tank1, (enemy3_loc[0], enemy3_loc[1])) # print(self.schedule.agents[1]) def step(self): self.schedule.step()
class PyDemicModel(Model): def __init__(self, n_agents, width=500, height=500): self.n_agents = n_agents self.space = ContinuousSpace(width, height, True) self.schedule = RandomActivation(self) self.make_agents() self.running = True def step(self): self.schedule.step() def make_agents(self): for idx in range(self.n_agents): pos = self.find_new_pos() if idx == 0: agent = PyDemicAgent(idx, self, pos, infected=True) else: agent = PyDemicAgent(idx, self, pos, infected=False) self.space.place_agent(agent, pos) self.schedule.add(agent) def find_new_pos(self): found = False while not found: x_pos = random.random() * self.space.x_max y_pos = random.random() * self.space.y_max found = True for agent in self.schedule.agents: if ((x_pos - agent.pos[0])**2 + (y_pos - agent.pos[1])**2) <= (2 * agent.radius)**2: found = False return (x_pos, y_pos)
class BoidFlockers(Model): """ Flocker model class. Handles agent creation, placement and scheduling. """ def __init__(self, params) -> None: """ 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.""" params_m = params["model"] self.width = params_m["width"] self.height = params_m["height"] self.agent_pos_lst = None self.agent_vision_lst = None self.fig = None self.ax = None self.text = None self.population = params_m["population"] self.vision = params_m["vision"] self.speed = params_m["speed"] self.separation = params_m["separation"] self.schedule = RandomActivation(self) self.space = ContinuousSpace(self.width, self.height, True) self.factors = dict( cohere=params_m["cohere"], separate=params_m["separate"], match=params_m["match"], ) self.make_agents() self.running = True def make_agents(self) -> None: """ Create self.population agents, with random positions and starting headings. """ for i in range(self.population): x = self.random.random() * self.space.x_max y = self.random.random() * self.space.y_max pos = np.array((x, y)) velocity = np.random.random(2) * 2 - 1 boid = Boid( i, self, pos, self.speed, velocity, self.vision, self.separation, **self.factors, ) self.space.place_agent(boid, pos) self.schedule.add(boid) def step(self) -> None: self.schedule.step() def draw_initial(self) -> None: self.fig, self.ax = plt.subplots() ax = self.ax self.text = ax.set_title(f"t={self.schedule.time:03d}") self.agent_pos_lst = {} self.agent_vision_lst = {} # エージェントを手前に、visionを奥側に描画する for agent in self.schedule.agents: x, y = agent.pos scat = ax.scatter(x, y, c="red", s=10, zorder=2) self.agent_pos_lst[agent.unique_id] = scat c = patches.Circle( xy=agent.pos, radius=self.vision, ec="lightgrey", fc="None", linestyle="--", zorder=1, ) ax.add_patch(c) self.agent_vision_lst[agent.unique_id] = c ax.set_xlim(0, self.width) ax.set_ylim(0, self.height) ax.set_aspect("equal") def draw_successive(self) -> None: self.text.set_text(f"t={self.schedule.time:03d}") for agent in self.schedule.agents: self.agent_pos_lst[agent.unique_id].set_offsets(agent.pos) self.agent_vision_lst[agent.unique_id].center = agent.pos
class ShoalModel(Model): """ Shoal model class. Handles agent creation, placement and scheduling. Parameters are interactive, using the user-settable parameters defined above. Parameters: n_fish: Initial number of "Fish" agents. width, height: Size of the space. speed: how fast the boids should 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. """ def __init__(self, n_fish=100, width=50, height=50, speed=10, vision=10, separation=2, cohere=0.25, separate=0.025, match=0.3): assert speed < width and speed < height, "speed can't be greater than model area dimensions" self.n_fish = n_fish self.vision = vision self.speed = speed self.separation = separation self.schedule = RandomActivation(self) self.space = ContinuousSpace(width, height, torus=True) self.factors = dict(cohere=cohere, separate=separate, match=match) self.make_obstructions( ) # Todo: un-comment this line to include obstructions self.make_fish() self.running = True def make_fish(self): """ Create N "Fish" agents. A random position and starting velocity is assigned for each fish. Call data collectors for fish collective behaviour """ for i in range(self.n_fish): # Todo: change these ranges to move agents around obstructions # Move agents below thermocline # x = random.randrange(2, (self.space.x_max - 2)) # y = random.randrange(28, (self.space.x_max - 2)) # Move agents above slope x = random.randrange(2, (self.space.x_max - 10)) y = random.randrange(2, 28) pos = np.array((x, y)) velocity = np.random.random( 2) * 2 - 1 # [-1.0 .. 1.0, -1.0 .. 1.0] fish = Fish(i, self, pos, self.speed, velocity, self.vision, self.separation, **self.factors) self.space.place_agent(fish, pos) self.schedule.add(fish) self.datacollector = DataCollector( # model_reporters={"test": test}) model_reporters={ "positions": positions, "heading": heading }) def make_obstructions(self): """ Create N "Obstruct" agents, with set positions & no movement. In this case, the obstructions form a line to represent an environmental variable such as a thermo- or halocline. """ # Todo: select type of line desired & change starting agent positions max_lim = self.space.x_max - 1 min_lim = self.space.x_min + 1 horizontal = np.linspace(start=min_lim, stop=max_lim, num=20000) # Create a horizontal line with a set number of points - thermocline # border = np.asarray([(n, 25) for n in horizontal]) # x_points = np.ndarray.tolist(border[:, 0]) # y_points = np.ndarray.tolist(border[:, 1]) # points = list(zip(x_points, y_points)) # Create a diagonal line with a set number of points - slope lift = np.linspace(start=max_lim, stop=30, num=20000) points = np.asarray( list(zip(horizontal, lift)) + [(max_lim, n) for n in np.linspace(start=30, stop=49, num=10000)]) for i in points: # create obstruction agent for all points along the borders pos = np.array(i) obstruct = Obstruct(i, self, pos) self.space.place_agent(obstruct, pos) self.schedule.add(obstruct) def step(self): self.datacollector.collect(self) self.schedule.step()
class FormationFlying(Model): # ========================================================================= # Create a new FormationFlying model. # # Args: # n_flights: Number of flights # width, height: Size of the space, in kilometers. # speed: cruise-speed of flights in m/s. # communication_range: 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 the three drives. # ========================================================================= def __init__( self, n_flights=2, n_origin_airports=2, n_destination_airports=2, width=1500, # [km] height=1500, speed=0.220, #[km/second] communication_range=50, #[km] departure_window = 3, origin_airport_x = [0.0, 0.3], # the origin airports are randomly generated within these boundaries origin_airport_y = [0.0, 0.3], destination_airport_x = [0.7, 0.9], # same for destination airports destination_airport_y = [0.7, 0.9], fuel_reduction = 0.75, negotiation_method = 0, PercentageAlliance = 40 ): # ===================================================================== # Initialize parameters, the exact values will be defined later on. # ===================================================================== self.n_flights = n_flights self.n_origin_airports = n_origin_airports self.n_destination_airports = n_destination_airports self.vision = communication_range self.speed = speed # The agents are activated in random order at each step, in a space that # has a certain width and height and that is not toroidal # (which means that edges do not wrap around) self.schedule = SimultaneousActivation(self) self.space = ContinuousSpace(width, height, False) # These are values between [0,1] that limit the boundaries of the # position of the origin- and destination airports. self.origin_airport_x = origin_airport_x self.origin_airport_y = origin_airport_y self.destination_airport_x = destination_airport_x self.destination_airport_y = destination_airport_y self.destination_agent_list = [] self.departure_window = departure_window self.fuel_reduction = fuel_reduction self.negotiation_method = negotiation_method self.PercentageAlliance = PercentageAlliance self.fuel_savings_closed_deals = 0 self.total_planned_fuel = 0 self.total_planned_time = 0 self.new_formation_counter = 0 self.add_to_formation_counter = 0 self.flights_not_in_formation = n_flights self.total_steps_till_formations = 0 self.total_fuel_consumption = 0 self.total_flight_time = 0 self.origin_list = [] self.destination_list = [] self.make_airports() self.make_agents() self.running = True self.datacollector = DataCollector(model_reporter_parameters, agent_reporter_parameters) # ========================================================================= # Create all flights, the flights are not all initialized at the same time, # but within a departure window. # ========================================================================= def make_agents(self): for i in range(self.n_flights): departure_time = self.random.uniform(0, self.departure_window) pos = self.random.choice(self.origin_list) destination_agent = self.random.choice(self.destination_agent_list) destination_pos = destination_agent.pos flight = Flight( i, self, pos, destination_agent, destination_pos, departure_time, self.speed, self.vision, ) self.space.place_agent(flight, pos) self.schedule.add(flight) # ============================================================================= # Create all airports. The option "inactive_airports" gives you the # opportunity to have airports close later on in the simulation. # ============================================================================= def make_airports(self): inactive_airports = 0 for i in range(self.n_origin_airports): x = self.random.uniform(self.origin_airport_x[0], self.origin_airport_x[1]) * self.space.x_max y = self.random.uniform(self.origin_airport_y[0], self.origin_airport_y[1]) * self.space.y_max closure_time = 0 pos = np.array((x, y)) airport = Airport(i + self.n_flights, self, pos, "Origin", closure_time) self.space.place_agent(airport, pos) self.schedule.add(airport) # they are only plotted if they are part of the schedule for i in range(self.n_destination_airports): x = self.random.uniform(self.destination_airport_x[0], self.destination_airport_x[1]) * self.space.x_max y = self.random.uniform(self.destination_airport_y[0], self.destination_airport_y[1]) * self.space.y_max if inactive_airports: closure_time = 50 inactive_airports = 0 else: closure_time = 0 pos = np.array((x, y)) airport = Airport(i + self.n_flights + self.n_origin_airports, self, pos, "Destination", closure_time) self.space.place_agent(airport, pos) self.destination_agent_list.append(airport) self.schedule.add(airport) # agents are only plotted if they are part of the schedule # ========================================================================= # Define what happens in the model in each step. # ========================================================================= def step(self): all_arrived = True total_deal_value = 0 for agent in self.schedule.agents: if type(agent) is Flight: total_deal_value += agent.deal_value if agent.state != "arrived": all_arrived = False if all_arrived: self.running = False # This is a verification that no deal value is created or lost (total deal value # must be 0, and 0.001 is chosen here to avoid any issues with rounded numbers) if abs(total_deal_value) > 0.001: raise Exception("Deal value is {}".format(total_deal_value)) self.schedule.step() self.datacollector.collect(self)
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) 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 World(Model): def __init__(self, num_agents, num_food, width, height, prob_pheromones, prob_create_nest, min_dist_between_nests): self.width = width self.height = height self.center = (width / 2, height / 2) self.num_agents = num_agents self.num_food = num_food self.prob_pheromones = prob_pheromones self.prob_create_nest = prob_create_nest self.min_dist_between_nests = min_dist_between_nests self.space = ContinuousSpace(width, height, True, 0, 0) self.schedule = RandomActivation(self) self.running = True self.agent_count = 0 self.food_distribution = "clustered" self.generate_nest(self.center) self.generate_ants() self.generate_food() def increment_agent_count(self): self.agent_count += 1 def get_agent_count(self): return self.agent_count def generate_ants(self): for i in range(1, self.num_agents): a = Ant(i, self) a.set_nest_location(self.center) self.schedule.add(a) self.space.place_agent(a, self.center) def generate_nest(self, position): n = Nest(self) self.schedule.add(n) self.space.place_agent(n, position) def generate_food(self): i = self.num_agents if (self.food_distribution == "clustered"): num_clusters = np.random.randint(3, 7) for j in range(num_clusters): x = np.random.rand() * self.space.width y = np.random.rand() * self.space.height size_of_cluster = np.random.randint(1, 6) for x1 in range(size_of_cluster): for y1 in range(4): f = Food(i, self) self.schedule.add(f) self.space.place_agent(f, (x + x1, y + y1)) i += 1 for j in range(i, self.num_food): f = Food(j, self) self.schedule.add(f) x = np.random.rand() * self.space.width y = np.random.rand() * self.space.height self.space.place_agent(f, (x, y)) else: for i in range(self.num_agents, self.num_food): f = Food(i, self) x = np.random.rand() * self.space.width y = np.random.rand() * self.space.height self.schedule.add(f) self.space.place_agent(f, (x, y)) def decrease_food_count(self): self.num_food = self.num_food - 1 def step(self): self.schedule.step() return self.num_food
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 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 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 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 PrestigeModel(Model): """A model with some number of agents.""" def __init__(self, N, width, height, neighbor_distance): self.num_agents = N self.neighbor_distance = neighbor_distance self.grid = ContinuousSpace(width, height, True) # True is for torroidal self.schedule = RandomActivation(self) # Create agents for i in range(self.num_agents): agent = PrestigeAgent(i, i, self) self.schedule.add(agent) # Add the agent to a random grid cell #x = random.randrange(self.grid.width) x = i % self.grid.width #y = random.randrange(self.grid.height) y = i // self.grid.height self.grid.place_agent(agent, (x, y)) agents_pos = [a.pos for a in self.schedule.agents] for a in self.schedule.agents: #all the agents including themselves a.all_agents = self.schedule.agents # all the agents, but not themselves -- if the other agents position isn't your your own position a.other_agents = [aa for aa in self.schedule.agents if aa != a] # use the get_distance function to calc distance from you to all the agents (including themselves) a.agents_dist = [self.get_distance(a.pos, p) for p in agents_pos] # all the agents close enough to you to count as a neighbor (but not yourself) a.neighbors = [ aa for aa, d in zip(a.all_agents, a.agents_dist) if aa != a and d < self.neighbor_distance ] #zip together the two lists to iterate through both, then create new list of neighbors who meet neighbor_distance criteria #print("**********") #print(a.unique_id) #print([b.unique_id for b in a.all_agents]) #print(a.agents_dist) self.datacollector = DataCollector( agent_reporters={"Copies": lambda a: a.copies}) def step(self): '''Advance the model by one step.''' self.datacollector.collect(self) self.schedule.step() def get_distance(self, pos_1, pos_2): """ Get the distance between two point, accounting for toroidal space. Args: pos_1, pos_2: Coordinate tuples for both points. """ pos_1 = np.array( pos_1) #convert pos tuple to an array to allow subtraction pos_2 = np.array(pos_2) delta_pos = abs(pos_1 - pos_2) if self.grid.torus: if delta_pos[0] > self.grid.width / 2: delta_pos[0] = self.grid.width - delta_pos[0] if delta_pos[1] > self.grid.height / 2: delta_pos[1] = self.grid.height - delta_pos[1] return np.linalg.norm(delta_pos)
class CrowdDynamics(Model): ''' Flocker model class. Handles agent creation, placement and scheduling. ''' def __init__(self, width, height, density, train=True): ''' Create a new Flockers model. Args: N: 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 separtion: What's the minimum distance each Boid will attempt to keep from any other ''' self.height = height self.width = width self.density = density self.space = ContinuousSpace(width, height, torus=True) self.schedule = RandomActivation(self) self.goal = Goal(0, self, (self.width // 2, self.height // 2)) self.schedule.add(self.goal) self.train = train self.agents_setup() self.robot_setup() self.running = True def agents_setup(self): ''' Create N agents, with random positions and starting headings. ''' N = int(self.density * self.height * self.width) for i in range(1, N + 1): x = self.width * self.random.random() if self.random.random() < 1 / 2: y = unif(0, self.height / 2) direction = False # -> else: y = unif(self.height / 2, self.height) direction = True # <- pos = np.array([x, y]) agent = Pedestrian(i, self, (x, y), direction) self.space.place_agent(agent, pos) self.schedule.add(agent) def robot_setup(self): j = int(self.density * self.height * self.width) + 1 state = self.reset() self.robot = Robot(j, self, state[0:2], state[2], CrowdEnv(self, state), train=self.train) self.space.place_agent(self.robot, state[0:2]) self.schedule.add(self.robot) def reset(self): x = self.width / 2 + unif(-2.5, 2.5) y = self.height / 2 + unif(-2.5, 2.5) phi = unif(0, 2 * pi) return np.array([x, y, phi]) def step(self): self.schedule.step()
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 ShoalModel(Model): """ Shoal model class. Handles agent creation, placement and scheduling. Parameters are interactive, using the user-settable parameters defined above. Parameters: initial_fish: Initial number of "Fish" agents. initial_obstruct: Initial number of "Obstruct" agents. width, height: Size of the space. speed: how fast the boids should 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. """ def __init__( self, initial_fish=50, initial_obstruct=192, # This is always len(borders) width=50, height=50, speed=2, vision=10, separation=2, cohere=0.025, separate=0.25, match=0.04): self.initial_fish = initial_fish self.initial_obstruct = initial_obstruct self.vision = vision self.speed = speed self.separation = separation self.schedule = RandomActivation(self) self.space = ContinuousSpace(width, height, torus=True) self.factors = dict(cohere=cohere, separate=separate, match=match) self.make_fish() self.make_obstructions() self.running = True def make_fish(self): """ Create N "Fish" agents. A random position and starting velocity is assigned for each fish. Call data collectors for fish collective behaviour """ for i in range(self.initial_fish): 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 fish = Fish(i, self, pos, self.speed, velocity, self.vision, self.separation, **self.factors) self.space.place_agent(fish, pos) self.schedule.add(fish) self.datacollector = DataCollector( model_reporters={"Polarization": polar}) def make_obstructions(self): """ Create N "Obstruct" agents, with set positions & no movement. Borders are defined as coordinate points between the maximum and minimum extent of the width/height of the obstruction. These ranges are drawn from the model space limits, with a slight buffer. The obstruction agents are then generated for every point along the defined borders. """ # if the space is square (i.e. y_max and x_max are the same): max_lim = self.space.x_max - 1 min_lim = self.space.x_min + 1 line = range(min_lim, max_lim) borders = np.asarray([(min_lim, n) for n in line] + [(n, max_lim) for n in line] + [(max_lim, n) for n in line] + [(n, min_lim) for n in line]) x_points = np.ndarray.tolist(borders[:, 0]) y_points = np.ndarray.tolist(borders[:, 1]) points = list(zip(x_points, y_points)) for i in points: # create obstruction agent for all points along the borders pos = np.array(i) obstruct = Obstruct(i, self, pos) self.space.place_agent(obstruct, pos) self.schedule.add(obstruct) def step(self): self.datacollector.collect(self) self.schedule.step()
class ProcessModel(Model): def __init__(self, initial_densities, width, height, density_radius=(1, 1, 1), frequency_radius=(1, 1, 1), dispersal_radius=(1, 1, 1), max_cells_per_unit=10, deterministic_death=True, age_limit=20, death_ratio=0.2, death_period_limit=0, birth_rates=(0.2, 0.2, 0.2), k=25, l=20, a=1): super().__init__() self.num_selfish, self.num_cooperative, self.num_tkiller = initial_densities self.num_tumor_cells = self.num_selfish + self.num_cooperative self.num_total = self.num_tumor_cells + self.num_tkiller self.space = ContinuousSpace(width, height, True) self.schedule = RandomActivation(self) self.density_radius = density_radius self.frequency_radius = frequency_radius self.dispersal_radius = dispersal_radius self.max_cells_per_unit = max_cells_per_unit self.deterministic_death = deterministic_death self.age_limit = age_limit self.death_ratio = death_ratio self.death_period_limit = death_period_limit self.birth_rates = birth_rates self.R = min(width, height)/2.0 self.k, self.l, self.a = k, l, a self.cells2add = [] self.cells2delete = [] self.all_cell_pos = [[], []] self.pos_selfish_cells = [[], []] self.pos_cooperative_cells = [[], []] self.pos_tkiller_cells = [[], []] self.pos_dead_cells = [[], []] added_selfish, added_cooperative, added_tkiller = 0, 0, 0 random.seed(100) def n_cells(): return added_selfish + added_cooperative + added_tkiller mortality_rates = [random.uniform(0, 0.2), random.uniform(0, 0.2), random.uniform(0, 0.2)] while n_cells() < self.num_total: rnd_i = random.randrange(3) if rnd_i == 0 and added_selfish < self.num_selfish: a = CellAgent(n_cells(), self, rnd_i) a.set_gamma(0.1) a.set_epsilon(0.7) a.set_d(mortality_rates[0]) added_selfish += 1 elif rnd_i == 1 and added_cooperative < self.num_cooperative: a = CellAgent(n_cells(), self, rnd_i) a.set_gamma(0.1) a.set_epsilon(0.7) a.set_d(mortality_rates[1]) added_cooperative += 1 elif rnd_i == 2 and added_tkiller < self.num_tkiller: a = CellAgent(n_cells(), self, rnd_i) a.set_gamma(0.1) a.set_delta(0.001) a.set_d(mortality_rates[2]) added_tkiller += 1 else: continue self.schedule.add(a) centered = 0.2 center_width_min = self.space.center[0] - (0.5 * self.space.width) center_width_max = self.space.center[0] + (0.5 * self.space.width) center_height_min = self.space.center[1] - (0.5 * self.space.height) center_height_max = self.space.center[1] + (0.5 * self.space.height) # Add the agent to a random pos x = random.uniform(center_width_min, center_width_max) y = random.uniform(center_height_min, center_height_max) self.space.place_agent(a, (x, y)) self.counter = 0 self.density = [] self.average_birthrate = [[0, 0], [0, 0]] self.average_deathrate = [[0, 0], [0, 0]] @property def g(self): density = self.get_density() if density[0] + density[1] == 0: return 0 return density[1]/(density[0] + density[1]) def get_density(self, agents=None): density = [0, 0, 0] if agents is None: agents = self.schedule.agents for cell in agents: density[cell.type] += 1 return density def new_cell2add(self, cell): if not self.cells2add.__contains__(cell): self.cells2add.append(cell) def new_cell2delete(self, cell): if not self.cells2delete.__contains__(cell): self.cells2delete.append(cell) def add_cell_pos(self, pos, cell_type): if cell_type == 0: self.pos_selfish_cells[0].append(pos[0]) self.pos_selfish_cells[1].append(pos[1]) elif cell_type == 1: self.pos_cooperative_cells[0].append(pos[0]) self.pos_cooperative_cells[1].append(pos[1]) elif cell_type == 2: self.pos_tkiller_cells[0].append(pos[0]) self.pos_tkiller_cells[1].append(pos[1]) else: return def clear_all_cell_pos(self): self.pos_selfish_cells = [[], []] self.pos_cooperative_cells = [[], []] self.pos_tkiller_cells = [[], []] def step(self): self.density = self.get_density() self.average_birthrate = [[0, 0], [0, 0]] self.average_deathrate = [[0, 0], [0, 0]] self.schedule.step() self.counter = 0 print("Average Birthrate: ", self.average_birthrate[0][0] / self.average_birthrate[0][1]) print("Average Deathrate: ", self.average_deathrate[0][0] / self.average_deathrate[0][1]) def add_new_cells(self): added_types = [0, 0, 0] for c, p in self.cells2add: added_types[c.type] += 1 self.schedule.add(c) self.space.place_agent(c, p) self.add_cell_pos(p, c.type) self.cells2add.remove((c, p)) return added_types def delete_dead_cells(self): dead_types = [0, 0, 0] for c in self.cells2delete: dead_types[c.type] += 1 removed_x, removed_y = False, False if c.type == 0: if self.pos_selfish_cells[0].__contains__(c.pos[0]): self.pos_selfish_cells[0].remove(c.pos[0]) if self.pos_selfish_cells[1].__contains__(c.pos[1]): self.pos_selfish_cells[1].remove(c.pos[1]) removed_y = True elif c.type == 1: if self.pos_cooperative_cells[0].__contains__(c.pos[0]): self.pos_cooperative_cells[0].remove(c.pos[0]) removed_x = True if self.pos_cooperative_cells[1].__contains__(c.pos[1]): self.pos_cooperative_cells[1].remove(c.pos[1]) removed_y = True elif c.type == 2: if self.pos_tkiller_cells[0].__contains__(c.pos[0]): self.pos_tkiller_cells[0].remove(c.pos[0]) removed_x = True if self.pos_tkiller_cells[1].__contains__(c.pos[1]): self.pos_tkiller_cells[1].remove(c.pos[1]) removed_y = True self.schedule.remove(c) self.cells2delete.remove(c) return dead_types