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

Update model.py #2295

Closed
wants to merge 60 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
1f5c004
Update model.py
quaquel Sep 13, 2024
0c222e3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 13, 2024
d6434bf
Update model.py
quaquel Sep 13, 2024
32b8a8a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 13, 2024
68eaa84
Update model.py
quaquel Sep 13, 2024
b0e7391
attempted fix
quaquel Sep 13, 2024
b81ccb8
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 13, 2024
a2d389d
Update test_time.py
quaquel Sep 13, 2024
53ddd1a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 13, 2024
2076325
Update test_time.py
quaquel Sep 13, 2024
cf24f15
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 13, 2024
7af339d
Update test_time.py
quaquel Sep 13, 2024
f102484
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 13, 2024
4e0ea57
Update test_time.py
quaquel Sep 13, 2024
c969069
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 13, 2024
2dfb3a5
Update test_time.py
quaquel Sep 13, 2024
3bdbf7e
another test
quaquel Sep 13, 2024
7f38321
Update test_time.py
quaquel Sep 13, 2024
37dc397
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 13, 2024
1ca3eb6
moving from unitest to pytest
quaquel Sep 14, 2024
40c0682
Update test_time.py
quaquel Sep 14, 2024
401c61b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 14, 2024
f80810f
complete move to pytest
quaquel Sep 14, 2024
063823a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 14, 2024
48319c7
Update test_time.py
quaquel Sep 14, 2024
5756d26
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 14, 2024
832c44b
test
quaquel Sep 14, 2024
8a58f7c
Update __init__.py
quaquel Sep 14, 2024
0a314c4
Update model.py
quaquel Sep 14, 2024
3487ccd
another iteration
quaquel Sep 14, 2024
e59cf58
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 14, 2024
2e93950
Update test_time.py
quaquel Sep 14, 2024
25ba70b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 14, 2024
bb891ea
Update test_time.py
quaquel Sep 14, 2024
378bd6e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 14, 2024
b0665c6
another test
quaquel Sep 14, 2024
b511cfe
stupid test
quaquel Sep 14, 2024
de106ce
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 14, 2024
6f24a5d
Update test_time.py
quaquel Sep 14, 2024
0606f17
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 14, 2024
4b99d06
Update test_time.py
quaquel Sep 14, 2024
486a3e3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 14, 2024
06d3259
another test
quaquel Sep 14, 2024
35ef235
Update test_time.py
quaquel Sep 14, 2024
a4c70fa
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 14, 2024
ddc5959
yet more tests
quaquel Sep 14, 2024
a2f2d7c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 14, 2024
c2198a5
another test
quaquel Sep 14, 2024
99a694b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 14, 2024
381f680
Update model.py
quaquel Sep 14, 2024
4d0d716
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 14, 2024
d0caf7e
updates
quaquel Sep 14, 2024
7a5d324
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 14, 2024
ee1268c
Update model.py
quaquel Sep 14, 2024
419c7ec
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 14, 2024
ac00812
Update model.py
quaquel Sep 14, 2024
fe68087
Update model.py
quaquel Sep 14, 2024
808232b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 14, 2024
4e3c85f
Update test_time.py
quaquel Sep 14, 2024
667ea37
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 14, 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
195 changes: 182 additions & 13 deletions mesa/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,179 @@
from mesa.datacollection import DataCollector


class BaseClass:
def __init__(self, seed=None):
"""Create a new model. Overload this method with the actual code to
start the model. Always start with super().__init__() to initialize the
model object properly.
"""
super().__init__()
self.running = True
self.schedule = None
self.steps: int = 0

self._setup_agent_registration()

self._seed = seed
if self._seed is None:
# We explicitly specify the seed here so that we know its value in
# advance.
self._seed = random.random()
self.random = random.Random(self._seed)

# Wrap the user-defined step method
self._user_step = self.step
self.step = self._wrapped_step

def _wrapped_step(self, *args: Any, **kwargs: Any) -> None:
"""Automatically increments time and steps after calling the user's step method."""
# Automatically increment time and step counters
self.steps += 1
# Call the original user-defined step method
self._user_step(*args, **kwargs)

def next_id(self) -> int:
warnings.warn(

Check warning on line 53 in mesa/model.py

View check run for this annotation

Codecov / codecov/patch

mesa/model.py#L53

Added line #L53 was not covered by tests
"using model.next_id() is deprecated. Agents track their unique ID automatically",
DeprecationWarning,
stacklevel=2,
)
return 0

Check warning on line 58 in mesa/model.py

View check run for this annotation

Codecov / codecov/patch

mesa/model.py#L58

Added line #L58 was not covered by tests

@property
def agents(self) -> AgentSet:
"""Provides an AgentSet of all agents in the model, combining agents from all types."""
return self._all_agents

@agents.setter
def agents(self, agents: Any) -> None:
raise AttributeError(

Check warning on line 67 in mesa/model.py

View check run for this annotation

Codecov / codecov/patch

mesa/model.py#L67

Added line #L67 was not covered by tests
"You are trying to set model.agents. In Mesa 3.0 and higher, this attribute is "
"used by Mesa itself, so you cannot use it directly anymore."
"Please adjust your code to use a different attribute name for custom agent storage."
)

@property
def agent_types(self) -> list[type]:
"""Return a list of all unique agent types registered with the model."""
return list(self._agents_by_type.keys())

@property
def agents_by_type(self) -> dict[type[Agent], AgentSet]:
"""A dictionary where the keys are agent types and the values are the corresponding AgentSets."""
return self._agents_by_type

