量子位元的穩定性是量子計算發展的關鍵挑戰。本篇將探討如何利用 Qiskit 工具比較 IBM Quantum 後端中不同量子位元對的 CX 門錯誤率。藉由選取最佳和最差的量子位元對,並執行相同的量子程式,我們可以觀察到量子硬體的效能差異,並理解如何針對特定硬體特性最佳化量子程式。

from qiskit import IBMQ, Aer, QuantumCircuit, ClassicalRegister, QuantumRegister, execute
from qiskit.tools.monitor import job_monitor
from qiskit.visualization import plot_histogram
from IPython.core.display import display

# ... (省略載入帳號與供應商程式碼)

內容解密:

此段程式碼匯入了必要的 Qiskit 模組,包含用於量子電路建構、執行和視覺化的工具。同時,也初始化了與 IBM Quantum 後端的連線。

def select_backend():
    available_backends = provider.backends(filters=lambda b: not b.configuration().simulator and b.configuration().n_qubits > 1 and b.status().operational)
    # ... (省略印出後端資訊與選擇程式碼)
    return backend

內容解密:

select_backend() 函式用於篩選可用的 IBM Quantum 後端,排除模擬器,並確保所選後端至少具有兩個量子位元且處於運作狀態。

def get_gate_info(backend):
    gates = backend.properties().gates
    cx_best_worst = [[[0, 0], 1], [[0, 0], 0]]
    # ... (省略CX門資訊擷取程式碼)
    return cx_best_worst

內容解密:

get_gate_info() 函式用於取得指定後端的 CX 門錯誤率資訊,並找出最佳和最差的量子位元對。

def create_circuits(backend, cx_best_worst):
    q1 = QuantumRegister(backend.configuration().n_qubits)
    c1 = ClassicalRegister(backend.configuration().n_qubits)
    qc_best = QuantumCircuit(q1, c1)
    qc_worst = QuantumCircuit(q1, c1)
    # ... (省略量子線路建構程式碼)
    return qc_best, qc_worst

內容解密:

create_circuits() 函式根據最佳和最差的 CX 門資訊,建立兩個量子線路,分別應用於對應的量子位元對。

def compare_cx(backend, qc_best, qc_worst):
    job_best = execute(qc_best, backend, shots=8192)
    job_monitor(job_best)
    job_worst = execute(qc_worst, backend, shots=8192)
    job_monitor(job_worst)
    # ... (省略結果處理與視覺化程式碼)

內容解密:

compare_cx() 函式在指定的後端上執行兩個量子線路,並將結果與模擬器結果進行比較,最後以直方圖呈現,方便觀察不同量子位元對的效能差異。

透過以上步驟,我們可以清楚地比較不同量子位元對的 CX 門錯誤率,並藉此評估量子硬體的效能。這對於設計更穩健的量子演算法至關重要,因為選擇適當的量子位元可以有效降低錯誤率,提高計算結果的可靠性。

8.3 比較同一塊晶片上的量子位元

本文將在一個選定的後端上實際比較同一個後端上的不同量子位元。示例將根據3種不同的設定,即理想量子電腦(qasm_simulator)、最空閒的5量子位元IBM Quantum裝置上的最佳量子位元對和最差量子位元對,執行同一個貝爾態量子程式。

8.3.1 準備工作

可以從本文 GitHub 倉函式庫中對應第8章的目錄中下載本文示例的 Python 檔案 ch8_r2_compare_qubits.py

示例程式碼

  1. 匯入所需的Qiskit類別和方法,並登入自己的帳號

    from qiskit import IBMQ, Aer, QuantumCircuit, ClassicalRegister, QuantumRegister, execute
    from qiskit.tools.monitor import job_monitor
    from qiskit.visualization import plot_histogram, plot_error_map
    from IPython.core.display import display
    print("Getting provider...")
    if not IBMQ.active_account():
        IBMQ.load_account()
    provider = IBMQ.get_provider()
    
  2. 使用函式 select_backend() 選擇一個可用的後端

    def select_backend():
        available_backends = provider.backends(filters=lambda b: not b.configuration().simulator and b.configuration().n_qubits > 1 and b.status().operational)
        print("{0:20} {1:<10} {2:<10}".format("Name", "#Qubits", "Pending jobs"))
        print("{0:20} {1:<10} {2:<10}".format("----", "-------", "------------"))
        for n in range(0, len(available_backends)):
            # ...
    

