From e7a8879a6e7df8c1919e4623a2f09d9589860c6a Mon Sep 17 00:00:00 2001 From: KLEPKO Date: Sat, 2 Nov 2024 15:25:06 +0200 Subject: [PATCH 1/4] fixed --- examples/color_patches/color_patches/model.py | 99 +++++++------------ .../color_patches/color_patches/server.py | 6 +- 2 files changed, 38 insertions(+), 67 deletions(-) diff --git a/examples/color_patches/color_patches/model.py b/examples/color_patches/color_patches/model.py index ca1aa263..182764a3 100644 --- a/examples/color_patches/color_patches/model.py +++ b/examples/color_patches/color_patches/model.py @@ -1,106 +1,77 @@ -""" -The model - a 2D lattice where agents live and have an opinion -""" - from collections import Counter - import mesa -class ColorCell(mesa.experimental.cell_space.CellAgent): +class ColorCell(mesa.Agent): """ Represents a cell's opinion (visualized by a color) """ OPINIONS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] - def __init__(self, model, initial_state): + def __init__(self, unique_id, model, initial_state): """ - Create a cell, in the given state, at the given row, col position. + Create a cell with the given opinion state. """ - super().__init__(model) + super().__init__(unique_id, model) self.state = initial_state self.next_state = None - def get_col(self): - """Return the col location of this cell.""" - return self.cell.coordinate[0] - - def get_row(self): - """Return the row location of this cell.""" - return self.cell.coordinate[1] - def determine_opinion(self): """ - Determines the agent opinion for the next step by polling its neighbors - The opinion is determined by the majority of the 8 neighbors' opinion - A choice is made at random in case of a tie - The next state is stored until all cells have been polled + Determines the agent's opinion for the next step by polling its neighbors. + The opinion is determined by the majority of the 8 neighbors' opinions. + A choice is made at random in case of a tie. + The next state is stored until all cells have been polled. """ - neighbors = self.cell.neighborhood.agents - neighbors_opinion = Counter(n.state for n in neighbors) - # Following is a a tuple (attribute, occurrences) + neighbors = self.model.grid.get_neighbors(self.pos, moore=True, include_center=False) + neighbors_opinion = Counter(neighbor.state for neighbor in neighbors) polled_opinions = neighbors_opinion.most_common() - tied_opinions = [] - for neighbor in polled_opinions: - if neighbor[1] == polled_opinions[0][1]: - tied_opinions.append(neighbor) - self.next_state = self.random.choice(tied_opinions)[0] + # Collect all tied opinions + tied_opinions = [opinion[0] for opinion in polled_opinions if opinion[1] == polled_opinions[0][1]] + self.next_state = self.random.choice(tied_opinions) def assume_opinion(self): """ - Set the state of the agent to the next state + Set the state of the agent to the next state. """ self.state = self.next_state class ColorPatches(mesa.Model): """ - represents a 2D lattice where agents live + Represents a 2D lattice where agents live. """ def __init__(self, width=20, height=20): """ - Create a 2D lattice with strict borders where agents live - The agents next state is first determined before updating the grid + Create a 2D lattice with strict borders where agents live. + The agents' next state is determined first, and then the grid is updated. """ super().__init__() - self._grid = mesa.experimental.cell_space.OrthogonalMooreGrid( - (width, height), torus=False - ) - - # self._grid.coord_iter() - # --> should really not return content + col + row - # -->but only col & row - # for (contents, col, row) in self._grid.coord_iter(): - # replaced content with _ to appease linter - for cell in self._grid.all_cells: - agent = ColorCell(self, ColorCell.OPINIONS[self.random.randrange(0, 16)]) - agent.move_to(cell) + self.width = width + self.height = height + self.grid = mesa.space.MultiGrid(width, height, torus=False) + self.schedule = mesa.time.RandomActivation(self) + + # Create agents + for (content, x, y) in self.grid.coord_iter(): + initial_state = ColorCell.OPINIONS[self.random.randrange(0, len(ColorCell.OPINIONS))] + agent = ColorCell(self.next_id(), self, initial_state) + self.grid.place_agent(agent, (x, y)) + self.schedule.add(agent) self.running = True def step(self): """ Perform the model step in two stages: - - First, all agents determine their next opinion based on their neighbors current opinions - - Then, all agents update their opinion to the next opinion - """ - self.agents.do("determine_opinion") - self.agents.do("assume_opinion") - - @property - def grid(self): - """ - /mesa/visualization/modules/CanvasGridVisualization.py - is directly accessing Model.grid - 76 def render(self, model): - 77 grid_state = defaultdict(list) - ---> 78 for y in range(model.grid.height): - 79 for x in range(model.grid.width): - 80 cell_objects = model.grid.get_cell_list_contents([(x, y)]) - - AttributeError: 'ColorPatches' object has no attribute 'grid' + - First, all agents determine their next opinion based on their neighbors' current opinions. + - Then, all agents update their opinion to the next opinion. """ - return self._grid + for agent in self.schedule.agents: + agent.determine_opinion() + for agent in self.schedule.agents: + agent.assume_opinion() + self.schedule.step() diff --git a/examples/color_patches/color_patches/server.py b/examples/color_patches/color_patches/server.py index 34d0d744..0baf5201 100644 --- a/examples/color_patches/color_patches/server.py +++ b/examples/color_patches/color_patches/server.py @@ -48,9 +48,9 @@ def color_patch_draw(cell): if cell is None: raise AssertionError portrayal = {"Shape": "rect", "w": 1, "h": 1, "Filled": "true", "Layer": 0} - portrayal["x"] = cell.get_row() - portrayal["y"] = cell.get_col() - portrayal["Color"] = _COLORS[cell.get_state()] + # Use cell.pos to get the (x, y) coordinates + portrayal["x"], portrayal["y"] = cell.pos + portrayal["Color"] = _COLORS[cell.state] # Make sure to use cell.state for the color return portrayal From 1fdc310ccc29a113967b1aa8e98cc183da9157b4 Mon Sep 17 00:00:00 2001 From: KLEPKO Date: Sun, 3 Nov 2024 19:21:03 +0200 Subject: [PATCH 2/4] test --- examples/color_patches/color_patches/model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/color_patches/color_patches/model.py b/examples/color_patches/color_patches/model.py index 182764a3..7c57db58 100644 --- a/examples/color_patches/color_patches/model.py +++ b/examples/color_patches/color_patches/model.py @@ -6,7 +6,7 @@ class ColorCell(mesa.Agent): """ Represents a cell's opinion (visualized by a color) """ - + #test OPINIONS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] def __init__(self, unique_id, model, initial_state): From 315129c49e06a946a56efed841bde7580acc2891 Mon Sep 17 00:00:00 2001 From: KLEPKO Date: Sun, 3 Nov 2024 20:58:43 +0200 Subject: [PATCH 3/4] mutations added, grid sizes changed --- examples/color_patches/color_patches/model.py | 28 +++++++++++++------ .../color_patches/color_patches/server.py | 4 +-- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/examples/color_patches/color_patches/model.py b/examples/color_patches/color_patches/model.py index 7c57db58..0feef5bb 100644 --- a/examples/color_patches/color_patches/model.py +++ b/examples/color_patches/color_patches/model.py @@ -1,4 +1,6 @@ from collections import Counter +from random import random + import mesa @@ -9,13 +11,14 @@ class ColorCell(mesa.Agent): #test OPINIONS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] - def __init__(self, unique_id, model, initial_state): + def __init__(self, unique_id, model, initial_state, mutation_prob=0.1): """ Create a cell with the given opinion state. """ super().__init__(unique_id, model) self.state = initial_state self.next_state = None + self.mutation_prob = mutation_prob def determine_opinion(self): """ @@ -24,13 +27,22 @@ def determine_opinion(self): A choice is made at random in case of a tie. The next state is stored until all cells have been polled. """ - neighbors = self.model.grid.get_neighbors(self.pos, moore=True, include_center=False) - neighbors_opinion = Counter(neighbor.state for neighbor in neighbors) - polled_opinions = neighbors_opinion.most_common() + if random() < 0.5: + self.next_state = self.state + return + + if random() < self.mutation_prob: + # Зміна кольору на випадковий незалежно від сусідів + self.next_state = self.random.choice(ColorCell.OPINIONS) + else: + # Стандартний процес визначення "думки" на основі сусідів + neighbors = self.model.grid.get_neighbors(self.pos, moore=True, include_center=False) + neighbors_opinion = Counter(neighbor.state for neighbor in neighbors) + polled_opinions = neighbors_opinion.most_common() - # Collect all tied opinions - tied_opinions = [opinion[0] for opinion in polled_opinions if opinion[1] == polled_opinions[0][1]] - self.next_state = self.random.choice(tied_opinions) + # Збираємо всі зв'язані думки (якщо є кілька з однаковою частотою) + tied_opinions = [opinion[0] for opinion in polled_opinions if opinion[1] == polled_opinions[0][1]] + self.next_state = self.random.choice(tied_opinions) def assume_opinion(self): """ @@ -58,7 +70,7 @@ def __init__(self, width=20, height=20): # Create agents for (content, x, y) in self.grid.coord_iter(): initial_state = ColorCell.OPINIONS[self.random.randrange(0, len(ColorCell.OPINIONS))] - agent = ColorCell(self.next_id(), self, initial_state) + agent = ColorCell(self.next_id(), self, initial_state, mutation_prob=0.01) self.grid.place_agent(agent, (x, y)) self.schedule.add(agent) diff --git a/examples/color_patches/color_patches/server.py b/examples/color_patches/color_patches/server.py index 0baf5201..51c1efd7 100644 --- a/examples/color_patches/color_patches/server.py +++ b/examples/color_patches/color_patches/server.py @@ -29,8 +29,8 @@ ] -grid_rows = 50 -grid_cols = 25 +grid_rows = 100 +grid_cols = 100 cell_size = 10 canvas_width = grid_rows * cell_size canvas_height = grid_cols * cell_size From 47e72ad0a0ad5275928a916e5ebe02fc8b32ae8d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 3 Nov 2024 19:01:22 +0000 Subject: [PATCH 4/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- examples/color_patches/color_patches/model.py | 19 ++++++++++++++----- .../color_patches/color_patches/server.py | 4 +++- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/examples/color_patches/color_patches/model.py b/examples/color_patches/color_patches/model.py index 0feef5bb..a4dd69a6 100644 --- a/examples/color_patches/color_patches/model.py +++ b/examples/color_patches/color_patches/model.py @@ -8,7 +8,8 @@ class ColorCell(mesa.Agent): """ Represents a cell's opinion (visualized by a color) """ - #test + + # test OPINIONS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] def __init__(self, unique_id, model, initial_state, mutation_prob=0.1): @@ -36,12 +37,18 @@ def determine_opinion(self): self.next_state = self.random.choice(ColorCell.OPINIONS) else: # Стандартний процес визначення "думки" на основі сусідів - neighbors = self.model.grid.get_neighbors(self.pos, moore=True, include_center=False) + neighbors = self.model.grid.get_neighbors( + self.pos, moore=True, include_center=False + ) neighbors_opinion = Counter(neighbor.state for neighbor in neighbors) polled_opinions = neighbors_opinion.most_common() # Збираємо всі зв'язані думки (якщо є кілька з однаковою частотою) - tied_opinions = [opinion[0] for opinion in polled_opinions if opinion[1] == polled_opinions[0][1]] + tied_opinions = [ + opinion[0] + for opinion in polled_opinions + if opinion[1] == polled_opinions[0][1] + ] self.next_state = self.random.choice(tied_opinions) def assume_opinion(self): @@ -68,8 +75,10 @@ def __init__(self, width=20, height=20): self.schedule = mesa.time.RandomActivation(self) # Create agents - for (content, x, y) in self.grid.coord_iter(): - initial_state = ColorCell.OPINIONS[self.random.randrange(0, len(ColorCell.OPINIONS))] + for content, x, y in self.grid.coord_iter(): + initial_state = ColorCell.OPINIONS[ + self.random.randrange(0, len(ColorCell.OPINIONS)) + ] agent = ColorCell(self.next_id(), self, initial_state, mutation_prob=0.01) self.grid.place_agent(agent, (x, y)) self.schedule.add(agent) diff --git a/examples/color_patches/color_patches/server.py b/examples/color_patches/color_patches/server.py index 51c1efd7..1084527f 100644 --- a/examples/color_patches/color_patches/server.py +++ b/examples/color_patches/color_patches/server.py @@ -50,7 +50,9 @@ def color_patch_draw(cell): portrayal = {"Shape": "rect", "w": 1, "h": 1, "Filled": "true", "Layer": 0} # Use cell.pos to get the (x, y) coordinates portrayal["x"], portrayal["y"] = cell.pos - portrayal["Color"] = _COLORS[cell.state] # Make sure to use cell.state for the color + portrayal["Color"] = _COLORS[ + cell.state + ] # Make sure to use cell.state for the color return portrayal