Skip to content

Instantly share code, notes, and snippets.

@timfi
Created February 20, 2020 22:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timfi/4141609c67735048d233377cb01bb6e9 to your computer and use it in GitHub Desktop.
Save timfi/4141609c67735048d233377cb01bb6e9 to your computer and use it in GitHub Desktop.
Elementary Cellular Automata
"""elementary.py
Summary
-------
This module implements 1D cellular automata, i.e. elementary cellular automata [1],
using rules formatted in Wolfram code [2].
Parameters
----------
rule : int, positive
The rule to simulate. This should be a 8-bit integer, you can make it bigger
but this function will only use the 8 least significant bits.
width : int, positive
The total width of the state you want to simulate.
iterations : int, positive
The number of iterations to simulate.
Usage
-----
Running this module from the commandline will yield a PBM-formatted image of the
simulation result. You can redirect stdout to a file or pipe the image into other
tools like magick or convert to further process the image.
References
----------
.. [1] Weisstein, Eric W. "Elementary Cellular Automaton."
From MathWorld--A Wolfram Web Resource.
http://mathworld.wolfram.com/ElementaryCellularAutomaton.html
.. [2] Wolfram, Stephen (July 1983). "Statistical Mechanics of Cellular Automata".
Reviews of Modern Physics. 55: 601–644. Bibcode:1983RvMP...55..601W.
"""
from typing import Iterator
import random
__all__ = ("simulate",)
def simulate(rule: int, width: int, inital_state: int = -1, iterations: int = -1) -> Iterator[int]:
"""Simulate 1D cellular automata.
Parameters
----------
rule : int
The rule to simulate. This should be a 8-bit integer, you can make it bigger
but this function will only use the 8 least significant bits.
width : int
The total width of the state you want to simulate.
inital_state : int
The state to start the simulation with. (the default is -1, which forces the
random generation of an initial state)
iterations : int
The number of iterations to simulate. (the default is -1, which causes the
simulation to run indefinitely)
Yields
------
state : int
The current state of the simulation.
Examples
--------
>>> for state in simulate(30, 8, iterations=8):
... print(f"{state:0>8b}")
01011110
11010001
00011011
10110010
10101110
10101000
10101101
00101001
"""
pattern = {
i: rule >> i & 1
for i in range(8)
}
if inital_state < 0:
inital_state = random.randrange(2 ** width)
i, state = 0, inital_state
while iterations < 0 or i < iterations:
i += 1
state = sum(
pattern[(
(state >> (i - 1) % width & 1) << 0 |
(state >> (i + 0) % width & 1) << 1 |
(state >> (i + 1) % width & 1) << 2
)] << i
for i in range(width)
)
yield state
if __name__ == "__main__":
import sys
try:
s_rule, s_width, s_iterations = sys.argv[1:]
rule = int(s_rule)
width = int(s_width)
iterations = int(s_iterations)
except:
print("Usage: python elementary.py RULE WIDTH ITERATIONS")
sys.exit(1)
if rule < 0 or width < 0 or iterations < 0:
sys.stderr.write("All parameters should be positive integers.\n")
sys.exit(1)
state_format = f"{{state:0>{width}b}}"
print(f"P1\n{width} {iterations}")
for state in simulate(rule, width, iterations=iterations):
print(state_format.format(state=state))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment