快速入门:使用PilotOS客户端Jupyter开发工具进行量子编程

了解如何使用Jupyter工具将pyqpanda量子线路提交到本地虚拟机。本示例使用的Jupyter开发工具和内置的pyqpanda编程框架,用户下载安装PilotOS客户端打开即用,无需安装或配置环境,用户在Jupyter编程方式与pyqpanda SDK安装在其他工具中编程方式一致。

用例说明

在量子计算机中构建量子纠缠态数学公式: ∣Ψ〉=12(∣00〉+∣11〉)∣Ψ〉=21(∣00〉+∣11〉) ,并对量子态进行测量,测量次数设定为1000次,统计测量结果的次数。 预期结果为”00”和”11”各占50%。

步骤一:导入pyqpanda模块


from pyqpanda import *

步骤二:初始化量子虚拟机

在真正的量子计算机没有成型之前,我们通过在经典计算机中的软件模拟构造了量子计算系统——量子虚拟机,用来验证量子算法和量子应用。为了让量子程序能够执行,首先要创建一个量子虚拟机,Jupyter支持向本地虚拟机和本源悟源超导量子计算机、集群虚拟机提交任务。示例以调用本地全振幅量子虚拟机为例:



#使用CPUQVM构造函数创建连接到虚拟机的qvm对象
#使用全振幅量子虚拟机
qvm = CPUQVM()
#初始化量子虚拟机
qvm.init_qvm()

步骤三:申请量子比特和经典寄存器

构建一个量子程序,我们需要先在虚拟机中申请量子比特。qAllocqAlloc_many函数分别可以从量子比特池中申请一个和多个量子比特。



#申请多个量子比特,示例为申请2个量子比特
qubits = qvm.qAlloc_many(2) 
#申请多个经典寄存器,示例为申请2个经典寄存器
cbits = qvm.cAlloc_many(2)

步骤四:构建量子程序

构建量子线路
量子线路QCircuit是由量子比特演化线路和作用在量子比特上的量子逻辑门构成的,量子线路产生的效果,等同于量子逻辑门依次作用在量子比特上。
向量子线路中插入H门CNOT门。添加以下代码并打印线路:

#初始化QCircuit实例
circuit = QCircuit()
#向量子线路中插入H门、CNOT门,H门作用在q_0比特上,CNOT门作用在控制比特q_0、目标比特q_1上
circuit << H(qubits[0]) \
<< CNOT(qubits[0], qubits[1])

打印量子线路

print(circuit)
打印的量子线路:
┌─┐ 
q_0: |0>─┤H├ ───■──
└─┘ ┌──┴─┐
q_1: |0>──── ┤CNOT├
└────┘

构建量子程序
在量子虚拟机中构建好的量子线路不能直接计算,需要进一步构建QProg实例。QProg是量子编程的一个容器类,是一个量子程序的最大单位。

#创建空的量子程序
prog = QProg()
#将量子线路插入量子程序
prog << circuit

步骤五:测量并运行量子程序

概率测量操作
概率测量,获得目标量子比特的振幅。prob_run_list函数能够运行程序并获得目标量子比特的振幅,目标量子比特可以是一个量子比特也可以是多个量子比特的集合。
使用方法如下:

# 运行量子程序,输出量子态的概率测量结果
pmeasure_result = qvm.prob_run_list(prog, qubits)
print(pmeasure_result)

输出结果如下:
[0.5000000000000001, 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.5000000000000001]

量子测量-蒙特卡罗测量操作
量子测量是指通过外界对量子系统进行干扰来获取需要的信息,是利用蒙特卡罗方法的投影测量方式,对量子比特进行测量,测量后量子态会坍缩到一个确定的态上。当构建好量子程序之后,需要对量子比特进行量子测量,将结果读取出来,并存储到经典寄存器上。在量子程序中,可以使用Measure对某一个量子比特做测量操作。
如果要测量所有的量子比特并将其存储到对应的经典寄存器上,可以进行如下操作:

# 量子程序插入量子测量
prog << measure_all(qubits, cbits)

通过调用run_with_configuration函数来得到量子程序的测量结果。使用方法如下:



