Skip to content

Commit e40075d

Browse files
authored
add agents property to all spaces (#2418)
1 parent 4dc65a3 commit e40075d

File tree

4 files changed

+102
-1
lines changed

4 files changed

+102
-1
lines changed

mesa/experimental/cell_space/discrete_space.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from random import Random
88
from typing import Any, Generic, TypeVar
99

10+
from mesa.agent import AgentSet
1011
from mesa.experimental.cell_space.cell import Cell
1112
from mesa.experimental.cell_space.cell_collection import CellCollection
1213
from mesa.space import PropertyLayer
@@ -55,6 +56,11 @@ def __init__(
5556
def cutoff_empties(self): # noqa
5657
return 7.953 * len(self._cells) ** 0.384
5758

59+
@property
60+
def agents(self) -> AgentSet:
61+
"""Return an AgentSet with the agents in the space."""
62+
return AgentSet(self.all_cells.agents, random=self.random)
63+
5864
def _connect_cells(self): ...
5965
def _connect_single_cell(self, cell: T): ...
6066

mesa/space.py

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
import numpy.typing as npt
4444

4545
# For Mypy
46-
from .agent import Agent
46+
from .agent import Agent, AgentSet
4747

4848
# for better performance, we calculate the tuple to use in the is_integer function
4949
_types_integer = (int, np.integer)
@@ -164,6 +164,26 @@ def build_empties(self) -> None:
164164
@overload
165165
def __getitem__(self, index: int | Sequence[Coordinate]) -> list[GridContent]: ...
166166

167+
@property
168+
def agents(self) -> AgentSet:
169+
"""Return an AgentSet with the agents in the space."""
170+
agents = []
171+
for entry in self:
172+
if not entry:
173+
continue
174+
if not isinstance(entry, list):
175+
entry = [entry] # noqa PLW2901
176+
for agent in entry:
177+
agents.append(agent)
178+
179+
# getting the rng is a bit hacky because old style spaces don't have the rng
180+
try:
181+
rng = agents[0].random
182+
except IndexError:
183+
# there are no agents in the space
184+
rng = None
185+
return AgentSet(agents, random=rng)
186+
167187
@overload
168188
def __getitem__(
169189
self, index: tuple[int | slice, int | slice]
@@ -1344,6 +1364,19 @@ def __init__(
13441364
self._index_to_agent: dict[int, Agent] = {}
13451365
self._agent_to_index: dict[Agent, int | None] = {}
13461366

1367+
@property
1368+
def agents(self) -> AgentSet:
1369+
"""Return an AgentSet with the agents in the space."""
1370+
agents = list(self._agent_to_index)
1371+
1372+
# getting the rng is a bit hacky because old style spaces don't have the rng
1373+
try:
1374+
rng = agents[0].random
1375+
except IndexError:
1376+
# there are no agents in the space
1377+
rng = None
1378+
return AgentSet(agents, random=rng)
1379+
13471380
def _build_agent_cache(self):
13481381
"""Cache agents positions to speed up neighbors calculations."""
13491382
self._index_to_agent = {}
@@ -1517,6 +1550,27 @@ def __init__(self, g: Any) -> None:
15171550
for node_id in self.G.nodes:
15181551
g.nodes[node_id]["agent"] = self.default_val()
15191552

1553+
@property
1554+
def agents(self) -> AgentSet:
1555+
"""Return an AgentSet with the agents in the space."""
1556+
agents = []
1557+
for node_id in self.G.nodes:
1558+
entry = self.G.nodes[node_id]["agent"]
1559+
if not entry:
1560+
continue
1561+
if not isinstance(entry, list):
1562+
entry = [entry]
1563+
for agent in entry:
1564+
agents.append(agent)
1565+
1566+
# getting the rng is a bit hacky because old style spaces don't have the rng
1567+
try:
1568+
rng = agents[0].random
1569+
except IndexError:
1570+
# there are no agents in the space
1571+
rng = None
1572+
return AgentSet(agents, random=rng)
1573+
15201574
@staticmethod
15211575
def default_val() -> list:
15221576
"""Default value for a new node."""

tests/test_cell_space.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,9 +439,29 @@ def test_empties_space():
439439
for i in range(8):
440440
grid._cells[i].add_agent(CellAgent(model))
441441

442+
443+
def test_agents_property():
444+
"""Test empties method for Discrete Spaces."""
445+
import networkx as nx
446+
447+
n = 10
448+
m = 20
449+
seed = 42
450+
G = nx.gnm_random_graph(n, m, seed=seed) # noqa: N806
451+
grid = Network(G)
452+
453+
model = Model()
454+
for i in range(8):
455+
grid._cells[i].add_agent(CellAgent(model))
456+
442457
cell = grid.select_random_empty_cell()
443458
assert cell.coordinate in {8, 9}
444459

460+
assert len(grid.agents) == 8
461+
462+
for i, j in enumerate(sorted(grid.agents.get("unique_id"))):
463+
assert (i + 1) == j # unique_id starts from 1
464+
445465

446466
def test_cell():
447467
"""Test Cell class."""

tests/test_space.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,13 @@ def setUp(self):
198198
self.agents.append(a)
199199
self.space.place_agent(a, pos)
200200

201+
def test_agents_property(self):
202+
"""Test whether space.agents returns correct agents."""
203+
for i, agent in enumerate(self.space.agents):
204+
self.assertEqual(i, agent.unique_id)
205+
206+
self.assertEqual(len(REMOVAL_TEST_AGENTS), len(self.space.agents))
207+
201208
def test_remove_first(self):
202209
"""Test removing the first entry."""
203210
agent_to_remove = self.agents[0]
@@ -403,6 +410,13 @@ def setUp(self): # noqa: D102
403410
self.agents.append(a)
404411
self.space.place_agent(a, pos)
405412

413+
def test_agents_property(self):
414+
"""Test whether space.agents returns correct agents."""
415+
for i, agent in enumerate(self.space.agents):
416+
self.assertEqual(i, agent.unique_id)
417+
418+
self.assertEqual(len(TEST_AGENTS_GRID), len(self.space.agents))
419+
406420
def test_agent_positions(self):
407421
"""Ensure that the agents are all placed properly."""
408422
for i, pos in enumerate(TEST_AGENTS_GRID):
@@ -827,6 +841,13 @@ def setUp(self):
827841
self.agents.append(a)
828842
self.space.place_agent(a, pos)
829843

844+
def test_agents_property(self):
845+
"""Test whether space.agents returns correct agents."""
846+
for i, agent in enumerate(self.space.agents):
847+
self.assertEqual(i, agent.unique_id)
848+
849+
self.assertEqual(len(TEST_AGENTS_NETWORK_SINGLE), len(self.space.agents))
850+
830851
def test_agent_positions(self):
831852
"""Ensure that the agents are all placed properly."""
832853
for i, pos in enumerate(TEST_AGENTS_NETWORK_SINGLE):

0 commit comments

Comments
 (0)