# graph_generators { #tvbo.graph_generators }

`graph_generators`

TVBO graph generators — declarative typed DAGs, one resolver.

A curated ``GraphGenerator`` under ``tvbo/database/graph_generators/`` is defined by its ``procedure:`` block: an ordered DAG of typed steps whose options are schema fields.
:mod:`tvbo.graph_generators.procedural` resolves that DAG to SymPy and renders it through the printer tables in ``tvbo/codegen/code.py``, so eager construction at ``Network`` load time and emitted backend source are the same expressions rendered twice. There are no per-generator Python materialisers.

Two kinds of generator sit outside the DAG, both through the standard ``bindings`` slot: library wrappers (Graphs.jl / NetworkX families) and the documented Callable exception below, for a construction the backend-independent primitive set genuinely cannot express.

The helper below is a *thin convenience wrapper* over the resolver (it holds no generation algorithm) for scripts and notebooks that want a matrix directly.

## Functions

| Name | Description |
| --- | --- |
| [random_reservoir](#tvbo.graph_generators.random_reservoir) | Materialise a ``RandomReservoir`` adjacency through the typed-DAG resolver. |
| [weight_shuffle](#tvbo.graph_generators.weight_shuffle) | Materialise a ``WeightShuffle`` null-model adjacency: permute the non-zero weights. |

### random_reservoir { #tvbo.graph_generators.random_reservoir }

```python
graph_generators.random_reservoir(
    n_nodes,
    sparsity=0.1,
    spectral_radius=0.95,
    weight_distribution=None,
    seed=None,
)
```

Materialise a ``RandomReservoir`` adjacency through the typed-DAG resolver.

### weight_shuffle { #tvbo.graph_generators.weight_shuffle }

```python
graph_generators.weight_shuffle(source, preserve='binary_mask', seed=None)
```

Materialise a ``WeightShuffle`` null-model adjacency: permute the non-zero weights.

This is the documented exception to the typed-DAG rule: a masked extract, a permutation and a scatter are not expressible in the backend-independent primitive set. Boolean-mask extraction in particular cannot survive expression parsing at all — ``M[M != 0]`` evaluates its comparison to a plain Python ``True`` before an expression tree is ever built. So the algorithm lives here as ordinary Python, reached through the generator's ``bindings.python`` binding like any other library wrapper.

``preserve='binary_mask'`` keeps the ``{0, nonzero}`` pattern and permutes the weight values among their existing positions, so density and topology are held fixed while the weight-to-edge assignment is randomised.

#### Parameters {.doc-section .doc-section-parameters}

| Name     | Type        | Description                                                             | Default         |
|----------|-------------|-------------------------------------------------------------------------|-----------------|
| source   | str         | IRI, path or database name of the reference Network to shuffle.         | _required_      |
| preserve | str         | Structural property to hold fixed. Only ``binary_mask`` is implemented. | `'binary_mask'` |
| seed     | int \| None | PRNG seed; ``None`` means 0, matching the generator's declared default. | `None`          |

#### Returns {.doc-section .doc-section-returns}

| Name   | Type   | Description                                               |
|--------|--------|-----------------------------------------------------------|
|        | dict   | ``{"weights": ndarray}`` — the permuted adjacency matrix. |