ข้ามไปยังเนื้อหาหลัก
โครงการนี้อยู่ในช่วงเบต้า พบข้อผิดพลาด? สร้าง GitHub Issue มีคำถามหรือไอเดีย? ถามใน Discussions — ยินดีรับฟังความคิดเห็น!
คุณภาพการแปลในหน้านี้เป็นอย่างไร?

สร้าง Noise Models

Package versions

โค้ดในหน้านี้พัฒนาโดยใช้ข้อกำหนดต่อไปนี้ เราแนะนำให้ใช้เวอร์ชันเหล่านี้หรือใหม่กว่า

qiskit[all]~=2.5.2
qiskit-ibm-runtime~=0.49.0
qiskit-aer~=0.17

หน้านี้แสดงวิธีใช้โมดูล Qiskit Aer noise เพื่อสร้าง noise model สำหรับจำลอง quantum circuit ในสภาวะที่มีข้อผิดพลาด สิ่งนี้มีประโยชน์สำหรับการจำลอง quantum processor ที่มี noise และสำหรับการศึกษาผลกระทบของ noise ต่อการทำงานของ quantum algorithm

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"numpy": "numpy", "qiskit": "qiskit", "qiskit_aer": "qiskit-aer", "qiskit_ibm_runtime": "qiskit-ibm-runtime"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
import numpy as np
from qiskit import QuantumCircuit
from qiskit.quantum_info import Kraus, SuperOp
from qiskit.visualization import plot_histogram
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_aer import AerSimulator

# Import from Qiskit Aer noise module
from qiskit_aer.noise import (
NoiseModel,
QuantumError,
ReadoutError,
depolarizing_error,
pauli_error,
thermal_relaxation_error,
)

โมดูล noise ของ Qiskit Aer​

โมดูล noise ของ Qiskit Aer มีคลาส Python สำหรับสร้าง noise model แบบกำหนดเองสำหรับการจำลอง โดยมีสามคลาสหลักดังนี้

  1. คลาส NoiseModel ซึ่งเก็บ noise model ที่ใช้สำหรับการจำลองแบบมี noise

  2. คลาส QuantumError ซึ่งอธิบาย CPTP gate error โดยสามารถนำไปใช้ได้:

    • หลังคำสั่ง gate หรือ reset

    • ก่อนคำสั่ง measure

  3. คลาส ReadoutError ซึ่งอธิบาย classical readout error

กำหนดค่า noise model จาก Backend​

สามารถกำหนดค่า noise model โดยใช้พารามิเตอร์จากข้อมูลการสอบเทียบล่าสุดของ Backend จริงได้

หมายเหตุ

ตัวอย่างเหล่านี้ใช้ mock backend FakeSherbrooke จาก qiskit_ibm_runtime แต่คุณสามารถลองใช้กับ backend จริงหรือ backend ปลอมใด ๆ ที่เข้ากันได้กับ Qiskit ก็ได้

from qiskit_ibm_runtime.fake_provider import FakeSherbrooke

backend = FakeSherbrooke()
noise_model = NoiseModel.from_backend(backend)

การทำเช่นนี้จะได้ noise model ที่ประมาณข้อผิดพลาดคร่าว ๆ ที่จะพบเมื่อใช้ Backend นั้น หากต้องการควบคุมพารามิเตอร์ของ noise model อย่างละเอียดกว่านี้ จำเป็นต้องสร้าง noise model เอง ตามที่อธิบายในส่วนที่เหลือของหน้านี้

ข้อผิดพลาดควอนตัม​

แทนที่จะจัดการกับออบเจกต์ QuantumError โดยตรง มีฟังก์ชันช่วยหลายตัวสำหรับสร้าง quantum error ชนิดต่าง ๆ แบบพารามิเตอร์โดยอัตโนมัติ ฟังก์ชันเหล่านี้อยู่ในโมดูล noise และครอบคลุม error ประเภทที่ใช้บ่อยในงานวิจัยคอมพิวเตอร์ควอนตัม ชื่อฟังก์ชันและประเภท error ที่คืนค่ากลับมาได้แก่

