สร้าง Noise Models
Package versions
โค้ดในหน้านี้พัฒนาโดยใช้ข้อกำหนดต่อไปนี้ เราแนะนำให้ใช้เวอร์ชันเหล่านี้หรือใหม่กว่า
qiskit[all]~=2.5.2
qiskit-ibm-runtime~=0.47.0
qiskit-aer~=0.17
หน้านี้แสดงวิธีใช้โมดูล Qiskit Aer noise เพื่อสร้าง noise model สำหรับจำลอง quantum circuit ในสภาวะที่มีข้อผิดพลาด สิ่งนี้มีประโยชน์สำหรับการจำลอง quantum processor ที่มี noise และสำหรับการศึกษาผลกระทบของ noise ต่อการทำงานของ quantum algorithm
# 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 แบบกำหนดเองสำหรับการจำลอง โดยมีสามคลาสหลักดังนี้
-
คลาส
NoiseModelซึ่งเก็บ noise model ที่ใช้สำหรับการจำลองแบบมีสัญญาณรบกวน -
คลาส
QuantumErrorซึ่งอธิบาย CPTP gate error โดยสามารถนำไปใช้ได้:-
หลังคำสั่ง gate หรือ reset
-
ก่อนคำสั่ง measure
-
-
คลาส
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_error | error channel CPTP แบบ n-qubit ทั่วไป ระบุเป็นรายการ Kraus matrices |
mixed_unitary_error | mixed unitary error แบบ n-qubit ระบุเป็นรายการ unitary matrices และความน่าจะเป็น |
coherent_unitary_error | coherent unitary error แบบ n-qubit ระบุเป็น unitary matrix เดี่ยว |
pauli_error | Pauli error channel แบบ n-qubit (mixed unitary) ระบุเป็นรายการ Pauli และความน่าจะเป็น |
depolarizing_error | depolarizing error channel แบบ n-qubit กำหนดพารามิเตอร์ด้วยความน่าจะเป็น depolarization |
reset_error | reset error แบบ single-qubit กำหนดพารามิเตอร์ด้วยความน่าจะเป็น ของการรีเซ็ตไปยังสถานะ , |
thermal_relaxation_error | thermal relaxation channel แบบ single qubit กำหนดพารามิเตอร์ด้วยค่าคงที่เวลาผ่อนคลาย , , เวลา gate , และประชากรเชิงความร้อนของสถานะกระตุ้น |
phase_amplitude_damping_error | generalized combined phase and amplitude damping error channel แบบ single-qubit ระบุด้วยพารามิเตอร์ amplitude damping , พารามิเตอร์ phase damping , และประชากรเชิงความร้อนของสถานะกระตุ้น |
amplitude_damping_error | generalized amplitude damping error channel แบบ single-qubit ระบุด้วยพารามิเตอร์ amplitude damping , และประชากรเชิงความร้อนของสถานะกระตุ้น |
phase_damping_error | phase damping error channel แบบ single-qubit ระบุด้วยพารามิเตอร์ phase damping |
รวม quantum errors
อินสแตนซ์ QuantumError สามารถรวมกันได้โดยใช้การประกอบ (composition) ผลคูณเทนเซอร์ (tensor product) และการขยายเทนเซอร์ (reversed order tensor product) เพื่อสร้าง QuantumErrors ใหม่ได้ดังนี้:
-
Composition: เขียนเป็น
error = error1.compose(error2) -
Tensor product: เขียนเป็น
error = error1.tensor(error2) -
Expand product: เขียนเป็น
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 :
-
คือค่า classical bit ที่ บันทึกไว้
-
คือค่า bit จริง ที่ได้จากการวัด
ตัวอย่างเช่น สำหรับหนึ่ง Qubit:
# 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 สองกรณีดังนี้
-
ข้อผิดพลาดควอนตัมแบบ all-qubit
-
ข้อผิดพลาดควอนตัมของ 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: ['u3', 'u1', 'u2']
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: ['u3', 'u1', 'u2']
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))
ตัวอย่างสัญญาณรบกวน 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: ['u1', 'u2', 'cx', 'measure', 'reset', 'u3']
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)
ตัวอย่างที่ 2: การผ่อนคลายเชิงความร้อนแบบ T1/T2
ลองพิจารณาโมเดลความผิดพลาดที่สมจริงมากขึ้น โดยอ้างอิงจากการผ่อนคลายเชิงความร้อนกับสภาพแวดล้อมของ Qubit:
- แต่ละ Qubit ถูกกำหนดพารามิเตอร์ด้วยค่าคงที่เวลาการผ่อนคลายเชิงความร้อน และค่าคงที่เวลาการสูญเสียเฟส
- โปรดทราบว่าเราต้องมี
- อัตราความผิดพลาดในคำสั่งต่าง ๆ ถูกกำหนดโดยเวลาของ Gate และค่า , ของแต่ละ 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: ['u2', 'cx', 'measure', 'reset', '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))]
รันการจำลองแบบมีสัญญาณรบกวน
# 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)
ขั้นตอนถัดไป
- สำหรับการจำลอง Circuit แบบมีสัญญาณรบกวน ดูที่ การจำลองแบบ exact และแบบมีสัญญาณรบกวนด้วย Qiskit Aer primitives
- ดูเอกสารอ้างอิง Qiskit Aer noise module