透過比較理想量子電腦和真實IBM Quantum裝置上的量子位元效能,可以深入理解當前NISQ機器的本質和侷限性,並進一步探索如何最佳化量子程式以適應真實量子硬體的特性。#### 內容解密: 此段程式碼的主要功能是選擇一個可用的量子計算後端,並顯示其相關資訊。以下將逐行詳細解析程式碼的作用、設計邏輯及技術原理:

  1. def select_backend():

    • 定義了一個名為 select_backend 的函式,用於選擇一個可用的量子計算後端。
    • 設計邏輯:封裝後端選擇的邏輯,使其可重複呼叫。
    • 技術原理:利用 Qiskit 的 provider.backends() 方法取得可用後端列表。
  2. available_backends = provider.backends(filters=lambda b: not b.configuration().simulator and b.configuration().n_qubits > 1 and b.status().operational)

    • 取得所有可用的、非模擬器且具有多於1個量子位元的後端,並且這些後端必須處於可操作狀態。
    • 作用:篩選出符合條件的後端,以供使用者選擇。
    • 技術原理:使用 Qiskit 的 backends() 方法並結合 lambda 函式進行篩選。
  3. print("{0:20} {1:<10} {2:<10}".format("Name", "#Qubits", "Pending jobs"))

    • 列印預表頭,顯示後端名稱、量子位元數量和待處理任務數。
    • 作用:提供清晰的輸出格式,方便使用者理解後端資訊。
    • 設計邏輯:使用字串格式化來對齊輸出,使資訊更易讀。
  4. for n in range(0, len(available_backends)):

    • 遍歷所有可用的後端,並逐一顯示其名稱、量子位元數量等資訊。
    • 作用:列出所有符合條件的後端供使用者選擇。
    • 技術原理:利用迴圈遍歷後端列表,並使用 get_backend() 方法取得後端物件。
  5. select_backend = input("Select a backend ('exit' to end): ")

    • 提示使用者輸入想要選擇的後端名稱,或輸入 ’exit’ 以離開。
    • 作用:允許使用者根據顯示的資訊選擇特定的後端。
    • 設計邏輯:使用 input() 函式取得使用者輸入,並提供離開選項。
  6. if select_backend != "exit": backend = provider.get_backend(select_backend)

    • 如果使用者輸入的不是 ’exit’,則根據輸入的名稱取得對應的後端物件。
    • 作用:將使用者選擇的後端名稱對映到實際的後端物件。
    • 技術原理:使用 provider.get_backend() 方法根據名稱取得後端。
  7. return backend

    • 傳回使用者選擇的後端物件。
    • 作用:將選擇的後端傳回給呼叫者,以便進一步操作。
    • 設計邏輯:封裝選擇邏輯,使呼叫者可以直接使用傳回的後端物件。
圖表翻譯:

此圖展示了使用者如何透過 select_backend() 函式選擇一個可用的量子計算後端。下面是對圖表的詳細解釋:

  1. 取得可用後端列表

    • 程式碼首先呼叫 provider.backends() 方法,並使用 lambda 函式篩選出所有可用的、非模擬器且具有多於1個量子位元的後端。
    • 作用:列出當前可用的量子計算後端。
  2. 顯示後端資訊

    • 對每個可用的後端,程式碼列印其名稱、量子位元數量和待處理任務數。
    • 作用:為使用者提供詳細的後端資訊,以便做出選擇。
  3. 使用者輸入

    • 使用者根據顯示的後端列表輸入想要選擇的後端名稱,或輸入 ’exit’ 以離開程式。
    • 作用:允許使用者選擇特定的後端進行進一步操作。
  4. 取得選擇的後端

    • 如果使用者輸入的不是 ’exit’,程式碼根據輸入的名稱取得對應的後端物件。
    • 作用:將使用者的選擇對映到實際的後端物件。
  5. 傳回後端物件

    • 最終,程式碼傳回使用者選擇的後端物件。
    • 作用:供呼叫者使用選擇的後端進行後續的量子計算操作。

圖表關鍵點:

  • 可用後端列表:顯示所有符合條件的後端。
  • 使用者選擇:使用者根據列表選擇一個後端。
  • 後端資訊:包括後端名稱、量子位元數量和待處理任務數。

透過這個過程,使用者可以方便地選擇一個合適的量子計算後端,以進行接下來的量子程式執行和測試。

量子錯誤率分析與比較

實驗目的與步驟

本實驗旨在探討IBM Quantum後端中,不同量子位元對之間的CX門錯誤率差異。透過選取效能最佳和最差的量子位元對,執行相同的量子程式,並比較其輸出結果,以直觀瞭解量子硬體的效能差異。

步驟1:選擇後端

首先,我們需要選擇一個可用的IBM Quantum後端。以下程式碼片段展示瞭如何列出可用的後端並選擇一個進行測試:

backend = provider.get_backend(str(available_backends[n]))
print("{0:20} {1:<10}".format(backend.name(), backend.configuration().n_qubits), backend.status().pending_jobs)
select_backend = input("Select a backend ('LB' for least busy): ")
if select_backend not in ["LB", "lb"]:
    backend = provider.get_backend(str(select_backend))
