예제 #1
0
def plot_longitudinal_sn_clusters(dynamic_graph,
                                  clusters,
                                  level=None,
                                  **kwargs):
    """
    A longitudinal view of snapshot clusters

    Snapshot clusters are a way to represent periods of the dynamic graphs similar in some way. It is similar to dynamic snapshot_communities,
    but all nodes of a snapshot belongs always to the same "community".

    Optional parameters (kwargs) are the same as for plot_longitudinal.

    :param dynamic_graph:  DynGraphSN or DynGraphIG
    :param clusters: clusters as a set of set of partitions ID. Can also be a hierarchical partitioning, represented as a list of clusters. The level to display is in this case decided by the level parameter
    :param level: if clusters is a hierarchical clustering, the level to display
    """
    if level != None:  #single level
        clusters = clusters[level]
    coms = tn.DynCommunitiesSN()
    for i, cl in enumerate(clusters):  #cl: a cluster
        for t in cl:
            coms.add_community(
                t, nodes=dynamic_graph.snapshot_affiliations(t).nodes, id=i)
    if isinstance(dynamic_graph, tn.DynGraphIG):
        coms = coms.to_DynCommunitiesIG()
    return plot_longitudinal(dynamic_graph, communities=coms, **kwargs)
예제 #2
0
def _convert_to_dyncom(coms, nodes_dict):
    nodes_dict_inv = {v: k for k, v in nodes_dict.items()}
    to_return = tn.DynCommunitiesSN()

    for t, partition in coms.items():
        partition = affiliations2nodesets(partition)
        for comID in partition:
            partition[comID] = {nodes_dict_inv[n] for n in partition[comID]}

        to_return.set_communities(t, partition)
    return to_return
예제 #3
0
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

    :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)
예제 #4
0
def transversal_network_leidenalg(dyn_graph: tn.DynGraphSN,
                                  interslice_weight=1,
                                  elapsed_time=False):
    """
    Multiplex community detection reimplemented in leidenalg

    Algorithm described in [1]
    (see method `mucha_original` for more information)
    This function use the implementation in the leidenalg library instead of the original matlab implementation.
    It requires the installation of the leidenalg library (including igraph).
    It is usually slower than the original implementation (but does not require matlab)

    [1]Mucha, P. J., Richardson, T., Macon, K., Porter, M. A., & Onnela, J. P. (2010).
    Community structure in time-dependent, multiscale, and multiplex networks.
    science, 328(5980), 876-878.

    :param dyn_graph: dynamic network
    :param interslice_weight:
    :param elapsed_time:
    :return:
    """
    print("preprocessing transversal network leidenalg ")

    graphs = dyn_graph.snapshots()
    igraph_graphs = sortedcontainers.SortedDict()
    for t, g in graphs.items():
        igraph_graphs[t] = __from_nx_to_igraph(g)

    start_time = time.time()
    print("calling external code")

    coms, scores = la.find_partition_temporal(
        list(igraph_graphs.values()),
        la.ModularityVertexPartition,
        interslice_weight=interslice_weight,
        vertex_id_attr="name")
    duration = time.time() - start_time
    print("postprocessing ")

    to_return = tn.DynCommunitiesSN()
    ts = list(igraph_graphs.keys())
    for i in range(len(coms)):
        t = ts[i]
        partition = single_list_community2nodesets(coms[i],
                                                   igraph_graphs[t].vs["name"])
        to_return.set_communities(t, partition)

    print("sucessfully finished transversal network leidenalg  ")

    if elapsed_time:
        return (to_return, {"total": duration})
    return to_return
예제 #5
0
    def slice(self, start, end):
        """
        Keep only the selected period

        :param start:
        :param end:
        """

        to_return = tn.DynCommunitiesSN()
        interv = tn.Intervals((start, end))
        for t in list(self.snapshots.keys()):
            if t in interv:
                to_return.set_communities(self.snapshots[t], t)
        return to_return
