进阶主题走读 (Walkthrough)¶
进阶部分覆盖编译内部、区域选择、变分量子算法、含噪 dummy 系统、calibration、error
mitigation、MPS 模拟器。每一节都对应一个可运行的 examples/2_advanced/*.py,
由文档构建器在 make html 时按 [doc-require:] 门控自动跑或仅展示源代码。
1. 编译内部选项¶
01 — Compile internals: levels, basis gates, virtual backends¶
Source: examples/2_advanced/01_compile_options.py
Status: pass
uniqc.compile.compile 把任意 Circuit 编译到目标后端的拓扑、基门集合和提交
语言。常用旋钮:
backend_info— 目标后端(拓扑 + basis gates 的来源);output_format="originir" | "qasm"— 提交语言;optimization_level=0..3— 编译激进度。
这里在两个虚拟后端上对比同一个跨距 CNOT 线路的编译产物。
Source code
"""01 — Compile internals: levels, basis gates, virtual backends
[doc-require: ]
[doc-output-include: stdout, source]
``uniqc.compile.compile`` 把任意 ``Circuit`` 编译到目标后端的拓扑、基门集合和提交
语言。常用旋钮:
* ``backend_info`` — 目标后端(拓扑 + basis gates 的来源);
* ``output_format="originir" | "qasm"`` — 提交语言;
* ``optimization_level=0..3`` — 编译激进度。
这里在两个虚拟后端上对比同一个跨距 CNOT 线路的编译产物。
"""
from __future__ import annotations
from uniqc import BackendInfo, Circuit, Platform, QubitTopology, compile
def make_backend(name: str, n: int, edges: list[tuple[int, int]]) -> BackendInfo:
return BackendInfo(
platform=Platform.DUMMY,
name=name,
num_qubits=n,
topology=tuple(QubitTopology(u, v) for u, v in edges),
status="available",
is_simulator=True,
)
def main() -> None:
circuit = Circuit()
circuit.h(0)
circuit.cnot(0, 3) # not nearest-neighbour
circuit.measure(0, 3)
line = make_backend("virtual-line-4", 4, [(0, 1), (1, 2), (2, 3)])
grid = make_backend("virtual-grid-2x2", 4, [(0, 1), (1, 2), (2, 3), (0, 3)])
for backend in (line, grid):
print(f"== compile target: {backend.full_id()} ==")
compiled = compile(circuit, backend_info=backend, output_format="originir")
print(compiled)
if __name__ == "__main__":
main()
Stdout
== compile target: dummy:virtual-line-4 ==
QINIT 4
CREG 2
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)
MEASURE q[0], c[0]
MEASURE q[1], c[1]
== compile target: dummy:virtual-grid-2x2 ==
QINIT 4
CREG 2
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)
MEASURE q[0], c[0]
MEASURE q[1], c[1]
完整接口签名与 BackendOptions 系列见 编译选项与 RegionSelector 与 编译强度。
2. RegionSelector:在芯片上挑选高保真度子区域¶
02 — RegionSelector: pick a high-fidelity sub-region of a chip¶
Source: examples/2_advanced/02_region_selector.py
Status: not-executed
RegionSelector 在芯片标定数据(拓扑 + 单/双比特保真度)上为你挑选一段
高保真度连续子区域(链或子区域),用于把小线路放到芯片上”最好的部分”。它接受
一个 ChipCharacterization,最常用的入口是 RegionSelector.from_backend。
真实芯片标定数据(uniqc backend update --platform originq 拉取)以及对应的
凭据。用法本身在所有平台上都一样。
Source code
"""02 — RegionSelector: pick a high-fidelity sub-region of a chip
[doc-require: originq]
[doc-skip-execute]
[doc-output-include: source]
``RegionSelector`` 在芯片标定数据(拓扑 + 单/双比特保真度)上为你挑选一段
**高保真度连续子区域**(链或子区域),用于把小线路放到芯片上"最好的部分"。它接受
一个 ``ChipCharacterization``,最常用的入口是 ``RegionSelector.from_backend``。
下面的代码片段标注了 ``[doc-skip-execute]``:本地 build_docs 不会跑它,因为它需要
真实芯片标定数据(``uniqc backend update --platform originq`` 拉取)以及对应的
凭据。用法本身在所有平台上都一样。
"""
from __future__ import annotations
from uniqc import RegionSelector
def main() -> None:
selector = RegionSelector.from_backend("originq:WK_C180")
chain = selector.find_best_1D_chain(length=5)
print("best 5-qubit chain:", chain.chain)
print("estimated fidelity:", chain.estimated_fidelity)
print("num swaps: ", chain.num_swaps)
if __name__ == "__main__":
main()
Note
Listed for reference; not executed during the docs build ([doc-skip-execute]).
详细 API 见 编译选项 · 区域选择器。
3. 变分量子算法(小型 QAOA)¶
03 — Variational quantum algorithm: a tiny QAOA loop¶
Source: examples/2_advanced/03_variational_qaoa.py
Status: pass
最小可执行的 QAOA 演示:固定 1 层、单参数对,扫两个角度找最优。
真正的 VQA 训练循环在 examples/3_best_practices/07_variational_circuit.py
和 examples/3_best_practices/08_torch_quantum_training.py。
Source code
"""03 — Variational quantum algorithm: a tiny QAOA loop
[doc-require: ]
[doc-output-include: stdout, source]
最小可执行的 QAOA 演示:固定 1 层、单参数对,扫两个角度找最优。
真正的 VQA 训练循环在 ``examples/3_best_practices/07_variational_circuit.py``
和 ``examples/3_best_practices/08_torch_quantum_training.py``。
"""
from __future__ import annotations
import itertools
from uniqc import Circuit
from uniqc.simulator import Simulator
def qaoa_layer(gamma: float, beta: float) -> Circuit:
c = Circuit(2)
c.h(0)
c.h(1)
# cost (ZZ): exp(-i gamma Z0Z1) ≡ CNOT-RZ-CNOT
c.cnot(0, 1)
c.rz(1, 2 * gamma)
c.cnot(0, 1)
# mixer
c.rx(0, 2 * beta)
c.rx(1, 2 * beta)
c.measure(0, 1)
return c
def main() -> None:
sim = Simulator()
best = None
for gamma, beta in itertools.product([0.2, 0.4, 0.6], [0.2, 0.4, 0.6]):
counts = sim.simulate_shots(qaoa_layer(gamma, beta).originir, shots=512)
# cost: <Z0 Z1> = P(00) + P(11) - P(01) - P(10), but we want max-cut → minimize.
total = sum(counts.values()) or 1
zz = (counts.get(0, 0) + counts.get(3, 0) - counts.get(1, 0) - counts.get(2, 0)) / total
if best is None or zz < best[2]:
best = (gamma, beta, zz)
print(f"gamma={gamma:.2f} beta={beta:.2f} <ZZ>={zz:+.4f}")
print("best:", best)
if __name__ == "__main__":
main()
Stdout
gamma=0.20 beta=0.20 <ZZ>=+0.3008
gamma=0.20 beta=0.40 <ZZ>=+0.4336
gamma=0.20 beta=0.60 <ZZ>=+0.2539
gamma=0.40 beta=0.20 <ZZ>=+0.5000
gamma=0.40 beta=0.40 <ZZ>=+0.6914
gamma=0.40 beta=0.60 <ZZ>=+0.5312
gamma=0.60 beta=0.20 <ZZ>=+0.6992
gamma=0.60 beta=0.40 <ZZ>=+0.9219
gamma=0.60 beta=0.60 <ZZ>=+0.6094
best: (0.2, 0.6, 0.25390625)
完整的 VQA 训练循环示例:
4. Dummy 系统:noiseless、virtual-topology、chip-noise¶
UnifiedQuantum 的 dummy 系统通过 backend id 文法区分三种语义:
id |
含义 |
|---|---|
|
完全无约束、无噪声 |
|
长度 N 的虚拟线性拓扑、无噪声 |
|
R×C 的虚拟网格拓扑、无噪声 |
|
MPS 引擎,线性拓扑 |
|
复用真实 backend 拓扑 + 标定噪声,先 compile/transpile 再本地含噪执行 |
04 — Dummy chip noise: dummy:<platform>:<backend>¶
Source: examples/2_advanced/04_dummy_chip_noise.py
Status: pass
dummy:<platform>:<backend> 是规则型 backend id:它不会出现在 backend 列表,
但提交时会先按真实 backend compile/transpile,然后用本地 dummy adapter 注入对应芯片
的标定噪声。常用形态:
dummy:local:simulator— 完全无约束、无噪声;dummy:local:virtual-line-N/virtual-grid-RxC— 虚拟拓扑、无噪声;dummy:local:mps-linear-N[:chi=K[:cutoff=E]]— 线性 MPS 引擎;dummy:<platform>:<backend>— 真芯片拓扑 + 标定噪声(需要芯片缓存)。
最后一种需要先用 uniqc backend update --platform originq 等命令把芯片缓存
拉下来;本例只演示三种 dummy:local:* 形态。
Source code
"""04 — Dummy chip noise: ``dummy:<platform>:<backend>``
[doc-require: ]
[doc-output-include: stdout, source]
``dummy:<platform>:<backend>`` 是规则型 backend id:**它不会出现在 backend 列表**,
但提交时会先按真实 backend compile/transpile,然后用本地 dummy adapter 注入对应芯片
的标定噪声。常用形态:
* ``dummy:local:simulator`` — 完全无约束、无噪声;
* ``dummy:local:virtual-line-N`` / ``virtual-grid-RxC`` — 虚拟拓扑、无噪声;
* ``dummy:local:mps-linear-N[:chi=K[:cutoff=E]]`` — 线性 MPS 引擎;
* ``dummy:<platform>:<backend>`` — 真芯片拓扑 + 标定噪声(需要芯片缓存)。
最后一种需要先用 ``uniqc backend update --platform originq`` 等命令把芯片缓存
拉下来;本例只演示三种 ``dummy:local:*`` 形态。
"""
from __future__ import annotations
from uniqc import Circuit
from uniqc.backend_adapter.dummy_backend import resolve_dummy_backend
from uniqc.backend_adapter.task_manager import submit_task, wait_for_result
def main() -> None:
circuit = Circuit(3)
circuit.h(0)
circuit.cnot(0, 1)
circuit.cnot(1, 2)
circuit.measure(0, 1, 2)
for backend in (
"dummy:local:simulator",
"dummy:local:virtual-line-3",
"dummy:local:mps-linear-3:chi=8",
):
spec = resolve_dummy_backend(backend)
print(f"== {backend} ==")
print(" description: ", spec.description)
print(" topology: ", spec.available_topology)
print(" simulator_kwargs:", spec.simulator_kwargs)
task = submit_task(circuit, backend=backend, shots=256)
result = wait_for_result(task, timeout=30)
print(" counts: ", result)
if __name__ == "__main__":
main()
Stdout
== dummy:local:simulator ==
description: Unconstrained noiseless local simulator
topology: None
simulator_kwargs: None
counts: UnifiedResult(counts={'000': 128, '111': 128}, probabilities={'000': 0.5, '111': 0.5}, shots=256, platform='dummy', task_id='uqt_9a02c4b299934f019a914bdb535eedc0', backend_name='dummy:local:simulator', execution_time=None, error_message=None)
== dummy:local:virtual-line-3 ==
description: Noiseless virtual 3-qubit line topology
topology: [[0, 1], [1, 2]]
simulator_kwargs: None
counts: UnifiedResult(counts={'000': 128, '111': 128}, probabilities={'000': 0.5, '111': 0.5}, shots=256, platform='dummy', task_id='uqt_15861f9aa3ca4426aa729ddcc0753763', backend_name='dummy:local:virtual-line-3', execution_time=None, error_message=None)
== dummy:local:mps-linear-3:chi=8 ==
description: Noiseless MPS simulator on a 3-qubit linear chain, chi=8
topology: [[0, 1], [1, 2]]
simulator_kwargs: {'chi_max': 8}
counts: UnifiedResult(counts={'000': 139, '111': 117}, probabilities={'000': 0.54296875, '111': 0.45703125}, shots=256, platform='dummy', task_id='uqt_ddef6695275449a0b0762ace7686fe6a', backend_name='dummy:local:mps-linear-3:chi=8', execution_time=None, error_message=None)
DummyBackend 编号规则与本地噪声模拟说明见 平台约定 · DummyBackend。
5. Calibration:1q / 2q / parallel-2q XEB + readout¶
05 — Calibration: 1q XEB on a noisy dummy backend¶
Source: examples/2_advanced/05_calibration_xeb.py
Status: pass
XEB 通过对比理论 vs 观测的 cross-entropy 来估计每层平均门保真度。这里在带显式去极化
噪声的 dummy:local:simulator 上跑一个非常小的 1q XEB,仅做接口路径验证。
真实芯片 XEB 通过 uniqc calibrate xeb CLI 跑,结果落在
~/.uniqc/calibration_cache/。
Source code
"""05 — Calibration: 1q XEB on a noisy dummy backend
[doc-require: ]
[doc-output-include: stdout, source]
XEB 通过对比理论 vs 观测的 cross-entropy 来估计每层平均门保真度。这里在带显式去极化
噪声的 ``dummy:local:simulator`` 上跑一个非常小的 1q XEB,仅做接口路径验证。
真实芯片 XEB 通过 ``uniqc calibrate xeb`` CLI 跑,结果落在
``~/.uniqc/calibration_cache/``。
"""
from __future__ import annotations
import tempfile
from uniqc import xeb_workflow
def main() -> None:
cache_dir = tempfile.mkdtemp(prefix="uniqc-cal-xeb-")
results = xeb_workflow.run_1q_xeb_workflow(
backend="dummy:local:simulator",
qubits=[0],
depths=[1, 2, 4, 8],
n_circuits=4,
shots=200,
use_readout_em=False,
noise_model={"depol": 0.005},
seed=3,
cache_dir=cache_dir,
)
r = results[0]
print(f"qubit: {r.qubit}")
print(f"depths: {r.depths}")
print(f"fidelity/layer: {r.fidelity_per_layer:.6f}")
print(f"fit A={r.fit_a:.4f} r={r.fit_r:.4f} B={r.fit_b:.4f}")
if __name__ == "__main__":
main()
Stdout
qubit: 0
depths: (1, 2, 4, 8)
fidelity/layer: 0.993333
fit A=1.0000 r=0.9933 B=0.0000
完整 workflow 见 uniqc calibrate xeb / uniqc calibrate readout /
uniqc calibrate pattern,结果统一缓存到 ~/.uniqc/calibration_cache/,
带 ISO-8601 时间戳和 TTL 新鲜度检查。详见 校准。
6. Error mitigation:M3 + ReadoutEM¶
06 — Error mitigation: M3 / readout EM¶
Source: examples/2_advanced/06_qem_m3.py
Status: pass
读取误差是芯片上最便宜的可纠错部分。ReadoutEM 自动从
~/.uniqc/calibration_cache/ 读 readout 校准结果,对 counts 做线性反演修正
(M3 在多比特上是更紧凑的 LSQR 实现)。
Source code
"""06 — Error mitigation: M3 / readout EM
[doc-require: ]
[doc-output-include: stdout, source]
读取误差是芯片上最便宜的可纠错部分。``ReadoutEM`` 自动从
``~/.uniqc/calibration_cache/`` 读 readout 校准结果,对 counts 做线性反演修正
(M3 在多比特上是更紧凑的 LSQR 实现)。
"""
from __future__ import annotations
import tempfile
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-qem-")
adapter = DummyAdapter(noise_model={"readout": [0.07, 0.10]})
ReadoutCalibrator(adapter=adapter, shots=200, cache_dir=cache_dir).calibrate_1q(0)
circuit = Circuit(1)
circuit.x(0)
circuit.measure(0)
task_id = adapter.submit(circuit.originir, shots=400)
raw = adapter.query(task_id)["result"]
observed = {int(k, 2): v for k, v in raw.items()}
mitigator = ReadoutEM(adapter=adapter, shots=200, cache_dir=cache_dir)
corrected = mitigator.mitigate_counts(observed, measured_qubits=[0])
print("observed: ", observed)
print("mitigated (~): ", {k: round(v, 2) for k, v in corrected.items()})
if __name__ == "__main__":
main()
Stdout
observed: {0: 40, 1: 360}
mitigated (~): {0: 0.0, 1: 400.0}
QEM 模块当前覆盖:
uniqc.M3Mitigator—— 多比特读取误差线性反演(M3 风格);uniqc.ReadoutEM—— 自动从 calibration cache 读校准、强制 TTL 检查;uniqc.qem.zne—— 零噪声外推(实验性)。
7. MPS 模拟器(长链可扩展)¶
07 — Matrix-product-state simulator on a long linear chain¶
Source: examples/2_advanced/07_mps_simulator.py
Status: pass
MPS 引擎是一个线性拓扑、无噪声、能扩展到上百比特的模拟器(前提是中等纠缠)。两种 入口:
MPSSimulator直接 API;submit_task(backend="dummy:local:mps-linear-N:chi=K:cutoff=E:seed=S")通过统一的 任务接口(参数解析见resolve_dummy_backend)。
Source code
"""07 — Matrix-product-state simulator on a long linear chain
[doc-require: ]
[doc-output-include: stdout, source]
MPS 引擎是一个线性拓扑、无噪声、能扩展到上百比特的模拟器(前提是中等纠缠)。两种
入口:
* ``MPSSimulator`` 直接 API;
* ``submit_task(backend="dummy:local:mps-linear-N:chi=K:cutoff=E:seed=S")`` 通过统一的
任务接口(参数解析见 ``resolve_dummy_backend``)。
"""
from __future__ import annotations
from uniqc import Circuit
from uniqc.backend_adapter.dummy_backend import resolve_dummy_backend
from uniqc.backend_adapter.task_manager import submit_task, wait_for_result
from uniqc.simulator import MPSConfig, MPSSimulator
def build_brick_ghz(n: int) -> Circuit:
c = Circuit(n)
c.h(0)
for i in range(n - 1):
c.cnot(i, i + 1)
for q in range(n):
c.measure(q)
return c
def main() -> None:
n = 32
print(f"== Direct MPSSimulator (N={n}) ==")
circuit = build_brick_ghz(n)
sim = MPSSimulator(MPSConfig(chi_max=64, svd_cutoff=1e-12, seed=2024))
counts = sim.simulate_shots(circuit.originir, shots=400)
print(f" observed keys: {sorted(counts)}")
print(f" total shots: {sum(counts.values())}")
print(f" max bond dim: {sim.max_bond}")
print(f"\n== dummy:local:mps-linear-{n} backend (chi=8, forces truncation) ==")
task = submit_task(
circuit,
backend=f"dummy:local:mps-linear-{n}:chi=8:cutoff=1e-10",
shots=400,
)
print(" result:", wait_for_result(task, timeout=60))
print("\n== Parameter parsing ==")
spec = resolve_dummy_backend("dummy:local:mps-linear-8:chi=16:cutoff=1e-8:seed=7")
print(" identifier: ", spec.identifier)
print(" available_qubits: ", spec.available_qubits)
print(" simulator_kwargs: ", spec.simulator_kwargs)
if __name__ == "__main__":
main()
Stdout
== Direct MPSSimulator (N=32) ==
observed keys: [0, 4294967295]
total shots: 400
max bond dim: 2
== dummy:local:mps-linear-32 backend (chi=8, forces truncation) ==
result: UnifiedResult(counts={'11111111111111111111111111111111': 210, '00000000000000000000000000000000': 190}, probabilities={'11111111111111111111111111111111': 0.525, '00000000000000000000000000000000': 0.475}, shots=400, platform='dummy', task_id='uqt_bdcbb90a4194447d9e8e02cf876029c6', backend_name='dummy:local:mps-linear-32:chi=8:cutoff=1e-10', execution_time=None, error_message=None)
== Parameter parsing ==
identifier: dummy:local:mps-linear-8:chi=16:cutoff=1e-8:seed=7
available_qubits: [0, 1, 2, 3, 4, 5, 6, 7]
simulator_kwargs: {'chi_max': 16, 'svd_cutoff': 1e-08, 'seed': 7}
MPS 引擎适合线性拓扑 + 中等纠缠的大规模线路,可扩展到上百比特。chi 决定
最大键维(精度↑ 内存↑ 时间↑),cutoff 是 SVD 截断阈值。完整文档见
MPS 模拟器。