5.2 Deutsch–Jozsa 演算法#
概念說明#
問題:已知 \(f:\{0,1\}^n \to \{0,1\}\) 保證是以下兩種之一——
- 常數函式:所有 \(x\) 都有 \(f(x)=c\) ;
- 平衡函式(balanced):恰好一半的 \(x\) 有 \(f(x)=0\) 。
請判斷它是哪一種。古典演算法最壞情況需查詢 \(2^{n-1}+1\) 次(查到一半一樣仍無法確定)。量子演算法只要 1 次查詢。
演算法步驟( \(n+1\) 個位元: \(x\) 暫存器與一個輔助位元 \(y\) ):
- 初始化 \(|0\rangle^{\otimes n}|1\rangle\) ,對輔助位元做 H 得 \(|-\rangle\) ;
- 全部輸入位元做 H,得 \(\frac{1}{\sqrt{2^n}}\sum_x |x\rangle|-\rangle\) ;
- 作用一次 \(U_f\) ,由 phase kickback 得 \(\frac{1}{\sqrt{2^n}}\sum_x (-1)^{f(x)}|x\rangle|-\rangle\) ;
- 對輸入暫存器再做 H,測量輸入暫存器:全 0 ⟺ 常數,否則為平衡。
振幅推導:Hadamard 的變換是 \(H|x\rangle = \frac{1}{\sqrt{2^n}}\sum_z (-1)^{x\cdot z}|z\rangle\) ,因此第 4 步後輸入暫存器在 \(|0\rangle\) 的振幅為
\[ \frac{1}{2^n}\sum_x (-1)^{f(x)} \]
常數函式時此和為 \(\pm 1\) (機率 1 測得全 0);平衡函式時恰好抵消為 0。
Python 範例#
import numpy as np
def dj_oracle_matrix(f, n):
N = 2**(n+1)
U = np.zeros((N, N), dtype=complex)
for x in range(2**n):
for y in range(2):
col, row = (x << 1)|y, (x << 1)|(y ^ f(x))
U[row, col] = 1
return U
def deutsch_jozsa(f, n):
Hn = np.kron(np.eye(2**n), np.array([[1,-1],[1,1]], dtype=complex))/np.sqrt(2)
psi = np.zeros(2**(n+1), dtype=complex)
psi[1] = 1 # |0...0>|1>
psi = np.kron(np.eye(2**n), H) @ psi if False else psi
# 直接構造:輸入暫存器 |+>^n、輔助 |->
plus_all = np.ones(2**n, dtype=complex)/np.sqrt(2**n)
aux = np.array([1,-1], dtype=complex)/np.sqrt(2)
psi = np.kron(plus_all, aux)
psi = dj_oracle_matrix(f, n) @ psi # 一次查詢
# 對輸入暫存器再做 H
H1 = np.array([[1,1],[1,-1]], dtype=complex)/np.sqrt(2)
Hn1 = np.eye(1)
for _ in range(n): Hn1 = np.kron(Hn1, H1)
psi = np.kron(Hn1, np.eye(2)) @ psi
p_all_zero = abs(psi[0])**2 # 機率:測得 |0...0>|.>
return "常數" if p_all_zero > 0.99 else "平衡"
H = np.array([[1,1],[1,-1]], dtype=complex)/np.sqrt(2)
for n in [1, 2, 3]:
f_const = lambda x: 1 # 常數
f_bal = lambda x: (x & 1) ^ ((x >> 1) & 1) # n>=2 平衡(XOR 各位)
print(f"n={n}: 常數函式 ->", deutsch_jozsa(f_const, n),
"| 平衡函式 ->", deutsch_jozsa(f_bal, n))
複雜度分析#
- 量子:查詢複雜度 1;電路閘數 \(O(n)\) ( \(n\) 個 H + 一次 \(U_f\) )。
- 古典(確定性):最壞 \(2^{n-1}+1\) 次查詢,這是可證明的最優。
- 模擬器成本: \(O(2^n)\) 狀態向量 × \(O(n)\) 閘。
練習#
- 對 \(n=2\) 手算平衡函式 \(f(x)=x_0 \oplus x_1\) 在 DJ 演算法中最終測得全 0 的機率,應為 0。
- (程式)把
deutsch_jozsa改成測量 1000 次統計分佈,對常數與平衡函式各印出結果。 - (觀念)若 \(f\) 既非常數也不平衡,DJ 演算法會輸出什麼?為什麼此演算法的前提(保證二選一)是必要的?