版权所有 (c) 2021 百度量子计算研究所,保留所有权利。
伯恩斯坦-瓦兹拉尼算法是由伯恩斯坦(Ethan Bernstein)和瓦兹拉尼(Umesh Vazirani)于 1992 年提出,用来展示量子算法在理论上有胜过经典计算机的潜力。
在这一节中我们将具体介绍量子黑盒的概念及其电路形式,并介绍设计量子算法中非常重要的步骤——均匀叠加,是实现量子并行计算的关键。量子黑盒与均匀叠加的概念对这一章后续的算法都非常重要。
以下我们形式化描述伯恩斯坦-瓦兹拉尼算法解决的问题。
给定一个黑盒(Oracle),计算布尔函数 。 满足以下性质:存在长度为 的比特串 (我们称 为函数 的隐藏比特串。)使得
其中 是点积运算,定义为 , 表示比特串 第 个比特, 表示模 加法运算。用 作为输入调用 ,黑盒的输出为 。算法的任务是通过调用 来计算比特串 。算法的复杂度定义为调用 的次数。
在这一节我们分析使用经典计算机完成该任务需要调用 的次数。任何经典算法调用一次 最多只能获取一比特信息,因此要计算长度为 的比特串 至少需要对 进行 次调用。另一方面,因为
即每次调用能够确定 的一位比特,所以对 调用 次可以计算 。经典计算机完成该任务需要调用 的次数为 。
在这一节我们介绍伯恩斯坦-瓦兹拉尼量子算法,该算法只需调用 次 即可计算 ,因此相对经典算法有多项式级加速。我们首先讨论如何构造一个量子门实现 “调用 ” 操作,然后利用该量子门给出伯恩斯坦-瓦兹拉尼算法的量子电路,最后逐步分析该量子电路的演化过程,证明算法的正确性。
我们首先要将“调用 ”翻译成量子计算机能识别的操作。为此,我们假设有如下形式的量子门:
图 1:伯恩斯坦-瓦兹拉尼算法的量子黑盒。
数学上,量子门 的定义为:
其中 是 量子比特串,我们称之为主寄存器; 是单量子比特,我们称之为辅助量子比特。可以证明如上构造的 是一个酉矩阵,它的作用是将输出 编码到辅助量子比特 上。从这个意义来讲, 实现了“调用 ”操作。当 满足 时,辅助量子比特不变;当输入 满足 时,辅助量子比特会被翻转。
习题 1. 证明满足公式 的 比特量子门 是一个酉矩阵。
伯恩斯坦-瓦兹拉尼算法的量子电路表示如下:
图 2:伯恩斯坦-瓦兹拉尼算法的量子电路。
以下我们按照量子电路从左至右逐步分析系统状态的演化过程。
步骤1:初始化系统量子态。 将主寄存器初始化为 ,即前 个量子比特初始化为 状态,并将辅助量子比特初始化为 状态。此时整个系统(主寄存器加辅助量子比特所构成的系统)所处的状态为
步骤2:均匀叠加。 即对所有 个量子比特分别作用 门,作用后的系统状态为:
最后一步利用了量子计算中的一个常用技巧:
注: 在这里我们解释并强调一下均匀叠加的重要性,这一步也是大多数基于黑盒的量子算法可以相对于经典算法实现加速的关键。注意到在经过均匀叠加后,主寄存器的量子态变成了 ,也就是所有可能输入的均匀叠加态,因此在后续作用量子黑盒后将实现对所有输入的并行计算,而这是经典计算所无法实现的。
步骤3:作用量子黑盒。 将 作用到 ,作用后的系统状态为:
推导的第四步利用了量子计算中常用的等式:。可以通过穷举 的值来证明该等式。 最后一步利用到公式 。
步骤4:对主寄存器的所有量子比特分别作用 门。 作用后的系统状态为:
最后一步利用了 门的基本性质: 门的逆变换仍为 ,即 。
步骤5:主寄存器的所有量子比特分别执行计算基测量。 由 的表达式可知,测量结果比特串就是 。
习题 2. 证明公式 。
需要的硬件设备:
输入: 量子黑盒 ,功能是 ,其中函数 如公式 定义。
输出: 隐藏比特串 。
运行代价: 调用一次量子黑盒 。
运行过程:
主寄存器量子比特初始化为 ,辅助量子比特初始化为 。
均匀叠加,对每个量子比特上作用 门得到
为了加深对此算法的理解,在这一小节,我们介绍如何在量易伏平台上进行模拟实验。我们将首先考虑一个三比特的简单例子,给出对应的量子黑盒,以及 QComposer 中的量子电路。有兴趣的读者可以登录量易伏平台搭建并体验使用量子真机运行,也可以考虑其他的隐藏比特串,设计对应的量子黑盒并搭建自己的电路。然后我们将基于混合语言编程给出此例子的代码,推荐读者在本地使用 QCompute SDK 进行模拟实验。
考虑隐藏比特串为 ,此时黑盒 计算的函数 可表示为
其中 表示 的第 比特。在 QComposer 中的电路如下图 3 所示(读者可自行验证此处量子黑盒部分实现了上述函数):
图 3:量易伏 QComposer 上对 的电路
其对应的 OPENQASM 代码如下:
OPENQASM 2.0;
include "qelib1.inc";
qreg q[4];
creg c[4];
// 将辅助量子比特初始化为|1>
//
x q[3];
// 所有 n+1 个量子比特分别作用 H 门
//
h q[0];
h q[1];
h q[2];
h q[3];
//
// 作用量子黑盒
cx q[0], q[3];
cx q[2], q[3];
// 主寄存器的所有量子比特分别作用 H 门
//
h q[0];
h q[1];
h q[2];
//
measure q[0] -> c[0];
measure q[1] -> c[1];
measure q[2] -> c[2];
理想模拟器输出结果为:
{
"101":1024
}
注: 量易伏平台上模拟返回的字符串从左往右第一位表示的是最高位的量子比特,和传入的信息顺序相反,故此处理想模拟器输出结果 101 在翻转后得到 101 即为隐藏比特串(如果读者考虑其他例子需要注意这一点)。
基于量易伏平台的具体代码如下:
from QCompute import *
import numpy as np
# 不直接给出输出,后续通过print给出需要信息
from QCompute import Define
Define.Settings.drawCircuitControl = []
Define.Settings.outputInfo = False
# 量子电路比特数
qubit_num = 4
# 测量次数
shots = 1024
# 创建环境
env = QEnv()
# 选择随机数
seed = int(2147483647*np.random.random())
# 选择后端
# 注:量易伏也支持云端模拟器和真机后端,访问 https://quantum-hub.baidu.com/ 获取更多信息。
env.backend(BackendName.LocalBaiduSim2, '-s ' + str(seed))
# 量子黑盒,其中比特串 s 为 101
def Oracle(q):
CX(q[0], q[3])
CX(q[2], q[3])
# 步骤 1:初始化 4 量子比特电路
q = [env.Q[i] for i in range(qubit_num)]
# 最后一个量子比特初始化为1
X(q[3])
# 步骤 2:加一层 H 门
for i in range(qubit_num):
H(q[i])
# 步骤 3:加入量子黑盒
Oracle(q)
# 步骤 4:加一层 H 门
for i in range(qubit_num):
H(q[i])
# 步骤 5:测量 0, 1, 2 号量子比特结果
MeasureZ([q[0], q[1], q[2]], range(3))
taskResult = env.commit(shots, fetchMeasure=True)
print("Shots", taskResult['shots'])
print("Counts", taskResult['counts'])
print("Seed", seed)
# QCompute 默认从最后一位开始测量,因此输出需要反向
bit = max(taskResult['counts'], key=taskResult['counts'].get)
bit[::-1]
print("解码得到隐藏比特串:", bit[::-1])
运行结束后我们会得到
Shots 1024
Counts {'101': 1024}
Seed 948332576
解码得到隐藏比特串: 101
这就是 对应的隐藏比特串 。
[1] Bernstein, Ethan, and Umesh Vazirani. "Quantum complexity theory." Proceedings of the 25th Annual ACM Symposium on Theory of Computing. 1993.
[2] Bernstein, Ethan, and Umesh Vazirani. "Quantum complexity theory." SIAM Journal on Computing 26.5 (1997): 1411-1473.
最后更新时间:2021年12月20日