Search code examples
pythongraphnetworkxadjacency-matrix

How does NetworkX adjacency_matrix() work internally?


As the title says, I'm working with graphs and using NetworkX. I looked for it but didn't found how the adjacency_matrix function works internally. If someone can explain or give me information about it I would appreciate it.


Solution

  • adjacency_matrix is basically an alias for to_scipy_sparse_matrix - the source code for which is below - I've added a few comments to what is in the networkx source. Further than that, you'll need to dig into the source code for scipy.sparse.coo_matrix.

    def to_scipy_sparse_matrix(G, nodelist=None, dtype=None,
                               weight='weight', format='csr'):
        from scipy import sparse
    
        # Generate nodelist if no nodelist was passed
        if nodelist is None:
            nodelist = list(G)
    
        # Check the graph has nodes/edges
        nlen = len(nodelist)
        if nlen == 0:
            raise nx.NetworkXError("Graph has no nodes or edges")
    
        # Check if nodelist has duplicates using a set
        if len(nodelist) != len(set(nodelist)):
            msg = "Ambiguous ordering: `nodelist` contained duplicates."
            raise nx.NetworkXError(msg)
    
        # Assign arbitrary indexes to each node
        index = dict(zip(nodelist, range(nlen)))
    
        # Create a zip of weight coefficients for every edge in the graph
        coefficients = zip(*((index[u], index[v], d.get(weight, 1))
                             for u, v, d in G.edges(nodelist, data=True)
                             if u in index and v in index))
        try:
            row, col, data = coefficients
        except ValueError:
            # there is no edge in the subgraph
            row, col, data = [], [], []
    
        # If G is a directed graph, call sparse.coo_matrix to generate the matrix
        # Otherwise, we need to symmetrise the matrix before calling this function.
        if G.is_directed():
            M = sparse.coo_matrix((data, (row, col)),
                                  shape=(nlen, nlen), dtype=dtype)
        else:
            # symmetrize matrix
            d = data + data
            r = row + col
            c = col + row
            # selfloop entries get double counted when symmetrizing
            # so we subtract the data on the diagonal
            selfloops = list(nx.selfloop_edges(G, data=True))
            if selfloops:
                diag_index, diag_data = zip(*((index[u], -d.get(weight, 1))
                                              for u, v, d in selfloops
                                              if u in index and v in index))
                d += diag_data
                r += diag_index
                c += diag_index
            M = sparse.coo_matrix((d, (r, c)), shape=(nlen, nlen), dtype=dtype)
        try:
            return M.asformat(format)
        # From Scipy 1.1.0, asformat will throw a ValueError instead of an
        # AttributeError if the format if not recognized.
        except (AttributeError, ValueError):
            raise nx.NetworkXError("Unknown sparse matrix format: %s" % format)