# Tutorial¶

## Reconstructing a graph¶

All reconstruction algorithms provide a simple interface. First, initialize the reconstructor object by calling its constructor with no arguments. Then, use the fit() method to obtain the reconstructed network.

TS = np.loadtxt('data/synth_4clique_N64_simple.csv',
delimiter=',',
encoding='utf8')
# TS is a NumPy array of shape N (number of nodes) x L (observations).

recon = netrd.reconstruction.RandomReconstructor()
G = recon.fit(TS)


Many reconstruction algorithms store additional metadata in a results dictionary.

# Another way to obtain the reconstructed graph
G = recon.results['graph']

# A dense matrix of weights
W = recon.results['weights_matrix']

# The binarized matrix from which the graph is created
A = recon.results['thresholded_matrix']


Many, though not all, reconstruction algorithms work by assigning each potential edge a weight and then thresholding the matrix to obtain a sparse representation. This thresholding can be controlled by setting the threshold_type argument to one of four values:

• range: Consider only weights whose values fall within a range.

• degree: Consider only the largest weights, targeting a specific average degree.

• quantile: Consider only weights in, e.g., the 0.90 quantile and above.

• custom: Pass a custom function for thresholding the matrix yourself.

Each of these has a specific argument to pass to tune the thresholding:

• cutoffs: A list of 2-tuples specifying the values to keep. For example, to keep only values whose absolute values are above 0.5, use cutoffs=[(-np.inf, -0.5), (0.5, np.inf)]

• avg_k: The desired average degree of the network.

• quantile: The appropriate quantile (not percentile).

• custom_thresholder: A user-defined function that returns an N x N NumPy array.

H = recon.fit(TS, threshold_type='degree', avg_k = 15.125)

print(nx.info(G))
# This network is a complete graph.

print(nx.info(H))
# This network is not.


## Distances between graphs¶

Distances behave similarly to reconstructors. All distance objects have a dist() method that takes two NetworkX graphs.

G1 = nx.fast_gnp_random_graph(1000, 0.1)
G2 = nx.fast_gnp_random_graph(1000, 0.1)

dist = netrd.distance.NetSimile()
D = dist.dist(G1, G2)


Some distances also store metadata in results dictionaries.

# Another way to get the distance
D = dist.results['dist']

# The underlying features used in NetSimile
vecs = dist.results['signature_vectors']


## Dynamics on graphs¶

As a utility, we also implement various ways to simulate dynamics on a network. These have a similar interface to reconstructors and distances. Their simulate() method takes an input graph and the desired length of the dynamics, returning the same N x L array used in the graph reconstruction methods.

model = netrd.dynamics.VoterModel()
TS = model.simulate(G, 1000, noise=.001)

# Another way to get the dynamics
TS = model.results['TS']

# The original graph is stored in results
H = model.results['ground_truth']