qnetbench.characterize¶
Demand-signature extraction: the single-trace axes, the swept fidelity and staleness curves, the cross-application table, and run provenance.
Narrative guide: Characterization.
Signature and report¶
qnetbench.characterize.report
¶
Per-application demand-signature report: the single-trace signature plus the summarised fidelity/staleness curves, and a cross-application table. This is the machine-readable form of the characterization (Deliverable 2).
AppSignature
¶
Bases: BaseModel
The full demand signature for one application.
staleness_halflife_range
class-attribute
instance-attribute
¶
fidelity_threshold_std
class-attribute
instance-attribute
¶
staleness_halflife_std
class-attribute
instance-attribute
¶
fidelity_threshold_bracket
class-attribute
instance-attribute
¶
staleness_halflife_bracket
class-attribute
instance-attribute
¶
fidelity_threshold_seed_median
class-attribute
instance-attribute
¶
staleness_halflife_seed_median
class-attribute
instance-attribute
¶
fidelity_threshold_seed_count
class-attribute
instance-attribute
¶
staleness_halflife_seed_count
class-attribute
instance-attribute
¶
characterize_app
¶
characterize_app(
app: str,
*,
coherence_time: float = 0.001,
seeds: Sequence[int] = range(SEEDS),
) -> tuple[AppSignature, CharacterizationCurves]
Characterize one application: returns its signature and the raw curves.
Source code in qnetbench/characterize/report.py
render_table
¶
render_table(signatures: list[AppSignature]) -> str
A compact cross-application demand-signature table.
Source code in qnetbench/characterize/report.py
render_latex
¶
render_latex(signatures: list[AppSignature]) -> str
The same table as a booktabs tabular, for \input{} into a paper.
Emits the tabular only — no table environment, caption or label — so the surrounding float stays in the manuscript and only the numbers are generated. Requires booktabs and a \code macro, both of which the manuscript defines.
Source code in qnetbench/characterize/report.py
Single-trace axes¶
qnetbench.characterize.signature
¶
Single-trace demand-signature extraction.
The dimensions here are read directly from one run's trace (no parameter sweep):
burstiness of entanglement requests, classical-communication coupling,
deadline-criticality, staleness-intolerance, and multipartiteness. The
fidelity/staleness curves (which need sweeps) live in curves.py.
TraceSignature
¶
Bases: BaseModel
Demand-signature dimensions measurable from a single trace.
min_staleness_tolerance
class-attribute
instance-attribute
¶
characterize_trace
¶
characterize_trace(events: list[Event]) -> TraceSignature
Source code in qnetbench/characterize/signature.py
Swept curves¶
qnetbench.characterize.curves
¶
Parametric demand-signature curves.
These need parameter sweeps rather than a single trace: the fidelity-sensitivity curve (utility vs delivered fidelity) and the staleness-tolerance curve (utility vs age of a pre-generated pair — directly feeding Issue #5). Both run on the reference backend, which is deterministic and fast, and both are regenerable from source so the characterization figures never drift from the code.
Curve
dataclass
¶
Curve(
x: list[float],
y: list[float],
xlabel: str,
ylabel: str = "utility",
y_std: list[float] = list(),
seed_utils: list[list[float]] = list(),
)
seed_utils
class-attribute
instance-attribute
¶
insert
¶
Insert one evaluated sweep point, keeping the curve sorted in x. Used by the bisection refinement, which adds points only where a crossing lies.
Source code in qnetbench/characterize/curves.py
as_rows
¶
CharacterizationCurves
dataclass
¶
CharacterizationCurves(
app: str,
fidelity: Curve,
staleness: Curve,
fidelity_threshold: float | None = None,
staleness_halflife: float | None = None,
fidelity_threshold_std: float | None = None,
staleness_halflife_std: float | None = None,
fidelity_threshold_seed_median: float | None = None,
staleness_halflife_seed_median: float | None = None,
fidelity_threshold_seed_count: int = 0,
staleness_halflife_seed_count: int = 0,
n_seeds: int = 0,
fidelity_range: float | None = None,
staleness_halflife_range: float | None = None,
fidelity_threshold_bracket: float | None = None,
staleness_halflife_bracket: float | None = None,
)
fidelity_threshold
class-attribute
instance-attribute
¶
staleness_halflife
class-attribute
instance-attribute
¶
fidelity_threshold_std
class-attribute
instance-attribute
¶
staleness_halflife_std
class-attribute
instance-attribute
¶
fidelity_threshold_seed_median
class-attribute
instance-attribute
¶
staleness_halflife_seed_median
class-attribute
instance-attribute
¶
fidelity_threshold_seed_count
class-attribute
instance-attribute
¶
staleness_halflife_seed_count
class-attribute
instance-attribute
¶
fidelity_range
class-attribute
instance-attribute
¶
staleness_halflife_range
class-attribute
instance-attribute
¶
fidelity_threshold_bracket
class-attribute
instance-attribute
¶
staleness_halflife_bracket
class-attribute
instance-attribute
¶
CrossingStats
dataclass
¶
CrossingStats(
median: float | None = None,
std: float | None = None,
n_crossing: int = 0,
n_seeds: int = 0,
)
Where the individual seeds cross, as distinct from where the mean curve does.
The two can disagree, and the disagreement is informative. A curve that
plateaus just above the level never crosses in the mean while a minority of
seeds dip below it; reporting only the mean crossing then yields a spread with
no location to be a spread of. median carries the location the crossing seeds
agree on and n_crossing says how many of them resolved one at all, so a
missing aggregate crossing can be reported as what it is — a curve that mostly
plateaus — rather than as a bare dash.
fidelity_curve
¶
fidelity_curve(
app: str,
fidelities: Sequence[float],
seeds: Sequence[int] = range(SEEDS),
) -> Curve
Source code in qnetbench/characterize/curves.py
staleness_curve
¶
staleness_curve(
app: str,
ages: Sequence[float],
coherence_time: float,
base_fidelity: float = 1.0,
seeds: Sequence[int] = range(SEEDS),
) -> Curve
Source code in qnetbench/characterize/curves.py
characterize_curves
¶
characterize_curves(
app: str,
*,
coherence_time: float = 0.001,
seeds: Sequence[int] = range(SEEDS),
) -> CharacterizationCurves
Source code in qnetbench/characterize/curves.py
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 | |
Provenance¶
qnetbench.characterize.provenance
¶
Run provenance for generated characterization data.
A characterization run writes one JSON file per application, incrementally, over several minutes. If it dies half way the directory still looks finished: the files present are individually valid, they are simply from two different runs, and nothing in them says so. A later consumer — a plotting script, a paper table — then silently mixes them.
That is not hypothetical. It is how this project's own Table III came to hold numbers from two runs at once, and the only reason it was caught is that somebody re-derived the numbers by hand. So every per-app file records the id of the run that wrote it, the directory carries a manifest describing that run, and the consumers refuse to build from a directory where the two disagree.
The manifest is written twice: once at the start with complete=False, and once
at the end with complete=True. An interrupted run therefore leaves a directory
that positively declares itself unfinished, rather than one that is merely missing
something nobody thought to check.
RunConsistencyError
¶
Bases: RuntimeError
A data directory does not hold exactly one complete characterization run.
RunManifest
¶
Bases: BaseModel
What produced the data in one output directory.
new_run_id
¶
git_state
¶
(commit, dirty). Both None outside a git checkout — the data is still usable, it just cannot be tied back to a revision.
Source code in qnetbench/characterize/provenance.py
start_run
¶
start_run(
out_dir: Path, apps: list[str], seeds: int
) -> RunManifest
Stamp a directory as belonging to a new, not-yet-finished run.
Source code in qnetbench/characterize/provenance.py
finish_run
¶
finish_run(out_dir: Path, manifest: RunManifest) -> None
write_manifest
¶
write_manifest(
out_dir: Path, manifest: RunManifest
) -> None
write_atomic
¶
Write via a temporary file in the same directory, then rename.
A plain > redirect truncates its target the moment the shell opens it, so a
run that dies before printing leaves an empty file where a reader expects a
table. Renaming into place means the file is either the previous contents or
the new ones, never a half-written state.
Source code in qnetbench/characterize/provenance.py
load_manifest
¶
load_manifest(out_dir: Path) -> RunManifest
Source code in qnetbench/characterize/provenance.py
app_files
¶
The per-app signature files in a directory, manifest excluded.
verify_run
¶
verify_run(out_dir: Path) -> RunManifest
Check that a directory holds exactly one complete run, and return its manifest.
Raises RunConsistencyError describing the specific failure, because the useful thing to tell somebody whose figure is about to be wrong is which files came from where.