使用 qodec 和來自 Microsoft Quantum Development Kit(QDK)的 qdk.ec 模組來定義量子錯誤更正(QEC)碼,並將其轉換為可執行協定。 在本文中,你將定義錯誤代碼、建立基準線 qodec、驗證其宣告、計算 gadget 距離,並儲存協定。
本文範例使用 $[[4,2,2]]$ C4 碼,該碼將兩個邏輯量子位元儲存在四個物理量子位元中,並偵測任何單一物理 Pauli 錯誤。
Prerequisites
開始前請完成以下任務:
- 安裝 QDK 以修正錯誤。
- 使用含有 Python 3.11 或更新版本的環境。
- 確認解析器是否 qodecStim 可用。 在 LinuxArm64 或 WindowsArm64 上,從原始碼安裝 Stim,然後在呼叫 Jupyter 之前重新啟動
build_qodec或 Python 核心。
定義此程式碼
建立 qodec.Code 一個物件,包含碼穩定子,並為每個邏輯量子位元建立一個邏輯 X 和 Z 代表元。
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 字母和一個實體量子比特標籤。 例如,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 錯誤分配成本為 1。 返回的 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_allprepare_x_allsyndromemeasure_z_allmeasure_x_allh_allcx_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))
A GadgetProfile 會擷取其輸入內容的快照,因此它不會反映後續的變更。 編輯完一個小工具後,建立一個新的設定檔。
審核通訊協定
請用 audit 來檢查整個 qodec。
report = ec.audit(protocol)
print(report)
若稽核未發現錯誤或警告,則列印如下:
audit: ok
審計會檢查以下幾個方面:
- 程式碼代數
- 指令與層結構
- Circuit 呼叫與參數綁定
- 小工具動作
- 檢查與讀值方程式
- 標記方程式
- 輸入與輸出框架關係
- 參考邊界與協定完整性
若要處理特定嚴重程度,請使用報表集合。
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 值表示報告中沒有錯誤。 警告不會改變這個屬性。
推導缺少的方程式
當草圖裝置或filled省略了可由精確模擬推導出的檢查或邏輯讀出方程式時,使用qodec。
以下範例會建立一個不完整的通訊協定副本。
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 函式會回傳一個新的 gadget 或 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錯誤
- 函式呼叫產生的讀出位元翻轉
- 這些誤差的相互關聯組合
在一次呼叫中,每個事件都算作一個,即使它具有相關的多量子位元錯誤。
一個代碼的距離可以是二,但它的一個小工具的距離是一。 例如,單一電路故障可能透過輔助量子位元擴散,產生未被偵測的邏輯錯誤。 新增檢查或標記電路,然後建立新的 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)
A 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 通過其審核並符合距離要求後,將邏輯程式編譯為量子中間表示(Quantum Intermediate RepresentationQIR),並讓其通過該協議。 參見 執行及解碼邏輯程序。