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 的基本流程为:

  1. Build:构造量子线路表示要解决的问题
  2. Execute:选择后台,执行实验
  3. 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)

运行结果如下:
在这里插入图片描述

在这里插入图片描述

以上程序可以被分为六步:

  1. 导入需要的包

    上面程序中,需要导入的包主要有下面几个:

    QuantumCircuit:这个包可以看作量子系统的操作指南,它包含了各种需要的量子操作。

    execute:这个包用来执行量子线路

    Aer:用来指定使用什么后台运行上面的线路

    plot_histogram:用来创建一个直方图

  2. 初始化变量

    circuit = QuantumCircuit(2, 2)
    

           该代码第一个参数表示输入零态量子比特的个数,第二个参数表示输入零态经典比特的个数。整句表示创建了一个有两个量子比特,两个经典比特输入的量子线路。

  3. 添加需要的门

    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 中。

  4. 查看设计的电路

    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')
    
  5. 模拟实验
           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) 获取指定线路的运行结果。

  6. 图形化得到的结果

    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输入2XOR输出
000
011
101
110

在量子计算机中,异或门通过 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)
0000
0111
1010
1101

从上表可以看出,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}
"""

在这里插入图片描述

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