예제 #6
0
def _read_stable_coms_PAF_format(inputFile):
    """
    blabla
    """
    dyn_coms = tn.DynCommunitiesSN()
    f = open(inputFile)
    i = 0
    for line in f:
        parts = line.split(" ")
        timestamps = parts[0].split(",")
        timestamps = [int(x) for x in timestamps]
        nodes = parts[1].split(",")
        nodes = set(nodes)
        dyn_coms.add_affiliation(nodes, i, timestamps)
        i += 1
    return dyn_coms
예제 #7
0
def _load_dynmoga(file, dic_nodes, dic_times, dyn_graph):

    to_return = tn.DynCommunitiesSN()
    res = scipy.io.loadmat(file)
    coms = res["Z1"]

    coms = zip(*coms)
    for i, partition in enumerate(coms):
        real_nodes = dyn_graph.snapshots(dic_times[i + 1]).nodes
        part_temp = {
            dic_nodes[i + 1]: partition[i]
            for i in range(len(dic_nodes)) if dic_nodes[i + 1] in real_nodes
        }
        part_temp = affiliations2nodesets(part_temp)
        to_return.set_communities(dic_times[i + 1], part_temp)
    return to_return
예제 #8
0
    def to_DynCommunitiesSN(self, slices=None):
        """
            Convert to a snapshot representation.

            :param slices: can be one of

            - None, snapshots are created such as a new snapshot is created at every node/edge change,
            - an integer, snapshots are created using a sliding window
            - a list of periods, represented as pairs (start, end), each period yielding a snapshot

            :return: a dynamic graph represented as snapshots, the weight of nodes/edges correspond to their presence time during the snapshot

        """
        dgSN = tn.DynCommunitiesSN()
        if slices == None:
            raise (
                "lack implementation to find automatically sn periods. Please use argument slices=..."
            )
            times = self.change_times()
            slices = [(times[i], times[i + 1]) for i in range(len(times) - 1)]

        if isinstance(slices, int):
            duration = slices
            slices = []
            start = self.start
            end = start + duration
            while (end <= self.end):
                end = start + duration
                slices.append((start, end))
                start = end
                end = end + duration

        for ts in slices:
            dgSN.set_communities(t=ts[0])

        sorted_times = [x[0] for x in slices]

        for cID, coms in self.communities().items():
            for n, interv in coms.items():
                intersection = interv._discretize(sorted_times)
                for t, presence in intersection.items():
                    if presence > 0:
                        dgSN.add_affiliation(n, cID, t)

        return dgSN
예제 #9
0
    def to_DynCommunitiesSN(self,slices=None):
        """
            Convert to a snapshot representation.

            :param slices: can be one of

            - None, snapshot_affiliations are created such as a new snapshot is created at every node/edge change,
            - an integer, snapshot_affiliations are created using a sliding window
            - a list of periods, represented as pairs (start, end), each period yielding a snapshot

            :return: a dynamic graph represented as snapshot_affiliations, the weight of nodes/edges correspond to their presence time during the snapshot

        """
        dgSN = tn.DynCommunitiesSN()
        if slices == None:
            times = self.change_times()
            slices = [(times[i], times[i + 1]) for i in range(len(times) - 1)]

        if isinstance(slices, int):
            duration = slices
            slices = []
            start = self.start
            end = start + duration
            while (end <= self.end):
                end = start + duration
                slices.append((start, end))
                start = end
                end = end + duration

        for ts in slices:
            dgSN.set_communities(t=ts[0])

        for cID, coms in self.communities().items():
            for n,interv in coms.items():
                for ts in slices:
                    presence = interv.intersection(Intervals([ts])).duration()
                    if presence > 0:
                        dgSN.add_affiliation(n,cID,ts[0])


        return dgSN
예제 #10
0
파일: PAF.py 프로젝트: Yquetzal/tnetwork
def read_coms_dynamo(dynGraph: tn.DynGraphSN, input_dir, nodes_dict):
    nodes_dict = {v: k for k, v in nodes_dict.items()}
    coms = tn.DynCommunitiesSN()
    i = 1
    for t, g in dynGraph.snapshots().items():
        communities_this_step = {}
        file_Addr = os.path.join(input_dir,
                                 "runDynamicModularity_com_" + str(i))
        i += 1
        f = open(file_Addr)
        for id_line, l in enumerate(f.readlines()):
            l = l[:-1]

            real_node = nodes_dict[id_line]
            if real_node in g.nodes:
                communities_this_step.setdefault(l, set())
                communities_this_step[l].add(real_node)
        coms.set_communities(t, communities_this_step)
    coms.create_standard_event_graph(threshold=0.3)
    #print(coms.events.edges)
    coms._relabel_coms_from_continue_events(typedEvents=False)
    return coms
