The problem: for n people, figure out who is brave by sending them to the rollercoaster. If a person is brave, and being sent to rollercoaster, and the number of people on the rollercoaster, the rollercoaster will start and tell you whether it is started.
Mathematically: Given a function f(B, A) : \{0, 1\}^n \times \{0, 1\}^n \to \{0, 1\}^n that is written as f(B, A) = (A_1 \land B_1) \oplus ... \oplus (A_n \land B_n), given mystery bits A_1, ..., A_n, figure out the mystery bits by plug in B_1, ..., B_n of your choice and observe the function's output.
More simply, figure out the behavior of function XOR_{B_1 ... B_n} (A_1, ..., A_n) (with constraints f(B, A) = (A_1 \land B_1) \oplus ... \oplus (A_n \land B_n)) by plug in A_1, ..., A_n of your choice.
XOR with bitmask: XOR_{B_1 ... B_n} (A_1, ..., A_n) = (A_1 \land B_1) \oplus ... \oplus (A_n \land B_n)
The subscript of
XOR
denotes whether the person is "brave".
We start by simulating the function XOR_{1101}(A_1, ..., A_n): A_i \to \{0, 1\}. On classical computer, it is identical to the following function: by the property of XOR:
The effect of XOR is simply counting how many input that is non-zero. XOR(x_1, ..., x_n) = \sum_{i = 1}^n x_i. The filtered XOR_{B_1 ... B_n} (A_1, ..., A_n) can be seen as dot product of vectors \begin{bmatrix}A_1 & ... & A_n\end{bmatrix} \cdot \begin{bmatrix}B_1 & ... & B_n\end{bmatrix}. Note that (\sum_i a_i \cdot b_i) \mod 2 = \sum_i ((a_i \cdot b_i) \mod 2).
Problem: figure out vector |A\rangle by giving you a blackbox f(|B\rangle) = \langle A | B \rangle, and you can only plug in |B\rangle.
def XOR_{1101}(A_1, ..., A_n):
CNOT A1 Ans
CNOT A2 Ans
(Skip A3 since the 3rd bit of mask is zero)
CNOT A4 Ans
return Ans
Observe that
XOR
is commutative and associative
From now we assume we have the secret strong 1101
. Our method is to show that we can compute 1101
to the truth table of XOR_{1101}(A_1, ..., A_n)
. So if we can obtain the truth table, then 1101
can be recovered. Note that obtaining the truth table itself do need 1101
, but not necessary in a human-readable form, we only need a code that has a secret 1101
in it.
If written in quantum code, XOR_{1101}(A_1, ..., A_n) can be sign-compute as the following:
def If XOR_1101_Then_Minus(A1, A2, A3, A4):
If A1 Then Minus A1
If A2 Then Minus A2
(Skip A3 since the 3rd bit of mask is zero)
If A4 Then Minus A4
Intuition: We first prepare uniform superposition, and for every possible state, sign compute XOR_B
on that state.
The circuit diagram can be written as follow
A1: H, Add_1, H
A2: H, Add_1, H
A3: H, Add_0, H
A4: H, Add_1, H
So we can re-write the code as follow using parallel computation
def If XOR_1101_Then_Minus(A1, A2, A3, A4):
// sign computes Add 1101 to A1, ..., An
H on A1, ..., An
Add 1101 to A1, ..., An
H on A1, ..., An
We are effectively load XOR result into amplitude with -1 (un-normalized) or 0 amplitudes, depending on the input.
Now, if we initialize all bits to uniform superposition, and then do the above instruction, we can load the truth table of XOR_{1101} into state.
@require A1, ..., An=0
def load_table():
// initialize to uniform superposition
H on A1, ..., An
// do sign compute
If XOR_1101_Then_Minus(A1, A2, A3, A4)
In above, code, we uniformly initialize A_1, ..., A_n to equal amplitude, and negate the sign of the amplitude by If XOR_1101_Then_Minus(A1, A2, A3, A4)
.
Observe the above function is the same as:
@require A1, ..., An=0 def load_table(): H on A1, ..., An // same as If XOR_1101_Then_Minus(A1, A2, A3, A4) below H on A1, ..., An Add 1101 to A1, ..., An H on A1, ..., An
Therefore can be simplified to@require A1, ..., An=0 def load_table(): // this two lines are canceled out Add 1101 to A1, ..., An // notice 1|1101> H on A1, ..., An
Therefore, we effectively sign computed If XOR_1101_Then_Minus(A1, A2, A3, A4)
Theorem: For any string b \in \{0, 1\}^n, if we initialize bits B_1, ..., B_n to string b, and do a H gate, then the resulting amplitude's sign encodes the truth table of XOR_b. That is:
Corollary: if you start with truth table of XOR_b as signed amplitude, then you could do the inverse of the above operation (H on A1, ..., An
) and end up with amplitude 1 on string b. This is because the second line of Add 1101 to A1, ..., An // notice 1|1101>
.
Input: classical code C that computes function F : \{0, 1\}^n \to \{0, 1\} where F is guaranteed to be some XOR_b function for some unknown b.
Output: deduce b
Classical Solution: run C with n \cdot |C| steps. (Where |C| is the steps of the original code and n is the length of truth table, or how many people there are in rollarcoaster)
Quantum: do If XOR_1101_Then_Minus(A1, A2, A3, A4)
with only 2|b| instruction (2 because we need garbage-free)
@require A1, ..., An = 0
def solve_bernstein_vazirani():
// make uniform superposition
Had on A1, ..., An
// load truth table
// assume we have blackbox XOR_b here
Sign Compute XOR_b(A1, ..., An)
H on A1, ..., An // by corollary, amplitude 1 on b
Print_All()
The above algorithm is O(2n + 2|C|) instructions. The entire procedural is like: 1. sign compute on uniform superposition using the blackbox XOR_b 2. try to reverse the blackbox, since we know the general structure of the blackbox 3. but only reverse half of it, to the point when it adds b, so we only need to reverse one instruction H 4. so after that we get some state that is equivalent of blackbox's H, H, CNOT b on 0, but that is exactly CNOT b on 0 which is b
Summary: there are two ways to sign compute
XOR_b
function: one using blackbox, the other using b which we don't know. We can sign compute using the first method, and reverse according to the second method to get b.
Table of Content