Esplorare l'incertezza
Per questo modulo Qiskit in Classrooms, gli studenti devono avere un ambiente Python funzionante con i seguenti pacchetti installati:
qiskitv2.1.0 o più recenteqiskit-ibm-runtimev0.40.1 o più recenteqiskit-aerv0.17.0 o più recenteqiskit.visualizationnumpypylatexenc
Per configurare e installare i pacchetti di cui sopra, consultare la guida Installare Qiskit. Per poter eseguire lavori su veri computer quantistici, gli studenti dovranno creare un account con IBM Quantum® seguendo i passaggi della guida Set up your IBM Cloud account.
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 che richiedono molto tempo sono segnalati come tali nei commenti dell'intestazione e possono essere eseguiti su simulatori se gli studenti hanno poco tempo a disposizione per il QPU. Una volta rimossi, il modulo richiede solo 30 secondi di tempo per la QPU.
# 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'Guardate la spiegazione del modulo da parte della dottoressa Katie McCormick qui sotto, oppure fate clic qui per guardarla su YouTube.
Introduzione
Probabilmente avete sentito parlare del principio di indeterminazione, anche al di fuori dei corsi di fisica. Un'espressione colloquiale comune dell'incertezza è: "Guardando qualcosa, la si influenza" Questo è certamente vero. Ma un modo più fisico di descrivere l'incertezza è che ci sono alcune osservabili fisiche che hanno un'incompatibilità che impedisce loro di essere conosciute simultaneamente con una precisione arbitraria. Molti studenti si imbattono per la prima volta nella coppia di variabili incompatibili e , che indicano rispettivamente la posizione lungo un asse, chiamato asse , e il momento lineare lungo quella direzione. Per queste variabili il vincolo sull'incertezza si scrive Qui, è chiamata "incertezza in ", che ha la stessa definizione della deviazione standard in statistica, e può essere definita come è definito nello stesso modo. In questa sede non ricaveremo questa relazione di incertezza, ma sottolineeremo che è coerente con la nostra comprensione delle onde classiche. Cioè, un'onda con una frequenza davvero perfetta e una lunghezza d'onda continuerebbe all'infinito come una sinusoide perfetta. Dal punto di vista quantomeccanico, ciò corrisponderebbe a conoscere perfettamente la quantità di moto secondo l'ipotesi di de Broglie: . Ma per conoscere la posizione di una particella ondulatoria, l'onda che la descrive deve diventare più netta nello spazio, come una gaussiana molto stretta, ad esempio. Sappiamo che possiamo esprimere qualsiasi funzione continua, comprese le funzioni d'onda a picco, come una serie di Fourier di funzioni sinusoidali con lunghezze d'onda diverse. Ma quando la funzione d'onda diventa più acuta (e la posizione è meglio conosciuta), avremo bisogno di più termini nella serie di Fourier, il che significa una miscela di più lunghezze d'onda (e quindi, quantomeccanicamente, più valori di quantità di moto).
Detto più semplicemente: uno stato con una quantità di moto ben definita (una sinusoide perfetta nello spazio) ha una posizione molto incerta. Uno stato con una posizione ben definita (come una distribuzione delta di Dirac) ha una quantità di moto molto incerta.
Esistono altre variabili che presentano questa incompatibilità. Ad esempio, lo spin di una particella può avere una proiezione ben definita lungo un asse, ma 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 (di 1 nel contesto di un qubit e di nel contesto di una particella spin-1/2 ). Ma questo stato può essere scritto come una sovrapposizione di due stati, ognuno dei quali ha una proiezione ben definita sull'asse : o equivalentemente 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 piccole differenze quando si parla di spin e di qubit. In generale, però, gli autostati delle matrici di Pauli hanno una relazione interessante che possiamo esplorare. Nel corso di questa lezione, verificheremo sperimentalmente la nostra intuizione sull'incertezza di queste variabili incompatibili e verificheremo che le relazioni di incertezza sono valide sui computer quantistici IBM®.
Semplice verifica dell'intuizione
In questo primo esperimento e in tutto il modulo, utilizzeremo un framework per il calcolo quantistico noto come "Qiskit patterns", che suddivide i flussi di lavoro nelle seguenti fasi:
- Fase 1: mappare gli input classici in un problema quantistico
- Fase 2: Ottimizzazione del problema per l'esecuzione quantistica
- Fase 3: Esecuzione tramite le primitive " IBM Quantum "
- Fase 4: post-elaborazione e analisi classica
In genere seguiamo questi passaggi, anche se non sempre li indichiamo esplicitamente.
Iniziamo caricando alcuni pacchetti necessari, tra cui le primitive di Runtime. Selezioneremo anche il computer quantistico meno impegnato a nostra disposizione.
Di seguito è riportato un codice per salvare le credenziali al primo utilizzo. Assicurarsi di eliminare queste informazioni dal blocco note dopo averlo salvato nel proprio ambiente, in modo che le credenziali non vengano accidentalmente condivise quando si condivide il blocco note. Per ulteriori informazioni, vedere Configurazione dell'account IBM Cloud e Inizializzazione del servizio in un ambiente non attendibile.
from numpy import pi
# Load IBM Quantum Compute 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)Output:
ibm_sherbrooke
Se uno studente esaurisce il tempo disponibile per il calcolo quantistico durante la lezione, le righe seguenti possono essere non commentate e utilizzate per impostare un simulatore che imiti in parte il comportamento del rumore 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}})Si ricorda che un autostato di un operatore, Z, non è un autostato di un altro operatore, X. Lo osserveremo ora, sperimentalmente, effettuando misure lungo gli assi e . Per la misura lungo , usiamo semplicemente qc.measure (), perché i computer quantistici IBM sono strutturati per misurare lungo . Ma per misurare lungo , dobbiamo ruotare il sistema per spostare effettivamente l'asse fino all'orientamento lungo il quale misuriamo. Questo si ottiene con un cancello di Hadamard. Un passo simile è richiesto per le misure lungo . I passaggi necessari sono raccolti qui per comodità:
- Per misurare lungo :
qc.measure() - Per misurare lungo :
qc.h()quindiqc.measure() - Per misurare lungo :
qc.sdg(),qc.h(),qc.spoiqc.measure()
Fase 1: mappare gli input classici su un problema quantistico
In questo caso, la fase di mappatura consiste semplicemente nell'esprimere le misure e le rotazioni descritte in precedenza 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")Output:
Fase 2: Ottimizzazione del problema per l'esecuzione quantistica
Questa fase prende le operazioni che vogliamo eseguire e le esprime in termini di funzionalità di uno specifico computer quantistico. Inoltre, il nostro problema è stato tracciato sul layout 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)Fase 3: Esecuzione tramite le primitive " IBM Quantum "
Possiamo utilizzare Sampler per raccogliere dati statistici sulle misurazioni. Realizzeremo la primitiva Sampler in modo che funzioni su un vero computer quantistico utilizzando mode = backend. Esistono altre modalità per altri flussi di lavoro, e ne useremo una qui di seguito. Sampler verrà utilizzato richiamando il suo metodo run() con un elenco di "pubs" (Primitive Unified Blocs). Ogni voce contiene fino a tre valori che, insieme, definiscono un'unità di lavoro che lo stimatore deve completare: circuiti, grandezze osservabili, parametri. È inoltre possibile fornire un elenco di circuiti, un elenco di grandezze osservabili e un elenco di parametri. Per ulteriori informazioni, consulta la panoramica sui PUB.
Vogliamo eseguire su un vero computer quantistico, in modo da realizzare un vero esperimento di fisica quantistica. Se si esaurisce il tempo a disposizione sui computer quantistici reali, è possibile 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()Fase 4: Post-elaborazione
Si tratta di un caso particolarmente semplice di post-elaborazione, in cui ci si limita a visualizzare i conteggi.
Si noti che Qiskit ordina i qubit, le misure e altre cose elencando l'elemento con il numero più basso per ultimo / a destra, una convenzione definita "little-endian". Ciò significa che la colonna sottostante etichettata "10" si riferisce ai conteggi in cui la prima misurazione ha prodotto uno "0" e la seconda un "1".
# Step 4: Post-process
from qiskit.visualization import plot_histogram
plot_histogram(counts)Output:
Se questa convenzione non è di vostro gradimento, potete usare marginal_counts per visualizzare i risultati di ogni misura separatamente:
from qiskit.result import marginal_counts
plot_histogram(
marginal_counts(counts, indices=[0]), title="Counts after first measurement"
)Output:
plot_histogram(
marginal_counts(counts, indices=[1]), title="Counts after second measurement"
)Output:
Per impostazione predefinita, gli stati in Qiskit sono inizializzati allo stato . Non sorprende quindi che quasi tutte le prime misurazioni abbiano dato come risultato . Si noti, tuttavia, che la seconda misurazione (quella che fornisce informazioni sulle proiezioni dello stato su ) è stata quasi equamente suddivisa. Sembra che questo stato, che ci dà un risultato molto prevedibile delle misurazioni lungo , ci dia un insieme molto imprevedibile di risultati per le misurazioni lungo . Esploriamo questo aspetto.
Cosa succede se si effettuano le misurazioni nell'ordine opposto? Potremmo iniziare usando il gate di Hadamard per ottenere statistiche sulla probabilità che sia misurato in . Poi, per la seconda misurazione, torneremo alla base utilizzando 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")Output:
# 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)Output:
Qui sembra che la prevedibilità sia ancora minore! Prima sapevamo almeno quale sarebbe stato il risultato della prima misurazione, ora abbiamo una distribuzione abbastanza uniforme tra tutti gli stati possibili. Non è difficile capire perché sia successo. Abbiamo iniziato con , che è una miscela al 50-50 di e , secondo È evidente che la probabilità di ottenere lo stato + o - (mappato a 0 e 1 nel grafico) per la prima misurazione deve essere uguale. La misura lungo fa collassare lo stato in un autostato o in un autostato . Ognuno di questi stati è una miscela 50-50 di e , in base a Quindi, una volta che il sistema si trova in un autostato di , è chiaro che le misure lungo produrranno sia sia , e lo faranno con una probabilità approssimativamente uguale. Il primo esempio ci ha mostrato che alcuni Stati avranno risultati molto prevedibili per alcune misure, ma imprevedibili per altre. L'esempio attuale ci dimostra che possiamo fare peggio di così. Ci sono stati che possono dare risultati imprevedibili per entrambe le misurazioni, anche se tutto ciò che facciamo è scambiare l'ordine delle misurazioni. Cerchiamo di capire quanto sia certa o incerta una quantità per un determinato stato.
Calcolo dell'incertezza
Possiamo quantificare questo aspetto utilizzando l'incertezza, o varianza. L'"incertezza" è spesso definita come la radice quadrata della "varianza" di una distribuzione. Cioè, l'incertezza per una certa osservabile è indicata con ed è data da
Per il caso delle matrici di Pauli, per le quali , questo diventa
Applichiamo questo principio a un esempio concreto. Partiamo dallo stato e determiniamo l'incertezza dell'osservabile in quello stato.
Verifica la tua comprensione
Calcolare l'incertezza di nello stato , a mano.
Nello stato dato, si ottiene:
Possiamo creare uno stato iniziale arbitrario usando qc.initialize(). Si noti che la sintassi per l'unità immaginaria è .
# Step 1: Map the problem into a quantum circuit
from qiskit.quantum_info import SparsePauliOp
import numpy as np
obs = SparsePauliOp("X")
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(1, "c")
qc = QuantumCircuit(qr, cr)
# Initialize the state
qc.initialize([1, 1j] / np.sqrt(2))
# Step 2: Transpile the circuit
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs_isa = obs.apply_layout(layout=qc_isa.layout)
# Step 3: Run the circuit on a real quantum computer
estimator = Estimator(mode=backend)
pubs = [(qc_isa, obs_isa)]
job = estimator.run([[qc_isa, obs_isa]])
res = job.result()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_estimator.run([[qc_isa,obs_isa]])
# res=job.result()
# Step 4: Return the result in classical form, and analyze.
print(res[0].data.evs)Output:
-0.02408454165642664
Secondo l'equazione di cui sopra, Manteniamo lo stesso stato, ma troviamo il valore di aspettativa di , ora:
# Step 1: Map the problem into a quantum circuit
obs = SparsePauliOp("Z")
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(1, "c")
qc = QuantumCircuit(qr, cr)
# Initialize the state to |+>_y
qc.initialize([1, 1j] / np.sqrt(2))
# Step 2: Transpile the circuit
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs_isa = obs.apply_layout(layout=qc_isa.layout)
# Step 3: Run the circuit on a real quantum computer
estimator = Estimator(mode=backend)
pubs = [(qc_isa, obs_isa)]
job = estimator.run(pubs)
res = job.result()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_estimator.run([[qc_isa,obs_isa]])
# res=job.result()
# Step 4: Return the result in classical form, and analyze.
print(res[0].data.evs)Output:
0.04958271968581247
Potremmo fare gli stessi calcoli di prima, ma vedremmo che la varianza è di nuovo molto vicina a 1.0. Potremmo concludere che . In effetti questo è approssimativamente corretto per lo stato che abbiamo scelto. Ma possiamo fare di meglio? O peggio?
Ricordiamo che esiste una relazione di incertezza tra la posizione lungo una direzione, e la quantità di moto lungo la stessa direzione, . Per queste variabili, ma la forma più familiare è probabilmente Se ricordiamo solo questo, potremmo essere tentati di pensare che anche e possano avere un limite fondamentale di incertezza. Forse è impossibile che il prodotto raggiunga lo zero? Proviamo con un altro stato e vediamo se questo regge. Questa volta useremo Vediamo cosa succede. Si noti che nel codice sottostante, lo stimatore può accettare due serie di circuiti e osservabili nello stesso invio di lavoro.
# Step 1: Map the problem into a quantum circuit
obs1 = SparsePauliOp("X")
obs2 = SparsePauliOp("Z")
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(1, "c")
qc = QuantumCircuit(qr, cr)
# Initialize the state
qc.initialize([1, 1] / np.sqrt(2))
# Step 2: Transpile the circuit
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs1_isa = obs1.apply_layout(layout=qc_isa.layout)
obs2_isa = obs2.apply_layout(layout=qc_isa.layout)
# Step 3: Run the circuit on a real quantum computer
with Batch(backend=backend) as batch:
estimator = Estimator(mode=batch)
pubs = [(qc_isa, obs1_isa), (qc_isa, obs2_isa)]
job = estimator.run(pubs)
res = job.result()
batch.close()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_estimator.run([[qc,obs1],[qc,obs2]])
# res=job.result()
# Step 4: Return the result in classical form, and analyze.
print("The expectation value of the first observable is: ", res[0].data.evs)
print("The expectation value of the second observable is: ", res[1].data.evs)Output:
The expectation value of the first observable is: 1.0011036174126302
The expectation value of the second observable is: 0.0029429797670141016
Il valore atteso di dovrebbe essere vicino a 1.0, ma non dovrebbe superare 1.0. Non preoccupatevi se supera di pochissimo 1.0. Ciò può essere attribuito a fattori quali il rumore e/o l'errore di lettura. Sebbene si tratti di un argomento molto importante, per ora possiamo ignorarlo.
Abbiamo ottenuto un valore di aspettativa di molto vicino a 1.0 (corrispondente a una varianza molto bassa per ). Ciò rende il prodotto delle due varianze piuttosto basso:
Anche se non è esattamente zero, questo valore diventa piccolo rispetto agli autovalori degli operatori di Pauli ( ). Si può ricordare che la relazione di incertezza tra posizione e quantità di moto lineare può essere scritta in modo diverso, utilizzando esplicitamente la relazione di commutazione tra gli operatori e :
Dove
è il commutatore di e .
Questa è la forma che può essere più facilmente estesa agli operatori di Pauli. In generale, per due operatori e ,
E nel caso delle matrici di Pauli e , abbiamo bisogno di per calcolare
Lo mostriamo qui e lasciamo al lettore calcoli simili come esercizio:
Si tratta di una risposta perfettamente accettabile, ma con un ulteriore passaggio, vediamo che
La nostra relazione di incertezza diventa quindi
Verifica la tua comprensione
Determinare e . Utilizzare questo dato per scrivere le relazioni di incertezza tra e , e e .
Combinando con la relazione di incertezza generale, abbiamo
Verifica la coerenza
Prima di proseguire, verifichiamo la coerenza con il risultato precedente. Abbiamo usato lo stato e abbiamo trovato che Ora sappiamo che questo prodotto deve essere maggiore o uguale a
Così, in effetti, è,
Utilizzate le domande che seguono per costruire un'intuizione su questi risultati:
Verifica la tua comprensione
Rispondere ai seguenti elementi insieme come un set:
(a) Quali stati vi aspettereste che abbiano un'incertezza pari a zero in ?
(b) Quali stati vi aspettereste che abbiano un'incertezza pari a zero in ?
(c) In quali stati si otterrebbe un valore di aspettativa nullo ?
(d) Le risposte alle domande precedenti sono coerenti con il caso ?
(e) Scrivere il codice per verificare esplicitamente questo dato utilizzando lo stimatore.
(a) Potremmo aspettarci che gli autostati dell'operatore producano un'incertezza pari a zero in . Infatti, usando abbiamo
(b) Potremmo aspettarci che gli autostati dell'operatore producano un'incertezza nulla in . Infatti, usando abbiamo
(c) Ci aspettiamo di trovare per tutti gli stati che, quando vengono misurati, producono una proiezione positiva sull'asse con la stessa frequenza di una proiezione negativa. Questi includono gli autostati di e .
(d) Sì. Ci si aspetterebbe un valore molto piccolo per il prodotto delle incertezze per gli autostati di o : Questo può valere perché ci aspetteremmo anche per questi stessi stati. Quindi la relazione di incertezza potrebbe essere soddisfatta.
(e) Un codice come il seguente potrebbe verificarlo:
obs1 = SparsePauliOp.from_list( [("X", 1.000)] ) obs2 = SparsePauliOp.from_list( [("Y", 1.000)] ) obs3 = SparsePauliOp.from_list( [("Z", 1.000)] ) qc = QuantumCircuit(1,1) qc.ry(pi/2,0) job = estimator.run([(qc, [[obs1], [obs2], [obs3]])], precision=0.001) res=job.result()Dove i risultati restituiscono tutti i valori di aspettativa. Per recuperare tutti i valori di aspettativa e calcolare le incertezze, si può utilizzare:
xs=res[0].data.evs[0] ys=abs(res[0].data.evs[1]) zs=res[0].data.evs[2] import math prodxz=((1-xs[i]*xs[i])**0.5)*(1-zs[i]*zs[i])**0.5
Rispondere ai seguenti elementi insieme come un set:
(a) Si può pensare a uno stato in cui si avrebbe un grande valore di aspettativa ?
(b) Vi aspettereste che lo stesso stato abbia una grande o piccola incertezza in ?
(c) Vi aspettereste che lo stesso stato abbia una grande o piccola incertezza in ?
(d) Le risposte alle domande precedenti sono coerenti con il caso ?
(e) Scrivere il codice per verificare esplicitamente questo dato utilizzando lo stimatore.
(a) Ci aspettiamo di trovare per l'autostato di : .
(b) Potremmo aspettarci che abbia una grande incertezza nello stato poiché la misurazione di in quello stato darebbe un risultato positivo e negativo con uguale frequenza/probabilità.
(c) Potremmo aspettarci che abbia una grande incertezza nello stato , poiché la misurazione di in quello stato darebbe un risultato positivo e negativo con uguale frequenza/probabilità.
(d) Sì. Ci si aspetterebbe un valore elevato per il prodotto delle incertezze per gli autostati di e per in particolare. Ci aspetteremmo anche per lo stesso stato. Quindi sia che sono entrambi abbastanza grandi in questo stato, ed è plausibile che la relazione di incertezza possa essere nuovamente soddisfatta.
(e) Un codice come il seguente potrebbe verificarlo:
obs1 = SparsePauliOp.from_list( [("X", 1.000)] ) obs2 = SparsePauliOp.from_list( [("Y", 1.000)] ) obs3 = SparsePauliOp.from_list( [("Z", 1.000)] ) qc = QuantumCircuit(1,1) qc.rx(-pi/2,0) job = estimator.run([(qc, [[obs1], [obs2], [obs3]])], precision=0.001) res=job.result()Dove i risultati restituiscono tutti i valori di aspettativa. Per recuperare tutti i valori di aspettativa e calcolare le incertezze, si può utilizzare:
xs=res[0].data.evs[0] ys=abs(res[0].data.evs[1]) zs=res[0].data.evs[2] import math prodxz=((1-xs[i]*xs[i])**0.5)*(1-zs[i]*zs[i])**0.5
Relazioni di incertezza nei test
Il test precedente ha dimostrato la validità della relazione di incertezza solo per una singola scelta del vettore di stato . Per convincerci che questa relazione è generalmente coerente con l'esperimento, dovremmo eseguire calcoli simili utilizzando lo stimatore per molte scelte del vettore di stato. Cominciamo a ruotare il nostro vettore di stato lontano dall'asse , usando un gate RY per produrre diversi stati iniziali usando un parametro .
# The calculation below uses approximately 3-4 minutes of QPU time.
# Step 1: Map the problem into a quantum circuit
from qiskit.circuit import Parameter
import numpy as np
# Specify observables
obs1 = SparsePauliOp("X")
obs2 = SparsePauliOp("Y")
obs3 = SparsePauliOp("Z")
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(1, "c")
qc = QuantumCircuit(qr, cr)
# Rotate away from |0>
theta = Parameter("θ")
qc.ry(theta, 0)
params = np.linspace(0, 2, num=21)
# Step 2: Transpile the circuit
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs1_isa = obs1.apply_layout(layout=qc_isa.layout)
obs2_isa = obs2.apply_layout(layout=qc_isa.layout)
obs3_isa = obs3.apply_layout(layout=qc_isa.layout)
# Step 3: Run the circuit on a real quantum computer
with Batch(backend=backend) as batch:
estimator = Estimator(mode=batch)
pubs = [(qc_isa, [[obs1_isa], [obs2_isa], [obs3_isa]], [params])]
job = estimator.run(pubs, precision=0.01)
res = job.result()
batch.close()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_estimator.run([(qc, [[obs1], [obs2], [obs3]], [params])])
# res=job.result()# Step 4: Post-processing and classical analysis.
xs = res[0].data.evs[0]
ys = abs(res[0].data.evs[1])
zs = res[0].data.evs[2]
# Calculate uncertainties
delx = []
delz = []
prodxz = []
for i in range(len(xs)):
delx.append(abs((1 - xs[i] * xs[i])) ** 0.5)
delz.append(abs((1 - zs[i] * zs[i])) ** 0.5)
prodxz.append(delx[i] * delz[i])# Here we can plot the results from this simulation.
import matplotlib.pyplot as plt
plt.plot(params, delx, label=r"$\Delta$ X")
plt.plot(params, ys, label=r"$\langle$ Y $\rangle$")
plt.plot(params, delz, label=r"$\Delta$ Z")
plt.plot(params, prodxz, label=r"$\Delta$X $\Delta$Z")
plt.xlabel(r"$\theta$")
plt.ylabel("Expectation/Uncertainty Values")
plt.legend()
plt.show()Output:
Si noti che la curva rossa è sempre maggiore della curva arancione A volte il prodotto dell'incertezza si abbassa e si avvicina al limite, altre volte si alza e si allontana dal limite, ma obbedisce sempre alla relazione di incertezza.
Naturalmente, questo potrebbe non essere il miglior test della relazione di incertezza, poiché il nostro limite è sempre molto vicino a zero. Utilizziamo uno stato quantico che abbia una proiezione maggiore sugli autostati di . In particolare, ruoteremo ancora verso il basso rispetto all'asse di vari angoli, ma ora ruoteremo anche lo stato risultante intorno a di un certo angolo, forse , e vedremo cosa succede.
# The calculation below uses approximately 3-4 minutes of QPU time.
from qiskit.circuit import Parameter
import numpy as np
# Step 1: Map the problem to a quantum circuit
# Specify observables
obs1 = SparsePauliOp("X")
obs2 = SparsePauliOp("Y")
obs3 = SparsePauliOp("Z")
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(1, "c")
qc = QuantumCircuit(qr, cr)
# Rotate away from |0> along one plane, and then along a transverse direction.
theta = Parameter("θ")
qc.ry(theta, 0)
qc.rz(pi / 4, 0)
params = np.linspace(0, 2, num=21)
# Step 2: Transpile the circuit
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs1_isa = obs1.apply_layout(layout=qc_isa.layout)
obs2_isa = obs2.apply_layout(layout=qc_isa.layout)
obs3_isa = obs3.apply_layout(layout=qc_isa.layout)
# Step 3: Run the circuit on a real quantum computer
with Batch(backend=backend) as batch:
estimator = Estimator(mode=batch)
pubs = [(qc_isa, [[obs1_isa], [obs2_isa], [obs3_isa]], [params])]
job = estimator.run(pubs, precision=0.01)
res = job.result()
batch.close()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_estimator.run([(qc, [[obs1], [obs2], [obs3]], [params])])
# res=job.result()# Step 4: Post-processing and classical analysis.
xs = res[0].data.evs[0]
ys = abs(res[0].data.evs[1])
zs = res[0].data.evs[2]
# Calculate uncertainties
delx = []
delz = []
prodxz = []
for i in range(len(xs)):
delx.append(abs((1 - xs[i] * xs[i])) ** 0.5)
delz.append(abs((1 - zs[i] * zs[i])) ** 0.5)
prodxz.append(delx[i] * delz[i])# Here we can plot the results from this simulation.
import matplotlib.pyplot as plt
plt.plot(params, delx, label=r"$\Delta$ X")
plt.plot(params, ys, label=r"$\langle$ Y $\rangle$")
plt.plot(params, delz, label=r"$\Delta$ Z")
plt.plot(params, prodxz, label=r"$\Delta$X $\Delta$Z")
plt.xlabel(r"$\theta$")
plt.ylabel("Expectation/Uncertainty Values")
plt.legend()
plt.show()Output:
Ora vediamo che il limite dell'incertezza viene messo alla prova! La curva rossa si avvicina molto di più alla curva arancione rispetto a prima. Infatti, in assenza di rumore, la relazione di indeterminazione sarebbe esattamente saturata ( ) un punto. In presenza di rumore ed errore di lettura, non dovrebbe sorprendere se occasionalmente una corsa produca un risultato leggermente superiore a Questo non è un vero e proprio caso di violazione dell'incertezza, ma solo un artefatto dell'errore diverso da zero.
Verifica la tua comprensione
Spiega come porteresti questo concetto al limite estremo, rendendo l’ e il più ampio possibile.
Il codice attualmente contiene linee che ruotano lo stato iniziale predefinito , verso il basso rispetto all'asse di un angolo parametrizzato e poi anche intorno all'asse di un angolo che ruota il vettore di stato per una parte del percorso verso l'asse .
qc.ry(theta,0)qc.rz(pi/4,0)Potremmo cambiare la rotazione intorno a da a , ruotando fino a un autostato di :
qc.ry(theta,0)qc.rz(pi/2,0)Non sono necessarie altre modifiche.
Modificare il codice o copiarlo e implementare il controllo della relazione di incertezza con il valore di aspettativa di Y massimizzato. La relazione di incertezza è valida?
Si utilizzerà esattamente il codice dell'esempio precedente, con
qc.rz(pi/2,0)sostituita da un'altra per sostituire
qc.rz(pi/4,0).La figura risultante dovrebbe assomigliare a quella qui sotto, e sì, il principio di indeterminazione dovrebbe essere ancora valido.

