Skip to content

[Feature]: adding abstraction of optimal agent movement #108

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
adamamer20 opened this issue Oct 28, 2024 · 4 comments
Open

[Feature]: adding abstraction of optimal agent movement #108

adamamer20 opened this issue Oct 28, 2024 · 4 comments
Labels
feature New functionality added to the project.
Milestone

Comments

@adamamer20
Copy link
Member

It would be beneficial to have a function in the DiscreteSpaceDF (and AgentContainer) for moving agents based on attributes:

move_to(agents: AgentLike, attr_names: str | list[str], rank_order: ['max' | 'min'] | list['max' | 'min'])

For example: move_to('sugar', 'max'). This would abstract the code for handling sequential conflicts, making it easier than handling them from scratch each time.

@adamamer20 adamamer20 added the feature New functionality added to the project. label Oct 28, 2024
@suryanshgargbpgc
Copy link

hi @adamamer20, I tried to understand this issue, if I am correct this feature aims to write a function which upon calling would solve the issue of multiple agents trying to move on the same grid at the same time which will prevent us from dealing with those edge cases everytime.
Can you please share me necessary resources which can help me address this issue ?
Also could you please elaborate on any points i missed.

@adamamer20
Copy link
Member Author

@suryanshgargbpgc You're correct in your understanding! I recommend checking out the sugarscape example for polars to get a clear picture of these concurrency conditions. You can see it here:

https://github.com/projectmesa/mesa-frames/blob/1d7b3ed11a61130cbee12fe0c9222d233b234669/examples/sugarscape_ig/ss_polars/agents.py#L174C1-L225C73

In this example, the best move might be the same for multiple agents at the same time. Since we're moving all ants simultaneously in a vectorized way, it's important to address this issue. I handled it this way in sugarscape, and I believe the same reasoning can be generalized to accommodate various agent attribute objectives, removing the burden of the implementation on the user

@suryanshgargbpgc
Copy link

Hi @adamamer20, sorry I had my exams, I was thinking the function could look something like

First, the function gathers all possible moves for each agent into a list. Each move records the candidate grids’ attribute value (like sugar) and a random number when conflict occurs. Next, the list is sorted so that grids with the best sugar value comes first (with the random number resolving ties). Then, the function iterates through the sorted moves and assigns each agent to the target grid if that agent hasn’t been assigned a move yet and the grid is still free. If an agent doesn’t secure a new grid, it remains in its original position. Finally, the agents’ positions are updated accordingly.
We can iterate through the list for low to high attribute value if the agent is avoiding the grid.

does it look fine?

@adamamer20
Copy link
Member Author

adamamer20 commented Mar 14, 2025

Hey @suryanshgargbpgc! Thanks for sharing the idea—it’s definitely an interesting approach. I have a few considerations that might help refine it:

  1. Iterating directly over rows in Python can become a bottleneck. One way around this is to use vectorized operations in Polars or even a compiled approach with Numba or Cython. You can see an example of how I’ve tried different methods in my code here. and here's you can see the results. Note that Polars has a lazy mode (docs) that can optimize queries further, though I haven’t fully tested that yet.

  2. Typically, “random activation” means we shuffle the agent list once at the start of a step and process them in that random order. Your proposal uses randomness for conflict resolution—that is, deciding who gets a cell when multiple agents want it.
    That can be totally fine if all you do in that step is move agents. But if there are other actions that also depend on the order of activation (e.g., agent interactions, resource consumption, etc.), then you’re effectively introducing multiple “random orders” in a single step. That might or might not matter, depending on the modeling goals. It’s an interesting idea, and it could even speed things up!

  3. Keep in mind scenarios where agent A is blocked by agent B, and agent B is blocked by agent C. If C moves, then B can move into C’s old spot, and A can move into B’s old spot. Make sure your approach handles that chain of moves correctly, so that an agent truly gets unblocked when another agent vacates a cell.

If you’d like to try building this out, feel free to open a PR! I’d be happy to help if you get stuck. It’s not the easiest problem to implement, but it’s definitely one of the more interesting ones. Good luck!

@adamamer20 adamamer20 added this to the 0.1.0-stable milestone Mar 18, 2025
@adamamer20 adamamer20 changed the title feat: adding abstraction of optimal agent movement [Feature]: adding abstraction of optimal agent movement Mar 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New functionality added to the project.
Projects
None yet
Development

No branches or pull requests

2 participants