# 在虚拟机上执行量子程序,统计量子程序1000次运行的测量结果
measure_result = qvm.run_with_configuration(prog, cbits, 1000) 
print(measure_result)

输出结果:
{'00': 488, '11': 512}

完整示例代码


from pyqpanda import *
# 创建一个CPU计算的量子虚拟机,然后初始化
qvm = CPUQVM()
qvm.init_qvm()
# 申请量子比特和经典寄存器
qubits = qvm.qAlloc_many(2)
cbits = qvm.cAlloc_many(2)
# 构建量子线路
circuit = QCircuit()
circuit << H(qubits[0]) \
<< CNOT(qubits[0], qubits[1])
print(circuit)
# 构建量子程序
prog = QProg()
prog << circuit
# 获得目标量子比特的概率测量结果
pmeasure_result = qvm.prob_run_dict(prog, qubits)
print(pmeasure_result)
# 量子程序插入量子测量
prog << measure_all(qubits, cbits)
# 打印量子程序
print(prog)
# 量子程序运行1000次,返回每次测量结果,并进行统计
measure_result = qvm.run_with_configuration(prog, cbits, 1000)
print(measure_result)
# 释放系统资源
qvm.finalize()

输出结果如下:



#打印线路
┌─┐
q_0: |0>─┤H├ ───■──
└─┘ ┌──┴─┐
q_1: |0>──── ┤CNOT├
└────┘
#获得目标量子比特的概率测量结果
{'00': 0.5000000000000001, '01': 0.0, '10': 0.0, '11': 0.5000000000000001}
#打印量子程序
┌─┐ ┌─┐ 
q_0: |0>─┤H├ ───■── ┤M├── 
└─┘ ┌──┴─┐ └╥┼─┐ 
q_1: |0>──── ┤CNOT├ ─╫┤M├ 
└────┘ ║└╥┘ 
c_0: 0 ═════════════╩═╬
║ 
c_1: 0 ═══════════════╩═
#打印测量结果
{'00': 488, '11': 512}

本地虚拟计算资源

在真正的量子计算机没有成型之前,需要使用量子虚拟机承担量子算法、量子应用的验证的问题,PilotOS客户端本地虚拟计算资源借助用户主机CPU资源,支持全振幅量子虚拟机、单振幅量子虚拟机、部分振幅量子虚拟机以及含噪声量子虚拟机。

全振幅量子虚拟机

全振幅量子虚拟机一次可以模拟计算出量子态的所有振幅,计算方式支持CPU、单线程计算和GPU,可以在初始化时配置,使用方式是完全一样的,只是其计算效率不同。

本地全振幅量子虚拟机调用方式


#选择本地全振幅量子虚拟机
qvm = CPUQVM()
#True: double精度, False: float精度
#初始化量子虚拟机
qvm.init_qvm(True)

完整代码示例


from pyqpanda import *

if __name__ == "__main__":
qvm = CPUQVM()
qvm.init_qvm()

qvm.set_configure(29, 29)
qubits = qvm.qAlloc_many(4)
cbits = qvm.cAlloc_many(4)

# 构建量子程序
prog = QProg()
prog << H(qubits[0]) << CNOT(qubits[0], qubits[1]) << Measure(qubits[0], cbits[0])

# 量子程序运行1000次,并返回测量结果
result = qvm.run_with_configuration(prog, cbits, 1000)

# 打印量子态在量子程序多次运行结果中出现的次数
print(result)
qvm.finalize()

运行结果

{'0000': 528, '0001': 472}

含噪声量子虚拟机

在真实的量子计算机中,受制于量子比特自身的物理特性,常常存在不可避免的计算误差。为了能在量子虚拟机中更好的模拟这种误差,在 量子虚拟机 的基础上, QPanda2带来了含噪声量子虚拟机。含噪声量子虚拟机的模拟更贴近真实的量子计算机,我们可以自定义支持的逻辑门类型,自定义逻辑门支持的噪声模型, 通过这些自定义形式,我们使用QPanda2开发量子程序的现实应用程度将更高。

本地含噪声量子虚拟机调用方式


#选择本地含噪声量子虚拟机
qvm = NoiseQVM()
#初始化量子虚拟机
qvm.init_qvm()

完整代码示例


