附录E:isq-Core 文档¶
isQ-core python 包安装使用说明¶
环境¶
python == 3.8
安装¶
pip
直接安装
pip install isqopen
通过源码进行离线安装
git clone https://gitee.com/arclight_quantum/isq-core/
python setup.py build
python setup.py install
硬件支持¶
isQ-core 支持创新院云平台的 12 比特量子硬件,使用量子硬件需先去该云台注册相应的账号密码。
isQ-core 支持aws braket对接的硬件,可通过设置硬件编号和 s3 存储桶使用对应量子硬件,当离线使用时,请先安装aws-braket-sdk
,注册 aws 账号,并开通 braket 相关权限,申请 s3 存储桶。在isQ 云平台时,平台提供 aws 使用权限,运行需消耗平台积分。
使用¶
使用时通过import isq
引入 isqopen
Device 使用¶
用户需先定义好使用的Device,然后编写好 isQ-core 程序,调用 Device 的run
接口即可运行,Device 初始化参数可详见 API 说明。LocalDevice
返回结果为测量的统计结果,以dict
的形式返回。QcisDevice
及AwsDevice
返回ISQTask,可通过result
接口获取结果(等待时间超过 max_wait_time 则返回空字典,可根据state
属性查询任务执行状态)。使用示例如下
from isq import LocalDevice, QcisDevice, AwsDevice
isq_str = '''
qbit a, b;
X(a);
CNOT(a, b);
M(a);
M(b);
'''
# local device
ld = LocalDevice(shots = 200)
# 返回dict
ld_res = ld.run(isq_str)
print(ld_res)
#qcis device
qd = QcisDevice(user = "xxx", passwd = "xxx", max_wait_time = 60)
#返回ISQTask
task = qd.run(file = './test.isq')
#输出状态和结果
print(task.state)
print(task.result())
import logging
logger = logging.getLogger() # initialize logging class
logger.setLevel(logging.CRITICAL)
#aws device
from isq import TaskState
ad = AwsDevice(shots=100, device_arn = "arn:aws:braket:::device/qpu/ionq/ionQdevice", s3 = ("amazon-braket-arclight", "simulate"), max_wait_time=10, logger = logger)
task = ad.run(isq_str)
print(task.state)
#等待结果直到执行完成
while task.state == TaskState.WAIT:
task.result()
print(task.result())
Device 提供compile_to_ir
接口,可将 isq 编译到 openqasm/qcis,示例如下:
'''
isQ-core -> openqasm2.0
qreg大小与isQ-core定义的量子比特数目一致
creg大小与测量的比特数目一致
测量结果按测量顺序从creg[0]开始依次存储
'''
ld = LocalDevice()
ir = ld.compile_to_ir(file = './test.isq', target="openqasm")
print(ir)
isq_str = '''
qbit a,b;
H(a);
CNOT(a,b);
M(a);
M(b);
'''
ld = LocalDevice()
ir = ld.compile_to_ir(isq_str, target="qcis")
print(ir)
量子核函数¶
isQ-core 提供了函数修饰符isq.qpu
,通过该修饰符可定义一个量子核函数,该修饰符有如下参数
参数名 | 类型 | 说明 | 默认值 |
---|---|---|---|
device | Device | 量子后端,可为LocalDeivce ,QcisDeivce ,AwsDeivce |
无 |
用该修饰符修饰的函数内部需采用注释的形式用 isQ-core 的相关语法进行编程。量子核函数的调用方式和 python 的函数调用方式一致,其返回结果与使用 Device 的run
函数一致
#使用模拟器运行,制备bell态
import isq
from isq import LocalDevice, QcisDevice, AwsDevice
ld = LocalDevice()
@isq.qpu(ld)
def bell_sim():
'''
qbit a, b;
X(a);
CNOT(a, b);
M(a);
M(b);
'''
res = bell_sim()
print(res)
ir = ld.get_ir()
print(ir)
#使用12bit量子硬件运行,制备bell态
qd = QcisDevice(user = "xxx", passwd = "xxx")
@isq.qpu(qd)
def bell_qcis():
'''
qbit a, b;
X(a);
CNOT(a, b);
M(a);
M(b);
'''
task = bell_qcis()
res = task.result()
print(res)
带参电路¶
isQ-core 支持编写带参的电路,并在编译运行时传入具体的参数值。用户可直接在编写电路时使用参数,并在 Device 调用编译运行的接口中传入**同名**参数的具体值,如
isq_str = '''
qbit a, b;
RX(theta[0], a);
RY(theta[1], b);
M(a);
M(b);
'''
from isq import LocalDevice
# local device
ld = LocalDevice(shots = 200)
# 返回dict
ld_res = ld.run(isq_str, theta = [0.2, 0.4])
print(ld_res)
或者通过量子核函数的方式,在定义核函数时确定参数名,并在调用函数时传入具体值,如
#带参数的量子核函数
import isq
from isq import LocalDevice
ld = LocalDevice()
@isq.qpu(ld)
def test(theta, a):
'''
qbit t[5];
if (a < 5){
X(t[0]);
}else{
RX(theta[1],t[1]);
}
M(t[1]);
'''
res = test([0.1, 0.2], 3)
自定义酉门¶
可使用quantumCor.addGate
函数在 kernel 外部声明自定义酉门,这些酉门可在所有 kernel 中直接使用(酉操作)。kernel 中声明同名酉门则会在内部覆盖。自定义酉门需传入两个参数,门名称(str)和门的矩阵表示(list/np.array),示例如下
from isq import quantumCor
import isq
a = [[0.5+0.8660254j,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]
quantumCor.addGate("Rs", a)
ld = LocalDevice()
@isq.qpu(ld)
def test():
'''
qbit a, b;
...
Rs(a, b);
...
'''
电路图生成¶
isQ-core 可通过 Device 的draw_circuit
函数,打印指令集的电路展示图。由于为从编译结果生成,电路图只包含基础门集,用户自定义门会被分解后展示。RX,RY,RZ 的旋转角度默认不显示,如需显示,可通过showparam
参数设置
from isq import LocalDevice
#定义量子线路
isq_str = '''
qbit a,b;
H(a);
CNOT(a,b);
RX(2.333, a);
M(a);
M(b);
'''
ld = LocalDevice()
ld.run(isq_str)
ld.draw_circuit()
ld.draw_circuit(True)
自动微分¶
isQ-core 可对参数化电路进行自动微分,并利用优化器进行参数优化。LocalDevice
内置了 probs 接口,其在编译阶段进行带参编译,生成参数化电路(目前只支持 RX, RY, RZ 门带参),这些参数是需要优化的参数,在调用接口传入时需用optv
进行封装,在模拟阶段,返回测量比特的概率值(不进行测量,直接返回概率)。
isQ-core 提供了基于梯度下降法的优化器optimizer
,其opt
接口接收用户自定义的损失函数,及需要优化的参数,并返回优化后参数及当次损失函数值
示例如下:
import isq
from isq import LocalDevice, optv
#定义量子线路
isq_str = '''
qbit q[2];
RX(theta[0], q[0]);
RY(theta[1], q[1]);
M(q[0]);
'''
#定义device
ld = LocalDevice()
#定义损失函数
def loss(params):
#使用probs函数进行带参编译和模拟,其中需要优化的参数通过optv封装后传入
c = ld.probs(isq_str, theta = optv(params))
return c[0] - c[1]
#定义optimizer
opt = isq.optimizer(0.01)
#获取优化后参数及当次损失函数计算值
newp, cost = opt.opt(loss, [0.2, 0.4])
print(newp, cost)
自定义 optimizer¶
isQ-core 提供自动微分接口grad
以使用户可根据微分结果自定义优化器。grad
接收损失函数及损失函数中需要微分的参数位置作为输入,返回一个可调用类型,再传入计算函数所需参数,即可返回参数的微分结果,示例如下
import isq
from isq import LocalDevice, optv
#定义量子线路
isq_str = '''
qbit q[2];
RX(theta[0], q[0]);
RY(theta[1], q[1]);
M(q[0]);
'''
#定义device
ld = LocalDevice()
#定义计算函数
def calc(params):
#使用probs函数进行带参编译和模拟,其中需要微分的参数通过optv封装后传入
c = ld.probs(isq_str, theta = optv(params))
return c[0] - c[1]
#定义grad,并调用,对第0个参数求微分
g = isq.grad(calc, [0])
d = g([0.2, 0.4])
print(d)
批量处理¶
isQ-core 通过 jax 的 vmap 提供自动微分的批处理功能,该功能在单次微分的运行效率上不如上述grad
接口,但是在批处理上有着明显的优势。
使用时需先安装jax
环境,并在损失函数中使用LocalDevice
的probs
接口时添加mod
参数,并设置为 1(默认为 0)。微分采用 jax 自带的grad 函数,批处理采用 jax 的vmap 函数,示例如下
from isq import LocalDevice
from jax import grad, vmap
from jax import numpy as jnp
#定义量子线路
isq_str = '''
qbit q[2];
RX(theta[0], q[0]);
RY(theta[1], q[1]);
M(q[0]);
'''
#定义device
ld = LocalDevice()
#定义计算函数
def calc(params):
#使用probs函数进行带参编译和模拟,其中需要优化的参数通过optv封装后传入,mod值为1,使用jax.numpy计算
c = ld.probs(isq_str, mod = 1, theta = optv(params))
return c[0] - c[1]
theta = jnp.array([[0.2, 0.4] for _ in range(10)])
#微分
g = grad(calc)
#vmap批处理,以第0轴索引,输出每个划分的微分结果。该例子中即为以行为划分,输出10个结果
c = jax.vmap(g)
d = c(theta)
print(d)
isQ-core 语法说明¶
isQ-core 编程语言包含如下操作
1.1 自定义 qubit 变量¶
isQ-core 支持用户定义 qubit 变量(仅支持定义全局变量),可为单个变量,或者 qubit 数组(注意在 isQ 中, qubit 对应的关键字是 qbit
),定义格式如下
其中ID
为变量名,由字母和数字构成,如 a, b2,变量名不能重复;数组变量形式为ID[NUMBER]
,NUMBER
为数字,如 a[3], b1[10];每一行可定义单个或多个变量/数组。所有的 qubit 变量均默认初始化为|0>
示例
qbit a;
qbit b[3];
qbit q, p[5];
注:当编译为 QCIS 指令集时,qubit 按顺序对应到物理比特上,如上述示例中 a->Q1,b[0]->Q2
1.2 自定义 qcouple 变量¶
isQ-core 支持用户定义 qcouple 变量(仅支持定义全局变量),qcouple 指代耦合的两个量子比特,定义格式如下
qcouple 的定义与 qubit 类似,在使用时,qcouple 只能用于两比特门,如 CNOT,CZ
示例
qcouple c;
qcouple qc[3];
qcouple q, p[5];
...
CZ(c);
...
注:当编译为 QCIS 指令集时,qcouple 按顺序对应到耦合的物理比特对上,如上述示例中 c->Q67(Q1, Q7),qc[0]->Q68(Q1, Q8)
1.3 经典变量定义¶
isQ-core 支持用户通过var
定义经典变量(仅支持定义全局变量)定义格式如下
经典变量定义时需要给初始值,这些经典变量一般可用于旋转门的参数
示例
qbit q[66];
var x = 1.3;
var theta = {1.2, 1.4};
...
RX(x, q[0]);
RXY(theta[0], theta[1], q[5]);
...
1.4 自定义酉门¶
isQ-core 允许用户自定义符合下述三个条件的酉门
- 门的大小为 2 的幂次
- 定义在程序一开始
- 不和基础门重名
示例:
defgate Rs = [
0.5+0.8660254j,0,0,0;
0,1,0,0;
0,0,1,0;
0,0,0,1
]
1.5 酉操作¶
在说明酉操作之前,我们先介绍一个概念:qbundle。qbundle 表示 qubit 数组内的一组 qubit,其表达形式如下:
qbundle
有两种表达形式,其中ID
为 qubit 变量名,必须为之前定义的数组变量,idx
为下标,可以为常数,或以四则运算构建的表达式。在第一种表达形式中,用一系列下标来表示这一组 qubit,如我们之前定义了t[10]
,则可以用t[1,3,5,7]
来表示t[1],t[3],t[5],t[7]
这四个 qubit。第二种表达形式类似 python 的 range,用start/stop
表示起始/终止下标(不包含 stop),step
表示步长,默认为 1。如t[1:4]
表示t[1],t[2],t[3]
酉操作为对 qubit 作用酉门,定义格式如下:
GateID
为酉门名称,现有基础门包括:H,X,Y,Z,S,T,SD,TD,X2P,X2M,Y2P,Y2M,CX, CY, CZ,CNOT,RX,RY,RZ,RXY
。n 为门作用的 qubit 数目(CZ,CNOT 为 2,其余门均为 1)。酉门可作用在 qubit 变量上(形式一)或者 qbundle(形式二)上。当作用在 qbundle 上时,qbound_i的长度必须一致,此时其语义为对每个 j,执行GateID<qbundle_{1,j},…,qbundle_{n,j}>
示例
H(q);
H(p[1+2]);
CNOT(q, p[1]);
CNOT(p[1:3], p[2:4]); // = CNOT<p[1], p[2]>, CNOT<p[2], p[3]>
RX(0.5, q);
1.6 测量操作¶
对 qubit 进行测量,定义格式类似上面的酉操作:
其中对 qbundle 测量的语义为对 qbundle 里每一个 qubit 进行测量
示例:
M(q);
M(p[1]);
M(p[1:4]); // = M(p[1]), M(p[2]), M(p[3]);
1.7 for 循环¶
为方便用户做一些循环酉操作,简化代码,isQ-core 提供了 for 循环的支持,定义格式如下:
其中cid
为循环自增变量名,start,stop,step
和qbundle
中定义一致,start/stop
表示起始/终止值(不包含 stop),step
表示步长。forloopBody
里面可包含酉操作,测量操作,for 循环及 if 条件语句。在forloopBody
中可用带 cid 的表达式做下标来访问 qubit 变量
示例:
for i in 1:3{
H(t[i]);
CZ(w[i],w[i+1]);
}
1.8 if 条件语句¶
isQ-core 提供了 if 条件分支语句,定义格式如下:
或者
其中express
为可计算的算是表达式,如常量,int 变量或者其四则运算,asso
为比较运算符,目前支持>,>=,<,<=,==,!=
。ifbody
和elseBody
与forloopBody
一致。
1.9 注释¶
isQ-core 提供单行注释功能,在需要注释内容前加 // 即可
isQ-core api 说明¶
quantumCor¶
addGate
¶
静态函数,注册用户自定义酉门
参数 | 类型 | 说明 | 默认值 |
---|---|---|---|
name | str | 酉门名称 | - |
val | [np.array, list] | 酉门矩阵表示 | - |
getGate
¶
静态函数,获取当前注册的酉门集合
getMapping
¶
静态函数,实现量子比特映射(QcisDevice 中已调用该接口实现创新院 12 比特量子硬件的映射)
参数 | 类型 | 说明 | 默认值 |
---|---|---|---|
qbit_num | int | 物理比特数 | - |
topo | list | 硬件拓扑结构 | - |
isq_ir | str | 编译得到的 isq_ir | - |
Device¶
run
¶
编译+运行,根据后台选择对应编译结果
参数 | 类型 | 说明 | 默认值 |
---|---|---|---|
isq_str | str | isq 源码 | '' |
file | str | isq 外部文件,当有 isq_str 和 file 同时存在时,优先编译文件内容 | None |
**kwargs | - | isq 参数 | - |
compile_to_ir
¶
编译
参数 | 类型 | 说明 | 默认值 |
---|---|---|---|
isq_str | isq 源码 | '' | |
file | str | isq 外部文件,当有 isq_str 和 file 同时存在时,优先编译文件内容 | None |
target | str | 编译目标,目前支持isq , qcis , openqasm |
isq |
**kwargs | - | isq 参数 | - |
get_ir
¶
获取当次run
的编译结果
draw_circuit
¶
打印当前编译得到的 ir 的电路图
参数 | 类型 | 说明 | 默认值 |
---|---|---|---|
showparam | bool | 是否显示 RX,RY,RZ 的角度 | False |
LocalDevice¶
__init__
初始化
参数 | 类型 | 说明 | 默认值 |
---|---|---|---|
shots | int | 运行次数 | 100 |
max_wait_time | int | 任务查询最大等待时间 | 60 |
name | str | 后台名称 | 'local_device' |
mode | str | 模拟模式,fast /normal |
fast |
logger | Logger | 日志对象 | logging.getLogger(name) |
probs
获取幅值(不进行测量,直接返回概率)
参数 | 类型 | 说明 | 默认值 |
---|---|---|---|
isq_str | str | isq 源码 | '' |
file | str | isq 外部文件,当有 isq_str 和 file 同时存在时,优先编译文件内容 | None |
mod | int | 采用的数据模式,0 —autograd.numpy, 1 —jax.numpy |
0 |
**kwargs | - | isq 参数,当需要配合优化器使用时,需要优化的参数用 optv 封装 | - |
QcisDevice¶
__init__
初始化
参数 | 类型 | 说明 | 默认值 |
---|---|---|---|
user | str | 创新院平台用户名 | - |
passwd | str | 创新院平台密码 | - |
shots | int | 运行次数 | 100 |
max_wait_time | int | 任务查询最大等待时间 | 60 |
name | str | 后台名称 | 'qcis_device' |
logger | Logger | 日志对象 | logging.getLogger(name) |
AwsDevice¶
__init__
初始化
参数 | 类型 | 说明 | 默认值 |
---|---|---|---|
device_arn | str | aws QPU, 可选值详见 braket 说明文档 | - |
s3 | tuple | aws s3 存储桶,云平台使用时,无需填写,使用平台提供的存储桶 | - |
shots | int | 运行次数 | 100 |
max_wait_time | int | 任务查询最大等待时间 | 60 |
name | str | 后台名称 | 'aws_device' |
logger | Logger | 日志对象 | logging.getLogger(name) |
ISQTask¶
__init__
¶
初始化
参数 | 类型 | 说明 | 默认值 |
---|---|---|---|
task_id | Union[int, str] | 任务编号 | - |
task_type | TaskType | 任务类型 | - |
state | TaskState | 任务状态 | - |
device | Device | 关联设备 | - |
**kwargs | - | 其他参数 | - |
result
¶
获取结果,当任务状态为TaskState.COMPLETE
时,直接返回结果,当状态为TaskState.WAIT
时,开始查询结果,当查询时间超过关联设备设置的任务查询最大等待时间,则任务仍在排队或运行中,返回空字典,否则,返回查询结果
cancel
¶
当使用 AwsDevice 生成任务时,可通过该接口取消任务(目前 QcisDevice 的任务无法取消)
TaskState¶
- WAIT
- COMPLETE
- FAIL
- CANCEL
TaskType¶
- QCSI
- AWS
optimizer¶
__init__
¶
初始化
参数 | 类型 | 说明 | 默认值 |
---|---|---|---|
lr | float | 学习率 | - |
argnum | list | 需要优化的参数位置 | [0] |
opt
¶
梯度下降法优化参数
参数 | 类型 | 说明 | 默认值 |
---|---|---|---|
fun | function | 损失函数 | - |
params | list | 需要优化的参数 | - |
grad¶
__init__
¶
初始化
参数 | 类型 | 说明 | 默认值 |
---|---|---|---|
fun | function | 损失函数 | - |
argnum | list | 需要优化的参数位置 | [0] |