qedclib Guide
qedclib is a quantum program execution engine with built-in performance monitoring. It provides backend abstraction, automatic metrics collection, batched execution, and multi-GPU support for quantum computing applications.
You can use qedclib independently of the QED-C benchmarks — it is available as a standalone package on PyPI:
pip install qedclib
Or install from the full repository (includes qedcbench benchmarks):
git clone https://github.com/SRI-International/QC-App-Oriented-Benchmarks.git
cd QC-App-Oriented-Benchmarks
pip install -e .
Initialization
Before using qedclib, initialize it with the quantum computing API you want to use. This loads the appropriate execution backend module.
import qedclib
# Initialize with the API (loads the execute module)
qedclib.initialize("qiskit")
# Access execute and metrics directly from qedclib
ex = qedclib.execute
ex.set_execution_target(backend_id="qasm_simulator")
# Metrics is always available
qedclib.metrics.verbose = True
After initialize() or get_kernel(), the execute module is available as qedclib.execute. Use ex = qedclib.execute for a shorter reference. The from qedclib import metrics shorthand also works: import qedclib.metrics as metrics.
Execution Paths
qedclib provides two execution paths depending on whether you want automatic metrics collection.
Path 1: Direct Execution
Use execute_circuits() for raw execution. You get back results directly and handle timing yourself.
from qiskit import QuantumCircuit
# Build circuits
circuits = []
for n in [3, 5, 8]:
qc = QuantumCircuit(n, n)
qc.h(0)
for i in range(n - 1):
qc.cx(i, i + 1)
qc.measure(range(n), range(n))
circuits.append(qc)
# Execute and get results
job_id, result = ex.execute_circuits(circuits, num_shots=1000)
# Process results
for i, counts in enumerate(result.get_counts()):
print(f"Circuit {i}: {counts}")
Path 2: Metrics-Integrated Execution
Use submit_circuits() for automatic metrics collection. Circuits are organized as a nested dict keyed by group (typically qubit width) and circuit ID. Timing, job IDs, and result processing are handled automatically.
from qedclib import metrics
# Build circuits as a nested dict {group: {circuit_id: qc}}
circuits = {}
for n_qubits in [4, 6, 8]:
group = str(n_qubits)
circuits[group] = {}
for cid in range(3):
qc = QuantumCircuit(n_qubits, n_qubits)
qc.h(0)
for i in range(n_qubits - 1):
qc.cx(i, i + 1)
qc.measure(range(n_qubits), range(n_qubits))
circuits[group][str(cid)] = qc
# Submit — auto-initializes metrics if needed
ex.submit_circuits(circuits, num_shots=1000)
# Finalize and retrieve metrics
metrics.end_metrics()
metrics.finalize_all_groups()
# Per-circuit metrics: {group: {circuit_id: {metric: value}}}
cm = metrics.get_circuit_metrics()
# Group-level averages with standard deviations
gm = metrics.get_group_metrics()
for i, group in enumerate(gm["groups"]):
print(f"Group {group}: avg_exec={gm['avg_exec_times'][i]:.4f}s "
f"+/- {gm['std_exec_times'][i]:.4f}s")
Result Handlers
A result handler is a callback that processes each circuit's results as they arrive. Use init_execution() to register one before calling submit_circuits().
def my_handler(qc, result, group, circuit_id, num_shots):
"""Called for each circuit after execution."""
counts = result.get_counts()
# Compute and store your own metrics (fidelity, expectation values, etc.)
fidelity = compute_fidelity(counts, expected)
metrics.store_metric(group, circuit_id, "fidelity", fidelity)
ex.init_execution(my_handler)
ex.submit_circuits(circuits, num_shots=1000)
Metrics Flow
The full metrics-integrated workflow:
qedclib.initialize("qiskit")
ex = qedclib.execute
ex.set_execution_target → ex.init_execution(handler)
→ ex.submit_circuits (one or more calls)
→ metrics.end_metrics()
→ metrics.finalize_all_groups()
→ metrics.save_app_metrics(benchmark_name, method=method)
→ metrics.get_group_metrics() / get_circuit_metrics()
→ metrics.plot_metrics("Title")
Note: save_app_metrics writes benchmark results to __data/DATA-{backend_id}.json. It is called explicitly in each benchmark's run_circuits() and is separate from plotting. The plot_metrics function is purely for visualization.
submit_circuits auto-calls metrics.init_metrics() if not yet initialized. You can call submit_circuits multiple times before finalizing — all results accumulate in the metrics module.
Backend Configuration
Local Simulators (Qiskit)
ex.set_execution_target(backend_id="qasm_simulator")
IBM Hardware
ex.set_execution_target(
backend_id="ibm_sherbrooke",
project="your-crn-or-instance",
exec_options={"use_ibm_quantum_platform": False}
)
IonQ
from qiskit_ionq import IonQProvider
provider = IonQProvider()
backend = provider.get_backend("ionq_simulator")
ex.set_execution_target(
backend_id="ionq_simulator",
provider_backend=backend
)
CUDA-Q (GPU Simulator)
qedclib.initialize("cudaq")
import execute as ex
ex.set_execution_target(backend_id="nvidia")
job_id, result = ex.execute_circuits(circuits, num_shots=1000)
API Reference
Top-Level Functions (qedclib)
| Function | Description |
|---|---|
initialize(api) |
Initialize qedclib: set API and load execution backend |
get_api() |
Get current quantum SDK name |
set_api(api) |
Set default quantum SDK (called automatically by initialize) |
get_kernel(name, api, benchmark) |
Load and return a benchmark kernel module |
is_leader() |
True if MPI rank 0 or MPI not active |
Execution Functions (execute as ex)
| Function | Description |
|---|---|
set_execution_target(backend_id, ...) |
Configure the backend for execution |
init_execution(handler) |
Register a result handler callback |
execute_circuits(circuits, num_shots) |
Execute a list of circuits, return (job_id, result) |
submit_circuits(circuits, num_shots, max_batch_size, batch_by_group) |
Execute a circuit dict with automatic metrics collection |
process_circuit_results(circuits_info, results, ...) |
Map batch results back to individual circuits and store metrics |
compute_all_circuit_metrics(circuits) |
Compute depth, gate count, and transpiled metrics for a circuit dict |
Metrics Functions (from qedclib import metrics)
| Function | Description |
|---|---|
init_metrics() |
Initialize/reset metrics tracking |
end_metrics() |
Record end time for the execution run |
store_metric(group, circuit, name, value) |
Store a custom metric value |
get_metric(group, circuit, name) |
Retrieve a stored metric value |
get_circuit_metrics() |
Return the full per-circuit metrics dict |
get_group_metrics() |
Return the aggregated group-level metrics dict |
finalize_all_groups() |
Aggregate per-circuit metrics into group averages |
aggregate_metrics() |
Compute group averages (called by finalize_all_groups) |
report_metrics() |
Print a summary of all group metrics |
save_app_metrics(name, method) |
Save metrics to __data/DATA-{backend_id}.json |
plot_metrics(title) |
Generate volumetric benchmarking plots (no side effects) |
Group Metrics Keys
After calling finalize_all_groups(), get_group_metrics() returns a dict with parallel arrays indexed by group. Key fields:
| Key | Description |
|---|---|
groups |
Group names (typically qubit widths) |
avg_elapsed_times / std_elapsed_times |
Wall-clock time per circuit (mean / std) |
avg_exec_times / std_exec_times |
Backend execution time per circuit (mean / std) |
avg_create_times / std_create_times |
Circuit creation time (mean / std) |
avg_depths |
Average algorithmic circuit depth |
avg_tr_depths / avg_tr_xis / avg_tr_n2qs |
Transpiled depth, xi, and 2-qubit gate counts |
avg_fidelities / std_fidelities |
Normalized fidelity (mean / std) |
avg_hf_fidelities / std_hf_fidelities |
Hellinger fidelity (mean / std) |
Examples
See the qedclib-examples repository for standalone usage examples.
Test scripts demonstrating various patterns are also included in qedclib/_tests/:
| Script | What it demonstrates |
|---|---|
01_basic_api.py |
Initialize, execute circuits, get counts |
02_parameter_sweep.py |
Parameterized circuits, batch execution |
03_backend_switching.py |
Configure different backends (simulator, IBM, IonQ, IQM) |
04_batch_scaling.py |
Batch size scaling, serial vs batch performance |
05_submit_with_metrics.py |
submit_circuits with automatic metrics collection |
© 2025 Quantum Economic Development Consortium (QED-C). All Rights Reserved.