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()
class Kvecinos(Model): def __init__(self, height, width, initial_population, n_clases, k): super().__init__() self.height = height self.width = width self.initial_population = initial_population # N_class será el número de colores self.n_clases = n_clases self.k = k self.unique_id = 0 # Creación del planificador y del grid self.schedule = RandomActivation(self) self.grid = MultiGrid(self.width, self.height, torus=False) self.colors = { 0: "red", 1: "blue", 2: "green0", 3: "violet", 4: "cyan", 5: "orange" } self.clases = [] self.setup() self.running = True def setup(self): for agent, x, y in self.grid.coord_iter(): patch = Cell(self.unique_id, self, (x, y), "black") self.unique_id += 1 self.grid.place_agent(patch, (x, y)) self.schedule.add(patch) for i in range(self.initial_population): x = random.randint(0, self.width - 1) y = random.randint(0, self.height - 1) pos = (x, y) color = random.randint(0, self.n_clases - 1) cell = self.grid.get_cell_list_contents(pos)[0] self.clases.append(cell) self.clases[i].color = self.colors[color] individual = Individual(self.unique_id, self, pos, self.colors[color]) self.unique_id += 1 self.grid.place_agent(individual, pos) def step(self): self.schedule.step()
class ConveyModel(Model): """A model with some number of agents.""" def __init__(self, N, width, height): super().__init__() self.num_agents = N self.grid = MultiGrid(width, height, True) self.schedule = BaseScheduler(self) # Create agents for i in range(self.num_agents): a = ConwayAgent(i, self) # Add the agent to a random grid cell x = random.randrange(self.grid.width) y = random.randrange(self.grid.height) while(len(self.grid.get_cell_list_contents((x,y)))): x = random.randrange(self.grid.width) y = random.randrange(self.grid.height) self.grid.place_agent(a, (x, y)) self.schedule.add(a) self.i = i self.datacollector = DataCollector( agent_reporters={"State": lambda a: a.die}) def step(self): self.datacollector.collect(self) new_agents = [] for (x, y) in product(range(self.grid.width), range(self.grid.height)): ns = self.grid.iter_neighbors((x,y), True) neighbors = 0 for n in ns: if(n): neighbors += 1 if(self.grid[x][y]): # live cell if(neighbors < 2): # underpopulation list(self.grid[x][y])[0].die = 1 elif(neighbors > 3): # overpopulation list(self.grid[x][y])[0].die = 1 else: # dead cell if(neighbors == 3): new_agents.append((x, y)) for (x, y) in product(range(self.grid.width), range(self.grid.height)): if self.grid[x][y]: a = list(self.grid[x][y])[0] if a.die: self.grid.remove_agent(a) self.schedule.remove(a) for na in new_agents: self.i += 1 a = ConwayAgent(self.i, self) self.grid.place_agent(a, na) self.schedule.add(a)
class Neighborhood(Model): """A model of a neighborhood with some number of agents.""" def __init__(self, N=10, width=None, height=None): """ Neighborhood: a neighborhood containing people Parameters ---------- N: number of people in the neighborhood width: width of the (rectangular) neighborhood area height: height of the (rectangular) neighborhood area """ super().__init__() self.num_agents = N self.width = width or min(N, 100) self.height = height or min(N, 100) self.grid = MultiGrid(self.width, self.height, True) self.schedule = RandomActivation(self) # Create agents for i in range(self.num_agents): rand = random.random() infection = rand >= (N-N**.5)/N print(i, rand, (N-N**.5)/N) a = Person(i, self, level_of_infection=int(infection)) print(a, a.level_of_infection) self.schedule.add(a) # adding the agent to a random position in the neighborhood (x, y) = random.random() * self.width, random.random() * self.height self.grid.place_agent(a, (int(x), int(y))) def step(self): """Advance the model by one step.""" self.schedule.step() def get_neighbors(self, person, radius=1): """ get neighbors of person """ neighbor_objects = self.grid.get_cell_list_contents([person.pos]) return [*filter(lambda x: type(x) is Person and x is not person, neighbor_objects)] def move_agent(self, *args, **kwargs): return self.grid.move_agent(*args, **kwargs)
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 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 WolfSheep(Model): """ Wolf-Sheep Predation Model """ height = 20 width = 20 initial_sheep = 2 initial_wolves = 5 sheep_reproduce = 0.04 wolf_reproduce = 0.05 wolf_gain_from_food = 20 grass = False grass_regrowth_time = 5 sheep_gain_from_food = 4 verbose = False # Print-monitoring description = ( "A model for simulating wolf and sheep (predator-prey) ecosystem modelling." ) def __init__(self, height=20, width=20, initial_sheep=100, initial_wolves=50, sheep_reproduce=0.04, wolf_reproduce=0.05, wolf_gain_from_food=20, grass=False, grass_regrowth_time=30, sheep_gain_from_food=4): """ Create a new Wolf-Sheep model with the given parameters. Args: initial_sheep: Number of sheep to start with initial_wolves: Number of wolves to start with sheep_reproduce: Probability of each sheep reproducing each step wolf_reproduce: Probability of each wolf reproducing each step wolf_gain_from_food: Energy a wolf gains from eating a sheep grass: Whether to have the sheep eat grass for energy grass_regrowth_time: How long it takes for a grass patch to regrow once it is eaten sheep_gain_from_food: Energy sheep gain from grass, if enabled. """ super().__init__() # Set parameters self.height = height self.width = width self.initial_sheep = initial_sheep self.initial_wolves = initial_wolves self.sheep_reproduce = sheep_reproduce self.wolf_reproduce = wolf_reproduce self.wolf_gain_from_food = wolf_gain_from_food self.grass = grass self.grass_regrowth_time = grass_regrowth_time self.sheep_gain_from_food = sheep_gain_from_food self.schedule = RandomActivationByBreed(self) self.grid = MultiGrid(self.height, self.width, torus=True) self.datacollector = DataCollector({ "Wolves": lambda m: m.schedule.get_breed_count(Wolf), "Sheep": lambda m: m.schedule.get_breed_count(Sheep), }) # Create Shed x = self.random.randrange(self.width) y = self.random.randrange(self.height) shed = Shed(self.next_id(), (x, y), self) self.grid.place_agent(shed, (x, y)) self.schedule.add(shed) # Create water source while True: x = self.random.randrange(self.width) y = self.random.randrange(self.height) this_cell = self.grid.get_cell_list_contents([(x, y)]) cell = [obj for obj in this_cell if isinstance(obj, Shed)] if len(cell) == 0: break ws1 = WaterSource(self.next_id(), (x, y), self) self.grid.place_agent(ws1, (x, y)) self.schedule.add(ws1) while True: x = self.random.randrange(self.width) y = self.random.randrange(self.height) this_cell = self.grid.get_cell_list_contents([(x, y)]) cell = [obj for obj in this_cell if isinstance(obj, Shed)] if len(cell) == 0: break cell = [obj for obj in this_cell if isinstance(obj, WaterSource)] if len(cell) == 0: break ws2 = WaterSource(self.next_id(), (x, y), self) self.grid.place_agent(ws2, (x, y)) self.schedule.add(ws2) # Create grass patches if self.grass: for agent, x, y in self.grid.coord_iter(): this_cell = self.grid.get_cell_list_contents([(x, y)]) is_water = [ obj for obj in this_cell if isinstance(obj, WaterSource) ] is_shed = [obj for obj in this_cell if isinstance(obj, Shed)] if len(is_water) > 0 or len(is_shed) > 0: continue fully_grown = self.random.choice([True, False]) if fully_grown: countdown = self.grass_regrowth_time else: countdown = self.random.randrange(self.grass_regrowth_time) patch = GrassPatch(self.next_id(), (x, y), self, fully_grown, countdown) self.grid.place_agent(patch, (x, y)) self.schedule.add(patch) # Create sheep: for i in range(self.initial_sheep): x = self.random.randrange(self.width) y = self.random.randrange(self.height) energy = self.random.randrange(2 * self.sheep_gain_from_food) sheep = Sheep(self.next_id(), (x, y), self, True, energy) sheep.target = shed self.grid.place_agent(sheep, (x, y)) self.schedule.add(sheep) # Create wolves for i in range(self.initial_wolves): x = self.random.randrange(self.width) y = self.random.randrange(self.height) energy = self.random.randrange(2 * self.wolf_gain_from_food) wolf = Wolf(self.next_id(), (x, y), self, True, energy) if abs(ws1.pos[0] - x) + abs(ws1.pos[1] - y) < abs( ws2.pos[0] - x) + abs(ws2.pos[1] - y): wolf.target = ws1 else: wolf.target = ws2 self.grid.place_agent(wolf, (x, y)) self.schedule.add(wolf) self.running = True self.datacollector.collect(self) def step(self): self.schedule.step() # collect data self.datacollector.collect(self) if self.verbose: print([ self.schedule.time, self.schedule.get_breed_count(Wolf), self.schedule.get_breed_count(Sheep), ]) def run_model(self, step_count=200): if self.verbose: print("Initial number wolves: ", self.schedule.get_breed_count(Wolf)) print("Initial number sheep: ", self.schedule.get_breed_count(Sheep)) for i in range(step_count): self.step() if self.verbose: print("") print("Final number wolves: ", self.schedule.get_breed_count(Wolf)) print("Final number sheep: ", self.schedule.get_breed_count(Sheep))
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 CovidModel(Model): def size(filename): return Image.open(filename).size def __init__(self, filename, num_infec_agents=20, num_uninfec_agents=20, num_rec_agents=20, mask_efficacy=95, passing=True, steps_per_hour_slow=12, steps_per_hour_fast=1, hours_per_day=3, days=1, cleans_per_day=1): im = Image.open(filename) # open image file self.surfaces = [] self.surface_pos = [] self.entrances = [] self.entrance_pos = [] self.humans = [] self.filename = filename self.width, self.height = im.size # Get the width and height of the image to iterate over self.schedule = RandomActivation(self) self.grid = MultiGrid(width=self.width, height=self.height, torus=False) self.mask_efficacy = mask_efficacy / 100 self.passing = passing self.steps_per_hour_slow = steps_per_hour_slow self.steps_per_hour_fast = steps_per_hour_fast self.steps_per_hour = self.steps_per_hour_fast self.hours_per_day = hours_per_day self.cleans_per_day = cleans_per_day self.hours = 0 self.days = days self.datacollector = DataCollector( model_reporters={ "Uninfected": get_uninfected_agents, "Recovered": get_recovered_agents, "Infected": get_infected_agents, "Quarantined of Infected": get_quarantined_agents, "Average Distance": get_average_distance, "Average Nearest Distance": get_avg_min_distance, "Days": get_days, "Hours": get_hours, "Average R_0": get_average_r0 }, agent_reporters={ # "Uninfected": lambda x: x.infected == False and x.recovered == False, # "Infected": lambda x: x.infected == True, # "Recovered": (add later) }) convert(filename, self, self.surfaces, self.entrances) # convert environment, create position lists for surface in self.surfaces: self.surface_pos.append(surface.pos) for entrance in self.entrances: self.entrance_pos.append(entrance.pos) # THIS SHOULD BE NOTED THAT THIS WILL ADD ONE TO THE TOTAL NUMBER OF HUMANS # create professor prof_seat = self.surfaces[0] pos = prof_seat.pos self.surfaces.remove(prof_seat) prof = Faculty(new_id(), self, pos=pos, next_pos=pos, seat=prof_seat, infected=False, recovered=False, masked=True, arrived=True) self.grid.place_agent(prof, pos) self.schedule.add(prof) self.humans.append(prof) # # setup_agnet(ag_type) # Find random starting postion and seat for agent. Create new agent with these parameters. Update # agent's infection status based off of ag_type. Give agent random caution level and update agent accordingly # Place agent on grid and add to scheduler and list of humans. def setup_agent(ag_type): pos = random.choice(self.entrance_pos) # start agents at entrance seat = random.choice( self.surfaces) # get random goal postion for agent self.surfaces.remove(seat) # make goal position unique next_pos = seat.pos new_human = Student(new_id(), self, pos=pos, next_pos=next_pos, seat=seat) # create new Student agent if ag_type == "uninfec": new_human.infected, new_human.recovered = False, False # set state of agent elif ag_type == "infec": new_human.init_infect() # needs deliberate setup elif ag_type == "rec": new_human.infected, new_human.recovered = False, True new_human.caution_level = random.randint( 0, max_caution_level) # create agents of different caution levels if new_human.caution_level == 0: new_human.masked = False elif new_human.caution_level == 1: new_human.masked = True elif new_human.caution_level == 2: new_human.masked = True if random.random( ) < percent_immunocompromised: # create immunocomprimised agents new_human.immunocompromised = True else: new_human.immunocompromised = False self.grid.place_agent(new_human, pos) # place agent on grid self.schedule.add(new_human) # add agent to schedule self.humans.append(new_human) for agents in range(num_uninfec_agents): setup_agent("uninfec", ) for agents in range(num_infec_agents): setup_agent("infec", ) for agents in range(num_rec_agents): setup_agent("rec", ) self.running = True # # self.check_arrival(destination) # Check arrival of nonquarantined agents at given destination. def check_arrival(self, destination): for human in self.humans: if not human.quarantined: # only check agents at class if destination == "seats": if not human.arrived or human.pos not in self.surface_pos: return False elif destination == "exit": if not human.arrived or human.pos not in self.entrance_pos: return False return True # # self.check_agents() # Cautious agents check selves for symptoms and self quarantine if necessary. def check_agents(self): for human in self.humans: if human.infected and human.symptomatic and human.caution_level > 0 and not human.quarantined: # if cautious person and symptomatic quarantine human.quarantine() #print("quarantined " + str(human.unique_id) + " on step" + str(self.schedule.steps)) # # self.leave() # Update agent's next position to be exit. def leave(self): for human in self.humans: human.next_pos = random.choice(self.entrance_pos) # # self.clean_grid() # Iterate over surface and door cells and clean cells of virus. def clean_grid(self): for pos in self.surface_pos: for x in self.grid.get_cell_list_contents(pos): if isinstance(x, BaseEnvironment): x.clean() for pos in self.entrance_pos: for x in self.grid.get_cell_list_contents(pos): if isinstance(x, BaseEnvironment): x.clean() #print("cleaned") # # self.reset # Reset next postion of all agents to their seat. def reset(self): for human in self.humans: human.next_pos = human.seat.pos # # self.step() # Update steps_per_hour based off of agent arrival. Complete one class day. Move agents off grid, # clean grid, and self-quarantine agents if necessary. Stop simulation if all agents are recovered or uninfected. def step(self): # can we stop? if get_recovered_agents(self) + get_uninfected_agents(self) == len( self.humans): self.running = False if self.check_arrival( "seats"): # if all agents have arrived class has "started" self.passing = False if self.passing: self.steps_per_hour = self.steps_per_hour_slow else: self.steps_per_hour = self.steps_per_hour_fast if not self.passing: self.hours += 1 / self.steps_per_hour # add time to class hours if self.hours % self.hours_per_day < 0.001: # after a 3 hour class self.leave() # move agents off grid self.passing = True # passing period begins again if self.hours % (self.hours_per_day / self.cleans_per_day) < 0.001: self.clean_grid() if self.check_arrival("exit"): # if all agents have left self.check_agents() # agents check selves for symptoms self.clean_grid() # clean grid self.hours = 0 self.days += 1 # number of days of class increases self.reset() # update scheduled position #print("a(s): " + str(self.check_arrival("seats")) + " a(e): " + str(self.check_arrival("exit")) + ", s_p_h: " + str(self.steps_per_hour) + ", h: " + str(self.hours) + ", d: " + str(self.days) + ", s: " + str(self.schedule.steps)) self.schedule.step() self.datacollector.collect(self) def run_model(self): #print("Rt: " + self.run_time) for i in range(self.run_time): self.step()
class Intersection(Model): """ Here the model is initialized. The Generatedmap.txt is read in order to locate traffic lights and car spawns. Cars and traffic lights are spawned here. """ def __init__(self, spawnrate, tactic, offset, cycletime): # Variable parameters self.tactic = tactic # [ Offset, Proportional, Lookahead, GreenWave] self.spawnrate = spawnrate self.offset = offset self.slowmotionrate = 0.2 self.cycletime = cycletime # Value initializations self.emission = [0, 0, 0] # emission per step self.traveltime = [] self.averagetraveltime = 0 self.carID = 0 self.averageemission = [] # Reading roadmap and emission values self.emissionvalues = reademissionvalues() [ self.roadmap, self.spawns, self.lights, self.height, self.cellsperlane, self.intersections, self.streetlength, self.gridsize, ] = readroadmap() # Model and visualization parameters self.schedule = RandomActivation(self) self.width = self.height self.grid = MultiGrid(self.width, self.height, True) self.running = True # Initializing matrix which shows what cars in front of traffic lights go to what over traffic lights. self.tlightmatrix = np.empty((len(self.lights), len(self.lights))) self.tlightmatrix[:] = np.nan self.trafficlightlist = [] self.lightcombinations = [ ["SR", "SD", "SL", "WR"], ["ER", "ED", "EL", "SR"], ["NR", "ND", "NL", "ER"], ["WR", "WD", "WL", "NR"], ] # Data collection self.datacollector = DataCollector( model_reporters={ "tactic": "tactic", "Spawnrate": "spawnrate", "Offset": "offset", "Cycletime": "cycletime", "AverageTraveltime": "averagetraveltime", "Totalcars": lambda m: self.numberofcars(), "CO2": lambda m: self.getco2(), "NOx": lambda m: self.getnox(), "PM10": lambda m: self.getpm(), "AverageCO2": lambda m: self.getaverageco2(), "AverageNOx": lambda m: self.getaveragenox(), "AveragePM": lambda m: self.getaveragepm(), }, ) # Needed for green wave tactic self.mostcars = [] self.goesto = [] self.firstgreenintersection = -1 self.secondgreenintersection = -1 self.firstcombination = None self.secondcombination = None self.firstcycledone = 0 # Needed for lookahead tactic self.mostexpectedcars = [0, 0, 0] # cars,intersection,combination # results in list of lists with intersectionnumbers in the right place, e.g.: [[0, 1],[2,3]] # Needed for the offset tactic to know which lights to offset self.intersectionmatrix = [] lastnumber = 0 for i in range(int(math.sqrt(self.intersections))): tempmaptrix = [] for j in range(int(math.sqrt(self.intersections))): tempmaptrix.append(j + lastnumber) lastnumber = tempmaptrix[-1] + 1 self.intersectionmatrix.append(tempmaptrix) self.intersectionmatrix = np.array(self.intersectionmatrix) # Initialize information dictionary (which lights are suppesed to be green and how long they have been green for self.trafficlightinfo = {} for i in range(self.intersections): self.trafficlightinfo.update( {f"intersection{i}": {"Trafficlightinfo": {}, "Timeinfo": {}}} ) # Initializes traffic lights for i, light in enumerate(self.lights): self.trafficlightinfo[f"intersection{light[1][3]}"]["Trafficlightinfo"][ f"{light[1][1:3]}" ] = i self.trafficlightinfo[f"intersection{light[1][3]}"]["Timeinfo"].update( { "Currentgreen": -1, "Currenttimegreen": 0, "Maxtimegreen": 0, "Allred": 1, } ) intersectionnumber = int(light[1][3]) intersectiony = np.where(self.intersectionmatrix == intersectionnumber)[0] intersectionx = np.where(self.intersectionmatrix == intersectionnumber)[1] direction = light[1][1] lane = light[1][2] location = light[0] xlocation = int(location[0]) ylocation = self.height - 1 - int(location[1]) trafficlight = TrafficLightAgent( f"{xlocation},{ylocation},{light[1][1:3]}", self, "red", direction, lane, i, intersectionnumber, self.tactic, self.offset, [intersectionx, intersectiony], self.cycletime, ) self.trafficlightlist.append([light[1], i]) self.schedule.add(trafficlight) self.grid.place_agent(trafficlight, (xlocation, ylocation)) self.tlightmatrix = lightconnection( self.tlightmatrix, self.trafficlightlist, self.intersections ) # Place legend self.grid.place_agent(LegendCarIcon("Caricon", self), (65, 68)) self.grid.place_agent(LegendGreenTlightIcon("GreenTlighticon", self), (65, 69)) self.grid.place_agent(LegendRedTlightIcon("RedTlighticon", self), (65, 70)) # Get emission values def getco2(self): return self.emission[0] def getnox(self): return self.emission[1] def getpm(self): return self.emission[2] def getaveragetraveltime(self): return self.averagetraveltime def getaverageco2(self): totalco2 = 0 if len(self.averageemission) > 0: for i, emissions in enumerate(self.averageemission): totalco2 += emissions[0] return totalco2 / len(self.averageemission) else: return 0 def getaveragenox(self): totalnox = 0 if len(self.averageemission) > 0: for i, emissions in enumerate(self.averageemission): totalnox += emissions[1] return totalnox / len(self.averageemission) else: return 0 def getaveragepm(self): totalpm = 0 if len(self.averageemission) > 0: for i, emissions in enumerate(self.averageemission): totalpm += emissions[2] return totalpm / len(self.averageemission) else: return 0 def numberofcars(self): return len(self.schedule.agents) - 12 * self.intersections def step(self): """ Step function that will randomly place cars based on the spawn chance and will visit all the agents to perform their step function. """ # Spawn cars for spawn in self.spawns: location = spawn[0] cell_contents = self.grid.get_cell_list_contents([location]) if ( not cell_contents and random.randint(0, int(100 / self.slowmotionrate)) < self.spawnrate ): location = spawn[0] xlocation = int(location[0]) ylocation = self.height - 1 - int(location[1]) direction = spawn[1][1] lane = spawn[1][2] car = CarAgent( f"car{self.carID}", self, direction, lane, [xlocation, ylocation] ) self.carID += 1 self.schedule.add(car) self.grid.place_agent(car, (xlocation, ylocation)) # Clear all previous step's emission and travel time if len(self.traveltime) > 0: self.averagetraveltime = sum(self.traveltime) / len(self.traveltime) # For the greenwave tactic if ( self.tactic == "GreenWave" and len(self.schedule.agents) > 12 * self.intersections and ((self.schedule.steps % (self.cycletime * 2)) == 0) ): self.firstcycledone = 0 self.mostcars = np.argmax(np.nansum(self.tlightmatrix, axis=1)) if self.mostcars: self.goesto = np.where(~np.isnan(self.tlightmatrix[self.mostcars])) self.firstgreenintersection = self.lights[self.mostcars][1][3] self.secondgreenintersection = self.lights[self.goesto[0][0]][1][3] # Determines the direction of traffic lights firstdirection = self.schedule.agents[int(self.mostcars)].direction seconddirection = self.schedule.agents[self.goesto[0][0]].direction # Determines combinations of traffic lights that can stay green for i, combination in enumerate(self.lightcombinations): if firstdirection + "D" in combination: self.firstcombination = self.lightcombinations[i] if seconddirection + "D" in combination: self.secondcombination = self.lightcombinations[i] # If 1st part of green wave is over (so 1 cycle has been done) if not ((self.schedule.steps % (self.cycletime * 2)) == 0): self.firstcycledone = 1 # For the proportional tactic if ( self.tactic == "Proportional" and len(self.schedule.agents) > 12 * self.intersections ): for i in range(self.intersections): currenttimegreen = self.trafficlightinfo[f"intersection{i}"][ "Timeinfo" ]["Currenttimegreen"] maxgreentime = self.trafficlightinfo[f"intersection{i}"]["Timeinfo"][ "Maxtimegreen" ] self.trafficlightinfo[f"intersection{i}"]["Timeinfo"][ "Currenttimegreen" ] = (currenttimegreen + 1) if currenttimegreen > maxgreentime + 6: carsinfront = np.nansum(self.tlightmatrix, axis=1) totalcars = [0, 0, 0, 0] for key in self.trafficlightinfo[f"intersection{i}"][ "Trafficlightinfo" ].keys(): trafficlight = int( self.trafficlightinfo[f"intersection{i}"][ "Trafficlightinfo" ][key] ) cars = carsinfront[trafficlight] for j, combi in enumerate(self.lightcombinations): if key in combi: totalcars[j] = totalcars[j] + cars # No cars? pick regular timeschedule if sum(totalcars) == 0: totalcars = [1, 1, 1, 1] self.trafficlightinfo[f"intersection{i}"]["Timeinfo"][ "Currentgreen" ] = totalcars.index(max(totalcars)) self.trafficlightinfo[f"intersection{i}"]["Timeinfo"][ "Maxtimegreen" ] = (max(totalcars) / (sum(totalcars) / 4) * self.cycletime) self.trafficlightinfo[f"intersection{i}"]["Timeinfo"][ "Currenttimegreen" ] = 0 if currenttimegreen == maxgreentime: self.trafficlightinfo[f"intersection{i}"]["Timeinfo"][ "Currentgreen" ] = -1 # For the lookahead tactic if ( self.tactic == "Lookahead" and len(self.schedule.agents) > 12 * self.intersections ): self.mostexpectedcars = [0, 0, 0] for i in range(self.intersections): currenttimegreen = self.trafficlightinfo[f"intersection{i}"][ "Timeinfo" ]["Currenttimegreen"] maxgreentime = self.trafficlightinfo[f"intersection{i}"]["Timeinfo"][ "Maxtimegreen" ] self.trafficlightinfo[f"intersection{i}"]["Timeinfo"][ "Currenttimegreen" ] = (currenttimegreen + 1) if currenttimegreen > maxgreentime + 6: self.trafficlightinfo[f"intersection{i}"]["Timeinfo"]["Allred"] = 0 carsexpected = np.nansum(self.tlightmatrix, axis=0) carsinfront = np.nansum(self.tlightmatrix, axis=1) totalcars = [0, 0, 0, 0] # For every direction + lane in intersection for key in self.trafficlightinfo[f"intersection{i}"][ "Trafficlightinfo" ].keys(): trafficlight = int( self.trafficlightinfo[f"intersection{i}"][ "Trafficlightinfo" ][key] ) cars = carsinfront[trafficlight] # For every lightcombination for j, combi in enumerate(self.lightcombinations): if key in combi: totalcars[j] = ( totalcars[j] + cars + carsexpected[trafficlight] ) if totalcars[j] > self.mostexpectedcars[0]: self.mostexpectedcars[0] = totalcars[j] self.mostexpectedcars[1] = i self.mostexpectedcars[2] = j # Reset timers self.trafficlightinfo[f"intersection{i}"]["Timeinfo"][ "Currentgreen" ] = ( self.trafficlightinfo[f"intersection{i}"]["Timeinfo"][ "Currentgreen" ] + 1 ) % 4 self.trafficlightinfo[f"intersection{i}"]["Timeinfo"][ "Maxtimegreen" ] = self.cycletime self.trafficlightinfo[f"intersection{i}"]["Timeinfo"][ "Currenttimegreen" ] = 0 if currenttimegreen == maxgreentime: self.trafficlightinfo[f"intersection{i}"]["Timeinfo"]["Allred"] = 1 if self.mostexpectedcars[0] != 0: # Change green light information of intersection with most expected cars self.trafficlightinfo[f"intersection{self.mostexpectedcars[1]}"][ "Timeinfo" ]["Currentgreen"] = self.mostexpectedcars[2] # Get trafficlightnumbers of ligths where most cars are expected mostcars = 0 mostcarslight = None comingfrom = np.nansum(self.tlightmatrix, axis=1) for direction in self.lightcombinations[self.mostexpectedcars[2]]: greenlight = int( self.trafficlightinfo[ f"intersection{self.mostexpectedcars[1]}" ]["Trafficlightinfo"][direction] ) # Where the cars to those lights come from. lightscomingfrom = np.argwhere( ~np.isnan(self.tlightmatrix[:, greenlight]) ) for light in lightscomingfrom: if light: light = light[0] carsinfront = np.sum(comingfrom[light]) if carsinfront > mostcars: mostcars = int(carsinfront) mostcarslight = light # Find intersection + directon of this light and change this intersection's green light information if mostcars != 0: intersection = int(self.lights[mostcarslight][1][3]) direction = self.lights[mostcarslight][1][1:3] for k, directs in enumerate(self.lightcombinations): if direction in directs[0:3]: self.trafficlightinfo[f"intersection{intersection}"][ "Timeinfo" ]["Currentgreen"] = k pass self.datacollector.collect(self) self.emission = [0, 0, 0] self.schedule.step()
class AntModel(Model): def __init__(self, num_ln, num_fj, num_mk_col, num_ft_col, width, height): """ :param num_ln: Number of L. Niger agents :param num_fj: Number of F. Japonica agents :param num_mk_col: Number of M. Kuricola colonies :param num_ft_col: Number of F. Tropicalis colonies :param width: Width of the model grid :param height: Height of the model grid """ super().__init__() self.num_ln = num_ln self.num_fj = num_fj self.num_mk_col = num_mk_col self.num_ft_col = num_ft_col self.grid = MultiGrid(width, height, True) self.schedule = RandomActivation(self) self.running = True for h in range(self.num_fj): ant = FJaponica(uuid4(), self) self.schedule.add(ant) self.grid.place_agent(ant, self.grid.find_empty()) for j in range(self.num_mk_col): colony = MKuricolaColony(uuid4(), self) self.schedule.add(colony) self.grid.place_agent(colony, self.grid.find_empty()) for k in range(self.num_ft_col): colony = FTropicalisColony(uuid4(), self) self.schedule.add(colony) self.grid.place_agent(colony, self.grid.find_empty()) for i in range(self.num_ln): ant = LNiger(uuid4(), self) self.schedule.add(ant) self.grid.place_agent(ant, self.grid.find_empty()) ant._init_post_place() self.data_collector = DataCollector( model_reporters={}, agent_reporters={"states": ant_state_collector}) self.weights_dict = json.load(open("newout.json", "r")) def drop_pheromone(self, location): """ Drops a LNPheromone object at the given location if one does not already exist. If one does already exist, 1 is added to the existing object's 'tracks' field. :param location: An (x, y) tuple detailing the location to drop the pheromone. :return: None """ if not self.is_pheromone_in_cell(location): self.grid.place_agent(LNPheromone(uuid4(), self), location) else: self.get_pheromone_in_cell(location).tracks += 1 def is_pheromone_in_cell(self, location): """ Determines if a pheromone already exists in a given cell. :param location: The location to check. :return: boolean """ return True in [ type(x) == LNPheromone for x in self.grid.get_cell_list_contents(location) ] def is_ant_in_cell(self, location): """ Determines whether an ant exists in a given cell. :param location: The location to check. :return: boolean """ return True in [ isinstance(x, Ant) for x in self.grid.get_cell_list_contents(location) ] def is_colony_in_cell(self, location): """ Determines whether an aphid colony exists in a given cell. :param location: The location to check. :return: boolean """ return True in [ type(x) == MKuricolaColony or type(x) == FTropicalisColony for x in self.grid.get_cell_list_contents(location) ] def get_pheromone_in_cell(self, location): """ Returns a LNPheromone object from a cell. ASsumes the cell has already been proven to have a pheromone object in it. :param location: The cell location to check. :return: The LNPheromone object within the cell. """ in_cell_pheromone = None for i in self.grid.get_cell_list_contents(location): if type(i) == LNPheromone: in_cell_pheromone = i return in_cell_pheromone def get_closest_agent_of_type(self, agent, agent_type): """ Gets the closest agent (besides self) of type agent_type. Returns -1 if it cannot find one. :param agent: The agent to find the closest agent_type to. :param agent_type: The type of the agent we are looking for. :return: """ for radius in range(1, self.grid.width): for neighbor in self.grid.get_neighbors(pos=agent.pos, moore=True, include_center=False, radius=radius): if isinstance(neighbor, agent_type): return neighbor return -1 def get_closest_colony(self, agent): """ Gets the closest colony to an agent. If an agent is of type colony, it returns itself. :param agent: The agent to find the closest colony to. :return: The closest colony or -1 if not found. """ return self.get_closest_agent_of_type(agent, Colony) @staticmethod def distance_between_cells(location_a, location_b): """ Calculates the distance between two cells on the grid. :param location_a: First cell location. :param location_b: Second cell location. :return: """ return np.sqrt((location_a[0] - location_b[0])**2 + (location_a[1] - location_a[1])**2) def get_nearest_cell_to_goal(self, goal_cell, possible_cells): """ Returns the cell from a list of possible cells which is closest to the end location. :param goal_cell: The goal cell of the agent :param possible_cells: Candidate cells. :return: The location of the closest cell to the goal cell. """ closest_neighbor_index = -1 closest_neighbor_distance = np.inf for i in range(0, len(possible_cells)): dist = self.distance_between_cells(possible_cells[i], goal_cell) if dist < closest_neighbor_distance: closest_neighbor_index = i closest_neighbor_distance = dist return possible_cells[closest_neighbor_index] def get_number_of_agents_in_radius(self, location, radius, agent_type): """ Returns the number of agents of type agent_type within a radius (not including center) of location. :param location: Location to search around. :param radius: Radius to search. :param agent_type: Type of agent to search for. :return: int """ total_agents = 0 for neighbor in self.grid.get_neighbors(pos=location, moore=True, include_center=False, radius=radius): if isinstance(neighbor, agent_type): total_agents += 1 return total_agents def get_all_of_agent_type(self, agent_type): """ Returns all instances of agents of type agent_type in the Grid. :param agent_type: The type of agent to find. :return: A list of agent objects. """ return [ x for x in self.grid.get_neighbors(pos=(0, 0), moore=True, include_center=True, radius=self.grid.width) if isinstance(x, agent_type) ] def step(self): """ A method called every step that occurs :return: None """ self.data_collector.collect(self) self.schedule.step()
class SOMENModel(Model): def __init__(self, width, height): # Model attributes initialization self.workers_number = 10 self.agents = [] self.workers = [] self.average_stress = 0 self.running = True #SOBA configuration.settings.init() configuration.defineOccupancy.init() configuration.defineMap.init() self.clock = Time() #Vars of control self.num_occupants = 0 self.day = self.clock.day self.NStep = 0 self.placeByStateByTypeAgent = {} self.agentsWorkingByStep = [] self.agentsIn = 0 # Schedule self.schedule = BaseScheduler(self) self.grid = MultiGrid(width, height, False) #Create the map self.createRooms() self.setMap(width, height) self.createDoors() self.createWalls() #Create agents self.setAgents() # Create timer agent self.timer = TimeAgent(len(self.agents), self) self.schedule.add(self.timer) self.agents.append(self.timer) # Create sensor agent self.sensor = SensorAgent(len(self.agents), self) self.schedule.add(self.sensor) self.agents.append(self.sensor) ''' # Create workers agents for i in range(self.workers_number): worker = WorkerAgent(i+len(self.agents), self) self.schedule.add(worker) self.workers.append(worker) ''' # Create data collectors self.model_collector = DataCollector( model_reporters={"Average Stress": lambda a: a.average_stress}) self.worker_collector = WorkerCollector( agent_reporters={ "Stress": lambda a: a.stress, "Event Stress": lambda a: a.event_stress, "Time Pressure": lambda a: a.time_pressure, "Effective Fatigue": lambda a: a.effective_fatigue, "Productivity": lambda a: a.productivity, 'Emails read': lambda a: a.emails_read, 'Pending tasks': lambda a: len(a.tasks), 'Overtime hours': lambda a: a.overtime_hours, 'Rest at work hours': lambda a: a.rest_at_work_hours, 'Tasks completed': lambda a: a.tasks_completed }) self.sensor_collector = SensorCollector( agent_reporters={ "Temperature": lambda a: a.wbgt, "Noise": lambda a: a.noise, "Luminosity": lambda a: a.luminosity }) self.time_collector = TimeCollector(agent_reporters={ "Day": lambda a: a.days, "Time": lambda a: a.clock }) #SOBA def setAgents(self): self.lights = [] id_light = 0 for room in self.rooms: if room.typeRoom != 'out' and room.light == False: light = Light(id_light, self, room) self.lights.append(light) id_light = id_light + 1 room.light = light for room2 in self.rooms: if room.name.split(r".")[0] == room2.name.split(r".")[0]: room2.light = light # Height and Width height = self.grid.height width = self.grid.width # CREATE AGENTS self.agents = [] # Create occupants for n_type_occupants in configuration.defineOccupancy.occupancy_json: self.placeByStateByTypeAgent[ n_type_occupants['type']] = n_type_occupants['states'] n_agents = n_type_occupants['N'] for i in range(0, n_agents): a = WorkerAgent(i + len(self.agents) + 1000, self, n_type_occupants) self.workers.append(a) self.schedule.add(a) self.grid.place_agent(a, self.outBuilding.pos) self.pushAgentRoom(a, self.outBuilding.pos) self.num_occupants = self.num_occupants + 1 self.schedule.add(self.clock) for light in self.lights: self.schedule.add(light) def isConected(self, pos): nextRoom = False for room in self.rooms: if room.pos == pos: nextRoom = room if nextRoom == False: return False for x in range(0, width): for y in range(0, height): self.pos_out_of_map.append(x, y) for room in self.rooms: self.pos_out_of_map.remove(room.pos) def createRooms(self): rooms = configuration.defineMap.rooms_json self.rooms = [] for room in rooms: newRoom = 0 name = room['name'] typeRoom = room['type'] if typeRoom != 'out': conectedTo = room.get('conectedTo') entrance = room.get('entrance') measures = room['measures'] dx = measures['dx'] dy = measures['dy'] newRoom = Room(name, typeRoom, conectedTo, dx, dy) newRoom.entrance = entrance else: newRoom = Room( name, typeRoom, None, 0, 0, ) self.outBuilding = newRoom self.rooms.append(newRoom) for room1 in self.rooms: if room1.conectedTo is not None: for otherRooms in list(room1.conectedTo.values()): for room2 in self.rooms: if room2.name == otherRooms: room1.roomsConected.append(room2) room2.roomsConected.append(room1) for room in self.rooms: room.roomsConected = list(set(room.roomsConected)) sameRoom = {} for room in self.rooms: if sameRoom.get(room.name.split(r".")[0]) is None: sameRoom[room.name.split(r".")[0]] = 1 else: sameRoom[room.name.split(r".") [0]] = sameRoom[room.name.split(r".")[0]] + 1 def setMap(self, width, height): rooms_noPos = self.rooms rooms_using = [] rooms_used = [] for room in self.rooms: if room.entrance is not None: room.pos = (int(1), 1) rooms_using.append(room) rooms_used.append(room) rooms_noPos.remove(room) break while len(rooms_noPos) > 0: for roomC in rooms_using: xc, yc = roomC.pos rooms_conected = roomC.conectedTo rooms_using.remove(roomC) if rooms_conected is not None: orientations = list(rooms_conected.keys()) for orientation in orientations: if orientation == 'R': for room in rooms_noPos: if room.name == rooms_conected['R']: room.pos = (int(xc + 1), yc) rooms_noPos.remove(room) rooms_used.append(room) rooms_using.append(room) elif orientation == 'U': for room in rooms_noPos: if room.name == rooms_conected['U']: room.pos = (xc, int(yc + 1)) rooms_noPos.remove(room) rooms_used.append(room) rooms_using.append(room) elif orientation == 'D': for room in rooms_noPos: if room.name == rooms_conected['D']: room.pos = (xc, int(yc - 1)) rooms_noPos.remove(room) rooms_used.append(room) rooms_using.append(room) elif orientation == 'L': for room in rooms_noPos: if room.name == rooms_conected['L']: room.pos = (int(xc - 1), yc) rooms_noPos.remove(room) rooms_used.append(room) rooms_using.append(room) else: pass self.rooms = rooms_used def createDoors(self): self.doors = [] for roomC in self.rooms: roomsConected = roomC.roomsConected for room in roomsConected: door_created = False same_corridor = False if room.name != roomC.name: for door in self.doors: if (door.room1.name == roomC.name and door.room2.name == room.name) or ( door.room2.name == roomC.name and door.room1.name == room.name): door_created = True if room.name.split(r".")[0] == roomC.name.split( r".")[0]: same_corridor = True if door_created == False and same_corridor == False: d = Door(roomC, room) self.doors.append(d) room.doors.append(d) roomC.doors.append(d) def createWalls(self): for room in self.rooms: if room.typeRoom != 'out': walls = [] xr, yr = room.pos roomA = self.getRoom((xr, yr + 1)) if roomA != False: if roomA.name.split(r".")[0] == room.name.split(r".")[0]: pass else: wall = Wall(room, roomA) walls.append(wall) else: wall = Wall(room) walls.append(wall) roomB = self.getRoom((xr, yr - 1)) if roomB != False: if roomB.name.split(r".")[0] == room.name.split(r".")[0]: pass else: wall = Wall(room, roomB) walls.append(wall) else: wall = Wall(room) walls.append(wall) roomC = self.getRoom((xr + 1, yr)) if roomC != False: if roomC.name.split(r".")[0] == room.name.split(r".")[0]: pass else: wall = Wall(room, roomC) walls.append(wall) else: wall = Wall(room) walls.append(wall) roomD = self.getRoom((xr - 1, yr)) if roomD != False: if roomD.name.split(r".")[0] == room.name.split(r".")[0]: pass else: wall = Wall(room, roomD) walls.append(wall) else: wall = Wall(room) walls.append(wall) room.walls = walls def getPosState(self, name, typeA): placeByStateByTypeAgent = self.placeByStateByTypeAgent n = 0 for state in self.placeByStateByTypeAgent[typeA]: if state.get('name') == name: pos1 = state.get('position') if isinstance(pos1, dict): for k, v in pos1.items(): if v > 0: placeByStateByTypeAgent[typeA][n]['position'][ k] = v - 1 self.placeByStateByTypeAgent = placeByStateByTypeAgent return k return list(pos1.keys())[-1] else: return pos1 n = n + 1 def thereIsClosedDoor(self, beforePos, nextPos): oldRoom = False newRoom = False for room in rooms: if room.pos == beforePos: oldRoom = room if room.pos == nextPos: newRoom = room for door in self.doors: if (door.room1.name == oldRoom.name and door.room2.name == newRoom.name) or (door.room2.name == oldRoom.name and door.room1.name == newRoom.name): if door.state == False: return True return False def thereIsOccupant(self, pos): possible_occupant = self.grid.get_cell_list_contents([pos]) if (len(possible_occupant) > 0): for occupant in possible_occupant: if isinstance(occupant, WorkerAgent): return True return False def ThereIsOtherOccupantInRoom(self, room, agent): for roomAux in self.rooms: possible_occupant = [] if roomAux.name.split(r".")[0] == room.name.split(r".")[0]: possible_occupant = self.grid.get_cell_list_contents( roomAux.pos) for occupant in possible_occupant: if isinstance(occupant, WorkerAgent) and occupant != agent: return True return False def ThereIsSomeOccupantInRoom(self, room): for roomAux in self.rooms: possible_occupant = [] if roomAux.name.split(r".")[0] == room.name.split(r".")[0]: possible_occupant = self.grid.get_cell_list_contents( roomAux.pos) for occupant in possible_occupant: if isinstance(occupant, WorkerAgent): return True return False def thereIsOccupantInRoom(self, room, agent): for roomAux in self.rooms: possible_occupant = [] if roomAux.name.split(r".")[0] == room.name.split(r".")[0]: possible_occupant = self.grid.get_cell_list_contents( roomAux.pos) for occupant in possible_occupant: if isinstance(occupant, WorkerAgent) and occupant == agent: return True return False def getRoom(self, pos): for room in self.rooms: if room.pos == pos: return room return False def pushAgentRoom(self, agent, pos): room = self.getRoom(pos) room.agentsInRoom.append(agent) def popAgentRoom(self, agent, pos): room = self.getRoom(pos) room.agentsInRoom.remove(agent) def openDoor(self, agent, room1, room2): for door in self.doors: if ((door.room1 == room1 and door.room2 == room2) or (door.room1 == room2 and door.room2 == room1)): door.state = False def closeDoor(self, agent, room1, room2): numb = random.randint(0, 10) for door in self.doors: if ((door.room1 == room1 and door.room2 == room2) or (door.room1 == room2 and door.room2 == room1)): if 7 >= numb: door.state = False else: door.state = True def getMatrix(self, agent): new_matrix = configuration.defineOccupancy.returnMatrix( agent, self.clock.clock) agent.markov_matrix = new_matrix def getTimeInState(self, agent): matrix_time_in_state = configuration.defineOccupancy.getTimeInState( agent, self.clock.clock) return matrix_time_in_state def sobaStep(self): aw = 0 for agent in self.agents: if agent.state == 'working in my workplace': aw = aw + 1 self.agentsWorkingByStep.append(aw) self.schedule.step() if (self.clock.day > self.day): self.day = self.day + 1 self.NStep = self.NStep + 1 if self.clock.clock > 17: model.ramenScript.generateJSON() while (True): pass def step(self): self.sobaStep() if self.timer.new_day: self.addTasks() self.createEmailsDistribution() self.average_stress = sum( worker.stress for worker in self.workers) / len(self.workers) if self.timer.new_hour: self.worker_collector.collect(self) self.sensor_collector.collect(self) self.time_collector.collect(self) self.model_collector.collect(self) def addTasks(self): ''' Add tasks to workers ''' # Get task distribution params mu, sigma = workload_settings.tasks_arriving_distribution_params tasks_arriving_distribution = np.random.normal( mu, sigma, self.workers_number * 10) for worker in self.workers: # Get number of tasks to add tasks_number = math.floor( abs(tasks_arriving_distribution[random.randint( 0, 10 * self.workers_number - 1)])) worker.tasks_completed = 0 # Add tasks for i in range(tasks_number): worker.addTask(Task()) worker.calculateAverageDailyTasks(self.timer.days) worker.calculateEventStress(tasks_number) # worker.printTasksNumber() # worker.printAverageDailyTasks() # worker.printEventStress() def createEmailsDistribution(self): '''Create emails distribution''' # Get emails distribution mu, sigma = email_settings.emails_read_distribution_params emails_read_distribution = np.random.normal(mu, sigma, self.workers_number * 10) for worker in self.workers: emails_received = math.floor( abs(emails_read_distribution[random.randint( 0, 10 * self.workers_number - 1)])) emails_distribution_over_time = np.random.choice( [0, 1], size=(480, ), p=[(480 - emails_received) / 480, emails_received / 480]) worker.emails_read = 0 worker.email_read_distribution_over_time = emails_distribution_over_time
class Map(Model): def __init__(self, ncells, obstacles_dist, ninjured): # used in server start self.running = True self.ncells = ncells self.obstacles_dist = obstacles_dist self.ninjured = ninjured # grid and schedule representation self.grid = MultiGrid(ncells + 2, ncells + 2, torus = False) self.schedule = RandomActivation(self) # unique counter for agents self.agent_counter = 1 out_grid = {} out_grid["Cell"] = {} out_grid["Injured"] = {} # place a cell agent for store data and visualization on each cell of the grid 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: difficulty = "inf" explored = -1 priority = 0 utility = "-inf" else: difficulty = np.random.randint(low = 1, high = 13) explored = 0 priority = 0 utility = 1.0 else: difficulty = np.random.randint(low = 1, high = 13) explored = -2 priority = "-inf" utility = "-inf" # generate big wall all across the map ''' _, y, x = i if x == 200 or x == 199: difficulty = "inf" explored = -1 priority = 0 utility = "-inf" if (x == 200 or x ==199) and (y == 150 or y == 50 or y == 250): difficulty = np.random.randint(low = 1, high = 13) explored = 0 priority = 0 utility = 1.0 ''' # place the agent in the grid out_grid["Cell"][i[1:]]= [self.agent_counter, i[1:], difficulty, explored, priority, utility] a = Cell(self.agent_counter, self, i[1:], difficulty, explored, priority, utility) self.schedule.add(a) self.grid.place_agent(a, i[1:]) self.agent_counter += 1 # generate buildings structure ''' for i in range(0, 50): x = rnd.randint(20,300) y = rnd.randint(20,300) for j in range(0,rnd.randint(0,3)): for k in range(0, rnd.randint(0,10)): cell = [e for e in self.grid.get_cell_list_contents(tuple([x+j, y+k])) if isinstance(e, Cell)][0] cell.difficulty = "inf" cell.explored = -1 cell.priority = 0 cell.utility = "-inf" ag_count = out_grid["Cell"][tuple([x+j,y+k])][0] out_grid["Cell"][tuple([x+j,y+k])]= [ag_count, cell.pos, cell.difficulty, cell.explored, cell.priority, cell.utility] for i in range(0, 50): x = rnd.randint(20,300) y = rnd.randint(20,300) for j in range(0,rnd.randint(0,3)): for k in range(0, rnd.randint(0,10)): cell = [e for e in self.grid.get_cell_list_contents(tuple([x+k, y+j])) if isinstance(e, Cell)][0] cell.difficulty = "inf" cell.explored = -1 cell.priority = 0 cell.utility = "-inf" ag_count = out_grid["Cell"][tuple([x+k,y+j])][0] out_grid["Cell"][tuple([x+k,y+j])]= [ag_count, cell.pos, cell.difficulty, cell.explored, cell.priority, cell.utility] ''' # 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(self.agent_counter, + self.agent_counter + self.ninjured): inj_index = rnd.choice(valid_coord) out_grid["Injured"][inj_index] = [i, inj_index] a = Injured(i, self, inj_index) self.schedule.add(a) self.grid.place_agent(a, inj_index) with open('robot_exploration/maps/mymap.py', 'w') as f: f.writelines([str(out_grid), '\n']) def step(self): pass
class Forest (Model): def __init__ (self, endophytism = True, ## allow endophyte life style in model run ws = 30, ## initial num of wood endodisp=2.0, ## dispersal of endos decompdisp=10.0, ## dispersal of decomps leafdisp = 4.0, ## how well do leaves disperse leaffall = 1, ## how frequently do leaves disperse numdecomp=1, ## initial number of decomposers numendo=1, ## initial number of endos endoloss=0.05, ## rate of loss of endophyte infect per step newwood = 15, ## total energy added in new logs each step woodfreq = 1, ## how often to put new logs onto the landscape width = 100, ## grid dimensions, only one (squares only) kappa = 0.03, ## average rate of parent tree clusters per unit distance sigma = 3.0, ## variance of child tree clusters, +/- spread of child clusters mu = 2.2, ## average rate of child tree clusters per unit distance nuke = False, ## make landscape, but no agents ): self.endophytism = endophytism self.nwood = ws self.endodisp = endodisp self.decompdisp = decompdisp self.leafdisp = leafdisp self.leaffall = leaffall self.numdecomp = numdecomp self.numendo = numendo self.endoloss = endoloss self.newwood = newwood self.woodfreq = woodfreq self.schedule = RandomActivation(self) self.grid = MultiGrid(width, width, torus = True) self.running = True self.width = width self.kappa = kappa self.sigma = sigma self.mu = mu self.decompspor = 0 ## sporulation events this turn self.endospor = 0 ## sporulation events this turn self.datacollector = DataCollector( model_reporters={ "Endophytes": sumendos, "Endo_subs": Endo_subs, "Decomposers": sumdecomps, "Decomp_subs": Decomp_subs, "Infected_trees": bluetrees, "decompspor_count": decompspor_count, "endospor_count": endospor_count, "Trees": tracktrees, }) ## make initial agents: if not nuke: ## if not a nuclear holocaust where life is devoid self.make_trees() for i in range(self.nwood): self.add_wood() ## no make_woods method self.make_fungi() def make_trees(self): ## let's use our thomas process module tname = 1 positions = tp.makepos(tp.ThomasPP(kappa = self.kappa, sigma=self.sigma, mu=self.mu, Dx=self.grid.width-1)) for i in positions: try: tree = Tree(tname, self, i, disp = self.leafdisp, leaffall = self.leaffall, endoloss = self.endoloss, infection = False) self.schedule.add(tree) self.grid.place_agent(tree, i) tname += 1 except IndexError: print ("Tree out-of-bounds, ipos=",i,"grid dim=", self.grid.width, self.grid.height) ## add initial wood to landscape def add_wood(self): wname = len(self.getall(Wood)) + 1 x = random.randrange(self.grid.width) y = random.randrange(self.grid.height) pos = (x, y) ## wood already present? then just add to the pile if any([ type(i)==Wood for i in self.grid.get_cell_list_contents(pos) ]): for i in self.grid.get_cell_list_contents(pos): if type(i)==Wood: i.energy += random.randrange(self.newwood) ## else: wood = Wood(wname, self, pos, energy = random.randrange(self.newwood)+1) ## self.grid.place_agent(wood, (x,y)) self.schedule.add(wood) wname += 1 ## non-initial, step addition of wood def cwd(self): cwdlist = [round(random.randrange(self.newwood))+1] ## our first log of the step, at least 1 while sum(cwdlist) < round(self.newwood*.9)-1 : ## until we get at 90% of our assigned cwd... newlog=round(random.randrange(self.newwood-sum(cwdlist)))+1 ## new log, at least 1 kg cwdlist.append(newlog) ## put newlog on the list, until newwood reached) wname = len(self.getall(Wood)) + 1 for i in cwdlist: self.add_wood() def make_fungi(self): fname = len(self.getall(Fungus)) + 1 ## decomposers first: decomps=0 while decomps < self.numdecomp: pos = self.findsubstrate(Wood) if any([ type(i)==Fungus for i in self.grid.get_cell_list_contents(pos) ]): pass else: fungus = Fungus(fname, self, pos, energy=10, endocomp=False, disp = self.decompdisp) self.schedule.add(fungus) self.grid.place_agent(fungus, pos) fname += 1; decomps += 1 ## then endophytes: endos=0 while endos < self.numendo: pos = self.findsubstrate(Wood) if any([ type(i)==Fungus for i in self.grid.get_cell_list_contents(pos) ]): pass else: fungus = Fungus(fname, self, pos, energy=10, endocomp=True, disp = self.endodisp) self.schedule.add(fungus) self.grid.place_agent(fungus, pos) fname += 1; endos += 1 def findsubstrate (self, substrate): Subs = self.getall(substrate) try: somestick = (random.choice(Subs).pos) ## pick from these, return position return(somestick) ## pick from these, return position except IndexError: print("no substrates") pass def selthin(self, intensity): ## intensity should be in the form of a percentage aa=self.getall(Tree) if intensity > 1 or intensity < 0: print("too intense! (or not intense enough)") pass else: bb=random.sample(aa, int(len(aa)*intensity)) [ i.die() for i in bb ] def getall(self, typeof): if not any([ type(i)==typeof for i in self.schedule.agents ]): return([]) else: istype = np.array([ type(i)==typeof for i in self.schedule.agents ]) ags = np.array(self.schedule.agents) return list(ags[istype]) ############### deforestation functions ########### ## forest fragmentation: def fragcenters(self,cens): ## cens=number of forest fragments centers=[] for i in range(cens): x=int(random.random()*self.width) ## self.width instead y=int(random.random()*self.width) ## self.width instead z=(x,y) centers.append(z) return(centers) def onefrag(self, center, ags, rad=10): ## center=center of fragment ## ags = list of trees ## rad = radius of fragment to be protected survivors = [] for i in ags: distf=((center[0]-i.pos[0])**2 + (center[1]-i.pos[1])**2)**(1/2) if distf <= rad: survivors.append(i) return(survivors) def fragup(self, centers, rad): ## 1 - get trees alltrees = self.getall(Tree) ## 2 - get centers fcenters = self.fragcenters(centers) ## 3 - designate survivors remnants = [] for i in fcenters: surv=self.onefrag(i, alltrees, rad) remnants.extend(surv) ## kill everything else cuttrees = set(alltrees) - set(remnants) for i in cuttrees: i.die() ## maybe useful for plotting, return the objects return({"alltrees":alltrees, "centers":fcenters, "remnants":remnants, "cuttrees":cuttrees, }) ## Selective thinning: def selthin(self, intensity): ## intensity should be in the form of a percentage aa=self.getall(Tree) if intensity > 1: print("too intense!") pass else: bb=random.sample(aa, int(len(aa)*intensity)) for i in bb: i.die() ## kill em ## plot data: return({"alltrees":aa, "centers":None, "remnants":self.getall(Tree), "cuttrees":bb, }) ############################################################# ## step def step(self): if self.schedule.time % self.woodfreq == self.woodfreq - 1: ## = delay from start self.cwd() ## add wood self.schedule.step() ## agents do their thing self.datacollector.collect(self) ## collect data self.decompspor = 0 ## reset sporulation event tally self.endospor = 0 ## reset sporulation event tally
class SpeedModel(Model): """ Model of the game "Spe_ed". This class controls the execution of the simulation. """ def __init__(self, width, height, nb_agents, agent_classes, initial_agents_params=None, cells=None, data_collector=None, save=False): """ Model-Initialization. :param width: Width of the field :param height: Height of the field :param nb_agents: Number of Agents :param agent_classes: List of classes of the agents that should be players in the game. The length has to be equal or greater than nb_agents :param initial_agents_params: A list of dictionaries containing initialization parameters for agents that should be initialized at the start of the simulation :param cells: A Spe_ed-cells like 2D-Array that initializes the field :param data_collector: Mesa data collector function :param save: whether or not track the games history """ super().__init__() self.data_collector = data_collector self.width = width self.height = height self.nb_agents = nb_agents self.save = save if self.save: self.history = [] if initial_agents_params is None: initial_agents_params = [{} for i in range(nb_agents)] else: initial_agents_params = copy.deepcopy(initial_agents_params) self.schedule = SimultaneousActivation(self) self.grid = MultiGrid(width, height, True) # width and height are swapped since height is rows and width is columns # an alternative to this representation would be to transpose cells everytime it is exposed # but that could be inefficient self.cells = np.zeros((height, width), dtype="int") # Init initial agents self.speed_agents = [] self.active_speed_agents = [] for i in range(nb_agents): agent_params = initial_agents_params[i] agent_params["model"] = self # set to random position/direction if no position/direction is given if "pos" not in agent_params: agent_params["pos"] = self.random.choice( list(self.grid.empties)) if "direction" not in agent_params: agent_params["direction"] = self.random.choice(list(Direction)) agent = agent_classes[i](**agent_params) # don't add agent to grid/cells if its out of bounds. But add it to the scheduler. if self.grid.out_of_bounds(agent_params["pos"]): self.schedule.add(agent) self.speed_agents.append(agent) else: self.add_agent(agent) self.speed_agents.append(agent) self.active_speed_agents.append(agent) if cells is not None: self.init_cells_and_grid(cells) def init_cells_and_grid(self, cells): """ Initializes Mesas Grid and the Model-cells the field with the information given in cells. :param cells: A Spe_ed-cells like 2D-Array that initializes the field :return: None """ self.cells = np.array(cells) # add traces to grid for y in range(self.cells.shape[0]): for x in range(self.cells.shape[1]): # cell is occupied by a collision if self.cells[y, x] == -1: agent = AgentTraceCollision(self, (x, y)) self.add_agent(agent) # cell is occupied by head or trace elif self.cells[y, x] != 0: # head of the agent is not already a entry in self.grid if len(self.grid.get_cell_list_contents((x, y))) == 0: # add trace agent = AgentTrace( self, (x, y), self.speed_agents[self.cells[y, x] - 1]) # get agent based on id self.add_agent(agent) def step(self): """ Computes one iteration of the model. :return: None """ if self.data_collector: self.data_collector.collect(self) if self.save: self.history.append(copy.deepcopy(model_to_json(self))) self.schedule.step() self.check_collisions() self.check_game_finished() def step_specific_agent(self, agent): """ Only steps one specific agent. This is only for specific applications (e.g. Multi-Minimax). Don't use this method if not necessary since it doesn't increment all model parts (e.g. time). :param cells: The agent to step :return: None """ agent.step() agent.advance() self.check_collisions() self.check_game_finished() def check_collisions(self): """ Checks every active agent for collisions with traces or other agents. Colliding agents are eliminated. :return: None """ agents_to_set_inactive = [] for agent in self.speed_agents: for t in agent.trace: cell_contents = self.grid.get_cell_list_contents(t) if len(cell_contents) > 1: if agent not in agents_to_set_inactive: agents_to_set_inactive.append(agent) self.add_agent(AgentTraceCollision(self, t)) for agent in agents_to_set_inactive: agent.set_inactive() def check_game_finished(self): """ Checks whether or not the game has finished (every agent is eliminated) and prints the result if finished. :return: None """ if len(self.active_speed_agents) <= 1: self.running = False if self.save: self.history.append(copy.deepcopy(model_to_json(self))) path = os.path.abspath("") + "/res/simulatedGames/" for entry in self.history: entry["cells"] = entry["cells"].tolist() with open( path + datetime.datetime.now().strftime( "%d-%m-%y__%H-%M-%S-%f") + ".json", "w") as f: json.dump(self.history, f, indent=4) def add_agent(self, agent): """ Adds an agent to the model. :param agent: The agent to add to the model :return: None """ self.schedule.add(agent) self.grid.place_agent(agent, agent.pos) # swapped position args since cells has the format (height, width) pos = (agent.pos[1], agent.pos[0]) if isinstance(agent, SpeedAgent): self.cells[pos] = agent.unique_id elif type(agent) is AgentTraceCollision: self.cells[pos] = -1 elif type(agent) is AgentTrace: self.cells[pos] = agent.origin.unique_id def remove_agent(self, agent): """ Removes an agent from the model. :param agent: The agent to remove from the model :return: None """ if agent in self.schedule.agents: self.schedule.remove(agent) self.grid.remove_agent(agent) def get_agent_by_id(self, unique_id): """ Returns an agent-object by its unique_id. :param unique_id: The agent id to search for :return: Agent or None if no match """ for agent in self.speed_agents: if agent.unique_id == unique_id: return agent return None
class SOBAModel(Model): def __init__(self, width, height, modelWay=None, seed=int(time()), nothing=1, voting_method=False): super().__init__(seed) #Init configurations and defines configuration.settings.init() configuration.defineOccupancy.init() configuration.defineMap.init() #Way of working if modelWay is None: self.modelWay = configuration.settings.model else: self.modelWay = modelWay #Mesa self.schedule = BaseScheduler(self) self.grid = MultiGrid(width, height, False) self.running = True #Control of time and energy self.energy = Energy() self.clock = Time() self.voting_method = voting_method self.sc = SocialChoice() #Log self.log = Log() if self.voting_method: self.log = Logsc() self.roomsSchedule = [] self.agentSatisfationByStep = [] self.fangerSatisfationByStep = [] self.agentsActivityByTime = [] self.averageSatisfationByTime = [] self.totalSatisfationByTime = [] self.occupantsValues = False if self.modelWay != 0 and os.path.isfile('../log/tmp/occupants.txt'): self.occupantsValues = self.log.getOccupantsValues() #Vars of control self.complete = False self.num_occupants = 0 self.day = self.clock.day self.NStep = 0 self.timeToSampling = 'init' # Temperature ThermalLoads self.placeByStateByTypeAgent = {} self.lightsOn = [] #Create the map self.createRooms() self.createThermalzones() self.setMap(width, height) self.createDoors() self.createWindows() self.createWalls() #Create agents self.setAgents() def consumeEnergy(self, appliance): if isinstance(appliance, PC): if appliance.state == 'on': self.energy.consumeEnergyAppliance('PC', appliance.consumeOn) elif appliance.state == 'standby': self.energy.consumeEnergyAppliance('PC', appliance.consumeStandby) else: self.energy.consumeEnergyAppliance('PC', 0) elif isinstance(appliance, Light): if appliance.state == 'on': self.energy.consumeEnergyAppliance('Light', appliance.consume) else: self.energy.consumeEnergyAppliance('Light', 0) elif isinstance(appliance, HVAC): if appliance.state == 'on': self.energy.consumeEnergyAppliance('HVAC', appliance.consumeOn) else: self.energy.consumeEnergyAppliance('HVAC', 0) else: pass def isConected(self, pos): nextRoom = False for room in self.rooms: if room.pos == pos: nextRoom = room if nextRoom == False: return False for x in range(0, width): for y in range(0, height): self.pos_out_of_map.append(x, y) for room in self.rooms: self.pos_out_of_map.remove(room.pos) def createRooms(self): rooms = configuration.defineMap.rooms_json self.rooms = [] #occupantsByTypeRoom = configuration.defineMap.NumberOccupancyByTypeRoom for room in rooms: newRoom = 0 name = room['name'] typeRoom = room['type'] if typeRoom != 'out': conectedTo = room.get('conectedTo') nameThermalZone = room.get('thermalZone') entrance = room.get('entrance') measures = room['measures'] dx = measures['dx'] dy = measures['dy'] dh = measures['dh'] jsonWindows = room.get('windows') newRoom = Room(name, typeRoom, conectedTo, nameThermalZone, dx, dy, dh, jsonWindows) newRoom.entrance = entrance else: newRoom = Room(name, typeRoom, None, False, 0, 0, 0, {}) self.outBuilding = newRoom self.rooms.append(newRoom) for room1 in self.rooms: if room1.conectedTo is not None: for otherRooms in list(room1.conectedTo.values()): for room2 in self.rooms: if room2.name == otherRooms: room1.roomsConected.append(room2) room2.roomsConected.append(room1) for room in self.rooms: room.roomsConected = list(set(room.roomsConected)) sameRoom = {} for room in self.rooms: if sameRoom.get(room.name.split(r".")[0]) is None: sameRoom[room.name.split(r".")[0]] = 1 else: sameRoom[room.name.split(r".") [0]] = sameRoom[room.name.split(r".")[0]] + 1 def createThermalzones(self): self.thermalZones = [] namesThermalZonesCreated = [] for room1 in self.rooms: posibleThermalZone = room1.nameThermalZone if posibleThermalZone not in namesThermalZonesCreated and posibleThermalZone != False and posibleThermalZone is not None: namesThermalZonesCreated.append(posibleThermalZone) rooms = [] for room2 in self.rooms: if room2.nameThermalZone == posibleThermalZone: rooms.append(room2) TZ = ThermalZone(self, posibleThermalZone, rooms) for room3 in TZ.rooms: room3.thermalZone = TZ self.thermalZones.append(TZ) if self.modelWay == 2: hoursRoomsOnOffByDay = {} hoursRoomsOnStrings = self.log.getScheduleRooms() hoursRoomsOn = [] for row in hoursRoomsOnStrings: hoursRoomsOn.append([row[0], float(row[1]), float(row[2])]) for room in self.rooms: count = 0 if room.typeRoom != 'out' and room.typeRoom != 'restroom': hoursOneRoomOn = [] for row in hoursRoomsOn: if row[0] == room.name: hoursOneRoomOn.append([row[1], row[2]]) hoursOneRoomOnByDay = [] for i in range(0, 5): hoursOneDay = [] for hour in hoursOneRoomOn: if int(hour[0]) == i: hoursOneDay.append(hour[1]) hoursOneRoomOnByDay.append(hoursOneDay) hoursOnOffOneRoomByDay = [] for i in range(0, 5): hoursOnOffOneRoomOneDay = [] hourOn = hoursOneRoomOnByDay[i] if len(hourOn) > 0: auxHour = hourOn[0] hourOnAux = hourOn[0] for hour in hourOn: if (auxHour != hour): if (hour > (auxHour + configuration.settings.setOffWorthIt) ): hourOff = auxHour - 0.01 pairOnOff = [ int(hourOnAux * 100) / 100, int(hourOff * 100) / 100 ] hoursOnOffOneRoomOneDay.append( pairOnOff) auxHour = hour + 0.01 hourOnAux = hour else: auxHour = hour + 0.01 else: auxHour = auxHour + 0.01 pairOnOffObligatory = [hourOnAux, hourOn.pop()] hoursOnOffOneRoomOneDay.append(pairOnOffObligatory) hoursOnOffOneRoomByDay.append( hoursOnOffOneRoomOneDay) else: hoursOnOffOneRoomByDay.append(False) hoursRoomsOnOffByDay[room.name] = hoursOnOffOneRoomByDay count = count + 1 for tz in self.thermalZones: schedule = [] for i in range(0, 5): scheduleByDay = [] for room in tz.rooms: hoursByDay = hoursRoomsOnOffByDay.get(room.name) if hoursByDay is not None and hoursByDay != False: hoursOneDay = hoursByDay[i] if hoursOneDay is not None and hoursOneDay != False: for hours in hoursOneDay: hourOn = hours[0] hourOff = hours[1] for pairHours in scheduleByDay: if hourOn > pairHours[0] and pairHours[ 1] > hourOn: scheduleByDay.remove( [pairHours[0], pairHours[1]]) hourOn = pairHours[0] if (hourOff < pairHours[1]): hourOff = pairHours[1] else: pass elif hourOff > pairHours[ 0] and pairHours[1] > hourOff: scheduleByDay.remove( [pairHours[0], pairHours[1]]) hourOff = pairHours[1] if (hourOn > pairHours[0]): hourOn = pairHours[0] else: pass elif hourOff > pairHours[ 1] and pairHours[0] > hourOn: scheduleByDay.remove( [pairHours[0], pairHours[1]]) scheduleByDay.append([hourOn, hourOff]) if len(scheduleByDay) == 0: scheduleByDay.append([False]) schedule.append(scheduleByDay) scheduleJoined = [] for day in schedule: if day != False: scheduleJoined.append(sorted(day)) for day in scheduleJoined: i = 0 if day != False: while (len(day) > (i + 1)): if (day[i][1] + configuration.settings.setOffWorthIt ) > day[i + 1][0]: day[i][1] = day[i + 1][1] day.pop(i + 1) else: i = i + 1 tz.schedule = scheduleJoined def setMap(self, width, height): rooms_noPos = self.rooms rooms_using = [] rooms_used = [] for room in self.rooms: if room.entrance is not None: room.pos = (int(1), 2) rooms_using.append(room) rooms_used.append(room) rooms_noPos.remove(room) break while len(rooms_noPos) > 0: for roomC in rooms_using: xc, yc = roomC.pos rooms_conected = roomC.conectedTo rooms_using.remove(roomC) if rooms_conected is not None: orientations = list(rooms_conected.keys()) for orientation in orientations: if orientation == 'R': for room in rooms_noPos: if room.name == rooms_conected['R']: room.pos = (int(xc + 1), yc) rooms_noPos.remove(room) rooms_used.append(room) rooms_using.append(room) elif orientation == 'U': for room in rooms_noPos: if room.name == rooms_conected['U']: room.pos = (xc, int(yc + 1)) rooms_noPos.remove(room) rooms_used.append(room) rooms_using.append(room) elif orientation == 'D': for room in rooms_noPos: if room.name == rooms_conected['D']: room.pos = (xc, int(yc - 1)) rooms_noPos.remove(room) rooms_used.append(room) rooms_using.append(room) elif orientation == 'L': for room in rooms_noPos: if room.name == rooms_conected['L']: room.pos = (int(xc - 1), yc) rooms_noPos.remove(room) rooms_used.append(room) rooms_using.append(room) else: pass self.rooms = rooms_used def createDoors(self): self.doors = [] for roomC in self.rooms: roomsConected = roomC.roomsConected for room in roomsConected: door_created = False same_corridor = False if room.name != roomC.name: for door in self.doors: if (door.room1.name == roomC.name and door.room2.name == room.name) or ( door.room2.name == roomC.name and door.room1.name == room.name): door_created = True if room.name.split(r".")[0] == roomC.name.split( r".")[0]: same_corridor = True if door_created == False and same_corridor == False: d = Door(roomC, room) self.doors.append(d) room.doors.append(d) roomC.doors.append(d) def createWindows(self): for room in self.rooms: windows = [] json = room.jsonWindows if json is None: pass else: for k in json: window = Window(k, json[k]['l1'], json[k]['l2']) windows.append(window) room.windows = windows def createWalls(self): for room in self.rooms: if room.typeRoom != 'out': walls = [] innerWalls = [] adjRooms = [] xr, yr = room.pos roomA = self.getRoom((xr, yr + 1)) if roomA != False: if roomA.typeRoom != 'out': if roomA.name.split(r".")[0] == room.name.split( r".")[0]: pass else: wall = Wall(room.dx, room.dh, room, roomA) innerWalls.append(wall) adjRooms.append(roomA) else: wall = Wall(room.dx, room.dh, orientation='N') walls.append(wall) else: wall = Wall(room.dx, room.dh, orientation='N') walls.append(wall) roomB = self.getRoom((xr, yr - 1)) if roomB != False: if roomB.typeRoom != 'out': if roomB.name.split(r".")[0] == room.name.split( r".")[0]: pass else: wall = Wall(room.dx, room.dh, room, roomB) innerWalls.append(wall) adjRooms.append(roomB) else: wall = Wall(room.dx, room.dh, orientation='S') walls.append(wall) else: wall = Wall(room.dx, room.dh, orientation='S') walls.append(wall) roomC = self.getRoom((xr + 1, yr)) if roomC != False: if roomC.typeRoom != 'out': if roomC.name.split(r".")[0] == room.name.split( r".")[0]: pass else: wall = Wall(room.dy, room.dh, room, roomC) innerWalls.append(wall) adjRooms.append(roomC) else: wall = Wall(room.dy, room.dh, orientation='E') walls.append(wall) else: wall = Wall(room.dy, room.dh, orientation='E') walls.append(wall) roomD = self.getRoom((xr - 1, yr)) if roomD != False: if roomD.typeRoom != 'out': if roomD.name.split(r".")[0] == room.name.split( r".")[0]: pass else: wall = Wall(room.dy, room.dh, room, roomD) innerWalls.append(wall) adjRooms.append(roomD) else: wall = Wall(room.dy, room.dh, orientation='W') walls.append(wall) else: wall = Wall(room.dy, room.dh, orientation='W') walls.append(wall) room.walls = walls room.innerWalls = innerWalls room.roomsAdj = adjRooms def setAgents(self): # Identifications id_offset = 1000 # Height and Width height = self.grid.height width = self.grid.width # CREATE AGENTS #Create Lightlights self.lights = [] id_light = 0 for room in self.rooms: if room.typeRoom != 'out' and room.light == False: light = Light(id_light, self, room) self.lights.append(light) id_light = id_light + 1 room.light = light for room2 in self.rooms: if room.name.split(r".")[0] == room2.name.split(r".")[0]: room2.light = light id_hvac = id_light + id_offset #Create HVAC self.HVACs = [] for thermalZone in self.thermalZones: restroom = False for room in thermalZone.rooms: if room.typeRoom == 'restroom': restroom = True if restroom == False: hvac = HVAC(id_hvac, self, thermalZone) thermalZone.hvac = hvac self.HVACs.append(hvac) id_hvac = id_hvac + 1 else: thermalZone.hvac = False #Create PC ''' self.workplaces = [] id_aux = 0 for room in self.rooms: #for i in range(0, room.PCs): pc = PC(id_pc + id_aux, self, room) room.PCs.append(pc) self.workplaces.append(pc) id_aux = id_aux + 1 ''' id_occupant = id_hvac + id_offset id_pc = id_occupant + id_offset self.workplaces = [] self.agents = [] # Create occupants if self.modelWay == 0: countPC = 0 print('Número de ocupantes: ', configuration.defineOccupancy.occupancy_json[0]['N']) for n_type_occupants in configuration.defineOccupancy.occupancy_json: self.placeByStateByTypeAgent[ n_type_occupants['type']] = n_type_occupants['states'] n_agents_perfect = int( (n_type_occupants['N'] * n_type_occupants['environment'][0]) / 100) for i in range(0, n_agents_perfect): rooms_with_already_pc = [] a = Occupant(id_occupant, self, n_type_occupants, 1) self.agents.append(a) id_occupant = 1 + id_occupant for state_use_PCs in n_type_occupants['PCs']: roomPC = False name_room_with_pc = a.positionByState[state_use_PCs] for room in self.rooms: if room.name.split(r".")[0] == name_room_with_pc: roomPC = room if roomPC != False and roomPC.typeRoom != 'out': if roomPC not in rooms_with_already_pc: pc = PC(id_pc, self, roomPC) id_pc = id_pc + 1 pc.owner = a self.workplaces.append(pc) a.PCs[state_use_PCs] = pc pc.states_when_is_used.append(state_use_PCs) roomPC.PCs.append(pc) else: for pcaux in roomPC.PCs: if pcaux.owner == a: a.PCs[state_use_PCs] = pcaux pc.states_when_is_used.append( state_use_PCs) self.schedule.add(a) self.grid.place_agent(a, self.outBuilding.pos) self.pushAgentRoom(a, self.outBuilding.pos) self.num_occupants = self.num_occupants + 1 n_agents_good = int((n_type_occupants['N'] * n_type_occupants['environment'][1]) / 100) for i in range(0, n_agents_good): rooms_with_already_pc = [] a = Occupant(id_occupant, self, n_type_occupants, 2) self.agents.append(a) id_occupant = 1 + id_occupant for state_use_PCs in n_type_occupants['PCs']: roomPC = False name_room_with_pc = a.positionByState[state_use_PCs] for room in self.rooms: if room.name.split(r".")[0] == name_room_with_pc: roomPC = room if roomPC != False and roomPC.typeRoom != 'out': if roomPC not in rooms_with_already_pc: pc = PC(id_pc, self, roomPC) id_pc = id_pc + 1 pc.owner = a self.workplaces.append(pc) a.PCs[state_use_PCs] = pc pc.states_when_is_used.append(state_use_PCs) roomPC.PCs.append(pc) else: for pcaux in roomPC.PCs: if pcaux.owner == a: a.PCs[state_use_PCs] = pcaux pc.states_when_is_used.append( state_use_PCs) self.schedule.add(a) self.grid.place_agent(a, self.outBuilding.pos) self.pushAgentRoom(a, self.outBuilding.pos) self.num_occupants = self.num_occupants + 1 n_agents_bad = int(n_type_occupants['N'] * n_type_occupants['environment'][2] / 100) allAgents = n_agents_perfect + n_agents_good + n_agents_bad if allAgents < n_type_occupants['N']: n_agents_bad = n_type_occupants['N'] - (n_agents_perfect + n_agents_good) for i in range(0, n_agents_bad): rooms_with_already_pc = [] a = Occupant(id_occupant, self, n_type_occupants, 3) self.agents.append(a) id_occupant = 1 + id_occupant for state_use_PCs in n_type_occupants['PCs']: roomPC = False name_room_with_pc = a.positionByState[state_use_PCs] for room in self.rooms: if room.name.split(r".")[0] == name_room_with_pc: roomPC = room if roomPC != False and roomPC.typeRoom != 'out': if roomPC not in rooms_with_already_pc: pc = PC(id_pc, self, roomPC) id_pc = id_pc + 1 pc.owner = a self.workplaces.append(pc) a.PCs[state_use_PCs] = pc pc.states_when_is_used.append(state_use_PCs) roomPC.PCs.append(pc) else: for pcaux in roomPC.PCs: if pcaux.owner == a: a.PCs[state_use_PCs] = pcaux pc.states_when_is_used.append( state_use_PCs) self.schedule.add(a) self.grid.place_agent(a, self.outBuilding.pos) self.pushAgentRoom(a, self.outBuilding.pos) self.num_occupants = self.num_occupants + 1 else: for n_type_occupants in configuration.defineOccupancy.occupancy_json: self.placeByStateByTypeAgent[ n_type_occupants['type']] = n_type_occupants['states'] n_agents = n_type_occupants['N'] for i in range(0, n_agents): rooms_with_already_pc = [] a = Occupant(id_occupant, self, n_type_occupants, '') self.agents.append(a) id_occupant = 1 + id_occupant for state_use_PCs in n_type_occupants['PCs']: roomPC = False name_room_with_pc = a.positionByState[state_use_PCs] for room in self.rooms: if room.name.split(r".")[0] == name_room_with_pc: roomPC = room if roomPC != False and roomPC.typeRoom != 'out': if roomPC not in rooms_with_already_pc: pc = PC(id_pc, self, roomPC) id_pc = id_pc + 1 pc.owner = a self.workplaces.append(pc) a.PCs[state_use_PCs] = pc pc.states_when_is_used.append(state_use_PCs) roomPC.PCs.append(pc) else: for pcaux in roomPC.PCs: if pcaux.owner == a: a.PCs[state_use_PCs] = pcaux pc.states_when_is_used.append( state_use_PCs) self.schedule.add(a) self.grid.place_agent(a, self.outBuilding.pos) self.pushAgentRoom(a, self.outBuilding.pos) self.num_occupants = self.num_occupants + 1 #Add to schedule for pc in self.workplaces: self.schedule.add(pc) for light in self.lights: self.schedule.add(light) for hvac in self.HVACs: self.schedule.add(hvac) self.schedule.add(self.clock) def getPosState(self, name, typeA): placeByStateByTypeAgent = self.placeByStateByTypeAgent n = 0 for state in self.placeByStateByTypeAgent[typeA]: if state.get('name') == name: pos1 = state.get('position') if isinstance(pos1, dict): for k, v in pos1.items(): if v > 0: placeByStateByTypeAgent[typeA][n]['position'][ k] = v - 1 self.placeByStateByTypeAgent = placeByStateByTypeAgent return k return list(pos1.keys())[-1] else: return pos1 n = n + 1 def thereIsClosedDoor(self, beforePos, nextPos): oldRoom = False newRoom = False for room in rooms: if room.pos == beforePos: oldRoom = room if room.pos == nextPos: newRoom = room for door in self.doors: if (door.room1.name == oldRoom.name and door.room2.name == newRoom.name) or (door.room2.name == oldRoom.name and door.room1.name == newRoom.name): if door.state == False: return True return False def thereIsPC(self, pos): x, y = pos for pc in self.workplaces: if pc.x == x and pc.y == y: return True return False def thereIsOccupant(self, pos): possible_occupant = self.grid.get_cell_list_contents([pos]) if (len(possible_occupant) > 0): for occupant in possible_occupant: if isinstance(occupant, Occupant): return True return False def ThereIsOtherOccupantInRoom(self, room, agent): for roomAux in self.rooms: possible_occupant = [] if roomAux.name.split(r".")[0] == room.name.split(r".")[0]: possible_occupant = self.grid.get_cell_list_contents( roomAux.pos) for occupant in possible_occupant: if isinstance(occupant, Occupant) and occupant != agent: return True return False def ThereIsSomeOccupantInRoom(self, room): for roomAux in self.rooms: possible_occupant = [] if roomAux.name.split(r".")[0] == room.name.split(r".")[0]: possible_occupant = self.grid.get_cell_list_contents( roomAux.pos) for occupant in possible_occupant: if isinstance(occupant, Occupant): return True return False def thereIsOccupantInRoom(self, room, agent): for roomAux in self.rooms: possible_occupant = [] if roomAux.name.split(r".")[0] == room.name.split(r".")[0]: possible_occupant = self.grid.get_cell_list_contents( roomAux.pos) for occupant in possible_occupant: if isinstance(occupant, Occupant) and occupant == agent: return True return False def getRoom(self, pos): for room in self.rooms: if room.pos == pos: return room return False def pushAgentRoom(self, agent, pos): room = self.getRoom(pos) room.agentsInRoom.append(agent) def popAgentRoom(self, agent, pos): room = self.getRoom(pos) room.agentsInRoom.remove(agent) def getLightWithRoom(self, room): for light in self.lights: if light.room == room: return light return False def crossDoor(self, agent, room1, room2): numb = random.randint(0, 10) for door in self.doors: if ((door.room1 == room1 and door.room2 == room2) or (door.room1 == room2 and door.room2 == room1)): if agent.leftClosedDoor >= numb: door.state = False else: door.state = True def getMatrix(self, agent): new_matrix = configuration.defineOccupancy.returnMatrix( agent, self.clock.clock) agent.markov_matrix = new_matrix def getTimeInState(self, agent): matrix_time_in_state = configuration.defineOccupancy.getTimeInState( agent, self.clock.clock) return matrix_time_in_state def end_work(self, agent, pc): change = configuration.defineOccupancy.environmentBehaviour( agent, self.clock.clock, 'pc')[int(agent.environment) - 1] print(change) if change == 'off': pc.turn_off() elif change == 'standby': pc.turn_standby() else: pass def switchLights(self, agent, currentRoom, nextRoom): change = configuration.defineOccupancy.environmentBehaviour( agent, self.clock.clock, 'light')[int(agent.environment) - 1] light_switch_on = nextRoom.light if light_switch_on != False and light_switch_on.state == 'off': light_switch_on.switch_on() if change == 'off': light_switch_off = currentRoom.light if self.ThereIsOtherOccupantInRoom(currentRoom, agent) == False: if light_switch_off != False: light_switch_off.switch_off() else: pass def step(self): if (self.running == False): os.system("kill -9 %d" % (os.getppid())) os.killpg(os.getpgid(os.getppid()), signal.SIGTERM) if (self.clock.day == 5): self.energy.finalDay(self.NStep) self.energy.finalWeek() self.running = False if self.voting_method: self.log.collectEnergyValues( self, self.energy.energyByDayTotal, self.energy.energyByDayHVAC, self.energy.energyByDayLPC, configuration.settings.time_by_step, self.energy.energyByStepTotal, self.energy.energyByStepHVACsTotal, self.energy.energyByStepLPCTotal) self.log.collectComfortValues( self, configuration.settings.time_by_step, self.agentSatisfationByStep, self.fangerSatisfationByStep) self.log.collectScheduleValues( self, configuration.settings.time_by_step, self.agentsActivityByTime) self.log.collectSatisfactionValues( self, configuration.settings.time_by_step, self.totalSatisfationByTime, self.averageSatisfationByTime) else: self.log.collectEnergyValues( self.modelWay, self.energy.energyByDayTotal, self.energy.energyByDayHVAC, self.energy.energyByDayLPC, configuration.settings.time_by_step, self.energy.energyByStepTotal, self.energy.energyByStepHVACsTotal, self.energy.energyByStepLPCTotal) self.log.collectComfortValues( self.modelWay, configuration.settings.time_by_step, self.agentSatisfationByStep, self.fangerSatisfationByStep) self.log.collectScheduleValues( self.modelWay, configuration.settings.time_by_step, self.agentsActivityByTime) self.log.collectSatisfactionValues( self.modelWay, configuration.settings.time_by_step, self.totalSatisfationByTime, self.averageSatisfationByTime) if self.modelWay == 0: self.log.saveScheduleRooms(self.roomsSchedule) dictAgents = {} for agent in self.agents: agent.scheduleLog.append( [self.day, agent.arrive, agent.leave]) scheduleByDay = {} for e in agent.scheduleLog: d = 'day' + str(e[0]) scheduleByDay[d] = {'arrive': e[1], 'leave': e[2]} posByState = {} for k, v in agent.positionByState.items(): posByState[k] = v dictAgents[str(agent.unique_id)] = { 'TComfort': agent.TComfort, 'posByState': posByState, 'schedule': scheduleByDay } self.log.saveOccupantsValues(dictAgents) return if self.modelWay == 0 or self.modelWay == 1: for hvac in self.HVACs: if ((self.clock.clock > (configuration.defineMap.ScheduleByTypeRoom.get( hvac.thermalZone.rooms[0].typeRoom)[0])) and (configuration.defineMap.ScheduleByTypeRoom.get( hvac.thermalZone.rooms[0].typeRoom)[1] > self.clock.clock)): hvac.working = True else: hvac.working = False elif self.modelWay == 2: for hvac in self.HVACs: for hours in hvac.thermalZone.schedule[self.clock.day]: if hours != [False]: if ((self.clock.getCorrectHour( self.clock.clock + configuration.settings.timeSetOnHVACBeforeGetT) ) > hours[0]) and ((self.clock.getDownCorrectHour( hours[1] - configuration.settings. timeSetOffHVACBeforeloseT)) > self.clock.clock): hvac.working = True elif ((hvac.thermalZone.rooms[0].typeRoom == 'class') and ((self.clock.getCorrectHour( self.clock.clock + configuration.settings. timeSetOnHVACBeforeGetTClass)) > hours[0]) and ((self.clock.getDownCorrectHour( hours[1] - configuration.settings. timeSetOffHVACBeforeloseT)) > self.clock.clock)): hvac.working = True else: usr = False if self.clock.getDownCorrectHour( hours[1]) > self.clock.clock: for room in hvac.thermalZone.rooms: if self.ThereIsSomeOccupantInRoom( room) == True: usr = True if usr == True: hvac.working = True else: hvac.working = False else: hvac.working = False #Temperature in TZ if (self.timeToSampling == 'init'): for tz in self.thermalZones: tz.getQ(self, configuration.settings.timeToSampling) self.timeToSampling = configuration.settings.timeToSampling * ( 1 / configuration.settings.time_by_step) elif (self.timeToSampling > 1): self.timeToSampling = self.timeToSampling - 1 else: for tz in self.thermalZones: tz.step() tz.getQ(self, configuration.settings.timeToSampling) self.timeToSampling = configuration.settings.timeToSampling * ( 1 / configuration.settings.time_by_step) self.schedule.step() #Rooms occupancy time = self.clock.clock day = self.clock.day for room in self.rooms: if len( room.agentsInRoom ) > 0 and room.typeRoom != 'out' and room.typeRoom != 'restRoom': self.roomsSchedule.append([room.name, day, time]) #Satisfation collection time = configuration.settings.time_by_step * self.NStep sumat = 0 number = 0 for agent in self.agents: if self.getRoom(agent.pos).typeRoom != 'out' and self.getRoom( agent.pos).typeRoom != 'restroom' and self.getRoom( agent.pos).typeRoom != 'hall' and self.getRoom( agent.pos).typeRoom != 'corridor': sumat = sumat + agent.comfort number = number + 1 if number > 0: self.agentSatisfationByStep.append(sumat / number) else: self.agentSatisfationByStep.append(0) sumat = 0 number = 0 for hvac in self.HVACs: varaux = False for room in hvac.thermalZone.rooms: if self.ThereIsSomeOccupantInRoom( room ) and room.typeRoom != 'out' and room.typeRoom != 'restroom' and room.typeRoom != 'corridor' and room.typeRoom != 'hall': varaux = True if varaux == True: sumat = sumat + hvac.fangerValue number = number + 1 if number > 0: self.fangerSatisfationByStep.append(sumat / number) else: self.fangerSatisfationByStep.append(0) # Satisfaction SC if self.voting_method: time = configuration.settings.time_by_step * self.NStep sumat = 0 number = 0 for agent in self.agents: if self.getRoom(agent.pos).typeRoom != 'out' and self.getRoom( agent.pos).typeRoom != 'restroom' and self.getRoom( agent.pos).typeRoom != 'hall' and self.getRoom( agent.pos).typeRoom != 'corridor': sumat += agent.preference['{:.1f}'.format( self.getRoom( agent.pos).thermalZone.hvac.desiredTemperature)] number += 1 self.totalSatisfationByTime.append(sumat) if number > 0: self.averageSatisfationByTime.append(sumat / number) else: self.averageSatisfationByTime.append(0) #Ocupancy activity collection time = configuration.settings.time_by_step * self.NStep sumat = 0 number = 0 for agent in self.agents: if (agent.state == 'working in my office') or ( agent.state == 'in a meeting') or ( agent.state == 'working in my laboratory') or (agent.state == 'giving class'): sumat = sumat + 1 self.agentsActivityByTime.append(sumat) if len(self.lightsOn) > 0 and (self.clock.clock > configuration.settings.offLights): for light in self.lightsOn: light.switch_off() self.energy.finalStep() if (self.clock.day > self.day): self.energy.finalDay(self.NStep) if self.modelWay == 0: for agent in self.agents: timeA = self.clock.getDownCorrectHour(agent.arrive - 0.10) timeB = self.clock.getDownCorrectHour(agent.leave - 0.10) agent.scheduleLog.append([self.day, timeA, timeB]) agent.arrive = False agent.leave = False if self.occupantsValues != False: for agent in self.agents: day = 'day' + str(self.day + 1) agent.behaviour['arriveTime'] = self.occupantsValues[str( agent.unique_id)]['schedule'][day]['arrive'] agent.behaviour['leaveWorkTime'] = self.occupantsValues[ str(agent.unique_id)]['schedule'][day]['leave'] self.day = self.day + 1 self.NStep = self.NStep + 1
class MesaTraitsModel(Model): ''' TODO: add new description here ''' height = 20 width = 20 no_of_species = 4 no_of_seeds = 1 verbose = False # Print-monitoring description = 'A model for creating patch expansion out of a few patches.' def __init__(self, height=60, width=60, no_of_species=4, no_of_seeds=2, no_of_agents=20): ''' Create a new MesaTraitsModel. Args: ''' super().__init__() # Set parameters self.height = height self.width = width self.no_of_agents = no_of_agents self.schedule = RandomActivationByBreed(self) self.grid = MultiGrid(self.height, self.width, torus=True) self.no_of_species = no_of_species self.no_of_seeds = no_of_seeds self.patch_manager = PatchManager() self.datacollector = DataCollector( {"Organisms": lambda m: m.schedule.get_breed_count(Organism)}) # Create patches for agent, x, y in self.grid.coord_iter(): #print("new patch added") grown = False patch = Patch(self.next_id(), (x, y), self, 0.04, None, grown) self.grid.place_agent(patch, (x, y)) self.schedule.add(patch) self.patch_manager.add_patch(patch) list_of_cells = [] #select some random patches (without substitution) total_seeds = no_of_species * no_of_seeds for i in range(self.width): for j in range(self.height): list_of_cells.append((i, j)) cords = random.sample(list_of_cells, total_seeds) #choose agents at those patches to be assigned the species _ = 0 for i in range(no_of_species): for j in range(no_of_seeds): patch = self.grid.get_cell_list_contents(cords[_]) patch[0].grown = True patch[0].species = i self.patch_manager.remove_patch(patch[0]) _ += 1 #make the patch grow self.patch_manager.grow_patches() # make moving agents for i in range(20): #20 agents x = random.choice(range(self.width)) y = random.choice(range(self.height)) agent = Organism(self.next_id(), (x, y), self, energy_tank=100, current_energy=50, metabolic_cost=1, energy_gain_per_patch=5, age=5, sexual=False, maturity_age=20, max_longevity=1000, patch_affinity=[1, 1, 0, 0], climatic_affinity=0.6, climatic_affinity_sd=0.05, line_of_sight=1, dispersal_speed=2, reproductive_delay=0, offspring_number=1, moore=True) self.grid.place_agent(agent, (x, y)) self.schedule.add(agent) self.running = True self.datacollector.collect(self) def step(self): self.schedule.step() # collect data self.datacollector.collect(self) def run_model(self, step_count=200): if self.verbose: pass for i in range(step_count): self.step() if self.verbose: pass
class TumorModel(Model): def __init__(self, width, height, initial_tumor_size=2, first_cycle_offset=80, treatment_cycles=30, treatment_cycle_interval=4, param_scale=1.0, kde=0.02, proliferative_growth_rate=0.121, proliferative_to_quiescent_rate=0.03, proliferative_elimination_rate=0.7, quiescent_to_damaged_rate=0.7, damaged_to_proliferative_rate=0.003, damaged_elimination_rate=0.008): self.initial_tumor_size = initial_tumor_size self.first_cycle_offset = first_cycle_offset self.treatment_cycles = treatment_cycles self.treatment_cycle_interval = treatment_cycle_interval self.dissolve_rate = (1 - kde) self.proliferative_growth_rate = proliferative_growth_rate * param_scale self.proliferative_elimination_rate = proliferative_elimination_rate * param_scale self.proliferative_to_quiescent_rate = proliferative_to_quiescent_rate * param_scale self.quiescent_to_damaged_rate = quiescent_to_damaged_rate * param_scale self.damaged_to_proliferative_rate = damaged_to_proliferative_rate * param_scale self.damaged_elimination_rate = damaged_elimination_rate * param_scale super().__init__() self.grid = MultiGrid(width, height, torus=False) self.schedule = RandomActivation(self) self.running = True self.step_number = 0 self.tumor_cells_count = initial_tumor_size ** 2 # Calculate tumor area coordinates x1 = self.grid.width // 2 - self.initial_tumor_size // 2 x2 = x1 + self.initial_tumor_size - 1 y1 = self.grid.height // 2 - self.initial_tumor_size // 2 y2 = y1 + self.initial_tumor_size - 1 # Create agents for x in range(self.grid.width): for y in range(self.grid.height): # uncomment to place a proliferative cell on the center if x in range(x1, x2 + 1) and y in range(y1, y2 + 1): if x == x1 or x == x2 or y == y1 or y == y2: a = ProliferativeCellAgent(y * width + x, self, 0) else: a = QuiescentCellAgent(y * width + x, self, 0) else: a = CellAgent(y * width + x, self, 0) self.schedule.add(a) self.grid.place_agent(a, (x, y)) self.datacollector = DataCollector( agent_reporters={"C": "C"}, model_reporters={"MTD": compute_MTD}) def step(self): if self.step_number >= self.first_cycle_offset and \ self.treatment_cycles > 0 and \ (self.step_number - self.first_cycle_offset) % \ self.treatment_cycle_interval == 0: self.treatment_cycles -= 1 for x in range(self.grid.width): for y in range(self.grid.height): cell = self.grid.get_cell_list_contents([(x,y)])[0] if cell.pos[0] == 0 or \ cell.pos[1] == 0 or \ cell.pos[0] == self.grid.width - 1 or \ cell.pos[1] == self.grid.height - 1: cell.C = 1 self.tumor_cells_count = tumor_cells_count(self) self.datacollector.collect(self) self.schedule.step() self.step_number += 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 Modelo(Model): """ A model with some number of ants and data. """ m = 5 ants = 1 data = pd.DataFrame() grid_clusters = {} lista_bordas = list() def __init__(self, ants=1000, grid_size=5, data=pd.DataFrame()): super().__init__() #self.running = True self.ants = ants self.m = grid_size self.v = False self.grid = MultiGrid(int(self.m), int(self.m), True) self.schedule = RandomActivation(self) self.verbose = False # Print-monitoring self.data = data # Create ants for i in range(self.ants): # Add the agent ant to a random grid cell x = self.random.randrange(self.grid.width) y = self.random.randrange(self.grid.height) while len(self.grid.get_cell_list_contents((x, y))) != 0: x = self.random.randrange(self.grid.width) y = self.random.randrange(self.grid.height) print("re-posicionando") a = AntAgent("ant_" + str(i), (x, y), self) self.schedule.add(a) self.grid.place_agent(a, (x, y)) # Create data for i in self.data.index: # Add the agent ant to a random grid cell x = self.random.randrange(self.grid.width) y = self.random.randrange(self.grid.height) while len(self.grid.get_cell_list_contents((x, y))) != 0: x = self.random.randrange(self.grid.width) y = self.random.randrange(self.grid.height) print("re-posicionando") d = DataAgent(i, (x, y), self) self.schedule.add(d) self.grid.place_agent(d, (x, y)) def step(self): #print(self.data) if (self.schedule.steps == 500 or self.schedule.steps == 1000 or self.schedule.steps == 1500 or self.schedule.steps == 2000 or self.schedule.steps == 2500 or self.schedule.steps == 3000 or self.schedule.steps == 3500 or self.schedule.steps == 4000 or self.schedule.steps == 4500 or self.schedule.steps == 5000): self.validar_clusters() if (self.schedule.steps == 510 or self.schedule.steps == 1010 or self.schedule.steps == 1510 or self.schedule.steps == 2010 or self.schedule.steps == 2510 or self.schedule.steps == 3010 or self.schedule.steps == 3510 or self.schedule.steps == 4010 or self.schedule.steps == 4510 or self.schedule.steps == 5010): self.remover_bordas() self.schedule.step() def validar_clusters(self): #print(self.grid.grid) x = list() y = list() ids = list() #classes= list() for l in self.grid.grid: for c in l: for agent in c: #print ("{} - {}".format(agent.unique_id, agent.pos)) if "data_" in agent.unique_id: #coloca o dado no data frame x_pos, y_pos = agent.pos ids.append(agent) x.append(x_pos) y.append(y_pos) positions = np.column_stack((x, y)) clustering = DBSCAN(eps=2, min_samples=3).fit(positions) self.grid_clusters = {} self.avaliar_clusters(clustering.labels_, ids) self.apresentar_clusters() self.definir_bordas() def avaliar_clusters(self, indicacoes, agentes): for i in range(len(indicacoes)): #print("{} - {}".format(agentes[i], indicacoes[i])) if indicacoes[i] == -1: continue if indicacoes[i] in self.grid_clusters.keys(): cluster = self.grid_clusters.get(indicacoes[i]) cluster.append(agentes[i]) self.grid_clusters.update({indicacoes[i]: cluster}) else: cluster = list() cluster.append(agentes[i]) self.grid_clusters.update({indicacoes[i]: cluster}) classes = list(self.data['class'].unique()) for numero_cluster in self.grid_clusters.keys(): cluster = self.grid_clusters.get(numero_cluster) indices = list() for a in self.grid_clusters.get(numero_cluster): indices.append(a.index_df) dados = self.data.loc[indices, :] gini = self.gini_index(dados, classes) self.grid_clusters.update( {numero_cluster: { 'agentes': cluster, 'gini': gini }}) def definir_bordas(self): for k in self.grid_clusters.keys(): #print("Cluster {}:".format(k)) #indices = list() for a in self.grid_clusters.get(k)['agentes']: #print(self.grid.get_neighbors(a.pos, True)) x, y = a.pos if (x + 1 >= self.grid.width): xp1 = 0 else: xp1 = x + 1 if (x - 1 < 0): xm1 = self.grid.width - 1 else: xm1 = x - 1 if (y + 1 >= self.grid.width): yp1 = 0 else: yp1 = y + 1 if (y - 1 < 0): ym1 = self.grid.width - 1 else: ym1 = y - 1 # x + 1 if (not self.tem_dado((xp1, y))): self.add_borda((xp1, y)) # x - 1 if (not self.tem_dado((xm1, y))): self.add_borda((xm1, y)) # y + 1 if (not self.tem_dado((x, yp1))): self.add_borda((x, yp1)) # y - 1 if (not self.tem_dado((x, ym1))): self.add_borda((x, ym1)) # x - 1 y - 1 if (not self.tem_dado((xm1, ym1))): self.add_borda((xm1, ym1)) # x - 1 y + 1 if (not self.tem_dado((xm1, yp1))): self.add_borda((xm1, yp1)) # x + 1 y - 1 if (not self.tem_dado((xp1, ym1))): self.add_borda((xp1, ym1)) # x + 1 y + 1 if (not self.tem_dado((xp1, yp1))): self.add_borda((xp1, yp1)) def gini_index(self, dados, classes): # quantidade de elementos no cluster n_instances = len(dados) # calculo do indice de gini gini = 0.0 score = 0.0 # indice do grupo, analisando o indice para cada classe for classe in classes: saida = dados['class'].value_counts() if hasattr(saida, classe): p = saida.loc[classe] / n_instances else: p = 0 score += p * p # ponderando o indice pelo tamenho do grupo gini += (1.0 - score) return gini def apresentar_clusters(self): with open('log_aca.txt', 'a') as f: print("Step: {}".format(self.schedule.steps), file=f) for k in self.grid_clusters.keys(): print("Cluster {}:".format(k), file=f) indices = list() for a in self.grid_clusters.get(k)['agentes']: indices.append(a.index_df) dados = self.data.loc[indices, :] print("Dados no cluster:", file=f) print(dados['class'].value_counts(), file=f) print("Gini index: {}".format( self.grid_clusters.get(k)['gini']), file=f) print("", file=f) def tem_dado(self, posicao): ocupantes = self.grid.get_cell_list_contents(posicao) for o in ocupantes: if (isinstance(o, DataAgent) or isinstance(o, BordaAgent)): return True return False def add_borda(self, posicao): a = BordaAgent("borda", posicao, self) self.schedule.add(a) self.lista_bordas.append(a) self.grid.place_agent(a, (posicao)) def remover_bordas(self): print("removendo") for o in self.lista_bordas: if (isinstance(o, BordaAgent)): print("borda") self.grid.remove_agent(o) self.lista_bordas = list()
class WolfSheep(Model): """ Wolf-Sheep Predation Model """ height = 20 width = 20 initial_sheep = 100 initial_wolves = 50 sheep_reproduce = 0.04 wolf_reproduce = 0.05 wolf_gain_from_food = 20 grass = False grass_regrowth_time = 30 sheep_gain_from_food = 4 grass_presence_probability = 1.0 moore = True description = ( "A model for simulating wolf and sheep (predator-prey) ecosystem modelling." ) def __init__( self, height=20, width=20, initial_sheep=100, initial_wolves=50, sheep_reproduce=0.04, wolf_reproduce=0.05, wolf_gain_from_food=20, grass=False, grass_regrowth_time=30, sheep_gain_from_food=4, initial_energy=10, moore=True, ): """ Create a new Wolf-Sheep model with the given parameters. Args: initial_sheep: Number of sheep to start with initial_wolves: Number of wolves to start with sheep_reproduce: Probability of each sheep reproducing each step wolf_reproduce: Probability of each wolf reproducing each step wolf_gain_from_food: Energy a wolf gains from eating a sheep grass: Whether to have the sheep eat grass for energy grass_regrowth_time: How long it takes for a grass patch to regrow once it is eaten sheep_gain_from_food: Energy sheep gain from grass, if enabled. """ super().__init__() # Set parameters self.height = height self.width = width self.initial_sheep = initial_sheep self.initial_wolves = initial_wolves self.sheep_reproduce = sheep_reproduce self.wolf_reproduce = wolf_reproduce self.wolf_gain_from_food = wolf_gain_from_food self.grass = grass self.grass_regrowth_time = grass_regrowth_time self.sheep_gain_from_food = sheep_gain_from_food self.initial_energy = initial_energy self.schedule = RandomActivationByBreed(self) self.grid = MultiGrid(self.height, self.width, torus=True) self.counter = 0 self.moore = moore self.datacollector = DataCollector( { "Wolves": lambda m: m.schedule.get_breed_count(Wolf), "Sheep": lambda m: m.schedule.get_breed_count(Sheep), } ) # Create sheep: for _ in range(initial_sheep): initial_position = (random.randint(0, height - 1), random.randint(0, width - 1)) # Incrementing counter self.counter += 1 # Creating sheep agent sheep_agent = Sheep(self.counter, initial_position, self, moore, initial_energy) # Adding sheep agent self.schedule.add(sheep_agent) # Placing agent self.grid.place_agent(sheep_agent, initial_position) # Create wolves for _ in range(initial_wolves): # Defining initial position initial_position = (random.randint(0, height - 1), random.randint(0, width - 1)) # Incrementing counter self.counter += 1 # Creating wolf agent wolf_agent = Wolf(self.counter, initial_position, self, moore, initial_energy) # Adding agent self.schedule.add(wolf_agent) # Placing agent self.grid.place_agent(wolf_agent, initial_position) # Create grass patches for grid_height in range(height): for grid_width in range(width): # Incrementing counter self.counter += 1 # Creating GrassPatch agent grass_patch_agent = GrassPatch( self.counter, self, True, self.grass_regrowth_time ) # Adding agent self.schedule.add(grass_patch_agent) # Placing agent self.grid.place_agent(grass_patch_agent, (grid_height, grid_width)) def get_agents_at_position(self, position: tuple): """ Returns all the agents located at a specific location """ return self.grid.get_cell_list_contents([position]) def get_grass_patch_to_eat_at_position(self, position: tuple) -> Union[GrassPatch, None]: """ This function returns a GrassPatch agent if and only if this agent is eatable """ grass_patch = None agents = self.get_agents_at_position(position) for agent in agents: if type(agent) == GrassPatch: grass_patch = agent break return grass_patch if grass_patch.is_eatable() else None def get_sheep_to_eat_at_position(self, position: tuple) -> Union[Sheep, None]: """ This function returns a sheep agent to be eaten by a wolf agent if the wolf agents calling this function shares its tile with a sheep agent. If there are several sheep agents on the same tile, one of them will be chosen randomly. """ sheep_agent = None agents = self.get_agents_at_position(position) for agent in agents: if type(agent) == Sheep: sheep_agent = agent break return sheep_agent def add_new_agent(self, agent_type: str, pos: tuple): agent = None # Increasing counter self.counter += 1 if agent_type == Wolf: agent = Wolf(self.counter, pos, self, self.moore, self.initial_energy) elif agent_type == Sheep: agent = Sheep(self.counter, pos, self, self.moore, self.initial_energy) # Adding agent in schedule's agents array self.schedule.add(agent) # Placing agent in the grid self.grid.place_agent(agent, pos) def remove_agent(self, agent: Agent): """ This function is to be called when an agent dies """ # Removing agent from the grid self.grid.remove_agent(agent) # Removing agent from schedule self.schedule.remove(agent) def step(self): self.schedule.step() # Collect data self.datacollector.collect(self) # ... to be completed def run_model(self, step_count=200): # Iterating for step in range(step_count): self.schedule.step() # Collect data self.datacollector.collect()
class SlimeModel(Model): def __init__(self, height, width, color, numAgents, gDense, kRate, dcDiffu, dhRes, dtRes, secRate): # number of agents per tile self.n = numAgents # grid density self.gD = gDense # rate of cAMP decay self.k = kRate # diffusion constant of cAMP self.Dc = dcDiffu # spatial resolution for cAMP simulation self.Dh = dhRes # time resolution for cAMP simulation self.Dt = dtRes # rate of cAMP secretion by an agent self.f = secRate # number of rows/columns in spatial array self.w = masterHeight # agent color self.color = color # height of grid self.height = masterHeight # width of grid self.width = masterWidth # Counter for generating sequential unique id's self.j = 0 # Counter for DataVis agents' unique id's self.dv = 0 # Counter for NumDataVis agents' unique id's self.ndv = 0 # Create randomly ordered scheduler self.schedule = SimultaneousActivation(self) # Create grid (of type MultiGrid to support multiple agents per cell self.grid = MultiGrid(self.width, self.height, torus=False) # Initialize list of cAMP molecules self.cAMPs = list() # Initialize dict for datacollector with total datacollector dc = {"Total Amount of cAMP": self.getAmts} # Initialize for iterating through columns (x) and rows (y) self.x = 0 self.y = 0 # Loop to fill datacollector dictionary with dict entries for each column and row for x in range(masterWidth): dc.update({("x: " + str(x)): self.getColAmts}) dc.update({("y: " + str(x)): self.getRowAmts}) # Create datacollector to retrieve total amounts of cAMP from dc dict created above self.datacollector = DataCollector(dc) # Variable for storing random numbers r = 0 # Initial loop to create agents and fill agents list with them for (contents, x, y) in self.grid.coord_iter(): # Create object of type cAMP cell = cAMP([x, y], self, self.j, 0) # Add random amoutn of cAMP to cell (<1) cell.add(random.random()) # Place cAMP onto grid at coordinates x, y self.grid._place_agent((x, y), cell) # Add cAMP molecule to list self.cAMPs.append(cell) # print("x:", x, " y:", y) if x == 50: # Create DataVis agent ag = DataVis([x, y], self, self.dv) # Place DataVis agent self.grid.place_agent(ag, tuple([x, y])) # Increment unique id counter self.dv += 1 elif x > 50: # Create NumDataVis agent with appropriate slice num ag = NumDataVis([x, y], self, self.ndv) # Place NumDataVis agent self.grid.place_agent(ag, tuple([x, y])) # Increment unique id counter self.ndv += 1 else: # Loop to create SlimeAgents if self.gD % 1 != 0: r = random.random() if r <= self.gD: for i in range(self.n): # Create object of type SlimeAgent ag = SlimeAgent([x, y], self, self.j, self.color) # Place agent onto grid at coordinates x, y self.grid.place_agent(ag, tuple([x, y])) # Add agent to schedule self.schedule.add(ag) # Increment j (unique_id variable) self.j += 1 else: for i in range(self.n): # Create object of type SlimeAgent ag = SlimeAgent([x, y], self, self.j, self.color) # Place agent onto grid at coordinates x, y self.grid.place_agent(ag, tuple([x, y])) # Add agent to schedule self.schedule.add(ag) # Increment j (unique_id variable) self.j += 1 # Print out number of agents print("# of agents:", self.j) self.running = True # Method for getting total cAMP amount def getAmts(self): # Initialize empty total variable total = 0 # Loop to get total amount of cAMP from cAMPs list for molecule in self.cAMPs: total += molecule.getAmt() return total def getRowAmts(self): total = 0 for x in range(masterWidth): try: total += self.grid.get_cell_list_contents( (x, self.y))[0].getAmt() except IndexError: continue if self.y == 49: self.y = 0 else: self.y += 1 return total def getRowAmt(self, y): total = 0 for x in range(masterWidth - 1): try: total += self.grid.get_cell_list_contents((x, y))[0].getAmt() except IndexError: continue if self.y == 49: self.y = 0 else: self.y += 1 return total def getColAmts(self): total = 0 for y in range(masterHeight): try: total += self.grid.get_cell_list_contents( (self.x, y))[0].getAmt() except IndexError: continue if self.x == 49: self.x = 0 else: self.x += 1 return total def sweepForClusters(): blacklist = list() neighbors = list() for (contents, x, y) in self.grid.coord_iter(): for agent in contents[1::]: if type(agent) == SlimeAgent and agent not in blacklist: neighbors = agent.getNeighbors() for neighbor in neighbors: blacklist.append(neighbor) ''' density = blacklist.length / density_coefficent_based_on_area clusteredAgents = ''' # Step method def step(self): cNeighbors = list() neighbors = list() lap = 0 amtSelf = 0 cAMPobj = cAMP newDiag = 0 oldDiag = 0 nAgents = 0 layer = 1 secRate = 0 ''' Perform cAMP decay and diffusion actions ''' for (contents, x, y) in self.grid.coord_iter(): # This block is a bit messy but it works for now cont = True for content in contents: # Set row amounts if an object is DataVis if type(content) is DataVis or type(content) is NumDataVis: content.setRowAmt(self.getRowAmt(y)) cont = False if cont: # Initialize number of agents for layer coloring nAgents = len(contents) - 1 # Reset lap to 0 lap = 0 # Set cAMPobj to current tile's cAMP agent cAMPobj = contents[0] # Set neighbors to cAMPobj's neighbors (Von Neumann) neighbors = cAMPobj.getNeighbors() # Add cAMP objects form neighbors to cNeighbors for neighbor in neighbors: if type(neighbor) is cAMP: cNeighbors.append(neighbor) # Add sum of neighbors to lap for mol in cNeighbors: lap += mol.getAmt() amtSelf = cAMPobj.getAmt() # Reassign lap to the laplacian (using previous neighbor sum value) lap = (lap - 4 * amtSelf) / (self.Dh**2) # Add decay to current cAMP object cAMPobj.add( (-cAMPobj.getDecayRate() * amtSelf + self.Dc * lap) * self.Dt) # Wipe cNeighbors cNeighbors.clear() # Iterate through all contents of a grid cell for agent in contents[1::]: # Get all neighbors (excuding self) neighbors = agent.getNeighbors() # Examine each neighbor for neighbor in neighbors: # Add cAMP neighbors to list if type(neighbor) is cAMP: cNeighbors.append(neighbor) # Add cAMP secretion to the cell that the agent shares with a cAMP object cAMPobj.add(agent.getSecRate() * self.Dt) # Decide whether or not to move newx = (x + random.randint(-1, 2)) % self.w newy = (y + random.randint(-1, 2)) % self.w # Calculate differences newDiag = ((self.grid[newx - 1][newy - 1])[0]).getAmt() diff = ((self.grid[x - 1][y - 1])[0]).getAmt() # Fix if there are crazy values for diff if diff > 10: diff = 10 elif diff < 10: diff = -10 # Decide to move if random.random() < np.exp(diff) / (1 + np.exp(diff)): agent.move(tuple([newx, newy])) # Layers for coloring agents based on density agent.addLayer() layer = agent.getLayer() # Only change color of agent that is on top of a stack if layer >= nAgents: self.pickColor(agent, nAgents) # Wipe cNeighbors cNeighbors.clear() # Add step to schedule self.schedule.step() # Collect new data self.datacollector.collect(self) # Method to select a color based on the topmost agent def pickColor(self, topAgent, nAgents): shade = topAgent.getShades() if nAgents <= 2: topAgent.setShade(shade[0]) elif nAgents == 3: topAgent.setShade(shade[1]) elif nAgents == 4: topAgent.setShade(shade[2]) elif nAgents == 5: topAgent.setShade(shade[3]) elif nAgents == 6: topAgent.setShade(shade[4]) elif nAgents == 7: topAgent.setShade(shade[5]) elif nAgents == 8: topAgent.setShade(shade[6]) elif nAgents == 9: topAgent.setShade(shade[7])
class LabModel(Model): def __init__(self, width, height): defineAgents.init() self.num_Users = 0 self.schedule = BaseScheduler(self) self.running = True self.grid = MultiGrid(width, height, False) self.agents_json = [] self.clock = Time() self.day = self.clock.day self.NStep = 0 self.createWalls(width, height) self.createDoors(width, height) self.savePosOutOfMap() self.setRooms() self.setAgents() self.getRules() def getRules(self): listdata1 = post.getEvents(0) self.actionsNear = listdata1[0] print('Near actions: ', self.actionsNear) listdata2 = post.getEvents(2) self.actionsFar = listdata2[0] print('Far actions: ', self.actionsFar) def createWalls(self, width, height): self.Walls = [] for y in range(int(height*0.2),height): x = width wall = Wall(x, y) self.Walls.append(wall) for x in range(0,int(width/2)): y = 0 wall = Wall(x,y) self.Walls.append(wall) for x in range(0,width): y = height*0.2 wall = Wall(x,y) self.Walls.append(wall) for y in range(0,height+1): x = 0 wall = Wall(x,y) self.Walls.append(wall) for y in range(0, height+1): x = width/2 wall = Wall(x,y) self.Walls.append(wall) for x in range(int(width/2), width): y = height* 0.6 wall = Wall(x,y) self.Walls.append(wall) for x in range(0, width): y = height wall = Wall(x,y) self.Walls.append(wall) def createDoors(self, width, height): door1 = Door(0,2,False, True) door2 = Door(4,3, True) door3 = Door(7,8) door4 = Door(7,12) self.doors = [door1, door2, door3, door4] # Clean positions of doors for wall in self.Walls: for door in self.doors: if ((wall.x == door.x) and (wall.y == door.y )): self.Walls.remove(wall) def savePosOutOfMap(self): self.pos_out_of_map = [] for x in range(8,15): for y in range(0,3): pos = (x,y) self.pos_out_of_map.append(pos) def setRooms(self): positions_room_out = [] positions_room_out.append((self.doors[0].x, self.doors[0].y)) #I understand that door 1 is out of the laboratory self.roomOut = Room(positions_room_out) positions_room1 = [] for x in range(1,7): for y in range(1,3): pos = (x, y) positions_room1.append(pos) room1 = Room(positions_room1) positions_room2 = [] for x in range(1,7): for y in range(4,17): pos = (x, y) positions_room2.append(pos) positions_room2.append((self.doors[1].x, self.doors[1].y)) room2 = Room(positions_room2) positions_room3 = [] for x in range(8,14): for y in range(4,10): pos = (x, y) positions_room3.append(pos) positions_room2.append((self.doors[2].x, self.doors[2].y)) room3 = Room(positions_room3) positions_room4 = [] for x in range(8,14): for y in range(11,17): pos = (x, y) positions_room4.append(pos) positions_room2.append((self.doors[3].x, self.doors[3].y)) room4 = Room(positions_room4) self.rooms = [room1, room2, room3, room4, self.roomOut] def isInMap(self, possible_steps_out_of_map): possible_step = possible_steps_out_of_map for each_pos in self.pos_out_of_map: xp, yp = each_pos xu, yu = possible_step if ((xp == xu) and (yp == yu)): return False return True def thereIsPC(self, pos): x,y = pos for pc in self.workplaces: if pc.x == x and pc.y == y: return True return False def thereIsWall(self, possible_steps_before_walls): possible_step = possible_steps_before_walls for each_wall in self.Walls: xw = each_wall.x yw = each_wall.y xu, yu = possible_step if ((xw == xu) and (yw == yu)): return True return False def thereIsClosedDoor(self, possible_steps_before_doors): xu,yu = possible_steps_before_doors for door in self.doors: if ((xu == door.x) and (yu == door.y)): if door.state == False: return True return False def ThereIsUserInRoom(self, room): for pos in room.pos_room: possible_user = self.grid.get_cell_list_contents([pos]) if (len(possible_user) > 0): for user in possible_user: if isinstance(user,UserAgent): return True return False def setAgents(self): # Identifications id_offset = 100 id_sensorCoffe = self.num_Users + id_offset id_sensorTV = id_sensorCoffe + id_offset id_sensorAccess = id_sensorTV + id_offset id_bulb = id_sensorAccess + id_offset id_pc = id_sensorAccess + id_bulb # Height and Width height = self.grid.height width = self.grid.width # CREATE AGENT # Create Coffe Maker capacity_coffeMaker = 30 self.cm = CoffeMakerAgent(id_sensorCoffe, self, capacity_coffeMaker) self.grid.place_agent(self.cm, (1, height-1)) # Create TV self.tv = TVAgent(id_sensorTV, self) self.grid.place_agent(self.tv, (4,height-1)) # Create Control Access self.ca = AccessAgent(id_sensorAccess, self, self.doors[1]) self.grid.place_agent(self.ca, (2, 3)) # Create LightBulbs self.bulbs = [] LB1 = Bulb(id_bulb, self, self.rooms[0]) self.bulbs.append(LB1) LB2 = Bulb(id_bulb+1, self, self.rooms[1]) self.bulbs.append(LB2) LB3 = Bulb(id_bulb+2, self, self.rooms[2]) self.bulbs.append(LB3) LB4 = Bulb(id_bulb+3, self, self.rooms[3]) self.bulbs.append(LB4) # Create PC self.workplaces = [] PC1 = PC(id_pc, self, 9, 6, 'd') self.grid.place_agent(PC1, (9, 6)) self.workplaces.append(PC1) PC2 = PC(id_pc+1, self, 11, 6, 'd') self.grid.place_agent(PC2, (11, 6)) self.workplaces.append(PC2) PC3 = PC(id_pc+2, self, 12, 6, 'd') self.grid.place_agent(PC3, (12, 6)) self.workplaces.append(PC3) PC4 = PC(id_pc+3, self, 11, 7, 'u') self.grid.place_agent(PC4, (11, 7)) self.workplaces.append(PC4) PC5 = PC(id_pc+4, self, 12, 7, 'u') self.grid.place_agent(PC5, (12, 7)) self.workplaces.append(PC5) PC6 = PC(id_pc+5, self, 9, 14, 'd') self.grid.place_agent(PC6, (9, 14)) self.workplaces.append(PC6) PC7 = PC(id_pc+6, self, 11, 14, 'u') self.grid.place_agent(PC7, (11, 14)) self.workplaces.append(PC7) PC8 = PC(id_pc+7, self, 12, 14, 'u') self.grid.place_agent(PC8, (12, 14)) self.workplaces.append(PC8) PC9 = PC(id_pc+8, self, 11, 13, 'd') self.grid.place_agent(PC9, (11, 13)) self.workplaces.append(PC9) PC10 = PC(id_pc+9, self, 12, 13, 'd') self.grid.place_agent(PC10, (12, 13)) self.workplaces.append(PC10) def getFreePlace(): x = random.randrange(self.grid.width) y = random.randrange(self.grid.height) position = (x,y) possible_free_place = self.grid.get_cell_list_contents([position]) if len(possible_free_place) == 0: there_is_wall = self.thereIsWall(position) if there_is_wall == False: place_in_map = self.isInMap(position) if place_in_map == True: return position return getFreePlace() # Create users countPC = 0 for n_type_users in defineAgents.agents_json: n_agents = n_type_users['N'] for i in range(0, n_agents): a = UserAgent(i, self, self.workplaces[countPC], n_type_users) self.schedule.add(a) self.grid.place_agent(a, (0, 2)) countPC = countPC + 1 #Add to schedule for pc in self.workplaces: self.schedule.add(pc) for bulb in self.bulbs: self.schedule.add(bulb) self.schedule.add(self.cm) self.schedule.add(self.tv) self.schedule.add(self.ca) self.schedule.add(self.clock) def createAgent(self, pos): if self.thereIsUser((0,2)) == False: self.num_Users = self.num_Users + 1 a = UserAgent(self.num_Users - 1, self, self.workplaces[self.num_Users - 1]) self.schedule.add(a) #x, y = getFreePlace() self.grid.place_agent(a, (0, 2)) def ThereIsUserNear(self, pos): xa, ya = pos round_pos = [] round_pos.append((xa-1,ya-1)) round_pos.append((xa-1,ya)) round_pos.append((xa-1,ya+1)) round_pos.append((xa+1,ya+1)) round_pos.append((xa,ya+1)) round_pos.append((xa,ya-1)) round_pos.append((xa+1,ya)) round_pos.append((xa+1,ya-1)) for pos in round_pos: xp, yp = pos if (xp>=0 and yp>=0 and yp < self.grid.height and xp < self.grid.width): possible_user = self.grid.get_cell_list_contents([pos]) if (len(possible_user) > 0): for user in possible_user: if isinstance(user,UserAgent): return True else: continue else: continue return False def ThereIsUserUp(self, pos, id_pc): xa, ya = pos possible_user = self.grid.get_cell_list_contents([(xa,ya+1)]) if (len(possible_user) > 0): for user in possible_user: if isinstance(user,UserAgent) and user.pc.unique_id == id_pc: return True return False def ThereIsUserDown(self, pos, id_pc): xa, ya = pos possible_user = self.grid.get_cell_list_contents([(xa,ya-1)]) if (len(possible_user) > 0): for user in possible_user: if isinstance(user,UserAgent) and user.pc.unique_id == id_pc: return True return False def ThereIsUserDownCM(self, pos): xa, ya = pos agents = [] possible_user = self.grid.get_cell_list_contents([(xa,ya-1)]) if (len(possible_user) > 0): for user in possible_user: if isinstance(user,UserAgent): agents.append(user) return agents def thereIsUser(self,pos): possible_user = self.grid.get_cell_list_contents([pos]) if (len(possible_user) > 0): for user in possible_user: if isinstance(user,UserAgent): return True return False def ThereIsOtherUserInRoom(self, room, agent): for pos in room.pos_room: possible_user = self.grid.get_cell_list_contents([pos]) if (len(possible_user) > 0): for user in possible_user: if isinstance(user,UserAgent) and user != agent: return True return False def getRoom(self, pos): for room in self.rooms: if pos in room.pos_room: return room return False def getLightWithRoom(self, room): for light in self.bulbs: if light.room == room: return light return False def openDoor(self,pos,agent = 0): x_pos, y_pos = pos doors = self.doors for door in doors: x = door.x y = door.y if ((x == x_pos) and (y == y_pos)): if isinstance(agent, AccessAgent): door.open(True) else: door.open() def closeDoor(self,pos): x_pos, y_pos = pos doors = self.doors for door in doors: x = door.x y = door.y if ((x == x_pos) and (y == y_pos)): door.close() def getMatrix(self,agent): new_matrix = defineAgents.returnMatrix(agent, self.clock.clock) agent.markov_matrix = new_matrix def getTimeInState(self, agent): matrix_time_in_state = defineAgents.getTimeInState(agent, self.clock.clock) return matrix_time_in_state def step(self): self.schedule.step() self.NStep = self.NStep + 1
class PlaneModel(Model): """ A model representing simple plane consisting of 16 rows of 6 seats (2 x 3) using a given boarding method """ method_types = { 'Random': methods.random, 'Front-to-back': methods.front_to_back, 'Front-to-back (4 groups)': methods.front_to_back_gr, 'Back-to-front': methods.back_to_front, 'Back-to-front (4 groups)': methods.back_to_front_gr, 'Window-Middle-Aisle': methods.win_mid_ais, 'Steffen Perfect': methods.steffen_perfect, 'Steffen Modified': methods.steffen_modified } def __init__(self, method, shuffle_enable=True, common_bags='normal'): self.grid = MultiGrid(21, 7, False) self.running = True self.schedule = queue_method.QueueActivation(self) self.method = self.method_types[method] self.entry_free = True self.shuffle_enable = shuffle_enable self.common_bags = common_bags # Create agents and splitting them into separate boarding groups accordingly to a given method self.boarding_queue = [] self.method(self) # Create patches representing corridor, seats and walls id = 97 for row in (0, 1, 2, 4, 5, 6): for col in (0, 1, 2): patch = PatchAgent(id, self, 'WALL') self.grid.place_agent(patch, (col, row)) id += 1 for col in range(3, 19): patch = PatchAgent(id, self, 'SEAT') self.grid.place_agent(patch, (col, row)) id += 1 for col in (19, 20): patch = PatchAgent(id, self, 'WALL') self.grid.place_agent(patch, (col, row)) id += 1 for col in range(21): patch = PatchAgent(id, self, 'CORRIDOR', 'FREE') self.grid.place_agent(patch, (col, 3)) id += 1 def step(self): self.schedule.step() if len(self.grid.get_cell_list_contents((0, 3))) == 1: self.get_patch((0, 3)).state = 'FREE' if self.get_patch((0, 3)).state == 'FREE' and len(self.boarding_queue) > 0: a = self.boarding_queue.pop() a.state = 'GOING' self.schedule.add(a) self.grid.place_agent(a, (0, 3)) self.get_patch((0, 3)).state = 'TAKEN' if self.schedule.get_agent_count() == 0: self.running = False def get_patch(self, pos): agents = self.grid.get_cell_list_contents(pos) for agent in agents: if isinstance(agent, PatchAgent): return agent return None def get_passenger(self, pos): agents = self.grid.get_cell_list_contents(pos) for agent in agents: if isinstance(agent, PassengerAgent): return agent return None
class EgyptSim(Model): """ Simulation Model for wealth distribution represented by grain in ancient Egypt """ # Variable declarations for non python programmer sanity # Map variables height = 30 width = 30 # Simulation Variables timeSpan = 500 currentTime = 0 startingSettlements = 14 startingHouseholds = 7 startingHouseholdSize = 5 startingGrain = 3000 minAmbition = 0.1 minCompetency = 0.5 generationalVariation = 0.9 knowledgeRadius = 20 distanceCost = 10 fallowLimit = 4 popGrowthRate = 0.1 fission = False fissionChance = 0.7 rental = True rentalRate = 0.5 totalPopulation = startingSettlements * startingHouseholds * startingHouseholdSize totalGrain = startingGrain * startingHouseholds startingPopulation = totalPopulation projectedHistoricalPopulation = totalPopulation maxHouseholdGrain = startingGrain # Step variables mu = 0 sigma = 0 alpha = 0 beta = 0 # Visualisation description = "A model simulating wealth growth and distribution in Ancient Egypt.\n\nThe model allows one to see how variables such as the flooding of the Nile, human character traits and random chance effect the acquisition and distribution of wealth." # List of identifiers and colors for settlements SETDICT = {"s1": "#FF0000", "s2": "#FF4500", "s3": "#BC8F8F", "s4": "#00FF00", "s5": "#00FFFF", "s6": "#0000FF", "s7": "#FF00FF", "s8": "#FF1493", "s9": "#708090", "s10": "#DC143C", "s11": "#FF8C00", "s12": "#FF69B4", "s13": "#800000", "s14": "#7CFC00", "s15": "#008B8B", "s16": "#483D8B", "s17": "#4B0082", "s18": "#FF69B4", "s19": "#000000", "s20": "#8B4513"} def __init__(self, height: int = 30, width: int = 30, timeSpan: int = 500, startingSettlements: int = 14, startingHouseholds: int = 7, startingHouseholdSize: int = 5, startingGrain: int = 3000, minAmbition: float = 0.1, minCompetency: float = 0.5, generationalVariation: float = 0.9, knowledgeRadius: int = 20, distanceCost: int = 10, fallowLimit: int = 4, popGrowthRate: float = 0.1, fission: bool = False, fissionChance: float = 0.7, rental: bool = True, rentalRate: float = 0.5): """ Create a new EgyptSim model Args: height: The height of the simulation grid width: The width of the simulation grid timeSpan: The number of years over which the model is to run startingSettlements: The starting number of Settlements startingHouseholds: The starting number of Households per Settlement startingHouseholdSize: The starting number of workers in a Household startingGrain: The starting amount of grain for each Household minAmbition: The minimum ambition value for a Household minCompetency: The minimum competency value for a Household generationalVariation: The difference between generations of a Household knowledgeRadius: How far outside ther Settlement a Household can "see" distanceCost: The cost to move grain per cell away from a settlemnt fallowLimit: The number of years a field can lay fallow before it is harvested popGrowthRate: The rate at which the population grows fission: If Household fission (Moving between settlements) is allowed fissionChance: The chance fission occuring rental: If land rental is allowed rentalRate: The rate at which households will rent land """ super().__init__() # Set Parameters # Map size self.height = height self.width = width # If the number of starting settlements is greater than the maximum reasonable number of households considering territory and farming area # Considers that each household needs at least two field to survive at a minimum number of members, a Settlment needs 9 (territory) + 2 * households # Tiles to survive if startingSettlements > ((width - 1) * height) // (9 + (startingHouseholds * 2)): if startingSettlements > 20: self.startingSettlements = 20 else: self.startingSettlements = ((height - 1) * width) // (9 + (startingHouseholds * 2)) print("Too many starting settlements to support the settlements and household, truncating to: ", self.startingSettlements) else: self.startingSettlements = startingSettlements # Simulation Variables self.timeSpan = timeSpan self.currentTime = 0 self.startingHouseholds = startingHouseholds self.startingHouseholdSize = startingHouseholdSize self.startingGrain = startingGrain self.minAmbition = minAmbition self.minCompetency = minCompetency self.generationalVariation = generationalVariation self.knowledgeRadius = knowledgeRadius self.distanceCost = distanceCost self.fallowLimit = fallowLimit self.popGrowthRate = popGrowthRate self.fission = fission self.fissionChance = fissionChance self.rental = rental self.rentalRate = rentalRate self.totalGrain = startingGrain * startingHouseholds * startingSettlements self.totalPopulation = startingSettlements * startingHouseholds * startingHouseholdSize self.startingPopulation = self.totalPopulation self.projectedHistoricalPopulation = self.startingPopulation self.maxHouseholdGrain = startingGrain # Scheduler and Grid self.schedule = EgyptSchedule(self) self.grid = MultiGrid(height = self.height, width = self.width, torus=False) # Define specific tables for data collection purposes setlist = [] for i in range(self.startingSettlements): setlist.append("s" + str(i + 1) + "_Population") tables = {"Settlement Population": setlist} # Data collection self.datacollector = DataCollector(model_reporters = {"Households": lambda m: m.schedule.get_breed_count(Household), "Settlements": lambda m: m.schedule.get_breed_count(Settlement), "Total Grain": lambda m: m.totalGrain, "Total Population": lambda m: m.totalPopulation, "Projected Hisorical Poulation (0.1% Growth)": lambda m: m.projectedHistoricalPopulation, "Gini-Index": gini, "Maximum Settlement Population": maxSetPop, "Minimum Settlement Population": minSetPop, "Mean Settlement Poulation" : meanSetPop, "Maximum Household Wealth": maxHWealth, "Minimum Household Wealth": minHWealth, "Mean Household Wealth" : meanHWealth, "Number of households with < 33% of wealthiest grain holding": lowerThirdGrainHoldings, "Number of households with 33 - 66% of wealthiest grain holding": middleThirdGrainHoldings, "Number of households with > 66% of wealthiest grain holding": upperThirdGrainHoldings }, tables = tables) self.setup() self.running = True self.collectTableData() self.datacollector.collect(self) def collectTableData(self): setPops = {} for s in self.schedule.get_breed(Settlement): setPops[s.unique_id + "_Population"] = s.population self.datacollector.add_table_row("Settlement Population", setPops, True) def setupMapBase(self): """ Create the grid as field and river """ for agent, x, y in self.grid.coord_iter(): # If on left edge, make a river if x == 0: uid = "r" + str(x) + "|" + str(y) river = River(uid, self, (x, y)) self.grid.place_agent(river, (x, y)) # Otherwise make a field else: uid = "f" + str(x) + "|" + str(y) field = Field(uid, self, (x, y), 0.0) self.grid.place_agent(field, (x, y)) self.schedule.add(field) def setupSettlementsHouseholds(self): """ Add settlements and households to the simulation """ h = 1 for i in range(self.startingSettlements): # Loop untill a suitable location is found while True: x = self.random.randrange(1, self.width) y = self.random.randrange(self.height) flag = False cell = self.grid.get_cell_list_contents((x, y)) # Check that tile is available for agent in cell: if agent.settlementTerritory: break else: flag = True break if flag: break # Add settlement to the grid population = self.startingHouseholds * self.startingHouseholdSize uid = "s" + str(i + 1) # Use a custom id for the datacollector settlement = Settlement(uid, self, (x, y), population, self.startingHouseholds, uid, self.SETDICT[uid]) self.grid.place_agent(settlement, (x, y)) # Set the surrounding fields as territory local = self.grid.get_neighbors((x, y), moore=True, include_center=True, radius=1) for a in local: a.settlementTerritory = True # Add households for the settlement to the scheduler for j in range(self.startingHouseholds): huid = "h" + str(h) # Use a custom id for the datacollector ambition = np.random.uniform(self.minAmbition, 1) competency = np.random.uniform(self.minCompetency, 1) genCount = self.random.randrange(5) + 10 household = Household(huid, self, settlement, (x, y), self.startingGrain, self.startingHouseholdSize, ambition, competency, genCount) # ! Dont add household to grid, is redundant self.schedule.add(household) h += 1 # Add settlement to the scheduler self.schedule.add(settlement) def setup(self): """ Setup model parameters """ self.setupMapBase() self.setupSettlementsHouseholds() def step(self): self.currentTime += 1 self.maxHouseholdGrain = 0 self.setupFlood() self.schedule.step() self.projectedHistoricalPopulation = round(self.startingPopulation * ((1.001) ** self.currentTime)) self.datacollector.collect(self) # Add settlement data to table self.collectTableData() # Cease running once time limit is reached or everyone is dead if self.currentTime >= self.timeSpan or self.totalPopulation == 0: self.running = False def setupFlood(self): """ Sets up common variables used for the flood method in Fields """ self.mu = random.randint(0, 10) + 5 self.sigma = random.randint(0, 5) + 5 self.alpha = (2 * self.sigma ** 2) self.beta = 1 / (self.sigma * math.sqrt(2 * math.pi))
class SamplePSO(PSO): def __init__(self, population: int, dimension: int, attraction_best_global: float, attraction_best_personal: float, lim_vel_particles: float, inertia_particle: float, max_iterations: int, width: int, height: int, num_max_locales: int, suavizar_espacio: int): super().__init__(population, dimension, attraction_best_global, attraction_best_personal, lim_vel_particles, inertia_particle, max_iterations) self.width = width self.height = height self.grid = MultiGrid(self.width, self.height, torus=False) # Variables para el espacio de busqueda self.num_max_locales = num_max_locales self.suavizar_espacio = suavizar_espacio # Crear espacio de busqueda self.setup_search_space() # Crear particulas # Lo hace la clase padre # Colocar particulas # Hay que adaptar pos interno al espacio de busqueda self.place_particles(True) # Captura de datos para grafica self.datacollector = DataCollector({ "Best": lambda m: m.global_best_value, "Average": lambda m: m.average() }) def average(self): sum = 0 for agent in self.schedule.agents: if isinstance(agent, Particle): sum += agent.personal_best_value return sum / self.population # Se modifica step del padre para añadir el collector def step(self): super().step() # Collect data self.datacollector.collect(self) # Stop si llega al máximo if self.global_best_value == 1: self.running = False def place_particles(self, initial=False): for particle in self.particles: pos = self.pos_particle_to_pos(particle) if initial: self.grid.place_agent(particle, pos) else: self.grid.move_agent(particle, pos) def pos_particle_to_pos(self, particle: Particle): # Convierte posiciones de particula [0 1] en posiciones de grid 2D min_xcor = 0 max_xcor = self.width - 1 min_ycor = 0 max_ycor = self.height - 1 x_cor = self.convert(particle.pos_particle[0], min_xcor, max_xcor) y_cor = self.convert(particle.pos_particle[1], min_ycor, max_ycor) return (x_cor, y_cor) @staticmethod def convert(x: float, a: float, b: float) -> int: # Bijection from [0, 1] to [a, b] return int(a + x * (b - a)) def setup_search_space(self): # Preparar un espacio de busqueda con colinas y valles if self.num_max_locales == 0: for agent, x, y in self.grid.coord_iter(): val = random.random() patch = Patch(self.unique_id, self, (x, y), val) self.unique_id += 1 self.grid.place_agent(patch, (x, y)) else: n_elements = (self.width - 1) * (self.height - 1) selected_elements = random.sample(range(n_elements), self.num_max_locales) element = 0 for (agentSet, x, y) in self.grid.coord_iter(): val = 10 * random.random( ) if element in selected_elements else 0 patch = Patch(self.unique_id, self, (x, y), val) self.unique_id += 1 self.grid.place_agent(patch, (x, y)) element += 1 # Suavizado del espacio for _ in range(self.suavizar_espacio): for (agentSet, x, y) in self.grid.coord_iter(): for agent in agentSet: if isinstance(agent, Patch): agent.diffuse_val(1) # Normalizacion del espacio 0 y 0.99999 min_val = 0 max_val = 0 for (agentSet, x, y) in self.grid.coord_iter(): for agent in agentSet: if isinstance(agent, Patch): if agent.val < min_val: min_val = agent.val if agent.val > max_val: max_val = agent.val for (agentSet, x, y) in self.grid.coord_iter(): for agent in agentSet: if isinstance(agent, Patch): agent.val = 0.99999 * (agent.val - min_val) / (max_val - min_val) # Marcar a 1 el máximo max_val = 0 max_patch = None for (agentSet, x, y) in self.grid.coord_iter(): for agent in agentSet: if isinstance(agent, Patch): if agent.val > max_val: max_patch = agent if isinstance(max_patch, Particle): max_patch.val = 1 # Colorear patches for (agentSet, x, y) in self.grid.coord_iter(): for agent in agentSet: if isinstance(agent, Patch): agent.set_color() # Se han de definir los métodos evaluation y psoexternalUpdate def evaluation(self, particle: Particle): # Se podría usar particle.pos si se ejecutara primero pso_external_update # Pero se ejecuta despues # Hay que revisar la primera evaluación al crear particulas if self.grid is not None: pos = self.pos_particle_to_pos(particle) for patch in self.grid.get_cell_list_contents(pos): if isinstance(patch, Patch): return patch.val else: return 0 def pso_external_update(self): self.place_particles()
class GentrifiedNeighbourhood(Model): def from_dict(self, d): self.__dict__.update(d) def __init__(self, people_inside, people_outside, outside_person_econ_dist_mean, share_threshold, property_value_dist_mean, num_residential, num_commercial, num_streets, width, height): super().__init__() self.people_inside = int(people_inside) self.people_outside = int(people_outside) self.num_people = people_inside + people_outside self.outside_person_econ_dist_mean = outside_person_econ_dist_mean self.share_threshold = share_threshold self.property_value_dist_mean = property_value_dist_mean self.num_residential = int(num_residential) self.num_commercial = int(num_commercial) self.num_streets = int(num_streets) self.schedule = RandomActivation(self) self.grid = MultiGrid(width, height, True) # Create agents available = [] indices = [] count = 0 for i in range(height): for j in range(width - 1): available.append((i, j)) indices.append(count) count += 1 occupied = [] res = [] res_ind = [] count = 0 sched = 0 for i in range(self.num_residential): # place residences randomly a = r.Residential(sched, self) placed = False while not placed: position = np.random.choice(indices) indices.remove(position) position = available[position] # if (x,y) is valid and it doesn't already have a house on it, add a house if position not in occupied: self.grid.place_agent(a, position) self.schedule.add(a) occupied.append(position) res.append(position) res_ind.append(count) count += 1 placed = True sched += 1 else: print('something wrong 1') for i in range(self.num_commercial): # place commercial randomly a = c.Commercial(sched, self) placed = False while not placed: position = np.random.choice(indices) indices.remove(position) position = available[position] # if (x,y) is valid and it doesn't already have a property on it, add a business if position not in occupied: self.grid.place_agent(a, position) self.schedule.add(a) occupied.append(position) placed = True sched += 1 for i in range(self.num_streets): a = s.Street(sched, self) placed = False while not placed: position = np.random.choice(indices) indices.remove(position) position = available[position] # if (x,y) is valid and it doesn't already have a property on it, add a business if position not in occupied: self.grid.place_agent(a, position) self.schedule.add(a) occupied.append(position) placed = True sched += 1 homes = [] for i in range(self.people_inside): a = p.Person(sched, self, True) placed = False while not placed: position = np.random.choice(res_ind) res_ind.remove(position) position = res[position] if position not in homes: self.grid.place_agent(a, position) self.schedule.add(a) a.Home = position a.resident_status = True a.in_neighbourhood = True homes.append(position) a.home = position Res = self.grid.get_cell_list_contents(position) home = [obj for obj in Res if isinstance(obj, r.Residential)] home = home[0] home.vacancy = False a.econ_status = home.property_value placed = True sched += 1 for i in range(self.people_outside): a = p.Person(sched, self, False) placed = False while not placed: y = random.randrange(self.grid.height) if y != self.grid.height: self.grid.place_agent(a, (y, self.grid.width - 1)) self.schedule.add(a) a.resident_status = False a.in_neighbourhood = False placed = True sched += 1 # DEBUG: Plot econ status distros # econ_inside = [person.econ_status for person in self.schedule.agents if # isinstance(person, p.Person) and person.in_neighbourhood] # econ_outside = [person.econ_status for person in self.schedule.agents if # isinstance(person, p.Person) and not person.in_neighbourhood] # # plt.hist(econ_inside) # plt.figure() # plt.hist(econ_outside) # plt.show() self.datacollector = DataCollector(model_reporters=model_reporters) def step(self): self.datacollector.collect(self) self.schedule.step()
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 Sugarscape2ConstantGrowback(Model): ''' Sugarscape 2 Constant Growback ''' verbose = True # Print-monitoring def __init__(self, N, beta_c, beta_d, beta_w, beer_consumption, serving_speed, height=34, width=18, bar1_y=1, bar2_y=32, stage=(9, 33)): ''' Create a new Constant Growback model with the given parameters. Args: initial_population: Number of population to start with ''' # Set parameters self.height = height self.width = width self.initial_population = N self.bar1 = (0, bar1_y) self.bar1crowd = 0 self.bar2 = (17, bar1_y) self.bar2crowd = 0 self.bar3 = (0, bar2_y) self.bar3crowd = 0 self.bar4 = (17, bar2_y) self.bar4crowd = 0 self.stage = stage self.beta_c = beta_c self.beta_w = beta_w self.beta_d = beta_d self.beer_consumption = beer_consumption self.serving_speed = serving_speed self.WaitingTimes = [] self.MaxAgents = 0 self.schedule = RandomActivationByBreed(self) self.grid = MultiGrid(self.width, self.height, torus=False) #self.datacollector = DataCollector({"SsAgent": lambda m: m.schedule.get_breed_count(SsAgent), }) self.datacollector = DataCollector({ "Waiting": lambda m: m.schedule.AverageWaitingTime(True), "MaxAgents": lambda m: m.schedule.MaxAgents() }) # Create sugar import numpy as np # Create agent: for i in range(self.initial_population): #x = random.randrange(self.width) #y = random.randrange(self.height) # Start position of agents at bottom of 'club' x = 7 + int(5 * np.random.random()) y = 0 vision = 2 ssa = SsAgent((x, y), self, beta_c, beta_d, beta_w, beer_consumption, serving_speed, True, vision) self.grid.place_agent(ssa, (x, y)) self.schedule.add(ssa) sugar_distribution = np.zeros([self.width, self.height]) for x in range(self.width): for y in range(self.height): sugar_distribution[x, y] = 0 for _, x, y in self.grid.coord_iter(): sugar = Sugar((x, y), self) self.grid.place_agent(sugar, (x, y)) self.schedule.add(sugar) self.running = True def WaitingTime(self, bar): # Calculate crowd (and thus waiting time) in front of a bar every model interation to decrease computational cost. busy = 0 (x, y) = bar for dx in range(-4, 5): for dy in range(-4, 5): x_cor = x + dx y_cor = y + dy if 0 <= x_cor < self.width and 0 <= y_cor < self.height: busy += len( self.grid.get_cell_list_contents([(x_cor, y_cor)])) return busy def step(self): self.WaitingTimes = [] # Calculate bar crowds per bar. self.bar1crowd = self.WaitingTime(self.bar1) self.bar2crowd = self.WaitingTime(self.bar2) self.bar3crowd = self.WaitingTime(self.bar3) self.bar4crowd = self.WaitingTime(self.bar4) self.schedule.step() self.datacollector.collect(self) if self.verbose: print([self.schedule.time, self.schedule.get_breed_count(SsAgent)]) def run_model(self, step_count=10): if self.verbose: print('Initial number Sugarscape Agent: ', self.schedule.get_breed_count(SsAgent)) for i in range(step_count): print(step_count) self.step() if self.verbose: print('') print('Final number Sugarscape Agent: ', self.schedule.get_breed_count(SsAgent))
class ciudad(Model): "Inicialización del modelo" "Se necesita incluir la base de datos, suponiendo que tendremos varias ciudades para que la inicialización sea genérica" def __init__(self, n, m, width, height, porcentaje_infectados, densidad, acumedad, sexo, edades, transporte, Casillas_zona, acummovilidad, movilidad, acummovilidad2, movilidad2, acummovilidad3, movilidad3, dias_cuarentena, long_paso, porcentaje_en_cuarentena, pruebas_disponibles, activacion_testing_aleatorio, activacion_contact_tracing, activación_cuarentena_acordeon, dia_inicio_acordeon, intervalo_acordeon, tiempo_zonificacion): self.total_agentes = n #número de agentes a iniciar self.schedule = RandomActivation( self) #inicialización en paralelo de todos los agentes self.grid = MultiGrid(width, height, True) #creación de la grilla genérica global PRUEBAS_DISPONIBLES global ACTIVACION_CONTACT_TRACING global ACTIVACION_TESTING_ALEATORIO global OLAS global ACTIVACION_CUARENTENA_ACORDEON global DIA_INICIO_ACORDEON global INTERVALO_ACORDEON global ACTIVACION_CUARENTENA global DURACION_CUARENTENA global PORCENTAJE_EN_CUARENTENA global ACTIVACION_CUARENTENA_ZONIFICADA global DURACION_CUARENTENA_ZONIFICADA global PORCENTAJE_EN_CUARENTENA_ZONIFICADA global TIEMPO_ZONIFICACION global MATRIZ_CASILLAS global MATRIZ_MOVILIDAD2 global MATRIZ_MOVILIDAD3 global ACUMULADA_MOVILIDAD2 global ACUMULADA_MOVILIDAD3 #Inicialización de las variables globales PRUEBAS_DISPONIBLES = pruebas_disponibles ACTIVACION_CONTACT_TRACING = activacion_contact_tracing ACTIVACION_TESTING_ALEATORIO = activacion_testing_aleatorio OLAS = round(PRUEBAS_DISPONIBLES / 12) ACTIVACION_CUARENTENA_ACORDEON = activación_cuarentena_acordeon DIA_INICIO_ACORDEON = dia_inicio_acordeon INTERVALO_ACORDEON = intervalo_acordeon ACTIVACION_CUARENTENA = (True if dias_cuarentena > 0 else False) DURACION_CUARENTENA = dias_cuarentena PORCENTAJE_EN_CUARENTENA = porcentaje_en_cuarentena TIEMPO_ZONIFICACION = tiempo_zonificacion #Guardar los datos de las nuevas matrices de movilidad MATRIZ_CASILLAS = Casillas_zona MATRIZ_MOVILIDAD2 = movilidad2 MATRIZ_MOVILIDAD3 = movilidad3 ACUMULADA_MOVILIDAD2 = acummovilidad2 ACUMULADA_MOVILIDAD3 = acummovilidad3 "Creación de cada agente" for i in range(self.total_agentes): n_id = random.random() estado = (2 if n_id > porcentaje_infectados else 1) tcontagio = (random.randint(5, 9) if estado == 2 else 0) nuevo = personas(i, self, self.total_agentes, m, estado, tcontagio, densidad, acumedad, sexo, edades, transporte, Casillas_zona, acummovilidad, movilidad, dias_cuarentena, long_paso, porcentaje_en_cuarentena) #asignación del id self.schedule.add(nuevo) #creación del agente en el sistema "Asignación del hogar" for i in Casillas_zona: values = Casillas_zona.get(i) for j in values: agentes = self.grid.get_cell_list_contents(j) if len(agentes) > 0: num_hogares = (1 if round(len(agentes) / 4) == 0 else round(len(agentes) / 4)) lista = [e for e in range(0, num_hogares)] for z in agentes: z.hogar = random.choice(lista) "Configurar el recolector de datos" self.datacollector = DataCollector( model_reporters={ "Susceptibles": susceptibles, "Total infectados": total_infectados, "Graves": infectados_graves, "Críticos": infectados_criticos, "Leves": infectados_leves, "Recuperados": recuperados, "Rt": rt, "Recuento_zonas": recuento_zonas, "0-4": recuento_ge1, "5-19": recuento_ge2, "20-39": recuento_ge3, "40-59": recuento_ge4, ">60": recuento_ge5, "En_cuarentena": en_cuarentena, "Vivos": agentes_vivos, "Día": dia, "Contactos_prom_trabajo": prom_contactos_trabajo, "Contactos_prom_transporte": prom_contactos_transporte, "Contactos_prom_casa": prom_contactos_casa, "Nuevos_infectados": nuevos_infectados, "Detectados": detectados, "En_testing": en_testing, "En_cama": en_cama, "En_UCI": en_uci, "Detectados_por_intervencion": detectados_interv, "#Intervenidos": intervenidos }) self.running = True "Avanzar el modelo" def step(self): global PRUEBAS_DISPONIBLES global ACTIVACION_TESTING_ALEATORIO global ACTIVACION_CONTACT_TRACING global OLAS global ACTIVACION_CUARENTENA_ACORDEON global DIA_INICIO_ACORDEON global INTERVALO_ACORDEON global ACTIVACION_CUARENTENA global DIA_INICIO_CUARENTENA global DURACION_CUARENTENA global PORCENTAJE_EN_CUARENTENA self.datacollector.collect(self) self.actualizar_movilidad() self.cuarentena_regular(ACTIVACION_CUARENTENA, DIA_INICIO_CUARENTENA, DURACION_CUARENTENA, PORCENTAJE_EN_CUARENTENA) self.cuarentena_acordeon(ACTIVACION_CUARENTENA_ACORDEON, DIA_INICIO_ACORDEON, INTERVALO_ACORDEON) self.schedule.step() self.dinamica_hospitales() self.testing_aleatorio(PRUEBAS_DISPONIBLES, ACTIVACION_TESTING_ALEATORIO) self.contact_tracing(ACTIVACION_CONTACT_TRACING) #self.cuarentena_zonificada(0.2) def actualizar_movilidad(self): global MATRIZ_CASILLAS global MATRIZ_MOVILIDAD2 global MATRIZ_MOVILIDAD3 global ACUMULADA_MOVILIDAD2 global ACUMULADA_MOVILIDAD3 t = self.schedule.time agentes = [agent for agent in self.schedule.agents] if t == 35: for i in agentes: i.set_posf(ACUMULADA_MOVILIDAD2, MATRIZ_MOVILIDAD2, MATRIZ_CASILLAS) #print(i.unique_id," Estado:",i.estado, " zona_origen:",i.zona," zona_destino:",i.zona_destino) if t == 49: for i in agentes: i.set_posf(ACUMULADA_MOVILIDAD3, MATRIZ_MOVILIDAD3, MATRIZ_CASILLAS) #print(i.unique_id," Estado:",i.estado, " zona_origen:",i.zona," zona_destino:",i.zona_destino) def cuarentena_zonificada(self, porcentaje_cierre): global TIEMPO_ZONIFICACION agentes = [agent for agent in self.schedule.agents] zonas = [] #Saca la lista de zonas for i in agentes: zonas.append(i.zona) zonas = unique(zonas) #Cálculo del porcentaje de detectados para cada zona for i in range(len(zonas)): suma_agentes_en_zona = 0 suma_detectados = 0 for j in agentes: if j.zona == i: suma_agentes_en_zona += 1 suma_detectados += j.detectado porcentaje = suma_detectados / suma_agentes_en_zona if porcentaje > porcentaje_cierre: for j in agentes: if j.cuarentena == 0: j.activar_zonificacion(i, TIEMPO_ZONIFICACION) def cuarentena_regular(self, activacion, inicio, duracion, porcentaje): if activacion == True: t = self.schedule.time if t == inicio: agentes = [agent for agent in self.schedule.agents] print(activacion, inicio, duracion, porcentaje) for i in agentes: i.activar_cuarentena(activacion, porcentaje, duracion) #print(i.cuarentena," t:",i.tcuarentena, " dt:",i.dias_cuarentena) def cuarentena_acordeon(self, activacion, inicio, intervalo): global DIA_INICIO_ACORDEON global INTERVALO_ACORDEON global PORCENTAJE_EN_CUARENTENA if activacion == True: t = self.schedule.time if t == inicio: agentes = [agent for agent in self.schedule.agents] for i in agentes: i.activar_cuarentena(activacion, PORCENTAJE_EN_CUARENTENA, intervalo) DIA_INICIO_ACORDEON += 2 * INTERVALO_ACORDEON def contact_tracing(self, activacion): global PRUEBAS_DISPONIBLES if activacion == True: if PRUEBAS_DISPONIBLES > 0: lista_para_contact_tracing = [] lista_para_intervenir = [] agentes = [agent for agent in self.schedule.agents] for i in agentes: if i.para_contact == 1 and i.detectado == 1: lista_para_contact_tracing.append(i) if len(lista_para_contact_tracing) > 0: for i in lista_para_contact_tracing: i.recopilar_contactos(lista_para_intervenir) if len(lista_para_intervenir) > 0: lista_para_intervenir = unique(lista_para_intervenir) for i in lista_para_intervenir: if PRUEBAS_DISPONIBLES > 1: i.contact_tracing() PRUEBAS_DISPONIBLES -= 1 def testing_aleatorio(self, pruebas, activacion): global TIEMPO global PRUEBAS_DISPONIBLES global OLAS if activacion == True: t = self.schedule.time agentes = [agent for agent in self.schedule.agents] if t == TIEMPO and pruebas > 0 and OLAS > 0: disponibles = pruebas / OLAS if OLAS == 1: for i in range(pruebas): n_agente = random.choice(agentes) n_agente = self.agente_valido(n_agente) n_agente.testeado = 1 n_agente.intervencion = 1 PRUEBAS_DISPONIBLES -= 1 else: for i in range(round(disponibles)): n_agente = random.choice(agentes) n_agente = self.agente_valido(n_agente) n_agente.testeado = 1 n_agente.intervencion = 1 PRUEBAS_DISPONIBLES -= 1 TIEMPO += 3 OLAS -= 1 def dinamica_hospitales(self): global CAMAS_DISPONIBLES global UCIS_DISPONIBLES agentes = [agent for agent in self.schedule.agents ] #recopila los agentes del modelo agentes_para_hospital = [] #0. trabajar solo con el arreglo de agentes graves o críticos for i in agentes: if i.estado == 3 or i.estado == 4: agentes_para_hospital.append(i) liberar_cama = [] liberar_uci = [] requerir_cama = [] if len(agentes_para_hospital) > 0: for i in agentes_para_hospital: #crear arreglos para priorizar salidas sobre ingresos en la orden de ejecución if i.estado == 3 and i.en_cama == 0: #ingresa a los graves a hospitalización requerir_cama.append(i) if i.estado == 3 and i.en_cama == 1 and i.thospitalizado == 8: #sale de hospitalización liberar_cama.append(i) if i.estado == 4 and i.en_cama == 1 and i.thospitalizado >= 6: #sale de hospitalización a UCI liberar_cama.append(i) if i.estado == 4 and i.en_uci == 1 and i.tuci >= 10: liberar_uci.append(i) if i.estado == 4 and i.en_cama == 1 and i.thospitalizado == 6 and i.tcontagio >= 24: liberar_cama.append(i) #Se van a liberar las personas de la cama if len(liberar_cama) > 0: for i in liberar_cama: if i.estado == 3 and i.en_cama == 1: #libero cama si son solo hospitalizados i.en_cama = 0 CAMAS_DISPONIBLES += 1 if i.estado == 4: if i.en_cama == 1 and i.thospitalizado == 6 and i.tcontagio >= 24: #libero la cama de segunda estancia i.en_cama = 0 CAMAS_DISPONIBLES += 1 else: if i.en_cama == 1: suma = UCIS_DISPONIBLES - 1 if suma >= 0: #libero cama si lo puedo meter en UCI i.procesado = 1 i.en_cama = 0 i.thospitalizado = 0 CAMAS_DISPONIBLES += 1 i.en_uci = 1 UCIS_DISPONIBLES -= 1 else: i.procesado = 0 #Se van a liberar las UCIs y se meten en camas si hay disponibles if len(liberar_uci) > 0: #print("liberando UCIs") for i in liberar_uci: if i.en_uci == 1: suma = CAMAS_DISPONIBLES - 1 if suma >= 0: i.en_uci = 0 UCIS_DISPONIBLES += 1 i.en_cama = 1 CAMAS_DISPONIBLES -= 1 #Se van a asignar cama para los que las necesitan if len(requerir_cama) > 0: #print("asignado camas") for i in requerir_cama: if i.en_cama == 0: suma = CAMAS_DISPONIBLES - 1 if suma >= 0: i.en_cama = 1 i.procesado = 1 CAMAS_DISPONIBLES -= 1 def agente_valido(self, n_agente): if n_agente.testeado == 0 and n_agente.detectado == 0 and n_agente.edad > 17 and n_agente.edad < 70: return n_agente else: agentes = [agent for agent in self.schedule.agents] return self.agente_valido(random.choice(agentes))
class SugarscapeModel(Model): def __init__(self, height=50, width=50, init_agents=500, max_metabolism=3, max_vision=10, max_init_sugar=5, min_age=30, max_age=60, init_poll=3, ex_ratio=2, ex_mod=1, poll_growth_rule=True, inheritance_rule=True): self.height = height self.width = width self.init_agents = init_agents self.init_poll = init_poll self.max_metabolism = max_metabolism self.max_vision = max_vision self.max_init_sugar = max_init_sugar self.min_age = min_age self.max_age = max_age self.ex_ratio = ex_ratio self.ex_mod = ex_mod self.replacement_rule = True self.pollution_rule = False self.diffusion_rule = False self.push_rule = False self.poll_growth_rule = poll_growth_rule self.expend_rule = True self.inheritance_rule = inheritance_rule self.map = self.import_map() self.grid = MultiGrid(height, width, torus=True) self.schedule = RandomActivationByType(self) self.datacollector = DataCollector({'Pollution': (lambda m: m.total_pollution), 'Wealth': (lambda m: m.total_wealth/m.init_agents), 'Agents': (lambda m: len(m.schedule.agents_by_type[ScapeAgent]))}, {'Wealth': self.collect_wealth, 'Metabolism': self.collect_metabolism, 'Vision': self.collect_vision}) self.total_wealth = 0 self.total_pollution = 0 self.populate_sugar() self.populate_agents() def step(self): ''' Step method run by the visualization module''' self.schedule.step([ScapeAgent, SugarPatch]) self.datacollector.collect(self) # if self.schedule.time == 20: # self.pollution_rule = True if self.schedule.time == 30: self.push_rule = True self.total_wealth = 0 self.total_pollution = 0 for agent in self.schedule.agents_by_type[ScapeAgent]: self.total_wealth += agent.wealth for patch in self.schedule.agents_by_type[SugarPatch]: self.total_pollution += patch.pollution def import_map(self): ''' Imports a text file into an array to be used when generating and placing the sugar Agents into the grid ''' f = open('Maps/sugar_map.txt', 'r') map_list = [] for line in f: num_list = line.split(' ') for num in num_list: map_list.append(int(num[0])) return map_list def new_agent(self, uid, inheritance): ''' Place a new agent on the sugarscape in order to replace a death''' free = False while not free: location = random.choice([cell for cell in self.grid.coord_iter()]) if len(location[0]) == 1: free = True pos = (location[1], location[2]) patch = self.grid.get_cell_list_contents([pos])[0] if self.inheritance_rule: if inheritance == 'rand': wealth = random.randint(1, self.max_init_sugar) else: wealth = inheritance else: wealth = random.randint(1, self.max_init_sugar) agent = ScapeAgent(uid, pos, wealth, random.randint(1,self.max_metabolism), random.randint(1,self.max_vision), random.randint(self.min_age, self.max_age), patch, self.ex_ratio, self.ex_mod) self.grid.place_agent(agent, agent.pos) self.schedule.add(agent) def populate_agents(self): ''' Place ScapeAgent's in random unoccupied locations on the grid with randomomized sets of parameters ''' cells = [(cell[1], cell[2]) for cell in self.grid.coord_iter()] for i in range(self.init_agents): uid = 'a' + str(i) location = random.choice(cells) cells.remove(location) patch = self.grid.get_cell_list_contents([location])[0] agent = ScapeAgent(uid, location, random.randint(1,self.max_init_sugar), random.randint(1,self.max_metabolism), random.randint(1,self.max_vision), random.randint(self.min_age, self.max_age), patch, self.ex_ratio, self.ex_mod) self.grid.place_agent(agent, location) self.schedule.add(agent) def populate_sugar(self): ''' Place SugarPatch's on every cell with maximum sugar content according to the imported 'sugar_map.txt' file ''' map_i = 0 for cell in self.grid.coord_iter(): x = cell[1] y = cell[2] uid = 's'+str(y)+str(x) # patch = SugarPatch(uid, (x,y), 3) patch = SugarPatch(uid, (x,y), self.map[map_i], self.init_poll) self.grid.place_agent(patch, (x,y)) self.schedule.add(patch) map_i += 1 def collect_wealth(self, agent): '''Method for datacollector''' if isinstance(agent, ScapeAgent): return agent.wealth def collect_metabolism(self, agent): '''Method for datacollector''' if isinstance(agent, ScapeAgent): return agent.metabolism def collect_vision(self, agent): '''Method for datacollector''' if isinstance(agent, ScapeAgent): return agent.vision def calc_gini(self, wealths): '''Returns gini coefficient''' sort_wealths = sorted(wealths) num_agents = len(sort_wealths) gini,count = 0,0 for wealth in sort_wealths: gini += wealth * (num_agents - count) count += 1 gini /= (num_agents*sum(sort_wealths)) return num_agents**(-1) - 2*gini + 1