格罗弗搜索算法

背景介绍

假设一个推销员想推销一种新出的量子计算机,他在世界各大城市间来回穿梭(纽约 上海 )并且最终回到位于起点的公司总部,他需要提前规划好一条可以经过所有大城市的最短路线以节省时间。这就是著名的旅行推销员问题。本质上,它是一个非结构化的搜索问题。

问题描述

非结构化的搜索问题可以形式化定义如下:

给定一个具有 个元素的集合 , 给定一个布尔函数 。目标是找到一个元素 使得 ,称其为非结构化搜索问题 的解。假定 的解共有 个。

其中"非结构化"是指我们没有关于这个数据集的先验知识,例如数据按照大小、首字母排序等。

经典搜索算法

对于如上定义的非结构化搜索问题,经典搜索算法只能枚举集合 中的元素 ,依次判断 是否等于 。当只有一个解(即 )时,最坏情况下这个算法需要检查完 中所有元素,即经典搜索算法在最坏情况下的复杂度为

格罗弗搜索算法

有趣的是,1996 年计算机科学家格罗弗(Lov Grover)发明了一种奇特的量子算法,它只需使用 次搜索步骤,就能找到非结构化搜索问题的一个解。格罗弗算法相比于经典算法是一个多项式加速算法,而不是像多伊奇-约萨算法那样有指数加速。尽管如此,假设非结构搜索的集合有 100 万个元素(),那么用格罗弗搜索算法只需搜索几千次左右就能找到一个解。这也是很大的进步了!另一方面,本内特等人证明对于非结构化的搜索问题,任何量子算法都至少需要做 次量子搜索,因此格罗弗算法对非结构化的搜索问题是渐进意义下的最优量子算法。

量子黑盒

在描述格罗弗算法之前,我们需要给出格罗弗算法中使用的量子黑盒。需要注意此处的量子黑盒与本章前几节的量子黑盒并不相同。

我们不妨假设集合 的元素个数是 的幂次。那么 中的元素可由 比特的长比特串编码, 比特输入的布尔函数,即

代表 的解。例如在旅行推销员问题中,满足 对应着最短路线。量子黑盒是一个酉矩阵 ,它能够 ‘‘识别’’ 问题 的解。其数学定义为

由定义可知,如果 的解,那么 会在对应的计算基态 引入相对相位 。格罗弗算法量子黑盒的具体实现与所计算的函数 相关,一般需要借助辅助量子比特。为了描述方便,在上式中我们省略了辅助量子比特。

习题 1. 证明公式 定义的量子门 可以等价表示为

由该等价表示,证明 是一个酉矩阵。

算法流程与算法分析

格罗弗算法的量子电路表示如下:

格罗弗算法过程

图 1:格罗弗算法的量子电路。

格罗弗算法的目标是在尽可能少的调用量子黑盒的前提下,找到非结构化搜索的一个解。如图 1 所示,在均匀叠加后,格罗弗算法会重复调用一个被称为“格罗弗迭代”的子程序,我们将这个子程序记为 的量子电路实现如下图 2 所示。

G 算子的量子电路

图 2: 算子的量子电路。

以下我们对“格罗弗迭代” 从左至右逐步分析其中系统状态的演化过程。

  1. 执行量子黑盒

  2. 执行 门,即

  3. 执行条件相位翻转,将所有非 的计算基乘上 的相位,即

其中克罗内克 函数 的定义为:如果 ,则 ;如果 ,则

  1. 执行 门,即

定义如下量子态:

经分析可发现第 2,3,4 步整体上实现了如下算子(我们称之为“弥散算子”):

因此格罗弗迭代实际上是实现算子 .

习题 2. 证明公式

几何解释

理解格罗弗算法的关键是理解格罗弗迭代算子 的功能。此处我们通过几何表示来帮助理解。

实际上,我们可以将格罗弗迭代算子视为一个 2 维向量空间上的旋转,这个 2 维向量空间由所有解的均匀叠加态和它的正交量子态张成。更具体地说,定义以下两个量子态:

