Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/networkx/algorithms/bipartite/edgelist.py: 18%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

74 statements  

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 

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

27 

28import networkx as nx 

29from networkx.utils import not_implemented_for, open_file 

30 

31 

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

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

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

35 

36 Parameters 

37 ---------- 

38 G : Graph 

39 A NetworkX bipartite graph 

40 path : file or string 

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

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

43 comments : string, optional 

44 The character used to indicate the start of a comment 

45 delimiter : string, optional 

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

47 data : bool or list, optional 

48 If False write no edge data. 

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

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

51 in the list. 

52 encoding: string, optional 

53 Specify which encoding to use when writing file. 

54 

55 Examples 

56 -------- 

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

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

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

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

61 >>> fh = open("test.edgelist_open", "wb") 

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

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

64 >>> nx.write_edgelist(G, "test.edgelist_nodata.gz", data=False) 

65 

66 >>> G = nx.Graph() 

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

68 >>> nx.write_edgelist(G, "test.edgelist_bigger_nodata", data=False) 

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

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

71 

72 See Also 

73 -------- 

74 write_edgelist 

75 generate_edgelist 

76 """ 

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

78 line += "\n" 

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

80 

81 

82@not_implemented_for("directed") 

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

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

85 

86 Parameters 

87 ---------- 

88 G : NetworkX graph 

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

90 the two graph parts 

91 

92 delimiter : string, optional 

93 Separator for node labels 

94 

95 data : bool or list of keys 

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

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

98 values corresponding to the keys. 

99 

100 Returns 

101 ------- 

102 lines : string 

103 Lines of data in adjlist format. 

104 

105 Examples 

106 -------- 

107 >>> from networkx.algorithms import bipartite 

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

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

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

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

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

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

114 ... print(line) 

115 0 1 

116 2 1 

117 2 3 

118 

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

120 ... print(line) 

121 0 1 {} 

122 2 1 {'weight': 3} 

123 2 3 {'capacity': 12} 

124 

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

126 ... print(line) 

127 0 1 

128 2 1 3 

129 2 3 

130 """ 

131 try: 

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

133 except BaseException as err: 

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

135 if data is True or data is False: 

136 for n in part0: 

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

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

139 else: 

140 for n in part0: 

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

142 edge = [u, v] 

143 try: 

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

145 except KeyError: 

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

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

148 

149 

150@nx._dispatchable(name="bipartite_parse_edgelist", graphs=None, returns_graph=True) 

151def parse_edgelist( 

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

153): 

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

155 

156 Parameters 

157 ---------- 

158 lines : list or iterator of strings 

159 Input data in edgelist format 

160 comments : string, optional 

161 Marker for comment lines 

162 delimiter : string, optional 

163 Separator for node labels 

164 create_using: NetworkX graph container, optional 

165 Use given NetworkX graph for holding nodes or edges. 

166 nodetype : Python type, optional 

167 Convert nodes to this type. 

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

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

170 representation of edge data or a list tuples specifying dictionary 

171 key names and types for edge data. 

172 

173 Returns 

174 ------- 

175 G: NetworkX Graph 

176 The bipartite graph corresponding to lines 

177 

178 Examples 

179 -------- 

180 Edgelist with no data: 

181 

182 >>> from networkx.algorithms import bipartite 

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

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

185 >>> sorted(G.nodes()) 

186 [1, 2, 3, 4] 

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

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

189 >>> sorted(G.edges()) 

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

191 

192 Edgelist with data in Python dictionary representation: 

193 

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

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

196 >>> sorted(G.nodes()) 

197 [1, 2, 3, 4] 

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

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

200 

201 Edgelist with data in a list: 

202 

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

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

205 >>> sorted(G.nodes()) 

206 [1, 2, 3, 4] 

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

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

209 

210 See Also 

211 -------- 

212 """ 

213 from ast import literal_eval 

214 

215 G = nx.empty_graph(0, create_using) 

216 for line in lines: 

217 p = line.find(comments) 

218 if p >= 0: 

219 line = line[:p] 

220 if not len(line): 

221 continue 

222 # split line, should have 2 or more 

223 s = line.rstrip("\n").split(delimiter) 

224 if len(s) < 2: 

225 continue 

226 u = s.pop(0) 

227 v = s.pop(0) 

228 d = s 

229 if nodetype is not None: 

230 try: 

231 u = nodetype(u) 

232 v = nodetype(v) 

233 except BaseException as err: 

234 raise TypeError( 

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

236 ) from err 

237 

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

239 # no data or data type specified 

240 edgedata = {} 

241 elif data is True: 

242 # no edge types specified 

243 try: # try to evaluate as dictionary 

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

245 except BaseException as err: 

246 raise TypeError( 

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

248 ) from err 

249 else: 

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

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

252 raise IndexError( 

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

254 ) 

255 edgedata = {} 

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

257 try: 

258 edge_value = edge_type(edge_value) 

259 except BaseException as err: 

260 raise TypeError( 

261 f"Failed to convert {edge_key} data " 

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

263 ) from err 

264 edgedata.update({edge_key: edge_value}) 

265 G.add_node(u, bipartite=0) 

266 G.add_node(v, bipartite=1) 

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

268 return G 

269 

270 

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

272@nx._dispatchable(name="bipartite_read_edgelist", graphs=None, returns_graph=True) 

273def read_edgelist( 

274 path, 

275 comments="#", 

276 delimiter=None, 

277 create_using=None, 

278 nodetype=None, 

279 data=True, 

280 edgetype=None, 

281 encoding="utf-8", 

282): 

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

284 

285 Parameters 

286 ---------- 

287 path : file or string 

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

289 opened in 'rb' mode. 

290 Filenames ending in .gz or .bz2 will be decompressed. 

291 comments : string, optional 

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

293 delimiter : string, optional 

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

295 create_using : Graph container, optional, 

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

297 an undirected graph. 

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

299 Convert node data from strings to specified type 

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

301 Tuples specifying dictionary key names and types for edge data 

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

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

304 encoding: string, optional 

305 Specify which encoding to use when reading file. 

306 

307 Returns 

308 ------- 

309 G : graph 

310 A networkx Graph or other type specified with create_using 

311 

312 Examples 

313 -------- 

314 >>> from networkx.algorithms import bipartite 

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

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

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

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

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

320 

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

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

323 >>> fh.close() 

324 

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

326 

327 Edgelist with data in a list: 

328 

329 >>> textline = "1 2 3" 

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

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

332 >>> fh.close() 

333 >>> G = bipartite.read_edgelist( 

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

335 ... ) 

336 >>> list(G) 

337 [1, 2] 

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

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

340 

341 See parse_edgelist() for more examples of formatting. 

342 

343 See Also 

344 -------- 

345 parse_edgelist 

346 

347 Notes 

348 ----- 

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

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

351 """ 

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

353 return parse_edgelist( 

354 lines, 

355 comments=comments, 

356 delimiter=delimiter, 

357 create_using=create_using, 

358 nodetype=nodetype, 

359 data=data, 

360 )