量子计算(五)——Deutsch-Jozsa算法与Simon算法

一、Deutsch算法
1.Deutsch问题与经典算法
Deutsch算法是利用量子特性实现的最简单量子算法。这个算法要解决的问题是:对于一个接受一位二进制数输入并输出一位二进制数的函数 ,判断它是常量的(Constant)还是平衡的(Balanced)。将其称为Deutsch问题。 11 当函数 对任意输入都得到相同输出时,称它是常量的,在这个问题中例如 那么 就是常量的;当函数的所有输出结果一半为 而另一半为 时,则称它是平衡的。
这个问题在经典算法里只有一种解决方法,即分别计算 ,判断结果是否相同:
def Judge(function(bool)) -> bool:
if (function(0) == function(1)):
return Constant
else: return Balanced这显然需要对函数计算两次才能判断函数性质。当然,“判断结果是否相同”也可以利用异或来解决,当函数为平衡函数时返回真:
def Judge(function(bool)) -> bool:
return (function(0) ^ function(1))2.黑箱量子门
对于量子位而言,函数的作用如下:

22 虽然在上面的量子电路中将函数 视作一个“量子门”绘制在其中,但需要注意这甚至有极大的概率是非法的——因为它不一定是严格意义的量子门、也即酉矩阵。例如对于常量函数 , 对应的矩阵 就不是一个酉矩阵。 为了实现Deutsch算法,我们需要对函数进行进一步的封装,使其接受两个量子位的输入,将其记为一个黑箱33 在英文中,会称之为Oracle,意为“神谕”。 ,量子电路如 图 2 所示。

44 其中 是异或,也即无进位二进制加法。为什么我们要大费周章设计这样一个黑箱?这是为了生成一个合法的量子门。为了证明 是一个量子门(酉矩阵),只需要假设在量子电路中连续作用两次 即可。此时第一个量子依然不变;第二个量子则是 ,回到原状态。因此, 的逆阵、转置共轭 就是其自身。
3.Deutsch算法的实现
Deutsch算法的完整量子电路如 图 3 所示。

也即可以用下列公式表示:
最终的判断结果由对 号量子的测量产生。计算可知这个线路如何实现函数性质的判断:
由最后一式可以看出, 号量子的测量结果必然为 ,也正如之前经典算法所述,此异或结果就是函数的性质!在这个算法中,我们只运行了一次线路即得到了结果。
另一个有趣的点在于,线路最后的运行结果 号量子和 号量子并非是纠缠的,不论测量谁都不影响另一个量子;而且,最后只有 号量子包含我们需要的信息, 号量子则被丢弃。
如果仔细观察,Deustch算法中,在 作用后, 号量子的状态为 ; 作用后, 号量子的状态依然为 !此事的蹊跷之处在于,我们一开始引入黑箱量子门 时,状态不变的是 号量子, 号量子反而才是应该发生改变的!
像这种“本应改变的量子位(通常是受控位)没变、不应变的量子位(通常是控制位)反而发生改变”的现象称为相位反冲(Phase Kick-back)。这一现象会是许多量子算法的基础。
二、Deutsch-Josza算法
1.哈达玛变换再探
对于哈达玛变换我们已经知道:
可以合并写为:
现在我们希望像上式最后一式那样,以求和的形式,写出 被 操作的结果。难点在于如何确定 的符号。注意到单个量子哈达玛变换后 必是正的,因此当 时不会对符号改变作出贡献(相当于用 乘上某个数)。当 时,符号就由 中有多少个 决定了。由此可以得出:
第二行中将指数部分的求和视作了向量点乘。
2.Deutsch-Josza算法的实现
现在我们来推广Deutsch问题。现在函数 接受一个长度为 的二进制串作为输入,而依然输出一位二进制数。要求判断这个函数是常量的还是平衡的。 55 显然当 时,函数可以既不是常量的也不是平衡的。为了问题的进一步讨论,应当指出我们会规定其为一个承诺问题(Promised Problem),即承诺受到判断的函数必然是常量的或是平衡的,不存在其他状态。
类似地,我们需要将函数封装为黑箱,它对量子系统的操作是:
其中 包含 个量子,而 。 66 值得一提的是,黑箱量子门 必然是一个置换矩阵(Permutation Matrix),即每行每列都有且只有一个 ,其余元素均为 。这也正是 是一个量子门(酉矩阵)的基础。(当然这也说明置换矩阵不一定是 ,因为置换矩阵的转置共轭矩阵不一定与自身相等。)
解决这个问题的算法即是Deutsch算法的推广——Deutsch-Josza算法。它使用的量子电路如 图 4 与Deutsch算法几乎一致:

