Weight-Threshold Networks

class neet.boolean.WTNetwork(weights, thresholds=None, theta=None, names=None, metadata=None)[source]

WTNetwork represents weight-threshold boolean network. This type of Boolean network model is common in biology as it represents activating/inhibiting interactions between subcomponents.

Inheritance diagram of WTNetwork

In addition to methods inherited from neet.boolean.BooleanNetwork, WTNetwork exposes the following attributes

weights The network’s square weight matrix.
thresholds The network’s threshold vector.
theta The network’s activation function.

and static methods:

read Read a network from a pair of node/edge files.
positive_threshold Activate if the stimulus is 0 or greater.
negative_threshold Activate if the stimulus exceeds 0.
split_threshold Activates if the stimulus exceeds 0, maintaining state if it is exactly 0.

At a minimum, WTNetworks accept either a weight matrix or a size. The weight matrix must be square, with the \((i,j)\) element representing the weight on the edge from \(j\)-th node to the \(i\)-th. If a size is provided, all weights are assumed to be \(0.0\).

>>> WTNetwork(3)
<neet.boolean.wtnetwork.WTNetwork object at 0x...>
>>> WTNetwork([[0, 1, 0], [-1, 0, -1], [-1, 1, 1]])
<neet.boolean.wtnetwork.WTNetwork object at 0x...>

Each node has associated with it a threshold value. These thresholds can be provided at initialization. If none are provided, all thresholds are assumed to be \(0.0\).

>>> net = WTNetwork(3, [0.5, 0.0, -0.5])
>>> net.thresholds
array([ 0.5,  0. , -0.5])
>>> WTNetwork([[0, 1, 0], [-1, 0, -1], [-1, 1, 1]], thresholds=[0.5, 0.0, -0.5])
<neet.boolean.wtnetwork.WTNetwork object at 0x...>

Finally, every node of the network is assumed to use the same activation function, theta. This function, if not provided, is assumed to be split_threshold().

>>> net = WTNetwork(3)
>>> net.theta
<function WTNetwork.split_threshold at 0x...>
>>> net = WTNetwork(3, theta=WTNetwork.negative_threshold)
>>> net.theta
<function WTNetwork.negative_threshold at 0x...>

This activation function must accept two arguments: the activation stimulus and the current state of the node or network. It should handle two types of arguments:

  1. stimulus and state are scalar
  2. stimulus and state are vectors (list or numpy.ndarray)

In case 2, the result should modify the state in-place and return the vector.

def theta(stimulus, state):
    if isinstance(stimulus, (list, numpy.ndarray)):
        for i, x in enumerate(stimulus):
            state[i] = theta(x, state[i])
        return state
    elif stimulus < 0:
        return 0
    else:
        return state
net = WTNetwork(3, theta=theta)
print(net.theta)
<function theta at 0x...>

As with all neet.Network classes, the names of the nodes and network-wide metadata can be provided.

Parameters:
  • weights (int, list, numpy.ndarray) – a weights matrix (rows → targets, columns → sources) or a size
  • thresholds (list, numpy.ndarray) – activation thresholds for the nodes
  • theta (callable) – the activation function for all nodes
  • names (seq) – an iterable object of the names of the nodes in the network
  • metadata (dict) – metadata dictionary for the network
Raises:
  • ValueError – if weights is not a integer or a square matrix
  • ValueError – if thresholds and weights have inconsistent dimensions
  • ValueError – if theta is not callable
weights

The network’s square weight matrix. The rows and columns are target and source nodes, respectively. That is, the \((i,j)\) element is the weight of the edge from the \(j\)-th node to the \(i\)-th.

Examples

>>> net = WTNetwork(3)
>>> net.weights
array([[0., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.]])

>>> net = WTNetwork([[1, 0, 1], [-1, 1, 0], [0, 0, 1]])
>>> net.weights
array([[ 1.,  0.,  1.],
       [-1.,  1.,  0.],
       [ 0.,  0.,  1.]])
Type:numpy.ndarray
thresholds

The network’s threshold vector. The \(i\)-th element is the threshold for the \(i\)-th node.

Examples

>>> net = WTNetwork(3)
>>> net.thresholds
array([0., 0., 0.])

>>> net = WTNetwork(3, thresholds=[0, 0.5, -0.5])
>>> net.thresholds
array([ 0. ,  0.5, -0.5])
Type:numpy.ndarray
theta

The network’s activation function. Every node in the network uses this function to determine its next state, based on the simulus it recieves.

>>> WTNetwork(3).theta
<function WTNetwork.split_threshold at 0x...>
>>> WTNetwork(3, theta=WTNetwork.negative_threshold).theta
<function WTNetwork.negative_threshold at 0x...>

This activation function must accept two arguments: the activation stimulus and the current state of the node or network. It should handle two types of arguments:

  1. stimulus and state are scalar
  2. stimulus and state are vectors (list or numpy.ndarray)

In case 2, the result should modify the state in-place and return the vector.

