Přeskočit na hlavní obsah
Tento projekt je v betě. Našel jsi chybu? Otevřít issue na GitHubu. Máš otázku nebo nápad? Zeptej se v Discussions — rádi si poslechneme tvou zpětnou vazbu!
Jaká je kvalita překladu na této stránce?

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.6.1
qiskit-ibm-runtime~=0.50.0
qiskit-aer~=0.18

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 — 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,
)

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:

  1. Třída NoiseModel, která uchovává šumový model používaný při simulaci se šumem.

  2. Třída QuantumError, která popisuje chyby CPTP Gate. Tyto chyby lze aplikovat:

    • Za instrukcemi gate nebo reset

    • Před instrukcemi measure.

  3. 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.

poznámka

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, na které bys narazil(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á funkcePodrobnosti
kraus_errorobecný n-qubitový CPTP chybový kanál zadaný jako seznam Krausových matic [K0,...][K_0, ...].
mixed_unitary_errorn-qubitová smíšená unitární chyba zadaná jako seznam unitárních matic a pravděpodobností [(U0,p0),...][(U_0, p_0),...].
coherent_unitary_errorn-qubitová koherentní unitární chyba zadaná jako jedna unitární matice UU.
pauli_errorn-qubitový Pauliho chybový kanál (smíšeně unitární) zadaný jako seznam Pauliho operátorů a pravděpodobností [(P0,p0),...][(P_0, p_0),...]
depolarizing_errorn-qubitový depolarizační chybový kanál parametrizovaný depolarizační pravděpodobností pp.
reset_errorjednoqubitová chyba resetu parametrizovaná pravděpodobnostmi p0,p1p_0, p_1 resetu do stavu ∣0⟩\vert0\rangle, ∣1⟩\vert1\rangle.
thermal_relaxation_errorjednoqubitový kanál tepelné relaxace parametrizovaný relaxačními časovými konstantami T1T_1, T2T_2, dobou Gate tt a tepelnou populací vzbuzeného stavu p1p_1.
phase_amplitude_damping_errorJednoqubitový zobecněný kombinovaný kanál fázového a amplitudového tlumení zadaný parametrem amplitudového tlumení λ\lambda, parametrem fázového tlumení γ\gamma a tepelnou populací vzbuzeného stavu p1p_1.
amplitude_damping_errorJednoqubitový zobecněný kanál amplitudového tlumení zadaný parametrem amplitudového tlumení λ\lambda a tepelnou populací vzbuzeného stavu p1p_1.
phase_damping_errorJednoqubitový kanál fázového tlumení zadaný parametrem fázového tlumení γ\gamma.

Kombinování kvantových chyb​

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: E(ρ)=E2(E1(ρ))\cal{E}(\rho)=\cal{E_2}(\cal{E_1}(\rho)) jako error = error1.compose(error2)

  • Tenzorový součin: E(ρ)=(E1⊗E2)(ρ)\cal{E}(\rho) =(\cal{E_1}\otimes\cal{E_2})(\rho) jako error = error1.tensor(error2)

  • Rozšířený součin: E(ρ)=(E2⊗E1)(ρ)\cal{E}(\rho) =(\cal{E_2}\otimes\cal{E_1})(\rho) 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í P(A∣B)P(A|B):

  • AA je zaznamenaná hodnota klasického bitu

  • BB je skutečná hodnota bitu vrácená z měření

Například pro jeden 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 ]])

Chyby čtení lze také kombinovat pomocí compose, tensor a expand, stejně jako u kvantových chyb.

Přidání chyb do šumového modelu​

Při přidávání kvantové chyby do šumového modelu musíme specifikovat typ instrukce, na kterou působí, a na které Qubity ji aplikovat. Existují dva případy kvantových chyb:

  1. Kvantová chyba pro všechny Qubity

  2. Kvantová chyba pro konkrétní Qubity

1. Kvantová chyba pro všechny Qubity​

Tím se stejná chyba aplikuje 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: ['u1', 'u2', 'u3']
All-qubits errors: ['u1', 'u2', 'u3']

2. Kvantová chyba pro konkrétní Qubity​

Tím se chyba aplikuje 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 dvouqubitový 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: ['u1', 'u2', 'u3']
Qubits with noise: [0]
Specific qubit errors: [('u1', (0,)), ('u2', (0,)), ('u3', (0,))]

Poznámka k nelokálním kvantovým chybám​

NoiseModel nepodporuje přidávání nelokálních kvantových chyb Qubitů. Ty by měly být řešeny mimo NoiseModel. Z toho plyne, že pokud potřebuješ vložit své kvantové chyby do obvodu 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í simulace se šumem pomocí šumového modelu​

Příkaz AerSimulator(noise_model=noise_model) vrátí simulátor nakonfigurovaný podle daného šumového modelu. Kromě nastavení šumového modelu simulátoru také přepíše bázové Gate (basis gates) simulátoru podle Gate šumového modelu.

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))

Výstup předchozí buňky kódu

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_reset resetujeme 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: ['reset', 'cx', 'u1', 'u3', 'measure', 'u2']
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)

Výstup předchozí buňky kódu

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 T1T_1 a časovou konstantou defázování T2T_2.
  • Platí, že musí být splněno T2≤2T1T_2 \le 2 T_1.
  • Chybové míry instrukcí jsou určeny dobami Gate a hodnotami T1T_1, T2T_2 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: ['reset', 'cx', 'u3', 'measure', 'u2']
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)

Výstup předchozí buňky kódu

Další kroky​

Doporučení