使用简单的线性代数我们可以证明

为便于后续讨论,这里我们将 记为

其中 满足

基于以上展开式,迭代算子 可以被简单优美地理解。

首先我们可以在二维平面上表示 , , 。注意到 正交(内积为 ),可以对应于 轴和 轴。由公式 ,可取 轴)夹角为 ,如图 3 所示(图片来自)。

格罗弗迭代对应于旋转变换

图 3:格罗弗迭代对应于旋转变换

然后注意到量子黑盒 操作可以表示为由 张成的平面上关于向量 的对称变换,即

类似的,() 操作可以表示为由 张成的平面上关于向量 的对称变换。故格罗弗迭代算子 相当于将量子态先对 轴)做镜像翻转,再对 做镜像翻转。有趣的事情出现了:这两个变换的复合其实是一个旋转操作(该旋转操作如图 3 所示)!可以看到,旋转的角度为 夹角的 倍,即为

通过计算可以发现,格罗弗算法中,经过一次格罗弗迭代,得到量子态变为

同理可知,将算子 连续作用 次到量子态 后,量子态变为

接近 时,我们即可通过测量得到一个可行解。

习题 3. 证明公式

习题 4. 证明公式

算法效果

为了找到一个解,我们需要使用多少次格罗弗迭代呢?以下我们假设 (对应 )然后给出需要迭代次数的精确解。 的情况分析方法类似,在此不再赘述。注意到我们整个算法的初始态是 ,算法的目标是经过演化之后系统状态逼近 。理论上旋转 弧度系统状态即为 。然而由于每次旋转转动的角度为 ,所以系统状态无法精确演化到 。记 为离实数 最近的整数。如果这样的整数有两个时则取较小的一个,例如 。将旋转次数设置为

可保证旋转之后得到的量子态 的夹角小于 。对 在计算基下进行测量并记录输出比特串,该比特串是无结构搜索问题的解的概率大于

公式 给出了需要旋转的次数 的精确解,但是 函数使得 之间的关系没有那么的显而易见,从而无法直接估算复杂度。通过对公式 右侧的表达式进行放缩,我们可以得到格罗弗迭代次数 的一个比较容易计算的上界:

其中第一个不等式成立是因为 函数在区间 单调下降, 第二个不等式成立是因为当 时,。 由公式 可知,最多执行 次格罗弗迭代(对应调用量子黑盒的次数)即可以超过 的概率获得一个无结构搜索问题的解。

算法总结

  • 需要的硬件设备:

    • 个量子比特。
    • Hadamard 门。
    • 量子黑盒
    • 计算基测量。
  • 输入: 量子黑盒 ,功能是 ,其中函数 如公式 定义。

  • 输出: 比特串 ,满足

  • 运行代价: 复杂度 ,成功概率 ,其中

  • 运行过程:

    1. 个量子比特初始化为

    2. 均匀叠加,对 个量子比特分别作用 门,作用后的系统状态为:

    1. 个量子比特作用 次格罗弗迭代 。作用后的系统状态极为接近:
    1. 个量子比特分别执行计算基测量,记录测量结果比特串

简例与量易伏平台演示

为了加深对格罗弗算法的理解,在这一小节,我们介绍如何在量易伏平台上模拟格罗弗算法。我们将首先考虑一个从 4 个元素集合搜索唯一 1 个目标元素的问题,并使用 QComposer 给出对应电路。值得注意的是,在这个例子中仅使用一次格罗弗迭代即可稳定得到目标元素。然后我们考虑一个相对复杂的例子,从 8 个元素集合搜索唯一 1 个目标元素,并给出基于混合语言编程的程序。

对 4 个元素集合的搜索

注: 需要注意,量易伏平台上模拟返回的字符串采用大端在前的标记方法,从左往右第一位表示的是最高位的量子比特(),故若测量结果为 10,需要翻转得到 01 即为目标元素。

