Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/networkx/generators/atlas.py: 41%
34 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-10-20 07:00 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-10-20 07:00 +0000
1"""
2Generators for the small graph atlas.
3"""
4import gzip
5import importlib.resources
6import os
7import os.path
8from itertools import islice
10import networkx as nx
12__all__ = ["graph_atlas", "graph_atlas_g"]
14#: The total number of graphs in the atlas.
15#:
16#: The graphs are labeled starting from 0 and extending to (but not
17#: including) this number.
18NUM_GRAPHS = 1253
20#: The path to the data file containing the graph edge lists.
21#:
22#: This is the absolute path of the gzipped text file containing the
23#: edge list for each graph in the atlas. The file contains one entry
24#: per graph in the atlas, in sequential order, starting from graph
25#: number 0 and extending through graph number 1252 (see
26#: :data:`NUM_GRAPHS`). Each entry looks like
27#:
28#: .. sourcecode:: text
29#:
30#: GRAPH 6
31#: NODES 3
32#: 0 1
33#: 0 2
34#:
35#: where the first two lines are the graph's index in the atlas and the
36#: number of nodes in the graph, and the remaining lines are the edge
37#: list.
38#:
39#: This file was generated from a Python list of graphs via code like
40#: the following::
41#:
42#: import gzip
43#: from networkx.generators.atlas import graph_atlas_g
44#: from networkx.readwrite.edgelist import write_edgelist
45#:
46#: with gzip.open('atlas.dat.gz', 'wb') as f:
47#: for i, G in enumerate(graph_atlas_g()):
48#: f.write(bytes(f'GRAPH {i}\n', encoding='utf-8'))
49#: f.write(bytes(f'NODES {len(G)}\n', encoding='utf-8'))
50#: write_edgelist(G, f, data=False)
51#:
53# Path to the atlas file
54ATLAS_FILE = importlib.resources.files("networkx.generators") / "atlas.dat.gz"
57def _generate_graphs():
58 """Sequentially read the file containing the edge list data for the
59 graphs in the atlas and generate the graphs one at a time.
61 This function reads the file given in :data:`.ATLAS_FILE`.
63 """
64 with gzip.open(ATLAS_FILE, "rb") as f:
65 line = f.readline()
66 while line and line.startswith(b"GRAPH"):
67 # The first two lines of each entry tell us the index of the
68 # graph in the list and the number of nodes in the graph.
69 # They look like this:
70 #
71 # GRAPH 3
72 # NODES 2
73 #
74 graph_index = int(line[6:].rstrip())
75 line = f.readline()
76 num_nodes = int(line[6:].rstrip())
77 # The remaining lines contain the edge list, until the next
78 # GRAPH line (or until the end of the file).
79 edgelist = []
80 line = f.readline()
81 while line and not line.startswith(b"GRAPH"):
82 edgelist.append(line.rstrip())
83 line = f.readline()
84 G = nx.Graph()
85 G.name = f"G{graph_index}"
86 G.add_nodes_from(range(num_nodes))
87 G.add_edges_from(tuple(map(int, e.split())) for e in edgelist)
88 yield G
91@nx._dispatch(graphs=None)
92def graph_atlas(i):
93 """Returns graph number `i` from the Graph Atlas.
95 For more information, see :func:`.graph_atlas_g`.
97 Parameters
98 ----------
99 i : int
100 The index of the graph from the atlas to get. The graph at index
101 0 is assumed to be the null graph.
103 Returns
104 -------
105 list
106 A list of :class:`~networkx.Graph` objects, the one at index *i*
107 corresponding to the graph *i* in the Graph Atlas.
109 See also
110 --------
111 graph_atlas_g
113 Notes
114 -----
115 The time required by this function increases linearly with the
116 argument `i`, since it reads a large file sequentially in order to
117 generate the graph [1]_.
119 References
120 ----------
121 .. [1] Ronald C. Read and Robin J. Wilson, *An Atlas of Graphs*.
122 Oxford University Press, 1998.
124 """
125 if not (0 <= i < NUM_GRAPHS):
126 raise ValueError(f"index must be between 0 and {NUM_GRAPHS}")
127 return next(islice(_generate_graphs(), i, None))
130@nx._dispatch(graphs=None)
131def graph_atlas_g():
132 """Returns the list of all graphs with up to seven nodes named in the
133 Graph Atlas.
135 The graphs are listed in increasing order by
137 1. number of nodes,
138 2. number of edges,
139 3. degree sequence (for example 111223 < 112222),
140 4. number of automorphisms,
142 in that order, with three exceptions as described in the *Notes*
143 section below. This causes the list to correspond with the index of
144 the graphs in the Graph Atlas [atlas]_, with the first graph,
145 ``G[0]``, being the null graph.
147 Returns
148 -------
149 list
150 A list of :class:`~networkx.Graph` objects, the one at index *i*
151 corresponding to the graph *i* in the Graph Atlas.
153 See also
154 --------
155 graph_atlas
157 Notes
158 -----
159 This function may be expensive in both time and space, since it
160 reads a large file sequentially in order to populate the list.
162 Although the NetworkX atlas functions match the order of graphs
163 given in the "Atlas of Graphs" book, there are (at least) three
164 errors in the ordering described in the book. The following three
165 pairs of nodes violate the lexicographically nondecreasing sorted
166 degree sequence rule:
168 - graphs 55 and 56 with degree sequences 001111 and 000112,
169 - graphs 1007 and 1008 with degree sequences 3333444 and 3333336,
170 - graphs 1012 and 1213 with degree sequences 1244555 and 1244456.
172 References
173 ----------
174 .. [atlas] Ronald C. Read and Robin J. Wilson,
175 *An Atlas of Graphs*.
176 Oxford University Press, 1998.
178 """
179 return list(_generate_graphs())