Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/skills
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -178,3 +178,9 @@ research_projects/**/results/
research_projects/**/phase*/
research_projects/lm_*/
research_projects/square_mesh_*/

# Timing records published with the tracked result fixtures
!tests/data/**/*results.run.json
!tests/autoresearch/data/
tests/autoresearch/data/*
!tests/autoresearch/data/*results.run.json
2 changes: 1 addition & 1 deletion .superset/workspace.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export PATH="$VIRTUAL_ENV/bin:$PATH"
if [[ "$mode" == setup ]]; then
python -m pip install -e '.[dev]'
python -m pip check
python -c 'import netlab, ngraph, netgraph_core, topogen; print("Workspace environment ready")'
python -c 'import netlab, ngraph, netgraph_core, netlab_topogen; print("Workspace environment ready")'
else
make check-ci
fi
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,32 @@

## [Unreleased]

## [0.6.0] - 2026-10-29

### Changed

- **BREAKING**: **Dependencies**: Require `ngraph>=0.26.0,<0.27` and `netlab-topogen>=0.6.1,<0.7`, which replaces TopoGen.
- **BREAKING**: **Scenarios**: Workflows use NetGraph 0.26 keys: `alpha_tolerance`, `workers`, `outputs.cost_distribution`, `preset`.
- **BREAKING**: **TopoGen configs**: Drop `build.tm_sizing.flow_placement`; traffic uses `TE_MAXFLOW_UNLIM` instead of `TE_WCMP_UNLIM`.
- **BREAKING**: **Input formats**: Read NetGraph 0.26 results: named steps, sampled cases, units of `units_report.q`, MSD `alpha_feasible`.
- **BREAKING**: **Metrics**: `netlab metrics` requires each result's run record, `<name>.results.run.json`, with every step's wall time.
- **BREAKING**: **Research**: Objectives read `steps.msd_baseline.result.alpha_feasible.value`; `init` writes that path.
- **BREAKING**: **Python API**: `compute_iter_ops` and `analyze_one_seed` take the run record; `pair_totals` takes the results, step and case.
- **Runs**: A run whose MSD search finds no feasible multiplier fails with the reason `none_feasible`.
- **Metrics**: Bandwidth follows NetGraph 0.26's whole units of `q`, and `random` failure rules draw per matched entity.
- **Metrics**: TE latency percentiles and shares read NetGraph's marginal cost curve; WES uses each row's mean path cost.
- **Metrics**: Provenance records NetLab's `commit` (clean checkout or GitHub install) and `dirty`, not its install URL; null if unknown.
- **Docs**: Explain samples and the baseline reference, bandwidth units, run records and TE latency; examples say when they need network.
- **Internal**: Regenerate fixtures with run records on the published packages; dev and workspace scripts use `netlab_topogen`.

### Added

- **Runs**: Run records store each step's wall time, measured by NetLab, as `step_durations_sec`; `tm_duration_*` read it.

### Removed

- **Python API**: Remove `expand_flow_results` and `flow_occurrence_count` from `netlab.metrics.common`.

## [0.5.0] - 2026-10-25

### Fixed
Expand Down
62 changes: 36 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# NetLab

NetLab builds network scenarios with [TopoGen](https://github.com/networmix/TopoGen),
runs them with [NetGraph](https://github.com/networmix/NetGraph), and compares the
results. It reports how much traffic survives failures, how path costs change,
and how much the modeled equipment costs and consumes.
NetLab builds network scenarios with
[NetLab-TopoGen](https://github.com/networmix/NetLab-TopoGen), runs them with
[NetGraph](https://github.com/networmix/NetGraph), and compares the results. It
reports how much traffic survives failures, how path costs change, and how much
the modeled equipment costs and consumes.

You can run several configurations and random seeds in one batch. NetLab also
supports parameter searches and experiments proposed by a language model.
Expand All @@ -16,9 +17,10 @@ Use Python 3.11 or later and Git. To install the command:
python -m pip install git+https://github.com/networmix/NetLab
```

This also installs NetGraph, TopoGen and the other dependencies.
[pyproject.toml](pyproject.toml) pins TopoGen to a release commit and lists the
supported NetGraph versions.
NetLab is installed from GitHub because the name `netlab` on PyPI belongs to
another project. The command also installs NetGraph (`ngraph`), NetLab-TopoGen
(`netlab-topogen`) and the other dependencies from PyPI;
[pyproject.toml](pyproject.toml) lists their supported versions.

To use the included examples, clone the repository and create its environment:

Expand All @@ -33,7 +35,10 @@ Run the commands below from the repository root.

## Run an example

This example uses saved geographic routes, so no Census download is needed:
This example uses saved geographic routes, so no Census download is needed. It
still needs network access: the build draws a site map for each scenario from
downloaded map tiles. To build offline, set `visualization.site_graph.export:
false` in a copy of the configuration.

```bash
netlab run topogen_configs_small/small_baseline.yml --seeds 11 12 \
Expand All @@ -43,13 +48,13 @@ netlab metrics scenarios/
```

The first command builds a network for each seed and runs its NetGraph workflow.
A **seed** is the scenario's random seed. It drives TopoGen's random traffic
A **seed** is the scenario's random seed. It drives NetLab-TopoGen's random traffic
choices and NetGraph's failure sampling, so the same seed repeats the same
experiment. The second command calculates metrics and renders comparison figures.

| Location | Contents |
| --- | --- |
| `scenarios/<config>/<config>__seed<N>/` | Scenario YAML, NetGraph results and task outcomes |
| `scenarios/<config>/<config>__seed<N>/` | Scenario YAML, NetGraph results and NetLab's run record |
| `scenarios/<config>/<config>_integrated_graph.json` | Geography generated when `--graphs-dir` is omitted |
| `scenarios/provenance.json` | Input hashes, settings, package versions and outcomes of the last batch |
| `scenarios_metrics/project.csv` | One summary row per configuration |
Expand All @@ -58,9 +63,9 @@ experiment. The second command calculates metrics and renders comparison figures

To build without simulating, use `netlab build` with the same input arguments.
To generate geography yourself, omit `--graphs-dir` and first download the
[data required by TopoGen](https://github.com/networmix/TopoGen#readme).
[data required by NetLab-TopoGen](https://github.com/networmix/NetLab-TopoGen#readme).
The `data/` and `lib/` paths are relative to your working directory. From the
repository root, `lib/workflows.yml` replaces TopoGen's `design_analysis_brief`
repository root, `lib/workflows.yml` replaces NetLab-TopoGen's `design_analysis_brief`
workflow with NetLab's version, and `lib/failure_policies.yml` adds `mc_hard`.

Saved geography must be a corridor `MultiGraph`: a graph that can keep several
Expand All @@ -83,9 +88,11 @@ NetLab reuses saved work only when a hash of its inputs still matches; a hash
identifies file contents, so any change to the inputs invalidates the cache.
Generated geography is reused while the configuration, data files and package
versions are unchanged. A simulation result is reused while the scenario,
package versions and the saved result file are unchanged.
package versions, the saved result file and its run record are unchanged.
Failed tasks make the command return a failure status; independent tasks continue.
Task outcomes are saved in `.run.json` files alongside the results.
Each run's outcome and the wall time of each workflow step are saved in a run
record, `<name>.results.run.json`, beside the results; a reused result keeps the
times of the run that produced it.

## Read and compare metrics

Expand All @@ -106,12 +113,13 @@ The workflow must include these step names:
| Step name | NetGraph analysis |
| --- | --- |
| `msd_baseline` | `MaximumSupportedDemand`, which searches for a traffic multiplier |
| `tm_placement` | `TrafficMatrixPlacement` at the MSD multiplier, with flow details enabled |
| `tm_placement` | `TrafficMatrixPlacement` with `alpha_from_step: msd_baseline`, and `outputs: {cost_distribution: true}` for latency |
| `network_statistics` | `NetworkStats`, which counts network objects |

`--enable-maxflow` also needs a `node_to_node_capacity_matrix` step for pairwise
capacity analysis. See [metrics.md](metrics.md) for definitions, required fields,
worked examples and output files. Failure statistics describe the configured
capacity analysis. Each result needs the run record NetLab writes beside it.
See [metrics.md](metrics.md) for definitions, required fields, worked examples
and output files. Failure statistics describe the configured
experiment; they are not measurements of network uptime.

To compare two configurations with matching seeds:
Expand All @@ -138,9 +146,9 @@ if __name__ == "__main__":
```

`run_simulation` runs in a local worker process. A successful run saves
`scenario.results.json` next to the scenario; every run records its status in
`scenario.results.run.json`. The `__main__` guard keeps a spawned worker from
running the script again. Use `simulate(yaml_text)` to run in the calling
`scenario.results.json` next to the scenario; every run records its status and
the wall time of each step it ran in `scenario.results.run.json`. The `__main__`
guard keeps a spawned worker from running the script again. Use `simulate(yaml_text)` to run in the calling
process, or `inspect_scenario(yaml_text)` to validate and count network objects.
See [architecture and batch APIs](dev/ARCHITECTURE.md).

Expand Down Expand Up @@ -168,13 +176,15 @@ They return the per-seed values described in [metrics.md](metrics.md).
An autoresearch project gives a language model a task description
(`program.md`), the parameters it may change (`hypothesis_template.yml`) and the
metric to optimize (`objective.yml`). `init` copies a base scenario that has a
`MaximumSupportedDemand` step. Each `${{name}}` placeholder in it becomes a
parameter, and the objective maximizes `steps.msd_baseline.data.alpha_star`.
Review the generated files before a run:
`MaximumSupportedDemand` step and at least one `${{name}}` placeholder. Each
placeholder becomes a parameter, and the objective maximizes
`steps.msd_baseline.result.alpha_feasible.value`, the multiplier of the step named
`msd_baseline`. A candidate whose search finds no feasible multiplier fails; it
never scores zero. Review the generated files before a run:

```bash
netlab autoresearch init --base-scenario scenario.yml --output project/
netlab autoresearch run project/ --backend mock
netlab autoresearch run project/ --backend mock --max-experiments 1
```

The `mock` backend is for testing the workflow. To use an external model, select
Expand All @@ -201,7 +211,7 @@ For data-center-to-backbone designs, see the
make check-ci
```

This checks formatting, lint, types and tests, including TopoGen → NetGraph →
This checks formatting, lint, types and tests, including NetLab-TopoGen → NetGraph →
metrics runs using saved geography. See [fixture regeneration](tests/data/README.md)
and [metric verification](dev/METRICS_VERIFICATION.md).

Expand All @@ -212,7 +222,7 @@ checkout. The Run button executes `make check-ci`.
To test local checkouts of all three dependencies:

```bash
bash dev/check_ngraph_integration.sh /path/to/NetGraph /path/to/NetGraph-Core /path/to/TopoGen
bash dev/check_ngraph_integration.sh /path/to/NetGraph /path/to/NetGraph-Core /path/to/NetLab-TopoGen
```

Replace the paths with your checkouts. The script builds Core and runs checks in
Expand Down
56 changes: 36 additions & 20 deletions dev/ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# How NetLab runs work

TopoGen creates geographic routes and network scenarios. NetGraph runs the
scenario's analysis steps. NetLab schedules those calls, saves their results
NetLab-TopoGen creates geographic routes and network scenarios. NetGraph runs
the scenario's analysis steps. NetLab schedules those calls, saves their results
and turns the results into metrics, tables and figures.

## Worker processes and time limits
Expand All @@ -15,14 +15,25 @@ is stopped and replaced. If a worker crashes, the pool replaces it too.
Other tasks can continue; failed tasks are reported without automatic retries.

`SimulationBatch` submits scenario files to a queue managed by its caller.
Each task loads a scenario once and executes its NetGraph workflow. The parent
process saves results only after success.
Each task loads a scenario once, prepares it with NetGraph's `prepare` and runs
it with `run`, passing a `step_hook` that measures the wall time of each named
step. NetGraph's `write_json` exports the results. The parent process then saves
the run record, `<name>.results.run.json` (status, error, whole-run time,
network counts and the step times), and, after success, the results
`<name>.results.json`. NetLab's times stay out of NetGraph's results. A cached
result is reused only together with its unchanged run record, so it keeps its
original times. A cached result whose record is missing or lacks a step time is
refused with an error; a forced run replaces both.

## Pipeline and cache

A master configuration is a TopoGen input file. `run_pipeline` generates or
loads one geographic graph per master configuration.
A master configuration is a NetLab-TopoGen input file. `run_pipeline` generates
or loads one geographic graph per master configuration.
It builds a scenario for each requested seed and can then simulate each scenario.
Each build calls `build_scenario` with the library loaded from `lib/`, checks the
result with `validate_scenario`, and only then writes the scenario and
NetLab-TopoGen's other build outputs, such as the site map (`write_scenario`,
`write_artifacts`).
Relative datasets and `lib/` definitions are read from the working directory.

```python
Expand All @@ -42,26 +53,30 @@ if __name__ == "__main__":
```

Run the example from the repository root. The supplied graph avoids a Census
download. Its filename prefix must match the master configuration.
download; its filename prefix must match the master configuration. The site
maps of the build still need network access for map tiles.

A generated graph is reused while the configuration, its data files and the
package versions are unchanged. Scenario assembly runs on each invocation; when
the rebuilt scenario differs from the saved one, its old results are removed.
A saved simulation is reused only when the scenario, package and result hashes
match. For editable packages, the package record also includes a fingerprint of
the source files, so source changes invalidate cached work. A failed build
removes the corresponding saved scenario and results rather than leaving them
available as valid outputs.
A saved simulation is reused only when the scenario, package, result and run
record hashes match. For editable packages, the package record also includes a
fingerprint of the source files, so source changes invalidate cached work. A
failed build removes the corresponding saved scenario, results and run record
rather than leaving them available as valid outputs.

## Metric calculation

Metric functions read NetGraph result dictionaries. `metrics/analysis.py`
validates and analyzes one seed. `metrics/batch.py` groups seeds and creates a
complete report. That report replaces the destination only when analysis
succeeds. `metrics/reporting.py` reads saved metric files to produce summaries
and figures.
Metric functions read NetGraph's exported results. `results.py` is the one
reader of their structure: steps found by name, sampled cases and their
occurrences, converged rows, and whole bandwidth units converted to physical
bandwidth with `units_report.q`. `run_record.py` reads the step times.
`metrics/analysis.py` validates and analyzes one seed. `metrics/batch.py` groups
seeds and creates a complete report. That report replaces the destination only
when analysis succeeds. `metrics/reporting.py` reads saved metric files to
produce summaries and figures.

A per-seed metric summarizes failure samples for one random seed. A project
A per-seed metric summarizes the sampled draws of one random seed. A project
metric usually takes the median of those seed summaries. Pooled curves instead
use all samples, so seeds with more samples have more weight. Definitions and
examples are in [metrics.md](../metrics.md).
Expand All @@ -83,8 +98,9 @@ Paths in the table are relative to `netlab/`.

| Responsibility | Modules |
| --- | --- |
| Queue, simulation and saved outputs | `tasks.py`, `simulation.py`, `artifacts.py` |
| TopoGen builds and batch execution | `topology.py`, `pipeline.py`, `cli.py` |
| Queue, simulation and saved outputs | `tasks.py`, `simulation.py`, `run_record.py`, `artifacts.py` |
| NetLab-TopoGen builds and batch execution | `topology.py`, `pipeline.py`, `cli.py` |
| Reading NetGraph results and bandwidth units | `results.py` |
| Experiment inputs | `scenario.py`, `experiment.py` |
| Metric calculation and validation | `metrics/` |
| Experiment failure summaries, comparisons and topology rendering | `metrics_failure.py`, `comparison.py`, `visualize.py` |
Expand Down
9 changes: 5 additions & 4 deletions dev/METRICS_VERIFICATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ The verification network has two routes between the same endpoints:
| Through node `v` | 3 | 4 |

With both routes available, it carries 8 units. If a link on the first route
fails, only 3 units can be delivered. The experiment includes one baseline and
one failure sample, so its bandwidth ratios are `1` and `3/8`. Their mean,
fails, only 3 units can be delivered. The experiment has one baseline reference
and one sampled draw, so its bandwidth ratios are `1` and `3/8`. Their mean,
the capped BAC score, is `(1 + 3/8) / 2 = 0.6875`.

The failure's delivered traffic uses the route of cost 4. The cheapest baseline
Expand All @@ -56,6 +56,7 @@ It also checks weighted samples, placement variants and several random seeds.

| Area | Independent check |
| --- | --- |
| Whole bandwidth units | Convert exported unit counts with `units_report.q` and compare them with physical capacities derived by hand |
| Bandwidth at a stated availability | Count samples that meet each threshold, including exact decimal boundaries and repeated samples |
| Availability curves | Count observations at or above each distinct delivered-bandwidth value |
| Latency stretch | Expand delivered-volume distributions and use a separate baseline cost for each endpoint pair |
Expand All @@ -77,8 +78,8 @@ The CLI tests also check tables and report replacement.
| `diamond-mask-*.json` | NetGraph results for each failed-link subset |
| `native-summary.json` | Expected and measured values for the small network |
| `variant-*.json` | Results for the additional model cases |
| `disconnected-msd.json` | The expected rejection when no positive demand multiplier is feasible |
| `multiseed/` | NetGraph results for three capacity variants, each with five seeds |
| `disconnected-msd.json` | The failed run, with reason `none_feasible`, when no tested demand multiplier is feasible |
| `multiseed/` | NetGraph results and NetLab run records for three capacity variants, each with five seeds |
| `multiseed-expected.json` | Independently calculated summaries across seeds |
| `multiseed_metrics/` | Generated tables and optional figures for those results |

Expand Down
Loading
Loading