返回文章列表

量子計算與量子程式設計入門

本文探討量子計算的基礎概念,包含量子位元的測量、量子閘的操作以及量子糾纏的現象。文章詳細介紹了單量子位元閘和受控非閘(CNOT)的原理和應用,並使用 QISKit SDK 演示如何建構量子電路、進行模擬和在真實量子裝置上執行。同時,也解析了 QISKit

量子計算 程式設計

量子計算的核心概念在於利用量子位元進行資訊處理,不同於傳統位元,量子位元可以同時處於多種狀態,實作平行計算。然而,量子態的測量並非直接取得量子態本身,而是得到一個經典位元,其機率與量子態係數的平方相關。這也意味著測量會破壞原始量子態,限制了單個量子位元所能儲存的資訊量。為了操作量子位元,需要使用量子閘,例如 X 閘、H 閘以及推廣的單量子位元閘,它們由麼正矩陣表示,確保量子態在操作後仍然保持歸一化。

量子態的測量比你想的更複雜

假設你在自家地下室有一個實驗室,你獲得了一個量子位元(qubit),其狀態為 $|ψ⟩ = α|0⟩+β |1⟩$,並且有一個測量儀器,你的任務是計算出 α 和 β 的係數。也就是說,要計算出量子態。這看起來似乎是一項簡單的任務,但事實上這是不可能的。量子力學的原理告訴我們,系統的量子態是無法直接觀察的。我們最多隻能猜測 α 和 β 的近似值。這個過程被稱為在計算基礎上的測量。

對量子態 $|ψ⟩ = α|0⟩+β |1⟩$ 進行測量的結果會給出經典位元: $α |0⟩+β |1⟩ → 0$ 的機率是 $|α|^2$ $α |0⟩+β |1⟩ → 1$ 的機率是 $|β|^2$

因此,測量過程輸出的經典位元 0 和 1 的機率等於係數 α 和 β 絕對值的平方。從物理上來說,這個過程可以被想像成透過測量儀器觀察一個物理光子、原子或電子。這就是為什麼測量經常被視為一種量子閘。

測量會干擾量子系統的狀態,從而給出一個經典位元的結果。重要的是要記住,在這個過程之後,係數 α 和 β 被破壞了。這意味著我們無法在一個量子位元中儲存大量的資訊。如果我們能夠測量出 α 和 β 的確切值,那麼理論上就可以透過使用複數在量子位元狀態中儲存無限量的經典資訊。但是,這是不可能的。量子力學禁止這樣做。

量子態的歸一化

給定在計算基礎上的測量 $α |0⟩+β |1⟩$,經典位元 0 和 1 的機率之和必須等於 1。即: $P(0) + P(1) = |α|^2 + |β|^2 = 1$

這意味著量子態向量的長度必須是 1(歸一化)。這是由於測量機率之和為 1。在下一節中,我們將討論單量子位元閘如何被推廣,它們是什麼,以及如何用它們來構建更複雜的電路。

推廣的單量子位元閘

到目前為止,我們已經看到了兩個簡單的閘:X 和 H,它們由矩陣表示: $X = \begin{bmatrix} 0 & 1 \ 1 & 0 \end{bmatrix}, H = \frac{1}{\sqrt{2}} \begin{bmatrix} 1 & 1 \ 1 & -1 \end{bmatrix}$

同樣,量子態的疊加可以表示為向量 $\begin{bmatrix} α \ β \end{bmatrix}$。然後,將這兩個閘應用於量子態可以推廣為任意酉矩陣: $U \begin{bmatrix} α \ β \end{bmatrix}$

U 被稱為推廣的單量子位元閘,條件是 U 必須是酉矩陣。

麼正矩陣

麼正矩陣的定義

一個矩陣 U 是酉矩陣,如果它與其厄米特共軛(Hermitian transpose)$U^\dagger$ 相乘得到單位矩陣:$U^\dagger U = I$。厄米特共軛或共軛轉置用匕首(†)符號表示 $U^\dagger = (U^T)^*$,即轉置後的複共軛。

麼正矩陣的重要性

酉矩陣對於量子閘來說是好的,因為它們保留了向量的長度。這對於量子閘來說是有用的,因為它們要求輸入和輸出狀態是歸一化的(具有向量長度 1)。事實上,酉矩陣是唯一能夠保留長度的矩陣型別,因此也是唯一可以用於量子閘的矩陣型別。

其他單量子位元閘

除了 X 和 H 之外,還有其他有用的單量子位元閘,如泡利矩陣(Pauli matrices)X、Y、Z: $X = \begin{bmatrix} 0 & 1 \ 1 & 0 \end{bmatrix}, Y = \begin{bmatrix} 0 & -i \ i & 0 \end{bmatrix}, Z = \begin{bmatrix} 1 & 0 \ 0 & -1 \end{bmatrix}$

