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
code
representing 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
code
is not an instance of int - ValueError – if
code
is not in \(\{0,1,\ldots,255\}\) - TypeError – if
boundary
is neitherNone
or an instance of tuple - ValueError – if
boundary
is a neitherNone
or 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
code
is not an instance of int - ValueError – if
code
is 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: None
or tupleRaises: - TypeError – if
boundary
is neitherNone
or an instance of tuple - ValueError – if
boundary
is a neitherNone
or a pair of binary states
- TypeError – if
-
state_space
(n)[source]¶ Return a
neet.statespace.StateSpace
object 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.StateSpace
Raises: ValueError – if n < 1
-
update
(lattice, index=None, pin=None, values=None)[source]¶ Update the state of the
lattice
in 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
lattice
is not in the ECA’s state space - IndexError – if
index is not None and index > len(states)
- ValueError – if
index
andpin
are both provided - ValueError – if
index
andvalues
are both provided - ValueError – if an element of
pin
is a key invalues
- ValueError – if a value in
values
is 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
pygraphviz
network 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
wiring
is 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
code
is not an instance of int - ValueError – if
code
is 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: None
or tupleRaises: - TypeError – if
boundary
is neitherNone
or an instance of tuple - ValueError – if
boundary
is a neitherNone
or 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.StateSpace
object 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
lattice
in 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
pygraphviz
network drawing
-