Skip to content

Commit 51c54cd

Browse files
authored
[Enhancement] Rename core classes (ModelDF, AgentsDF, etc.) for clarity (#175)
1 parent 8db08de commit 51c54cd

36 files changed

+2467
-2216
lines changed

AGENTS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
- Install (dev stack): `uv sync` (always use uv)
1515
- Lint & format: `uv run ruff check . --fix && uv run ruff format .`
16-
- Tests (quiet + coverage): `export MESA_FRAMES_RUNTIME_TYPECHECKING = 1 && uv run pytest -q --cov=mesa_frames --cov-report=term-missing`
16+
- Tests (quiet + coverage): `export MESA_FRAMES_RUNTIME_TYPECHECKING=1 && uv run pytest -q --cov=mesa_frames --cov-report=term-missing`
1717
- Pre-commit (all files): `uv run pre-commit run -a`
1818
- Docs preview: `uv run mkdocs serve`
1919

@@ -36,7 +36,7 @@ Always run tools via uv: `uv run <command>`.
3636
## Commit & Pull Request Guidelines
3737

3838
- Commits: Imperative mood, concise subject, meaningful body when needed.
39-
Example: `Fix AgentsDF.sets copy binding and tests`.
39+
Example: `Fix AgentSetRegistry.sets copy binding and tests`.
4040
- PRs: Link issues, summarize changes, note API impacts, add/adjust tests and docs.
4141
- CI hygiene: Run `ruff`, `pytest`, and `pre-commit` locally before pushing.
4242

README.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,13 @@ pip install -e .
8888

8989
### Creation of an Agent
9090

91-
The agent implementation differs from base mesa. Agents are only defined at the AgentSet level. You can import `AgentSetPolars`. As in mesa, you subclass and make sure to call `super().__init__(model)`. You can use the `add` method or the `+=` operator to add agents to the AgentSet. Most methods mirror the functionality of `mesa.AgentSet`. Additionally, `mesa-frames.AgentSet` implements many dunder methods such as `AgentSet[mask, attr]` to get and set items intuitively. All operations are by default inplace, but if you'd like to use functional programming, mesa-frames implements a fast copy method which aims to reduce memory usage, relying on reference-only and native copy methods.
91+
The agent implementation differs from base mesa. Agents are only defined at the AgentSet level. You can import `AgentSet`. As in mesa, you subclass and make sure to call `super().__init__(model)`. You can use the `add` method or the `+=` operator to add agents to the AgentSet. Most methods mirror the functionality of `mesa.AgentSet`. Additionally, `mesa-frames.AgentSet` implements many dunder methods such as `AgentSet[mask, attr]` to get and set items intuitively. All operations are by default inplace, but if you'd like to use functional programming, mesa-frames implements a fast copy method which aims to reduce memory usage, relying on reference-only and native copy methods.
9292

9393
```python
94-
from mesa-frames import AgentSetPolars
94+
from mesa-frames import AgentSet
9595

96-
class MoneyAgentPolars(AgentSetPolars):
97-
def __init__(self, n: int, model: ModelDF):
96+
class MoneyAgents(AgentSet):
97+
def __init__(self, n: int, model: Model):
9898
super().__init__(model)
9999
# Adding the agents to the agent set
100100
self += pl.DataFrame(
@@ -126,20 +126,20 @@ class MoneyAgentPolars(AgentSetPolars):
126126

127127
### Creation of the Model
128128

129-
Creation of the model is fairly similar to the process in mesa. You subclass `ModelDF` and call `super().__init__()`. The `model.agents` attribute has the same interface as `mesa-frames.AgentSet`. You can use `+=` or `self.agents.add` with a `mesa-frames.AgentSet` (or a list of `AgentSet`) to add agents to the model.
129+
Creation of the model is fairly similar to the process in mesa. You subclass `Model` and call `super().__init__()`. The `model.sets` attribute has the same interface as `mesa-frames.AgentSet`. You can use `+=` or `self.sets.add` with a `mesa-frames.AgentSet` (or a list of `AgentSet`) to add agents to the model.
130130

131131
```python
132-
from mesa-frames import ModelDF
132+
from mesa-frames import Model
133133

134-
class MoneyModelDF(ModelDF):
134+
class MoneyModelDF(Model):
135135
def __init__(self, N: int, agents_cls):
136136
super().__init__()
137137
self.n_agents = N
138-
self.agents += MoneyAgentPolars(N, self)
138+
self.sets += MoneyAgents(N, self)
139139

140140
def step(self):
141-
# Executes the step method for every agentset in self.agents
142-
self.agents.do("step")
141+
# Executes the step method for every agentset in self.sets
142+
self.sets.do("step")
143143

144144
def run_model(self, n):
145145
for _ in range(n):

ROADMAP.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ The Sugarscape example demonstrates the need for this abstraction, as multiple a
4949

5050
#### Progress and Next Steps
5151

52-
- Create utility functions in `DiscreteSpaceDF` and `AgentContainer` to move agents optimally based on specified attributes
52+
- Create utility functions in `DiscreteSpace` and `AgentSetRegistry` to move agents optimally based on specified attributes
5353
- Provide built-in resolution strategies for common concurrency scenarios
5454
- Ensure the implementation works efficiently with the vectorized approach of mesa-frames
5555

docs/api/conf.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@
44
# If extensions (or modules to document with autodoc) are in another directory,
55
# add these directories to sys.path here.
66
import sys
7+
from datetime import datetime
78
from pathlib import Path
89

910
sys.path.insert(0, str(Path("..").resolve()))
1011

1112
# -- Project information -----------------------------------------------------
1213
project = "mesa-frames"
1314
author = "Project Mesa, Adam Amer"
14-
copyright = f"2023, {author}"
15+
copyright = f"{datetime.now().year}, {author}"
1516

1617
# -- General configuration ---------------------------------------------------
1718
extensions = [

docs/api/reference/agents/index.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ Agents
44
.. currentmodule:: mesa_frames
55

66

7-
.. autoclass:: AgentSetPolars
7+
.. autoclass:: AgentSet
88
:members:
99
:inherited-members:
1010
:autosummary:
1111
:autosummary-nosignatures:
1212

13-
.. autoclass:: AgentsDF
13+
.. autoclass:: AgentSetRegistry
1414
:members:
1515
:inherited-members:
1616
:autosummary:
17-
:autosummary-nosignatures:
17+
:autosummary-nosignatures:

docs/api/reference/model.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Model
33

44
.. currentmodule:: mesa_frames
55

6-
.. autoclass:: ModelDF
6+
.. autoclass:: Model
77
:members:
88
:inherited-members:
99
:autosummary:

docs/api/reference/space/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ This page provides a high-level overview of possible space objects for mesa-fram
44

55
.. currentmodule:: mesa_frames
66

7-
.. autoclass:: GridPolars
7+
.. autoclass:: Grid
88
:members:
99
:inherited-members:
1010
:autosummary:

docs/general/index.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,11 @@ pip install -e .
4141
Here's a quick example of how to create a model using mesa-frames:
4242

4343
```python
44-
from mesa_frames import AgentSetPolars, ModelDF
44+
from mesa_frames import AgentSet, Model
4545
import polars as pl
4646

47-
class MoneyAgentPolars(AgentSetPolars):
48-
def __init__(self, n: int, model: ModelDF):
47+
class MoneyAgents(AgentSet):
48+
def __init__(self, n: int, model: Model):
4949
super().__init__(model)
5050
self += pl.DataFrame(
5151
{"wealth": pl.ones(n, eager=True)}
@@ -57,13 +57,13 @@ class MoneyAgentPolars(AgentSetPolars):
5757
def give_money(self):
5858
# ... (implementation details)
5959

60-
class MoneyModelDF(ModelDF):
60+
class MoneyModel(Model):
6161
def __init__(self, N: int):
6262
super().__init__()
63-
self.agents += MoneyAgentPolars(N, self)
63+
self.sets += MoneyAgents(N, self)
6464

6565
def step(self):
66-
self.agents.do("step")
66+
self.sets.do("step")
6767

6868
def run_model(self, n):
6969
for _ in range(n):

docs/general/user-guide/0_getting-started.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,14 @@ Here's a comparison between mesa-frames and mesa:
3535
=== "mesa-frames"
3636

3737
```python
38-
class MoneyAgentPolarsConcise(AgentSetPolars):
38+
class MoneyAgents(AgentSet):
3939
# initialization...
4040
def give_money(self):
4141
# Active agents are changed to wealthy agents
4242
self.select(self.wealth > 0)
4343

4444
# Receiving agents are sampled (only native expressions currently supported)
45-
other_agents = self.agents.sample(
45+
other_agents = self.sets.sample(
4646
n=len(self.active_agents), with_replacement=True
4747
)
4848

@@ -64,7 +64,7 @@ Here's a comparison between mesa-frames and mesa:
6464
def give_money(self):
6565
# Verify agent has some wealth
6666
if self.wealth > 0:
67-
other_agent = self.random.choice(self.model.agents)
67+
other_agent = self.random.choice(self.model.sets)
6868
if other_agent is not None:
6969
other_agent.wealth += 1
7070
self.wealth -= 1
@@ -84,15 +84,15 @@ If you're familiar with mesa, this guide will help you understand the key differ
8484
=== "mesa-frames"
8585

8686
```python
87-
class MoneyAgentSet(AgentSetPolars):
87+
class MoneyAgents(AgentSet):
8888
def __init__(self, n, model):
8989
super().__init__(model)
9090
self += pl.DataFrame({
9191
"wealth": pl.ones(n)
9292
})
9393
def step(self):
9494
givers = self.wealth > 0
95-
receivers = self.agents.sample(n=len(self.active_agents))
95+
receivers = self.sets.sample(n=len(self.active_agents))
9696
self[givers, "wealth"] -= 1
9797
new_wealth = receivers.groupby("unique_id").count()
9898
self[new_wealth["unique_id"], "wealth"] += new_wealth["count"]
@@ -121,13 +121,13 @@ If you're familiar with mesa, this guide will help you understand the key differ
121121
=== "mesa-frames"
122122

123123
```python
124-
class MoneyModel(ModelDF):
124+
class MoneyModel(Model):
125125
def __init__(self, N):
126126
super().__init__()
127-
self.agents += MoneyAgentSet(N, self)
127+
self.sets += MoneyAgents(N, self)
128128

129129
def step(self):
130-
self.agents.do("step")
130+
self.sets.do("step")
131131

132132
```
133133

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
# Classes 📚
22

3-
## AgentSetDF 👥
3+
## AgentSet 👥
44

5-
To create your own AgentSetDF class, you need to subclass the AgentSetPolars class and make sure to call `super().__init__(model)`.
5+
To create your own AgentSet class, you need to subclass the AgentSet class and make sure to call `super().__init__(model)`.
66

7-
Typically, the next step would be to populate the class with your agents. To do that, you need to add a DataFrame to the AgentSetDF. You can do `self += agents` or `self.add(agents)`, where `agents` is a DataFrame or something that could be passed to a DataFrame constructor, like a dictionary or lists of lists. You need to make sure your DataFrame doesn't have a 'unique_id' column because IDs are generated automatically, otherwise you will get an error raised. In the DataFrame, you should also put any attribute of the agent you are using.
7+
Typically, the next step would be to populate the class with your agents. To do that, you need to add a DataFrame to the AgentSet. You can do `self += agents` or `self.add(agents)`, where `agents` is a DataFrame or something that could be passed to a DataFrame constructor, like a dictionary or lists of lists. You need to make sure your DataFrame doesn't have a 'unique_id' column because IDs are generated automatically, otherwise you will get an error raised. In the DataFrame, you should also put any attribute of the agent you are using.
88

99
How can you choose which agents should be in the same AgentSet? The idea is that you should minimize the missing values in the DataFrame (so they should have similar/same attributes) and mostly everybody should do the same actions.
1010

1111
Example:
1212

1313
```python
14-
class MoneyAgent(AgentSetPolars):
15-
def __init__(self, n: int, model: ModelDF):
14+
class MoneyAgents(AgentSet):
15+
def __init__(self, n: int, model: Model):
1616
super().__init__(model)
1717
self.initial_wealth = pl.ones(n)
1818
self += pl.DataFrame({
@@ -25,28 +25,28 @@ class MoneyAgent(AgentSetPolars):
2525

2626
You can access the underlying DataFrame where agents are stored with `self.df`. This allows you to use DataFrame methods like `self.df.sample` or `self.df.group_by("wealth")` and more.
2727

28-
## ModelDF 🏗️
28+
## Model 🏗️
2929

30-
To add your AgentSetDF to your ModelDF, you should also add it to the agents with `+=` or `add`.
30+
To add your AgentSet to your Model, you should also add it to the sets with `+=` or `add`.
3131

32-
NOTE: ModelDF.agents are stored in a class which is entirely similar to AgentSetDF called AgentsDF. The API of the two are the same. If you try accessing AgentsDF.df, you will get a dictionary of `[AgentSetDF, DataFrame]`.
32+
NOTE: Model.sets are stored in a class which is entirely similar to AgentSet called AgentSetRegistry. The API of the two are the same. If you try accessing AgentSetRegistry.df, you will get a dictionary of `[AgentSet, DataFrame]`.
3333

3434
Example:
3535

3636
```python
37-
class EcosystemModel(ModelDF):
37+
class EcosystemModel(Model):
3838
def __init__(self, n_prey, n_predators):
3939
super().__init__()
40-
self.agents += Preys(n_prey, self)
41-
self.agents += Predators(n_predators, self)
40+
self.sets += Preys(n_prey, self)
41+
self.sets += Predators(n_predators, self)
4242

4343
def step(self):
44-
self.agents.do("move")
45-
self.agents.do("hunt")
44+
self.sets.do("move")
45+
self.sets.do("hunt")
4646
self.prey.do("reproduce")
4747
```
4848

49-
## Space: GridDF 🌐
49+
## Space: Grid 🌐
5050

5151
mesa-frames provides efficient implementations of spatial environments:
5252

@@ -55,12 +55,12 @@ mesa-frames provides efficient implementations of spatial environments:
5555
Example:
5656

5757
```python
58-
class GridWorld(ModelDF):
58+
class GridWorld(Model):
5959
def __init__(self, width, height):
6060
super().__init__()
61-
self.space = GridPolars(self, (width, height))
62-
self.agents += AgentSet(100, self)
63-
self.space.place_to_empty(self.agents)
61+
self.space = Grid(self, (width, height))
62+
self.sets += AgentSet(100, self)
63+
self.space.place_to_empty(self.sets)
6464
```
6565

6666
A continuous GeoSpace, NetworkSpace, and a collection to have multiple spaces in the models are in the works! 🚧
@@ -73,21 +73,21 @@ You configure what to collect, how to store it, and when to trigger collection.
7373
Example:
7474

7575
```python
76-
class ExampleModel(ModelDF):
76+
class ExampleModel(Model):
7777
def __init__(self):
7878
super().__init__()
79-
self.agents = MoneyAgent(self)
79+
self.sets = MoneyAgent(self)
8080
self.datacollector = DataCollector(
8181
model=self,
82-
model_reporters={"total_wealth": lambda m: m.agents["wealth"].sum()},
82+
model_reporters={"total_wealth": lambda m: lambda m: list(m.sets.df.values())[0]["wealth"].sum()},
8383
agent_reporters={"wealth": "wealth"},
8484
storage="csv",
8585
storage_uri="./data",
8686
trigger=lambda m: m.schedule.steps % 2 == 0
8787
)
8888

8989
def step(self):
90-
self.agents.step()
90+
self.sets.step()
9191
self.datacollector.conditional_collect()
9292
self.datacollector.flush()
9393
```

0 commit comments

Comments
 (0)