Support multiple spaces (using observable positions)#3043
Support multiple spaces (using observable positions)#3043
Conversation
Not validated yet, just as an illustration
|
Currently we save the membership of agents to cell spaces in both in the Agent |
|
Some random thoughts.
# Create aligned spaces (all use the same coordinate system)
self.continuous = ContinuousSpace([[0, 10], [0, 10]], random=self.random)
self.grid = OrthogonalMooreGrid([10, 10], random=self.random, shared_coordinates=self.continuous)
self.hex_grid = HexGrid([10, 10], random=self.random, shared_coordinates=self.continuous)Clearly, the keyword name
|
As indicated under 3 and 4, I am not sure about this design in the first place. Is it a property of the agents to be present in multiple spaces, or is it a relationship between spaces within which agents reside? |
|
Thanks for your insights. There are certainly trade offs in this design. I will get back to some of your questions and thoughts later. Maybe we need to take some time to meet up and align goals, design directions and possible implementations. I feel like al the ideas are there, it just needs to come together. |
|
A few initial responses:
# Both work:
self.position = [5.0, 5.0] # Direct assignment, all spaces sync
self.model.grid.move(self, target_cell, align="center") # Space-guided movementWhat doesn't work, is changing We might allow custom cell names for each space. So one space might use
I don't subscribe to core idea of that there should be one "master" space. A (discrete) space is an division of area, and each division of area could have certain (zero to n) properties.
|
Can you elaborate on this because I don't understand what you are trying to say.
I believe this is a crucial question we need to address, as it has profound design implications. You seem inclined to go with the first because you wrote "agents using multiple spaces". I am inclined to the second because, in my view, spaces have relations via a coordinate system that allows translation. The second also seems more GIS-like, but that is more of a hunch. |
This is the proper GIS way. I think this is the most powerful way to approach this, while its overkill for many models. I think the concept of neighbours is also a bit different from discrete spaces, but the question is also how important discrete-neighbour calling really is. I also suspect performance is vastly different than our solutions, but maybe @wang-boyu can give some insights on it. I must say I was initially leaning this mesa-geo style way, (see the
Discrete spaces are a way to chop up a plane (or space) into fragments. As long as they are the exact same fragments, you can work with properties or property layers. As soon as you have different fragments, we call it a new "space".
Oh no I fully support the latter over the former. Only, I recognize:
So basically, while this is my take on how to do the former, mesa.world was my (GIS-style) take on how to do the latter. |
Ok, that makes sense. However, spaces have a lot more functionality than property layers. Most notably, of course, distance and neighborhood stuff.
Ok, that helps a lot. But that means, in my view, that relationships between spaces should be defined at the level of spaces, not indirectly at the agent level.
I am not sure how much performance you save by this. In cell spaces, the primary cost is finding the cells. In continuous spaces, it involves a distance calculation, but we can test how this scales with the number of agents. Additionally, from a design perspective, you currently have agents opting in. An alternative might be an opt-out. Therefore, by default, if an agent is present in any space that is part of a collection of shared spaces, it has access to all spaces within that collection.
Can you give an example? |
|
We have this and #3034, which have been useful for pathfinding, but do we need to keep them open? They are linked to from the relevant discussions. Its clear that neither will be merged. |
|
Yes, we can close them. I'm good with you having the lead on space implementation. We're aligned on direction. To be continued in #2585. |
|
As @tpike3 / @edgeofchaos42 wrote
So what is needed is a clean implementation for adding and removing agents from a meta agent. This probably requires some tracking mechanism inside MetaAgent. |
|
I think this comment was in the wrong PR |
|
No idea how that happend. I'll move it later to the right place. |
Proof of concept
Summary
This PR implements support for agents existing in multiple aligned spatial representations simultaneously (e.g., continuous space + grid + hex grid), with automatic synchronization across all spaces through a unified position model.
Motive
Current Mesa models are limited to agents existing in a single space. However, many real-world models benefit from multiple spatial views:
The key challenge is maintaining consistency: when an agent moves, all spatial representations must update correctly and efficiently.
Implementation
Core Architecture: Position as Single Source of Truth
Agents now have a unified
agent.position(numpy array) that serves as the authoritative location. All spaces reference this shared position rather than maintaining separate copies:Observable Position Pattern
Discrete spaces (grids, hex grids) subscribe to position updates via an observable pattern. When
agent.positionchanges, the setter automatically notifies registered spaces to update cell membership:cell.agentsto be correct)Space API Changes
Spaces now provide:
space.add(agent)- Register agent in spacespace.cell(agent)- Read-only query of current cellspace.move(agent, target_cell, align="center")- Move agent, updating positionspace.position_to_cell(position)- Convert position to cell (O(1) for grids, O(log n) for Voronoi)space.cell_to_position(cell)- Get canonical position for cell (typically center)Efficient Position-to-Cell Conversion
Each space type implements efficient coordinate conversion:
floor(x),floor(y)Usage Examples
Movement Options
Spaces provide flexible positioning within cells:
For a full example model, see the implemented example model in this PR.
Additional Notes
Backwards Compatibility:
agent.posis preserved for compatibility. New code should useagent.position.Performance: Zero overhead for single-space models (current behavior). Multi-space models have minimal overhead:
Future Work:
Related Discussions:
Feedback appreciated!