Skip to content
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

Add full support for property layers to cell spaces #2512

Merged
merged 60 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
9b8e6a0
initial commit
quaquel Nov 17, 2024
a6161c7
Update property_layer.py
quaquel Nov 17, 2024
7aec942
Update property_layer.py
quaquel Nov 17, 2024
d62ef3e
first set of tests
quaquel Nov 18, 2024
57cfae5
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 18, 2024
a8b4a84
Update cell.py
quaquel Nov 18, 2024
3817633
typo fixes
quaquel Nov 18, 2024
67c8af2
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 18, 2024
80c0379
Merge branch 'main' into property_layer
quaquel Nov 18, 2024
a4718a6
fix mpl_space_drawing tests
quaquel Nov 18, 2024
46e6957
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 18, 2024
738f251
reenable second set of tests
quaquel Nov 18, 2024
b1d2577
reenable last set of tests
quaquel Nov 18, 2024
73c37e7
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 18, 2024
bb6c06e
make mask work
quaquel Nov 19, 2024
f6d6bc6
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 19, 2024
5efa89f
precommit fixes
quaquel Nov 19, 2024
02c07ad
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 19, 2024
b11eaec
Update test_cell_space.py
quaquel Nov 19, 2024
64edf8f
make empty property layer work
quaquel Nov 19, 2024
b33a275
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 19, 2024
a83f817
Merge branch 'main' into property_layer
quaquel Nov 19, 2024
1f6a5c2
Update test_cell_space.py
quaquel Nov 19, 2024
6966d00
minor tweaks
quaquel Nov 23, 2024
4872a9a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 23, 2024
fc72b6c
Update property_layer.py
quaquel Nov 23, 2024
6975781
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 23, 2024
8acc487
cleanup
quaquel Nov 23, 2024
425bc9a
Merge remote-tracking branch 'upstream/main' into property_layer
quaquel Nov 24, 2024
a494335
various additional tests
quaquel Nov 24, 2024
fcb4a06
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 24, 2024
26d291b
some extra protection for changing PropertyLayer.data
quaquel Nov 24, 2024
dba1137
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 24, 2024
ded2d91
Update property_layer.py
quaquel Nov 24, 2024
1f56ded
Update property_layer.py
quaquel Nov 24, 2024
68356a8
raise a value error if name of layer clashes with existing attribute …
quaquel Nov 25, 2024
4de5c98
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 25, 2024
dcb0fe6
Merge remote-tracking branch 'upstream/main' into property_layer
quaquel Nov 25, 2024
8baaec5
pickle and deepcopy work
quaquel Nov 25, 2024
e3e5d52
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 25, 2024
9211b74
ruff
quaquel Nov 25, 2024
43dda87
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 25, 2024
41f3d6b
some explanation
quaquel Nov 25, 2024
3536861
Update test_cell_space.py
quaquel Nov 25, 2024
412d5f6
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 25, 2024
455c9a9
ruff
quaquel Nov 25, 2024
68885e3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 25, 2024
17bd930
add attribute like access for layers
quaquel Dec 1, 2024
ff5c8a2
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 1, 2024
1de6580
precommit related
quaquel Dec 1, 2024
d6f8e7b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 1, 2024
85bd5f6
some additional protection
quaquel Dec 1, 2024
8284b2d
Update property_layer.py
quaquel Dec 1, 2024
83b3e1d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 1, 2024
42349b1
Update property_layer.py
quaquel Dec 3, 2024
0f5dce2
Merge remote-tracking branch 'upstream/main' into property_layer
quaquel Dec 3, 2024
0c9c25b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 3, 2024
b4355df
Update cell.py
quaquel Dec 3, 2024
c77a8ee
Update cell.py
quaquel Dec 3, 2024
9cea6df
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions mesa/experimental/cell_space/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
OrthogonalVonNeumannGrid,
)
from mesa.experimental.cell_space.network import Network
from mesa.experimental.cell_space.property_layer import PropertyLayer
from mesa.experimental.cell_space.voronoi import VoronoiGrid

__all__ = [
Expand All @@ -35,4 +36,5 @@
"OrthogonalVonNeumannGrid",
"Network",
"VoronoiGrid",
"PropertyLayer",
]
20 changes: 5 additions & 15 deletions mesa/experimental/cell_space/cell.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

from mesa.experimental.cell_space.cell_agent import CellAgent
from mesa.experimental.cell_space.cell_collection import CellCollection
from mesa.space import PropertyLayer

if TYPE_CHECKING:
from mesa.agent import Agent
Expand All @@ -24,7 +23,6 @@ class Cell:
coordinate (Tuple[int, int]) : the position of the cell in the discrete space
agents (List[Agent]): the agents occupying the cell
capacity (int): the maximum number of agents that can simultaneously occupy the cell
properties (dict[str, Any]): the properties of the cell
random (Random): the random number generator