from pyqpanda import *
import numpy as np
if __name__ == "__main__":
qvm = NoiseQVM()
qvm.init_qvm()
q = qvm.qAlloc_many(4)
c = qvm.cAlloc_many(4)
qvm.set_noise_model(NoiseModel.BITFLIP_KRAUS_OPERATOR, GateType.PAULI_X_GATE, 0.1)
qv0 = [q[0], q[1]]
qvm.set_noise_model(NoiseModel.DEPHASING_KRAUS_OPERATOR, GateType.HADAMARD_GATE, 0.1, qv0)
qves = [[q[0], q[1]], [q[1], q[2]]]
qvm.set_noise_model(NoiseModel.DAMPING_KRAUS_OPERATOR, GateType.CNOT_GATE, 0.1, qves)
f0 = 0.9
f1 = 0.85
qvm.set_readout_error([[f0, 1 - f0], [1 - f1, f1]])
qvm.set_rotation_error(0.05)
prog = QProg()
prog << X(q[0]) << H(q[0]) \
<< CNOT(q[0], q[1]) \
<< CNOT(q[1], q[2]) \
<< CNOT(q[2], q[3]) \
<< measure_all(q, c)
result = qvm.run_with_configuration(prog, c, 1000)
print(result)

运行结果

{'0000': 343, '0001': 74, '0010': 49, '0011': 29, '0100': 43, '0101': 15, '0110': 21, '0111': 32, '1000': 37, '1001': 15, '1010': 11, '1011': 30, '1100': 20, '1101': 58, '1110': 50, '1111': 173}

单振幅量子虚拟机

目前我们可以通过量子计算的相关理论,用经典计算机实现模拟量子虚拟机。 量子虚拟机的模拟主要有全振幅与单振幅两种解决方案,其主要区别在于,全振幅一次模拟计算就能算出量子态的所有振幅,单振幅一次模拟计算只能计算出2�2N个振幅中的一个。

然而全振幅模拟量子计算时间较长,计算量随量子比特数指数增长, 在现有硬件下,无法模拟超过49量子比特。通过单振幅量子虚拟机技术可以模拟超过49量子比特,同时模拟速度有较大提升,且算法的计算量不随量子比特数指数提升。

本地单振幅量子虚拟机调用方式


#选择本地单振幅量子虚拟机
qvm = SingleAmpQVM()
#初始化量子虚拟机
qvm.init_qvm()

完整代码示例



from pyqpanda import *
from numpy import pi

qvm = SingleAmpQVM()
qvm.init_qvm()
qv = qvm.qAlloc_many(10)
cv = qvm.cAlloc_many(10)
prog = QProg()
# 构建量子程序
prog << CZ(qv[1], qv[5])\
<< CZ(qv[3], qv[5])\
<< CZ(qv[2], qv[4])\
<< CZ(qv[3], qv[7])\
<< CZ(qv[0], qv[4])\
<< RY(qv[7], pi / 2)\
<< RX(qv[8], pi / 2)\
<< RX(qv[9], pi / 2)\
<< CR(qv[0], qv[1], pi)\
<< CR(qv[2], qv[3], pi)\
<< RY(qv[4], pi / 2)\
<< RZ(qv[5], pi / 4)\
<< RX(qv[6], pi / 2)\
<< RZ(qv[7], pi / 4)\
<< CR(qv[8], qv[9], pi)\
<< CR(qv[1], qv[2], pi)\
<< RY(qv[3], pi / 2)\
<< RX(qv[4], pi / 2)\
<< RX(qv[5], pi / 2)\
<< CR(qv[9], qv[1], pi)\
<< RY(qv[1], pi / 2)\
<< RY(qv[2], pi / 2)\
<< RZ(qv[3], pi / 4)\
<< CR(qv[7], qv[8], pi)
# run 有三个参数,默认2个,
# 第一个执行的量子程序
# 第二个为申请的量子比特
# 第三个为最大RANK,这里根据内存设置,默认30
# 第四个就是quickBB优化的最大运行时间,默认5s
qvm.run(prog, qv)
bin_result = qvm.pmeasure_bin_index("0001000000")
print("0001000000 : ", bin_result)

运行结果