ฟังก์ชัน error มาตรฐานรายละเอียด
kraus_errorerror channel CPTP แบบ n-qubit ทั่วไป ระบุเป็นรายการ Kraus matrices [K0,...][K_0, ...]
mixed_unitary_errormixed unitary error แบบ n-qubit ระบุเป็นรายการ unitary matrices และความน่าจะเป็น [(U0,p0),...][(U_0, p_0),...]
coherent_unitary_errorcoherent unitary error แบบ n-qubit ระบุเป็น unitary matrix เดี่ยว UU
pauli_errorPauli error channel แบบ n-qubit (mixed unitary) ระบุเป็นรายการ Pauli และความน่าจะเป็น [(P0,p0),...][(P_0, p_0),...]
depolarizing_errordepolarizing error channel แบบ n-qubit กำหนดพารามิเตอร์ด้วยความน่าจะเป็น depolarization pp
reset_errorreset error แบบ single-qubit กำหนดพารามิเตอร์ด้วยความน่าจะเป็น p0,p1p_0, p_1 ของการรีเซ็ตไปยังสถานะ ∣0⟩\vert0\rangle, ∣1⟩\vert1\rangle
thermal_relaxation_errorthermal relaxation channel แบบ single qubit กำหนดพารามิเตอร์ด้วยค่าคงที่เวลาผ่อนคลาย T1T_1, T2T_2, เวลา gate tt, และประชากรเชิงความร้อนของสถานะกระตุ้น p1p_1
phase_amplitude_damping_errorgeneralized combined phase and amplitude damping error channel แบบ single-qubit ระบุด้วยพารามิเตอร์ amplitude damping λ\lambda, พารามิเตอร์ phase damping γ\gamma, และประชากรเชิงความร้อนของสถานะกระตุ้น p1p_1
amplitude_damping_errorgeneralized amplitude damping error channel แบบ single-qubit ระบุด้วยพารามิเตอร์ amplitude damping λ\lambda, และประชากรเชิงความร้อนของสถานะกระตุ้น p1p_1
phase_damping_errorphase damping error channel แบบ single-qubit ระบุด้วยพารามิเตอร์ phase damping γ\gamma

รวม quantum errors​

อินสแตนซ์ QuantumError สามารถรวมกันได้โดยใช้การประกอบ (composition) ผลคูณเทนเซอร์ (tensor product) และการขยายเทนเซอร์ (reversed order tensor product) เพื่อสร้าง QuantumErrors ใหม่ได้ดังนี้:

  • Composition: E(ρ)=E2(E1(ρ))\cal{E}(\rho)=\cal{E_2}(\cal{E_1}(\rho)) เขียนเป็น error = error1.compose(error2)

  • Tensor product: E(ρ)=(E1⊗E2)(ρ)\cal{E}(\rho) =(\cal{E_1}\otimes\cal{E_2})(\rho) เขียนเป็น error = error1.tensor(error2)

  • Expand product: E(ρ)=(E2⊗E1)(ρ)\cal{E}(\rho) =(\cal{E_2}\otimes\cal{E_1})(\rho) เขียนเป็น error = error1.expand(error2)

ตัวอย่าง​

การสร้าง single-qubit bit-flip error 5%:

