#原理暂时缺,可以参考尼尔森的书。
#经典状态的传输,只需要拷贝一份,发送给对方就行
#但是量子信息不允许克隆(量子不可克隆定理)
#但是我们利用纠缠信道和经典信道对量子信息进行传态。量子隐形传态。
#引入必要的包
import numpy as np
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister, execute, BasicAer, IBMQ, Aer
from qiskit.visualization import plot_histogram, plot_bloch_multivector
from qiskit.extensions import Initialize
from qiskit_textbook.tools import random_state, array_to_latex
#创建量子电路
qr = QuantumRegister(3) #需要三个量子寄存器
crz = ClassicalRegister(1)#一个经典量子比特
crx = ClassicalRegister(1)#第二个经典信道
teleportation_qc = QuantumCircuit(qr, crz, crx)
#创建Bell 纠缠态
def create_bell_pair(qc, a, b):
qc.h(a)
qc.cx(a,b)
create_bell_pair(teleportation_qc, 1,2) #第1个QuantumRegister 用于成那代传的量子态
#第2个和第三个量子比特形成纠缠态
teleportation_qc.draw()
q2_0: ────────── ┌───┐ q2_1: ┤ H ├──■── └───┘┌─┴─┐ q2_2: ─────┤ X ├ └───┘ c4: 1/══════════ c5: 1/══════════
#Alice 在q_1上应用一个由q_0控制的受控非门,然后Alice再应用一个Hadamard门作用到q_0上。
def alice_gates(qc, psi, a):
qc.cx(psi, a)
qc.h(psi)
teleportation_qc.barrier()
alice_gates(teleportation_qc, 0, 1)
teleportation_qc.draw()
░ ┌───┐ q2_0: ───────────░───■──┤ H ├ ┌───┐ ░ ┌─┴─┐└───┘ q2_1: ┤ H ├──■───░─┤ X ├───── └───┘┌─┴─┐ ░ └───┘ q2_2: ─────┤ X ├─░─────────── └───┘ ░ c4: 1/═══════════════════════ c5: 1/═══════════════════════
#定义测量,实际上这里的电路的建立实际上时非常深奥的,尤其是要理解,虽然公式写法不同,但量子电路
#依旧发生了改变了,改变的莫名其妙。我的理解实际上完成了一次Bell基测量。
def measure_and_send(qc, a, b):
qc.barrier()
qc.measure(a, 0)
qc.measure(b, 1)
measure_and_send(teleportation_qc, 0,1)
teleportation_qc.draw()
░ ┌───┐ ░ ┌─┐ q2_0: ───────────░───■──┤ H ├─░─┤M├─── ┌───┐ ░ ┌─┴─┐└───┘ ░ └╥┘┌─┐ q2_1: ┤ H ├──■───░─┤ X ├──────░──╫─┤M├ └───┘┌─┴─┐ ░ └───┘ ░ ║ └╥┘ q2_2: ─────┤ X ├─░────────────░──╫──╫─ └───┘ ░ ░ ║ ║ c4: 1/═══════════════════════════╩══╬═ 0 ║ ║ c5: 1/══════════════════════════════╩═ 0
#经典操作加上判断
def bob_gates(qc, qubit, crz, crx):
qc.x(qubit).c_if(crx, 1)
qc.z(qubit).c_if(crz, 1)
#这段代码十分优雅,也十分有用。
bob_gates(teleportation_qc, 2, crz, crx)
teleportation_qc.draw()
░ ┌───┐ ░ ┌─┐ q2_0: ───────────░───■──┤ H ├─░─┤M├───────────────── ┌───┐ ░ ┌─┴─┐└───┘ ░ └╥┘┌─┐ q2_1: ┤ H ├──■───░─┤ X ├──────░──╫─┤M├────────────── └───┘┌─┴─┐ ░ └───┘ ░ ║ └╥┘ ┌───┐ ┌───┐ q2_2: ─────┤ X ├─░────────────░──╫──╫──┤ X ├──┤ Z ├─ └───┘ ░ ░ ║ ║ └─╥─┘ └─╥─┘ ║ ║ ║ ┌──╨──┐ c4: 1/═══════════════════════════╩══╬════╬═══╡ = 1 ╞ 0 ║ ┌──╨──┐└─────┘ c5: 1/══════════════════════════════╩═╡ = 1 ╞═══════ 0 └─────┘
#现在开始仿真
psi = random_state(1)
display(array_to_latex(psi))
plot_bloch_multivector(psi)
#这里又得到了呈现变量数值的方法。
$\displaystyle
\begin{bmatrix}
-0.48157 - 0.2293i \
0.39904 - 0.74584i
\end{bmatrix}
$
None
/home/yquqing/anaconda3/envs/qiskit/lib/python3.8/site-packages/qiskit/visualization/bloch.py:68: MatplotlibDeprecationWarning:
The M attribute was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use self.axes.M instead.
x_s, y_s, _ = proj3d.proj_transform(xs3d, ys3d, zs3d, renderer.M)
用Bloch 球显示量子比特。
init_gate = Initialize(psi)
init_gate.label ="init"
## SETUP
qr = QuantumRegister(3, name="q") # Protocol uses 3 qubits
crz = ClassicalRegister(1, name="crz") # and 2 classical registers
crx = ClassicalRegister(1, name="crx")
qc = QuantumCircuit(qr, crz, crx)
## STEP 0
# First, let's initialize Alice's q0
qc.append(init_gate, [0]) #增加自定义门的方法
qc.barrier()
## STEP 1
# Now begins the teleportation protocol
create_bell_pair(qc, 1, 2)
qc.barrier()
## STEP 2
# Send q1 to Alice and q2 to Bob
alice_gates(qc, 0, 1)
## STEP 3
# Alice then sends her classical bits to Bob
measure_and_send(qc, 0, 1)
## STEP 4
# Bob decodes qubits
bob_gates(qc, 2, crz, crx)
# Display the circuit
qc.draw()
┌─────────────────────────────────────────┐ ░ ░ ┌───┐ ░ » q_0: ┤ init(-0.48157-0.2293j,0.39904-0.74584j) ├─░────────────░───■──┤ H ├─░─» └─────────────────────────────────────────┘ ░ ┌───┐ ░ ┌─┴─┐└───┘ ░ » q_1: ────────────────────────────────────────────░─┤ H ├──■───░─┤ X ├──────░─» ░ └───┘┌─┴─┐ ░ └───┘ ░ » q_2: ────────────────────────────────────────────░──────┤ X ├─░────────────░─» ░ └───┘ ░ ░ » crz: 1/════════════════════════════════════════════════════════════════════════» » crx: 1/════════════════════════════════════════════════════════════════════════» » « ┌─┐ « q_0: ┤M├───────────────── « └╥┘┌─┐ « q_1: ─╫─┤M├────────────── « ║ └╥┘ ┌───┐ ┌───┐ « q_2: ─╫──╫──┤ X ├──┤ Z ├─ « ║ ║ └─╥─┘ └─╥─┘ « ║ ║ ║ ┌──╨──┐ «crz: 1/═╩══╬════╬═══╡ = 1 ╞ « 0 ║ ┌──╨──┐└─────┘ «crx: 1/════╩═╡ = 1 ╞═══════ « 0 └─────┘
#用Aer进行simulator
sim = Aer.get_backend('aer_simulator')
qc.save_statevector()
out_vector = sim.run(qc).result().get_statevector()
plot_bloch_multivector(out_vector)
/home/yquqing/anaconda3/envs/qiskit/lib/python3.8/site-packages/qiskit/visualization/bloch.py:68: MatplotlibDeprecationWarning:
The M attribute was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use self.axes.M instead.
x_s, y_s, _ = proj3d.proj_transform(xs3d, ys3d, zs3d, renderer.M)
Bloch球显示的量子比特
#计数方法,因上面的方法无法实现计数功能,因此想出了一个验证方法,如果,加入一个段电路,能够实现,init函数
#的逆,那么可以凭借是否接近100%的概率输出|0>,来判断电路的可行性。
## SETUP
inverse_init_gate = init_gate.gates_to_uncompute()#实现了初始函数的逆运算。
qr = QuantumRegister(3, name="q") # Protocol uses 3 qubits
crz = ClassicalRegister(1, name="crz") # and 2 classical registers
crx = ClassicalRegister(1, name="crx")
qc = QuantumCircuit(qr, crz, crx)
## STEP 0
# First, let's initialize Alice's q0
qc.append(init_gate, [0])
qc.barrier()
## STEP 1
# Now begins the teleportation protocol
create_bell_pair(qc, 1, 2)
qc.barrier()
## STEP 2
# Send q1 to Alice and q2 to Bob
alice_gates(qc, 0, 1)
## STEP 3
# Alice then sends her classical bits to Bob
measure_and_send(qc, 0, 1)
## STEP 4
# Bob decodes qubits
bob_gates(qc, 2, crz, crx)
## STEP 5
# reverse the initialization process
qc.append(inverse_init_gate, [2]) #挂到了第三个量子寄存器上了。
# Display the circuit
qc.draw()
┌─────────────────────────────────────────┐ ░ ░ ┌───┐ ░ » q_0: ┤ init(-0.48157-0.2293j,0.39904-0.74584j) ├─░────────────░───■──┤ H ├─░─» └─────────────────────────────────────────┘ ░ ┌───┐ ░ ┌─┴─┐└───┘ ░ » q_1: ────────────────────────────────────────────░─┤ H ├──■───░─┤ X ├──────░─» ░ └───┘┌─┴─┐ ░ └───┘ ░ » q_2: ────────────────────────────────────────────░──────┤ X ├─░────────────░─» ░ └───┘ ░ ░ » crz: 1/════════════════════════════════════════════════════════════════════════» » crx: 1/════════════════════════════════════════════════════════════════════════» » « ┌─┐ « q_0: ┤M├───────────────────────────────── « └╥┘┌─┐ « q_1: ─╫─┤M├────────────────────────────── « ║ └╥┘ ┌───┐ ┌───┐ ┌──────────────┐ « q_2: ─╫──╫──┤ X ├──┤ Z ├─┤ disentangler ├ « ║ ║ └─╥─┘ └─╥─┘ └──────────────┘ « ║ ║ ║ ┌──╨──┐ «crz: 1/═╩══╬════╬═══╡ = 1 ╞════════════════ « 0 ║ ┌──╨──┐└─────┘ «crx: 1/════╩═╡ = 1 ╞═══════════════════════ « 0 └─────┘
# Need to add a new ClassicalRegister
# to see the result
cr_result = ClassicalRegister(1)
qc.add_register(cr_result)
qc.measure(2,2)
qc.draw()
from qiskit import *
t_qc = transpile(qc, sim)
t_qc.save_statevector()
counts = sim.run(t_qc).result().get_counts()
plot_histogram(counts)
We can see we have a 100% chance of measuring q2(the leftmost bit in the string) in the state |0⟩. This is the expected result, and indicates the teleportation protocol has worked properly.
IBM量子计算机目前不支持测量后的指令,这意味着我们无法在真实硬件上以当前形式运行量子隐形传态。幸运的是,由于[1]第4.4章中讨论的延迟测量原则,这并不限制我们执行任何计算的能力。该原理表明,任何测量都可以推迟到电路的末尾,也就是说,我们可以将所有测量移到末尾,我们应该看到相同的结果。早期测量的任何好处都与硬件有关:如果我们能够早期测量,我们可能能够重用量子位,或者减少我们的量子位处于脆弱叠加状态的时间。在这个例子中,量子隐形传态的早期测量将允许我们在没有直接量子通信信道的情况下传输量子比特态。
虽然移动门可以让我们在真实硬件上演示“隐形传态”电路,但应该注意的是,隐形传态过程(通过经典通道传输量子态)的好处已经丧失。
早期测量的任何好处都与硬件有关:如果我们能够早期测量,我们可能能够重用量子位,或者减少我们的量子位处于脆弱叠加状态的时间。在这个例子中,量子隐形传态的早期测量将允许我们在没有直接量子通信信道的情况下传输量子比特态。
虽然移动门可以让我们在真实硬件上演示“隐形传态”电路,但应该注意的是,隐形传态过程(通过经典通道传输量子态)的好处已经丧失。
由此,可以看出,原理上正确的东西,实际实验并不能支持。
#真正的量子计算机上运行隐形传态
def new_bob_gates(qc, a, b, c):
qc.cx(b, c)
qc.cz(a, c)
qc = QuantumCircuit(3,1)
# First, let's initialize Alice's q0
qc.append(init_gate, [0])
qc.barrier()
# Now begins the teleportation protocol
create_bell_pair(qc, 1, 2)
qc.barrier()
# Send q1 to Alice and q2 to Bob
alice_gates(qc, 0, 1)
qc.barrier()
# Alice sends classical bits to Bob
new_bob_gates(qc, 0, 1, 2)
# We undo the initialization process
qc.append(inverse_init_gate, [2])
# See the results, we only care about the state of qubit 2
qc.measure(2,0)
# View the results:
qc.draw()
┌─────────────────────────────────────────┐ ░ ░ ┌───┐ ░ » q_0: ┤ init(-0.48157-0.2293j,0.39904-0.74584j) ├─░────────────░───■──┤ H ├─░─» └─────────────────────────────────────────┘ ░ ┌───┐ ░ ┌─┴─┐└───┘ ░ » q_1: ────────────────────────────────────────────░─┤ H ├──■───░─┤ X ├──────░─» ░ └───┘┌─┴─┐ ░ └───┘ ░ » q_2: ────────────────────────────────────────────░──────┤ X ├─░────────────░─» ░ └───┘ ░ ░ » c: 1/════════════════════════════════════════════════════════════════════════» » « «q_0: ──────■──────────────────── « │ «q_1: ──■───┼──────────────────── « ┌─┴─┐ │ ┌──────────────┐┌─┐ «q_2: ┤ X ├─■─┤ disentangler ├┤M├ « └───┘ └──────────────┘└╥┘ «c: 1/═════════════════════════╩═ « 0
# First, see what devices we are allowed to use by loading our saved accounts
IBMQ.load_account()
provider = IBMQ.get_provider(hub='ibm-q')
# get the least-busy backend at IBM and run the quantum circuit there
from qiskit.providers.ibmq import least_busy
from qiskit.tools.monitor import job_monitor
backend = least_busy(provider.backends(filters=lambda b: b.configuration().n_qubits >= 3 and
not b.configuration().simulator and b.status().operational==True))
t_qc = transpile(qc, backend, optimization_level=3)
job = backend.run(t_qc)
job_monitor(job) # displays job status under cell
Job Status: job has successfully run
# Get the results and display them
exp_result = job.result()
exp_counts = exp_result.get_counts(qc)
print(exp_counts)
plot_histogram(exp_counts)
{'0': 980, '1': 44}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SZqmoW70-1629518119971)(output_19_1.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fL9zXAsa-1629518119973)(output_19_2.png)]
正如我们在这里看到的,我们测量了一些结果
|1.⟩
. 这些都是由于门和量子位中的错误引起的。相比之下,我们在笔记本的前半部分中的模拟器在其门中没有错误,并且允许无错误的远程传送。
正如我们在这里看到的,我们测量了一些结果|1.⟩
. 这些都是由于门和量子位中的错误引起的。相比之下,我们在笔记本的前半部分中的模拟器在其门中没有错误,并且允许无错误的远程传送。
print(f"The experimental error rate : {exp_counts['1']/sum(exp_counts.values()):.3f}%")
#打印错误率
The experimental error rate : 0.043%
由此可以看出,backend选择simulator,和实际量子计算机是不同的。根据实际需要来决定不同的backend。