Source code for mcs.ca

from .mcs import *


[docs] class CA(MCS): """Cellular automata simulation. Override this class to customize configuration and state-transition function. Attributes: max_step: The max step. size_x: Number of cells in x dimension. size_y: Number of cells in y dimension. seed: NumPy random seed. s: An `~numpy.ndarray` of shape (max_step, size_x) or (max_step, size_y, size_x) representing the states. step: The current step. """ def __init__(self, max_step: int, size_x: int, size_y: int = 1, seed: int = 42): super().__init__(max_step) self.size_x = size_x self.size_y = size_y self.seed = seed if size_y == 1: self.s = np.zeros((max_step, size_x)) else: self.s = np.zeros((max_step, size_y, size_x))
[docs] def initialize(self): """Sets up the initial configuration.""" np.random.seed(self.seed) self.s[0] = np.random.randint(2, size=self.s[0].shape)
[docs] def update(self, *, F: Callable = None): """Updates the states in the next step. Args: F: A state transition function which returns an `~numpy.ndarray`. """ if F is None: F = self._identity config = self.s[self.step] self.step += 1 self.s[self.step] = F(config)
@staticmethod def rule184(config): assert config.ndim == 1 size = len(config) config_next = np.zeros(size) neighborhoods = set([(1, 1, 1), (1, 0, 1), (1, 0, 0), (0, 1, 1)]) for x in range(size): pattern = (config[(x - 1) % size], config[x], config[(x + 1) % size]) if pattern in neighborhoods: config_next[x] = 1 return config_next @staticmethod def game_of_life(config): assert config.ndim == 2 config_next = np.copy(config) num_alive = signal.convolve2d(config, np.ones((3, 3)), mode="same", boundary="wrap") config_next[(config == 0) & (num_alive == 3)] = 1 config_next[(config == 1) & ((num_alive < 3) | (num_alive > 4))] = 0 return config_next
[docs] def visualize(self, *, step: int = -1): """Visualizes the states of the system using an image of shape (step, size_x) or (size_y, size_x). Args: step: The step to plot. Returns: A `matplotlib.figure.Figure` object. """ fig, ax = plt.subplots() if self.s.ndim == 2: ax.imshow(self.s[:step], cmap=plt.cm.binary) elif self.s.ndim == 3: ax.imshow(self.s[step], cmap=plt.cm.binary) return fig