0001000000 : 0.001953123603016138

部分振幅量子虚拟机

目前用经典计算机模拟量子虚拟机的主流解决方案有全振幅与单振幅两种。除此之外,还有部分振幅量子虚拟机,该方案能在更低的硬件条件下,实现更高的模拟效率。

本地部分振幅量子虚拟机调用方式


#选择本地含噪声量子虚拟机
machine = PartialAmpQVM()
#初始化量子虚拟机
machine.init_qvm()

完整代码示例


from pyqpanda import *
from numpy import pi
machine = PartialAmpQVM()
machine.init_qvm()
q = machine.qAlloc_many(10)
c = machine.cAlloc_many(10)
# 构建量子程序
prog = QProg()
prog << hadamard_circuit(q)\
<< CZ(q[1], q[5])\
<< CZ(q[3], q[7])\
<< CZ(q[0], q[4])\
<< RZ(q[7], pi / 4)\
<< RX(q[5], pi / 4)\
<< RX(q[4], pi / 4)\
<< RY(q[3], pi / 4)\
<< CZ(q[2], q[6])\
<< RZ(q[3], pi / 4)\
<< RZ(q[8], pi / 4)\
<< CZ(q[9], q[5])\
<< RY(q[2], pi / 4)\
<< RZ(q[9], pi / 4)\
<< CZ(q[2], q[3])
machine.run(prog)
result = machine.pmeasure_bin_index("0000000000")
print(result)

运行结果

(-0.00647208746522665-0.006472080945968628j)

张量网络量子虚拟机

对于�N个量子比特的自旋体系,对应的希尔伯特空间维数为2�2N。
对于该复杂系统的状态演化,传统的全振幅模拟器将其看做一个有2�2N个元素的一维向量。
然而从张量网络的角度来看,整个系统量子态的系数对应2�2N维张量(即N阶张量,即有�N个指标,每个指标的维数是2),量子操作算符的系数为22�22N维张量(2�2N阶张量,即有2�2N个指标,每个指标的维数是2),我们可以用如下图形来表示量子态:
 

【量子计算从入门到精通】--快速开始_子程序

当量子系统的自旋个数增加时,量子态系数的个数随指数增加,称为指数墙问题,这一障碍限制了传统全振幅模拟器的最大模拟自旋数和模拟性能。

但是可通过张量网络处理这一问题,从而绕过指数墙障碍,在张量网络中,我们对量子系统的模拟,包括量子逻辑门操作和测量操作,均可以通过对于张量的缩并与分解来实现。矩阵乘积态是张量网络中最常用的表示形式,在多线性代数中称为张量列或TT(Tensor-Train),示意图如下:
 

【量子计算从入门到精通】--快速开始_ci_02

将量子态分解成等式右边的表示形式,对于量子线路中部分量子逻辑门操作,可以将全局问题转化为局部的张量处理问题,从而有效地降低了时间复杂度和空间复杂度。

张量网络模拟器与单振幅类似,与单振幅对比,可以模拟多控制门,同时在深度较高的线路模拟上存在性能优势。

本地张量网络量子虚拟机调用方式

pyqpanda中可以通过 MPSQVM类实现用张量网络模拟量子电路。和许多其他模拟器的使用方法一样,都具有相同的量子虚拟机接口。



# 构建量子虚拟机
qvm = MPSQVM()
# 初始化操作
qvm.set_configure(64, 64)
qvm.init_qvm()

完整代码示例



from numpy import pi
from pyqpanda import *
qvm = MPSQVM()
qvm.set_configure(64, 64)
qvm.init_qvm()
q = qvm.qAlloc_many(10)
c = qvm.cAlloc_many(10)
prog = QProg()
prog << hadamard_circuit(q)\
<< CZ(q[2], q[4])\
<< CZ(q[3], q[7])\
<< CNOT(q[0], q[1])\
<< CZ(q[3], q[7])\
<< CZ(q[0], q[4])\
<< RY(q[7], pi / 2)\
<< RX(q[8], pi / 2)\
<< RX(q[9], pi / 2)\
<< CR(q[0], q[1], pi)\
<< CR(q[2], q[3], pi)\
<< RY(q[4], pi / 2)\
<< RZ(q[5], pi / 4)\
<< Measure(q[0], c[0])\
<< Measure(q[1], c[1])\
<< Measure(q[2], c[2])
# Monte Carlo采样模拟接口
result0 = qvm.run_with_configuration(prog, c, 100)
# 概率测量接口
result1 = qvm.prob_run_dict(prog, [q[0], q[1], q[2]], -1)
print(result0)
print(result1)
qvm.finalize()

