Simulate a continuous-time threshold model on static networks.

## Project description

Simulate a continuous-time threshold model on static networks using Gillespie’s stochastic simulation algorithm (SSA). The networks can be directed and/or weighted.

In contrast to the original discrete-time model, nodes whose aggregated inputs exceed their respective thresholds will not flip after the “next time step” because there are no time steps. Instead, a node whose threshold has been exceeded will enter an alert state from which it will enter the activated state with rate $gamma = 1$.

## Install

pip install thresholdmodel

## Example

Simulate on an ER random graph.

import numpy as np import networkx as nx import matplotlib.pyplot as plt from thresholdmodel import ThreshModel N = 1000 k = 10 thresholds = 0.1 initially_activated = np.arange(100) G = nx.fast_gnp_random_graph(N, k/(N-1.0)) Thresh = ThreshModel(G,initially_activated,thresholds) t, cascade_size = Thresh.simulate() plt.plot(t,cascade_size) plt.show()

## API

### Simulate

Given a networkx-Graph object `G` (can be a `networkx.DiGraph`,
too), and values for `initially_activated` and `thresholds`,
simulate like this

Thresh = ThreshModel(G,initially_activated,thresholds) t, a = Thresh.simulate()

`t` is a `numpy.ndarray` containing the times at which node
activations happened. `a` is a `numpy.ndarray` containing the
relative cascade size at the corresponding time in `t`. Note that the
whole process is modeled as a Poisson process such that the time `t`
will be given in units of the node activation rate `gamma = 1.0`. If
you want to simulate for another node activation rate, simply rescale
time as `t /= gamma`.

When the simulation is started with the `save_activated_nodes=True`
flag, a list of activated nodes per time leap is saved in
`ThreshModel.activated_nodes`.

t, a = Thresh.simulate(save_activated_nodes=True) print(Thresh.activated_nodes)

You can repeat a simulation with the same initial conditions by simply
calling `Thresh.simulate()` again, all the necessary things will be
reset automatically.

### Set initially activated nodes

Set nodes 3, 5, and 8 to be activated initially.

initially_activated = [3, 5, 8] # this could also be a numpy array

Choose 20% of all nodes randomly to be activated initially. When the simulation is restarted, the same nodes will be chosen as initial conditions.

initially_activated = 0.2

Choose 35 randomly selected nodes to be activated initially. When the simulation is restarted, the same nodes will be chosen as initial conditions.

initially_activated = 35

### Set thresholds

Activation thresholds can be set for all nodes

thresholds = np.random.rand(G.number_of_nodes())

Note that thresholds need to lie in the domain `[0,1]`.

You can also set a universal threshold

thresholds = 0.1

Here, 10% of a node’s neighbors need to be activated in order for the node to become active, too.

### Directed networks

A node will become active if the sufficient number of nodes pointing
*towards* the node are active. This means that a node’s in-degree will
be the important measure to determine wether this particular node will
become active.

### Weighted networks

If you want to simulate on a weighted network, provide the `weight`
keyword

Thresh = ThreshModel(G,initially_activated,thresholds,weight='weight')

Similar to the networkx-documentation: `weight` (string, optional
(default=`None`)) - The attribute name to obtain the edge weights.
E.g.: `G.edges[0,1]['weight']`.

A focal node will become active when the cumulative edge weights of all
activated nodes pointing towards the focal node will reach
`> threshold*in_degree`.

## Docstring

This is the model’s docstring.

