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.3.0
qiskit-aer~=0.17
La simulazione esatta con le primitive di Qiskit mostra come usare le primitive di riferimento incluse in Qiskit per eseguire la simulazione esatta di circuiti quantistici. I processori quantistici attualmente esistenti sono soggetti a errori, o rumore, quindi i risultati di una simulazione esatta non riflettono necessariamente i risultati che ti aspetteresti 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 ottenere prestazioni migliori e più funzionalità. Fa parte del Qiskit Ecosystem. In questo articolo, dimostriamo l'uso delle primitive di Qiskit Aer per la simulazione esatta e rumorosa.
- È richiesta la versione
qiskit-aerv0.14 o successiva. - Sebbene le primitive di Qiskit Aer implementino le interfacce primitive, non forniscono le stesse opzioni delle primitive di Qiskit Runtime. Il livello di resilienza, 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 — required packages for this notebook
!pip install -q qiskit qiskit-aer
from qiskit.circuit.library import efficient_su2
n_qubits = 8
circuit = efficient_su2(n_qubits)
circuit.draw("mpl")
Questo circuito contiene parametri per rappresentare gli angoli di rotazione dei gate e . Quando si simula questo circuito, è necessario 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 .
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
Adesso, 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 gate CX — è la fonte di errore dominante 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.7247404214143528
Come puoi vedere, il valore di aspettazione in presenza del rumore è abbastanza lontano dal valore corretto. In pratica, puoi impiegare una varietà di tecniche di mitigazione degli errori per contrastare gli effetti del rumore, ma la discussione di queste tecniche va oltre lo 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à è definito come un canale quantistico che ha la seguente azione su una matrice densità :
dove è il numero di qubit, in questo caso 2. Ovvero, con probabilità , lo stato viene sostituito con lo stato completamente misto, e lo stato viene preservato con probabilità . Dopo applicazioni del canale di depolarizzazione, la probabilità che lo stato venga preservato sarebbe . Pertanto, ci aspettiamo che la probabilità di conservare 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 . 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 le 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()
{'00100000': 1,
'00000000': 65,
'10101000': 1,
'10000000': 5,
'00001000': 1,
'00000110': 2,
'11110010': 1,
'00000011': 3,
'01010000': 3,
'11000000': 3,
'01111000': 1,
'01000000': 2,
'00000010': 1,
'01100000': 1,
'00011000': 1,
'00111100': 1,
'00010100': 1,
'00001111': 1,
'00110000': 1,
'01100101': 1,
'00000100': 1,
'10100000': 1,
'00000001': 1,
'11010000': 1}
Passi successivi
- Per simulare circuiti piccoli e semplici, consulta Simulazione esatta con le primitive di Qiskit.
- Consulta la documentazione di Qiskit Aer.