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
« 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.
7Format
8------
9You can read or write three formats of edge lists with these functions.
11Node pairs with no data::
13 1 2
15Python dictionary as data::
17 1 2 {'weight':7, 'color':'green'}
19Arbitrary data::
21 1 2 7 green
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"]
27import networkx as nx
28from networkx.utils import not_implemented_for, open_file
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.
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.
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)
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"])
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))
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.
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
91 delimiter : string, optional
92 Separator for node labels
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.
99 Returns
100 -------
101 lines : string
102 Lines of data in adjlist format.
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
118 >>> for line in bipartite.generate_edgelist(G):
119 ... print(line)
120 0 1 {}
121 2 1 {'weight': 3}
122 2 3 {'capacity': 12}
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))
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.
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.
172 Returns
173 -------
174 G: NetworkX Graph
175 The bipartite graph corresponding to lines
177 Examples
178 --------
179 Edgelist with no data:
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)]
191 Edgelist with data in Python dictionary representation:
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})]
200 Edgelist with data in a list:
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})]
209 See Also
210 --------
211 """
212 from ast import literal_eval
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
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
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.
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.
306 Returns
307 -------
308 G : graph
309 A networkx Graph or other type specified with create_using
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")
320 >>> fh = open("test.edgelist", "rb")
321 >>> G = bipartite.read_edgelist(fh)
322 >>> fh.close()
324 >>> G = bipartite.read_edgelist("test.edgelist", nodetype=int)
326 Edgelist with data in a list:
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})]
340 See parse_edgelist() for more examples of formatting.
342 See Also
343 --------
344 parse_edgelist
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 )