Tvorba šumových modelů
Package versions
Kód na této stránce byl vyvinut s použitím následujících závislostí. Doporučujeme používat tyto nebo novější verze.
qiskit[all]~=2.4.0
qiskit-ibm-runtime~=0.46.1
qiskit-aer~=0.17
Tato stránka ukazuje, jak pomocí modulu noise z Qiskit Aer vytvářet šumové modely pro simulaci kvantových obvodů v přítomnosti chyb. To je užitečné pro emulaci zašuměných kvantových procesorů a pro studium vlivu šumu na provádění kvantových algoritmů.
# 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,
)
Modul noise v Qiskit Aer
Modul noise v Qiskit Aer obsahuje Python třídy pro vytváření vlastních šumových modelů pro simulaci. Existují tři klíčové třídy:
-
Třída
NoiseModel, která uchovává šumový model používaný při simulaci se šumem. -
Třída
QuantumError, která popisuje chyby CPTP hradel. Tyto chyby lze aplikovat:- Za instrukcemi gate nebo reset
- Před instrukcemi measure.
-
Třída
ReadoutError, která popisuje klasické chyby čtení.
Inicializace šumového modelu z backend
Šumový model s parametry nastavenými z nejnovějších kalibračních dat fyzického backend lze inicializovat takto.
V těchto příkladech se používá falešný backend FakeSherbrooke z qiskit_ibm_runtime, ale můžeš to vyzkoušet na libovolném skutečném nebo falešném backend kompatibilním s Qiskit.
from qiskit_ibm_runtime.fake_provider import FakeSherbrooke
backend = FakeSherbrooke()
noise_model = NoiseModel.from_backend(backend)
Výsledkem bude šumový model, který přibližně napodobuje chyby, s nimiž by ses setkal/a při používání daného Backend. Pokud chceš mít podrobnější kontrolu nad parametry šumového modelu, budeš si muset vytvořit vlastní šumový model, jak je popsáno ve zbytku této stránky.
Kvantové chyby
Namísto přímé práce s objektem QuantumError existuje mnoho pomocných funkcí, které automaticky generují konkrétní typ parametrizované kvantové chyby. Jsou obsaženy v modulu noise a zahrnují funkce pro mnoho běžných typů chyb používaných v kvantovém výzkumu. Názvy funkcí a typy chyb, které vrací, jsou:
| Standardní chybová funkce | Podrobnosti |
|---|---|
kraus_error | obecný n-qubitový CPTP chybový kanál zadaný jako seznam Krausových matic . |
mixed_unitary_error | n-qubitová smíšená unitární chyba zadaná jako seznam unitárních matic a pravděpodobností . |
coherent_unitary_error | n-qubitová koherentní unitární chyba zadaná jako jedna unitární matice . |
pauli_error | n-qubitový Pauliho chybový kanál (smíšeně unitární) zadaný jako seznam Pauliho operátorů a pravděpodobností |
depolarizing_error | n-qubitový depolarizační chybový kanál parametrizovaný depolarizační pravděpodobností . |
reset_error | jednoqubitová chyba resetu parametrizovaná pravděpodobnostmi resetu do stavu , . |
thermal_relaxation_error | jednoqubitový kanál tepelné relaxace parametrizovaný relaxačními časovými konstantami , , dobou hradla a tepelnou populací vzbuzeného stavu . |
phase_amplitude_damping_error | Jednoqubitový zobecněný kombinovaný kanál fázového a amplitudového tlumení zadaný parametrem amplitudového tlumení , parametrem fázového tlumení a tepelnou populací vzbuzeného stavu . |
amplitude_damping_error | Jednoqubitový zobecněný kanál amplitudového tlumení zadaný parametrem amplitudového tlumení a tepelnou populací vzbuzeného stavu . |
phase_damping_error | Jednoqubitový kanál fázového tlumení zadaný parametrem fázového tlumení . |
Kombinuj kvantové chyby
Instance QuantumError lze kombinovat pomocí kompozice, tenzorového součinu a tenzorového rozšíření (tenzorový součin v opačném pořadí), čímž vznikají nové QuantumErrors:
- Kompozice: jako
error = error1.compose(error2) - Tenzorový součin: jako
error = error1.tensor(error2) - Rozšířený součin: jako
error = error1.expand(error2)
Příklad
Pro sestavení 5% jednoqubitové chyby překlopení bitu:
# 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 ├
└───┘
Převod na operátory QuantumChannel a zpět
Objekty QuantumError v Qiskit Aer lze také převádět na objekty QuantumChannel v Qiskit a zpět.
# 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
Chyba čtení
Klasické chyby čtení jsou specifikovány seznamem vektorů pravděpodobnosti přiřazení :
- je zaznamenaná hodnota klasického bitu
- je skutečná hodnota bitu vrácená z měření
Například pro jeden 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 ]])
Chyby čtení lze také kombinovat pomocí compose, tensor a expand, stejně jako u kvantových chyb.
Přidání chyb do modelu šumu
Při přidávání kvantové chyby do modelu šumu musíme specifikovat typ instrukce, na kterou působí, a na které Qubity ji aplikovat. Existují dva případy kvantových chyb:
- Kvantová chyba pro všechny Qubity
- Kvantová chyba pro konkrétní Qubity
1. Kvantová chyba pro všechny Qubity
Tato chyba aplikuje stejnou chybu na každý výskyt instrukce, bez ohledu na to, na které Qubity působí.
Přidává se jako 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. Kvantová chyba pro konkrétní Qubity
Tato chyba aplikuje chybu na každý výskyt instrukce působící na zadaný seznam Qubitů. Všimni si, že na pořadí Qubitů záleží: například chyba aplikovaná na Qubity [0, 1] pro dvouqubitovou Gate se liší od chyby aplikované na Qubity [1, 0].
Přidává se jako 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,))]
Poznámka k nelokální kvantové chybě Qubitů
NoiseModel nepodporuje přidávání nelokálních kvantových chyb Qubitů. Ty by měly být řešeny mimo NoiseModel. To znamená, že pokud potřebuješ vložit své kvantové chyby do obvod za vlastních podmínek, měl(a) bys napsat vlastní transpiler pass (TransformationPass) a spustit ho těsně před spuštěním simulátoru.
Spuštění šumové simulace s modelem šumu
Příkaz AerSimulator(noise_model=noise_model) vrátí simulátor nakonfigurovaný podle daného modelu šumu. Kromě nastavení modelu šumu simulátoru také přepíše základní Gate simulátoru podle Gate modelu šumu.
Příklady šumových modelů
Nyní si ukážeme několik příkladů šumových modelů. Pro demonstraci použijeme jednoduchý testovací Circuit, který generuje n-qubitový stav GHZ:
# 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
Ideální simulace
# Ideal simulator and execution
sim_ideal = AerSimulator()
result_ideal = sim_ideal.run(circ).result()
plot_histogram(result_ideal.get_counts(0))
Příklad šumu 1: Základní šumový model s chybou překlopení bitu
Uvažujme jednoduchý ilustrativní příklad šumového modelu, který je běžný ve výzkumu teorie kvantové informace:
- Při aplikaci jednoqubitového Gate překlopíme stav Qubitu s pravděpodobností
p_gate1. - Při aplikaci dvouqubitového Gate aplikujeme jednoqubitové chyby na každý qubit.
- Při resetování Qubitu ho s pravděpodobností
p_resetresetujeme do stavu 1 místo 0. - Při měření Qubitu překlopíme jeho stav s pravděpodobností
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: ['measure', 'cx', 'reset', 'u2', 'u3', 'u1']
All-qubits errors: ['reset', 'measure', 'u1', 'u2', 'u3', 'cx']
Spuštění simulace se šumem
# 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)
Příklad 2: Tepelná relaxace T1/T2
Nyní uvažujme realističtější model chyb založený na tepelné relaxaci s prostředím qubitu:
- Každý qubit je parametrizován časovou konstantou tepelné relaxace a časovou konstantou defázování .
- Platí, že musí být splněno .
- Chybové míry instrukcí jsou určeny dobami Gate a hodnotami , jednotlivých 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: ['cx', 'measure', 'reset', 'u2', '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))]
Spuštění simulace se šumem
# 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)
Další kroky
- Chceš-li simulovat Circuit se šumem, přečti si Přesná a zašuměná simulace s primitivy Qiskit Aer.
- Prostuduj si referenci modulu šumu Qiskit Aer.