跳转至

附录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的形式返回。QcisDeviceAwsDevice返回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 量子后端,可为LocalDeivceQcisDeivceAwsDeivce

用该修饰符修饰的函数内部需采用注释的形式用 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环境,并在损失函数中使用LocalDeviceprobs接口时添加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),定义格式如下

qbit \ ID; \\ qbit \ ID[NUMBER]; \\ qbit \ ID_1,…, ID_n[NUMBER];

其中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 \ ID; \\ qcouple \ ID[NUMBER]; \\ qcouple \ ID_1,…, ID_n[NUMBER];

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定义经典变量(仅支持定义全局变量)定义格式如下

var \ ID = NUMBER; \\\ var \ ID[n] = \{NUMBER_1,...,NUMBER_n\};

经典变量定义时需要给初始值,这些经典变量一般可用于旋转门的参数

示例

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,其表达形式如下:

ID[idx_1, idx_2,..., idx_n] \\\ ID[sart:stop:step]

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 (qid_1,…,qid_n) \\\ GateID (qbundle_1,…,qbundle_n) \\\ GateID (theta, qid) \\\ GateID (theta, qbundle) \\\ GateID (phi, theta, qid) \\\ GateID (phi, theta, qbundle)

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 进行测量,定义格式类似上面的酉操作:

M (qid) \\\ M (qbundle)

其中对 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 循环的支持,定义格式如下:

for \ cid \ in \ start:stop:step\{ \\\ forloopBody \\\ \}

其中cid为循环自增变量名,start,stop,stepqbundle中定义一致,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 条件分支语句,定义格式如下:

if (expression \ asso \ expression )\{ \\\ ifBody \\\ \}

或者

if (expression \ asso \ expression )\{ \\\ ifBody \\\ \}else\{ elseBody \}

其中express为可计算的算是表达式,如常量,int 变量或者其四则运算,asso为比较运算符,目前支持>,>=,<,<=,==,!=ifbodyelseBodyforloopBody一致。

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]