Source code for easygraph.utils.relabel

import easygraph as eg


__all__ = ["relabel_nodes", "convert_node_labels_to_integers"]


[docs]def relabel_nodes(G, mapping): if not hasattr(mapping, "__getitem__"): m = {n: mapping(n) for n in G} else: m = mapping return _relabel_copy(G, m)
def _relabel_copy(G, mapping): H = G.__class__() H.add_nodes_from(mapping.get(n, n) for n in G) H._node.update((mapping.get(n, n), d.copy()) for n, d in G.nodes.items()) if G.is_multigraph(): new_edges = [ (mapping.get(n1, n1), mapping.get(n2, n2), k, d.copy()) for (n1, n2, k, d) in G.edges ] # check for conflicting edge-keys undirected = not G.is_directed() seen_edges = set() for i, (source, target, key, data) in enumerate(new_edges): while (source, target, key) in seen_edges: if not isinstance(key, (int, float)): key = 0 key += 1 seen_edges.add((source, target, key)) if undirected: seen_edges.add((target, source, key)) new_edges[i] = (source, target, key, data) H.add_edges_from(new_edges) else: H.add_edges_from( (mapping.get(n1, n1), mapping.get(n2, n2), d.copy()) for (n1, n2, d) in G.edges ) H.graph.update(G.graph) return H
[docs]def convert_node_labels_to_integers( G, first_label=0, ordering="default", label_attribute=None ): """Returns a copy of the graph G with the nodes relabeled using consecutive integers. Parameters ---------- G : graph A easygraph graph first_label : int, optional (default=0) An integer specifying the starting offset in numbering nodes. The new integer labels are numbered first_label, ..., n-1+first_label. ordering : string "default" : inherit node ordering from G.nodes "sorted" : inherit node ordering from sorted(G.nodes) "increasing degree" : nodes are sorted by increasing degree "decreasing degree" : nodes are sorted by decreasing degree label_attribute : string, optional (default=None) Name of node attribute to store old label. If None no attribute is created. Notes ----- Node and edge attribute data are copied to the new (relabeled) graph. There is no guarantee that the relabeling of nodes to integers will give the same two integers for two (even identical graphs). Use the `ordering` argument to try to preserve the order. See Also -------- relabel_nodes """ N = G.number_of_nodes() + first_label if ordering == "default": mapping = dict(zip(G.nodes, range(first_label, N))) elif ordering == "sorted": nlist = sorted(G.nodes) mapping = dict(zip(nlist, range(first_label, N))) elif ordering == "increasing degree": dv_pairs = [(d, n) for (n, d) in G.degree()] dv_pairs.sort() # in-place sort from lowest to highest degree mapping = dict(zip([n for d, n in dv_pairs], range(first_label, N))) elif ordering == "decreasing degree": dv_pairs = [(d, n) for (n, d) in G.degree()] dv_pairs.sort() # in-place sort from lowest to highest degree dv_pairs.reverse() mapping = dict(zip([n for d, n in dv_pairs], range(first_label, N))) else: raise eg.EasyGraphError(f"Unknown node ordering: {ordering}") H = relabel_nodes(G, mapping) # create node attribute with the old label if label_attribute is not None: eg.set_node_attributes(H, {v: k for k, v in mapping.items()}, label_attribute) return H