基礎量子演算法與應用 | 2026 高中量子計算暑期營筆記
前言
會參加這個活動一是因為課程內容看起來就很酷,二是能水一整個禮拜的免費午餐,而且還送書,就是好東西不用錢還反過來送你禮物,這種東西哪裡找對吧!而且還不用考試選拔就能享受XD
我都考過物奧了這種課程對我來說應該輕輕鬆鬆(x
這次活動附中的特別多,是因為全校都把活動資訊丟在家長群,我比較納悶的是為什麼不直接丟給學生🤔
以下可能有很多地方都沒有寫的很清楚,這是因為這是一篇筆記文而非教學文。


基本的量子力學
古典物理告訴我們的事情
- 慣性: 無法區分靜 / 動
- 帶電 / 磁物體具有加速度會發射電磁波
Bra-Ket
叫做 Ket,就是我們熟悉的列向量,而每個 Ket 都有與之對應的 Bra:,是 Ket 的共軛轉置,為行向量,也就是 。我們可以輕易驗證兩向量 、 的內積就是 。
我們會用一個 Hilbert space 裡的向量來表示一個量子態,Hilbert space 表示完備的內積空間。
我們定義以下常用的 basis:
Bloch Sphere
球座標表示,就這樣。

Stern-Gerlach 實驗

量子力學中非常非常重要的實驗,不同於巨觀世界的直覺,說明量子力學中有疊加態且測量很重要。
我們以向量表示一個量子態,那測量就可以想像成把這個向量投影到測量的方向,能以此簡易的理解實驗結果。

量子力學 4 大公設

以下解釋 Unitary 和 Tensor product 是什麼
Unitary Matrix
矩陣 是 Unitary 矩陣表示
為什麼量子變換都一定是 Unitary 呢?是因為 Unitary 能保正交(因為要機率守恆),見以下:
為了保內積,我們要求
Tensor product
去看這篇w 09 張量積(Tensor product) - HackMD
CHSH game
這和貝爾不等式等價,所以上課沒講貝爾不等式講這個。
這個遊戲這樣進行:有一名裁判®和兩名玩家(A, B),R產生2個古典位元分別傳給 A, B,A, B 收到之後需要個別回傳一個古典位元,a, b。玩家獲勝的條件為 。過程中 A, B 兩人在遊戲過程中是不能交流的。
古典策略
圖片來源:CHSH game | IBM Quantum Learning
以下表格列出幾個例子
| x | y | a | b | xy | Result | |
|---|---|---|---|---|---|---|
| 0 | 1 | 0 | 1 | 0 | 1 | Loss |
| 0 | 1 | 1 | 1 | 0 | 0 | Win |
| 1 | 1 | 1 | 0 | 1 | 1 | Win |
古典策略能做到最好的勝率為 ,作法是 A 和 B 都無論如何回傳 0。
量子策略
勝率 ,看起來不能再高了對吧?但如果量子力學是對的那就不一樣了。A 和 B 可以事先準備一對處於最大疊加態 (Bell State) 的粒子對:,然後一人拿一顆。
而玩家 A、B 策略分別為:
- 玩家A:如果 ,在 Z 方向測量;如果 ,在 X 方向測量
- 玩家B:如果 ,在 方向測量;如果 ,在 方向測量
我們窮舉 的四種可能,可以發現勝率全部都是 ,比古典策略高。
薛丁格方程式
猜出方程式
教授:這只有用到高中知識,所以理論上你們都能寫下薛丁格方程式
我上課時沒拍到,所以我是課後問 Gemini 的
薛丁格是怎麼猜出薛丁格方程式的呢?
既然是波,那他也只能長成這樣(至少組成單元是這樣)
從量子力學的能量和物質波公式能得出
帶回去,能得到
對 微分兩次可得
對 微分一次可得
我們將他們代入能量守恆(兩邊同乘):
即可得到
這是一維的,稍加推廣就可以得到上面那個。
量子計算基礎
量子邏輯閘
首先,量子邏輯閘一定是 Unitary 的,常見的量子邏輯閘整理如下:
註:為了銜接,以下用 IBM Quantum Platform 的約定,最右邊為第一個 q bit。
單閘:
| Gate | Matrix | Vector | Maze |
|---|---|---|---|
| X | ![]() |
||
| Y | ![]() |
||
| Z | ![]() |
||
| H | ![]() |
雙閘:
| Gate | Matrix | Vector | Maze |
|---|---|---|---|
| CNOT | ![]() |
||
| CZ | ![]() |
AI 好讚,幫我生出這些,難以想像手搓 LaTeX 和那個 Maze 要搞多久
生成 Maze 那幾張圖片的 code
這也是 AI 生的w
import matplotlib.pyplot as plt
# 定義顏色常數
COLOR_MAP = {
'blue': '#3498db', # 正實數 (+1)
'red': '#e74c3c', # 負實數 (-1)
'gold': '#f1c40f', # 正虛數 (+i)
'purple': '#9b59b6' # 負虛數 (-i)
}
def draw_maze(gate_name, connections, is_two_qubit=False, filename=''):
fig, ax = plt.subplots(figsize=(3.5, 3.5 if is_two_qubit else 2))
if is_two_qubit:
# 在 IBM 標準下,由上到下排列:00, 01, 10, 11
labels = ['00', '01', '10', '11']
y_positions = [3, 2, 1, 0]
y_lim = (-0.5, 3.5)
else:
labels = ['0', '1']
y_positions = [1, 0]
y_lim = (-0.4, 1.4)
# 畫輸入端節點
ax.scatter([0] * len(y_positions), y_positions, color='black', s=100, zorder=5)
for label, y in zip(labels, y_positions):
ax.text(-0.15, y, label, ha='right', va='center', fontsize=12, weight='bold')
# 畫輸出端節點
ax.scatter([1] * len(y_positions), y_positions, color='black', s=100, zorder=5)
for label, y in zip(labels, y_positions):
ax.text(1.15, y, label, ha='left', va='center', fontsize=12, weight='bold')
# 連線映射
label_to_y = {l: y for l, y in zip(labels, y_positions)}
for start_lbl, end_lbl, color_key in connections:
start_y = label_to_y[start_lbl]
end_y = label_to_y[end_lbl]
color = COLOR_MAP[color_key]
ax.annotate('', xy=(1, end_y), xytext=(0, start_y),
arrowprops=dict(arrowstyle="->", color=color, lw=3, shrinkA=6, shrinkB=6))
ax.set_xlim(-0.5, 1.5)
ax.set_ylim(y_lim)
ax.axis('off')
plt.title(f"{gate_name} Gate", fontsize=15, weight='bold', pad=10)
plt.savefig(filename, bbox_inches='tight', dpi=300, transparent=True)
plt.close()
# ==== 執行繪製 ====
# 一維閘保持不變
draw_maze('X', [('0', '1', 'blue'), ('1', '0', 'blue')], False, 'x_maze.png')
draw_maze('Y', [('0', '1', 'gold'), ('1', '0', 'purple')], False, 'y_maze.png')
draw_maze('Z', [('0', '0', 'blue'), ('1', '1', 'red')], False, 'z_maze.png')
draw_maze('H', [('0', '0', 'blue'), ('0', '1', 'blue'), ('1', '0', 'blue'), ('1', '1', 'red')], False, 'h_maze.png')
# 修正:CNOT 閘 (IBM標準,q0控制右位元。01->11, 11->01,其餘不變)
cnot_connections = [('00', '00', 'blue'), ('01', '11', 'blue'), ('10', '10', 'blue'), ('11', '01', 'blue')]
draw_maze('CNOT', cnot_connections, True, 'cnot_maze.png')
# CZ 閘 (由於CZ只作用於 |11>,所以不論哪一種矩陣序,節點連接與對射皆維持不變)
cz_connections = [('00', '00', 'blue'), ('01', '01', 'blue'), ('10', '10', 'blue'), ('11', '11', 'red')]
draw_maze('CZ', cz_connections, True, 'cz_maze.png')
print("IBM 標準迷宮圖片生成完畢!")
可以驗證 ,這讓我想起矩陣對角化
預測量子電路結果的三種方式
給一個量子電路,我們怎麼知道跑出來的結果是什麼呢?我們統一以以下這個量子電路:

他的結果如下:

我們分別用以下三種方法求出答案
矩陣法
把它看成三個部分,第一個部分是對 q0, q1 分別作 H Gate,組合起來就是:
第二部分是對 q0 作 I (也就是什麼都不做)、對 q1 做 Z Gate,組合起來是:
第三部分是一個 CNOT Gate,因為他本來就是二元的 Gate 所以可以直接用。
所以我們可以計算總電路等價於:
在 IBM Composer 上預設每個量子位元初始都是 ,所以結果就會是
這個做法的好處就是我們只要推導一次,之後就算 Init state 變了還是一樣把整體矩陣左乘即可;缺點是計算量大。
向量法
連連看

AI 好讚 生圖的扣的
import matplotlib.pyplot as plt
# 定義迷宮方法顏色常數
COLOR_MAP = {
'blue': '#3498db', # 正實數振幅 (+1)
'red': '#e74c3c', # 負實數振幅 (-1)
}
fig, ax = plt.subplots(figsize=(14, 5))
# 建立 5 個時間點的 X 軸位置 (0 到 4)
x_positions = [0, 1, 2, 3, 4]
labels = ['00', '01', '10', '11']
y_positions = [3, 2, 1, 0] # 由上至下排列
label_to_y = {l: y for l, y in zip(labels, y_positions)}
# 1. 繪製所有的黑點節點
for x in x_positions:
ax.scatter([x] * 4, y_positions, color='black', s=100, zorder=5)
# 2. 僅在「最左邊」與「最右邊」標註狀態標籤
for lbl, y in zip(labels, y_positions):
ax.text(-0.15, y, lbl, ha='right', va='center', fontsize=14, weight='bold')
ax.text(4.15, y, lbl, ha='left', va='center', fontsize=14, weight='bold')
# 3. 定義每個時間段的箭頭映射關係 (start_label, end_label, color)
# Step 1: H_q0 (x=0 -> x=1)
step1 = [('00', '00', 'blue'), ('00', '01', 'blue')]
# Step 2: H_q1 (x=1 -> x=2)
step2 = [('00', '00', 'blue'), ('00', '10', 'blue'),
('01', '01', 'blue'), ('01', '11', 'blue')]
# Step 3: Z_q1 (x=2 -> x=3)
step3 = [('00', '00', 'blue'), ('01', '01', 'blue'),
('10', '10', 'red'), ('11', '11', 'red')]
# Step 4: CNOT (x=3 -> x=4)
step4 = [('00', '00', 'blue'), ('01', '11', 'blue'),
('10', '10', 'red'), ('11', '01', 'red')]
all_steps = [step1, step2, step3, step4]
# 4. 繪製穿梭在節點間的彩色箭頭
for idx, step_connections in enumerate(all_steps):
x_start = x_positions[idx]
x_end = x_positions[idx + 1]
for start_lbl, end_lbl, color_key in step_connections:
sy = label_to_y[start_lbl]
ey = label_to_y[end_lbl]
color = COLOR_MAP[color_key]
ax.annotate('', xy=(x_end, ey), xytext=(x_start, sy),
arrowprops=dict(arrowstyle="->", color=color, lw=3, shrinkA=6, shrinkB=6))
# 5. 在每一段的上方中央對齊標註 Gate Name
gate_names = ["$H_{q_0}$", "$H_{q_1}$", "$Z_{q_1}$", "CNOT"]
for idx, name in enumerate(gate_names):
x_center = (x_positions[idx] + x_positions[idx + 1]) / 2
ax.text(x_center, 3.6, name, ha='center', va='bottom', fontsize=14, weight='bold')
# 微調畫布邊界並關閉座標軸
ax.set_xlim(-0.6, 4.6)
ax.set_ylim(-0.5, 4.0)
ax.axis('off')
plt.tight_layout()
# 匯出成高解析度、透明背景的網頁圖檔
plt.savefig('maze_combined.png', bbox_inches='tight', dpi=300, transparent=True)
plt.close()
print("一體化演進迷宮圖已成功生成:maze_combined.png")
常用的量子態製作
平均疊加態
對每個 qubits 都上 H Gate:
糾纏態:Bell State
| Bell State | Quantum circuit |
|---|---|
![]() |
|
![]() |
|
![]() |
|
![]() |
IBM Quantum Platform
以 .edu 的 Gmail 註冊還可以獲得 10 分鐘的免費實機額度!
documentation/academic-initiative/how-to/How-to-request-and-IBM-Cloud-Feature-Code/readme.md at main · academic-initiative/documentation
量子演算法

Deutsch algorithm
考慮函數 ,這個演算法能用來判斷 是不是常數函數
這個演算法看似很廢(畢竟 也只有 4 種可能),但作為第一個量子演算法是挺重要的。
在古典演算法中需要分別計算 、,看他們是否相同才能知道,但在量子演算法中可以只跑一次就知道答案。
他的線路十分簡單:

圖片來源:Step by step guide to Deutsch’s Algorithm
函數 f 的電路
中間這個 要怎麼設計呢?(也就是要如何把 轉換成量子電路?)
我們以 為例
我們先做出下表:
| 0 0 | 1 | 1 0 |
| 0 1 | 0 | 0 1 |
| 1 0 | 1 | 0 0 |
| 1 1 | 0 | 1 1 |
則我們要設計的 就是滿足
| Input() | Output() |
|---|---|
| 0 0 | 1 0 |
| 0 1 | 0 1 |
| 1 0 | 0 0 |
| 1 1 | 1 1 |
的電路。
經由簡單的通靈就可以發現
總電路和結果如下:


演算法成功關鍵
為何這個演算法能成功?這歸功於
- 疊加態:演算法可以一次性嘗試很多
- 相位:可以發生干涉,把不合的消掉
以上面那個 為例,他的 maze 長這樣:

一樣是 Gemini 寫的生圖扣的
import matplotlib.pyplot as plt
# 定義迷宮方法顏色常數
COLOR_MAP = {
'blue': '#3498db', # 正實數振幅 (+1)
'red': '#e74c3c', # 負實數振幅 (-1)
}
fig, ax = plt.subplots(figsize=(16, 5))
# 建立 7 個時間點的 X 軸位置 (0 到 6)
x_positions = [0, 1, 2, 3, 4, 5, 6]
labels = ['00', '01', '10', '11']
y_positions = [3, 2, 1, 0] # 由上至下排列
label_to_y = {l: y for l, y in zip(labels, y_positions)}
# 1. 繪製所有的黑點節點
for x in x_positions:
ax.scatter([x] * 4, y_positions, color='black', s=100, zorder=5)
# 2. 僅在「最左邊」與「最右邊」標註狀態標籤
for lbl, y in zip(labels, y_positions):
ax.text(-0.15, y, lbl, ha='right', va='center', fontsize=14, weight='bold')
ax.text(6.15, y, lbl, ha='left', va='center', fontsize=14, weight='bold')
# 3. 定義每個時間段的箭頭映射關係 (根據量子閘矩陣運算)
# Step 1: X_q1 (0 -> 1) -> 翻轉左位元
step1 = [('00', '10', 'blue')]
# Step 2: H_q1 H_q0 (1 -> 2) -> 從 10 點分岔出四個狀態,後兩個帶負號(紅)
step2 = [
('10', '00', 'blue'), ('10', '01', 'blue'),
('10', '10', 'red'), ('10', '11', 'red')
]
# Step 3: X_q0 (2 -> 3) -> 翻轉右位元 (00<->01, 10<->11)
step3 = [
('00', '01', 'blue'), ('01', '00', 'blue'),
('10', '11', 'red'), ('11', '10', 'red')
]
# Step 4: CNOT (3 -> 4) -> q0控制q1 (右位元為1時,左位元翻轉)
step4 = [
('00', '00', 'blue'), ('01', '11', 'blue'),
('10', '10', 'red'), ('11', '01', 'red')
]
# Step 5: X_q0 (4 -> 5) -> 再次翻轉右位元
step5 = [
('00', '01', 'blue'), ('11', '10', 'blue'),
('10', '11', 'red'), ('01', '00', 'red')
]
# Step 6: H_q0 (5 -> 6) -> Hadamard 作用在右位元,展開並引入對應相位
step6 = [
('00', '00', 'red'), ('00', '01', 'red'),
('01', '00', 'blue'), ('01', '01', 'red'),
('10', '10', 'blue'), ('10', '11', 'blue'),
('11', '10', 'red'), ('11', '11', 'blue')
]
all_steps = [step1, step2, step3, step4, step5, step6]
# 4. 繪製彩色方向箭頭
for idx, step_connections in enumerate(all_steps):
x_start = x_positions[idx]
x_end = x_positions[idx + 1]
for start_lbl, end_lbl, color_key in step_connections:
sy = label_to_y[start_lbl]
ey = label_to_y[end_lbl]
color = COLOR_MAP[color_key]
ax.annotate('', xy=(x_end, ey), xytext=(x_start, sy),
arrowprops=dict(arrowstyle="->", color=color, lw=3, shrinkA=6, shrinkB=6))
# 5. 在每一段上方中央標註 Gate Name (對應你的 OpenQASM 順序)
gate_names = ["$X_{q_1}$", "$H_{q_1}H_{q_0}$", "$X_{q_0}$", "CNOT", "$X_{q_0}$", "$H_{q_0}$"]
for idx, name in enumerate(gate_names):
x_center = (x_positions[idx] + x_positions[idx + 1]) / 2
ax.text(x_center, 3.6, name, ha='center', va='bottom', fontsize=14, weight='bold')
# 微調畫布邊界並關閉座標軸
ax.set_xlim(-0.6, 6.6)
ax.set_ylim(-0.5, 4.0)
ax.axis('off')
plt.tight_layout()
# 儲存圖片
plt.savefig('maze.png', bbox_inches='tight', dpi=300, transparent=True)
plt.close()
print("新電路的串聯迷宮演進圖已成功生成:maze.png")
可以看到在跑完 之後分散成了四條線,對應到第 1 點。
而在最後可以看到紅色跟藍色的線碰在一起發生破壞性干涉消掉,對應到第 2 點。
Deutsch–Jozsa algorithm
這是上面那個演算法的加強版,從 1 個 bytes 推廣成 n 個 bytes。
印象中上課時就簡單帶過,書裡有詳細寫但我現在還懶得看XD
所以就放一張上課拍的簡報草草了事w
這個在古典中用最爛的演算法需要計算 次 ,比較 次;但用這個量子演算法只要計算 1 次,比較 次!
如何設計 f(x) 的線路
和之前一樣的問題,一樣放上課拍的黑板草草了事w
反正就是拆項看,然後用 Gate。

Grover algorithm
這是一個量子無序搜尋演算法,比古典好,古典需要 ,這個只要 ( 是資料數量)
這個演算法的原理是先創造平均量子態,然後重複若干次以下由 Oracle 和 Diffusion Operator 組合而成的 運算子:
- Oracle(神諭):把要找的項標記──加負號(把相位轉 180 度)
- Diffusion Operator:把目前狀態對平均量子態做對稱,這會讓目標的振幅變大,其他變小。
我們要跑適當輪數的 讓 State vector 旋轉到與目標狀態重合(與非目標狀態夾角接近 ),然後執行測量。
這個的幾何圖形可以上網查到
2 個 qubits
我們先從最簡單的 2 個 qubits 開始。將要找的資料以 00, 01, 10, 11 編號。
有兩種實現方式,第一種需要引進額外的一個輔助位元,第二種則不用,我們先依序來看
方法1:需要輔助位元
流程如下:

而具體線路會長這樣:

方法2:不需要輔助位元

以上是搜尋 11 的,如果今天是要搜尋 00, 01 或 10 呢?
我們只會搜尋 11,所以方法就是將我們的目標先「偽裝」成 11 再還原回來
所以我們要對 Oracle 進行修改(因為 Oracle 是拿來標記目標的),如以下(應該不難理解):

3 個 qubits
和前面類似,所以我就直接把搜尋 111 的兩種方式的線路跟結果放上來
方法1


方法2


放個實機跑的結果:
這裡說一下 CZ Gate 變成了什麼。他其實應該對應的被換成 CCZ Gate,但因為系統上沒 CCZ Gate 可以用所以我們借助之前提到的 來達到等價的效果。
其實 Grover 演算法可以一次找不只一個目標,那就是要去設計對應的 Oracle 了
複雜度分析
假設重複迭代了 次,此時量子態為
我們目標是讓操作完的量子態接近 y 軸,即
當資料量 很大時, 會很小,因此
故可得
Shor algorithm
好可惜喔這上課沒講,改天來研究看看,但我可能要先去把傅立葉轉換那 part 補起來XD。
量子通訊
Superdense coding
可以用一個量子位元傳遞兩個古典位元的資訊。ㄟ而且這已經被實驗驗證了。

用一個例子來示範就好,其他可以自己試。比如 Alice 今天要傳「01」
第一個 bit 是 1,所以他要執行 Z,第二個 bit 是 0,所以什麼事都不用做。
這樣 Alice 做完會是
Bob 接著反過來操作:
對吧!最後得到的 01 就是 Alice 一開始要傳的訊息啊!
Quantum teleportation
用量子糾纏來傳訊息,如下圖,A、B 是糾纏的一對粒子,我們把粒子 B 留在 Bob 手上,粒子 A 讓 Alice 帶出去。假設今天 Alice 想傳送資訊 給 Bob,即下圖中的粒子 D。Alice 可以藉由對 A 和 D 進行一些測量、操作,把結果藉由古典通道傳回給 Bob,Bob 就能回推出 !就如圖中的把 B 變成 D!
以下是具體步驟

圖片來源:Simulating Quantum Teleportation - Marek Narozniak’s Homepage
一開始的 H Gate 和 CNOT Gate 是拿來創造 Bell State 的。上圖中第一列是 ,也就是我們想傳遞的粒子 D 的資訊;第二列是 A,第三列是 B。所以
做一個 CNOT Gate
做一個 H Gate
接著 Alice 對 D 和 A 進行測量 (也就是圖中第一列、第二列的 qubit),然後把它回傳。
從 可以發現只要確定 D 和 A,那麼就能確定 B 的狀態,進而對他進行 NOT 或 Z Gate 把他轉換成
舉例來說,如果 Alice 量到 D 跟 A 都是 1,代表 B 一定是
那我們對他做 X Gate 再做 Z Gate,他就會變成
其他三種情形也可簡易驗證。
這裡的操作其實和前面的 Superdense coding 很像,都是 CNOT 跟 CZ 在操作
常見問題:這有違反「不可複製原理」嗎?
答:沒有,複製是我有一個原本的東西,然後又有一個複製出來的東西。這裡因為測量已經破壞掉原本那顆了,所以不算。
QKD - BB84
BB84 只是其中一種 QKD 協議,似乎還有 B92、E91 之類的東西
這個協議不但能安全的約定出一次性密碼,還可以偵測出有沒有監聽者!
我想偷懶,所以我查到這篇文寫的還不錯所以就看他吧XD
量子加密技術極簡介 (QKD-Quantum Key Distribution)
這裡要補充的只有他們可以拿部分的 bits 來抓監聽者,剩下的再當 key,因為抓監聽者需要交換 Alice 和 Bob 各自算出的 Key,有洩漏 key 的風險。比如他們發 1000 個 bits,平均而言應該會有 500 個是可用的,他們就能約定好拿前 100 個用來抓有沒有監聽者,剩下的 400 個才當 key。大概是這樣的概念:)
其他
萬物怎麼來

