Cellular Automata¶
Cellular automata are a special type of network. They can be envisioned
at a boolean networks wherein every node has exactly 3 incoming edges. The
neet.automata modules provides two submodules, neet.automata.eca
and neet.automata.reca. As a convenience, the classes in each are
exposed in the neet.automata, so you never have to reference the
submodules unless you so choose.
API Documentation¶
Elementary Cellular Automata¶
The neet.automata.eca.ECA class describes an Elementary Cellular
Automaton
with an arbitrary rule. The ECA class is not a fixed sized network.
This means that the size is determined when it is used based on arguments
passed to the relevant methods or functions.
Examples
>>> ca = ECA(30)
>>> ca.update([0, 0, 1, 0, 0])
[0, 1, 1, 1, 0]
>>> ca.update([0, 1, 0])
[1, 1, 1]
>>> transitions(ca, size=3)
[[0, 0, 0], [1, 1, 1], [1, 1, 1], [1, 0, 0], [1, 1, 1], [0, 0, 1], [0, 1, 0], [0, 0, 0]]
-
class
neet.automata.eca.ECA(code, boundary=None)[source]¶ ECA is a class to represent elementary cellular automaton rules. Each ECA contains an 8-bit integral member variable
coderepresenting the Wolfram code for the ECA rule and a set of boundary conditions which is eitherNone, signifying periodic boundary conditions, or a pair of cell states signifying fixed, open boundary conditions.-
__init__(code, boundary=None)[source]¶ Construct an elementary cellular automaton rule.
Examples
>>> ca = ECA(30) >>> ca.code 30 >>> ca.boundary >>> ca = ECA(30, boundary=(0,0)) >>> ca.boundary (0, 0)
Parameters: - code (int) – the Wolfram code for the ECA
- boundary (tuple or None) – the boundary conditions for the CA
Raises: - TypeError – if
codeis not an instance of int - ValueError – if
codeis not in \(\{0,1,\ldots,255\}\) - TypeError – if
boundaryis neitherNoneor an instance of tuple - ValueError – if
boundaryis a neitherNoneor a pair of binary states
-
code¶ The Wolfram code of the elementary cellular automaton
Examples
>>> eca = ECA(30) >>> eca.code 30 >>> eca.code = 45 >>> eca.code 45 >>> eca.code = 256 Traceback (most recent call last): ... ValueError: invalid ECA code
Type: int
Raises: - TypeError – if
codeis not an instance of int - ValueError – if
codeis not in \(\{0,1,\ldots,255\}\)
- TypeError – if
-
boundary¶ The boundary conditions of the elemenary cellular automaton
Examples
>>> eca = ECA(30) >>> eca.boundary >>> eca.boundary = (0,1) >>> eca.boundary (0, 1) >>> eca.boundary = None >>> eca.boundary >>> eca.boundary = [0,1] Traceback (most recent call last): ... TypeError: ECA boundary are neither None nor a tuple
Type: Noneor tupleRaises: - TypeError – if
boundaryis neitherNoneor an instance of tuple - ValueError – if
boundaryis a neitherNoneor a pair of binary states
- TypeError – if
-
state_space(n)[source]¶ Return a
neet.statespace.StateSpaceobject for a lattice of lengthn.>>> eca = ECA(30) >>> eca.state_space(3) <neet.statespace.StateSpace object at 0x...> >>> space = eca.state_space(3) >>> list(space) [[0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0], [0, 0, 1], [1, 0, 1], [0, 1, 1], [1, 1, 1]]
Parameters: n (int) – the number of nodes in the lattice Returns: neet.statespace.StateSpaceRaises: ValueError – if n < 1
-
update(lattice, index=None, pin=None, values=None)[source]¶ Update the state of the
latticein place.Basic Use:
>>> ca = ECA(30) >>> xs = [0,0,1,0,0] >>> ca.update(xs) [0, 1, 1, 1, 0] >>> ca.boundary = (1,1) >>> ca.update([0,0,1,0,0]) [1, 1, 1, 1, 1]
Single-Node Update:
>>> ca.boundary = None >>> xs = [0,0,1,0,0] >>> ca.update(xs, index=1) [0, 1, 1, 0, 0] >>> xs [0, 1, 1, 0, 0] >>> ca.boundary = (1,1) >>> ca.update(xs, index=-1) [0, 1, 1, 0, 1]
State Pinning:
>>> ca.boundary = None >>> xs = [0,0,1,0,0] >>> ca.update(xs, pin=[-2]) [0, 1, 1, 0, 0] >>> ca.boundary = (1,1) >>> ca.update(xs, pin=[4]) [0, 1, 0, 1, 0]
Value Fixing:
>>> ca.boundary = None >>> xs = [0,0,1,0,0] >>> ca.update(xs, values={0:1,-2:0}) [1, 1, 1, 0, 0] >>> ca.boundary = (1,1) >>> xs = [1,1,1,0,0] >>> ca.update(xs, values={1:0,-1:0}) [0, 0, 0, 1, 0]
Erroneous Usage:
>>> xs = [] >>> ca.update(xs) Traceback (most recent call last): ... ValueError: lattice is empty >>> xs = [0,0,2,0,0] >>> ca.update(xs) Traceback (most recent call last): ... ValueError: invalid value "2" in lattice >>> ca.update(xs, index=5) Traceback (most recent call last): ... ValueError: the provided state is not in the ECA's state space >>> ca.update([0,0,1,0,0,], index=1, pin=[0]) Traceback (most recent call last): ... ValueError: cannot provide both the index and pin arguments >>> ca.update([0,0,1,0,0], index=1, values={0:0}) Traceback (most recent call last): ... ValueError: cannot provide both the index and values arguments >>> ca.update([0,0,1,0,0], pin=[2], values={2:0}) Traceback (most recent call last): ... ValueError: cannot set a value for a pinned state >>> ca.update([0,0,1,0,0], values={2:2}) Traceback (most recent call last): ... ValueError: invalid state in values argument
Parameters: - lattice – the one-dimensional sequence of states
- index – the index to update (or None)
- pin – a sequence of indicies to pin (or None)
- values – a dictionary of index-value pairs to fix after update
Returns: the updated lattice
Raises: - ValueError – if
latticeis not in the ECA’s state space - IndexError – if
index is not None and index > len(states) - ValueError – if
indexandpinare both provided - ValueError – if
indexandvaluesare both provided - ValueError – if an element of
pinis a key invalues - ValueError – if a value in
valuesis not binary (0 or 1)
-
neighbors_in(index, size, **kwargs)[source]¶ Return the set of all incoming neighbor nodes.
In the cases of the lattices having fixed boundary conditions, the left boundary, being on the left of the leftmost index 0, has an index of -1, while the right boundary’s index is the size+1. The full state of the lattices and the boundaries is equavolent to: [cell0, cell1, …, cellN, right_boundary, left_boundary] if it is ever presented as a single list in Python.
Parameters: - index – node index
- size – size of ECA
Returns: the set of all node indices which point toward the index node
Raises: ValueError – if index < 0 or index > n - 1
Basic Use:
>>> net = ECA(30) >>> net.neighbors_in(1, size=3) {0, 1, 2} >>> net.neighbors_in(2, size=3) {0, 1, 2} >>> net.boundary = (1,1) >>> net.neighbors_in(2, size=3) {1, 2, 3} >>> net.neighbors_in(0, 3) {0, 1, -1}
Erroneous Usage:
>>> net = ECA(30,boundary=(1, 1)) >>> net.neighbors_in(5, 3) Traceback (most recent call last): ... ValueError: index must be a non-negative integer less than size
-
neighbors_out(index, size)[source]¶ Return the set of all outgoing neighbor nodes.
Fixed boundaries are excluded as they are not affected by internal states.
Parameters: - index – node index
- size – size of ECA
Returns: the set of all node indices which point from the index node
Raises: ValueError – if index < 0 or index > n - 1
Basic Use:
>>> net = ECA(30) >>> net.neighbors_out(1, 3) {0, 1, 2} >>> net.neighbors_out(2, 3) {0, 1, 2} >>> net.boundary = (1, 1) >>> net.neighbors_out(2, 3) {1, 2} >>> net.neighbors_out(0, 3) {0, 1}
Erroneous Usage:
>>> net = ECA(30,boundary=(1, 1)) >>> net.neighbors_out(5, 3) Traceback (most recent call last): ... ValueError: index must be a non-negative integer less than size
-
neighbors(index, size)[source]¶ Return a set of neighbors for a specified node.
In the cases of the lattices having fixed boundary conditions, the left boundary, being on the left of the leftmost index 0, has an index of -1, while the right boundary’s index is the size+1. The full state of the lattices and the boundaries is equavolent to: [cell0, cell1, …, cellN, right_boundary, left_boundary] if it is ever presented as a single list in Python.
Parameters: - index – node index
- size – size of ECA
Returns: the set of all node indices adjacent to the index node
Raises: ValueError – if index < 0 or index > n - 1
Basic Use:
>>> net = ECA(30) >>> net.neighbors(1, size=3) {0, 1, 2} >>> net.neighbors(2, size=3) {0, 1, 2} >>> net.boundary = (1,1) >>> net.neighbors(2, size=3) {1, 2, 3} >>> net.neighbors(0, 3) {0, 1, -1}
Erroneous Usage:
>>> net = ECA(30,boundary=(1, 1)) >>> net.neighbors(5, 3) Traceback (most recent call last): ... ValueError: index must be a non-negative integer less than size
-
to_networkx_graph(size)[source]¶ Return networkx graph given neet network. Requires networkx.
Parameters: size – size of ECA, required if network is an ECA Returns: a networkx.DiGraph
-
draw(size, filename=None)[source]¶ Output a file with a simple network drawing.
Requires networkx and pygraphviz.
Supported image formats are determined by graphviz. In particular, pdf support requires ‘cairo’ and ‘pango’ to be installed prior to graphviz installation.
Parameters: - filename – filename to write drawing to. Temporary filename will be used if no filename provided.
- size – size of ECA, required if network is an ECA
Returns: a
pygraphviznetwork drawing
-
Rewired Elementary Cellular Automata¶
The neet.automata.reca.RewiredECA implements a variant of an ECA
wherein the neighbors of a give cell can be specified by the user. This
allows one to study, for example, the role of topology in the dynamics of a
network. Every ECA can be represented as a RewiredECA with standard
wiring, but all RewiredECA are fixed sized networks.
Examples
>>> ca = RewiredECA(30, size=3)
>>> ca.update([0, 1, 0])
[1, 1, 1]
>>> ca = RewiredECA(30, wiring=[[0,1,3], [1,1,1], [2,1,2]])
>>> ca.update([0, 1, 0])
[1, 0, 1]
-
class
neet.automata.reca.RewiredECA(code, boundary=None, size=None, wiring=None)[source]¶ RewiredECA is a class to represent elementary cellular automata rules with arbitrarily defined topology. Since the topology must be provided, RewiredECA are naturally fixed-sized.
-
__init__(code, boundary=None, size=None, wiring=None)[source]¶ Construct a rewired elementary cellular automaton rule.
Examples
>>> reca = RewiredECA(30, size=3) >>> reca.code 30 >>> reca.size 3 >>> reca.wiring array([[-1, 0, 1], [ 0, 1, 2], [ 1, 2, 3]])
>>> reca = RewiredECA(30, wiring=[[0,1,2],[-1,0,0],[2,3,1]]) >>> reca.code 30 >>> reca.size 3 >>> reca.wiring array([[ 0, 1, 2], [-1, 0, 0], [ 2, 3, 1]])
Parameters: - code (int) – the 8-bit Wolfram code for the rule
- boundary (tuple or None) – the boundary conditions for the CA
- size (int or None) – the number of cells in the lattice
- wiring – a wiring matrix
Raises: - ValueError – if
size is None and wiring is None - ValueError – if
size is not None and wiring is not None - TypeError – if
size is not None and not isinstance(size, int) - ValueError – if
size is not None and size <= 0 - TypeError – if
not isinstance(wiring, list) and not isinstance(wiring, numpy.ndarray) - ValueError – if
wiringis not \(3 imes N\) - ValueError – if
any(wiring < -1) or any(wiring > N)
-
code¶ The Wolfram code of the elementary cellular automaton
Examples
>>> eca = ECA(30) >>> eca.code 30 >>> eca.code = 45 >>> eca.code 45 >>> eca.code = 256 Traceback (most recent call last): ... ValueError: invalid ECA code
Type: int
Raises: - TypeError – if
codeis not an instance of int - ValueError – if
codeis not in \(\{0,1,\ldots,255\}\)
- TypeError – if
-
boundary¶ The boundary conditions of the elemenary cellular automaton
Examples
>>> eca = ECA(30) >>> eca.boundary >>> eca.boundary = (0,1) >>> eca.boundary (0, 1) >>> eca.boundary = None >>> eca.boundary >>> eca.boundary = [0,1] Traceback (most recent call last): ... TypeError: ECA boundary are neither None nor a tuple
Type: Noneor tupleRaises: - TypeError – if
boundaryis neitherNoneor an instance of tuple - ValueError – if
boundaryis a neitherNoneor a pair of binary states
- TypeError – if
-
size¶ The number of cells in the CA lattice.
Examples
>>> eca = RewiredECA(30, size=3) >>> eca.size 3 >>> eca = RewiredECA(30, wiring=[[-1,0], [0,1], [1,0]]) >>> eca.size 2
Type: int
-
wiring¶ The wiring matrix for the rule.
Examples
>>> reca = RewiredECA(30, size=3) >>> reca.wiring array([[-1, 0, 1], [ 0, 1, 2], [ 1, 2, 3]]) >>> eca = RewiredECA(30, wiring=[[0,1],[1,1],[-1,-1]]) >>> eca.wiring array([[ 0, 1], [ 1, 1], [-1, -1]])
Type: numpy.ndarray
-
state_space()[source]¶ Return a
neet.statespace.StateSpaceobject for the cellular automaton lattice.Examples
>>> eca = RewiredECA(30, size=3) >>> eca.state_space() <neet.statespace.StateSpace object at 0x...> >>> space = eca.state_space() >>> list(space) [[0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0], [0, 0, 1], [1, 0, 1], [0, 1, 1], [1, 1, 1]]
Returns: neet.statespace.StateSpace
-
update(lattice, index=None, pin=None, values=None)[source]¶ Update the state of the
latticein place.Examples
>>> reca = RewiredECA(30, size=5) >>> reca.update([1,0,0,0,0]) [1, 1, 0, 0, 1] >>> reca.wiring[:,:] = [[-1, 2, 1, 2, -1], [0, 1, 2, 3, 4], [0, 2, 3, 4, 5]] >>> reca.update([0,0,1,0,0]) [0, 0, 1, 1, 0] >>> reca.update([1,1,1,1,1]) [0, 0, 0, 0, 0] >>> reca.update([1,1,1,1,1], index=2) [1, 1, 0, 1, 1] >>> reca.update([1,1,1,1,1], pin=[1, 3]) [0, 1, 0, 1, 0] >>> reca.update([1,1,1,1,1], values={0: 1, -1: 1}) [1, 0, 0, 0, 1]
Parameters: - lattice – the one-dimensional sequence of states
- index – the index to update (optional)
- pin – a sequence of indices to fix (optional)
- values – a dict of index/value pairs to set (optional)
Returns: the updated lattice
-
neighbors_in(index, size, **kwargs)¶ Return the set of all incoming neighbor nodes.
In the cases of the lattices having fixed boundary conditions, the left boundary, being on the left of the leftmost index 0, has an index of -1, while the right boundary’s index is the size+1. The full state of the lattices and the boundaries is equavolent to: [cell0, cell1, …, cellN, right_boundary, left_boundary] if it is ever presented as a single list in Python.
Parameters: - index – node index
- size – size of ECA
Returns: the set of all node indices which point toward the index node
Raises: ValueError – if index < 0 or index > n - 1
Basic Use:
>>> net = ECA(30) >>> net.neighbors_in(1, size=3) {0, 1, 2} >>> net.neighbors_in(2, size=3) {0, 1, 2} >>> net.boundary = (1,1) >>> net.neighbors_in(2, size=3) {1, 2, 3} >>> net.neighbors_in(0, 3) {0, 1, -1}
Erroneous Usage:
>>> net = ECA(30,boundary=(1, 1)) >>> net.neighbors_in(5, 3) Traceback (most recent call last): ... ValueError: index must be a non-negative integer less than size
-
neighbors_out(index, size)¶ Return the set of all outgoing neighbor nodes.
Fixed boundaries are excluded as they are not affected by internal states.
Parameters: - index – node index
- size – size of ECA
Returns: the set of all node indices which point from the index node
Raises: ValueError – if index < 0 or index > n - 1
Basic Use:
>>> net = ECA(30) >>> net.neighbors_out(1, 3) {0, 1, 2} >>> net.neighbors_out(2, 3) {0, 1, 2} >>> net.boundary = (1, 1) >>> net.neighbors_out(2, 3) {1, 2} >>> net.neighbors_out(0, 3) {0, 1}
Erroneous Usage:
>>> net = ECA(30,boundary=(1, 1)) >>> net.neighbors_out(5, 3) Traceback (most recent call last): ... ValueError: index must be a non-negative integer less than size
-
neighbors(index, size)¶ Return a set of neighbors for a specified node.
In the cases of the lattices having fixed boundary conditions, the left boundary, being on the left of the leftmost index 0, has an index of -1, while the right boundary’s index is the size+1. The full state of the lattices and the boundaries is equavolent to: [cell0, cell1, …, cellN, right_boundary, left_boundary] if it is ever presented as a single list in Python.
Parameters: - index – node index
- size – size of ECA
Returns: the set of all node indices adjacent to the index node
Raises: ValueError – if index < 0 or index > n - 1
Basic Use:
>>> net = ECA(30) >>> net.neighbors(1, size=3) {0, 1, 2} >>> net.neighbors(2, size=3) {0, 1, 2} >>> net.boundary = (1,1) >>> net.neighbors(2, size=3) {1, 2, 3} >>> net.neighbors(0, 3) {0, 1, -1}
Erroneous Usage:
>>> net = ECA(30,boundary=(1, 1)) >>> net.neighbors(5, 3) Traceback (most recent call last): ... ValueError: index must be a non-negative integer less than size
-
to_networkx_graph(size)¶ Return networkx graph given neet network. Requires networkx.
Parameters: size – size of ECA, required if network is an ECA Returns: a networkx.DiGraph
-
draw(size, filename=None)¶ Output a file with a simple network drawing.
Requires networkx and pygraphviz.
Supported image formats are determined by graphviz. In particular, pdf support requires ‘cairo’ and ‘pango’ to be installed prior to graphviz installation.
Parameters: - filename – filename to write drawing to. Temporary filename will be used if no filename provided.
- size – size of ECA, required if network is an ECA
Returns: a
pygraphviznetwork drawing
-