예제 #11
0
def plot_longitudinal(dynamic_graph=None,communities=None, sn_duration=None,to_datetime=False, nodes=None,width=800,height=600,bokeh=False,auto_show=False):
    """
    A longitudinal view of nodes/snapshot_communities

    Plot snapshot_affiliations such as each node corresponds to a horizontal line and time corresponds to the horizontal axis

    :param dynamic_graph: DynGraphSN or DynGraphIG
    :param communities: dynamic snapshot_affiliations, DynCommunitiesSN or DynCommunitiesIG
    :param sn_duration: the duration of a snapshot, as int or timedelta. If none, inferred automatically as lasting until next snpashot
    :param to_datetime: one of True/False/function. If True, step IDs are converted to dates using datetime.utcfromtimestamp. If a function, should take a step ID and return a datetime object.
    :param nodes: If none, plot all nodes in lexicographic order. If a list of nodes, plot only those nodes, in that order
    :param width: width of the figure
    :param height: height of the figure
    """

    if dynamic_graph==None:
        if isinstance(communities,tn.DynCommunitiesSN):
            dynamic_graph = tn.DynGraphSN()
        else:
            dynamic_graph = tn.DynGraphIG()
    if to_datetime==True:
        to_datetime=datetime.utcfromtimestamp
        if sn_duration!=None and not isinstance(sn_duration,timedelta):
            sn_duration=timedelta(seconds=sn_duration)


    if isinstance(dynamic_graph,tn.DynGraphSN):
        if communities == None:
            communities = tn.DynCommunitiesSN()
        t = list(dynamic_graph.snapshots_timesteps())

        if communities != None and isinstance(communities,tn.DynCommunitiesSN):
            t = t + list(communities.snapshots.keys())
            t = sorted(list(set(t)))
        CDS = _sn_graph2CDS(dynamic_graph, communities, to_datetime=to_datetime,ts=t)
    else:
        if communities == None:
            communities = tn.DynCommunitiesIG()
        CDS = _ig_graph2CDS(dynamic_graph, communities, to_datetime=to_datetime)

    if isinstance(dynamic_graph,tn.DynGraphSN) and sn_duration!=None:
        CDS.data["duration"] = [sn_duration]*len(CDS.data["time"])



    if to_datetime!=False:
        CDS.data["duration_display"] = [x/1000 for x in CDS.data["duration"]]
    else:
        CDS.data["duration_display"]=CDS.data["duration"]

    #CDS.data["duration"] = [v+0.1 for v in CDS.data["duration"]]

    #should work for timedelta and integers
    CDS.data["time_shift"] = [CDS.data["time"][i] + CDS.data["duration"][i] / 2 for i in range(len(CDS.data["duration"]))]

    if nodes==None:
        nodes = sorted(list(set(CDS.data["node"])))
        nodes = [str(x) for x in nodes]

    #return _plot_longitudinal_bokeh(CDS,nodes,to_datetime,width,height,auto_show)
    if bokeh:
        return _plot_longitudinal_bokeh(CDS,nodes,to_datetime,width,height, auto_show)
    else:
        return _plot_longitudinal_pyplot(CDS,nodes,to_datetime,width,height)
