Zkoumání neurčitosti
Pro tento modul Qiskit in Classrooms musí mít studenti funkční prostředí Python s nainstalovanými následujícími balíčky:
qiskitv2.1.0 nebo novějšíqiskit-ibm-runtimev0.40.1 nebo novějšíqiskit-aerv0.17.0 nebo novějšíqiskit.visualizationnumpypylatexenc
Pokyny k nastavení a instalaci výše uvedených balíčků najdeš v průvodci Instalace Qiskitu. Aby studenti mohli spouštět úlohy na skutečných kvantových počítačích, musí si vytvořit účet u IBM Quantum® podle kroků popsaných v průvodci Nastavení účtu IBM Cloud.
Tento modul byl otestován a spotřeboval 8 minut QPU času. Jde pouze o odhad – skutečná spotřeba se může lišit. Dvě časově náročné výpočty jsou v komentářích záhlaví takto označeny a lze je provést na simulátorech, pokud studenti nemají dostatek QPU času. Bez nich modul vyžaduje pouze přibližně 30 sekund QPU času.
# 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'
Podívej se na průvodce modulem od Dr. Katie McCormick níže, nebo klikni sem a sleduj ho na YouTube.
Úvod
O principu neurčitosti sis pravděpodobně slyšel/a i mimo své fyzikální kurzy. Běžné hovorové přeformulování neurčitosti zní: „Tím, že se na něco podíváš, to ovlivníš." To je jistě pravda. Fyzikálnější způsob popisu neurčitosti je ale ten, že existují určité fyzikální pozorovatelné veličiny, které jsou vzájemně neslučitelné – nelze je obě současně znát s libovolnou přesností. Mnoho studentů se poprvé setkává s dvojicí neslučitelných proměnných a , tedy polohou podél osy a hybností podél tohoto směru. Pro tyto proměnné se omezení neurčitosti zapisuje jako Zde se nazývá „neurčitost ", která má stejnou definici jako směrodatná odchylka ve statistice, a lze ji definovat jako je definována obdobně. Tuto relaci neurčitosti zde nebudeme odvozovat; upozorníme pouze na to, že je v souladu s naším chápáním klasických vln. Vlna s jednou dokonale přesnou frekvencí a vlnovou délkou by se šířila donekonečna jako dokonalá sinusoida. Kvantově mechanicky by to odpovídalo dokonalé znalosti hybnosti podle de Broglieovy hypotézy: . Abychom ale věděli, se částice s vlnovým charakterem nachází, musí se popisující vlna stát v prostoru ostřeji soustředěnou – například jako velmi úzká Gaussova funkce. Víme, že jakoukoli spojitou funkci, včetně takto ostře soustředěných vlnových funkcí, lze vyjádřit jako Fourierovu řadu sinusoid s různými vlnovými délkami. Jak se vlnová funkce stává ostřeji soustředěnou (a poloha je lépe známa), potřebujeme ve Fourierově řadě více členů, tedy směs více vlnových délek (a kvantově mechanicky tedy více hodnot hybnosti).
Jednodušeji řečeno: stav s dobře definovanou hybností (dokonalá sinusoida v prostoru) má velmi neurčitou polohu. Stav s dobře definovanou polohou (jako Diracovo delta rozdělení) má velmi neurčitou hybnost.
Existují i jiné veličiny, které vykazují takovou neslučitelnost. Například spin částice může mít dobře definovanou projekci podél jedné osy, přičemž o projekci na kolmou osu nevíme nic. Stav (pro Qubit nebo spin-1/2 částici) má určitou projekci podél osy (hodnotu 1 v kontextu Qubitu a v kontextu spin-1/2 částice). Tento stav však lze zapsat jako superpozici dvou stavů, z nichž každý má dobře definovanou projekci na osu : neboli ekvivalentně má dobře definovanou projekci na , stejně tak . Pokud tedy určíme projekci stavu podél osy , neznáme projekci podél osy . A pokud určíme projekci na ose , neznáme projekci podél . Existují drobné rozdíly při diskusi v kontextu spinu a Qubitů. Obecně ale platí, že vlastní stavy Pauliho matic mají zajímavý vztah, který můžeme prozkoumat. V průběhu této lekce budeme experimentálně ověřovat svou intuici ohledně neurčitosti těchto neslučitelných veličin a budeme na kvantových počítačích IBM® ověřovat platnost relací neurčitosti.
Jednoduchá intuitivní zkouška
V tomto prvním experimentu a v celém modulu budeme používat rámec pro kvantové výpočty známý jako „Qiskit patterns", který rozděluje pracovní postupy do následujících kroků:
- Krok 1: Mapování klasických vstupů na kvantový problém
- Krok 2: Optimalizace problému pro kvantové spuštění
- Krok 3: Spuštění pomocí Qiskit Runtime Primitives
- Krok 4: Post-processing a klasická analýza
Tyto kroky budeme obecně dodržovat, i když je nemusíme vždy explicitně označovat.
Začněme načtením potřebných balíčků včetně Runtime primitiv. Zároveň vybereme nejméně vytížený dostupný kvantový počítač.
Níže je uveden kód pro uložení přihlašovacích údajů při prvním použití. Po uložení do svého prostředí tyto informace z notebooku smaž, aby nebyly náhodně sdíleny spolu s notebookem. Více informací najdeš v průvodcích Nastavení účtu IBM Cloud a Inicializace služby v nedůvěryhodném prostředí.
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
Pokud student vyčerpá dostupný čas na kvantových počítačích během lekce, lze níže uvedené řádky odkomentovat a použít pro nastavení simulátoru, který částečně napodobuje šumové chování výše vybraného kvantového počítače.
# 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}})
Možná si vzpomeneš, že vlastní stav jednoho operátoru Z není vlastním stavem jiného operátoru X. Nyní to experimentálně pozorujeme měřením podél os a . Pro měření podél jednoduše použijeme qc.measure(), protože kvantové počítače IBM jsou konstruovány tak, aby měřily podél . Aby bylo možné měřit podél , musíme systém otočit tak, abychom efektivně přesunuli osu do orientace, podél níž měříme. Toho je dosaženo pomocí Hadamardova Gate. Pro měření podél je nutný podobný krok. Potřebné kroky jsou zde shrnuty pro přehlednost:
- Měření podél :
qc.measure() - Měření podél :
qc.h()a pakqc.measure() - Měření podél :
qc.sdg(),qc.h(),qc.sa pakqc.measure()
Krok 1: Mapování klasických vstupů na kvantový problém
V tomto případě krok mapování spočívá jednoduše ve vyjádření výše popsaných měření a rotací v kvantovém Circuit:
# 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")
Krok 2: Optimalizace problému pro kvantové spuštění
Tento krok vezme operace, které chceme provést, a vyjádří je v termínech funkcionality konkrétního kvantového počítače. Zároveň mapuje náš problém na topologii kvantového počítače.
# 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)
Krok 3: Spuštění pomocí Qiskit Runtime Primitives
Pro sběr statistik z měření můžeme použít Sampler. Primitivum Sampler nakonfigurujeme tak, aby běželo na skutečném kvantovém počítači, pomocí mode = backend. Existují i jiné režimy pro jiné pracovní postupy, jeden z nich použijeme níže. Sampler se spustí voláním jeho metody run() se seznamem „PUBů" (Primitive Unified Blocs). Každý PUB obsahuje až tři hodnoty, které společně definují výpočetní jednotku práce pro Estimator: circuits, observables, parameters. Lze také poskytnout seznam circuits, seznam observables a seznam parameters. Více informací najdeš v části Přehled PUBů.
Chceme spustit výpočet na skutečném kvantovém počítači, abychom prováděli skutečný experiment z kvantové fyziky. Pokud vyčerpáš přidělený čas na skutečných kvantových počítačích, můžeš níže uvést kód pro kvantový počítač do komentáře a odkomentovat kód pro spuštění na simulátoru.
# 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()
Krok 4: Post-processing
Toto je obzvláště jednoduchý případ post-processingu, při kterém jednoduše vizualizujeme počty.
Všimni si, že Qiskit řadí Qubity, měření a další věci tak, že položku s nejnižším číslem uvádí jako poslední / napravo – tato konvence se nazývá „little-endian". To znamená, že sloupec označený níže jako „10" odpovídá počtům, při nichž první měření vrátilo „0" a druhé měření vrátilo „1".
# Step 4: Post-process
from qiskit.visualization import plot_histogram
plot_histogram(counts)
Pokud ti tato konvence nevyhovuje, můžeš použít marginal_counts a vizualizovat výsledky každého měření samostatně:
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"
)
Ve výchozím nastavení jsou stavy v Qiskitu inicializovány do stavu . Není tedy překvapením, že téměř všechna první měření dala výsledek . Všimni si však, že ve druhém měření (které poskytuje informaci o projekcích stavu na osu ) byl výsledek téměř rovnoměrně rozdělen. Zdá se, že stav, který dává velmi předvídatelný výsledek měření podél , nám dává velmi nepředvídatelnou sadu výsledků pro měření podél . Pojďme to prozkoumat.
Co se stane, pokud provedeme měření v opačném pořadí? Mohli bychom začít tím, že pomocí Hadamardovy Gate získáme statistiku pravděpodobnosti změření v . Poté při druhém měření převedeme základ zpět na pomocí druhé Hadamardovy Gate.
# 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)
Zde máme zdánlivě ještě méně předvídatelnosti! Dříve jsme alespoň věděli, jaký bude výsledek prvního měření, nyní máme poměrně rovnoměrné rozdělení přes všechny možné stavy. Není příliš těžké pochopit, proč k tomu došlo. Začali jsme ve stavu , který je směsí 50–50 stavů a podle vztahu Takže je zřejmé, že pravděpodobnost naměření stavu + nebo − (mapovaných na 0 a 1 v grafu) při prvním měření by měla být stejná. Měření podél zkolabuje stav buď do vlastního stavu , nebo do vlastního stavu . Každý z těchto stavů je směsí 50–50 stavů a podle vztahů Jakmile je systém ve vlastním stavu , jsou výsledky měření podél zřejmě i , a to přibližně se stejnou pravděpodobností. Náš první příklad nám tedy ukázal, že některé stavy budou mít velmi předvídatelné výsledky určitých měření, ale nepředvídatelné výsledky jiných měření. Aktuální příklad ukazuje, že to může být ještě horší. Existují stavy, které mohou dávat nepředvídatelné výsledky pro obě měření, i když pouze prohodíme jejich pořadí. Pojďme prozkoumat, jak jistá nebo nejistá je daná veličina pro určitý stav.
Výpočet nejistoty
Tuto nejistotu, neboli rozptyl, lze kvantifikovat. „Nejistota" je často definována jako odmocnina „rozptylu" rozdělení. Jinak řečeno, nejistota pro pozorovatelnou veličinu se označuje a je dána vztahem
Pro případ Pauliho matic, pro které platí , se tento výraz zjednodušší na
Aplikujme to na konkrétní příklad. Začněme stavem a určeme nejistotu pozorovatelné veličiny v tomto stavu.
Otestuj své znalosti
Přečti si otázku níže, zamysli se nad odpovědí a pak klikni na trojúhelník, abys odhalil řešení.
Vypočítej neurčitost ve stavu ručně.
Odpověď:
V daném stavu to dává:
Libovolný počáteční stav můžeme vytvořit pomocí qc.initialize(). Všimni si, že syntaxe pro imaginární jednotku je zde .
# 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
Podle naší rovnice výše, Zůstaňme u stejného stavu, ale tentokrát zjistíme střední hodnotu :
# 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
Mohli bychom provést stejné výpočty jako předtím, ale viděli bychom, že rozptyl je opět velmi blízký 1,0. Mohli bychom tedy konstatovat, že . Pro námi zvolený stav to skutečně přibližně platí. Ale lze toho dosáhnout lépe? Nebo hůře?
Vzpomeň si, že mezi polohou v jednom směru, a hybností ve stejném směru, platí relace neurčitosti. Pro tyto veličiny je nejznámější tvar pravděpodobně Pokud si pamatujeme jen tohle, mohli bychom být v pokušení myslet si, že a mají také takové fundamentální omezení neurčitosti. Možná je nemožné, aby součin dosáhl nuly? Zkusme jiný stav a uvidíme, zda to platí. Tentokrát použijeme Podívejme se, co se stane. Všimni si, že v níže uvedeném kódu může Estimator přijmout dvě sady obvodů a pozorovatelných veličin ve stejném odeslaném jobu.
# 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
Střední hodnota by měla být blízká 1,0, ale neměla by překročit 1,0. Neznepokojuj se, pokud ji překročí o velmi malou částku. To lze přičíst faktorům, jako je šum nebo chyba čtení. Ačkoli se jedná o velmi důležité téma, prozatím ho můžeme ignorovat.
Získali jsme střední hodnotu velmi blízkou 1,0 (což odpovídá velmi nízkému rozptylu pro ). Díky tomu je součin obou rozptylů poměrně malý:
Přestože to není přesně nula, tato hodnota je ve srovnání s vlastními hodnotami Pauliho operátorů () malá. Možná si vzpomínáš, že relaci neurčitosti mezi lineární polohou a hybností lze zapsat jinak — s explicitním použitím komutátoru operátorů a :
kde
je komutátor a .
Tento tvar lze nejsnáze rozšířit na Pauliho operátory. Obecně platí pro dva operátory a :
A v případě Pauliho matic a potřebujeme , abychom mohli vypočítat
Ukážeme to zde a podobné výpočty necháváme čtenáři jako cvičení:
Toto je zcela přijatelná odpověď, ale jedním dalším krokem vidíme
Naše relace neurčitosti se tak stává
Ověř své porozumění
Přečti si otázku níže, zamysli se nad odpovědí a pak klikni na trojúhelník, aby se zobrazilo řešení.
Urči a . Pomocí výsledků zapiš relace neurčitosti mezi a a mezi a .
Odpověď:
V kombinaci s obecnou relací neurčitosti dostaneme
Ověření konzistence
Než budeme pokračovat, zkontrolujeme, zda je to v souladu s naším předchozím zjištěním. Použili jsme stav A zjistili jsme, že Nyní víme, že tento součin by měl být větší nebo roven
Skutečně tedy platí . Pomocí následujících otázek si vytvoř intuici pro tato zjištění:
Ověř své porozumění
Přečti si otázky níže, zamysli se nad odpověďmi a pak klikni na trojúhelníky, aby se zobrazila řešení.
Odpověz na následující body jako celek:
(a) U jakých stavů bys očekával(a) nulovou neurčitost v ?
(b) U jakých stavů bys očekával(a) nulovou neurčitost v ?
(c) V jakých stavech bys získal(a) nulovou střední hodnotu ?
(d) Jsou odpovědi na výše uvedené otázky konzistentní s případem ?
(e) Napiš kód, který to explicitně ověří pomocí estimatoru.
Odpovědi:
(a) Mohli bychom očekávat, že vlastní stavy operátoru dají nulovou neurčitost v . Skutečně, pro platí
(b) Mohli bychom očekávat, že vlastní stavy operátoru dají nulovou neurčitost v . Skutečně, pro platí
(c) Očekáváme pro stavy, které při měření dávají kladnou projekci na osu stejně často jako zápornou. Patří sem vlastní stavy a .
(d) Ano. U vlastních stavů nebo bychom očekávali velmi malou hodnotu součinu neurčitostí : To může platit, protože pro tytéž stavy bychom rovněž očekávali . Relace neurčitosti tak může být splněna.
(e) Následující kód by to ověřil:
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()
Výsledky vrátí všechny střední hodnoty. Abychom je všechny získali a vypočítali neurčitosti, mohli bychom použít:
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
Odpověz na následující body jako celek:
(a) Dokážeš si představit stav, ve kterém by střední hodnota byla velká?
(b) Očekával(a) bys u téhož stavu velkou, nebo malou neurčitost v ?
(c) Očekával(a) bys u téhož stavu velkou, nebo malou neurčitost v ?
(d) Jsou odpovědi na výše uvedené otázky konzistentní s případem ?
(e) Napiš kód, který to explicitně ověří pomocí estimatoru.
Odpovědi:
(a) Očekáváme pro vlastní stav : .
(b) Mohli bychom očekávat velkou neurčitost ve stavu , protože měření v tomto stavu by dávalo kladný a záporný výsledek se stejnou četností/pravděpodobností.
(c) Mohli bychom očekávat velkou neurčitost ve stavu , protože měření v tomto stavu by dávalo kladný a záporný výsledek se stejnou četností/pravděpodobností.
(d) Ano. U vlastních stavů , a konkrétně u , bychom očekávali velkou hodnotu součinu neurčitostí . U téhož stavu bychom rovněž očekávali . Tedy jak , tak jsou v tomto stavu celkem velké a je přijatelné, že relace neurčitosti může být opět splněna.
(e) Následující kód by to ověřil:
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()
Výsledky vrátí všechny střední hodnoty. Abychom je všechny získali a vypočítali neurčitosti, mohli bychom použít:
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
Testování relací neurčitosti
Výše uvedený test prokázal platnost relace neurčitosti pouze pro jediný výběr stavového vektoru . Abychom se přesvědčili, že je to obecně v souladu s experimentem, měli bychom provést podobné výpočty pomocí Estimatoru pro mnoho různých stavových vektorů. Začneme tím, že otočíme náš stavový vektor pryč od osy pomocí Gate RY, čímž vytvoříme různé počáteční stavy s parametrem .
# 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()
Všimni si, že červená křivka je vždy větší než oranžová křivka Někdy součin neurčitostí klesne a přiblíží se limitu, jindy stoupne a od limitu se vzdálí, ale relaci neurčitosti vždy splňuje.
Tento test relace neurčitosti ovšem nemusí být nejlepší, protože naše mez je vždy velmi blízko nule. Použijme kvantový stav s větší projekcí na vlastní stavy . Konkrétně budeme stále otáčet dolů od osy o různé úhly, ale tentokrát výsledný stav ještě otočíme kolem osy o určitý úhel, třeba , a uvidíme, co se stane.
# 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()
Nyní vidíme, že mez neurčitosti je opravdu prověřována! Červená křivka se k oranžové přibližuje mnohem více než dříve. Ve skutečnosti by v nepřítomnosti šumu byla relace neurčitosti přesně saturována () v jednom bodě. V přítomnosti šumu a chyby čtení by nemělo překvapit, pokud běh občas vykáže velmi mírně větší než Nejde o skutečné porušení principu neurčitosti — je to jen artefakt nenulové chyby.
Ověř si porozumění
Přečti si otázky níže, zamysli se nad odpověďmi a pak klikni na trojúhelníky pro zobrazení řešení.
Vysvětli, jak bys to dotáhl do absolutního extrému a maximalizoval ?
Odpověď:
Kód aktuálně obsahuje řádky, které rotují výchozí počáteční stav od osy o parametrizovaný úhel a pak také kolem osy o úhel , čímž se stavový vektor přesune částečně směrem k ose .
qc.ry(theta,0)
qc.rz(pi/4,0)
Mohli bychom změnit rotaci kolem z na , čímž bychom stav přesunuli celý až do vlastního stavu :
qc.ry(theta,0)
qc.rz(pi/2,0)
Žádné další změny by nebyly potřeba.
Uprav kód nebo ho zkopíruj a implementuj tuto kontrolu relace neurčitosti s maximalizovanou střední hodnotou Y. Platí relace neurčitosti?
Odpověď:
Použili bychom přesně kód z výše uvedeného příkladu, přičemž bychom nahradili
qc.rz(pi/4,0).
za
qc.rz(pi/2,0)
Výsledný graf by měl vypadat jako ten níže a ano, princip neurčitosti by měl stále platit.