计算可得:
也就是说,最后 号量子的状态是:
其中,计算基态 的振幅是:
因此,当函数是常量的时,计算基态 的概率是:
而问题又是受承诺的,因此当测量结果并非全 时,函数就必然是平衡的了。
3.与经典算法对比
也许您在阅读Deutsch算法时会认为,量子算法计算一次相比经典算法的计算两次来说也并没有多大优势,甚至在时序上量子算法还要经过三个量子门,是完全的小题大做。但量子算法的优势需要在大规模数据前体现。例如对于推广的Deutsch问题来说,经典算法最差时、以及完全确定时需要计算 次,而Deutsch-Josza算法依然只需要计算一次。
当然,从实用性来说,Deutsch问题确实不具有太大的现实意义,更像是为了彰显量子优越性刻意设计的问题。但也正因如此,我们得以见识一个设计精妙的量子算法可以产生多大的加速效果。
经典算法的解决思路是:纯随机无重复地从 的字符串中挑选代入函数,如果出现一次计算结果与之前不同,即可确定是平衡函数;否则,以指数上升的概率认为其是常量函数;直到计算到第 次即可完全确定函数性质。
三、Simon算法
1.Simon问题
Simon问题也是一个与函数有关的承诺问题。设函数 接受长度为 的二进制字符串输入,输出也是长度为 的二进制串。承诺如果两个输入 有相同的输出即 ,那么两者的(按位)异或必然是 位全零字符串、或是某个特定字符串 ,即:
应当注意我们允许特殊字符串 是 ,此时函数是一一映射的。
这个问题要解决的是:寻找到这个特定字符串 。
2.Simon算法的实现
Simon算法使用的量子电路如 图 5 和 式(15) 所示。

其中,黑箱 的作用与D-J算法差不多,但现在是二进制串间的按位异或:
因此,计算算法运行过程可得:
最后我们只对 号量子测量。当特殊字符串 时, 是一一映射函数,因此 ——也就是说,所有计算基态 都会作为态矢量 出现,只是不一定按自然数递增顺序出现而已。因此,在 的情况下对 号量子的测量,任意一个状态出现的概率都是 。
当 时,那么在 的值域中的任意一个输出 ,应当存在且仅存在两个不同的输入 使 。而由于按位异或是循环的,前式也能写为 。于是,计算任意态 被测量得到的概率为:
也就是说,在这种情况下,测量出的态 必定符合条件 。但显然要想确定特殊字符串 ,测量一次绝对是不够的—— 中含有 个未知字符,按照方程理论,需要 个线性无关的方程才能完全确定(也就是 次测量),但实际上受“二进制字符串且不是 ”这个条件的限制,只需要 个线性无关的方程即可。
因此要想算得 ,至少需要通过测量得到 个线性无关的计算基态。在 次测量下得到 个线性无关的计算基态的概率是:
取对数后放缩可得:
也就是 ,几乎三成的概率可以在 次测量下得到线性无关方程组。
使用计算机可以得到实际近似值约为:
public class Main {
public static void main(String[] args) {
System.out.println(Tandem(100));
}
public static BigDecimal Tandem(int iteration) {
BigDecimal halve = BigDecimal.valueOf(1);
BigDecimal result = BigDecimal.valueOf(1);
for (int it = 1; it <= iteration; it++) {
halve = halve.divide(BigDecimal.valueOf(2));
result = result.multiply(BigDecimal.ONE.subtract(halve));
}
return result;
}
}--->result = 0.28878809508660242127...当然您会说三成的概率小的离谱了,从抽卡经验来看相当于必歪呀!但如果将这 次测量再进行 次呢?那么能够得到线性无关方程组的概率就非常大了——只需要计算不能得到的概率至多为:
例如当将整个过程重复 次时,不能得到线性无关方程组的概率就降为 ,几乎是必然可以解决问题的。这大抵就是量子算法与概率的魅力吧。