예제 #12
0
def plot_as_graph(dynamic_graph, communities=None, ts=None, width=800, height=600, slider=False, to_datetime=False,bokeh = False, auto_show=False, **kwargs):
    """
    Plot to see the static graph at each snapshot

    can be row of graphs or an interactive graph with a slider to change snapshot.
    In all cases, the position of nodes is the same in all snapshots.

    The position of nodes is determined using the networkx force directed layout, addition parameters of the function are passed
    to this functions (e.g., iterations=100, k=2...)

    :param dynamic_graph: DynGraphSN
    :param communities: dynamic snapshot_affiliations of the network (can be ignored)
    :param ts: time of snapshot(s) to display. single value or list. default None means all snapshots.
    :param slider: If None, a slider allows to interactively choose the step (work only in jupyter notebooks on a local machine)
    :param to_datetime: one of True/False/function. If True, step IDs are converted to dates using datetime.utcfromtimestamp. If a function, should take a step ID and return a datetime object.
    :param width: width of the figure
    :param height: height of the figure
    :return: bokeh layout containing slider and plot, or only plot if no slider.
    """


    if to_datetime==True:
        to_datetime=datetime.utcfromtimestamp


    # cleaning ts parameter
    if ts == None:
        if isinstance(dynamic_graph, tn.DynGraphIG):
            raise Exception(
                "If using IG graphs/communities, you must specified the desired t to plot")

        ts= list(dynamic_graph.snapshots_timesteps())
        if communities != None:
            ts = ts + list(communities.snapshots.keys())
            ts = sorted(list(set(ts)))

    if not isinstance(ts, list):
        ts = [ts]

    # Obtain snapshots for desired ts (graph and communities)
    if isinstance(dynamic_graph,tn.DynGraphIG):
        temp_graph_sn = tn.DynGraphSN()
        for t in ts:
            #print(t)
            temp_graph_sn.add_snapshot(t, dynamic_graph.graph_at_time(t))
        if communities!=None:
            temp_coms_sn = tn.DynCommunitiesSN()
            for t in ts:
                temp_coms_sn.set_communities(t,communities.communities(t))
            communities = temp_coms_sn

        dynamic_graph=temp_graph_sn

    #Obtain CDS for those snapshots
    CDS = _sn_graph2CDS(dynamic_graph, communities, to_datetime, ts=ts)


    unique_pos = _unique_positions(dynamic_graph,ts=ts,**kwargs)

    if bokeh:
        return _plot_as_graph_bokeh(ts,slider,dynamic_graph,CDS,unique_pos,width,height,to_datetime,auto_show)
    else:
        return _plot_as_graph_nx(ts,dynamic_graph,CDS,unique_pos,width,height,to_datetime)
예제 #13
0
def _subset(graph, com, length):
    subgraph = tn.DynGraphSN(list(graph.snapshots().values())[:length])
    subcomsGT = tn.DynCommunitiesSN()
    for t in subgraph.snapshots_timesteps():
        subcomsGT.set_communities(t, com.snapshot_communities(t))
    return (subgraph, subcomsGT)
예제 #14
0
def muchaOriginal(dynNetSN: tn.DynGraphSN,
                  om=0.5,
                  form="local",
                  elapsed_time=False):
    print("INITIALISING MUCHA ")

    #dynNetSN.remove_nodes_from(dynNetSN.isolates())

    graphs = dynNetSN.snapshots()

    nodeOrderAllSN = []
    listModularityMatrices = []

    #for each graph in order
    for i, gT in enumerate(graphs):
        g = graphs[gT]
        nodeOrder = list(g.nodes())
        nodeOrderAllSN += [(i, n) for n in nodeOrder]

        gmat = nx.to_numpy_matrix(g, nodelist=nodeOrder)

        #
        k = gmat.sum(axis=0)  #degrees of nodes
        twom = k.sum(axis=1)  #sum of degrees
        nullModel = k.transpose() * k / twom
        listModularityMatrices.append(gmat - nullModel)

    #Concatenate all null modularity matrices
    B = scipy.linalg.block_diag(*listModularityMatrices)
    #B = scipy.sparse.block_diag(listModularityMatrices)

    #add the link between same nodes in different timestamps
    multipleAppearances = {}  #for each node, list of indices where it appears
    for (i, (t, n)) in enumerate(nodeOrderAllSN):
        multipleAppearances.setdefault(n, []).append(i)

    if form == "global":
        for (n, nAppearences) in multipleAppearances.items():
            for i in nAppearences:
                for j in nAppearences:
                    if i != j:
                        B[i, j] = om
    if form == "local":
        #print(multipleAppearances)
        for (n, nAppearences) in multipleAppearances.items():
            orderedAppearences = nAppearences
            for i in range(0, len(orderedAppearences) - 1, 1):
                B[orderedAppearences[i], orderedAppearences[i + 1]] = om

    print("saving temp file")
    numpy.savetxt("test.csv", B, fmt="%.2f", delimiter=",")
    print("file saved")

    #B = scipy.sparse.coo_matrix(B)

    (S, duration) = runMatlabCode(B)
    print("transforming back to dynamic net")

    DCSN = tn.DynCommunitiesSN()
    for i in range(len(S)):
        DCSN.add_affiliation(nodeOrderAllSN[i][1], S[i], nodeOrderAllSN[i][0])

    if elapsed_time:
        return (DCSN, {"total": duration})
    return DCSN


