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
100 changes: 100 additions & 0 deletions CHANGELOG.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ perf:
validate:
@echo "📋 Validating YAML schemas..."
@if $(PYTHON) -c "import jsonschema" >/dev/null 2>&1; then \
$(PYTHON) -c "import json, yaml, jsonschema, pathlib; from importlib import resources as res; f=res.files('ngraph.schemas').joinpath('scenario.json').open('r', encoding='utf-8'); schema=json.load(f); f.close(); scenario_files=list(pathlib.Path('scenarios').rglob('*.yaml')); integration_files=list(pathlib.Path('tests/integration').glob('*.yaml')); all_files=scenario_files+integration_files; [jsonschema.validate(yaml.safe_load(open(fp)), schema) for fp in all_files]; print(f'✅ Validated {len(all_files)} YAML files against schema ({len(scenario_files)} scenarios, {len(integration_files)} integration tests)')"; \
$(PYTHON) -c "import json, yaml, jsonschema, pathlib; from importlib import resources as res; f=res.files('ngraph.schemas').joinpath('scenario.json').open('r', encoding='utf-8'); schema=json.load(f); f.close(); scenario_files=sorted(set(pathlib.Path('scenarios').rglob('*.yaml')) | set(pathlib.Path('scenarios').rglob('*.yml'))); integration_files=sorted(set(pathlib.Path('tests/integration').glob('*.yaml')) | set(pathlib.Path('tests/integration').glob('*.yml'))); all_files=scenario_files+integration_files; [jsonschema.validate(yaml.safe_load(open(fp)), schema) for fp in all_files]; print(f'✅ Validated {len(all_files)} YAML files against schema ({len(scenario_files)} scenarios, {len(integration_files)} integration tests)')"; \
else \
echo "⚠️ jsonschema not installed. Skipping schema validation"; \
fi
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ print(result) # {('^A$', '^C$'): 10.0}

## Scenario DSL

For reproducible analysis workflows, define topology, traffic, demands, and failure policies in YAML:
For reproducible analysis workflows, define topology, demands, and failure policies in YAML:

```yaml
seed: 42
Expand Down
10 changes: 9 additions & 1 deletion dev/generate_api_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,11 +279,19 @@ def get_class_info(cls):
else:
default_val = None

default_str = str(default_val) if default_val is not None else None
# Drop non-reproducible reprs such as
# "<unlocked _thread.lock object at 0x109648810>": the address changes
# on every run, so the documented value is meaningless to a reader
# and makes the generated file differ between runs.
if default_str is not None and " object at 0x" in default_str:
default_str = None

info["attributes"].append(
{
"name": field_name,
"type": field_type,
"default": str(default_val) if default_val is not None else None,
"default": default_str,
}
)

Expand Down
2 changes: 1 addition & 1 deletion docs/assets/diagrams/system_pipeline.dot
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ digraph SystemPipeline {

subgraph cluster_model {
label=""; style=invis;
scenario [label="Scenario\n·Network\n·FailurePolicySet\n·TrafficMatrixSet\n·Workflow", shape=box];
scenario [label="Scenario\n·Network\n·FailurePolicySet\n·DemandSet\n·Workflow", shape=box];
}

subgraph cluster_exec {
Expand Down
2 changes: 1 addition & 1 deletion docs/assets/diagrams/system_pipeline.dot.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions docs/examples/basic.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Basic Example

This example builds a tiny topology inline to show APIs. For real analysis, prefer running a provided scenario and generating metrics via the CLI.
A tiny topology defined inline, used here to walk through the analysis APIs. For real analysis, run a bundled scenario through the CLI and generate metrics from that.

See [Tutorial](../getting-started/tutorial.md) for CLI usage and bundled scenarios.

Expand All @@ -19,7 +19,7 @@ See [Tutorial](../getting-started/tutorial.md) for CLI usage and bundled scenari
They have the same metric of 1 but different capacities (1 and 2).
```

Let's create this network by using NetGraph's scenario system:
Build it with the scenario system:

```python
from ngraph.scenario import Scenario
Expand Down Expand Up @@ -77,7 +77,7 @@ scenario = Scenario.from_yaml(scenario_yaml)
network = scenario.network
```

