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
| Class | Constructor | Purpose |
|---|---|---|
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
- Validating a .qnet File — catch errors before simulation
- Diffing Topology Versions — track changes between network designs