Skip to main content
IBM Quantum Platform

Simulazione esatta e rumorosa con le primitive Aer di Qiskit

  • 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-aer~=0.17
    

La simulazione esatta con le primitive " Qiskit SDK " illustra come utilizzare le primitive di riferimento incluse in Qiskit per eseguire la simulazione esatta dei circuiti quantistici. I processori quantistici attualmente esistenti sono soggetti a errori, o rumore, pertanto i risultati di una simulazione esatta non riflettono necessariamente i risultati che ci si aspetterebbe eseguendo i circuiti su hardware reale. Sebbene le primitive di riferimento in Qiskit non supportino la modellizzazione del rumore, Qiskit Aer include implementazioni delle primitive che supportano tale modellizzazione. Qiskit Aer è un simulatore di circuiti quantistici ad alte prestazioni che è possibile utilizzare al posto delle primitive di riferimento per ottenere prestazioni migliori e funzionalità aggiuntive. Fa parte dell 'ecosistema Qiskit. In questo articolo illustriamo l'uso delle primitive di Qiskit Aer per la simulazione esatta e quella con rumore.

Note
  • qiskit-aer v0.14 o successivo è necessario.
  • Sebbene le primitive di Qiskit Aer implementino le interfacce delle primitive, non offrono le stesse opzioni delle primitive di IBM Quantum. Il livello di resilienza, ad esempio, non è disponibile con le primitive di Qiskit Aer.
  • Per maggiori dettagli sulle opzioni del metodo di simulazione supportate da Aer, consultare la documentazione AerSimulator.

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

from qiskit.circuit.library import efficient_su2

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

Output:

Output of the previous code cell

Questo circuito contiene parametri che rappresentano gli angoli di rotazione per le porte RyR_y e RzR_z. Quando si simula questo circuito, è necessario specificare i valori espliciti di questi parametri. Nella cella successiva, specifichiamo alcuni valori per questi parametri e utilizziamo la primitiva Estimator di Qiskit Aer per calcolare il valore esatto dell'aspettativa dell'osservabile ZZZZZ \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

Output:

0.8870140234256602

Ora inizializziamo un modello di rumore che includa un errore di depolarizzazione del 2% su ogni gate CX. In pratica, gli errori derivanti dai gate a due qubit, che in questo caso sono gate CX, costituiscono la principale fonte di errore durante l'esecuzione di un circuito. Per una panoramica sulla creazione di modelli di rumore in Qiskit Aer, consultare la sezione "Creazione di modelli di rumore".

Nella cella successiva, costruiamo uno stimatore che incorpora questo modello di rumore e lo utilizziamo per calcolare il valore di aspettativa 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

Output:

0.7247404214143528

Come si può notare, il valore di aspettativa in presenza di rumore è molto lontano dal valore corretto. In pratica, è possibile utilizzare una serie di tecniche di mitigazione degli errori per contrastare gli effetti del rumore, ma la discussione di queste tecniche esula dallo scopo di questo articolo.

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

E(ρ)=(1p)ρ+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, mentre lo stato viene conservato con probabilità 1p1 - p. Dopo mm applicazioni del canale depolarizzante, la probabilità che lo stato sia conservato sarebbe (1p)m(1 - p)^m. Pertanto, ci aspettiamo che la probabilità di conservare lo stato corretto alla fine della simulazione diminuisca esponenzialmente con il numero di porte CX nel nostro circuito.

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

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

Output:

0.6542558123199923

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

La seguente cella di codice mostra come utilizzare la primitiva Sampler di Qiskit Aer per campionare il circuito rumoroso. È necessario aggiungere delle misure 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()

Output:

{'00000000': 60,
 '00001111': 1,
 '11000000': 3,
 '10100000': 3,
 '10001111': 1,
 '00010000': 1,
 '00001010': 1,
 '00111100': 1,
 '01000000': 6,
 '10000000': 5,
 '00110000': 1,
 '00011000': 2,
 '01100000': 2,
 '00000110': 2,
 '11000100': 1,
 '10000110': 1,
 '01010000': 2,
 '00011110': 1,
 '00010100': 2,
 '01011010': 1,
 '00000010': 1,
 '00001100': 1,
 '11100000': 1}

Passi successivi

Suggerimenti
Questa pagina è stata utile?
Segnala un bug, un errore di battitura o richiedi contenuti su GitHub.