generators.md
397 lines · skills/networkx/references/generators.md at 5f2bc03
NetworkX Graph Generators
API patterns assume import networkx as nx. A generated model is a hypothesis about a graph, not evidence that observed data follow that model. Preserve direction, loops, multiplicity, size, degree constraints and seed/version provenance when constructing null ensembles. See review.md.
Classic Graphs
Raw lines 5 to 6Complete Graphs
# Complete graph (all nodes connected to all others)
G = nx.complete_graph(n=10)
# Complete bipartite graph
G = nx.complete_bipartite_graph(n1=5, n2=7)
# Complete multipartite graph
G = nx.complete_multipartite_graph(3, 4, 5) # Three partitionsRaw lines 7 to 18Cycle and Path Graphs
# Cycle graph (nodes arranged in circle)
G = nx.cycle_graph(n=20)
# Path graph (linear chain)
G = nx.path_graph(n=15)
# Circular ladder graph
G = nx.circular_ladder_graph(n=10)Raw lines 19 to 30Regular Graphs
# Empty graph (no edges)
G = nx.empty_graph(n=10)
# Null graph (no nodes)
G = nx.null_graph()
# Star graph (one central node connected to all others)
G = nx.star_graph(n=19) # Creates 20-node star
# Wheel graph (cycle with central hub)
G = nx.wheel_graph(n=10)Raw lines 31 to 45Special Named Graphs
# Bull graph
G = nx.bull_graph()
# Chvatal graph
G = nx.chvatal_graph()
# Cubical graph
G = nx.cubical_graph()
# Diamond graph
G = nx.diamond_graph()
# Dodecahedral graph
G = nx.dodecahedral_graph()
# Heawood graph
G = nx.heawood_graph()
# House graph
G = nx.house_graph()
# Petersen graph
G = nx.petersen_graph()
# Karate club graph (classic social network)
G = nx.karate_club_graph()Raw lines 46 to 75Random Graphs
Raw lines 76 to 77Erdős-Rényi Graphs
# G(n, p) model: n nodes, edge probability p
G = nx.erdos_renyi_graph(n=100, p=0.1, seed=42)
# G(n, m) model: n nodes, exactly m edges
G = nx.gnm_random_graph(n=100, m=500, seed=42)
# Fast version (for large sparse graphs)
G = nx.fast_gnp_random_graph(n=10000, p=0.0001, seed=42)Raw lines 78 to 89Watts-Strogatz Small-World
# Small-world network with rewiring
# n nodes, k nearest neighbors, rewiring probability p
G = nx.watts_strogatz_graph(n=100, k=6, p=0.1, seed=42)
# Returns a connected sample or raises after tries attempts
G = nx.connected_watts_strogatz_graph(n=100, k=6, p=0.1, tries=100, seed=42)Raw lines 90 to 99Barabási-Albert Preferential Attachment
# Preferential-attachment model; finite samples do not establish a power law
# n nodes, m edges to attach from new node
G = nx.barabasi_albert_graph(n=100, m=3, seed=42)
# Extended version with parameters
G = nx.extended_barabasi_albert_graph(n=100, m=3, p=0.5, q=0.2, seed=42)Raw lines 100 to 109Power Law Degree Sequence
# Power law cluster graph
G = nx.powerlaw_cluster_graph(n=100, m=3, p=0.1, seed=42)
# Random power law tree
G = nx.random_powerlaw_tree(n=100, gamma=3, seed=42, tries=1000)Raw lines 110 to 118Configuration Model
# Graph with specified degree sequence
degree_sequence = [3, 3, 2, 2, 2, 2] # Even sum required
G = nx.configuration_model(degree_sequence, seed=42)
assert [G.degree(i) for i in range(len(degree_sequence))] == degree_sequence
# Optional simplification changes the degree sequence and null model
H = nx.Graph(G)
H.remove_edges_from(list(nx.selfloop_edges(H)))The configuration model is a stub-matching multigraph with possible self-loops. Removing loops/parallel edges does not preserve the specified degrees. havel_hakimi_graph gives one simple realization of a graphical sequence, not a uniform random sample. Degree-preserving swaps need adequate mixing and convergence checks; neither a single sample nor a fixed seed establishes null-model validity.
Random Geometric Graphs
# Nodes in unit square, edges if distance < radius
G = nx.random_geometric_graph(n=100, radius=0.2, seed=42)
# With positions
pos = nx.get_node_attributes(G, 'pos')Raw lines 133 to 141Random Regular Graphs
# Every node has exactly d neighbors
G = nx.random_regular_graph(d=3, n=100, seed=42)Raw lines 142 to 147Stochastic Block Model
# Community structure model
sizes = [50, 50, 50] # Three communities
probs = [[0.25, 0.05, 0.02], # Within and between community probabilities
[0.05, 0.35, 0.07],
[0.02, 0.07, 0.40]]
G = nx.stochastic_block_model(sizes, probs, seed=42)Raw lines 148 to 157Lattice and Grid Graphs
Raw lines 158 to 159Grid Graphs
# 2D grid
G = nx.grid_2d_graph(m=5, n=7) # 5x7 grid
# 3D grid
G = nx.grid_graph(dim=[5, 7, 3]) # 5x7x3 grid
# Hexagonal lattice
G = nx.hexagonal_lattice_graph(m=5, n=7)
# Triangular lattice
G = nx.triangular_lattice_graph(m=5, n=7)Raw lines 160 to 174Tree Graphs
Raw lines 181 to 182Random Trees
# Random labeled tree with n nodes, sampled uniformly over labeled trees
# (nx.random_tree was removed in NetworkX 3.4)
G = nx.random_labeled_tree(100, seed=42)
# Sample uniformly over isomorphism classes instead
G = nx.random_unlabeled_tree(100, seed=42)
# Rooted variant is still an undirected Graph, with G.graph["root"]
G = nx.random_labeled_rooted_tree(100, seed=42)
# Prefix tree (tries)
G = nx.prefix_tree([[0, 1, 2], [0, 1, 3], [0, 4]])Raw lines 183 to 198Balanced Trees
# Balanced r-ary tree of height h
G = nx.balanced_tree(r=2, h=5) # Binary tree, height 5
# Full r-ary tree with n nodes
G = nx.full_rary_tree(r=3, n=100) # Ternary treeRaw lines 199 to 207Barbell and Lollipop Graphs
# Two complete graphs connected by path
G = nx.barbell_graph(m1=5, m2=3) # Two K_5 graphs with 3-node path
# Complete graph connected to path
G = nx.lollipop_graph(m=7, n=5) # K_7 with 5-node pathRaw lines 208 to 216Social Network Models
Raw lines 217 to 218Karate Club
# Zachary's karate club (classic social network)
G = nx.karate_club_graph()Raw lines 219 to 224Davis Southern Women
# Bipartite social network
G = nx.davis_southern_women_graph()Raw lines 225 to 230Florentine Families
# Historical marriage network (this generator does not add business ties)
G = nx.florentine_families_graph()Raw lines 231 to 236Directed Graph Generators
Raw lines 243 to 244Random Directed Graphs
# Directed Erdős-Rényi
G = nx.gnp_random_graph(n=100, p=0.1, directed=True, seed=42)
# Directed MultiDiGraph; parallel edges and self-loops can occur
G = nx.scale_free_graph(n=100, seed=42)Raw lines 245 to 253DAG (Directed Acyclic Graph)
# Ordered random DAG; this is not uniform over all DAGs
R = nx.gnp_random_graph(n=20, p=0.2, directed=True, seed=42)
G = nx.DiGraph()
G.add_nodes_from(R) # Preserve isolates
G.add_edges_from((u, v) for u, v in R.edges() if u < v)
assert len(G) == 20 and nx.is_directed_acyclic_graph(G)Raw lines 254 to 263Tournament Graphs
# Random tournament (complete directed graph); lives in the tournament module
G = nx.tournament.random_tournament(n=10, seed=42)Raw lines 264 to 269Duplication-Divergence Models
Raw lines 270 to 271Duplication Divergence Graph
# Biological network model (protein interaction networks)
G = nx.duplication_divergence_graph(n=100, p=0.5, seed=42)Raw lines 272 to 277Degree Sequence Generators
Raw lines 278 to 279Valid Degree Sequences
# Check if degree sequence is valid (graphical)
sequence = [3, 3, 2, 2, 2, 2]
is_valid = nx.is_graphical(sequence)
# For directed graphs
in_sequence = [2, 2, 2, 1, 1]
out_sequence = [2, 2, 1, 2, 1]
is_valid = nx.is_digraphical(in_sequence, out_sequence)Raw lines 280 to 291Creating from Degree Sequence
# Havel-Hakimi algorithm
G = nx.havel_hakimi_graph(degree_sequence)
# Configuration model (allows multi-edges/self-loops)
G = nx.configuration_model(degree_sequence, seed=42)
# Directed configuration model: sums must match
G = nx.directed_configuration_model(in_sequence, out_sequence, seed=42)Raw lines 292 to 303Bipartite Graphs
Raw lines 304 to 305Random Bipartite
# Random bipartite with two node sets
G = nx.bipartite.random_graph(n=50, m=30, p=0.1, seed=42)
# Configuration model for bipartite
G = nx.bipartite.configuration_model(aseq=[3, 3, 2], bseq=[2, 2, 2, 2], seed=42)Raw lines 306 to 314Bipartite Generators
# Complete bipartite
G = nx.complete_bipartite_graph(n1=5, n2=7)
# Gnmk random bipartite (n, m nodes, k edges)
G = nx.bipartite.gnmk_random_graph(n=10, m=8, k=20, seed=42)Raw lines 315 to 323Operators on Graphs
Raw lines 324 to 325Graph Operations
# Union requires disjoint node labels (or supply rename prefixes)
G = nx.union(G1, G2)
# Disjoint union
G = nx.disjoint_union(G1, G2)
# Compose (overlay)
G = nx.compose(G1, G2)
# Complement
G = nx.complement(G1)
# Cartesian product
G = nx.cartesian_product(G1, G2)
# Tensor (Kronecker) product
G = nx.tensor_product(G1, G2)
# Strong product
G = nx.strong_product(G1, G2)Raw lines 326 to 349Customization and Seeding
Raw lines 350 to 351Setting Random Seed
Set a seed and record NetworkX/Python versions and generation parameters. A seed does not promise identical graphs across releases/backends:
G = nx.erdos_renyi_graph(n=100, p=0.1, seed=42)Raw lines 352 to 357Converting Graph Types
# Convert to specific type
G_directed = G.to_directed()
G_undirected = G.to_undirected()
G_multi = nx.MultiGraph(G)Raw lines 358 to 365Performance Considerations
Raw lines 366 to 367Fast Generators
For large graphs, use optimized generators:
# Fast ER graph (sparse)
G = nx.fast_gnp_random_graph(n=10000, p=0.0001, seed=42)Raw lines 368 to 374Memory Efficiency
Some generators create graphs incrementally to save memory. For very large graphs, consider:
- Using sparse representations
- Generating subgraphs as needed
- Working with adjacency lists or edge lists instead of full graphs
Validation and Properties
Raw lines 381 to 382Checking Generated Graphs
# Verify properties
print(f"Nodes: {G.number_of_nodes()}")
print(f"Edges: {G.number_of_edges()}")
print(f"Density: {nx.density(G)}")
if len(G):
connected = nx.is_weakly_connected(G) if G.is_directed() else nx.is_connected(G)
print(f"Connected (weak if directed): {connected}")
else:
print("Connectivity undefined for the null graph")
# Degree distribution
degree_sequence = sorted([d for n, d in G.degree()], reverse=True)Raw lines 383 to 397