>>> help(ThreshModel) Help on class ThreshModel in module thresholdmodel.model: class ThreshModel(builtins.object) | ThreshModel(G, initially_activated, thresholds, weight=None) | | A simple simulation class that runs | a threshold-model activation process | on a static network (potentially weighted and directed) | in continuous time using Gillespie's | stochastic simulation algorithm. | | The temporal dimension is fixed by assuming | that every node whose activation threshold | has been exceeded by neighboring inputs | is activated with constant and uniform | rate :math:`\gamma = 1`. | | Parameters | ========== | G : networkx.Graph, networkx.DiGraph | The network on which to simulate. | Nodes must be integers in the range | of ``[0, N-1]``. | initially_activated: float, int, or list of ints | Can be either of three things: | | 1. float of value ``0 < initially_activated < 1``. | In this case, ``initially_activated`` is | interpreted to represent a fraction of nodes | that will be randomly selected from the | set of nodes and set to be activated. | 2. int of value ``1 <= initially_activated < N-1``. | In this case, ``initially_activated`` nodes | will be randomly sampled from the node set | and set to be activated. | 3. list of ints. In this case, ``initially_activated`` | is interpreted to contain indices of nodes | that will be activated initially. | thresholds: float or iterable of floats | Can be either of two things: | | 1. float of value ``0 < thresholds <= 1``. | In this case, every node will have the same | activation threshold. | 2. iterable of values ``0 < thresholds <=1``. | In this case, the function expectes a list, | tuple, or array with length equal to the | number of nodes. Each entry `m` of this list | will be interpreted to be node `m`'s activation | threshold. | weight: str, default = None | A string that represents the weight keyword of a link. | If `None`, the network is assumed to be unweighted. | | Example | ======= | | >>> G = nx.fast_gnp_random_graph(1000,20/(1000-1)) | >>> model = TreshModel(G, 100, 0.1) | >>> t, cascade_size = model.simulate() | | Attributes | ========== | G : nx.Graph or nx.DiGraph | The network on which to simulate. | Nodes must be integers in the range | of ``[0, N-1]``. | N : int | The number of nodes in the network | weight: str | A string that represents the weight keyword of a link. | If `None`, the network is assumed to be unweighted. | in_deg : numpy.ndarray | Contains the in-degree of every node. | thresholds: numpy.ndarray | Each entry `m` of this array | represents node `m`'s activation | threshold. | initially_activated: numpy.ndarray | Each entry of this array contains | a node that will be activated initially. | time: numpy.ndarray | Contains every time point at which a node was | activates (after ``simulation()`` was called). | The temporal dimension is given by assuming | that every node whose activation threshold | has been exceeded by activation inputs | is activated with constant and uniform | rate :math:`\gamma = 1`. | cascade_size: numpy.ndarray | The relative size of the activation cascade | at the corrsponding time value in ``time`` | (relative to the size of the node set). | Only available after ``simulation()`` was called. | activated_nodes: list | A list of lists. | Each entry contains a list of integers representing | the nodes that have been activated | at the corrsponding time value in ``time``. | Each list entry will contain only a single node | for every other time than the initial time. | Only available after ``simulation()`` was called. | | Methods defined here: | | __init__(self, G, initially_activated, thresholds, weight=None) | Initialize self. See help(type(self)) for accurate signature. | | reset(self) | Reset the simulation. | | set_initially_activated(self, initially_activated) | Set the process's initial activation state. | | Parameters | ========== | initially_activated: float, int, or list of ints | Can be either of three things: | | 1. float of value ``0 < initially_activated < 1``. | In this case, ``initially_activated`` is | interpreted to represent a fraction of nodes | that will be randomly selected from the | set of nodes and set to be activated. | 2. int of value ``1 <= initially_activated < N-1``. | In this case, ``initially_activated`` nodes | will be randomly sampled from the node set | and set to be activated. | 3. list of ints. In this case, ``initially_activated`` | is interpreted to contain indices of nodes | that will be activated initially. | | set_thresholds(self, thresholds) | Set node activation thresholds. | | Parameters | ========== | thresholds: float or iterable of floats | Can be either of two things: | | 1. float of value ``0 < thresholds <= 1``. | In this case, every node will have the same | activation threshold. | 2. iterable of values ``0 < thresholds <=1``. | In this case, the function expectes a list, | tuple, or array with length equal to the | number of nodes. Each entry `m` of this list | will be interpreted to be node `m`'s activation | threshold. | | simulate(self, save_activated_nodes=False) | Simulate until all nodes that can be activated | have been activated. | | Parameters | ========== | save_activated_nodes: bool, default = False | If ``True``, write a list of activated nodes | to the class attribute ``activated_nodes`` | every time an activation event happens. | Such a list will contain only a single node | for every other time than the initial time. | | Returns | ======= | time : numpy.ndarray | Time points at which nodes were activated. | cascade_size : numpy.ndarray | The relative size of the activation cascade | at the corrsponding time value in ``time`` | (relative to the size of the node set).

## Project details

## Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Filename, size | File type | Python version | Upload date | Hashes |
---|---|---|---|---|

Filename, size thresholdmodel-0.0.3.tar.gz (32.1 kB) | File type Source | Python version None | Upload date | Hashes View |