对于 的情况,其算法在 QComposer 上的电路图如图 4:

量易伏 QComposer 格罗弗算法电路

图 4:量易伏上 QComposer 对格罗弗算法 00 情况的电路

OPENQASM 2.0;
include "qelib1.inc";
//初始化系统量子态
qreg q[2];
creg c[2];
// 均匀叠加
//
h q[0];
h q[1];
//调用量子黑盒 U_f
//
s q[0];
s q[1];
cz q[0],q[1];
s q[0];
s q[1];
//执行 n 个 H 门
//
h q[0];
h q[1];
//执行条件相位翻转
//
x q[0];
x q[1];
cz q[0], q[1];
x q[0];
x q[1];
//执行 n 个 H 门
//
h q[0];
h q[1];
//主寄存器的所有量子比特分别执行计算基测量
measure q[0] -> c[0];
measure q[1] -> c[1];
复制

理想模拟器输出结果为:

{
    "00": 1024
}
复制

对于 的情况,其算法在 QComposer 上的电路图如图 5:

量易伏 QComposer 格罗弗算法电路

图 5:量易伏上 QComposer 对格罗弗算法 01 情况的电路

OPENQASM 2.0;
include "qelib1.inc";
//初始化系统量子态
qreg q[2];
creg c[2];
// 均匀叠加
//
h q[0];
h q[1];
//调用量子黑盒 U_f
//
s q[1];
cz q[0],q[1];
s q[1];
//执行 n 个 H 门
//
h q[0];
h q[1];
//执行条件相位翻转
//
x q[0];
x q[1];
cz q[0],q[1];
x q[0];
x q[1];
//执行 n 个 H 门
//
h q[0];
h q[1];
//主寄存器的所有量子比特分别执行计算基测量
measure q[0] -> c[0];
measure q[1] -> c[1];
复制

理想模拟器输出结果如下,翻转得到 01 即为目标元素:

{
    "10": 1024
}
复制

对于 的情况,其算法在 QComposer 上的电路图如图 6:

量易伏 QComposer 格罗弗算法电路

图 6:量易伏上 QComposer 对格罗弗算法 10 情况的电路

OPENQASM 2.0;
include "qelib1.inc";
//初始化系统量子态
qreg q[2];
creg c[2];
// 均匀叠加
//
h q[0];
h q[1];
//调用量子黑盒 U_f
//
s q[0];
cz q[0],q[1];
s q[0];
//执行 n 个 H 门
//
h q[0];
h q[1];
//执行条件相位翻转
//
x q[1];
x q[0];
cz q[0],q[1];
x q[0];
x q[1];
//执行 n 个 H 门
//
h q[0];
h q[1];
//主寄存器的所有量子比特分别执行计算基测量
measure q[0] -> c[0];
measure q[1] -> c[1];
复制

理想模拟器输出结果如下,翻转得到 10 即为目标元素:

{
    "01": 1024
}
复制

对于 的情况,其算法在 QComposer 上的电路图如图 7:

量易伏 QComposer 格罗弗算法电路

图 7:量易伏上 QComposer 对格罗弗算法 11 情况的电路

OPENQASM 2.0;
include "qelib1.inc";
//初始化系统量子态
qreg q[2];
creg c[2];
// 均匀叠加
//
h q[0];
h q[1];
//调用量子黑盒 U_f
//
cz q[0],q[1];
//执行 n 个 H 门
//
h q[0];
h q[1];
//执行条件相位翻转
//
z q[0];
z q[1];
cz q[0],q[1];
//执行 n 个 H 门
//
h q[0];
h q[1];
//主寄存器的所有量子比特分别执行计算基测量
measure q[0] -> c[0];
measure q[1] -> c[1];
复制

理想模拟器输出结果为:

{
    "11": 1024
}
复制

对 8 个元素集合的搜索

