你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。

开发和验证 QEC 协议

使用 qodec 和 Microsoft Quantum 开发工具包 (QDK) 中的 qdk.ec 模块来定义量子错误更正 (QEC) 代码并将其转换为可执行协议。 在本文中,你定义错误代码,构建基线 qodec,验证其声明,计算小工具距离,并保存协议。

本文中的示例使用 $[[4,2,2]]$ C4 代码,该代码将两个逻辑量子比特存储在四个物理量子比特中,并检测任何单个物理 Pauli 错误。

Prerequisites

在开始之前完成这些任务:

  • 安装 QDK 以更正错误。
  • 使用 3.11 或更高版本的 Python 环境。
  • 确认 qodecStim 解析器可用。 在 LinuxArm64 或 WindowsArm64 上,从源代码安装 Stim,然后在调用 build_qodec 之前重启 Python 或 Jupyter 内核。

定义代码

为每个逻辑量子比特创建一个带有代码稳定器以及一个逻辑 X 和 Z 代表的 qodec.Code 对象。

import qodec

c4 = qodec.Code(
    "C4",
    stabilizers=["X_0 X_1 X_2 X_3", "Z_0 Z_1 Z_2 Z_3"],
    x=["X_0 X_1", "X_0 X_2"],
    z=["Z_0 Z_2", "Z_0 Z_1"],
)

包 qodec 对 Pauli 字符串使用稀疏表示法。 每个术语都有一个 Pauli 字母和一个物理 qubit 标签。 例如, X_0 X_2 将 X 应用于物理量子比特 0 和 2。

代码定义是静态数学对象。 它不包括准备、保留或测量编码状态的线路。

分析代码

要检查代码运算符的快照,请创建 CodeProfile。

from qdk import ec

profile = ec.CodeProfile(c4)

print("Physical support:", sorted(profile.support))
print("Physical qubits:", profile.length)
print("Logical qubits:", profile.logical_qubit_count)
print("Stabilizers:", profile.stabilizers)
print("Logical X operators:", profile.x)
print("Logical Z operators:", profile.z)

如果以后更改原始 qodec.Code 对象,配置文件不会更改。

计算代码距离

要查找导致具有零综合征的非平凡逻辑效果的允许物理错误的最小数量,请调用 distance。

distance = profile.distance()
print("Code distance:", distance)

error = distance.witness.product
syndrome = profile.syndrome_of(error)
logical_effect = profile.logical_effect_of(error)

print("Witness:", error)
print("Syndrome:", sorted(syndrome))
print("Logical effect:", logical_effect)

assert distance.value == 2
assert profile.is_logical(error)

默认情况下,搜索为每个单量子位 X、Y 或 Z 错误分配一个成本。 返回的 Distance 具有认证边界和任何有限上限的见证。

当完全确切的搜索成本过高时,请使用 distance_bounds。

bounds = profile.distance_bounds(upper_bound=4)
print("Distance bounds:", bounds)
print("Lower bound:", bounds.lower_bound)
print("Upper bound:", bounds.upper_bound)

默认求解器为 HiGHS. 要使用不同的求解器,请设置 solver="enumeration",或安装 MWPF 并设置 solver="mwpf"。

建立基线 qodec

qodec 描述了如何运行已编码的指令。 它具有指令集、代码、层、器件、电路、检查和读出公式。

使用 build_qodec 从 C4 代码创建两层协议。

protocol = ec.build_qodec(
    c4,
    strategy="bare-css/v1",
    strict=False,
)

此示例使用 bare-css/v1,让您检查一个没有标记量子比特的简单协议。

Caution

该 bare-css/v1 策略不承诺容错电路。 在将协议用于噪声实验之前,计算每个小工具的距离。

构建器尝试创建以下逻辑指令:

  • prepare_z_all
  • prepare_x_all
  • syndrome
  • measure_z_all
  • measure_x_all
  • h_all
  • cx_all

_all 后缀表示指令对块中的每个逻辑量子位执行操作。 例如,cx_all 在两个块中的对应逻辑量子位之间应用 CNOT。

并非每个操作码都支持每个候选指令。 使用 strict=True默认值时,生成器在无法生成和验证候选项时引发错误。 使用 strict=False 时,构建器会保留受支持的指令,并将遗漏记录在 protocol.metadata["qdk.ec"]["build"]["omitted"] 中。

检查逻辑层及其小工具。

logical_layer = protocol.layers[0]

print("Instructions:")
for mnemonic in logical_layer.instruction_set.instructions:
    print(" -", mnemonic)

print("Gadgets:")
for mnemonic in logical_layer.gadgets:
    print(" -", mnemonic)

第二层包含生成的线路使用的物理 Stim 指令集。

检查小工具

逻辑指令声明契约。 其小工具提供实现契约的线路。

检查 prepare_z_all 小工具。

gadget = logical_layer.gadgets["prepare_z_all"]
gadget_profile = ec.GadgetProfile(gadget)

print("Declared objective:")
print(gadget_profile.objective)

