import deepquantum as dq
import numpy as np
import torch
print('version', dq.__version__)
version 4.2.0
基于测量的量子计算(MBQC)教程#
构建Pattern#
通过转译QubitCircuit线路构建Pattern#
构建QubitCircuit
cir = dq.QubitCircuit(2)
cir.h(0)
cir.h(1)
cir.cnot(0, 1)
cir.draw()
转译为MBQC的Pattern类
# Transpile circuit to measurement pattern
pattern = cir.pattern()
print(pattern)
Pattern(
(init_state): GraphState(
(subgraphs): ModuleList(
(0): SubGraphState(nodes_state=[0], nodes=[0])
(1): SubGraphState(nodes_state=[1], nodes=[1])
)
)
(commands): Sequential(
(0): Node(nodes=[2])
(1): Entanglement(nodes=[0, 2])
(2): Measurement(nodes=[0], plane=XY, angle=0.0, s_domain=set(), t_domain=set())
(3): Correction(basis=x, nodes=[2], domain={0})
(4): Node(nodes=[3])
(5): Entanglement(nodes=[1, 3])
(6): Measurement(nodes=[1], plane=XY, angle=0.0, s_domain=set(), t_domain=set())
(7): Correction(basis=x, nodes=[3], domain={1})
(8): Node(nodes=[4, 5])
(9): Entanglement(nodes=[3, 4])
(10): Entanglement(nodes=[2, 4])
(11): Entanglement(nodes=[4, 5])
(12): Measurement(nodes=[3], plane=XY, angle=0.0, s_domain=set(), t_domain=set())
(13): Measurement(nodes=[4], plane=XY, angle=0.0, s_domain=set(), t_domain=set())
(14): Correction(basis=x, nodes=[5], domain={4})
(15): Correction(basis=z, nodes=[5], domain={3})
(16): Correction(basis=z, nodes=[2], domain={3})
)
)
如果QubitCircuit初态是batch形式,转译后的Pattern初态依然是batch形式。
n_qubits = 2
batch_size = 5
init_state = torch.rand(batch_size, 2**n_qubits) # 输入QubitCiurcuit后会自动归一化
cir = dq.QubitCircuit(n_qubits, init_state=init_state)
cir.h(0)
cir.h(1)
cir.cnot(0, 1)
pattern = cir.pattern()
print(pattern.init_state.full_state.shape)
print(pattern.init_state.full_state)
torch.Size([5, 4, 1])
tensor([[[0.7524+0.j],
[0.1355+0.j],
[0.6322+0.j],
[0.1257+0.j]],
[[0.5817+0.j],
[0.4449+0.j],
[0.6000+0.j],
[0.3220+0.j]],
[[0.0243+0.j],
[0.3302+0.j],
[0.0513+0.j],
[0.9422+0.j]],
[[0.2712+0.j],
[0.5765+0.j],
[0.3570+0.j],
[0.6831+0.j]],
[[0.4778+0.j],
[0.4311+0.j],
[0.5746+0.j],
[0.5057+0.j]]])
可视化构建的图态。其中,方形node表示输入,edge表示node间存在CZ纠缠,蓝色node表示待测,剩余的灰色node表示输出。
绿色/红色虚线表示测量角度对于t domain/s domain的依赖。因为转译完得到的是未经优化的wild pattern,中间的Z/X修正尚未转移到测量角度上,所以图中并没有显示。
pattern.draw()
手动构建Pattern#
除了通过QubitCircuit的转译,用户可以初始化Pattern后,通过手动添加NEMCcommands,构建自定义的Pattern。
输入的节点可以用初始化参数中nodes_state设置,类型可以是int,代表初始化节点的数量,也可以用List指定节点的编号。
而初态用参数state设置,默认为全 \( \left |+\right \rangle\) 态。除了输入自定义的态矢,可以用str类型的输入,支持'plus', 'minus', 'zero'和'one'。
pattern = dq.Pattern(nodes_state=[0, 1])
## 等效为 pattern = dq.Pattern(nodes_state=2)
print(pattern.init_state.full_state)
pattern.draw()
tensor([[0.5000+0.j],
[0.5000+0.j],
[0.5000+0.j],
[0.5000+0.j]])
# 自定义初态
pattern = dq.Pattern(nodes_state=[0, 1], state=[1, 0, 0, 0])
print(pattern.init_state.full_state)
# 初态str表示
pattern = dq.Pattern(nodes_state=[0, 1], state='minus')
print(pattern.init_state.full_state)
pattern = dq.Pattern(nodes_state=[0, 1], state='zero')
print(pattern.init_state.full_state)
pattern = dq.Pattern(nodes_state=[0, 1], state='one')
print(pattern.init_state.full_state)
tensor([[1.+0.j],
[0.+0.j],
[0.+0.j],
[0.+0.j]])
tensor([[ 0.5000+0.j],
[-0.5000+0.j],
[-0.5000+0.j],
[ 0.5000-0.j]])
tensor([[1.+0.j],
[0.+0.j],
[0.+0.j],
[0.+0.j]])
tensor([[0.+0.j],
[0.+0.j],
[0.+0.j],
[1.+0.j]])
可以在nodes_state的基础上,额外加入edges和nodes作为输入的初始图态。
pattern = dq.Pattern(nodes_state=[0, 1], nodes=[2, 3], edges=[[2, 3]])
pattern.draw()
根据NEMC Commands序列,生成特定的Pattern
Command |
定义 |
Pattern函数 |
|---|---|---|
\(N_i\) |
Node (qubit) preparation command with node index \(i\) |
\(n(i)\) |
\(E_{ij}\) |
Entanglement command which apply \(CZ\) gate to nodes \((i, j)\) |
\(e(i, j)\) |
\(^t[M_i^{\lambda, \alpha}]^s\) |
Measurement command which perform measurement of node \(i\) ,with |
\(m(i, \alpha, \lambda, t, s)\) |
\(X_i^s\) |
Correction X command applied to qubit \(i\) with signal domain \(s\) |
\(x(i, s)\) |
\(Z_i^s\) |
Correction Z command applied to qubit \(i\) with signal domain \(s\) |
\(z(i, s)\) |
例如,生成 \( X_3^{s_0+s_1}\ ^{t_1} [M_2^{\pi}]^{s_0}E_{23}N_3[M_1^{\pi}]^{s_0} M_0^{\pi}E_{12}E_{02}N_2E_{01}N_1N_0\)
pattern = dq.Pattern(nodes_state=[0, 1])
pattern.n(2)
pattern.e(0, 2)
pattern.e(1, 2)
pattern.m(node=0, angle=np.pi)
pattern.m(node=1, angle=np.pi, s_domain=[0])
pattern.n(3)
pattern.e(2, 3)
pattern.m(node=2, angle=np.pi, s_domain=[0], t_domain=[1])
pattern.x(node=3, domain=[0, 1])
pattern.draw()
优化Pattern#
进行standardize操作,将Pattern从右向左按NEMC的指令类型进行排列,形成标准形式。
注意,相比wild pattern,standard form会占用更多内存。如果标准化后出现内存溢出的报错,可以尝试对wild pattern直接进行前向演化。
pattern.standardize()
print(pattern)
Pattern(
(init_state): GraphState(
(subgraphs): ModuleList(
(0): SubGraphState(nodes_state=[0, 1], nodes=[0, 1])
)
)
(commands): Sequential(
(0): Node(nodes=[2])
(1): Node(nodes=[3])
(2): Entanglement(nodes=[0, 2])
(3): Entanglement(nodes=[1, 2])
(4): Entanglement(nodes=[2, 3])
(5): Measurement(nodes=[0], plane=XY, angle=3.1415927410125732, s_domain=set(), t_domain=set())
(6): Measurement(nodes=[1], plane=XY, angle=3.1415927410125732, s_domain={0}, t_domain=set())
(7): Measurement(nodes=[2], plane=XY, angle=3.1415927410125732, s_domain={0}, t_domain={1})
(8): Correction(basis=x, nodes=[3], domain={0, 1})
)
)
通过signal shifting 进一步优化,目的是消除测量角度对于t_domain的依赖(Z-dependency),从而降低量子深度。
pattern.shift_signals()
print(pattern)
Pattern(
(init_state): GraphState(
(subgraphs): ModuleList(
(0): SubGraphState(nodes_state=[0, 1], nodes=[0, 1])
)
)
(commands): Sequential(
(0): Node(nodes=[2])
(1): Node(nodes=[3])
(2): Entanglement(nodes=[0, 2])
(3): Entanglement(nodes=[1, 2])
(4): Entanglement(nodes=[2, 3])
(5): Measurement(nodes=[0], plane=XY, angle=3.1415927410125732, s_domain=set(), t_domain=set())
(6): Measurement(nodes=[1], plane=XY, angle=3.1415927410125732, s_domain={0}, t_domain=set())
(7): Measurement(nodes=[2], plane=XY, angle=3.1415927410125732, s_domain={0}, t_domain=set())
(8): Correction(basis=x, nodes=[3], domain={0, 1})
)
)
通过图态的可视化,可以观察到signal shifting后的测量不再依赖于绿色的Z修正。
pattern.draw()
执行MBQC模拟#
前向演化#
和DeepQuantum其它模块一样,仅需一个前向函数即可执行对Pattern的模拟。
pattern()
GraphState(
(subgraphs): ModuleList(
(0): SubGraphState(nodes_state=[3], nodes=[3])
)
)
返回的结果是末态输出的GraphState,使用属性full_state可以得到末态的态矢。
state = pattern().full_state
print(state)
tensor([[-0.7071+6.1817e-08j],
[-0.7071+6.1817e-08j]])
对应的测量结果由GraphState中measure_dict保存:
print(pattern.state.measure_dict)
defaultdict(list, {0: [1], 1: [1], 2: [1]})
支持通过 data 输入Pattern中 encode=True 的command参数(即测量角度),通过 state 指定初态,对Pattern进行演化:
pattern = dq.Pattern(nodes_state=[0, 1])
pattern.n(2)
pattern.e(0, 2)
pattern.e(1, 2)
pattern.m(node=0, encode=True)
pattern.m(node=1, encode=True, s_domain=[0])
pattern.x(node=2, domain=[0, 1])
angle = torch.randn(2)
print(pattern(data=angle).full_state)
tensor([[0.8211+0.5634j],
[0.0754+0.0517j]])
初态的类型需要是GraphState:
init_graph_state = dq.GraphState([0, 1], state=[1, 0, 0, 0])
print(pattern(data=angle, state=init_graph_state).full_state)
tensor([[0.7071+0.j],
[0.7071+0.j]])
支持batch输入#
测量角度的batch输入:
angle = torch.randn(6, 2)
print(pattern(data=angle).full_state)
tensor([[[ 0.0848-0.9064j],
[ 0.0386-0.4119j]],
[[ 0.0642+0.6187j],
[-0.0809-0.7788j]],
[[-0.1213-0.0096j],
[-0.9895-0.0783j]],
[[-0.0070-0.0196j],
[-0.3388-0.9406j]],
[[-0.0062-0.0012j],
[-0.9820-0.1889j]],
[[-0.3533+0.0935j],
[-0.8998+0.2382j]]])
初态的batch输入:
init_graph_state = dq.GraphState([0, 1], state=[[1, 0, 0, 0], [0, 1, 0, 0]])
print(pattern(state=init_graph_state).full_state)
tensor([[[-3.0909e-08-0.7071j],
[-3.0909e-08-0.7071j]],
[[ 1.2410e-01-0.6961j],
[-1.2410e-01+0.6961j]]])
也支持转译前QubitCircuit中参数化门的encode:
cir = dq.QubitCircuit(2)
cir.h(0)
cir.rz(0, encode=True)
cir.ry(1, encode=True)
cir.cnot(0, 1)
pattern = cir.pattern()
data = torch.randn(2)
print(pattern(data=data).full_state)
data = torch.randn(6, 2)
print(pattern(data=data).full_state)
tensor([[-0.6325+0.2172j],
[ 0.2172-0.0746j],
[ 0.2232-0.0543j],
[-0.6498+0.1580j]])
tensor([[[-0.1562+0.6707j],
[-0.0364+0.1562j],
[-0.1566-0.0348j],
[-0.6723-0.1493j]],
[[-0.2429-0.6104j],
[ 0.0967+0.2429j],
[-0.1348+0.2241j],
[ 0.3386-0.5630j]],
[[ 0.2640+0.5887j],
[-0.1184-0.2640j],
[-0.2793-0.0755j],
[ 0.6229+0.1683j]],
[[-0.2568-0.5965j],
[ 0.1106+0.2568j],
[ 0.2546+0.1156j],
[-0.5914-0.2685j]],
[[-0.5688+0.2805j],
[ 0.2805-0.1383j],
[-0.2847+0.1294j],
[ 0.5773-0.2624j]],
[[-0.1979-0.6466j],
[ 0.0605+0.1979j],
[-0.0180+0.2061j],
[ 0.0589-0.6736j]]])
支持自动微分#
MBQC模块支持基于PyTorch的自动微分,用户可以利用这一特性设计和模拟含梯度优化的变分算法(VMBQC)。
data = torch.randn(2, requires_grad=True)
print(pattern(data=data).full_state)
tensor([[-0.1982-0.6463j],
[ 0.0608+0.1982j],
[ 0.0490-0.2015j],
[-0.1599+0.6568j]], grad_fn=<SqueezeBackward1>)