Lecture 008 - Rollercoasters

Rollercoasters

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.

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".

Sign Computes XOR with Filter

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:

XOR(x_1, x_2, ..., x_n) = \begin{cases} 1 & \text{if }|\{x | x = 1\}| \mod 2 = 1\\ 0 & \text{otherwise} \end{cases} = \sum_{i = 1}^n x_i

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.

Load Filtered Input to Amplitude

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.

Getting Truth Table Result to Amplitude Space

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:

Amplitude[a] = \begin{cases} +x & \text{if } XOR_b(a) = 0\\ -x & \text{if } XOR_b(a) = 1\\ \end{cases}

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>.

Bernstein-Vazirani Problem (Cira 1991)

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