秀尔算法

背景介绍

整数分解(Integer Factorization)指将一个正整数 分解为若干更小(大于 的)正整数的乘积,比如 。若这些更小的整数均为素数,这种分解又称为素因数分解(Prime Factorization),比如 。由

定理 1(算术基本定理,Fundamental Theorem of Arithmetic). 任何一个大于 的正整数 可以唯一分解成有限个素数的乘积 ,这里 均为素数,指数 是正整数。

正整数的素因数分解唯一,继而正整数的素因数分解问题方才有意义。整数分解问题历史悠久,上述算数基本定理可考的证明最早可以追溯到古希腊数学家欧几里得的著作《几何原本》。

现代密码学中最重要的公开密钥密码体系(Public Key Cryptosystem)之一 RSA 便是基于素因数分解问题提出的,该公钥体系的安全性正是基于整数分解问题的困难性。目前已知的渐近运行时间最好的经典算法是普通数域筛选法(General Number Field Sieve),其运行时间是

秀尔算法(Shor's Algorithm),是秀尔在 1994 年提出的量子算法,可以在多项式时间

给出 的一个整数分解。进而表明整数分解问题属于复杂度类 BQP,是量子计算机可以高效求解的一个问题。由于 RSA 密码体系的安全性依赖于整数分解问题的困难性,秀尔算法的提出使得这些密码体系在量子计算机面前不再安全。为了让更多的读者更好地了解量子算法特别是秀尔算法的魅力,我们将先介绍整体的算法流程与框架,再给出基于量易伏平台的具体用例,将更详细的技术细节后置于附录,以供想要深入研究的同学进一步学习。

章节目录

  • 我们在第 2 段介绍秀尔算法的经典部分和一些需要引入的简单知识,并在算法 11 中给出完整的秀尔算法流程,大量的证明和细节留到第 6 段供感兴趣的读者深入阅读;

  • 我们在第 3 段介绍秀尔算法的量子部分——量子求阶算法,部分证明也留到第 6 段再补充;

  • 我们在第 4 段中使用量子编程平台量易伏给出两个例子——分解 ,供读者自己体验一下量子编程的乐趣;

  • 我们在第 6 段中补充定理的证明及算法的一些细节,不同部分需要的知识储备不尽相同,这里将其分为 5 个部分,供读者自行抉择:

    • 6.1 子段补充量子求阶算法中 门的本征值本征向量相关内容,需要一点点线性代数的知识背景;
    • 6.2 子段补充量子求阶算法中连分数展开这一步骤的正确性的证明,不需要知识背景但证明略繁琐需要读者的耐心;
    • 6.3 子段补充量子求阶算法成功概率相关内容,需要一点点初等数论的知识背景;
    • 6.4 子段补充秀尔算法搜索 具有“良性”的概率,更紧的下界需要一些抽象代数的知识背景;
    • 6.5 子段补充 门的分解,这是物理实现必要的步骤,这里给出了参考文献供读者延伸阅读。

算法总览

阅读本节后续内容需要一些基本的数学背景知识如下:

  1. 记整数集合为 ,正整数集合为
  2. 给定整数 ,若 也是整数,称 整除(Divide) 因数(Factor),记为 ;否则称 不整除 ,记为 的平凡因数指
  3. 素数(Prime) 指没有非平凡因数的正整数,正 合数(Composite) 指既不是素数也不是 的正整数;
  4. 偶数必然有素因数 ,负数的因数与其相反数无异;
  5. 两个整数的 最大公因数(Greatest Common Divisor) 定义为同时整除这两个整数的最大的正整数,记为 ,可以使用 欧几里得辗转相除法 高效计算;称最大公因数为 的两个整数互素;
  6. 给定整数 ,若 ,称 同余,记为
  7. 给定互素的整数 ,若 是使得 的最小正整数,称 ,记为

我们重申整数分解问题和素因数分解问题,并引入素数判定问题如下:

问题 2(整数分解). 给定一个正整数 ,若 是合数,求 的一个不平凡因数。

问题 3(素因数分解). 给定一个正整数 ,求 的素因数分解。

问题 4(素数判定). 给定一个正整数 ,判断 是否是素数。

关于素数判定问题,目前已知的最好的经典算法是确定性的多项式时间算法—— AKS 素数测试算法

因为素数判定问题可以有效解决,所以这里关于整数分解和素因数分解的问题描述,便可改为更一般地表达,去掉输入为合数这一个条件。并且我们可以声明:素因数分解问题可以多项式归约到整数分解问题,也就是说如果存在求解整数分解问题的多项式时间算法,那么存在求解素因数分解问题的多项式时间算法:比如我们要求 的素因数分解,通过整数分解算法找到了一个非平凡因子 ,那么 就是 的一个整数分解。我们分别对 递归地做整数分解算法,直到每个因数都是素数(通过素数判定算法检验),整个过程就是一个素因数分解算法。这个素因数分解算法的复杂度为: 素数判定的复杂度 整数分解的复杂度 迭代次数,这里迭代次数 的各素因数重数和的两倍 ,这里 关于素因子 重数指使得 的最大整数 。故而上述归约是多项式归约。

故我们只需要考虑整数分解问题。

给定输入正整数 后我们可以调用 AKS 素数测试算法,判断 是否是素数,如果它是素数,返回 表示 没有非平凡因数。如果它不是素数,那么它一定是合数。有两类合数很容易地判断出来,同时也能找到其非平凡因数:偶数和整数幂。偶数的判定是简单的,我们用计算 ,若它是整数, 便有非平凡因数 ;否则 就不是偶数,即奇数。

整数幂是指形如 的一类合数,其中 是大于 的整数,例如 等等。我们可以用以下算法判断正合数 是不是整数幂:

算法 5(整数幂判定).

输入: 正合数

输出: [因数 , 对应的幂次 ],若 是整数幂;否则输出 False

for m in range(2, int(math.log(N,2)) + 1):
    a = int(N ** (1 / m))
    if N == a ** m
        return [a,m]
return False 
复制

这里 int(N ** (1 / m)) 可以用数值方法计算,确保多项式时间内可以完成整数幂的判定。特别地,当已知 是奇数时,int(math.log(N,2)) 可以改为 int(math.log(N,3))。如果 是整数幂,算法 5 返回的因数 便是 的一个不平凡因数。

经过素数判定、偶数判定和整数幂判定之后,我们便可假设正整数 是奇合数且不是整数幂,也就是说 是至少包含两个不同的奇素因数的奇合数(否则 是奇数且只含有一种素因数可以推出 是某个素数的幂,与 不是整数幂矛盾)。至此才进入狭义的整数分解问题:

问题 6(狭义的整数分解). 给定一个不是整数幂的正奇合数 ,求 的一个不平凡因数。

对于这一问题有着非常多的经典求解办法,秀尔基于其中一种思路给出了量子版本的算法:基于量子求阶算法的整数分解算法。

我们再来回顾一下阶的概念:

定义 7(模 的阶). 给定整数 ,若存在 是使得 的最小正整数,称 ,记为 ;否则称 的阶不存在。在不引发歧义的时候简称为 的阶。

如果我们知道整数 和其模 的阶 ,便有 。若追加假设 是偶数,那么由平方差公式有 ,由阶定义中的最小性知 。若再追加假设 ,有 。故而 均为 的不平凡因数。更详细准确的证明可以参照下述定理 10。

定义 8(“良性”). 给定互素的整数 ,设 的阶,若 是偶数且 ,我们称 是“良性”的;否则称为“非良性”的。

这里的“良性”是为了简化表述给出的称谓,无通用正式的术语。我们依旧在不引发歧义时略去“模 ”以简化表述。

我们已经知道“良性”的 及其阶 可以诱导出 的非平凡因子,但如何找到“良性”的 和如何计算 的阶都是尚未解决的问题。但是如果我们有对任意的 可以计算阶 的算法,便可随机抽选整数 ,然后计算其阶 ,再判断 是不是“良性”的,若其是“良性”的,便可返回 的不平凡因数;否则重新抽选 ,并重复上述流程。特别地,如果我们抽选到的 不互素,虽然 的阶不存在,但 已经是 的一个非平凡因数了,此时也没必要进入求阶步骤了。

例 9. 考虑 ,可以验证 ,进而 是“良性”的, 均为 的非平凡因数。特别地,恰有

在例 9 中我们指出若 是“良性”的,其便能诱导 的一个不平凡的分解,这里更准确地表述成定理如下:

定理 10 给定正整数 ,设 。若 是奇数且 是“良性”的, 则有 的一个不平凡的分解:

证明.,易验证 。设 。考虑到 为奇数,进而有

故而可设 ,这里 表示一组数的最大公因数。由

此时 。由 ;由 。故而 的一个不平凡的分解, 都是 的非平凡因数。

秀尔算法是对整数分解问题的一个经典求解算法的量子改进:

  1. 两者均将整数分解问题转化为求阶问题(Order-Finding);
  2. 秀尔在求阶问题上获得了突破,提出了量子求阶算法(Quantum Order-Finding Algorithm);
  3. 将量子求阶算法替换经典算法中求阶的步骤,便可得到量子版本的整数分解算法,即秀尔算法。

关于求阶这一步骤我们将在下一段中展开,这也是秀尔算法中唯一量子的部分。作为本段的最后,我们总结一下秀尔算法的流程如下:

算法 11(秀尔算法).

输入: 正整数

输出: 的一个非平凡的正因数,或 表示 没有非平凡的正因数。

  1. 返回
  2. 使用 AKS 素数测试算法 判定 是否为素数,返回
  3. 是偶数,返回
  4. 用数值计算的方法依次判断 是否为整数, 为整数则 返回 这个整数;
  5. 随机选取整数 使得
  6. 使用 欧几里得辗转相除法 计算最大公因数
  7. 返回
  8. 否则,使用(量子)求阶算法计算
  9. 为奇数 或者 转移 到步骤 5;
  10. 否则返回 (或 )。

关于秀尔算法复杂度的分析需要 6.3 子段分析算法 11 步骤 8 的成功概率,以及 6.4 子段分析算法 11 步骤 9 发生循环的概率作为支撑。

量子求阶算法

因为算法旨在求解 的阶 ,我们称其为量子求阶算法。考虑到

为周期函数,其(最小正)周期恰是 ,量子求阶算法可作为 量子周期求解算法(Period-Finding)的一个特例,这里 除以 的余数。从本质上讲,量子相位估计算法也是量子周期求解算法的一个特例,但是从周期求解算法的方式来理解量子求阶算法和量子相位估计算法相对要困难一些,感兴趣的同学可以自行尝试了解

秀尔的量子求阶算法基于量子相位估计算法,将阶这一信息编码到某个量子门(或量子子电路)的本征相位上去,借由相位估计算法估计出该相位,进而可以恢复出阶的值。

将阶编码到本征相位

给定 互素,现要求解 的阶 。使用 个量子比特来编码,设有量子门

习题 1. 验证 为酉矩阵。

我们可以计算(证明参见附录 6.1 子段。)

引理 12. 有本征值形如

且有对应的本征态

为了让读者们更清晰的看到 及其性质,我们给出如下例子:

例 13.,我们有

部分本征值及本征态如下:

当我们对算符 及其本征态 执行量子相位估计算法时便可得到相位参数 的一个估计,借助连分数展开算法便有概率恢复出其分母

考虑到在 未知的前提下,我们无法制备量子态 ,但我们有如下恒等式(证明参见附录 6.1 子段):

引理 14.

也就是说,计算基中的 可以看做本征态 的一个同概率幅叠加。

当我们对算符 及量子态 执行量子相位估计算法时,可以得到相位参数 的估计值的一个叠加态,记为混态 (相位估计算法输出的是两个寄存器,当我们只关心辅助寄存器时,它的状态就是一个混态)。关于混态的系综表示可以参考 1.4 节,这里可以简单理解为对该叠加态的辅助寄存器进行测量时如同先以概率 抽选到量子态 ,再对 进行测量。这里相位估计算法的精度取 ,如果在辅助寄存器使用 个量子比特,相位估计算法的成功概率不少于 (符号和理论的正确性参照 4.3 节)。

连分数展开解码相位为阶

当我们对辅助寄存器 用计算基进行测量后,设测量结果为 ,我们有至少 的把握认为存在 使得 的一个 -估计。对 做连分数展开,并依次计算其截断 的分母 ,找到满足条件 的最大分母

这里举例演示一下连分数展开算法,更多细节参考篇末的附录 6.2 子段:

例 15. 考虑 时,对 执行连分数展开:

可以看出连分数展开的过程就是欧几里得辗转相除法,每一次迭代将分数表示为带分数的形式,然后将带分数的分数部分的分子化为 ,将新的分母作为下一次迭代的输入,循环至带分数为整数止。 分别称式 中的 为连分数 的第 ,第 ,第 和第 截断。考虑其中满足条件分母 的最大分母为

注 16. 连分数展开截断总能恢复出 的分母,但 的分母不一定是 :当 时, 的分母是 的概率即 的概率 ,这里 是连分数展开各截断的分母中满足 条件的最大值, 是欧拉函数(不超过 且与 互素的正整数数量,参见附录 6.1 子段定义 28)。

这里可以恢复出 的概率 没有良好的下界,也就是说存在极端的情况 趋近于 ,为了提高恢复出 的概率,目前最好的办法是执行两次求阶算法并计算分母的最小公倍数:

定理 17. 通过执行两次量子求阶算法,可以得到两个分母 ,计算 的最小公倍数 ,则 的概率 ,这里 是相位估计算法的失败概率。

本定理的证明参阅附录 6.3 子段。

总结

本段的最后,我们再总结一下量子求阶算法,并将在下段给出两个具体的例子。

算法 18(量子求阶算法).

输入: 整数 互素,相位估计算法的失败概率

输出:

  1. 执行两次:使用 个量子比特作为辅助寄存器对量子门 和量子态 执行量子相位估计算法并对辅助寄存器进行测量。分别得到
  2. 分别对 做连分数展开,分别计算它们各个截断的分母中满足 条件的最大整数
  3. 计算 返回 否则 转移 到步骤 2 重新计算。

算法 18 步骤 4 的成功率不小于 。特别地,取 时,,算法 18 步骤 4 的成功概率不小于 ,此时执行至多 次步骤 4 可以使计算出 的概率不少于 。关于量子门 的制备可以参阅附录 6.5 子段;更多的细节以及证明也请参考篇末的附录,其需要更多的数学背景知识。

简例与量易伏平台演示

在本小节中,我们使用量易伏平台来演示秀尔算法。 我们首先使用 QComposer 分解一个简单的例子——,并给出对应电路图。然后考虑一个更复杂的例子——,并给出基于混合语言编程的代码。

分解

依次做素数判定、偶数判定和整数幂判定,知 满足狭义的整数分解的输入条件。 随机选取 得到 (我们这里先随机拿到了 ,为了更好地演示算法重新随机得到了这个值)。 验证知 ,进入量子求阶算法求 。( 均可经典地得到 的分解。)

我们需要 个量子比特来编码算符 (本子段中也简记为 ):

我们可以用如下电路实现 ,第 比特控制作用在第 比特上的一个 门的一种电路分解如下图 1 所示:

在量易伏 QComposer 上实现 \operatorname{controlled^0-}U_{2,15}^{1,2,3,4}

图 1:在量易伏 QComposer 上实现

对应 OPENQASM 代码如下:

OPENQASM 2.0;
include "qelib1.inc";
qreg q[6];
creg c[6];
ccx q[0], q[4], q[1];
ccx q[0], q[4], q[2];
ccx q[0], q[4], q[3];
ccx q[0], q[3], q[4];
ccx q[0], q[4], q[3];
ccx q[0], q[2], q[3];
ccx q[0], q[3], q[2];
ccx q[0], q[1], q[2];
ccx q[0], q[2], q[1];
复制

相位估计算法中还需要用到其它 门:

这里 为第 比特为控制比特、以第 比特为受控比特的 门。 使用 个量子比特估计量子态 的相位,QComposer 中的电路如下图 2 所示(这里略去了可以忽略的 门):

在量易伏 QComposer 上求解 \textrm{Ord}(2,15)"

图 2:在量易伏 QComposer 上求解

其对应的 OPENQASM 代码如下:

OPENQASM 2.0;
include "qelib1.inc";
qreg q[13]; // q[0],...,q[8] 为辅助寄存器,q[9],...,q[12] 为工作寄存器
creg c[13];
x q[12]; // 制备初始状态|0>|1>,下面开始执行相位估计算法
h q[0];
h q[1];
h q[2];
h q[3];
h q[4];
h q[5];
h q[6];
h q[7];
h q[8]; // 相位估计的辅助步,对辅助寄存器取平均叠加完毕
ccx q[8], q[12], q[9];
ccx q[8], q[12], q[10];
ccx q[8], q[12], q[11];
ccx q[8], q[11], q[12];
ccx q[8], q[12], q[11];
ccx q[8], q[10], q[11];
ccx q[8], q[11], q[10];
ccx q[8], q[9], q[10];
ccx q[8], q[10], q[9]; // 上一注释至此实现了 C(U) 门,q[8] 控制工作寄存器
cswap q[7], q[9], q[11];
cswap q[7], q[10], q[12]; //上一注释至此实现了 C(U^2) 门,q[7] 控制工作寄存器
// 略去为 I 的其他 C(U^(2^j)) 门,准备开始对辅助寄存器做逆傅里叶变换
swap q[0], q[8];
swap q[1], q[7];
swap q[2], q[6];
swap q[3], q[5];
h q[8];
cu(0, 0, -pi/2) q[8], q[7];
h q[7];
cu(0, 0, -pi/4) q[8], q[6];
cu(0, 0, -pi/2) q[7], q[6];
h q[6];
cu(0, 0, -pi/8) q[8], q[5];
cu(0, 0, -pi/4) q[7], q[5];
cu(0, 0, -pi/2) q[6], q[5];
h q[5];
cu(0, 0, -pi/16) q[8], q[4];
cu(0, 0, -pi/8) q[7], q[4];
cu(0, 0, -pi/4) q[6], q[4];
cu(0, 0, -pi/2) q[5], q[4];
h q[4];
cu(0, 0, -pi/32) q[8], q[3];
cu(0, 0, -pi/16) q[7], q[3];
cu(0, 0, -pi/8) q[6], q[3];
cu(0, 0, -pi/4) q[5], q[3];
cu(0, 0, -pi/2) q[4], q[3];
h q[3];
cu(0, 0, -pi/64) q[8], q[2];
cu(0, 0, -pi/32) q[7], q[2];
cu(0, 0, -pi/16) q[6], q[2];
cu(0, 0, -pi/8) q[5], q[2];
cu(0, 0, -pi/4) q[4], q[2];
cu(0, 0, -pi/2) q[3], q[2];
h q[2];
cu(0, 0, -pi/128) q[8], q[1];
cu(0, 0, -pi/64) q[7], q[1];
cu(0, 0, -pi/32) q[6], q[1];
cu(0, 0, -pi/16) q[5], q[1];
cu(0, 0, -pi/8) q[4], q[1];
cu(0, 0, -pi/4) q[3], q[1];
cu(0, 0, -pi/2) q[2], q[1];
h q[1];
cu(0, 0, -pi/256) q[8], q[0];
cu(0, 0, -pi/128) q[7], q[0];
cu(0, 0, -pi/64) q[6], q[0];
cu(0, 0, -pi/32) q[5], q[0];
cu(0, 0, -pi/16) q[4], q[0];
cu(0, 0, -pi/8) q[3], q[0];
cu(0, 0, -pi/4) q[2], q[0];
cu(0, 0, -pi/2) q[1], q[0];
h q[0]; // 逆傅里叶变换结束,相位估计算法进入测量阶段
measure q[8] -> c[8];
measure q[7] -> c[7];
measure q[6] -> c[6];
measure q[5] -> c[5];
measure q[4] -> c[4];
measure q[3] -> c[3];
measure q[2] -> c[2];
measure q[1] -> c[1];
measure q[0] -> c[0];
复制

某次运行结果如下:

{
    "000000011": 237,
    "000000010": 257,
    "000000000": 269,
    "000000001": 261
}
复制

测量结果大约为等频率的 ,分别对应真分数 。这里仅 可以做连分数展开:

其第 截断为

故而每次相位估计算法有约 的概率可以得到正确结果 ,两次实验有约 的概率可以得到正确结果。 由 诱导了 的一个不平凡的分解:

至此完成了秀尔算法分解 的演示。

后话:代码演示中“略去为 的其他 门”有循环论证之嫌,正确的演示应当将这些门逐个分解,而不是利用理论证明的方法计算得出 ,在下一子段中,我们在演示 的分解时避开了这一问题。

分解

在本子段中,我们基于混合语言编程给出秀尔算法的演示代码,推荐读者在本地使用 QCompute SDK 进行模拟实验。

选取 ,验证知 ,进入量子求阶算法求 。我们需要 个量子比特来编码算符 (本子段中也简记为 ),使用 个辅助量子比特来估计相位。考虑到 时,

这里 表示 除以 的余数 。故而我们只需要分解门 (细节详见下述代码)。量易伏中的代码如下:

import numpy as np
from QCompute import *


# 初始化量子环境,选择使用本地自研模拟器
# 注:量易伏也支持云端模拟器和真机后端,访问 https://quantum-hub.baidu.com/ 获取更多信息。
env = QEnv()
env.backend(BackendName.LocalBaiduSim2)

pi = np.pi
L = 6  # 编码 U 门需要的量子比特数、工作寄存器的量子比特数
N = 3 * L + 1  # 算法需要使用的总量子比特数
t = 2 * L + 1  # 相位估计算法所需的辅助比特数、辅助寄存器的量子比特数

q = [env.Q[i] for i in range(0, N)]  # 量子比特的列表

X(q[N - 1])  # 在工作寄存器制备初始状态 |1>,下面开始执行相位估计算法

# 相位估计的第一步,对辅助寄存器取平均叠加完毕,下面开始将相位估计算法的转存步骤
for i in range(0, t):
    H(q[i])

# 实现门 C(U),辅助寄存器的最后一个量子比特控制工作寄存器
CCX(q[2 * L], q[t + 5], q[t + 0])
CCX(q[2 * L], q[t + 5], q[t + 1])
CCX(q[2 * L], q[t + 5], q[t + 2])
CCX(q[2 * L], q[t + 5], q[t + 4])
CCX(q[2 * L], q[t + 5], q[t + 3])
CCX(q[2 * L], q[t + 4], q[t + 5])
CCX(q[2 * L], q[t + 5], q[t + 4])
CCX(q[2 * L], q[t + 3], q[t + 4])
CCX(q[2 * L], q[t + 4], q[t + 3])
CCX(q[2 * L], q[t + 2], q[t + 3])
CCX(q[2 * L], q[t + 3], q[t + 2])
CCX(q[2 * L], q[t + 1], q[t + 2])
CCX(q[2 * L], q[t + 2], q[t + 1])
CCX(q[2 * L], q[t + 0], q[t + 1])
CCX(q[2 * L], q[t + 1], q[t + 0])

# 依次作用其他 C(U^(2^j)) 门
s = 2 * L - 1
while s >= 0:
    if s % 2 == 1:
        CCX(q[s], q[t + 5], q[t + 1])
        CCX(q[s], q[t + 5], q[t + 3])
        CCX(q[s], q[t + 4], q[t + 0])
        CCX(q[s], q[t + 4], q[t + 2])
        CCX(q[s], q[t + 3], q[t + 5])
        CCX(q[s], q[t + 5], q[t + 3])
        CCX(q[s], q[t + 2], q[t + 4])
        CCX(q[s], q[t + 4], q[t + 2])
        CCX(q[s], q[t + 1], q[t + 3])
        CCX(q[s], q[t + 3], q[t + 1])
        CCX(q[s], q[t + 0], q[t + 2])
        CCX(q[s], q[t + 2], q[t + 0])  # 本条件下的门组合后即门 C(U^2)
    else:
        CCX(q[s], q[t + 5], q[t + 1])
        CCX(q[s], q[t + 5], q[t + 3])
        CCX(q[s], q[t + 4], q[t + 0])
        CCX(q[s], q[t + 4], q[t + 2])
        CCX(q[s], q[t + 3], q[t + 5])
        CCX(q[s], q[t + 3], q[t + 1])
        CCX(q[s], q[t + 5], q[t + 3])
        CCX(q[s], q[t + 2], q[t + 4])
        CCX(q[s], q[t + 2], q[t + 0])
        CCX(q[s], q[t + 4], q[t + 2])
        CCX(q[s], q[t + 1], q[t + 5])
        CCX(q[s], q[t + 5], q[t + 1])
        CCX(q[s], q[t + 0], q[t + 4])
        CCX(q[s], q[t + 4], q[t + 0])  # 本条件下的门组合后即门 C(U^4)

# 逆傅里叶变换中的 swap 步骤
for i in range(0, t // 2):
    SWAP(q[i], q[t - i - 1])

# 逆傅里叶变换中的控制旋转步骤
for i in range(0, t - 1):
    H(q[t - i - 1])
    for j in range(0, i + 1):
        CRZ(-pi / 2 ** (i - j + 1))(q[t - j - 1], q[t - i - 2])
        RZ(-pi / 2 ** (i - j + 2))(q[t - j - 1])
H(q[0])

# 完成逆傅里叶变换,完成相位估计算法,等待测量
MeasureZ(q[:L], range(0, L))  # 只测量辅助寄存器即前 L 个比特
env.commit(8192, downloadResult=False)
复制

执行算法 次,忽略总频次 的一些小概率结果,其余结果经数据处理后如下,其中 "4096": 1419 表示 出现了 次:

{
    "4096": 1419,
    "0": 1287,
    "5461": 955,
    "2731": 955,
    "1365": 940,
    "6827": 896,
    "6826": 252,
    "1366": 250,
    "2730": 246,
    "5462": 219,
    "2732": 56,
    "5460": 53,
    "6828": 52,
    "1364": 49,
    "2729": 47,
    "1367": 41,
    "5463": 36,
    "6825": 34,
} 
复制

分别对这些结果对应的分数做连分数展开并截断,得:

{
    {{0, 1/2}: 1419},
    {{0}: 1287},
    {{0, 1, 1/2, 2/3, 5461/8192}: 955},
    {{0, 1/2, 1/3, 2731/8192}: 955},
    {{0, 1/6, 682/4093, 1365/8192}: 940}, 
    {{0, 1, 5/6, 3411/4093, 6827/8192}: 896}, 
    {{0, 1, 4/5, 5/6, 1704/2045, 3413/4096}: 252}, 
    {{0, 1/5, 1/6, 341/2045, 683/4096}: 250}, 
    {{0, 1/3, 1365/4096}: 246}, 
    {{0, 1, 2/3, 2731/4096}: 219}, 
    {{0, 1/2, 1/3, 683/2048}: 56}, 
    {{0, 1, 1/2, 2/3, 1365/2048}: 53}, 
    {{0, 1, 5/6, 851/1021, 1707/2048}: 52},
    {{0, 1/6, 170/1021, 341/2048}: 49}, 
    {{0, 1/3, 545/1636, 546/1639, 2729/8192}: 47}, 
    {{0, 1/5, 1/6, 136/815, 137/821, 410/2457, 1367/8192}: 41},
    {{0, 1, 2/3, 1091/1636, 1093/1639, 5463/8192}: 36},
    {{0, 1, 4/5, 5/6, 679/815, 684/821, 2047/2457, 6825/8192}: 34}
} 
复制

考虑各行第一个分量中分母不超过 且分母最大的分数的分母(这里仅有 ), 其中可以得到的分母为 的频次分别为 。考虑到 ,故而每次相位估计算法有约 的概率可以得到正确结果 ,两次实验有约

的概率可以得到正确结果 ,这里最后一个加项表示两次测量中一次结果为 而另一次为 。由 诱导了 的一个不平凡的分解:

参考资料

[1] Pomerance, Carl. "A tale of two sieves." Notices Amer. Math. Soc., 1996.

[2] Shor, Peter W. "Algorithms for quantum computation: discrete logarithms and factoring." Proceedings 35th Annual Symposium on Foundations of Computer Science, IEEE, 1994.

[3] Agrawal, Manindra, Neeraj Kayal, and Nitin Saxena. "PRIMES is in P." Annals of Mathematics (2004): 781-793.

[4] Lenstra Jr, H. W., and Carl Pomerance. "Primality testing with Gaussian periods." Archived version 20110412, Dartmouth College, US, 2011.

[5] Nielsen, Michael A., and Isaac L. Chuang. "Quantum Computation and Quantum Information: 10th Anniversary Edition." Cambridge University Press, 2010.

[6] Vedral, Vlatko, Adriano Barenco, and Artur Ekert. "Quantum networks for elementary arithmetic operations." Physical Review A 54.1(1996): 147.

[7] Beauregard, Stephane. "Circuit for Shor's algorithm using 2n+3 qubits." arXiv preprint , 2002.

附录

附录中会补充一些定理的证明,以及更多的细节,建议打开两个窗口平行阅读。附录中有些公式会有两个编号,此时第一个编号是该公式上一次在本节中出现时的编号。

本段目录重申如下:

  • 6.1 子段补充量子求阶算法中 门的本征值本征向量相关内容,需要一点点线性代数的知识背景
  • 6.2 子段补充量子求阶算法中连分数展开这一步骤的正确性的证明,不需要知识背景,但证明略繁琐需要读者的耐心;
  • 6.2 子段补充量子求阶算法成功概率相关内容,需要一点点初等数论的知识背景;
  • 6.4 子段补充秀尔算法搜索 具有“良性”的概率,更紧的下界需要一些抽象代数的知识背景;
  • 6.5 子段补充 门的分解,这是物理实现必要的步骤,这里给出了参考文献供读者延伸阅读,另外读者也可以参考 QCompute SDK 中的秀尔算法代码样例和教程。

门的本征

本子段旨在补全引理 12 和引理 14 的证明,需要的知识仅有线性代数,不熟练 Dirac 符号的读者可以再回顾下 1.2 节。这里先重申一下 门的定义:

引理 12. 有本征值形如

且有对应本征态

证明. 可以验证

进而有 的任意本征值 满足 ,故而存在 , 使得 。 设 如式 ,考虑到

是本征值 的一个本征向量,这里 处使用了变量代换

再来验算 是单位向量,进而 的一个本征态:

这里 蕴含 当且仅当

引理 14.

证明.

其中 为等比数列求和, 为克罗内克 函数,定义为

连分数展开

本子段讲述算法 18 的步骤 3 连分数展开相关内容的正确性,所必要的连分数相关知识封闭,全部呈现如下。这里没有引入太多高深的数学知识与工具,只要读者有足够的耐心,定能从中所得。对证明过程并不感兴趣的读者可以只阅读各个定理的内容,直至定理 28,其支撑起了量子求阶算法连分数展开这一步骤的正确性。另外,更本质的量子周期求解算法中也需要用到连分数展开这一步骤。

定义 19(连分数,Continued Fraction). 给定非负整数 个正整数 ,设正有理数

称式 为正有理数 的连分数表示,简记为 。特别地, 确定且 时, 连分数表示唯一。

鉴于正有理数的连分数表示唯一,我们有如下简单的算法计算其连分数表示,称为连分数展开算法。

算法 20(连分数展开).

输入: 正整数对 表示正有理数

输出: 正有理数 的连分数表示 ,其中

def Euclidean_Algorithm(p, q, L=[]):
    """
    :param p: 分子,整数
    :param q: 分母,正整数
    :param L: 连分数展开数组的储存器,整数数组,可以理解为使用了数据结构队列
    :return: 将 p/q 连分数展开,各项构成的整数数组
    """
    # L 为连分数表示结果的寄存器,首次被调用时初始化为 []
    Quotient = p // q # 计算商
    Remainder = p - q * Quotient # 计算余数
    L.append(Quotient) # 将商添加到连分数表示队列尾,即 a_n
    if Remainder != 0: # 在余数不为 0 时
        # 递归调用,注意上一步的分母是这一步的分子,上一步的余数是这一步的分母
        return Euclidean_Algorithm(q, Remainder, L) 
    else:
        return L # 返回值 L=[a_0,...,a_M] 即输出
复制

在流程上,上述算法就是欧几里得辗转相除法,特别的是欧几里得辗转相除法关心最后一次余数为 时的除数是多少,而连分数展开算法关心每一步的商是多少。

定义 21(截断). 给定连分数 ,称连分数 为连分数 的第 截断 (-th convergent)。

这里因为此处 convergent 的中文译名不常见,直译第 “收敛”又会让人感到费解,笔者特选择“截断”一词作为意译。 如例 15 所示对 执行连分数展开有:

可以看出连分数展开的过程就是欧几里得辗转相除法,每一次迭代将分数表示为带分数的形式,然后将带分数的分数部分的分子化为 ,将新的分母作为下一次迭代的输入,循环至带分数为整数止。而将有理数表示为带分数就是“相除”,分子化为 就是 “辗转”。式 中的 即为连分数 的第 ,第 ,第 和第 截断。

引入截断是为了更好解释连分数的一些性质,这里我们首先给出各截断与连分数表示之间的关系,如下:

定理 22. 给定连分数 ,令 ,对

则对 ,我们有连分数

特别地, 都是严格单调递增的正整数列。

证明. 可以直接验证定理 22 在 时成立。对 归纳,假设定理 22 在 时成立。当 时,我们需要验证定理 22 仍成立。考虑连分数表示 ,这里尽管 不是整数,但上述的连分数的定义仍可推广至此,我们可以验证定理 22 在 的情形对该新连分数仍成立。设 在定理 22 中诱导出的序列 ,那么我们有 。然后由式 有:

及式 都是严格单调递增的正整数列。

除了单调之外,截断还有下述额外性质,其蕴含了 是既约分数,或者说 互素:

推论 23(裴蜀问题). 符号定义同定理 22,对整数 有:

特别地 还蕴含了 互素。

证明. 由定义验证可知 ,即 时式 成立。当 时,将式 代入式 左边有:

归纳可知对任意正整数

考虑最大公因数 ,故而 ,即 互素。

除了整数列 单调以外, 关于 也是单调的,即推论 26,但这个单调性的证明就没那么好证了。笔者不才,下面给出一种比较繁琐的证明方式,需要途经引理 24 和 25 方才得到推论 26。

引理 24. 符号定义同定理 22,对任意的非负整数

更一般地,对正整数

其中 为奇数, 为偶数。特别地,

这里 表示实数 的符号。

证明. 由推论 23 有

再由式

完成了式 的证明。更一般地,对正整数

这里式 处将第二个加项采用 重新表示,式 处代入了式 。因为式 第二个乘项 ,故而 的符号与 相同。

以引理 24 为工具,我们先考虑 作为 的数列相邻两项的大小关系:

引理 25. 符号定义同引理 23,给定两个正整数 ,有

证明. 考虑式 左边与右边差的符号,带入式 有:

其中式 处带入了式 函数内第一个加项再次带入了式 ,第二个加项中由数列 的严格单调递增性(定理 22)可以推出 ,故而加上绝对值符号后外面的系数发生了变号;式 处提出了因数 ;式 严格大于 诱导该 函数值为 (不是 )。故式 得证。

将引理 25 推广到一般情形有:

推论 26. 符号定义同引理 23,给定三个正整数 ,有

即连分数 的第 截断与该连分数的距离关于 严格单调递减。

下面的定理 27 讲的是连分数截断的必然性,若一个有理数 是另一个有理数 满足一定条件的逼近,那么 必然是 的连分数表示的某个截断:

定理 27. 给定有理数 ,若另一个(既约)有理数 满足

那么 的连分数表示的某个截断,也就是说

证明.,如式 定义正整数列 ,设 ,那么我们有

再由 及式 。设

将式 代入,上式 化简为

经验算可知

和(由定理 22)

(a)当 时,由式

此时可记 ,那么我们有

(b)当 时,我们不能使用相同的办法得到如式 的结果。先做如下修改:

这里由算法 20 的流程可知 ,否则 。然后以新的连分数表示计算数列 ,并改记为 。类似式 和 式 ,我们有

此时可记 ,由式 ,我们有

综(a)(b)所述, 的连分数表示的某个截断。

有了推论 26 和定理 27 还不足以证明连分数展开步骤的正确性,所缺失的最后一块拼图是有理数的间隙有多大:

定理 28. 当相位估计算法返回了 的一个 -估计 时, 的连分数表示有唯一截断 满足 。此时 恰是 的连分数表示的截断 中满足 最大的那个截断。

证明.-估计及 ,有

由定理 27 有 的连分数表示的某个截断。 考虑分母不超过 的有理数全体构成的集合 ,其中的任意两个元素的距离不少于

故而集合 中至多一个元素与 距离 ,也就是说 是集合 中与 距离最近(且唯一)的元素。由推论 26 知, 的各截断与 的距离随截断序数增加而减少,故 恰是满足 最大的那个截断

量子求阶算法的成功概率

本子段旨在给出量子求阶算法的成功概率,即定理 17 的证明,需要引入一些初等数论相关的知识:主要扩展模 的阶这一概念。

首先我们引入 欧拉函数(Euler's Totient Function)费马-欧拉定理

定义 29(欧拉函数). 给定正整数 ,记 中与 互素的元素数量为欧拉函数 。设 的素因数分解,其中 为互不相同的素数, 为正整数,有欧拉函数

特别地,,对素数

定理 30(费马-欧拉定理). 任给定互素的正整数 ,有

由费马-欧拉定理可知 互素时 的阶 存在。另外阶 与欧拉函数 之间还有整除关系,更一般的形式即下述习题 2,为了证明习题 2 我们还要引入两个数的最大公约数与这两个数之间的关系,即 裴蜀恒等式(Bézout's Identity)

定理 31(裴蜀恒等式). 给定整数 ,存在整数 ,使得

由裴蜀恒等式便可推导出:

习题 2. 任给定正整数 ,若正整数 满足 ,则有 的阶 存在,且 。特别地,

最后我们再来证明量子求阶算法的成功概率,即定理 17。

定理 17. 通过执行两次量子求阶算法,可以得到两个分母 ,计算 的最小公倍数 ,则 的概率 ,这里 是相位估计算法的失败概率。

证明. 先假设两次相位估计都达到了精度

由注 16,可设 ,有

这里用到了最大公因数的一条性质 。所以 当且仅当 。由引理 14, 独立地服从 上的均匀分布,那么 的概率为

这里 表示 遍历所有 的素数,使用了级数 这一结果(最常见的证明需要傅里叶分析)。

通过更细致地分析,借由黎曼 函数的欧拉乘积公式(Euler Product Formula for the Riemann zeta Function):

可以得到

这里 表示遍历全部素数 ,计算累积。

考虑到量子相位估计算法的成功概率为 蕴含 ,综上所述,本引理得证。

由注 16 有:

推论 32. 若只执行一次量子求阶算法,得到的分母 的概率不少于 ,这里 是相位估计算法的失败概率, 为定义 29 中的欧拉函数。

“良性”的比例

本子段需要一些抽象代数(或称近世代数)的知识,即环论的中国剩余定理(或称孙子定理),用于估算秀尔算法中搜索的 具有“良性”的概率。阅读本节需要知道有限群的阶,群中元素的阶,商环等概念。

整数环的商环的中国剩余定理可描述如下,为了合理地简化问题,我们这里假设 是奇数,即没有素因子

定理 33(中国剩余定理). 为正奇数 的素因数分解,其中 为互不相同的奇素数, 为正整数,那么有环同构:

其诱导了环的乘法群的群同构:

这里 表示 阶循环群。记 使得 为奇数,且 为正整数,有:

这里 是各 中的最大值, 是与 相等的 的数量。特别地,这里 为一个奇数阶交换群, 为一个 的幂次阶交换群(,这里用 表述群的元素数量,称群的 )。

考虑 具有偶数阶 ,这里 分别称为 中的投影, 为正整数, 为正奇数,那么

这里向量表示的环中元素改用加法表示交换群上的乘法,改用数乘表示群上的整数幂运算。考虑到 为一个奇数阶交换群, 为一个 的幂次阶交换群,我们有(由群中元素的阶整除群的阶,类似习题 2)

将上式 带入式 可以得到 。所以,,与 中的投影 无关。故而当我们考虑元素 是否具有“良性”时,可以不失一般性地假设 为平凡群,只考虑另一部分:交换群

仍记 上的投影为 ,有:

假设

使得

上式 与式 矛盾,这迫使

亦有式 可化简为

此时相当于 ,解之得

故而满足式 的数量为

其中 所含不同素因数的数量。

,由式 我们有式 蕴含 。故由式

那么 具备“良性”的概率

整理结论得到下述定理,这个结果已经过度放缩了,式 中蕴含了更紧的下界。

定理 34. 随机抽取 ,其具有“良性”即满足

的概率 ,其中 互不相同的素因数的数量。

门的实现

在量易伏实现中,我们使用代数手段将 分解为 门的组合,并借由经典计算简化了 门。这在逻辑上其实是说不通的,无论是门的分解的过程,还是省略计算的过程都有循环论证之嫌:涉及到或者蕴含到已知 的分解这一事实。若想引入一个常规的泛用的 门的分解可以参照文献 等。另外读者也可以参考 QCompute SDK 中的秀尔算法代码样例和教程。

除了这种为了控制辅助量子比特数量而设计的复杂的方法之外,我们可以借助经典的可逆计算的途径来实现

从(经典)可逆计算开始

什么是经典的可逆计算?大家应该都知道经典计算机是基于 2 进制数及逻辑运算实现的,逻辑运算一般用三种基本的门“与”门 、“或”门 和“非”门 来实现,除去“非”门外,“与”门和“或”门都是两个输入一个输出:

这种无法从输出完全恢复出输入信息的计算就被称为不可逆计算,反之称为 可逆计算。可以看出对可逆计算而言,输入与输出的比特数量应当相等,比如上述的“非”门就是可逆计算。

可以预料到当我们保留输入信息,并在额外的寄存器上实现计算时,实现的计算必然是可逆计算,比如:

这里 是任意一个 的函数。

最后我们来讲,通过引入辅助量子比特,量子计算中的 门、 门和 Toffoli 门 , 便可模拟所有的可逆计算,其中:

这里“扇出” 是将一个经典比特复制为两份,这在量子计算对计算基能有效实现。另外由“或”门的分解,我们也可以得到其量子版本:

量子“或”门

图 3:量子“或”门

回到

给定一个输入 ,我们总能经典地计算判断 ,并在 时计算 ,这个判断和计算的过程终归是用逻辑运算实现的,即最终被分解为“与”门、“非”门和“扇出”门的组合,进而可被量子电路等效实现。最终我们获得了一个由若干 门、 门和 Toffoli 门组成的量子电路 ,其实现了

其中 是整个电路需要引入的辅助量子比特的数目。根据可逆计算的性质,上述电路中所需量子门的数目和 都不超过经典计算中逻辑运算次数的两倍,这保证了 可以被有效实现。

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

Navigated to 量易简