Uprav výše uvedený kód tak, aby vznikl podobný graf, který na základě měření na kvantovém počítači ukáže, že součin se chová správně. Zvol libovolnou sadu stavů.
Odpověď:
Použili bychom přesně kód z výše uvedeného příkladu, a vlastně bychom mohli využít stejné výsledky jako výše – jen bychom pomocí středních hodnot vypočítali různé neurčitosti. Například bychom mohli použít
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)
a mohli bychom vykreslit
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()
Výzva: Napiš kód, který prochází mnoho hodnot , stejně jako jsme procházeli mnoho hodnot , a vytvoř 3D graf ukazující, že relace neurčitosti není nikdy porušena. Zvol libovolné observabely.
Otázky
Instruktoři mohou požádat o verze těchto notebooků s klíčem k odpovědím a pokyny k zařazení do běžných osnov vyplněním tohoto krátkého dotazníku o tom, jak jsou notebooky využívány.
Klíčové pojmy:
- Existují relace neurčitosti mezi mnoha dvojicemi fyzikálních observabelů, včetně polohy a hybnosti a složek spinu.
- Pauliho matice spolu nekomutují. To je matematickým odrazem skutečnosti, že ne všechny složky spinu lze současně znát či určit.
- Kvantové výpočty hojně využívají Pauliho operátory/matice, proto je užitečné znát relace neurčitosti pro Pauliho operátory i úzce příbuzné spinové operátory.
- Obecný vzorec pro neurčitost dvou operátorů a je
- Vlastní stav nějakého operátoru dává nulovou neurčitost fyzikální observabely přidružené k tomuto operátoru. Dokonce i experimentálně platí
- Vlastní stav nějakého operátoru dá větší neurčitost pro operátor , který s nekomutuje.
- Experimentální výsledky z reálného kvantového počítače potvrzují intuici, kterou získáváme z maticových reprezentací fyzikálních operátorů.
Otázky pravda/nepravda:
- P/N Lze současně měřit a , ale ne .
- P/N Lze současně měřit a , ale ne .
- P/N Operátory lineární polohy a lineární hybnosti spolu nekomutují.
- P/N Kvantové počítače IBM měří standardně podél , takže pro měření v jakémkoli jiném směru je nutné provést rotaci.
- P/N Circuit níže efektivně měří nejprve a poté .
Otázky s výběrem odpovědi:
-
Diagram níže demonstruje kterou z následujících relací neurčitosti?
- a.
- b.
- c.
- d. Žádnou z výše uvedených

