-
Notifications
You must be signed in to change notification settings - Fork 162
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
GoL_fast: Add fast PropertyLayer implementation of Game of Life
A special implementation of Conway's Game of Life, using only the PropertyLayer, without needing a Grid or even any Agents.
- Loading branch information
Showing
1 changed file
with
35 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import numpy as np | ||
from mesa import Model | ||
from mesa.space import PropertyLayer | ||
from scipy.signal import convolve2d | ||
|
||
class GameOfLifeModel(Model): | ||
def __init__(self, width, height, alive_fraction=0.2): | ||
super().__init__() | ||
# Initialize the property layer for cell states | ||
self.cell_layer = PropertyLayer("cells", width, height, False, dtype=bool) | ||
# Randomly set cells to alive | ||
self.cell_layer.data = np.random.choice([True, False], size=(width, height), p=[alive_fraction, 1 - alive_fraction]) | ||
|
||
def step(self): | ||
self._advance_time() | ||
# Define a kernel for counting neighbors. The kernel has 1s around the center cell (which is 0). | ||
# This setup allows us to count the live neighbors of each cell when we apply convolution. | ||
kernel = np.array([[1, 1, 1], | ||
[1, 0, 1], | ||
[1, 1, 1]]) | ||
|
||
# Count neighbors using convolution. | ||
# convolve2d applies the kernel to each cell of the grid, summing up the values of neighbors. | ||
# boundary="wrap" ensures that the grid wraps around, simulating a toroidal surface. | ||
neighbor_count = convolve2d(self.cell_layer.data, kernel, mode="same", boundary="wrap") | ||
|
||
# Apply Game of Life rules: | ||
# 1. A live cell with 2 or 3 live neighbors survives, otherwise it dies. | ||
# 2. A dead cell with exactly 3 live neighbors becomes alive. | ||
# These rules are implemented using logical operations on the grid. | ||
self.cell_layer.data = np.logical_or( | ||
np.logical_and(self.cell_layer.data, np.logical_or(neighbor_count == 2, neighbor_count == 3)), | ||
# Rule for live cells | ||
np.logical_and(~self.cell_layer.data, neighbor_count == 3) # Rule for dead cells | ||
) |