运行结果

Monte Carlo 采样模拟结果

{'0000000000': 7, '0000000001': 12, '0000000010': 13, '0000000011': 10, '0000000100': 16, '0000000101': 14, '0000000110': 12, '0000000111': 16}概率测量结果
{'000': 0.12499999999999194, '001': 0.12499999999999185, '010': 0.12499999999999194, '011': 0.124999999999992, '100': 0.12499999999999198, '101': 0.12499999999999194, '110': 0.12499999999999198, '111': 0.12499999999999208}

 

OriginQ计算资源

通过接入本源量子云计算服务平台,使用本源悟源系列超导量子计算机和集群虚拟计算服务。

计算服务概览

类型

名称

说明

真实量子计算服务

悟源1号

本源悟源6比特超导量子计算机

真实量子计算服务

悟源2号

本源悟源6比特超导量子计算机

OriginQ计算集群

全振幅量子虚拟机

一次可以模拟计算出量子态的所有振幅,最大支持35比特

OriginQ计算集群

部分振幅量子虚拟机

一次计算可输出2^N个振幅中的一部分,最大支持68比特

OriginQ计算集群

单振幅量子虚拟机

一次模拟计算计算出2^N个振幅中的一个,最大支持200比特

OriginQ计算集群

含噪声量子虚拟机

支持自定义逻辑门和噪声模型关系,最大支持34比特

获取个人API KEY信息

API KEY 是用户使用OriginQ量子云计算资源的授权凭据,属于用户个人所有,其形式是一串 128位字符,用户可在登录后点击【Dashboard】页,复制API KEY即可。

【量子计算从入门到精通】--快速开始_ci_03

真实量子计算服务

本源量子OriginQ云平台提供2台超导量子计算机,用户可以通过 OriginQ 的计算服务页,了解 QPU 的实时状态信息。

【量子计算从入门到精通】--快速开始_子程序_04

悟源1号&悟源2号芯片拓扑结构如下图所示:

 

【量子计算从入门到精通】--快速开始_初始化_05

悟源1号&悟源2号芯片芯片参数信息如下图所示:

 

【量子计算从入门到精通】--快速开始_量子计算_06

 

【量子计算从入门到精通】--快速开始_子程序_07

调用示例

传入API KEY


# 通过QCloud()创建量子云虚拟机
qm = QCloud()
# 通过传入当前用户的API KEY来初始化
qm.init_qvm("用户API KEY")

设置计算后端

# 调用真实芯片计算接口,需要量子程序和测量次数两个参数
result0 = qm.real_chip_measure(prog, 1000)
# 调用全振幅蒙特卡洛测量操作计算接口,需要量子程序和测量次数两个参数
result1 = QCM.full_amplitude_measure(measure_prog, 1000)
# 调用全振概率测量操作计算接口,需要量子程序和测量比特两个参数
result2 = QCM.full_amplitude_pmeasure(pmeasure_prog, [0, 1, 2])
# 调用部分振幅计算接口,需要量子程序和量子态振幅两个参数
result3 = QCM.partial_amplitude_pmeasure(pmeasure_prog, ["0", "1", "2"])
# 调用单振幅计算接口,需要量子程序和测量振幅两个参数
result4 = QCM.single_amplitude_pmeasure(pmeasure_prog, "0")
# 调用噪声模拟计算接口,set_noise_model是设置噪声参数,NoiseModel.BIT_PHASE_FLIP_OPRATOR为噪声模型,[0.01]为单门噪声参数,[0.02]为双门噪声参数
QCM.set_noise_model(NoiseModel.BIT_PHASE_FLIP_OPRATOR, [0.01], [0.02])
result5 = QCM.noise_measure(measure_prog, 100)

完整代码示例


from pyqpanda import *

