使用 Microsoft Quantum Development Kit(QDK)將邏輯 Q# 或 OpenQASM 程式編譯為 Quantum Intermediate Representation(QIR),然後使用 qdk.simulation.run_qir 讓程式透過 qodec 執行。 建立雜訊模型,然後選擇內建的症候群解碼器或選用的 deq 電路級解碼器。
Prerequisites
開始前請完成以下任務:
- 安裝QDK以修正錯誤。
- 開發並驗證 QEC 協定,或從其他來源取得完整的 qodec
- 使用
qdk.ec.audit稽核qodec。
範例中使用Q#一個名為C4、包含protocol程式碼指令的qodec。 若要建立,請參見 「開發並驗證 QEC 協議」。
import qodec
from qdk import ec
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"],
)
protocol = ec.build_qodec(
c4,
strategy="bare-css/v1",
strict=False,
)
report = ec.audit(protocol)
if report.errors or report.warnings:
raise ValueError(str(report))
在執行前先審核 qodec 。 執行階段信任 qodec 的檢查、讀值、旗標和影格方程式,因此無效宣告可能導致錯誤的邏輯結果或解碼器故障。
此工作流程使用 qdk.simulation.run_qir 搭配 qodec。 該 qodec 工具使用獨立的 StimPython 套件 來解析 Stim 格式的 gadget 電路。 它不會呼叫 qdk.stim.run。 在 LinuxArm64 或 WindowsArm64 上,從原始碼安裝 Stim,然後在執行帶有 Jupyter-format 電路的 Python 之前重新啟動 qodec 或 Stim 核心。
將qodec呼叫與QIR指令匹配
將 QIR 程式中的每個量子呼叫與 qodec 的最上層指令集中的一項指令相匹配。 指令助記符必須與被叫者名稱完全一致 QIR 。
下表顯示範例對應:
| 來源呼叫 | 必填 qodec 助記鍵 |
|---|---|
Q#
X(q) 或 OpenQASMx q; |
__quantum__qis__x__body |
Q#
H(q) 或 OpenQASMh q; |
__quantum__qis__h__body |
Q#
CNOT(a, b) 或 OpenQASMcx a, b; |
__quantum__qis__cx__body |
Q#
Adjoint S(q) 或 OpenQASMsdg q; |
__quantum__qis__s__adj |
Q#
M(q) 或 OpenQASMc = measure q; |
__quantum__qis__m__body |
Q# 內建操作 Foo |
Foo |
OpenQASM 內在閘門或稱為 def 的閘門 foo |
foo |
QIR 參數依序綁定於 qodec 指令元素:
- 量子位元指標參數會綁定到區塊運算元。
- 標量引數會繫結至指令參數。
- 結果指標參數會接收指令結果及任何回傳的旗標。
如果量子調用與頂層指令集中的指令不匹配,編譯器會引發錯誤。
在 Q# 中宣告邏輯指令
qodec 由 C4 程式碼建構,並提供如 prepare_z_all、measure_z_all、syndrome 和 cx_all 等自訂指令。 宣告名稱相同的 Q# 內在操作。
使用自適應目標設定檔初始化 Q#,因為自訂測量操作需要。
from qdk import TargetProfile, qsharp
qsharp.init(target_profile=TargetProfile.Adaptive_RI)
將 C4 指令宣告為 Q# 作業。
qsharp.eval("""
@Measurement()
operation prepare_z_all(block : Qubit) : Result { body intrinsic; }
@Measurement()
operation prepare_x_all(block : Qubit) : Result { body intrinsic; }
@Measurement()
operation measure_z_all(block : Qubit) : (Result, Result) { body intrinsic; }
@Measurement()
operation measure_x_all(block : Qubit) : (Result, Result) { body intrinsic; }
operation cx_all(control : Qubit, target : Qubit) : Unit { body intrinsic; }
operation syndrome(block : Qubit) : Unit { body intrinsic; }
""")
在此程式中,Q#Qubit 各自代表一個編碼區塊。 該 C4 區塊有兩個邏輯量子位元,因此每次測量操作會回傳兩個邏輯結果。 每個準備操作回傳一個拒絕標記。
編譯一個邏輯Q#實驗
定義狀態準備與測量(SPAM)實驗。
qsharp.eval("""
operation TestSpamZ() : (Result[], Result[]) {
use block = Qubit();
let reject = prepare_z_all(block);
let (left, right) = measure_z_all(block);
([reject], [left, right])
}
""")
將 TestSpamZ 作業編譯為 QIR。
qir = str(qsharp.compile("TestSpamZ()"))
QIR 會保留對 prepare_z_all 和 measure_z_all 的呼叫。 當程式執行時,qodec 執行階段環境會將這些名稱與頂端指令集比對,並用其 gadget 替換每個邏輯呼叫。
使用內建解碼器執行
打電話run_qir並傳遞qodec。 若 decoder 為 None,則執行階段會使用內建的最小權重 Pauli 解碼器。
from qdk.simulation import run_qir
results = run_qir(
qir,
qodec=protocol,
type="stabilizer",
shots=100,
seed=42,
)
print(results[:5])
要執行 qodec,請使用以下模擬器選項:
type 數值 |
Behavior |
|---|---|
None 或 "stabilizer" |
使用穩定器後端 |
"cpu" |
對支援的程式使用狀態向量後端 |
"gpu" |
不支援搭配 qodec |
執行時會在每個程式量子位元首次使用前就先做準備,除非第一條指令建立其區塊。 準備指令有輸出區塊、無輸入區塊,以及一個使邏輯 Z穩定的動作。
單量子位元 Pauli 解碼器的修正與 qodec 影格更新使用無 Pauli 噪音的影格,而不是有雜訊的物理閘。
設定模擬器雜訊
請定義模擬器操作的雜訊,而非 qodec 指令名稱。 執行時會將底層指令轉換成一個或多個模擬器操作,因此這些操作會適用噪音設定。
C4逐步解說使用以下映射:
| 底層指令 | 模擬器運作 |
NoiseConfig 欄位 |
|---|---|---|
R |
準備好或重置為 Z+ | mresetz |
H |
哈達馬爾 | h |
CX |
Controlled X | cx |
M |
Z-基底測量 | mresetz |
建立一個簡單的1%雜訊模型:
from qdk.simulation import NoiseConfig
noise = NoiseConfig()
for gate in (noise.h, noise.cx):
gate.set_depolarizing(0.01)
noise.mresetz.x = 0.01
執行含雜訊的實驗:
results = run_qir(
qir,
qodec=protocol,
noise=noise,
type="stabilizer",
shots=1000,
seed=42,
on_shot_failure="discard",
)
噪聲mresetz在測量或準備後作用於量子位元。 它不會翻轉模擬器已經記錄的測量結果位元。 要研究記錄的位元翻轉,可以使用 qodec 讀出故障模型和 gadget 分析。
控制拍攝失敗
用 on_shot_failure 來選擇當 qodec 旗標、解碼器或讀出未產生可接受的 shot 時,執行階段的反應。
| Value | Behavior |
|---|---|
"discard" |
將失敗的鏡頭從退回清單中刪除。 此值為預設值。 |
"raise" |
第一次嘗試失敗時就停止。 |
"retry" |
重新開始失敗的射擊,最多可以再嘗試 max_retries 次。 |
在此 "discard" 策略中,參數 shots 會計算嘗試次數,因此傳回的清單項目數可能少於 shots。
只有當邏輯程式沒有收到該標記時,旗標才會觸發該射擊策略。 若操作 Q#@Measurement() 為旗標回傳額外的 Result,程式會接收旗標並決定是否拒絕該射擊。
在範例 TestSpamZ 中,程式回傳第一個陣列中的準備旗標。 所以設定 on_shot_failure="discard" 不會移除回傳旗標為 One 的列。
選擇解碼器
要選擇錯誤的解碼方式,請使用 decoder 參數為每個編碼層傳遞解碼器準備可呼叫物件。
QDK 具有下列解碼器:
| 譯碼器 | 用它來做 |
|---|---|
| 預設校驗子解碼器 | 從綜合徵證據推斷最小權重 Pauli 修正。 請使用 decoder=None。 |
| 幀解碼器 | 追蹤無噪音的影格,卻不推斷實體故障。 請使用 prepare_frame_decoder。 |
| deq 解碼器 | 使用 deq 解碼電路層級故障模型。 請使用 prepare_deq_decoder。 |
使用預設 deq 配置
安裝 deq 和 deq-runtime,然後傳遞 prepare_deq_decoder。
from qdk.simulation.decoders import prepare_deq_decoder
results = run_qir(
qir,
qodec=protocol,
decoder=prepare_deq_decoder,
noise=noise,
type="stabilizer",
shots=1000,
seed=42,
on_shot_failure="discard",
)
預設情況下,該 deq 介面卡使用中繼信念傳播與視窗協調器。 要更改這些設定,請使用執行時工廠。
配置一個單體式 deq 執行時
若要直接選擇 deq 設定,請將執行時工廠傳給 prepare_deq_decoder。
from functools import partial
from deq.runtime import Runtime
from qdk.simulation import decoders
def make_runtime(seed: int) -> Runtime:
return Runtime(
decoder="black-box-relay-bp",
decoder_config={"parallel": 1, "seed": seed},
coordinator="monolithic",
controller="jit",
)
results = run_qir(
qir,
qodec=protocol,
decoder=partial(
decoders.prepare_deq_decoder,
runtime_factory=make_runtime,
),
noise=noise,
type="stabilizer",
shots=1000,
seed=42,
on_shot_failure="discard",
)
每次工廠函式呼叫時都要傳回新的 Runtime。
QDK 會啟動並關閉每個執行階段。
Note
deq轉接器需要:
- 一個已編碼的層
- 一個與測量無關的Clifford執行軌跡
- 穩定器後端
- 一個沒有量子位元損失的雜訊模型
deq 轉接器不支援重試政策。 不支援的節目串流會產生錯誤,而不會退回到其他解碼器。
拒絕低信賴度 deq 結果
deq 配接器會為每個邏輯讀數回傳一個分數。 分數越低,表示對所選修正的偏好越強。 這些分數並不是經過校正的失效機率。
要拒絕低信心結果,請在準備解碼器時傳入 max_readout_score,如下範例所示:
from functools import partial
from qdk.simulation import decoders
scored_decoder = partial(
decoders.prepare_deq_decoder,
max_readout_score=0.2,
)
results = run_qir(
qir,
qodec=protocol,
decoder=scored_decoder,
noise=noise,
type="stabilizer",
shots=1000,
on_shot_failure="discard",
)
只有當每個回傳的邏輯讀數分數都在或低於閾值時,執行階段才會接受 shot。 這個門檻不適用於原始旗標或未使用的中間讀數。
基於分數的剔除可以降低被接受的投籃的邏輯錯誤率。 但同時也減少了被接受的鏡頭數量,並增加了解碼工作。
編譯 OpenQASM 程式
標準OpenQASM運算使用與標準QIR運算相同的Q#助記法規則。
from qdk import TargetProfile, openqasm
source = """
OPENQASM 3.0;
include "stdgates.inc";
qubit q;
bit c;
x q;
c = measure q;
"""
qir = openqasm.compile(
source,
target_profile=TargetProfile.Adaptive_RI,
)
print(qir)
要透過 qodec 執行此程式,請確保 qodec 的頂端指令集具有 __quantum__qis__x__body 和 __quantum__qis__m__body,且區塊運算元相容且有一個測量結果。
OpenQASM一個名為 foo 的內在函式或子程式使用助記符 foo。 量子位元參數會繫結至區塊操作數。
float、int 與 bool 引數會依宣告順序繫結至指令參數。
OpenQASM 對 qodec 通話有以下限制:
- 自訂內建函式無法回傳 QIR
Result. 要得到一個測量結果,請使用標準measure陳述式。 -
OpenQASM 程式無法執行自訂測量、從一次呼叫中接收多個結果,或接收回傳的標記。 在這種情況下,請使用 Q#
@Measurement()運算。 - 執行階段控制程式無法接收的任何旗標 OpenQASM,這些旗標可能會使一次拍攝遭到拒絕。
如需詳細的對應範例,請參閱以下 QDK 筆記本:
審查要求與限制
在進行大型實驗前,請先檢視這些要求、限制與結果差異。
要求:
- 每個 QIR 量子呼叫都必須對應到頂層 qodec 指令。
- 執行前請審核該協定。 qodec執行時信任你寫的方程式,不會檢查它們。
Limitations:
- GPU 模擬不支援 qodec 執行。
- 預設的小工具故障集合會呈指數成長,因此精確距離搜尋可能需要很長時間。
- deq 和 Stim 套件有平台限制。 欲了解更多資訊,請參閱 安裝 QDK 以進行錯誤修正。
結果差異:
- 精確的輸出數量會因解碼器而異。
- 丟棄與重試政策可能會改變回傳的結果分布。
若要完整體驗含雜訊掃描、deq 解碼及基於置信度的拒判的 Q# 實驗,請參閱 QEC 協議攻略。