Esplorare l'incertezza
Per questo modulo Qiskit in Classrooms, gli studenti devono disporre di un ambiente Python funzionante con i seguenti pacchetti installati:
qiskitv2.1.0 o successivoqiskit-ibm-runtimev0.40.1 o successivoqiskit-aerv0.17.0 o successivoqiskit.visualizationnumpypylatexenc
Per configurare e installare i pacchetti elencati sopra, consulta la guida Installare Qiskit. Per eseguire job su veri computer quantistici, gli studenti dovranno creare un account IBM Quantum® seguendo i passaggi descritti nella guida Configura il tuo account IBM Cloud.
Questo modulo è stato testato e ha utilizzato 8 minuti di tempo QPU. Si tratta solo di una stima; l'utilizzo effettivo può variare. Due calcoli particolarmente dispendiosi in termini di tempo sono segnalati come tali nei commenti dell'intestazione e possono essere eseguiti su simulatori se gli studenti dispongono di poco tempo QPU. Senza di essi, il modulo richiede solo circa 30 secondi di tempo QPU.
# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy qiskit qiskit-aer qiskit-ibm-runtime
# Uncomment and modify this line as needed to install dependencies
#!pip install 'qiskit>=2.1.0' 'qiskit-ibm-runtime>=0.40.1' 'qiskit-aer>=0.17.0' 'numpy' 'pylatexenc'
Guarda il video introduttivo del modulo della Dr.ssa Katie McCormick qui sotto, oppure clicca qui per vederlo su YouTube.
Introduzione
Hai probabilmente sentito parlare del principio di indeterminazione, anche al di fuori dei tuoi corsi di fisica. Una riformulazione colloquiale comune dell'incertezza è: "Osservando qualcosa, lo si influenza." Questo è certamente vero. Ma un modo più fisico di descrivere l'incertezza è che esistono alcune osservabili fisiche tra loro incompatibili, che non possono essere entrambe conosciute simultaneamente con precisione arbitraria. Molti studenti incontrano per la prima volta la coppia di variabili incompatibili e , ovvero la posizione lungo un asse chiamato e la quantità di moto lineare lungo quella direzione, rispettivamente. Per tali variabili, il vincolo sull'incertezza è scritto come Qui, è chiamato "incertezza in ", che ha la stessa definizione della deviazione standard in statistica, e può essere definito come è definito nello stesso modo. Qui non ricaveremo questa relazione di indeterminazione; osserveremo solo che essa è coerente con la nostra comprensione delle onde classiche. Cioè, un'onda con una sola frequenza e lunghezza d'onda perfettamente definita si estenderebbe all'infinito come un sinusoide perfetto. In meccanica quantistica, questo corrisponderebbe a conoscere il momento con precisione assoluta secondo l'ipotesi di de Broglie: . Ma per sapere si trova una particella di tipo ondulatorio, l'onda che la descrive deve diventare più concentrata nello spazio, come una gaussiana molto stretta, ad esempio. Sappiamo che possiamo esprimere qualsiasi funzione continua, comprese queste funzioni d'onda molto concentrate, come serie di Fourier di funzioni sinusoidali con diverse lunghezze d'onda. Ma man mano che la funzione d'onda diventa più concentrata (e la posizione è meglio nota), saranno necessari più termini nella serie di Fourier, ovvero una combinazione di più lunghezze d'onda (e quindi, in meccanica quantistica, di più valori di momento).
Detto in modo più semplice: uno stato con momento ben definito (un sinusoide perfetto nello spazio) ha una posizione molto indeterminata. Uno stato con posizione ben definita (come una distribuzione delta di Dirac) ha un momento molto indeterminato.
Esistono altre variabili che mostrano tale incompatibilità. Ad esempio, lo spin di una particella può avere una proiezione ben definita lungo un asse, ma allora non sappiamo nulla della proiezione su un asse ortogonale. Ad esempio, lo stato (per un qubit o una particella spin-1/2) ha una proiezione definita lungo l'asse (pari a 1 nel contesto di un qubit, e a nel contesto di una particella spin-1/2). Ma questo stato può essere scritto come sovrapposizione di due stati, ciascuno dei quali ha una proiezione ben definita sull'asse : oppure in modo equivalente ha una proiezione ben definita su , così come . Quindi, se specifichiamo la proiezione di uno stato lungo l'asse , non conosciamo la proiezione lungo l'asse . E se specifichiamo la proiezione sull'asse , non conosciamo la proiezione lungo . Ci sono alcune differenze minori quando si discute ciò nel contesto dello spin e dei qubit. In linea generale, però, gli autostati delle matrici di Pauli hanno una relazione interessante che possiamo esplorare. In tutta questa lezione, verificheremo sperimentalmente la nostra intuizione sull'incertezza in queste variabili incompatibili e verificheremo che le relazioni di indeterminazione siano rispettate sui computer quantistici IBM®.
Verifica semplice dell'intuizione
In questo primo esperimento e durante tutto il modulo, utilizzeremo un framework per il quantum computing noto come "Qiskit patterns", che suddivide i flussi di lavoro nei seguenti passi:
- Passo 1: Mappa gli input classici in un problema quantistico
- Passo 2: Ottimizza il problema per l'esecuzione quantistica
- Passo 3: Esegui usando le Primitive di Qiskit Runtime
- Passo 4: Post-elaborazione e analisi classica
Seguiremo generalmente questi passi, anche se non li etichetteremo sempre esplicitamente.
Iniziamo caricando alcuni pacchetti necessari, incluse le primitive di Runtime. Selezioneremo anche il computer quantistico meno occupato disponibile.
Il codice sottostante contiene le istruzioni per salvare le tue credenziali al primo utilizzo. Assicurati di eliminare queste informazioni dal notebook dopo averle salvate nel tuo ambiente, in modo che le tue credenziali non vengano condivise accidentalmente quando condividi il notebook. Consulta Configura il tuo account IBM Cloud e Inizializza il servizio in un ambiente non attendibile per ulteriori indicazioni.
from numpy import pi
# Load the Qiskit Runtime service
from qiskit_ibm_runtime import QiskitRuntimeService
# Syntax for first saving your token. Delete these lines after saving your credentials.
# QiskitRuntimeService.save_account(channel='ibm_quantum_platform', instance = '<YOUR_IBM_INSTANCE_CRN>', token='<YOUR-API_KEY>', overwrite=True, set_as_default=True)
# service = QiskitRuntimeService(channel='ibm_quantum_platform')
# Load saved credentials
service = QiskitRuntimeService()
# Load the Runtime primitive and session
from qiskit_ibm_runtime import (
Batch,
SamplerV2 as Sampler,
EstimatorV2 as Estimator,
)
# Use the least busy backend
backend = service.least_busy(min_num_qubits=127)
print(backend.name)
ibm_sherbrooke
Se uno studente esaurisce il tempo di quantum computing disponibile durante la lezione, le righe sottostanti possono essere decommentate e utilizzate per configurare un simulatore che riproduce in parte il comportamento rumoroso del computer quantistico selezionato sopra.
# Import an estimator, this time from qiskit (we will import from Runtime for real hardware)
from qiskit_aer.primitives import SamplerV2, EstimatorV2
from qiskit_aer.noise import NoiseModel
# Generate the noise model from the backend properties
noise_model = NoiseModel.from_backend(backend)
noisy_sampler = SamplerV2(options={"backend_options": {"noise_model": noise_model}})
noisy_estimator = EstimatorV2(options={"backend_options": {"noise_model": noise_model}})
Ricorderai che un autostato di un operatore, Z, non è un autostato di un altro operatore X. Lo osserveremo ora sperimentalmente, effettuando misurazioni lungo gli assi e . Per la misurazione lungo , usiamo semplicemente qc.measure(), poiché i computer quantistici IBM sono strutturati per misurare lungo . Ma per misurare lungo , dobbiamo ruotare il sistema in modo da portare effettivamente l'asse nella direzione di misurazione. Questo si ottiene con un gate di Hadamard. Un passaggio simile è necessario per le misurazioni lungo . I passaggi necessari sono raccolti qui per comodità:
- Per misurare lungo :
qc.measure() - Per misurare lungo :
qc.h()poiqc.measure() - Per misurare lungo :
qc.sdg(),qc.h(),qc.spoiqc.measure()
Passo 1: Mappa gli input classici in un problema quantistico
In questo caso, il passo di mappatura consiste semplicemente nell'esprimere le misurazioni e le rotazioni descritte sopra in un circuito quantistico:
# Step 1: Map
# Import some general packages
from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(2, "c")
qc = QuantumCircuit(qr, cr)
# Add a first measurement
qc.measure(qr, cr[0])
qc.barrier()
# Change basis so that measurements made on quantum computer which normally tell us about z, now tell us about x.
qc.h(qr)
# Add a second measurement
qc.measure(qr, cr[1])
qc.draw("mpl")
Passo 2: Ottimizza il problema per l'esecuzione quantistica
Questo passo prende le operazioni che vogliamo eseguire e le esprime in termini delle funzionalità di uno specifico computer quantistico. Mappa inoltre il nostro problema sulla topologia del computer quantistico.
# Step 2: Transpile
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
Passo 3: Esegui usando le primitive di Qiskit Runtime
Possiamo usare il Sampler per raccogliere statistiche sulle misurazioni. Costruiremo la primitiva Sampler per l'esecuzione su un vero computer quantistico usando mode = backend. Esistono altre modalità per altri flussi di lavoro, e ne utilizzeremo una in seguito. Il Sampler verrà usato chiamando il suo metodo run() con una lista di "pub" (Primitive Unified Blocs). Ogni pub contiene fino a tre valori che, insieme, definiscono un'unità di lavoro computazionale che l'estimator deve completare: circuit, osservabili, parametri. È anche possibile fornire una lista di circuit, una lista di osservabili e una lista di parametri. Per ulteriori informazioni, leggi la Panoramica dei PUB.
Vogliamo eseguire su un vero computer quantistico, in modo da effettuare un vero esperimento di fisica quantistica. Se esaurisci il tempo disponibile sui computer quantistici reali, puoi commentare il codice sottostante per il computer quantistico e decommentare il codice per l'esecuzione su un simulatore.
# Step 3: Run the job on a real quantum computer
sampler = Sampler(mode=backend)
pubs = [qc_isa]
job = sampler.run(pubs)
res = job.result()
counts = res[0].data.c.get_counts()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_sampler.run([qc_isa])
# res=job.result()
# counts=res[0].data.c.get_counts()
Passo 4: Post-elaborazione
Questo è un caso di post-elaborazione particolarmente semplice, in cui visualizziamo semplicemente i conteggi.
Nota che Qiskit ordina i qubit, le misurazioni e altri elementi elencando il numero più basso per ultimo / a destra, una convenzione denominata "little-endian". Ciò significa che la colonna etichettata "10" di seguito si riferisce ai conteggi in cui la prima misurazione ha restituito "0" e la seconda misurazione ha restituito "1".
# Step 4: Post-process
from qiskit.visualization import plot_histogram
plot_histogram(counts)
Se questa convenzione non ti piace, puoi usare marginal_counts per visualizzare i risultati di ogni misurazione separatamente:
from qiskit.result import marginal_counts
plot_histogram(
marginal_counts(counts, indices=[0]), title="Counts after first measurement"
)
plot_histogram(
marginal_counts(counts, indices=[1]), title="Counts after second measurement"
)
Per impostazione predefinita, gli stati in Qiskit vengono inizializzati allo stato . Non sorprende quindi che quasi tutte le prime misurazioni abbiano restituito . Nota però che nella seconda misurazione (quella che fornisce informazioni sulle proiezioni dello stato su ) c'è stato quasi un pareggio. Sembra che questo stato, che ci dà un risultato molto prevedibile per le misurazioni lungo , ci dia un insieme di risultati molto imprevedibile per le misurazioni lungo . Esploriamo questo aspetto.
Cosa succede se effettuiamo le misurazioni nell'ordine inverso? Potremmo iniziare usando il gate di Hadamard per ottenere statistiche sulla probabilità di misurare in . Poi, per la seconda misurazione, torneremo alla base usando un secondo gate di Hadamard.
# Step 1:
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(2, "c")
qc = QuantumCircuit(qr, cr)
# Change basis to measure along x.
qc.h(qr)
qc.measure(qr, cr[0])
qc.barrier()
# Change our basis back to z and make a second measurement
qc.h(qr)
qc.measure(qr, cr[1])
qc.draw("mpl")
# Step 2: Transpile the circuit for running on a quantum computer
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
# Step 3: Run the job on a real quantum computer
sampler = Sampler(mode=backend)
pubs = [qc_isa]
job = sampler.run(pubs)
res = job.result()
counts = res[0].data.c.get_counts()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_sampler.run([qc_isa])
# res=job.result()
# counts=res[0].data.c.get_counts()
# Step 4: Post-process
from qiskit.visualization import plot_histogram
plot_histogram(counts)
Qui sembriamo avere ancora meno prevedibilità! In precedenza, almeno sapevamo quale sarebbe stato l'esito della prima misurazione; ora abbiamo una distribuzione piuttosto uniforme su tutti i possibili stati. Non è difficile capire perché sia successo. Siamo partiti da , che è una miscela 50-50 di e , secondo Quindi, chiaramente, la probabilità di ottenere lo stato + o - (mappato rispettivamente a 0 e 1 nel grafico) per la prima misurazione deve essere uguale. La misurazione lungo collassa lo stato in uno degli autostati oppure . Ciascuno di questi stati è una miscela 50-50 di e , secondo Quindi, una volta che il sistema si trova in un autostato di , le misurazioni lungo daranno ovviamente sia che , e lo faranno con probabilità approssimativamente uguali. Il nostro primo esempio ci ha mostrato che alcuni stati hanno risultati molto prevedibili per alcune misurazioni, ma imprevedibili per altre. L'esempio attuale ci mostra che si può fare peggio: ci sono stati che possono darci risultati imprevedibili per entrambe le misurazioni, anche se ci limitiamo a scambiare l'ordine delle misurazioni. Indaghiamo quanto una grandezza sia certa o incerta per un dato stato.
Calcolare l'incertezza
Possiamo quantificare tutto ciò usando l'incertezza, o varianza. L'"incertezza" è spesso definita come la radice quadrata della "varianza" di una distribuzione. Ovvero, l'incertezza per un'osservabile si denota ed è data da