Qiskit汉化-2.3 Phase Kickback

相位反冲

1. 探索CNOT门

在上一节中,我们看到了CNOT门的一些非常基本的结果。这里我们将探索一些更有趣的结果。

我们看到,我们可以通过将控制量子比特置于$\ket{+}$状态来纠缠这两个量子比特:

CNOT\ket{0+} = \tfrac{1}{\sqrt{2}}(\ket{00} + \ket{11})

但是如果我们使第二个量子比特处于叠加态会发生什么?

from qiskit import QuantumCircuit, Aer, assemble
from math import pi
import numpy as np
from qiskit.visualization import plot_bloch_multivector, plot_histogram, array_to_latex
qc = QuantumCircuit(2)
qc.h(0)
qc.h(1)
qc.cx(0,1)
qc.draw()

1

在上述电路中,我们使CNOT作用于状态:

\ket{++} = \tfrac{1}{\sqrt{2}}(\ket{00} + \ket{01} + \ket{10} + \ket{11})

由于CNOT交换了 \ket{01}\ket{11} 的振幅 ,因此没有变化。

qc = QuantumCircuit(2)
qc.h(0)
qc.h(1)
qc.cx(0,1)
display(qc.draw())  # `display` is a command for Jupyter notebooks
                    # similar to `print`, but for rich content

# Let's see the result
svsim = Aer.get_backend('aer_simulator')
qc.save_statevector()
qobj = assemble(qc)
final_state = svsim.run(qobj).result().get_statevector()
display(array_to_latex(final_state, prefix="\\text{Statevector} = "))
plot_bloch_multivector(final_state)

2

Statevector = [\tfrac{1}{2} \quad \tfrac{1}{2} \quad \tfrac{1}{2} \quad \tfrac{1}{2}]

3

让我们使目标量子比特处于状态 \ket{-} ,所以它的相位是负的:

qc = QuantumCircuit(2)
qc.h(0)
qc.x(1)
qc.h(1)
qc.draw()

4

这创造了状态:

\ket{-+} = \tfrac{1}{\sqrt{2}}(\ket{00} + \ket{01} - \ket{10} - \ket{11})
qc = QuantumCircuit(2)
qc.h(0)
qc.x(1)
qc.h(1)
display(qc.draw())
# See the result
qc1 = qc.copy()
qc1.save_statevector()
final_state = svsim.run(qc1).result().get_statevector()
display(array_to_latex(final_state, prefix="\\text{Statevector} = "))
plot_bloch_multivector(final_state)

5

Statevector = [\tfrac{1}{2} \quad \tfrac{1}{2} \quad -\tfrac{1}{2} \quad -\tfrac{1}{2}]

6

如果CNOT作用于这个状态,将交换 \ket{01}\ket{11} 的振幅,产生的状态是:

\begin{aligned} CNOT\ket{-+} & = \tfrac{1}{2}(\ket{00} - \ket{01} - \ket{10} + \ket{11}) \\ & = \ket{--} \end{aligned}

这很有趣,因为它影响了控制量子比特的状态,而使目标量子比特的状态没有变化。

qc.cx(0,1)
display(qc.draw())

qc.save_statevector()
qobj = assemble(qc)
final_state = svsim.run(qobj).result().get_statevector()
display(array_to_latex(final_state, prefix="\\text{Statevector} = "))
plot_bloch_multivector(final_state)

7

Statevector = [\tfrac{1}{2} \quad -\tfrac{1}{2} \quad -\tfrac{1}{2} \quad \tfrac{1}{2}]

8

如果你还记得H门变换 \ket{+} \rightarrow \ket{0}\ket{-} \rightarrow \ket{1} ,我们可以看到在H门中包裹一个CNOT等价于一个CNOT反方向作用:

9

我们可以用Qiskit的Aer模拟器验证这一点:

qc = QuantumCircuit(2)
qc.h(0)
qc.h(1)
qc.cx(0,1)
qc.h(0)
qc.h(1)
display(qc.draw()) 

qc.save_unitary()
usim = Aer.get_backend('aer_simulator')
qobj = assemble(qc)
unitary = usim.run(qobj).result().get_unitary()
array_to_latex(unitary, prefix="\\text{Circuit = }\n")