# Construct a 1-qubit bit-flip and phase-flip errors
p_error = 0.05
bit_flip = pauli_error([("X", p_error), ("I", 1 - p_error)])
phase_flip = pauli_error([("Z", p_error), ("I", 1 - p_error)])
print(bit_flip)
print(phase_flip)
QuantumError on 1 qubits. Noise circuits:
P(0) = 0.05, Circuit =
┌───┐
q: ┤ X ├
└───┘
P(1) = 0.95, Circuit =
┌───┐
q: ┤ I ├
└───┘
QuantumError on 1 qubits. Noise circuits:
P(0) = 0.05, Circuit =
┌───┐
q: ┤ Z ├
└───┘
P(1) = 0.95, Circuit =
┌───┐
q: ┤ I ├
└───┘
# Compose two bit-flip and phase-flip errors
bitphase_flip = bit_flip.compose(phase_flip)
print(bitphase_flip)
QuantumError on 1 qubits. Noise circuits:
P(0) = 0.0025000000000000005, Circuit =
┌───┐┌───┐
q: ┤ X ├┤ Z ├
└───┘└───┘
P(1) = 0.0475, Circuit =
┌───┐┌───┐
q: ┤ X ├┤ I ├
└───┘└───┘
P(2) = 0.0475, Circuit =
┌───┐┌───┐
q: ┤ I ├┤ Z ├
└───┘└───┘
P(3) = 0.9025, Circuit =
┌───┐┌───┐
q: ┤ I ├┤ I ├
└───┘└───┘
# Tensor product two bit-flip and phase-flip errors with
# bit-flip on qubit-0, phase-flip on qubit-1
error2 = phase_flip.tensor(bit_flip)
print(error2)
QuantumError on 2 qubits. Noise circuits:
P(0) = 0.0025000000000000005, Circuit =
┌───┐
q_0: ┤ X ├
├───┤
q_1: ┤ Z ├
└───┘
P(1) = 0.0475, Circuit =
┌───┐
q_0: ┤ I ├
├───┤
q_1: ┤ Z ├
└───┘
P(2) = 0.0475, Circuit =
┌───┐
q_0: ┤ X ├
├───┤
q_1: ┤ I ├
└───┘
P(3) = 0.9025, Circuit =
┌───┐
q_0: ┤ I ├
├───┤
q_1: ┤ I ├
└───┘

แปลงไปและกลับจาก QuantumChannel operators​

สามารถแปลงระหว่างออบเจกต์ QuantumError ใน Qiskit Aer และออบเจกต์ QuantumChannel ใน Qiskit ได้ด้วย

# Convert to Kraus operator
bit_flip_kraus = Kraus(bit_flip)
print(bit_flip_kraus)
Kraus([[[-9.74679434e-01+0.j, 0.00000000e+00+0.j],
[ 0.00000000e+00+0.j, -9.74679434e-01+0.j]],

[[ 0.00000000e+00+0.j, 2.23606798e-01+0.j],
[ 2.23606798e-01+0.j, -4.96506831e-17+0.j]]],
input_dims=(2,), output_dims=(2,))
# Convert to Superoperator
phase_flip_sop = SuperOp(phase_flip)
print(phase_flip_sop)
SuperOp([[1. +0.j, 0. +0.j, 0. +0.j, 0. +0.j],
[0. +0.j, 0.9+0.j, 0. +0.j, 0. +0.j],
[0. +0.j, 0. +0.j, 0.9+0.j, 0. +0.j],
[0. +0.j, 0. +0.j, 0. +0.j, 1. +0.j]],
input_dims=(2,), output_dims=(2,))
# Convert back to a quantum error
print(QuantumError(bit_flip_kraus))

# Check conversion is equivalent to original error
QuantumError(bit_flip_kraus) == bit_flip
QuantumError on 1 qubits. Noise circuits:
P(0) = 1.0, Circuit =
┌───────┐
q: ┤ kraus ├
└───────┘
True

ข้อผิดพลาดการอ่านค่า (Readout error)​

Classical readout error ระบุเป็นรายการ assignment probability vectors P(A∣B)P(A|B):

  • AA คือค่า classical bit ที่ บันทึกไว้

  • BB คือค่า bit จริง ที่ได้จากการวัด

ตัวอย่างเช่น สำหรับหนึ่ง Qubit: P(A∣B)=[P(A∣0),P(A∣1)] P(A|B) = [P(A|0), P(A|1)]

# Measurement misassignment probabilities
p0given1 = 0.1
p1given0 = 0.05

ReadoutError([[1 - p1given0, p1given0], [p0given1, 1 - p0given1]])
ReadoutError([[0.95 0.05]
[0.1 0.9 ]])

Readout error ยังสามารถรวมกันได้โดยใช้ compose, tensor และ expand เช่นเดียวกับ quantum error

การเพิ่ม error เข้าไปใน noise model​

