.. _temp_network_classes:
Temporal network classes
========================
Undirected and unweighted temporal networks are composed of :math:`N` nodes
and up to :math:`m_{\mathrm{max}}=N(N-1)/2` edges, where each edge :math:`(i,j)` can be
described as a series of events where the edge is either switched on
or switched off. One way of expressing that is to define the temporal
adjacency matrix
.. math::
A_{ij}(t) = \begin{cases} 1, & (i,j)\ \mathrm{connected\ at\ time\ } t\\
0, & \mathrm{else}.
\end{cases}
In `tacoma`, we will interpret temporal networks as if they were recorded in an experiment.
We expect that over the course of time :math:`t_0\leq t < t_\mathrm{max}` in which we
recorded activity, we encountered :math:`N` nodes from the node set
:math:`V=\{0,1,\dots,N-1\}` (nodes possess an integer label). However, nodes do not need
to be active (i.e. connected to other nodes) during the time of the experiment to be considered
in the node set.
.. figure:: img/example_temporal_network.png
:alt: A temporal network and how it was recorded in an experiment
A temporal network and how it was recorded in an experiment. We additionally
assume to know that the network consists of :math:`N=8` nodes.
Edges existed before
we started measuring. An edge is considered to be "on" when it exists, shown as
a grey bar in this figure. Each time an edge is switched "on" or switched "off",
respectively, the network structure changes and hence this event is recorded. Here,
the experiment ends before the edge :math:`(0,1)` is switched off.
The experiment begins at time :math:`t_0`, where the network consists of an
edge set :math:`E_0 \subseteq \{i,j: V\times V, i double containing
the similarities of two edges. The integers in the pairs correspond to the index of the edges
in `trajectories`. This dictionary is computed when :class:`_tacoma.edge_trajectories`
is generated from a conversion using :func:`tacoma.api.get_edge_trajectories`
with ``return_edge_similarity = True``.
The network described in the figure above would be recorded as
.. code:: python
import tacoma as tc
traj = tc.edge_trajectories()
entry = tc.edge_trajectory_entry
traj.N = 8
traj.t0 = 0.0
traj.tmax = 8.1
traj.trajectories = [
entry( (0,1), [(0., 3.), (7.0, 8.1)] ),
entry( (2,5), [(3., 7.31)] ),
entry( (1,7), [(0., 1.), (1.5, 4.0)] ),
]
traj.time_unit = 's'
traj.notes = 'This experiment was conducted as a test.'
traj.int_to_node = {
0 : 'Alice',
1 : 'Bob',
2 : 'Clara',
3 : 'Darren',
4 : 'Elle',
5 : 'Felicitas',
6 : 'George',
7 : 'Harriett',
}
List of adjacency matrices
~~~~~~~~~~~~~~~~~~~~~~~~~~
For some cases it might be useful to actually have matrices in memory (e.g. to
compute the epidemic threshold in SIS-models). ``tacoma`` offers the possibility to
convert instances of :class:`_tacoma.edge_lists` and :class:`_tacoma.edge_changes`
to :class:`tacoma.network_formats.sparse_adjacency_matrices` or
:class:`tacoma.network_formats.adjacency_matrices`.
These classes have the same attributes as :class:`_tacoma.edge_lists`, but
instead of the attribute ``edges`` they have the attribute ``adjacency_matrices``.
Convert a temporal network ``tn`` as follows
.. code:: python
A = tc.adjacency_matrices(tn)
A = tc.sparse_adjacency_matrices(tn)
Note that you can pass any desired ``scipy.sparse``-matrix class and ``dtype``
to :class:`tacoma.network_formats.sparse_adjacency_matrices` for matrix construction.
Which class to use
~~~~~~~~~~~~~~~~~~
Each of the classes above has its specific use cases. Since most algorithms rely on
the actual order of network-changing events, the main classes in tacoma are
:class:`_tacoma.edge_lists` and :class:`_tacoma.edge_changes`, meaning that
almost all of the algorithms in this package are specifically implemented for both,
but not for :class:`_tacoma.edge_trajectories`.
:class:`_tacoma.edge_lists` is to prefer if you just want to sample an edge list at
a specific time. For :class:`_tacoma.edge_changes`, you would have to start at the
beginning of the network, then fast forward to that time to obtain an edge list. Edge
lists are often easier to deal with, however, if the inter-event times are rather small
and the network is not sparse, two consecutive edge lists might be overlapping strongly.
Hence, edge changes are often faster to deal with and need less memory. Furthermore,
Algorithms which explicitly rely on edge changes, as e.g. dynamic Gillespie algorithms
are natively faster on :class:`_tacoma.edge_changes`.
:class:`_tacoma.edge_trajectories` is preffered for drawing an
:func:`tacoma.drawing.edge_activity_plot` or to estimate edge-activity rates.