你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
如何调试和测试量子代码
与经典编程一样,能够检查量子程序是否按预期方式运行,并且能够诊断不正确的行为是至关重要的。 本文讨论 Azure Quantum Development Kit 提供用于测试和调试量子程序的工具。
Q#调试程序
Azure Quantum Development Kit (QDK) Visual Studio Code 扩展包括程序 Q# 调试器。 可以设置断点、单步执行代码并进入每个函数或操作,不仅跟踪局部变量,还可以跟踪量子比特的量子态。
注意
VS Code 调试器仅适用于 Q# (.qs) 文件,不适用于 Q# Jupyter Notebook 中的单元格。 若要测试 Jupyter Notebook 单元格,请参阅 测试代码。
以下示例演示调试器的基本功能。 有关使用 VS Code 调试器的完整信息,请参阅 “调试”。
在 VS Code 中,使用以下代码创建并保存新的 .qs 文件:
import Microsoft.Quantum.Arrays.*;
import Microsoft.Quantum.Convert.*;
operation Main() : Result {
use qubit = Qubit();
H(qubit);
let result = M(qubit);
Reset(qubit);
return result;
}
- 通过单击行号左侧的行设置断点
H(qubit)
。 - 选择调试器图标以打开调试器窗格,然后选择“运行”和“ 调试”。 调试器控件显示在屏幕顶部。
- 选择 F5 以开始调试并继续到断点。 在调试器 “变量 ”窗格中,展开 “量子状态 ”类别。 可以看到量子比特已初始化为 |0> 状态。
- 单步执行操作并显示操作的源代码
H
( F11H
)。 在逐步执行操作时,请注意,当操作将量子位置于叠加状态时H
,量子值会发生变化。 - 执行操作时(F10)
M
将量子值解析为 |0> 或 |1> ,并显示经典变量result
的值。 - 单步执行
Reset
操作时,量子位将重置为 |0>。
测试代码
尽管 VS Code Q# 调试器不适用于 Q# Jupyter Notebook 中的单元格,但 Azure QDK 提供了一些表达式和函数,可帮助对代码进行故障排除。
Fail 表达式
表达式 fail
完全结束计算,这与停止程序的致命错误相对应。
请考虑验证参数值的简单示例:
# import qsharp package to access the %%qsharp magic command
import qsharp
// use the %%qsharp magic command to change the cell type from Python to Q#
%%qsharp
function PositivityFact(value : Int) : Unit {
if value <= 0 {
fail $"{value} isn't a positive number.";
}
}
PositivityFact(0);
Error: program failed: 0 isn't a positive number.
Call stack:
at PositivityFact in line_2
Qsc.Eval.UserFail
× runtime error
╰─▶ program failed: 0 isn't a positive number.
╭─[line_2:5:1]
5 │
6 │ fail $"{value} isn't a positive number.";
· ────────────────────┬───────────────────
· ╰── explicit fail
7 │ }
╰────
在这里,表达式 fail
阻止程序继续运行无效数据。
Fact() 函数
可以使用命名空间中的Fact()
Microsoft.Quantum.Diagnostics
函数实现与上一示例相同的行为。 该 Fact()
函数计算给定的经典条件,如果为 false,则会引发异常。
import qsharp
%%qsharp
function PositivityFact(value : Int) : Unit {
Fact(value > 0, "Expected a positive number.");
}
PositivityFact(4);
Error: program failed: Expected a positive number.
Call stack:
at Microsoft.Quantum.Diagnostics.Fact in diagnostics.qs
at PositivityFact in line_4
Qsc.Eval.UserFail
× runtime error
╰─▶ program failed: Expected a positive number.
╭─[diagnostics.qs:29:1]
29 │ if (not actual) {
30 │ fail message;
· ──────┬─────
· ╰── explicit fail
31 │ }
╰────
DumpMachine() 函数
DumpMachine()
是一个 Q# 函数,可用于将有关计算机当前状态 target 的信息转储到控制台并继续运行程序。
注意
随着 Azure Quantum Development Kit的发布,该 DumpMachine()
函数现在对其输出使用 big-endian 排序。
import qsharp
%%qsharp
import Microsoft.Quantum.Diagnostics.*;
operation MultiQubitDumpMachineDemo() : 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);
}
MultiQubitDumpMachineDemo();
Basis State
(|𝜓₁…𝜓ₙ⟩) Amplitude Measurement Probability Phase
|00⟩ 0.7071+0.0000𝑖 50.0000% ↑ 0.0000
|01⟩ −0.7071+0.0000𝑖 50.0000% ↓ -3.1416
Basis State
(|𝜓₁…𝜓ₙ⟩) Amplitude Measurement Probability Phase
|00⟩ 0.7071+0.0000𝑖 50.0000% ↑ 0.0000
|01⟩ −0.6533−0.2706𝑖 50.0000% ↙ -2.7489
dump_machine() 函数
dump_machine
是一个 Python 函数,它返回当前分配的量子比特计数和可分析的稀疏状态振幅的 Python 字典。 使用 Jupyter Notebook 中的任一函数,可以像调试器一样逐步执行操作。 使用前面的示例程序:
import qsharp
%%qsharp
use qubits = Qubit[2];
X(qubits[0]);
H(qubits[1]);
dump = qsharp.dump_machine()
dump
Basis State
(|𝜓₁…𝜓ₙ⟩) Amplitude Measurement Probability Phase
|10⟩ 0.7071+0.0000𝑖 50.0000% ↑ 0.0000
|11⟩ 0.7071+0.0000𝑖 50.0000% ↑ 0.0000
%%qsharp
R1Frac(1, 2, qubits[0]);
R1Frac(1, 3, qubits[1]);
dump = qsharp.dump_machine()
dump
Basis State
(|𝜓₁…𝜓ₙ⟩) Amplitude Measurement Probability Phase
|10⟩ 0.5000+0.5000𝑖 50.0000% ↗ 0.7854
|11⟩ 0.2706+0.6533𝑖 50.0000% ↗ 1.1781
# you can print an abbreviated version of the values
print(dump)
STATE:
|10⟩: 0.5000+0.5000𝑖
|11⟩: 0.2706+0.6533𝑖
# you can access the current qubit count
dump.qubit_count
2
# you can access individual states by their index
dump[2]
(0.5+0.5000000000000001j)
dump[3]
(0.27059805007309845+0.6532814824381883j)
CheckZero() 和 CheckAllZero() 操作
CheckZero()
以及CheckAllZero()
Q#可以检查量子比特或量子比特数组的当前状态是 $\ket{0}$的操作。 CheckZero()
true
如果量子比特处于 $\ket{0}$ 状态,并且它处于任何其他状态,则false
返回。 CheckAllZero()
如果 true
数组中的所有量子比特都处于 $\ket{0}$ 状态,并且 false
量子比特处于任何其他状态,则返回。
import Microsoft.Quantum.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");
}
}
dump_operation() 函数
dump_operation
是一个 Python 函数,它采用操作或操作定义,以及要使用的多个量子位,并返回表示操作输出的复数的平方矩阵。
从qsharp.utils
中导入 dump_operation
。
import qsharp
from qsharp.utils import dump_operation
此示例打印单量子比特标识门和 Hadamard 门的矩阵。
res = dump_operation("qs => ()", 1)
print(res)
res = dump_operation("qs => H(qs[0])", 1)
print(res)
[[(1+0j), 0j], [0j, (1+0j)]]
[[(0.707107+0j), (0.707107+0j)], [(0.707107+0j), (-0.707107-0j)]]
还可以使用 qsharp.eval()
定义函数或操作,然后从中 dump_operation
引用它。 前面表示的单个量子比特也可以表示为
qsharp.eval("operation SingleQ(qs : Qubit[]) : Unit { }")
res = dump_operation("SingleQ", 1)
print(res)
[[(1+0j), 0j], [0j, (1+0j)]]
此示例使用 Controlled Ry
门将旋转应用到第二个量子位
qsharp.eval ("operation ControlRy(qs : Qubit[]) : Unit {qs[0]; Controlled Ry([qs[0]], (0.5, qs[1]));}")
res = dump_operation("ControlRy", 2)
print(res)
[[(1+0j), 0j, 0j, 0j], [0j, (1+0j), 0j, 0j], [0j, 0j, (0.968912+0j), (-0.247404+0j)], [0j, 0j, (0.247404+0j), (0.968912+0j)]]
以下代码定义 Q# 操作 ApplySWAP
,并输出其矩阵以及双量子比特标识操作的矩阵。
qsharp.eval("operation ApplySWAP(qs : Qubit[]) : Unit is Ctl + Adj { SWAP(qs[0], qs[1]); }")
res = dump_operation("qs => ()", 2)
print(res)
res = dump_operation("ApplySWAP", 2)
print(res)
[[(1+0j), 0j, 0j, 0j], [0j, (1+0j), 0j, 0j], [0j, 0j, (1+0j), 0j], [0j, 0j, 0j, (1+0j)]]
[[(1+0j), 0j, 0j, 0j], [0j, 0j, (1+0j), 0j], [0j, (1+0j), 0j, 0j], [0j, 0j, 0j, (1+0j)]]
可以在 QDK 中的“测试操作”示例页中找到更多使用dump_operation()
测试操作的示例。