def theta(stimulus, state):
    if isinstance(stimulus, (list, numpy.ndarray)):
        for i, x in enumerate(stimulus):
            state[i] = theta(x, state[i])
        return state
    elif stimulus < 0:
        return 0
    else:
        return state
net = WTNetwork(3, theta=theta)
print(net.theta)
<function theta at 0x...>

As with all neet.Network classes, the names of the nodes and network-wide metadata can be provided.

Type:callable
static read(nodes_path, edges_path, theta=None, metadata=None)[source]

Read a network from a pair of node/edge files.

>>> nodes_path = '../neet/boolean/data/s_pombe-nodes.txt'
>>> edges_path = '../neet/boolean/data/s_pombe-edges.txt'
>>> net = WTNetwork.read(nodes_path, edges_path)
>>> net.size
9
>>> net.names
['SK', 'Cdc2_Cdc13', 'Ste9', 'Rum1', 'Slp1', 'Cdc2_Cdc13_active', 'Wee1_Mik1', 'Cdc25', 'PP']
Parameters:
  • nodes_path (str) – path to the nodes file
  • edges_path (str) – path to the edges file
  • theta (callable) – the activation function
  • metadata (dict) – metadata dictionary for the network
Returns:

a WTNetwork

static positive_threshold(values, states)[source]

Activate if the stimulus is 0 or greater. That is, it “leans positive” if the simulus is 0:

\[\begin{split}\theta_p(x) = \begin{cases} 0 & x < 0 \\ 1 & x \geq 0. \end{cases}\end{split}\]

If values and states are iterable, then apply the above function to each pair (x,y) in zip(values, states) and stores the result in states.

If values and states are scalar values, then simply apply the above threshold function to the pair (values, states) and return the result.

Examples

>>> ys = [0,0,0]
>>> WTNetwork.positive_threshold([1, -1, 0], ys)
[1, 0, 1]
>>> ys
[1, 0, 1]
>>> ys = [1,1,1]
>>> WTNetwork.positive_threshold([1, -1, 0], ys)
[1, 0, 1]
>>> ys
[1, 0, 1]
>>> WTNetwork.positive_threshold(0,0)
1
>>> WTNetwork.positive_threshold(0,1)
1
>>> WTNetwork.positive_threshold(1,0)
1
>>> WTNetwork.positive_threshold(-1,0)
0
Parameters:
  • values – the threshold-shifted values of each node
  • states – the pre-updated states of the nodes
Returns:

the updated states

static negative_threshold(values, states)[source]

Activate if the stimulus exceeds 0. That is, it “leans negative” if the simulus is 0:

\[\begin{split}\theta_n(x) = \begin{cases} 0 & x \leq 0 \\ 1 & x > 0. \end{cases}\end{split}\]

If values and states are iterable, then apply the above function to each pair (x,y) in zip(values, states) and stores the result in states.

If values and states are scalar values, then simply apply the above threshold function to the pair (values, states) and return the result.

Examples

>>> ys = [0,0,0]
>>> WTNetwork.negative_threshold([1, -1, 0], ys)
[1, 0, 0]
>>> ys
[1, 0, 0]
>>> ys = [1,1,1]
>>> WTNetwork.negative_threshold([1, -1, 0], ys)
[1, 0, 0]
>>> ys
[1, 0, 0]
>>> WTNetwork.negative_threshold(0,0)
0
>>> WTNetwork.negative_threshold(0,1)
0
>>> WTNetwork.negative_threshold(1,0)
1
>>> WTNetwork.negative_threshold(1,1)
1
Parameters:
  • values – the threshold-shifted values of each node
  • states – the pre-updated states of the nodes
Returns:

the updated states

static split_threshold(values, states)[source]

Activates if the stimulus exceeds 0, maintaining state if it is exactly 0. That is, it is a middle ground between negative_threshold() and positive_threshold():

\[\begin{split}\theta_s(x,y) = \begin{cases} 0 & x < 0 \\ y & x = 0 \\ 1 & x > 0. \end{cases}\end{split}\]

If values and states are iterable, then apply the above function to each pair (x,y) in zip(values, states) and stores the result in states.

If values and states are scalar values, then simply apply the above threshold function to the pair (values, states) and return the result.

Examples

>>> ys = [0,0,0]
>>> WTNetwork.split_threshold([1, -1, 0], ys)
[1, 0, 0]
>>> ys
[1, 0, 0]
>>> ys = [1,1,1]
>>> WTNetwork.split_threshold([1, -1, 0], ys)
[1, 0, 1]
>>> ys
[1, 0, 1]
>>> WTNetwork.split_threshold(0,0)
0
>>> WTNetwork.split_threshold(0,1)
1
>>> WTNetwork.split_threshold(1,0)
1
>>> WTNetwork.split_threshold(1,1)
1
Parameters:
  • values – the threshold-shifted values of each node
  • states – the pre-updated states of the nodes
Returns:

the updated states