Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/networkx/algorithms/bipartite/edgelist.py: 16%

73 statements  

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

1""" 

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

3Bipartite Edge Lists 

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

5Read and write NetworkX graphs as bipartite edge lists. 

6 

7Format 

8------ 

9You can read or write three formats of edge lists with these functions. 

10 

11Node pairs with no data:: 

12 

13 1 2 

14 

15Python dictionary as data:: 

16 

17 1 2 {'weight':7, 'color':'green'} 

18 

19Arbitrary data:: 

20 

21 1 2 7 green 

22 

23For each edge (u, v) the node u is assigned to part 0 and the node v to part 1. 

24""" 

25__all__ = ["generate_edgelist", "write_edgelist", "parse_edgelist", "read_edgelist"] 

26 

27import networkx as nx 

28from networkx.utils import not_implemented_for, open_file 

29 

30 

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

32def write_edgelist(G, path, comments="#", delimiter=" ", data=True, encoding="utf-8"): 

33 """Write a bipartite graph as a list of edges. 

34 

35 Parameters 

36 ---------- 

37 G : Graph 

38 A NetworkX bipartite graph 

39 path : file or string 

40 File or filename to write. If a file is provided, it must be 

41 opened in 'wb' mode. Filenames ending in .gz or .bz2 will be compressed. 

42 comments : string, optional 

43 The character used to indicate the start of a comment 

44 delimiter : string, optional 

45 The string used to separate values. The default is whitespace. 

46 data : bool or list, optional 

47 If False write no edge data. 

48 If True write a string representation of the edge data dictionary.. 

49 If a list (or other iterable) is provided, write the keys specified 

50 in the list. 

51 encoding: string, optional 

52 Specify which encoding to use when writing file. 

53 

54 Examples 

55 -------- 

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

57 >>> G.add_nodes_from([0, 2], bipartite=0) 

58 >>> G.add_nodes_from([1, 3], bipartite=1) 

59 >>> nx.write_edgelist(G, "test.edgelist") 

60 >>> fh = open("test.edgelist", "wb") 

61 >>> nx.write_edgelist(G, fh) 

62 >>> nx.write_edgelist(G, "test.edgelist.gz") 

63 >>> nx.write_edgelist(G, "test.edgelist.gz", data=False) 

64 

65 >>> G = nx.Graph() 

66 >>> G.add_edge(1, 2, weight=7, color="red") 

67 >>> nx.write_edgelist(G, "test.edgelist", data=False) 

68 >>> nx.write_edgelist(G, "test.edgelist", data=["color"]) 

69 >>> nx.write_edgelist(G, "test.edgelist", data=["color", "weight"]) 

70 

71 See Also 

72 -------- 

73 write_edgelist 

74 generate_edgelist 

75 """ 

76 for line in generate_edgelist(G, delimiter, data): 

77 line += "\n" 

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

79 

80 

81@not_implemented_for("directed") 

82def generate_edgelist(G, delimiter=" ", data=True): 

83 """Generate a single line of the bipartite graph G in edge list format. 

84 

85 Parameters 

86 ---------- 

87 G : NetworkX graph 

88 The graph is assumed to have node attribute `part` set to 0,1 representing 

89 the two graph parts 

90 

91 delimiter : string, optional 

92 Separator for node labels 

93 

94 data : bool or list of keys 

95 If False generate no edge data. If True use a dictionary 

96 representation of edge data. If a list of keys use a list of data 

97 values corresponding to the keys. 

98 

99 Returns 

100 ------- 

101 lines : string 

102 Lines of data in adjlist format. 

103 

104 Examples 

105 -------- 

106 >>> from networkx.algorithms import bipartite 

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

108 >>> G.add_nodes_from([0, 2], bipartite=0) 

109 >>> G.add_nodes_from([1, 3], bipartite=1) 

110 >>> G[1][2]["weight"] = 3 

111 >>> G[2][3]["capacity"] = 12 

112 >>> for line in bipartite.generate_edgelist(G, data=False): 

113 ... print(line) 

114 0 1 

115 2 1 

116 2 3 

117 

118 >>> for line in bipartite.generate_edgelist(G): 

119 ... print(line) 

120 0 1 {} 

121 2 1 {'weight': 3} 

122 2 3 {'capacity': 12} 

123 

124 >>> for line in bipartite.generate_edgelist(G, data=["weight"]): 

125 ... print(line) 

126 0 1 

127 2 1 3 

128 2 3 

129 """ 

