Finding cycle of 3 nodes ( or triangles) in a graph

后端 未结 11 2066
南旧
南旧 2020-12-31 15:42

I am working with complex networks. I want to find group of nodes which forms a cycle of 3 nodes (or triangles) in a given graph. As my graph contains about million edges, u

相关标签:
11条回答
  • 2020-12-31 16:21

    i just found that nx.edge_disjoint_paths works to count the triangle contains certain edges. faster than nx.enumerate_all_cliques and nx.cycle_basis. It returns the edges disjoint paths between source and target.Edge disjoint paths are paths that do not share any edge.
    And result-1 is the number of triangles that contain certain edges or between source node and target node.

    edge_triangle_dict = {}
    for i in g.edges:
        edge_triangle_dict[i] = len(list(nx.edge_disjoint_paths(g, i[0], i[1]))-1)
    
    0 讨论(0)
  • 2020-12-31 16:23

    This is a more efficient version of Ajay M answer (I would have commented it, but I've not enough reputation).

    Indeed the enumerate_all_cliques method of networkx will return all cliques in the graph, irrespectively of their length; hence looping over it may take a lot of time (especially with very dense graphs).

    Moreover, once defined for triangles, it's just a matter of parametrization to generalize the method for every clique length so here's a function:

    import networkx as nx
    
    def get_cliques_by_length(G, length_clique):
        """ Return the list of all cliques in an undirected graph G with length 
        equal to length_clique. """
        cliques = []
        for c in nx.enumerate_all_cliques(G) :
            if len(c) <= length_clique:
                if len(c) == length_clique:
                    cliques.append(c)            
            else:
                return cliques
        # return empty list if nothing is found
        return cliques
    

    To get triangles just use get_cliques_by_length(G, 3).

    Caveat: this method works only for undirected graphs. Algorithm for cliques in directed graphs are not provided in networkx

    0 讨论(0)
  • 2020-12-31 16:27

    I don't want to sound harsh, but have you tried to Google it? The first link is a pretty quick algorithm to do that: http://www.mail-archive.com/algogeeks@googlegroups.com/msg05642.html

    And then there is this article on ACM (which you may have access to): http://portal.acm.org/citation.cfm?id=244866 (and if you don't have access, I am sure if you kindly ask the lady who wrote it, you will get a copy.)

    Also, I can imagine a triangle enumeration method based on clique-decomposition, but I don't know if it was described somewhere.

    0 讨论(0)
  • 2020-12-31 16:33

    Assuming its an undirected graph, the answer lies in networkx library of python. if you just need to count triangles, use:

    import networkx as nx
    tri=nx.triangles(g)
    

    But if you need to know the edge list with triangle (triadic) relationship, use

    all_cliques= nx.enumerate_all_cliques(g)
    

    This will give you all cliques (k=1,2,3...max degree - 1)

    So, to filter just triangles i.e k=3,

    triad_cliques=[x for x in all_cliques if len(x)==3 ]
    

    The triad_cliques will give a edge list with only triangles.

    0 讨论(0)
  • 2020-12-31 16:33

    Surprised to see no mention of the Networkx triangles function. I know it doesn't necessarily return the groups of nodes that form a triangle, but should be pretty relevant to many who find themselves on this page.

    nx.triangles(G) # list of how many triangles each node is part of
    sum(nx.triangles(G).values())/3 # total number of triangles
    

    An alternative way to return clumps of nodes would be something like...

    for u,v,d in G.edges(data=True):
        u_array = adj_m.getrow(u).nonzero()[1] # get lists of all adjacent nodes
        v_array = adj_m.getrow(v).nonzero()[1]
        # find the intersection of the two sets - these are the third node of the triangle
        np.intersect1d(v_array,u_array)
    
    0 讨论(0)
  • 2020-12-31 16:33

    If you don't care about multiple copies of the same triangle in different order then a list of 3-tuples works:

    from itertools import combinations as combos
    [(n,nbr,nbr2) for n in G for nbr, nbr2 in combos(G[n],2) if nbr in G[nbr2]]
    

    The logic here is to check each pair of neighbors of every node to see if they are connected. G[n] is a fast way to iterate over or look up neighbors.

    If you want to get rid of reorderings, turn each triple into a frozenset and make a set of the frozensets:

    set(frozenset([n,nbr,nbr2]) for n in G for nbr, nbr2 in combos(G[n]) if nbr in G[nbr2])
    

    If you don't like frozenset and want a list of sets then:

    triple_iter = ((n, nbr, nbr2) for n in G for nbr, nbr2 in combos(G[n],2) if nbr in G[nbr2])
    triangles = set(frozenset(tri) for tri in triple_iter)
    nice_triangles = [set(tri) for tri in triangles]
    
    0 讨论(0)
提交回复
热议问题