Skip to main content

Tutorial 10 — Authoring a .qnet File from Scratch

Objective: Build a QNetFile programmatically, save it to disk, then reload it with from_qnet_file() into a fresh engine ready for simulation.

The .qnet JSON format allows you to version-control network topologies, share configurations between teams, and separate network design from simulation code.

Step 1: Build the Network Programmatically

from qnet_core import QNetFile, QNetNodeType

qf = QNetFile(name="my_custom_network")

# Add metadata for tracking
qf.metadata.description = "Custom 3-node repeater chain"
qf.metadata.author = "Alice"

# Add nodes with optional properties
qf.add_node("Alice", memory_lifetime_ms=1000.0, memory_capacity=4, node_type=QNetNodeType.Ground)
qf.add_node("R1", memory_lifetime_ms=800.0, memory_capacity=4, node_type=QNetNodeType.Repeater)
qf.add_node("Bob", memory_lifetime_ms=1000.0, memory_capacity=4, node_type=QNetNodeType.Ground)

# Add links — src parameter maps to the "from" field in JSON
qf.add_link(
"link_01", src="Alice", to="R1",
distance_km=15.0, base_fidelity=0.93, generation_rate_hz=800.0,
)
qf.add_link(
"link_02", src="R1", to="Bob",
distance_km=15.0, base_fidelity=0.90, generation_rate_hz=700.0,
)

print(f"Nodes: {len(qf.nodes)}") # → 3
print(f"Links: {len(qf.links)}") # → 2
print(f"Version: {qf.version}") # → "1.0"

Step 2: Save to Disk

from qnet_core import save_qnet_file_wrapper

save_qnet_file_wrapper(qf, "examples/network_demo.qnet")
print("Saved to examples/network_demo.qnet")

The saved file is pretty-printed JSON with version "1.0". You can inspect it directly:

{
"version": "1.0",
"metadata": { "name": "my_custom_network", "description": "Custom 3-node repeater chain", ... },
"nodes": [
{ "id": "Alice", "memory_lifetime_ms": 1000.0, "node_type": "Ground" },
{ "id": "R1", "memory_lifetime_ms": 800.0, "node_type": "Repeater" },
...
],
"links": [ ... ]
}

Step 3: Reload from Disk

from qnet_core import load_qnet_file

reloaded = load_qnet_file("examples/network_demo.qnet")
print(f"Name: {reloaded.metadata.name}") # → "my_custom_network"
print(f"Nodes ({len(reloaded.nodes)}): {[n.id for n in reloaded.nodes]}")
print(f"Links ({len(reloaded.links)}): {[f'{l.src}->{l.to}' for l in reloaded.links]}")

Step 4: One-Call Start with from_qnet_file()

from qnet_core import from_qnet_file

# Factory: loads the file AND initializes an engine — ready to simulate
engine = from_qnet_file("examples/network_demo.qnet")

stats = engine.simulate(
from_node="Alice",
to="Bob",
fidelity_target=0.85,
max_latency_ms=10_000.0,
runs=200,
seed=42,
)

print(f"Success rate: {stats.empirical_success_rate:.1%}")
print(f"Mean latency: {stats.mean_latency_ms:.1f} ms")
print(f"Mean fidelity: {stats.mean_fidelity:.4f}")

.qnet File Type Reference

ClassConstructorPurpose
QNetFile(name)(name: str)Top-level container for the JSON document
QNetNode(id, ...)(id, memory_lifetime_ms?, memory_capacity?, node_type?)Node entry in the file
QNetLink(id, src, to, ...)(id, src, to, distance_km, base_fidelity, generation_rate_hz, link_type?, satellite?)Link entry
QNetConfig(...)(alpha_loss?, beta_fidelity_decay?, gamma_swapping?, max_attempts?)Physics parameters
QNetConstraints(...)(fidelity_target?, max_latency_ms?)Simulation constraints
QNetMetadata(name, ...)(name, description?, author?, created_at?)File metadata

What's next