qml.workflow¶
模块
该模块包含管理PennyLane工作流程的核心对象。
执行函数和工具¶
|
一个在支持自动微分的设备上执行一批录音带的函数。 |
|
为变换程序中的指定阶段构建磁带。 |
|
构建指定阶段的磁带批次和后处理,以用于转换程序。 |
|
在指定级别提取转换程序。 |
|
返回一个函数,该函数计算特定 QNode 的“最佳”微分方法。 |
雅可比乘积计算¶
提供计算带子和切线/余切线的雅可比矩阵之间的JVP/VJP的方法。 |
|
|
通过梯度变换计算VJPs、JVPs和雅可比矩阵 |
|
通过提供的雅可比计算雅可比乘积。 |
|
使用本地设备方法计算雅可比乘积。 |
返回类型规范¶
本节描述了在PennyLane中执行量子电路时数值输出的形状和类型。
该规范适用于整个工作流程,从设备实例一直到 QNode。 与给定电路相对应的结果对象将匹配,无论电路是传递到设备、由变换处理、其导数绑定到 ML 接口,还是从 QNode 返回。
虽然本节提到 tuple 并在本文档中包含使用 tuple 的示例,但返回类型规范允许 tuple 和 list 可以互换使用。在检查和后处理结果时,您总是应该允许 list 被替代为 tuple。考虑到它们的性能提升和对意外副作用的保护,建议在可行的情况下使用 tuple 而不是 list。
外部维度到内部维度的嵌套为:
批处理中的量子带。这个维度对于一批带子总是存在的。
在射击向量中的射击选择。如果没有射击向量,则此维度将不存在。
量子带中的测量。如果量子带只有一个测量,则此维度将不存在。
参数广播。如果没有参数广播,则不存在。增加数组形状,而不是增加元组嵌套。
基本测量形状。
个体测量¶
每个单独的测量对应其自身类型的结果。这个结果可以是类似于张量的(Python 数字,numpy 数组,ML 数组),但也可以是任何其他类型的对象。例如,CountsMP 对应一个字典。我们还可以想象一个场景,其中一个测量对应某种其他类型的自定义数据结构。
>>> def example_value(m):
... tape = qml.tape.QuantumScript((), (m,), shots=50)
... return qml.device('default.qubit').execute(tape)
>>> example_value(qml.probs(wires=0))
array([1., 0.])
>>> example_value(qml.expval(qml.Z(0)))
1.0
>>> example_value(qml.counts(wires=0))
{'0': 50}
>>> example_value(qml.sample(wires=0))
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0])
空白线路¶
某些测量允许在所有可用的线缆上进行广播,如 qml.probs()、qml.sample() 或 qml.state()。在这种情况下,测量过程实例应具有空线缆。结果对象的形状可能由设备或电路中存在的其他操作决定。
>>> qml.probs().wires
Wires([])
>>> tape = qml.tape.QuantumScript([qml.S(0)], (qml.probs(),))
>>> qml.device('default.qubit').execute(tape)
array([1., 0.])
>>> qml.device('default.mixed', wires=(0,1,2)).execute(tape)
array([1., 0., 0., 0., 0., 0., 0., 0.])
广播¶
参数广播为数字数组本身添加了一个前置维度。
如果对应的录音带有一个 batch_size 并且结果对象是数值型的,那么数值对象应该获得一个主维度。请注意,批量大小为 1 仍然是一个批量大小,并且仍然应该对应于一个主维度。
>>> op = qml.RX((0, np.pi/4, np.pi/2), wires=0)
>>> tape = qml.tape.QuantumScript((op,), [qml.probs(wires=0)])
>>> result = qml.device('default.qubit').execute(tape)
>>> result
array([[1. , 0. ],
[0.85355339, 0.14644661],
[0.5 , 0.5 ]])
>>> result.shape
(3, 2)
>>> tape = qml.tape.QuantumScript((op,), [qml.expval(qml.Z(0))])
>>> result = qml.device('default.qubit').execute(tape)
>>> result
array([1.00000000e+00, 7.07106781e-01, 2.22044605e-16])
>>> result.shape
(3,)
非张量数组可能以不同的方式处理广播。对于 CountsMP 的 'default.qubit' 输出是一个字典列表,但当与 broadcast_expand() 一起使用时,结果对象变为 numpy.ndarray 的数据类型 object。
>>> tape = qml.tape.QuantumScript((op,), (qml.counts(),), shots=50)
>>> result = qml.device('default.qubit').execute(tape)
>>> result
[{'0': 50}, {'0': 46, '1': 4}, {'0': 32, '1': 18}]
>>> batch, fn = qml.transforms.broadcast_expand(tape)
>>> fn(qml.device('default.qubit').execute(batch))
array([{'0': 50}, {'0': 39, '1': 11}, {'0': 28, '1': 22}], dtype=object)
单磁带¶
如果录音带只有一个测量,那么对应的结果简单地遵循上述规范。否则,单个录音带的结果是一个 tuple,其中每个条目对应于每个相应的测量。在下面的示例中,第一个条目对应于第一个测量过程 qml.expval(qml.Z(0)),第二个条目对应于第二个测量过程 qml.probs(wires=0),第三个结果对应于第三个测量过程 qml.state()。
>>> tape = qml.tape.QuantumScript((), (qml.expval(qml.Z(0)), qml.probs(wires=0), qml.state()))
>>> qml.device('default.qubit').execute(tape)
(1.0, array([1., 0.]), array([1.+0.j, 0.+0.j]))
射击向量¶
当存在一个射击向量 shots.has_partitioned_shot 时,测量结果变为一个元组,其中每个条目对应于不同的射击值。
>>> measurements = (qml.expval(qml.Z(0)), qml.probs(wires=0))
>>> tape = qml.tape.QuantumScript((), measurements, shots=(50,50,50))
>>> result = qml.device('default.qubit').execute(tape)
>>> result
((1.0, array([1., 0.])), (1.0, array([1., 0.])), (1.0, array([1., 0.])))
>>> result[0]
(1.0, array([1., 0.]))
>>> tape = qml.tape.QuantumScript((), [qml.counts(wires=0)], shots=(1, 10, 100))
>>> qml.device('default.qubit').execute(tape)
({'0': 1}, {'0': 10}, {'0': 100})
让我们看一个包含所有层次结构的例子。在这里,我们有一个批量大小为 3 的带子,三种不同的测量,具有不同的基本形状,以及一个包含三个不同值的射击向量。
>>> op = qml.RX((1.2, 2.3, 3.4), 0)
>>> ms = (qml.expval(qml.Z(0)), qml.probs(wires=0), qml.counts())
>>> tape = qml.tape.QuantumScript((op,), ms, shots=(1, 100, 1000))
>>> result = qml.device('default.qubit').execute(tape)
>>> result
((array([ 1., -1., -1.]),
array([[1., 0.],
[0., 1.],
[0., 1.]]),
[{'0': 1}, {'1': 1}, {'1': 1}]),
(array([ 0.3 , -0.66, -0.98]),
array([[0.61, 0.39],
[0.13, 0.87],
[0.03, 0.97]]),
[{'0': 61, '1': 39}, {'0': 13, '1': 87}, {'0': 3, '1': 97}]),
(array([ 0.364, -0.648, -0.962]),
array([[0.669, 0.331],
[0.165, 0.835],
[0.012, 0.988]]),
[{'0': 669, '1': 331}, {'0': 165, '1': 835}, {'0': 12, '1': 988}]))
>>> result[0][0] # first shot value, first measurement
array([ 1., -1., -1.])
>>> result[0][0][0] # first shot value, first measurement, and parameter of 1.2
1.0
>>> result[1][2] # second shot value, third measurement, all three parameter values
[{'0': 74, '1': 26}, {'0': 23, '1': 77}, {'1': 100}]
批处理¶
一个批次是多个磁带的元组或列表。在这种情况下,结果应该始终是一个元组,其中每个条目对应于相应磁带的结果。
>>> tape1 = qml.tape.QuantumScript([qml.X(0)], [qml.state()])
>>> tape2 = qml.tape.QuantumScript([qml.Hadamard(0)], [qml.counts()], shots=100)
>>> tape3 = qml.tape.QuantumScript([], [qml.expval(qml.Z(0)), qml.expval(qml.X(0))])
>>> batch = (tape1, tape2, tape3)
>>> qml.device('default.qubit').execute(batch)
(array([0.+0.j, 1.+0.j]), {'0': 50, '1': 50}, (1.0, 0.0))