10

Circuit = \begin{bmatrix} 1 \quad \ 0 \quad \ 0 \quad \ 0 \\ 0 \quad \ 1 \quad \ 0 \quad \ 0 \\ 0 \quad \ 0 \quad \ 0 \quad \ 1 \\ 0 \quad \ 0 \quad \ 1 \quad \ 0 \\ \end{bmatrix}
qc = QuantumCircuit(2)
qc.cx(1,0)
display(qc.draw())
qc.save_unitary()

qobj = assemble(qc)
unitary = usim.run(qobj).result().get_unitary()
array_to_latex(unitary, prefix="\\text{Circuit = }\n")

11

Circuit = \begin{bmatrix} 1 \quad \ 0 \quad \ 0 \quad \ 0 \\ 0 \quad \ 1 \quad \ 0 \quad \ 0 \\ 0 \quad \ 0 \quad \ 0 \quad \ 1 \\ 0 \quad \ 0 \quad \ 1 \quad \ 0 \\ \end{bmatrix}

这个特性是相位反冲的一个例子,它引导我们进入下一节…

2. 相位反冲

2.1 解释CNOT电路的特性

在上一节中,我们看到了这个特性:

12

这是一个反冲的例子(或者说,相位反冲),它非常重要,几乎在每个量子算法中都会用到。反冲是指通过一个门添加到一个量子比特的特征值通过一个受控的操作被 "踢回 "到另一个量子比特。例如,我们看到,在一个 \ket{-} 量子比特上执行一个X门会使其具有相位 -1

X\ket{-} = -\ket{-}

当我们的控制量子比特处于 \ket{0}\ket{1} ,这个相位会影响整个状态,然而它是一个全局相位,没有可观察到的影响:

\begin{aligned} CNOT\ket{-0} & = \ket{-} \otimes \ket{0} \\ & = \ket{-0} \\ \quad & \\ CNOT\ket{-1} & = X\ket{-} \otimes \ket{1} \\ & = -\ket{-} \otimes \ket{1} \\ & = -\ket{-1} \\ \end{aligned}

有趣的效果是当我们的控制量子比特处于叠加态时。位于 \ket{1} 方向上的控制量子比特的分量将该相位因子应用于对应的目标量子比特。这个应用的相位因子反过来又给控制量子比特引入了一个相对相位:

\begin{aligned} CNOT\ket{-+} & = \tfrac{1}{\sqrt{2}}(CNOT\ket{-0} + CNOT\ket{-1}) \\ & = \tfrac{1}{\sqrt{2}}(\ket{-0} + X\ket{-1}) \\ & = \tfrac{1}{\sqrt{2}}(\ket{-0} - \ket{-1}) \\ \end{aligned}

这就可以写成两个可分离的量子比特状态:

\begin{aligned} CNOT\ket{-+} & = \tfrac{1}{\sqrt{2}}(\ket{0} - \ket{1}) \\ & = \ket{--} \end{aligned}

将CNOT包裹在H门中,将量子比特的计算基变换为 (\ket{+}, \ket{-}) 基,在这里我们可以看到这种效果。这个特性在硬件中非常有用,因为有些硬件只允许两个特定的量子比特之间有一个方向的CNOTs。我们可以用这个特性来克服这个问题,允许双向的CNOTs。

2.2 T门的相位反冲

让我们来看看另一个受控操作——受控T门。

qc = QuantumCircuit(2)
qc.cp(pi/4, 0, 1)
qc.draw()

13

T门的矩阵为:

T = \begin{bmatrix} 1 & 0 \\ 0 & e^{i\pi/4}\\ \end{bmatrix}

受控T门的矩阵为:

Controlled-T = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & e^{i\pi/4}\\ \end{bmatrix}

我们可以用Qiskit的Aer模拟器验证这一点:

qc = QuantumCircuit(2)
qc.cp(pi/4, 0, 1)
display(qc.draw())
# See Results:
qc.save_unitary()
qobj = assemble(qc)
unitary = usim.run(qobj).result().get_unitary()
array_to_latex(unitary, prefix="\\text{Controlled-T} = \n")

