---
# System prepended metadata

title: 03 DJ algorithm（上）
tags: [量子演算法（下）]

---

# Deutsch-Jozsa Algorithm（上）
前面介紹的 Deutsch 演算法只能解決單變數之函數問題（就兩張撲克牌），Jozsa 將 Deutsch 的想法延伸到可以應用在多變數之函數問題（多張撲克牌），即耳熟能詳的 DJ 演算法。

## 要解決什麼問題？
與上一節類似，只是問題變成多變數函數，一樣要判斷函數是 constant 還是 balanced function，或是用撲克牌的例子，判斷多張撲克牌會是下咧兩種情況的哪種：
1. 所有的牌都是紅色或是黑色
2. 有一半的牌是紅色，另外一半是黑色

舉個例子，比方說判斷有兩個變數的函數（兩個變數代表可以表示四張撲克牌）：

\begin{split}
f(x_0,x_1)=x_0\oplus x_1
\end{split}

這函數所有的輸入與輸出為：

\begin{split}
f(0,0)=0\\
f(0,1)=1\\
f(1,0)=1\\
f(1,1)=0
\end{split}

不是全部的輸出都一樣，而是有一半的輸出是 $0$，另外一半輸出是 $1$，因此這函數是 balance function。

## 經典電腦的解法
### 第一種解法
如果是你眼前的電腦或手機，跟上節一樣，就是所有的可能的輸入都算過一遍後，比較函數輸出結果來判斷函數的類型。當函數有 $n$ 個變數時，就要計算 $2^n$ 種可能，並進行$\frac{(2^n-1)2^n}{2}$ 次比較。

以上面提到兩變數 function 為例，

\begin{split}
\text{Step 1: }&f(0,0)=a \\
\text{Step 2: }&f(0,1)=b \\
\text{Step 3: }&f(1,0)=c \\
\text{Step 4: }&f(1,1)=d \\
\text{Step 5: }& a=b? \\
\text{Step 6: }& a=c? \\
\text{Step 7: }& a=d? \\
\text{Step 8: }& b=c? \\
\text{Step 9: }& b=d? \\
\text{Step 10: }& c=d? \\
\end{split}

總共需要要 4 次計算和 6 次比較，經典電腦總共要執行 10 步才能告訴你這函數是 balanced 還是 constant。

### 第二種解法

不過以上是最笨的做法，但也是最保證不會出錯。另一種解法就是我們在 Deutsch 演算法中提到撲克牌的例子，檢查一半數目的撲克牌後再多檢查一張牌，寫成數學式就是，當函數有 $n$ 個變數，就要計算 $\frac{2^n}{2}+1=2^{n-1}+1$ 次。以前面的函數為例子，原本要算 4 次，現在僅需 3 次。

所以，經典演算法的複雜度為 $O(2^n)$。

## 量子電腦的解法
如果今天問題是單變數，像是 $f(x)=x$，電路會長得跟 Deutsch 演算法一樣

<div style="text-align: center;">
    <img src="https://hackmd.io/_uploads/B1cljkukkx.svg" alt="D circuit" width="100%"/>
    <p>
    </p>
</div>

當問題是多變數時，像是 $f(x_0,x_1)=x_0\oplus x_1$，就是簡單地把上圖延伸成

<div style="text-align: center;">
    <img src="https://hackmd.io/_uploads/HJc2hvvKye.svg" alt="DJ circuit" width="100%"/>
    <p>
    </p>
</div>

如果測量結果（$|m_0m_1m_2...m_{n-1}\rangle$）都是 0，表示這函數是 constant function；如果不是，代表這函數是 balanced function。

不管函數有幾個變量時，量子電腦都只需要計算 1 次，因此演算法複雜度為 $O(1)$，相比經典電腦，當變數越多時，量子電腦所謂的加速作用會越明顯