# 通过QCloud()创建量子云虚拟机
qm = QCloud()

# 通过传入当前用户的API KEY来初始化
qm.init_qvm("填入个人的API KEY")

qlist = qm.qAlloc_many(6)
clist = qm.cAlloc_many(6)

# 构建量子程序,可以手动输入,也可以来自OriginIR或QASM语法文件等
prog = QProg()
prog << hadamard_circuit(qlist)\
<< CZ(qlist[1], qlist[5])\
<< Measure(qlist[0], clist[0])\
<< Measure(qlist[1], clist[1])

# 调用真实芯片计算接口,需要量子程序和测量次数两个参数
result = qm.real_chip_measure(prog, 1000)
print(result)
qm.finalize()

运行结果

{'00': 0.2557673019057172, '01': 0.2597793380140421, '10': 0.2306920762286861, '11': 0.25376128385155466}

虚拟量子计算服务

虚拟量子计算服务是本源量子OriginQ云平台为用户提供的免费高性能计算集群。

全振幅模拟云计算

蒙特卡洛测量操作使用示例


from pyqpanda import *
import numpy as np
# 通过QCloud()创建量子云虚拟机
QCM = QCloud()
# 通过传入当前用户的API KEY来初始化
QCM.init_qvm("填入个人的API KEY")
qlist = QCM.qAlloc_many(6)
clist = QCM.cAlloc_many(6)
# 构建量子程序,可以手动输入,也可以来自OriginIR或QASM语法文件等
measure_prog = QProg()
measure_prog << hadamard_circuit(qlist)\
<< CZ(qlist[1], qlist[5])\
<< Measure(qlist[0], clist[0])\
<< Measure(qlist[1], clist[1])
pmeasure_prog = QProg()
pmeasure_prog << hadamard_circuit(qlist)\
<< CZ(qlist[1], qlist[5])\
<< RX(qlist[2], np.pi / 4)\
<< RX(qlist[1], np.pi / 4)\
# 调用全振幅蒙特卡洛测量操作计算接口,需要量子程序和测量次数两个参数
result = QCM.full_amplitude_measure(measure_prog, 1000)
print(result)

运行结果

{'00': 0.263, '01': 0.255, '10': 0.241, '11': 0.241}

概率测量操作调用示例


result1 = QCM.full_amplitude_pmeasure(pmeasure_prog, [0, 1, 2])
print(result1)

运行结果

{'000': 0.12499999999999988, '001': 0.12499999999999988, '010': 0.12499999999999988, '011': 0.12499999999999988, '100': 0.12499999999999988, '101': 0.12499999999999988, '110': 0.12499999999999988, '111': 0.12499999999999988}

部分振幅模拟云计算

调用示例



result2 = QCM.partial_amplitude_pmeasure(pmeasure_prog, ["0", "1", "2"])
print(result2)

运行结果

{'0': (0.08838832192122936-0.08838833495974541j), '1': (0.08838832192122936-0.08838833495974541j), '2': (0.08838832192122936-0.08838833495974541j)}

单振幅模拟云计算

调用示例



result3 = QCM.single_amplitude_pmeasure(pmeasure_prog, "0")
print(result3)

运行结果

(0.08838833056846361-0.08838833850593952j)

噪声模拟云计算

调用示例


QCM.set_noise_model(NoiseModel.BIT_PHASE_FLIP_OPRATOR, [0.01], [0.02])
result4 = QCM.noise_measure(measure_prog, 100)
print(result4)

运行结果

{'00': 0.27, '01': 0.22, '10': 0.21, '11': 0.30}

 

公共集群计算资源

通过在超算中心或公共计算集群部署本源司南操作系统,可实现计算资源对外提供高性能虚拟量子计算服务。

本源司南产品架构图

【量子计算从入门到精通】--快速开始_初始化_08

本源司南特点

支持量子比特量子线路到目标量子芯片的编译优化;

支持多量子处理器分布式调度;

支持“经典—量子”计算任务的调度;

支持高性能集群与量子计算集群混合计算;

支持至少2种体系的量子芯片对接;

支持高性能集群管理;

量子操作系统支持量子经典混合编程;

量子操作系统支持至少三种专用领域应用开发服务框架。