进阶主题走读 (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.pyexamples/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

含义

dummy / dummy:local:simulator

完全无约束、无噪声

dummy:local:virtual-line-N

长度 N 的虚拟线性拓扑、无噪声

dummy:local:virtual-grid-RxC

R×C 的虚拟网格拓扑、无噪声

dummy:local:mps-linear-N[:chi=K[:cutoff=E]]

MPS 引擎,线性拓扑

dummy:<platform>:<backend>

复用真实 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 —— 零噪声外推(实验性)。

详见 校准 · M3 / ReadoutEM

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 模拟器