130 try: 

131 part0 = [n for n, d in G.nodes.items() if d["bipartite"] == 0] 

132 except BaseException as err: 

133 raise AttributeError("Missing node attribute `bipartite`") from err 

134 if data is True or data is False: 

135 for n in part0: 

136 for edge in G.edges(n, data=data): 

137 yield delimiter.join(map(str, edge)) 

138 else: 

139 for n in part0: 

140 for u, v, d in G.edges(n, data=True): 

141 edge = [u, v] 

142 try: 

143 edge.extend(d[k] for k in data) 

144 except KeyError: 

145 pass # missing data for this edge, should warn? 

146 yield delimiter.join(map(str, edge)) 

147 

148 

149@nx._dispatch(name="bipartite_parse_edgelist", graphs=None) 

150def parse_edgelist( 

151 lines, comments="#", delimiter=None, create_using=None, nodetype=None, data=True 

152): 

153 """Parse lines of an edge list representation of a bipartite graph. 

154 

155 Parameters 

156 ---------- 

157 lines : list or iterator of strings 

158 Input data in edgelist format 

159 comments : string, optional 

160 Marker for comment lines 

161 delimiter : string, optional 

162 Separator for node labels 

163 create_using: NetworkX graph container, optional 

164 Use given NetworkX graph for holding nodes or edges. 

165 nodetype : Python type, optional 

166 Convert nodes to this type. 

167 data : bool or list of (label,type) tuples 

168 If False generate no edge data or if True use a dictionary 

169 representation of edge data or a list tuples specifying dictionary 

170 key names and types for edge data. 

171 

172 Returns 

173 ------- 

174 G: NetworkX Graph 

175 The bipartite graph corresponding to lines 

176 

177 Examples 

178 -------- 

179 Edgelist with no data: 

180 

181 >>> from networkx.algorithms import bipartite 

182 >>> lines = ["1 2", "2 3", "3 4"] 

183 >>> G = bipartite.parse_edgelist(lines, nodetype=int) 

184 >>> sorted(G.nodes()) 

185 [1, 2, 3, 4] 

186 >>> sorted(G.nodes(data=True)) 

187 [(1, {'bipartite': 0}), (2, {'bipartite': 0}), (3, {'bipartite': 0}), (4, {'bipartite': 1})] 

188 >>> sorted(G.edges()) 

189 [(1, 2), (2, 3), (3, 4)] 

190 

191 Edgelist with data in Python dictionary representation: 

192 

193 >>> lines = ["1 2 {'weight':3}", "2 3 {'weight':27}", "3 4 {'weight':3.0}"] 

194 >>> G = bipartite.parse_edgelist(lines, nodetype=int) 

195 >>> sorted(G.nodes()) 

196 [1, 2, 3, 4] 

197 >>> sorted(G.edges(data=True)) 

198 [(1, 2, {'weight': 3}), (2, 3, {'weight': 27}), (3, 4, {'weight': 3.0})] 

199 

200 Edgelist with data in a list: 

201 

202 >>> lines = ["1 2 3", "2 3 27", "3 4 3.0"] 

203 >>> G = bipartite.parse_edgelist(lines, nodetype=int, data=(("weight", float),)) 

204 >>> sorted(G.nodes()) 

205 [1, 2, 3, 4] 

206 >>> sorted(G.edges(data=True)) 

207 [(1, 2, {'weight': 3.0}), (2, 3, {'weight': 27.0}), (3, 4, {'weight': 3.0})] 

208 

209 See Also 

210 -------- 

211 """ 

212 from ast import literal_eval 

213 

214 G = nx.empty_graph(0, create_using) 

215 for line in lines: 

216 p = line.find(comments) 

217 if p >= 0: 

218 line = line[:p] 

219 if not len(line): 

220 continue 

221 # split line, should have 2 or more 

222 s = line.strip().split(delimiter) 

223 if len(s) < 2: 

224 continue 

225 u = s.pop(0) 

226 v = s.pop(0) 

227 d = s 

228 if nodetype is not None: 

229 try: 

230 u = nodetype(u) 

231 v = nodetype(v) 

232 except BaseException as err: 