เมื่อเพิ่ม quantum error เข้าไปใน noise model ต้องระบุประเภท instruction ที่มันทำงานและ Qubit ที่จะนำไปใช้ มี quantum error สองกรณีดังนี้

  1. ข้อผิดพลาดควอนตัมแบบ all-qubit

  2. ข้อผิดพลาดควอนตัมของ qubit เฉพาะ

1. ข้อผิดพลาดควอนตัมแบบ all-qubit​

ใช้ error เดียวกันกับทุกครั้งที่พบ instruction นั้น ไม่ว่ามันจะทำงานบน Qubit ใดก็ตาม

เพิ่มด้วย noise_model.add_all_qubit_quantum_error(error, instructions):

# Create an empty noise model
noise_model = NoiseModel()

# Add depolarizing error to all single qubit u1, u2, u3 gates
error = depolarizing_error(0.05, 1)
noise_model.add_all_qubit_quantum_error(error, ["u1", "u2", "u3"])

# Print noise model info
print(noise_model)
NoiseModel:
Basis gates: ['cx', 'id', 'rz', 'sx', 'u1', 'u2', 'u3']
Instructions with noise: ['u1', 'u2', 'u3']
All-qubits errors: ['u1', 'u2', 'u3']

2. ข้อผิดพลาดควอนตัมของ qubit เฉพาะ​

ใช้ error กับทุก instruction ที่ทำงานบน Qubit ที่ระบุในรายการ สังเกตว่าลำดับของ Qubit มีความสำคัญ ตัวอย่างเช่น error ที่ใช้กับ Qubit [0, 1] สำหรับ two-qubit gate ต่างจาก error ที่ใช้กับ Qubit [1, 0]

เพิ่มด้วย noise_model.add_quantum_error(error, instructions, qubits):

# Create an empty noise model
noise_model = NoiseModel()

# Add depolarizing error to all single qubit u1, u2, u3 gates on qubit 0 only
error = depolarizing_error(0.05, 1)
noise_model.add_quantum_error(error, ["u1", "u2", "u3"], [0])

# Print noise model info
print(noise_model)
NoiseModel:
Basis gates: ['cx', 'id', 'rz', 'sx', 'u1', 'u2', 'u3']
Instructions with noise: ['u1', 'u2', 'u3']
Qubits with noise: [0]
Specific qubit errors: [('u1', (0,)), ('u2', (0,)), ('u3', (0,))]

หมายเหตุเกี่ยวกับ non-local qubit quantum error​

NoiseModel ไม่รองรับการเพิ่ม non-local qubit quantum error ควรจัดการนอก NoiseModel นั่นหมายความว่าถ้าต้องการแทรก quantum error เข้าไปใน Circuit ภายใต้เงื่อนไขของตัวเอง ควรเขียน transpiler pass ของตัวเอง (TransformationPass) และรัน pass นั้นทันทีก่อนรัน simulator

การรันการจำลองแบบมีสัญญาณรบกวนด้วย noise model​

คำสั่ง AerSimulator(noise_model=noise_model) คืนค่า simulator ที่กำหนดค่าตาม noise model ที่ระบุ นอกจากตั้งค่า noise model ของ simulator แล้ว ยังแทนที่ basis gate ของ simulator ตาม gate ของ noise model ด้วย

ตัวอย่าง noise model​

ต่อไปนี้จะแสดงตัวอย่าง noise model สำหรับการสาธิต เราใช้ Circuit ทดสอบง่าย ๆ ที่สร้างสถานะ GHZ แบบ n-qubit:

# System Specification
n_qubits = 4
circ = QuantumCircuit(n_qubits)

# Test Circuit
circ.h(0)
for qubit in range(n_qubits - 1):
circ.cx(qubit, qubit + 1)
circ.measure_all()
print(circ)
┌───┐ ░ ┌─┐
q_0: ┤ H ├──■─────────────░─┤M├─────────
└───┘┌─┴─┐ ░ └╥┘┌─┐
q_1: ─────┤ X ├──■────────░──╫─┤M├──────
└───┘┌─┴─┐ ░ ║ └╥┘┌─┐
q_2: ──────────┤ X ├──■───░──╫──╫─┤M├───
└───┘┌─┴─┐ ░ ║ ║ └╥┘┌─┐
q_3: ───────────────┤ X ├─░──╫──╫──╫─┤M├
└───┘ ░ ║ ║ ║ └╥┘
meas: 4/════════════════════════╩══╩══╩══╩═
0 1 2 3

