Explorând incertitudinea
Pentru acest modul Qiskit in Classrooms, studenții trebuie să aibă un mediu Python funcțional cu următoarele pachete instalate:
qiskitv2.1.0 sau mai nouqiskit-ibm-runtimev0.40.1 sau mai nouqiskit-aerv0.17.0 sau mai nouqiskit.visualizationnumpypylatexenc
Pentru a configura și instala pachetele de mai sus, consulta ghidul Instalare Qiskit. Pentru a rula joburi pe calculatoare cuantice reale, studenții vor trebui să își creeze un cont IBM Quantum® urmând pașii din ghidul Configurează-ți contul IBM Cloud.
Acest modul a fost testat și a utilizat 8 minute de timp QPU. Aceasta este doar o estimare. Utilizarea ta reală poate varia. Două calcule care consumă mult timp sunt marcate ca atare în comentariile de antet și pot fi efectuate pe simulatoare dacă studenții au puțin timp QPU disponibil. Fără acestea, modulul necesită doar ~30 de secunde de timp 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'
Urmărește prezentarea modulului de Dr. Katie McCormick mai jos sau dă clic aici pentru a o urmări pe YouTube.
Introducere
Probabil că ai auzit de principiul incertitudinii chiar și în afara cursurilor de fizică. O reformulare colocvială frecventă a incertitudinii este: „Privind ceva, îl influențezi." Acest lucru este cu siguranță adevărat. Dar un mod mai fizic de a descrie incertitudinea este că există anumite observabile fizice care au o incompatibilitate ce le împiedică pe ambele să fie cunoscute simultan cu orice acuratețe arbitrară. Mulți studenți întâlnesc pentru prima dată perechea de variabile incompatibile și , adică poziția de-a lungul unei axe numite axa și, respectiv, impulsul liniar de-a lungul acelei direcții. Pentru acele variabile, constrângerea asupra incertitudinii se scrie Aici, se numește „incertitudinea în ", care are aceeași definiție ca deviația standard în statistică, și poate fi definită ca este definit în același mod. Aici nu vom deriva această relație de incertitudine; vom sublinia că este consistentă cu înțelegerea noastră a undelor clasice. Adică, o undă cu o frecvență și o lungime de undă cu adevărat perfecte ar continua la nesfârșit ca un sinusoid perfect. Din punct de vedere al mecanicii cuantice, acest lucru ar corespunde cunoașterii perfecte a impulsului conform ipotezei lui de Broglie: . Dar pentru a ști se află o particulă asemănătoare unei unde, unda care o descrie trebuie să devină mai abruptă în spațiu, ca o gaussiană foarte îngustă, de exemplu. Știm că putem exprima orice funcție continuă, inclusiv astfel de funcții de undă ascuțite, ca o serie Fourier de funcții sinusoidale cu diferite lungimi de undă. Dar pe măsură ce funcția de undă devine mai abruptă (și poziția este mai bine cunoscută), vom necesita mai mulți termeni în seria Fourier, adică un amestec de mai multe lungimi de undă (și, din punct de vedere al mecanicii cuantice, mai multe valori ale impulsului).
Spus mai simplu: o stare cu un impuls bine definit (un sinusoid perfect în spațiu) are o poziție foarte incertă. O stare cu o poziție bine definită (ca o distribuție Dirac delta) are un impuls foarte incert.
Există și alte variabile care prezintă o astfel de incompatibilitate. De exemplu, spinul unei particule poate avea o proiecție bine definită de-a lungul unei axe, dar atunci nu știm nimic despre proiecția pe o axă ortogonală. De exemplu, starea (pentru un Qubit sau o particulă spin-1/2) are o proiecție certă de-a lungul axei (de 1 în contextul unui Qubit și de în contextul unei particule spin-1/2). Dar această stare poate fi scrisă ca o superpozitie a două stări, fiecare având o proiecție bine definită pe axa : sau echivalent are o proiecție bine definită pe , la fel și . Deci, dacă specificăm proiecția unei stări de-a lungul axei , nu știm proiecția de-a lungul axei . Iar dacă specificăm proiecția pe axa , nu știm proiecția de-a lungul lui . Există mici diferențe atunci când discutăm acest lucru în contextul spinului față de Qubiți. Dar, în general, stările proprii ale matricelor Pauli au o relație interesantă pe care o putem explora. Pe parcursul acestei lecții, vom verifica experimental intuiția noastră pentru incertitudinea din aceste variabile incompatibile și vom verifica că relațiile de incertitudine sunt valabile pe calculatoarele cuantice IBM®.
Verificare simplă a intuiției
În acest prim experiment și pe parcursul întregului modul, vom folosi un cadru pentru calculul cuantic cunoscut sub numele de „Qiskit patterns", care împarte fluxurile de lucru în următorii pași:
- Pasul 1: Maparea intrărilor clasice la o problemă cuantică
- Pasul 2: Optimizarea problemei pentru execuția cuantică
- Pasul 3: Execuția folosind Qiskit Runtime Primitives
- Pasul 4: Post-procesarea și analiza clasică
În general, vom urma acești pași, deși nu îi vom eticheta întotdeauna explicit.
Să începem prin a încărca câteva pachete necesare, inclusiv primitive Runtime. De asemenea, vom selecta calculatorul cuantic cel mai puțin ocupat disponibil.
Mai jos există cod pentru salvarea credențialelor la prima utilizare. Asigură-te că ștergi aceste informații din notebook după ce le salvezi în mediul tău, astfel încât credențialele să nu fie împărtășite accidental atunci când distribui notebook-ul. Consultă Configurarea contului tău IBM Cloud și Inițializarea serviciului într-un mediu neîncrezut pentru mai multe îndrumări.
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
Dacă un student epuizează timpul disponibil de calcul cuantic în timpul lecției, liniile de mai jos pot fi decomentate și folosite pentru a configura un simulator care imită parțial comportamentul de zgomot al calculatorului cuantic selectat mai sus.
# 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}})
Poate îți amintești că o stare proprie a unui operator, Z, nu este o stare proprie a unui alt operator X. Vom observa asta acum, experimental, efectuând măsurători de-a lungul axelor și . Pentru măsurătoarea de-a lungul lui , pur și simplu folosim qc.measure(), deoarece calculatoarele cuantice IBM sunt concepute să măsoare de-a lungul lui . Dar pentru a măsura de-a lungul lui , trebuie să rotim sistemul pentru a muta efectiv axa în orientarea de-a lungul căreia măsurăm. Aceasta se realizează cu o poartă Hadamard. Există un pas similar necesar pentru măsurătorile de-a lungul lui . Pașii necesari sunt reuniți aici pentru comoditate:
- Pentru a măsura de-a lungul lui :
qc.measure() - Pentru a măsura de-a lungul lui :
qc.h()apoiqc.measure() - Pentru a măsura de-a lungul lui :
qc.sdg(),qc.h(),qc.sapoiqc.measure()
Pasul 1: Maparea intrărilor clasice la o problemă cuantică
În acest caz, pasul de mapare constă pur și simplu în exprimarea măsurătorilor și rotațiilor descrise mai sus într-un Circuit cuantic:
# 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")
Pasul 2: Optimizează problema pentru execuție cuantică
Acest pas preia operațiile pe care dorim să le efectuăm și le exprimă în termenii funcționalității unui calculator cuantic specific. De asemenea, mapează problema noastră pe structura calculatorului cuantic.
# 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)
Pasul 3: Execută folosind primitivele Qiskit Runtime
Putem folosi Sampler pentru a colecta statistici despre măsurători. Vom construi primitiva Sampler pentru a rula pe un calculator cuantic real folosind mode = backend. Există și alte moduri pentru alte fluxuri de lucru, pe care le vom folosi mai jos. Sampler va fi utilizat apelând metoda run() cu o listă de „pub-uri" (Primitive Unified Blocs). Fiecare pub conține până la trei valori care, împreună, definesc o unitate de calcul pe care estimatorul trebuie să o execute: circuite, observabile, parametri. Poți furniza, de asemenea, o listă de circuite, o listă de observabile și o listă de parametri. Pentru mai multe informații, citește Prezentarea generală a PUB-urilor.
Vrem să rulăm pe un calculator cuantic real, astfel încât să desfășurăm un experiment de fizică cuantică real. Dacă epuizezi timpul alocat pe calculatoarele cuantice reale, poți comenta codul de mai jos pentru calculatorul cuantic și decomenta codul pentru rularea pe un simulator.
# 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()
Pasul 4: Post-procesare
Acesta este un caz deosebit de simplu de post-procesare, în care pur și simplu vizualizăm numărătorile.
Reține că Qiskit ordonează qubiții, măsurătorile și alte elemente listând elementul cu numărul cel mai mic ultimul / la dreapta, o convenție denumită „little-endian". Aceasta înseamnă că coloana de mai jos etichetată „10" se referă la numărătorile în care prima măsurătoare a dat un „0", iar a doua măsurătoare a dat un „1".
# Step 4: Post-process
from qiskit.visualization import plot_histogram
plot_histogram(counts)
Dacă această convenție nu îți convine, poți folosi marginal_counts pentru a vizualiza rezultatele fiecărei măsurători separat:
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"
)
În mod implicit, stările în Qiskit sunt inițializate în starea . Prin urmare, nu este surprinzător că aproape toate primele măsurători au dat . Observă totuși că a existat o împărțire aproape egală în a doua măsurătoare (cea care oferă informații despre proiecțiile stării pe ). Se pare că această stare, care ne dă un rezultat foarte previzibil al măsurătorilor de-a lungul lui , ne dă un set de rezultate foarte imprevizibil pentru măsurătorile de-a lungul lui . Să explorăm asta.
Ce se întâmplă dacă facem măsurătorile în ordine inversă? Am putea începe folosind poarta Hadamard pentru a obține statistici despre probabilitatea ca să fie măsurat în . Apoi, pentru a doua măsurătoare, vom reveni la baza folosind o a doua poartă 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)
Aici, se pare că avem și mai puțină previzibilitate! Anterior, știam cel puțin care va fi rezultatul primei măsurători; acum avem o distribuție destul de uniformă între toate stările posibile. Nu este greu de înțeles de ce s-a întâmplat asta. Am pornit din , care este un amestec 50-50 de și , conform relației Deci, în mod evident, ar trebui să existe probabilitate egală de a obține starea + sau - (mapate la 0 și 1 în grafic) pentru prima măsurătoare. Măsurătoarea de-a lungul lui prăbușește starea fie într-o stare proprie , fie în starea proprie . Fiecare dintre aceste stări este un amestec 50-50 de și , conform relațiilor Prin urmare, odată ce sistemul se află într-o stare proprie a lui , măsurătorile de-a lungul lui vor da atât , cât și , și vor face asta cu probabilitate aproximativ egală. Astfel, primul nostru exemplu ne-a arătat că unele stări vor da rezultate foarte previzibile pentru anumite măsurători, dar rezultate imprevizibile pentru alte măsurători. Exemplul de față ne arată că putem face și mai rău decât atât. Există stări care pot da rezultate imprevizibile pentru ambele măsurători, chiar dacă tot ce facem este să schimbăm ordinea măsurătorilor. Să investigăm cât de certă sau de incertă este o mărime pentru o stare dată.
Calcularea incertitudinii
Putem cuantifica acest lucru folosind incertitudinea sau varianța. „Incertitudinea" este adesea definită ca rădăcina pătrată a „varianței" unei distribuții. Adică, incertitudinea pentru un observabil este notată și este dată de
Pentru cazul matricelor Pauli, pentru care , aceasta devine
Să aplicăm aceasta la un exemplu concret. Să pornim de la starea și să determinăm incertitudinea observabilului în acea stare.
Verifică-ți înțelegerea
Citește întrebarea de mai jos, gândește-te la răspuns, apoi apasă pe triunghi pentru a descoperi soluția.
Calculează incertitudinea lui în starea , de mână.
Răspuns:
În starea dată, aceasta produce:
Putem crea o stare inițială arbitrară folosind qc.initialize(). Rețineți că sintaxa pentru unitatea imaginară este .
# 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)
-0.02408454165642664
Conform ecuației de mai sus, Să rămânem cu aceeași stare, dar să găsim acum valoarea de așteptare a lui :
# 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)
0.04958271968581247
Am putea face același calcul ca înainte, dar am vedea că varianța este din nou foarte aproape de 1.0. Am putea concluziona că . Aceasta este într-adevăr aproximativ corectă pentru starea pe care am ales-o. Dar putem face mai bine? Sau mai rău?
Reamintim că există o relație de incertitudine între poziția de-a lungul unei direcții, și momentul de-a lungul aceleiași direcții, Pentru aceste variabile, cea mai familiară formă este probabil Dacă ne amintim doar atât, am putea fi tentați să credem că și ar putea avea și ele o limită fundamentală a incertitudinii. Poate că este imposibil ca produsul să atingă zero? Să încercăm o altă stare și să vedem dacă acest lucru se confirmă. De data aceasta, vom folosi Să vedem ce se întâmplă. Reține că în codul de mai jos, estimatorul poate accepta două seturi de circuite și observabile în aceeași trimitere de job.
# 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)
The expectation value of the first observable is: 1.0011036174126302
The expectation value of the second observable is: 0.0029429797670141016
Valoarea de așteptare a lui ar trebui să fie apropiată de 1,0, dar nu ar trebui să depășească 1,0. Nu te îngrijora dacă depășește 1,0 cu o cantitate foarte mică. Acest lucru poate fi atribuit unor factori precum zgomotul și/sau eroarea de citire. Deși acesta este un subiect foarte important, îl putem ignora pentru moment.
Am obținut o valoare de așteptare a lui foarte apropiată de 1,0 (corespunzând unei variații foarte mici pentru ). Aceasta face ca produsul celor două variații să fie destul de mic:
Deși acesta nu este exact zero, această valoare devine mică în comparație cu valorile proprii ale operatorilor Pauli (). Ei bine, poate îți amintești că relația de incertitudine dintre poziția liniară și moment putea fi scrisă diferit, folosind explicit relația de comutare dintre operatorii și :
unde
este comutatorul lui și .
Aceasta este forma care poate fi extinsă cel mai ușor la operatorii Pauli. În general, pentru doi operatori și ,
Iar în cazul matricelor Pauli și , avem nevoie de pentru a calcula
Arătăm acest lucru mai jos și lăsăm calcule similare cititorului ca exercițiu:
Acesta este un răspuns perfect acceptabil, dar cu încă un pas, vedem că
Relația noastră de incertitudine devine astfel
Verifică-ți înțelegerea
Citește întrebarea de mai jos, gândește-te la răspuns, apoi apasă pe triunghi pentru a dezvălui soluția.
Determină și . Folosește acestea pentru a scrie relațiile de incertitudine dintre & , și & .
Răspuns:
Combinând cu relația generală de incertitudine, obținem
Verifică consistența
Înainte de a continua, să verificăm că acest rezultat este consistent cu ce am găsit anterior. Am folosit starea Și am găsit că Acum știm că acest produs ar trebui să fie mai mare sau egal cu
Deci într-adevăr, Folosește întrebările de mai jos pentru a-ți dezvolta intuiția pentru aceste rezultate:
Verifică-ți înțelegerea
Citește întrebările de mai jos, gândește-te la răspunsuri, apoi apasă triunghiurile pentru a dezvălui soluțiile.
Răspunde la următoarele puncte împreună, ca un set:
(a) Ce stări ai aștepta să aibă incertitudine zero în ?
(b) Ce stări ai aștepta să aibă incertitudine zero în ?
(c) În ce stări ai obține o valoare de așteptare zero ?
(d) Sunt răspunsurile la întrebările de mai sus consistente cu cazul ?
(e) Scrie cod pentru a verifica explicit acest lucru folosind estimator.
Răspunsuri:
(a) Ne-am putea aștepta că stările proprii ale operatorului să producă incertitudine zero în . Într-adevăr, folosind avem
(b) Ne-am putea aștepta că stările proprii ale operatorului să producă incertitudine zero în . Într-adevăr, folosind avem
(c) Ne așteptăm să găsim pentru orice stări care, atunci când sunt măsurate, produc o proiecție pozitivă pe axa tot atât de des cât și o proiecție negativă. Acestea includ stările proprii ale și .
(d) Da. Ne-am aștepta la o valoare foarte mică pentru produsul incertitudinilor pentru stările proprii ale sau : Acest lucru poate fi valabil deoarece ne-am aștepta și la pentru aceleași stări. Astfel, relația de incertitudine ar putea fi satisfăcută.
(e) Cod de genul următor ar verifica acest lucru:
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()
Unde rezultatele returnează toate valorile de așteptare. Pentru a recupera toate valorile de așteptare și a calcula incertitudinile, am putea folosi:
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
Răspunde la următoarele puncte împreună, ca un set:
(a) Te poți gândi la o stare în care ai avea o valoare de așteptare mare ?
(b) Te-ai aștepta ca aceeași stare să aibă incertitudine mare sau mică în ?
(c) Te-ai aștepta ca aceeași stare să aibă incertitudine mare sau mică în ?
(d) Sunt răspunsurile la întrebările de mai sus consistente cu cazul ?
(e) Scrie cod pentru a verifica explicit acest lucru folosind estimator.
Răspunsuri:
(a) Ne așteptăm să găsim pentru starea proprie a lui : .
(b) Ne-am putea aștepta ca să aibă incertitudine mare în starea deoarece măsurarea lui în acea stare ar produce un rezultat pozitiv și unul negativ cu frecvență/probabilitate egală.
(c) Ne-am putea aștepta ca să aibă incertitudine mare în starea deoarece măsurarea lui în acea stare ar produce un rezultat pozitiv și unul negativ cu frecvență/probabilitate egală.
(d) Da. Ne-am aștepta la o valoare mare pentru produsul incertitudinilor pentru stările proprii ale și pentru în mod special. Ne-am aștepta, de asemenea, ca pentru acea aceeași stare. Astfel, atât cât și sunt ambele destul de mari în această stare, și este plauzibil că relația de incertitudine ar putea fi satisfăcută din nou.
(e) Cod de genul următor ar verifica acest lucru:
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()
Unde rezultatele returnează toate valorile de așteptare. Pentru a recupera toate valorile de așteptare și a calcula incertitudinile, am putea folosi:
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
Testarea relațiilor de incertitudine
Testul de mai sus a demonstrat valabilitatea relației de incertitudine doar pentru o singură alegere a vectorului de stare . Pentru a ne convinge că acest lucru este în general consistent cu experimentul, ar trebui să efectuăm calcule similare folosind estimatorul pentru multe alegeri ale vectorului de stare. Să începem prin a roti vectorul de stare față de axa , folosind un Gate RY pentru a produce diferite stări inițiale cu ajutorul unui parametru .
# 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()
Observă că curba roșie este întotdeauna mai mare decât curba portocalie Uneori produsul de incertitudine scade și este oarecum aproape de limită, iar alteori crește și este mai departe de limită, dar respectă întotdeauna relația de incertitudine.
Desigur, acesta s-ar putea să nu fie cel mai bun test al relației de incertitudine, deoarece limita noastră este întotdeauna foarte aproape de zero. Să folosim o stare cuantică care are o proiecție mai mare pe stările proprii ale lui . Mai precis, vom roti în continuare față de axa cu unghiuri variabile, dar acum vom roti și starea rezultată în jurul lui cu un anumit unghi, poate , și vom vedea ce se întâmplă.
# 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()
Acum vedem că limita incertitudinii este pusă cu adevărat la încercare! Curba roșie se apropie mult mai mult de curba portocalie decât înainte. De fapt, în absența zgomotului, relația de incertitudine ar fi exact saturată () într-un punct. În prezența zgomotului și a erorilor de citire, nu ar trebui să fie surprinzător dacă o rulare produce ocazional ușor mai mare decât Aceasta nu este o adevărată încălcare a incertitudinii; este doar un artefact al erorii non-zero.
Verifică-ți înțelegerea
Citește întrebările de mai jos, gândește-te la răspunsuri, apoi apasă pe triunghiuri pentru a dezvălui soluțiile.
Explică cum ai putea duce asta la limita absolută, maximizând cât mai mult posibil?
Răspuns:
Codul are în prezent linii care rotesc starea inițială implicită , coborând de pe axa cu un unghi parametrizat și apoi și în jurul axei cu un unghi care rotește vectorul de stare parțial spre axa .
qc.ry(theta,0)
qc.rz(pi/4,0)
Am putea schimba rotația în jurul lui de la la , rotind complet până la o stare proprie a lui :
qc.ry(theta,0)
qc.rz(pi/2,0)
Nu ar fi necesare alte modificări.
Modifică codul sau copiază-l și implementează acea verificare a relației de incertitudine cu valoarea de așteptare a lui Y maximizată. Relația de incertitudine se respectă?
Răspuns:
Am folosi exact codul din exemplul de mai sus, cu
qc.rz(pi/2,0)
înlocuind
qc.rz(pi/4,0).
Figura rezultată ar trebui să arate ca cea de mai jos și, da, principiul incertitudinii ar trebui să fie în continuare valabil.

