Kvantové bity, brány a obvody
Kifumi Numata (19 Apr 2024)
Klikni zde a stáhni si PDF původní přednášky. Některé ukázky kódu mohou být zastaralé, protože se jedná o statické obrázky.
Přibližná doba QPU pro spuštění tohoto experimentu je 5 sekund.
1. Úvod
Bity, brány a obvody jsou základní stavební kameny kvantových výpočtů. Naučíš se kvantové výpočty s obvodovým modelem pomocí kvantových bitů a bran a také si zopakuješ superpozici, měření a provázanost.
V této lekci se naučíš:
- Single-qubit gates
- Bloch sphere
- Superpozici
- Měření
- Two-qubit gates a stav provázanosti
Na konci této přednášky se dozvíš o hloubce obvodu, která je klíčová pro kvantové výpočty v užitkové škále.
2. Výpočet jako diagram
Když pracujeme s qubity nebo bity, potřebujeme s nimi manipulovat, abychom ze vstupů, které máme, dostali výstupy, které potřebujeme. Pro nejjednodušší programy s velmi malým počtem bitů je užitečné tento proces znázornit pomocí diagramu zvaného schéma obvodu.
Obrázek vlevo dole je příkladem klasického obvodu a obrázek vpravo dole je příkladem kvantového obvodu. V obou případech jsou vstupy vlevo a výstupy vpravo, zatímco operace jsou znázorněny symboly. Symboly používané pro operace se nazývají „Gate", převážně z historických důvodů.
3. Single-qubit quantum gate
3.1 Quantum state and Bloch sphere
Stav Qubitu je reprezentován jako superpozice a . Libovolný kvantový stav je vyjádřen jako
kde a jsou komplexní čísla taková, že .
a jsou vektory ve dvourozměrném komplexním vektorovém prostoru:
Libovolný kvantový stav je tedy také vyjádřen jako
Z toho vidíme, že stav kvantového bitu je jednotkový vektor ve dvourozměrném komplexním prostoru se skalárním součinem s ortonormální bází a . Je normalizován na 1.
|\psi\rangle =\begin\{pmatrix\} \alpha \\ \beta \end\{pmatrix\} se také nazývá stavový vektor (statevector).
Stav jednoho Qubitu lze také vyjádřit jako
kde a jsou úhly Blochovy sféry na následujícím obrázku.
V několika následujících buňkách kódu postupně sestavíme základní výpočty ze stavebních prvků v Qiskitu. Vytvoříme prázdný Circuit a pak přidáme kvantové operace – budeme probírat jednotlivé Gate a vizualizovat jejich efekty.
Buňku spustíš stisknutím „Shift" + „Enter". Nejprve importuj knihovny.
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-aer qiskit-ibm-runtime
# Import the qiskit library
from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
from qiskit.quantum_info import Statevector
from qiskit.visualization import plot_bloch_multivector
from qiskit_ibm_runtime import Sampler
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit.visualization import plot_histogram
Příprava kvantového obvodu
Vytvoříme a nakreslíme Circuit s jedním Qubitem.
# Create the single-qubit quantum circuit
qc = QuantumCircuit(1)
# Draw the circuit
qc.draw("mpl")
X Gate
X Gate je rotace o kolem osy na Blochově sféře. Aplikování X Gate na dá a aplikování X Gate na dá , takže jde o operaci podobnou klasickému hradlu NOT, která se také nazývá překlopení bitu (bit flip). Maticová reprezentace X Gate je níže.
qc = QuantumCircuit(1) # Prepare the single-qubit quantum circuit
# Apply a X gate to qubit 0
qc.x(0)
# Draw the circuit
qc.draw("mpl")
V IBM Quantum® je počáteční stav nastaven na , takže výše uvedený kvantový Circuit v maticové reprezentaci je
Dále spustíme tento Circuit pomocí simulátoru stavového vektoru.
# See the statevector
out_vector = Statevector(qc)
print(out_vector)
# Draw a Bloch sphere
plot_bloch_multivector(out_vector)
Statevector([0.+0.j, 1.+0.j],
dims=(2,))
Svislý vektor je zobrazen jako řádkový vektor s komplexními čísly (imaginární část je indexována ).
H Gate
Hadamardův Gate je rotace o kolem osy ležící na půl cesty mezi osami a na Blochově sféře. Aplikování H Gate na vytvoří superpozici ve tvaru . Maticová reprezentace H Gate je níže.
qc = QuantumCircuit(1) # Create the single-qubit quantum circuit
# Apply an Hadamard gate to qubit 0
qc.h(0)
# Draw the circuit
qc.draw(output="mpl")
# See the statevector
out_vector = Statevector(qc)
print(out_vector)
# Draw a Bloch sphere
plot_bloch_multivector(out_vector)
Statevector([0.70710678+0.j, 0.70710678+0.j],
dims=(2,))
Toto je
Tento stav superpozice je tak běžný a důležitý, že má vlastní symbol:
Aplikováním H Gate na jsme vytvořili superpozici a , kde by měření ve výpočetní bázi (podél osy z v obrazci Blochovy sféry) dalo každý stav se stejnou pravděpodobností.
Stav
Možná sis uhodl/a, že existuje odpovídající stav :
Pro vytvoření tohoto stavu nejprve aplikuj X Gate, aby vznikl , a pak aplikuj H Gate.
qc = QuantumCircuit(1) # Create the single-qubit quantum circuit
# Apply a X gate to qubit 0
qc.x(0)
# Apply an Hadamard gate to qubit 0
qc.h(0)
# draw the circuit
qc.draw(output="mpl")
# See the statevector
out_vector = Statevector(qc)
print(out_vector)
# Draw a Bloch sphere
plot_bloch_multivector(out_vector)
Statevector([ 0.70710678+0.j, -0.70710678+0.j],
dims=(2,))
Toto je
Aplikováním H Gate na dostaneme rovnoměrnou superpozici a , ale znaménko u je záporné.
3.2 Single-qubit quantum state and unitary evolution
Akce všech Gate, které jsme dosud viděli, byly unitární, což znamená, že je lze reprezentovat unitárním operátorem. Jinými slovy, výstupní stav lze získat působením unitární matice na počáteční stav:
Unitární matice je matice splňující
Z hlediska provozu kvantového počítače bychom řekli, že aplikace kvantového Gate na Qubit vyvíjí kvantový stav. Mezi běžné jednoqubitové Gate patří následující.
Pauli Gate:
kde vnější součin byl vypočítán takto:
Další typické jednoqubitové Gate:
Význam a použití těchto Gate jsou podrobněji popsány v kurzu Základy kvantových informací.
Exercise 1
Použij Qiskit k vytvoření kvantových Circuit, které připraví níže popsané stavy. Poté spusť každý Circuit pomocí simulátoru stavového vektoru a zobraz výsledný stav na Bloch sféře. Jako bonus zkus odhadnout, jaký by měl být konečný stav, na základě intuice o Gate a rotacích v Bloch sféře.
(1)
(2)
(3)
Tip: Gate Z lze použít pomocí
qc.z(0)
Řešení:
### (1) XX|0> ###
# Create the single-qubit quantum circuit
qc = QuantumCircuit(1) ##your code goes here##
# Add a X gate to qubit 0
qc.x(0) ##your code goes here##
# Add a X gate to qubit 0
qc.x(0) ##your code goes here##
# Draw a circuit
qc.draw(output="mpl")
# See the statevector
out_vector = Statevector(qc)
print(out_vector)
# Draw a Bloch sphere
plot_bloch_multivector(out_vector)
Statevector([1.+0.j, 0.+0.j],
dims=(2,))
### (2) HH|0> ###
##your code goes here##
qc = QuantumCircuit(1)
qc.h(0)
qc.h(0)
qc.draw("mpl")
# See the statevector
out_vector = Statevector(qc)
print(out_vector)
# Draw a Bloch sphere
plot_bloch_multivector(out_vector)
Statevector([1.+0.j, 0.+0.j],
dims=(2,))
### (3) HZH|0> ###
##your code goes here##
qc = QuantumCircuit(1)
qc.h(0)
qc.z(0)
qc.h(0)
qc.draw("mpl")
# See the statevector
out_vector = Statevector(qc)
print(out_vector)
# Draw a Bloch sphere
plot_bloch_multivector(out_vector)
Statevector([0.+0.j, 1.+0.j],
dims=(2,))
3.3 Měření
Měření je teoreticky velmi složité téma. V praxi však měření podél (jak to dělají všechny kvantové počítače IBM®) jednoduše přinutí stav qubitu přejít buď do , nebo do , a my pozorujeme výsledek.
- je pravděpodobnost, že při měření dostaneme .
- je pravděpodobnost, že při měření dostaneme .
Tedy a se nazývají pravděpodobnostní amplitudy. (viz „Bornovo pravidlo")
Například má při měření stejnou pravděpodobnost přechodu do nebo . má 75% šanci přejít do .
Qiskit Aer Simulator
Teď změříme Circuit, který připraví výše zmíněnou superpozici s rovnými pravděpodobnostmi. Přidáme měřicí Gate, protože Qiskit Aer simulator ve výchozím nastavení simuluje ideální kvantový hardware (bez šumu). Poznámka: Aer simulator může také aplikovat model šumu založený na skutečném kvantovém počítači. K modelům šumu se vrátíme později.
# Create a new circuit with one qubits (first argument) and one classical bits (second argument)
qc = QuantumCircuit(1, 1)
qc.h(0)
qc.measure(0, 0) # Add the measurement gate
qc.draw(output="mpl")
Jsme nyní připraveni spustit náš Circuit na Aer simulatoru. V tomto příkladu použijeme výchozí shots=1024, což znamená, že budeme měřit 1024krát. Poté zobrazíme tyto počty v histogramu.
# Run the circuit on a simulator to get the results
# Define backend
backend = AerSimulator()
# Transpile to backend
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_qc = pm.run(qc)
# Run the job
sampler = Sampler(mode=backend)
job = sampler.run([isa_qc])
result = job.result()
# Print the results
counts = result[0].data.c.get_counts()
print(counts)
# Plot the counts in a histogram
plot_histogram(counts)
{'0': 521, '1': 503}
Vidíme, že hodnoty 0 a 1 byly naměřeny s pravděpodobností téměř 50 % každá. Přestože zde nebyl simulován šum, stavy jsou stále pravděpodobnostní. Takže i když očekáváme přibližně rozdělení 50:50, jen zřídka najdeme přesně takový výsledek. Stejně jako 100 hodů mincí by jen zřídka přineslo přesně 50 výskytů každé strany.
4. Multi-qubit quantum gate and entanglement
4.1 Multi-qubit quantum circuit
Dvouqubitový kvantový Circuit můžeme vytvořit pomocí následujícího kódu. Na každý Qubit aplikujeme Hadamard Gate.
# Create the two qubits quantum circuit
qc = QuantumCircuit(2)
# Apply an H gate to qubit 0
qc.h(0)
# Apply an H gate to qubit 1
qc.h(1)
# Draw the circuit
qc.draw(output="mpl")
# See the statevector
out_vector = Statevector(qc)
print(out_vector)
Statevector([0.5+0.j, 0.5+0.j, 0.5+0.j, 0.5+0.j],
dims=(2, 2))
Poznámka: Řazení bitů v Qiskitu
Qiskit používá pro řazení Qubitů a bitů notaci Little Endian, což znamená, že Qubit 0 je nejpravější bit v bitových řetězcích. Příklad: znamená, že q0 je a q1 je . Buď opatrný, protože část literatury v oblasti kvantových výpočtů používá notaci Big Endian (Qubit 0 je nejlevější bit) a stejně tak velká část literatury z kvantové mechaniky.
Další věcí, které si všimni, je, že při znázornění kvantového Circuitu je vždy umístěn v horní části Circuitu. S tímto na paměti lze kvantový stav výše uvedeného Circuitu zapsat jako tenzorový součin jednoqubitových kvantových stavů.
( )
Počáteční stav Qiskitu je , takže aplikováním na každý Qubit se změní na stav rovnoměrné superpozice.
Pravidlo měření je stejné jako v případě jednoqubitovém: pravděpodobnost naměření je .
# Draw a Bloch sphere
plot_bloch_multivector(out_vector)

Teď tento Circuit změříme.
# Create a new circuit with two qubits (first argument) and two classical bits (second argument)
qc = QuantumCircuit(2, 2)
# Apply the gates
qc.h(0)
qc.h(1)
# Add the measurement gates
qc.measure(0, 0) # Measure qubit 0 and save the result in bit 0
qc.measure(1, 1) # Measure qubit 1 and save the result in bit 1
# Draw the circuit
qc.draw(output="mpl")
Nyní opět použijeme Aer simulator k experimentálnímu ověření, že relativní pravděpodobnosti všech možných výstupních stavů jsou přibližně stejné.
# Run the circuit on a simulator to get the results
# Define backend
backend = AerSimulator()
# Transpile to backend
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_qc = pm.run(qc)
# Run the job
sampler = Sampler(mode=backend)
job = sampler.run([isa_qc])
result = job.result()
# Print the results
counts = result[0].data.c.get_counts()
print(counts)
# Plot the counts in a histogram
plot_histogram(counts)
{'10': 262, '01': 246, '00': 265, '11': 251}
Jak bylo očekáváno, stavy , , , byly naměřeny přibližně z 25 % každý.
4.2 Multi-qubit quantum gates
CNOT Gate
CNOT Gate („controlled NOT" neboli CX) je dvouqubitový Gate, což znamená, že jeho akce zahrnuje dva Qubity najednou: řídící Qubit a cílový Qubit. CNOT překlopí cílový Qubit pouze tehdy, když je řídící Qubit ve stavu .
| Vstup (cíl, řídící) | Výstup (cíl, řídící) |
|---|---|
| 00 | 00 |
| 01 | 11 |
| 10 | 10 |
| 11 | 01 |
Nejprve nasimulujme akci tohoto dvouqubitového Gate, když jsou q0 i q1 ve stavu , a získejme výstupní stavový vektor. Použitá Qiskit syntaxe je qc.cx(control qubit, target qubit).
# Create a circuit with two quantum registers and two classical registers
qc = QuantumCircuit(2, 2)
# Apply the CNOT (cx) gate to a |00> state.
qc.cx(0, 1) # Here the control is set to q0 and the target is set to q1.
# Draw the circuit
qc.draw(output="mpl")
# See the statevector
out_vector = Statevector(qc)
print(out_vector)
Statevector([1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
dims=(2, 2))
Jak bylo očekáváno, aplikace CNOT Gate na nezměnila stav, protože řídící Qubit byl ve stavu . Vraťme se k naší operaci CNOT. Tentokrát aplikujeme CNOT Gate na a uvidíme, co se stane.
qc = QuantumCircuit(2, 2)
# q0=1, q1=0
qc.x(0) # Apply a X gate to initialize q0 to 1
qc.cx(0, 1) # Set the control bit to q0 and the target bit to q1.
# Draw the circuit
qc.draw(output="mpl")
# See the statevector
out_vector = Statevector(qc)
print(out_vector)
Statevector([0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j],
dims=(2, 2))
Aplikací CNOT Gate se stav změnil na .
Ověřme tyto výsledky spuštěním Circuit na simulátoru.
# Add measurements
qc.measure(0, 0)
qc.measure(1, 1)
# Draw the circuit
qc.draw(output="mpl")
# Run the circuit on a simulator to get the results
# Define backend
backend = AerSimulator()
# Transpile to backend
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_qc = pm.run(qc)
# Run the job
sampler = Sampler(backend)
job = sampler.run([isa_qc])
result = job.result()
# Print the results
counts = result[0].data.c.get_counts()
print(counts)
# Plot the counts in a histogram
plot_histogram(counts)
{'11': 1024}
Výsledky by ti měly ukázat, že bylo naměřeno se 100% pravděpodobností.
4.3 Quantum entanglement and execution on a real quantum device
Začněme představením konkrétního provázaného stavu, který je v kvantovém výpočtu obzvláště důležitý, a poté definujeme pojem „provázaný":
a tento stav se nazývá Bell state.
Provázaný stav je stav skládající se z kvantových stavů a , který nelze vyjádřit jako tenzorový součin jednotlivých kvantových stavů.
Pokud níže obsahuje dva stavy a ;
tenzorový součin těchto dvou stavů je následující
ale neexistují žádné koeficienty a , které by splňovaly tyto dvě rovnice. Proto není vyjádřitelný jako tenzorový součin jednotlivých kvantových stavů a , což znamená, že je provázaný stav.
Vytvořme Bell state a spusťme ho na skutečném kvantovém počítači. Nyní budeme postupovat podle čtyř kroků pro psaní kvantového programu, které se nazývají Qiskit patterns:
- Map problem to quantum circuits and operators
- Optimize for target hardware
- Execute on target hardware
- Post-process the results
Krok 1. Namapování problému na Circuit a operátory
V kvantovém programu jsou Circuit nativním formátem pro reprezentaci kvantových instrukcí. Při vytváření Circuit obvykle vytvoříš nový objekt QuantumCircuit a pak do něj sekvenčně přidáváš instrukce.
Následující buňka kódu vytvoří Circuit, který produkuje Bell state, konkrétní dvouqubitový provázaný stav uvedený výše.
qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure(0, 0)
qc.measure(1, 1)
qc.draw("mpl")
Krok 2. Optimalizace pro cílový hardware
Qiskit převádí abstraktní Circuit na QISA (Quantum Instruction Set Architecture) Circuit, které respektují omezení cílového hardware, a optimalizuje výkon Circuit. Před optimalizací tedy určíme cílový hardware.
Pokud nemáš nainstalováno qiskit-ibm-runtime, budeš ho nejprve muset nainstalovat. Více informací o Qiskit Runtime najdeš v referenci API.
# Install
# !pip install qiskit-ibm-runtime
Určíme cílový hardware.
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()
service.backends()
# You can specify the device
# backend = service.backend('ibm_kingston')
# You can also identify the least busy device
backend = service.least_busy(operational=True)
print("The least busy device is ", backend)
Transpilace Circuit je další složitý proces. Stručně řečeno, přepíše Circuit na logicky ekvivalentní pomocí „nativních Gate" (Gate, které dokáže konkrétní kvantový počítač implementovat) a namapuje Qubity ve tvém Circuit na optimální skutečné Qubity na cílovém kvantovém počítači. Více o transpilaci najdeš v této dokumentaci.
# Transpile the circuit into basis gates executable on the hardware
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
target_circuit = pm.run(qc)
target_circuit.draw("mpl", idle_wires=False)
Vidíš, že při transpilaci byl Circuit přepsán pomocí nových Gate. Více informací najdeš v dokumentaci ECRGate.
Krok 3. Spuštění cílového Circuit
Nyní spustíme cílový Circuit na skutečném zařízení.
sampler = Sampler(backend)
job_real = sampler.run([target_circuit])
job_id = job_real.job_id()
print("job id:", job_id)
Spuštění na skutečném zařízení může vyžadovat čekání ve frontě, protože kvantové počítače jsou cenné zdroje a jsou velmi žádané. job_id se používá ke kontrole stavu spuštění a výsledků úlohy později.
# Check the job status (replace the job id below with your own)
job_real.status(job_id)
Stav úlohy můžeš také zkontrolovat ze svého IBM Quantum dashboardu:https://quantum.cloud.ibm.com/workloads
# If the Notebook session got disconnected you can also check your job status by running the following code
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()
job_real = service.job(job_id) # Input your job-id between the quotations
job_real.status()
# Execute after job has successfully run
result_real = job_real.result()
print(result_real[0].data.c.get_counts())
Krok 4. Post-processing výsledků
Nakonec musíme zpracovat naše výsledky a vytvořit výstupy v očekávaném formátu, například hodnoty nebo grafy.
plot_histogram(result_real[0].data.c.get_counts())
Jak vidíš, a jsou nejčastěji pozorované výsledky. Existuje několik výsledků jiných než očekávaná data a jsou způsobeny šumem a dekoherencí Qubitů. O chybách a šumu v kvantových počítačích se dozvíme více v pozdějších lekcích tohoto kurzu.
GHZ stav
Koncept provázání lze rozšířit na systémy s více než dvěma qubity. GHZ stav (Greenberger-Horne-Zeilinger stav) je maximálně provázaný stav tří nebo více qubitů. GHZ stav pro tři qubity je definován jako
Lze ho vytvořit pomocí následujícího kvantového Circuit.
qc = QuantumCircuit(3, 3)
qc.h(0)
qc.cx(0, 1)
qc.cx(1, 2)
qc.measure(0, 0)
qc.measure(1, 1)
qc.measure(2, 2)
qc.draw("mpl")
„Hloubka" kvantového Circuit je užitečná a běžně používaná metrika pro popis kvantových obvodů. Sleduj cestu skrz kvantový Circuit zleva doprava, přičemž měníš qubity pouze tehdy, jsou-li propojeny vícequbitovým Gate. Počítej počet Gate podél této cesty. Maximální počet Gate pro jakoukoli takovou cestu skrz Circuit je jeho hloubka. V moderních hlučných kvantových počítačích mají Circuit s malou hloubkou méně chyb a pravděpodobněji vrátí dobré výsledky. Velmi hluboké Circuit to tak nemají.
Pomocí QuantumCircuit.depth() můžeme zkontrolovat hloubku našeho kvantového Circuit. Hloubka výše uvedeného Circuit je 4. Horní Qubit má pouze tři Gate včetně měření. Ale existuje cesta z horního qubitu dolů k qubitu 1 nebo qubitu 2, která zahrnuje další CNOT Gate.
qc.depth()
4
Cvičení 2
GHZ stav 8-qubitového systému je
Napiš kód pro přípravu tohoto stavu s co nejmělčím možným Circuit. Hloubka nejmělčího kvantového Circuit je 5, včetně měřicích Gate.
Řešení:
# Step 1
qc = QuantumCircuit(8, 8)
##your code goes here##
qc.h(0)
qc.cx(0, 4)
qc.cx(4, 6)
qc.cx(6, 7)
qc.cx(4, 5)
qc.cx(0, 2)
qc.cx(2, 3)
qc.cx(0, 1)
qc.barrier() # for visual separation
# measure
for i in range(8):
qc.measure(i, i)
qc.draw("mpl")
# print(qc.depth())
print(qc.depth())
5
from qiskit.visualization import plot_histogram
# Step 2
# For this exercise, the circuit and operators are simple, so no optimizations are needed.
# Step 3
# Run the circuit on a simulator to get the results
backend = AerSimulator()
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_qc = pm.run(qc)
sampler = Sampler(mode=backend)
job = sampler.run([isa_qc], shots=1024)
result = job.result()
counts = result[0].data.c.get_counts()
print(counts)
# Step 4
# Plot the counts in a histogram
plot_histogram(counts)
{'11111111': 535, '00000000': 489}
5. Shrnutí
Naučil ses kvantové výpočty s modelem Circuit pomocí kvantových bitů a Gate, a zopakoval sis superpozici, měření a provázání. Také ses naučil metodu pro spouštění kvantového Circuit na skutečném kvantovém zařízení.
V závěrečném cvičení na vytvoření GHZ Circuit ses pokusil snížit hloubku Circuit, což je důležitý faktor pro dosažení řešení v měřítku utility na hlučném kvantovém počítači. V pozdějších lekcích tohoto kurzu se dozvíš podrobnosti o hluku a metodách potlačení chyb. V této lekci jsme jako úvod uvažovali o snižování hloubky Circuit na ideálním zařízení, ale ve skutečnosti musíme brát v úvahu omezení reálného zařízení, jako je konektivita qubitů. Více se o tom dozvíš v dalších lekcích tohoto kurzu.
# See the version of Qiskit
import qiskit
qiskit.__version__
'2.0.2'