-
Jaká je standardní posloupnost kroků pro měření podél ?
- a. Pouze
qc.measure() - b.
qc.h()a potéqc.measure() - c.
qc.h(),qc.h()a potéqc.measure() - d.
qc.h(),qc.s,qc.h()a potéqc.measure() - e.
qc.sdg(),qc.h(),qc.sa potéqc.measure() - f.
qc.sdg(),qc.h(),qc.s,qc.h()a potéqc.measure()
- a. Pouze
-
Který z následujících stavů dává největší střední hodnotu ?
- a.
- b.
- c. také označovaný jako
- d. také označovaný jako
- e. také označovaný jako
- f. také označovaný jako
-
Který z následujících stavů dává největší neurčitost ?
- a.
- b. také označovaný jako
- c. také označovaný jako
- d. a a b jsou vyrovnané
- e. b a c jsou vyrovnané
- f. a, b a c jsou vyrovnané
Diskusní otázky:
-
Je tento koncept neurčitosti v nějakém ohledu v rozporu s představou spinu jako vektorové šipky v kartézském prostoru? A co na Blochově sféře?
-
Předpokládejme, že orientuješ měřicí přístroj ve směru přesně uprostřed mezi osami a . Co se stane? Lze v tomto směru měřit? Jak to souvisí s neurčitostí v a ?
-
Jaké další experimenty bys chtěl provést, abys se přesvědčil o výsledcích získaných zde?