qml.调试

该模块包含调试量子程序在模拟器设备上功能。

breakpoint

一个冻结执行并启动PennyLane调试器(PLDB)的函数。

debug_expval

计算量子电路当前点上可观测量的期望值。

debug_probs

计算量子电路当前点状态的概率分布。

debug_state

计算量子电路当前点的量子态。

debug_tape

访问量子电路的记录。

snapshots

该变换处理电路中包含的 Snapshot 实例,具体取决于执行设备的兼容性。

进入调试上下文

函数 breakpoint() 提供了一个接口,用于在执行过程中与量子电路进行交互和逐步执行。它通过提供对电路内部状态和 QuantumTape 的访问,允许更快速的调试。当电路操作应用时,功能在下面的示例电路中得到了突出展示。

 1import pennylane as qml
 2
 3@qml.qnode(qml.device('default.qubit', wires=(0,1,2)))
 4def circuit(x):
 5    qml.breakpoint()
 6
 7    qml.Hadamard(wires=0)
 8    qml.CNOT(wires=(0,2))
 9
10    for w in (0, 1, 2):
11        qml.RX(2*x, wires=w)
12
13    qml.breakpoint()
14    qml.RX(-x, wires=1)
15    return qml.sample()
16
17circuit(1.2345)

运行上述 python 脚本将在终端中打开交互式 [pldb] 提示符。当代码到达 qml.breakpoint() 时,它将暂停并启动一个交互式调试提示符。该提示符指定脚本的路径以及在断点之后要执行的下一行:

> /Users/your/path/to/script.py(7)circuit()
-> qml.Hadamard(wires=0)
[pldb]

在调试环境中控制代码执行

Pennylane调试器(PLDB)建立在原生python调试器(PDB)之上。因此,它具有相似的界面。我们可以使用内置命令与调试器进行交互,例如listlonglistnextcontinuequit。在量子函数作用域内定义的任何变量也可以从调试器中访问。

[pldb] print(x)
1.2345

list (和 longlist) 命令将打印出断点周围的一段代码,突出显示将要执行的下一行。这可以用于确定电路中执行的位置。

[pldb] longlist
  3         @qml.qnode(qml.device('default.qubit', wires=(0,1,2)))
  4         def circuit(x):
  5             qml.breakpoint()
  6
  7  ->         qml.Hadamard(wires=0)
  8             qml.CNOT(wires=(0,2))
  9
 10             for w in (0, 1, 2):
 11                 qml.RX(2*x, wires=w)
 12
 13             qml.breakpoint()
 14             qml.RX(-x, wires=1)
 15             return qml.sample()

命令 next 将执行下一行代码,并打印接下来要执行的行。在这个例子中,接下来要执行的操作是 CNOT

[pldb] next
> /Users/your/path/to/script.py(8)circuit()
-> qml.CNOT(wires=(0,2))
[pldb] list
  3         @qml.qnode(qml.device('default.qubit', wires=(0,1,2)))
  4         def circuit(x):
  5             qml.breakpoint()
  6
  7             qml.Hadamard(wires=0)
  8  ->         qml.CNOT(wires=(0,2))
  9
 10             for w in (0, 1, 2):
 11                 qml.RX(2*x, wires=w)
 12
 13             qml.breakpoint()

或者,continue 命令允许在断点之间跳转。该命令恢复 代码执行,直到达到下一个断点,或者如果没有断点则终止。最后,quit 命令结束调试提示并完全终止执行。

[pldb] continue
> /Users/your/path/to/script.py(14)circuit()
-> qml.RX(-x, wires=1)
[pldb] list
  9
 10             for w in (0, 1, 2):
 11                 qml.RX(2*x, wires=w)
 12
 13             qml.breakpoint()
 14  ->         qml.RX(-x, wires=1)
 15             return qml.sample()
 16
 17         circuit(1.2345)
[EOF]
[pldb] quit

提取电路信息

在调试提示中,我们可以使用 debug_tape() 提取关于量子带当前内容的信息。我们还可以使用 debug_expval()debug_state()debug_probs() 动态地对量子电路进行测量。

考虑上面的电路,

> /Users/your/path/to/script.py(7)circuit()
-> qml.Hadamard(wires=0)
[pldb] longlist
  3         @qml.qnode(qml.device('default.qubit', wires=(0,1,2)))
  4         def circuit(x):
  5             qml.breakpoint()
  6
  7  ->         qml.Hadamard(wires=0)
  8             qml.CNOT(wires=(0,2))
  9
 10             for w in (0, 1, 2):
 11                 qml.RX(2*x, wires=w)
 12
 13             qml.breakpoint()
 14             qml.RX(-x, wires=1)
 15             return qml.sample()
[pldb] next
> /Users/your/path/to/script.py(8)circuit()
-> qml.CNOT(wires=(0,2))
[pldb] next
> /Users/your/path/to/script.py(10)circuit()
-> for w in (0, 1, 2):
[pldb]

到目前为止应用的所有操作都记录在电路的 QuantumTape 中,可以使用 debug_tape() 进行访问。这可以用于 可视化 调试电路。

[pldb] qtape = qml.debug_tape()
[pldb] qtape.operations
[Hadamard(wires=[0]), CNOT(wires=[0, 2])]
[pldb] print(qtape.draw())
0: ──H─╭●─┤
2: ────╰X─┤

此时电路的量子状态可以使用 debug_state()提取。相关的概率分布 可以通过debug_probs()进行探测。

[pldb] qml.debug_state()
array([0.70710678+0.j, 0.        +0.j, 0.        +0.j, 0.        +0.j,
       0.        +0.j, 0.70710678+0.j, 0.        +0.j, 0.        +0.j])
[pldb] qml.debug_probs(wires=(0,2))
array([0.5, 0. , 0. , 0.5])

探测系统的另一种方法是通过测量可观测量来实现 debug_expval()

[pldb] qml.debug_expval(qml.Z(0))
0.0
[pldb] qml.debug_expval(qml.X(0) @ qml.X(2))
0.9999999999999996

此外,量子电路可以通过直接从提示中添加门进行动态更新。这允许用户实时修改电路 on-the-fly!

[pldb] continue
> /Users/your/path/to/script.py(14)circuit()
-> qml.RX(-x, wires=1)
[pldb] qtape = qml.debug_tape()
[pldb] print(qtape.draw(wire_order=(0,1,2)))
0: ──H─╭●──RX─┤
1: ────│───RX─┤
2: ────╰X──RX─┤
[pldb] qml.RZ(0.5*x, wires=0)
RZ(0.61725, wires=[0])
[pldb] qml.CZ(wires=(1,2))
CZ(wires=[1, 2])
[pldb] qtape = qml.debug_tape()
[pldb] print(qtape.draw(wire_order=(0,1,2)))
0: ──H─╭●──RX──RZ─┤
1: ────│───RX─╭●──┤
2: ────╰X──RX─╰Z──┤