-
-
Notifications
You must be signed in to change notification settings - Fork 1k
Description
The current movement implementation in the wolf-sheep model performs redundant checks when agents search their neighborhood for valid moves, after #2503.
mesa/mesa/examples/advanced/wolf_sheep/agents.py
Lines 70 to 72 in dd77c0a
cells_without_wolves = self.cell.neighborhood.select( | |
lambda cell: not any(isinstance(obj, Wolf) for obj in cell.agents) | |
) |
mesa/mesa/examples/advanced/wolf_sheep/agents.py
Lines 78 to 82 in dd77c0a
cells_with_grass = cells_without_wolves.select( | |
lambda cell: any( | |
isinstance(obj, GrassPatch) and obj.fully_grown for obj in cell.agents | |
) | |
) |
mesa/mesa/examples/advanced/wolf_sheep/agents.py
Lines 103 to 105 in dd77c0a
cells_with_sheep = self.cell.neighborhood.select( | |
lambda cell: any(isinstance(obj, Sheep) for obj in cell.agents) | |
) |
This could be performance optimized. Two promising optimization approaches:
-
Early exit strategy
Instead of checking every cell in the neighborhood for agent types, we can break out of loops early once a valid cell is found. For example, when a sheep checks for wolves, it can immediately skip a cell once a wolf is detected rather than continuing to check other agents. -
PropertyLayer-based vectorization
We can leverage Mesa's PropertyLayer to track wolf and grass positions as boolean layers. By having wolves and grass patches update their position in the property layer during movement, we can perform vectorized operations to find valid moves instead of iterating through agent lists. This would allow expressing the entire movement logic using fast numpy operations.
Trade-offs:
- Early exits: Simpler implementation but more limited gains
- PropertyLayer: More complex but potentially much faster for large grids, at cost of extra memory
Worth benchmarking both approaches against current implementation with different model parameters.
Somewhat related: