最佳实践¶
11 个发布前可重跑的完整场景:从配置/缓存、构造电路、编译、API/CLI 提交、变分线路、
Torch 集成,到 calibration + QEM、XEB workflow。每一个都对应
examples/3_best_practices/<n>_*.py,并由 scripts/build_docs.py 在文档构建时
按 [doc-require:] 门控自动重跑。
覆盖矩阵¶
案例 |
配置 |
后端缓存 |
裸 Circuit |
Named |
虚拟/本地后端 |
API 提交 |
CLI 提交 |
可视化 |
变分 |
Torch |
Calibration/QEM |
|---|---|---|---|---|---|---|---|---|---|---|---|
00 配置与后端缓存 |
✓ |
✓ |
✓ |
||||||||
01 裸线路模拟 |
✓ |
✓ |
✓ |
||||||||
02 Named Circuit |
✓ |
✓ |
✓ |
✓ |
|||||||
03 编译与虚拟后端 |
✓ |
✓ |
|||||||||
04 API 提交 |
✓ |
✓ |
✓ |
✓ |
|||||||
05 CLI 提交 |
✓ |
✓ |
✓ |
||||||||
06 云后端模板 |
✓ |
✓ |
✓ |
✓ |
✓ |
||||||
07 变分线路 |
✓ |
✓ |
✓ |
✓ |
|||||||
08 Torch 集成 |
✓ |
✓ |
✓ |
✓ |
✓ |
||||||
09 Calibration + QEM |
✓ |
✓ |
✓ |
||||||||
10 XEB workflow |
✓ |
✓ |
✓ |
✓ |
案例¶
00 — 配置 Key 与后端缓存¶
Source: examples/3_best_practices/00_config_and_backend_cache.py
Status: pass
最早的用户路径:创建配置、写入平台 token(脱敏)、校验配置结构,并用本地构造的
BackendInfo 演示后端缓存的写入、读取和审查。真实 token 不会写入文档输出。
Source code
"""00 — 配置 Key 与后端缓存
[doc-require: ]
[doc-output-include: stdout, source]
最早的用户路径:创建配置、写入平台 token(脱敏)、校验配置结构,并用本地构造的
``BackendInfo`` 演示后端缓存的写入、读取和审查。真实 token 不会写入文档输出。
"""
from __future__ import annotations
import tempfile
from pathlib import Path
from uniqc import BackendInfo, Platform, QubitTopology, audit_backends
from uniqc.backend_adapter.backend_cache import (
cache_info,
get_cached_backends,
update_cache,
)
from uniqc.backend_adapter.config import load_config, save_config, validate_config
def main() -> None:
workdir = Path(tempfile.mkdtemp(prefix="uniqc-bp-config-"))
config_path = workdir / "config.yaml"
config = {
"active_profile": "release-check",
"release-check": {
"originq": {"token": "originq-token-redacted"},
"quafu": {"token": "quafu-token-redacted"},
"ibm": {"token": "ibm-token-redacted", "proxy": {"http": "", "https": ""}},
},
}
save_config(config, config_path=config_path)
loaded = load_config(config_path=config_path)
errors = validate_config(config_path=config_path)
print("profile:", loaded["active_profile"])
print("validation errors:", errors)
backend = BackendInfo(
platform=Platform.DUMMY,
name="virtual-line-3",
description="release-check virtual backend",
num_qubits=3,
topology=(QubitTopology(0, 1), QubitTopology(1, 2)),
status="available",
is_simulator=True,
)
update_cache(Platform.DUMMY, [backend], cache_dir=workdir)
cached = get_cached_backends(Platform.DUMMY, cache_dir=workdir)
print("cached backend ids:", [b.full_id() for b in cached])
print("cache platforms:", sorted(cache_info(cache_dir=workdir)))
print("audit issues:", audit_backends(cached))
if __name__ == "__main__":
main()
Stdout
profile: release-check
validation errors: []
cached backend ids: ['dummy:virtual-line-3']
cache platforms: ['dummy']
audit issues: []
01 — 裸 Circuit、本地模拟与结果可视化¶
Source: examples/3_best_practices/01_bare_circuit_simulation.py
Status: pass
从空 Circuit 构造 Bell 态,导出 OriginIR / OpenQASM 2.0,使用本地模拟器得到
概率分布并画图。
Source code
"""01 — 裸 Circuit、本地模拟与结果可视化
[doc-require: matplotlib]
[doc-output-include: stdout, figures, source]
从空 ``Circuit`` 构造 Bell 态,导出 OriginIR / OpenQASM 2.0,使用本地模拟器得到
概率分布并画图。
"""
from __future__ import annotations
import math
import matplotlib.pyplot as plt
from uniqc import Circuit
from uniqc.simulator import Simulator
def probability_dict(values):
if isinstance(values, dict):
total = sum(values.values()) or 1
return {
format(int(k), "b") if isinstance(k, int) else str(k): v / total
for k, v in values.items()
}
n = int(math.log2(len(values))) if values else 0
return {
format(i, f"0{n}b"): float(p)
for i, p in enumerate(values)
if abs(float(p)) > 1e-12
}
def plot_probs(probs, title):
labels = list(probs)
values = [probs[k] for k in labels]
fig, ax = plt.subplots(figsize=(6, 3.4))
ax.bar(labels, values, color="#3267a8")
ax.set_ylim(0, max(1.0, max(values, default=0) * 1.2))
ax.set_xlabel("bitstring")
ax.set_ylabel("probability")
ax.set_title(title)
ax.grid(axis="y", alpha=0.25)
fig.tight_layout()
def main() -> None:
circuit = Circuit()
circuit.h(0)
circuit.cnot(0, 1)
circuit.measure(0, 1)
print("OriginIR:")
print(circuit.originir)
print("QASM header:")
print("\n".join(circuit.qasm.splitlines()[:6]))
sim = Simulator()
probs = probability_dict(sim.simulate_pmeasure(circuit.originir))
print("probabilities:", probs)
plot_probs(probs, "Bell state probabilities")
if __name__ == "__main__":
main()
Stdout
OriginIR:
QINIT 2
CREG 2
H q[0]
CNOT q[0], q[1]
MEASURE q[0], c[0]
MEASURE q[1], c[1]
QASM header:
OPENQASM 2.0;
include "qelib1.inc";
qreg q[2];
creg c[2];
h q[0];
cx q[0], q[1];
probabilities: {'00': 0.4999999999999999, '11': 0.4999999999999999}
Figures
02 — Named Circuit 与可复用线路¶
Source: examples/3_best_practices/02_named_circuit_and_reuse.py
Status: pass
用命名寄存器和 @circuit_def 组织可复用子线路,再组合成一个 4-qubit GHZ-like 电路。
Source code
"""02 — Named Circuit 与可复用线路
[doc-require: matplotlib]
[doc-output-include: stdout, figures, source]
用命名寄存器和 ``@circuit_def`` 组织可复用子线路,再组合成一个 4-qubit GHZ-like 电路。
"""
from __future__ import annotations
import math
import matplotlib.pyplot as plt
from uniqc import Circuit, circuit_def
from uniqc.simulator import Simulator
def probability_dict(values):
n = int(round(math.log2(len(values)))) if values else 0
return {
format(i, f"0{n}b"): float(p)
for i, p in enumerate(values)
if abs(float(p)) > 1e-12
}
def plot_probs(probs, title):
labels = list(probs)
values = [probs[k] for k in labels]
fig, ax = plt.subplots(figsize=(6, 3.4))
ax.bar(labels, values, color="#3267a8")
ax.set_ylim(0, max(1.0, max(values, default=0) * 1.2))
ax.set_xlabel("bitstring")
ax.set_ylabel("probability")
ax.set_title(title)
ax.grid(axis="y", alpha=0.25)
fig.tight_layout()
@circuit_def(name="bell_pair", qregs={"q": 2})
def bell_pair(circ, q):
circ.h(q[0])
circ.cnot(q[0], q[1])
return circ
@circuit_def(name="rz_layer", qregs={"q": 4}, params=["angle"])
def rz_layer(circ, q, angle):
for i in range(4):
circ.rz(q[i], angle)
return circ
def main() -> None:
circuit = Circuit(qregs={"data": 4})
data = circuit.get_qreg("data")
bell_pair(circuit, qreg_mapping={"q": [data[0], data[1]]})
bell_pair(circuit, qreg_mapping={"q": [data[2], data[3]]})
circuit.cnot(data[1], data[2])
rz_layer(
circuit,
qreg_mapping={"q": [data[0], data[1], data[2], data[3]]},
param_values={"angle": 0.25},
)
circuit.measure(0, 1, 2, 3)
print("DEF export:")
print(bell_pair.to_originir_def())
print("operations:", len(circuit.opcode_list))
probs = probability_dict(Simulator().simulate_pmeasure(circuit.originir))
print("non-zero states:", probs)
plot_probs(probs, "Named circuit result")
if __name__ == "__main__":
main()
Stdout
DEF export:
DEF bell_pair(q[0], q[1])
H q[0]
CNOT q[0], q[1]
ENDDEF
operations: 9
non-zero states: {'0000': 0.24999999999999978, '0111': 0.2499999999999998, '1011': 0.24999999999999986, '1100': 0.24999999999999983}
Figures
03 — 编译、拓扑与虚拟后端¶
Source: examples/3_best_practices/03_compile_region_dummy_backend.py
Status: pass
构造一个虚拟线性拓扑后端,把不满足相邻拓扑的线路编译到目标基门集合,并检查编译产物。
Source code
"""03 — 编译、拓扑与虚拟后端
[doc-require: ]
[doc-output-include: stdout, source]
构造一个虚拟线性拓扑后端,把不满足相邻拓扑的线路编译到目标基门集合,并检查编译产物。
"""
from __future__ import annotations
from uniqc import BackendInfo, Circuit, Platform, QubitTopology, compile
def main() -> None:
circuit = Circuit()
circuit.h(0)
circuit.cnot(0, 2)
backend = BackendInfo(
platform=Platform.DUMMY,
name="virtual-line-3",
num_qubits=3,
topology=(QubitTopology(0, 1), QubitTopology(1, 2)),
status="available",
is_simulator=True,
)
compiled_originir = compile(circuit, backend_info=backend, output_format="originir")
compiled_qasm = compile(circuit, backend_info=backend, output_format="qasm")
print("backend:", backend.full_id())
print("compiled OriginIR:")
print(compiled_originir)
print("compiled QASM first lines:")
print("\n".join(compiled_qasm.splitlines()[:8]))
if __name__ == "__main__":
main()
Stdout
backend: dummy:virtual-line-3
compiled OriginIR:
QINIT 3
CREG 0
RZ q[0], (1.5707963267948966)
SX q[0]
RZ q[0], (1.5707963267948966)
RZ q[1], (1.5707963267948966)
SX q[1]
RZ q[1], (3.141592653589793)
CZ q[0], q[1]
SX q[1]
RZ q[1], (1.5707963267948966)
compiled QASM first lines:
OPENQASM 2.0;
include "qelib1.inc";
qreg q[3];
creg c[0];
rz(pi/2) q[0];
sx q[0];
rz(pi/2) q[0];
rz(pi/2) q[1];
04 — Python API 提交、取回与可视化¶
Source: examples/3_best_practices/04_api_submit_dummy_result.py
Status: pass
使用 submit_task(backend="dummy:local:simulator") 验证远端任务接口的本地替代
路径:提交、等待、查询缓存、画图。
backend="dummy:local:simulator"表示无约束、无噪声;需要虚拟拓扑时使用
dummy:local:virtual-line-N/dummy:local:virtual-grid-RxC;需要真实芯片噪声时使用
dummy:<platform>:<backend>。
Source code
"""04 — Python API 提交、取回与可视化
[doc-require: matplotlib]
[doc-output-include: stdout, figures, source]
使用 ``submit_task(backend="dummy:local:simulator")`` 验证远端任务接口的本地替代
路径:提交、等待、查询缓存、画图。
* ``backend="dummy:local:simulator"`` 表示无约束、无噪声;
* 需要虚拟拓扑时使用 ``dummy:local:virtual-line-N`` / ``dummy:local:virtual-grid-RxC``;
* 需要真实芯片噪声时使用 ``dummy:<platform>:<backend>``。
"""
from __future__ import annotations
import matplotlib.pyplot as plt
from uniqc import Circuit, get_task, submit_task, wait_for_result
def plot_probs(probs, title):
labels = list(probs)
values = [probs[k] for k in labels]
fig, ax = plt.subplots(figsize=(6, 3.4))
ax.bar(labels, values, color="#3267a8")
ax.set_ylim(0, max(1.0, max(values, default=0) * 1.2))
ax.set_xlabel("bitstring")
ax.set_ylabel("probability")
ax.set_title(title)
ax.grid(axis="y", alpha=0.25)
fig.tight_layout()
def main() -> None:
circuit = Circuit()
circuit.h(0)
circuit.cnot(0, 1)
circuit.measure(0, 1)
task_id = submit_task(
circuit,
backend="dummy:local:simulator",
shots=128,
metadata={"example": "best-practices-api"},
)
counts = wait_for_result(task_id)
task = get_task(task_id)
print("task_id:", task_id)
print("status:", task.status)
print("counts:", counts)
probs = {k: v / sum(counts.values()) for k, v in counts.items()}
plot_probs(probs, "API dummy submission result")
if __name__ == "__main__":
main()
Stdout
task_id: uqt_eae7e360b52a40f28686206ebb385441
status: success
counts: UnifiedResult(counts={'00': 64, '11': 64}, probabilities={'00': 0.5, '11': 0.5}, shots=128, platform='dummy', task_id='uqt_eae7e360b52a40f28686206ebb385441', backend_name='dummy:local:simulator', execution_time=None, error_message=None)
Figures
05 — CLI 提交完整链路¶
Source: examples/3_best_practices/05_cli_workflow_dummy.py
Status: pass
通过 subprocess.run 执行 CLI:写出 OriginIR 文件,uniqc submit --backend dummy --wait,
并展示返回结果。
--backend dummy(默认)对应无约束、无噪声的dummy:local:simulator;可通过
--backend dummy:local:virtual-line-3指定虚拟拓扑;也可通过
--backend dummy:originq:WK_C180走真实 backend compile/transpile + 本地含噪执行。
Source code
"""05 — CLI 提交完整链路
[doc-require: ]
[doc-output-include: stdout, source]
通过 ``subprocess.run`` 执行 CLI:写出 OriginIR 文件,``uniqc submit --backend dummy --wait``,
并展示返回结果。
* ``--backend dummy``(默认)对应无约束、无噪声的 ``dummy:local:simulator``;
* 可通过 ``--backend dummy:local:virtual-line-3`` 指定虚拟拓扑;
* 也可通过 ``--backend dummy:originq:WK_C180`` 走真实 backend compile/transpile + 本地含噪执行。
"""
from __future__ import annotations
import pathlib
import subprocess
import sys
import tempfile
PROJECT_ROOT = pathlib.Path(__file__).resolve().parents[2]
def main() -> None:
workdir = pathlib.Path(tempfile.mkdtemp(prefix="uniqc-bp-cli-"))
circuit_file = workdir / "bell.originir"
circuit_file.write_text(
"QINIT 2\nCREG 2\nH q[0]\nCNOT q[0], q[1]\n"
"MEASURE q[0], c[0]\nMEASURE q[1], c[1]\n",
encoding="utf-8",
)
cmd = [
sys.executable,
"-m",
"uniqc.cli",
"submit",
str(circuit_file),
"--backend",
"dummy",
"-s",
"64",
"--wait",
"--format",
"json",
]
completed = subprocess.run(
cmd,
cwd=PROJECT_ROOT,
text=True,
capture_output=True,
check=True,
)
print("command:", " ".join(cmd))
print(completed.stdout)
if __name__ == "__main__":
main()
Stdout
command: /home/agony/projects/uniqc-dev/UnifiedQuantum/.venv/bin/python3 -m uniqc.cli submit /tmp/uniqc-bp-cli-_x2r5t8y/bell.originir --backend dummy -s 64 --wait --format json
{
"task_id": "uqt_ed3f17897c5f44c88fd8696722ae7d50",
"backend": "dummy:local:simulator",
"shots": 64
}
{
"counts": {
"00": 32,
"11": 32
},
"probabilities": {
"00": 0.5,
"11": 0.5
},
"shots": 64,
"platform": "dummy",
"task_id": "uqt_ed3f17897c5f44c88fd8696722ae7d50",
"backend_name": "dummy:local:simulator",
"execution_time": null,
"error_message": null
}
06 — 云后端提交模板与 dry-run¶
Source: examples/3_best_practices/06_cloud_backend_template.py
Status: pass
展示真实后端路径的安全模板:先 dry_run_task,再提交。该例子默认仅执行 dummy
dry-run;真实 OriginQ / Quafu / IBM 提交单元应在维护者确认 token、账号额度和后端
Source code
"""06 — 云后端提交模板与 dry-run
[doc-require: ]
[doc-output-include: stdout, source]
展示真实后端路径的安全模板:先 ``dry_run_task``,再提交。该例子默认仅执行 dummy
dry-run;真实 OriginQ / Quafu / IBM 提交单元应在维护者确认 token、账号额度和后端
可用后再打开(参考 ``[doc-require: originq]`` 等门控)。
"""
from __future__ import annotations
from uniqc import Circuit, dry_run_task
def main() -> None:
circuit = Circuit()
circuit.h(0)
circuit.measure(0)
result = dry_run_task(circuit, backend="dummy:local:simulator", shots=100)
print("dummy dry-run success:", result.success)
print("details:", result.details)
cloud_templates = {
"originq API": "submit_task(circuit, backend='originq:PQPUMESH8', shots=1000)",
"quafu API": "submit_task(circuit, backend='quafu:ScQ-P18', shots=1000)",
"ibm API": "submit_task(circuit, backend='ibm:ibm_fez', shots=1000)",
"CLI dry-run": "uniqc submit bell.originir --backend quafu:ScQ-P18 --dry-run",
}
for name, snippet in cloud_templates.items():
print(f"{name}: {snippet}")
if __name__ == "__main__":
main()
Stdout
dummy dry-run success: True
details: Dry-run passed for dummy simulator: OriginIR is valid. Qubits=1, shots=100
originq API: submit_task(circuit, backend='originq:PQPUMESH8', shots=1000)
quafu API: submit_task(circuit, backend='quafu:ScQ-P18', shots=1000)
ibm API: submit_task(circuit, backend='ibm:ibm_fez', shots=1000)
CLI dry-run: uniqc submit bell.originir --backend quafu:ScQ-P18 --dry-run
07 — 简单变分量子线路¶
Source: examples/3_best_practices/07_variational_circuit.py
Status: pass
用一个单参数 ansatz 最小化 <Z>。该例子故意不用外部优化库,便于确认线路、模拟和
可视化路径。
Source code
"""07 — 简单变分量子线路
[doc-require: matplotlib]
[doc-output-include: stdout, figures, source]
用一个单参数 ansatz 最小化 ``<Z>``。该例子故意不用外部优化库,便于确认线路、模拟和
可视化路径。
"""
from __future__ import annotations
import math
import matplotlib.pyplot as plt
from uniqc import Circuit
from uniqc.simulator import Simulator
def build_ansatz(theta):
c = Circuit()
c.ry(0, float(theta))
c.measure(0)
return c
def z_expectation(theta):
counts = Simulator().simulate_shots(build_ansatz(theta).originir, shots=400)
total = sum(counts.values()) or 1
p0 = counts.get(0, 0) / total
p1 = counts.get(1, 0) / total
return p0 - p1
def main() -> None:
theta = 0.2
history = []
for step in range(18):
value = z_expectation(theta)
plus = z_expectation(theta + math.pi / 2)
minus = z_expectation(theta - math.pi / 2)
grad = 0.5 * (plus - minus)
history.append((step, theta, value, grad))
theta -= 0.25 * grad
for row in history[::4]:
print("step=%02d theta=%.3f <Z>=%.3f grad=%.3f" % row)
print("final theta:", round(theta, 4))
fig, ax = plt.subplots(figsize=(6, 3.4))
ax.plot([r[0] for r in history], [r[2] for r in history], marker="o")
ax.set_xlabel("step")
ax.set_ylabel("<Z>")
ax.set_title("Variational circuit optimization")
ax.grid(alpha=0.25)
fig.tight_layout()
if __name__ == "__main__":
main()
Stdout
step=00 theta=0.200 <Z>=0.990 grad=-0.240
step=04 theta=0.496 <Z>=0.850 grad=-0.495
step=08 theta=1.130 <Z>=0.385 grad=-0.912
step=12 theta=2.098 <Z>=-0.505 grad=-0.872
step=16 theta=2.748 <Z>=-0.925 grad=-0.463
final theta: 2.9356
Figures
08 — Torch 集成后的量子线路¶
Source: examples/3_best_practices/08_torch_quantum_training.py
Status: pass
用 PyTorch 管理参数和优化器,量子期望值由 UnifiedQuantum 线路和模拟器计算,梯度 使用 parameter-shift 写回。
Source code
"""08 — Torch 集成后的量子线路
[doc-require: pytorch, matplotlib]
[doc-output-include: stdout, figures, source]
用 PyTorch 管理参数和优化器,量子期望值由 UnifiedQuantum 线路和模拟器计算,梯度
使用 parameter-shift 写回。
"""
from __future__ import annotations
import math
import matplotlib.pyplot as plt
import torch
from uniqc import Circuit
from uniqc.simulator import Simulator
def circuit_for(theta):
c = Circuit()
c.ry(0, float(theta))
c.measure(0)
return c
def z_expectation(theta):
counts = Simulator().simulate_shots(circuit_for(theta).originir, shots=400)
total = sum(counts.values()) or 1
return (counts.get(0, 0) - counts.get(1, 0)) / total
def main() -> None:
torch.manual_seed(7)
theta = torch.nn.Parameter(torch.tensor(0.1))
optimizer = torch.optim.SGD([theta], lr=0.3)
history = []
for step in range(16):
optimizer.zero_grad()
value = z_expectation(theta.item())
grad = 0.5 * (
z_expectation(theta.item() + math.pi / 2)
- z_expectation(theta.item() - math.pi / 2)
)
theta.grad = torch.tensor(grad)
optimizer.step()
history.append((step, theta.item(), value, grad))
print("torch parameter:", theta)
print("last rows:", history[-3:])
fig, ax = plt.subplots(figsize=(6, 3.4))
ax.plot([r[0] for r in history], [r[2] for r in history], marker="o", label="<Z>")
ax.plot([r[0] for r in history], [r[1] for r in history], marker="s", label="theta")
ax.set_xlabel("step")
ax.set_title("Torch optimizer with quantum expectation")
ax.grid(alpha=0.25)
ax.legend()
fig.tight_layout()
if __name__ == "__main__":
main()
Stdout
torch parameter: Parameter containing:
tensor(2.7580, requires_grad=True)
last rows: [(13, 2.3747503757476807, -0.56, -0.8125), (14, 2.575000286102295, -0.715, -0.6675), (15, 2.758000373840332, -0.885, -0.61)]
Figures
09 — Calibration + QEM¶
Source: examples/3_best_practices/09_calibration_qem_dummy.py
Status: pass
在带显式读出噪声的 dummy adapter 上运行读出校准,将校准结果写入临时缓存,再用
ReadoutEM 对同一个 noisy backend 产生的观测 counts 做修正。
Source code
"""09 — Calibration + QEM
[doc-require: matplotlib]
[doc-output-include: stdout, figures, source]
在带显式读出噪声的 dummy adapter 上运行读出校准,将校准结果写入临时缓存,再用
``ReadoutEM`` 对同一个 noisy backend 产生的观测 counts 做修正。
"""
from __future__ import annotations
import tempfile
import matplotlib.pyplot as plt
from uniqc import Circuit
from uniqc.backend_adapter.task.adapters import DummyAdapter
from uniqc.calibration.readout import ReadoutCalibrator
from uniqc.qem import ReadoutEM
def main() -> None:
cache_dir = tempfile.mkdtemp(prefix="uniqc-bp-calibration-")
adapter = DummyAdapter(noise_model={"readout": [0.08, 0.12]})
calibrator = ReadoutCalibrator(adapter=adapter, shots=200, cache_dir=cache_dir)
calibration = calibrator.calibrate_1q(0)
observed_circuit = Circuit(1)
observed_circuit.x(0)
observed_circuit.measure(0)
task_id = adapter.submit(observed_circuit.originir, shots=200)
raw_counts = adapter.query(task_id)["result"]
observed = {int(k, 2): v for k, v in raw_counts.items()}
mitigator = ReadoutEM(adapter=adapter, shots=200, cache_dir=cache_dir)
corrected = mitigator.mitigate_counts(observed, measured_qubits=[0])
print("assignment fidelity:", round(calibration["assignment_fidelity"], 4))
print("confusion matrix:", calibration["confusion_matrix"])
print("observed:", observed)
print("corrected:", {k: round(v, 2) for k, v in corrected.items()})
labels = ["0", "1"]
fig, ax = plt.subplots(figsize=(6, 3.4))
x = range(len(labels))
ax.bar([i - 0.18 for i in x], [observed[i] for i in x], width=0.36, label="observed")
ax.bar([i + 0.18 for i in x], [corrected[i] for i in x], width=0.36, label="mitigated")
ax.set_xticks(list(x))
ax.set_xticklabels(labels)
ax.set_ylabel("counts")
ax.set_title("Readout error mitigation")
ax.legend()
ax.grid(axis="y", alpha=0.25)
fig.tight_layout()
if __name__ == "__main__":
main()
Stdout
assignment fidelity: 0.9
confusion matrix: ((0.92, 0.12), (0.08, 0.88))
observed: {0: 24, 1: 176}
corrected: {0: 0.0, 1: 200.0}
Figures
10 — XEB workflow¶
Source: examples/3_best_practices/10_xeb_workflow_dummy.py
Status: pass
使用很小的参数运行 1q XEB,覆盖校准、ReadoutEM、随机线路生成、fidelity 拟合和结果
图示。本例子使用 backend="dummy:local:simulator" 搭配显式 noise_model 做本地
含噪发布检查;如果要检查真实芯片标定噪声路径,应改用 backend="dummy:originq:WK_C180"
这类规则型 backend id,它会先按真实 backend compile/transpile,再本地含噪执行。
Source code
"""10 — XEB workflow
[doc-require: matplotlib]
[doc-output-include: stdout, figures, source]
使用很小的参数运行 1q XEB,覆盖校准、ReadoutEM、随机线路生成、fidelity 拟合和结果
图示。本例子使用 ``backend="dummy:local:simulator"`` 搭配显式 ``noise_model`` 做本地
含噪发布检查;如果要检查真实芯片标定噪声路径,应改用 ``backend="dummy:originq:WK_C180"``
这类规则型 backend id,它会先按真实 backend compile/transpile,再本地含噪执行。
"""
from __future__ import annotations
import tempfile
import matplotlib.pyplot as plt
from uniqc import xeb_workflow
def main() -> None:
cache_dir = tempfile.mkdtemp(prefix="uniqc-bp-xeb-")
results = xeb_workflow.run_1q_xeb_workflow(
backend="dummy:local:simulator",
qubits=[0],
depths=[1, 2, 3],
n_circuits=3,
shots=128,
use_readout_em=True,
noise_model={"depol": 0.01, "readout": 0.04},
seed=11,
cache_dir=cache_dir,
)
result = results[0]
print("fidelity_per_layer:", round(result.fidelity_per_layer, 6))
print(
"fit parameters:",
{
"A": round(result.fit_a, 6),
"B": round(result.fit_b, 6),
"r": round(result.fit_r, 6),
},
)
print("depths:", result.depths)
fitted = [
result.fit_a * (result.fit_r ** depth) + result.fit_b for depth in result.depths
]
fig, ax = plt.subplots(figsize=(6, 3.4))
ax.plot(result.depths, fitted, marker="o")
ax.set_xlabel("depth")
ax.set_ylabel("fitted fidelity")
ax.set_title("1q XEB fitted release-check result")
ax.grid(alpha=0.25)
fig.tight_layout()
if __name__ == "__main__":
main()
Stdout
fidelity_per_layer: 0.983341
fit parameters: {'A': 1.01276, 'B': 0.0, 'r': 0.983341}
depths: (1, 2, 3)
Figures
发布前重跑¶
维护者发布前应该用全开发环境重跑一次完整 docs 流水线(含 pre-doc-execution):
uv sync --all-extras --group dev --group docs --upgrade
cd docs
uv run make html
如果某个示例因为缺少依赖或凭据无法执行,scripts/build_docs.py 会跳过而不是
失败;请保证至少 dummy:local:* 路径全部 pass。如果某个示例真的产生了 warning /
error 而它本应被忽略(比如来自某个第三方库的 deprecation),用
[doc-warning-ignore: <regex>] 在示例 docstring 里标注即可。