def __call__(self, **kwargs): """ Agents will 'act' by being called as a function. If the agent has no `action()` function, do nothing. If returns False, by default agent will move. """ self.duration -= 1 acted = False moved = False if self.duration > 0: if self.action is not None: acted = True # the action was defined outside this class, so pass self: if not self.action(self, **kwargs): # False return means agent is "unhappy" and # so agent will move (if located). max_move = DEF_MAX_MOVE if "max_move" in self: max_move = self["max_move"] angle = None if "angle" in self: angle = self["angle"] self.move(max_move=max_move, angle=angle) moved = True elif DEBUG2: user_log_notif("I'm " + self.name + " and I have no action!") else: self.active = False return acted, moved
def tree_action(agent, **kwargs): """ This is what trees do each turn in the forest. """ execution_key = get_exec_key(kwargs=kwargs) old_state = agent["state"] if is_healthy(agent): if exists_neighbor(agent, pred=is_on_fire, execution_key=execution_key): if DEBUG2: user_log_notif("Setting nearby tree on fire!") agent["state"] = NF # if we didn't catch on fire above, do probabilistic transition: if old_state == agent["state"]: # we gotta do these str/int shenanigans with state cause # JSON only allows strings as dict keys agent["state"] = \ str(prob_state_trans(int(old_state), get_env_attr(TRANS_TABLE, execution_key=execution_key))) if DEBUG2: if agent["state"] == NF: user_log_notif("Tree spontaneously catching fire.") if old_state != agent["state"]: # if we entered a new state, then... env = get_env(execution_key=execution_key) group_map = get_env_attr(GROUP_MAP, execution_key=execution_key) if group_map is None: user_log_err("group_map is None!") return True agent.has_acted = True env.add_switch(agent, group_map[old_state], group_map[agent["state"]]) return True
def set_env_attrs(execution_key=CLI_EXEC_KEY): user_log_notif("Setting env attrs for " + MODEL_NAME) set_env_attr(GROUP_MAP, {HE: HEALTHY, EX: EXPOSED, IN: INFECTED, CN: CONTAGIOUS, DE: DEAD, IM: IMMUNE}, execution_key) set_env_attr("census_func", epidemic_report, execution_key)
def main(): global trader_group global max_utility (trader_group, max_utility) = set_up() if DEBUG.debug2: user_log_notif(get_env().__repr__()) get_env()() return 0
def change_color(agent, society, opp_group): """ change agent's DISPLAY_COLOR to its opposite color """ if DEBUG2: user_log_notif("Agent " + agent.name + " is changing colors" + "; its prim group is " + agent.prim_group_nm()) agent[DISPLAY_COLOR] = not agent[DISPLAY_COLOR] society.add_switch(agent, agent.prim_group_nm(), opp_group[agent.prim_group_nm()])
def set_env_attrs(execution_key=CLI_EXEC_KEY): """ I actually don't think we need to do this here! It can be done once in set_up(). """ user_log_notif("Setting env attrs for forest fire.") set_env_attr(GROUP_MAP, { HE: HEALTHY, NF: NEW_FIRE, OF: ON_FIRE, BO: BURNED_OUT, NG: NEW_GROWTH }, execution_key)
def move(self, max_move=DEF_MAX_MOVE, angle=None): """ Move this agent to a random pos within max_move of its current pos. """ if (self.is_located() and self.locator is not None and not self.locator.is_full()): new_xy = None if angle is not None: if DEBUG2: user_log_notif("Using angled move") new_xy = self.locator.point_from_vector( angle, max_move, self.pos) self.locator.place_member(self, max_move=max_move, xy=new_xy)
def join(agent1, agent2): """ Create connection between agent1 and agent2. """ if not is_composite(agent1): user_log_err("Attempt to place " + str(agent2) + " in non-group " + str(agent1)) return False else: if not agent1.add_member(agent2): user_log_notif("Could not add mbr " + str(agent2) + " to " + str(agent1)) if not agent2.add_group(agent1): user_log_notif("Could not add grp " + str(agent2) + " to " + str(agent1)) return True
def set_up(props=None): """ A func to set up run that can also be used by test code. """ global max_utility pa = init_props(MODEL_NAME, props, model_dir="capital") trader_group = Composite("trader", {"color": BLUE}, member_creator=create_trader, props=pa, num_members=get_prop('num_traders', DEF_NUM_TRADER)) Env("env", height=get_prop('grid_height', DEF_HEIGHT), width=get_prop('grid_width', DEF_WIDTH), members=[trader_group]) for trader in trader_group: allocate_resources(trader_group[trader], GOODS) user_log_notif(trader_group[trader]["goods"]) return (trader_group, max_utility)
def switch(agent_nm, grp1_nm, grp2_nm, execution_key=None): """ Move agent from grp1 to grp2. We first must recover agent objects from the registry. """ agent = get_registration(agent_nm, execution_key=execution_key) if agent is None: user_log_notif("In switch; could not find agent: " + str(agent)) grp1 = get_group(grp1_nm, execution_key=execution_key) if grp1 is None: user_log_notif("In switch; could not find from group: " + str(grp1)) grp2 = get_group(grp2_nm, execution_key=execution_key) if grp2 is None: user_log_notif("In switch; could not find to group: " + str(grp2)) split_em = split(grp1, agent) joined_em = join(grp2, agent) if DEBUG and split_em and joined_em: user_log_notif("Switched agent " + str(agent) + " from grp " + grp1_nm + "(id: " + str(id(grp1)) + ")" + " to grp " + grp2_nm + "(id: " + str(id(grp2)) + ")")
def set_env_attrs(execution_key=CLI_EXEC_KEY): user_log_notif("Setting env attrs for " + MODEL_NAME)
def set_env_attrs(execution_key=CLI_EXEC_KEY): user_log_notif("Setting env attrs for " + MODEL_NAME) set_env_attr("pop_hist_func", record_price, execution_key=execution_key) set_env_attr("census_func", market_report, execution_key=execution_key)
def switch_groups(self, g1, g2): if not self.del_group(g1): user_log_notif("Could not delete ", str(g1)) if not self.add_group(g2): user_log_notif("Could not add agent to ", str(g2))
def person_action(agent, **kwargs): """ This is what people do each turn in the epidemic. """ execution_key = get_exec_key(kwargs=kwargs) infec_dist = get_prop('infection_distance', DEF_INFEC_DIST, execution_key=execution_key) old_state = agent[STATE] if is_healthy(agent): distance_mod = 1 if agent["is_wearing_mask"]: distance_mod = 0.5 curr_reg = CircularRegion(center=agent.get_pos(), radius=(2 * infec_dist * distance_mod), execution_key=execution_key) sub_reg = curr_reg.create_sub_reg(center=agent.get_pos(), radius=(infec_dist * distance_mod), execution_key=execution_key) agent_list = sub_reg.get_agents(exclude_self=True) if (agent_list is not None and (len(agent_list) > 0)): if DEBUG2: user_log_notif("Exposing nearby people!") agent[STATE] = EX else: for curr_agent in curr_reg.get_agents(exclude_self=True): curr_distance = (distance(curr_agent, agent) - DEF_INFEC_DIST) if (curr_distance > infec_dist and curr_distance <= (infec_dist * 2)): inverse_square_val = ((1 / (curr_distance ** 2)) * distance_mod) if inverse_square_val > 0: r = random() if inverse_square_val / 100 > r: agent[STATE] = EX # if we didn't catch disease above, do probabilistic transition: if old_state == agent[STATE]: # we gotta do these str/int shenanigans with state cause # JSON only allows strings as dict keys agent[STATE] = str(prob_state_trans(int(old_state), STATE_TRANS)) if agent[STATE] == EX: user_log_notif("Person spontaneously catching virus.") if old_state != agent[STATE]: # if we entered a new state, then... group_map = get_env(execution_key=execution_key).get_attr(GROUP_MAP) if group_map is None: user_log_err("group_map is None!") return DONT_MOVE agent.has_acted = True get_env(execution_key=execution_key).add_switch(agent, group_map[old_state], group_map[ agent[STATE]]) if is_dead(agent): return DONT_MOVE if not is_isolated(agent, **kwargs): social_distancing(agent, **kwargs) return MOVE
def set_up(props=None): """ A func to set up run that can also be used by test code. """ pa = init_props(MODEL_NAME, props, model_dir="capital") execution_key = int(props[EXEC_KEY].val) \ if props is not None else CLI_EXEC_KEY num_traders = get_prop('num_traders', DEF_NUM_TRADER, execution_key=execution_key) trader_group = Composite("trader", {"color": BLUE}, member_creator=create_trader, props=pa, num_members=num_traders, execution_key=execution_key) Env(MODEL_NAME, height=get_prop('grid_height', DEF_HEIGHT, execution_key=execution_key), width=get_prop('grid_width', DEF_WIDTH, execution_key=execution_key), members=[trader_group], execution_key=execution_key) set_env_attrs(execution_key=execution_key) num_resources = get_prop('num_resources', DEF_NUM_RESOURCES, execution_key=execution_key) MKT_GOODS = { "truck": { AMT_AVAIL: num_resources, UTIL_FUNC: "steep_util_func", "incr": 0, COMPLEMENTS: ["fuel", "land"] }, "penguin": { AMT_AVAIL: num_resources, UTIL_FUNC: "steep_util_func", "incr": 0, COMPLEMENTS: ["pet_food", "meat"] }, "pet_food": { AMT_AVAIL: num_resources, UTIL_FUNC: "steep_util_func", "incr": 0, COMPLEMENTS: ["penguin", "meat"] }, "fuel": { AMT_AVAIL: num_resources, UTIL_FUNC: "steep_util_func", "incr": 0, COMPLEMENTS: ["truck", "land"] }, "land": { AMT_AVAIL: num_resources, UTIL_FUNC: "steep_util_func", "incr": 0, COMPLEMENTS: ["truck", "fuel"] }, "meat": { AMT_AVAIL: num_resources, UTIL_FUNC: "steep_util_func", "incr": 0, COMPLEMENTS: ["penguin", "pet_food"] } } for trader in trader_group: for i in range(len(MKT_GOODS) // num_traders): allocate_resources(trader_group[trader], MKT_GOODS) user_log_notif(repr(trader_group[trader]["goods"]))
def set_env_attrs(execution_key=CLI_EXEC_KEY): user_log_notif("Setting env attrs for forest fire.") width = get_prop('grid_width', DEF_WIDTH, execution_key=execution_key) height = get_prop('grid_height', DEF_HEIGHT, execution_key=execution_key) get_env(execution_key).attrs["center"] = get_env(execution_key)\ .get_agent_at(height // 2, width // 2)
def set_env_attrs(): user_log_notif("Setting env attrs for " + MODEL_NAME) set_env_attr("census_func", height_rpt)
def set_env_attrs(execution_key=CLI_EXEC_KEY): user_log_notif("Setting env attrs for " + MODEL_NAME) set_env_attr("pop_hist_func", attendance, execution_key) set_env_attr("census_func", attendance_report, execution_key)
def run_notice(model_nm): return reg.user_log_notif(model_nm)