Tutorial 12 — Diffing Two Topology Versions
Objective: Use diff() to show what changed between a v1 and v2 network design, enabling version control for quantum network configurations.
Network topologies evolve over time — adding nodes, adjusting link parameters, removing unused infrastructure. The diff() function provides structured output you can use in CI/CD, changelogs, or team reviews.
Use the Repo's Existing v1/v2 Files
from qnet_core import diff
v1_path = "network_v1.qnet" # 2 nodes, 1 link
v2_path = "network_v2.qnet" # 3 nodes, 2 links — extended version
result = diff(v1_path, v2_path)
print(f"Summary: {result.get('summary', 'N/A')}\n")
if result.get("nodes_added"):
print("Nodes ADDED:")
for n in result["nodes_added"]:
print(f" + {n}")
if result.get("nodes_removed"):
print("Nodes REMOVED:")
for n in result["nodes_removed"]:
print(f" - {n}")
if result.get("nodes_modified"):
print("Nodes MODIFIED:")
for n in result["nodes_modified"]:
print(f" ~ {n}")
if result.get("links_added"):
print("\nLinks ADDED:")
for l in result["links_added"]:
print(f" + {l}")
if result.get("links_removed"):
print("\nLinks REMOVED:")
for l in result["links_removed"]:
print(f" - {l}")
if result.get("links_modified"):
print("\nLinks MODIFIED:")
for l in result["links_modified"]:
print(f" ~ {l}")
Create Two Custom Versions and Diff Them
from qnet_core import QNetFile, save_qnet_file_wrapper
# Version A — baseline
v_a = QNetFile(name="version_a")
v_a.add_node("X", memory_lifetime_ms=500.0)
v_a.add_node("Y", memory_lifetime_ms=1000.0)
v_a.add_link("l1", src="X", to="Y", distance_km=10.0, base_fidelity=0.95, generation_rate_hz=1_000.0)
# Version B — changes: modified X's T2, added node Z, modified l1 params, added link
v_b = QNetFile(name="version_b")
v_b.add_node("X", memory_lifetime_ms=800.0) # changed T2 from 500→800
v_b.add_node("Y", memory_lifetime_ms=1000.0) # unchanged
v_b.add_node("Z", memory_lifetime_ms=600.0) # NEW node
v_b.add_link("l1", src="X", to="Y", distance_km=20.0, base_fidelity=0.90, generation_rate_hz=800.0) # modified
v_b.add_link("l2", src="Y", to="Z", distance_km=15.0, base_fidelity=0.88, generation_rate_hz=700.0) # NEW link
save_qnet_file_wrapper(v_a, "examples/v_a.qnet")
save_qnet_file_wrapper(v_b, "examples/v_b.qnet")
diff_result = diff("examples/v_a.qnet", "examples/v_b.qnet")
print(f"Summary: {diff_result.get('summary', 'N/A')}")
for key in ("nodes_added", "nodes_removed", "nodes_modified",
"links_added", "links_removed", "links_modified"):
items = diff_result.get(key, [])
if items:
print(f" {key}: {items}")
Diff Return Format
The function returns a dict with these keys (all lists of strings):
| Key | Content |
|---|---|
summary | Human-readable one-line summary |
nodes_added | List of new node IDs |
nodes_removed | List of removed node IDs |
nodes_modified | List of modified node descriptions |
links_added | List of new link descriptions |
links_removed | List of removed link descriptions |
links_modified | List of modified link descriptions |
error | Present only if a file failed to load: {"error": "..."} |
Programmatic Diff with Snapshots
For comparing topologies in code (not on disk), use diff_topologies():
from qnet_core import diff_topologies, TopologySnapshot, TopologyMetadata, TopologyConfig
snap1 = TopologySnapshot(
metadata=TopologyMetadata(name="v1", version="1.0"),
nodes=[...], # list of NodeDefinition
links=[...], # list of LinkDefinition
config=TopologyConfig(alpha_loss=0.22, gamma_swapping=0.9),
)
snap2 = TopologySnapshot(...)
diff = diff_topologies(snap1, snap2)
print(diff.summary)
# Access: diff.nodes_added, diff.nodes_removed, diff.nodes_modified
# diff.links_added, diff.links_removed, diff.links_modified
What's next
- Comparing Candidate Topologies — numerical comparison with Monte Carlo simulation
- Tuning Physical Constants — parameter sensitivity analysis