Open EwoutH opened 8 months ago
I was thinking about how this would integrate with the _PropertyGrid introduced in https://github.com/projectmesa/mesa/pull/1898. That currently offers separate functions for the selection of target cells, and then moving to the target cells.
def select_cells_by_properties():
def move_agent_to_cell_by_properties():
def select_extreme_value_cells():
def move_agent_to_extreme_value_cell():
If move_agent
would also take a list or mask of target cells, that could allow removing the two movement methods from #1898, and make the API more consistent. All movement goes through move_agents
, and any amount of custom methods can be written to select some target cells.
Currently, #1898 also include two mask functions which limit the number of candidate cells to cells empty or in a neighborhood.
def get_empty_mask():
def get_neighborhood_mask():
We might also want to integrate that into the move_agent
method. It could take a mask or a list of masks.
A utility method to combine a list of masks into a single mask could also be provided.
Maybe we can combine things:
def move_agent(agent, pos=None, empty=False, neighborhood=None, mask=None, selection="random"):
@jackiekazil @tpike3 Same story as with #1905, I would like to discuss and potentially implement this before moving on the PropertyLayer (#1898), since this is a more generalized solution for a problem that I specifically solve in that PR. So if we can implement this, it would make especially the _PropertyGrid in #1898 a lot simpler.
So my specific questions are:
move_agent()
movement method to allow moving to an empty, random or neighbouring cell?I went for a relatively simple implementation: The move_agent
method now can take a list of positions and choose either one randomly or the closest:
Selecting neighborhoods and empty cells can be done with other functions, and support for masks will be added in #1898.
There is still possibility for improvement here. The current most elegant way to place an agent on an empty cell I discovered is:
self.grid.place_agent(agent, pos=mesa.model.random.choice(list(self.grid.empties)))
This can't be the best way. The current problems are:
place_agent
doesn't directly allow selecting an empty cell, or a random cell for that matter. It needs a single position, and doesn't allow a list of positions like move_agent
move_to_empty
, move_agent_to_one_of
and move_agent
) require a current position to be had, since they call remove_agent
internally.I would like to discuss how we can make placing an agent on a random empty cell more elegant.
The Mesa Space module allows a few specific agent movements and interactions within a grid environment. However, the current methods lack a consistent way to apply different movement strategies. This proposal suggests integrating a single, versatile
move_agent
method, accepting a parameter that can either be a tuple for specific coordinates, a string indicating a movement strategy (like "random" or "empty"), or an object defining a neighborhood.In the future, it can be extended with movement strategies based on properties (see #1898).
Motivation
I was building a toy model, and
just looked weird and limited.
Proposed changes
Unified move method:
move_agent(agent: Agent, destination) → None
destination
parameter is versatile:(x, y)
for moving the agent to specific coordinates."random"
for a random cell,"empty"
for a random empty cell.Retiring redundant methods:
move_to_empty
andplace_agent
would be redundant and can be removed, as their functionalities are integrated into the newmove_agent
.Enhanced out-of-bounds and validity checking:
out_of_bounds
method, but possibly enhance it to include checks for cell occupancy, ensuring valid movement destinations.Agent removal and position swapping:
remove_agent
andswap_pos
methods remain useful and unchanged.Example Implementations
Conclusion
This proposal aims to simplify and unify the movement methods in the Mesa Space module. By consolidating various movement strategies into a single method, we enhance the API's usability and flexibility, allowing users to execute complex movements with minimal and more intuitive code.
Notes
Structural Pattern Matching in Python 3.10 might help a lot with the implementation.