<div style="text-align: center;">
    <img src="https://hackmd.io/_uploads/SJ5auEY1Jl.svg" alt="圖片內容" width="90%"/>
    <br>
    <p>藍色和橘色都是經典電腦，藍色是透過最笨的方式，橘色則是經第二種解法；灰色則為量子電腦。當函數的變數來到 5 個時，經典電腦最少也需要計算 17 次，而量子電腦僅需 1 次，大大減少計算所需時間
</p>
</div>

## 範例
回到前面提的例子：

\begin{split}
f(x_0,x_1)=x_0\oplus x_1
\end{split}

這函數有兩個變數，所以要用 3 個 qubits，DJ 演算法基本會長這樣：

<div style="text-align: center;">
    <img src="https://hackmd.io/_uploads/rkJxK4tJ1e.svg" alt="圖片內容" width="100%"/>
    <br>
    <p>後面還有測量動作，這邊沒有秀出來
    </p>
</div>

中間的 $U_f$ 會長什麼樣子呢？跟 Deutsch 演算法的思路一樣，要先知道經過 $U_f$ 操作後各 qubit 的狀態為何。我們知道前面 2 個 qubits 的狀態不會變，第 3 個 qubit 的狀態會變成： 

\begin{split}
y\oplus f(x)&=y\oplus (x_0\oplus x_1)\\
&=(y\oplus x_0)\oplus x_1
\end{split}

先看第一項 $y\oplus x_0$，將表格寫出來後長這樣

\begin{array}{|c|c|}
\hline
\text{輸入} &U_f\text{ 輸出} & U_f\text{ 輸出}\\
\hline
x_0 \quad y & x_0 & y\oplus x_0 \\
\hline
0\quad 0 & 0 & 0 \\
\hline
0\quad 1 & 0 & 1 \\
\hline
1\quad 0 & 1 & 1\\
\hline
1\quad 1 & 1 & 0\\
\hline
\end{array}

給你點時間想想什麼樣的 gate 能產生如同表格中呈現的效果。你可以看到只有輸入 $(x_0,y)$ 為 $(1,0)$ 和 $(1,1)$，狀態（輸出）才會改變。沒錯！就是 CNOT gate，所以 $U_f$ 有一部分長這樣：

<div style="text-align: center;">
    <img src="https://hackmd.io/_uploads/Bkf-KNKyJe.svg" alt="圖片內容" width="100%"/>
    <br>
    <p>
    </p>
</div>

緊接著是第二項 $[(y\oplus x_0)]\oplus x_1$

\begin{array}{|c|c|}
\hline
\text{輸入} & \text{輸入} &U_f\text{ 輸出} & U_f\text{ 輸出}\\
\hline
y\oplus x_0 & x_1 & y\oplus x_0 & [y\oplus x_0]\oplus x_1 \\
\hline
0 & 0 & 0 & 0 \\
\hline
0 & 1 & 0 & 1 \\
\hline
1 & 0 & 1 & 1\\
\hline
1 & 1 & 1 & 0\\
\hline
\end{array}

老掉牙了，這很明顯也是 CNOT gate，所以完整電路長這樣

<div style="text-align: center;">
    <img src="https://hackmd.io/_uploads/SkwMYNK1ke.svg" alt="圖片內容" width="100%"/>
    <br>
    <p>
    </p>
</div>

簡單自己算一下，或是用 Qiskit composer 操作，這測量結果不是 $|00\rangle$，所以這函數是 balanced function。

## 演算法的應用
現在，給你點時間想想這演算法能應用在生活上什麼地方。

沒錯！沒有，不過這不代表這演算法沒有任何價值，事實上它在量子計算發展的初期提供一個很好的模型，展示量子電腦如何“加速”計算，比經典電腦更快。

這邊作者特別介紹，比 DJ 演算法更快的算法，只要看到多變數的 function，先猜 "balance function" 就對了，你會發現在多變數的情況下，要湊出 "constant function" 並不容易。