#preprocessMatrixForm(0.5)
#muchaOriginal("bla")
예제 #15
0
def plot_as_graph(dynamic_graph,
                  communities=None,
                  ts=None,
                  slider=False,
                  to_datetime=False,
                  width=800,
                  height=600,
                  auto_show=False):
    """
    Plot to see the static graph at each snapshot

    can be row of graphs or an interactive graph with a slider to change snapshot.
    In all cases, the position of nodes is the same in all snapshots

    :param dynamic_graph: DynGraphSN
    :param communities: dynamic snapshot_affiliations of the network (can be ignored)
    :param ts: time of snapshot(s) to display. single value or list. default None means all snapshots.
    :param slider: If None, a slider allows to interactively choose the step (work only in jupyter notebooks on a local machine)
    :param to_datetime: one of True/False/function. If True, step IDs are converted to dates using datetime.utcfromtimestamp. If a function, should take a step ID and return a datetime object.
    :param width: width of the figure
    :param height: height of the figure
    :param auto_show: if True, the plot is directly displayed in a jupyter notebook. In any other setting, should be False, and the graph should be displayed as any bokeh plot, depending on the setting.
    :return: bokeh layout containing slider and plot, or only plot if no slider.
    """

    if to_datetime == True:
        to_datetime = datetime.utcfromtimestamp

    if ts == None:
        if isinstance(dynamic_graph, tn.DynGraphIG):
            raise Exception(
                "If using IG graphs/communities, you must specified the desired t to plot"
            )

        ts = list(dynamic_graph.snapshots_timesteps())
        if communities != None:
            ts = ts + list(communities.snapshots.keys())
            ts = sorted(list(set(ts)))

    if not isinstance(ts, list):
        ts = [ts]

    if isinstance(dynamic_graph, tn.DynGraphIG):
        temp_graph_sn = tn.DynGraphSN()
        for t in ts:
            #print(t)
            temp_graph_sn.add_snapshot(t, dynamic_graph.graph_at_time(t))
        if communities != None:
            temp_coms_sn = tn.DynCommunitiesSN()
            for t in ts:
                temp_coms_sn.set_communities(t, communities.communities(t))
        dynamic_graph = temp_graph_sn
        communities = temp_coms_sn
    CDS = _sn_graph2CDS(dynamic_graph, communities, to_datetime, ts=ts)

    unique_pos = _unique_positions(dynamic_graph, ts=ts)

    if not slider:
        list_of_figures = []
        for current_t in ts:
            (a_figure,
             a_graph_plot) = _init_net_properties(dynamic_graph, CDS,
                                                  unique_pos, current_t, width,
                                                  height, to_datetime)
            list_of_figures.append(a_figure)
        layout = bokeh.layouts.row(list_of_figures)

    else:
        init_t = ts[0]
        #slider_Step = min([allTimes[i+1]-allTimes[i] for i in range(0,len(allTimes)-1)])
        slider_Step = 1
        slider_object = bokeh.models.Slider(
            start=0, end=len(ts), value=init_t, step=1,
            title="Plotted_step")  #,callback_policy="mouseup")

        (a_figure,
         a_graph_plot) = _init_net_properties(dynamic_graph, CDS, unique_pos,
                                              init_t, width, height,
                                              to_datetime)

        def update_graph(a, oldt, newt):
            _update_net(ts[newt], a_graph_plot, dynamic_graph)

        slider_object.on_change('value', update_graph)

        layout = bokeh.layouts.column(slider_object, a_figure)

    if auto_show:

        def modify_doc(doc):
            doc.add_root(layout)

        bokeh.io.output_notebook()
        bokeh.io.show(modify_doc)
    else:
        return layout
