Spaces:
Paused
Paused
| """ | |
| ************** | |
| Adjacency List | |
| ************** | |
| Read and write NetworkX graphs as adjacency lists. | |
| Adjacency list format is useful for graphs without data associated | |
| with nodes or edges and for nodes that can be meaningfully represented | |
| as strings. | |
| Format | |
| ------ | |
| The adjacency list format consists of lines with node labels. The | |
| first label in a line is the source node. Further labels in the line | |
| are considered target nodes and are added to the graph along with an edge | |
| between the source node and target node. | |
| The graph with edges a-b, a-c, d-e can be represented as the following | |
| adjacency list (anything following the # in a line is a comment):: | |
| a b c # source target target | |
| d e | |
| """ | |
| __all__ = ["generate_adjlist", "write_adjlist", "parse_adjlist", "read_adjlist"] | |
| import networkx as nx | |
| from networkx.utils import open_file | |
| def generate_adjlist(G, delimiter=" "): | |
| """Generate a single line of the graph G in adjacency list format. | |
| Parameters | |
| ---------- | |
| G : NetworkX graph | |
| delimiter : string, optional | |
| Separator for node labels | |
| Returns | |
| ------- | |
| lines : string | |
| Lines of data in adjlist format. | |
| Examples | |
| -------- | |
| >>> G = nx.lollipop_graph(4, 3) | |
| >>> for line in nx.generate_adjlist(G): | |
| ... print(line) | |
| 0 1 2 3 | |
| 1 2 3 | |
| 2 3 | |
| 3 4 | |
| 4 5 | |
| 5 6 | |
| 6 | |
| See Also | |
| -------- | |
| write_adjlist, read_adjlist | |
| Notes | |
| ----- | |
| The default `delimiter=" "` will result in unexpected results if node names contain | |
| whitespace characters. To avoid this problem, specify an alternate delimiter when spaces are | |
| valid in node names. | |
| NB: This option is not available for data that isn't user-generated. | |
| """ | |
| directed = G.is_directed() | |
| seen = set() | |
| for s, nbrs in G.adjacency(): | |
| line = str(s) + delimiter | |
| for t, data in nbrs.items(): | |
| if not directed and t in seen: | |
| continue | |
| if G.is_multigraph(): | |
| for d in data.values(): | |
| line += str(t) + delimiter | |
| else: | |
| line += str(t) + delimiter | |
| if not directed: | |
| seen.add(s) | |
| yield line[: -len(delimiter)] | |
| def write_adjlist(G, path, comments="#", delimiter=" ", encoding="utf-8"): | |
| """Write graph G in single-line adjacency-list format to path. | |
| Parameters | |
| ---------- | |
| G : NetworkX graph | |
| path : string or file | |
| Filename or file handle for data output. | |
| Filenames ending in .gz or .bz2 will be compressed. | |
| comments : string, optional | |
| Marker for comment lines | |
| delimiter : string, optional | |
| Separator for node labels | |
| encoding : string, optional | |
| Text encoding. | |
| Examples | |
| -------- | |
| >>> G = nx.path_graph(4) | |
| >>> nx.write_adjlist(G, "test.adjlist") | |
| The path can be a filehandle or a string with the name of the file. If a | |
| filehandle is provided, it has to be opened in 'wb' mode. | |
| >>> fh = open("test.adjlist", "wb") | |
| >>> nx.write_adjlist(G, fh) | |
| Notes | |
| ----- | |
| The default `delimiter=" "` will result in unexpected results if node names contain | |
| whitespace characters. To avoid this problem, specify an alternate delimiter when spaces are | |
| valid in node names. | |
| NB: This option is not available for data that isn't user-generated. | |
| This format does not store graph, node, or edge data. | |
| See Also | |
| -------- | |
| read_adjlist, generate_adjlist | |
| """ | |
| import sys | |
| import time | |
| pargs = comments + " ".join(sys.argv) + "\n" | |
| header = ( | |
| pargs | |
| + comments | |
| + f" GMT {time.asctime(time.gmtime())}\n" | |
| + comments | |
| + f" {G.name}\n" | |
| ) | |
| path.write(header.encode(encoding)) | |
| for line in generate_adjlist(G, delimiter): | |
| line += "\n" | |
| path.write(line.encode(encoding)) | |
| def parse_adjlist( | |
| lines, comments="#", delimiter=None, create_using=None, nodetype=None | |
| ): | |
| """Parse lines of a graph adjacency list representation. | |
| Parameters | |
| ---------- | |
| lines : list or iterator of strings | |
| Input data in adjlist format | |
| create_using : NetworkX graph constructor, optional (default=nx.Graph) | |
| Graph type to create. If graph instance, then cleared before populated. | |
| nodetype : Python type, optional | |
| Convert nodes to this type. | |
| comments : string, optional | |
| Marker for comment lines | |
| delimiter : string, optional | |
| Separator for node labels. The default is whitespace. | |
| Returns | |
| ------- | |
| G: NetworkX graph | |
| The graph corresponding to the lines in adjacency list format. | |
| Examples | |
| -------- | |
| >>> lines = ["1 2 5", "2 3 4", "3 5", "4", "5"] | |
| >>> G = nx.parse_adjlist(lines, nodetype=int) | |
| >>> nodes = [1, 2, 3, 4, 5] | |
| >>> all(node in G for node in nodes) | |
| True | |
| >>> edges = [(1, 2), (1, 5), (2, 3), (2, 4), (3, 5)] | |
| >>> all((u, v) in G.edges() or (v, u) in G.edges() for (u, v) in edges) | |
| True | |
| See Also | |
| -------- | |
| read_adjlist | |
| """ | |
| G = nx.empty_graph(0, create_using) | |
| for line in lines: | |
| p = line.find(comments) | |
| if p >= 0: | |
| line = line[:p] | |
| if not len(line): | |
| continue | |
| vlist = line.strip().split(delimiter) | |
| u = vlist.pop(0) | |
| # convert types | |
| if nodetype is not None: | |
| try: | |
| u = nodetype(u) | |
| except BaseException as err: | |
| raise TypeError( | |
| f"Failed to convert node ({u}) to type " f"{nodetype}" | |
| ) from err | |
| G.add_node(u) | |
| if nodetype is not None: | |
| try: | |
| vlist = list(map(nodetype, vlist)) | |
| except BaseException as err: | |
| raise TypeError( | |
| f"Failed to convert nodes ({','.join(vlist)}) to type {nodetype}" | |
| ) from err | |
| G.add_edges_from([(u, v) for v in vlist]) | |
| return G | |
| def read_adjlist( | |
| path, | |
| comments="#", | |
| delimiter=None, | |
| create_using=None, | |
| nodetype=None, | |
| encoding="utf-8", | |
| ): | |
| """Read graph in adjacency list format from path. | |
| Parameters | |
| ---------- | |
| path : string or file | |
| Filename or file handle to read. | |
| Filenames ending in .gz or .bz2 will be uncompressed. | |
| create_using : NetworkX graph constructor, optional (default=nx.Graph) | |
| Graph type to create. If graph instance, then cleared before populated. | |
| nodetype : Python type, optional | |
| Convert nodes to this type. | |
| comments : string, optional | |
| Marker for comment lines | |
| delimiter : string, optional | |
| Separator for node labels. The default is whitespace. | |
| Returns | |
| ------- | |
| G: NetworkX graph | |
| The graph corresponding to the lines in adjacency list format. | |
| Examples | |
| -------- | |
| >>> G = nx.path_graph(4) | |
| >>> nx.write_adjlist(G, "test.adjlist") | |
| >>> G = nx.read_adjlist("test.adjlist") | |
| The path can be a filehandle or a string with the name of the file. If a | |
| filehandle is provided, it has to be opened in 'rb' mode. | |
| >>> fh = open("test.adjlist", "rb") | |
| >>> G = nx.read_adjlist(fh) | |
| Filenames ending in .gz or .bz2 will be compressed. | |
| >>> nx.write_adjlist(G, "test.adjlist.gz") | |
| >>> G = nx.read_adjlist("test.adjlist.gz") | |
| The optional nodetype is a function to convert node strings to nodetype. | |
| For example | |
| >>> G = nx.read_adjlist("test.adjlist", nodetype=int) | |
| will attempt to convert all nodes to integer type. | |
| Since nodes must be hashable, the function nodetype must return hashable | |
| types (e.g. int, float, str, frozenset - or tuples of those, etc.) | |
| The optional create_using parameter indicates the type of NetworkX graph | |
| created. The default is `nx.Graph`, an undirected graph. | |
| To read the data as a directed graph use | |
| >>> G = nx.read_adjlist("test.adjlist", create_using=nx.DiGraph) | |
| Notes | |
| ----- | |
| This format does not store graph or node data. | |
| See Also | |
| -------- | |
| write_adjlist | |
| """ | |
| lines = (line.decode(encoding) for line in path) | |
| return parse_adjlist( | |
| lines, | |
| comments=comments, | |
| delimiter=delimiter, | |
| create_using=create_using, | |
| nodetype=nodetype, | |
| ) | |