233 raise TypeError( 

234 f"Failed to convert nodes {u},{v} " f"to type {nodetype}." 

235 ) from err 

236 

237 if len(d) == 0 or data is False: 

238 # no data or data type specified 

239 edgedata = {} 

240 elif data is True: 

241 # no edge types specified 

242 try: # try to evaluate as dictionary 

243 edgedata = dict(literal_eval(" ".join(d))) 

244 except BaseException as err: 

245 raise TypeError( 

246 f"Failed to convert edge data ({d})" f"to dictionary." 

247 ) from err 

248 else: 

249 # convert edge data to dictionary with specified keys and type 

250 if len(d) != len(data): 

251 raise IndexError( 

252 f"Edge data {d} and data_keys {data} are not the same length" 

253 ) 

254 edgedata = {} 

255 for (edge_key, edge_type), edge_value in zip(data, d): 

256 try: 

257 edge_value = edge_type(edge_value) 

258 except BaseException as err: 

259 raise TypeError( 

260 f"Failed to convert {edge_key} data " 

261 f"{edge_value} to type {edge_type}." 

262 ) from err 

263 edgedata.update({edge_key: edge_value}) 

264 G.add_node(u, bipartite=0) 

265 G.add_node(v, bipartite=1) 

266 G.add_edge(u, v, **edgedata) 

267 return G 

268 

269 

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

271@nx._dispatch(name="bipartite_read_edgelist", graphs=None) 

272def read_edgelist( 

273 path, 

274 comments="#", 

275 delimiter=None, 

276 create_using=None, 

277 nodetype=None, 

278 data=True, 

279 edgetype=None, 

280 encoding="utf-8", 

281): 

282 """Read a bipartite graph from a list of edges. 

283 

284 Parameters 

285 ---------- 

286 path : file or string 

287 File or filename to read. If a file is provided, it must be 

288 opened in 'rb' mode. 

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

290 comments : string, optional 

291 The character used to indicate the start of a comment. 

292 delimiter : string, optional 

293 The string used to separate values. The default is whitespace. 

294 create_using : Graph container, optional, 

295 Use specified container to build graph. The default is networkx.Graph, 

296 an undirected graph. 

297 nodetype : int, float, str, Python type, optional 

298 Convert node data from strings to specified type 

299 data : bool or list of (label,type) tuples 

300 Tuples specifying dictionary key names and types for edge data 

301 edgetype : int, float, str, Python type, optional OBSOLETE 

302 Convert edge data from strings to specified type and use as 'weight' 

303 encoding: string, optional 

304 Specify which encoding to use when reading file. 

305 

306 Returns 

307 ------- 

308 G : graph 

309 A networkx Graph or other type specified with create_using 

310 

311 Examples 

312 -------- 

313 >>> from networkx.algorithms import bipartite 

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

315 >>> G.add_nodes_from([0, 2], bipartite=0) 

316 >>> G.add_nodes_from([1, 3], bipartite=1) 

317 >>> bipartite.write_edgelist(G, "test.edgelist") 

318 >>> G = bipartite.read_edgelist("test.edgelist") 

319 

320 >>> fh = open("test.edgelist", "rb") 

321 >>> G = bipartite.read_edgelist(fh) 

322 >>> fh.close() 

323 

324 >>> G = bipartite.read_edgelist("test.edgelist", nodetype=int) 

325 

326 Edgelist with data in a list: 

327 

328 >>> textline = "1 2 3" 

329 >>> fh = open("test.edgelist", "w") 

330 >>> d = fh.write(textline) 

331 >>> fh.close() 

332 >>> G = bipartite.read_edgelist( 

333 ... "test.edgelist", nodetype=int, data=(("weight", float),) 

334 ... ) 

335 >>> list(G) 

336 [1, 2] 

337 >>> list(G.edges(data=True)) 

338 [(1, 2, {'weight': 3.0})] 

339 

340 See parse_edgelist() for more examples of formatting. 

341 

342 See Also 

343 -------- 

344 parse_edgelist 

345 

346 Notes 

347 ----- 

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

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

350 """ 

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

352 return parse_edgelist( 

353 lines, 

354 comments=comments, 

355 delimiter=delimiter, 

356 create_using=create_using, 

357 nodetype=nodetype, 

358 data=data, 

359 )