Vai al contenuto principale
Questo progetto è in fase beta. Hai trovato un bug? Apri una issue su GitHub. Hai una domanda o un'idea? Chiedi su GitHub Discussions — apprezziamo il tuo feedback!
Com'è la qualità della traduzione su questa pagina?

Simulazione esatta e rumorosa con le primitive di Qiskit Aer

Versioni dei pacchetti

Il codice in questa pagina è stato sviluppato utilizzando i seguenti requisiti. Si consiglia di usare queste versioni o versioni più recenti.

qiskit[all]~=2.5.2
qiskit-aer~=0.17

Simulazione esatta con le primitive di Qiskit SDK mostra come usare le primitive di riferimento incluse in Qiskit per eseguire la simulazione esatta di circuiti quantistici. Gli attuali processori quantistici soffrono di errori, ovvero rumore, quindi i risultati di una simulazione esatta non riflettono necessariamente i risultati che ci si aspetterebbe eseguendo i circuiti su hardware reale. Mentre le primitive di riferimento in Qiskit non supportano la modellazione del rumore, Qiskit Aer include implementazioni delle primitive che supportano la modellazione del rumore. Qiskit Aer è un simulatore di circuiti quantistici ad alte prestazioni che puoi usare al posto delle primitive di riferimento per prestazioni migliori e più funzionalità. Fa parte del Qiskit Ecosystem. In questo articolo, mostriamo l'uso delle primitive di Qiskit Aer per la simulazione esatta e rumorosa.

Note
  • È richiesto qiskit-aer v0.14 o successivo.
  • Sebbene le primitive di Qiskit Aer implementino le interfacce delle primitive, non forniscono le stesse opzioni delle primitive IBM Quantum. Il resilience level, ad esempio, non è disponibile con le primitive di Qiskit Aer.
  • Consulta la documentazione di AerSimulator per i dettagli sulle opzioni del metodo di simulazione supportate da Aer.

Per esplorare la simulazione esatta e rumorosa, crea un circuito di esempio su otto qubit:

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"qiskit": "qiskit", "qiskit_aer": "qiskit-aer"}
_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")
from qiskit.circuit.library import efficient_su2

n_qubits = 8
circuit = efficient_su2(n_qubits)
circuit.draw("mpl")

Output of the previous code cell

Questo circuito contiene parametri che rappresentano gli angoli di rotazione per i gate RyR_y e RzR_z. Quando simuliamo questo circuito, dobbiamo specificare valori espliciti per questi parametri. Nella cella successiva, specifichiamo alcuni valori per questi parametri e usiamo la primitiva Estimator di Qiskit Aer per calcolare il valore di aspettazione esatto dell'osservabile ZZ⋯ZZZ \cdots Z.

from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_aer import AerSimulator
from qiskit_aer.primitives import EstimatorV2 as Estimator

observable = SparsePauliOp("Z" * n_qubits)
params = [0.1] * circuit.num_parameters

exact_estimator = Estimator()
# The circuit needs to be transpiled to the AerSimulator target
pass_manager = generate_preset_pass_manager(3, AerSimulator())
isa_circuit = pass_manager.run(circuit)
pub = (isa_circuit, observable, params)
job = exact_estimator.run([pub])
result = job.result()
pub_result = result[0]
exact_value = float(pub_result.data.evs)
exact_value
0.8870140234256602

Ora, inizializziamo un modello di rumore che include un errore di depolarizzazione del 2% su ogni gate CX. In pratica, l'errore derivante dai gate a due qubit, che qui sono i gate CX, è la fonte dominante di errore quando si esegue un circuito. Consulta Costruire modelli di rumore per una panoramica sulla costruzione di modelli di rumore in Qiskit Aer.

Nella cella successiva, costruiamo un Estimator che incorpora questo modello di rumore e lo usiamo per calcolare il valore di aspettazione dell'osservabile.

from qiskit_aer.noise import NoiseModel, depolarizing_error

noise_model = NoiseModel()
cx_depolarizing_prob = 0.02
noise_model.add_all_qubit_quantum_error(
depolarizing_error(cx_depolarizing_prob, 2), ["cx"]
)

noisy_estimator = Estimator(
options=dict(backend_options=dict(noise_model=noise_model))
)
job = noisy_estimator.run([pub])
result = job.result()
pub_result = result[0]
noisy_value = float(pub_result.data.evs)
noisy_value
0.7247404214143529

Come puoi vedere, il valore di aspettazione in presenza di rumore è piuttosto lontano dal valore corretto. In pratica, puoi utilizzare una varietà di tecniche di mitigazione degli errori per contrastare gli effetti del rumore, ma una discussione di queste tecniche esula dallo scopo di questo articolo.

Per avere un'idea molto approssimativa di come il rumore influisce sul risultato finale, considera il nostro modello di rumore, che aggiunge un errore di depolarizzazione del 2% a ogni gate CX. L'errore di depolarizzazione con probabilità pp è definito come un canale quantistico EE che ha la seguente azione su una matrice di densità ρ\rho:

E(ρ)=(1−p)ρ+pI2nE(\rho) = (1 - p) \rho + p\frac{I}{2^n}

dove nn è il numero di qubit, in questo caso, 2. Cioè, con probabilità pp, lo stato viene sostituito con lo stato completamente misto, e lo stato viene preservato con probabilità 1−p1 - p. Dopo mm applicazioni del canale di depolarizzazione, la probabilità che lo stato venga preservato sarebbe (1−p)m(1 - p)^m. Pertanto, ci aspettiamo che la probabilità di mantenere lo stato corretto alla fine della simulazione diminuisca esponenzialmente con il numero di gate CX nel nostro circuito.

Contiamo il numero di gate CX nel nostro circuito e calcoliamo (1−p)m(1 - p)^m. Chiamiamo count_ops per ottenere un dizionario che mappa i nomi dei gate ai conteggi, e recuperiamo la voce per il gate CX.

cx_count = circuit.count_ops()["cx"]
(1 - cx_depolarizing_prob) ** cx_count
0.6542558123199923

Questo valore, 65%, fornisce una stima approssimativa della probabilità che il nostro stato finale sia corretto. È una stima conservativa perché non tiene conto dello stato iniziale della simulazione.

La seguente cella di codice mostra come usare la primitiva Sampler di Qiskit Aer per campionare dal circuito rumoroso. Dobbiamo aggiungere misurazioni al circuito prima di eseguirlo con la primitiva Sampler.

from qiskit_aer.primitives import SamplerV2 as Sampler

measured_circuit = circuit.copy()
measured_circuit.measure_all()

noisy_sampler = Sampler(
options=dict(backend_options=dict(noise_model=noise_model))
)
# The circuit needs to be transpiled to the AerSimulator target
pass_manager = generate_preset_pass_manager(3, AerSimulator())
isa_circuit = pass_manager.run(measured_circuit)
pub = (isa_circuit, params, 100)
job = noisy_sampler.run([pub])
result = job.result()
pub_result = result[0]
pub_result.data.meas.get_counts()
{'00000000': 69,
'00100000': 2,
'00000110': 1,
'11000000': 2,
'00010100': 1,
'01100000': 2,
'01010000': 3,
'00101000': 1,
'10100000': 2,
'01100101': 1,
'00001010': 1,
'10000000': 2,
'00000010': 3,
'01000000': 4,
'11100000': 1,
'10000101': 1,
'00110000': 1,
'00001100': 1,
'00011000': 2}

Passi successivi​

Raccomandazioni