考虑具有 个元素的集合 ,定义在 上的非结构化搜索问题 满足 。以下我们具体分析这个例子的每一个步骤,并给出对应代码,推荐读者在本地使用 QCompute SDK 进行模拟实验。

预处理和初始化: 我们需要使用 个量子比特来编码搜索空间 的元素,分别对应计算基 。我们将这 个量子比特初始化为

均匀叠加: 接下来,我们对每一个量子比特作用 门来获得叠加态

其在计算基下的展开为

作用量子黑盒 作用量子黑盒 ,我们得到量子态

作用弥散算子: 在我们的例子中,格罗弗迭代算子 中的第二步可以数学上表示为

为实现“弥散算子” ,我们可以先实现条件相位翻转操作 ,该操作会在所有非 计算基上乘以 。然后在条件相位翻转操作前后每个量子比特各作用 门即可。当我们把量子黑盒和弥散算子结合到一起,得到格罗弗迭代

代码实现: 以下我们在量易伏平台上逐步实现“系统初始化,均匀叠加,作用量子黑盒 ,作用弥散算子 ”等操作,来演示一轮格罗弗迭代过程。

from QCompute import *
import numpy as np

# 不直接给出输出,后续通过print给出需要信息
from QCompute import Define
Define.Settings.drawCircuitControl = []
Define.Settings.outputInfo = False

qubit_num = 3
shots = 1000

def main(iteration=1):
    """
    main
    """
    # 创建环境
    env = QEnv()
    # 选择随机数
    seed = int(2147483647*np.random.random())
    # 选择 Backend 为本地模拟器
    # 注:量易伏也支持云端模拟器和真机后端,访问 https://quantum-hub.baidu.com/ 获取更多信息。
    env.backend(BackendName.LocalBaiduSim2, '-s ' + str(seed))

    # 初始化三量子比特电路
    q = [env.Q[i] for i in range(qubit_num)]

    # 叠加态
    for i in range(qubit_num):
        H(q[i])

    for i in range(iteration):
        # 针对于 |101> 的黑盒
        X(q[1])
        H(q[2])
        CCX(q[0], q[1], q[2])
        X(q[1])
        H(q[2])

        # 弥散算子
        for i in range(qubit_num):
            H(q[i])
            X(q[i])

        H(q[2])
        CCX(q[0], q[1], q[2])
        H(q[2])

        for i in range(qubit_num):
            X(q[i])
            H(q[i])

    # 测量结果
    MeasureZ(q, range(qubit_num))
    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])
    return taskResult['counts']


if __name__ == '__main__':
    main(iteration=1)
复制

测量结果是:

Shots 1000
Counts {'101': 793, '111': 30, '011': 29, '110': 27, '001': 29, '100': 36, '010': 29, '000': 27}
Seed 402200469
解码得到的隐藏比特串: 101
复制

注: 返回的结果均为二进制。

从测量结果可以看出,我们运行一次格罗弗迭代后测到解 的概率为

再执行一次格罗弗迭代,即将上述代码片段中的“作用量子黑盒 ”和“作用弥散算子 ”重复一次,得到的测量结果如下。

Shots 1000
Counts {'101': 945, '011': 11, '100': 9, '001': 3, '000': 10, '111': 9, '010': 5, '110': 8}
Seed 710563953
解码得到的经典信息: 101
复制

从测量结果可以看出,测到解 的概率会增大为

参考资料

[1] Grover, Lov K. "A fast quantum mechanical algorithm for database search." Proceedings of the 28th Annual ACM Symposium on Theory of Computing. 1996.

[2] Bennett, Charles H., et al. "Strengths and weaknesses of quantum computing." SIAM Journal on Computing 26.5 (1997): 1510-1523.

[3] Wikipedia contributors. "Grover's algorithm." Wikipedia, The Free Encyclopedia. Wikipedia, The Free Encyclopedia, Web. 26 Nov. 2020.

最后更新时间:2021年12月20日

Navigated to 量易简