"""
Expand All @@ -34,21 +32,10 @@ class Cell:
"connections",
"agents",
"capacity",
"properties",
"random",
"_mesa_property_layers",
"__dict__",
]

# def __new__(cls,
# coordinate: tuple[int, ...],
# capacity: float | None = None,
# random: Random | None = None,):
# if capacity != 1:
# return object.__new__(cls)
# else:
# return object.__new__(SingleAgentCell)

def __init__(
self,
coordinate: Coordinate,
Expand All @@ -70,9 +57,10 @@ def __init__(
Agent
] = [] # TODO:: change to AgentSet or weakrefs? (neither is very performant, )
self.capacity: int | None = capacity
self.properties: dict[Coordinate, object] = {}
self.properties: dict[
Coordinate, object
] = {} # fixme still used by voronoi mesh
self.random = random
self._mesa_property_layers: dict[str, PropertyLayer] = {}

def connect(self, other: Cell, key: Coordinate | None = None) -> None:
"""Connects this cell to another cell.
Expand Down Expand Up @@ -105,6 +93,7 @@ def add_agent(self, agent: CellAgent) -> None:

"""
n = len(self.agents)
self.empty = False

if self.capacity and n >= self.capacity:
raise Exception(
Expand All @@ -121,6 +110,7 @@ def remove_agent(self, agent: CellAgent) -> None:

"""
self.agents.remove(agent)
self.empty = self.is_empty

@property
def is_empty(self) -> bool:
Expand Down
66 changes: 3 additions & 63 deletions mesa/experimental/cell_space/discrete_space.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@
from __future__ import annotations

import warnings
from collections.abc import Callable
from functools import cached_property
from random import Random
from typing import Any, Generic, TypeVar
from typing import Generic, TypeVar

from mesa.agent import AgentSet
from mesa.experimental.cell_space.cell import Cell
from mesa.experimental.cell_space.cell_collection import CellCollection
from mesa.space import PropertyLayer

T = TypeVar("T", bound=Cell)

Expand Down Expand Up @@ -61,8 +59,8 @@ def __init__(
self.cell_klass = cell_klass

self._empties: dict[tuple[int, ...], None] = {}
self._empties_initialized = False
self.property_layers: dict[str, PropertyLayer] = {}
# self._empties_initialized = False
# self.property_layers: dict[str, PropertyLayer] = {}

@property
def cutoff_empties(self): # noqa
Expand Down Expand Up @@ -98,64 +96,6 @@ def select_random_empty_cell(self) -> T:
"""Select random empty cell."""
return self.random.choice(list(self.empties))

# PropertyLayer methods
def add_property_layer(
self, property_layer: PropertyLayer, add_to_cells: bool = True
):
"""Add a property layer to the grid.

Args:
property_layer: the property layer to add
add_to_cells: whether to add the property layer to all cells (default: True)
"""
if property_layer.name in self.property_layers:
raise ValueError(f"Property layer {property_layer.name} already exists.")
self.property_layers[property_layer.name] = property_layer
if add_to_cells:
for cell in self._cells.values():
cell._mesa_property_layers[property_layer.name] = property_layer

def remove_property_layer(self, property_name: str, remove_from_cells: bool = True):
"""Remove a property layer from the grid.

Args:
property_name: the name of the property layer to remove
remove_from_cells: whether to remove the property layer from all cells (default: True)
"""
del self.property_layers[property_name]
if remove_from_cells:
for cell in self._cells.values():
del cell._mesa_property_layers[property_name]

def set_property(
self, property_name: str, value, condition: Callable[[T], bool] | None = None
):
"""Set the value of a property for all cells in the grid.

Args:
property_name: the name of the property to set
value: the value to set
condition: a function that takes a cell and returns a boolean
"""
self.property_layers[property_name].set_cells(value, condition)

def modify_properties(
self,
property_name: str,
operation: Callable,
value: Any = None,
condition: Callable[[T], bool] | None = None,
):
"""Modify the values of a specific property for all cells in the grid.

Args:
property_name: the name of the property to modify
operation: the operation to perform
value: the value to use in the operation
condition: a function that takes a cell and returns a boolean (used to filter cells)
"""
self.property_layers[property_name].modify_cells(operation, value, condition)

def __setstate__(self, state):
"""Set the state of the discrete space and rebuild the connections."""
self.__dict__ = state
Expand Down
9 changes: 7 additions & 2 deletions mesa/experimental/cell_space/grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
from typing import Generic, TypeVar

from mesa.experimental.cell_space import Cell, DiscreteSpace
from mesa.experimental.cell_space.property_layer import HasPropertyLayers

T = TypeVar("T", bound=Cell)


class Grid(DiscreteSpace[T], Generic[T]):
class Grid(DiscreteSpace[T], Generic[T], HasPropertyLayers):
"""Base class for all grid classes.

Attributes:
Expand Down Expand Up @@ -60,14 +61,18 @@ def __init__(
self._try_random = True
self._ndims = len(dimensions)
self._validate_parameters()
self.cell_klass = type(
"GridCell", (self.cell_klass,), {}
) # fixme name needs to dynamic to support multiple grids in parallel

coordinates = product(*(range(dim) for dim in self.dimensions))

self._cells = {
coord: cell_klass(coord, capacity, random=self.random)
coord: self.cell_klass(coord, capacity, random=self.random)
for coord in coordinates
}
self._connect_cells()
self.create_property_layer("empty", default_value=True, dtype=bool)

def _connect_cells(self) -> None:
if self._ndims == 2:
Expand Down
Loading
Loading