|
The graph::generators namespace provides functions that return edge lists suitable for loading into any graph container. Each generator produces a std::vector<graph::copyable_edge_t<VId, EV>> that can be passed to dynamic_graph::load_edges() or used to construct a compressed_graph.
All generators are header-only and require no external dependencies.
#include <graph/generators.hpp> // umbrella — includes all generators
// Or include individually:
#include <graph/generators/path.hpp>
#include <graph/generators/grid.hpp>
#include <graph/generators/complete.hpp>
#include <graph/generators/erdos_renyi.hpp>
#include <graph/generators/gnm.hpp>
#include <graph/generators/barabasi_albert.hpp>
#include <graph/generators/watts_strogatz.hpp>
#include <graph/generators/rmat.hpp>
#include <graph/generators/plod.hpp>
#include <graph/generators/ssca.hpp>Creates a linear path graph: 0 → 1 → 2 → … → n-1.
template <std::unsigned_integral VId = uint32_t>
auto path_graph(VId num_vertices) -> std::vector<copyable_edge_t<VId, void>>;| Parameter | Description |
|---|---|
num_vertices |
Number of vertices in the path |
Returns: n-1 directed edges forming a simple path.
auto edges = graph::generators::path_graph(5u);
// edges: {0→1, 1→2, 2→3, 3→4}Creates a 2D grid (lattice) graph with rows × cols vertices.
template <std::unsigned_integral VId = uint32_t>
auto grid_graph(VId rows, VId cols) -> std::vector<copyable_edge_t<VId, void>>;| Parameter | Description |
|---|---|
rows |
Number of rows |
cols |
Number of columns |
Returns: Directed edges connecting each vertex to its right and bottom neighbors. Vertex IDs are laid out row-major: vertex at (r, c) has ID r * cols + c.
auto edges = graph::generators::grid_graph(3u, 4u);
// 12 vertices in a 3×4 grid, edges go right and downGenerates a complete graph K(n): every ordered pair (u, v) with u ≠ v.
template <class VId = uint32_t>
auto complete_graph(VId n, uint64_t seed = 42,
weight_dist wdist = weight_dist::uniform)
-> std::vector<copyable_edge_t<VId, double>>;| Parameter | Description |
|---|---|
n |
Number of vertices |
seed |
Random seed for reproducible edge weights |
wdist |
Edge-weight distribution: weight_dist::uniform (U[1,100], default), weight_dist::exponential (Exp(0.1)+1), or weight_dist::constant_one (1.0) |
Returns: n * (n-1) directed edges — the fully-connected graph — sorted by
source id, then target id.
Warning: the edge count grows as O(n²); generating K(n) for large
nis memory-intensive (e.g.n = 10'000yields ~100M edges).
auto edges = graph::generators::complete_graph(100u);
// 100 * 99 = 9'900 directed edgesGenerates a random graph using the Erdős–Rényi G(n, p) model.
template <std::unsigned_integral VId = uint32_t>
auto erdos_renyi_graph(VId num_vertices, double edge_probability,
uint64_t seed = 42)
-> std::vector<copyable_edge_t<VId, void>>;| Parameter | Description |
|---|---|
num_vertices |
Number of vertices |
edge_probability |
Probability p that each directed edge exists (0.0–1.0) |
seed |
Random seed for reproducibility |
Returns: A random directed graph where each potential edge (u, v) with u ≠ v exists independently with probability p.
auto edges = graph::generators::erdos_renyi_graph(100u, 0.05);
// ~495 edges on average (100*99*0.05)Generates a random graph using the Erdős–Rényi G(n, m) model — the
fixed-edge-count companion to erdos_renyi. Exactly m distinct edges are
selected uniformly at random from the n * (n-1) ordered pairs.
template <class VId = uint32_t>
auto erdos_renyi_gnm(VId n, size_t m, uint64_t seed = 42,
weight_dist wdist = weight_dist::uniform)
-> std::vector<copyable_edge_t<VId, double>>;| Parameter | Description |
|---|---|
n |
Number of vertices |
m |
Number of edges to generate (clamped to n * (n-1) if larger) |
seed |
Random seed for reproducibility |
wdist |
Edge-weight distribution: weight_dist::uniform (U[1,100], default), weight_dist::exponential (Exp(0.1)+1), or weight_dist::constant_one (1.0) |
Returns: Exactly m distinct directed edges (u ≠ v), sorted by source id.
Use this model when a precise edge count is required (e.g. controlling graph
density for benchmarks); use erdos_renyi (G(n, p)) when each edge should exist
independently with a fixed probability.
auto edges = graph::generators::erdos_renyi_gnm(100u, 500u);
// exactly 500 distinct directed edgesGenerates a scale-free graph using the Barabási–Albert preferential attachment model.
template <std::unsigned_integral VId = uint32_t>
auto barabasi_albert_graph(VId num_vertices, VId edges_per_vertex,
uint64_t seed = 42)
-> std::vector<copyable_edge_t<VId, void>>;| Parameter | Description |
|---|---|
num_vertices |
Total number of vertices |
edges_per_vertex |
Number of edges each new vertex attaches to existing vertices (m) |
seed |
Random seed for reproducibility |
Returns: A directed graph exhibiting power-law degree distribution. The initial seed graph is a complete graph on edges_per_vertex + 1 vertices.
auto edges = graph::generators::barabasi_albert_graph(1000u, 3u);
// ~3000 edges, scale-free topologyGenerates a small-world graph using the Watts–Strogatz model: a ring lattice
where each vertex connects to its k nearest neighbours, with each forward
lattice edge rewired to a random target with probability beta.
template <class VId = uint32_t>
auto watts_strogatz(VId n, VId k, double beta, uint64_t seed = 42,
weight_dist wdist = weight_dist::uniform)
-> std::vector<copyable_edge_t<VId, double>>;| Parameter | Description |
|---|---|
n |
Number of vertices (must be > k) |
k |
Each vertex connects to its k nearest ring neighbours (rounded down to even) |
beta |
Rewiring probability in [0, 1]: 0 = pure ring lattice, 1 ≈ random graph |
seed |
Random seed for reproducibility |
wdist |
Edge-weight distribution: weight_dist::uniform (default), weight_dist::exponential, or weight_dist::constant_one |
Returns: Bidirectional edges (each undirected pair emitted both ways), sorted
by source id. Intermediate beta (~0.01–0.1) produces the characteristic
small-world regime: high clustering with short average path length.
auto edges = graph::generators::watts_strogatz(100u, 6u, 0.1);
// ring lattice of degree 6, 10% of edges rewiredGenerates a directed graph using the R-MAT (Recursive MATrix) model, which
produces the power-law / community structure used by the Graph500 benchmark.
Each edge is placed by recursively descending into one of four adjacency-matrix
quadrants with probabilities (a, b, c, d).
template <class VId = uint32_t>
auto rmat(uint32_t scale, size_t m,
double a = 0.57, double b = 0.19, double c = 0.19, double d = 0.05,
uint64_t seed = 42, weight_dist wdist = weight_dist::uniform)
-> std::vector<copyable_edge_t<VId, double>>;| Parameter | Description |
|---|---|
scale |
Graph has 2^scale vertices |
m |
Number of directed edges to attempt to place |
a, b, c, d |
Quadrant probabilities (should sum to ~1; normalised internally) |
seed |
Random seed for reproducibility |
wdist |
Edge-weight distribution (see above) |
Returns: Up to m distinct directed edges (self-loops and duplicates
removed), sorted by source id. The default (0.57, 0.19, 0.19, 0.05) are the
standard Graph500 parameters.
auto edges = graph::generators::rmat<uint32_t>(16, 1u << 18);
// 65'536 vertices, ~256K edges, skewed degree distributionGenerates a directed graph with a power-law out-degree distribution (Palmer–Steffan PLOD model). Each vertex is assigned a target out-degree drawn from a power law, then edges are placed to random targets.
template <class VId = uint32_t>
auto plod(VId n, double alpha = 2.5, double beta = 10.0,
uint64_t seed = 42, weight_dist wdist = weight_dist::uniform)
-> std::vector<copyable_edge_t<VId, double>>;| Parameter | Description |
|---|---|
n |
Number of vertices |
alpha |
Power-law exponent (larger ⇒ steeper degree decay) |
beta |
Degree scaling factor (larger ⇒ denser graph) |
seed |
Random seed for reproducibility |
wdist |
Edge-weight distribution (see above) |
Returns: Directed edges (no self-loops or duplicates), sorted by source id.
Note: For most scale-free use cases
barabasi_albert_graphis a better choice;plodis provided for BGL parity.
auto edges = graph::generators::plod(1000u, 2.5, 10.0);
// power-law out-degree distributionGenerates an SSCA#2 (HPCS Scalable Synthetic Compact Applications #2) benchmark graph: randomly-sized cliques connected by sparse inter-clique edges whose probability decays with the inter-clique id distance.
template <class VId = uint32_t>
auto ssca(VId n, VId max_clique_size = 8, double prob_inter_clique = 0.2,
int max_parallel_edges = 2, uint64_t seed = 42,
weight_dist wdist = weight_dist::uniform)
-> std::vector<copyable_edge_t<VId, double>>;| Parameter | Description |
|---|---|
n |
Number of vertices |
max_clique_size |
Maximum clique size (sizes drawn uniformly from [1, this]) |
prob_inter_clique |
Probability a vertex emits an inter-clique edge |
max_parallel_edges |
Maximum parallel edges per intra-clique pair |
seed |
Random seed for reproducibility |
wdist |
Edge-weight distribution (see above) |
Returns: Directed edges sorted by source id. Vertices are partitioned into
consecutive cliques; every ordered pair within a clique is connected (with up to
max_parallel_edges parallel edges — a defining SSCA#2 trait), plus sparse
inter-clique links. Self-loops are skipped.
auto edges = graph::generators::ssca(1000u, 8u, 0.2);
// clustered graph: dense cliques + sparse inter-clique edges#include <graph/generators.hpp>
#include <graph/container/dynamic_graph.hpp>
#include <graph/graph.hpp>
#include <iostream>
int main() {
// Generate a 10×10 grid graph
auto edge_list = graph::generators::grid_graph(10u, 10u);
// Load into a dynamic_graph
using G = graph::container::dynamic_graph<void, void, void, uint32_t, false,
graph::container::vov_graph_traits<void, void, void, uint32_t, false>>;
G g;
g.load_edges(edge_list, std::identity{}, uint32_t{100});
std::cout << "Vertices: " << graph::num_vertices(g) << "\n";
// Output: Vertices: 100
// Count total edges
size_t edge_count = 0;
for (auto u : graph::vertices(g))
for ([[maybe_unused]] auto uv : graph::edges(g, u))
++edge_count;
std::cout << "Edges: " << edge_count << "\n";
// Output: Edges: 180
}