在真实量子设备中,由于现阶段技术的不成熟,量子系统会由于量子操作、环境影响等各种因素而产生噪声。现阶段噪声对量子设备的影响不可忽略,因此在量子线路中加入对噪声的模拟,可以帮助我们寻找对噪声具有鲁棒性的量子算法,或设计减少噪声影响的纠错方案。
接下来将介绍常见的量子信道和噪声模拟器,以及如何利用 MindSpore Quantum 完成含噪声的量子模拟,同时我们利用benchmark采用随机量子线路任务,并在每个单量子比特门后加入比特翻转信道和热驰豫信道,每个双量子比特门后加入去极化信道,完成含噪声的量子线路模拟。以4到24量子比特为例,MindSpore Quantum 与主流软件 Qiskit 相比,任务运行速度快1000倍以上,结果如下图:
硬件信息:Kunlun 9032-32P (Intel CPU E7-8890,8U32G)
计算精度:Qiskit、MindSpore Quantum是FP64
软件版本:Qiskit 0.45.2、MindSpore Quantum0.9.11
扫码查看benchmark开源代码仓
01
什么是量子信道
噪声分为两种类型:相干噪声和非相干噪声。相干噪声一般来源于门操作中参数的噪声化,因此是幺正演化并且易于模拟;非相干噪声则来源于系统与环境的相互作用,因此通常是非幺正演化,会使量子系统从纯态变为混态,这个过程也被称为量子信道(Quantum channel)。
混态的量子系统通常用密度矩阵的形式表示,但也可以通过“采样-统计”的蒙特卡洛法得到统计模拟结果。在 MindSpore Quantum 中,我们用蒙特卡洛法来模拟量子信道,其中噪声门会以一定概率影响量子比特,通过对线路的多次采样,可以得到含噪声量子线路的模拟运行结果。
量子信道的数学表示如下:
02
如何将 MindSpore Quantum 中的噪声信道加入量子线路中
以去极化信道为例:
from mindquantum.core.gates.channel import DepolarizingChannel
from mindquantum import Circuit, X
circ = Circuit()
circ += X.on(0)
circ += DepolarizingChannel(0.1).on(0)
circ.measure(0)
circ.svg()
复制
此时我们成功搭建了一个单比特的量子线路,该比特在作用X
门后,会受到去极化噪声的影响,具体表现为有10%概率额外作用一个泡利门,其中X
、Y
、Z
门平分概率。
现在我们对该线路进行1000次模拟并输出采样结果:
from mindquantum import Simulator
sim = Simulator('projectq', 1)
result = sim.sampling(circ, shots=1000)
result.svg()
复制
03
如何在 MindSpore Quantum 中构建噪声模型
MindSpore Quantum 中包含各种噪声信道,利用噪声信道我们可以对真实的量子芯片进行模拟。在 MindSpore Quantum 中,我们定义了各种 ChannelAdder,可以有选择性的在量子线路的不同位置添加噪声信道,依次完成含噪声的量子模拟。下面介绍几种 ChannelAdder 以及在 MindSpore Quantum 中如何定义。
ChannelAdder 是一个能够在量子线路特定位置添加特定信道的处理器,例如在测量门后添加比特翻转信道。ChannelAdder 类主要由三个函数构成,_accepter()、_excluder() 和 _handler(BasicGate),其功能对应如下:
-
_accepter():返回一个由函数构成的列表,称为接受规则集,其中每个接受规则函数的输入都是一个量子门,当函数返回值为 True 时表示我们可以在该量子门后添加信道。
-
_excluder():返回一个由函数构成的列表,称为拒绝规则集,其中每个拒绝规则函数的输入都是一个量子门,当函数返回值为 True 时表示我们拒绝在该量子门后添加信道。
-
_handler(BasicGate):输入一个量子门,返回一段量子线路,表示在输入量子门后添加一段自定义的信道。
我们重定义类 ChannelAdder 的 __call__ 函数,直接调用 ChannelAdder 即可生成处理后的量子线路。
BitFlipAdder
BitFlipAdder 的接口定义为:
BitFlipAdder(flip_rate: float, with_ctrl=True, focus_on: int = None, add_after: bool = True)
复制
该 Adder 会在量子门后添加一个比特翻转信道,接口的参数含义为:
-
flip_rate (float):比特翻转信道的翻转概率。
-
with_ctrl (bool):是否在控制位上添加比特。默认值:True。
-
focus_on (bool):只将该噪声信道作用在 focus_on 比特上。如果为 None,则作用在量子门的所有比特上。默认值:None。
-
add_after (bool):是否在量子门后面添加信道。如果为 False,信道将会加在量子门前面。默认值:True。
例如,我们可以通过如下接口,在给定量子线路的每个量子门后都添加一个翻转概率为 0.3 的比特翻转信道:
from mindquantum.core.circuit.channel_adder import BitFlipAdder
from mindquantum.core import gates as G
from mindquantum.core.circuit import Circuit
circ = Circuit()+G.H(0)+G.RX('a').on(1)+G.Z(1, 0)
circ.svg()
复制
bit_flip_adder = BitFlipAdder(0.3, with_ctrl=False)
new_circ = bit_flip_adder(circ)
new_circ.svg()
复制
MeasureAccepter
MeasureAccepter()
复制
该 Adder 会选择对应的测量门,它目前只是一个 Accepter,不会改变量子线路中的任何门,需要利用 MixerAdder,跟其他的 Adder 搭配使用。
MixerAdder
MixerAdder(adders: typing.List[ChannelAdderBase])
复制
MixerAdder 可以将多个 Adder 混合起来,保证量子门在每一个 Adder 中的接受函数集和拒绝函数集同时满足时,顺序添加 _handler 产生的量子线路。
举例来说,我们可以将上文提到的 BitFlipAdder 和 MeasureAccepter 混合起来,达到只在测量门前添加比特翻转信道的功能:
from IPython.display import display_svg
from mindquantum.core.circuit.channel_adder import MixerAdder, MeasureAccepter
mixer = MixerAdder([
BitFlipAdder(flip_rate=0.01),
MeasureAccepter(),
], add_after=False)
print(mixer)
circ = Circuit() + G.H(0) + G.RX('a').on(1) + G.Z(1, 0) + G.Measure().on(0)
display_svg(circ.svg())
new_circ = mixer(circ)
new_circ.svg()
复制
SequentialAdder
SequentialAdder(adders: typing.List[ChannelAdderBase])
复制
SequentialAdder 是由多个 Adder 顺序构成类,量子线路会经过 SequentialAdder 中的 Adder 依次处理,生成最终的量子线路。例如,我们想构建一个先在测量门前添加一个 p=0.01 的比特翻转信道,然后在 q1 比特上的非测量门和非噪声信道后添加 p=0.05 的去极化信道。
自定义 Adder
我们首先自定义在某个比特添加比特翻转信道的 Adder。
from mindquantum.core.circuit.channel_adder import ChannelAdderBase, SequentialAdder
class CustomDepolarizingAdder(ChannelAdderBase):
def __init__(self, q, p):
self.q = q
self.p = p
super().__init__()
def _accepter(self):
return [lambda x: self.q in x.obj_qubits or self.q in x.ctrl_qubits]
def _excluder(self):
return [lambda x: isinstance(x, (G.Measure, G.NoiseGate))]
def _handler(self, g):
return Circuit([G.DepolarizingChannel(self.p).on(self.q)])
def __repr__(self):
return f"CustomDepolarizingAdder<q={self.q}, flip_rate={self.p}>"
seq_adder = SequentialAdder([
MixerAdder([
MeasureAccepter(),
BitFlipAdder(flip_rate=0.01),
], add_after=False),
CustomDepolarizingAdder(q=1, p=0.05),
])
print(seq_adder)
复制
circ = Circuit() + G.H(0) + G.RX('a').on(1) + G.Z(1, 0) + G.Measure().on(0)
display_svg(circ.svg())
new_circ = seq_adder(circ)
new_circ.svg()
复制
上述自定义量子信道也可以通过 MindSpore Quantum 中的预定义信道搭建而成。
from mindquantum.core.circuit import ReverseAdder, NoiseExcluder, NoiseChannelAdder
seq_adder = SequentialAdder([
MixerAdder([
MeasureAccepter(),
BitFlipAdder(flip_rate=0.01),
], add_after=False),
MixerAdder([
ReverseAdder(MeasureAccepter()),
NoiseExcluder(),
NoiseChannelAdder(G.DepolarizingChannel(0.05), focus_on=1),
])
])
print(seq_adder)
seq_adder(circ).svg()
复制
更复杂的例子下面我们来搭建一个更复杂的 ChannelAdder 例子,在该例子中,芯片的不同比特上的单比特门操作的噪声可以忽略不记,而双比特门在不同比特上具有不同的去极化信道,且线路的测量具有一个翻转概率为0.01的比特翻转错误。
我们假设不同两比特上的去极化率为:
然后,我们定义出满足要求的 Adder:
from mindquantum.core.circuit import QubitNumberConstrain, QubitIDConstrain, DepolarizingChannelAdder
noise_adder = SequentialAdder([
MixerAdder([
NoiseExcluder(),
ReverseAdder(MeasureAccepter()),
QubitNumberConstrain(2),
QubitIDConstrain([0, 1]),
DepolarizingChannelAdder(0.01, 2)
]),
MixerAdder([
NoiseExcluder(),
ReverseAdder(MeasureAccepter()),
QubitNumberConstrain(2),
QubitIDConstrain([1, 2]),
DepolarizingChannelAdder(0.02, 2)
]),
MixerAdder([
NoiseExcluder(),
ReverseAdder(MeasureAccepter()),
QubitNumberConstrain(2),
QubitIDConstrain([0, 2]),
DepolarizingChannelAdder(0.03, 2)
]),
MixerAdder([
NoiseExcluder(),
MeasureAccepter(),
BitFlipAdder(0.01)
], add_after=False),
])
noise_adder
复制
ChannelAdder 列表
下面列举出 MindSpore Quantum 中现有的一些 ChannelAdder,并给出具体含义:
ChannelAdder | 功能 |
---|---|
ChannelAdderBase | 在量子门前面或者后面添加信道 |
NoiseChannelAdder | 添加一个单比特量子信道 |
MeasureAccepter | 选取测量门 |
ReverseAdder | 翻转给定信道添加器的接受和拒绝规则 |
NoiseExcluder | 排除噪声门 |
BitFlipAdder | 在量子门前面或者后面添加一个比特翻转信道 |
MixerAdder | 在子添加器的接受集被满足、拒绝集被拒绝时依次执行所有的添加器 |
SequentialAdder | 依次执行每一个添加器 |
QubitNumberConstrain | 只将噪声信道作用在比特数为 n_qubits 的量子门上 |
QubitIDConstrain | 只将噪声信道作用在给定比特序号的量子门上 |
GateSelector | 选择想要的量子门添加信道 |
DepolarizingChannelAdder | 添加去极化信道 |
04
如何在 MindSpore Quantum 中进行噪声模拟
我们可以将如上定义的各种 Adder 与现有的模拟器组合,构成一个含噪声模拟器。
noise_sim = Simulator(NoiseBackend('mqvector', 2, seq_adder))
res2 = noise_sim.sampling(noiseless_circ, shots=10000)
display(res2.svg())
display(noise_sim.backend.transform_circ(noiseless_circ).svg())
复制
其他教程
MindSpore Quantum 系列教程15 | 高级使用指南——布洛赫球
MindSpore Quantum 系列教程14 | 高级使用指南——含噪声量子线路
MindSpore Quantum 系列教程13 | 高级使用指南——Shor算法
MindSpore Quantum 系列教程12 | 高级使用指南——Grover搜索算法
MindSpore Quantum 系列教程11 | 高级使用指南——量子相位估计算法
扫码查看更多关于MindSpore Quantum的教程