Skip to content

Commit 6e62857

Browse files
EwoutHtpike3
authored andcommitted
Native support for multiple agent types
Tracks agents in the model with a defaultdict. This PR adds a new `agents` dictionary to the Mesa `Model` class, enabling native support for handling multiple agent types within models. This way all modules can know which agents and agents type are in the model at any given time, by calling `model.agents`. NetLogo has had agent types, called [`breeds`](https://ccl.northwestern.edu/netlogo/docs/dict/breed.html), built-in from the start. It works perfectly in all NetLogo components, because it's a first class citizen and all components need to be designed to consider different breeds. In Mesa, agent types are an afterthought at best. Almost nothing is currently designed with multiple agent types in mind. That has caused several issues and limitations over the years, including: - #348 - #1142 - #1162 Especially in scheduling, space and datacollection, lack of a native, consistent construct for agent types severely limits the possibilities. With the discussion about patches and "empty" this discussion done again. You might want empty to refer to all agents or only a subset of types or single type. That's currently cumbersome to implement. Basically, by always having dictionary available of which agents of which types are in the model, you can always trust on a consistent construct to iterate over agents and agent types. - The `Model` class now uses a `defaultdict` to store agents, ensuring a set is automatically created for each new agent type. - The `Agent` class has been updated to leverage this feature, simplifying the registration process when an agent is created. - The `remove` method in the `Agent` class now uses `discard`, providing a safer way to remove agents from the model.
1 parent 3b326c8 commit 6e62857

File tree

2 files changed

+26
-4
lines changed

2 files changed

+26
-4
lines changed

mesa/agent.py

+19-4
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,34 @@
2020

2121

2222
class Agent:
23-
"""Base class for a model agent."""
23+
"""
24+
Base class for a model agent in Mesa.
25+
26+
Attributes:
27+
unique_id (int): A unique identifier for this agent.
28+
model (Model): A reference to the model instance.
29+
self.pos: Position | None = None
30+
"""
2431

2532
def __init__(self, unique_id: int, model: Model) -> None:
26-
"""Create a new agent.
33+
"""
34+
Create a new agent.
2735
2836
Args:
29-
unique_id (int): A unique numeric identified for the agent
30-
model: (Model): Instance of the model that contains the agent
37+
unique_id (int): A unique identifier for this agent.
38+
model (Model): The model instance in which the agent exists.
3139
"""
3240
self.unique_id = unique_id
3341
self.model = model
3442
self.pos: Position | None = None
3543

44+
# Register the agent with the model using defaultdict
45+
self.model.agents[type(self)].add(self)
46+
47+
def remove(self) -> None:
48+
"""Remove and delete the agent from the model."""
49+
self.model.agents[type(self)].discard(self)
50+
3651
def step(self) -> None:
3752
"""A single step of the agent."""
3853

mesa/model.py

+7
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from __future__ import annotations
99

1010
import random
11+
from collections import defaultdict
1112

1213
# mypy
1314
from typing import Any
@@ -41,6 +42,12 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
4142
self.running = True
4243
self.schedule = None
4344
self.current_id = 0
45+
self.agents: defaultdict[type, set] = defaultdict(set)
46+
47+
@property
48+
def agent_types(self) -> list:
49+
"""Return a list of different agent types."""
50+
return list(self.agents.keys())
4451

4552
def run_model(self) -> None:
4653
"""Run the model until the end condition is reached. Overload as

0 commit comments

Comments
 (0)