qalgora-Q Docs Hub量子文档 ✦ Ask AI✦ 问问文档

Bernstein-Vazirani Algorithm

With a single oracle query, recover a hidden n-bit string s from a black-box function f(x)=s·x — where any classical deterministic query algorithm needs n queries in the worst case; even a randomized algorithm with high success probability still needs Ω(n) queries.

The problem it solves

Someone has fixed a hidden bit-string s and handed you an oracle that computes the mod-2 inner product of s with your input x:

f(x) = s·x = (s0x0 ⊕ s1x1 ⊕ … ⊕ sn−1xn−1)

Your job is to determine s. Classically, each query returns just one parity bit, so you are forced to probe one position at a time: use x = 100…0 to read s0, x = 010…0 to read s1, and so on. For a classical deterministic algorithm, getting all n bits takes n queries.

Hidden string length nClassical queriesBernstein–Vazirani
881
64641
100010001

From O(n) to O(1): however long s is, the quantum algorithm asks just once.

Intuition — reading every bit in one question

The classical limitation is that each input "flattens" the entire hidden string into a single parity bit, discarding the detail. Bernstein–Vazirani instead feeds all 2n inputs through the oracle in a uniform superposition at once, letting the oracle write every bit of s simultaneously into the phase structure of the state; a layer of Hadamards then "decodes" those phases back to the computational basis, so that s appears directly as the measurement result.

Why it works — the Hadamard sandwich and phase kickback

As in Deutsch, first prepare the auxiliary qubit in |−⟩. Then the oracle |x⟩|y⟩ → |x⟩|y⊕f(x)⟩ reduces to a pure phase acting on the data register:

|x⟩ → (−1)s·x |x⟩

Applying the oracle to the uniform superposition (1/√2n) Σx |x⟩ tags every basis state |x⟩ with the phase (−1)s·x. The key identity is that under an n-qubit Hadamard,

H⊗n (1/√2n) Σx (−1)s·x |x⟩ = |s⟩

In other words, a uniform superposition phased by (−1)s·x, run through a Hadamard transform, undergoes constructive interference toward |s⟩ and destructive interference that erases everything else. So the closing Hadamard sandwich turns the phase-encoded hidden string exactly back into the computational basis state |s⟩, and one measurement reads out all n bits.

The mechanism

StepRole
Prepare |−⟩ auxiliaryMakes the oracle act by phase kickback: writes (−1)s·x onto the data register.
First Hadamard layerPrepares the uniform superposition of all inputs, so one query covers every x.
OracleEncodes every bit of the hidden string s into each basis state's phase (−1)s·x.
Final Hadamard layerDecodes the phase encoding into the computational basis state |s⟩ via interference.
The principle in one line
The Hadamard-sandwich structure restores the phase-encoded hidden string to the computational basis, so a single measurement reads out all n bits. The trick is not "seeing more" — it is letting 2n interfering paths do the decoding for you.

What it shows — and what it doesn't

  • A deterministic, exponential query advantage. The n→1 speedup is deterministic and holds every run — but the advantage is in query complexity, not the speed of general computation.
  • It is a close cousin of Deutsch–Jozsa. The same Hadamard-sandwich-plus-kickback skeleton is used here to read out an entire string at once, rather than to decide a single global bit.
  • The oracle must genuinely encode s. It is the oracle's internal structure (which positions are controlled) that carries the answer; the algorithm only extracts it efficiently — it cannot guess from nothing.
  • It is a stepping stone to deeper algorithms. The same interference-based decoding idea is pushed to far more powerful forms in the period-finding of Simon's and Shor's algorithms.

The algorithm, step by step

  1. Prepare the auxiliary qubit in |−⟩ (x then h).
  2. Apply h to the n data qubits, making a uniform superposition of all inputs.
  3. Call the oracle; via phase kickback, each basis state acquires the phase (−1)s·x.
  4. Apply h to the data register again; interference converges onto |s⟩.
  5. Measure the data register and read off s directly.

Seeing it in code

Read it against the theory above: x(aux); h(aux) prepares the auxiliary in |−⟩; the first h(q) makes the n-qubit uniform superposition; the for loop is the oracle — it places an x.ctrl(q[i], aux) only on the positions where secret[i] == 1, writing the inner product s·x into the phase by kickback; the closing h(q) completes the decoding, and mz(q) hands back the hidden string. In the example secret = [1,0,1,1], so the counts peak at "1011".

If a backend displays bit strings with a different endianness, the output string may appear reversed; it still corresponds to the same hidden string. This page interprets outputs in q[0], q[1], … order.

import qalgora

@qalgora.kernel
def bv(secret: list[int]):
    n = len(secret)
    q = qalgora.qvector(n)
    aux = qalgora.qubit()
    x(aux); h(aux)
    h(q)
    for i in range(n):           # oracle encodes the secret string
        if secret[i] == 1:
            x.ctrl(q[i], aux)
    h(q)
    mz(q)

print(qalgora.sample(bv, [1, 0, 1, 1]))   # peaks at "1011"
Try it yourself
Change secret (say to [1,1,1,1,0,0,1,0]) and watch the counts peak move exactly onto that string — no matter how long s is, the oracle is still called only once, in sharp contrast to the bit-by-bit classical approach. The Deutsch algorithm page shows the same phase-kickback mechanism that underpins this one.

References

Bernstein-Vazirani 算法