Modifică codul de mai sus pentru a crea o imagine similară, demonstrând că din măsurătorile efectuate pe calculatorul cuantic produsul se comportă cum ar trebui. Alege orice set de stări dorești.
Răspuns:
Am folosi exact codul din exemplul de mai sus și, de fapt, am putea folosi aceleași rezultate de mai sus, utilizând pur și simplu valorile de așteptare pentru a calcula incertitudini diferite. De exemplu, am putea folosi
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)
și am putea reprezenta grafic
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()
Provocare: Scrie cod pentru a parcurge mai multe valori ale lui , la fel cum am parcurs mai multe valori ale lui , și creează un grafic 3D care să demonstreze că relația de incertitudine nu este niciodată violată. Alege orice observabile dorești.
Întrebări
Instructorii pot solicita versiuni ale acestor notebook-uri cu chei de răspuns și indicații privind plasarea în curricule comune, completând acest sondaj rapid despre modul în care sunt utilizate notebook-urile.
Concepte critice:
- Există relații de incertitudine între multe seturi de observabile fizice, inclusiv poziția și impulsul liniar, și componentele spinului.
- Matricele Pauli nu comutează. Aceasta este o reflectare matematică a faptului că nu toate componentele spinului pot fi cunoscute/determinate simultan.
- Calculul cuantic face uz intens de operatorii/matricele Pauli, deci este util să cunoști relația de incertitudine pentru operatorii Pauli, precum și operatorii de spin strâns înrudiți.
- O formulă generală pentru incertitudinea a doi operatori și este
- O stare proprie a unui operator produce incertitudine zero în observabila fizică asociată acelui operator. Chiar și experimental,
- O stare proprie a unui operator va produce o incertitudine mai mare pentru un operator care nu comutează cu .
- Rezultatele experimentale obținute folosind un calculator cuantic real confirmă intuiția pe care o câștigăm din reprezentările matriceale ale operatorilor fizici.
Întrebări A/F:
- A/F Se pot măsura simultan și , dar nu și .
- A/F Se pot măsura simultan și , dar nu și .
- A/F Operatorii de poziție liniară și de impuls liniar nu comutează.
- A/F Calculatoarele cuantice IBM măsoară implicit de-a lungul , deci trebuie efectuată o rotație pentru a măsura de-a lungul oricărei alte direcții.
- A/F Circuitul de mai jos măsoară efectiv și apoi .
Întrebări cu răspuns multiplu:
-
Diagrama de mai jos demonstrează care dintre următoarele relații de incertitudine?
- a.
- b.
- c.
- d. Niciuna dintre cele de mai sus

