Skip to main content

Tutorial 11 — Validating a .qnet File

Objective: Intentionally introduce errors in a QNetFile to see how validate() catches them before simulation, preventing wasted compute time.

The validate() function is designed to never raise exceptions — it returns a structured dict describing all errors and warnings found in the file. This makes it safe to use on untrusted input.

Validate a Well-Formed File

from qnet_core import validate, QNetFile, save_qnet_file_wrapper

# Create a valid file first
qf_valid = QNetFile(name="valid_network")
qf_valid.add_node("A", memory_lifetime_ms=1000.0)
qf_valid.add_node("B", memory_lifetime_ms=1000.0)
qf_valid.add_link("link_1", src="A", to="B", distance_km=10.0,
base_fidelity=0.95, generation_rate_hz=1000.0)

valid_path = "examples/valid_network.qnet"
save_qnet_file_wrapper(qf_valid, valid_path)

print("=== Validating a well-formed file ===")
result = validate(valid_path)
print(f"Valid: {result['valid']}")
if result.get("warnings"):
print(f"Warnings ({len(result['warnings'])}):")
for w in result["warnings"]:
print(f" - [{w['type']}] {w['message']}")

Validate with a Self-Loop Error

# Self-loop: both src and to reference the same node
self_loop = QNetFile(name="self_loop_test")
self_loop.add_node("NodeX", memory_lifetime_ms=1000.0)
self_loop.add_link("bad_link", src="NodeX", to="NodeX", distance_km=10.0,
base_fidelity=0.95, generation_rate_hz=1000.0)

save_qnet_file_wrapper(self_loop, "examples/self_loop.qnet")

print("\n=== Validating with self-loop error ===")
result = validate("examples/self_loop.qnet")
print(f"Valid: {result['valid']}") # → False
for err in result.get("errors", []):
print(f" Error [{err['type']}]: {err['message']}")

Validate the Built-in Invalid File

The repo includes invalid_network.qnet with known structural issues:

print("\n=== Validating the repo's invalid_network.qnet ===")
result = validate("invalid_network.qnet")
print(f"Valid: {result['valid']}")
for err in result.get("errors", []):
print(f" [{err['type']}] {err['message']}")

Error Types Detected by validate()

Error TypeDescription
DuplicateNodeIdTwo nodes share the same ID
UnknownNodeReferenceA link references a node that doesn't exist
SelfLoopA link has the same source and destination node
InvalidDistanceDistance is non-positive or unreasonably large
InvalidFidelityFidelity is outside [0, 1] range
InvalidGenerationRateGeneration rate is non-positive
GraphDisconnectedThe network graph has unreachable components

Validate Return Format

result = validate("network.qnet")

# Always check this first:
if not result["valid"]:
for err in result["errors"]:
print(f" ERROR [{err['type']}]: {err['message']}")

# Warnings don't block simulation but flag issues:
for warn in result.get("warnings", []):
print(f" WARN: {warn['message']}")

# The validated file can be loaded normally (errors are informational, not blocking):
if result["valid"]:
engine = from_qnet_file(result["filepath"])

Key Design Principle

validate() never raises — it always returns a dict. This makes it safe to use in CI/CD pipelines, before simulation jobs, and on user-provided input. Always call validate() before attempting resource-intensive simulations on untrusted .qnet files.

What's next