Source code for Steppables

[docs]class Steppable(object): """ Represents generic steppable object. Steppables represent entities which can be added to the schedule and whose logic is excuted once per epoch. Steppables implement a prologue, main and epilogue. All prologues for all steppables are executed first, followed by all mains followed by all epilogues. """ def __init__(self): pass
[docs] def step_prologue(self, model): """ Placeholder to enforce that all steppables implement a stepPrologue method with the correct signature. Per se, this method does nothing but can be overridden by child classes. Parameters ---------- model : Model The instance of the model to which the schedule to which the agent belong is bound. """ pass
[docs] def step_main(self, model): """ Placeholder to enforce that all steppables implement a stepMain method with the correct signature. Per se, this method does nothing but can be overridden by child classes. Parameters ---------- model : Model The instance of the model to which the schedule to which the agent belong is bound. """ pass
[docs] def step_epilogue(self, model): """ Placeholder to enforce that all steppables implement a stepEpilogue method with the correct signature. Per se, this method does nothing but can be overridden by child classes. Parameters ---------- model : Model The instance of the model to which the schedule to which the agent belong is bound. """ pass
[docs]class Agent(Steppable): """ An agent represents a self-contained unit in the simulation with a state, a beahaviour and which may interact with, be affected by and affect the environment and other agents. A simulation may have multiple agent classes. Examples of agent classes may include people, tissue cells, etc. """ def __init__(self): # This is a dictionary mapping an environment name to a position. # This is so we don't have to do a search # on the environment grid each time we want to know our position. At # the same time, it's useful to also have # a grid of agents to quickly search neighbourhoods. self.environment_positions = dict()
[docs] def add_agent_to_grid(self, environment_name, position, model): """ Adds an agent to a position in a grid. This both updates the state of the grid (via API calls to the grid object) **and** the internal state of the agent. This does **not** check if the agent already exists in the grid. So, it potentially allows for the agent to be added to the same grid multiple times. This method does check whether a position is valid, and where that is not the case the agent is not added and a warning is printed to screen. Parameters ---------- environment_name : string The name of the environment to which the agent should be added. This should match the name property in the environment object. position : tuple The position to which the agent will be added. This should be given as a tuple of two or three values, depending if this object grid is associated to a 2D or 3D environment. model : Model The instance of the model on which the simulation is based. """ env = model.environments[environment_name] if env.valid_position(position): self.environment_positions[environment_name] = position env.add_agent(self, position) else: print("Invalid position %s on grid %s" % ( str(position), environment_name))
[docs] def move_agent(self, environment_name, position_new, model): """ Moves an agent from a position to another in an environment. This both updates the state of the grid (via API calls to the grid object) **and** the internal state of the agent. This method does check whether a position is valid, and where that is not the case the agent is not moved and a warning is printed to screen. Parameters ---------- environment_name : string The name of the environment to which the agent should be added. This should match the name property in the environment object. position_new : tuple The position to which the agent will be moved to. This should be given as a tuple of two or three values, depending if this object grid is associated to a 2D or 3D environment. model : Model The instance of the model on which the simulation is based. """ env = model.environments[environment_name] if env.valid_position(position_new): position_old = self.environment_positions[environment_name] # Updating the agent's internal representation self.environment_positions[environment_name] = position_new # Asking the environment to update its internal representation env.move_agent(self, position_old, position_new)
[docs] def remove_agent_from_grid(self, environment_name, model): """ Removes an agent from an environment. This both updates the state of the grid (via API calls to the grid object) **and** the internal state of the agent. This method does not check if an agent exists in an environment, but if it doesn't the method is trivially void. Parameters ---------- environment_name : string The name of the environment to which the agent should be added. This should match the name property in the environment object. model : Model The instance of the model on which the simulation is based. """ env = model.environments[environment_name] position = self.environment_positions[environment_name] env.remove_agent(self, position) self.environment_positions[environment_name] = None
[docs] def remove_agent(self, model): """ Removes an agent from the simulation. This removes the agent all environments and from the schedule. In removing an agent from all environments, the internal state of the agent is also updated. In practice, the agent is not immediately removed from the schedule but is added to the list of agents to remove and will be removed at the following epcoh. Parameters ---------- model : Model The instance of the model on which the simulation is based. """ envs = self.environment_positions.keys() for env in envs: self.remove_agent_from_grid(env, model) model.schedule.agents_to_remove.add(self)
[docs]class Helper(Steppable): """ A placeholder class to allow for helper steppables to have their own data-type. A helper allows to encapsulate logic that should be executed at each time-step, but which does not belong to any agent. Common examples could include functions to save text or graphics to an output file, record model properties, update environment properties, etc. This class does not provide methods or attributes, but allows for the "Helper" data-type to exist which is a bit more informative than simply having objects of 'Steppable' type. """ def __init__(self): pass