Note that here we used a simple `nodes` and `links` structure to directly define the network topology. The optional `seed` parameter ensures reproducible results when using randomized workflow steps. In more complex scenarios, you would typically use node groups with `count` and `template` to define groups of nodes and link rules to define their connections, or even leverage the `blueprints` to create reusable components. This advanced functionality is explained in the [DSL Reference](../reference/dsl.md) and used in the [Clos Fabric Analysis](clos-fabric.md) example.
This spells out every node and link individually. The optional `seed` makes randomized workflow steps reproducible. Larger topologies instead use node groups (`count` plus `template`) with link rules connecting them, or `blueprints` for reusable components - see the [DSL Reference](../reference/dsl.md) and the [Clos Fabric Analysis](clos-fabric.md) example.

### Flow Analysis Variants

Expand Down
4 changes: 2 additions & 2 deletions docs/examples/bundled-scenarios.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Inspect first, then run:
# Inspect (structure, steps, demands, failure policies)
ngraph inspect scenarios/backbone_clos.yml --detail

# Run and write JSON results next to the scenario (or under --output)
# Run and write JSON results in the current directory (or under --output)
ngraph run scenarios/backbone_clos.yml --output out
```

Expand Down Expand Up @@ -76,4 +76,4 @@ ngraph run scenarios/nsfnet.yaml --keys node_to_node_capacity_matrix_1 --stdout

## Notes on results

All runs emit a consistent JSON shape with `workflow`, `steps`, and `scenario` sections. Steps like `MaxFlow` and `TrafficMatrixPlacement` store per-iteration lists under `data.flow_results` with `summary` and optional `cost_distribution` or `min_cut` fields. See Reference -> Workflow for the exact schema.
All runs emit a consistent JSON shape with `workflow`, `steps`, and `scenario` sections. Steps like `MaxFlow` and `TrafficMatrixPlacement` store a list under `data.flow_results` with one entry per unique failure pattern - patterns are deduplicated across iterations, so the list holds at most `iterations` entries and usually far fewer - alongside a single unfailed entry under `data.baseline`; with no `failure_policy`, `flow_results` is empty. Each entry carries a `summary` and per-flow `flows` entries whose `cost_distribution` is populated when `include_flow_details` is set (and `{}` otherwise), and with `include_min_cut` the min-cut edges appear under a flow entry's `data` (`edges` plus `edges_kind: "min_cut"`). See Reference -> Workflow for the exact schema.
16 changes: 6 additions & 10 deletions docs/examples/clos-fabric.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
# Clos Fabric Analysis

This example demonstrates analysis of a 3-tier Clos fabric. For production use, run the bundled scenario and generate metrics via CLI, then iterate in Python if needed.
Analysis of a 3-tier Clos fabric. For production use, run the bundled scenario and generate metrics via CLI, then iterate in Python if needed.

Refer to [Tutorial](../getting-started/tutorial.md) for running bundled scenarios via CLI.

## Scenario Overview

We'll create two separate 3-tier Clos networks and analyze the maximum flow capacity between them. This scenario showcases:

- Hierarchical blueprint composition
- Complex link patterns
- Flow analysis with different placement policies
Two separate 3-tier Clos networks, with maximum flow capacity measured between them. The scenario nests blueprints inside blueprints, wires the tiers with `mesh` and `one_to_one` link patterns, and compares flow placement policies.

## Programmatic scenario

Expand Down Expand Up @@ -112,14 +108,14 @@ NetGraph supports different flow placement policies:

Combined with the path selection settings (shortest_path=True|False), we can achieve different flow placement policies emulating ECMP, WCMP, and TE behavior in IP/MPLS networks.

In this example, we use the `FlowPlacement.EQUAL_BALANCED` policy and `shortest_path=True` to emulate ECMP behavior and we will compare it with WCMP `FlowPlacement.PROPORTIONAL` (capacity-weighted split across equal-cost paths) under two conditions:
The example above pairs `FlowPlacement.EQUAL_BALANCED` with `shortest_path=True` to emulate ECMP. Compare it against `FlowPlacement.PROPORTIONAL` (WCMP) under two conditions:

- Baseline: symmetric parallel inter-spine links -> ECMP = WCMP (256.0).
- Uneven links: make capacities within each equal-cost bundle different -> WCMP
- Uneven links: capacities differ within each equal-cost bundle -> WCMP
achieves higher throughput than ECMP, which is limited by equal splitting.

We emulate partial inter-spine degradation by making capacities uneven across the
4 parallel spine-to-spine links per pair while keeping equal costs. This isolates
Partial inter-spine degradation is emulated by making capacities uneven across the
4 parallel spine-to-spine links per pair while keeping costs equal, which isolates
the effect of the splitting policy.

```python
Expand Down
5 changes: 4 additions & 1 deletion docs/getting-started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,15 @@ pip install -e .
# Install NetGraph
cd ../NetGraph
pip install -e .