是說,「道元」是什麼?那是教授對 Token 的翻譯。他說他想了三天三夜,突然想到「象形文字」是基本單元,所以想翻譯成「象元」,然後一查發現這個詞只被用在老子象元篇。再想一想覺得「道元」比較好。
量子相關活動
| 活動 | 大約的時間 |
|---|---|
| TAQCIT 年會 | 八月 |
| 高中量子計算暑期營 | 七月 |
| 高中種子教師培訓 | 七或八月 |
| 量子黑客松 | 八月 |
| Semicon Taiwan | 九月 |
| QRACON 學生量子電腦年會 | 今年在十二月 |
能量、資訊、物質
能量、物質能互通;能量、資訊能互通,那物質跟資訊呢?

我懶得再重新製圖XD
後記
參加這個課程受益良多啊,其中一點是讓我找回念物理跟數學的熱忱XD
值得注意的是許多教授在講課時都能感受到他們對這些東西的熱情,也上的很活潑生動,一直亂 cue 人
我除了下課跑去找教授練肖維(笑死某個教授一直洗腦(?催眠(?說服(?大家去念物理系w),還認識了兩個附中高二的新朋友每天放學聊天!
btw 午休 2 小時真的好爽啊XD 星期五我無聊繞進次震宇宙館,感覺還是像之前一樣震撼:D















