測試和調試在量子程式設計中與在經典程式設計中一樣重要。 本文討論如何使用 Visual Studio Code (VS Code) 和 Jupyter Notebook 中的 Azure Quantum Development Kit (QDK) 偵錯和測試量子程式。
除錯量子程式
QDK 提供數個工具來偵錯程式碼。 如果您在 VS Code 中撰寫 Q# 或 OpenQASM 程式,則可以使用 VS Code 除錯器在程式中設定岔斷點並分析程式碼。 QDK 也提供一組轉儲函數,可用來取得程式中不同點的資訊。
如何使用 VS Code 偵錯工具
透過 VS Code 中的 QDK 延伸模組,您可以使用偵錯工具逐步執行程式碼並進入每個函式或作業、追蹤局部變數的值,以及追蹤量子位元的量子狀態。
下列範例示範如何在 Q# 程式中使用偵錯工具。 如需 VS Code 偵錯工具的完整資訊,請參閱 VS Code 網站上的 偵錯 。
在 VS Code 中,使用下列程式碼建立並儲存新
.qs檔案:import Std.Arrays.*; import Std.Convert.*; operation Main() : Result { use qubit = Qubit(); H(qubit); let result = M(qubit); Reset(qubit); return result; }在第 6 行 上,
H(qubit)按一下行號左側的 以設定中斷點。 出現一個紅色圓圈。在 [主要側邊列] 中,選擇偵錯工具圖示以開啟偵錯工具窗格,然後選擇 [執行和偵錯]。 偵錯工具控制列隨即出現。
按 F5 啟動偵錯工具,並繼續至岔斷點。 在偵錯工具窗格的 [變數] 功能表中,展開 [量子狀態] 下拉式清單,以查看量子位已在 $\ket{0}$ 狀態中初始化。
按 F11 進入
H作業。 作業的H原始程式碼隨即顯示。 請注意,當您逐步執行時,H會變更為疊加態。按 F10 以逐步執行
M作業。 請注意, 量子狀態 在測量之後解析為 $\ket{0}$ 或 $\ket{1}$。 變數result也會顯示在 [區域變數] 底下。再次按 F10 以略過
Reset作業。 請注意, 量子狀態 會重設為 $\ket{0}$。
當您完成探索偵錯工具時,請按 *Ctrl + F5 以結束偵錯工具。
注意
VS Code 除錯工具僅適用於 Q# (.qs) 和 OpenQASM (.qasm) 檔案。 您無法在 Jupyter Notebook 中的儲存格上使用 Q# VS Code 偵錯工具。
如何使用 QDK 傾印函數進行除錯
QDK 提供數個 Q# 以及 Python 函數,當您呼叫這些函數時,會輸出程式當前狀態的相關資訊。 使用這些轉儲功能中的資訊來檢查程式是否如預期般運作。
Q#
DumpMachine函數
DumpMachine 是一個 Q# 函數,可讓您在程式執行時將量子位元系統目前狀態的相關資訊轉儲到控制台。
DumpMachine 不會在運行時間停止或中斷您的程序。
下列範例會在DumpMachine程式中兩個點呼叫Q#,並檢視結果。
在 VS Code 中,使用下列程式碼建立並儲存新
.qs檔案:import Std.Diagnostics.*; operation Main() : Unit { use qubits = Qubit[2]; X(qubits[1]); H(qubits[1]); DumpMachine(); R1Frac(1, 2, qubits[0]); R1Frac(1, 3, qubits[1]); DumpMachine(); ResetAll(qubits); }按 Ctrl + Shift + Y 打開 調試控制台。
按 Ctrl + F5 運行您的程序。 下列
DumpMachine輸出會顯示在 偵錯主控台中:Basis | Amplitude | Probability | Phase ----------------------------------------------- |00⟩ | 0.7071+0.0000𝑖 | 50.0000% | 0.0000 |01⟩ | −0.7071+0.0000𝑖 | 50.0000% | -3.1416 Basis | Amplitude | Probability | Phase ----------------------------------------------- |00⟩ | 0.7071+0.0000𝑖 | 50.0000% | 0.0000 |01⟩ | −0.6533−0.2706𝑖 | 50.0000% | -2.7489
的 DumpMachine 輸出顯示了量子位元系統的狀態在每組閘之後如何變化。
注意
的 DumpMachine 輸出會使用大端排序。
Python dump_machine 函數
函數是 dump_machine Python 套件中的 qsharp 函數。 此函式會傳回目前配置的量子位計數,以及包含量子位系統稀疏狀態幅度的字典。
下列範例會執行與上一個 DumpMachine 範例相同的程式,但在 Jupyter Notebook 中執行,而不是 .qs 在檔案中執行。
在 VS Code 中,按 Ctrl + Shift + P 開啟 命令面板。
輸入 Create: New Jupyter Notebook ,然後按 Enter。 新的 Jupyter Notebook 索引標籤開啟。
在第一個儲存格中,複製並執行下列程式碼:
from qdk import qsharp建立新的程式碼儲存格,然後複製並執行下列 Q# 程式碼:
%%qsharp use qubits = Qubit[2]; X(qubits[0]); H(qubits[1]);建立新的程式碼儲存格。 複製並執行下列 Python 程式碼,以檢視程式中此時的量子位元狀態:
dump = qsharp.dump_machine() dump函式會
dump_machine顯示下列輸出:Basis State (|𝜓₁…𝜓ₙ⟩) Amplitude Measurement Probability Phase |10⟩ 0.7071+0.0000𝑖 50.0000% ↑ 0.0000 |11⟩ 0.7071+0.0000𝑖 50.0000% ↑ 0.0000建立新的程式碼儲存格,然後複製並執行下列 Q# 程式碼:
%%qsharp R1Frac(1, 2, qubits[0]); R1Frac(1, 3, qubits[1]);建立新的程式碼儲存格。 複製並執行下列 Python 程式碼,以檢視程式中此時的量子位元狀態:
dump = qsharp.dump_machine() dump函式會
dump_machine顯示下列輸出:Basis State (|𝜓₁…𝜓ₙ⟩) Amplitude Measurement Probability Phase |10⟩ 0.5000+0.5000𝑖 50.0000% ↗ 0.7854 |11⟩ 0.2706+0.6533𝑖 50.0000% ↗ 1.1781若要列印輸出的
dump_machine縮寫版本,請建立新儲存格並執行下列 Python 程式碼:print(dump)若要取得系統中的量子位元總數,請建立新的程式碼儲存格,並執行下列 Python 程式碼:
dump.qubit_count您可以存取具有非零振幅的個別量子位元狀態的振幅。 例如,建立新的程式碼儲存格並執行下列 Python 程式碼,以取得 $\ket$ 和 $\ket{10}{11}$ 狀態的個別振幅:
print(dump[2]) print(dump[3])
dump_operation 函式
函數是 dump_operation Python 套件中的 qsharp.utils 函數。 此函式會接受兩個輸入: Q# 運算或運算定義作為字串,以及運算中使用的量子位元數目。 輸出 dump_operation 是一個巢狀列表,代表對應於給定量子運算的複數方陣。 矩陣值位於計算基礎中,每個子清單代表矩陣的一列。
使用下列範例 dump_operation 顯示 1 量子位和 2 量子位系統的資訊。
在 VS Code 中,按 Ctrl + Shift + P 開啟 命令面板。
輸入 Create: New Jupyter Notebook ,然後按 Enter。 新的 Jupyter Notebook 索引標籤開啟。
在第一個儲存格中,複製並執行下列程式碼:
from qdk import qsharp from qsharp.utils import dump_operation若要顯示單一量子位閘門的矩陣元素,請呼叫
dump_operation並傳遞 1 以取得量子位元數目。 例如,在新的程式碼儲存格中複製並執行下列 Python 程式碼,以取得身分閘道和 Hadamard 閘道的矩陣元素:res = dump_operation("qs => ()", 1) print("Single-qubit identity gate:\n", res) print() res = dump_operation("qs => H(qs[0])", 1) print("Single-qubit Hadamard gate:\n", res)您也可以呼叫函數
qsharp.eval,然後參考 Q# 操作以dump_operation取得相同的結果。 例如,建立新的程式碼儲存格,然後複製並執行下列 Python 程式碼,以列印單一量子位元 Hadamard 閘的矩陣元素:qsharp.eval("operation SingleH(qs : Qubit[]) : Unit { H(qs[0]) }") res = dump_operation("SingleH", 1) print("Single-qubit Hadamard gate:\n", res)若要顯示雙量子位閘門的矩陣元素,請呼叫
dump_operation並傳遞 2 以取得量子位元數目。 例如,在新的程式碼儲存格中複製並執行下列 Python 程式碼,以取得受控 Ry 作業的矩陣元素,其中第二個量子位是 target 量子位:qsharp.eval ("operation ControlRy(qs : Qubit[]) : Unit { Controlled Ry([qs[0]], (0.5, qs[1])); }") res = dump_operation("ControlRy", 2) print("Controlled Ry rotation gate:\n", res)
如需如何測試及偵錯您的程式碼的更多範例,請查看 QDK 範例中的 dump_operation。
測試您的量子程式碼
QDK 提供數個 Q# 函數和作業,可用來在程式碼執行時測試程式碼。 您也可以為程式撰寫 Q# 單元測試。
fail 運算式
運算式 fail 會立即結束您的程式。 若要將測試併入程式碼中,請使用條件語句內的 fail 運算式。
下列範例使用 fail 陳述式來測試量子位元陣列是否正好包含 3 個量子位元。 當測試未通過時,程式會以錯誤訊息結束。
在 VS Code 中,使用下列程式碼建立並儲存新
.qs檔案:operation Main() : Unit { use qs = Qubit[6]; let n_qubits = Length(qs); if n_qubits != 3 { fail $"The system should have 3 qubits, not {n_qubits}."; } }按 Ctrl + F5 運行程序。 您的程式失敗,且下列輸出會出現在 偵錯主控台中:
Error: program failed: The system should have 3 qubits, not 6.從
Qubit[6]編輯Qubit[3]程式碼,儲存檔案,然後按 Ctrl + F5 再次執行程式。 程式執行時沒有錯誤,因為測試通過了。
Fact 函式
您也可以使用 Q#Fact 命名空間中的 Std.Diagnostics 函式來測試程式碼。 此函式接受 Fact 布林運算式和一個錯誤訊息字串。 如果布林運算式為 true,則測試會通過,且程式會繼續執行。 如果布林運算式為 false,則 Fact 結束程式並顯示錯誤訊息。
若要在先前的程式碼中執行相同的陣列長度測試,使用 Fact 函數,請遵循下列步驟:
在 VS Code 中,使用下列程式碼建立並儲存新
.qs檔案:import Std.Diagnostics.Fact; operation Main() : Unit { use qs = Qubit[6]; let n_qubits = Length(qs); Fact(n_qubits == 3, $"The system should have 3 qubits, not {n_qubits}.") }按 Ctrl + F5 運行程序。 中的
Fact測試條件未通過,且錯誤訊息會出現在 偵錯主控台中。從
Qubit[6]編輯Qubit[3]程式碼,儲存檔案,然後按 Ctrl + F5 再次執行程式。 測試Fact條件會通過,且您的程式執行時不會發生錯誤。
使用標註 Q# 撰寫 @Test() 單元測試
在Q#程式中,您可以將@Test()註解套用至可呼叫項(函數或操作),從而將其轉換為單元測試。 這些單元測試會出現在 VS Code 的 [測試] 功能表中,以便您可以利用此 VS Code 功能。 只有在可呼叫項目不採用輸入參數時,您才能將可呼叫項目轉換為單元測試。
下列範例會將陣列長度測試程式碼包裝在作業中,並將該作業轉換為單元測試:
在 VS Code 中,使用下列程式碼建立並儲存新
.qs檔案:import Std.Diagnostics.Fact; @Test() operation TestCase() : Unit { use qs = Qubit[3]; let n_qubits = Length(qs); Fact(n_qubits == 3, $"The system should have 3 qubits, not {n_qubits}."); }@Test()作業定義之前TestCase行上的註釋會將作業轉換為 VS Code 單元測試。 作業定義行上會出現綠色箭頭。選擇綠色箭號以執行
TestCase並報告測試結果。若要在 VS Code 測試檢視器中與單元測試互動,請選擇主要側邊列中的測試燒瓶圖示。
請將您的程式碼從
Qubit[3]編輯為Qubit[6],然後再次執行單元測試,以查看測試資訊如何變更。
您可以在 VS Code 中撰寫和執行 Q# 單元測試,而不需要程式中的進入點作業。
注意
Std.Diagnostics 命名空間中的可調用項目與 QIR 生成不相容,因此請僅在模擬器上運行的程式碼中包含單元測試。 如果您想要從程式碼產生 Q# QIR,請勿在程式碼中包含單元測試。
這些CheckZero和CheckAllZero操作
CheckZero作業和CheckAllZeroQ#作業會檢查量子位元或量子位元陣列的目前狀態是否為 $\ket{0}$。 此CheckZero作業會採用單一量子位,只有在量子位處於 $\kettrue$ 狀態時才會傳回{0}。 這些CheckAllZero作業會採用量子位陣列,並且只有在陣列中的所有量子位都處於 $\kettrue$ 狀態時才會傳回{0}。 若要使用 CheckZero 和 CheckAllZero,請從命名空間匯 Std.Diagnostics 入它們。
下列範例會使用這兩個作業。
CheckZero 測試X作業是否能將第一個量子比特從 $\ket{0}$ 狀態翻轉至 $\ket{1}$ 狀態,而CheckAllZero作業測試兩個量子比特是否重設為 $\ket{0}$ 狀態。
在 VS Code 中,使用下列程式碼建立並儲存新 .qs 檔案,然後執行程式並在 偵錯主控台中檢查輸出。
import Std.Diagnostics.*;
operation Main() : Unit {
use qs = Qubit[2];
X(qs[0]);
if CheckZero(qs[0]) {
Message("X operation failed");
}
else {
Message("X operation succeeded");
}
ResetAll(qs);
if CheckAllZero(qs) {
Message("Reset operation succeeded");
}
else {
Message("Reset operation failed");
}
}