仅凭一次谕示(oracle)查询,从黑盒函数 f(x)=s·x 中恢复出隐藏的 n 比特串 s——而任何确定性经典查询算法在最坏情况下需要 n 次查询;若允许随机算法并要求高成功率,查询复杂度仍为 Ω(n) 量级。

它解决的问题

有人选定了一个隐藏比特串 s,并交给你一个谕示,它计算 s 与你的输入 x带模 2 内积

f(x) = s·x = (s0x0 ⊕ s1x1 ⊕ … ⊕ sn−1xn−1)

你的任务是确定 s。经典上,每次查询只能问回一个奇偶比特,因此你只能逐位试探:用 x = 100…0 问出 s0,用 x = 010…0 问出 s1,依此类推。对确定性经典算法而言,要拿全 n 个比特,就要 n 次查询。

隐藏串长度 n经典查询次数Bernstein–Vazirani
881
64641
100010001

从 O(n) 到 O(1):无论 s 多长,量子算法都只问一次。

直觉 一次问出全部比特

经典查询的局限在于:每个输入都把整个隐藏串"压扁"成一个奇偶比特,丢掉了细节。Bernstein–Vazirani 的思路是把所有 2n 个输入做成均匀叠加同时喂给谕示,让谕示把 s 的每一位都同时写进量子态的相位结构里;随后用一层 Hadamard 把这些相位"解码"回计算基,使 s 直接显形为测量结果。

为何成立 Hadamard 夹心与相位回踢

与 Deutsch 一样,先把辅助比特预备为 |−⟩。这样谕示 |x⟩|y⟩ → |x⟩|y⊕f(x)⟩ 就退化为对数据寄存器的纯相位作用:

|x⟩ → (−1)s·x |x⟩

对均匀叠加 (1/√2n) Σx |x⟩ 施加谕示后,每个基矢 |x⟩ 都带上了 (−1)s·x 的相位。关键恒等式是:对 n 比特施加 Hadamard 时,

H⊗n (1/√2n) Σx (−1)s·x |x⟩ = |s⟩

也就是说,"被 (−1)s·x 调相的均匀叠加"经 Hadamard 变换后,会发生相长干涉指向 |s⟩、相消干涉抹去其余一切。于是末端的 Hadamard 夹层把相位编码的隐藏串精确地还原成计算基态 |s⟩,单次测量即可读出全部 n 位。

核心机制

步骤作用
制备 |−⟩ 辅助比特令谕示以相位回踢形式生效:把 (−1)s·x 写到数据寄存器上。
首层 Hadamard制备全体输入的均匀叠加,使一次查询覆盖所有 x
谕示把隐藏串 s 的每一位编码进各基矢的相位 (−1)s·x
末层 Hadamard通过干涉把相位编码解码为计算基态 |s⟩
原理一句话
Hadamard 夹心结构把相位编码的隐藏串还原到计算基,因此单次测量即可读出全部 n 个比特。诀窍不在于"看得更多",而在于让 2n 条干涉路径替你完成解码。

它能说明什么 又不能说明什么

  • 确定性、指数级的查询优势。n→1 的加速是确定的、每次都成立——但优势体现在查询复杂度上,而非通用计算的速度。
  • 它是 Deutsch–Jozsa 的近亲。同一套 Hadamard 夹心加相位回踢的骨架,这里被用来一次性读出整个串,而非仅判断一个全局比特。
  • 谕示必须真把 s 编码进去。是谕示内部结构(哪些位被控制)携带了答案;算法只是高效地把它抽取出来,并不能凭空猜测。
  • 它是更深算法的垫脚石。同样的干涉式解码思想,在 Simon 算法和 Shor 算法的周期查找中被推向更强大的形态。

算法逐步拆解

  1. 把辅助比特预备为 |−⟩(先 xh)。
  2. 对 n 个数据比特施加 h,制备所有输入的均匀叠加。
  3. 调用谕示;通过相位回踢,每个基矢获得相位 (−1)s·x
  4. 对数据寄存器再施加 h,干涉收敛到 |s⟩
  5. 测量数据寄存器,直接读出 s

对照代码理解

请对照上文原理来读:x(aux); h(aux) 把辅助比特制成 |−⟩;首个 h(q) 制备 n 比特均匀叠加;for 循环就是谕示——只在 secret[i] == 1 的位上放一条 x.ctrl(q[i], aux),从而把内积 s·x 经相位回踢写入相位;末端 h(q) 完成解码,mz(q) 便直接给出隐藏串。示例中 secret = [1,0,1,1],故计数峰落在 "1011"

若后端采用不同的比特串显示端序,输出字符串可能按相反顺序显示;物理含义仍对应同一个隐藏串。本文默认按 q[0], q[1], ... 的顺序解释输出。

import qalgora

@qalgora.kernel
def bv(secret: list[int]):
    n = len(secret)
    q = qalgora.qvector(n)
    aux = qalgora.qubit()
    x(aux); h(aux)
    h(q)
    for i in range(n):           # oracle encodes the secret string
        if secret[i] == 1:
            x.ctrl(q[i], aux)
    h(q)
    mz(q)

print(qalgora.sample(bv, [1, 0, 1, 1]))   # peaks at "1011"
动手试试
改动 secret(例如 [1,1,1,1,0,0,1,0]),观察计数峰精确移到那串比特上——无论 s 多长,谕示始终只被调用一次。这与逐位试探的经典做法形成鲜明对照。Deutsch 算法展示了支撑这里的同一套相位回踢机制。

参考文献