這些矩陣對於諸如超密集編碼(SDC)等資訊處理任務非常有用。超密集編碼是一種試圖在量子位元中高效儲存經典資訊的過程。它們還出現在分析原子屬性(如電子自旋)時。此外,它們與空間的三個維度 XYZ 緊密相關。

受控非閘(CNOT)與量子糾纏

CNOT 閘是一種雙量子位元閘,具有四個計算基礎狀態。對於一個疊加態,四個基礎狀態可以表示為: $α |00⟩ + β |01⟩ + δ |10⟩ + γ |11⟩$

其中 α、β、δ 和 γ 是疊加係數。

CNOT 閘的操作

CNOT 閘的操作如下:

  • 如果控制量子位元為 1,則翻轉目標量子位元。
  • 否則,不做任何事情。

CNOT 閘對於生成糾纏態至關重要,並且在各種任務中發揮關鍵作用,包括量子隱形傳態、超密集編碼和幾乎所有量子演算法。

CNOT 矩陣表示

CNOT 閘對於基礎狀態的矩陣表示為: $\begin{bmatrix} 1 & 0 & 0 & 0 \ 0 & 1 & 0 & 0 \ 0 & 0 & 0 & 1 \ 0 & 0 & 1 & 0 \end{bmatrix}$

CNOT 電路圖如下所示,其中加號(+)符號代表目標量子位元,下面的藍點代表控制量子位元。

此圖示顯示了CNOT閘的基本結構,其中控制量子位元決定是否對目標量子位元進行翻轉操作。

程式碼範例與解析

from qiskit import QuantumCircuit, execute, Aer

# 建立一個2量子位元的量子電路
qc = QuantumCircuit(2)

# 在第一個量子位元上應用Hadamard門
qc.h(0)

# 在兩個量子位元之間應用CNOT門
qc.cx(0, 1)

# 將電路繪製出來
qc.draw()

#### 內容解密:
此程式碼建立了一個簡單的2量子位元量子電路首先我們匯入必要的模組並建立一個包含2個量子位元的QuantumCircuit物件
然後我們在第一個量子位元上應用Hadamard門H),使其進入疊加態
接著我們在第一個和第二個量子位元之間應用CNOT門CX),這將使兩個量子位元糾纏起來
最後我們呼叫`draw()`方法將電路圖繪製出來用於視覺化我們的量子電路設計

量子程式設計入門與QISKit實作

量子計算是一種利用量子力學原理進行資訊處理的新型計算方式。與傳統計算相比,量子計算具有巨大的潛力,可以解決一些傳統電腦難以解決的問題。在本章中,我們將介紹量子程式設計的基本概念,並使用QISKit(一款強大的Python量子程式設計SDK)來實作一個簡單的量子程式。

量子糾纏與量子閘

在量子計算中,量子位元(qubit)是基本的資訊單位。與傳統位元不同,量子位元可以同時存在於多個狀態,這使得量子計算具有平行處理的能力。為了操作量子位元,我們需要使用量子閘。

其中一個重要的量子閘是CNOT閘,它可以將兩個量子位元進行糾纏。糾纏是一種量子力學現象,使得兩個或多個量子位元之間存在著某種關聯。CNOT閘的運作原理是:當控制位元為1時,將目標位元進行翻轉。

# 建立一個包含2個量子位元的量子暫存器
qr = qp.create_quantum_register("qr", 2)
# 建立一個包含2個經典位元的經典暫存器
cr = qp.create_classical_register("cr", 2)
# 建立一個電路
qp.create_circuit("Circuit", [qr], [cr])
# 取得電路
circuit = qp.get_circuit('Circuit')
# 對第一個量子位元施加Hadamard閘
circuit.h(qr[0])
# 對第二個量子位元施加CNOT閘,控制位元為第一個量子位元
circuit.cx(qr[0], qr[1])

#### 內容解密:
1. `circuit.h(qr[0])`:對第一個量子位元施加Hadamard閘使其進入疊加狀態
2. `circuit.cx(qr[0], qr[1])`:對第二個量子位元施加CNOT閘控制位元為第一個量子位元從而實作兩個量子位元的糾纏

量子程式的基本結構

一個典型的量子程式包括以下幾個步驟:

  1. 建立一個量子程式。
  2. 建立量子位元和經典暫存器。
  3. 建立一個電路,將量子位元和經典暫存器納入其中。
  4. 對量子位元施加量子閘,以實作所需的運算。
  5. 對量子位元進行測量,將結果儲存到經典暫存器中。
  6. 編譯程式,將其轉換為可執行的格式。
  7. 在模擬器或真實的量子裝置上執行程式。
