Sensitivity Analysis

class neet.boolean.SensitivityMixin[source]

SensitivityMixin provides methods for sensitivity analysis. That is, methods to quantify the degree to which perturbations of a network’s state propagate and spread. As part of this, we also provide methods for identifying “canalizing edges”: edges for which a state of the source node uniquely determines the state of the target regardless of other sources.

sensitivity Compute the Boolean sensitivity at a given network state.
average_sensitivity Calculate average Boolean network sensitivity, as defined in [Shmulevich2004].
lambdaQ Compute the sensitivity eigenvalue, \(\lambda_Q\).
difference_matrix Compute the difference matrix at a given state.
average_difference_matrix Compute the difference matrix, averaged over some states.
is_canalizing Determine whether a given network edge is canalizing.
canalizing_edges Get the set of all canalizing edges in the network.
canalizing_nodes Get a set of all nodes with at least one incoming canalizing edge.

The neet.boolean.BooleanNetwork class derives from SensitivityMixin to provide sensitivity analysis to all of Neet’s Boolean network models.

sensitivity(state, transitions=None)[source]

Compute the Boolean sensitivity at a given network state.

The sensitivity of a Boolean function \(f\) on state vector \(x\) is the number of Hamming neighbors of \(x\) on which the function value is different than on \(x\), as defined in [Shmulevich2004].

This method calculates the average sensitivity over all \(N\) boolean functions, where \(N\) is the number of nodes in the network.

Examples

>>> s_pombe.sensitivity([0, 0, 0, 0, 0, 1, 1, 0, 0])
1.0
>>> s_pombe.sensitivity([0, 1, 1, 0, 1, 0, 0, 1, 0])
0.4444444444444444
>>> c_elegans.sensitivity([0, 0, 0, 0, 0, 0, 0, 0])
1.75
>>> c_elegans.sensitivity([1, 1, 1, 1, 1, 1, 1, 1])
1.25

Optionally, the user can provide a pre-computed array of state transitions to improve performance when this function is repeatedly called.

>>> trans = list(map(s_pombe.decode, s_pombe.transitions))
>>> s_pombe.sensitivity([0, 0, 0, 0, 0, 1, 1, 0, 0], transitions=trans)
1.0
>>> s_pombe.sensitivity([0, 1, 1, 0, 1, 0, 0, 1, 0], transitions=trans)
0.4444444444444444
Parameters:
Returns:

the sensitivity at the provided state

average_sensitivity(states=None, weights=None, calc_trans=True)[source]

Calculate average Boolean network sensitivity, as defined in [Shmulevich2004].

The sensitivity of a Boolean function \(f\) on state vector \(x\) is the number of Hamming neighbors of \(x\) on which the function value is different than on \(x\).

The average sensitivity is an average taken over initial states.

Examples

>>> c_elegans.average_sensitivity()
1.265625
>>> c_elegans.average_sensitivity(states=[[0, 0, 0, 0, 0, 0, 0, 0],
... [1, 1, 1, 1, 1, 1, 1, 1]])
...
1.5
>>> c_elegans.average_sensitivity(states=[[0, 0, 0, 0, 0, 0, 0, 0],
... [1, 1, 1, 1, 1, 1, 1, 1]], weights=[0.9, 0.1])
...
1.7
>>> c_elegans.average_sensitivity(states=[[0, 0, 0, 0, 0, 0, 0, 0],
... [1, 1, 1, 1, 1, 1, 1, 1]], weights=[9, 1])
...
1.7
Parameters:
  • states (list, numpy.ndarray, None) – The states to average over; all states if None
  • weights (list, numpy.ndarray, None) – weights for a weighted average over states; all \(1\).
  • calc_trans – pre-compute all state transitions; ignored if states or weights is None.
Returns:

the average sensitivity of net

See also

sensitivity()

lambdaQ(**kwargs)[source]

Compute the sensitivity eigenvalue, \(\lambda_Q\). That is, the largest eigenvalue of the sensitivity matrix average_difference_matrix().

This is analogous to the eigenvalue calculated in [Pomerance2009].

Examples

>>> s_pombe.lambdaQ()
0.8265021276831896
>>> c_elegans.lambdaQ()
1.263099227661824
Returns:the sensitivity eigenvalue (\(\lambda_Q\)) of net
difference_matrix(state, transitions=None)[source]

Compute the difference matrix at a given state.

For a network with \(N\) nodes, with Boolean functions \(f_i\), the difference matrix is a \(N \times N\) matrix

\[A_{ij} = f_i(x) \oplus f_i(x \oplus e_j)\]

where \(e_j\) is the network state with the \(j\)-th node in the \(1\) state while all others are \(0\). In other words, the element \(A_{ij}\) signifies whether or not flipping the \(j\)-th node’s state changes the subsequent state of the \(i\)-th node.

Examples

>>> s_pombe.difference_matrix([0, 0, 0, 0, 0, 0, 0, 0, 0])
array([[0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 1., 1., 1., 0., 0., 0., 0.],
       [0., 0., 1., 0., 0., 0., 0., 0., 1.],
       [0., 0., 0., 1., 0., 0., 0., 0., 1.],
       [0., 0., 0., 0., 0., 1., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 1., 0.],
       [0., 0., 0., 0., 0., 0., 1., 0., 1.],
       [0., 1., 0., 0., 0., 0., 0., 1., 0.],
       [0., 0., 0., 0., 1., 0., 0., 0., 0.]])
