一、Qiskit 基础和简单线路
1. 安装 Qiskit1.1 安装命令可以直接使用 pip 命令安装 qiskit 包:pip install qiskit若要使用其中的一些可视化功能,可以安装可视化包pip install qiskit[visualization]1.2 检查安装 Qiskit 包含一系列不同的元素,运行qiskit.__ve
1. 安装 Qiskit
1.1 安装命令
可以直接使用 pip 命令安装 qiskit 包:
pip install qiskit
若要使用其中的一些可视化功能,可以安装可视化包
pip install qiskit[visualization]
1.2 检查安装
Qiskit 包含一系列不同的元素,运行 qiskit.__version__
返回 qiskit-terra
包的版本,因为 qiskit 是来自 qiskit-terra
包。
可以使用 qiskit.__qiskit_version__
查看所有 Qiskit 包元素的版本。
2. Qiskit 的简单使用
使用 Qiskit 的基本流程为:
- Build:构造量子线路表示要解决的问题
- Execute:选择后台,执行实验
- Analyze:计算汇总统计,构造实验结果
这里用一个简单的例子看一下它的使用方法:
import numpy as np
from qiskit import(
QuantumCircuit,
execute,
Aer)
from qiskit.visualization import plot_histogram
# Use Aer's qasm_simulator
simulator = Aer.get_backend('qasm_simulator')
# Create a Quantum Circuit acting on the q register
circuit = QuantumCircuit(2, 2)
# Add a H gate on qubit 0
circuit.h(0)
# Add a CX (CNOT) gate on control qubit 0 and target qubit 1
circuit.cx(0, 1)
# Map the quantum measurement to the classical bits
circuit.measure([0,1], [0,1])
# Execute the circuit on the qasm simulator
job = execute(circuit, simulator, shots=1000)
# Grab results from the job
result = job.result()
# Returns counts
counts = result.get_counts(circuit)
print("\nTotal count for 00 and 11 are:",counts)
# Draw the circuit
circuit.draw()
# Plot a histogram
plot_histogram(counts)
运行结果如下:
以上程序可以被分为六步:
-
导入需要的包
上面程序中,需要导入的包主要有下面几个:
QuantumCircuit
:这个包可以看作量子系统的操作指南,它包含了各种需要的量子操作。execute
:这个包用来执行量子线路Aer
:用来指定使用什么后台运行上面的线路plot_histogram
:用来创建一个直方图 -
初始化变量
circuit = QuantumCircuit(2, 2)
该代码第一个参数表示输入零态量子比特的个数,第二个参数表示输入零态经典比特的个数。整句表示创建了一个有两个量子比特,两个经典比特输入的量子线路。
-
添加需要的门
circuit.h(0) circuit.cx(0, 1) circuit.measure([0,1], [0,1])
QuantumCircuit.h(0)
:为 qubit 0 添加一个 Hadamard 门,该门将输入态转换为叠加态。QuantumCircuit.cx(0, 1)
:添加一个从 qubit 0 作用到 qubit 1 的 C-NOT 门。QuantumCircuit.measure([0,1], [0,1])
:将第一个列表中对应位置 qubit 的测量结果,保存到第二个列表对应位置的经典 bit 中。整体表示,对 qubit 0 和 qubit 1 进行测量,将他们的结果分别保存到 bit 0 和 bit 1 中。 -
查看设计的电路
circuit.draw()
使用
qiskit.circuit.QuantumCircuit.draw()
可以查看上面设计的电路。下面是构建的线路
在这个线路中,上面的是 qubit 0,下面的是 qubit 1 ,整个线路从左到右运行,比特从左到右依次通过每个门。默认的
QuantumCircuit.draw()
和qiskit.visualization.circuit_drawer()
使用文本模式,可以根据本地环境选择其他的展示方式,默认使用在~/.qiskit/settings.conf
的配置文件中指定的circuit_drawer = *
绘图方式,也可以在QuantumCircuit.draw()
中使用字符串指定绘图的方式,可以指定的方式包括:QuantumCircuit.draw('text') #默认的绘图方式 QuantumCircuit.draw('mpl') #使用 MatPlotLib 绘图 QuantumCircuit.draw('latex') QuantumCircuit.draw('latex_source')
-
模拟实验
Qiskit Aer 是一个高性能的量子线路模拟框架,它提供了很多模拟后台使用,如果 Aer 出错了,可以使用 Qiskit Terra 中的 Basic Aer 来代替,即使用下面的导入包:import numpy as np from qiskit import( QuantumCircuit, execute, BasicAer)
下面的代码使用
qasm_simulator
运行量子线路,使用Aer.get_backend()
指定模拟器。simulator = Aer.get_backend('qasm_simulator') #指定模拟器 job = execute(circuit, simulator, shots=1000) #执行量子线路 result = job.result() counts = result.get_counts(circuit) print("\nTotal count for 00 and 11 are:",counts) """ Total count for 00 and 11 are: {'00': 504, '11': 496} """
execute
可以指定三个参数,分别是 运行的量子线路名(circuit)、使用哪个模拟器(simulator)、执行多少次(shots,默认为 1024 次)。可以通过
result.get_counts(circuit)
获取指定线路的运行结果。 -
图形化得到的结果
plot_histogram(counts)
可以使用
plot_histogram
函数,以直方图的形式展示线路执行的结果。
3. 创建一个加法线路
2.1 编码指定的输入状态
在使用电路时,默认的电路输入全部为 ∣ 0 ⟩ |0\rangle ∣0⟩ ,但是我们可能会需要其他的状态作为输入,这里我们使用 NOT 门实现 ∣ 0 ⟩ |0\rangle ∣0⟩ 状态和 ∣ 1 ⟩ |1\rangle ∣1⟩ 之间的转化,我们把这个 NOT 门称为 x 操作,下面我们用一个示例展示使用 X 操作得到我们想要的输入比特流。
下面我们创建了一个量子线路,并对他们进行测量,并运行,输出测量的结果,
from qiskit import QuantumCircuit,execute,Aer
qc_output = QuantumCircuit(8,8) #创建有8个qubit和8个bit输入的电路
for i in range(8):
qc_output.measure(i,i) #为每条量子线路添加测量门
simulator=Aer.get_backend('qasm_simulator') #指定使用什么模拟器
counts = execute(qc_output,simulator).result().get_counts() #使用指定的那个的模拟器运行电路,并获取运行结果,得到每种输入出现了几次(默认运行1024次)
print(counts)
qc_output.draw() #画出该线路
"""
{'00000000': 1024}
"""
从上面的结果可以看出,我们对线路的输入进行测量,得到的结果全部为 0 ,这也验证了每个输入态都是 ∣ 0 ⟩ |0\rangle ∣0⟩ ,同时从输出的 counts 可以知道,线路运行 1024 次,得到的结果都是 0000000 。
下面我们创建一个 x 操作加入到上面所示的电路,再次运行,并测量结果,代码如下:
from qiskit import QuantumCircuit,execute,Aer
qc_output = QuantumCircuit(8,8)
for i in range(8):
qc_output.measure(i,i)
qc_encode = QuantumCircuit(8,8) #创建有8个qubit和8个bit输入的电路
qc=qc_encode+qc_output #将上面的两个电路相加,也就是组合在一起
simulator=Aer.get_backend('qasm_simulator')
counts = execute(qc,simulator).result().get_counts()
print(counts)
qc.draw()
"""
{'10000000': 1024}
"""
上面的代码首先创建了一个电路,并在第七个量子位增加了一个 x 操作,然后将两个电路组合起来,在 Qiskit 中,可以将两个具有相同大小的电路用 + + + 组合起来。之后我们对经过编码的量子位测量,可以发现我们得到的结果为 10000000 ,这里要注意,Qiskit 中,低量子位排在 qubit 0 上,我们在第七个 qubit 上进行了 NOT 操作,最终可以看出是作用在比特流的第一个,这样我们得到的比特流表示的数字是 128 。
2.2 使用 Qiskit 创建一个半加器
对于二进制的加法运算,我们通常需要考虑的加法进位只有四种情况:
0+0 = 00 (in decimal, this is 0+0=0)
0+1 = 01 (in decimal, this is 0+1=1)
1+0 = 01 (in decimal, this is 1+0=1)
1+1 = 10 (in decimal, this is 1+1=2)
在 1+1=10 时,结果的第一个 1 表示需要进位,我们称实现这种包含进位的加法器为 半加器 。这里我们使用 Qiskit 实现一个半加器。
观察累加的等式,我们可以发现,结果的右边比特有一个特点,就是当两个输入相同时,该位为 0 ;两个输入不同时,该位为 1 。也就是 0+0 和 1+1 ,右边比特为 0 ;对于 0+1 和 1+0 ,右边比特为 1 。为了实现这一部分的解,我们需要判断输入的两个比特是否相同,在经典计算中,我们称这种计算为异或运算,可以通过异或门(XOR gate)实现。即:
输入1 | 输入2 | XOR输出 |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
在量子计算机中,异或门通过 controlled-NOT 门实现,简记为 CNOT 。在 Qiskit 中为 cx ,使用如下:
from qiskit import QuantumCircuit,execute,Aer
qc_cnot = QuantumCircuit(2)
qc_cnot.cx(0,1)
qc_cnot.draw()
如上图所示,CNOT 门作用于两个 qubit ,一个 qubit 为 控制位(使用点表示),另外一个 qubit 为 目标位 (使用圆形表示)。CNOT 门的作用为,当控制位为 1 时,目标位执行比特翻转,如果控制位为 0 ,那么什么也不做。我们可以更直观的表示为:
因此,上面代码中的 CNOT 对应的输入输出可以表示为:
输入(q1 q0) | 输出(q1 q0) |
---|---|
00 | 00 |
01 | 11 |
10 | 10 |
11 | 01 |
从上表可以看出,q1 其实就是两个 qubit 进行异或的结果。可以用图形表示为:
这里我们已经知道了怎么使用逻辑门来计算第二位量子位的结果了,所以我们首先构造能够计算第二位量子的电路,我们创建含有四个 qubit 的电路,前两个 qubit 表示输入,后两个 qubit 保存经过半加器后的结果,我们构造以下电路:
from qiskit import QuantumCircuit,execute,Aer
qc_ha = QuantumCircuit(4,2)
qc_ha.barrier() #创建一个分界线
#使用两个 CNOT 门,将异或的结果保存到 qubit 2
qc_ha.cx(0,2)
qc_ha.cx(1,2)
qc_ha.barrier()
qc_ha.measure(2,0) #对 qubit 2 测量,将测量的结果保存到 bit 0
qc_ha.measure(3,1) #对 qubit 3 测量,将测量的结果保存到 bit 1
qc_ha.draw()
上面代码中使用两个 CNOT 门将异或的结果保存到 qubit 2,还用到了 qc.barrier()
,其表示在线路中画出一个分界线,该线对整个电路没有影响,只是方便我们区分线路的不同部分。
现在我们解决了结果的第二位量子位,我们要考虑第一位量子位。对于结果的第一位量子位,只有在两个输入都为 1 时,其才得到 1 ,即 1+1 = 10 。这里我们引入一个 Toffoli 门,它类似于 CNOT 门,但是它由两个 qubit 作为控制位,一个 qubit 作为目标位,当两个控制门都是 1 时,对目标 qubit 执行比特翻转。 Toffoli 门在 Qiskit 中使用 ccx 命令表示。所以整个电路可以变为:
from qiskit import QuantumCircuit,execute,Aer
qc_ha = QuantumCircuit(4,2)
qc_ha.barrier() #创建一个分界线
#使用两个 CNOT 门,将异或的结果保存到 qubit 2
qc_ha.cx(0,2)
qc_ha.cx(1,2)
qc_ha.ccx(0,1,3) #创建一个 qubit 0 和 qubit 1 为控制位,qubit 3 为目标位的 Toffoli 门
qc_ha.barrier()
qc_ha.measure(2,0) #对 qubit 2 测量,将测量的结果保存到 bit 0
qc_ha.measure(3,1) #对 qubit 3 测量,将测量的结果保存到 bit 1
qc_ha.draw()
至此,我们就完成了整个半加器的创建,这个电路默认计算的两个输入都为 0,如果想要计算其他的输入,我们只需要在 qubit 0 或 qubit 1 处添加 NOT 门,将他们构成我们想要的输入即可。
如,我们想要计算 1+0 ,只需要将 qubit 0 设置为 1 ,将 qubit 1 设置为 0 ,这时我们在 qubit 0 处添加一个 NOT 门,就可以得到我们想要的结果了,具体结果如下:
from qiskit import QuantumCircuit,execute,Aer
qc_ha = QuantumCircuit(4,2)
qc_ha.x(0) #将 qubit 0 由 0 变为 1
print("compute 1+0")
qc_ha.barrier() #创建一个分界线
#使用两个 CNOT 门,将异或的结果保存到 qubit 2
qc_ha.cx(0,2)
qc_ha.cx(1,2)
qc_ha.ccx(0,1,3) #创建一个 qubit 0 和 qubit 1 为控制位,qubit 3 为目标位的 Toffoli 门
qc_ha.barrier() #创建一个分界线
qc_ha.measure(2,0) #对 qubit 2 测量,将测量的结果保存到 bit 0
qc_ha.measure(3,1) #对 qubit 3 测量,将测量的结果保存到 bit 1
counts = execute(qc_ha,Aer.get_backend('qasm_simulator')).result().get_counts()
print(counts)
qc_ha.draw()
"""
compute 1+0
{'01': 1024}
"""
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)