# 建立一個量子程式
qp = QuantumProgram()
# 建立1個量子位元
quantum_r = qp.create_quantum_register("qr", 1)
# 建立1個經典暫存器
classical_r = qp.create_classical_register("cr", 1)
# 建立一個電路
qp.create_circuit("Circuit", [quantum_r], [classical_r])
# 取得電路
circuit = qp.get_circuit('Circuit')
# 對量子位元施加Pauli X閘(bit flip)
circuit.x(quantum_r[0])
# 對量子位元進行測量
circuit.measure(quantum_r[0], classical_r[0])

#### 內容解密:
1. `circuit.x(quantum_r[0])`:對量子位元施加Pauli X閘將其從基態|0>翻轉到|1>
2. `circuit.measure(quantum_r[0], classical_r[0])`:對量子位元進行測量將結果儲存到經典暫存器中

QISKit實作範例

以下是一個使用QISKit實作的簡單量子程式範例:

import sys
import qiskit
import logging
from qiskit import QuantumProgram

def main():
    # 建立一個量子程式
    qp = QuantumProgram()
    # 建立1個量子位元
    quantum_r = qp.create_quantum_register("qr", 1)
    # 建立1個經典暫存器
    classical_r = qp.create_classical_register("cr", 1)
    # 建立一個電路
    qp.create_circuit("Circuit", [quantum_r], [classical_r])
    # 取得電路
    circuit = qp.get_circuit('Circuit')
    # 對量子位元施加Pauli X閘(bit flip)
    circuit.x(quantum_r[0])
    # 對量子位元進行測量
    circuit.measure(quantum_r[0], classical_r[0])
    # 編譯程式
    qobj = qp.compile(["Circuit"], backend='local_qasm_simulator')
    # 執行程式
    result = qp.run(qobj, timeout=240)
    # 輸出結果
    print(str(result.get_counts('Circuit')))

if __name__ == '__main__':
    main()

#### 內容解密:
1. 程式首先建立了一個包含1個量子位元和1個經典暫存器的電路
2. 對量子位元施加Pauli X閘將其從基態|0>翻轉到|1>
3. 對量子位元進行測量將結果儲存到經典暫存器中
4. 編譯程式並在模擬器上執行最後輸出測量結果

本章介紹了量子程式設計的基本概念和QISKit的使用方法。透過實作範例,我們展示瞭如何使用QISKit建立一個簡單的量子程式,並在模擬器上執行。未來,我們將繼續探索更複雜的量子演算法和應用。

QISKit SDK 內部運作:電路編譯與 QASM

QISKit 是一個強大的量子程式設計 SDK,它允許開發者在 Python 中編寫量子程式並在本地或遠端模擬器上執行。本章節將探討 QISKit 的內部運作,特別是在電路編譯和 QASM 方面的內容。

電路編譯

當你使用 QISKit 編寫一個量子程式時,它首先會被編譯成一個 JSON 檔案,該檔案包含了電路的描述和其他相關資訊。這個編譯過程是將你的程式轉換成模擬器可以理解的格式。

編譯格式