การจำลองในอุดมคติ​

# Ideal simulator and execution
sim_ideal = AerSimulator()
result_ideal = sim_ideal.run(circ).result()
plot_histogram(result_ideal.get_counts(0))

Output of the previous code cell

ตัวอย่าง noise 1: noise model แบบ bit-flip error พื้นฐาน​

มาดูตัวอย่าง toy noise model อย่างง่ายที่พบบ่อยในการวิจัยทฤษฎีสารสนเทศควอนตัม:

  • เมื่อใช้ Gate แบบ single-qubit จะพลิกสถานะของ Qubit ด้วยความน่าจะเป็น p_gate1

  • เมื่อใช้ Gate แบบ two-qubit จะใส่ความผิดพลาดของ single-qubit ให้กับแต่ละ Qubit

  • เมื่อรีเซ็ต Qubit จะรีเซ็ตเป็น 1 แทนที่จะเป็น 0 ด้วยความน่าจะเป็น p_reset

  • เมื่อวัดค่า Qubit จะพลิกสถานะของ Qubit ด้วยความน่าจะเป็น p_meas

# Example error probabilities
p_reset = 0.03
p_meas = 0.1
p_gate1 = 0.05

# QuantumError objects
error_reset = pauli_error([("X", p_reset), ("I", 1 - p_reset)])
error_meas = pauli_error([("X", p_meas), ("I", 1 - p_meas)])
error_gate1 = pauli_error([("X", p_gate1), ("I", 1 - p_gate1)])
error_gate2 = error_gate1.tensor(error_gate1)

# Add errors to noise model
noise_bit_flip = NoiseModel()
noise_bit_flip.add_all_qubit_quantum_error(error_reset, "reset")
noise_bit_flip.add_all_qubit_quantum_error(error_meas, "measure")
noise_bit_flip.add_all_qubit_quantum_error(error_gate1, ["u1", "u2", "u3"])
noise_bit_flip.add_all_qubit_quantum_error(error_gate2, ["cx"])

print(noise_bit_flip)
NoiseModel:
Basis gates: ['cx', 'id', 'rz', 'sx', 'u1', 'u2', 'u3']
Instructions with noise: ['reset', 'u2', 'measure', 'cx', 'u3', 'u1']
All-qubits errors: ['reset', 'measure', 'u1', 'u2', 'u3', 'cx']

รันการจำลองแบบมี noise​

# Create noisy simulator backend
sim_noise = AerSimulator(noise_model=noise_bit_flip)

# Transpile circuit for noisy basis gates
passmanager = generate_preset_pass_manager(
optimization_level=3, backend=sim_noise
)
circ_tnoise = passmanager.run(circ)

# Run and get counts
result_bit_flip = sim_noise.run(circ_tnoise).result()
counts_bit_flip = result_bit_flip.get_counts(0)

# Plot noisy output
plot_histogram(counts_bit_flip)

Output of the previous code cell

ตัวอย่างที่ 2: การผ่อนคลายเชิงความร้อนแบบ T1/T2​

ลองพิจารณาโมเดลความผิดพลาดที่สมจริงมากขึ้น โดยอ้างอิงจากการผ่อนคลายเชิงความร้อนกับสภาพแวดล้อมของ Qubit:

  • แต่ละ Qubit ถูกกำหนดพารามิเตอร์ด้วยค่าคงที่เวลาการผ่อนคลายเชิงความร้อน T1T_1 และค่าคงที่เวลาการสูญเสียเฟส T2T_2
  • โปรดทราบว่าเราต้องมี T2≤2T1T_2 \le 2 T_1
  • อัตราความผิดพลาดในคำสั่งต่าง ๆ ถูกกำหนดโดยเวลาของ Gate และค่า T1T_1, T2T_2 ของแต่ละ Qubit
