Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/networkx/readwrite/adjlist.py: 19%

57 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-10-20 07:00 +0000

1""" 

2************** 

3Adjacency List 

4************** 

5Read and write NetworkX graphs as adjacency lists. 

6 

7Adjacency list format is useful for graphs without data associated 

8with nodes or edges and for nodes that can be meaningfully represented 

9as strings. 

10 

11Format 

12------ 

13The adjacency list format consists of lines with node labels. The 

14first label in a line is the source node. Further labels in the line 

15are considered target nodes and are added to the graph along with an edge 

16between the source node and target node. 

17 

18The graph with edges a-b, a-c, d-e can be represented as the following 

19adjacency list (anything following the # in a line is a comment):: 

20 

21 a b c # source target target 

22 d e 

23""" 

24 

25__all__ = ["generate_adjlist", "write_adjlist", "parse_adjlist", "read_adjlist"] 

26 

27import networkx as nx 

28from networkx.utils import open_file 

29 

30 

31def generate_adjlist(G, delimiter=" "): 

32 """Generate a single line of the graph G in adjacency list format. 

33 

34 Parameters 

35 ---------- 

36 G : NetworkX graph 

37 

38 delimiter : string, optional 

39 Separator for node labels 

40 

41 Returns 

42 ------- 

43 lines : string 

44 Lines of data in adjlist format. 

45 

46 Examples 

47 -------- 

48 >>> G = nx.lollipop_graph(4, 3) 

49 >>> for line in nx.generate_adjlist(G): 

50 ... print(line) 

51 0 1 2 3 

52 1 2 3 

53 2 3 

54 3 4 

55 4 5 

56 5 6 

57 6 

58 

59 See Also 

60 -------- 

61 write_adjlist, read_adjlist 

62 

63 Notes 

64 ----- 

65 The default `delimiter=" "` will result in unexpected results if node names contain 

66 whitespace characters. To avoid this problem, specify an alternate delimiter when spaces are 

67 valid in node names. 

68 

69 NB: This option is not available for data that isn't user-generated. 

70 

71 """ 

72 directed = G.is_directed() 

73 seen = set() 

74 for s, nbrs in G.adjacency(): 

75 line = str(s) + delimiter 

76 for t, data in nbrs.items(): 

77 if not directed and t in seen: 

78 continue 

79 if G.is_multigraph(): 

80 for d in data.values(): 

81 line += str(t) + delimiter 

82 else: 

83 line += str(t) + delimiter 

84 if not directed: 

85 seen.add(s) 

86 yield line[: -len(delimiter)] 

87 

88 

89@open_file(1, mode="wb") 

90def write_adjlist(G, path, comments="#", delimiter=" ", encoding="utf-8"): 

91 """Write graph G in single-line adjacency-list format to path. 

92 

93 

94 Parameters 

95 ---------- 

96 G : NetworkX graph 

97 

98 path : string or file 

99 Filename or file handle for data output. 

100 Filenames ending in .gz or .bz2 will be compressed. 

101 

102 comments : string, optional 

103 Marker for comment lines 

104 

105 delimiter : string, optional 

106 Separator for node labels 

107 

108 encoding : string, optional 

109 Text encoding. 

110 

111 Examples 

112 -------- 

113 >>> G = nx.path_graph(4) 

114 >>> nx.write_adjlist(G, "test.adjlist") 

115 

116 The path can be a filehandle or a string with the name of the file. If a 

117 filehandle is provided, it has to be opened in 'wb' mode. 

118 

119 >>> fh = open("test.adjlist", "wb") 

120 >>> nx.write_adjlist(G, fh) 

121 

122 Notes 

123 ----- 

124 The default `delimiter=" "` will result in unexpected results if node names contain 

125 whitespace characters. To avoid this problem, specify an alternate delimiter when spaces are 

126 valid in node names. 

127 NB: This option is not available for data that isn't user-generated. 

128 

129 This format does not store graph, node, or edge data. 

130 

131 See Also 

132 -------- 

133 read_adjlist, generate_adjlist 

134 """ 

135 import sys 

136 import time 

137 

138 pargs = comments + " ".join(sys.argv) + "\n" 

139 header = ( 

140 pargs 

141 + comments 

142 + f" GMT {time.asctime(time.gmtime())}\n" 

143 + comments 

144 + f" {G.name}\n" 

145 ) 

146 path.write(header.encode(encoding)) 

147 

148 for line in generate_adjlist(G, delimiter): 

149 line += "\n" 

150 path.write(line.encode(encoding)) 

151 

152 

153@nx._dispatch(graphs=None) 

154def parse_adjlist( 

155 lines, comments="#", delimiter=None, create_using=None, nodetype=None 

156): 