def get_agents_of_type(self, agenttype: type[Agent]) -> AgentSet:
"""Deprecated: Retrieves an AgentSet containing all agents of the specified type."""
warnings.warn(

Check warning on line 85 in mesa/model.py

View check run for this annotation

Codecov / codecov/patch

mesa/model.py#L85

Added line #L85 was not covered by tests
f"Model.get_agents_of_type() is deprecated, please replace get_agents_of_type({agenttype})"
f"with the property agents_by_type[{agenttype}].",
DeprecationWarning,
stacklevel=2,
)
return self.agents_by_type[agenttype]

Check warning on line 91 in mesa/model.py

View check run for this annotation

Codecov / codecov/patch

mesa/model.py#L91

Added line #L91 was not covered by tests

def _setup_agent_registration(self):
"""helper method to initialize the agent registration datastructures"""
self._agents = {} # the hard references to all agents in the model
self._agents_by_type: dict[
type[Agent], AgentSet
] = {} # a dict with an agentset for each class of agents
self._all_agents = AgentSet([], self) # an agenset with all agents

def register_agent(self, agent):
"""Register the agent with the model

Args:
agent: The agent to register.

Notes:
This method is called automatically by ``Agent.__init__``, so there is no need to use this
if you are subclassing Agent and calling its super in the ``__init__`` method.

"""
if not hasattr(self, "_agents"):
self._setup_agent_registration()

Check warning on line 113 in mesa/model.py

View check run for this annotation

Codecov / codecov/patch

mesa/model.py#L113

Added line #L113 was not covered by tests

warnings.warn(

Check warning on line 115 in mesa/model.py

View check run for this annotation

Codecov / codecov/patch

mesa/model.py#L115

Added line #L115 was not covered by tests
"The Mesa Model class was not initialized. In the future, you need to explicitly initialize "
"the Model by calling super().__init__() on initialization.",
FutureWarning,
stacklevel=2,
)

self._agents[agent] = None

# because AgentSet requires model, we cannot use defaultdict
# tricks with a function won't work because model then cannot be pickled
try:
self._agents_by_type[type(agent)].add(agent)
except KeyError:
self._agents_by_type[type(agent)] = AgentSet(
[
agent,
],
self,
)

self._all_agents.add(agent)

def deregister_agent(self, agent):
"""Deregister the agent with the model

Notes::
This method is called automatically by ``Agent.remove``

"""
del self._agents[agent]
self._agents_by_type[type(agent)].remove(agent)
self._all_agents.remove(agent)

def run_model(self) -> None:
"""Run the model until the end condition is reached. Overload as
needed.
"""
while self.running:
self.step()

Check warning on line 154 in mesa/model.py

View check run for this annotation

Codecov / codecov/patch

mesa/model.py#L154

Added line #L154 was not covered by tests

def step(self) -> None:
"""A single step. Fill in here."""

def reset_randomizer(self, seed: int | None = None) -> None:
"""Reset the model random number generator.

Args:
seed: A new seed for the RNG; if None, reset using the current seed
"""

if seed is None:
seed = self._seed
self.random.seed(seed)
self._seed = seed

Check warning on line 169 in mesa/model.py

View check run for this annotation

Codecov / codecov/patch

mesa/model.py#L167-L169

Added lines #L167 - L169 were not covered by tests

def initialize_data_collector(
self,
model_reporters=None,
agent_reporters=None,
tables=None,
) -> None:
if not hasattr(self, "schedule") or self.schedule is None:
raise RuntimeError(

Check warning on line 178 in mesa/model.py

View check run for this annotation

Codecov / codecov/patch

mesa/model.py#L178

Added line #L178 was not covered by tests
"You must initialize the scheduler (self.schedule) before initializing the data collector."
)
if self.schedule.get_agent_count() == 0:
raise RuntimeError(

Check warning on line 182 in mesa/model.py

View check run for this annotation

Codecov / codecov/patch

mesa/model.py#L182

Added line #L182 was not covered by tests
"You must add agents to the scheduler before initializing the data collector."
)
self.datacollector = DataCollector(

Check warning on line 185 in mesa/model.py

View check run for this annotation

Codecov / codecov/patch

mesa/model.py#L185

Added line #L185 was not covered by tests
model_reporters=model_reporters,
agent_reporters=agent_reporters,
tables=tables,
)
# Collect data for the first time during initialization.
self.datacollector.collect(self)

Check warning on line 191 in mesa/model.py

View check run for this annotation

Codecov / codecov/patch

mesa/model.py#L191

Added line #L191 was not covered by tests


class Model:
"""Base class for models in the Mesa ABM library.

Expand Down Expand Up @@ -54,29 +227,25 @@

"""

def __new__(cls, *args: Any, **kwargs: Any) -> Any:
"""Create a new model object and instantiate its RNG automatically."""
obj = object.__new__(cls)
obj._seed = kwargs.get("seed")
if obj._seed is None:
# We explicitly specify the seed here so that we know its value in
# advance.
obj._seed = random.random()
obj.random = random.Random(obj._seed)
return obj

def __init__(self, *args: Any, **kwargs: Any) -> None:
def __init__(self, seed=None):
"""Create a new model. Overload this method with the actual code to
start the model. Always start with super().__init__() to initialize the
model object properly.
"""

super().__init__()
self.running = True
self.schedule = None
self.steps: int = 0

self._setup_agent_registration()

self._seed = seed
if self._seed is None:
# We explicitly specify the seed here so that we know its value in
# advance.
self._seed = random.random()
self.random = random.Random(self._seed)

# Wrap the user-defined step method
self._user_step = self.step
self.step = self._wrapped_step
Expand Down
Loading
Loading