else:
    from qiskit.providers.ibmq import least_busy
    backend = least_busy(provider.backends(filters=lambda b: not b.configuration().simulator and b.configuration().n_qubits > 1 and b.status().operational))
print("Selected backend:", backend.status().backend_name)
return backend

內容解密:

此段程式碼首先列出所有可用的後端及其相關資訊,包括名稱、量子位元數量和待處理的工作數量。使用者可以輸入後端名稱或輸入’LB’選擇最不繁忙的後端。

步驟2:取得CX門資訊

接下來,我們需要取得所選後端中CX門的錯誤率資訊,並找出效能最佳和最差的CX門。以下程式碼片段展示瞭如何實作這一步驟:

def get_gate_info(backend):
    gates = backend.properties().gates
    cx_best_worst = [[[0, 0], 1], [[0, 0], 0]]
    for n in range(0, len(gates)):
        if gates[n].gate == "cx":
            print(gates[n].name, ":", gates[n].parameters[0].name, "=", gates[n].parameters[0].value)
            if cx_best_worst[0][1] > gates[n].parameters[0].value:
                cx_best_worst[0][1] = gates[n].parameters[0].value
                cx_best_worst[0][0] = gates[n].qubits
            if cx_best_worst[1][1] < gates[n].parameters[0].value:
                cx_best_worst[1][1] = gates[n].parameters[0].value
                cx_best_worst[1][0] = gates[n].qubits
    print("Best cx gate:", cx_best_worst[0][0], ",", round(cx_best_worst[0][1] * 100, 3), "%")
    print("Worst cx gate:", cx_best_worst[1][0], ",", round(cx_best_worst[1][1] * 100, 3), "%")
    return cx_best_worst

內容解密:

此函式遍歷後端的所有門操作,找出錯誤率最低和最高的CX門,並傳回相關資訊。

步驟3:建立量子線路

根據所選後端和取得的CX門資訊,我們建立兩個量子線路,分別對應效能最佳和最差的CX門。以下程式碼片段展示瞭如何建立這些量子線路:

def create_circuits(backend, cx_best_worst):
    q1 = QuantumRegister(backend.configuration().n_qubits)
    c1 = ClassicalRegister(backend.configuration().n_qubits)
    qc_best = QuantumCircuit(q1, c1)
    qc_worst = QuantumCircuit(q1, c1)
    # Best circuit
    qc_best.h(q1[cx_best_worst[0][0][0]])
    qc_best.cx(q1[cx_best_worst[0][0][0]], q1[cx_best_worst[0][0][1]])
    qc_best.measure(q1[cx_best_worst[0][0][0]], c1[0])
    qc_best.measure(q1[cx_best_worst[0][0][1]], c1[1])
    # Worst circuit
    qc_worst.h(q1[cx_best_worst[1][0][0]])
    qc_worst.cx(q1[cx_best_worst[1][0][0]], q1[cx_best_worst[1][0][1]])
    qc_worst.measure(q1[cx_best_worst[1][0][0]], c1[0])
    qc_worst.measure(q1[cx_best_worst[1][0][1]], c1[1])
    return qc_best, qc_worst

內容解密:

此函式根據效能最佳和最差的CX門資訊,建立兩個量子線路,並對其進行測量。

步驟4:比較CX門效能

最後,我們在所選後端上執行這兩個量子線路,並比較其輸出結果。以下程式碼片段展示瞭如何實作這一步驟:

def compare_cx(backend, qc_best, qc_worst):
    job_best = execute(qc_best, backend, shots=8192)
    job_monitor(job_best)
    job_worst = execute(qc_worst, backend, shots=8192)
    job_monitor(job_worst)
    # 取得結果並繪製直方圖
    best_result = job_best.result()
    counts_best = best_result.get_counts(qc_best)
    worst_result = job_worst.result()
    counts_worst = worst_result.get_counts(qc_worst)
    # 模擬結果作為對照
    backend_sim = Aer.get_backend('qasm_simulator')
    job_sim = execute(qc_best, backend_sim)
    sim_result = job_sim.result()
    counts_sim = sim_result.get_counts(qc_best)
    display(plot_histogram([counts_best, counts_worst, counts_sim], title="Best and worst qubit pair for: " + backend.name(),
                            legend=["Best qubit pair", "Worst qubit pair", "Simulated baseline"], sort='desc', figsize=(15, 12),
                            color=['green', 'red', 'blue'], bar_labels=True))

內容解密:

此函式在所選後端上執行兩個量子線路,並將結果與模擬結果進行比較,最終繪製直方圖展示差異。