林尚廷
No Code No Life :: A competitive programmer
說說看你們對量子運算的看法吧!
優質影片欣賞
首先量子運算要有量子電腦
量子電腦比較快嗎?
如果是,那量子電腦為什麼比較快?
那我們為什麼需要量子電腦?
有什麼開發量子電腦的當務之急?
它的原理是什麼?
我們要怎麼編寫量子電腦程式?
量子位元
同時是0也是1 (????)
光偏振:電場振動方向
測量:光束通過偏振片
一個光子通過偏振片 (?)
量子位元
垂直偏振
水平偏振
斜向偏振
量子電腦可以促進以下領域的發展:
經典位元 (binary digit, bit):一個0或1
量子位元 (quantum bit, qubit):
0或1,或0和1的疊加態
\(|\psi \rangle =\alpha |0\rangle +\beta |1\rangle \quad \alpha ,\beta \in {\mathbb {C}}\)
其中\(|\alpha| ^ 2\)是測量它之後觀測到\(0\)的機率;\(|\beta| ^ 2\)是測量它之後觀測到\(1\)的機率,所以
\(|\alpha| ^ 2 + |\beta| ^ 2 = 1\)
一個量子位元也可以表示成一個向量:
$$\begin{bmatrix} \alpha\\ \beta \end{bmatrix}$$
\(|\alpha| ^ 2\)是測量它之後觀測到\(0\)的機率;
\(|\beta| ^ 2\)是測量它之後觀測到\(1\)的機率
量子位元也可以表示0或1:
$$|0\rangle = \begin{bmatrix} 1\\ 0 \end{bmatrix}, |1\rangle = \begin{bmatrix} 0\\ 1 \end{bmatrix}$$
所以它理論上可以做到任何經典運算能做的事
例如加減乘除
或許你覺得矩陣很複雜:
但我覺得這其實更複雜 QQ
不同於經典位元,量子位元可以這樣
$$|+\rangle = \begin{bmatrix} \frac{1}{\sqrt 2}\\ \frac{1}{\sqrt 2} \end{bmatrix}$$
$$|-\rangle = \begin{bmatrix} \frac{1}{\sqrt 2}\\ \frac{-1}{\sqrt 2} \end{bmatrix}$$
兩個量子位元有時可以纏結在一起
為了表示兩個量子位元纏結
我們必須引進雙量子系統
如果其中一個量子是\(|\psi \rangle\),另一個量子是 \(|\delta \rangle\) 那麼兩個量子寫在一起就是 \(|\psi\rangle\otimes|\delta\rangle\)
比如說其中一個量子是\(|+ \rangle\),另一個量子是 \(|0 \rangle\) 那麼兩個量子寫在一起就是 \(|+\rangle\otimes|0 \rangle = |+0\rangle\)
有時候雙量子的量子態無法拆成兩個獨立的量子態
就稱為量子纏結
兩個量子位元纏結之後無法用bloch sphere表示
只能用 qsphere 同時表示兩個位元
量子運算也有NOT閘,叫做 Pauli X gate,用途就是把0變成1,反之亦然
\(\begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix} \begin{bmatrix} 1 \\ 0 \end{bmatrix} = \begin{bmatrix} 0 \\ 1 \end{bmatrix}\)
它的作用很像沿 X 軸轉 180 度
\(\begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix} \begin{bmatrix} 1 \\ 0 \end{bmatrix} = \begin{bmatrix} 0 \\ 1 \end{bmatrix}\)
達到這種奇怪狀態的方法是 \(H\) 閘,右邊那種狀態叫做疊加態
$$\frac{1}{\sqrt 2} \begin{bmatrix}1 & 1 \\ 1 & -1 \end{bmatrix} \begin{bmatrix} 1 \\ 0 \end{bmatrix} = \begin{bmatrix} \frac{1}{\sqrt 2} \\ \frac{1}{\sqrt 2}\end{bmatrix}$$
它就是沿 \(X=Z\) 軸轉 180 度
$$\frac{1}{\sqrt 2} \begin{bmatrix}1 & 1 \\ 1 & -1 \end{bmatrix} \begin{bmatrix} 1 \\ 0 \end{bmatrix} = \begin{bmatrix} \frac{1}{\sqrt 2} \\ \frac{1}{\sqrt 2}\end{bmatrix}$$
cnot gate 是雙量子位元邏輯閘
它的作用是:
如果一個特定 bit 是1,則會反轉\((X)\)另一個 bit
所以如果這個特定 bit 是疊加態,另一個 bit 會與之纏結
我知道很難想像 QAQ 所以來做例題吧
我們假設所有 qubit 的初始狀態都是 \(|0\rangle\)
嘗試對這些 qubit 使用\(X, H, CNOT\)使它們變成指定狀態
最簡單的纏結可以經由疊加態產生
首先將其中一個 bit 變成疊加態
然後再把兩個 bit 丟進 cnot gate
cnot gate 的作用是:
如果一個特定 bit 是1,則會反轉另一個 bit
所以如果這個特定 bit 是疊加態,另一個 bit 只能跟它纏結在一起了
$$\begin{bmatrix}1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \end{bmatrix} \begin{bmatrix} \frac{1}{\sqrt 2} \\ 0\\ \frac{1}{\sqrt 2} \\ 0 \end{bmatrix} = \begin{bmatrix} \frac{1}{\sqrt 2} \\ 0 \\ 0 \\ \frac{1}{\sqrt 2}\end{bmatrix}$$
Python is powerful... and fast;
plays well with others;
runs everywhere;
is friendly & easy to learn;
is Open.
線上Python整合開發環境
提供免費GPU
多樣的套件
簡單, 快速且
免費
!pip install qiskit
from qiskit import *
from qiskit.visualization import *
from qiskit.tools import job_monitor
# 2 量子位元 (qubits) / 2 經典位元 (classical bits)
circuit = QuantumCircuit(2, 2)
# 將qubit通過hadamard閘
circuit.h(0)
# CNOT, Controlled NOT.
# 如果第一個qubit是1,則將第二個qubit翻轉 (flip)
circuit.cx(0, 1)
# 測量qubit的值到對應的經典位元
circuit.measure([0, 1], [0, 1])
circuit.draw() # ASCII ART!!!!!!
circuit.draw(output='mpl') # use matplotlib
登入並取得 Token
登入並取得 Token
# please paste your token here
IBMQ.save_account("TOKEN")
# load your account after save it
IBMQ.load_account()
provider = IBMQ.get_provider("ibm-q")
backend = provider.get_backend("ibmq_burlington")
job = execute(circuit, backend, shots=512)
job_monitor(job) # 監控有多少工作正在排隊
稍候以下訊息出現 ...
Job Status: job has successfully run
counts = job.result().get_counts()
plot_histogram(counts)
backend = Aer.get_backend("qasm_simulator")
job = execute(circuit, backend, shots=512)
# job_monitor(job)
counts = job.result().get_counts()
plot_histogram(counts)
backend = Aer.get_backend("statevector_simulator")
job = execute(circuit, backend)
# job_monitor(job)
statevec = job.result().get_statevector()
plot_bloch_multivector(statevec)
發生什麼事?
circuit = QuantumCircuit(2, 2)
circuit.h(0)
circuit.cx(0, 1)
# circuit.measure([0, 1], [0, 1])
job = execute(circuit, backend)
# job_monitor(job)
statevec = job.result().get_statevector()
plot_bloch_multivector(statevec)
發生什麼事?
circuit = QuantumCircuit(2, 2)
circuit.h(0)
circuit.cx(0, 1)
# circuit.measure([0, 1], [0, 1])
job = execute(circuit, backend)
# job_monitor(job)
statevec = job.result().get_statevector()
plot_state_qsphere(statevec)
backend = Aer.get_backend("unitary_simulator")
job = execute(circuit, backend)
# job_monitor(job)
unitary = job.result().get_unitary()
print(unitary)
發生什麼事?
# quantum assembly simulator
plot_histogram(execute(circuit, backend=Aer.get_backend("qasm_simulator"), shots=1024).result().get_counts())
# statevector simulator
plot_bloch_multivector(execute(circuit, Aer.get_backend("statevector_simulator")).result().get_statevector())
# unitary simulator
print(execute(c, Aer.get_backend("unitary_simulator")).result().get_unitary())
# qsphere simulator
plot_state_qsphere(execute(circuit, Aer.get_backend("statevector_simulator")).result().get_statevector())
circuit = q.QuantumCircuit(1)
# 翻轉 (flip) 閘
circuit.x(0)
circuit.y(0)
circuit.z(0)
circuit = q.QuantumCircuit(1)
# hadamard 閘,通常拿來製造疊加態
circuit.h(0)
circuit = q.QuantumCircuit(1)
# 旋轉閘:axis(angle, bit)
circuit.rx(Math.pi, 0)
circuit.ry(Math.pi/2, 0)
circuit.rz(1.8, 0)
circuit = q.QuantumCircuit(2)
# axis(control, target)
# 如果控制位元是1,就翻轉目標位元
circuit.cx(0, 1)
circuit.cy(0, 1)
circuit.cz(0, 1)
如果控制位元是疊加態呢 ?????
circuit = q.QuantumCircuit(2)
# axis(angle, control, target)
# 如果控制位元是1,就旋轉目標位元 (target)
circuit.crx(Math.pi, 0, 1)
circuit.cry(Math.pi * 2, 0, 1)
circuit.crz(0, 0, 1)
circuit = q.QuantumCircuit(3)
# toffoli閘, 量子電腦的NAND閘
# axis(control, control, target)
# 如果兩個控制位元都是1,就翻轉目標位元
circuit.ccx(0, 1, 2)
circuit = q.QuantumCircuit(2, 2)
# 做某些事
circuit = do_something(circuit)
# 然後量它
# [list of qubits], [list of classical bits]
circuit.measure([0, 1], [0, 1])
測量是量子運算唯一的不可逆操作
這是做啥用的?
跑跑看就知道了!
qr = QuantumRegister(1, 'qr')
cr = ClassicalRegister(1, 'cr')
c = q.QuantumCircuit(qr, cr)
# do something
c.measure([0], [0])
c.x(0).c_if(cr, 1)
# do something
c.measure([0], [0])
c.draw()
I, at any rate, am convinced that He does not throw dice. -- Albert Einstein
大家都知道電腦的隨機數都不是真隨機
// C++ 偽隨機數生成器
static long long seed = 1;
long long rand(void) {
return seed = (seed * 998244353) % 1000000009;
}
但是量子電腦是真亂數
# 單位元真亂數產生器
c = q.QuantumCircuit(1, 1)
c.h(0)
c.measure([0], [0])
更多位元
# 雙位元真亂數產生器 (0~3)
c = q.QuantumCircuit(2, 2)
c.h([0, 1])
c.measure([0, 1], [0, 1])
How to do this ???
import math
c = QuantumCircuit(2, 2)
c.ry(2 * math.asin(1 / math.sqrt(3)), 0)
c.x(0)
c.ch(0, 1)
c.measure([0, 1], [0, 1])
c.draw()
Constant function:
\(f(x) = 0\)
\(f(x, y, z) = 1\)
\(f(x, y, z, ...) = \) 常數
Balanced function:
\(f(x, y, z, ...) = x+y\)
\(f(x, y, z) = cnot(x, z)\)
\(f(x, y, z, ...) = H(y)\)
你要試多少次才能確定它是哪種函數?
量子電路必須是可逆的!
# bit 0 is the input
# bit 1 is the output
def black_box(c):
c.cx(0, 1)
return c
Constant ?
Balanced ?
# bit 0, 1 is the input
# bit 2 is the output
def black_box(c):
c.cx(0, 2)
c.cx(1, 2)
return c
Constant ?
Balanced ?
# bit 0 is the input
# bit 1 is the output
def black_box(c):
c.z(0)
c.x(1)
return c
Constant ?
Balanced ?
c = q.QuantumCircuit(2, 1)
# 將輸出位元通過NOT閘
c.x(1)
# 將所有位元通過H閘
c.h([0, 1])
# 通過 black box
c = black_box(c)
# 再一次將所有位元通過H閘
c.h([0, 1])
# 測量所有輸入位元
c.measure([0], [0])
傳送 qubit0 的量子態到 qubit 2
量子電路必須是可逆的!
c = q.QuantumCircuit(3, 3)
# c.barrier()
c.h(1)
c.cx(1, 2)
c.cx(0, 1)
c.h(0)
# c.barrier()
c.measure([0, 1], [0, 1])
# c.barrier()
c.cx(1, 2)
c.cz(0, 2)
# c.barrier()
為什麼不用簡單的交換閘 (swap gate) ?
c = q.QuantumCircuit(3)
c.swap(0, 2)
箱子裡有一個秘密的 \(n\)位元數字 \(s\)
每次詢問你可以:
問箱子一個數字 \(x\),然後它會回答你 \(s\ \&\ x\)
最壞情況下最少需要猜多少次呢?
# secret_number = "101001"
def secret_box_AND(c):
c.cx([5, 3, 0], 6)
return c
箱子可能長成這樣
# secret_number = "????"
def secret_box_AND(c):
c.cx([3, 2, 0], 4)
return c
# secret_number = "???"
def secret_box_AND(c):
c.cx(0, 3)
return c
# secret_number = "?????"
def secret_box_AND(c):
c.cx([1, 2], 5)
return c
secreat_number = "101001"
def secreat_box_AND(c):
for i, istrue in enumerate(reversed(secreat_number)):
if istrue == '1':
c.cx(i, 6);
return c
更加一般化的形式
# 要猜的數字為6位元整數
c = q.QuantumCircuit(6 + 1, 6)
c.h([0, 1, 2, 3, 4, 5])
c.x(6)
c.h(6)
c.barrier()
c = secreat_box_AND(c)
c.barrier()
c.h([0, 1, 2, 3, 4, 5])
c.measure([0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5])
# 要猜的數字是 [size] 位元整數
c = q.QuantumCircuit(size + 1, size)
c.h(range(size))
c.x(size)
c.h(size)
c.barrier()
c = secreat_box_AND(c)
c.barrier()
c.h(range(size))
c.measure(range(size), range(size))
Quantum Computing for Computer Scientists:
https://www.youtube.com/watch?v=F_Riqjdh2oM
Quantum Computer Programming w/ Qiskit:
https://www.youtube.com/watch?v=aPCZcv-5qfA
https://www.youtube.com/watch?v=lB_5pC1MkGg
https://www.youtube.com/watch?v=_BHvE_pwF6E
Introduction to quantum programming
https://www.youtube.com/playlist?list=PLIxlJjN2V90w3KBWpELOE7jNQMICxoRwc
“Nature isn't classical, dammit, and if you want to make a simulation of nature, you'd better make it quantum mechanical, and by golly it's a wonderful problem, because it doesn't look so easy.”
----Richard Feynman
“大自然不是古典的,如果你想要模擬大自然,你最好把它變成是量子力學的,而這是一個精彩的好問題,因為它看起來並不是那麼容易。”
——理查費曼
By 林尚廷
量子運算 :: 應該是寒訓講義的東西