\(|0> = \begin{bmatrix} 1 \\ 0 \end{bmatrix} = | \uparrow >\)
\(|1> = \begin{bmatrix} 0 \\ 1 \end{bmatrix} = | \downarrow >\)
\(|0> \xrightarrow{H \ gate} |+> \equiv \cfrac{1}{\sqrt{2}}(|0>+|1>)\)
\(|1> \xrightarrow{H \ gate} |-> \equiv \cfrac{1}{\sqrt{2}}(|0>-|1>)\)
\(\Longrightarrow H \ gate = Ry(\cfrac{\pi}{2}) \ast Rx(\pi)\)
創建 Bell State (糾纏態)
\(\otimes\) 的算法是這樣 :
qc.compose(qc要結合到的地方,{可多加一項 front = True表示加在要結合的電路的前面})
: 結合電路
qiskit.__version__
或 qiskit.__qiskit_version__
: 是查看 qiskit 的版本
job_monitor
: 監測現在的工作狀態
Aer.get_backend("qasm_simulator")
: 獲取名叫 qasm_simulator 的後端
operator(qc)
: 把電路轉為矩陣
qc.to_gate
: 把電路轉為可以重複使用的 gate
qc.append(HGate(),[0])
: 在編號 0 的 qubit 中放入 H 閘,並且直接應用,沒有轉換
execute(...).result().get_memory()
: 最後面的get_memory
代表需要返回測量結果
execute(qc, sim, basic_gates = [u, cx])
: 在 sim 這個模擬器後端中執行 qc 這段電路後,展開到 u 閘 & cx 閘
%qiskit_backend_overview
: check information on connective
qc.measure_all()
: 在電路添加新的傳統位元保存狀態
.dim
: 得知電路的維度,假設有2量子位元,就代表維度是2^2 = 4維,另外,輸入維度會等同於輸出維度
QuantumRegister(7)
: 創建一個7量子位元的儲存器,英文描述會長這樣:quantum register with 7 qubits
保真度 : 檢查2者是否相同,也就是說,假設2個相同的閘就算全局變量不一樣保真度還是會相同,保真度等於 1
而看保真度的程式碼是 average_..._fidelity
: …當中可以填入gate或state,但比較的雙方一定要是一樣的屬性,如果跑出來等於 1 ,就代表2者是相同的,下方是舉例 :
\(\Longrightarrow
\begin{cases} X gate = exp(-1j / 2) * X gate \ \ \ (gate 對上gate)\\
\\
[0,1] = [0, 1j] \ \ \ (state 對上 state)
\end{cases}\) ,這2者的保真度都是 1
另外看保真度的函式其實有這3種,通常選項出現3種問說哪些是對的時要選 average_..._fidelity
以及 process_fidelity
, 但 state_fidelity
是錯誤的(我也不知為啥)
sv.draw('hinton')
或是 sv.draw('hinton_plot')
: 用 statevector 畫出 hinton plot
qc.qasm()
: print in QASM syntax
plot_barriers = False
in QuantumCircuit.draw : 不會顯示出barriers
plot_gate_map
還有 plot_error_map
: show the gate map of the device
qc.draw('...',style = {'backgroundcolor' = '<color>'})
: 畫出電路圖, … 當中可以填上這3種 \(\Longrightarrow\)
\(\begin{cases}
i. \ \ \ mpl : 一般的電路圖,常看到的那種(內建) \\
ii. \ \ latex : 高質量的圖 \\
iii. \ text : ASCII 的表示圖
\end{cases}\)
QuantumRegister(int, name = '')
是叫出量子位元,可以附上名字,假設名字寫 a ,那出來的電路會寫 a0, a1 ,…;
ClassicalRegister(int, name = '')
是叫出傳統位元,可以附上名字;
QuantumCircuit(q,c)
是創建量子電路,裡面可以放入上述2種位元或是用 int 叫出
qc.measure(qubit, cbit)
: 當中填入的 qubit & cbit 可以用 list 取代,像這樣
qc.measure([0,1,2],[0,2,1])
是代表 \(\begin{cases}
0 \ qubit \Rightarrow 0 \ cbit \\
1 \ qubit \Rightarrow 2 \ cbit \\
2 \ qubit \Rightarrow 1 \ cbit
\end{cases}\)
如果要在所有 qubits 中放上 barriers 可以用以下方法 :
# 先假設創建 3 qubits & 3 cbits
qc = QuantumCircuit(3,3)
# 第一種
qc.barrier([0,1,2])
# 第二種
qc.barrier([0:3])
# 第三種
qc.barrier()
# 第四種
qc.barrier(0,1,2)
要輸出 matrix1 \(\otimes\) matrix2 :
matrix1 = DensityMatrix(matrix1)
result = matrix1.tensor(matrix2)
print(result)
創建一個用 QASM 字串表達的量子電路 :
qc = QuantumCircuit.from_qasm_str(qasm_str)
qc.initialize(state, qubit)
: state 可以放入 list 或 int 之類的,範例如下 \(\Longrightarrow\)
假設要創建這樣的 statevector : [0.707+0.j, 0.+0.j, 0.+0.j, 0.707+0.j] 可以由以下2種方法達成
# 第一種
qc = QuantumCircuit(2)
v = [1/sqrt(2), 0, 0, 1/sqrt(2)]
qc.initialize(v,[0,1])
#第二種
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0,1)
但如果有 2 個 qubit 的話就要這樣寫
qc.initialize([1,0,0,0],[0,1])
plot_state_city(sv, color = ["red","red"])
: 做出 3 維的柱狀圖,柱子顏色是紅色
plot_histogram(dict)
: dict 放入字典,並且在後面可以加上 bar_labels=False ,讓圖上不會出現數字,下面是舉例
plot_histogram({'000' : 450, '111' : 550}, bar_labels = False)
如果沒有 bar_labels=False 的話在橘色圈圈處會出現 450 以及 550
plot_bloch_multivector
: 在球上有 statevector ,有多少 qubit 就會有多少球
plot_bloch_vector
: 只會出現 1 顆球而已
plot_bloch_cartesian
: 以笛卡爾座標繪製,在球上標點而已
qc.decompose().draw()
: 把電路上的 gate 拆成單量子或是雙量子位元的 gate (英文會這樣描述 : draw the circuit as single and two-qubits gates only),像是假設電路上放了 ccx gate 那就會被拆成很多 H CX T gate 之類的
plot_error_map()
: 畫出錯誤率圖,長的像下圖這樣
plot_gate_map()
: 畫出 物理qubit 以及 邏輯qubit 之間的關係,幫助了解現在的量子拓樸結構,長的像下圖這樣
execute(..., ..., optimization_level)
: in the execute
function, the parameter – optimization_level can set how much optimization to perform on the circuit
plot_bloch_multivector(vector)
: vector 是要放入經過計算之後的 statevector,下方是舉例
要產生這個圖 :
首先我們知道要用 plot_bloch_multivector
接著可以透過圖得知 qubit 0 沒有經過 gate 的旋轉,但 qubit 1 經過了 H gate 的旋轉
那我們就可以先畫出電路圖 :
再來可以去算 statevector :
\(q_0 : \begin{bmatrix} 1 \\ 0 \end{bmatrix}\)
\(q_1 : \begin{bmatrix} 1 \\ 0 \end{bmatrix} \times \begin{bmatrix} \cfrac{1}{\sqrt{2}} \ \cfrac{1}{\sqrt{2}} \\ \cfrac{1}{\sqrt{2}} \ \cfrac{-1}{\sqrt{2}} \end{bmatrix} = \begin{bmatrix} \cfrac{1}{\sqrt{2}} \\ \cfrac{1}{\sqrt{2}} \end{bmatrix}\)
我們知道了 \(q_0, q_1\) 各自的 statevector 後接著就可以算綜合的 :
\(\begin{bmatrix} 1 \\ 0 \end{bmatrix} \otimes \begin{bmatrix} \cfrac{1}{\sqrt{2}} \\ \cfrac{1}{\sqrt{2}} \end{bmatrix} = \begin{bmatrix} \cfrac{1}{\sqrt{2}} \\ 0 \\ \cfrac{1}{\sqrt{2}} \\ 0 \end{bmatrix}\)
所以如果要畫出上述的2顆球的程式碼就會是這樣 :
plot_bloch_multivector([1/sqrt(2),0, 1/sqrt(2),0])
job.status()
以及 job_monitor(job)
: 查看目前的 job 的詳細資料(to get the information of the job when job = execute(qc,backend)
)
補充 : 沒有這幾個用法
job_monitor(backend)
: 不能把 backend 放在裡面provider.status()
: Account 不能得知目前狀態backend.status()
: 雖然可以執行,但不能得知 job 的詳細資料,只能得到 backend 的詳細資料random_unitary(2)
: 輸出 \([[\ ... ,\ ...], \ [\ ...,\ ...]],\ input\ dim = 2, \ output\ dim = 2\)
random_statevector(2)
: 輸出 \([...,\ ...],\dim = 2\)
circuit 也就是電路才有辦法 draw 出來, Register 或閘門之類的不能單純 draw 出來
閱讀這種類型的東西時,注意是從高位到低位:|00>+|11> \(\Rightarrow\) |00>+|10> 代表是經過CNOT並且控制的部分是 1 號位元而目標是 0 號位元
.get_backend()
非常重要,就是要用哪個simulator來當後端
只有 plot_histogram
沒有 plot_bar_chart
之類的,但可以透過plot_histogram([c1, c2],...)
來達成製作 bar 圖的目的
text is the default output method used to draw the circuit
execute
這個函數非常重要, execute(qc, sim, backend, basic_gates = [...], coupling_map = [[...],[...],...], optimization_level = n).result().get_memory()
這些都是常用會加上去的,請注意除了這些之外其他一些奇怪的不會加,例如甚麼mode, device之類的就不會
如果要建立最大糾纏態 (entangle value) ,以 2 qubit 為例 :
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0,1)
# 注意 cx 的部分不可被改為 cy 或 cz
基礎的 python 觀念 : [ a : b ] 是代表輸出 a ~ (b-1) 的數字不是 a~b
判斷電路深度 : 畫出來,下面是範例
qc = QuantumCircuit(5)
qc.cx(0,1)
qc.cx(2,3)
qc.cx(3,4)
畫出來會長這樣,所以深度是 2
plot_error.gate_map()
plot_VisualizationError()
qc.cexchange()
qc.ct()
先釐清一個重要觀念,所謂的rotate X(或是Y、Z之類的),就是圍繞該軸旋轉,像是下圖:
對於 |0> 來說原本是指向 0 的相位(粉色的線),經過 RY gate 的旋轉 \(\pi\) 後(藍色的線),會變成圖上箭頭的相位,也就是 1 ;同時最重要的,他的狀態向量會從 1|0> + 0|1> 變成 0|0> + 1|1>,在"|"前面的是出現的機率,後面的是出現的相位會是 0 或是 1
所以同理可以知道這樣是經過RY gate轉了 \(3/4 \pi\)後的結果(箭頭始終在x-z平面上旋轉所以只有經過RY gate 而已)
接下來介紹箭頭指向不同方向的 statevector 是甚麼 :
然後這是不同方向對應到的 statevector :
除此之外,如果是純vector的話就是一般的 3 維概念 :
像這張圖片就是用這個向量表現出來的 [1/sqrt(2),-1/sqrt(2),0]
接著,我們要判斷有多少 qubits 在 qsphere 上,可以藉由這些方法 :
先藉由數上面共有多少個點,像現在有8個點,也就是 2^3,所以共有 3 qubits
但像這個上面就已經有標向量了就看是幾位數,像 |000>就是 3 qubits
(以下沒特別註明的話都是放在qubit中)
\(\cfrac{1}{\sqrt{2}} = 0.707\)
H gate :
函數 : qc.h(target)
電路圖 : qc.h(0)
矩陣 : \(\cfrac{1}{\sqrt{2}} \times \begin{bmatrix} 1 & 1 \\ 1 & -1 \end{bmatrix}\)
補充 : H = Ry(\(\cfrac{\pi}{2}\)) * Rx(\(\pi\)), 如果有 2 個 H gate 會互相抵銷回到原始態
另外 H gate 的bloch sphere 長這樣 :
T gate :
函數 : qc.t(target)
電路圖 : qc.t(0)
矩陣 : \(\begin{bmatrix}
1 & 0\\
0 & e^{i \cdot \pi/4}\\
\end{bmatrix}\)
補充 : 等同於繞 Z 軸旋轉 \(\cfrac{\pi}{4}\),也就是說 T = Rz(\(\cfrac{\pi}{4}\))
S gate :
函數 : qc.s(target)
電路圖 : qc.s(0)
矩陣 : \(\begin{bmatrix}
1 & 0\\
0 & e^{i \cdot \pi/2}\\
\end{bmatrix}\)
補充 : 等同於繞 Z 軸旋轉 \(\cfrac{\pi}{2}\),也就是說 \(S\) = \(T^2\) = \(Rz(\cfrac{\pi}{2})\)
Sdg gate :
函數 : qc.sdg(target)
電路圖 : qc.sdg(0)
矩陣 : \(\begin{bmatrix}
1 & 0\\
0 & e^{-i \cdot \pi/2}\\
\end{bmatrix}\)
補充 : 等同於 S gate 的逆門(共軛),也就是說會跟 S gate 抵銷掉,\(S^{\dagger} = Rz(-\cfrac{\pi}{2})\)
X gate :
函數 : qc.x(target)
電路圖 : qc.x(0)
矩陣 : \(\begin{bmatrix}
0 & 1\\
1 & 0\\
\end{bmatrix}\)
Y gate :
函數 : qc.y(target)
電路圖 : qc.y(0)
矩陣 : \(\begin{bmatrix}
0 & -i\\
i & 0\\
\end{bmatrix}\)
補充 : 是 X gate 和 Z gate 的組合,也就是說 Y gate 不只交換了 |0> 和 |1> 的狀態,還在結果狀態中添加了 i 的相對相位
Z gate :
函數 : qc.z(target)
電路圖 : qc.z(0)
矩陣 : \(\begin{bmatrix}
1 & 0\\
0 & -1\\
\end{bmatrix}\)
補充 : 對 |0>、|1>沒有影響,但會更改相位,像是\(\begin{cases}
Z|0> = \ \ \ |0> \\
Z|1> = -|1>
\end{cases}\)
CNOT (CX) gate :
函數 : qc.cx(control, target)
電路圖 : qc.cx(0, 1)
矩陣 : \(\begin{bmatrix}
1 & 0 & 0 & 0\\
0 & 1 & 0 & 0\\
0 & 0 & 0 & 1\\
0 & 0 & 1 & 0\\
\end{bmatrix}\)
CRY gate :
函數 : qc.cry(theta, control, target)
電路圖 : qc.cry(np.pi, 0,1)
MCT gate : 一次串聯好幾個控制位元(用 list 串起來)
函數 : mct([x1, x2, x3, ...], target)
電路圖 : qc.mct([0,1,2], 3)
CCNOT (CCX) gate :
函數 : qc.ccx(control_q1, control_q2, target)
電路圖 : qc.ccx(0,1,2)
CZ gate :
函數 : qc.cz(control, target)
電路圖 : qc.cz(0,1)
矩陣 : \(\begin{bmatrix}
1 & 0 & 0 & 0\\
0 & 1 & 0 & 0\\
0 & 0 & 1 & 0\\
0 & 0 & 0 & -1\\
\end{bmatrix}\)
補充-1 : 其實不只有CZ可以對 Z 軸旋轉,事實上可以藉由這 3 種 gate 達到:
CZ, CP, CRZ,對應到的 gate 依序長這樣 \(\Longrightarrow\)
此外 CZ gate 等價於 H, CNOT, H 組合再一起
補充-2 : 創建 Bell state
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0,1)
statevector 長這樣
電路圖長這樣
補充-3 : 創建 GHZ state
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0,1)
qc.cx(0,2)
statevector 長這樣
電路圖長這樣
補充-4 :
from qiskit import QuantumCircuit, Aer
qc = QuantumCircuit(1)
qc.h(0)
qc.x(0)
simulator=Aer.get_backend('unitary_simulator')
result = execute(qc,simulator).result()
unitary = result.get_unitary(qc)
print(unitary)
在 unitary_simulator 中執行這段程式碼會得到這個2維矩陣(非1維),而矩陣的值可以通過計算經過的 gate 得到
補充-5 : Pauli gates
補充-6 : 旋轉門
補充-7 : 暱稱
Qiskit 共有4大組件,分別是 :
然後有這幾個重要的 simulator :
在 BasicAer 中可以用的模擬器有這3個:
在ibmq quito當中畫出讀取誤差 :
provider = IBMQ.load_account()
backend = provider.get_backend('ibmq_quito')
plot_error_map(backend)
assign qasm_simulator :
BasicAer.get_backend('qasm_simulator')
Aer.get_backend('qasm_simulator')
obtain the unitary of a circuit : unitary_simulator
在 OpenQASM 當中創建 1 qubit & 1 cbit 的疊加態 :
qreg q[1] # 建 1 qubit
creg c[1] # 建 1 cbit
h q[0] # 在 qubit 上放 H gate
區分 Aer 跟 BasicAer 的用法:
Aer.get_backend("unitary_simulator")
result = execute(qc, simulator).result()
unitary = result.get_unitary(qc)
BasicAer.get_backend("unitary_simulator")
result = execute(qc, simulator).result()
unitary = result.get_unitary(qc)
結論 : 似乎沒什麼差別,都要先經過 get_backend execute 最後是 get_unitary
BasicAer.backends()
: 列出所有可用的 backends(會用 list 表示)
Statevector.from_int(3,2**3)
: 第一個 3 代表改變第 3 個(從 0 開始算,左到右),第二部分 2 ** 3 代表共有 2 ** 3=8 個qubits
如果 qubits 是特徵態 (eigenstate) : 那該電路的statevector會是最少並且全部包含,像是 \(\Longrightarrow\) 在 3 qubits 中會出現 000 –- 111、 001 –- 110、 011 –- 100之類的
注意 qiskit 當中的 qubit 是依照(大到小)顯示的,也就是
{'\(\underbrace{0}_{這是第2號位元}\) \(0\) \(\underbrace{1}_{這是第0號位元}\) \(:\) \(1000\) '}
這樣是經過了qc.x(0)所產生的結果
eigenstate of \(\begin{cases} X \ axis \Rightarrow |+> ,\ |-> \\ Y \ axis \Rightarrow |1> ,\ |-1> \\ Z \ axis \Rightarrow |\Psi_1> , \ |\Psi_2> (\Psi是非0複數) \end{cases}\)
經過 CX gate :
eg.
qc.h(0) # q_0 : 1/sqrt(2) * (|0>+|1>), q_1 : |0>
qc.cx(0,1)
# 先把q_0 q_1 綜合起來(用otimes) : 1/sqrt(2) * (|00>+|01>)
# 接者套用 cx gate 的概念 當q_0 是 1 的時後翻轉 q_1
# 最後得到 1/sqrt(2) * (|00>+|11>)
閱讀 plot_state_city
: (目前其實也還沒很懂)
先看會出哪幾種 state (|00>, |11> 之類的)
而至於會出現甚麼 state 需要自己計算
eg. 創建 Bell State :
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0,1)
從程式碼中我們可以計算出 state = \(\cfrac{1}{\sqrt{2}} \times (|00>+|11>)\)
所以在 plot_state_city
中我們只會看到 00 跟 11 有柱子而已
# 做出ry gate並且輸出statevector以及blochsphere
from qiskit import QuantumCircuit, Aer, transpile, assemble
from qiskit.visualization import plot_bloch_multivector
import numpy as np
theta = np.pi
# 創建量子電路
qc = QuantumCircuit(1)
a = qc.ry(theta, 0)
# 使用模擬器來模擬量子電路並取得輸出狀態向量
simulator = Aer.get_backend('statevector_simulator')
qc_transpiled = transpile(qc, simulator)
result = simulator.run(qc_transpiled).result()
statevector_result = result.get_statevector()
print(statevector_result)
# 繪製Bloch球
plot_bloch_multivector(statevector_result)