-
Care dintre următoarele este secvența standard pentru a efectua o măsurătoare de-a lungul ?
- a. Doar
qc.measure() - b.
qc.h()apoiqc.measure() - c.
qc.h(),qc.h()apoiqc.measure() - d.
qc.h(),qc.s,qc.h()apoiqc.measure() - e.
qc.sdg(),qc.h(),qc.sapoiqc.measure() - f.
qc.sdg(),qc.h(),qc.s,qc.h()apoiqc.measure()
- a. Doar
-
Care dintre următoarele stări produce cea mai mare valoare de așteptare ?
- a.
- b.
- c. numită și
- d. numită și
- e. numită și
- f. numită și
-
Care dintre următoarele stări produce cea mai mare incertitudine ?
- a.
- b. numită și
- c. numită și
- d. a și b sunt la egalitate
- e. b și c sunt la egalitate
- f. a, b și c sunt la egalitate
Întrebări de discuție:
-
Acest concept de incertitudine intră în conflict în vreun fel cu noțiunea de spin ca săgeată vectorială în spațiul cartezian? Dar pe sfera Bloch?
-
Presupune că orientezi un dispozitiv de măsurare de-a lungul unei direcții la jumătatea distanței dintre axele și . Ce se întâmplă? Poți efectua o măsurătoare de-a lungul acestei direcții? Cum se raportează aceasta la incertitudinea în și ?
-
Ce experimente suplimentare ai dori să faci pentru a te convinge de rezultatele obținute aici?