예제 #16
0
def transversal_network_mucha_original(dyn_graph: tn.DynGraphSN,
                                       om=0.5,
                                       form="local",
                                       elapsed_time=False,
                                       matlab_session=None):
    """
    Multiplex community detection, Mucha et al.

    Algorithm described in [1]

    Brief summary: a single network is created by adding nodes between themselves in different snaphsots. A modified modularity optimization algorithm is run
    on this network

    For this function, it is necessary to have Matlab installed
    And to set up the matlab for python engine, see how to there
    https://fr.mathworks.com/help/matlab/matlab_external/install-the-matlab-engine-for-python.html
    (you can find the value of matlabroot by tapping matlabroot in your matlab console)

    If you do not have matlab, you can try to use the transversal_network_leidenalg which is slower but requires only a package installation

    [1] Mucha, P. J., Richardson, T., Macon, K., Porter, M. A., & Onnela, J. P. (2010).
    Community structure in time-dependent, multiscale, and multiplex networks.
    science, 328(5980), 876-878.

    :param dyn_graph: dynamic network
    :param om:
    :param form:
    :param elapsed_time:
    :param matlab_session:
    :return:
    """
    print("preprocessing MUCHA ")

    #Original example on genlouvain website
    #N = length(A{1});
    #T = length(A);
    #B = spalloc(N * T, N * T, N * N * T + 2 * N * T);
    #twomu = 0;
    #for s=1:T
    #     k = sum(A{s});
    #     twom = sum(k);
    #     twomu = twomu + twom;
    #     indx = [1:N]+(s - 1) * N;
    #     B(indx, indx) = A
    #     {s} - gamma * k'*k/twom;
    #
    #
    # end
    # twomu = twomu + 2 * omega * N * (T - 1);
    # B = B + omega * spdiags(ones(N * T, 2), [-N, N], N * T, N * T);
    # [S, Q] = genlouvain(B);
    # Q = Q / twomu
    # S = reshape(S, N, T);

    graphs = dyn_graph.snapshots()

    nodeOrderAllSN = []
    listModularityMatrices = []

    #for each graph in order
    for t, gT in enumerate(graphs):
        g = graphs[gT]
        nodeOrder = list(g.nodes())
        if len(nodeOrder) > 0:
            nodeOrderAllSN += [(t, n) for n in nodeOrder]

            gmat = nx.to_scipy_sparse_matrix(g,
                                             nodelist=nodeOrder,
                                             format="dok")
            k = gmat.sum(axis=0)  #degrees of nodes
            twom = k.sum(axis=1)  #sum of degrees
            nullModel = k.transpose() * k / twom
            listModularityMatrices.append(gmat - nullModel)

    #Concatenate all null modularity matrices
    #B = scipy.sparse.block_diag(*listModularityMatrices)
    B = scipy.sparse.block_diag(listModularityMatrices, format="dok")
    listModularityMatrices = None

    #B = scipy.sparse.dok_matrix(B)

    #add the link between same nodes in different timestamps
    multipleAppearances = {}  #for each node, list of indices where it appears

    ordered_real_times = dyn_graph.snapshots_timesteps()
    for (i, (t, n)) in enumerate(nodeOrderAllSN):
        multipleAppearances.setdefault(n, []).append((i, t))

    if form == "global":
        for (n, nAppearences) in multipleAppearances.items():
            for (i, t) in nAppearences:
                for (j, t) in nAppearences:
                    if i != j:
                        B[i, j] = om
    if form == "local":
        #print(multipleAppearances)
        for (n, orderedAppearences) in multipleAppearances.items():
            #print(orderedAppearences)
            for i in range(0, len(orderedAppearences) - 1):
                #BE CAREFUL, modified recently
                ii, t = orderedAppearences[i]
                ii_next, t_next = orderedAppearences[i + 1]
                #index_t = ordered_real_times.index(t)

                if ordered_real_times[t + 1] == ordered_real_times[t_next]:
                    B[ii, ii_next] = om

    if form == "local_relaxed":
        #print(multipleAppearances)
        for (n, orderedAppearences) in multipleAppearances.items():
            for i in range(0, len(orderedAppearences) - 1):
                ii, t = orderedAppearences[i]
                ii_next, t_next = orderedAppearences[i + 1]
                B[ii, ii_next] = om

    #print("saving temp file")
    #numpy.savetxt("test.csv", B, fmt="%.2f", delimiter=",")
    #print("file saved")

    #B = scipy.sparse.coo_matrix(B)
    print("calling external code")

    (S, duration) = _runMatlabCode(B, matlab_session=matlab_session)
    #print("transforming back to dynamic net")

    DCSN = tn.DynCommunitiesSN()
    times = dyn_graph.snapshots_timesteps()
    for i in range(len(S)):
        DCSN.add_affiliation(nodeOrderAllSN[i][1], S[i],
                             times[nodeOrderAllSN[i][0]])

    print("sucessfully finished MUCHA ")

    if elapsed_time:
        return (DCSN, {"total": duration})
    return DCSN
