MultiGraph—Undirected graphs with self loops and parallel edges¶
Overview¶
-
class
MultiGraph
(incoming_graph_data=None, **attr)[source]¶ An undirected graph class that can store multiedges.
Multiedges are multiple edges between two nodes. Each edge can hold optional data or attributes.
A MultiGraph holds undirected edges. Self loops are allowed.
Nodes can be arbitrary (hashable) Python objects with optional key/value attributes. By convention
None
is not used as a node.Edges are represented as links between nodes with optional key/value attributes.
Parameters: - incoming_graph_data (input graph (optional, default: None)) – Data to initialize graph. If None (default) an empty graph is created. The data can be any format that is supported by the to_networkx_graph() function, currently including edge list, dict of dicts, dict of lists, NetworkX graph, NumPy matrix or 2d ndarray, SciPy sparse matrix, or PyGraphviz graph.
- attr (keyword arguments, optional (default= no attributes)) – Attributes to add to graph as key=value pairs.
See also
Examples
Create an empty graph structure (a “null graph”) with no nodes and no edges.
>>> G = nx.MultiGraph()
G can be grown in several ways.
Nodes:
Add one node at a time:
>>> G.add_node(1)
Add the nodes from any container (a list, dict, set or even the lines from a file or the nodes from another graph).
>>> G.add_nodes_from([2, 3]) >>> G.add_nodes_from(range(100, 110)) >>> H = nx.path_graph(10) >>> G.add_nodes_from(H)
In addition to strings and integers any hashable Python object (except None) can represent a node, e.g. a customized node object, or even another Graph.
>>> G.add_node(H)
Edges:
G can also be grown by adding edges.
Add one edge,
>>> key = G.add_edge(1, 2)
a list of edges,
>>> keys = G.add_edges_from([(1, 2), (1, 3)])
or a collection of edges,
>>> keys = G.add_edges_from(H.edges)
If some edges connect nodes not yet in the graph, the nodes are added automatically. If an edge already exists, an additional edge is created and stored using a key to identify the edge. By default the key is the lowest unused integer.
>>> keys = G.add_edges_from([(4,5,{'route':28}), (4,5,{'route':37})]) >>> G[4] AdjacencyView({3: {0: {}}, 5: {0: {}, 1: {'route': 28}, 2: {'route': 37}}})
Attributes:
Each graph, node, and edge can hold key/value attribute pairs in an associated attribute dictionary (the keys must be hashable). By default these are empty, but can be added or changed using add_edge, add_node or direct manipulation of the attribute dictionaries named graph, node and edge respectively.
>>> G = nx.MultiGraph(day="Friday") >>> G.graph {'day': 'Friday'}
Add node attributes using add_node(), add_nodes_from() or G.nodes
>>> G.add_node(1, time='5pm') >>> G.add_nodes_from([3], time='2pm') >>> G.nodes[1] {'time': '5pm'} >>> G.nodes[1]['room'] = 714 >>> del G.nodes[1]['room'] # remove attribute >>> list(G.nodes(data=True)) [(1, {'time': '5pm'}), (3, {'time': '2pm'})]
Add edge attributes using add_edge(), add_edges_from(), subscript notation, or G.edges.
>>> key = G.add_edge(1, 2, weight=4.7 ) >>> keys = G.add_edges_from([(3, 4), (4, 5)], color='red') >>> keys = G.add_edges_from([(1,2,{'color':'blue'}), (2,3,{'weight':8})]) >>> G[1][2][0]['weight'] = 4.7 >>> G.edges[1, 2, 0]['weight'] = 4
Warning: we protect the graph data structure by making
G.edges[1, 2]
a read-only dict-like structure. However, you can assign to attributes in e.g.G.edges[1, 2]
. Thus, use 2 sets of brackets to add/change data attributes:G.edges[1, 2]['weight'] = 4
(For multigraphs:MG.edges[u, v, key][name] = value
).Shortcuts:
Many common graph features allow python syntax to speed reporting.
>>> 1 in G # check if node in graph True >>> [n for n in G if n<3] # iterate through nodes [1, 2] >>> len(G) # number of nodes in graph 5 >>> G[1] # adjacency dict-like view keyed by neighbor to edge attributes AdjacencyView({2: {0: {'weight': 4}, 1: {'color': 'blue'}}})
Often the best way to traverse all edges of a graph is via the neighbors. The neighbors are reported as an adjacency-dict
G.adj
orG.adjacency()
.>>> for n, nbrsdict in G.adjacency(): ... for nbr, keydict in nbrsdict.items(): ... for key, eattr in keydict.items(): ... if 'weight' in eattr: ... # Do something useful with the edges ... pass
But the edges() method is often more convenient:
>>> for u, v, keys, weight in G.edges(data='weight', keys=True): ... if weight is not None: ... # Do something useful with the edges ... pass
Reporting:
Simple graph information is obtained using methods and object-attributes. Reporting usually provides views instead of containers to reduce memory usage. The views update as the graph is updated similarly to dict-views. The objects
nodes, `edges
andadj
provide access to data attributes via lookup (e.g.nodes[n], `edges[u, v]
,adj[u][v]
) and iteration (e.g.nodes.items()
,nodes.data('color')
,nodes.data('color', default='blue')
and similarly foredges
) Views exist fornodes
,edges
,neighbors()
/adj
anddegree
.For details on these and other miscellaneous methods, see below.
Subclasses (Advanced):
The MultiGraph class uses a dict-of-dict-of-dict-of-dict data structure. The outer dict (node_dict) holds adjacency information keyed by node. The next dict (adjlist_dict) represents the adjacency information and holds edge_key dicts keyed by neighbor. The edge_key dict holds each edge_attr dict keyed by edge key. The inner dict (edge_attr_dict) represents the edge data and holds edge attribute values keyed by attribute names.
Each of these four dicts in the dict-of-dict-of-dict-of-dict structure can be replaced by a user defined dict-like object. In general, the dict-like features should be maintained but extra features can be added. To replace one of the dicts create a new graph class by changing the class(!) variable holding the factory for that dict-like structure. The variable names are node_dict_factory, adjlist_inner_dict_factory, adjlist_outer_dict_factory, and edge_attr_dict_factory.
- node_dict_factory : function, (default: dict)
- Factory function to be used to create the dict containing node attributes, keyed by node id. It should require no arguments and return a dict-like object
- adjlist_outer_dict_factory : function, (default: dict)
- Factory function to be used to create the outer-most dict in the data structure that holds adjacency info keyed by node. It should require no arguments and return a dict-like object.
- adjlist_inner_dict_factory : function, (default: dict)
- Factory function to be used to create the adjacency list dict which holds multiedge key dicts keyed by neighbor. It should require no arguments and return a dict-like object.
- edge_key_dict_factory : function, (default: dict)
- Factory function to be used to create the edge key dict which holds edge data keyed by edge key. It should require no arguments and return a dict-like object.
- edge_attr_dict_factory : function, (default: dict)
- Factory function to be used to create the edge attribute dict which holds attrbute values keyed by attribute name. It should require no arguments and return a dict-like object.
Typically, if your extension doesn’t impact the data structure all methods will inherited without issue except:
to_directed/to_undirected
. By default these methods create a DiGraph/Graph class and you probably want them to create your extension of a DiGraph/Graph. To facilitate this we define two class variables that you can set in your subclass.- to_directed_class : callable, (default: DiGraph or MultiDiGraph)
- Class to create a new graph structure in the
to_directed
method. IfNone
, a NetworkX class (DiGraph or MultiDiGraph) is used. - to_undirected_class : callable, (default: Graph or MultiGraph)
- Class to create a new graph structure in the
to_undirected
method. IfNone
, a NetworkX class (Graph or MultiGraph) is used.
Examples
Please see
ordered
for examples of creating graph subclasses by overwriting the base classdict
with a dictionary-like object.
Methods¶
Adding and removing nodes and edges¶
MultiGraph.__init__ ([incoming_graph_data]) |
Initialize a graph with edges, name, or graph attributes. |
MultiGraph.add_node (node_for_adding, **attr) |
Add a single node node_for_adding and update node attributes. |
MultiGraph.add_nodes_from (nodes_for_adding, …) |
Add multiple nodes. |
MultiGraph.remove_node (n) |
Remove node n. |
MultiGraph.remove_nodes_from (nodes) |
Remove multiple nodes. |
MultiGraph.add_edge (u_for_edge, v_for_edge) |
Add an edge between u and v. |
MultiGraph.add_edges_from (ebunch_to_add, **attr) |
Add all the edges in ebunch_to_add. |
MultiGraph.add_weighted_edges_from (ebunch_to_add) |
Add weighted edges in ebunch_to_add with specified weight attr |
MultiGraph.new_edge_key (u, v) |
Return an unused key for edges between nodes u and v . |
MultiGraph.remove_edge (u, v[, key]) |
Remove an edge between u and v. |
MultiGraph.remove_edges_from (ebunch) |
Remove all edges specified in ebunch. |
MultiGraph.update ([edges, nodes]) |
Update the graph using nodes/edges/graphs as input. |
MultiGraph.clear () |
Remove all nodes and edges from the graph. |
Reporting nodes edges and neighbors¶
MultiGraph.nodes |
A NodeView of the Graph as G.nodes or G.nodes(). |
MultiGraph.__iter__ () |
Iterate over the nodes. |
MultiGraph.has_node (n) |
Return True if the graph contains the node n. |
MultiGraph.__contains__ (n) |
Return True if n is a node, False otherwise. |
MultiGraph.edges |
Return an iterator over the edges. |
MultiGraph.has_edge (u, v[, key]) |
Return True if the graph has an edge between nodes u and v. |
MultiGraph.get_edge_data (u, v[, key, default]) |
Return the attribute dictionary associated with edge (u, v). |
MultiGraph.neighbors (n) |
Return an iterator over all neighbors of node n. |
MultiGraph.adj |
Graph adjacency object holding the neighbors of each node. |
MultiGraph.__getitem__ (n) |
Return a dict of neighbors of node n. |
MultiGraph.adjacency () |
Return an iterator over (node, adjacency dict) tuples for all nodes. |
MultiGraph.nbunch_iter ([nbunch]) |
Return an iterator over nodes contained in nbunch that are also in the graph. |
Counting nodes edges and neighbors¶
MultiGraph.order () |
Return the number of nodes in the graph. |
MultiGraph.number_of_nodes () |
Return the number of nodes in the graph. |
MultiGraph.__len__ () |
Return the number of nodes. |
MultiGraph.degree |
A DegreeView for the Graph as G.degree or G.degree(). |
MultiGraph.size ([weight]) |
Return the number of edges or total of all edge weights. |
MultiGraph.number_of_edges ([u, v]) |
Return the number of edges between two nodes. |
Making copies and subgraphs¶
MultiGraph.copy ([as_view]) |
Return a copy of the graph. |
MultiGraph.to_undirected ([as_view]) |
Return an undirected copy of the graph. |
MultiGraph.to_directed ([as_view]) |
Return a directed representation of the graph. |
MultiGraph.subgraph (nodes) |
Return a SubGraph view of the subgraph induced on nodes . |
MultiGraph.edge_subgraph (edges) |
Returns the subgraph induced by the specified edges. |