Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/networkx/classes/multidigraph.py @ 1:56ad4e20f292 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
author | guerler |
---|---|
date | Fri, 31 Jul 2020 00:32:28 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:d30785e31577 | 1:56ad4e20f292 |
---|---|
1 # Copyright (C) 2004-2019 by | |
2 # Aric Hagberg <hagberg@lanl.gov> | |
3 # Dan Schult <dschult@colgate.edu> | |
4 # Pieter Swart <swart@lanl.gov> | |
5 # All rights reserved. | |
6 # BSD license. | |
7 # | |
8 # Authors: Aric Hagberg <hagberg@lanl.gov> | |
9 # Dan Schult <dschult@colgate.edu> | |
10 # Pieter Swart <swart@lanl.gov> | |
11 """Base class for MultiDiGraph.""" | |
12 from copy import deepcopy | |
13 | |
14 import networkx as nx | |
15 from networkx.classes.graph import Graph # for doctests | |
16 from networkx.classes.digraph import DiGraph | |
17 from networkx.classes.multigraph import MultiGraph | |
18 from networkx.classes.coreviews import MultiAdjacencyView | |
19 from networkx.classes.reportviews import OutMultiEdgeView, InMultiEdgeView, \ | |
20 DiMultiDegreeView, OutMultiDegreeView, InMultiDegreeView | |
21 from networkx.exception import NetworkXError | |
22 | |
23 | |
24 class MultiDiGraph(MultiGraph, DiGraph): | |
25 """A directed graph class that can store multiedges. | |
26 | |
27 Multiedges are multiple edges between two nodes. Each edge | |
28 can hold optional data or attributes. | |
29 | |
30 A MultiDiGraph holds directed edges. Self loops are allowed. | |
31 | |
32 Nodes can be arbitrary (hashable) Python objects with optional | |
33 key/value attributes. By convention `None` is not used as a node. | |
34 | |
35 Edges are represented as links between nodes with optional | |
36 key/value attributes. | |
37 | |
38 Parameters | |
39 ---------- | |
40 incoming_graph_data : input graph (optional, default: None) | |
41 Data to initialize graph. If None (default) an empty | |
42 graph is created. The data can be any format that is supported | |
43 by the to_networkx_graph() function, currently including edge list, | |
44 dict of dicts, dict of lists, NetworkX graph, NumPy matrix | |
45 or 2d ndarray, SciPy sparse matrix, or PyGraphviz graph. | |
46 | |
47 attr : keyword arguments, optional (default= no attributes) | |
48 Attributes to add to graph as key=value pairs. | |
49 | |
50 See Also | |
51 -------- | |
52 Graph | |
53 DiGraph | |
54 MultiGraph | |
55 OrderedMultiDiGraph | |
56 | |
57 Examples | |
58 -------- | |
59 Create an empty graph structure (a "null graph") with no nodes and | |
60 no edges. | |
61 | |
62 >>> G = nx.MultiDiGraph() | |
63 | |
64 G can be grown in several ways. | |
65 | |
66 **Nodes:** | |
67 | |
68 Add one node at a time: | |
69 | |
70 >>> G.add_node(1) | |
71 | |
72 Add the nodes from any container (a list, dict, set or | |
73 even the lines from a file or the nodes from another graph). | |
74 | |
75 >>> G.add_nodes_from([2, 3]) | |
76 >>> G.add_nodes_from(range(100, 110)) | |
77 >>> H = nx.path_graph(10) | |
78 >>> G.add_nodes_from(H) | |
79 | |
80 In addition to strings and integers any hashable Python object | |
81 (except None) can represent a node, e.g. a customized node object, | |
82 or even another Graph. | |
83 | |
84 >>> G.add_node(H) | |
85 | |
86 **Edges:** | |
87 | |
88 G can also be grown by adding edges. | |
89 | |
90 Add one edge, | |
91 | |
92 >>> key = G.add_edge(1, 2) | |
93 | |
94 a list of edges, | |
95 | |
96 >>> keys = G.add_edges_from([(1, 2), (1, 3)]) | |
97 | |
98 or a collection of edges, | |
99 | |
100 >>> keys = G.add_edges_from(H.edges) | |
101 | |
102 If some edges connect nodes not yet in the graph, the nodes | |
103 are added automatically. If an edge already exists, an additional | |
104 edge is created and stored using a key to identify the edge. | |
105 By default the key is the lowest unused integer. | |
106 | |
107 >>> keys = G.add_edges_from([(4,5,dict(route=282)), (4,5,dict(route=37))]) | |
108 >>> G[4] | |
109 AdjacencyView({5: {0: {}, 1: {'route': 282}, 2: {'route': 37}}}) | |
110 | |
111 **Attributes:** | |
112 | |
113 Each graph, node, and edge can hold key/value attribute pairs | |
114 in an associated attribute dictionary (the keys must be hashable). | |
115 By default these are empty, but can be added or changed using | |
116 add_edge, add_node or direct manipulation of the attribute | |
117 dictionaries named graph, node and edge respectively. | |
118 | |
119 >>> G = nx.MultiDiGraph(day="Friday") | |
120 >>> G.graph | |
121 {'day': 'Friday'} | |
122 | |
123 Add node attributes using add_node(), add_nodes_from() or G.nodes | |
124 | |
125 >>> G.add_node(1, time='5pm') | |
126 >>> G.add_nodes_from([3], time='2pm') | |
127 >>> G.nodes[1] | |
128 {'time': '5pm'} | |
129 >>> G.nodes[1]['room'] = 714 | |
130 >>> del G.nodes[1]['room'] # remove attribute | |
131 >>> list(G.nodes(data=True)) | |
132 [(1, {'time': '5pm'}), (3, {'time': '2pm'})] | |
133 | |
134 Add edge attributes using add_edge(), add_edges_from(), subscript | |
135 notation, or G.edges. | |
136 | |
137 >>> key = G.add_edge(1, 2, weight=4.7 ) | |
138 >>> keys = G.add_edges_from([(3, 4), (4, 5)], color='red') | |
139 >>> keys = G.add_edges_from([(1,2,{'color':'blue'}), (2,3,{'weight':8})]) | |
140 >>> G[1][2][0]['weight'] = 4.7 | |
141 >>> G.edges[1, 2, 0]['weight'] = 4 | |
142 | |
143 Warning: we protect the graph data structure by making `G.edges[1, 2]` a | |
144 read-only dict-like structure. However, you can assign to attributes | |
145 in e.g. `G.edges[1, 2]`. Thus, use 2 sets of brackets to add/change | |
146 data attributes: `G.edges[1, 2]['weight'] = 4` | |
147 (For multigraphs: `MG.edges[u, v, key][name] = value`). | |
148 | |
149 **Shortcuts:** | |
150 | |
151 Many common graph features allow python syntax to speed reporting. | |
152 | |
153 >>> 1 in G # check if node in graph | |
154 True | |
155 >>> [n for n in G if n<3] # iterate through nodes | |
156 [1, 2] | |
157 >>> len(G) # number of nodes in graph | |
158 5 | |
159 >>> G[1] # adjacency dict-like view keyed by neighbor to edge attributes | |
160 AdjacencyView({2: {0: {'weight': 4}, 1: {'color': 'blue'}}}) | |
161 | |
162 Often the best way to traverse all edges of a graph is via the neighbors. | |
163 The neighbors are available as an adjacency-view `G.adj` object or via | |
164 the method `G.adjacency()`. | |
165 | |
166 >>> for n, nbrsdict in G.adjacency(): | |
167 ... for nbr, keydict in nbrsdict.items(): | |
168 ... for key, eattr in keydict.items(): | |
169 ... if 'weight' in eattr: | |
170 ... # Do something useful with the edges | |
171 ... pass | |
172 | |
173 But the edges() method is often more convenient: | |
174 | |
175 >>> for u, v, keys, weight in G.edges(data='weight', keys=True): | |
176 ... if weight is not None: | |
177 ... # Do something useful with the edges | |
178 ... pass | |
179 | |
180 **Reporting:** | |
181 | |
182 Simple graph information is obtained using methods and object-attributes. | |
183 Reporting usually provides views instead of containers to reduce memory | |
184 usage. The views update as the graph is updated similarly to dict-views. | |
185 The objects `nodes, `edges` and `adj` provide access to data attributes | |
186 via lookup (e.g. `nodes[n], `edges[u, v]`, `adj[u][v]`) and iteration | |
187 (e.g. `nodes.items()`, `nodes.data('color')`, | |
188 `nodes.data('color', default='blue')` and similarly for `edges`) | |
189 Views exist for `nodes`, `edges`, `neighbors()`/`adj` and `degree`. | |
190 | |
191 For details on these and other miscellaneous methods, see below. | |
192 | |
193 **Subclasses (Advanced):** | |
194 | |
195 The MultiDiGraph class uses a dict-of-dict-of-dict-of-dict structure. | |
196 The outer dict (node_dict) holds adjacency information keyed by node. | |
197 The next dict (adjlist_dict) represents the adjacency information and holds | |
198 edge_key dicts keyed by neighbor. The edge_key dict holds each edge_attr | |
199 dict keyed by edge key. The inner dict (edge_attr_dict) represents | |
200 the edge data and holds edge attribute values keyed by attribute names. | |
201 | |
202 Each of these four dicts in the dict-of-dict-of-dict-of-dict | |
203 structure can be replaced by a user defined dict-like object. | |
204 In general, the dict-like features should be maintained but | |
205 extra features can be added. To replace one of the dicts create | |
206 a new graph class by changing the class(!) variable holding the | |
207 factory for that dict-like structure. The variable names are | |
208 node_dict_factory, node_attr_dict_factory, adjlist_inner_dict_factory, | |
209 adjlist_outer_dict_factory, edge_key_dict_factory, edge_attr_dict_factory | |
210 and graph_attr_dict_factory. | |
211 | |
212 node_dict_factory : function, (default: dict) | |
213 Factory function to be used to create the dict containing node | |
214 attributes, keyed by node id. | |
215 It should require no arguments and return a dict-like object | |
216 | |
217 node_attr_dict_factory: function, (default: dict) | |
218 Factory function to be used to create the node attribute | |
219 dict which holds attribute values keyed by attribute name. | |
220 It should require no arguments and return a dict-like object | |
221 | |
222 adjlist_outer_dict_factory : function, (default: dict) | |
223 Factory function to be used to create the outer-most dict | |
224 in the data structure that holds adjacency info keyed by node. | |
225 It should require no arguments and return a dict-like object. | |
226 | |
227 adjlist_inner_dict_factory : function, (default: dict) | |
228 Factory function to be used to create the adjacency list | |
229 dict which holds multiedge key dicts keyed by neighbor. | |
230 It should require no arguments and return a dict-like object. | |
231 | |
232 edge_key_dict_factory : function, (default: dict) | |
233 Factory function to be used to create the edge key dict | |
234 which holds edge data keyed by edge key. | |
235 It should require no arguments and return a dict-like object. | |
236 | |
237 edge_attr_dict_factory : function, (default: dict) | |
238 Factory function to be used to create the edge attribute | |
239 dict which holds attribute values keyed by attribute name. | |
240 It should require no arguments and return a dict-like object. | |
241 | |
242 graph_attr_dict_factory : function, (default: dict) | |
243 Factory function to be used to create the graph attribute | |
244 dict which holds attribute values keyed by attribute name. | |
245 It should require no arguments and return a dict-like object. | |
246 | |
247 Typically, if your extension doesn't impact the data structure all | |
248 methods will inherited without issue except: `to_directed/to_undirected`. | |
249 By default these methods create a DiGraph/Graph class and you probably | |
250 want them to create your extension of a DiGraph/Graph. To facilitate | |
251 this we define two class variables that you can set in your subclass. | |
252 | |
253 to_directed_class : callable, (default: DiGraph or MultiDiGraph) | |
254 Class to create a new graph structure in the `to_directed` method. | |
255 If `None`, a NetworkX class (DiGraph or MultiDiGraph) is used. | |
256 | |
257 to_undirected_class : callable, (default: Graph or MultiGraph) | |
258 Class to create a new graph structure in the `to_undirected` method. | |
259 If `None`, a NetworkX class (Graph or MultiGraph) is used. | |
260 | |
261 Examples | |
262 -------- | |
263 | |
264 Please see :mod:`~networkx.classes.ordered` for examples of | |
265 creating graph subclasses by overwriting the base class `dict` with | |
266 a dictionary-like object. | |
267 """ | |
268 # node_dict_factory = dict # already assigned in Graph | |
269 # adjlist_outer_dict_factory = dict | |
270 # adjlist_inner_dict_factory = dict | |
271 edge_key_dict_factory = dict | |
272 # edge_attr_dict_factory = dict | |
273 | |
274 def __init__(self, incoming_graph_data=None, **attr): | |
275 """Initialize a graph with edges, name, or graph attributes. | |
276 | |
277 Parameters | |
278 ---------- | |
279 incoming_graph_data : input graph | |
280 Data to initialize graph. If incoming_graph_data=None (default) | |
281 an empty graph is created. The data can be an edge list, or any | |
282 NetworkX graph object. If the corresponding optional Python | |
283 packages are installed the data can also be a NumPy matrix | |
284 or 2d ndarray, a SciPy sparse matrix, or a PyGraphviz graph. | |
285 | |
286 attr : keyword arguments, optional (default= no attributes) | |
287 Attributes to add to graph as key=value pairs. | |
288 | |
289 See Also | |
290 -------- | |
291 convert | |
292 | |
293 Examples | |
294 -------- | |
295 >>> G = nx.Graph() # or DiGraph, MultiGraph, MultiDiGraph, etc | |
296 >>> G = nx.Graph(name='my graph') | |
297 >>> e = [(1, 2), (2, 3), (3, 4)] # list of edges | |
298 >>> G = nx.Graph(e) | |
299 | |
300 Arbitrary graph attribute pairs (key=value) may be assigned | |
301 | |
302 >>> G = nx.Graph(e, day="Friday") | |
303 >>> G.graph | |
304 {'day': 'Friday'} | |
305 | |
306 """ | |
307 self.edge_key_dict_factory = self.edge_key_dict_factory | |
308 DiGraph.__init__(self, incoming_graph_data, **attr) | |
309 | |
310 @property | |
311 def adj(self): | |
312 """Graph adjacency object holding the neighbors of each node. | |
313 | |
314 This object is a read-only dict-like structure with node keys | |
315 and neighbor-dict values. The neighbor-dict is keyed by neighbor | |
316 to the edgekey-dict. So `G.adj[3][2][0]['color'] = 'blue'` sets | |
317 the color of the edge `(3, 2, 0)` to `"blue"`. | |
318 | |
319 Iterating over G.adj behaves like a dict. Useful idioms include | |
320 `for nbr, datadict in G.adj[n].items():`. | |
321 | |
322 The neighbor information is also provided by subscripting the graph. | |
323 So `for nbr, foovalue in G[node].data('foo', default=1):` works. | |
324 | |
325 For directed graphs, `G.adj` holds outgoing (successor) info. | |
326 """ | |
327 return MultiAdjacencyView(self._succ) | |
328 | |
329 @property | |
330 def succ(self): | |
331 """Graph adjacency object holding the successors of each node. | |
332 | |
333 This object is a read-only dict-like structure with node keys | |
334 and neighbor-dict values. The neighbor-dict is keyed by neighbor | |
335 to the edgekey-dict. So `G.adj[3][2][0]['color'] = 'blue'` sets | |
336 the color of the edge `(3, 2, 0)` to `"blue"`. | |
337 | |
338 Iterating over G.adj behaves like a dict. Useful idioms include | |
339 `for nbr, datadict in G.adj[n].items():`. | |
340 | |
341 The neighbor information is also provided by subscripting the graph. | |
342 So `for nbr, foovalue in G[node].data('foo', default=1):` works. | |
343 | |
344 For directed graphs, `G.succ` is identical to `G.adj`. | |
345 """ | |
346 return MultiAdjacencyView(self._succ) | |
347 | |
348 @property | |
349 def pred(self): | |
350 """Graph adjacency object holding the predecessors of each node. | |
351 | |
352 This object is a read-only dict-like structure with node keys | |
353 and neighbor-dict values. The neighbor-dict is keyed by neighbor | |
354 to the edgekey-dict. So `G.adj[3][2][0]['color'] = 'blue'` sets | |
355 the color of the edge `(3, 2, 0)` to `"blue"`. | |
356 | |
357 Iterating over G.adj behaves like a dict. Useful idioms include | |
358 `for nbr, datadict in G.adj[n].items():`. | |
359 """ | |
360 return MultiAdjacencyView(self._pred) | |
361 | |
362 def add_edge(self, u_for_edge, v_for_edge, key=None, **attr): | |
363 """Add an edge between u and v. | |
364 | |
365 The nodes u and v will be automatically added if they are | |
366 not already in the graph. | |
367 | |
368 Edge attributes can be specified with keywords or by directly | |
369 accessing the edge's attribute dictionary. See examples below. | |
370 | |
371 Parameters | |
372 ---------- | |
373 u_for_edge, v_for_edge : nodes | |
374 Nodes can be, for example, strings or numbers. | |
375 Nodes must be hashable (and not None) Python objects. | |
376 key : hashable identifier, optional (default=lowest unused integer) | |
377 Used to distinguish multiedges between a pair of nodes. | |
378 attr_dict : dictionary, optional (default= no attributes) | |
379 Dictionary of edge attributes. Key/value pairs will | |
380 update existing data associated with the edge. | |
381 attr : keyword arguments, optional | |
382 Edge data (or labels or objects) can be assigned using | |
383 keyword arguments. | |
384 | |
385 Returns | |
386 ------- | |
387 The edge key assigned to the edge. | |
388 | |
389 See Also | |
390 -------- | |
391 add_edges_from : add a collection of edges | |
392 | |
393 Notes | |
394 ----- | |
395 To replace/update edge data, use the optional key argument | |
396 to identify a unique edge. Otherwise a new edge will be created. | |
397 | |
398 NetworkX algorithms designed for weighted graphs cannot use | |
399 multigraphs directly because it is not clear how to handle | |
400 multiedge weights. Convert to Graph using edge attribute | |
401 'weight' to enable weighted graph algorithms. | |
402 | |
403 Default keys are generated using the method `new_edge_key()`. | |
404 This method can be overridden by subclassing the base class and | |
405 providing a custom `new_edge_key()` method. | |
406 | |
407 Examples | |
408 -------- | |
409 The following all add the edge e=(1, 2) to graph G: | |
410 | |
411 >>> G = nx.MultiDiGraph() | |
412 >>> e = (1, 2) | |
413 >>> key = G.add_edge(1, 2) # explicit two-node form | |
414 >>> G.add_edge(*e) # single edge as tuple of two nodes | |
415 1 | |
416 >>> G.add_edges_from( [(1, 2)] ) # add edges from iterable container | |
417 [2] | |
418 | |
419 Associate data to edges using keywords: | |
420 | |
421 >>> key = G.add_edge(1, 2, weight=3) | |
422 >>> key = G.add_edge(1, 2, key=0, weight=4) # update data for key=0 | |
423 >>> key = G.add_edge(1, 3, weight=7, capacity=15, length=342.7) | |
424 | |
425 For non-string attribute keys, use subscript notation. | |
426 | |
427 >>> ekey = G.add_edge(1, 2) | |
428 >>> G[1][2][0].update({0: 5}) | |
429 >>> G.edges[1, 2, 0].update({0: 5}) | |
430 """ | |
431 u, v = u_for_edge, v_for_edge | |
432 # add nodes | |
433 if u not in self._succ: | |
434 self._succ[u] = self.adjlist_inner_dict_factory() | |
435 self._pred[u] = self.adjlist_inner_dict_factory() | |
436 self._node[u] = self.node_attr_dict_factory() | |
437 if v not in self._succ: | |
438 self._succ[v] = self.adjlist_inner_dict_factory() | |
439 self._pred[v] = self.adjlist_inner_dict_factory() | |
440 self._node[v] = self.node_attr_dict_factory() | |
441 if key is None: | |
442 key = self.new_edge_key(u, v) | |
443 if v in self._succ[u]: | |
444 keydict = self._adj[u][v] | |
445 datadict = keydict.get(key, self.edge_key_dict_factory()) | |
446 datadict.update(attr) | |
447 keydict[key] = datadict | |
448 else: | |
449 # selfloops work this way without special treatment | |
450 datadict = self.edge_attr_dict_factory() | |
451 datadict.update(attr) | |
452 keydict = self.edge_key_dict_factory() | |
453 keydict[key] = datadict | |
454 self._succ[u][v] = keydict | |
455 self._pred[v][u] = keydict | |
456 return key | |
457 | |
458 def remove_edge(self, u, v, key=None): | |
459 """Remove an edge between u and v. | |
460 | |
461 Parameters | |
462 ---------- | |
463 u, v : nodes | |
464 Remove an edge between nodes u and v. | |
465 key : hashable identifier, optional (default=None) | |
466 Used to distinguish multiple edges between a pair of nodes. | |
467 If None remove a single (arbitrary) edge between u and v. | |
468 | |
469 Raises | |
470 ------ | |
471 NetworkXError | |
472 If there is not an edge between u and v, or | |
473 if there is no edge with the specified key. | |
474 | |
475 See Also | |
476 -------- | |
477 remove_edges_from : remove a collection of edges | |
478 | |
479 Examples | |
480 -------- | |
481 >>> G = nx.MultiDiGraph() | |
482 >>> nx.add_path(G, [0, 1, 2, 3]) | |
483 >>> G.remove_edge(0, 1) | |
484 >>> e = (1, 2) | |
485 >>> G.remove_edge(*e) # unpacks e from an edge tuple | |
486 | |
487 For multiple edges | |
488 | |
489 >>> G = nx.MultiDiGraph() | |
490 >>> G.add_edges_from([(1, 2), (1, 2), (1, 2)]) # key_list returned | |
491 [0, 1, 2] | |
492 >>> G.remove_edge(1, 2) # remove a single (arbitrary) edge | |
493 | |
494 For edges with keys | |
495 | |
496 >>> G = nx.MultiDiGraph() | |
497 >>> G.add_edge(1, 2, key='first') | |
498 'first' | |
499 >>> G.add_edge(1, 2, key='second') | |
500 'second' | |
501 >>> G.remove_edge(1, 2, key='second') | |
502 | |
503 """ | |
504 try: | |
505 d = self._adj[u][v] | |
506 except KeyError: | |
507 raise NetworkXError( | |
508 "The edge %s-%s is not in the graph." % (u, v)) | |
509 # remove the edge with specified data | |
510 if key is None: | |
511 d.popitem() | |
512 else: | |
513 try: | |
514 del d[key] | |
515 except KeyError: | |
516 msg = "The edge %s-%s with key %s is not in the graph." | |
517 raise NetworkXError(msg % (u, v, key)) | |
518 if len(d) == 0: | |
519 # remove the key entries if last edge | |
520 del self._succ[u][v] | |
521 del self._pred[v][u] | |
522 | |
523 @property | |
524 def edges(self): | |
525 """An OutMultiEdgeView of the Graph as G.edges or G.edges(). | |
526 | |
527 edges(self, nbunch=None, data=False, keys=False, default=None) | |
528 | |
529 The OutMultiEdgeView provides set-like operations on the edge-tuples | |
530 as well as edge attribute lookup. When called, it also provides | |
531 an EdgeDataView object which allows control of access to edge | |
532 attributes (but does not provide set-like operations). | |
533 Hence, `G.edges[u, v]['color']` provides the value of the color | |
534 attribute for edge `(u, v)` while | |
535 `for (u, v, c) in G.edges(data='color', default='red'):` | |
536 iterates through all the edges yielding the color attribute | |
537 with default `'red'` if no color attribute exists. | |
538 | |
539 Edges are returned as tuples with optional data and keys | |
540 in the order (node, neighbor, key, data). | |
541 | |
542 Parameters | |
543 ---------- | |
544 nbunch : single node, container, or all nodes (default= all nodes) | |
545 The view will only report edges incident to these nodes. | |
546 data : string or bool, optional (default=False) | |
547 The edge attribute returned in 3-tuple (u, v, ddict[data]). | |
548 If True, return edge attribute dict in 3-tuple (u, v, ddict). | |
549 If False, return 2-tuple (u, v). | |
550 keys : bool, optional (default=False) | |
551 If True, return edge keys with each edge. | |
552 default : value, optional (default=None) | |
553 Value used for edges that don't have the requested attribute. | |
554 Only relevant if data is not True or False. | |
555 | |
556 Returns | |
557 ------- | |
558 edges : EdgeView | |
559 A view of edge attributes, usually it iterates over (u, v) | |
560 (u, v, k) or (u, v, k, d) tuples of edges, but can also be | |
561 used for attribute lookup as `edges[u, v, k]['foo']`. | |
562 | |
563 Notes | |
564 ----- | |
565 Nodes in nbunch that are not in the graph will be (quietly) ignored. | |
566 For directed graphs this returns the out-edges. | |
567 | |
568 Examples | |
569 -------- | |
570 >>> G = nx.MultiDiGraph() | |
571 >>> nx.add_path(G, [0, 1, 2]) | |
572 >>> key = G.add_edge(2, 3, weight=5) | |
573 >>> [e for e in G.edges()] | |
574 [(0, 1), (1, 2), (2, 3)] | |
575 >>> list(G.edges(data=True)) # default data is {} (empty dict) | |
576 [(0, 1, {}), (1, 2, {}), (2, 3, {'weight': 5})] | |
577 >>> list(G.edges(data='weight', default=1)) | |
578 [(0, 1, 1), (1, 2, 1), (2, 3, 5)] | |
579 >>> list(G.edges(keys=True)) # default keys are integers | |
580 [(0, 1, 0), (1, 2, 0), (2, 3, 0)] | |
581 >>> list(G.edges(data=True, keys=True)) | |
582 [(0, 1, 0, {}), (1, 2, 0, {}), (2, 3, 0, {'weight': 5})] | |
583 >>> list(G.edges(data='weight', default=1, keys=True)) | |
584 [(0, 1, 0, 1), (1, 2, 0, 1), (2, 3, 0, 5)] | |
585 >>> list(G.edges([0, 2])) | |
586 [(0, 1), (2, 3)] | |
587 >>> list(G.edges(0)) | |
588 [(0, 1)] | |
589 | |
590 See Also | |
591 -------- | |
592 in_edges, out_edges | |
593 """ | |
594 return OutMultiEdgeView(self) | |
595 | |
596 # alias out_edges to edges | |
597 out_edges = edges | |
598 | |
599 @property | |
600 def in_edges(self): | |
601 """An InMultiEdgeView of the Graph as G.in_edges or G.in_edges(). | |
602 | |
603 in_edges(self, nbunch=None, data=False, keys=False, default=None) | |
604 | |
605 Parameters | |
606 ---------- | |
607 nbunch : single node, container, or all nodes (default= all nodes) | |
608 The view will only report edges incident to these nodes. | |
609 data : string or bool, optional (default=False) | |
610 The edge attribute returned in 3-tuple (u, v, ddict[data]). | |
611 If True, return edge attribute dict in 3-tuple (u, v, ddict). | |
612 If False, return 2-tuple (u, v). | |
613 keys : bool, optional (default=False) | |
614 If True, return edge keys with each edge. | |
615 default : value, optional (default=None) | |
616 Value used for edges that don't have the requested attribute. | |
617 Only relevant if data is not True or False. | |
618 | |
619 Returns | |
620 ------- | |
621 in_edges : InMultiEdgeView | |
622 A view of edge attributes, usually it iterates over (u, v) | |
623 or (u, v, k) or (u, v, k, d) tuples of edges, but can also be | |
624 used for attribute lookup as `edges[u, v, k]['foo']`. | |
625 | |
626 See Also | |
627 -------- | |
628 edges | |
629 """ | |
630 return InMultiEdgeView(self) | |
631 | |
632 @property | |
633 def degree(self): | |
634 """A DegreeView for the Graph as G.degree or G.degree(). | |
635 | |
636 The node degree is the number of edges adjacent to the node. | |
637 The weighted node degree is the sum of the edge weights for | |
638 edges incident to that node. | |
639 | |
640 This object provides an iterator for (node, degree) as well as | |
641 lookup for the degree for a single node. | |
642 | |
643 Parameters | |
644 ---------- | |
645 nbunch : single node, container, or all nodes (default= all nodes) | |
646 The view will only report edges incident to these nodes. | |
647 | |
648 weight : string or None, optional (default=None) | |
649 The name of an edge attribute that holds the numerical value used | |
650 as a weight. If None, then each edge has weight 1. | |
651 The degree is the sum of the edge weights adjacent to the node. | |
652 | |
653 Returns | |
654 ------- | |
655 If a single nodes is requested | |
656 deg : int | |
657 Degree of the node | |
658 | |
659 OR if multiple nodes are requested | |
660 nd_iter : iterator | |
661 The iterator returns two-tuples of (node, degree). | |
662 | |
663 See Also | |
664 -------- | |
665 out_degree, in_degree | |
666 | |
667 Examples | |
668 -------- | |
669 >>> G = nx.MultiDiGraph() | |
670 >>> nx.add_path(G, [0, 1, 2, 3]) | |
671 >>> G.degree(0) # node 0 with degree 1 | |
672 1 | |
673 >>> list(G.degree([0, 1, 2])) | |
674 [(0, 1), (1, 2), (2, 2)] | |
675 | |
676 """ | |
677 return DiMultiDegreeView(self) | |
678 | |
679 @property | |
680 def in_degree(self): | |
681 """A DegreeView for (node, in_degree) or in_degree for single node. | |
682 | |
683 The node in-degree is the number of edges pointing in to the node. | |
684 The weighted node degree is the sum of the edge weights for | |
685 edges incident to that node. | |
686 | |
687 This object provides an iterator for (node, degree) as well as | |
688 lookup for the degree for a single node. | |
689 | |
690 Parameters | |
691 ---------- | |
692 nbunch : single node, container, or all nodes (default= all nodes) | |
693 The view will only report edges incident to these nodes. | |
694 | |
695 weight : string or None, optional (default=None) | |
696 The edge attribute that holds the numerical value used | |
697 as a weight. If None, then each edge has weight 1. | |
698 The degree is the sum of the edge weights adjacent to the node. | |
699 | |
700 Returns | |
701 ------- | |
702 If a single node is requested | |
703 deg : int | |
704 Degree of the node | |
705 | |
706 OR if multiple nodes are requested | |
707 nd_iter : iterator | |
708 The iterator returns two-tuples of (node, in-degree). | |
709 | |
710 See Also | |
711 -------- | |
712 degree, out_degree | |
713 | |
714 Examples | |
715 -------- | |
716 >>> G = nx.MultiDiGraph() | |
717 >>> nx.add_path(G, [0, 1, 2, 3]) | |
718 >>> G.in_degree(0) # node 0 with degree 0 | |
719 0 | |
720 >>> list(G.in_degree([0, 1, 2])) | |
721 [(0, 0), (1, 1), (2, 1)] | |
722 | |
723 """ | |
724 return InMultiDegreeView(self) | |
725 | |
726 @property | |
727 def out_degree(self): | |
728 """Returns an iterator for (node, out-degree) or out-degree for single node. | |
729 | |
730 out_degree(self, nbunch=None, weight=None) | |
731 | |
732 The node out-degree is the number of edges pointing out of the node. | |
733 This function returns the out-degree for a single node or an iterator | |
734 for a bunch of nodes or if nothing is passed as argument. | |
735 | |
736 Parameters | |
737 ---------- | |
738 nbunch : single node, container, or all nodes (default= all nodes) | |
739 The view will only report edges incident to these nodes. | |
740 | |
741 weight : string or None, optional (default=None) | |
742 The edge attribute that holds the numerical value used | |
743 as a weight. If None, then each edge has weight 1. | |
744 The degree is the sum of the edge weights. | |
745 | |
746 Returns | |
747 ------- | |
748 If a single node is requested | |
749 deg : int | |
750 Degree of the node | |
751 | |
752 OR if multiple nodes are requested | |
753 nd_iter : iterator | |
754 The iterator returns two-tuples of (node, out-degree). | |
755 | |
756 See Also | |
757 -------- | |
758 degree, in_degree | |
759 | |
760 Examples | |
761 -------- | |
762 >>> G = nx.MultiDiGraph() | |
763 >>> nx.add_path(G, [0, 1, 2, 3]) | |
764 >>> G.out_degree(0) # node 0 with degree 1 | |
765 1 | |
766 >>> list(G.out_degree([0, 1, 2])) | |
767 [(0, 1), (1, 1), (2, 1)] | |
768 | |
769 """ | |
770 return OutMultiDegreeView(self) | |
771 | |
772 def is_multigraph(self): | |
773 """Returns True if graph is a multigraph, False otherwise.""" | |
774 return True | |
775 | |
776 def is_directed(self): | |
777 """Returns True if graph is directed, False otherwise.""" | |
778 return True | |
779 | |
780 def to_undirected(self, reciprocal=False, as_view=False): | |
781 """Returns an undirected representation of the digraph. | |
782 | |
783 Parameters | |
784 ---------- | |
785 reciprocal : bool (optional) | |
786 If True only keep edges that appear in both directions | |
787 in the original digraph. | |
788 as_view : bool (optional, default=False) | |
789 If True return an undirected view of the original directed graph. | |
790 | |
791 Returns | |
792 ------- | |
793 G : MultiGraph | |
794 An undirected graph with the same name and nodes and | |
795 with edge (u, v, data) if either (u, v, data) or (v, u, data) | |
796 is in the digraph. If both edges exist in digraph and | |
797 their edge data is different, only one edge is created | |
798 with an arbitrary choice of which edge data to use. | |
799 You must check and correct for this manually if desired. | |
800 | |
801 See Also | |
802 -------- | |
803 MultiGraph, copy, add_edge, add_edges_from | |
804 | |
805 Notes | |
806 ----- | |
807 This returns a "deepcopy" of the edge, node, and | |
808 graph attributes which attempts to completely copy | |
809 all of the data and references. | |
810 | |
811 This is in contrast to the similar D=MultiiGraph(G) which | |
812 returns a shallow copy of the data. | |
813 | |
814 See the Python copy module for more information on shallow | |
815 and deep copies, https://docs.python.org/2/library/copy.html. | |
816 | |
817 Warning: If you have subclassed MultiDiGraph to use dict-like | |
818 objects in the data structure, those changes do not transfer | |
819 to the MultiGraph created by this method. | |
820 | |
821 Examples | |
822 -------- | |
823 >>> G = nx.path_graph(2) # or MultiGraph, etc | |
824 >>> H = G.to_directed() | |
825 >>> list(H.edges) | |
826 [(0, 1), (1, 0)] | |
827 >>> G2 = H.to_undirected() | |
828 >>> list(G2.edges) | |
829 [(0, 1)] | |
830 """ | |
831 graph_class = self.to_undirected_class() | |
832 if as_view is True: | |
833 return nx.graphviews.generic_graph_view(self, graph_class) | |
834 # deepcopy when not a view | |
835 G = graph_class() | |
836 G.graph.update(deepcopy(self.graph)) | |
837 G.add_nodes_from((n, deepcopy(d)) for n, d in self._node.items()) | |
838 if reciprocal is True: | |
839 G.add_edges_from((u, v, key, deepcopy(data)) | |
840 for u, nbrs in self._adj.items() | |
841 for v, keydict in nbrs.items() | |
842 for key, data in keydict.items() | |
843 if v in self._pred[u] and key in self._pred[u][v]) | |
844 else: | |
845 G.add_edges_from((u, v, key, deepcopy(data)) | |
846 for u, nbrs in self._adj.items() | |
847 for v, keydict in nbrs.items() | |
848 for key, data in keydict.items()) | |
849 return G | |
850 | |
851 def reverse(self, copy=True): | |
852 """Returns the reverse of the graph. | |
853 | |
854 The reverse is a graph with the same nodes and edges | |
855 but with the directions of the edges reversed. | |
856 | |
857 Parameters | |
858 ---------- | |
859 copy : bool optional (default=True) | |
860 If True, return a new DiGraph holding the reversed edges. | |
861 If False, the reverse graph is created using a view of | |
862 the original graph. | |
863 """ | |
864 if copy: | |
865 H = self.__class__() | |
866 H.graph.update(deepcopy(self.graph)) | |
867 H.add_nodes_from((n, deepcopy(d)) for n, d in self._node.items()) | |
868 H.add_edges_from((v, u, k, deepcopy(d)) for u, v, k, d | |
869 in self.edges(keys=True, data=True)) | |
870 return H | |
871 return nx.graphviews.reverse_view(self) |