
Day2 說明了如何從振幅算出量測機率。例如,狀態 [0.6, 0.8]ᵀ 量到 0 的機率是 36%,量到 1 的機率是 64%。今天往前走一步:如果想改變這兩個機率,應該對狀態做什麼?
一個簡單的操作,是把兩個振幅交換,變成 [0.8, 0.6]ᵀ。另一個操作可能只改變正負號,當下的機率不變,卻影響後續計算。還有一類操作帶著可調整的角度,讓輸出隨角度連續變化,成為後續模型學習的元件。
這些改變狀態的基本操作稱為量子閘,依序串接就形成量子電路。本章先用具體數值理解操作,再把規則寫成矩陣與 Python 程式,最後用保存的角度掃描結果核對推導。範圍限定為單一量子位元的理想運算;本日執行的是一般電腦上的數值模擬。
Day2 explained how amplitudes determine measurement probabilities. Day3 examines how quantum gates change those amplitudes. Worked examples lead from swapping components and changing relative phase to adjustable rotations, matrix calculations, and Python implementations. A fifteen-point rotation experiment checks theoretical predictions and shows why identical probabilities in one measurement basis do not imply identical states or gates.
先沿用 [0.6, 0.8]ᵀ。這是兩個振幅依序對應 0 與 1 的狀態向量;ᵀ 表示把橫向排列改成直向排列。要把它們交換,可以使用這張兩列、兩欄的數值表:
X = [0 1]
[1 0]
這張表稱為矩陣。它的第一列決定第一個新振幅,第二列決定第二個新振幅。計算時,把該列數字與輸入的對應分量相乘,再相加:
第一個新振幅 = 0 × 0.6 + 1 × 0.8 = 0.8
第二個新振幅 = 1 × 0.6 + 0 × 0.8 = 0.6
輸出狀態:[0.8, 0.6]ᵀ
輸出機率:[0.64, 0.36]
這就是矩陣乘上向量。注意運算順序:先改變振幅,再取絕對值平方算機率。X 恰好只是交換分量,因此看起來像直接交換機率也行;遇到會讓振幅相加或抵消的閘,就不能省略振幅這一層。
把數字換成變數後,規則仍然相同:
U = [a b] 輸入 = [α]
[c d] [β]
第一個新振幅 = aα + bβ
第二個新振幅 = cα + dβ
論文會把整段計算簡寫為 |ψ′⟩ = U|ψ⟩:|ψ⟩ 是輸入狀態,U 是操作矩陣,|ψ′⟩ 是輸出,右上角的小撇號表示「改變後」。單一量子位元有兩個振幅,所以本章使用 2 × 2 矩陣。
上一節的矩陣就是 X 閘。它作用在最基本的兩個狀態時:
|0⟩ = [1, 0]ᵀ → X → [0, 1]ᵀ = |1⟩
|1⟩ = [0, 1]ᵀ → X → [1, 0]ᵀ = |0⟩
因此,X 在這兩個輸入上很像一般電腦的 NOT 操作:0 變 1,1 變 0。但它也能作用在疊加態上,完整規則是將 [α, β]ᵀ 變成 [β, α]ᵀ。
再做一次 X,就會交換回來:
[0.6, 0.8]ᵀ → X → [0.8, 0.6]ᵀ → X → [0.6, 0.8]ᵀ
這是一個可以還原的操作。量子閘並不會每次都改變機率,例如對兩個分量相等的 |+⟩ = [1/√2, 1/√2]ᵀ 做 X,交換後仍是同一個向量。描述一個閘的效果時,要一併交代輸入。
Day2 使用的 Hadamard 閘,簡記 H,寫成矩陣是:
H = (1/√2) × [1 1]
[1 −1]
依照第 1 節的乘法規則:
第一個新振幅 = (α + β) / √2
第二個新振幅 = (α − β) / √2
對 |0⟩ = [1, 0]ᵀ 而言,兩個新振幅都是 1/√2,所以得到 |+⟩,直接量測時 0、1 各有一半機率。若再做一次 H,第一項相加成 1,第二項抵消成 0,就回到 |0⟩。
H 的狀態轉換本身是確定的。只有在量測時,才會依輸出狀態的機率產生結果。如果把 H 理解成「隨機選一個答案」,就無法解釋為什麼連做兩次會回到原本狀態。以下流程假設兩個 H 中間沒有量測或干擾:
|0⟩ → H → |+⟩ → H → |0⟩ → 量測必定得到 0
Z 的規則更短:保留第一項,將第二項乘上 −1。
Z = [1 0] [α, β]ᵀ → [α, −β]ᵀ
[0 −1]
對 |0⟩ 做 Z,向量不變;對 |1⟩ 做 Z,得到 −|1⟩,只差整體相位,仍代表同一個物理純態。但對 |+⟩ 而言,只改第二項的符號,會得到另一個狀態:
|+⟩ = [1/√2, 1/√2]ᵀ → Z → [1/√2, −1/√2]ᵀ = |−⟩
兩項之間的方向差稱為相對相位。直接量測 0/1 時,正負號在絕對值平方中消失,因此仍是各一半;接上 H 之後,卻會得到 |1⟩:
流程 A:|0⟩ → H → |+⟩ → H → |0⟩ → 得到 0
流程 B:|0⟩ → H → |+⟩ → Z → |−⟩ → H → |1⟩ → 得到 1
兩條流程在最後一個 H 之前,直接量測的機率相同。最後的 H 讓不同相對相位造成的相加、抵消變成不同答案,這就是干涉的具體計算。
流程 B 寫成公式是 HZH|0⟩,最靠近狀態的操作先執行,所以從右往左讀:先 H,再 Z,再 H。程式可以依執行時間逐行寫,減少讀反的機會。
操作順序不能任意交換。例如,先 Z 再 H,|0⟩ 會變成 |+⟩;先 H 再 Z,則變成 |−⟩。它們直接量測都是各一半,但再接一個 H 就能區分。只比較最後一份 0/1 機率表,可能看不出電路排列上的差異。
假設把兩個振幅都放大兩倍:
[0.6, 0.8]ᵀ → [1.2, 1.6]ᵀ
機率總和 = 1.2² + 1.6² = 4
這不符合機率總和為 1 的條件。對本章理想、沒有外界干擾的量子演化,操作必須保持狀態向量的長度,不能任意放大或壓縮。
符合這項要求的方形矩陣稱為么正矩陣(unitary matrix,也稱酉矩陣)。它的標準檢查式是:
U†U = UU† = I
可以先把它讀成:「做完 U,再做它的反向操作,等於什麼都沒改。」I 是單位矩陣,會保留輸入;U† 是 U 的共軛轉置,也就是先交換列與欄,再把複數的虛部反號。對么正矩陣,這個矩陣恰好就是反向操作。
以 X 為例,交換兩次回到原狀,所以 X² = I。H 也有 H² = I。但不是每個閘的反向操作都等於自己,後面旋轉閘的反向操作通常要把角度改成負值。
Day2 用 ⟨ψ|ψ⟩ 表示振幅絕對值平方的總和,也就是向量長度平方。把輸出 U|ψ⟩ 代入,就得到:
輸出長度平方 = ⟨ψ|U†U|ψ⟩
= ⟨ψ|I|ψ⟩
= ⟨ψ|ψ⟩ = 1
中間一步只用了 U†U = I。更一般地,這類操作也保持不同向量之間的內積,也就是它們的重疊關係。
這個條件要對所有合法輸入成立。只測一個輸入的長度沒有變,還不足以證明整張矩陣么正。程式因此會直接檢查 U†U,再另外檢查輸入狀態。
量測、重設狀態,以及描述雜訊的操作,不能全部套進這種「同一系統上可反轉的矩陣乘法」。這裡先建立理想量子閘的規則,後續再處理那些情況。
X、Y、Z 合稱 Pauli 閘,名稱來自物理學家 Pauli。已經看過 X 的交換與 Z 的反號,Y 則把交換與複數相位放在一起:
Y = [0 −i] [α, β]ᵀ → [−iβ, iα]ᵀ
[i 0]
i 是滿足 i² = −1 的虛數單位。依規則代入:
Y|0⟩ = i|1⟩
Y|1⟩ = −i|0⟩
對輸入 |0⟩ 而言,X 得到 |1⟩,Y 得到 i|1⟩,兩者只差整體相位,代表同一個物理純態。這仍不能說明 X 與 Y 是同一個操作,因為它們對其他輸入可能不同。
例如,X 保留 |+⟩,而 Y 得到 −i|−⟩。忽略不影響物理預測的整體相位後,後者是 |−⟩;再做 H 就能與前者區分。判斷兩個操作是否等效,需要考慮它們對其他輸入的作用。
前面的閘像是固定指令。若希望模型能調整輸出,就需要帶有參數的操作。旋轉閘使用角度 θ(theta)作為可調數值;在 Day2 的布洛赫球表示中,RX、RY、RZ 分別對應繞 x、y、z 軸的旋轉。
RY(θ) = [cos(θ/2) −sin(θ/2)]
[sin(θ/2) cos(θ/2)]
sin 與 cos 是三角函數。角度以弧度表示:π 是半圈,2π 是一圈,π/2 是四分之一圈。程式的 np.pi 代表 π,不能直接把 90 當成 90 度傳入。
對 |0⟩ = [1, 0]ᵀ 做矩陣乘法,只會留下矩陣的第一欄:
RY(θ)|0⟩ = [cos(θ/2), sin(θ/2)]ᵀ
P(0) = cos²(θ/2)
P(1) = sin²(θ/2)
這已經是一條從角度到輸出分數的明確規則:
| 角度 θ | 代入的半角 θ/2 | 量到 1 的機率 |
|---|---|---|
| 0 | 0 | 0 |
| π/2 | π/4 | 0.5 |
| π | π/2 | 1 |
半角不能省略。布洛赫球上旋轉半圈的 RY(π),在振幅公式裡代入的是 π/2,因此把 |0⟩ 轉成 |1⟩。這個寫法也讓振幅的絕對值平方,與 Day2 的球面位置及量測機率一致。
令 c = cos(θ/2)、s = sin(θ/2),RX 可以寫成:
RX(θ) = [ c −is]
[−is c ]
RX(θ)|0⟩ = [c, −is]ᵀ
它量到 1 的機率也是 s²,因為 −i 的絕對值是 1。但 RY(π/2)|0⟩ 的振幅是 [1/√2, 1/√2]ᵀ,RX 的則是 [1/√2, −i/√2]ᵀ,兩項之間的相位不同。
如果各自再做 H,RY 的結果必定量到 0,RX 的結果仍是各一半。這提供一個具體方式,檢查「同樣機率」背後是否有不同狀態。
RZ(θ) = [e^(−iθ/2) 0 ]
[ 0 e^(iθ/2) ]
e^(iφ) = cosφ + i sinφ 是長度為 1、方向角為 φ 的複數。RZ 對第一個振幅乘上往一側轉的相位,對第二個振幅乘上往另一側轉的相位。
如果輸入是 |0⟩,第二項原本就是 0,結果只有 e^(−iθ/2)|0⟩,屬於整體相位。因此無論改多少角度,直接量到 1 的機率都還是 0。
若輸入換成 |+⟩,兩項都不為零,就會改變相對相位。再接一個 H,便得到:
|0⟩ → H → RZ(θ) → H → 量測
P(1) = sin²(θ/2)
例如 θ 從 0 改成 π,最後量到 1 的機率便從 0 變成 1。這項結果來自上述矩陣的推導,並非下節保存的 RZ 掃描資料;保存實驗的輸入是 |0⟩,沒有前後兩個 H。
三種旋轉閘可統一寫成:
RX(θ) = cos(θ/2)I − i sin(θ/2)X
RY(θ) = cos(θ/2)I − i sin(θ/2)Y
RZ(θ) = cos(θ/2)I − i sin(θ/2)Z
程式正是用這個形式建立矩陣。論文也常用 exp(−iθX/2) 等形式表示同一件事;這裡的 exp 是矩陣指數,不能解讀成對每個矩陣元素各自取指數。
在相同旋轉軸上,角度 θ 的反向操作是 −θ。當 θ = π 時,RX、RY、RZ 分別等於 −iX、−iY、−iZ,和對應 Pauli 閘只差整體相位。
本章用 NumPy,也就是 Python 的數值運算套件,直接保存矩陣與狀態。最小範例可以獨立執行:
import numpy as np
state = np.array([0.6, 0.8], dtype=complex)
x_gate = np.array([[0, 1], [1, 0]], dtype=complex)
output = x_gate @ state
print("output =", output)
print("probabilities =", np.abs(output) ** 2)
預期輸出:
output = [0.8+0.j 0.6+0.j]
probabilities = [0.64 0.36]
dtype=complex 讓陣列可以保存複數,@ 是矩陣乘法。* 在 NumPy 陣列上通常是逐元素相乘,不能用來替代這裡的 @。輸出中的 0.j 表示虛部是 0,並不是額外的量測結果。
專案版本在 quantum_gates.py,除了定義矩陣,也會檢查閘是否為 2 × 2、狀態是否有兩個分量、矩陣是否么正,以及狀態是否已正規化。它使用 complex128 保存複數,其中實部與虛部各使用 64 位元。
程式的 matrix.conj().T 對應 U†:.conj() 取複共軛,.T 交換列與欄。只寫 .T 可能讓純實數範例通過,卻在含有複數的 Y 或 RX 上出錯。
電腦以有限位數表示小數,因此檢查 U†U 是否等於 I 時,會使用允許微小誤差的比較,這個允許範圍稱為容差。例如 0.4999999999999999 與 0.5 的差異可能只是數值精度,不能直接當作物理效應。
若尚未建立本專案環境,可在專案根目錄使用以下 Linux/Ubuntu 指令:
python3.12 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements-day03.txt
.venv 是分開保存專案套件的虛擬環境。已建好環境時,只需啟用它,再執行範例。本日固定使用 NumPy 2.2.6,版本清單見 requirements-day03.txt,設備與環境背景見 ENVIRONMENT.md。
python articles/day03/demo.py
demo.py 的輸出為:
X|0> P(0)=0.000000 P(1)=1.000000
H|0> P(0)=0.500000 P(1)=0.500000
HH|0> P(0)=1.000000 P(1)=0.000000
HZH|0> P(0)=0.000000 P(1)=1.000000
RY(pi/2)|0> P(0)=0.500000 P(1)=0.500000
每一列都可以回到前面的公式核對。這些是從向量直接算出的機率,沒有進行有限次量測抽樣,也沒有使用 GPU 或真實量子處理器。
本日保存的實驗問題是:對相同輸入 |0⟩,分別調整 RX、RY、RZ 的角度,輸出機率與狀態會如何變化?
為了能歸因於閘與角度的差異,其他條件保持一致:
| 項目 | 設定與用途 |
|---|---|
| 輸入 | 每筆都從 |0⟩ 開始,不沿用上一筆輸出 |
| 操作 | 每筆只施加一個 RX、RY 或 RZ |
| 角度 | 0、π/4、π/2、3π/4、π,共五種 |
| 計算方式 | NumPy 在 CPU 上直接計算完整狀態向量 |
| 記錄 | 0/1 機率、X/Y/Z 期望值、向量長度平方 |
| 抽樣 | 沒有有限 shots,也不需要隨機種子 |
三種閘各五個角度,共得到 15 筆紀錄。這叫作掃描:按預先指定的設定逐一觀察輸出。程式尚未根據資料的正確答案來選角度,所以還不是訓練。
只看 0/1 機率,無法區分剛才的 RX 與 RY 輸出。為了補上相位資訊,實驗也計算三種量測方向的平均值,稱為 X、Y、Z 的期望值。它們正好對應單一量子位元布洛赫球的三個座標。
Day2 已用過 Z 的計算方式:把量到 0 記為 +1、量到 1 記為 −1,平均就是 P(0) − P(1)。X 與 Y 則對應其他量測方向,而不是對同一份 0/1 計數換個欄位名稱。
在本章的向量表示中,計算公式是:
⟨O⟩ = ⟨ψ|O|ψ⟩
O 是用矩陣表示的量測量,稱為可觀測量;X、Y、Z 都可放在這個位置。讀法是先計算 O|ψ⟩,再與原本的 |ψ⟩ 取內積。作為可觀測量的矩陣要等於自己的共軛轉置,稱為厄米矩陣,這能保證期望值是實數。
同一個 X 矩陣可以用來描述「施加 X 閘」,也可以用來定義「計算 X 的期望值」,但兩者是不同工作:前者更新狀態,後者從狀態算出一個平均數。程式以 apply_gate 與 expectation 分別處理。
模擬器能直接利用完整向量算出三項數值。若改用硬體,通常要重新準備狀態、使用不同量測設定並累積統計,不能以為一筆 0/1 結果就同時提供了三個座標。
python articles/day03/experiment.py
python -m unittest discover -s articles/day03 -p 'test_*.py' -v
experiment.py 會更新 gate_sweep.csv 與 summary.json。CSV 按列保存每個角度的結果,JSON 摘要保存 Python、NumPy、作業系統與執行後端等條件。這裡的後端是實際負責數值計算的 numpy-cpu。
CSV 的 norm 欄位實際保存的是向量長度的平方,已正規化時應接近 1。摘要的 max_norm_error 則是這個數值與 1 之間的最大差距。讀結果時,要對照欄位的計算方式,不能只依名稱猜測。
以下從保存的 15 筆資料整理,機率四捨五入到小數點後六位:
| 角度 θ | RX 的 P(1) | RY 的 P(1) | RZ 的 P(1) |
|---|---|---|---|
| 0 | 0.000000 | 0.000000 | 0.000000 |
| π/4 | 0.146447 | 0.146447 | 0.000000 |
| π/2 | 0.500000 | 0.500000 | 0.000000 |
| 3π/4 | 0.853553 | 0.853553 | 0.000000 |
| π | 1.000000 | 1.000000 | 0.000000 |
RX 與 RY 符合前面的 sin²(θ/2) 推導;RZ 的 P(1) 則保持 0。但換看角度 π/2 的三個期望值,就能看到狀態差異:
操作,輸入皆為 |0⟩ |
X 期望值 | Y 期望值 | Z 期望值 |
|---|---|---|---|
| RX(π/2) | 0 | −1 | 約 0 |
| RY(π/2) | 1 | 0 | 約 0 |
| RZ(π/2) | 0 | 0 | 1 |
RX 與 RY 都把狀態移到赤道,直接量測各有一半機率;但它們位於赤道上不同方向。這解釋了為什麼相同的 Z 機率,仍可能對後續操作產生不同反應。
保存摘要的環境是 Python 3.12.7、NumPy 2.2.6、Linux x86_64。2026-09-11 重新核對時,示範程式與 7 項既有測試均通過,重新計算的 15 筆掃描資料也與保存數值在容差內一致。測試涵蓋閘的么正性、部分基底作用、H 的反向性、旋轉端點、相位干涉,以及拒絕非么正矩陣。
這些證據支持的是:本日程式在已檢查條件下,與指定的矩陣定義及理論預測一致。它們沒有測試分類品質、訓練速度或真實量子硬體表現。
若用量到 1 的機率當作預測分數,RY(θ)|0⟩ 已提供一個可調函數:
分數 = sin²(θ/2)
下一步可以讓一般電腦比較分數與正確答案,再選擇新的 θ。這種帶有可調參數的電路稱為參數化量子電路。Mitarai 等人的研究提出以一般電腦反覆調整電路參數,讓量子電路參與學習的流程。Quantum circuit learning
不過,只對所有花使用同一個 RY(θ)|0⟩,每朵花都會得到相同分數,還不能根據尺寸分類。後續必須讓輸入資料進入電路,並區分「由資料決定的角度」與「由訓練調整的參數」。
另一個問題是,有參數也不保證它會影響目前讀取的輸出。本日 RZ(θ)|0⟩ 的 P(1) 對所有角度都是 0。若模型只有這段電路,而誤差只依這個機率計算,調整 θ 就無法改善預測。這個失效原因能直接從電路結構看出,不需要先怪罪負責更新參數的最佳化器。
更有用的實驗問題因此是:
在輸入與其他操作固定時,改變這個參數,會不會改變模型實際使用的輸出?若不會,是輸入狀態、操作順序,還是量測方式讓差異看不見?
前面的 H → RZ(θ) → H 提供一個可計算的對照。它展示了如何改變流程,使相對相位對輸出產生影響;是否因此形成好的分類模型,仍需要資料與訓練實驗。
一般神經網路也是把多段計算串起來,但每一段不必可反轉。例如 ReLU 會保留正數、把負數變成 0;−1 與 −2 都變成 0,無法單靠輸出還原輸入。本章的理想量子閘則保持長度與內積,而且有反向操作。
矩陣乘法對狀態向量是線性的:先把兩個向量加起來再操作,等於分別操作後再相加。但整個模型從資料到預測,還包含資料轉換與機率計算。像 sin²(θ/2) 這種角度與分數的關係就不是直線,因此不能從「量子閘是線性操作」推論「模型只能表示線性關係」。
| 觀察到的情況 | 先核對什麼? |
|---|---|
| 機率總和偏離 1 | 輸入是否正規化,矩陣是否么正,是否誤用逐元素乘法 |
| 90 度的結果不符合預期 | 程式是否用了弧度 π/2,矩陣是否使用半角 |
| 純實數閘正常,複數閘的檢查失敗 | 是否把共軛轉置寫成只有轉置 |
RX(π) 輸出 −i|1⟩ |
與 |1⟩ 只差整體相位,需按物理狀態比較 |
| RZ 改了角度,輸出卻不變 | 輸入是否為 |0⟩,後續操作與量測是否能顯示相位差 |
| 理論上為 0,程式卻有極小數值 | 差異是否在浮點容差內,先看數值尺度 |
本日的實驗紀錄應把輸入、操作順序、角度、讀取方式與計算環境連在一起。這樣即使某個輸出沒有變化,也能說明原因,並設計下一個能區分假設的對照,而不只是列出「程式成功執行」。
[N3] Seungcheol Oh et al. “Fourier Analysis Perspective on Quantum Neural Networks.” Communications Physics 9, 176 (2026);觀點論文。原始來源;完整書目。
本章的旋轉閘可銜接輸入與輸出之間的振盪關係;頻率表示輸入改變時,輸出起伏的快慢。
今天的閘都只處理一個量子位元。下一篇會把兩個量子位元放在一起,從四種可能的 0/1 組合開始,說明如何讓其中一個位元控制另一個的操作,再觀察兩者之間無法用各自獨立狀態完整描述的關係。