# Source code for netrd.dynamics.single_unbiased_random_walker

"""
single_unbiased_random_walker.py
--------------------------------

Simulate a lonely walker on a network.

"""
from .base import BaseDynamics
import networkx as nx
import numpy as np

[docs]class SingleUnbiasedRandomWalker(BaseDynamics):
"""Random walk dynamics."""

[docs]    def simulate(self, G, L, initial_node=None):
r"""Simulate single random-walker dynamics on a ground truth network.

Generates an :math:N \times L time series TS with
TS[j,t]==1 if the walker is at node :math:j at time
:math:t, and TS[j,t]==0 otherwise.

The results dictionary also stores the ground truth network as
'ground_truth'.

Examples
--------
.. code:: python

G = nx.ring_of_cliques(4,16)
L = 2001
dynamics = SingleUnbiasedRandomWalker()
TS = dynamics.simulate(G, L)

Parameters
----------
G (nx.Graph)
The input (ground-truth) graph with :math:N nodes.

L (int)
The length of the desired time series.

Returns
-------
TS (np.ndarray)
An :math:N \times L array of synthetic time series data.

"""
# get adjacency matrix and set up vector of indices
A = nx.to_numpy_array(G)
N = G.number_of_nodes()
W = np.zeros(L, dtype=int)
# place walker at initial location
if initial_node:
W[0] = initial_node
else:
W[0] = np.random.randint(N)

# run dynamical process
for t in range(L - 1):
W[t + 1] = np.random.choice(np.where(A[W[t], :])[0])
self.results['node_index_sequence'] = W
# turn into a binary-valued
TS = np.zeros((N, L))
for t, w in enumerate(W):
TS[w, t] = 1
self.results['TS'] = TS
self.results['ground_truth'] = G
return TS