157 """Parse lines of a graph adjacency list representation. 

158 

159 Parameters 

160 ---------- 

161 lines : list or iterator of strings 

162 Input data in adjlist format 

163 

164 create_using : NetworkX graph constructor, optional (default=nx.Graph) 

165 Graph type to create. If graph instance, then cleared before populated. 

166 

167 nodetype : Python type, optional 

168 Convert nodes to this type. 

169 

170 comments : string, optional 

171 Marker for comment lines 

172 

173 delimiter : string, optional 

174 Separator for node labels. The default is whitespace. 

175 

176 Returns 

177 ------- 

178 G: NetworkX graph 

179 The graph corresponding to the lines in adjacency list format. 

180 

181 Examples 

182 -------- 

183 >>> lines = ["1 2 5", "2 3 4", "3 5", "4", "5"] 

184 >>> G = nx.parse_adjlist(lines, nodetype=int) 

185 >>> nodes = [1, 2, 3, 4, 5] 

186 >>> all(node in G for node in nodes) 

187 True 

188 >>> edges = [(1, 2), (1, 5), (2, 3), (2, 4), (3, 5)] 

189 >>> all((u, v) in G.edges() or (v, u) in G.edges() for (u, v) in edges) 

190 True 

191 

192 See Also 

193 -------- 

194 read_adjlist 

195 

196 """ 

197 G = nx.empty_graph(0, create_using) 

198 for line in lines: 

199 p = line.find(comments) 

200 if p >= 0: 

201 line = line[:p] 

202 if not len(line): 

203 continue 

204 vlist = line.strip().split(delimiter) 

205 u = vlist.pop(0) 

206 # convert types 

207 if nodetype is not None: 

208 try: 

209 u = nodetype(u) 

210 except BaseException as err: 

211 raise TypeError( 

212 f"Failed to convert node ({u}) to type " f"{nodetype}" 

213 ) from err 

214 G.add_node(u) 

215 if nodetype is not None: 

216 try: 

217 vlist = list(map(nodetype, vlist)) 

218 except BaseException as err: 

219 raise TypeError( 

220 f"Failed to convert nodes ({','.join(vlist)}) to type {nodetype}" 

221 ) from err 

222 G.add_edges_from([(u, v) for v in vlist]) 

223 return G 

224 

225 

226@open_file(0, mode="rb") 

227@nx._dispatch(graphs=None) 

228def read_adjlist( 

229 path, 

230 comments="#", 

231 delimiter=None, 

232 create_using=None, 

233 nodetype=None, 

234 encoding="utf-8", 

235): 

236 """Read graph in adjacency list format from path. 

237 

238 Parameters 

239 ---------- 

240 path : string or file 

241 Filename or file handle to read. 

242 Filenames ending in .gz or .bz2 will be uncompressed. 

243 

244 create_using : NetworkX graph constructor, optional (default=nx.Graph) 

245 Graph type to create. If graph instance, then cleared before populated. 

246 

247 nodetype : Python type, optional 

248 Convert nodes to this type. 

249 

250 comments : string, optional 

251 Marker for comment lines 

252 

253 delimiter : string, optional 

254 Separator for node labels. The default is whitespace. 

255 

256 Returns 

257 ------- 

258 G: NetworkX graph 

259 The graph corresponding to the lines in adjacency list format. 

260 

261 Examples 

262 -------- 

263 >>> G = nx.path_graph(4) 

264 >>> nx.write_adjlist(G, "test.adjlist") 

265 >>> G = nx.read_adjlist("test.adjlist") 

266 

267 The path can be a filehandle or a string with the name of the file. If a 

268 filehandle is provided, it has to be opened in 'rb' mode. 

269 

270 >>> fh = open("test.adjlist", "rb") 

271 >>> G = nx.read_adjlist(fh) 

272 

273 Filenames ending in .gz or .bz2 will be compressed. 

274 

275 >>> nx.write_adjlist(G, "test.adjlist.gz") 

276 >>> G = nx.read_adjlist("test.adjlist.gz") 

277 

278 The optional nodetype is a function to convert node strings to nodetype. 

279 

280 For example 

281 

282 >>> G = nx.read_adjlist("test.adjlist", nodetype=int) 

283 

284 will attempt to convert all nodes to integer type. 

285 

286 Since nodes must be hashable, the function nodetype must return hashable 

287 types (e.g. int, float, str, frozenset - or tuples of those, etc.) 

288 

289 The optional create_using parameter indicates the type of NetworkX graph 

290 created. The default is `nx.Graph`, an undirected graph. 

291 To read the data as a directed graph use 

292 

293 >>> G = nx.read_adjlist("test.adjlist", create_using=nx.DiGraph) 

294 

295 Notes 

296 ----- 

297 This format does not store graph or node data. 

298 

299 See Also 

300 -------- 

301 write_adjlist 

302 """ 

303 lines = (line.decode(encoding) for line in path) 

304 return parse_adjlist( 

305 lines, 

306 comments=comments, 

307 delimiter=delimiter, 

308 create_using=create_using, 

309 nodetype=nodetype, 

310 )