14

Controlled-T = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & \tfrac{1}{\sqrt{2}}(1 + i) \\ \end{bmatrix}

更一般地说,我们可以使用以下规则找到任意受控U操作的矩阵:

\begin{aligned} U = \begin{bmatrix} u_{00} & u_{01} \\ u_{10} & u_{11} \\ \end{bmatrix} \end{aligned}
\begin{aligned} Controlled-U = \begin{bmatrix} I & 0 \\ 0 & U \\ \end{bmatrix} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & u_{00} & u_{01} \\ 0 & 0 & u_{10} & u_{11}\\ \end{bmatrix} \end{aligned}

或者,使用Qiskit的量子比特排序:

Controlled-U = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & u_{00} & 0 & u_{01} \\ 0 & 0 & 1 & 0 \\ 0 & u_{10} & 0 & u_{11}\\ \end{bmatrix}

如果我们将T型门应用于一个处于状态 \ket{1} 的量子比特时,我们会给这个量子比特增加一个 e^{i\pi/4} 的相位。

T\ket{1} = e^{i\pi/4}\ket{1}

这是不可观察的全局相位。但如果我们用另一个处于 \ket{+} 状态的量子比特来控制这个操作,相位就不再是全局的,而是相对的,这就改变了我们控制量子比特的相对相位

\begin{aligned} \ket{1+} & = \ket{1} \otimes \tfrac{1}{\sqrt{2}}(\ket{0} + \ket{1}) \\ & = \tfrac{1}{\sqrt{2}}(\ket{10} + \ket{11}) \\ & \\ Controlled-T\ket{1+} & = \tfrac{1}{\sqrt{2}}(\ket{10} + e^{i\pi/4}\ket{11}) \\ & \\ & = \ket{1} \otimes \tfrac{1}{\sqrt{2}}(\ket{0} + e^{i\pi/4}\ket{1}) \end{aligned}

这具有使我们的控制量子比特围绕Bloch球面的Z轴旋转的效果,而使目标量子比特保持不变。让我们在Qiskit中看看:

qc = QuantumCircuit(2)
qc.h(0)
qc.x(1)
display(qc.draw())
# See Results:
qc.save_statevector()
qobj = assemble(qc)
final_state = svsim.run(qobj).result().get_statevector()
plot_bloch_multivector(final_state)

15

qc = QuantumCircuit(2)
qc.h(0)
qc.x(1)
# Add Controlled-T
qc.cp(pi/4, 0, 1)
display(qc.draw())
# See Results:
qc.save_statevector()
qobj = assemble(qc)
final_state = svsim.run(qobj).result().get_statevector()
plot_bloch_multivector(final_state)

16

我们可以看到,最左边的量子比特按照预期围绕Bloch球面的Z轴旋转了 π/4 。在探索了这一行为之后,我们可能会明白为什么Qiskit会以这种对称的方式(两个控制而不是一个控制和一个目标)绘制受控Z旋转门。在所有情况下,都没有明确的控制或目标量子比特。

17

快速练习

  1. 如果目标量子比特(q1)处于状态 \ket{0} ,那么控制量子比特(q0)的最终状态是什么?(如下图所示电路)?用Qiskit来验证你的答案。
    18
  2. 如果目标量子比特(q1)处于状态 \ket{1} ,且电路使用受控Sdg门而不是受控T(如下图所示电路),控制量子比特(q0)会发生什么变化?
    19
  3. 在应用受控T(如下图所示电路)之前,如果控制量子比特(q0)处于状态 \ket{1} ,而不是状态 \ket{+} ,将会发生什么变化?
    20
import qiskit.tools.jupyter
%qiskit_version_table

版本信息

Qiskit Software Version
Qiskit 0.27.0
Terra 0.17.4
Aer 0.8.2
Ignis 0.6.0
Aqua 0.9.2
IBM Q Provider 0.14.0
System information
Python 3.7.7 (default, May 6 2020, 04:59:01) [Clang 4.0.1 (tags/RELEASE_401/final)]
OS Darwin
CPUs 8
Memory (Gb) 32.0

Fri Jun 18 18:38:49 2021 BST