# T1 and T2 values for qubits 0-3
T1s = np.random.normal(
50e3, 10e3, 4
) # Sampled from normal distribution mean 50 microsec
T2s = np.random.normal(
70e3, 10e3, 4
) # Sampled from normal distribution mean 50 microsec

# Truncate random T2s <= T1s
T2s = np.array([min(T2s[j], 2 * T1s[j]) for j in range(4)])

# Instruction times (in nanoseconds)
time_u1 = 0 # virtual gate
time_u2 = 50 # (single X90 pulse)
time_u3 = 100 # (two X90 pulses)
time_cx = 300
time_reset = 1000 # 1 microsecond
time_measure = 1000 # 1 microsecond

# QuantumError objects
errors_reset = [
thermal_relaxation_error(t1, t2, time_reset) for t1, t2 in zip(T1s, T2s)
]
errors_measure = [
thermal_relaxation_error(t1, t2, time_measure) for t1, t2 in zip(T1s, T2s)
]
errors_u1 = [
thermal_relaxation_error(t1, t2, time_u1) for t1, t2 in zip(T1s, T2s)
]
errors_u2 = [
thermal_relaxation_error(t1, t2, time_u2) for t1, t2 in zip(T1s, T2s)
]
errors_u3 = [
thermal_relaxation_error(t1, t2, time_u3) for t1, t2 in zip(T1s, T2s)
]
errors_cx = [
[
thermal_relaxation_error(t1a, t2a, time_cx).expand(
thermal_relaxation_error(t1b, t2b, time_cx)
)
for t1a, t2a in zip(T1s, T2s)
]
for t1b, t2b in zip(T1s, T2s)
]

# Add errors to noise model
noise_thermal = NoiseModel()
for j in range(4):
noise_thermal.add_quantum_error(errors_reset[j], "reset", [j])
noise_thermal.add_quantum_error(errors_measure[j], "measure", [j])
noise_thermal.add_quantum_error(errors_u1[j], "u1", [j])
noise_thermal.add_quantum_error(errors_u2[j], "u2", [j])
noise_thermal.add_quantum_error(errors_u3[j], "u3", [j])
for k in range(4):
noise_thermal.add_quantum_error(errors_cx[j][k], "cx", [j, k])

print(noise_thermal)
NoiseModel:
Basis gates: ['cx', 'id', 'rz', 'sx', 'u2', 'u3']
Instructions with noise: ['reset', 'u2', 'measure', 'cx', 'u3']
Qubits with noise: [0, 1, 2, 3]
Specific qubit errors: [('reset', (0,)), ('reset', (1,)), ('reset', (2,)), ('reset', (3,)), ('measure', (0,)), ('measure', (1,)), ('measure', (2,)), ('measure', (3,)), ('u2', (0,)), ('u2', (1,)), ('u2', (2,)), ('u2', (3,)), ('u3', (0,)), ('u3', (1,)), ('u3', (2,)), ('u3', (3,)), ('cx', (0, 0)), ('cx', (0, 1)), ('cx', (0, 2)), ('cx', (0, 3)), ('cx', (1, 0)), ('cx', (1, 1)), ('cx', (1, 2)), ('cx', (1, 3)), ('cx', (2, 0)), ('cx', (2, 1)), ('cx', (2, 2)), ('cx', (2, 3)), ('cx', (3, 0)), ('cx', (3, 1)), ('cx', (3, 2)), ('cx', (3, 3))]

รันการจำลองแบบมี noise​

# Run the noisy simulation
sim_thermal = AerSimulator(noise_model=noise_thermal)

# Transpile circuit for noisy basis gates
passmanager = generate_preset_pass_manager(
optimization_level=3, backend=sim_thermal
)
circ_tthermal = passmanager.run(circ)

# Run and get counts
result_thermal = sim_thermal.run(circ_tthermal).result()
counts_thermal = result_thermal.get_counts(0)

# Plot noisy output
plot_histogram(counts_thermal)

Output of the previous code cell

ขั้นตอนถัดไป​

คำแนะนำ