# Or, with development tooling (tests, linters, docs):
pip install -e '.[dev]'
```

## Platform Notes

**Pre-built wheels**: Available for Linux (x86_64, aarch64), macOS (x86_64, arm64), and Windows (x86_64).

**Building from source**: Requires CMake 3.15+. Builds automatically during `pip install` if no compatible wheel is available.
**Building from source**: Requires CMake 3.23+ and a C++20 compiler (per netgraph-core's build configuration). Builds automatically during `pip install` if no compatible wheel is available.

**Next**: See [Tutorial](tutorial.md) for running scenarios and programmatic usage examples.
4 changes: 2 additions & 2 deletions docs/getting-started/tutorial.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Tutorial

This guide shows the fastest way to run a scenario from the CLI and a minimal programmatic example. See the Examples section for detailed scenarios and policies.
The fastest way to run a scenario from the CLI, plus a minimal programmatic example. See the Examples section for fuller scenarios and for flow placement and failure policies.

## CLI: run and inspect

```bash
# Inspect (validate and preview structure, steps, demands)
ngraph inspect scenarios/square_mesh.yaml --detail

# Run and store results (JSON) next to the scenario or under --output
# Run and store results (JSON) in the current directory or under --output
ngraph run scenarios/square_mesh.yaml --output out

# Filter exported results by workflow step names
Expand Down
16 changes: 8 additions & 8 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@

[![Python-test](https://github.com/networmix/NetGraph/actions/workflows/python-test.yml/badge.svg?branch=main)](https://github.com/networmix/NetGraph/actions/workflows/python-test.yml)

Scenario-driven network modeling and analysis framework combining Python's flexibility with high-performance C++ algorithms.
Scenario-driven network modeling and analysis framework combining Python with C++ graph algorithms.

## Overview

NetGraph enables declarative modeling of network topologies, traffic matrices, and failure scenarios. It delegates computationally intensive graph algorithms to [NetGraph-Core](https://github.com/networmix/NetGraph-Core) while providing a rich Python API and CLI for orchestration.
Model network topologies, traffic matrices, and failure scenarios declaratively. Graph algorithms are delegated to [NetGraph-Core](https://github.com/networmix/NetGraph-Core); NetGraph itself provides the Python API and CLI that orchestrate them.

## Architecture

NetGraph employs a **hybrid Python+C++ architecture**:
NetGraph uses a hybrid Python+C++ architecture, split across two layers:

- **Python layer (NetGraph)**: Scenario DSL parsing, workflow orchestration, result aggregation, and high-level APIs.
- **C++ layer (NetGraph-Core)**: Performance-critical graph algorithms (SPF, KSP, Max-Flow) executing in optimized C++ with the GIL released.
- **C++ layer (NetGraph-Core)**: The compute-intensive graph algorithms (SPF, KSP, Max-Flow), executed in C++ with the GIL released.

## Key Features

Expand All @@ -31,15 +31,15 @@ NetGraph employs a **hybrid Python+C++ architecture**:

### Traffic Engineering

- **Routing Modes**: Unified modeling of **IP Routing** (static costs, oblivious to congestion) and **Traffic Engineering** (dynamic residuals, congestion-aware).
- **Flow Placement**: Strategies for **ECMP** (Equal-Cost Multi-Path) and **WCMP** (Weighted Cost Multi-Path).
- **Routing Modes**: Unified modeling of IP routing (static costs, oblivious to congestion) and traffic engineering (dynamic residuals, congestion-aware).
- **Flow Placement**: Strategies for ECMP (Equal-Cost Multi-Path) and WCMP (Weighted Cost Multi-Path).
- **Capacity Analysis**: Compute max-flow envelopes and demand allocation with configurable placement policies.

### Workflow & Integration

- **Structured Results**: Export analysis artifacts to JSON for downstream processing.
- **CLI**: Comprehensive command-line interface for validation and execution.
- **Python API**: Full programmatic access to all modeling and solving capabilities.
- **CLI**: Validate, inspect, and run scenarios from the command line.
- **Python API**: Programmatic access to the same modeling and solving entry points.

## Getting Started

Expand Down
Loading
Loading