Modificate il codice precedente per realizzare un'immagine simile, dimostrando che dalle misure sul computer quantistico il prodotto si comporta come dovrebbe. Scegliere una serie di stati a piacere.
Utilizzeremmo esattamente il codice dell'esempio precedente e, in effetti, potremmo usare gli stessi risultati di prima, solo utilizzando i valori di aspettativa per calcolare le diverse incertezze. Ad esempio, si può usare
xs=res[0].data.evs[0] ys=res[0].data.evs[1] zs=abs(res[0].data.evs[2]) import math delx = [] dely = [] prodxy=[] for i in range(len(xs)): delx.append((1-xs[i]*xs[i])**0.5) dely.append((1-ys[i]*ys[i])**0.5) prodxy.append(((1-xs[i]*xs[i])**0.5)*(1-ys[i]*ys[i])**0.5)e potremmo tracciare
import matplotlib.pyplot as plt plt.plot(params, delx, label=r'$\Delta$ X') plt.plot(params, dely, label=r'$\langle$ Y $\rangle$') plt.plot(params, zs, label=r'$\Delta$ Z') plt.plot(params, prodxy, label=r'$\Delta$X $\Delta$Z') plt.xlabel(r'$\theta$') plt.ylabel('Expectation/Uncertainty Values') plt.legend() plt.show()
Sfida: Scrivere un codice per analizzare molti valori di , così come abbiamo analizzato molti valori di , e creare un grafico 3D che mostri che la relazione di incertezza non viene mai violata. Scegliere gli osservabili desiderati.
Domande
Gli insegnanti possono richiedere le versioni di questi quaderni con le chiavi di risposta e le indicazioni per l'inserimento nei curricula comuni compilando questo rapido sondaggio sull'utilizzo dei quaderni.
Concetti fondamentali:
- Esistono relazioni di incertezza tra molti insiemi di osservabili fisici, tra cui la posizione, la quantità di moto lineare e le componenti dello spin.
- Le matrici di Pauli non commutano. Questo è un riflesso matematico del fatto che non tutte le componenti dello spin possono essere conosciute/determinate simultaneamente.
- L'informatica quantistica fa un uso massiccio degli operatori/matrici di Pauli, quindi è utile conoscere la relazione di incertezza per gli operatori di Pauli e per gli operatori di spin strettamente correlati.
- Una formula generale per l'incertezza di due operatori e è
- Uno stato proprio di un operatore comporta un'incertezza pari a zero nell'osservabile fisico associato a tale operatore. Anche a livello sperimentale,
- Un autostato di un qualche operatore produrrà un'incertezza maggiore per un operatore che non commuta con .
- I risultati sperimentali ottenuti con un computer quantistico reale confermano l'intuizione che si ottiene dalle rappresentazioni matriciali degli operatori fisici.
Domande vero/falso:
- T/F Si possono misurare contemporaneamente e , ma non .
- T/F Si possono misurare contemporaneamente e , ma non .
- T/F Gli operatori di posizione lineare e di quantità di moto lineare non si commutano.
- T/F IBM computer quantistici misurano per default lungo , quindi è necessario eseguire una rotazione per misurare lungo qualsiasi altra direzione.
- T/F Il circuito sottostante misura effettivamente e poi .
Domande dell'MC:
-
Il diagramma seguente dimostra quale delle seguenti relazioni di incertezza?
- a.
- b.
- c.
- d. Nessuna delle precedenti
-
Quale delle seguenti è la sequenza standard per eseguire una misura lungo ?
- a. Solo
qc.measure() - b.
qc.h()alloraqc.measure() - c.
qc.h(),qc.h()alloraqc.measure() - d.
qc.h(),qc.s,qc.h()alloraqc.measure() - e.
qc.sdg(),qc.h(),qc.salloraqc.measure() - f.
qc.sdg(),qc.h(),qc.s,qc.h()poiqc.measure()
- a. Solo
-
Quale dei seguenti stati produce il più grande valore di aspettativa ?
- a.
- b.
- c. chiamato anche
- d. chiamato anche
- e. chiamato anche
- f. chiamato anche
-
Quale dei seguenti stati produce la maggiore incertezza ?
- a.
- b. chiamato anche
- c. chiamato anche
- d. a e b sono in parità
- e. b e c sono in parità
- f. a, b e c sono in parità
Domande di discussione:
-
Questo concetto di incertezza è in qualche modo in conflitto con la nozione di spin come freccia vettoriale nello spazio cartesiano? E sulla sfera di Bloch?
-
Supponiamo di orientare un dispositivo di misura lungo una direzione a metà strada tra gli assi e . Cosa succede? È possibile effettuare una misurazione in questa direzione? In che modo questo si collega all'incertezza di e ?
-
Quali altri esperimenti vorreste fare per convincervi dei risultati ottenuti?