print("Computed action:")
print(gadget_profile.action)

将线路计算的操作与声明的指令目标进行比较。

objective = gadget_profile.objective
assert objective is not None

if gadget_profile.action.is_equivalent_to(objective):
    print("The gadget implements its declared instruction.")
else:
    print(objective.why_not_equivalent_to(gadget_profile.action))

GadgetProfile 获取其输入的快照,因此不反映后续更改。 编辑小工具后,创建新的配置文件。

审核协议

使用 audit 检查整个 qodec。

report = ec.audit(protocol)
print(report)

如果审核未发现错误或警告,则会打印:

audit: ok

审核将检查以下方面:

  • 代码代数
  • 指令和层结构
  • 线路调用和参数绑定
  • 小工具操作
  • 校验和读出方程
  • 标记公式
  • 输入和输出帧关系
  • 参考边界和协议完整性

若要处理特定严重性,请使用报表集合。

if report.errors:
    for diagnostic in report.errors:
        print(diagnostic)
    raise ValueError("The qodec has audit errors.")

if report.warnings:
    for diagnostic in report.warnings:
        print(diagnostic)

report.ok值表示报表没有错误。 警告不会更改该属性。

推导缺失的公式

当草稿小工具或 qodec 省略精确模拟可以推导的校验或逻辑读出方程时,请使用 filled。

以下示例创建了协议的一个不完整副本。

draft = qodec.Qodec.loads(protocol.dumps())
draft_gadgets = draft.layers[0].gadgets

draft_gadgets["measure_x_all"].readouts = []
draft_gadgets["cx_all"].checks = []

print(ec.audit(draft))

填写受支持的公式,然后审核结果。

completed = ec.filled(draft)
print(ec.audit(completed))

filled 函数返回新的小工具或 qodec,并且不更改其输入。 它推导校验、可观察读出方程和帧关系。 它保留标志绑定,因为无噪声模拟无法识别标志应检测到的故障。

如果原始协议已经有经过验证的直接公式,filled 会在可能的情况下保留这些公式。

分析小工具故障

未发现错误的审计证明了无噪声一致性。 它并不能证明系统具有容错能力。

调用 GadgetProfile.distance 以查找在声明所有校验和标志保持为零时导致逻辑故障的允许线路故障的最小数量。 组合故障还必须将每个输出保留在其代码空间内。

protocol = completed

for mnemonic, gadget in sorted(protocol.layers[0].gadgets.items()):
    result = ec.GadgetProfile(gadget).distance()
    witness = result.witness if result.upper_bound is not None else "none"
    print(f"{mnemonic}: distance={result}, witness={witness}")

默认故障模型在每个电路调用后包括以下事件:

  • 调用涉及的量子位上的 Pauli 错误
  • 调用产生的读出位翻转
  • 这些错误的关联组合

每个事件在一次调用中都算作一个,即使它具有相关的多量子比特错误也是如此。

代码的距离可以为 2,而其小工具之一的距离可以为 1。 例如,单个线路故障可以通过辅助位传播并创建未检测到的逻辑错误。 添加校验或标志线路,然后创建新的 GadgetProfile 并重新计算距离。

检查特定故障

使用 FaultEvent.after 在从零开始的线路调用索引之后定义故障。

gadget = protocol.layers[0].gadgets["syndrome"]
profile = ec.GadgetProfile(gadget)

fault = ec.FaultEvent.after(0, ec.Pauli("X_0"))
(effect,) = profile.effects_of([fault])

print("Fault:", fault)
print("Changed quantities:", effect)

FaultEffect 可以包含更改的校验、逻辑读出和输出帧符号。 当默认线路级模型与硬件假设不匹配时,请使用显式故障集。

result = profile.distance(faults=[fault])
print(result)

精确小工具搜索可能需要很长时间,因为默认故障集随每个调用的支持呈指数增长。 在需要限制搜索时,使用 distance_bounds、显式故障集或 upper_bound。

保存协议

在保存最终的 qodec 之前对其进行审核。

report = ec.audit(protocol)
if report.errors or report.warnings:
    raise ValueError(str(report))

将协议保存为单个 YAML 捆绑包,然后再次加载以检查它是否与原始协议匹配。

from pathlib import Path

output_directory = Path("qodec-output")
output_directory.mkdir(exist_ok=True)

saved_path = protocol.save(str(output_directory), single_file=True)
loaded = qodec.Qodec.load(saved_path)

assert loaded == protocol
print("Saved qodec:", saved_path)

单文件捆绑包将清单、代码定义、指令集、gadgets 和电路源文件存储在一个 YAML 文件中,这样可以轻松共享和重新加载。

运行协议

在 qodec 通过审核并满足距离要求后,将逻辑程序编译为量子中间表示 (QIR),并通过协议运行它。 请参阅“运行和解码逻辑程序”。

有关添加标志线路并比较逻辑错误率的完整示例,请参阅 QDK GitHub 存储库上的 QEC 协议演练。