Source code for tnetwork.DCD.multi_temporal_scale

import tnetwork as tn
import networkx as nx
import numpy as np


def _generate_a_community(to_return_graph,to_return_com,nb_nodes, duration, frequency):
    """
    This method add a community with desired properties to the provided dynamic graphs and dynamic coms

    :param to_return_graph: dynamic graph to modify
    :param to_return_com: dynamic coms to modify
    :param nb_nodes: nb nodes in the community
    :param duration: duration of the community
    :param frequency: community edges appear every 1/frequency snapshots in average
    :return:
    """

    #Choose a random start date and fix the end date accordingly
    nb_steps = len(to_return_graph.snapshots())
    start = int(np.random.randint(0, nb_steps - duration))
    end = start + duration

    #Choose random nodes
    nodes = np.random.choice(to_return_graph.snapshots(start).nodes, nb_nodes, replace=False)

    # Add this community to the dyn com
    to_return_com.add_affiliation(nodes, str(start).zfill(5)+str(nodes), [x for x in range(start, end)])

    #For every step, add edges with probability frequency
    for step in range(start, end):
        current_graph = to_return_graph.snapshots(step)
        randoms = np.random.random(nb_nodes * nb_nodes)
        for i in range(len(nodes)):
            for j in range(i + 1, len(nodes)):
                if randoms[i * nb_nodes + j] < frequency:
                    current_graph.add_edge(nodes[i], nodes[j])


[docs]def generate_multi_temporal_scale(nb_steps=5000,nb_nodes=100,nb_com = 10,noise=None,max_com_size=None,max_com_duration=None): """ Generate dynamic graph with stable communities This benchmark allows to generate temporal networks as described in `Detecting Stable Communities in Link Streams at Multiple Temporal Scales. Boudebza, S., Cazabet, R., Nouali, O., & Azouaou, F. (2019).`. To sum up the method, *stable* communities are generated (i.e., no node change). These communities exist for some periods, but have different *temporal scales*, i.e., some of them have a high frequency of edges (their edges appear at every step) while others have a lower frequency (i.e., each edge appear only every $t$ steps). To simplify, communities are complete cliques.(but for the low frequency ones, we might observe only a small fraction of their edges in every step) The basic parameters are the number of steps, number of nodes and number of communities. There are other parameters allowing to modify the random noise, the maximal size of communities and the maximal duration of communities, that are by default assigned with values scaled according to the other parameters. :param nb_steps: steps in the graph :param nb_nodes: total nb nodes :param nb_com: nb desired communities :param noise: random noise at each step, i.e. probability for any edge to exist at any step. default,1/(nb_nodes**2) :param max_com_size: max number of nodes. Default: nb_nodes/4 :param max_com_duration: max community duration. Default: nb_steps/2 :return: """ to_return_graph = tn.DynGraphSN() to_return_com = tn.DynCommunitiesSN() if noise==None: noise = 1/(nb_nodes*nb_nodes) #in average, 1 random interaction per timestep if max_com_duration==None: max_com_duration = nb_steps/2 if max_com_size==None: max_com_size = int(nb_nodes/4) #initialise each step with a random graph with noise for i in range(nb_steps): to_return_graph.add_snapshot(i,nx.erdos_renyi_graph(nb_nodes,noise)) #for each desired community for n in range(nb_com): #get a random size size = np.random.uniform(np.log(4),np.log(max_com_size)) size = int(np.exp(size)) #get a random duration duration = np.random.uniform(np.log(10),np.log(max_com_duration)) duration = int(np.exp(duration)) #We whoose the clique frequency so that all communities last long enough to be detectable cliques_frequency = 10/duration _generate_a_community(to_return_graph,to_return_com,size, duration, cliques_frequency) return (to_return_graph,to_return_com)