編譯後的 JSON 檔案包含了以下資訊:

  • 執行 ID
  • 後端模擬器的資訊(例如名稱、使用的點數等)
  • 電路的描述,包括名稱、量子位元的佈局、基礎閘(basis gates)等
  • 編譯後的電路,包括應用於電路的操作(閘)及其引數
{
  "id": "aA46vJHgnKQko3u5L1QqbUDk31sY2m",
  "config": {
    "max_credits": 10,
    "backend": "local_qasm_simulator",
    "shots": 1024
  },
  "circuits": [{
    "name": "Circuit",
    "config": {
      "coupling_map": "None",
      "layout": "None",
      "basis_gates": "u1,u2,u3,cx,id",
      "seed": "None"
    },
    #### 內容解密:
    - `"id"`:指定此次執行的唯一識別碼。
    - `"config"`:包含執行組態的詳細資訊,如最大積分點數、後端模擬器名稱和執行的次數(shots)。
    - `"circuits"`:陣列中包含一個或多個電路的描述,每個電路都有自己的名稱和組態。

QASM:量子組合語言

編譯後的電路還包括了一個 QASM(Quantum Assembly Language)表示。QASM是一種用於描述量子電路的語言,可以被 IBM Q Experience 的遠端模擬器理解和執行。

OPENQASM 2.0;
include "qelib1.inc";
qreg qr[1];
creg cr[1];
u3(3.141592653589793, 0.0, 3.141592653589793) qr[0];
measure qr[0] -> cr[0];

#### 內容解密:
- `OPENQASM 2.0;`:指定 QASM 的版本。
- `include "qelib1.inc";`:引入標準的量子閘函式庫。
- `qreg qr[1];` 和 `creg cr[1];`:宣告一個量子暫存器和一個經典暫存器,每個暫存器包含一個位元。
- `u3(3.141592653589793, 0.0, 3.141592653589793) qr[0];`:在量子位元 `qr[0]` 上應用一個 U3 閘,等同於 X 閘。
- `measure qr[0] -> cr[0];`:測量量子位元 `qr[0]` 並將結果儲存到經典位元 `cr[0]`。

執行結果

當模擬器執行編譯後的電路後,它會傳回一個結果檔案,該檔案包含了執行的結果,如測量的次數、執行的時間等。

{
  "backend": "local_qiskit_simulator",
  "id": "aA46vJHgnKQko3u5L1QqbUDk31sY2m",
  "result": [{
    "data": {
      "counts": {
        "1": 1024
      },
      "time_taken": 0.0780002
    },
    "name": "Circuit",
    "seed": 123,
    "shots": 1024,
    "status": "DONE",
    "success": true,
    "threads_shot": 4
  }],
  #### 內容解密:
  - `"backend"`:指定執行模擬的後端。
  - `"result"`:包含執行的結果,如測量結果的次數(counts)和執行時間(time_taken)。

QISKit 模擬器與真實量子裝置執行

QISKit 提供多種模擬器以滿足不同測試需求,包括本地模擬器和遠端模擬器。IBM Q Experience 的真實量子裝置存取受限於信用系統,因此使用模擬器進行測試是必要的。

本地模擬器

QISKit 預設使用純 Python 模擬器(local_qasm_simulator),但也可以使用高效的 C++ 模擬器(local_clifford_simulator 或 local_qiskit_simulator)。使用 C++ 模擬器需要注意以下事項:

  • Linux 使用者需要 gcc 5.3 或更高版本。
  • Windows 使用者需要使用 CMake 實用程式來建置模擬器。

C++ 模擬器的使用方法

  1. 將後端名稱更改為 local_clifford_simulatorlocal_qiskit_simulator
  2. 確保已安裝必要的建置工具。

遠端模擬器

要使用 IBM Q Experience 的遠端模擬器,需要進行以下更改:

  1. 將後端名稱更改為 ibmq_qasm_simulator
  2. 設定 API 引數,使用 qp.set_api() 方法。
  3. 使用 qp.execute() 方法執行電路。
backend = 'ibmqx_qasm_simulator'
qp.set_api(Qconfig.APItoken, Qconfig.config['url'])
result = qp.execute(circuits, backend, shots=512, max_credits=3, wait=10, timeout=240)

內容解密:

此段程式碼設定了遠端模擬器的後端名稱、API 引數,並執行了電路。qp.set_api() 方法用於設定 API 金鑰和 URL,而 qp.execute() 方法則用於執行電路並取得結果。

模擬器效能比較

經過測試,IBM Q Experience 的遠端模擬器表現最佳,其次是純 Python 模擬器,而 C++ 模擬器則表現最差。圖 4-6 展示了不同模擬器的執行時間。

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title 量子計算與量子程式設計入門

package "系統架構" {
    package "前端層" {
        component [使用者介面] as ui
        component [API 客戶端] as client
    }

    package "後端層" {
        component [API 服務] as api
        component [業務邏輯] as logic
        component [資料存取] as dao
    }

    package "資料層" {
        database [主資料庫] as db
        database [快取] as cache
    }
}

ui --> client : 使用者操作
client --> api : HTTP 請求
api --> logic : 處理邏輯
logic --> dao : 資料操作
dao --> db : 持久化
dao --> cache : 快取

note right of api
  RESTful API
  或 GraphQL
end note

@enduml

此圖示說明瞭不同模擬器的執行時間比較。

在真實量子裝置上執行

要修改程式以在真實量子裝置上執行,需要建立一個更複雜的電路。清單 4-6 展示了一個範例電路,該電路對量子電腦的第一個量子位元執行一系列旋轉操作。

# 建立電路
qc = QuantumCircuit(1)
qc.u3(theta, phi, lambda, 0)

內容解密:

此段程式碼建立了一個量子電路,並對第一個量子位元執行了 U3 旋轉操作。U3 門用於旋轉量子位元在 Bloch 球上的狀態。

Bloch 球表示法

Bloch 球是單個量子位元的幾何表示法,其中 Z 軸的頂部代表基態 |0>,底部代表 |1>。對給定軸的旋轉代表了在測量時量子位元當機到特定方向的機率。