ข้ามไปยังเนื้อหาหลัก

สร้าง noise models

เวอร์ชันของแพ็กเกจ

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

qiskit[all]~=2.3.0
qiskit-ibm-runtime~=0.43.1
qiskit-aer~=0.17

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

# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-aer qiskit-ibm-runtime
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 ที่ใช้สำหรับการจำลองแบบมีสัญญาณรบกวน

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

    • หลังคำสั่ง gate หรือ reset
    • ก่อนคำสั่ง measure
  3. คลาส ReadoutError ซึ่งอธิบาย classical readout error

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

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

from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
backend = service.backend("ibm_fez")
noise_model = NoiseModel.from_backend(backend)

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

Quantum errors

แทนที่จะจัดการกับออบเจกต์ 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, และ tensor expansion (tensor product ในลำดับกลับ) เพื่อสร้าง QuantumError ใหม่ ดังนี้

  • Composition: E(ρ)=E2(E1(ρ))\cal{E}(\rho)=\cal{E_2}(\cal{E_1}(\rho)) เขียนเป็น error = error1.compose(error2)
  • Tensor product: E(ρ)=(E1E2)(ρ)\cal{E}(\rho) =(\cal{E_1}\otimes\cal{E_2})(\rho) เขียนเป็น error = error1.tensor(error2)
  • Expand product: E(ρ)=(E2E1)(ρ)\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(AB)P(A|B):

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

ตัวอย่างเช่น สำหรับหนึ่ง Qubit: P(AB)=[P(A0),P(A1)] 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 quantum error
  2. Specific qubit quantum error

1. All-qubit quantum error

ใช้ 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: ['u3', 'u2', 'u1']
All-qubits errors: ['u1', 'u2', 'u3']

2. Specific qubit quantum error

ใช้ 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: ['u3', 'u2', 'u1']
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

ตัวอย่างเสียงรบกวน 1: โมเดลเสียงรบกวนแบบ bit-flip พื้นฐาน

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

  • เมื่อใช้ 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: ['u3', 'u2', 'measure', 'cx', 'reset', 'u1']
All-qubits errors: ['reset', 'measure', 'u1', 'u2', 'u3', 'cx']

รันการจำลองแบบมีเสียงรบกวน

# 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
  • โปรดทราบว่าเราต้องมี T22T1T_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: ['u3', 'u2', 'measure', 'cx', 'reset']
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))]

รันการจำลองแบบมีเสียงรบกวน

# 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

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

คำแนะนำ
Source: IBM Quantum docs — updated 27 เม.ย. 2569
English version on doQumentation — updated 7 พ.ค. 2569
This translation based on the English version of 11 มี.ค. 2569