跳轉到

5.3 Bernstein–Vazirani 演算法#

概念說明#

問題:黑箱內藏 \(f(x) = a \cdot x \bmod 2\) (內積、逐位 AND 再求和 mod 2),其中 \(a \in \{0,1\}^n\) 是未知字串。請找出 \(a\) 。

  • 古典(確定性):需要 \(n\) 次查詢——每次詢問一個單位向量 \(e_i\) ,讀出 \(a_i\) 。
  • 量子(Bernstein–Vazirani, 1993):只需 1 次查詢。

演算法步驟:

  1. \(|0\rangle^{\otimes n}\) 全部 H,輔助位元 \(|-\rangle\) ;
  2. 一次 \(U_f\) ,phase kickback 得 \(\frac{1}{\sqrt{2^n}}\sum_x (-1)^{a\cdot x}|x\rangle\) ;
  3. 再做一層 H。關鍵恆等式:
\[ H^{\otimes n}\left(\frac{1}{\sqrt{2^n}}\sum_x (-1)^{a\cdot x}|x\rangle\right) = |a\rangle \]

證明: \(H^{\otimes n}|z\rangle = \frac{1}{\sqrt{2^n}}\sum_x (-1)^{z\cdot x}|x\rangle\) ,把 \((-1)^{a\cdot x}\) 展開為 \(\frac{1}{\sqrt{2^n}}\sum_z (-1)^{a\cdot z}(-1)^{x\cdot z}\) 並對 \(x\) 求和,只剩 \(z=a\) 項存活(其他完全干涉抵消)。這是「干涉把振幅全部集中到答案」最乾淨的展示。

電路: \(n+1\) 位元,共 \(2n+1\) 個基本閘( \(2n\) 個 H + 1 次黑箱),一次測量直接讀出 \(a\) 。

Python 範例(用第 3 章的模擬器)#

import numpy as np

H = np.array([[1,1],[1,-1]], dtype=complex)/np.sqrt(2)
X = np.array([[0,1],[1,0]], dtype=complex)

def bv_run(a, n, shots=1000, seed=0):
    """a: 整數形式的隱藏字串,第 0 位是最低位"""
    N = 2**(n+1)
    # 狀態:|0^n>|1>,輔助位元放最高位(index n)
    psi = np.zeros(N, dtype=complex); psi[1] = 1
    # 輔助位元 H、X
    Hn = np.eye(1, dtype=complex)
    for _ in range(n): Hn = np.kron(Hn, H)
    psi = np.kron(Hn, H @ X) @ psi            # |+^n>|->
    # 一次黑箱:phase kickback -> sum (-1)^{a·x}|x>
    amps = psi.reshape(2**n, 2)[:, 0]         # 輔助位元=|-| 的部分
    for x in range(2**n):
        amps[x] *= (-1)**(bin(a & x).count("1") % 2)
    # 輸入暫存器再做 H
    new = Hn @ amps
    p = np.abs(new)**2
    rng = np.random.default_rng(seed)
    return rng.choice(2**n, size=shots, p=p)

for a_int, n in [(0b1011, 4), (0b110010, 6), (0b11111111, 8)]:
    res = bv_run(a_int, n, shots=1000, seed=42)
    got = np.bincount(res, minlength=2**n).argmax()
    print(f"隱藏 a={bin(a_int)} n={n} -> 演算法讀出 {bin(got)},"
          f"一次查詢,正確率 {np.mean(res == got):.0%}")

# 古典對照:n 次查詢
def classical_find_a(f, n):
    a = 0
    for i in range(n):
        if f(1 << i): a |= (1 << i)
    return a
print("古典需要 n 次查詢;量子只要 1 次")

複雜度分析#

查詢次數 閘數
古典確定性 \(n\) \(O(n)\)
量子 BV 1 \(2n+1\)

這裡的加速是「 \(n \to 1\) 」,不如 DJ 的指數差距戲劇化,但 BV 的架構(H–oracle–H)就是 Grover 擴散算子的前身,值得牢牢記住。模擬成本 \(O(2^n)\) 。

練習#

  1. 證明 \(H^{\otimes n}|a\rangle = \frac{1}{\sqrt{2^n}}\sum_x (-1)^{a\cdot x}|x\rangle\) ,並說明為何 BV 中兩層 H 恰好互相抵消掉 \(a\) 的資訊反轉。
  2. (程式)修改 bv_run,讓黑箱是 \(f(x)=a\cdot x \oplus b\) (多一個常數偏移 \(b\) ),觀察結果差一個全 1 字串,並解釋原因。
  3. (觀念)為什麼古典演算法無法用 1 次查詢找出 \(a\) ?(提示:一次查詢只能得到 1 位元資訊。)