예제 #17
0
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)
예제 #18
0
def estrangement_confinement(dyn_graph: tn.DynGraphSN,
                             tolerance=0.00001,
                             convergence_tolerance=0.01,
                             delta=0.05,
                             elapsed_time=False,
                             **kwargs):
    """
    Estrangement confinement

    Algorithm introduced in [1]. Uses original code.



    [1]Kawadia, V., & Sreenivasan, S. (2012).
    Sequential detection of temporal communities by estrangement confinement.
    Scientific reports, 2, 794.

    :param delta: see original article
    :param convergence_tolerance: see original article
    :param tolerance: see original article
    :return:
    """
    print("preprocessing estrangement confinement")

    #write files
    dir = os.path.dirname(__file__)
    dir_graphs = os.path.join(dir, "temp", "estrangement", "graph")
    result_file = os.path.join(dir, "temp", "estrangement", "result.log")
    clean_create_dir(dir_graphs)
    clear_file(result_file)

    all_nodes = set()
    allGraphs = dyn_graph.snapshots()
    for g in allGraphs.values():
        all_nodes = all_nodes.union(g.nodes())
    node_dict = {v: k for k, v in enumerate(all_nodes)}
    node_dict_reversed = {v: k for k, v in node_dict.items()}

    for i, g in enumerate(allGraphs.values()):
        nx.set_edge_attributes(g, 1, "weight")
        g_copy = nx.relabel_nodes(g, node_dict, copy=True)
        _write_network_file(g_copy,
                            os.path.join(dir_graphs, str(i)),
                            out_format="ncol",
                            weight=["weight"])
    start_time = time.time()
    print("calling external code")

    ECA(dir_graphs,
        result_file,
        tolerance=tolerance,
        convergence_tolerance=convergence_tolerance,
        delta=delta,
        **kwargs)
    print("postprocessing")
    duration = time.time() - start_time

    with open(result_file, 'r') as fr:
        result = eval(fr.read())
    to_return = tn.DynCommunitiesSN()
    for t, affils in result.items():
        partitions = tn.utils.community_utils.affiliations2nodesets(affils)
        #print(partitions)
        for c, nodes in partitions.items():
            partitions[c] = [node_dict_reversed[x] for x in nodes]
        to_return.set_communities(t, partitions)

    # to_return = tn.DynCommunitiesSN()
    # ts  =list(igraph_graphs.keys())
    # for i in range(len(coms)):
    #     t= ts[i]
    #     partition = single_list_community2nodesets(coms[i],igraph_graphs[t].vs["name"])
    #    to_return.set_communities(t,partition)

    print("sucessfully estrangement confinement")

    if elapsed_time:
        return (to_return, {"total": duration})
    return to_return