Costruire modelli di rumore
Il codice di questa pagina è stato sviluppato in base ai seguenti requisiti. Si consiglia di utilizzare queste versioni o versioni più recenti.
qiskit[all]~=2.5.1 qiskit-ibm-runtime~=0.47.0 qiskit-aer~=0.17
Questa pagina mostra come utilizzare il modulo Qiskit Aer noise per costruire modelli di rumore per la simulazione di circuiti quantistici in presenza di errori. Ciò è utile per emulare processori quantistici rumorosi e per studiare gli effetti del rumore sull'esecuzione di algoritmi quantistici.
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,
)Modulo noise Qiskit Aer
Il modulo Qiskit Aer noise contiene le classi Python per costruire modelli di rumore personalizzati per la simulazione. Le classi principali sono tre:
-
La classe
NoiseModelche memorizza un modello di rumore utilizzato per la simulazione del rumore. -
La classe
QuantumErrorche descrive gli errori del gate CPTP. Questi possono essere applicati:- Dopo il cancello o le istruzioni di reset
- Istruzioni prima della misura.
-
La classe
ReadoutErrorche descrive gli errori di lettura classici.
Inizializzare un modello di rumore da un backend
È possibile inizializzare un modello di rumore utilizzando i parametri ricavati dagli ultimi dati di calibrazione relativi a un backend fisico.
In questi esempi viene utilizzato il backend FakeSherbrooke``qiskit_ibm_runtime fittizio di, ma è possibile provarlo su qualsiasi backend reale o fittizio compatibile con Qiskit.
from qiskit_ibm_runtime.fake_provider import FakeSherbrooke
backend = FakeSherbrooke()
noise_model = NoiseModel.from_backend(backend)In questo modo si otterrà un modello di rumore che approssima gli errori che si incontrano quando si usa quel backend. Se si desidera avere un controllo più dettagliato sui parametri del modello di rumore, è necessario creare il proprio modello di rumore, come descritto nel resto di questa pagina.
Errori quantistici
Anziché gestire direttamente QuantumError l'oggetto, esistono molte funzioni di supporto che generano automaticamente un tipo specifico di errore quantistico parametrizzato. Queste sono contenute nel noise modulo e includono funzioni per molti tipi di errori comuni utilizzati nella ricerca sull'informatica quantistica. I nomi delle funzioni e il tipo di errore che restituiscono sono:
Funzione di errore standard | Dettagli |
|---|---|
kraus_error | un canale di errore CPTP generale a n-qubit dato come una lista di matrici di Kraus . |
mixed_unitary_error | un errore unitario misto a n-qubit dato come lista di matrici unitarie e probabilità . |
coherent_unitary_error | un errore unitario coerente a n-qubit dato da una singola matrice unitaria . |
pauli_error | un canale di errore Pauli a n-qubit (misto unitario) dato come un elenco di Pauli e di probabilità |
depolarizing_error | un canale di errore depolarizzante a n-qubit parametrizzato da una probabilità di depolarizzazione . |
reset_error | un errore di reset di un singolo qubit parametrizzato dalle probabilità di reset allo stato . |
thermal_relaxation_error | un canale di rilassamento termico a singolo qubit parametrizzato dalle costanti di tempo di rilassamento , , dal tempo di gate e dalla popolazione termica dello stato eccitato . |
phase_amplitude_damping_error | Un canale di errore di smorzamento di fase e di ampiezza generalizzato a singolo qubit dato da un parametro di smorzamento di ampiezza , un parametro di smorzamento di fase e una popolazione termica di stato eccitato . |
amplitude_damping_error | Un canale di errore generalizzato a smorzamento di ampiezza a singolo qubit dato da un parametro di smorzamento di ampiezza e da una popolazione termica di stato eccitato . |
phase_damping_error | Canale di errore di smorzamento di fase a singolo qubit dato da un parametro di smorzamento di fase. |
Sommare gli errori quantistici
QuantumError le istanze possono essere combinate utilizzando la composizione, il prodotto tensoriale e l'espansione tensoriale (prodotto tensoriale di ordine inverso) per produrre nuovi QuantumErrors come:
- Composizione: come
error = error1.compose(error2) - Prodotto tensoriale: come
error = error1.tensor(error2) - Espandi prodotto: come
error = error1.expand(error2)
Esempio
Per costruire un errore di bit-flip a singolo qubit del 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)Output:
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)Output:
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)Output:
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 ├
└───┘
Conversione da e verso gli operatori di " QuantumChannel "
È inoltre possibile convertire tra gli oggetti QuantumError di Qiskit Aer e gli oggetti QuantumChannel di Qiskit.
# Convert to Kraus operator
bit_flip_kraus = Kraus(bit_flip)
print(bit_flip_kraus)Output:
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)Output:
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_flipOutput:
QuantumError on 1 qubits. Noise circuits:
P(0) = 1.0, Circuit =
┌───────┐
q: ┤ kraus ├
└───────┘
True
Errore di lettura
Gli errori di lettura classici sono specificati da un elenco di vettori di probabilità di assegnazione:
- è il valore di bit classico registrato
- è il valore vero del bit restituito dalla misura
Ad esempio, per un qubit: .
# Measurement misassignment probabilities
p0given1 = 0.1
p1given0 = 0.05
ReadoutError([[1 - p1given0, p1given0], [p0given1, 1 - p0given1]])Output:
ReadoutError([[0.95 0.05]
[0.1 0.9 ]])
Gli errori di lettura possono anche essere combinati utilizzando compose, tensor e expand, come nel caso degli errori quantistici.
Aggiungi errori a un modello di rumore
Quando si aggiunge un errore quantistico a un modello di rumore, occorre specificare il tipo di istruzione su cui agisce e a quali qubit applicarlo. Esistono due casi di errori quantistici:
- Errore quantistico all-qubit
- Errore quantistico specifico del qubit
1. Errore quantistico all-qubit
In questo modo si applica lo stesso errore a qualsiasi occorrenza di un'istruzione, indipendentemente dai qubit su cui agisce.
Viene aggiunto come 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)Output:
NoiseModel:
Basis gates: ['cx', 'id', 'rz', 'sx', 'u1', 'u2', 'u3']
Instructions with noise: ['u2', 'u1', 'u3']
All-qubits errors: ['u1', 'u2', 'u3']
2. Errore quantistico specifico del qubit
Applica l'errore a qualsiasi occorrenza di un'istruzione che agisce su un elenco specificato di qubit. Si noti che l'ordine dei qubit è importante: ad esempio, un errore applicato ai qubit [0, 1] per un gate a due qubit è diverso da uno applicato ai qubit [1, 0].
Viene aggiunto come 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)Output:
NoiseModel:
Basis gates: ['cx', 'id', 'rz', 'sx', 'u1', 'u2', 'u3']
Instructions with noise: ['u2', 'u1', 'u3']
Qubits with noise: [0]
Specific qubit errors: [('u1', (0,)), ('u2', (0,)), ('u3', (0,))]
Nota sugli errori quantistici dei qubit non locali
NoiseModel non supporta l'aggiunta di errori quantistici su qubit non locali. Dovrebbero essere gestiti al di fuori di NoiseModel. Ciò significa che dovresti scrivere il tuo passaggio di transpiler (TransformationPass) ed eseguirlo immediatamente prima di avviare il simulatore, se hai bisogno di inserire gli errori quantistici nel tuo circuito secondo le tue specifiche condizioni.
Eseguire una simulazione rumorosa con un modello di rumore
Il comando AerSimulator(noise_model=noise_model) restituisce un simulatore configurato in base al modello di rumore indicato. Oltre a impostare il modello di rumore del simulatore, sovrascrive anche le porte di base del simulatore, in base alle porte del modello di rumore.
Esempi di modelli di rumore
Di seguito forniremo alcuni esempi di modelli di rumore. Per le nostre dimostrazioni utilizziamo un semplice circuito di prova che genera uno stato GHZ a 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)Output:
┌───┐ ░ ┌─┐
q_0: ┤ H ├──■─────────────░─┤M├─────────
└───┘┌─┴─┐ ░ └╥┘┌─┐
q_1: ─────┤ X ├──■────────░──╫─┤M├──────
└───┘┌─┴─┐ ░ ║ └╥┘┌─┐
q_2: ──────────┤ X ├──■───░──╫──╫─┤M├───
└───┘┌─┴─┐ ░ ║ ║ └╥┘┌─┐
q_3: ───────────────┤ X ├─░──╫──╫──╫─┤M├
└───┘ ░ ║ ║ ║ └╥┘
meas: 4/════════════════════════╩══╩══╩══╩═
0 1 2 3
Simulazione ideale
# Ideal simulator and execution
sim_ideal = AerSimulator()
result_ideal = sim_ideal.run(circ).result()
plot_histogram(result_ideal.get_counts(0))Output:
Esempio di rumore 1: Modello di rumore di base con errore di inversione di bit
Consideriamo un semplice esempio di modello di rumore giocattolo comune nella ricerca sulla teoria dell'informazione quantistica:
- Quando si applica un gate a singolo qubit, si capovolge lo stato del qubit con la probabilità
p_gate1. - Quando si applica un gate a due qubit, applicare errori a singolo qubit a ciascun qubit.
- Quando si azzera un qubit, si azzera a 1 invece che a 0 con probabilità
p_reset. - Quando si misura un qubit, si capovolge lo stato del qubit con la probabilità
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)Output:
NoiseModel:
Basis gates: ['cx', 'id', 'rz', 'sx', 'u1', 'u2', 'u3']
Instructions with noise: ['u3', 'u1', 'u2', 'reset', 'cx', 'measure']
All-qubits errors: ['reset', 'measure', 'u1', 'u2', 'u3', 'cx']
Eseguire la simulazione rumorosa
# 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:
Esempio 2: rilassamento termico dell' T1/T2
Consideriamo ora un modello di errore più realistico basato sul rilassamento termico con l'ambiente del qubit:
- Ogni qubit è parametrizzato da una costante di tempo di rilassamento termico e da una costante di tempo di dephasing .
- Si noti che dobbiamo avere .
- I tassi di errore sulle istruzioni sono determinati dai tempi dei gate e dai valori dei 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)Output:
NoiseModel:
Basis gates: ['cx', 'id', 'rz', 'sx', 'u2', 'u3']
Instructions with noise: ['u3', 'u2', 'reset', 'cx', 'measure']
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))]
Eseguire la simulazione rumorosa
# 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:
Passi successivi
- Per simulare circuiti con rumore, consultare la sezione "Simulazione esatta e con rumore con le primitive di Qiskit Aer ".
- Esaminare il riferimento del modulo di rumore Qiskit Aer.