class TestMultiGrid(unittest.TestCase): ''' Testing a toroidal MultiGrid ''' torus = True def setUp(self): ''' Create a test non-toroidal grid and populate it with Mock Agents ''' width = 3 height = 5 self.grid = MultiGrid(width, height, self.torus) self.agents = [] counter = 0 for x in range(width): for y in range(height): for i in range(TEST_MULTIGRID[x][y]): counter += 1 # Create and place the mock agent a = MockAgent(counter, None) self.agents.append(a) self.grid.place_agent(a, (x, y)) def test_agent_positions(self): ''' Ensure that the agents are all placed properly on the MultiGrid. ''' for agent in self.agents: x, y = agent.pos assert agent in self.grid[x][y] def test_neighbors(self): ''' Test the toroidal MultiGrid neighborhood methods. ''' neighborhood = self.grid.get_neighborhood((1, 1), moore=True) assert len(neighborhood) == 8 neighborhood = self.grid.get_neighborhood((1, 4), moore=True) assert len(neighborhood) == 8 neighborhood = self.grid.get_neighborhood((0, 0), moore=False) assert len(neighborhood) == 4 neighbors = self.grid.get_neighbors((1, 4), moore=False) assert len(neighbors) == 0 neighbors = self.grid.get_neighbors((1, 4), moore=True) assert len(neighbors) == 5 neighbors = self.grid.get_neighbors((1, 1), moore=False, include_center=True) assert len(neighbors) == 7 neighbors = self.grid.get_neighbors((1, 3), moore=False, radius=2) assert len(neighbors) == 11
class bacModel(Model): '''world model for Eden Growth Model Simulation''' def __init__(self, beginRad, splitChance, x=-1, y=-1, mut_rate=MUTATION_RATE): self.running = True self.num_agents = 0 self.schedule = RandomActivation(self) self.grid = MultiGrid(WIDTH, HEIGHT, IS_TOROIDAL) #True for toroidal #self.datacollector = DataCollector( # model_reporters = {"Identifier": function_name}, #note no parentheses, just function name # agent_reporter = {"Identifier2": function_name2}) if x == -1: x = self.grid.width // 2 if y == -1: y = self.grid.height // 2 #create subsequent agents positions = self.grid.get_neighborhood((x,y), moore=False, radius=beginRad, include_center=True) for coord in positions: roll = random.random() a = bacAgent(self.num_agents, self, False, splitChance) self.num_agents += 1 self.schedule.add(a) self.grid.place_agent(a, coord) def step(self): #self.datacollector.collect(self) self.schedule.step()
class bacServerModel(Model): ################ ###Deprecated### ################ def __init__(self, width, height, beginRad): self.running = True self.num_agents = width * height self.schedule = RandomActivation(self) self.grid = MultiGrid(width, height, IS_TOROIDAL) #True for toroidal #self.datacollector = DataCollector( # model_reporters = {"Identifier": function_name}, #note no parentheses, just function name # agent_reporter = {"Identifier2": function_name2}) for x in range(self.grid.width): for y in range(self.grid.height): a = bacServerAgent(self.num_agents, self) self.num_agents += 1 self.schedule.add(a) self.grid.place_agent(a, (x,y)) x = self.grid.width // 2 y = self.grid.height // 2 #create subsequent agents positions = self.grid.get_neighborhood((x,y), moore=False, radius=beginRad, include_center=True) for coord in positions: ag = self.grid.get_cell_list_contents([coord])[0] ag.activate() def step(self): #self.datacollector.collect(self) self.schedule.step()
def move(self): ''' The random move function for the fish schools. ''' neighbourhood = MultiGrid.get_neighborhood(self.model.grid, self.pos, True, False, 1) new_pos = random.choice(neighbourhood) MultiGrid.move_agent(self.model.grid, self, new_pos)
def fisherman_move(self): ''' The random move function for the fisherman. ''' neighbourhood = MultiGrid.get_neighborhood(self.model.grid, self.pos, True, False, 1) new_pos = random.choice(neighbourhood) while (new_pos[0] < self.model.no_fish_size) and (new_pos[1] < self.model.no_fish_size): new_pos = random.choice(neighbourhood) MultiGrid.move_agent(self.model.grid, self, new_pos)
class HoominWorld(Model): LEFT = 0 RIGHT = 1 STRAIGHT = 2 FRIENDNODELOGNAME = "friendnodes" TOTALMESSAGELOGNAME = "totalmessages" STEPSTOCOMPLETIONLOGNAME = "stepstocompletion" verbose = False description = "A model of foot traffic and radio communication in an urban environment" def __init__(self, height=50, width=50, initial_hoomins=10, logtag="default"): super().__init__() print("initializing ", settings.width, settings.height) #map height and width self.height = settings.height self.width = settings.width #logging framework self.logger = Logging("logs", logtag) self.logtag = logtag self.G = nx.Graph() #graph visualization if not settings.runheadless: plt.ion() plt.show() #ignore this. it does nothing self.hoomin_level = 0 #road generation tuning self.straightweight = settings.straightweight self.leftweight = settings.leftweight self.rightweight = settings.rightweight self.initial_roads = settings.initial_roads self.initial_road_seeds = settings.initial_road_seeds self.gridspacing = settings.gridspacing self.roadcurrentcoord = np.array((0, 0)) self.roaddir = np.array((1, 0)) self.roadset = set() #home tuning options self.homes_per_hoomins = 1 self.initial_homes = self.homes_per_hoomins * initial_hoomins self.homeset = set() #scatterbrain metrics self.total_scattermessages = 0 self.global_scattermessages = 0 self.hoominzero_nodecount = 0 #hoomin tuning values self.initial_hoomins = settings.initial_hoomins self.schedule = RandomHoominActivation(self) self.grid = MultiGrid(self.height, self.width, torus=True) self.datacollector = DataCollector({ "Messages Exchanged": lambda m: m.total_scattermessages, "FriendGraph Node Count": lambda m: m.hoominzero_nodecount }) #initialize roads for i in range(self.initial_road_seeds): x = self.random.randrange(self.width) y = self.random.randrange(self.height) self.singleroad((x, y)) homelist = [] #initialize homes for i in range(self.initial_homes): road = self.random.sample(self.roadset, 1) if len(road) > 0 and road[0] is not None: neighbors = self.grid.get_neighborhood(road[0].pos, False, True) for neighbor in neighbors: n = [] if len(self.grid.get_cell_list_contents(neighbor)) is 0: n.append(neighbor) if len(n) > 0: homeblock = self.random.sample(n, 1) home = Home(self.next_id(), homeblock[0], self) homelist.append(home) self.grid.place_agent(home, homeblock[0]) else: print( "systemic oppression under capitalism forclosed on one hoomin's home." ) self.homeset = self.homeset.union(set(homelist)) #initialize hoomins for i in range(self.initial_hoomins): x = self.random.randrange(self.width) y = self.random.randrange(self.height) hoomin = SocialHoomin(self.next_id(), (x, y), self) if i == 1: for x in range(settings.initial_scattermessages): hoomin.store_scattermessage("hoomin!") hoomin.pos = (0, 0) x = 0 y = 0 self.hoomin_zero_id = hoomin.unique_id if i == self.initial_hoomins - 1: self.final_hoomin_id = hoomin.unique_id hoomin.pos = (self.width - 1, self.height - 1) x = self.width - 1 y = self.height - 1 possiblehomes = self.homeset.difference(Home.claimedhomes) if len(possiblehomes) > 0: myhome = self.random.sample(possiblehomes, 1) if len(myhome) > 0: myhome[0].claim(hoomin) self.grid.place_agent(hoomin, (x, y)) self.schedule.add(hoomin) self.G.add_node(hoomin, agent=[hoomin]) #initialize hoomin friends friendlist = set(self.schedule._agents) for i in self.schedule._agents: fren = self.random.sample(friendlist.difference(set([i])), settings.friendsperhoomin) for x in fren: self.schedule._agents[i].addfriend(x) self.G.add_edge(self.schedule._agents[i], self.schedule._agents[x]) self.roadplace_grid() self.running = True self.datacollector.collect(self) def roadplace_grid(self): for h in range(self.height): if h % self.gridspacing is 0: for w in range(self.width): road = Road(self.next_id(), (w, h), self) self.grid.place_agent(road, (w, h)) for w in range(self.width): if w % self.gridspacing is 0: for h in range(self.height): road = Road(self.next_id(), (w, h), self) self.grid.place_agent(road, (w, h)) def roadplace_random(self, direction=0): if direction is HoominWorld.STRAIGHT: True elif direction is HoominWorld.LEFT: self.roaddir = np.array((-1 * self.roaddir[1], self.roaddir[0])) elif direction is HoominWorld.RIGHT: self.roaddir = np.array((self.roaddir[1], -1 * self.roaddir[0])) else: self.roaddir = np.array((0, 0)) print("bad bad bad") # print("placing road, direction ", direction, " coord: ", self.roadcurrentcoord) newcoord = self.roadcurrentcoord + self.roaddir if newcoord[0] >= self.width or newcoord[0] < 0: return None if newcoord[1] >= self.height or newcoord[1] < 0: return None self.roadcurrentcoord += self.roaddir road = Road(self.next_id(), tuple(self.roadcurrentcoord), self) self.grid.place_agent(road, tuple(self.roadcurrentcoord)) return road def singleroad(self, initialcoord=(0, 0)): #initialize roads #print("placing road seed: ", initialcoord) roaddir = self.random.randrange(4) roadseedx = self.random.randrange(self.width) roadseedy = self.random.randrange(self.height) road = Road(self.next_id(), (roadseedx, roadseedy), self) self.roadcurrentcoord = (roadseedx, roadseedy) self.grid.place_agent(road, (roadseedx, roadseedy)) #note: roads are not scheduled because they do nothing road = None counter = 0 roadlist = [] for i in range(self.initial_roads): while road is None: val = self.random.random() #print("val: " , val) if val <= self.straightweight: road = self.roadplace_random(HoominWorld.STRAIGHT) elif val > self.straightweight and val <= self.leftweight + self.straightweight: road = self.roadplace_random(HoominWorld.LEFT) elif val > self.leftweight + self.straightweight: road = self.roadplace_random(HoominWorld.RIGHT) if road is None: #print("err: road is none") True roadlist.append(road) road = None counter += 1 #print("initialized ", counter, " road tiles") self.roadset = self.roadset.union(set(roadlist)) del roadlist def get_hoomin_level(self): return self.hoomin_level def logstep(self): if not self.logger.isopen(HoominWorld.FRIENDNODELOGNAME): self.logger.open(HoominWorld.FRIENDNODELOGNAME, overwrite=True) if not self.logger.isopen(HoominWorld.TOTALMESSAGELOGNAME): self.logger.open(HoominWorld.TOTALMESSAGELOGNAME, overwrite=True) self.logger.write( HoominWorld.TOTALMESSAGELOGNAME, str(self.hoomin_level) + " " + str(self.global_scattermessages)) st = "STEP: " + str(self.hoomin_level) + " hoominzero: " + str( self.schedule._agents[self.hoomin_zero_id].friendgraph. number_of_nodes()) + " finalhoomin: " + str(self.schedule._agents[ self.final_hoomin_id].friendgraph.number_of_nodes()) self.logger.write(HoominWorld.FRIENDNODELOGNAME, st) def step(self): self.schedule.step() self.datacollector.collect(self) self.hoomin_level += 1 if self.hoomin_level % settings.graphrefreshfreq == 0 and settings.displayfriendgraph and not settings.runheadless: plt.cla() plt.clf() nx.draw(self.schedule._agents[self.hoomin_zero_id].friendgraph) plt.draw() plt.pause(0.001) if self.verbose: print([self.schedule.time, "nothing yet"]) if len(self.schedule._agents[self.final_hoomin_id].scatterbuffer ) >= settings.initial_scattermessages: print("model completed") self.running = False if not self.logger.isopen(HoominWorld.STEPSTOCOMPLETIONLOGNAME): self.logger.open(HoominWorld.STEPSTOCOMPLETIONLOGNAME, overwrite=True) self.logger.write(HoominWorld.STEPSTOCOMPLETIONLOGNAME, self.hoomin_level) self.logger.close(HoominWorld.STEPSTOCOMPLETIONLOGNAME) self.logstep() def run_model(self, step_count=200): if self.verbose: print("Initializing hoomins", self.schedule.get_hoomin_count(Hoomin)) while self.running: self.step()
class EmasModel(Model): description = ( "A model for simulating using EMAS model" ) def __init__( self, height=HEIGHT, width=WIDTH, columns=2, rows=2, death_level=0, migration_level=10, init_energy=100, moore=True, reproduction_level=7, parent_part_to_child=30, base_child_energy=5, energy_redistribution_radius=4, islands=[] ): super().__init__() self.height: int = height self.width: int = width self.columns: int = columns self.rows: int = rows self.death_level: float = death_level self.migration_level: float = migration_level self.moore: bool = moore self.reproduction_level: float = reproduction_level self.parent_part_to_child: float = parent_part_to_child self.base_child_energy: float = base_child_energy self.init_energy: float = init_energy self.energy_redistribution_radius: int = energy_redistribution_radius self.islands: List[Tuple[Tuple[int, int], Tuple[int, int]]] = islands self.grid = MultiGrid(self.height, self.width, torus=True) borders_x_indexes = sorted([int(self.width * part / columns) for part in range(1, self.columns)]) columns_points: Set[Tuple[int, int]] = {(x, y) for x in borders_x_indexes for y in range(self.height)} borders_y_indexes = sorted([int(self.height * part / rows) for part in range(1, self.rows)]) rows_points: Set[Tuple[int, int]] = {(x, y) for x in range(self.width) for y in borders_y_indexes} for border_cords in columns_points | rows_points: border = IslandBorderAgent(self.next_id(), border_cords, self) self.grid.place_agent(border, border_cords) islands_x_corners = [-1] + borders_x_indexes + [self.width] islands_y_corners = [-1] + borders_y_indexes + [self.height] # left lower and right upper corner self.islands = [ ((x, y), (islands_x_corners[x_u + 1], islands_y_corners[y_u + 1])) for x_u, x in enumerate(islands_x_corners) if x != self.width for y_u, y in enumerate(islands_y_corners) if y != self.height ] def get_neighborhood(self, pos: Coordinate, include_center=False, radius=1, moore=True): next_moves = self.grid.get_neighborhood(pos, moore, include_center, radius) island = self.get_island(pos) return self._filter_coors_in_island(island, next_moves) def redistribute_energy(self, pos: Coordinate, energy: float, include_center=False, radius=10): neighbours = self.grid.get_neighbors(pos, self.moore, include_center, radius) island = self.get_island(pos) close_neighbours = list(filter(lambda n: self._is_in_island(island, n.pos), neighbours)) emas_neighbours = list(filter(lambda a: isinstance(a, EmasAgent), close_neighbours)) if emas_neighbours: energy_delta = energy / len(emas_neighbours) for neighbour in emas_neighbours: neighbour.energy += energy_delta def get_island(self, pos: Coordinate): return list(filter(lambda coors: coors[0][0] < pos[0] < coors[1][0] and coors[0][1] < pos[1] < coors[1][1], self.islands)).pop() def _filter_coors_in_island(self, island: Tuple[Tuple[int, int], Tuple[int, int]], positions: List[Tuple[int, int]]): return list(filter(lambda move: island[0][0] < move[0] < island[1][0] and island[0][1] < move[1] < island[1][1], positions)) def _is_in_island(self, island, pos): return island[0][0] < pos[0] < island[1][0] and island[0][1] < pos[1] < island[1][1] def _filter_for_emas_agents(self, agents): return filter(lambda a: isinstance(a, EmasAgent), agents) def get_closest_neighbour_on_island(self, pos: Coordinate): island = self.get_island(pos) taxi_radius = abs(island[0][0] - island[1][0]) + abs(island[0][1] - island[1][1]) # moore=False -> find neighbourhood using taxi metric neighbours = self.grid.get_neighbors(pos, False, include_center=False, radius=taxi_radius) island_neighbours = [ agent for agent in neighbours if self._is_in_island(island, agent.pos) and isinstance(agent, EmasAgent) ] closest_neighbour = None closest_distance = taxi_radius for agent in island_neighbours: if self.taxi_distance(pos, agent.pos) < closest_distance: closest_distance = self.taxi_distance(pos, agent.pos) closest_neighbour = agent return closest_neighbour def taxi_distance(self, pos_a: Coordinate, pos_b: Coordinate): return abs(pos_a[0] - pos_b[0]) + abs(pos_a[1] - pos_b[1])
class ExplorationArea(Model): def __init__( self, nrobots, wifi_range, radar_radius=6, alpha=8.175, gamma=0.65, inj_pri=0, ninjured=None, ncells=None, obstacles_dist=None, load_file=None, dump_datas=True, # enable data collection alpha_variation=False, # record datas for alpha variation studies alpha_csv=alpha_csv, # aggregate datas alpha_step_csv=alpha_step_csv, # single step datas gamma_variation=False, # record datas for gamma variation studies gamma_csv=gamma_csv, optimization_task=False, # enable a small part of data collection for optimization task time_csv=number_of_steps_csv, robot_status_csv=robot_status_csv): # checking params consistency if not load_file and (not ncells or not obstacles_dist or not ninjured): print("Invalid params") sys.exit(-1) # used in server start self.running = True self.nrobots = nrobots self.radar_radius = radar_radius self.ncells = ncells self.obstacles_dist = obstacles_dist self.wifi_range = wifi_range self.alpha = alpha self.gamma = gamma self.ninjured = ninjured self.inj_pri = inj_pri self.dump_datas = dump_datas self.optimization_task = optimization_task self.frontier = set() self.broken_beans = 0 # Data collection tools if self.dump_datas: # it represents the sum of the difficulties of every cell self.total_difficulty = 0 self.dc_robot_status = DataCollector({ "idling": lambda m: self.get_number_robots_status(m, "idling"), "travelling": lambda m: self.get_number_robots_status(m, "travelling"), "exploring": lambda m: self.get_number_robots_status(m, "exploring"), "deploying_bean": lambda m: self.get_number_robots_status(m, "deploying_bean"), "step": lambda m: self.get_step(m) }) self.time_csv = time_csv self.robot_status_csv = robot_status_csv if self.optimization_task: self.total_idling_time = 0 self.alpha_variation = alpha_variation self.gamma_variation = gamma_variation if self.alpha_variation: self.costs_each_path = list() self.alpha_csv = alpha_csv self.alpha_step = dict() self.alpha_step_csv = alpha_step_csv if self.gamma_variation: self.gamma_df = pd.DataFrame(columns=["step", "mean", "std"]) self.gamma_csv = gamma_csv self.schedule = RandomActivation(self) # unique counter for agents self.agent_counter = 1 self.nobstacle = 0 # graph of seen cells self.seen_graph = nx.DiGraph() rnd.seed() # place a cell agent for store data and visualization on each cell of the grid # if map is not taken from file, create it if load_file == None: self.grid = MultiGrid(ncells + 2, ncells + 2, torus=False) for i in self.grid.coord_iter(): if i[1] != 0 and i[2] != 0 and i[1] != self.ncells + 1 and i[ 2] != self.ncells + 1: rand = np.random.random_sample() obstacle = True if rand < self.obstacles_dist else False # if obstacle if obstacle: self.nobstacle += 1 difficulty = math.inf explored = -1 priority = 0 utility = -math.inf # if free else: difficulty = np.random.randint(low=1, high=13) if self.dump_datas: self.total_difficulty += difficulty explored = 0 priority = 0 utility = 1.0 # if contour cell else: difficulty = np.random.randint(low=1, high=13) explored = -2 priority = -math.inf utility = -math.inf # place the agent in the grid a = Cell(self.agent_counter, self, i[1:], difficulty, explored, priority, utility) self.grid.place_agent(a, i[1:]) self.agent_counter += 1 # create injured agents valid_coord = [] for i in self.grid.coord_iter(): cell = [ e for e in self.grid.get_cell_list_contents(i[1:]) if isinstance(e, Cell) ][0] if cell.explored == 0: valid_coord.append(cell.pos) for i in range(0, ninjured): inj_index = rnd.choice(valid_coord) a = Injured(self.agent_counter, self, inj_index) self.schedule.add(a) self.grid.place_agent(a, inj_index) self.agent_counter += 1 else: # load map from file try: with open(load_file, 'r') as f: file = f.read() except: print("file not found") sys.exit(-1) exported_map = literal_eval(file) self.ncells = int(math.sqrt(len(exported_map["Cell"].keys()))) - 2 self.grid = MultiGrid(self.ncells + 2, self.ncells + 2, torus=False) for index in exported_map["Cell"].keys(): cell = exported_map["Cell"][index] difficulty = cell[2] explored = cell[3] priority = cell[4] utility = cell[5] if difficulty == "inf": difficulty = math.inf if priority == "-inf": priority = -math.inf if utility == "-inf": utility = -math.inf if explored == -1: self.nobstacle += 1 if self.dump_datas and utility == 1: self.total_difficulty += difficulty a = Cell(self.agent_counter, self, index, difficulty, explored, priority, utility) self.grid.place_agent(a, index) self.agent_counter += 1 for index in exported_map["Injured"].keys(): a = Injured(self.agent_counter, self, index) self.schedule.add(a) self.grid.place_agent(a, index) self.agent_counter += 1 # create robotic agents row = 0 starting_coord = [] # data collection number of beans requested if self.dump_datas: self.deployed_beans_at_start = 0 # generating the list for the starting position of robots for c in range(self.grid.width): # take the agent cell cell = [ e for e in self.grid.get_cell_list_contents(tuple([c, row])) if isinstance(e, Cell) ][0] if cell.explored != -1: starting_coord.append(c) for i in range(0, self.nrobots): column = rnd.choice(starting_coord) a = Robot(self.agent_counter, self, tuple([column, row]), self.radar_radius) self.schedule.add(a) self.grid.place_agent(a, (column, row)) self.agent_counter += 1 # create initial frontier: add cell in front of the robot if valid and not obstacles cell = [ e for e in self.grid.get_cell_list_contents( tuple([column, row + 1])) if isinstance(e, Cell) ][0] if cell.explored == 0: self.frontier.add(tuple([column, row + 1])) try: cell = [ e for e in self.grid.get_cell_list_contents( tuple([column + 1, row + 1])) if isinstance(e, Cell) ][0] if cell.explored == 0: self.frontier.add(tuple([column + 1, row + 1])) except: pass try: cell = [ e for e in self.grid.get_cell_list_contents( tuple([column - 1, row + 1])) if isinstance(e, Cell) ][0] if cell.explored == 0: self.frontier.add(tuple([column - 1, row + 1])) except: pass cell = [ e for e in self.grid.get_cell_list_contents(tuple([column, row])) if isinstance(e, Cell) ][0] # in the cell where some robots are deployed, only one bean is deployed if not cell.wifi_bean: cell.wifi_bean = True for index in self.grid.get_neighborhood( cell.pos, "moore", include_center=False, radius=self.wifi_range): cell = [ e for e in self.grid.get_cell_list_contents(index) if isinstance(e, Cell) ][0] cell.wifi_covered = True if self.dump_datas: self.deployed_beans_at_start += 1 # what the model does at each time step def step(self): # data collection for alpha variation if self.alpha_variation: sim_step = self.get_step(self) self.alpha_step[sim_step] = list() # call step function for all of the robots in random order self.schedule.step() if self.dump_datas: self.dc_robot_status.collect(self) if self.optimization_task: self.total_idling_time += self.get_number_robots_status( self, "idling") if self.gamma_variation: distances = self.compute_robot_distances(self) self.gamma_df = self.gamma_df.append( { "step": self.get_step(self), "mean": distances[0], "std": distances[1] }, ignore_index=True, sort=False) # if all seen cells have benn explored, stop the simulation # we do this so if there are unreachable cells, the cannot be seen, so the simulation stops anyway stop_exploration_done = True for node in self.seen_graph.nodes(): cell = [ obj for obj in self.grid.get_cell_list_contents(node) if isinstance(obj, Cell) ][0] if cell.explored == 0 or cell.explored == 1: stop_exploration_done = False stop_no_robots = False if len([x for x in self.schedule.agents if isinstance(x, Robot)]) == 0: stop_no_robots = True stop = stop_exploration_done or stop_no_robots if stop: print("Simultation ended") # Data collection if self.dump_datas: df = pd.read_csv(self.time_csv) df = df.append( { "nrobots": self.nrobots, "ncells": self.ncells, "steps": self.schedule.steps, "total_difficulty": self.total_difficulty, "beans_deployed": self.get_number_bean_deployed(self) }, ignore_index=True) df.to_csv(self.time_csv, index=False) df_robots_status = self.dc_robot_status.get_model_vars_dataframe( ) df = pd.read_csv(self.robot_status_csv) if len(df["sim_id"]) == 0: df_robots_status["sim_id"] = 0 else: df_robots_status["sim_id"] = df["sim_id"][df.index[-1]] + 1 df = df.append(df_robots_status, ignore_index=True, sort=False) df.to_csv(self.robot_status_csv, index=False) if self.alpha_variation: mean = round(np.mean(self.costs_each_path), 3) std = round(np.std(self.costs_each_path), 3) df = pd.read_csv(self.alpha_csv) df = df.append( { "nrobots": self.nrobots, "radar_radius": self.radar_radius, "alpha": self.alpha, "gamma": self.gamma, "mean": mean, "std": std }, ignore_index=True) df.to_csv(self.alpha_csv, index=False) tmp_df = pd.DataFrame(columns=["step", "cost"]) for s, costs in zip(self.alpha_step.keys(), self.alpha_step.values()): if not costs: tmp_df = tmp_df.append({ "step": s, "cost": -1 }, ignore_index=True, sort=False) continue for c in costs: tmp_df = tmp_df.append({ "step": s, "cost": c }, ignore_index=True, sort=False) df = pd.read_csv(self.alpha_step_csv) if len(df["sim_id"]) == 0: tmp_df["sim_id"] = 0 else: tmp_df["sim_id"] = df["sim_id"][df.index[-1]] + 1 tmp_df["nrobots"] = self.nrobots tmp_df["radar_radius"] = self.radar_radius tmp_df["alpha"] = self.alpha tmp_df["gamma"] = self.gamma df = df.append(tmp_df, ignore_index=True, sort=False) df.to_csv(self.alpha_step_csv, index=False) if self.gamma_variation: df = pd.read_csv(self.gamma_csv) if len(df["sim_id"]) == 0: self.gamma_df["sim_id"] = 0 else: self.gamma_df["sim_id"] = df["sim_id"][df.index[-1]] + 1 self.gamma_df["nrobots"] = self.nrobots self.gamma_df["radar_radius"] = self.radar_radius self.gamma_df["alpha"] = self.alpha self.gamma_df["gamma"] = self.gamma df = df.append(self.gamma_df, ignore_index=True, sort=False) df.to_csv(self.gamma_csv, index=False) self.running = False def run_model(self): while (True): # search for unexplored cells stop = True for node in self.seen_graph.nodes(): cell = [ obj for obj in self.grid.get_cell_list_contents(node) if isinstance(obj, Cell) ][0] if cell.explored == 0 or cell.explored == 1: stop = False # if all seen cells have benn explored, stop the simulation # we do this so if there are unreachable cells, the cannot be seen, so the simulation stops anyway if stop: self.running = False break else: self.step() # Data collection utilities @staticmethod def get_step(m): return m.schedule.steps # these two should go faster since cells are not in the scheduler anymore @staticmethod def get_number_robots_status(m, status): status_value = { "idling": 0, "travelling": 1, "exploring": 2, "deploying_bean": 3 } return len([ x for x in m.schedule.agents if isinstance(x, Robot) and x.status == status_value[status] ]) @staticmethod def get_number_bean_deployed(m): return sum([ x.number_bean_deployed for x in m.schedule.agents if isinstance(x, Robot) ]) + m.deployed_beans_at_start # function for gamma variation @staticmethod def compute_robot_distances(m): nrobots = m.nrobots T_up = np.full( (nrobots, nrobots), 0.0) # if it's only zero, numpy represents only integers # didn't dig deep in numpy doc but it looks like it handles triangualr matrices as "normal" matrices, so # i just initilize a full matrix and then i'll use it as a triangular. robots = [x for x in m.schedule.agents if isinstance(x, Robot)] # the order of the robots in robots can change from step to step (due to the random scheduler), # This shouldn't create any type of problem, but to avoid a lot of problems with indexes later on # we sort them basing on the unique_id robots.sort(key=lambda x: x.unique_id) # I need the lowest id to shift back the ids to fit the matrices coordinations lowest_id = robots[0].unique_id for r in robots: matrix_id_row = r.unique_id - lowest_id # the distance of a robot to itself is zero by definition y1, x1 = r.pos for i in range(matrix_id_row + 1, nrobots): r2 = robots[i] # i can do this because they are sorted y2, x2 = r2.pos T_up[matrix_id_row][i] = distance.euclidean([x1, y1], [x2, y2]) mean_dist_robots = list() # the robot 0 has only the rows mean_robot_zero = sum(T_up[0, 1:nrobots]) mean_dist_robots.append(mean_robot_zero) for i in range(1, nrobots - 1): # the last row has no values, i iters the rows mean_robot = (sum(T_up[0:i, i]) + sum(T_up[i, i + 1:nrobots])) / (nrobots - 1) mean_dist_robots.append(mean_robot) # last robot has only the columns mean_last_robot = sum(T_up[0:nrobots - 1, nrobots - 1]) mean_dist_robots.append(mean_last_robot) return tuple([ round(np.mean(mean_dist_robots), 3), round(np.std(mean_dist_robots), 3) ])
class Model(Model): def __init__(self, N, B, T, Treg, width, height): self.num_myelin = N * 8 self.num_agents = N + B + T + Treg + self.num_myelin self.num_neurons = N self.num_myelin = 4 self.num_limfocytB = B self.num_active_B = 0 self.num_infected_B = 0 self.num_limfocytT = T self.num_activeT = 0 self.num_limfocytTreg = Treg self.grid = MultiGrid(width, height, True) self.schedule = RandomActivation(self) self.available_ids = set() self.dead_agents = set() self.new_agents = set() self.max_id = 0 self.step_count = 1 self.cytokina = 0 self.cytokina_prev = 0 self.sum = 0 self.B = 0 self.a = 0.80 self.Ymax = 100 open('new_and_dead.txt', 'w').close() # Create agents neuron_positions = [[3, 3], [3, 10], [3, 20], [3, 27], [10, 3], [10, 10], [10, 20], [10, 27], [19, 3], [19, 10], [19, 20], [19, 27], [26, 3], [26, 10], [26, 20], [26, 27], [14, 15]] for i in range(self.num_neurons): a = Neuron(i, self, "Neuron") self.schedule.add(a) #Add agent to a random grid cell #x=self.random.randrange(self.grid.width) #y=self.random.randrange(self.grid.height) #self.grid.place_agent(a,(x,y)) pos = neuron_positions[i] self.grid.place_agent(a, (pos[0], pos[1])) cells = self.grid.get_neighborhood(a.pos, True, False, 1) id = self.num_agents - i * 8 for cell in cells: m = Myelin(id, self, "Myelin") self.schedule.add(m) self.grid.place_agent(m, cell) id -= 1 #dodawanie różnych typów agentów zgodnie z ich liczbą podaną przy inicjacji modelu for i in range(self.num_limfocytB): a = LimfocytB(i + self.num_neurons, self, "LimfocytB") self.schedule.add(a) #Add agent to a random grid cell x = self.random.randrange(self.grid.width) y = self.random.randrange(self.grid.height) self.grid.place_agent(a, (x, y)) for i in range(self.num_limfocytT): a = LimfocytT(i + N + B, self, "LimfocytT") self.schedule.add(a) #Add agent to a random grid cell x = self.random.randrange(self.grid.width) y = self.random.randrange(self.grid.height) self.grid.place_agent(a, (x, y)) for i in range(self.num_limfocytTreg): a = LimfocytTreg(i + N + B + T, self, "LimfocytTreg") self.schedule.add(a) #Add agent to a random grid cell x = self.random.randrange(self.grid.width) y = self.random.randrange(self.grid.height) self.grid.place_agent(a, (x, y)) self.max_id = self.num_agents - 1 self.datacollector_population = DataCollector( model_reporters={"Populacja": compute_population}) self.datacollector_T_population = DataCollector( model_reporters={"Populacja Limfocytów T": T_population}) #self.datacollector_T_precentage=DataCollector( #model_reporters={"Precentage Limfocyt T": T_popualtion_precentage}) self.datacollector_B_population = DataCollector( model_reporters={"Populacja Limfocytów B": B_population}) self.datacollector_Treg_population = DataCollector( model_reporters={"Populacja Limfocytów Treg": Treg_population}) self.datacollector_B_active_population = DataCollector( model_reporters={ "Populacja Aktywnych Limfocytów B": B_activated_population }) self.datacollector_T_active_population = DataCollector( model_reporters={ "Populacja Aktywnych Limfocytów T": T_activated_population }) self.datacollector_B_infected_population = DataCollector( model_reporters={ "Populacja Zainfekowanych Limfocytów B": B_infected_population }) self.datacollector_myelin_population = DataCollector( model_reporters={ "Populacja osłonek mielinowych": myelin_population }) self.datacollector_myelin_healths = DataCollector( model_reporters={ "Suma punktów życia osłonek mielinowych": myelin_healths }) def step(self): #print("self running: "+str(self.running())) self.schedule.step() self.datacollector_population.collect(self) self.datacollector_T_population.collect(self) #self.datacollector_T_precentage.collect(self) self.datacollector_B_population.collect(self) self.datacollector_Treg_population.collect(self) self.datacollector_B_active_population.collect(self) self.datacollector_T_active_population.collect(self) self.datacollector_B_infected_population.collect(self) self.datacollector_myelin_population.collect(self) self.datacollector_myelin_healths.collect(self) self.adding_removing() self.datacollector_myelin_healths.get_model_vars_dataframe().to_csv( r'Data/myelin_healths25.txt', sep=' ', mode='w') self.datacollector_T_population.get_model_vars_dataframe().to_csv( r'Data/T_population25.txt', sep=' ', mode='w') self.datacollector_B_population.get_model_vars_dataframe().to_csv( r'Data/B_population25.txt', sep=' ', mode='w') self.datacollector_Treg_population.get_model_vars_dataframe().to_csv( r'Data/Treg_population25.txt', sep=' ', mode='w') self.datacollector_B_active_population.get_model_vars_dataframe( ).to_csv(r'Data/B_active_population25.txt', sep=' ', mode='w') self.datacollector_T_active_population.get_model_vars_dataframe( ).to_csv(r'Data/T_active_population25.txt', sep=' ', mode='w') self.datacollector_B_infected_population.get_model_vars_dataframe( ).to_csv(r'Data/B_infected_population25.txt', sep=' ', mode='w') print("Liczba agentów: " + str(self.num_agents)) print("MaxID: " + str(self.max_id)) self.cytokina = max( min((self.B + self.cytokina_prev), self.Ymax) * self.a, 0) print("Cytokina " + str(self.cytokina)) print("Cytokina_prev " + str(self.cytokina_prev)) f = open("agents.txt", 'a') f.write("======Step : " + str(self.step_count) + "\n") for agent in self.schedule.agents: f.write("Agent: " + str(agent.type) + " " + str(agent.unique_id) + str(agent.pos) + "\n") f.close() self.cytokina_prev = self.cytokina self.B = 0 def running(self): self.step() def adding_removing( self): #funckja odpowiedzialna za dodawanie i usuwanie agentów #print("AddingRemoving") f = open("new_and_dead.txt", 'a') f.write("Step " + str(self.step_count) + "\n") f.write("======Dead agents======: " + "\n") for d in self.dead_agents: try: self.schedule.remove(d) self.num_agents -= 1 self.available_ids.add(d.unique_id) except KeyError: continue try: self.grid._remove_agent(d.pos, d) except KeyError: continue f.write(str(d.unique_id) + " " + d.type + "\n") #if d.type=="AktywowanyLimfocytT": # self.cytokina-=1 self.dead_agents.clear() f.write("======New Agents=====: " + "\n") for n in self.new_agents: self.schedule.add(n) self.num_agents += 1 self.grid.place_agent(n, n.pos) if n.unique_id in self.available_ids: self.available_ids.remove(n.unique_id) f.write(str(n.unique_id) + " " + n.type + "\n") #if n.type=="AktywowanyLimfocytT": # self.cytokina+=1 self.new_agents.clear() m = 1 n = 0 for agent in self.schedule.agents: if agent.unique_id > m: m = agent.unique_id if (agent.type == "LimfocytT") or (agent.type == "AktywowanyLimfocytT"): n += 1 self.max_id = m self.num_limfocytT = 0 self.deficiencies() f.close() def deficiencies(self): n = B_population(self) if n == 0: if len(self.available_ids) == 0: self.max_id += 1 id = self.max_id else: id = min(self.available_ids) self.available_ids.remove(id) agent = LimfocytB(id, self, "LimfocytB") self.schedule.add(agent) x = self.random.randrange(self.grid.width) y = self.random.randrange(self.grid.height) self.grid.place_agent(agent, (x, y)) self.num_agents += 1 n = T_population(self) if n == 0: for i in range(10): if len(self.available_ids) == 0: self.max_id += 1 id = self.max_id else: id = min(self.available_ids) self.available_ids.remove(id) agent = LimfocytB(id, self, "LimfocytT") self.schedule.add(agent) x = self.random.randrange(self.grid.width) y = self.random.randrange(self.grid.height) self.grid.place_agent(agent, (x, y)) self.num_agents += 1 n = Treg_population(self) if n == 0: if len(self.available_ids) == 0: self.max_id += 1 id = self.max_id else: id = min(self.available_ids) self.available_ids.remove(id) agent = LimfocytB(id, self, "LimfocytTreg") self.schedule.add(agent) x = self.random.randrange(self.grid.width) y = self.random.randrange(self.grid.height) self.grid.place_agent(agent, (x, y)) self.num_agents += 1
class Model(Model): """A model with a number of agents. It represents a space where you can experiment by varying parameters""" def __init__(self, n_victims, n_offenders, n_criminal_generators, r_criminal_generators, max_cp, pop_count, width, height): self.grid = MultiGrid(width, height, torus=False) self.schedule = RandomActivation(self) self.datacollector = DataCollector( model_reporters={"Average Perception of Safety": average_perception_of_safety, "Crime-rate": crime_rate_single_run}, ) self.width = width self.height = height self.running = True # Number of crimes committed per time step. self.crime_number = 0.0 # User settable parameters self.num_victims = n_victims self.num_offenders = n_offenders self.num_crime_areas = n_criminal_generators self.crime_area_rad = r_criminal_generators self.hotspot_rad = 1 self.max_criminal_preference = max_cp self.pop_count = pop_count # add light agents to the grid self.light_layer() # add possible victims to the grid self.add_victims() # add possible offenders to the grid self.add_offenders() # add crime areas self.add_criminal_areas() self.datacollector.collect(self) def light_layer(self): """Add the light layer to the model. """ for i in range(self.width): for j in range(self.height): l = Light(uuid.uuid4(), i + j, self) self.schedule.add(l) # light is ordered from darkest to lightest from the # bottom left corner to the top right corner. self.grid.place_agent(l, (i, j)) # light is randomised, so long as the # luminance difference of surrounding cells is within a limit # self.grid.place_agent(l, self.r_pos(l)) def r_pos(self, new_l): """Randomises the positions of the light realistically by considering the difference between the illuminance in one position and another""" # Position precisely one light agent per position. valid = False while not valid: x = self.random.randrange(self.width) y = self.random.randrange(self.height) # Check if there is already a light agent in this spot if not (any(isinstance(agent, Light) for agent in self.grid.get_cell_list_contents((x, y)))): # Check whether given the difference in the influencing factors between the agent # and surrounding agents, the new agent can be placed in this position. # Returns True or False if self.valid_pos((x, y), new_l, 1): valid = True return x, y def valid_pos(self, n_pos, new_a, delta): """Check whether this position is a valid position given the difference in the inlfueincing factors between the new agent and the surrounding agents""" # Get the surrounding positions neighborhood = self.grid.get_neighborhood(n_pos, moore=True, include_center=False) # Get the surrounding positions containing light agents. cell_contents = [] for pos in neighborhood: cell_contents.append(self.grid.get_cell_list_contents([pos])) f_cell_contents = [val for sublist in cell_contents for val in sublist] surr_light = [a for a in f_cell_contents if isinstance(a, Light)] # If the surrounding light list is empty, return the position if len(surr_light) == 0: return True else: # Check whether the difference in illuminance is within the valid scope for l in surr_light: if abs(l.illuminance - new_a.illuminance) >= delta: return False return True def get_random_pos(self): x = self.random.randrange(self.grid.width) y = self.random.randrange(self.grid.height) return (x, y) def add_victims(self): for i in range(self.num_victims): # Generate a safe location for this agent. s = SafeLocation(uuid.uuid4(), self) self.schedule.add(s) self.grid.place_agent(s, self.get_random_pos()) # Generate the agent given its safe location. p = PossibleVictim(uuid.uuid4(), self, s) self.schedule.add(p) self.grid.place_agent(p, self.get_random_pos()) def add_offenders(self): for i in range(self.num_offenders): c = PossibleOffender(uuid.uuid4(), self, self.max_criminal_preference) self.schedule.add(c) x = self.random.randrange(self.grid.width) y = self.random.randrange(self.grid.height) self.grid.place_agent(c, (x, y)) def generate_criminal_areas(self): """ Return a list of criminal areas with specified centroids and radius. If criminal areas overlap, update the criminal areas. DOES NOT ADD THE AREAS TO THE MODEL, AS IT IS ONLY THE POSITIONS WITHIN THE AREAS THAT ARE ADDED TO THE MODEL. """ # ----- HELPER FUNCTION ----- def generate_centroid_list(n): """ If no centroids have been passed, generate random centroids for the criminal areas. """ centroids = [] for i in range(n): x = self.random.randrange(self.grid.width) y = self.random.randrange(self.grid.height) centroids.append((x, y)) return centroids def get_surr_pos(pos, r=3): return self.grid.get_neighborhood(pos, moore=True, include_center=True, radius=r) # --------------------------- centroids = self.num_crime_areas radius = self.crime_area_rad # If the parameter passed as the centroid is an int, generate this number of centroids. if isinstance(centroids, int): centroids = generate_centroid_list(centroids) criminal_area = [] # For every centroid in the list, create either a hotspot or a criminal area depending # on the type. for c in centroids: criminal_area.append(CrimeGenerator(uuid.uuid4(), self, c, radius)) # Return a list of criminal areas. return criminal_area def add_criminal_areas(self, criminal_area=None): """Add crime areas to the model. """ # If no criminal area has been passed, generate random criminal area. if criminal_area is None: criminal_area = self.generate_criminal_areas() def increment_crimes(self): self.crime_number += 1 global crime_number crime_number += 1 def check_victim_agents(self): if not [agent for agent in self.schedule.agents if isinstance(agent, PossibleVictim)]: self.running = False def step(self): """Advance the model by one step.""" self.schedule.step() self.datacollector.collect(self) self.check_victim_agents() self.crime_number = 0
class SleepAnimals_sinDataColl(Model): ''' Analysis of the evolution of sleep in animals ''' # Default values width = 40 height = 40 number_food_patch = 40 number_sleep_patch = 40 interdistance_factor = 0.7 intradistance_factor = 0.2 fp_depletion_tick = 60 def __init__(self, model_id , genome,width = 40, height = 40, number_food_patch = 40, number_sleep_patch = 40, interdistance_factor = 0.7, intradistance_factor = 0.2, fp_depletion = 60, sleep_and_food_gainfactor = 1): super().__init__() # Setting Parameters self.model_id = model_id self.width = width self.height = height self.number_food_patch = number_food_patch self.number_sleep_patch = number_sleep_patch self.interdistance_factor = interdistance_factor self.intradistance_factor = intradistance_factor self.sue_factor = sleep_and_food_gainfactor self.genome = genome self.fp_center_x = 0 self.fp_center_y = 0 self.sp_center_x = 0 self.sp_center_y = 0 self.current_id_food_patch = 0 self.current_id_sleep_patch = 0 self.fp_tick_to_depletion = fp_depletion self.schedule = RandomActivation(self) self.grid = MultiGrid(self.width, self.height, torus = False) #self.datacollector = DataCollector( # agent_reporters={"Food_fitness" : lambda a: a.fitness_food, # "Sleep_fitness" : lambda a: a.fitness_sleep, # "Fitness" : lambda a: a.fitness, # "Mode" : lambda a: a.mode, # "Direction" : lambda a: a.lookingto}) # Picking Centers for Food and Sleep Patches self.interdistance = 0 self.intradistance = 0 self.findingcenters() # Populating Food Patches self.available_food_patches = self.grid.get_neighborhood( (self.fp_center_x, self.fp_center_y), False, True, self.intradistance ) i = 0 while i < self.number_food_patch: self.new_foodpatch() i += 1 # Populating Sleep Patches self.available_sleep_patches = self.grid.get_neighborhood( (self.sp_center_x, self.sp_center_y), False, True, self.intradistance ) i = 0 while i < self.number_sleep_patch: current_spot = random.choice(self.available_sleep_patches) if not self.grid.is_cell_empty(current_spot): continue sleep_patch = SleepPatch( self.next_id_sleeppatch(), self, current_spot ) self.grid.place_agent( sleep_patch, current_spot ) i += 1 # Adding Animal to the world current_spot = random.choice( self.grid.empties ) animal = Animal( self.next_id(), self, current_spot, self.genome, self.sue_factor, self.sue_factor ) self.grid.place_agent( animal, current_spot ) self.schedule.add( animal ) def step(self): '''Advance the model by one step.''' # self.datacollector.collect(self) self.schedule.step() def findingcenters(self): max_manhattan_length = self.height + self.width self.interdistance = int(max_manhattan_length * self.interdistance_factor) self.intradistance = int(max_manhattan_length * self.intradistance_factor) fp_center_x = 0 fp_center_y = 0 sp_center_x = 0 sp_center_y = 0 centers_selected = False while not centers_selected: fp_center_x = random.randrange(self.width) fp_center_y = random.randrange(self.height) fp_center = (fp_center_x, fp_center_y) available_spots_food = self.grid.get_neighborhood(fp_center, False, False, self.intradistance) if len(available_spots_food) < 80: continue if self.interdistance > 0: list_centers_sp = list( set( self.grid.get_neighborhood(fp_center, False, False, self.interdistance + 1) ) - set( self.grid.get_neighborhood(fp_center, False, False, self.interdistance - 1) ) ) if len(list_centers_sp) < 5: continue else: list_centers_sp = [(fp_center_x,fp_center_y)] sp_center = random.choice(list_centers_sp) (sp_center_x, sp_center_y) = sp_center available_spots_sleep = self.grid.get_neighborhood(sp_center, False, False, self.intradistance) if len(available_spots_sleep) < 80: continue centers_selected = True self.fp_center_x = fp_center_x self.fp_center_y = fp_center_y self.sp_center_x = sp_center_x self.sp_center_y = sp_center_y def next_id_foodpatch(self): """ Return the next unique ID for food patches, increment current_id""" self.current_id_food_patch += 1 a = 'M' + str(self.model_id) + 'F' + str(self.current_id_food_patch) return a def next_id_sleeppatch(self): """ Return the next unique ID for sleep patches, increment current_id""" self.current_id_sleep_patch += 1 a = 'M' + str(self.model_id) + 'S' + str(self.current_id_sleep_patch) return a def new_foodpatch(self): spot_found = False while not spot_found : current_spot = random.choice(self.available_food_patches) if not self.grid.is_cell_empty(current_spot): continue food_patch = FoodPatch(self.next_id_foodpatch(), self, current_spot, self.fp_tick_to_depletion) self.grid.place_agent(food_patch, current_spot) spot_found = True def arrayRGB_clusters(self): available_spots = np.full( (self.grid.width , self.grid.height , 3) , 255) for coordinates in self.available_sleep_patches: (x, y) = coordinates available_spots[x][y]= [100, 0, 150] for coordinates in self.available_food_patches: (x, y) = coordinates available_spots[x][y]= [10, 150, 0] return available_spots def arrayRGB_display(self): RGBdisplay = np.full((self.grid.width, self.grid.height,3), 255) for cell in self.grid.coord_iter(): cell_content, x, y = cell a = list(cell_content) if len(a) == 0: RGBdisplay[x][y] = [255,255,255] elif len(a) == 1: if isinstance(a[0], SleepPatch): RGBdisplay[x][y] = [100,0,150] elif isinstance(a[0], FoodPatch): RGBdisplay[x][y] = [10,150,0] elif isinstance(a[0], Animal): RGBdisplay[x][y] = [0,0,0] else: pass elif len(a) == 2: RGBdisplay[x][y] = [0,0,0] else: pass return RGBdisplay def array2D_display(self): display2D = np.zeros((self.grid.width, self.grid.height)) for cell in self.grid.coord_iter(): cell_content, x, y = cell a = list(cell_content) if len(a) == 0: display2D[x][y] = 0 elif len(a) == 1: if isinstance(a[0], SleepPatch): display2D[x][y] = 10 elif isinstance(a[0], FoodPatch): display2D[x][y] = 20 elif isinstance(a[0], Animal): display2D[x][y] = 30 else: pass else: pass return display2D
class FireEvacuation(Model): MIN_HEALTH = 0.75 MAX_HEALTH = 1 MIN_SPEED = 1 MAX_SPEED = 2 MIN_NERVOUSNESS = 1 MAX_NERVOUSNESS = 10 MIN_EXPERIENCE = 1 MAX_EXPERIENCE = 10 MIN_VISION = 1 # MAX_VISION is simply the size of the grid def __init__(self, floor_plan_file, human_count, collaboration_percentage, fire_probability, visualise_vision, random_spawn, save_plots): # Load floorplan # floorplan = np.genfromtxt(path.join("fire_evacuation/floorplans/", floor_plan_file)) with open(os.path.join("fire_evacuation/floorplans/", floor_plan_file), "rt") as f: floorplan = np.matrix([line.strip().split() for line in f.readlines()]) # Rotate the floorplan so it's interpreted as seen in the text file floorplan = np.rot90(floorplan, 3) # Check what dimension our floorplan is width, height = np.shape(floorplan) # Init params self.width = width self.height = height self.human_count = human_count self.collaboration_percentage = collaboration_percentage self.visualise_vision = visualise_vision self.fire_probability = fire_probability self.fire_started = False # Turns to true when a fire has started self.save_plots = save_plots # Set up model objects self.schedule = RandomActivation(self) self.grid = MultiGrid(height, width, torus=False) # Used to start a fire at a random furniture location self.furniture_list = [] # Used to easily see if a location is a FireExit or Door, since this needs to be done a lot self.fire_exit_list = [] self.door_list = [] # If random spawn is false, spawn_list will contain the list of possible spawn points according to the floorplan self.random_spawn = random_spawn self.spawn_list = [] # Load floorplan objects for (x, y), value in np.ndenumerate(floorplan): value = str(value) floor_object = None if value is "W": floor_object = Wall((x, y), self) elif value is "E": floor_object = FireExit((x, y), self) self.fire_exit_list.append((x, y)) self.door_list.append((x, y)) # Add fire exits to doors as well, since, well, they are elif value is "F": floor_object = Furniture((x, y), self) self.furniture_list.append((x, y)) elif value is "D": floor_object = Door((x, y), self) self.door_list.append((x, y)) elif value is "S": self.spawn_list.append((x, y)) if floor_object: self.grid.place_agent(floor_object, (x, y)) self.schedule.add(floor_object) # Create a graph of traversable routes, used by agents for pathing self.graph = nx.Graph() for agents, x, y in self.grid.coord_iter(): pos = (x, y) # If the location is empty, or a door if not agents or any(isinstance(agent, Door) for agent in agents): neighbors = self.grid.get_neighborhood(pos, moore=True, include_center=True, radius=1) for neighbor in neighbors: # If there is contents at this location and they are not Doors or FireExits, skip them if not self.grid.is_cell_empty(neighbor) and neighbor not in self.door_list: continue self.graph.add_edge(pos, neighbor) # Collects statistics from our model run self.datacollector = DataCollector( { "Alive": lambda m: self.count_human_status(m, Human.Status.ALIVE), "Dead": lambda m: self.count_human_status(m, Human.Status.DEAD), "Escaped": lambda m: self.count_human_status(m, Human.Status.ESCAPED), "Incapacitated": lambda m: self.count_human_mobility(m, Human.Mobility.INCAPACITATED), "Normal": lambda m: self.count_human_mobility(m, Human.Mobility.NORMAL), "Panic": lambda m: self.count_human_mobility(m, Human.Mobility.PANIC), "Verbal Collaboration": lambda m: self.count_human_collaboration(m, Human.Action.VERBAL_SUPPORT), "Physical Collaboration": lambda m: self.count_human_collaboration(m, Human.Action.PHYSICAL_SUPPORT), "Morale Collaboration": lambda m: self.count_human_collaboration(m, Human.Action.MORALE_SUPPORT) } ) # Calculate how many agents will be collaborators number_collaborators = int(round(self.human_count * (self.collaboration_percentage / 100))) # Start placing human agents for i in range(0, self.human_count): if self.random_spawn: # Place human agents randomly pos = self.grid.find_empty() else: # Place human agents at specified spawn locations pos = random.choice(self.spawn_list) if pos: # Create a random human health = random.randint(self.MIN_HEALTH * 100, self.MAX_HEALTH * 100) / 100 speed = random.randint(self.MIN_SPEED, self.MAX_SPEED) if number_collaborators > 0: collaborates = True number_collaborators -= 1 else: collaborates = False # Vision statistics obtained from http://www.who.int/blindness/GLOBALDATAFINALforweb.pdf vision_distribution = [0.0058, 0.0365, 0.0424, 0.9153] vision = int(np.random.choice(np.arange(self.MIN_VISION, self.width + 1, (self.width / len(vision_distribution))), p=vision_distribution)) nervousness_distribution = [0.025, 0.025, 0.1, 0.1, 0.1, 0.3, 0.2, 0.1, 0.025, 0.025] # Distribution with slight higher weighting for above median nerovusness nervousness = int(np.random.choice(range(self.MIN_NERVOUSNESS, self.MAX_NERVOUSNESS + 1), p=nervousness_distribution)) # Random choice starting at 1 and up to and including 10 experience = random.randint(self.MIN_EXPERIENCE, self.MAX_EXPERIENCE) belief_distribution = [0.9, 0.1] # [Believes, Doesn't Believe] believes_alarm = np.random.choice([True, False], p=belief_distribution) human = Human(pos, health=health, speed=speed, vision=vision, collaborates=collaborates, nervousness=nervousness, experience=experience, believes_alarm=believes_alarm, model=self) self.grid.place_agent(human, pos) self.schedule.add(human) else: print("No tile empty for human placement!") self.running = True # Plots line charts of various statistics from a run def save_figures(self): DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) OUTPUT_DIR = DIR + "/output" results = self.datacollector.get_model_vars_dataframe() dpi = 100 fig, axes = plt.subplots(figsize=(1920 / dpi, 1080 / dpi), dpi=dpi, nrows=1, ncols=3) status_results = results.loc[:, ['Alive', 'Dead', 'Escaped']] status_plot = status_results.plot(ax=axes[0]) status_plot.set_title("Human Status") status_plot.set_xlabel("Simulation Step") status_plot.set_ylabel("Count") mobility_results = results.loc[:, ['Incapacitated', 'Normal', 'Panic']] mobility_plot = mobility_results.plot(ax=axes[1]) mobility_plot.set_title("Human Mobility") mobility_plot.set_xlabel("Simulation Step") mobility_plot.set_ylabel("Count") collaboration_results = results.loc[:, ['Verbal Collaboration', 'Physical Collaboration', 'Morale Collaboration']] collaboration_plot = collaboration_results.plot(ax=axes[2]) collaboration_plot.set_title("Human Collaboration") collaboration_plot.set_xlabel("Simulation Step") collaboration_plot.set_ylabel("Successful Attempts") collaboration_plot.set_ylim(ymin=0) timestr = time.strftime("%Y%m%d-%H%M%S") plt.suptitle("Percentage Collaborating: " + str(self.collaboration_percentage) + "%, Number of Human Agents: " + str(self.human_count), fontsize=16) plt.savefig(OUTPUT_DIR + "/model_graphs/" + timestr + ".png") plt.close(fig) # Starts a fire at a random piece of furniture with file_probability chance def start_fire(self): rand = random.random() if rand < self.fire_probability: fire_furniture = random.choice(self.furniture_list) fire = Fire(fire_furniture, self) self.grid.place_agent(fire, fire_furniture) self.schedule.add(fire) self.fire_started = True print("Fire started at:", fire_furniture) def step(self): """ Advance the model by one step. """ self.schedule.step() # If there's no fire yet, attempt to start one if not self.fire_started: self.start_fire() self.datacollector.collect(self) # If no more agents are alive, stop the model and collect the results if self.count_human_status(self, Human.Status.ALIVE) == 0: self.running = False if self.save_plots: self.save_figures() @staticmethod def count_human_collaboration(model, collaboration_type): """ Helper method to count the number of collaborations performed by Human agents in the model """ count = 0 for agent in model.schedule.agents: if isinstance(agent, Human): if collaboration_type == Human.Action.VERBAL_SUPPORT: count += agent.get_verbal_collaboration_count() elif collaboration_type == Human.Action.MORALE_SUPPORT: count += agent.get_morale_collaboration_count() elif collaboration_type == Human.Action.PHYSICAL_SUPPORT: count += agent.get_physical_collaboration_count() return count @staticmethod def count_human_status(model, status): """ Helper method to count the status of Human agents in the model """ count = 0 for agent in model.schedule.agents: if isinstance(agent, Human): if agent.get_status() == status: count += 1 return count @staticmethod def count_human_mobility(model, mobility): """ Helper method to count the mobility of Human agents in the model """ count = 0 for agent in model.schedule.agents: if isinstance(agent, Human): if agent.get_mobility() == mobility: count += 1 return count
class InfectionModel(Model): """A model for infection spread.""" def __init__(self, human_count, random_spawn, save_plots, floor_plan_file="floorplan_1.txt", N=30, width=10, height=10, ptrans=0.5, progression_period=3, progression_sd=2, death_rate=0.0193, recovery_days=21, recovery_sd=7): # Load floorplan # floorplan = np.genfromtxt(path.join("infection_spread/floorplans/", floor_plan_file)) with open( os.path.join("infection_spread/floorplans/", floor_plan_file), "rt") as f: floorplan = np.matrix( [line.strip().split() for line in f.readlines()]) # Rotate the floorplan so it's interpreted as seen in the text file floorplan = np.rot90(floorplan, 3) # Check what dimension our floorplan is width, height = np.shape(floorplan) # Init params self.num_agents = N self.initial_outbreak_size = 1 self.recovery_days = recovery_days self.recovery_sd = recovery_sd self.ptrans = ptrans self.death_rate = death_rate self.running = True self.dead_agents = [] self.width = width self.height = height self.human_count = human_count # Set up model objects self.schedule = RandomActivation(self) self.grid = MultiGrid(height, width, torus=False) # Used to easily see if a location is an Exit or Door, since this needs to be done a lot self.exit_list = [] self.door_list = [] # If random spawn is false, spawn_list will contain the list of possible spawn points according to the floorplan self.random_spawn = random_spawn self.spawn_list = [] # Load floorplan objects for (x, y), value in np.ndenumerate(floorplan): value = str(value) floor_object = None if value == "W": floor_object = Wall((x, y), self) elif value == "E": floor_object = Exit((x, y), self) self.exit_list.append((x, y)) self.door_list.append((x, y)) # Add exits to doors as well elif value == "D": floor_object = Door((x, y), self) self.door_list.append((x, y)) elif value == "S": self.spawn_list.append((x, y)) if floor_object: self.grid.place_agent(floor_object, (x, y)) self.schedule.add(floor_object) # Create a graph of traversable routes, used by agents for pathing self.graph = nx.Graph() for agents, x, y in self.grid.coord_iter(): pos = (x, y) # If the location is empty, or a door if not agents or any(isinstance(agent, Door) for agent in agents): neighbors = self.grid.get_neighborhood(pos, moore=True, include_center=True, radius=1) for neighbor in neighbors: # If there is contents at this location and they are not Doors or Exits, skip them if not self.grid.is_cell_empty( neighbor) and neighbor not in self.door_list: continue self.graph.add_edge(pos, neighbor) # Collects statistics from our model run self.datacollector = DataCollector({ "Susceptible": lambda m: self.count_human_status(m, Human.State.SUSCEPTIBLE), "Infected": lambda m: self.count_human_status(m, Human.State.INFECTED), "Removed": lambda m: self.count_human_status(m, Human.State.REMOVED) }) # Start placing human agents # for i in range(0, self.human_count): # if self.random_spawn: # Place human agents randomly # pos = self.grid.find_empty() # else: # Place human agents at specified spawn locations # pos = random.choice(self.spawn_list) #if pos: # Create a random human # health = random.randint(self.MIN_HEALTH * 100, self.MAX_HEALTH * 100) / 100 # speed = random.randint(self.MIN_SPEED, self.MAX_SPEED) for i in range(0, self.num_agents): a = Human(unique_id=i, model=self) self.schedule.add(a) # Add the agent to a random grid cell # x = self.random.randrange(self.grid.width) # y = self.random.randrange(self.grid.height) # self.grid.place_agent(a, (x, y)) if self.random_spawn: # Place human agents randomly pos = self.grid.find_empty() else: # Place human agents at specified spawn locations pos = random.choice(self.spawn_list) self.grid.place_agent(a, pos) #make some agents infected at start infected = np.random.choice([0, 1], 1, p=[0.98, 0.02]) if infected == 1: a.state = State.INFECTED a.recovery_time = self.get_recovery_time() self.datacollector = DataCollector( #model_reporters={"Gini": compute_gini}, agent_reporters={"State": "state"}) def get_recovery_time(self): return int( self.random.normalvariate(self.recovery_days, self.recovery_sd)) def step(self): """ Advance the model by one step. """ self.schedule.step() self.datacollector.collect(self)
class CancerModel(Model): def __init__(self,cancer_cells_number,cure_number,eat_values, verovatnoca_mutacije): self.counter = 0 self.cure_number = cure_number radoznalosti = list(np.arange(0.01,KILLING_PROBABILITY,0.01)) print(radoznalosti) self.datacollector = DataCollector( model_reporters = {"FitnessFunction":fitness_funkcija, "SpeedSum":overall_speed,"SmartMedicine":num_of_smart_medicine, "RadoznalostSum":radoznalost_sum }) grid_size = math.ceil(math.sqrt(cancer_cells_number*4)) self.grid = MultiGrid(grid_size,grid_size,False) speeds = list(range(grid_size//2)) #popravi te boje TODO print(speeds) poss = self.generate_cancer_cell_positions(grid_size,cancer_cells_number) num_CSC = math.ceil(percentage(1,cancer_cells_number)) pos_CSC = [self.random.choice(poss) for i in range(num_CSC)] self.schedule = RandomActivation(self) self.running = True for i in range(cancer_cells_number): pos = poss[i] c = CancerStemCell(uuid.uuid4(),self,value = eat_values[CancerStemCell.__class__]) if pos in pos_CSC else CancerCell(i,self,value=eat_values[CancerCell.__class__]) self.grid.place_agent(c,pos) self.schedule.add(c) for i in range(cure_number): #pos = self.grid.find_empty() pos = (0,0) radoznalost = self.random.choice(radoznalosti) speed = self.random.choice(speeds) a = CureAgent(uuid.uuid4(),self,speed = speed,radoznalost=radoznalost) if i< cure_number//2 else SmartCureAgent(uuid.uuid4(),self,speed=speed,radoznalost = radoznalost) self.grid.place_agent(a,pos) self.schedule.add(a) for (i,(contents, x,y)) in enumerate(self.grid.coord_iter()): if not contents: c = HealthyCell(uuid.uuid4(),self,eat_values[HealthyCell.__class__]) self.grid.place_agent(c,(x,y)) self.schedule.add(c) def generate_cancer_cell_positions(self,grid_size,cancer_cells_number): center = grid_size//2 poss = [(center,center)] for pos in poss: poss+=[n for n in self.grid.get_neighborhood(pos,moore=True,include_center=False) if n not in poss] if len(set(poss))>=cancer_cells_number: break poss = list(set(poss)) return poss def duplicate_or_kill(self): koliko = math.ceil(percentage(5,self.cure_number)) # TODO igor javlja kako biramo procena cureagents = [c for c in self.schedule.agents if isinstance(c,CureAgent)] sortirani = sorted(cureagents, key=lambda x: x.points, reverse=True) poslednji = sortirani[-koliko:] prvi = sortirani[:koliko] assert(len(prvi)==len(poslednji)) self.remove_agents(poslednji) self.duplicate_agents(prvi) def remove_agents(self,agents): for a in agents: self.schedule.remove(a) self.grid.remove_agent(a) def duplicate_agents(self,agents): for a in agents: a_new = a.__class__(uuid.uuid4(),model=self,speed = a.speed,radoznalost = a.radoznalost) #TODO ostale parametre isto poistoveti self.grid.place_agent(a_new,(1,1)) self.schedule.add(a_new) def step(self): self.datacollector.collect(self) self.counter+=1 self.schedule.step() if self.counter%10 ==0: # TODO ovo menjamo, parameter TODO #TODO sredi boje i #TODO sredi ovo pucanje zbog nule u latin hypercube #TODO napravi da je R promenljivo self.duplicate_or_kill()
class PandemicsModel(Model): def __init__(self, config=default_config, disease=dis.covid_disease): self.agents_count = config.citizens_count + config.policemen_count self.disease = disease self.deceased = [] self.buried = [] self.deceased_counter = 0 self.infected_counter = 0 self.grid = MultiGrid(config.width, config.height, True) self.safety_per_cell = np.ones((config.height, config.width)) self.buildings_map = np.zeros((config.height, config.width)) self.buildings_id_map = np.zeros((config.height, config.width)) self.schedule = SimultaneousActivation(self) self.datacollector = DataCollector( model_reporters={ "deceased": "deceased_counter", "infected": "infected_counter"}, agent_reporters={ "hp": lambda a: a.profile["hp"], "mask_protection": "mask_protection", "infection_day": lambda a: a.profile["infection_day"], "obedience": lambda a: a.profile["obedience"], "fear": lambda a: a.profile["fear"]} ) self.config = config self.buildings = {b["id"] : b for b in self.config.buildings} self.houses = [x for x in self.buildings.values() if x['type'] == 'house'] self.workplaces = [x for x in self.buildings.values() if x['type'] == 'workplace'] self.shops = [x for x in self.buildings.values() if x['type'] == 'shop'] self.add_buildings_to_map(self.buildings) self.street_positions = [] for x in range(self.config.width): for y in range(self.config.height): if self.buildings_map[y][x] == 0: self.street_positions.append((x, y)) self.house_to_agents = defaultdict(list) self.workplace_to_agents = defaultdict(list) self.current_location_type = None # Create agents for i in range(self.agents_count): if i < config.policemen_count: a = agent.create_distribution_policeman_agent( i, self, config.policemen_mental_features_distribution) a.assign_house(self, self.houses) elif i < config.policemen_count + config.citizens_count: a = agent.create_distribution_citizen_agent( i, self, config.citizens_mental_features_distribution) a.assign_house(self, self.houses) a.assign_workplace(self, self.workplaces) self.add_agent(a) for i in self.random.choices(self.schedule.agents, k=config.infected_count): i.start_infection() self.running = True self.steps_count = 0 self.datacollector.collect(self) # Returns (type, id) of the building where agent a is currently located def where_is_agent(self, a): (x, y) = a.pos return (self.buildings_map[y][x], self.buildings_id_map[y][x]) def compute_time_of_day(self): return self.steps_count % self.config.steps_per_day / (self.config.steps_per_day / HOURS_PER_DAY) def compute_current_location_type(self): t = self.compute_time_of_day() return self.config.day_plan[t] if t in self.config.day_plan else \ self.config.day_plan[min(self.config.day_plan.keys(), key=lambda k: k-t)] # Updates current location type based on time of day and the config schedule # Returns true if there is a change in current_location_type def update_current_location_type(self): t = self.compute_time_of_day() if t in self.config.day_plan: self.current_location_type = self.config.day_plan[t] return True return False def add_buildings_to_map(self, buildings): for b in buildings.values(): (x, y) = b["bottom-left"] for i in range(x, x+b["width"]): for j in range(y, y+b["height"]): self.buildings_map[j][i] = self.config.building_tags[b['type']] self.buildings_id_map[j][i] = b['id'] def add_agent(self, a): self.schedule.add(a) # Add the agent to a random grid cell x = self.random.randrange(self.grid.width) y = self.random.randrange(self.grid.height) self.grid.place_agent(a, (x, y)) def bury_agent(self, a): self.schedule.remove(a) self.grid.remove_agent(a) self.deceased_counter += 1 self.buried.append(a) def risk_from_agents(self, agents, weight): risk = 0 for a in agents: risk += 1 - a.mask_protection return risk*weight def evaluate_safety_per_cell(self): """ 1.0 is a perfectly safe cell - empty, with all neighbours and neighbours-of-neighbours empty as well """ for content, x, y in model.grid.coord_iter(): self.safety_per_cell[y][x] = 1 # initial value # Compute risk from (x,y) cell ring0_risk = self.risk_from_agents(content, weight=0.5) considered_cells = {(x,y)} # Compute risk coming from the neighbours of (x,y) cell neighbours = self.grid.get_neighborhood( (x,y), moore=True, include_center=False) neighbours_content = self.grid.get_cell_list_contents(neighbours) ring1_risk = self.risk_from_agents(neighbours_content, 0.25) considered_cells | set(neighbours) # Compute risk coming from # the neighbours of the neighbours of (x,y) cell neighbours_of_neighbours = set() for c in neighbours: neighbours_of_neighbours | set( self.grid.get_neighborhood( (x,y),moore=True, include_center=False)) neighbours_of_neighbours -= considered_cells ring2_risk = self.risk_from_agents( self.grid.get_cell_list_contents(neighbours_of_neighbours), 0.125) self.safety_per_cell[y][x] -= ring0_risk + ring1_risk + ring2_risk def step(self): if (self.update_current_location_type()): for a in self.schedule.agents: if (self.current_location_type is not None): b = a.select_building(self.current_location_type) a.teleport_to_building(b) else: a.teleport_to_street() self.evaluate_safety_per_cell() self.schedule.step() self.steps_count += 1 # collect data self.datacollector.collect(self) for d in self.deceased: self.bury_agent(d) self.deceased = [] def run_model(self, n): for i in range(n): self.step()
class Environment(Model): """ A model which contains a number of ant colonies. """ def __init__(self, width, height, n_colonies, n_ants, n_obstacles, decay=0.2, sigma=0.1, moore=False, birth=True, death=True): """ :param width: int, width of the system :param height: int, height of the system :param n_colonies: int, number of colonies :param n_ants: int, number of ants per colony :param decay: float, the rate in which the pheromone decays :param sigma: float, sigma of the Gaussian convolution :param moore: boolean, True/False whether Moore/vonNeumann is used """ super().__init__() # Agent variables self.birth = birth self.death = death self.pheromone_level = 1 # Environment variables self.width = width self.height = height self.grid = MultiGrid(width, height, False) self.moore = moore self.sigma = sigma self.decay = decay # Environment attributes self.schedule = RandomActivation(self) self.colonies = [Colony(self, i, (width // 2, height // 2), n_ants, birth=self.birth, death=self.death) for i in range(n_colonies)] self.pheromones = np.zeros((width, height), dtype=np.float) self.pheromone_updates = [] self.food = FoodGrid(self) self.food.add_food() self.obstacles = [] for _ in range(n_obstacles): self.obstacles.append(Obstacle(self)) # Metric + data collection self.min_distance = distance.cityblock(self.colonies[0].pos, self.food.get_food_pos()) self.datacollector = DataCollector( model_reporters={"Minimum path length": metrics.min_path_length, "Mean minimum path length": metrics.mean_min_path_length}, agent_reporters={"Agent minimum path length": lambda x: min(x.path_lengths), "Encounters": Ant.count_encounters}) # Animation attributes self.pheromone_im = None self.ax = None def step(self): """ Do a single time-step using freeze-dry states, colonies are updated each time-step in random orders, and ants are updated per colony in random order. """ self.food.step() self.datacollector.collect(self) # Update all colonies for col in random.sample(self.colonies, len(self.colonies)): col.step() self.schedule.step() self.update_pheromones() def move_agent(self, ant, pos): """ Move an agent across the map. :param ant: class Ant :param pos: tuple (x, y) """ if self.moore: assert np.sum(np.subtract(pos, ant.pos) ** 2) in [1, 2], \ "the ant can't move from its original position {} to the new position {}, because the distance " \ "is too large".format(ant.pos, pos) else: assert np.sum(np.subtract(pos, ant.pos) ** 2) == 1, \ "the ant can't move from its original position {} to the new position {}, because the distance " \ "is too large, loc_food {}".format(ant.pos, pos, self.food.get_food_pos()) self.grid.move_agent(ant, pos) def get_random_position(self): return (np.random.randint(0, self.width), np.random.randint(0, self.height)) def position_taken(self, pos): if pos in self.food.get_food_pos(): return True for colony in self.colonies: if colony.on_colony(pos): return True for obstacle in self.obstacles: if obstacle.on_obstacle(pos): return True return False def add_food(self): """ Add food somewhere on the map, which is not occupied by a colony yet """ self.food.add_food() def place_pheromones(self, pos): """ Add pheromone somewhere on the map :param pos: tuple (x, y) """ self.pheromone_updates.append((pos, self.pheromone_level)) def get_neighbor_pheromones(self, pos, id): """ Get the passable neighboring positions and their respective pheromone levels for the pheromone id :param pos: :param id: :return: """ indices = self.grid.get_neighborhood(pos, self.moore) indices = [x for x in indices if not any([isinstance(x, Obstacle) for x in self.grid[x[0]][x[1]]])] pheromones = [self.pheromones[x, y] for x, y in indices] return indices, pheromones def update_pheromones(self): """ Place the pheromones at the end of a timestep on the grid. This is necessary for freeze-dry time-steps """ for (pos, level) in self.pheromone_updates: # self.pheromones[pos] += level self.pheromones[pos] += 1 self.pheromone_updates = [] # gaussian convolution using self.sigma self.pheromones = gaussian_filter(self.pheromones, self.sigma) * self.decay def animate(self, ax): """ :param ax: :return: """ self.ax = ax self.animate_pheromones() self.animate_colonies() self.animate_ants() self.animate_food() self.animate_obstacles() def animate_pheromones(self): """ Update the visualization part of the Pheromones. :param ax: """ pheromones = np.rot90(self.pheromones.astype(np.float64).reshape(self.width, self.height)) if not self.pheromone_im: self.pheromone_im = self.ax.imshow(pheromones, vmin=0, vmax=50, interpolation='None', cmap="Purples") else: self.pheromone_im.set_array(pheromones) def animate_colonies(self): """ Update the visualization part of the Colonies. :return: """ for colony in self.colonies: colony.update_vis() def animate_food(self): """ Update the visualization part of the FoodGrid. :return: """ self.food.update_vis() def animate_ants(self): """ Update the visualization part of the Ants. """ for ant in self.schedule.agents: ant.update_vis() def animate_obstacles(self): """ Update the visualization part of the Obstacles. :return: """ for obstacle in self.obstacles: obstacle.update_vis() def grid_to_array(self, pos): """ Convert the position/indices on self.grid to imshow array. :param pos: tuple (int: x, int: y) :return: tuple (float: x, float: y) """ return pos[0] - 0.5, self.height - pos[1] - 1.5 def pheromone_threshold(self, threshold): """ Returns an array of the positions in the grid in which the pheromone levels are above the given threshold""" pher_above_thres = np.where(self.pheromones >= threshold) return list(zip(pher_above_thres[0],pher_above_thres[1])) def find_path(self, pher_above_thres): """ Returns the shortest paths from all the colonies to all the food sources. A path can only use the positions in the given array. Therefore, this function checks whether there is a possible path for a certain pheremone level. Essentially a breadth first search""" space_searched = False all_paths = [] food_sources = self.food.get_food_pos() # Search the paths for a colony to all food sources for colony in self.colonies: colony_paths = [] pos_list = {colony.pos} # Prooning possible_paths = [[colony.pos]] # Continue expanding search area until all food sources found # or until the entire space is searched while food_sources != [] and not space_searched: space_searched = True temp = [] for path in possible_paths: for neighbor in self.grid.get_neighborhood(include_center=False, radius=1, pos=path[-1], moore=self.moore): if neighbor in food_sources: food_path = copy(path) food_path.append(neighbor) colony_paths.append(food_path) food_sources.remove(neighbor) # Add epanded paths to the possible paths if neighbor in pher_above_thres and neighbor not in pos_list: space_searched = False temp_path = copy(path) temp_path.append(neighbor) temp.append(temp_path) pos_list.add(neighbor) possible_paths.remove(path) possible_paths += temp all_paths.append(colony_paths) return all_paths
class World(Model): def __init__(self, N, coop, width=100, height=100): self.num_agents = N self.grid = MultiGrid(width, height, False) self.schedule = RandomActivation(self) self.running = True self.population_center_x = np.random.randint( POP_MARGIN, self.grid.width - POP_MARGIN) self.population_center_y = np.random.randint( POP_MARGIN, self.grid.height - POP_MARGIN) self.num_energy_resources = RESERVE_SIZE self.ages = [] self.expected_ages = [] self.num_explorers = 0 self.num_exploiters = 0 self.datacollector = DataCollector(model_reporters={ "Num_Explorer": "num_explorers", "Num_Exploiter": "num_exploiters" }) self.bases = self.init_base() # add social agents to the world for i in range(1, self.num_agents + 1): if np.random.uniform() <= EXPLORER_RATIO: # create a new explorer a = Explorer("explorer_%d" % (i), self, coop) self.num_explorers += 1 else: # create a new exploiter a = Exploiter("exploiter_%d" % (i), self, coop) self.num_exploiters += 1 # keep society members confined at beginning x = np.random.randint(self.population_center_x - POP_SPREAD, self.population_center_x + POP_SPREAD) y = np.random.randint(self.population_center_y - POP_SPREAD, self.population_center_y + POP_SPREAD) self.grid.place_agent(a, (x, y)) # add agent to scheduler self.schedule.add(a) self.expected_ages.append(a.energy / a.living_cost) # add energy reserves to the world for i in range(self.num_energy_resources): a = EnergyResource("energy_reserve_%d" % (i), self) # decide location of energy reserve x = np.random.randint(0, self.grid.width) y = np.random.randint(0, self.grid.height) self.grid.place_agent(a, (x, y)) self.schedule.add(a) def init_base(self): pos = (self.population_center_x, self.population_center_y) return self.grid.get_neighborhood(pos, True, radius=POP_SPREAD) def step(self): self.datacollector.collect(self) self.schedule.step() if self.schedule.steps % NEW_ENERGY_STEPS == 0: num_dead = len(self.ages) remaining = self.num_agents - num_dead if np.random.uniform() < NEW_ENERGY_PROB and remaining > 10: self.num_energy_resources += 1 a = EnergyResource( "energy_reserve_%d" % (self.num_energy_resources), self) # decide location of energy reserve x = np.random.randint(0, self.grid.width) y = np.random.randint(0, self.grid.height) self.grid.place_agent(a, (x, y)) self.schedule.add(a)
class CancerModel(Model): def xprint(self, *args): logger.info("CANCER MODEL: " + " ".join(map(str, args))) def __init__(self, cure_agent_type, config): self.xprint("STARTING SIMULATION !!!") self.counter = 0 self.decay_number = 0 self.lifetime_counter = 0 self.metastasis_score = 0 eat_values = {CancerCell: 1, HealthyCell: -1, CancerStemCell: 5} assert (issubclass(cure_agent_type, CureAgent)) agent_memory_range = config["Agent"]["memory_limit"] agent_memory_type = config["Agent"]["memory_type"] radoznalost = config["Agent"]["curiosity"] turn_off_modifiers = config["Tumor"]["turn_off_modifiers"] CC_mutation_probability = config["Tumor"]["mutation_probability"] is_tumor_growing = config["Tumor"]["is_growing"] tumor_movement_stopping_range = config["Tumor"][ "movement_stopping_range"] steps_before_mutation = config["Model"]["steps_before_mutation"] self.SAMPLE_i = config["Model"]["sample_i"] self.cure_number = config["Model"]["NA_number"] self.probabilites_ranges = config["Agent"]["probabilities_limits"] self.modifier_fraction = config["Tumor"]["modifier_fraction"] self.mode = config["Simulation"]["mode"] fname = "xxx" if self.mode == "learning" else config["Simulation"][ "fname"] self.MUTATION_PERCENTAGE = config["Model"]["mutation_percentage"] tumor_growth_probability = config["Tumor"]["growth_probability"] cancer_cell_number = config["Model"]["CC_number"] #DATA COLLECTION self.datacollector = DataCollector( model_reporters={ "FitnessFunction": fitness_funkcija, "AverageSpeed": speed_avg, "AverageMemoryCapacity": memory_size_all_avg, "PopulationHeterogenity": population_heterogenity, "MutationAmount": mutation_amount, "CancerStemCell Number": CSC_number, "CSC Specialized Agents": CSC_specialized_agents, "CancerHeterogenity1": cancer_heterogenity_1, "CancerHeterogenity2": cancer_heterogenity_2, "CC_Number": CC_number, "HealthyCell_Number": HC_number, "MetastasisScore": "metastasis_score", "CancerSize": cancer_size, "TotalTumorResiliance": overall_cancer_resiliance, "TumorResiliance_Pi": cancer_resiliance_Pi, "TumorResiliance_Pd": cancer_resiliance_Pd, "TumorResiliance_Pa": cancer_resiliance_Pa, "TumorResiliance_Pk": cancer_resiliance_Pk, "TumorResiliance_Psd": cancer_resiliance_Psd, "NumberOfMutatedCells": mutated_CCs_num, "TumorCoverage": tumor_coverage, "AveragePd": average_Pd, "AveragePa": average_Pa, "AveragePi": average_Pi, "AveragePk": average_Pk, "AveragePsd": average_Psd, # "PopulationClusters":cluster_counts }, agent_reporters={ "Pi": get_Pi, "Pa": get_Pa, "Pd": get_Pd, "speed": get_speed, "Psd": get_Psd, "Pk": get_Pk, "memory_size": get_memory_size, "type": get_agent_type }) grid_size = math.ceil(math.sqrt(cancer_cell_number * 4)) self.STEPS_BEFORE_MUTATION = steps_before_mutation self.grid = MultiGrid(grid_size, grid_size, False) self.NUM_OF_INJECTION_POINTS = config["Model"]["injection_points"] # self.speeds = list(range(1,grid_size//2)) self.speeds = [ 1 ] #TODO ovo mozda bolje? ne znam da li treba u config fajlu? poss = self.generate_cancer_cell_positions(grid_size, cancer_cell_number) num_CSC = math.ceil(percentage(1, cancer_cell_number)) pos_CSC = [self.random.choice(poss) for i in range(num_CSC)] #ACTIVATE SIMULATION self.schedule = RandomActivation(self) self.running = True #PLACE CANCER CELLS for i in range(cancer_cell_number): pos = poss[i] has_modifiers = False if ((i < ( (1 - self.modifier_fraction) * cancer_cell_number)) or turn_off_modifiers is True ) else True #10 % will be with modifiers c = CancerStemCell("CANCER_STEM_CELL-"+str(uuid.uuid4()),self,value = eat_values[CancerStemCell],has_modifiers=has_modifiers,mutation_probability=CC_mutation_probability,grows=is_tumor_growing,growth_probability=tumor_growth_probability) \ if pos in pos_CSC else CancerCell("CANCER_CELL-"+str(uuid.uuid4()),self,value=eat_values[CancerCell],has_modifiers=has_modifiers,mutation_probability=CC_mutation_probability,grows=is_tumor_growing,growth_probability=tumor_growth_probability) self.grid.place_agent(c, pos) self.schedule.add(c) #PLACE HEALTHY CELLS for (i, (contents, x, y)) in enumerate(self.grid.coord_iter()): nbrs = self.grid.get_neighborhood([x, y], moore=True) second_nbrs = [] for nbr in nbrs: second_nbrs += self.grid.get_neighborhood(nbr, moore=True) nbrs = nbrs + second_nbrs nbr_contents = self.grid.get_cell_list_contents(nbrs) nbr_CCs = [ nbr for nbr in nbr_contents if isinstance(nbr, CancerCell) ] if not contents and len(nbr_CCs) == 0: c = HealthyCell(uuid.uuid4(), self, eat_values[HealthyCell]) self.grid.place_agent(c, (x, y)) self.schedule.add(c) if self.mode == "simulation": self.duplicate_mutate_or_kill = self.simulation_mode_function self.decay_probability = 0.04 #MAGIC NUMBER self.read_nanoagents_from_file( fname=fname, cure_agent_type=cure_agent_type, tumor_movement_stopping_range=tumor_movement_stopping_range, agent_memory_range=agent_memory_range, radoznalost=radoznalost) elif self.mode == "learning": self.decay_probability = 0 self.make_nanoagents_from_scratch(cure_agent_type, radoznalost, agent_memory_type, agent_memory_range, tumor_movement_stopping_range, grid_size) else: assert ("False") def get_random_positions_on_empty_cells(self): """Gets the N random currently empty positions on the grid""" #GETTING EMPTY POSITIONS (for placing nano agents) empty_cells = [(x, y) for (i, (contents, x, y)) in enumerate(self.grid.coord_iter()) if not contents] positions = [ self.random.choice(empty_cells) for i in range(self.NUM_OF_INJECTION_POINTS) ] self.xprint("The 5 random empty positions are %s" % positions) return positions def inject_nanoagents(self): """Injects the nanoagents, they will be activated slowly after""" from itertools import cycle positions = cycle(self.get_random_positions_on_empty_cells()) for a in self.agents: self.grid.place_agent(a, next(positions)) self.agents_iterator = iter(self.agents) def activate_next_batch_of_agents(self): agents_to_be_placed_at_each_steps = round(len(self.agents) / 14) #MAGIC NUMBER for i in range(agents_to_be_placed_at_each_steps): self.schedule.add(next(self.agents_iterator)) def read_nanoagents_from_file(self, fname, cure_agent_type, radoznalost, agent_memory_range, tumor_movement_stopping_range): import pandas as pd self.xprint("Reading nanoagents from file") df = pd.read_csv(fname) self.agents = [] for i, row in df.iterrows(): a = cure_agent_type( uuid.uuid4(), self, speeds=self.speeds, radoznalost=radoznalost, memory_type=row.memory_size, memory_range=agent_memory_range, tumor_movement_stopping_range=tumor_movement_stopping_range, probabilities_ranges=self.probabilites_ranges) a.Pi = row.Pi a.Pa = row.Pa a.Pd = row.Pd a.memory_size = row.memory_size a.memorija = FixSizeOrderedDict(max=row.memory_size) a.tumor_movement_stopping_rate = row.tumor_movement_stopping_rate self.agents.append(a) def make_nanoagents_from_scratch(self, cure_agent_type, radoznalost, agent_memory_type, agent_memory_range, tumor_movement_stopping_range, grid_size): from itertools import cycle self.xprint("Making nanoagents from scratch") positions = cycle(self.get_random_positions_on_empty_cells()) for i in range(self.cure_number): pos = next(positions) self.xprint(pos) a = cure_agent_type( uuid.uuid4(), self, speeds=self.speeds, radoznalost=radoznalost, memory_type=agent_memory_type, memory_range=agent_memory_range, tumor_movement_stopping_range=tumor_movement_stopping_range, probabilities_ranges=self.probabilites_ranges) self.grid.place_agent(a, pos) self.schedule.add(a) def simulation_mode_function(self): self.xprint("In simulation mode - not duplicating or mutating") return def generate_cancer_cell_positions(self, grid_size, cancer_cells_number): center = grid_size // 2 poss = [(center, center)] for pos in poss: poss += [ n for n in self.grid.get_neighborhood( pos, moore=True, include_center=False) if n not in poss ] if len(set(poss)) >= cancer_cells_number: break poss = list(set(poss)) return poss def duplicate_mutate_or_kill(self): if self.mode == "simulation": assert (False) koliko = math.ceil( percentage(self.MUTATION_PERCENTAGE, self.cure_number)) cureagents = [ c for c in self.schedule.agents if isinstance(c, CureAgent) ] sortirani = sorted(cureagents, key=lambda x: x.points, reverse=True) poslednji = sortirani[-koliko:] prvi = sortirani[:koliko] sredina = len(sortirani) // 2 pocetak_sredine = sredina - (koliko // 2) kraj_sredine = sredina + (koliko // 2) srednji = sortirani[pocetak_sredine:kraj_sredine] self.mutate_agents(srednji) assert (len(prvi) == len(poslednji)) self.remove_agents(poslednji) self.duplicate_agents(prvi) def mutate_agents(self, agents): self.xprint("Mutating middle agents") for a in agents: a.mutate() def remove_agents(self, agents): for a in agents: self.kill_cell(a) def duplicate_agents(self, agents): for a in agents: a_new = a.copy() self.grid.place_agent(a_new, (1, 1)) self.schedule.add(a_new) def kill_cell(self, cell): self.grid.remove_agent(cell) self.schedule.remove(cell) def detach_stem_cell(self, cell): self.metastasis_score += 1 self.kill_cell(cell) def kill_all_agents(self): agents = [a for a in self.schedule.agents if isinstance(a, CureAgent)] for a in agents: a.kill_self() def write_population_to_file(self, i): df = record_model_population(self) df.to_csv("./Populations/Population{}-step{}.csv".format( self.SAMPLE_i, i)) def step(self): self.datacollector.collect(self) if self.mode == "simulation": self.simulation_step() self.write_population_to_file(self.counter) self.schedule.step() self.counter += 1 self.lifetime_counter += 1 if self.counter % self.STEPS_BEFORE_MUTATION == 0: #ovde ga stavljamo da izbegnemo da na nultom koraku uradi to self.duplicate_mutate_or_kill() def simulation_step(self): LIFETIME_OF_NANOAGENTS = 80 REINJECTION_PERIOD = 100 if self.lifetime_counter > LIFETIME_OF_NANOAGENTS: self.kill_all_agents() # if self.counter%(LIFETIME_OF_NANOAGENTS+REINJECTION_PERIOD)==0: # #svakih 180 koraka se ubrizgavaju # self.inject_nanoagents() # self.lifetime_counter = 0 agents_at_each_step = round(self.cure_number / 14) for i in range(agents_at_each_step): try: self.schedule.add(next(self.agents_iterator)) except StopIteration: break agents = [a for a in self.schedule.agents if isinstance(a, CureAgent)] assert (len(agents) <= self.cure_number)
class World(Model): def __init__(self, N, coop, e_prob, width=100, height=100): self.num_agents = N self.grid = MultiGrid(width, height, False) self.schedule = RandomActivation(self) self.running = True self.population_center_x = np.random.randint(POP_MARGIN, self.grid.width - POP_MARGIN) self.population_center_y = np.random.randint(POP_MARGIN, self.grid.height - POP_MARGIN) self.num_energy_resources = RESERVE_SIZE self.num_explorers = 0 self.num_exploiters = 0 self.datacollector = DataCollector(model_reporters={"Num_Explorer": "num_explorers","Num_Exploiter": "num_exploiters"}) self.bases = self.init_base() self.ages = dict() self.memoryLens = dict() # This will store average memory length at death for agent self.expected_ages = [] self.member_tracker = [] self.energy_tracker = [] self.decay_rates = self.init_decay_rates() # add social agents to the world for i in range(1, self.num_agents + 1): if np.random.uniform() <= EXPLORER_RATIO: # create a new explorer a = Explorer("explorer_%d" %(i), self, coop) self.num_explorers += 1 else: # create a new exploiter a = Exploiter("exploiter_%d" %(i), self, coop, e_prob) self.num_exploiters += 1 # keep society members confined at beginning x = np.random.randint(self.population_center_x - POP_SPREAD, self.population_center_x + POP_SPREAD) y = np.random.randint(self.population_center_y - POP_SPREAD, self.population_center_y + POP_SPREAD) self.grid.place_agent(a, (x, y)) # add agent to scheduler self.schedule.add(a) self.expected_ages.append(a.energy / a.living_cost) # add energy reserves to the world for i in range(self.num_energy_resources): a = EnergyResource("energy_reserve_%d" %(i), self, self.decay_rates[i]) # decide location of energy reserve x = np.random.randint(0, self.grid.width) y = np.random.randint(0, self.grid.height) self.grid.place_agent(a, (x, y)) self.schedule.add(a) def init_base(self): pos = (self.population_center_x, self.population_center_y) return self.grid.get_neighborhood(pos, True, radius=POP_SPREAD) def init_decay_rates(self): decay_rates = list(np.random.uniform(-0.1, 0.02, self.num_energy_resources)) np.random.shuffle(decay_rates) return decay_rates def step(self): self.datacollector.collect(self) self.schedule.step() self.member_tracker.append((self.num_explorers, self.num_exploiters)) # keep track of total energy in world if self.schedule.time % 50 == 0: energies = [e.reserve for e in self.schedule.agents if isinstance(e, EnergyResource)] if len(energies) > 0: mean_energy = np.mean(energies) else: mean_energy = 0 self.energy_tracker.append(mean_energy) # change location of energy resources every 500 steps randomly # and change decay_rate to opposite every 100 steps if self.schedule.time % 50 == 0: for e in self.schedule.agents: if isinstance(e, EnergyResource) and np.random.uniform() < 0.1: # change location e.decay_rate *= -1 if self.schedule.time % 500 == 0: self.grid.remove_agent(e) x = np.random.randint(0, self.grid.width) y = np.random.randint(0, self.grid.height) self.grid.place_agent(e, (x, y))
class World(Model): def __init__(self, N, coop, e_prob, width=100, height=100): self.num_agents = N self.grid = MultiGrid(width, height, False) self.schedule = RandomActivation(self) self.running = True self.population_center_x = np.random.randint( POP_MARGIN, self.grid.width - POP_MARGIN) self.population_center_y = np.random.randint( POP_MARGIN, self.grid.height - POP_MARGIN) self.num_energy_resources = RESERVE_SIZE self.num_explorers = 0 self.num_exploiters = 0 self.datacollector = DataCollector(model_reporters={ "Num_Explorer": "num_explorers", "Num_Exploiter": "num_exploiters" }) self.bases = self.init_base() self.ages = [] self.expected_ages = [] self.member_tracker = [] self.energy_tracker = [] # add social agents to the world for i in range(1, self.num_agents + 1): if np.random.uniform() <= EXPLORER_RATIO: # create a new explorer a = Explorer("explorer_%d" % (i), self, coop) self.num_explorers += 1 else: # create a new exploiter a = Exploiter("exploiter_%d" % (i), self, coop, e_prob) self.num_exploiters += 1 # keep society members confined at beginning x = np.random.randint(self.population_center_x - POP_SPREAD, self.population_center_x + POP_SPREAD) y = np.random.randint(self.population_center_y - POP_SPREAD, self.population_center_y + POP_SPREAD) self.grid.place_agent(a, (x, y)) # add agent to scheduler self.schedule.add(a) self.expected_ages.append(a.energy / a.living_cost) # add energy reserves to the world for i in range(self.num_energy_resources): a = EnergyResource("energy_reserve_%d" % (i), self) # decide location of energy reserve x = np.random.randint(0, self.grid.width) y = np.random.randint(0, self.grid.height) self.grid.place_agent(a, (x, y)) self.schedule.add(a) def init_base(self): pos = (self.population_center_x, self.population_center_y) return self.grid.get_neighborhood(pos, True, radius=POP_SPREAD) def step(self): self.datacollector.collect(self) self.schedule.step() self.member_tracker.append((self.num_explorers, self.num_exploiters)) # keep track of total energy in world energies = [ e.reserve for e in self.schedule.agents if isinstance(e, EnergyResource) ] if len(energies) > 0: mean_energy = np.mean(energies) else: mean_energy = 0 self.energy_tracker.append(mean_energy) # adjust decay rates to keep mean energy balanced in the world if mean_energy <= MEAN_RESERVE - 5 * STDDEV_ENERGY: for e in self.schedule.agents: if isinstance(e, EnergyResource) and np.random.uniform() < 0.1: e.decay_rate -= DECAY_RATE_ADJUST elif mean_energy >= MEAN_RESERVE + 5 * STDDEV_RESERVE: for e in self.schedule.agents: if isinstance(e, EnergyResource) and np.random.uniform() < 0.1: e.decay_rate += DECAY_RATE_ADJUST # change location of energy resources every 100 steps randomly if self.schedule.time % 100 == 0: for e in self.schedule.agents: if isinstance(e, EnergyResource) and np.random.uniform() < 0.1: # change location self.grid.remove_agent(e) x = np.random.randint(0, self.grid.width) y = np.random.randint(0, self.grid.height) self.grid.place_agent(e, (x, y))
class PsyRTSGame(Model): # id generator to track run number in batch run data id_gen = itertools.count(1) height = 20 width = 20 verbose = False # Print-monitoring description = 'A model for simulating participants running the different experiments.' def __init__(self, height=20, width=20, visibility = False ,initial_competitors=0, initial_explorers=1, initial_predators=0 , impactTotalVisibility =.3 , impactPartialVisibility = .35, impactParticipants = .0, impactCompetitors= .0, impactPredators= .0 ): ''' Create a new PsyRTS model with the given parameters. Args initial_competitors: Number of units each participant knows initial_explorers: Number of sheep to start with initial_predators: Number of wolves to start with visibility : total or partial visibility ''' super().__init__() self.uid = next(self.id_gen) self.fps = 0 # Set parameters self.height = height self.width = width self.visibility = visibility self.initial_competitors = initial_competitors self.initial_explorers = initial_explorers self.initial_predators = initial_predators self.schedule = RandomActivationByBreed(self) self.grid = MultiGrid(self.height, self.width, torus=False) self.uncertainty = 0.0 self.resources= 0 self.resourcesParticipants =0 self.resourcesCompetitors = 0 self.visitedCells = 0 self.stepsExploring = 0 self.stepsExploiting = 0 #parameters model mu, sigma = impactTotalVisibility, 0.05 # mean and standard deviation tv = np.random.normal(mu, sigma) if tv < 0: tv = 0 # print( "Starting with tv " , tv) mu, sigma = impactPartialVisibility, 0.05 # mean and standard deviation pv = np.random.normal(mu, sigma) if pv < 0: pv = 0 #print("Starting with pv ", pv) self.impactTotalVisibility = tv self.impactPartialVisibility = pv self.impactParticipants = impactParticipants self.impactCompetitors = impactCompetitors self.impactPredators = impactPredators self.TotalCells = next_moves = self.grid.get_neighborhood( (10,10), True, True, 11) locationsResources = [(4,3) , (16,3), (3,10) , (10,10),(17,10) , (16,17),(4,17) ] locationCPCompetitor = (10, 3) locationCPParticipant = (10, 17) self.locationsExploitation =[] for loc in locationsResources:#resources self.locationsExploitation = self.locationsExploitation + self.grid.get_neighborhood(loc, True, True,1) #cfp self.locationsExploitation = self.locationsExploitation + self.grid.get_neighborhood(locationCPParticipant, True, True, 1) #print( "size grid exploiit " + str(len(self.locationsExploitation))) self.locationsExploration = list(set(self.TotalCells) - set(self.locationsExploitation)) #print("size grid explore " + str(len(self.locationsExploration))) locationsParticipants = [(10, 16), (13, 15), (7, 15), ( 8, 15), (12, 15) ] locationsCompetitors = [(10, 4), (13, 5), (7, 5), ( 8, 5), (12, 5) ] locationsPredators = [(10, 10), (13, 10), (7, 10), ( 8, 10), (12, 10) ] self.datacollector = DataCollector( model_reporters={ "Experiment_Synth": track_experiment, "Conditions": track_params, "Step": track_run, "Exploration": exploration , "Exploitation": exploitation, "ResourcesRatio": resourcesRatio, "ProportionEE": proportionEE, "MapExplored": mapExplored, }) #reporto a datos centralplaceparticipant = CentralPlace(self.next_id(), locationCPParticipant, self, True) self.grid.place_agent(centralplaceparticipant, locationCPParticipant) self.schedule.add(centralplaceparticipant) centralplacecompetitor = CentralPlace(self.next_id(), locationCPCompetitor, self, False) self.grid.place_agent(centralplacecompetitor, locationCPCompetitor) self.schedule.add(centralplacecompetitor) # Create competitor: for i in range(self.initial_competitors): sheep = Competitor(self.next_id(), locationsCompetitors[i], self, True, centralplacecompetitor) self.grid.place_agent(sheep, locationsCompetitors[i]) self.schedule.add(sheep) # Create explorers: for i in range(self.initial_explorers): sheep = Participant(self.next_id(), locationsParticipants[i], self, True, centralplaceparticipant) self.grid.place_agent(sheep, locationsParticipants[i]) self.schedule.add(sheep) # Create predators for i in range(self.initial_predators): wolf = Predator(self.next_id(), locationsPredators[i], self, True) self.grid.place_agent(wolf, locationsPredators[i]) self.schedule.add(wolf) for pa in locationsResources: # randrange gives you an integral value irand = randrange(1, 11) #irand = 4 #print("resource con valores {} ". format( irand) ) self.resources = self.resources + irand patch = Resources(self.next_id(), pa, self, irand) self.grid.place_agent(patch, pa) self.schedule.add(patch) for x in range(0,20): for y in range(0, 20): breadcrumb = BreadCrumb(self.next_id(), (x,y), self) self.grid.place_agent(breadcrumb, (x,y)) self.schedule.add(breadcrumb) self.running = True self.datacollector.collect(self) def updateUncertainty(self): # information que gana por conocer el ambiente #participantExploration = (number_visited(self, True) +number_visited(self, False))/400 participantExploration = mapExplored(self) uncertaintyVisibility = 0 # if self.model.visibility : # multitaskingFriction = (1 - self.model.impactParticipants ) ** self.model.initial_explorers # else: if self.visibility: uncertaintyVisibility = self.impactTotalVisibility self.uncertainty = uncertaintyVisibility else: uncertaintyVisibility = self.impactPartialVisibility self.uncertainty = uncertaintyVisibility* (1-participantExploration) if self.uncertainty <0 : self.uncertainty = 0 #print("explored map {} uncertainty in the environment {} ".format ( participantExploration, self.uncertainty )) def step(self): self.datacollector.collect(self) self.schedule.step() self.updateUncertainty() # collect data participantsAlive = self.schedule.get_breed_count(Participant) if participantsAlive <=0: print("Stop Participants dead") self.running = False if self.resourcesCompetitors +self.resourcesParticipants == self.resources: print("Stop No More Resources") self.running = False if self.schedule.steps>150: print("toomany steps") self.running = False def run_model(self, step_count=150): for i in range(step_count): self.step()