Synthetic graphs

NEExT can generate labeled graph datasets for benchmarking, testing, and learning the pipeline without external data. There are three entry points, from highest-level to most hands-on.

1. Presets (one call)

generate_synthetic_graphs returns a ready-to-use GraphCollection from a named preset. Extra keyword arguments are forwarded to the underlying preset.

preset.py
from NEExT import NEExT

nxt = NEExT()
graphs = nxt.generate_synthetic_graphs(
  preset="er_vs_ba",
  n_per_class=50,
  n_nodes=50,
  seed=42,
)
presetTaskKey arguments (defaults)
er_vs_baBinary: Erdős–Rényi vs Barabási–Albertn_per_class=50, n_nodes=50
multiclass_topology4-class topology (ER / BA / WS / geometric)n_per_class=30, n_nodes=50
community_gradientCommunity-clarity gradient (SBM)n_per_level=20, n_nodes=90, n_communities=3
scalabilityIncreasing graph sizes for benchmarkingsizes=None, n_per_size=10, generator_type="erdos_renyi"
variable_sizeSize-invariance: small ER vs large BAn_per_class=50, class_a_range=(20,50), class_b_range=(80,150)
anomaly_detectionPlanted node anomalies (marks is_outlier)n_graphs=5, n_nodes=200, anomaly_fraction=0.05

The anomaly_detection preset pairs naturally with egonets for node-level outlier detection.

2. The generator registry

For full control over the mix, use GraphGenerator with GeneratorSpecs. Each spec names a generator, its parameters, and a label.

generator.py
from NEExT.generators import GraphGenerator, GeneratorSpec

gen = GraphGenerator(seed=42)

specs = [
  (GeneratorSpec(generator_type="erdos_renyi", params={"n": 100, "p": 0.05}, label=0), 50),
  (GeneratorSpec(generator_type="barabasi_albert", params={"n": 100, "m": 3}, label=1), 50),
]
nx_graphs = gen.generate_collection(specs, shuffle=True)

# Convert to a NEExT GraphCollection
graphs = gen.to_graph_collection(nx_graphs)

The 16 built-in generators: erdos_renyi, barabasi_albert, watts_strogatz, stochastic_block_model, planted_partition, lfr_benchmark, random_geometric, powerlaw_cluster, configuration_model, caveman, connected_caveman, cycle, star, complete, tree, grid_2d. Register your own with gen.register_generator(name, fn).

GeneratorSpec fields: generator_type (str), params (dict), label (int/float, default 0), and n_range (optional (min, max) for variable-size sampling).

3. The fluent builder

GraphBuilder composes a single graph step by step — start from a generator, plant communities, attach motifs, then label and build.

builder.py
from NEExT.generators import GraphBuilder

G = (
  GraphBuilder(seed=42)
  .empty(n=20)
  .plant_community(size=10, p_internal=0.8, p_bridge=0.1)
  .attach_motif("clique", size=5, attach_to="random")
  .set_label(1)
  .build()
)

Every mutation method returns the builder, so calls chain; build() finalizes and returns an nx.Graph with G.graph["label"] set (and resets the builder). Collect a list of these and load them with load_from_networkx.

GraphGenerator, GraphBuilder, and SyntheticPresets are also exported from the top level: from NEExT import GraphGenerator, GraphBuilder, SyntheticPresets.