From ebf948a80c74f6e565824142d5266f42de983944 Mon Sep 17 00:00:00 2001 From: rht Date: Sat, 6 Jan 2024 18:54:14 -0500 Subject: [PATCH 01/12] model: Move random seed and random to __init__ Given that `super().__init__()` is now necessary for user's model class `__init__()`, this simplifies the `Model` construct. And `model.random` can be initialized with other RNG objects (`np.random.default_rng(...)`, or any other RNG). Prior discussion https://github.com/projectmesa/mesa/discussions/1938.# Please enter the commit message for your changes. Lines starting --- mesa/model.py | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/mesa/model.py b/mesa/model.py index bcd5902f2eb..ca872b86135 100644 --- a/mesa/model.py +++ b/mesa/model.py @@ -48,20 +48,6 @@ class Model: initialize_data_collector: Sets up the data collector for the model, requiring an initialized scheduler and agents. """ - 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) - # TODO: Remove these 2 lines just before Mesa 3.0 - obj._steps = 0 - obj._time = 0 - return obj - def __init__(self, *args: Any, **kwargs: Any) -> None: """Create a new model. Overload this method with the actual code to start the model. Always start with super().__init__() to initialize the @@ -73,6 +59,13 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.current_id = 0 self.agents_: defaultdict[type, dict] = defaultdict(dict) + self._seed = kwargs.get("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) + self._steps: int = 0 self._time: TimeT = 0 # the model's clock From 9fc2422da34e964ee632787bac45f8eb09693b7d Mon Sep 17 00:00:00 2001 From: rht Date: Fri, 23 Aug 2024 07:46:02 -0400 Subject: [PATCH 02/12] model: Set seed as keyword argument --- mesa/model.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mesa/model.py b/mesa/model.py index ca872b86135..0714a7cc6a2 100644 --- a/mesa/model.py +++ b/mesa/model.py @@ -48,7 +48,7 @@ class Model: initialize_data_collector: Sets up the data collector for the model, requiring an initialized scheduler and agents. """ - def __init__(self, *args: Any, **kwargs: Any) -> None: + def __init__(self, *args: Any, seed: float | None = None, **kwargs: Any) -> 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. @@ -59,7 +59,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.current_id = 0 self.agents_: defaultdict[type, dict] = defaultdict(dict) - self._seed = kwargs.get("seed") + self._seed = seed if self._seed is None: # We explicitly specify the seed here so that we know its value in # advance. From 4466e2d6f364161e7e668441cfa58c6fd749097a Mon Sep 17 00:00:00 2001 From: rht Date: Fri, 23 Aug 2024 07:51:34 -0400 Subject: [PATCH 03/12] make_model: Set seed after model initialization This is because the seed param is no longer always passed by the user to mesa.Model.__init__. --- mesa/visualization/solara_viz.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/mesa/visualization/solara_viz.py b/mesa/visualization/solara_viz.py index 6ec33231cae..cae0cc67e77 100644 --- a/mesa/visualization/solara_viz.py +++ b/mesa/visualization/solara_viz.py @@ -127,10 +127,8 @@ def SolaraViz( # 2. Set up Model def make_model(): """Create a new model instance with current parameters and seed.""" - model = model_class.__new__( - model_class, **model_parameters, seed=reactive_seed.value - ) - model.__init__(**model_parameters) + model = model_class(**model_parameters) + model._seed = reactive_seed.value current_step.value = 0 return model From 26d9dbf6baefe3385ef76dc62b307ebcce8304ee Mon Sep 17 00:00:00 2001 From: Jan Kwakkel Date: Fri, 13 Sep 2024 17:57:43 +0200 Subject: [PATCH 04/12] add super call in model.__init__ --- mesa/model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesa/model.py b/mesa/model.py index b954ba7b945..072d816897b 100644 --- a/mesa/model.py +++ b/mesa/model.py @@ -59,7 +59,7 @@ def __init__(self, *args: Any, seed: float | None = None, **kwargs: Any) -> None start the model. Always start with super().__init__() to initialize the model object properly. """ - + super().__init__(*args, **kwargs) self.running = True self.schedule = None self.steps: int = 0 From b3af6c661d6862004ddfd2bbf6fc04b9a364b6a8 Mon Sep 17 00:00:00 2001 From: Jan Kwakkel Date: Fri, 13 Sep 2024 20:11:27 +0200 Subject: [PATCH 05/12] attempted debug --- tests/test_time.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/test_time.py b/tests/test_time.py index 13d71d22eb0..9fe4c17de6f 100644 --- a/tests/test_time.py +++ b/tests/test_time.py @@ -5,7 +5,9 @@ import unittest from unittest import TestCase, mock -from mesa import Agent, Model +import mesa +from mesa.agent import Agent +from mesa.model import Model from mesa.time import ( BaseScheduler, RandomActivation, @@ -111,7 +113,12 @@ def test_no_shuffle(self): """ Testing the staged activation without shuffling. """ - model = MockModel(shuffle=False) + + try: + model = MockModel(shuffle=False) + except TypeError: + print(f"what the f... {mesa.__version__}") + model.step() model.step() assert all(i == j for i, j in zip(model.log[:5], model.log[5:])) From 77348863c35a17d68fc835f27fa59798698d0a38 Mon Sep 17 00:00:00 2001 From: Jan Kwakkel Date: Fri, 13 Sep 2024 20:15:11 +0200 Subject: [PATCH 06/12] Update test_time.py --- tests/test_time.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_time.py b/tests/test_time.py index 9fe4c17de6f..5292ed0ca25 100644 --- a/tests/test_time.py +++ b/tests/test_time.py @@ -116,8 +116,9 @@ def test_no_shuffle(self): try: model = MockModel(shuffle=False) - except TypeError: + except TypeError as e: print(f"what the f... {mesa.__version__}") + raise e model.step() model.step() From f1f512f92ffb91f38bcc7673a5cd526e353a61ee Mon Sep 17 00:00:00 2001 From: Jan Kwakkel Date: Fri, 13 Sep 2024 20:19:15 +0200 Subject: [PATCH 07/12] Update test_time.py --- tests/test_time.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/tests/test_time.py b/tests/test_time.py index 5292ed0ca25..366d341eb94 100644 --- a/tests/test_time.py +++ b/tests/test_time.py @@ -71,7 +71,7 @@ def __init__(self, shuffle=False, activation=STAGED, enable_kill_other_agent=Fal 'staged' creates a StagedActivation scheduler. The default scheduler is a BaseScheduler. """ - super().__init__() + super().__init__(seed=None) self.log = [] self.enable_kill_other_agent = enable_kill_other_agent @@ -114,12 +114,7 @@ def test_no_shuffle(self): Testing the staged activation without shuffling. """ - try: - model = MockModel(shuffle=False) - except TypeError as e: - print(f"what the f... {mesa.__version__}") - raise e - + model = MockModel(shuffle=False) model.step() model.step() assert all(i == j for i, j in zip(model.log[:5], model.log[5:])) From b18c4a82ebab044d374af71989ef4c5db8357ce6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 13 Sep 2024 18:19:24 +0000 Subject: [PATCH 08/12] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_time.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_time.py b/tests/test_time.py index 366d341eb94..1f06b7c691c 100644 --- a/tests/test_time.py +++ b/tests/test_time.py @@ -5,7 +5,6 @@ import unittest from unittest import TestCase, mock -import mesa from mesa.agent import Agent from mesa.model import Model from mesa.time import ( From e23972a4571a109d1202c3043488e9748c2534ce Mon Sep 17 00:00:00 2001 From: rht Date: Sat, 14 Sep 2024 16:13:19 -0400 Subject: [PATCH 09/12] Ensure object.__init__ has no other argument --- mesa/model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesa/model.py b/mesa/model.py index 072d816897b..a88f1dbbb19 100644 --- a/mesa/model.py +++ b/mesa/model.py @@ -59,7 +59,7 @@ def __init__(self, *args: Any, seed: float | None = None, **kwargs: Any) -> None start the model. Always start with super().__init__() to initialize the model object properly. """ - super().__init__(*args, **kwargs) + super().__init__() self.running = True self.schedule = None self.steps: int = 0 From 4f056278da17782f369d53e220dd3181d6529a25 Mon Sep 17 00:00:00 2001 From: rht Date: Sat, 14 Sep 2024 17:23:40 -0400 Subject: [PATCH 10/12] fix: Remove need of __new__ in ModelCreator --- mesa/visualization/solara_viz.py | 6 ++---- tests/test_solara_viz.py | 1 - tests/test_time.py | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/mesa/visualization/solara_viz.py b/mesa/visualization/solara_viz.py index 1187373f2ef..a21ce67dea2 100644 --- a/mesa/visualization/solara_viz.py +++ b/mesa/visualization/solara_viz.py @@ -260,10 +260,8 @@ def on_change(name, value): set_model_parameters({**model_parameters, name: value}) def create_model(): - model.value = model.value.__class__.__new__( - model.value.__class__, **model_parameters, seed=reactive_seed.value - ) - model.value.__init__(**model_parameters) + model.value = model.value.__class__(**model_parameters) + model.value._seed = reactive_seed.value solara.use_effect(create_model, [model_parameters, reactive_seed.value]) diff --git a/tests/test_solara_viz.py b/tests/test_solara_viz.py index 3ff8164065e..cd5ffe1b5dd 100644 --- a/tests/test_solara_viz.py +++ b/tests/test_solara_viz.py @@ -89,7 +89,6 @@ def test_call_space_drawer(mocker): ) model = mesa.Model() - mocker.patch.object(mesa.Model, "__new__", return_value=model) mocker.patch.object(mesa.Model, "__init__", return_value=None) agent_portrayal = { diff --git a/tests/test_time.py b/tests/test_time.py index 1f06b7c691c..b21b7b9555d 100644 --- a/tests/test_time.py +++ b/tests/test_time.py @@ -70,7 +70,7 @@ def __init__(self, shuffle=False, activation=STAGED, enable_kill_other_agent=Fal 'staged' creates a StagedActivation scheduler. The default scheduler is a BaseScheduler. """ - super().__init__(seed=None) + super().__init__() self.log = [] self.enable_kill_other_agent = enable_kill_other_agent From 7666fdec6dd262f2e6fd7217f7ab29fde2a36674 Mon Sep 17 00:00:00 2001 From: rht Date: Sat, 14 Sep 2024 17:46:06 -0400 Subject: [PATCH 11/12] Remove obsolete attributes --- mesa/model.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/mesa/model.py b/mesa/model.py index a88f1dbbb19..3425481a278 100644 --- a/mesa/model.py +++ b/mesa/model.py @@ -73,9 +73,6 @@ def __init__(self, *args: Any, seed: float | None = None, **kwargs: Any) -> None self._seed = random.random() self.random = random.Random(self._seed) - self._steps: int = 0 - self._time: TimeT = 0 # the model's clock - # Wrap the user-defined step method self._user_step = self.step self.step = self._wrapped_step From 3adc42b2b377d1a96a89b4f936542f428b44fb22 Mon Sep 17 00:00:00 2001 From: rht Date: Sat, 14 Sep 2024 17:46:54 -0400 Subject: [PATCH 12/12] Remove superfluous code --- mesa/model.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mesa/model.py b/mesa/model.py index 3425481a278..836f7445ca7 100644 --- a/mesa/model.py +++ b/mesa/model.py @@ -59,7 +59,6 @@ def __init__(self, *args: Any, seed: float | None = None, **kwargs: Any) -> None 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