>>> c_elegans.difference_matrix([0, 0, 0, 0, 0, 0, 0, 0])
array([[1., 0., 0., 0., 0., 0., 0., 1.],
       [0., 0., 1., 1., 0., 0., 0., 0.],
       [0., 0., 1., 0., 1., 0., 0., 0.],
       [0., 0., 1., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 1., 1., 0., 1.],
       [0., 0., 0., 0., 0., 1., 1., 0.],
       [1., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 1.]])
Parameters:
Returns:

the difference matrix

average_difference_matrix(states=None, weights=None, calc_trans=True)[source]

Compute the difference matrix, averaged over some states.

Examples

>>> s_pombe.average_difference_matrix()
array([[0.    , 0.    , 0.    , 0.    , 0.    , 0.    , 0.    , 0.    ,
        0.    ],
       [0.    , 0.    , 0.25  , 0.25  , 0.25  , 0.    , 0.    , 0.    ,
        0.    ],
       [0.25  , 0.25  , 0.25  , 0.    , 0.    , 0.25  , 0.    , 0.    ,
        0.25  ],
       [0.25  , 0.25  , 0.    , 0.25  , 0.    , 0.25  , 0.    , 0.    ,
        0.25  ],
       [0.    , 0.    , 0.    , 0.    , 0.    , 1.    , 0.    , 0.    ,
        0.    ],
       [0.    , 0.    , 0.0625, 0.0625, 0.0625, 0.    , 0.0625, 0.0625,
        0.    ],
       [0.    , 0.5   , 0.    , 0.    , 0.    , 0.    , 0.5   , 0.    ,
        0.5   ],
       [0.    , 0.5   , 0.    , 0.    , 0.    , 0.    , 0.    , 0.5   ,
        0.5   ],
       [0.    , 0.    , 0.    , 0.    , 1.    , 0.    , 0.    , 0.    ,
        0.    ]])
>>> c_elegans.average_difference_matrix()
array([[0.25  , 0.25  , 0.    , 0.    , 0.    , 0.25  , 0.25  , 0.25  ],
       [0.    , 0.    , 0.5   , 0.5   , 0.    , 0.    , 0.    , 0.    ],
       [0.5   , 0.    , 0.5   , 0.    , 0.5   , 0.    , 0.    , 0.    ],
       [0.    , 0.    , 1.    , 0.    , 0.    , 0.    , 0.    , 0.    ],
       [0.    , 0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.    , 0.3125],
       [0.5   , 0.    , 0.    , 0.    , 0.    , 0.5   , 0.5   , 0.    ],
       [1.    , 0.    , 0.    , 0.    , 0.    , 0.    , 0.    , 0.    ],
       [0.    , 0.    , 0.    , 0.    , 0.    , 0.    , 0.5   , 0.5   ]])
Parameters:
  • states (list, numpy.ndarray, None) – the states to average over; all states if None
  • weights (list, numpy.ndarray, None) – weights for a weighted average over states; uniform weighting if None
  • calc_trans (bool) – pre-compute all state transitions; ignored if states or weights is None
Returns:

the difference matrix as a numpy.ndarray().

is_canalizing(x, y)[source]

Determine whether a given network edge is canalizing.

An edge \((y,x)\) is canalyzing if \(x\)’s value at \(t+1\) is fully determined when \(y\)’s value has a particular value at \(t\), regardless of the values of other nodes.

According to (Stauffer 1987):

"A rule [...] is called forcing, or canalizing, if at least one of
its :math:`K` arguments has the property that the result of the
function is already fixed if this argument has one particular
value, regardless of the values for the :math:`K-1` other
arguments."  Note that this is a definition for whether a node's
rule is canalizing, whereas this function calculates whether a
specific edge is canalizing.  Under this definition, if a node has
any incoming canalizing edges, then its rule is canalizing.

Examples

>>> s_pombe.is_canalizing(1, 2)
True
>>> s_pombe.is_canalizing(2, 1)
False
>>> c_elegans.is_canalizing(7, 7)
True
>>> c_elegans.is_canalizing(1, 3)
True
>>> c_elegans.is_canalizing(4, 3)
False
Parameters:
  • x (int) – target node’s index
  • y (int) – source node’s index
Returns:

whether or not the edge (y,x) is canalizing; None if the edge does not exist

canalizing_edges()[source]

Get the set of all canalizing edges in the network.

Examples

>>> s_pombe.canalizing_edges()
{(1, 2), (5, 4), (0, 0), (1, 3), (4, 5), (5, 6), (5, 7), (1, 4), (8, 4), (5, 2), (5, 3)}
>>> c_elegans.canalizing_edges()
{(1, 2), (3, 2), (1, 3), (7, 6), (6, 0), (7, 7)}
Returns:the set of canalizing edges as in the form (target, source)
canalizing_nodes()[source]

Get a set of all nodes with at least one incoming canalizing edge.

Examples

>>> s_pombe.canalizing_nodes()
{0, 1, 4, 5, 8}
>>> c_elegans.canalizing_nodes()
{1, 3, 6, 7}
Returns:the set indices of nodes with at least one canalizing input edge