"""
.. currentmodule:: neet.boolean
.. testsetup:: boolean_network
from neet.boolean.examples import s_pombe
"""
from neet import UniformNetwork
from neet.python import long
from .sensitivity import SensitivityMixin
import copy
[docs]class BooleanNetwork(SensitivityMixin, UniformNetwork):
"""
The BooleanNetwork class is a base class for all of Neet's Boolean
networks. The BooleanNetwork class inherits from both
:class:`neet.UniformNetwork` and :class:`neet.boolean.SensitivityMixin`,
and specializes the inherited :class:`neet.StateSpace` methods to exploit
the Boolean structure.
.. inheritance-diagram:: neet.boolean.BooleanNetwork
:parts: 1
In addition to all of its inherited methods, BooleanNetwork also exposes the following methods:
.. autosummary::
:nosignatures:
subspace
distance
hamming_neighbors
BooleanNetwork is an *abstract* class, meaning it cannot be instantiated.
Initialization of a BooleaNetwork requires, at a minimum, the number of
nodes in the network. As with all classes that derive from
:class:`neet.Network`, the user may optionally provide a list of names for
the nodes of the network and a metadata dictionary for the network as a
whole (e.g. citation information).
:param size: number of nodes in the network
:type size: int
:param names: an iterable object of the names of the nodes in the network
:type names: seq
:param metadata: metadata dictionary for the network
:type metadata: dict
"""
def __init__(self, size, names=None, metadata=None):
super(BooleanNetwork, self).__init__(size, 2, names, metadata)
def __iter__(self):
size = self.size
state = [0] * size
yield state[:]
i = 0
while i != size:
if state[i] == 0:
state[i] = 1
for j in range(i):
state[j] = 0
i = 0
yield state[:]
else:
i += 1
def __contains__(self, state):
try:
if len(state) != self.size:
return False
for x in state:
if x != 0 and x != 1:
return False
return True
except TypeError:
return False
def _unsafe_encode(self, state):
encoded, place = long(0), long(1)
for x in state:
encoded += place * long(x)
place <<= 1
return encoded
def decode(self, encoded):
size = self.size
state = [0] * size
for i in range(size):
state[i] = encoded & 1
encoded >>= 1
return state
[docs] def subspace(self, indices, state=None):
"""
Generate all states in a given subspace. This method varies each node
specified by the ``indicies`` array independently. The optional
``state`` parameter specifies the state of the non-varying states of
the network. If ``state`` is not provided, all nodes not in
``indicies`` will have state ``0``.
.. rubric:: Examples
.. doctest:: boolean_network
>>> s_pombe.subspace([0])
<generator object BooleanNetwork.subspace at 0x...>
>>> list(s_pombe.subspace([0]))
[[0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0]]
>>> list(s_pombe.subspace([0, 3]))
[[0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0], [1, 0, 0, 1, 0, 0, 0, 0, 0]]
.. doctest:: boolean_network
>>> s_pombe.subspace([0], state=[0, 1, 0, 1, 0, 1, 0, 1, 0])
<generator object BooleanNetwork.subspace at 0x...>
>>> list(s_pombe.subspace([0], state=[0, 1, 0, 1, 0, 1, 0, 1, 0]))
[[0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 1, 0, 1, 0, 1, 0, 1, 0]]
>>> list(s_pombe.subspace([0, 3], state=[0, 1, 0, 1, 0, 1, 0, 1, 0]))
[[0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 1, 0, 1, 0, 1, 0, 1, 0], [0, 1, 0, 0, 0, 1, 0, 1, 0], [1, 1, 0, 0, 0, 1, 0, 1, 0]]
:param indicies: the indicies to vary in the subspace
:type indicies: list, numpy.ndarray, iterable
:param state: a state which specifes the state of the non-varying nodes
:type state: list, numpy.ndarray
:yield: the states of the subspace
"""
size = self.size
if state is not None and state not in self:
raise ValueError('provided state is not in the state space')
elif state is None:
state = [0] * size
indices = list(set(indices))
indices.sort()
nindices = len(indices)
if nindices == 0:
yield copy.copy(state)
elif indices[0] < 0 or indices[-1] >= size:
raise IndexError('index out of range')
elif nindices == size:
for state in self:
yield state
else:
initial = copy.copy(state)
yield copy.copy(state)
i = 0
while i != nindices:
if state[indices[i]] == initial[indices[i]]:
state[indices[i]] ^= 1
for j in range(i):
state[indices[j]] = initial[indices[j]]
i = 0
yield copy.copy(state)
else:
i += 1
[docs] def hamming_neighbors(self, state):
"""
Get all states that one unit of Hamming distance from a given state.
.. rubric:: Examples
.. doctest:: boolean_network
>>> s_pombe.hamming_neighbors([0, 0, 0, 0, 0, 0, 0, 0, 0])
[[1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1]]
>>> s_pombe.hamming_neighbors([0, 1, 1, 0, 1, 0, 1, 0, 0])
[[1, 1, 1, 0, 1, 0, 1, 0, 0], [0, 0, 1, 0, 1, 0, 1, 0, 0], [0, 1, 0, 0, 1, 0, 1, 0, 0], [0, 1, 1, 1, 1, 0, 1, 0, 0], [0, 1, 1, 0, 0, 0, 1, 0, 0], [0, 1, 1, 0, 1, 1, 1, 0, 0], [0, 1, 1, 0, 1, 0, 0, 0, 0], [0, 1, 1, 0, 1, 0, 1, 1, 0], [0, 1, 1, 0, 1, 0, 1, 0, 1]]
:param state: the state whose neighbors are desired
:type state: list, numpy.ndarray
:return: a list of neighbors of the given state
:raises ValueError: if the state is not in the network's state space
"""
if state not in self:
raise ValueError('state is not in state space')
neighbors = [None] * self.size
for i in range(self.size):
neighbors[i] = copy.copy(state)
neighbors[i][i] ^= 1
return neighbors
[docs] def distance(self, a, b):
"""
Compute the Hamming distance between two states.
.. rubric:: Examples
.. doctest:: boolean_network
>>> s_pombe.distance([0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 1, 1, 0, 1, 0, 0])
4
>>> s_pombe.distance([0, 1, 0, 1, 1, 0, 1, 0, 0], [0, 1, 0, 1, 1, 0, 1, 0, 0])
0
:param a: the first state
:type a: list, numpy.ndarray
:param b: the second state
:type b: list, numpy.ndarray
:return: the Hamming distance between the states
:raises ValueError: if either state is not in the network's state space
"""
if a not in self:
raise ValueError('first state is not in state space')
if b not in self:
raise ValueError('second state is not in state space')
out = 0
for i in range(self.size):
out += a[i] ^ b[i]
return out
UniformNetwork.register(BooleanNetwork)