Directed graphs and multigraphs

NetworkX · Essentials · 10 min

Picking the wrong graph class silently changes results, from degrees to shortest paths.

NetworkX has four graph classes:

  • Graph: undirected, at most one edge per pair. Friendships, road segments.
  • DiGraph: directed edges u -> v. Follows, links, dependencies, one-way streets.
  • MultiGraph: undirected, several parallel edges allowed. Multiple flights between two cities.
  • MultiDiGraph: directed with parallel edges. Transaction logs, OpenStreetMap road networks.

In a DiGraph, G.successors(n) gives out-neighbours and G.predecessors(n) in-neighbours; neighbors means successors. G.in_degree(n) and G.out_degree(n) count each direction. Algorithms respect direction: a path must follow arrows. G.reverse() flips every edge, and G.to_undirected() drops direction.

In a multigraph, each edge has a key distinguishing parallel edges: G.add_edge("A", "B", key="morning", price=99) returns the key, and G.edges(keys=True, data=True) shows them all. Many algorithms don't support multigraphs or treat parallel edges specially. Converting with nx.Graph(M) keeps just one edge per pair and its attributes, possibly not the ones you want, so aggregate explicitly first if needed.

Check a graph's type with G.is_directed() and G.is_multigraph().

Example

import networkx as nx

D = nx.DiGraph([("ana", "ben"), ("ben", "cy"), ("cy", "ana"), ("di", "ana")])
print(sorted(D.successors("ana")), sorted(D.predecessors("ana")))
# ['ben'] ['cy', 'di']
print(D.in_degree("ana"), D.out_degree("ana"))     # 2 1
print(nx.has_path(D, "ana", "di"))                 # False (arrows point to ana)
print(nx.has_path(D.to_undirected(), "ana", "di")) # True

M = nx.MultiGraph()
M.add_edge("OSL", "BGO", key="07:00", price=99)
M.add_edge("OSL", "BGO", key="18:30", price=149)
print(M.number_of_edges("OSL", "BGO"))             # 2
print(sorted(M.edges(keys=True, data="price")))
# [('OSL', 'BGO', '07:00', 99), ('OSL', 'BGO', '18:30', 149)]
print(nx.Graph(M).number_of_edges())               # 1

Remember

  • Graph, DiGraph, MultiGraph, MultiDiGraph: direction and parallel edges
  • DiGraphs have successors/predecessors and in/out degree
  • Multigraph edges are identified by (u, v, key)

Watch out for

  • Modelling one-way relationships with an undirected Graph, so paths ignore direction.

Check yourself

  1. In a DiGraph with edge ('a', 'b'), what does list(G.neighbors('b')) contain?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: networkx.org/documentation/stable/reference/classes/index.html