Get the list of Triad nodes , who fall under the category of individual Triadic Census

前端 未结 2 783
温柔的废话
温柔的废话 2021-01-27 05:14

By executing Networkx triadic_census Algorithm, I\'m able to get the dictionary of the number of nodes falling on each type of triadic census

triad_census_socia         


        
2条回答
  •  难免孤独
    2021-01-27 05:35

    Building on vurmux's answer (by fixing the '102' and '012' triads):

    import networkx as nx
    import itertools
    
    
    def _tricode(G, v, u, w):
        """Returns the integer code of the given triad.
    
        This is some fancy magic that comes from Batagelj and Mrvar's paper. It
        treats each edge joining a pair of `v`, `u`, and `w` as a bit in
        the binary representation of an integer.
    
        """
        combos = ((v, u, 1), (u, v, 2), (v, w, 4), (w, v, 8), (u, w, 16),
                  (w, u, 32))
        return sum(x for u, v, x in combos if v in G[u])
    
    
    G = nx.DiGraph()
    G.add_nodes_from([1, 2, 3, 4, 5])
    G.add_edges_from([(1, 2), (2, 3), (2, 4), (4, 5)])
    
    #: The integer codes representing each type of triad.
    #: Triads that are the same up to symmetry have the same code.
    TRICODES = (1, 2, 2, 3, 2, 4, 6, 8, 2, 6, 5, 7, 3, 8, 7, 11, 2, 6, 4, 8, 5, 9,
                9, 13, 6, 10, 9, 14, 7, 14, 12, 15, 2, 5, 6, 7, 6, 9, 10, 14, 4, 9,
                9, 12, 8, 13, 14, 15, 3, 7, 8, 11, 7, 12, 14, 15, 8, 14, 13, 15,
                11, 15, 15, 16)
    
    #: The names of each type of triad. The order of the elements is
    #: important: it corresponds to the tricodes given in :data:`TRICODES`.
    TRIAD_NAMES = ('003', '012', '102', '021D', '021U', '021C', '111D', '111U',
                   '030T', '030C', '201', '120D', '120U', '120C', '210', '300')
    
    #: A dictionary mapping triad code to triad name.
    TRICODE_TO_NAME = {i: TRIAD_NAMES[code - 1] for i, code in enumerate(TRICODES)}
    
    triad_nodes = {name: set([]) for name in TRIAD_NAMES}
    m = {v: i for i, v in enumerate(G)}
    for v in G:
        vnbrs = set(G.pred[v]) | set(G.succ[v])
        for u in vnbrs:
            if m[u] > m[v]:
                unbrs = set(G.pred[u]) | set(G.succ[u])
                neighbors = (vnbrs | unbrs) - {u, v}
                not_neighbors = set(G.nodes()) - neighbors - {u, v}
                # Find dyadic triads
                for w in not_neighbors:
                    if v in G[u] and u in G[v]:
                        triad_nodes['102'].add(tuple(sorted([u, v, w])))
                    else:
                        triad_nodes['012'].add(tuple(sorted([u, v, w])))
                for w in neighbors:
                    if m[u] < m[w] or (m[v] < m[w] < m[u] and
                                       v not in G.pred[w] and
                                       v not in G.succ[w]):
                        code = _tricode(G, v, u, w)
                        triad_nodes[TRICODE_TO_NAME[code]].add(
                            tuple(sorted([u, v, w])))
    # find null triads
    all_tuples = set()
    for s in triad_nodes.values():
        all_tuples = all_tuples.union(s)
    triad_nodes['003'] = set(itertools.combinations(G.nodes(), 3)).difference(all_tuples)
    

    Result

    # print(triad_nodes)
    
    # {'003': {(1, 3, 4), (1, 3, 5)},
    #  '012': {(1, 2, 5), (1, 4, 5), (2, 3, 5), (3, 4, 5)},
    #  '102': set(),
    #  '021D': {(2, 3, 4)},
    #  '021U': set(),
    #  '021C': {(1, 2, 3), (1, 2, 4), (2, 4, 5)},
    #  '111D': set(),
    #  '111U': set(),
    #  '030T': set(),
    #  '030C': set(),
    #  '201': set(),
    #  '120D': set(),
    #  '120U': set(),
    #  '120C': set(),
    #  '210': set(),
    #  '300': set()}
    

    In agreement with nx.triadic_census

    # print(nx.triadic_census(G))
    # {'003': 2,
    #  '012': 4,
    #  '102': 0,
    #  '021D': 1,
    #  '021U': 0,
    #  '021C': 3,
    #  '111D': 0,
    #  '111U': 0,
    #  '030T': 0,
    #  '030C': 0,
    #  '201': 0,
    #  '120D': 0,
    #  '120U': 0,
    #  '120C': 0,
    #  '210': 0,
    #  '300': 0}
    

提交回复
热议问题